Fossil SCM

chat: re-integrated JS-based div.content resizer to do approximately what the preferred 'vh' CSS units would, but upon which Safari apparently chokes. Message area now gets a scrollbar. This works reasonably well on FF/Chrome on both Linux and Android. The jury is still out on Safari.

stephan 2020-12-27 04:30 trunk
Commit d488f5c66c10b351045a27bcae64351091dd2f4c60b007dda1cf57c5625bc337
2 files changed +34 -4 +4
+34 -4
--- src/chat.js
+++ src/chat.js
@@ -16,10 +16,35 @@
1616
rect.left >= 0 &&
1717
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
1818
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
1919
);
2020
};
21
+
22
+ const ForceResizeKludge = 0 ? function(){} : (function(){
23
+ /* Workaround for Safari mayhem regarding use of vh CSS units....
24
+ We tried to use vh units to set the content area size for the
25
+ chat layout, but Safari chokes on that, so we calculate that
26
+ height here: 85% when in "normal" mode and 95% in chat-only
27
+ mode. Larger than ~95% is too big for Firefox on Android,
28
+ causing the input area to move off-screen. */
29
+ const contentArea = E1('div.content'),
30
+ bcl = document.body.classList;
31
+ const resized = function(){
32
+ const wh = window.innerHeight,
33
+ mult = bcl.contains('chat-only-mode') ? 0.95 : 0.85;
34
+ contentArea.style.maxHeight = (wh * mult)+"px";
35
+ console.debug("resized.",wh, mult, window.getComputedStyle(contentArea).maxHeight);
36
+ };
37
+ var doit;
38
+ window.addEventListener('resize',function(ev){
39
+ clearTimeout(doit);
40
+ doit = setTimeout(resized, 100);
41
+ }, false);
42
+ resized();
43
+ return resized;
44
+ })();
45
+
2146
const Chat = (function(){
2247
const cs = {
2348
e:{/*map of certain DOM elements.*/
2449
messageInjectPoint: E1('#message-inject-point'),
2550
pageTitle: E1('head title'),
@@ -120,26 +145,30 @@
120145
],
121146
/* Injects element e as a new row in the chat, at the top of the
122147
list if atEnd is falsy, else at the end of the list, before
123148
the load-history widget. */
124149
injectMessageElem: function f(e, atEnd){
125
- const mip = atEnd ? this.e.loadOlderToolbar : this.e.messageInjectPoint,
126
- holder = this.e.messagesWrapper;
150
+ const mip = atEnd ? this.e.loadOlderToolbar : this.e.messageInjectPoint;
151
+ /* Reminder: this placement is kinda odd because of the
152
+ flex-direction:column-reverse in this.e.messagesWrapper,
153
+ which reverses our directions. */
127154
if(atEnd){
155
+ mip.parentNode.insertBefore(e, mip);
156
+ }else{
128157
const fe = mip.nextElementSibling;
129158
if(fe) mip.parentNode.insertBefore(e, fe);
130159
else D.append(mip.parentNode, e);
131
- }else{
132
- D.append(holder,e);
133160
}
134161
if(!atEnd && !this.isMassLoading
135162
&& e.dataset.xfrom!==Chat.me && !isInViewport(e)){
136163
/* If a new non-history message arrives while the user is
137164
scrolled elsewhere, do not scroll to the latest
138165
message, but gently alert the user that a new message
139166
has arrived. */
140167
F.toast.message("New message has arrived.");
168
+ }else if(e.dataset.xfrom===Chat.me){
169
+ e.scrollIntoView();
141170
}
142171
},
143172
/** Returns true if chat-only mode is enabled. */
144173
isChatOnlyMode: ()=>document.body.classList.contains('chat-only-mode'),
145174
/**
@@ -165,10 +194,11 @@
165194
D.removeClass(f.elemsToToggle, 'hidden');
166195
D.removeClass(document.body, 'chat-only-mode');
167196
}
168197
const msg = document.querySelector('.message-widget');
169198
if(msg) setTimeout(()=>msg.scrollIntoView(),0);
199
+ ForceResizeKludge();
170200
return this;
171201
},
172202
toggleChatOnlyMode: function(){
173203
return this.chatOnlyMode(!this.isChatOnlyMode());
174204
},
175205
--- src/chat.js
+++ src/chat.js
@@ -16,10 +16,35 @@
16 rect.left >= 0 &&
17 rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
18 rect.right <= (window.innerWidth || document.documentElement.clientWidth)
19 );
20 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21 const Chat = (function(){
22 const cs = {
23 e:{/*map of certain DOM elements.*/
24 messageInjectPoint: E1('#message-inject-point'),
25 pageTitle: E1('head title'),
@@ -120,26 +145,30 @@
120 ],
121 /* Injects element e as a new row in the chat, at the top of the
122 list if atEnd is falsy, else at the end of the list, before
123 the load-history widget. */
124 injectMessageElem: function f(e, atEnd){
125 const mip = atEnd ? this.e.loadOlderToolbar : this.e.messageInjectPoint,
126 holder = this.e.messagesWrapper;
 
 
127 if(atEnd){
 
 
128 const fe = mip.nextElementSibling;
129 if(fe) mip.parentNode.insertBefore(e, fe);
130 else D.append(mip.parentNode, e);
131 }else{
132 D.append(holder,e);
133 }
134 if(!atEnd && !this.isMassLoading
135 && e.dataset.xfrom!==Chat.me && !isInViewport(e)){
136 /* If a new non-history message arrives while the user is
137 scrolled elsewhere, do not scroll to the latest
138 message, but gently alert the user that a new message
139 has arrived. */
140 F.toast.message("New message has arrived.");
 
 
141 }
142 },
143 /** Returns true if chat-only mode is enabled. */
144 isChatOnlyMode: ()=>document.body.classList.contains('chat-only-mode'),
145 /**
@@ -165,10 +194,11 @@
165 D.removeClass(f.elemsToToggle, 'hidden');
166 D.removeClass(document.body, 'chat-only-mode');
167 }
168 const msg = document.querySelector('.message-widget');
169 if(msg) setTimeout(()=>msg.scrollIntoView(),0);
 
170 return this;
171 },
172 toggleChatOnlyMode: function(){
173 return this.chatOnlyMode(!this.isChatOnlyMode());
174 },
175
--- src/chat.js
+++ src/chat.js
@@ -16,10 +16,35 @@
16 rect.left >= 0 &&
17 rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
18 rect.right <= (window.innerWidth || document.documentElement.clientWidth)
19 );
20 };
21
22 const ForceResizeKludge = 0 ? function(){} : (function(){
23 /* Workaround for Safari mayhem regarding use of vh CSS units....
24 We tried to use vh units to set the content area size for the
25 chat layout, but Safari chokes on that, so we calculate that
26 height here: 85% when in "normal" mode and 95% in chat-only
27 mode. Larger than ~95% is too big for Firefox on Android,
28 causing the input area to move off-screen. */
29 const contentArea = E1('div.content'),
30 bcl = document.body.classList;
31 const resized = function(){
32 const wh = window.innerHeight,
33 mult = bcl.contains('chat-only-mode') ? 0.95 : 0.85;
34 contentArea.style.maxHeight = (wh * mult)+"px";
35 console.debug("resized.",wh, mult, window.getComputedStyle(contentArea).maxHeight);
36 };
37 var doit;
38 window.addEventListener('resize',function(ev){
39 clearTimeout(doit);
40 doit = setTimeout(resized, 100);
41 }, false);
42 resized();
43 return resized;
44 })();
45
46 const Chat = (function(){
47 const cs = {
48 e:{/*map of certain DOM elements.*/
49 messageInjectPoint: E1('#message-inject-point'),
50 pageTitle: E1('head title'),
@@ -120,26 +145,30 @@
145 ],
146 /* Injects element e as a new row in the chat, at the top of the
147 list if atEnd is falsy, else at the end of the list, before
148 the load-history widget. */
149 injectMessageElem: function f(e, atEnd){
150 const mip = atEnd ? this.e.loadOlderToolbar : this.e.messageInjectPoint;
151 /* Reminder: this placement is kinda odd because of the
152 flex-direction:column-reverse in this.e.messagesWrapper,
153 which reverses our directions. */
154 if(atEnd){
155 mip.parentNode.insertBefore(e, mip);
156 }else{
157 const fe = mip.nextElementSibling;
158 if(fe) mip.parentNode.insertBefore(e, fe);
159 else D.append(mip.parentNode, e);
 
 
160 }
161 if(!atEnd && !this.isMassLoading
162 && e.dataset.xfrom!==Chat.me && !isInViewport(e)){
163 /* If a new non-history message arrives while the user is
164 scrolled elsewhere, do not scroll to the latest
165 message, but gently alert the user that a new message
166 has arrived. */
167 F.toast.message("New message has arrived.");
168 }else if(e.dataset.xfrom===Chat.me){
169 e.scrollIntoView();
170 }
171 },
172 /** Returns true if chat-only mode is enabled. */
173 isChatOnlyMode: ()=>document.body.classList.contains('chat-only-mode'),
174 /**
@@ -165,10 +194,11 @@
194 D.removeClass(f.elemsToToggle, 'hidden');
195 D.removeClass(document.body, 'chat-only-mode');
196 }
197 const msg = document.querySelector('.message-widget');
198 if(msg) setTimeout(()=>msg.scrollIntoView(),0);
199 ForceResizeKludge();
200 return this;
201 },
202 toggleChatOnlyMode: function(){
203 return this.chatOnlyMode(!this.isChatOnlyMode());
204 },
205
--- src/default.css
+++ src/default.css
@@ -1636,10 +1636,14 @@
16361636
body.chat .chat-settings-popup > span.menu-entry > input[type=checkbox] {
16371637
cursor: inherit;
16381638
}
16391639
/** Container for the list of /chat messages. */
16401640
body.chat #chat-messages-wrapper {
1641
+ overflow: auto;
1642
+ max-height: 200em/*we *really* want approx. 85vh*/;
1643
+ display: flex;
1644
+ flex-direction: column-reverse/*necessary for scrolling gravity!*/;
16411645
}
16421646
body.chat div.content {
16431647
margin: 0;
16441648
padding: 0;
16451649
display: flex;
16461650
--- src/default.css
+++ src/default.css
@@ -1636,10 +1636,14 @@
1636 body.chat .chat-settings-popup > span.menu-entry > input[type=checkbox] {
1637 cursor: inherit;
1638 }
1639 /** Container for the list of /chat messages. */
1640 body.chat #chat-messages-wrapper {
 
 
 
 
1641 }
1642 body.chat div.content {
1643 margin: 0;
1644 padding: 0;
1645 display: flex;
1646
--- src/default.css
+++ src/default.css
@@ -1636,10 +1636,14 @@
1636 body.chat .chat-settings-popup > span.menu-entry > input[type=checkbox] {
1637 cursor: inherit;
1638 }
1639 /** Container for the list of /chat messages. */
1640 body.chat #chat-messages-wrapper {
1641 overflow: auto;
1642 max-height: 200em/*we *really* want approx. 85vh*/;
1643 display: flex;
1644 flex-direction: column-reverse/*necessary for scrolling gravity!*/;
1645 }
1646 body.chat div.content {
1647 margin: 0;
1648 padding: 0;
1649 display: flex;
1650

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button