Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Initial impl for chat message deletion. The ajax bits are in place and message deletion propagates to other connected clients (if the message is owned by the poster or the user is an admin) but there's not currently a user interface. TODO: add related controls to the same popup used for the message timestamps. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
247276113c0a0dc475dddf64fe54d613 |
| User & Date: | stephan 2020-12-24 05:03:27.127 |
Context
|
2020-12-24
| ||
| 05:58 | Added UI to delete chat posts (tap on the message header). Made a change to the semantics of when fossil.PopupWidget's refresh() callback is triggered to account for the common case of having to show() the popup twice in a row without a hide() in between. ... (check-in: b7f106da8a user: stephan tags: trunk) | |
| 05:03 | Initial impl for chat message deletion. The ajax bits are in place and message deletion propagates to other connected clients (if the message is owned by the poster or the user is an admin) but there's not currently a user interface. TODO: add related controls to the same popup used for the message timestamps. ... (check-in: 247276113c user: stephan tags: trunk) | |
| 03:34 | The /chat page now redirects to the login page if needed. ... (check-in: 77d3058600 user: drh tags: trunk) | |
Changes
Changes to src/builtin.c.
| ︙ | ︙ | |||
635 636 637 638 639 640 641 |
CX("name: %!j,", skin_in_use());*/
CX("isDark: %s"
"/*true if the current skin has the 'white-foreground' detail*/",
skin_detail_boolean("white-foreground") ? "true" : "false");
CX("}\n"/*fossil.config.skin*/);
CX("};\n"/* fossil.config */);
CX("window.fossil.user = {");
| | > | 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 |
CX("name: %!j,", skin_in_use());*/
CX("isDark: %s"
"/*true if the current skin has the 'white-foreground' detail*/",
skin_detail_boolean("white-foreground") ? "true" : "false");
CX("}\n"/*fossil.config.skin*/);
CX("};\n"/* fossil.config */);
CX("window.fossil.user = {");
CX("name: %!j,", (g.zLogin&&*g.zLogin) ? g.zLogin : "guest");
CX("isAdmin: %s", (g.perm.Admin || g.perm.Setup) ? "true" : "false");
CX("};\n"/*fossil.user*/);
CX("if(fossil.config.skin.isDark) "
"document.body.classList.add('fossil-dark-style');\n");
#if 0
/* Is it safe to emit the CSRF token here? Some pages add it
** as a hidden form field. */
if(g.zCsrfToken[0]!=0){
|
| ︙ | ︙ |
Changes to src/chat.js.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
onPageInactive: function(){console.debug("Page inactive.")} //override below
};
document.addEventListener('visibilitychange', function(ev){
cs.pageIsActive = !document.hidden;
if(cs.pageIsActive) cs.onPageActive();
else cs.onPageInactive();
}, true);
return cs;
})();
/* State for paste and drag/drop */
const BlobXferState = {
dropDetails: document.querySelector('#chat-drop-details'),
blob: undefined
};
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
onPageInactive: function(){console.debug("Page inactive.")} //override below
};
document.addEventListener('visibilitychange', function(ev){
cs.pageIsActive = !document.hidden;
if(cs.pageIsActive) cs.onPageActive();
else cs.onPageInactive();
}, true);
const qs = (e)=>document.querySelector(e);
const argsToArray = function(args){
return Array.prototype.slice.call(args,0);
};
cs.reportError = function(/*msg args*/){
const args = argsToArray(arguments);
console.error("chat error:",args);
F.toast.error.apply(F.toast, args);
};
cs.getMessageElemById = function(id){
return qs('[data-msgid="'+id+'"]');
};
cs.deleteMessageElemById = function(id){
const e = this.getMessageElemById(id);
if(e) D.remove(e);
return !!e;
};
/**
Removes the given message ID from the local chat record and, if
the message was posted by this user OR this user in an
admin/setup, also submits it for removal on the remote.
*/
cs.deleteMessageById = function(id){
const e = this.getMessageElemById(id);
if(!e) return;
if(this.me === e.dataset.xfrom
|| F.user.isAdmin/*will be confirmed server-side*/
){
fetch("chat-delete?name=" + id)
.then(()=>D.remove(e))
.then(()=>F.toast.message("Deleted message "+id+"."))
.catch(err=>this.reportError(err))
}else{
D.remove(e);
F.toast.message("Locally removed message "+id+".");
}
};
return cs;
})();
/* State for paste and drag/drop */
const BlobXferState = {
dropDetails: document.querySelector('#chat-drop-details'),
blob: undefined
};
|
| ︙ | ︙ | |||
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
};
/** Callback for poll() to inject new content into the page. */
function newcontent(jx){
var i;
for(i=0; i<jx.msgs.length; ++i){
const m = jx.msgs[i];
if( m.msgid>Chat.mxMsg ) Chat.mxMsg = m.msgid;
const eWho = D.create('legend'),
row = D.addClass(D.fieldset(eWho), 'message-row');
injectMessage(row);
eWho.dataset.timestamp = m.mtime;
eWho.addEventListener('click', handleLegendClicked, false);
if( m.xfrom==Chat.me && window.outerWidth<1000 ){
eWho.setAttribute('align', 'right');
row.style.justifyContent = "flex-end";
}else{
| > > > > > > > | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
};
/** Callback for poll() to inject new content into the page. */
function newcontent(jx){
var i;
for(i=0; i<jx.msgs.length; ++i){
const m = jx.msgs[i];
if( m.msgid>Chat.mxMsg ) Chat.mxMsg = m.msgid;
if( m.mdel ){
/* A record deletion notice. */
Chat.deleteMessageElemById(m.mdel);
continue;
}
const eWho = D.create('legend'),
row = D.addClass(D.fieldset(eWho), 'message-row');
row.dataset.msgid = m.msgid;
row.dataset.xfrom = m.xfrom;
injectMessage(row);
eWho.dataset.timestamp = m.mtime;
eWho.addEventListener('click', handleLegendClicked, false);
if( m.xfrom==Chat.me && window.outerWidth<1000 ){
eWho.setAttribute('align', 'right');
row.style.justifyContent = "flex-end";
}else{
|
| ︙ | ︙ | |||
250 251 252 253 254 255 256 257 |
.then(x=>x.json())
.then(y=>newcontent(y))
.catch(e=>console.error(e))
.finally(()=>poll.running=false)
}
poll();
setInterval(poll, 1000);
})();
| > | 298 299 300 301 302 303 304 305 306 |
.then(x=>x.json())
.then(y=>newcontent(y))
.catch(e=>console.error(e))
.finally(()=>poll.running=false)
}
poll();
setInterval(poll, 1000);
F.page.chat = Chat;
})();
|
Changes to src/fossil.dom.js.
| ︙ | ︙ | |||
287 288 289 290 291 292 293 |
var e = a[i];
if(isArray(e) || e.forEach){
e.forEach((x)=>f.call(this, parent,x));
continue;
}
if('string'===typeof e
|| 'number'===typeof e
| | > | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
var e = a[i];
if(isArray(e) || e.forEach){
e.forEach((x)=>f.call(this, parent,x));
continue;
}
if('string'===typeof e
|| 'number'===typeof e
|| 'boolean'===typeof e
|| e instanceof Error) e = this.text(e);
parent.appendChild(e);
}
return parent;
};
dom.input = function(type){
return this.attr(this.create('input'), 'type', type);
|
| ︙ | ︙ |
Changes to src/fossil.popupwidget.js.
| ︙ | ︙ | |||
270 271 272 273 274 275 276 |
Displays a toast with the 'warning' CSS class assigned to it. It
displays for 1.5 times as long as a normal toast.
*/
warning: function(/*...*/){
return toastImpl('warning',1.5,arguments);
},
/**
| | | 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
Displays a toast with the 'warning' CSS class assigned to it. It
displays for 1.5 times as long as a normal toast.
*/
warning: function(/*...*/){
return toastImpl('warning',1.5,arguments);
},
/**
Displays a toast with the 'error' CSS class assigned to it. It
displays for twice as long as a normal toast.
*/
error: function(/*...*/){
return toastImpl('error',2,arguments);
}
}/*F.toast*/;
|
| ︙ | ︙ |