Index: src/chat.js ================================================================== --- src/chat.js +++ src/chat.js @@ -7,19 +7,54 @@ const E1 = function(selector){ const e = document.querySelector(selector); if(!e) throw new Error("missing required DOM element: "+selector); return e; }; + + (function(){ + let dbg = document.querySelector('#debugMsg'); + if(dbg){ + /* This can inadvertently influence our flexbox layouts, so move + it out of the way. */ + D.append(document.body,dbg); + } + })(); + const isInViewport = function(e) { const rect = e.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); }; + + const ForceResizeKludge = 0 ? function(){} : (function(){ + /* Workaround for Safari mayhem regarding use of vh CSS units.... + We tried to use vh units to set the content area size for the + chat layout, but Safari chokes on that, so we calculate that + height here: 85% when in "normal" mode and 95% in chat-only + mode. Larger than ~95% is too big for Firefox on Android, + causing the input area to move off-screen. */ + const contentArea = E1('div.content'), + bcl = document.body.classList; + const resized = function(){ + const wh = window.innerHeight, + mult = bcl.contains('chat-only-mode') ? 0.95 : 0.85; + contentArea.style.maxHeight = (wh * mult)+"px"; + //console.debug("resized.",wh, mult, window.getComputedStyle(contentArea).maxHeight); + }; + var doit; + window.addEventListener('resize',function(ev){ + clearTimeout(doit); + doit = setTimeout(resized, 100); + }, false); + resized(); + return resized; + })(); + const Chat = (function(){ const cs = { e:{/*map of certain DOM elements.*/ messageInjectPoint: E1('#message-inject-point'), pageTitle: E1('head title'), @@ -120,26 +155,30 @@ ], /* Injects element e as a new row in the chat, at the top of the list if atEnd is falsy, else at the end of the list, before the load-history widget. */ injectMessageElem: function f(e, atEnd){ - const mip = atEnd ? this.e.loadOlderToolbar : this.e.messageInjectPoint, - holder = this.e.messagesWrapper; + const mip = atEnd ? this.e.loadOlderToolbar : this.e.messageInjectPoint; + /* Reminder: this placement is kinda odd because of the + flex-direction:column-reverse in this.e.messagesWrapper, + which reverses our directions. */ if(atEnd){ + mip.parentNode.insertBefore(e, mip); + }else{ const fe = mip.nextElementSibling; if(fe) mip.parentNode.insertBefore(e, fe); else D.append(mip.parentNode, e); - }else{ - D.append(holder,e); } if(!atEnd && !this.isMassLoading && e.dataset.xfrom!==Chat.me && !isInViewport(e)){ /* If a new non-history message arrives while the user is scrolled elsewhere, do not scroll to the latest message, but gently alert the user that a new message has arrived. */ F.toast.message("New message has arrived."); + }else if(e.dataset.xfrom===Chat.me){ + e.scrollIntoView(); } }, /** Returns true if chat-only mode is enabled. */ isChatOnlyMode: ()=>document.body.classList.contains('chat-only-mode'), /** @@ -150,11 +189,14 @@ */ chatOnlyMode: function f(yes){ if(undefined === f.elemsToToggle){ f.elemsToToggle = []; document.querySelectorAll( - "body > div.header, body > div.mainmenu, body > div.footer" + ["body > div.header", + "body > div.mainmenu", + "body > div.footer", + "#debugMsg"].join(',') ).forEach((e)=>f.elemsToToggle.push(e)); } if(!arguments.length) yes = true; if(yes === this.isChatOnlyMode()) return this; if(yes){ @@ -165,10 +207,11 @@ D.removeClass(f.elemsToToggle, 'hidden'); D.removeClass(document.body, 'chat-only-mode'); } const msg = document.querySelector('.message-widget'); if(msg) setTimeout(()=>msg.scrollIntoView(),0); + ForceResizeKludge(); return this; }, toggleChatOnlyMode: function(){ return this.chatOnlyMode(!this.isChatOnlyMode()); }, Index: src/default.css ================================================================== --- src/default.css +++ src/default.css @@ -1636,10 +1636,14 @@ body.chat .chat-settings-popup > span.menu-entry > input[type=checkbox] { cursor: inherit; } /** Container for the list of /chat messages. */ body.chat #chat-messages-wrapper { + overflow: auto; + max-height: 200em/*we *really* want approx. 85vh*/; + display: flex; + flex-direction: column-reverse/*necessary for scrolling gravity!*/; } body.chat div.content { margin: 0; padding: 0; display: flex; @@ -1650,10 +1654,18 @@ changes #chat-messages-wrapper's "gravity" for purposes of scrolling! If we instead use flex-direction:column then each new message pushes #chat-input-area down further off the screen! */ align-items: stretch; +} +body.chat.chat-only-mode div.content { + /*max-height: 95vh*//*larger than approx. this is too big for Firefox on Android*/; + /* Some skins set margins and a max-width on div.content, but we + needn't(?) honor those in chat-only mode. */ + margin: 0; + width: 100%; + max-width: 100%; } /* Wrapper for /chat user input controls */ body.chat #chat-input-area { display: flex; flex-direction: column; @@ -1660,12 +1672,10 @@ padding: 0.5em 1em; border-bottom: none; border-top: 1px solid black; margin-bottom: 0; margin-top: 0.5em; - position: initial /*sticky currently disabled due to scrolling-related issues*/; - bottom: 0; } /* Widget holding the chat message input field, send button, and settings button. */ body.chat #chat-input-line { display: flex; @@ -1716,6 +1726,10 @@ flex: 0 1 auto; padding: 0.5em 1em; margin-left: 0.5em; white-space: pre; font-family: monospace; +} +body.chat #chat-drop-details img { + max-width: 45%; + max-height: 45%; }