[TikiWiki-commits] [Git][tikiwiki/tiki][master ] [ENH] Minichat UI improvement – updated chat bu bble style and message layout

Benoit Grégoire (@benoitg) via TikiWiki-cvs <[email protected]>
Newsgroups gmane.comp.cms.tiki.cvs
Message-ID <68fcdfcb566e8_2cc7432e877021@gitlab-sidekiq-low-urgency-cpu-bound-v2-854849f664-jckhl.mail>

Benoit Grégoire pushed to branch master at Tiki Wiki CMS Groupware / Tiki


Commits:
2904b01f by Yves Ngalamulume at 2025-10-25T14:26:00+00:00
[ENH] Minichat UI improvement – updated chat bubble style and message layout
---
* [ENH] Move remaining SCSS rules to appropriate partials

* [ENH][UI] Improve Minichat interface – message bubbles and layout update

* [ENH][UI] Minichat UI enhancement: message styles and animations

* [ENH] Minichat UI improvement – updated chat bubble style and message layout

See merge request tikiwiki/tiki!8801

- - - - -


6 changed files:

- templates/modules/mod-minichat.tpl
- themes/base_files/css/tiki_base.scss
- themes/base_files/scss/_tiki-menus.scss
- themes/base_files/scss/_tiki-tabs_and_tables.scss
- themes/quartz/scss/_bootswatch.scss
- tiki-minichat_ajax.php


Changes:

=====================================
templates/modules/mod-minichat.tpl
=====================================
@@ -1,18 +1,37 @@
 {tikimodule error=$module_params.error title=$tpl_module_title name="minichat" flip=$module_params.flip decorations=$module_params.decorations nobox=$module_params.nobox notitle=$module_params.notitle}
     {if $tiki_p_chat eq 'y'}
-    <div id='minichatchans' class='btn-group minichatchans mb-2'{if $module_params.nochannelbar && $module_params.nochannelbar != "n"} style="height: 0; visibility: hidden"{/if}></div>
+    <div
+    id="minichatchans"
+    class="btn-group minichatchans mb-2"
+    {if $module_params.nochannelbar && $module_params.nochannelbar != "n"}
+    style="height:0;visibility:hidden"
+    {/if}>
+    </div>
 
-    <div id='minichat' class='minichat well well-sm' style='overflow-x: hidden; overflow-y: auto; height: {$module_rows}em;'></div>
+    <div
+    id="minichat"
+    class="card card-body mb-2 overflow-auto"
+    style="height: {$module_rows}em;">
+    </div>
 
-    <div class="minichatinputs">
-        <form name='minichatinputform' action='javascript:minichatpost();'>
-            <div class="input-group input-group-sm">
-                <input class="form-control" name='minichatinput' id='minichatinput' type='text' autocomplete='off'>
-                <input class="btn btn-primary" type='submit' value="{tr}OK{/tr}">
-            </div>
-        </form>
+    <div class="border-top pt-2 bg-body">
+    <form name="minichatinputform" onsubmit="minichatpost(); return false;">
+    <div class="input-group input-group-sm">
+        <input
+            id="minichatinput"
+            name="minichatinput"
+            type="text"
+            class="form-control rounded-pill"
+            autocomplete="off"
+            placeholder="{tr}Type a message...{/tr}">
+        <button type="submit" class="btn btn-primary rounded-pill">
+            {tr}Send{/tr}
+        </button>
     </div>
-    {else}
+    </form>
+    </div>
+
+{else}
     {tr}You do not have the permission that is needed to use this feature.{/tr}
     {/if}
 {/tikimodule}
@@ -57,29 +76,37 @@
         function minichat_loadJS(file) {
             var head = document.getElementsByTagName('head').item(0);
             var scriptTag = document.getElementById('minichat_loadJS');
+            const chat = document.getElementById('minichat');
             if (scriptTag) head.removeChild(scriptTag);
             script = document.createElement('script');
             script.src = file;
             script.type = 'text/javascript';
             script.id = 'minichat_loadJS';
             head.appendChild(script);
+           
+            chat.scrollTop = chat.scrollHeight;
         }
 
         function minichat_update() {
             var u=minichat_mkurl();
             minichat_loadJS(u);
+            setTimeout(function() {
+            var chatDiv = document.getElementById('minichat');
+                if (chatDiv) chatDiv.scrollTop = chatDiv.scrollHeight;
+            }, 500);
         }
 
         function minichatpost() {
-            var obj=document.getElementById('minichatinput');
-            var value=minichat_urlencode(obj.value);
-
-            var u=minichat_mkurl();
-            if (minichat_selectedchan) u+="&msgon="+minichat_urlencode(minichat_selectedchan.name);
-            u+="&msg="+value;
+            var obj = document.getElementById('minichatinput');
+            var value = minichat_urlencode(obj.value);
 
+            var u = minichat_mkurl();
+            if (minichat_selectedchan) u += "&msgon=" + minichat_urlencode(minichat_selectedchan.name);
+            u += "&msg_chat=" + value;
+           
             minichat_loadJS(u);
-            obj.value='';
+            obj.value = '';
+
         }
 
         function minichat_newelem(type, vals) {


=====================================
themes/base_files/css/tiki_base.scss
=====================================
@@ -50,79 +50,4 @@
 @import "../scss/_tiki-debugger_console.scss";
 @import "../scss/_tiki-show_database_query_log.scss";
 //@import "../scss/_pivot-tiki.scss";
-//@import "../scss/_conversejs-tiki.scss";
-//@import "../scss/_tiki-selectors.scss";
-
-// Sticky tables
-.tiki .table-sticky {
-    overflow: visible !important;
-}
-.tiki .table-sticky thead {
-    position: -webkit-sticky;
-    /* for Safari */
-    position: sticky;
-    top: 0;
-    z-index: 2;
-}
-.tiki .table-sticky tbody th {
-    position: sticky;
-    position: -webkit-sticky;
-    width: 100px;
-    min-width: 100px;
-    max-width: 100px;
-    left: 0px;
-    z-index: 1;
-}
-// Icon to toggle table formatting for small devices
-.toggle-table-wrap .btn {
-    font-family: 'Font Awesome 6 Free';
-    font-weight: 600;
-    font-size: 1.25rem;
-}
-
-li.highlight {
-    background-color: var(--bs-secondary-bg-subtle);
-    transition: all 0.3s ease;
-}
-
-.password-container {
-    position: relative;
-    display: inline-block;
-    width: 100%;
-
-    input {
-        padding-right: 30px;
-    }
-
-    i {
-        position: absolute;
-        right: 10px;
-        top: 50%;
-        transform: translateY(-50%);
-        cursor: pointer;
-        visibility: hidden; /* Hidden by default */
-    }
-}
-/* --- Force all dropdowns to open upwards ---*/
-.dropdown-menu-bottom {
-    top: auto !important;
-    bottom: 100% !important;
-    margin-bottom: .5rem;
-    margin-top: 0 !important;
-    max-height: 65vh;
-    overflow-y: auto;
-    overflow-x: hidden;
-}
-
-.dropdown-menu-top,
-.dropdown-menu-end,
-.dropdown-menu-start {
-  top: 100%;
-  bottom: auto;
-  max-height: 40vh;
-  overflow-y: auto;
-  overflow-x: hidden;
-  z-index: 3000;
-}
-
-/* End of file */
+//@import "../scss/_conversejs-tiki.scss";
\ No newline at end of file


=====================================
themes/base_files/scss/_tiki-menus.scss
=====================================
@@ -153,3 +153,25 @@
     text-rendering: auto;
     -webkit-font-smoothing: antialiased;
 }
+
+/* --- Force all dropdowns to open upwards ---*/
+.dropdown-menu-bottom {
+    top: auto !important;
+    bottom: 100% !important;
+    margin-bottom: .5rem;
+    margin-top: 0 !important;
+    max-height: 65vh;
+    overflow-y: auto;
+    overflow-x: hidden;
+}
+
+.dropdown-menu-top,
+.dropdown-menu-end,
+.dropdown-menu-start {
+  top: 100%;
+  bottom: auto;
+  max-height: 40vh;
+  overflow-y: auto;
+  overflow-x: hidden;
+  z-index: 3000;
+}


=====================================
themes/base_files/scss/_tiki-tabs_and_tables.scss
=====================================
@@ -234,3 +234,32 @@ td.url{
         }
     }
 }
+
+// Sticky tables
+.tiki .table-sticky {
+    overflow: visible !important;
+}
+.tiki .table-sticky thead {
+    position: -webkit-sticky;
+    /* for Safari */
+    position: sticky;
+    top: 0;
+    z-index: 2;
+}
+.tiki .table-sticky tbody th {
+    position: sticky;
+    position: -webkit-sticky;
+    width: 100px;
+    min-width: 100px;
+    max-width: 100px;
+    left: 0px;
+    z-index: 1;
+}
+// Icon to toggle table formatting for small devices
+.toggle-table-wrap .btn {
+    font-family: 'Font Awesome 6 Free';
+    font-weight: 600;
+    font-size: 1.25rem;
+}
+
+


=====================================
themes/quartz/scss/_bootswatch.scss
=====================================
@@ -101,6 +101,30 @@ body {
   border-right: none;
 }
 
+li.highlight {
+    background-color: var(--bs-secondary-bg-subtle);
+    transition: all 0.3s ease;
+}
+
+.password-container {
+    position: relative;
+    display: inline-block;
+    width: 100%;
+
+    input {
+        padding-right: 30px;
+    }
+
+    i {
+        position: absolute;
+        right: 10px;
+        top: 50%;
+        transform: translateY(-50%);
+        cursor: pointer;
+        visibility: hidden; /* Hidden by default */
+    }
+}
+
 .form-select:not([multiple]) {
   transition: border-color .15s ease-in-out;
 


=====================================
tiki-minichat_ajax.php
=====================================
@@ -49,8 +49,8 @@ function initchannelssession($chans)
         $_SESSION['minichat_channels'][] = $channel;
     }
 }
-if (isset($_REQUEST['msg'])) {
-    $msg = $_REQUEST['msg'];
+if (isset($_REQUEST['msg_chat'])) {
+    $msg = $_REQUEST['msg_chat'];
     $msg = strtr($msg, "\n\r\t", "   ");
     $msgon = $_REQUEST['msgon'] ?? null;
     if (empty($msg)) {
@@ -124,14 +124,17 @@ foreach ($chans as $chan) {
     }
     if ($lastid == 0) {
         $result = $tikilib->query("SELECT * FROM tiki_minichat WHERE channel=? ORDER by id desc LIMIT 100", [$channel]);
-        $msgtotal = "";
+        // collect rows, reverse to chronological order (oldest first)
+        $rows = [];
         while ($row = $result->fetchRow()) {
-            if (! $lastid) {
-                $lastid = $row['id'];
-                echo "minichat_updatelastid('$channel', $lastid);\n";
-            }
-            # if timestamp corresponds to previous days than current, show date with display_order according to the global preference
-            # daytmes = day from the time stamp of the message; daytnow = current day;
+            $rows[] = $row;
+        }
+        $rows = array_reverse($rows);
+
+        $msgtotal = "";
+        $prev_user = null;
+        foreach ($rows as $row) {
+            // compute time display (same logic as before)
             $daytmes = date("d/m/y", $row['ts']);
             $daytnow = date("d/m/y");
             if ($daytmes == $daytnow) {
@@ -153,12 +156,39 @@ foreach ($chans as $chan) {
                     $t = date("H:i", $row['ts']);
                 }
             }
-    //TODO: improve matching and replace with better smileys + use global lib
-            $msgtotal = "<span class='minichat_ts'>[$t]</span>&nbsp;<span class='minichat_nick'>&lt;" . ($row['nick'] == '' ? "<em>" . tra('Anonymous') . "</em>" : str_replace('"', '\"', smarty_modifier_userlink($row['user']))) . "&gt;</span> <span class='minichat_msg'>" . htmlentities($row['msg'], ENT_QUOTES, 'UTF-8') . "</span><br>" . $msgtotal;
+
+            $nick_html = ($row['nick'] == '' ? "<em>" . tra('Anonymous') . "</em>" : smarty_modifier_userlink($row['user']));
+            $msg_html = htmlentities($row['msg'], ENT_QUOTES, 'UTF-8');
+            $side_class = ($row['user'] == $user) ? 'mine' : 'other';
+
+            $show_header = ($prev_user !== $row['user']);
+
+            $align_class = ($side_class === 'mine') ? 'justify-content-end' : 'justify-content-start';
+            $card_classes = ($side_class === 'mine') ? 'card text-white bg-info' : 'card bg-light';
+
+            $bubble = "<div class='d-flex mb-2 {$align_class}'>";
+            $bubble .= "<div class='{$card_classes}' style='max-width:70%'>";
+            $bubble .= "<div class='card-body p-2'>";
+            if ($show_header) {
+                $bubble .= "<div class='fw-bold small'>" . $nick_html . "</div>";
+            }
+            $bubble .= "<div class='card-text'>{$msg_html}</div>";
+            $bubble .= "<div class='text-end'><small class='text-muted'>{$t}</small></div>";
+            $bubble .= "</div></div></div>";
+
+            $msgtotal .= $bubble; // append to keep chronological order top->bottom
+            $prev_user = $row['user'];
+        }
+
+        // update lastid with the newest message id (last element in $rows)
+        if (! empty($rows)) {
+            $newlast = $rows[count($rows) - 1]['id'];
+            $lastid = (int)$newlast;
+            echo "minichat_updatelastid(" . json_encode($channel) . ", $lastid);\n";
         }
         $editlib = TikiLib::lib('edit');
         $msgtotal = $editlib->convertSmileysToUnicode($msgtotal);
-        echo "document.getElementById('minichatdiv_'+minichat_getchanid('$channel')).innerHTML=\"$msgtotal\";\n";
+        echo "document.getElementById('minichatdiv_'+minichat_getchanid(" . json_encode($channel) . ")).innerHTML=" . json_encode($msgtotal) . ";\n";
         echo "document.getElementById('minichat').scrollTop=99999;\n";
     }
 }



View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/2904b01ff48ad740231eacf86a95d8edf97863bd

-- 
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/2904b01ff48ad740231eacf86a95d8edf97863bd
You're receiving this email because of your account on gitlab.com.

_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.