1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/**
This file contains the client-side implementation of fossil's /chat
application.
*/
(function(){
const F = window.fossil, D = F.dom;
const E1 = function(selector){
const e = document.querySelector(selector);
if(!e) throw new Error("missing required DOM element: "+selector);
return e;
};
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)
);
};
(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);
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
/**
This file contains the client-side implementation of fossil's /chat
application.
*/
(function(){
const F = window.fossil, D = F.dom;
const E1 = function(selector){
const e = document.querySelector(selector);
if(!e) throw new Error("missing required DOM element: "+selector);
return e;
};
/**
Returns true if e is entirely within the bounds of the window's viewport.
*/
const isEntirelyInViewport = 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)
);
};
/**
Returns true if e's on-screen position vertically overlaps that
of element v's. Horizontal overlap is ignored (we don't need it
for our case).
*/
const overlapsElemView = function(e,v) {
const r1 = e.getBoundingClientRect(),
r2 = v.getBoundingClientRect();
if(r1.top<=r2.bottom && r1.top>=r2.top) return true;
else if(r1.bottom<=r2.bottom && r1.bottom>=r2.top) return true;
return false;
};
(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);
|
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
|
if(fe) mip.parentNode.insertBefore(e, fe);
else D.append(mip.parentNode, e);
}else{
D.append(holder,e);
this.e.newestMessage = e;
}
if(!atEnd && !this.isBatchLoading
&& e.dataset.xfrom!==this.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(!this.isBatchLoading && e.dataset.xfrom===Chat.me){
this.scheduleScrollOfMsg(e);
|
|
>
>
>
|
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
|
if(fe) mip.parentNode.insertBefore(e, fe);
else D.append(mip.parentNode, e);
}else{
D.append(holder,e);
this.e.newestMessage = e;
}
if(!atEnd && !this.isBatchLoading
&& e.dataset.xfrom!==this.me
&& (prevMessage
? !overlapsElemView(prevMessage, this.e.messagesWrapper)
: false)){
/* 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(!this.isBatchLoading && e.dataset.xfrom===Chat.me){
this.scheduleScrollOfMsg(e);
|
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
|
yet have enough information to know how far to scroll!
For such cases we have to delay the scroll until the
image loads (and we hope it does so before another
message arrives).
*/
if(1===+e.dataset.hasImage){
e.querySelector('img').addEventListener('load',()=>e.scrollIntoView());
}else if(!prevMessage || (prevMessage && isInViewport(prevMessage))){
e.scrollIntoView(false);
}
}
},
/** Returns true if chat-only mode is enabled. */
isChatOnlyMode: ()=>document.body.classList.contains('chat-only-mode'),
/**
|
|
|
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
|
yet have enough information to know how far to scroll!
For such cases we have to delay the scroll until the
image loads (and we hope it does so before another
message arrives).
*/
if(1===+e.dataset.hasImage){
e.querySelector('img').addEventListener('load',()=>e.scrollIntoView());
}else if(!prevMessage || (prevMessage && isEntirelyInViewport(prevMessage))){
e.scrollIntoView(false);
}
}
},
/** Returns true if chat-only mode is enabled. */
isChatOnlyMode: ()=>document.body.classList.contains('chat-only-mode'),
/**
|