Fossil SCM

Chat message precise timestamps are now shown via a tap/click popup, rather than hoverhelp, for mobile compatibility.

stephan 2020-12-23 06:26 chatroom-dev
Commit 0101325f9dcc55cbc8eb871cc1d855642fc3bfc548daa32b1b9a674cec36b9fd
+11 -1
--- src/chat.c
+++ src/chat.c
@@ -87,10 +87,17 @@
8787
@ align-items: center;
8888
@ }
8989
@ #chat-input-file > input {
9090
@ flex: 1 0 auto;
9191
@ }
92
+ @ .chat-timestamp {
93
+ @ font-family: monospace;
94
+ @ font-size: 0.8em;
95
+ @ white-space: pre;
96
+ @ text-align: left;
97
+ @ opacity: 0.8;
98
+ @ }
9299
@ </style>
93100
@ <form accept-encoding="utf-8" id="chat-form">
94101
@ <div id='chat-input-area'>
95102
@ <div id='chat-input-line'>
96103
@ <input type="text" name="msg" id="sbox"\
@@ -109,12 +116,15 @@
109116
@ <span id='message-inject-point'></span>
110117
111118
builtin_fossil_js_bundle_or("popupwidget", NULL);
112119
/* Always in-line the javascript for the chat page */
113120
@ <script nonce="%h(style_nonce())">/* chat.c:%d(__LINE__) */
114
- @ let _me = "%j(g.zLogin)";
121
+ @ window.addEventListener('load', function(){
122
+ /* We need an onload handler to ensure that window.fossil is
123
+ loaded first. */
115124
cgi_append_content(builtin_text("chat.js"),-1);
125
+ @ }, false);
116126
@ </script>
117127
118128
style_finish_page();
119129
}
120130
121131
--- src/chat.c
+++ src/chat.c
@@ -87,10 +87,17 @@
87 @ align-items: center;
88 @ }
89 @ #chat-input-file > input {
90 @ flex: 1 0 auto;
91 @ }
 
 
 
 
 
 
 
92 @ </style>
93 @ <form accept-encoding="utf-8" id="chat-form">
94 @ <div id='chat-input-area'>
95 @ <div id='chat-input-line'>
96 @ <input type="text" name="msg" id="sbox"\
@@ -109,12 +116,15 @@
109 @ <span id='message-inject-point'></span>
110
111 builtin_fossil_js_bundle_or("popupwidget", NULL);
112 /* Always in-line the javascript for the chat page */
113 @ <script nonce="%h(style_nonce())">/* chat.c:%d(__LINE__) */
114 @ let _me = "%j(g.zLogin)";
 
 
115 cgi_append_content(builtin_text("chat.js"),-1);
 
116 @ </script>
117
118 style_finish_page();
119 }
120
121
--- src/chat.c
+++ src/chat.c
@@ -87,10 +87,17 @@
87 @ align-items: center;
88 @ }
89 @ #chat-input-file > input {
90 @ flex: 1 0 auto;
91 @ }
92 @ .chat-timestamp {
93 @ font-family: monospace;
94 @ font-size: 0.8em;
95 @ white-space: pre;
96 @ text-align: left;
97 @ opacity: 0.8;
98 @ }
99 @ </style>
100 @ <form accept-encoding="utf-8" id="chat-form">
101 @ <div id='chat-input-area'>
102 @ <div id='chat-input-line'>
103 @ <input type="text" name="msg" id="sbox"\
@@ -109,12 +116,15 @@
116 @ <span id='message-inject-point'></span>
117
118 builtin_fossil_js_bundle_or("popupwidget", NULL);
119 /* Always in-line the javascript for the chat page */
120 @ <script nonce="%h(style_nonce())">/* chat.c:%d(__LINE__) */
121 @ window.addEventListener('load', function(){
122 /* We need an onload handler to ensure that window.fossil is
123 loaded first. */
124 cgi_append_content(builtin_text("chat.js"),-1);
125 @ }, false);
126 @ </script>
127
128 style_finish_page();
129 }
130
131
+47 -9
--- src/chat.js
+++ src/chat.js
@@ -1,10 +1,10 @@
11
(function(){
22
const form = document.querySelector('#chat-form');
33
let mxMsg = 0;
4
- // let _me = "%string($me)";
5
- let me = window.fossil.user.name;
4
+ const F = window.fossil;
5
+ const _me = F.user.name;
66
form.addEventListener('submit',(e)=>{
77
e.preventDefault();
88
if( form.msg.value.length>0 || form.file.value.length>0 ){
99
fetch("chat-send",{
1010
method: 'POST',
@@ -39,19 +39,64 @@
3939
'-',ff.pad(d.getDate()),
4040
' ',ff.pad(d.getHours()),':',ff.pad(d.getMinutes()),
4141
':',ff.pad(d.getSeconds())
4242
].join('');
4343
};
44
+ /* Returns an almost-ISO8601 form of Date object d. */
45
+ const iso8601ish = function(d){
46
+ return d.toISOString()
47
+ .replace('T',' ').replace(/\.\d+/,'').replace('Z', ' GMT');
48
+ };
49
+ /* Timestampt popup widget */
50
+ const tsPopup = new F.PopupWidget({
51
+ cssClass: ['fossil-tooltip', 'chat-timestamp'],
52
+ refresh:function(){
53
+ const D = F.dom;
54
+ D.clearElement(this.e);
55
+ const d = new Date(this._timestamp+"Z");
56
+ if(d.getMinutes().toString()!=="NaN"){
57
+ // Date works, render informative timestamps
58
+ D.append(this.e, localTimeString(d)," client-local", D.br(),
59
+ iso8601ish(d));
60
+ }else{
61
+ // Date doesn't work, so dumb it down...
62
+ D.append(this.e, this._timestamp," GMT");
63
+ }
64
+ }
65
+ });
66
+ const hidePopup = ()=>tsPopup.hide();
67
+ tsPopup.e.addEventListener('click', hidePopup, false);
68
+ document.body.addEventListener('click', hidePopup, true);
69
+ document.body.addEventListener('keydown', function(ev){
70
+ if(tsPopup.isShown() && 27===ev.which) tsPopup.hide();
71
+ }, true);
72
+ /* Event handler for clicking .message-user elements to show their
73
+ timestamps. */
74
+ const handleLegendClicked = function(ev){
75
+ const rect = ev.target.getBoundingClientRect();
76
+ tsPopup._timestamp = ev.target.dataset.timestamp;
77
+ let x = rect.left, y = rect.top - 10;
78
+ tsPopup.show(ev.target)/*so we can get its computed size*/;
79
+ // Shift to the left for right-aligned messages
80
+ if('right'===ev.target.getAttribute('align')){
81
+ const pRect = tsPopup.e.getBoundingClientRect();
82
+ x -= pRect.width/3*2;
83
+ }
84
+ tsPopup.show(x, y);
85
+ };
86
+
4487
function newcontent(jx){
4588
var i;
4689
for(i=0; i<jx.msgs.length; ++i){
4790
let m = jx.msgs[i];
4891
let row = document.createElement("fieldset");
4992
if( m.msgid>mxMsg ) mxMsg = m.msgid;
5093
row.classList.add('message-row');
5194
injectMessage(row);
5295
const eWho = document.createElement('legend');
96
+ eWho.dataset.timestamp = m.mtime;
97
+ eWho.addEventListener('click', handleLegendClicked, false);
5398
eWho.setAttribute('align', (m.xfrom===_me ? 'right' : 'left'));
5499
eWho.style.backgroundColor = m.uclr;
55100
row.appendChild(eWho);
56101
eWho.classList.add('message-user');
57102
let whoName;
@@ -61,17 +106,10 @@
61106
}else{
62107
whoName = m.xfrom;
63108
}
64109
var d = new Date(m.mtime + "Z");
65110
if( d.getMinutes().toString()!="NaN" ){
66
- eWho.setAttribute('title',localTimeString(d)
67
- +' client-local\n'
68
- +d.toISOString()
69
- .replace('T',' ')
70
- .replace(/\.\d+/,'')
71
- .replace('Z', ' GMT')
72
- );
73111
/* Show local time when we can compute it */
74112
eWho.append(textNode(whoName+' @ '+
75113
d.getHours()+":"+(d.getMinutes()+100).toString().slice(1,3)
76114
))
77115
}else{
78116
--- src/chat.js
+++ src/chat.js
@@ -1,10 +1,10 @@
1 (function(){
2 const form = document.querySelector('#chat-form');
3 let mxMsg = 0;
4 // let _me = "%string($me)";
5 let me = window.fossil.user.name;
6 form.addEventListener('submit',(e)=>{
7 e.preventDefault();
8 if( form.msg.value.length>0 || form.file.value.length>0 ){
9 fetch("chat-send",{
10 method: 'POST',
@@ -39,19 +39,64 @@
39 '-',ff.pad(d.getDate()),
40 ' ',ff.pad(d.getHours()),':',ff.pad(d.getMinutes()),
41 ':',ff.pad(d.getSeconds())
42 ].join('');
43 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44 function newcontent(jx){
45 var i;
46 for(i=0; i<jx.msgs.length; ++i){
47 let m = jx.msgs[i];
48 let row = document.createElement("fieldset");
49 if( m.msgid>mxMsg ) mxMsg = m.msgid;
50 row.classList.add('message-row');
51 injectMessage(row);
52 const eWho = document.createElement('legend');
 
 
53 eWho.setAttribute('align', (m.xfrom===_me ? 'right' : 'left'));
54 eWho.style.backgroundColor = m.uclr;
55 row.appendChild(eWho);
56 eWho.classList.add('message-user');
57 let whoName;
@@ -61,17 +106,10 @@
61 }else{
62 whoName = m.xfrom;
63 }
64 var d = new Date(m.mtime + "Z");
65 if( d.getMinutes().toString()!="NaN" ){
66 eWho.setAttribute('title',localTimeString(d)
67 +' client-local\n'
68 +d.toISOString()
69 .replace('T',' ')
70 .replace(/\.\d+/,'')
71 .replace('Z', ' GMT')
72 );
73 /* Show local time when we can compute it */
74 eWho.append(textNode(whoName+' @ '+
75 d.getHours()+":"+(d.getMinutes()+100).toString().slice(1,3)
76 ))
77 }else{
78
--- src/chat.js
+++ src/chat.js
@@ -1,10 +1,10 @@
1 (function(){
2 const form = document.querySelector('#chat-form');
3 let mxMsg = 0;
4 const F = window.fossil;
5 const _me = F.user.name;
6 form.addEventListener('submit',(e)=>{
7 e.preventDefault();
8 if( form.msg.value.length>0 || form.file.value.length>0 ){
9 fetch("chat-send",{
10 method: 'POST',
@@ -39,19 +39,64 @@
39 '-',ff.pad(d.getDate()),
40 ' ',ff.pad(d.getHours()),':',ff.pad(d.getMinutes()),
41 ':',ff.pad(d.getSeconds())
42 ].join('');
43 };
44 /* Returns an almost-ISO8601 form of Date object d. */
45 const iso8601ish = function(d){
46 return d.toISOString()
47 .replace('T',' ').replace(/\.\d+/,'').replace('Z', ' GMT');
48 };
49 /* Timestampt popup widget */
50 const tsPopup = new F.PopupWidget({
51 cssClass: ['fossil-tooltip', 'chat-timestamp'],
52 refresh:function(){
53 const D = F.dom;
54 D.clearElement(this.e);
55 const d = new Date(this._timestamp+"Z");
56 if(d.getMinutes().toString()!=="NaN"){
57 // Date works, render informative timestamps
58 D.append(this.e, localTimeString(d)," client-local", D.br(),
59 iso8601ish(d));
60 }else{
61 // Date doesn't work, so dumb it down...
62 D.append(this.e, this._timestamp," GMT");
63 }
64 }
65 });
66 const hidePopup = ()=>tsPopup.hide();
67 tsPopup.e.addEventListener('click', hidePopup, false);
68 document.body.addEventListener('click', hidePopup, true);
69 document.body.addEventListener('keydown', function(ev){
70 if(tsPopup.isShown() && 27===ev.which) tsPopup.hide();
71 }, true);
72 /* Event handler for clicking .message-user elements to show their
73 timestamps. */
74 const handleLegendClicked = function(ev){
75 const rect = ev.target.getBoundingClientRect();
76 tsPopup._timestamp = ev.target.dataset.timestamp;
77 let x = rect.left, y = rect.top - 10;
78 tsPopup.show(ev.target)/*so we can get its computed size*/;
79 // Shift to the left for right-aligned messages
80 if('right'===ev.target.getAttribute('align')){
81 const pRect = tsPopup.e.getBoundingClientRect();
82 x -= pRect.width/3*2;
83 }
84 tsPopup.show(x, y);
85 };
86
87 function newcontent(jx){
88 var i;
89 for(i=0; i<jx.msgs.length; ++i){
90 let m = jx.msgs[i];
91 let row = document.createElement("fieldset");
92 if( m.msgid>mxMsg ) mxMsg = m.msgid;
93 row.classList.add('message-row');
94 injectMessage(row);
95 const eWho = document.createElement('legend');
96 eWho.dataset.timestamp = m.mtime;
97 eWho.addEventListener('click', handleLegendClicked, false);
98 eWho.setAttribute('align', (m.xfrom===_me ? 'right' : 'left'));
99 eWho.style.backgroundColor = m.uclr;
100 row.appendChild(eWho);
101 eWho.classList.add('message-user');
102 let whoName;
@@ -61,17 +106,10 @@
106 }else{
107 whoName = m.xfrom;
108 }
109 var d = new Date(m.mtime + "Z");
110 if( d.getMinutes().toString()!="NaN" ){
 
 
 
 
 
 
 
111 /* Show local time when we can compute it */
112 eWho.append(textNode(whoName+' @ '+
113 d.getHours()+":"+(d.getMinutes()+100).toString().slice(1,3)
114 ))
115 }else{
116
--- src/default.css
+++ src/default.css
@@ -1502,10 +1502,11 @@
15021502
padding: 0 0.5em;
15031503
/*text-align: left; Firefox requires the 'align' attribute */
15041504
margin-left: 0.15em;
15051505
padding: 0 0.5em 0em 0.5em;
15061506
margin-bottom: 0.4em;
1507
+ cursor: pointer;
15071508
}
15081509
/* Reposition "my" posts to the right */
15091510
.message-row.user-is-me .message-user {
15101511
/*text-align: right; Firefox requires the 'align' attribute */
15111512
margin-left: 0;
15121513
--- src/default.css
+++ src/default.css
@@ -1502,10 +1502,11 @@
1502 padding: 0 0.5em;
1503 /*text-align: left; Firefox requires the 'align' attribute */
1504 margin-left: 0.15em;
1505 padding: 0 0.5em 0em 0.5em;
1506 margin-bottom: 0.4em;
 
1507 }
1508 /* Reposition "my" posts to the right */
1509 .message-row.user-is-me .message-user {
1510 /*text-align: right; Firefox requires the 'align' attribute */
1511 margin-left: 0;
1512
--- src/default.css
+++ src/default.css
@@ -1502,10 +1502,11 @@
1502 padding: 0 0.5em;
1503 /*text-align: left; Firefox requires the 'align' attribute */
1504 margin-left: 0.15em;
1505 padding: 0 0.5em 0em 0.5em;
1506 margin-bottom: 0.4em;
1507 cursor: pointer;
1508 }
1509 /* Reposition "my" posts to the right */
1510 .message-row.user-is-me .message-user {
1511 /*text-align: right; Firefox requires the 'align' attribute */
1512 margin-left: 0;
1513

Keyboard Shortcuts

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