Fossil SCM
In /chat, add a config option to audibly notify only for the first message received when the tab is not visible, and then remain silent until chat is visited again.
Commit
df86fa33571d6c4e3b0bd0ff08f305df6274cd239a3c5105e00c18ed0a412ce1
Parent
ea1b76bc9abdf00…
1 file changed
+19
-3
+19
-3
| --- src/fossil.page.chat.js | ||
| +++ src/fossil.page.chat.js | ||
| @@ -127,10 +127,11 @@ | ||
| 127 | 127 | fossil.FRK = ForceResizeKludge/*for debugging*/; |
| 128 | 128 | const Chat = ForceResizeKludge.chat = (function(){ |
| 129 | 129 | const cs = { // the "Chat" object (result of this function) |
| 130 | 130 | verboseErrors: false /* if true then certain, mostly extraneous, |
| 131 | 131 | error messages may be sent to the console. */, |
| 132 | + playedBeep: false /* used for the beep-once setting */, | |
| 132 | 133 | e:{/*map of certain DOM elements.*/ |
| 133 | 134 | messageInjectPoint: E1('#message-inject-point'), |
| 134 | 135 | pageTitle: E1('head title'), |
| 135 | 136 | loadOlderToolbar: undefined /* the load-posts toolbar (dynamically created) */, |
| 136 | 137 | inputWrapper: E1("#chat-input-area"), |
| @@ -410,10 +411,13 @@ | ||
| 410 | 411 | /* When set to a URI, it is assumed to be an audio file, |
| 411 | 412 | which gets played when new messages arrive. When true, |
| 412 | 413 | the first entry in the audio file selection list will be |
| 413 | 414 | used. */ |
| 414 | 415 | "audible-alert": true, |
| 416 | + /* | |
| 417 | + */ | |
| 418 | + "beep-once": false, | |
| 415 | 419 | /* When on, show the list of "active" users - those from |
| 416 | 420 | whom we have messages in the currently-loaded history |
| 417 | 421 | (noting that deletions are also messages). */ |
| 418 | 422 | "active-user-list": false, |
| 419 | 423 | /* When on, the [active-user-list] setting includes the |
| @@ -434,11 +438,17 @@ | ||
| 434 | 438 | /** Plays a new-message notification sound IF the audible-alert |
| 435 | 439 | setting is true, else this is a no-op. Returns this. |
| 436 | 440 | */ |
| 437 | 441 | playNewMessageSound: function f(){ |
| 438 | 442 | if(f.uri){ |
| 443 | + if(!cs.pageIsActive | |
| 444 | + /* ^^^ this could also arguably apply when chat is visible */ | |
| 445 | + && this.playedBeep && this.settings.getBool('beep-once',false)){ | |
| 446 | + return; | |
| 447 | + } | |
| 439 | 448 | try{ |
| 449 | + this.playedBeep = true; | |
| 440 | 450 | if(!f.audio) f.audio = new Audio(f.uri); |
| 441 | 451 | f.audio.currentTime = 0; |
| 442 | 452 | f.audio.play(); |
| 443 | 453 | }catch(e){ |
| 444 | 454 | console.error("Audio playblack failed.", f.uri, e); |
| @@ -451,10 +461,11 @@ | ||
| 451 | 461 | repository-relative path which responds with an audio |
| 452 | 462 | file). Pass a falsy value to disable audio alerts. Returns |
| 453 | 463 | this. |
| 454 | 464 | */ |
| 455 | 465 | setNewMessageSound: function f(uri){ |
| 466 | + this.playedBeep = false; | |
| 456 | 467 | delete this.playNewMessageSound.audio; |
| 457 | 468 | this.playNewMessageSound.uri = uri; |
| 458 | 469 | this.settings.set('audible-alert', uri); |
| 459 | 470 | return this; |
| 460 | 471 | }, |
| @@ -780,19 +791,19 @@ | ||
| 780 | 791 | cs._newResponseError = function(response){ |
| 781 | 792 | return new Error([ |
| 782 | 793 | "HTTP status ", response.status,": ",response.url,": ", |
| 783 | 794 | response.statusText].join('')); |
| 784 | 795 | }; |
| 785 | - | |
| 796 | + | |
| 786 | 797 | /** Helper for reporting HTTP-level response errors via fetch(). |
| 787 | 798 | If response.ok then response.json() is returned, else an Error |
| 788 | 799 | is thrown. */ |
| 789 | 800 | cs._fetchJsonOrError = function(response){ |
| 790 | 801 | if(response.ok) return response.json(); |
| 791 | 802 | else throw cs._newResponseError(response); |
| 792 | 803 | }; |
| 793 | - | |
| 804 | + | |
| 794 | 805 | /** |
| 795 | 806 | Removes the given message ID from the local chat record and, if |
| 796 | 807 | the message was posted by this user OR this user in an |
| 797 | 808 | admin/setup, also submits it for removal on the remote. |
| 798 | 809 | |
| @@ -819,10 +830,11 @@ | ||
| 819 | 830 | this.deleteMessageElem(id); |
| 820 | 831 | } |
| 821 | 832 | }; |
| 822 | 833 | document.addEventListener('visibilitychange', function(ev){ |
| 823 | 834 | cs.pageIsActive = ('visible' === document.visibilityState); |
| 835 | + cs.playedBeep = false; | |
| 824 | 836 | if(cs.pageIsActive){ |
| 825 | 837 | cs.e.pageTitle.innerText = cs.pageTitleOrig; |
| 826 | 838 | if(document.activeElement!==cs.inputElement()){ |
| 827 | 839 | /* An attempt to resolve usability problem reported by Joe |
| 828 | 840 | M. where the Pale Moon browser is giving input focus to |
| @@ -1738,10 +1750,14 @@ | ||
| 1738 | 1750 | const v = ev.target.value; |
| 1739 | 1751 | Chat.setNewMessageSound(v); |
| 1740 | 1752 | F.toast.message("Audio notifications "+(v ? "enabled" : "disabled")+"."); |
| 1741 | 1753 | if(v) setTimeout(()=>Chat.playNewMessageSound(), 0); |
| 1742 | 1754 | } |
| 1755 | + },{ | |
| 1756 | + label: "Notify only once when away", | |
| 1757 | + hint: "Notify only for the first message received after chat is hidden from view.", | |
| 1758 | + boolValue: 'beep-once' | |
| 1743 | 1759 | },{ |
| 1744 | 1760 | label: "Play notification for your own messages", |
| 1745 | 1761 | hint: "When enabled, the audio notification will be played for all messages, "+ |
| 1746 | 1762 | "including your own. When disabled only messages from other users "+ |
| 1747 | 1763 | "will trigger a notification.", |
| @@ -1922,11 +1938,11 @@ | ||
| 1922 | 1938 | Chat.settings.set(k,v) |
| 1923 | 1939 | /* fires event listeners so that the Config area checkboxes |
| 1924 | 1940 | get in sync */; |
| 1925 | 1941 | }); |
| 1926 | 1942 | })(); |
| 1927 | - | |
| 1943 | + | |
| 1928 | 1944 | (function(){/*set up message preview*/ |
| 1929 | 1945 | const btnPreview = Chat.e.btnPreview; |
| 1930 | 1946 | Chat.setPreviewText = function(t){ |
| 1931 | 1947 | this.setCurrentView(this.e.viewPreview); |
| 1932 | 1948 | this.e.previewContent.innerHTML = t; |
| 1933 | 1949 |
| --- src/fossil.page.chat.js | |
| +++ src/fossil.page.chat.js | |
| @@ -127,10 +127,11 @@ | |
| 127 | fossil.FRK = ForceResizeKludge/*for debugging*/; |
| 128 | const Chat = ForceResizeKludge.chat = (function(){ |
| 129 | const cs = { // the "Chat" object (result of this function) |
| 130 | verboseErrors: false /* if true then certain, mostly extraneous, |
| 131 | error messages may be sent to the console. */, |
| 132 | e:{/*map of certain DOM elements.*/ |
| 133 | messageInjectPoint: E1('#message-inject-point'), |
| 134 | pageTitle: E1('head title'), |
| 135 | loadOlderToolbar: undefined /* the load-posts toolbar (dynamically created) */, |
| 136 | inputWrapper: E1("#chat-input-area"), |
| @@ -410,10 +411,13 @@ | |
| 410 | /* When set to a URI, it is assumed to be an audio file, |
| 411 | which gets played when new messages arrive. When true, |
| 412 | the first entry in the audio file selection list will be |
| 413 | used. */ |
| 414 | "audible-alert": true, |
| 415 | /* When on, show the list of "active" users - those from |
| 416 | whom we have messages in the currently-loaded history |
| 417 | (noting that deletions are also messages). */ |
| 418 | "active-user-list": false, |
| 419 | /* When on, the [active-user-list] setting includes the |
| @@ -434,11 +438,17 @@ | |
| 434 | /** Plays a new-message notification sound IF the audible-alert |
| 435 | setting is true, else this is a no-op. Returns this. |
| 436 | */ |
| 437 | playNewMessageSound: function f(){ |
| 438 | if(f.uri){ |
| 439 | try{ |
| 440 | if(!f.audio) f.audio = new Audio(f.uri); |
| 441 | f.audio.currentTime = 0; |
| 442 | f.audio.play(); |
| 443 | }catch(e){ |
| 444 | console.error("Audio playblack failed.", f.uri, e); |
| @@ -451,10 +461,11 @@ | |
| 451 | repository-relative path which responds with an audio |
| 452 | file). Pass a falsy value to disable audio alerts. Returns |
| 453 | this. |
| 454 | */ |
| 455 | setNewMessageSound: function f(uri){ |
| 456 | delete this.playNewMessageSound.audio; |
| 457 | this.playNewMessageSound.uri = uri; |
| 458 | this.settings.set('audible-alert', uri); |
| 459 | return this; |
| 460 | }, |
| @@ -780,19 +791,19 @@ | |
| 780 | cs._newResponseError = function(response){ |
| 781 | return new Error([ |
| 782 | "HTTP status ", response.status,": ",response.url,": ", |
| 783 | response.statusText].join('')); |
| 784 | }; |
| 785 | |
| 786 | /** Helper for reporting HTTP-level response errors via fetch(). |
| 787 | If response.ok then response.json() is returned, else an Error |
| 788 | is thrown. */ |
| 789 | cs._fetchJsonOrError = function(response){ |
| 790 | if(response.ok) return response.json(); |
| 791 | else throw cs._newResponseError(response); |
| 792 | }; |
| 793 | |
| 794 | /** |
| 795 | Removes the given message ID from the local chat record and, if |
| 796 | the message was posted by this user OR this user in an |
| 797 | admin/setup, also submits it for removal on the remote. |
| 798 | |
| @@ -819,10 +830,11 @@ | |
| 819 | this.deleteMessageElem(id); |
| 820 | } |
| 821 | }; |
| 822 | document.addEventListener('visibilitychange', function(ev){ |
| 823 | cs.pageIsActive = ('visible' === document.visibilityState); |
| 824 | if(cs.pageIsActive){ |
| 825 | cs.e.pageTitle.innerText = cs.pageTitleOrig; |
| 826 | if(document.activeElement!==cs.inputElement()){ |
| 827 | /* An attempt to resolve usability problem reported by Joe |
| 828 | M. where the Pale Moon browser is giving input focus to |
| @@ -1738,10 +1750,14 @@ | |
| 1738 | const v = ev.target.value; |
| 1739 | Chat.setNewMessageSound(v); |
| 1740 | F.toast.message("Audio notifications "+(v ? "enabled" : "disabled")+"."); |
| 1741 | if(v) setTimeout(()=>Chat.playNewMessageSound(), 0); |
| 1742 | } |
| 1743 | },{ |
| 1744 | label: "Play notification for your own messages", |
| 1745 | hint: "When enabled, the audio notification will be played for all messages, "+ |
| 1746 | "including your own. When disabled only messages from other users "+ |
| 1747 | "will trigger a notification.", |
| @@ -1922,11 +1938,11 @@ | |
| 1922 | Chat.settings.set(k,v) |
| 1923 | /* fires event listeners so that the Config area checkboxes |
| 1924 | get in sync */; |
| 1925 | }); |
| 1926 | })(); |
| 1927 | |
| 1928 | (function(){/*set up message preview*/ |
| 1929 | const btnPreview = Chat.e.btnPreview; |
| 1930 | Chat.setPreviewText = function(t){ |
| 1931 | this.setCurrentView(this.e.viewPreview); |
| 1932 | this.e.previewContent.innerHTML = t; |
| 1933 |
| --- src/fossil.page.chat.js | |
| +++ src/fossil.page.chat.js | |
| @@ -127,10 +127,11 @@ | |
| 127 | fossil.FRK = ForceResizeKludge/*for debugging*/; |
| 128 | const Chat = ForceResizeKludge.chat = (function(){ |
| 129 | const cs = { // the "Chat" object (result of this function) |
| 130 | verboseErrors: false /* if true then certain, mostly extraneous, |
| 131 | error messages may be sent to the console. */, |
| 132 | playedBeep: false /* used for the beep-once setting */, |
| 133 | e:{/*map of certain DOM elements.*/ |
| 134 | messageInjectPoint: E1('#message-inject-point'), |
| 135 | pageTitle: E1('head title'), |
| 136 | loadOlderToolbar: undefined /* the load-posts toolbar (dynamically created) */, |
| 137 | inputWrapper: E1("#chat-input-area"), |
| @@ -410,10 +411,13 @@ | |
| 411 | /* When set to a URI, it is assumed to be an audio file, |
| 412 | which gets played when new messages arrive. When true, |
| 413 | the first entry in the audio file selection list will be |
| 414 | used. */ |
| 415 | "audible-alert": true, |
| 416 | /* |
| 417 | */ |
| 418 | "beep-once": false, |
| 419 | /* When on, show the list of "active" users - those from |
| 420 | whom we have messages in the currently-loaded history |
| 421 | (noting that deletions are also messages). */ |
| 422 | "active-user-list": false, |
| 423 | /* When on, the [active-user-list] setting includes the |
| @@ -434,11 +438,17 @@ | |
| 438 | /** Plays a new-message notification sound IF the audible-alert |
| 439 | setting is true, else this is a no-op. Returns this. |
| 440 | */ |
| 441 | playNewMessageSound: function f(){ |
| 442 | if(f.uri){ |
| 443 | if(!cs.pageIsActive |
| 444 | /* ^^^ this could also arguably apply when chat is visible */ |
| 445 | && this.playedBeep && this.settings.getBool('beep-once',false)){ |
| 446 | return; |
| 447 | } |
| 448 | try{ |
| 449 | this.playedBeep = true; |
| 450 | if(!f.audio) f.audio = new Audio(f.uri); |
| 451 | f.audio.currentTime = 0; |
| 452 | f.audio.play(); |
| 453 | }catch(e){ |
| 454 | console.error("Audio playblack failed.", f.uri, e); |
| @@ -451,10 +461,11 @@ | |
| 461 | repository-relative path which responds with an audio |
| 462 | file). Pass a falsy value to disable audio alerts. Returns |
| 463 | this. |
| 464 | */ |
| 465 | setNewMessageSound: function f(uri){ |
| 466 | this.playedBeep = false; |
| 467 | delete this.playNewMessageSound.audio; |
| 468 | this.playNewMessageSound.uri = uri; |
| 469 | this.settings.set('audible-alert', uri); |
| 470 | return this; |
| 471 | }, |
| @@ -780,19 +791,19 @@ | |
| 791 | cs._newResponseError = function(response){ |
| 792 | return new Error([ |
| 793 | "HTTP status ", response.status,": ",response.url,": ", |
| 794 | response.statusText].join('')); |
| 795 | }; |
| 796 | |
| 797 | /** Helper for reporting HTTP-level response errors via fetch(). |
| 798 | If response.ok then response.json() is returned, else an Error |
| 799 | is thrown. */ |
| 800 | cs._fetchJsonOrError = function(response){ |
| 801 | if(response.ok) return response.json(); |
| 802 | else throw cs._newResponseError(response); |
| 803 | }; |
| 804 | |
| 805 | /** |
| 806 | Removes the given message ID from the local chat record and, if |
| 807 | the message was posted by this user OR this user in an |
| 808 | admin/setup, also submits it for removal on the remote. |
| 809 | |
| @@ -819,10 +830,11 @@ | |
| 830 | this.deleteMessageElem(id); |
| 831 | } |
| 832 | }; |
| 833 | document.addEventListener('visibilitychange', function(ev){ |
| 834 | cs.pageIsActive = ('visible' === document.visibilityState); |
| 835 | cs.playedBeep = false; |
| 836 | if(cs.pageIsActive){ |
| 837 | cs.e.pageTitle.innerText = cs.pageTitleOrig; |
| 838 | if(document.activeElement!==cs.inputElement()){ |
| 839 | /* An attempt to resolve usability problem reported by Joe |
| 840 | M. where the Pale Moon browser is giving input focus to |
| @@ -1738,10 +1750,14 @@ | |
| 1750 | const v = ev.target.value; |
| 1751 | Chat.setNewMessageSound(v); |
| 1752 | F.toast.message("Audio notifications "+(v ? "enabled" : "disabled")+"."); |
| 1753 | if(v) setTimeout(()=>Chat.playNewMessageSound(), 0); |
| 1754 | } |
| 1755 | },{ |
| 1756 | label: "Notify only once when away", |
| 1757 | hint: "Notify only for the first message received after chat is hidden from view.", |
| 1758 | boolValue: 'beep-once' |
| 1759 | },{ |
| 1760 | label: "Play notification for your own messages", |
| 1761 | hint: "When enabled, the audio notification will be played for all messages, "+ |
| 1762 | "including your own. When disabled only messages from other users "+ |
| 1763 | "will trigger a notification.", |
| @@ -1922,11 +1938,11 @@ | |
| 1938 | Chat.settings.set(k,v) |
| 1939 | /* fires event listeners so that the Config area checkboxes |
| 1940 | get in sync */; |
| 1941 | }); |
| 1942 | })(); |
| 1943 | |
| 1944 | (function(){/*set up message preview*/ |
| 1945 | const btnPreview = Chat.e.btnPreview; |
| 1946 | Chat.setPreviewText = function(t){ |
| 1947 | this.setCurrentView(this.e.viewPreview); |
| 1948 | this.e.previewContent.innerHTML = t; |
| 1949 |