Fossil SCM

When deleting a connection-restored notification, also delete the connection-broken notification it's associated with. Add a button to the message popup for connection-related notifications to delete all connection-related notifications. When running on localhost, reduce the /chat poller timeout to 15s.

stephan 2025-04-10 07:23 chat-backoff-timer2
Commit 79932a5210bf409cd247c71599639ae81fea707719c5d3b406e30c1a98460f63
1 file changed +40 -10
--- src/fossil.page.chat.js
+++ src/fossil.page.chat.js
@@ -758,24 +758,41 @@
758758
/**
759759
LOCALLY deletes a message element by the message ID or passing
760760
the .message-row element. Returns true if it removes an element,
761761
else false.
762762
*/
763
- cs.deleteMessageElem = function(id){
763
+ cs.deleteMessageElem = function(id, silent){
764764
var e;
765
+ //console.warn("Chat.deleteMessageElem",id,silent);
765766
if(id instanceof HTMLElement){
766767
e = id;
767768
id = e.dataset.msgid;
768
- }else{
769
+ delete e.dataset.msgid;
770
+ if( e?.dataset?.alsoRemove ){
771
+ const xId = e.dataset.alsoRemove;
772
+ delete e.dataset.alsoRemove;
773
+ this.deleteMessageElem( xId );
774
+ }
775
+ }else if(e instanceof Chat.MessageWidget) {
776
+ if( this.e.eMsgPollError === e.body ){
777
+ this.e.eMsgPollError = undefined;
778
+ }
779
+ if(e.e.body){
780
+ this.deleteMessageElem(e.e.body);
781
+ }
782
+ return;
783
+ } else{
769784
e = this.getMessageElemById(id);
770785
}
771786
if(e && id){
772787
D.remove(e);
773788
if(e===this.e.newestMessage){
774789
this.fetchLastMessageElem();
775790
}
776
- F.toast.message("Deleted message "+id+".");
791
+ if( !silent ){
792
+ F.toast.message("Deleted message "+id+".");
793
+ }
777794
}
778795
return !!e;
779796
};
780797
781798
/**
@@ -1107,10 +1124,11 @@
11071124
11081125
ctor.prototype = {
11091126
scrollIntoView: function(){
11101127
this.e.content.scrollIntoView();
11111128
},
1129
+ //remove: function(silent){Chat.deleteMessageElem(this, silent);},
11121130
setMessage: function(m){
11131131
const ds = this.e.body.dataset;
11141132
ds.timestamp = m.mtime;
11151133
ds.lmtime = m.lmtime;
11161134
ds.msgid = m.msgid;
@@ -1284,12 +1302,21 @@
12841302
const btnDeleteLocal = D.button("Delete locally");
12851303
D.append(toolbar, btnDeleteLocal);
12861304
const self = this;
12871305
btnDeleteLocal.addEventListener('click', function(){
12881306
self.hide();
1289
- Chat.deleteMessageElem(eMsg);
1307
+ Chat.deleteMessageElem(eMsg)
12901308
});
1309
+ if( eMsg.classList.contains('poller-connection') ){
1310
+ const btnDeletePoll = D.button("Delete poller messages?");
1311
+ D.append(toolbar, btnDeletePoll);
1312
+ btnDeletePoll.addEventListener('click', function(){
1313
+ self.hide();
1314
+ Chat.e.viewMessages.querySelectorAll('.message-widget.poller-connection')
1315
+ .forEach(e=>Chat.deleteMessageElem(e, true));
1316
+ });
1317
+ }
12911318
if(Chat.userMayDelete(eMsg)){
12921319
const btnDeleteGlobal = D.button("Delete globally");
12931320
D.append(toolbar, btnDeleteGlobal);
12941321
F.confirmer(btnDeleteGlobal,{
12951322
pinSize: true,
@@ -1713,15 +1740,16 @@
17131740
clearTimeout(Chat.timer.tidReconnect);
17141741
Chat.timer.tidReconnect = 0;
17151742
}
17161743
Chat.timer.resetDelay();
17171744
if( Chat.e.eMsgPollError ) {
1745
+ const oldErrMsg = Chat.e.eMsgPollError;
17181746
Chat.e.eMsgPollError = undefined;
17191747
if( showMsg ){
1720
- Chat.reportReconnection(
1721
- "Poller connection restored."
1722
- );
1748
+ const m = Chat.reportReconnection("Poller connection restored.");
1749
+ m.e.body.dataset.alsoRemove = oldErrMsg?.e?.body?.dataset?.msgid;
1750
+ D.addClass(m.e.body,'poller-connection');
17231751
}
17241752
}
17251753
setTimeout( Chat.poll, 0 );
17261754
};
17271755
@@ -2610,10 +2638,11 @@
26102638
Chat.e.eMsgPollError.e.content.innerText = msg;
26112639
}else {
26122640
/* Set current (new) error MessageWidget */
26132641
Chat.e.eMsgPollError = Chat.reportErrorAsMessage(msg);
26142642
//Chat.playNewMessageSound();// browser complains b/c this wasn't via human interaction
2643
+ D.addClass(Chat.e.eMsgPollError.e.body,'poller-connection');
26152644
}
26162645
Chat.timer.tidPoller = setTimeout(()=>{
26172646
poll();
26182647
}, delay);
26192648
}
@@ -2681,13 +2710,14 @@
26812710
1000
26822711
);
26832712
}
26842713
let nErr = 0;
26852714
F.fetch("chat-poll",{
2686
- timeout: 1
2687
- ? 420 * 1000/*FIXME: get the value from the server*/
2688
- : 15000,
2715
+ timeout: window.location.hostname.match(
2716
+ "localhost" /*presumably local dev mode*/
2717
+ ) ? 15000
2718
+ : 420 * 1000/*FIXME: get the value from the server*/,
26892719
urlParams:{
26902720
name: Chat.mxMsg
26912721
},
26922722
responseType: "json",
26932723
// Disable the ajax start/end handling for this long-polling op:
26942724
--- src/fossil.page.chat.js
+++ src/fossil.page.chat.js
@@ -758,24 +758,41 @@
758 /**
759 LOCALLY deletes a message element by the message ID or passing
760 the .message-row element. Returns true if it removes an element,
761 else false.
762 */
763 cs.deleteMessageElem = function(id){
764 var e;
 
765 if(id instanceof HTMLElement){
766 e = id;
767 id = e.dataset.msgid;
768 }else{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
769 e = this.getMessageElemById(id);
770 }
771 if(e && id){
772 D.remove(e);
773 if(e===this.e.newestMessage){
774 this.fetchLastMessageElem();
775 }
776 F.toast.message("Deleted message "+id+".");
 
 
777 }
778 return !!e;
779 };
780
781 /**
@@ -1107,10 +1124,11 @@
1107
1108 ctor.prototype = {
1109 scrollIntoView: function(){
1110 this.e.content.scrollIntoView();
1111 },
 
1112 setMessage: function(m){
1113 const ds = this.e.body.dataset;
1114 ds.timestamp = m.mtime;
1115 ds.lmtime = m.lmtime;
1116 ds.msgid = m.msgid;
@@ -1284,12 +1302,21 @@
1284 const btnDeleteLocal = D.button("Delete locally");
1285 D.append(toolbar, btnDeleteLocal);
1286 const self = this;
1287 btnDeleteLocal.addEventListener('click', function(){
1288 self.hide();
1289 Chat.deleteMessageElem(eMsg);
1290 });
 
 
 
 
 
 
 
 
 
1291 if(Chat.userMayDelete(eMsg)){
1292 const btnDeleteGlobal = D.button("Delete globally");
1293 D.append(toolbar, btnDeleteGlobal);
1294 F.confirmer(btnDeleteGlobal,{
1295 pinSize: true,
@@ -1713,15 +1740,16 @@
1713 clearTimeout(Chat.timer.tidReconnect);
1714 Chat.timer.tidReconnect = 0;
1715 }
1716 Chat.timer.resetDelay();
1717 if( Chat.e.eMsgPollError ) {
 
1718 Chat.e.eMsgPollError = undefined;
1719 if( showMsg ){
1720 Chat.reportReconnection(
1721 "Poller connection restored."
1722 );
1723 }
1724 }
1725 setTimeout( Chat.poll, 0 );
1726 };
1727
@@ -2610,10 +2638,11 @@
2610 Chat.e.eMsgPollError.e.content.innerText = msg;
2611 }else {
2612 /* Set current (new) error MessageWidget */
2613 Chat.e.eMsgPollError = Chat.reportErrorAsMessage(msg);
2614 //Chat.playNewMessageSound();// browser complains b/c this wasn't via human interaction
 
2615 }
2616 Chat.timer.tidPoller = setTimeout(()=>{
2617 poll();
2618 }, delay);
2619 }
@@ -2681,13 +2710,14 @@
2681 1000
2682 );
2683 }
2684 let nErr = 0;
2685 F.fetch("chat-poll",{
2686 timeout: 1
2687 ? 420 * 1000/*FIXME: get the value from the server*/
2688 : 15000,
 
2689 urlParams:{
2690 name: Chat.mxMsg
2691 },
2692 responseType: "json",
2693 // Disable the ajax start/end handling for this long-polling op:
2694
--- src/fossil.page.chat.js
+++ src/fossil.page.chat.js
@@ -758,24 +758,41 @@
758 /**
759 LOCALLY deletes a message element by the message ID or passing
760 the .message-row element. Returns true if it removes an element,
761 else false.
762 */
763 cs.deleteMessageElem = function(id, silent){
764 var e;
765 //console.warn("Chat.deleteMessageElem",id,silent);
766 if(id instanceof HTMLElement){
767 e = id;
768 id = e.dataset.msgid;
769 delete e.dataset.msgid;
770 if( e?.dataset?.alsoRemove ){
771 const xId = e.dataset.alsoRemove;
772 delete e.dataset.alsoRemove;
773 this.deleteMessageElem( xId );
774 }
775 }else if(e instanceof Chat.MessageWidget) {
776 if( this.e.eMsgPollError === e.body ){
777 this.e.eMsgPollError = undefined;
778 }
779 if(e.e.body){
780 this.deleteMessageElem(e.e.body);
781 }
782 return;
783 } else{
784 e = this.getMessageElemById(id);
785 }
786 if(e && id){
787 D.remove(e);
788 if(e===this.e.newestMessage){
789 this.fetchLastMessageElem();
790 }
791 if( !silent ){
792 F.toast.message("Deleted message "+id+".");
793 }
794 }
795 return !!e;
796 };
797
798 /**
@@ -1107,10 +1124,11 @@
1124
1125 ctor.prototype = {
1126 scrollIntoView: function(){
1127 this.e.content.scrollIntoView();
1128 },
1129 //remove: function(silent){Chat.deleteMessageElem(this, silent);},
1130 setMessage: function(m){
1131 const ds = this.e.body.dataset;
1132 ds.timestamp = m.mtime;
1133 ds.lmtime = m.lmtime;
1134 ds.msgid = m.msgid;
@@ -1284,12 +1302,21 @@
1302 const btnDeleteLocal = D.button("Delete locally");
1303 D.append(toolbar, btnDeleteLocal);
1304 const self = this;
1305 btnDeleteLocal.addEventListener('click', function(){
1306 self.hide();
1307 Chat.deleteMessageElem(eMsg)
1308 });
1309 if( eMsg.classList.contains('poller-connection') ){
1310 const btnDeletePoll = D.button("Delete poller messages?");
1311 D.append(toolbar, btnDeletePoll);
1312 btnDeletePoll.addEventListener('click', function(){
1313 self.hide();
1314 Chat.e.viewMessages.querySelectorAll('.message-widget.poller-connection')
1315 .forEach(e=>Chat.deleteMessageElem(e, true));
1316 });
1317 }
1318 if(Chat.userMayDelete(eMsg)){
1319 const btnDeleteGlobal = D.button("Delete globally");
1320 D.append(toolbar, btnDeleteGlobal);
1321 F.confirmer(btnDeleteGlobal,{
1322 pinSize: true,
@@ -1713,15 +1740,16 @@
1740 clearTimeout(Chat.timer.tidReconnect);
1741 Chat.timer.tidReconnect = 0;
1742 }
1743 Chat.timer.resetDelay();
1744 if( Chat.e.eMsgPollError ) {
1745 const oldErrMsg = Chat.e.eMsgPollError;
1746 Chat.e.eMsgPollError = undefined;
1747 if( showMsg ){
1748 const m = Chat.reportReconnection("Poller connection restored.");
1749 m.e.body.dataset.alsoRemove = oldErrMsg?.e?.body?.dataset?.msgid;
1750 D.addClass(m.e.body,'poller-connection');
1751 }
1752 }
1753 setTimeout( Chat.poll, 0 );
1754 };
1755
@@ -2610,10 +2638,11 @@
2638 Chat.e.eMsgPollError.e.content.innerText = msg;
2639 }else {
2640 /* Set current (new) error MessageWidget */
2641 Chat.e.eMsgPollError = Chat.reportErrorAsMessage(msg);
2642 //Chat.playNewMessageSound();// browser complains b/c this wasn't via human interaction
2643 D.addClass(Chat.e.eMsgPollError.e.body,'poller-connection');
2644 }
2645 Chat.timer.tidPoller = setTimeout(()=>{
2646 poll();
2647 }, delay);
2648 }
@@ -2681,13 +2710,14 @@
2710 1000
2711 );
2712 }
2713 let nErr = 0;
2714 F.fetch("chat-poll",{
2715 timeout: window.location.hostname.match(
2716 "localhost" /*presumably local dev mode*/
2717 ) ? 15000
2718 : 420 * 1000/*FIXME: get the value from the server*/,
2719 urlParams:{
2720 name: Chat.mxMsg
2721 },
2722 responseType: "json",
2723 // Disable the ajax start/end handling for this long-polling op:
2724

Keyboard Shortcuts

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