@@ -13,6 +13,10 @@ var userAddress = "";
1313
1414const attachBar = document . getElementById ( "attach-bar" ) ;
1515
16+ const messagesEl = document . getElementById ( "messages" ) ;
17+ const chatHolderEl = document . getElementById ( "chatholder" ) ;
18+ const wrapEl = document . getElementById ( "wrap" ) ;
19+
1620function onChatScreenLoad ( ) {
1721 document . getElementById ( "chat_input" ) . focus ( ) ;
1822
@@ -103,9 +107,9 @@ function setBotMode(bot, cost, costText, admin, botDescription, notificationsStr
103107 document . getElementsByClassName ( "spixi-channel-bar" ) [ 0 ] . style . display = "table" ;
104108
105109 if ( isPaid ) {
106- document . getElementById ( "messages" ) . style . height = "calc(100vh - 175px)" ;
110+ messagesEl . style . height = "calc(100vh - 175px)" ;
107111 } else {
108- document . getElementById ( "messages" ) . style . height = "calc(100vh - 150px)" ;
112+ messagesEl . style . height = "calc(100vh - 150px)" ;
109113 }
110114
111115 } else {
@@ -159,6 +163,11 @@ function setInitialStickyDate() {
159163}
160164
161165function onChatScreenLoaded ( ) {
166+ debouncedScrollToBottom ( ) ;
167+ if ( SL_Platform == "Xamarin-iOS" ) {
168+ debouncedIOSFixer ( ) ;
169+ }
170+
162171 document . getElementById ( "chat_input" ) . focus ( ) ;
163172 updateChatInputPlaceholder ( ) ;
164173
@@ -328,9 +337,8 @@ var chatInput = document.getElementById("chat_input");
328337
329338function scrollToBottom ( ) {
330339 if ( shouldScroll ( ) ) {
331- var messagesDiv = document . getElementById ( 'messages' ) ;
332340 requestAnimationFrame ( function ( ) {
333- messagesDiv . scrollTop = messagesDiv . scrollHeight ;
341+ messagesEl . scrollTop = messagesEl . scrollHeight ;
334342 } ) ;
335343 }
336344}
@@ -343,12 +351,12 @@ $("#chat_input").focus(function (event) {
343351 if (shouldScroll()) {
344352 setTimeout(function () {
345353 //document.getElementById("chatholder").scrollIntoView(false);
346- var messagesDiv = document.getElementById('messages');
347- messagesDiv .scrollTop = messagesDiv .scrollHeight;
354+ var messagesEl = document.getElementById('messages');
355+ messagesEl .scrollTop = messagesEl .scrollHeight;
348356 // Hack for slow devices
349357 setTimeout(function () {
350358 //document.getElementById("chatholder").scrollIntoView(false);
351- messagesDiv .scrollTop = messagesDiv .scrollHeight;
359+ messagesEl .scrollTop = messagesEl .scrollHeight;
352360 }, 800);
353361 }, 200);
354362 }*/
@@ -401,9 +409,6 @@ function clearInput() {
401409 document . getElementById ( "chat_send" ) . className = "chatbar-sendbutton" ;
402410}
403411
404- var messagesEl = document . getElementById ( "messages" ) ;
405- var chatHolderEl = document . getElementById ( "chatholder" ) ;
406-
407412let scrollTimeout ;
408413
409414messagesEl . addEventListener ( "scroll" , ( ) => {
@@ -463,7 +468,6 @@ function addReactions(id, reactions) {
463468 reactionsEl . parentNode . removeChild ( reactionsEl ) ;
464469 }
465470
466- const messagesEl = document . getElementById ( "messages" ) ;
467471 if ( messagesEl ) {
468472 messagesEl . scrollTop = messagesEl . scrollHeight ;
469473 }
@@ -702,7 +706,6 @@ function addText(id, address, nick, avatar, text, time, className) {
702706
703707// TODO: optimize and merge this function with addText
704708function adjustLastestBubbles ( ) {
705- var messagesEl = document . getElementById ( "messages" ) ;
706709 var bubbles = messagesEl . querySelectorAll ( ".spixi-bubble" ) ;
707710
708711 if ( bubbles . length < 2 ) {
@@ -868,7 +871,7 @@ function addCall(id, message, declined, time) {
868871
869872
870873 if ( append ) {
871- document . getElementById ( "messages" ) . appendChild ( bubbleEl ) ;
874+ messagesEl . appendChild ( bubbleEl ) ;
872875 }
873876
874877 scrollToBottom ( ) ;
@@ -1777,40 +1780,68 @@ function getCaretPosition(editableDiv) {
17771780}
17781781
17791782// Fix for iOS toolbar offscreen issue when soft keyboard is shown
1780- var initialOffset = window . outerHeight - window . innerHeight ;
1781- var msgHeight = document . getElementById ( "messages" ) . style . height ;
1783+ const initialOffset = window . outerHeight - window . innerHeight ;
1784+ let updatedOffset = initialOffset ;
1785+ let msgHeight = messagesEl . style . height || ( window . innerHeight - 120 ) + "px" ;
17821786
1783- function iosFixer ( ) {
1784- var newOffset = window . outerHeight - window . innerHeight ;
1787+ function iosFixer ( overshoot = 0 ) {
1788+ const newOffset = window . outerHeight - window . innerHeight ;
17851789
1786- if ( newOffset > initialOffset ) {
1787- var diff = newOffset - initialOffset ;
1788- document . getElementById ( "wrap" ) . style . maxHeight = "${window.innerHeight}px" ;
1789- document . getElementById ( "wrap" ) . style . top = diff + "px ";
1790- msgHeight = document . getElementById ( "messages" ) . style . height ;
1790+ if ( newOffset >= updatedOffset ) {
1791+ const diff = newOffset - initialOffset ;
1792+ requestAnimationFrame ( function ( ) {
1793+ wrapEl . style . transition = "top 0.20s ease-out ";
1794+ messagesEl . style . transition = " height 0.20s ease-out" ;
17911795
1792- document . getElementById ( "messages" ) . style . height = ( window . innerHeight - 120 ) + "px" ; // ${newDiff}px";// (msgHeight - diff + 20) + "px";
1796+ wrapEl . style . top = `${ diff + overshoot } px` ;
1797+ messagesEl . style . height = `${ window . innerHeight - overshoot - 120 } px` ;
1798+ debouncedScrollToBottom ( ) ;
1799+ } ) ;
1800+ } else if ( newOffset < updatedOffset && wrapEl . style . top != "0px" ) {
1801+ requestAnimationFrame ( function ( ) {
1802+ wrapEl . style . transition = "top 0.20s ease-out" ;
1803+ messagesEl . style . transition = "height 0.20s ease-out" ;
17931804
1794- scrollToBottom ( ) ;
1795- } else if ( newOffset < initialOffset ) {
1796- document . getElementById ( "wrap" ) . style . maxHeight = '' ;
1797- document . getElementById ( "wrap" ) . style . top = "0px" ;
1798- document . getElementById ( "messages" ) . style . height = msgHeight ;
1805+ wrapEl . style . top = "0px" ;
1806+ messagesEl . style . height = msgHeight ;
1807+ debouncedScrollToBottom ( ) ;
1808+ } ) ;
17991809 }
1800- initialOffset = newOffset ;
1810+ updatedOffset = newOffset ;
18011811}
18021812
1813+ const throttle = ( fn , delay ) => {
1814+ let lastCall = 0 ;
1815+ return ( ...args ) => {
1816+ const now = Date . now ( ) ;
1817+ if ( now - lastCall >= delay ) {
1818+ lastCall = now ;
1819+ fn ( ...args ) ;
1820+ }
1821+ } ;
1822+ } ;
1823+
1824+ const debounce = ( fn , delay ) => {
1825+ let timeout ;
1826+ return ( ...args ) => {
1827+ clearTimeout ( timeout ) ;
1828+ timeout = setTimeout ( ( ) => fn ( ...args ) , delay ) ;
1829+ } ;
1830+ } ;
1831+
1832+ const debouncedScrollToBottom = debounce ( scrollToBottom , 200 ) ;
1833+ const debouncedIOSFixer = debounce ( iosFixer , 25 ) ;
18031834
18041835// Mobile only logic
18051836if ( SL_Platform != "Xamarin-WPF" ) {
1806-
18071837 if ( SL_Platform == "Xamarin-iOS" ) {
18081838 window . visualViewport . addEventListener ( 'resize' , ( ) => {
1809- iosFixer ( ) ;
1839+ debouncedIOSFixer ( ) ;
1840+ debouncedScrollToBottom ( ) ;
1841+ } ) ;
1842+ } else {
1843+ window . addEventListener ( 'resize' , function ( ) {
1844+ debouncedScrollToBottom ( ) ;
18101845 } ) ;
18111846 }
1812-
1813- window . addEventListener ( 'resize' , function ( ) {
1814- scrollToBottom ( ) ;
1815- } ) ;
18161847}
0 commit comments