Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | /chat: experimentally render a list of users ordered by most recent activity. Until/unless we can find a useful function for the list, though, it's really just a somewhat pretty screen space hog. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | chat-user-last-seen |
| Files: | files | file ages | folders |
| SHA3-256: |
c7ee6f4ef19a3b1ef94ded459b98bd94 |
| User & Date: | stephan 2021-06-14 13:48:08.910 |
Context
|
2021-06-15
| ||
| 03:00 | Merged in trunk for SSL improvements and deployment to test server. ... (check-in: 422323618e user: stephan tags: chat-user-last-seen) | |
|
2021-06-14
| ||
| 13:48 | /chat: experimentally render a list of users ordered by most recent activity. Until/unless we can find a useful function for the list, though, it's really just a somewhat pretty screen space hog. ... (check-in: c7ee6f4ef1 user: stephan tags: chat-user-last-seen) | |
| 10:52 | /chat now experimentally keeps track of the timestamp of the most recent message received from each user so that we can eventually integrate that information into the UI to provide a list of currently-active users (noting that we have no way of tracking the existence of lurkers). ... (check-in: be07b8d137 user: stephan tags: chat-user-last-seen) | |
Changes
Changes to src/chat.js.
| ︙ | ︙ | |||
107 108 109 110 111 112 113 |
messagesWrapper: E1('#chat-messages-wrapper'),
inputForm: E1('#chat-form'),
btnSubmit: E1('#chat-message-submit'),
inputSingle: E1('#chat-input-single'),
inputMulti: E1('#chat-input-multi'),
inputCurrent: undefined/*one of inputSingle or inputMulti*/,
inputFile: E1('#chat-input-file'),
| | > | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
messagesWrapper: E1('#chat-messages-wrapper'),
inputForm: E1('#chat-form'),
btnSubmit: E1('#chat-message-submit'),
inputSingle: E1('#chat-input-single'),
inputMulti: E1('#chat-input-multi'),
inputCurrent: undefined/*one of inputSingle or inputMulti*/,
inputFile: E1('#chat-input-file'),
contentDiv: E1('div.content'),
activeUserList: undefined/*active user list (dynamically created later on)*/
},
me: F.user.name,
mxMsg: F.config.chat.initSize ? -F.config.chat.initSize : -50,
mnMsg: undefined/*lowest message ID we've seen so far (for history loading)*/,
pageIsActive: 'visible'===document.visibilityState,
changesSincePageHidden: 0,
notificationBubbleColor: 'white',
|
| ︙ | ︙ | |||
392 393 394 395 396 397 398 399 400 401 402 403 404 405 |
this.
*/
setNewMessageSound: function f(uri){
delete this.playNewMessageSound.audio;
this.playNewMessageSound.uri = uri;
this.settings.set('audible-alert', !!uri);
return this;
}
};
F.fetch.beforesend = ()=>cs.ajaxStart();
F.fetch.aftersend = ()=>cs.ajaxEnd();
cs.e.inputCurrent = cs.e.inputSingle;
/* Install default settings... */
Object.keys(cs.settings.defaults).forEach(function(k){
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
this.
*/
setNewMessageSound: function f(uri){
delete this.playNewMessageSound.audio;
this.playNewMessageSound.uri = uri;
this.settings.set('audible-alert', !!uri);
return this;
},
/**
Updates the "active user list" view.
*/
updateActiveUserList: function callee(){
if(!this.e.activeUserList){
/** Array.sort() callback. Expects an array of user names and
sorts them in last-received message order (newest first). */
const usersLastSeen = this.usersLastSeen;
callee.sortUsersSeen = function(l,r){
l = usersLastSeen[l];
r = usersLastSeen[r];
if(l && r) return r - l;
else if(l) return -1;
else if(r) return 1;
else return 0;
};
const content = document.querySelector('body > div.content');
const ael = this.e.activeUserList =
D.attr(D.div(),'id','active-user-list');
D.append(ael, "user list placeholder");
content.insertBefore(ael, content.firstElementChild)
/*remember: layout is reversed!*/;
}
const self = this,
users = Object.keys(this.usersLastSeen).sort(callee.sortUsersSeen);
if(!users.length) return this;
const ael = this.e.activeUserList;
D.clearElement(ael);
users.forEach(function(u){
const uSpan = D.addClass(D.span(), 'chat-user');
const uDate = self.usersLastSeen[u];
D.append(uSpan, u);
if(uDate.$uColor){
uSpan.style.backgroundColor = uDate.$uColor;
}
D.append(ael, uSpan);
});
}
};
F.fetch.beforesend = ()=>cs.ajaxStart();
F.fetch.aftersend = ()=>cs.ajaxEnd();
cs.e.inputCurrent = cs.e.inputSingle;
/* Install default settings... */
Object.keys(cs.settings.defaults).forEach(function(k){
|
| ︙ | ︙ | |||
1084 1085 1086 1087 1088 1089 1090 |
/** Callback for poll() to inject new content into the page. jx ==
the response from /chat-poll. If atEnd is true, the message is
appended to the end of the chat list (for loading older
messages), else the beginning (the default). */
const newcontent = function f(jx,atEnd){
if(!f.processPost){
| < < < < < < < < < < > > | > | < < < | < | 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 |
/** Callback for poll() to inject new content into the page. jx ==
the response from /chat-poll. If atEnd is true, the message is
appended to the end of the chat list (for loading older
messages), else the beginning (the default). */
const newcontent = function f(jx,atEnd){
if(!f.processPost){
/** Processes chat message m, placing it either at the start (if
atEnd is falsy) or end (if atEnd is truthy) of the chat
history. atEnd should only be true when loading older
messages. */
f.processPost = function(m,atEnd){
++Chat.totalMessageCount;
if( m.msgid>Chat.mxMsg ) Chat.mxMsg = m.msgid;
if( !Chat.mnMsg || m.msgid<Chat.mnMsg) Chat.mnMsg = m.msgid;
if(m.xfrom && m.mtime){
const d = new Date(m.mtime);
const uls = Chat.usersLastSeen[m.xfrom];
if(!uls || uls<d){
d.$uColor = m.uclr;
Chat.usersLastSeen[m.xfrom] = d;
}
}
if( m.mdel ){
/* A record deletion notice. */
Chat.deleteMessageElem(m.mdel);
return;
}
if(!Chat._isBatchLoading /*&& Chat.me!==m.xfrom*/ && Chat.playNewMessageSound){
Chat.playNewMessageSound();
}
const row = new Chat.MessageWidget(m);
Chat.injectMessageElem(row.e.body,atEnd);
if(m.isError){
Chat._gotServerError = m;
}else{
Chat.updateActiveUserList();
}
}/*processPost()*/;
}/*end static init*/
jx.msgs.forEach((m)=>f.processPost(m,atEnd));
if('visible'===document.visibilityState){
if(Chat.changesSincePageHidden){
Chat.changesSincePageHidden = 0;
|
| ︙ | ︙ |
Changes to src/default.css.
| ︙ | ︙ | |||
1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 |
white-space: pre;
font-family: monospace;
}
body.chat #chat-drop-details img {
max-width: 45%;
max-height: 45%;
}
input[type="checkbox"].diff-toggle {
float: right;
}
body.branch .brlist > table > tbody > tr:hover:not(.selected),
| > > > > > > > > > > > > > > > > > > | 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 |
white-space: pre;
font-family: monospace;
}
body.chat #chat-drop-details img {
max-width: 45%;
max-height: 45%;
}
body.chat #active-user-list {
border: 1px inset;
padding: 0.1em 0.2em;
border-radius: 0.25em;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
font-size: 80%;
}
body.chat #active-user-list::before {
content: "Most recently active:";
}
body.chat #active-user-list span.chat-user {
margin: 0.2em;
padding: 0.15em;
border-radius: 0.25em;
}
input[type="checkbox"].diff-toggle {
float: right;
}
body.branch .brlist > table > tbody > tr:hover:not(.selected),
|
| ︙ | ︙ |