Fossil SCM
Add a 'retry now' button to the /chat poller timeout notification widgets. Fix a bug which kept Chat.deleteMessageElem() from working if it was passed a MessageWidget instance.
Commit
8c64fa26f3f51eeecd221180ef004286301fb23be284a1bf99dc10ca03d3a34e
Parent
5fc2f2a034197ef…
1 file changed
+31
-16
+31
-16
| --- src/fossil.page.chat.js | ||
| +++ src/fossil.page.chat.js | ||
| @@ -760,26 +760,25 @@ | ||
| 760 | 760 | the .message-row element. Returns true if it removes an element, |
| 761 | 761 | else false. |
| 762 | 762 | */ |
| 763 | 763 | cs.deleteMessageElem = function(id, silent){ |
| 764 | 764 | var e; |
| 765 | - //console.warn("Chat.deleteMessageElem",id,silent); | |
| 766 | 765 | if(id instanceof HTMLElement){ |
| 767 | 766 | e = id; |
| 768 | 767 | id = e.dataset.msgid; |
| 769 | 768 | delete e.dataset.msgid; |
| 770 | 769 | if( e?.dataset?.alsoRemove ){ |
| 771 | 770 | const xId = e.dataset.alsoRemove; |
| 772 | 771 | delete e.dataset.alsoRemove; |
| 773 | 772 | this.deleteMessageElem( xId ); |
| 774 | 773 | } |
| 775 | - }else if(e instanceof Chat.MessageWidget) { | |
| 776 | - if( this.e.eMsgPollError === e.body ){ | |
| 774 | + }else if(id instanceof Chat.MessageWidget) { | |
| 775 | + if( this.e.eMsgPollError === e ){ | |
| 777 | 776 | this.e.eMsgPollError = undefined; |
| 778 | 777 | } |
| 779 | - if(e.e.body){ | |
| 780 | - this.deleteMessageElem(e.e.body); | |
| 778 | + if(id.e?.body){ | |
| 779 | + this.deleteMessageElem(id.e.body); | |
| 781 | 780 | } |
| 782 | 781 | return; |
| 783 | 782 | } else{ |
| 784 | 783 | e = this.getMessageElemById(id); |
| 785 | 784 | } |
| @@ -1744,10 +1743,13 @@ | ||
| 1744 | 1743 | if( Chat.e.eMsgPollError ) { |
| 1745 | 1744 | const oldErrMsg = Chat.e.eMsgPollError; |
| 1746 | 1745 | Chat.e.eMsgPollError = undefined; |
| 1747 | 1746 | if( showMsg ){ |
| 1748 | 1747 | const m = Chat.reportReconnection("Poller connection restored."); |
| 1748 | + if( oldErrMsg ){ | |
| 1749 | + D.remove(oldErrMsg.e?.body.querySelector('button.retry-now')); | |
| 1750 | + } | |
| 1749 | 1751 | m.e.body.dataset.alsoRemove = oldErrMsg?.e?.body?.dataset?.msgid; |
| 1750 | 1752 | D.addClass(m.e.body,'poller-connection'); |
| 1751 | 1753 | } |
| 1752 | 1754 | } |
| 1753 | 1755 | setTimeout( Chat.poll, 0 ); |
| @@ -2631,25 +2633,38 @@ | ||
| 2631 | 2633 | resolves, in which case they'll clear this timeout and the |
| 2632 | 2634 | UI message about the outage. */ |
| 2633 | 2635 | const delay = Chat.timer.incrDelay(); |
| 2634 | 2636 | //console.warn("afterPollFetch Chat.e.eMsgPollError",Chat.e.eMsgPollError); |
| 2635 | 2637 | const msg = "Poller connection error. Retrying in "+delay+ " ms."; |
| 2636 | - if( Chat.e.eMsgPollError ){ | |
| 2637 | - /* Update the error message on the current error MessageWidget */ | |
| 2638 | - /* The disadvantage to doing this is that we don't update the timestamp. */ | |
| 2639 | - Chat.e.eMsgPollError.e.content.innerText = msg; | |
| 2640 | - }else { | |
| 2641 | - /* Set current (new) error MessageWidget */ | |
| 2642 | - Chat.e.eMsgPollError = Chat.reportErrorAsMessage(msg); | |
| 2643 | - //Chat.playNewMessageSound();// browser complains b/c this wasn't via human interaction | |
| 2644 | - D.addClass(Chat.e.eMsgPollError.e.body,'poller-connection'); | |
| 2645 | - } | |
| 2638 | + /* Replace the current/newest connection error widget. We could also | |
| 2639 | + just update its body with the new message, but then its timestamp | |
| 2640 | + never updates. OTOH, if we replace the message, we lose the | |
| 2641 | + start time of the outage in the log. It seems more useful to | |
| 2642 | + update the timestamp so that it doesn't look like it's hung. */ | |
| 2643 | + if( Chat.e.eMsgPollError ){ | |
| 2644 | + Chat.deleteMessageElem(Chat.e.eMsgPollError, false); | |
| 2645 | + } | |
| 2646 | + const theMsg = Chat.e.eMsgPollError = Chat.reportErrorAsMessage(msg); | |
| 2647 | + D.addClass(Chat.e.eMsgPollError.e.body,'poller-connection'); | |
| 2648 | + /* Add a "retry now" button */ | |
| 2649 | + const btnDel = D.addClass(D.button("Retry now"), 'retry-now'); | |
| 2650 | + D.append(Chat.e.eMsgPollError.e.content, " ", btnDel); | |
| 2651 | + btnDel.addEventListener('click', function(){ | |
| 2652 | + D.remove(btnDel); | |
| 2653 | + Chat.timer.currentDelay = | |
| 2654 | + Chat.timer.resetDelay() + 1 /*workaround for showing the "connection restored" message*/; | |
| 2655 | + if( Chat.timer.tidPoller ){ | |
| 2656 | + clearTimeout(Chat.timer.tidPoller); | |
| 2657 | + Chat.timer.tidPoller = 0; | |
| 2658 | + } | |
| 2659 | + poll(); | |
| 2660 | + }); | |
| 2661 | + //Chat.playNewMessageSound();// browser complains b/c this wasn't via human interaction | |
| 2646 | 2662 | Chat.timer.tidPoller = setTimeout(()=>{ |
| 2647 | 2663 | poll(); |
| 2648 | 2664 | }, delay); |
| 2649 | 2665 | } |
| 2650 | - //console.log("isOkay =",isOkay,"currentDelay =",Chat.timer.currentDelay); | |
| 2651 | 2666 | } |
| 2652 | 2667 | }; |
| 2653 | 2668 | afterPollFetch.isFirstCall = true; |
| 2654 | 2669 | |
| 2655 | 2670 | /** |
| 2656 | 2671 |
| --- src/fossil.page.chat.js | |
| +++ src/fossil.page.chat.js | |
| @@ -760,26 +760,25 @@ | |
| 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 | } |
| @@ -1744,10 +1743,13 @@ | |
| 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 ); |
| @@ -2631,25 +2633,38 @@ | |
| 2631 | resolves, in which case they'll clear this timeout and the |
| 2632 | UI message about the outage. */ |
| 2633 | const delay = Chat.timer.incrDelay(); |
| 2634 | //console.warn("afterPollFetch Chat.e.eMsgPollError",Chat.e.eMsgPollError); |
| 2635 | const msg = "Poller connection error. Retrying in "+delay+ " ms."; |
| 2636 | if( Chat.e.eMsgPollError ){ |
| 2637 | /* Update the error message on the current error MessageWidget */ |
| 2638 | /* The disadvantage to doing this is that we don't update the timestamp. */ |
| 2639 | Chat.e.eMsgPollError.e.content.innerText = msg; |
| 2640 | }else { |
| 2641 | /* Set current (new) error MessageWidget */ |
| 2642 | Chat.e.eMsgPollError = Chat.reportErrorAsMessage(msg); |
| 2643 | //Chat.playNewMessageSound();// browser complains b/c this wasn't via human interaction |
| 2644 | D.addClass(Chat.e.eMsgPollError.e.body,'poller-connection'); |
| 2645 | } |
| 2646 | Chat.timer.tidPoller = setTimeout(()=>{ |
| 2647 | poll(); |
| 2648 | }, delay); |
| 2649 | } |
| 2650 | //console.log("isOkay =",isOkay,"currentDelay =",Chat.timer.currentDelay); |
| 2651 | } |
| 2652 | }; |
| 2653 | afterPollFetch.isFirstCall = true; |
| 2654 | |
| 2655 | /** |
| 2656 |
| --- src/fossil.page.chat.js | |
| +++ src/fossil.page.chat.js | |
| @@ -760,26 +760,25 @@ | |
| 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 | if(id instanceof HTMLElement){ |
| 766 | e = id; |
| 767 | id = e.dataset.msgid; |
| 768 | delete e.dataset.msgid; |
| 769 | if( e?.dataset?.alsoRemove ){ |
| 770 | const xId = e.dataset.alsoRemove; |
| 771 | delete e.dataset.alsoRemove; |
| 772 | this.deleteMessageElem( xId ); |
| 773 | } |
| 774 | }else if(id instanceof Chat.MessageWidget) { |
| 775 | if( this.e.eMsgPollError === e ){ |
| 776 | this.e.eMsgPollError = undefined; |
| 777 | } |
| 778 | if(id.e?.body){ |
| 779 | this.deleteMessageElem(id.e.body); |
| 780 | } |
| 781 | return; |
| 782 | } else{ |
| 783 | e = this.getMessageElemById(id); |
| 784 | } |
| @@ -1744,10 +1743,13 @@ | |
| 1743 | if( Chat.e.eMsgPollError ) { |
| 1744 | const oldErrMsg = Chat.e.eMsgPollError; |
| 1745 | Chat.e.eMsgPollError = undefined; |
| 1746 | if( showMsg ){ |
| 1747 | const m = Chat.reportReconnection("Poller connection restored."); |
| 1748 | if( oldErrMsg ){ |
| 1749 | D.remove(oldErrMsg.e?.body.querySelector('button.retry-now')); |
| 1750 | } |
| 1751 | m.e.body.dataset.alsoRemove = oldErrMsg?.e?.body?.dataset?.msgid; |
| 1752 | D.addClass(m.e.body,'poller-connection'); |
| 1753 | } |
| 1754 | } |
| 1755 | setTimeout( Chat.poll, 0 ); |
| @@ -2631,25 +2633,38 @@ | |
| 2633 | resolves, in which case they'll clear this timeout and the |
| 2634 | UI message about the outage. */ |
| 2635 | const delay = Chat.timer.incrDelay(); |
| 2636 | //console.warn("afterPollFetch Chat.e.eMsgPollError",Chat.e.eMsgPollError); |
| 2637 | const msg = "Poller connection error. Retrying in "+delay+ " ms."; |
| 2638 | /* Replace the current/newest connection error widget. We could also |
| 2639 | just update its body with the new message, but then its timestamp |
| 2640 | never updates. OTOH, if we replace the message, we lose the |
| 2641 | start time of the outage in the log. It seems more useful to |
| 2642 | update the timestamp so that it doesn't look like it's hung. */ |
| 2643 | if( Chat.e.eMsgPollError ){ |
| 2644 | Chat.deleteMessageElem(Chat.e.eMsgPollError, false); |
| 2645 | } |
| 2646 | const theMsg = Chat.e.eMsgPollError = Chat.reportErrorAsMessage(msg); |
| 2647 | D.addClass(Chat.e.eMsgPollError.e.body,'poller-connection'); |
| 2648 | /* Add a "retry now" button */ |
| 2649 | const btnDel = D.addClass(D.button("Retry now"), 'retry-now'); |
| 2650 | D.append(Chat.e.eMsgPollError.e.content, " ", btnDel); |
| 2651 | btnDel.addEventListener('click', function(){ |
| 2652 | D.remove(btnDel); |
| 2653 | Chat.timer.currentDelay = |
| 2654 | Chat.timer.resetDelay() + 1 /*workaround for showing the "connection restored" message*/; |
| 2655 | if( Chat.timer.tidPoller ){ |
| 2656 | clearTimeout(Chat.timer.tidPoller); |
| 2657 | Chat.timer.tidPoller = 0; |
| 2658 | } |
| 2659 | poll(); |
| 2660 | }); |
| 2661 | //Chat.playNewMessageSound();// browser complains b/c this wasn't via human interaction |
| 2662 | Chat.timer.tidPoller = setTimeout(()=>{ |
| 2663 | poll(); |
| 2664 | }, delay); |
| 2665 | } |
| 2666 | } |
| 2667 | }; |
| 2668 | afterPollFetch.isFirstCall = true; |
| 2669 | |
| 2670 | /** |
| 2671 |