changeset 362:b2b859a62e70

bulma (chat): new templates and CSS for chat page.
author Goffi <goffi@goffi.org>
date Wed, 28 Jun 2023 10:40:50 +0200
parents e44c0627d00b
children cddac8502c4b
files sat_templates/templates/bulma/chat/attachment_preview.html sat_templates/templates/bulma/chat/chat.html sat_templates/templates/bulma/chat/message.html sat_templates/templates/bulma/static/chat.css
diffstat 4 files changed, 258 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sat_templates/templates/bulma/chat/attachment_preview.html	Wed Jun 28 10:40:50 2023 +0200
@@ -0,0 +1,26 @@
+<div class="attachment-preview is-flex is-flex-direction-column is-align-items-center mx-2">
+    {% if file.mime_type|media_type_main == 'image' %}
+        <!-- Show image thumbnail -->
+        <div class="thumbnail-container">
+            <img src="{{ file.url }}" class="thumbnail-image" alt="{{file.name}}">
+        </div>
+    {% elif file.mime_type|media_type_main == 'video' %}
+        <!-- Show video thumbnail with play icon -->
+        <a href="{{file.url}}" class="is-video-thumbnail-wrapper is-wrapping photo_thumb_click">
+            <img class="is-photo-thumbnail" src="{{file.thumb_url}}">
+            <div class="media_overlay_play is-flex has-items-centered">
+                <span class="icon">
+                    <i class="icon-play-circled"></i>
+                </span>
+            </div>
+        </a>
+    {% else %}
+        <!-- Show a generic file icon if not an image or video -->
+        {{ icon('doc', cls='icon is-large') }}
+    {% endif %}
+    <div class="attachment-name mx-2 has-text-weight-bold" title="{{ file.name }}">{{ file.name }}</div>
+    <button class="delete is-small attachment-delete-button action_delete"></button>
+    {% if uploading %}
+        <progress class="progress is-info has-background-white" value="0" max="100">0%</progress>
+    {% endif %}
+</div>
--- a/sat_templates/templates/bulma/chat/chat.html	Thu Jun 22 16:31:26 2023 +0200
+++ b/sat_templates/templates/bulma/chat/chat.html	Wed Jun 28 10:40:50 2023 +0200
@@ -1,19 +1,63 @@
-{{ script.include('chat') }}
 {% if not embedded %}{% extends 'base/base.html' %}{% endif %}
 {% block title %}{{ target_jid }} - {{ super() }}{% endblock %}
 {% block body %}
-    <div id="chat-panel">
-        {% if subject is defined %}
-            <div class="notification is-primary my-0">
-                {{- subject|urlize(nofollow=true,target='_blank') -}}
-            </div>
-        {% endif %}
-        <div id="messages" class="has-background-white pt-4 px-4">
+        {{ icon_defs("lock-open", "lock-filled", "ok", "pencil", "dot-3", "share", "attach", "paper-plane-empty", "doc", "download") }}
+
+    {# TODO: this should be done in a more generic way in dialog module #}
+    <div id="modal" class="modal">
+        <div class="modal-background"></div>
+        <div class="modal-content">
+            <p class="image">
+            <img id="modal-image" src="" alt="">
+            </p>
+        </div>
+        <button class="modal-close is-large" aria-label="close"></button>
+    </div>
+
+    <div id="chat-panel" class="is-flex is-flex-direction-column is-justify-content-space-between is-align-items-stretch pt-4"> <!-- calculate height depending on your navbar size -->
+        <!-- Header -->
+        <div id="header" class="box p-4 is-flex is-justify-content-space-between is-align-items-center is-flex-shrink-0">
+            {% if subject is defined %}
+                <h2 id="room-subject" class="title is-5 has-text-weight-bold">{{- subject|urlize(nofollow=true,target='_blank') -}}</h2>
+            {% endif %}
+        </div>
+
+        <!-- Messages -->
+        <div id="messages" class="box p-4 has-background-white mb-4 is-flex-grow-1 is-flex-direction-column-reverse is-overflow-auto">
             {% for msg in messages %}
                 {% include 'chat/message.html' %}
             {% endfor %}
         </div>
-        <textarea id="message_input" class="textarea mt-4 chat_input mb-4" name="message" type="text" rows="1" placeholder="{{_("enter your message")}}"></textarea>
+
+    <!-- Attachments -->
+    <div id="attachments" class="box has-background-white is-flex is-flex-grow-0 is-flex-shrink-0 is-align-items-center is-overflow-auto is-contracted">
+        {% for file in attachments %}
+            {% include 'chat/attachment_preview.html' %}
+        {% endfor %}
+    </div>
+
+    <!-- Input -->
+    <div id="input-area" class="field has-addons py-4 is-flex-shrink-0">
+        <p class="control is-expanded">
+            <textarea id="message_input" class="textarea" name="message" type="text" rows="1" placeholder="{{_("enter your message")}}"></textarea>
+        </p>
+        <div class="control">
+            <button class="button" id="attach_button">
+                <span class="icon is-small">
+                    {{ icon('attach', cls='has-text-info') }}
+                </span>
+            </button>
+            <input id="file_input" type="file" multiple="true" style="display: none" />
+        </div>
+        <div class="control">
+            <button class="button" id="send_button">
+                <span class="icon is-small">
+                    {{ icon('paper-plane-empty') }}
+                </span>
+            </button>
+        </div>
+    </div>
+
     </div>
 {% endblock body %}
 
--- a/sat_templates/templates/bulma/chat/message.html	Thu Jun 22 16:31:26 2023 +0200
+++ b/sat_templates/templates/bulma/chat/message.html	Wed Jun 28 10:40:50 2023 +0200
@@ -1,31 +1,69 @@
 {% import 'components/avatar.html' as avatar with context %}
 
-<div id="{{msg.id}}" class="media is-chat-message msg_{{msg.type}} {{'own_msg' if msg.from_ == own_jid.full()}}">
+<div id="{{msg.id}}" class="media is-chat-message msg_{{msg.type}} {{'own_msg' if msg.from_ == own_jid}}" style="padding: 0.5em;" role="listitem" aria-label="Chat Message">
     {%- if msg.type != C.MESS_TYPE_INFO %}
         {%- set author = identities[msg.from_].nicknames[0] | default(msg.from_) -%}
-        <figure class="media-left">
+        <figure class="media-left pt-1">
             {{ avatar.avatar(msg.from_, "is-32x32") }}
         </figure>
     {% endif -%}
-    <div class="media-content">
+    <div class="media-content is-relative">
         <div class="content">
             {%- if msg.type != C.MESS_TYPE_INFO %}
                 <nav class="level is-mobile is-marginless is-size-7">
                     <div class="level-left has-text-weight-bold">
                         <div class="level-item">
-                            <span class="author">{{author}}</span>
+                            <span class="author" id="msg_author_{{msg.id}}">{{author}}</span>
                         </div>
                     </div>
                     <div class="level-right is-italic">
                         <div class="level-item">
-                            <span class="date">{{msg.timestamp|date_fmt('auto_day')}}</span>
+                            <span class="date" id="msg_date_{{msg.id}}">{{msg.timestamp|date_fmt('auto_day')}}</span>
+                            <div id="status_icons_{{msg.id}}" class="status-icons level-item has-padding-left">
+                                {% if msg.encrypted %}
+                                    {{ icon('lock-filled', cls='icon is-small has-text-success') }}
+                                {% else %}
+                                    {{ icon('lock-open', cls='icon is-small has-text-danger') }}
+                                {% endif %}
+                                {% if msg.received %}
+                                    {{ icon('ok', cls='icon is-small has-text-link') }}
+                                {% endif %}
+                                {% if msg.edited %}
+                                    {{ icon('pencil', cls='icon is-small has-text-info') }}
+                                {% endif %}
+                            </div>
                         </div>
                     </div>
                 </nav>
             {% endif -%}
-            <p class="msg_body has-whitespace-pre-wrap">
-            {{- msg.html or (msg.text|urlize(nofollow=true, target="_blank")) -}}
+            <p class="msg_body has-whitespace-pre-wrap" id="msg_body_{{msg.id}}" style="margin: 0;">
+            {{- msg.html or (msg.text|urlize) -}}
             </p>
+            <div id="actions_{{msg.id}}" class="level is-mobile actions mb-0">
+                <div class="level-right">
+                    {#{{ icon('share', cls='icon is-small action-button', id='msg_share_{{msg.id}}') }} #}
+                    {{ icon('dot-3', cls='icon is-small action-button', id='msg_actions_{{msg.id}}') }}
+                </div>
+            </div>
+            <div id="msg_reactions_{{msg.id}}" style="margin-top: 0.5em;">
+                <!-- Reactions will go here -->
+            </div>
+        {% if msg.attachments %}
+            <div class="message-attachments pt-2">
+                {%- for attachment in msg.attachments %}
+                    <figure class="image message-attachment">
+                        {%- if attachment.media_type|media_type_main == 'image' %}
+                            <img src="{{attachment.sources[0].url}}" alt="{{attachment.name}}">
+                        {%- else %}
+                            {{ icon('doc', cls='icon') }}
+                        {%- endif %}
+                        <figcaption class="has-text-centered is-size-7">
+                            <a href="{{attachment.sources[0].url}}" target="_blank" class="has-text-grey">{{attachment.name}}</a>
+                        </figcaption>
+                    </figure>
+                {%- endfor %}
+            </div>
+        {% endif %}
         </div>
     </div>
 </div>
--- a/sat_templates/templates/bulma/static/chat.css	Thu Jun 22 16:31:26 2023 +0200
+++ b/sat_templates/templates/bulma/static/chat.css	Wed Jun 28 10:40:50 2023 +0200
@@ -1,10 +1,139 @@
 #chat-panel {
-	height: calc(100vh - 3.25rem);
-    padding-top: 1rem;
-    display: flex;
-    flex-direction: column;
+    height: calc(100vh - 3.25rem);
 }
 
 #messages {
-    overflow: auto;
+    overflow-y: auto;
+}
+
+#attachments {
+    overflow-x: auto;
+    white-space: nowrap;
+}
+
+#message_input {
+    resize: None;
+    max-height: 20rem;
+    min-height: 48px;
+}
+
+.is-chat-message {
+    transition: all 0.3s ease;
+    padding-left: 1.5em;
+}
+
+.is-chat-message:hover {
+    background-color: #f5f5f5;
+    box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
+}
+
+.message-attachment {
+    max-width: 20rem;
+}
+
+.status-icons {
+    padding-bottom: 0.4rem;
+}
+
+.actions {
+    position: absolute;
+    right: 5px;
+    bottom: 5px;
+    opacity: 0;
+}
+
+.is-chat-message:hover .actions {
+    opacity: 1;
+}
+
+.action-button {
+    box-sizing: border-box;
+    margin: 0 0.2rem;
+}
+
+.action-button:hover {
+    box-shadow: 0 0 0 10px rgba(0,0,0,0.1);
+    border-radius: 50%;
+    transition: box-shadow 0.3s ease;
+}
+
+.has-padding-left {
+    padding-left: 0.5em;
+}
+
+#attach_button, #send_button {
+    height: 100%;
 }
+
+/* attachments */
+
+#attachments {
+    opacity: 1;
+    max-height: 1000px;
+    transition: opacity 0.5s ease-in-out, max-height 0.5s ease-in-out, padding 0.5s ease-in-out, margin 0.5s ease-in-out;
+    overflow-x: auto;
+    overflow-y: hidden;
+    padding: 1.25rem 0;
+    margin: 0;
+}
+
+#attachments.is-contracted {
+    opacity: 0;
+    max-height: 0;
+    padding: 0;
+}
+
+.attachment-preview {
+    position: relative;
+    border: 1px solid #dbdbdb;
+    padding: 0.3rem 0.5rem;
+    border-radius: 4px;
+    background-color: #f5f5f5;
+    width: 9rem;
+    height: 6rem;
+}
+
+.thumbnail-container {
+    width: 150px;
+    height: 80px;
+    overflow: hidden;
+    position: relative;
+}
+.icon {
+    width: 60px;
+    height: 60px;
+}
+
+.thumbnail-image {
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    height: 100%;
+    width: auto;
+    transform: translate(-50%, -50%);
+}
+
+.attachment-name {
+    text-overflow: ellipsis;
+    overflow: hidden;
+    white-space: nowrap;
+    max-width: 100%;
+    font-size: 0.8em;
+    letter-spacing: 0.02em;
+    text-align: center;
+    margin-top: auto;
+}
+
+.thumbnail-image:empty {
+    left: 50%;
+    top: 50%;
+    width: 8rem;
+    height: auto;
+    transform: translate(-50%, -50%);
+}
+
+.attachment-delete-button {
+    position: absolute;
+    top: -10px;
+    right: -10px;
+}