changeset 371:a5a80d761e3e

bulma (call): update template to integrate call features: previously, call template was a minimum UI for testing implementation. This commit introduce a usable UI with search interface, mute and full screen button, animations, and other UI/UX improvments. rel 423
author Goffi <goffi@goffi.org>
date Wed, 09 Aug 2023 00:11:39 +0200
parents 281d1c958d56
children a603cf0fa5d1
files sat_templates/templates/bulma/call/call.html sat_templates/templates/bulma/call/call_avatar.html sat_templates/templates/bulma/call/call_button.html sat_templates/templates/bulma/call/call_status.html sat_templates/templates/bulma/chat/message.html sat_templates/templates/bulma/static/call.css sat_templates/templates/bulma/static/styles.css
diffstat 7 files changed, 292 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/sat_templates/templates/bulma/call/call.html	Mon Jul 10 15:43:49 2023 +0200
+++ b/sat_templates/templates/bulma/call/call.html	Wed Aug 09 00:11:39 2023 +0200
@@ -4,32 +4,76 @@
 {% endif %}
 
 {% block body %}
-<section class="section">
+    {{ icon_defs(
+    "resize-full", "resize-small", "volume-up", "videocam", "dot-3-vert", "wrench", "user-circle"
+    ) }}
+    <audio id="audio_player" class="is-hidden" src="{{media_path}}sounds/notifications/ring_1.mp3" preload="auto" loop></audio>
+    <section class="section is-full-below-menu" style="position: relative" >
+    <div id="containers_wrapper">
+
+    {# Search #}
+    <div id="search_container" class="is-overlay">
+        <div id="search_header" class="columns is-1">
+            <div class="column">
+                <input class="input" type="search" id="search" placeholder="Enter contact's name or address">
+            </div>
 
-    <div class="call_box">
-        <video id="remote_video" autoplay playsinline></video>
-        <video id="local_video" autoplay playsinline muted></video>
+        <div class="column is-narrow buttons has-addons">
+            <button class="button is-primary" id="call_btn">
+                <i class="icon-videocam" aria-hidden="true"></i>
+                {% trans %}Video Call{% endtrans %}
+            </button>
+            <button class="button is-primary" id="toggle_call_mode_btn">
+                <span class="icon is-small">
+                    <i class="icon-exchange" aria-hidden="true"></i>
+                </span>
+            </button>
+        </div>
+        </div>
+
+        <div id="contacts" class="columns is-multiline is-mobile">
+        </div>
+
     </div>
 
-    <div class="field is-horizontal">
-        <div class="field-label is-normal">
-            <label class="label" for="jid">{% trans %}Callee JID{% endtrans %}</label>
-        </div>
-        <div class="field-body">
-            <div class="field">
-                <div class="control">
-                    <input class="input" type="text" id="callee_jid" value="louise@tazar3.int">
+    {# Calls #}
+    <div class="is-hidden is-flex is-flex-direction-column" id="call_container">
+
+        <div class="columns is-1 is-centered is-vcentered m-0" id="call_header">
+            <div class="column p-0">
+                <div class="columns is-mobile is-1 is-vcentered m-0">
+                    <div class="column is-narrow px-0" id="call_avatar_wrapper"></div>
+                    <div class="column" id="call_status_wrapper"></div>
                 </div>
             </div>
-            <div class="field">
-                <div class="control">
-                    <button class="button is-primary" id="call_btn">&#128222; {% trans %}Call{% endtrans %}</button>
-                    <button class="button is-hidden" id="hangup_btn">{% trans %}Hang Up{% endtrans %}</button>
-                </div>
+            <div class="column is-narrow has-text-centered px-0" id="hangup_wrapper">
+                <button class="button is-danger" id="hangup_btn">{% trans %}Hang Up{% endtrans %}</button>
+            </div>
+        </div>
+
+        <div id="call_box" class="is-relative mt-3 is-flex-grow-1">
+            <video id="remote_video" class="is-video-only" autoplay playsinline></video>
+            <div class="fullscreen-btn is-video-only">
+                <button class="button is-light" id="full_screen_btn">
+                    {{ icon('resize-full', cls='image is-24x24 is-inline-block') }}
+                </button>
+                <button class="button is-light is-hidden" id="exit_full_screen_btn">
+                    {{ icon('resize-small', cls='image is-24x24 is-inline-block') }}
+                </button>
+            </div>
+            <video id="local_video" class="is-video-only" autoplay playsinline muted></video>
+
+            <div class="controls is-flex is-justify-content-center is-align-items-center p-4">
+                <button class="button is-success mx-2" id="mute_audio_btn">
+                    {{ icon('volume-up', cls='image is-24x24 is-inline-block') }}
+                </button>
+                <button class="button is-success mx-2 is-video-only" id="mute_video_btn">
+                    {{ icon('videocam', cls='image is-24x24 is-inline-block') }}
+                </button>
             </div>
         </div>
     </div>
 
-
+</div>
 </section>
 {% endblock body %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sat_templates/templates/bulma/call/call_avatar.html	Wed Aug 09 00:11:39 2023 +0200
@@ -0,0 +1,3 @@
+{% import 'components/avatar.html' as avatar with context %}
+
+{{ avatar.avatar(entity, "is-64x64") }}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sat_templates/templates/bulma/call/call_button.html	Wed Aug 09 00:11:39 2023 +0200
@@ -0,0 +1,9 @@
+<button class="button {% if call_mode == 'video' %}is-success{% else %}is-dark{% endif %}" id="call_btn">
+    {% if call_mode == 'video' %}
+        <i class="icon-videocam" aria-hidden="true"></i>
+        {% trans %}Video Call{% endtrans %}
+    {% else %}
+        <i class="icon-phone" aria-hidden="true"></i>
+        {% trans %}Audio Call{% endtrans %}
+    {% endif %}
+</button>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sat_templates/templates/bulma/call/call_status.html	Wed Aug 09 00:11:39 2023 +0200
@@ -0,0 +1,8 @@
+{% if status == none %}
+    <div class="call_status notification is-info column my-0">
+    </div>
+{% elif status == "dialing" %}
+    <div class="call_status notification is-info column my-0">
+        <p>{% trans %}Calling {{name}}…{% endtrans %}</p>
+    </div>
+{% endif %}
--- a/sat_templates/templates/bulma/chat/message.html	Mon Jul 10 15:43:49 2023 +0200
+++ b/sat_templates/templates/bulma/chat/message.html	Wed Aug 09 00:11:39 2023 +0200
@@ -63,7 +63,7 @@
                             {{ 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>
+                            <a href="{{attachment.sources[0].url if attachment.sources}}" target="_blank" class="has-text-grey">{{attachment.name}}</a>
                         </figcaption>
                     </figure>
                 {%- endfor %}
--- a/sat_templates/templates/bulma/static/call.css	Mon Jul 10 15:43:49 2023 +0200
+++ b/sat_templates/templates/bulma/static/call.css	Wed Aug 09 00:11:39 2023 +0200
@@ -1,11 +1,14 @@
+#containers_wrapper {
+    position: relative;
+    height: 100%;
+    width: 100%;
 
-.call_box {
+}
+
+#call_container {
+  position: absolute;
+  height: 100%;
   width: 100%;
-  height: 500px;
-  position: relative;
-  overflow: hidden;
-  border: 1px solid #ddd;
-  margin-bottom: 15px;
 }
 
 #remote_video, #local_video {
@@ -13,7 +16,8 @@
   box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.1);
   width: 100%;
   height: 100%;
-  object-fit: cover;
+  object-fit: contain;
+  background-color: #000;
 }
 
 #remote_video {
@@ -22,11 +26,56 @@
   left: 0;
 }
 
+#hangup_btn {
+    padding-top: 2rem;
+    padding-bottom: 2rem;
+}
+
+.fullscreen-btn {
+  position: absolute;
+  top: 10px;
+  right: 10px;
+  z-index: 2;
+}
+
 #local_video {
   position: absolute;
-  bottom: 10px;
-  right: 10px;
+  bottom: 0;
+  right: 0;
   width: 30%;
   height: 30%;
 }
 
+.controls {
+  position: absolute;
+  bottom: 10px;
+  left: 0;
+  right: 0;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 2;
+}
+
+.muted::after {
+    content: "/";
+    position: absolute;
+    font-size: 50px;
+    color: red;
+    top: 43%;
+    left: 52%;
+    transform: translate(-50%, -50%) rotate(45deg);
+}
+
+.dropdown .dropdown-menu {
+  display: none;
+}
+
+.dropdown.is-active .dropdown-menu {
+  display: block;
+}
+
+.call_status {
+    padding-top: 1.3rem;
+    padding-bottom: 1.3rem;
+}
--- a/sat_templates/templates/bulma/static/styles.css	Mon Jul 10 15:43:49 2023 +0200
+++ b/sat_templates/templates/bulma/static/styles.css	Wed Aug 09 00:11:39 2023 +0200
@@ -18,6 +18,12 @@
     overflow: hidden;
 }
 
+.is-full-below-menu {
+    /* full viewport minus top menu height */
+    position:relative;
+    height: calc(100vh - 52px);
+}
+
 .has-whitespace-pre-wrap {
     white-space: pre-wrap;
 }
@@ -613,3 +619,148 @@
     transform: rotate(359deg);
   }
 }
+
+
+/**************
+ * animations *
+ *************/
+
+/* Fade In */
+
+@keyframes fade-in {
+  0% {
+    opacity: 0;
+  }
+  100% {
+    opacity: 1;
+  }
+}
+
+.fade-in {
+  animation: fade-in 0.5s ease-in forwards;
+}
+
+@keyframes fade-in-x {
+  0% {
+    opacity: 0;
+    transform: scaleX(0);
+  }
+  100% {
+    opacity: 1;
+    transform: scaleX(1);
+  }
+}
+
+.fade-in-x {
+  animation: fade-in-x 0.5s ease-in forwards;
+}
+
+@keyframes fade-in-y {
+  0% {
+    opacity: 0;
+    transform: scaleY(0);
+  }
+  100% {
+    opacity: 1;
+    transform: scaleY(1);
+  }
+}
+
+.fade-in-y {
+  animation: fade-in-y 0.5s ease-in forwards;
+}
+
+@keyframes fade-in-xy {
+  0% {
+    opacity: 0;
+    transform: scale(0);
+  }
+  100% {
+    opacity: 1;
+    transform: scale(1);
+  }
+}
+
+.fade-in-xy {
+  animation: fade-in-xy 0.5s ease-in forwards;
+}
+
+/* Fade Out */
+
+@keyframes fade-out {
+  0% {
+    opacity: 1;
+  }
+  100% {
+    opacity: 0;
+  }
+}
+
+.fade-out {
+  animation: fade-out 0.5s ease-in forwards;
+}
+
+@keyframes fade-out-x {
+  0% {
+    opacity: 1;
+    transform: scaleX(1);
+  }
+  100% {
+    opacity: 0;
+    transform: scaleX(0);
+  }
+}
+
+.fade-out-x {
+  animation: fade-out-x 0.5s ease-in forwards;
+}
+
+@keyframes fade-out-y {
+  0% {
+    opacity: 1;
+    transform: scaleY(1);
+  }
+  100% {
+    opacity: 0;
+    transform: scaleY(0);
+  }
+}
+
+.fade-out-y {
+  animation: fade-out-y 0.5s ease-in forwards;
+}
+
+@keyframes fade-out-xy {
+  0% {
+    opacity: 1;
+    transform: scale(1);
+  }
+  100% {
+    opacity: 0;
+    transform: scale(0);
+  }
+}
+
+.fade-out-xy {
+  animation: fade-out-xy 0.5s ease-in forwards;
+}
+
+/* Slide In */
+@keyframes slide-in {
+  0% {
+    transform: translateY(100%);
+    opacity: 0;
+  }
+  100% {
+    transform: translateY(0);
+    opacity: 1;
+  }
+}
+
+.slide-in {
+  animation: slide-in 0.5s ease-in-out forwards;
+}
+
+.animation-reverse {
+  animation-direction: reverse;
+}