Mercurial > libervia-templates
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; +}