Fossil SCM

Some flicker reduction when batch loading chat messages. Minor chat layout tweaks.

stephan 2020-12-27 09:56 trunk
Commit 5e046b64c73fced861b93dce559545e8ea9e9f2df5188b8aa1e09773056c03d7
2 files changed +19 -11 +5 -1
+19 -11
--- src/chat.js
+++ src/chat.js
@@ -206,20 +206,20 @@
206206
else D.append(mip.parentNode, e);
207207
}else{
208208
D.append(holder,e);
209209
this.e.newestMessage = e;
210210
}
211
- if(!atEnd && !this.isMassLoading
211
+ if(!atEnd && !this.isBatchLoading
212212
&& e.dataset.xfrom!==this.me && !isInViewport(e)){
213213
/* If a new non-history message arrives while the user is
214214
scrolled elsewhere, do not scroll to the latest
215215
message, but gently alert the user that a new message
216216
has arrived. */
217217
F.toast.message("New message has arrived.");
218
- }else if(!this.isMassLoading && e.dataset.xfrom===Chat.me){
218
+ }else if(!this.isBatchLoading && e.dataset.xfrom===Chat.me){
219219
this.scheduleScrollOfMsg(e);
220
- }else if(!this.isMassLoading){
220
+ }else if(!this.isBatchLoading){
221221
/* When a message from someone else arrives, we have to
222222
figure out whether or not to scroll it into view. Ideally
223223
we'd just stuff it in the UI and let the flexbox layout
224224
DTRT, but Safari has expressed, in no uncertain terms,
225225
some disappointment with that approach, so we'll
@@ -289,11 +289,11 @@
289289
if(where<0){
290290
Chat.e.messagesWrapper.scrollTop = 0;
291291
}else if(where>0){
292292
Chat.e.messagesWrapper.scrollTop = Chat.e.messagesWrapper.scrollHeight;
293293
}else if(Chat.e.newestMessage){
294
- Chat.e.newestMessage.scrollIntoView();
294
+ Chat.e.newestMessage.scrollIntoView(false);
295295
}
296296
},
297297
toggleChatOnlyMode: function(){
298298
return this.chatOnlyMode(!this.isChatOnlyMode());
299299
},
@@ -918,23 +918,27 @@
918918
);
919919
Chat.disableDuringAjax.push(toolbar);
920920
/* Loads the next n oldest messages, or all previous history if n is negative. */
921921
const loadOldMessages = function(n){
922922
Chat.ajaxStart();
923
+ Chat.e.messagesWrapper.classList.add('loading');
924
+ Chat.isBatchLoading = true;
923925
var gotMessages = false;
924926
fetch("chat-poll?before="+Chat.mnMsg+"&n="+n)
925927
.then(x=>x.json())
926928
.then(function(x){
927929
gotMessages = x.msgs.length;
928930
newcontent(x,true);
929931
})
930932
.catch(e=>Chat.reportError(e))
931933
.finally(function(){
934
+ Chat.isBatchLoading = false;
935
+ Chat.e.messagesWrapper.classList.remove('loading');
932936
if(n<0/*we asked for all history*/
933937
|| 0===gotMessages/*we found no history*/
934938
|| (n>0 && gotMessages<n /*we got fewer history entries than requested*/)
935
- || (false!==gotMessages && n<0 && gotMessages<Chat.loadMessageCount
939
+ || (false!==gotMessages && n===0 && gotMessages<Chat.loadMessageCount
936940
/*we asked for default amount and got fewer than that.*/)){
937941
/* We've loaded all history. Permanently disable the
938942
history-load toolbar and keep it from being re-enabled
939943
via the ajaxStart()/ajaxEnd() mechanism... */
940944
const div = Chat.e.loadOlderToolbar.querySelector('div');
@@ -963,30 +967,34 @@
963967
})()/*end history loading widget setup*/;
964968
965969
async function poll(isFirstCall){
966970
if(poll.running) return;
967971
poll.running = true;
968
- if(isFirstCall) Chat.ajaxStart();
969
- Chat.isMassLoading = isFirstCall;
972
+ if(isFirstCall){
973
+ Chat.ajaxStart();
974
+ Chat.e.messagesWrapper.classList.add('loading');
975
+ }
976
+ Chat.isBatchLoading = isFirstCall;
970977
var p = fetch("chat-poll?name=" + Chat.mxMsg);
971978
p.then(x=>x.json())
972979
.then(y=>newcontent(y))
973980
.catch(e=>console.error(e))
974981
/* ^^^ we don't use Chat.reportError(e) here b/c the polling
975982
fails exepectedly when it times out, but is then immediately
976983
resumed, and reportError() produces a loud error message. */
977984
.finally(function(){
978985
if(isFirstCall){
979
- Chat.isMassLoading = false;
986
+ Chat.isBatchLoading = false;
980987
Chat.ajaxEnd();
981
- const m = Chat.e.newestMessage;
982
- if(m) Chat.scheduleScrollOfMsg(m);
983
- setTimeout(()=>Chat.e.inputWrapper.scrollIntoView(), 0);
988
+ setTimeout(function(){
989
+ Chat.scrollMessagesTo(1);
990
+ Chat.e.messagesWrapper.classList.remove('loading');
991
+ }, 250);
984992
}
985993
poll.running=false;
986994
});
987995
}
988996
poll.running = false;
989997
poll(true);
990998
setInterval(poll, 1000);
991999
F.page.chat = Chat/* enables testing the APIs via the dev tools */;
9921000
})();
9931001
--- src/chat.js
+++ src/chat.js
@@ -206,20 +206,20 @@
206 else D.append(mip.parentNode, e);
207 }else{
208 D.append(holder,e);
209 this.e.newestMessage = e;
210 }
211 if(!atEnd && !this.isMassLoading
212 && e.dataset.xfrom!==this.me && !isInViewport(e)){
213 /* If a new non-history message arrives while the user is
214 scrolled elsewhere, do not scroll to the latest
215 message, but gently alert the user that a new message
216 has arrived. */
217 F.toast.message("New message has arrived.");
218 }else if(!this.isMassLoading && e.dataset.xfrom===Chat.me){
219 this.scheduleScrollOfMsg(e);
220 }else if(!this.isMassLoading){
221 /* When a message from someone else arrives, we have to
222 figure out whether or not to scroll it into view. Ideally
223 we'd just stuff it in the UI and let the flexbox layout
224 DTRT, but Safari has expressed, in no uncertain terms,
225 some disappointment with that approach, so we'll
@@ -289,11 +289,11 @@
289 if(where<0){
290 Chat.e.messagesWrapper.scrollTop = 0;
291 }else if(where>0){
292 Chat.e.messagesWrapper.scrollTop = Chat.e.messagesWrapper.scrollHeight;
293 }else if(Chat.e.newestMessage){
294 Chat.e.newestMessage.scrollIntoView();
295 }
296 },
297 toggleChatOnlyMode: function(){
298 return this.chatOnlyMode(!this.isChatOnlyMode());
299 },
@@ -918,23 +918,27 @@
918 );
919 Chat.disableDuringAjax.push(toolbar);
920 /* Loads the next n oldest messages, or all previous history if n is negative. */
921 const loadOldMessages = function(n){
922 Chat.ajaxStart();
 
 
923 var gotMessages = false;
924 fetch("chat-poll?before="+Chat.mnMsg+"&n="+n)
925 .then(x=>x.json())
926 .then(function(x){
927 gotMessages = x.msgs.length;
928 newcontent(x,true);
929 })
930 .catch(e=>Chat.reportError(e))
931 .finally(function(){
 
 
932 if(n<0/*we asked for all history*/
933 || 0===gotMessages/*we found no history*/
934 || (n>0 && gotMessages<n /*we got fewer history entries than requested*/)
935 || (false!==gotMessages && n<0 && gotMessages<Chat.loadMessageCount
936 /*we asked for default amount and got fewer than that.*/)){
937 /* We've loaded all history. Permanently disable the
938 history-load toolbar and keep it from being re-enabled
939 via the ajaxStart()/ajaxEnd() mechanism... */
940 const div = Chat.e.loadOlderToolbar.querySelector('div');
@@ -963,30 +967,34 @@
963 })()/*end history loading widget setup*/;
964
965 async function poll(isFirstCall){
966 if(poll.running) return;
967 poll.running = true;
968 if(isFirstCall) Chat.ajaxStart();
969 Chat.isMassLoading = isFirstCall;
 
 
 
970 var p = fetch("chat-poll?name=" + Chat.mxMsg);
971 p.then(x=>x.json())
972 .then(y=>newcontent(y))
973 .catch(e=>console.error(e))
974 /* ^^^ we don't use Chat.reportError(e) here b/c the polling
975 fails exepectedly when it times out, but is then immediately
976 resumed, and reportError() produces a loud error message. */
977 .finally(function(){
978 if(isFirstCall){
979 Chat.isMassLoading = false;
980 Chat.ajaxEnd();
981 const m = Chat.e.newestMessage;
982 if(m) Chat.scheduleScrollOfMsg(m);
983 setTimeout(()=>Chat.e.inputWrapper.scrollIntoView(), 0);
 
984 }
985 poll.running=false;
986 });
987 }
988 poll.running = false;
989 poll(true);
990 setInterval(poll, 1000);
991 F.page.chat = Chat/* enables testing the APIs via the dev tools */;
992 })();
993
--- src/chat.js
+++ src/chat.js
@@ -206,20 +206,20 @@
206 else D.append(mip.parentNode, e);
207 }else{
208 D.append(holder,e);
209 this.e.newestMessage = e;
210 }
211 if(!atEnd && !this.isBatchLoading
212 && e.dataset.xfrom!==this.me && !isInViewport(e)){
213 /* If a new non-history message arrives while the user is
214 scrolled elsewhere, do not scroll to the latest
215 message, but gently alert the user that a new message
216 has arrived. */
217 F.toast.message("New message has arrived.");
218 }else if(!this.isBatchLoading && e.dataset.xfrom===Chat.me){
219 this.scheduleScrollOfMsg(e);
220 }else if(!this.isBatchLoading){
221 /* When a message from someone else arrives, we have to
222 figure out whether or not to scroll it into view. Ideally
223 we'd just stuff it in the UI and let the flexbox layout
224 DTRT, but Safari has expressed, in no uncertain terms,
225 some disappointment with that approach, so we'll
@@ -289,11 +289,11 @@
289 if(where<0){
290 Chat.e.messagesWrapper.scrollTop = 0;
291 }else if(where>0){
292 Chat.e.messagesWrapper.scrollTop = Chat.e.messagesWrapper.scrollHeight;
293 }else if(Chat.e.newestMessage){
294 Chat.e.newestMessage.scrollIntoView(false);
295 }
296 },
297 toggleChatOnlyMode: function(){
298 return this.chatOnlyMode(!this.isChatOnlyMode());
299 },
@@ -918,23 +918,27 @@
918 );
919 Chat.disableDuringAjax.push(toolbar);
920 /* Loads the next n oldest messages, or all previous history if n is negative. */
921 const loadOldMessages = function(n){
922 Chat.ajaxStart();
923 Chat.e.messagesWrapper.classList.add('loading');
924 Chat.isBatchLoading = true;
925 var gotMessages = false;
926 fetch("chat-poll?before="+Chat.mnMsg+"&n="+n)
927 .then(x=>x.json())
928 .then(function(x){
929 gotMessages = x.msgs.length;
930 newcontent(x,true);
931 })
932 .catch(e=>Chat.reportError(e))
933 .finally(function(){
934 Chat.isBatchLoading = false;
935 Chat.e.messagesWrapper.classList.remove('loading');
936 if(n<0/*we asked for all history*/
937 || 0===gotMessages/*we found no history*/
938 || (n>0 && gotMessages<n /*we got fewer history entries than requested*/)
939 || (false!==gotMessages && n===0 && gotMessages<Chat.loadMessageCount
940 /*we asked for default amount and got fewer than that.*/)){
941 /* We've loaded all history. Permanently disable the
942 history-load toolbar and keep it from being re-enabled
943 via the ajaxStart()/ajaxEnd() mechanism... */
944 const div = Chat.e.loadOlderToolbar.querySelector('div');
@@ -963,30 +967,34 @@
967 })()/*end history loading widget setup*/;
968
969 async function poll(isFirstCall){
970 if(poll.running) return;
971 poll.running = true;
972 if(isFirstCall){
973 Chat.ajaxStart();
974 Chat.e.messagesWrapper.classList.add('loading');
975 }
976 Chat.isBatchLoading = isFirstCall;
977 var p = fetch("chat-poll?name=" + Chat.mxMsg);
978 p.then(x=>x.json())
979 .then(y=>newcontent(y))
980 .catch(e=>console.error(e))
981 /* ^^^ we don't use Chat.reportError(e) here b/c the polling
982 fails exepectedly when it times out, but is then immediately
983 resumed, and reportError() produces a loud error message. */
984 .finally(function(){
985 if(isFirstCall){
986 Chat.isBatchLoading = false;
987 Chat.ajaxEnd();
988 setTimeout(function(){
989 Chat.scrollMessagesTo(1);
990 Chat.e.messagesWrapper.classList.remove('loading');
991 }, 250);
992 }
993 poll.running=false;
994 });
995 }
996 poll.running = false;
997 poll(true);
998 setInterval(poll, 1000);
999 F.page.chat = Chat/* enables testing the APIs via the dev tools */;
1000 })();
1001
+5 -1
--- src/default.css
+++ src/default.css
@@ -1639,10 +1639,14 @@
16391639
/** Container for the list of /chat messages. */
16401640
body.chat #chat-messages-wrapper {
16411641
overflow: auto;
16421642
/*max-height: 800em*//*will be re-calc'd in JS*/;
16431643
flex: 2 1 auto;
1644
+}
1645
+body.chat #chat-messages-wrapper.loading > * {
1646
+ /* An attempt at reducing flicker when loading lots of messages. */
1647
+ visibility: hidden;
16441648
}
16451649
body.chat div.content {
16461650
margin: 0;
16471651
padding: 0;
16481652
display: flex;
@@ -1678,11 +1682,11 @@
16781682
settings button. */
16791683
body.chat #chat-input-line {
16801684
display: flex;
16811685
flex-direction: row;
16821686
margin-bottom: 0.25em;
1683
- align-items: flex-start;
1687
+ align-items: center;
16841688
}
16851689
body.chat #chat-input-line > input[type=submit],
16861690
body.chat #chat-input-line > #chat-settings-button,
16871691
body.chat #chat-input-line > button {
16881692
flex: 1 5 auto;
16891693
--- src/default.css
+++ src/default.css
@@ -1639,10 +1639,14 @@
1639 /** Container for the list of /chat messages. */
1640 body.chat #chat-messages-wrapper {
1641 overflow: auto;
1642 /*max-height: 800em*//*will be re-calc'd in JS*/;
1643 flex: 2 1 auto;
 
 
 
 
1644 }
1645 body.chat div.content {
1646 margin: 0;
1647 padding: 0;
1648 display: flex;
@@ -1678,11 +1682,11 @@
1678 settings button. */
1679 body.chat #chat-input-line {
1680 display: flex;
1681 flex-direction: row;
1682 margin-bottom: 0.25em;
1683 align-items: flex-start;
1684 }
1685 body.chat #chat-input-line > input[type=submit],
1686 body.chat #chat-input-line > #chat-settings-button,
1687 body.chat #chat-input-line > button {
1688 flex: 1 5 auto;
1689
--- src/default.css
+++ src/default.css
@@ -1639,10 +1639,14 @@
1639 /** Container for the list of /chat messages. */
1640 body.chat #chat-messages-wrapper {
1641 overflow: auto;
1642 /*max-height: 800em*//*will be re-calc'd in JS*/;
1643 flex: 2 1 auto;
1644 }
1645 body.chat #chat-messages-wrapper.loading > * {
1646 /* An attempt at reducing flicker when loading lots of messages. */
1647 visibility: hidden;
1648 }
1649 body.chat div.content {
1650 margin: 0;
1651 padding: 0;
1652 display: flex;
@@ -1678,11 +1682,11 @@
1682 settings button. */
1683 body.chat #chat-input-line {
1684 display: flex;
1685 flex-direction: row;
1686 margin-bottom: 0.25em;
1687 align-items: center;
1688 }
1689 body.chat #chat-input-line > input[type=submit],
1690 body.chat #chat-input-line > #chat-settings-button,
1691 body.chat #chat-input-line > button {
1692 flex: 1 5 auto;
1693

Keyboard Shortcuts

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