Fossil SCM
Chat: if the current tab is not active when a message arrives, update the title to show the new message count. When the tab is active, revert the title. Note that deletions currently count towards new events, but that's arguable.
Commit
d79592059ae211427d37acf00bc9e78c0bb1638a294d106a28f6a92954944ef8
Parent
c5095283fb44031…
1 file changed
+20
-11
+20
-11
| --- src/chat.js | ||
| +++ src/chat.js | ||
| @@ -1,22 +1,22 @@ | ||
| 1 | +/** | |
| 2 | + This file contains the client-side implementation of fossil's /chat | |
| 3 | + application. | |
| 4 | +*/ | |
| 1 | 5 | (function(){ |
| 2 | 6 | const form = document.querySelector('#chat-form'); |
| 3 | 7 | const F = window.fossil, D = F.dom; |
| 4 | 8 | const Chat = (function(){ |
| 5 | 9 | const cs = { |
| 6 | 10 | me: F.user.name, |
| 7 | 11 | mxMsg: F.config.chatInitSize ? -F.config.chatInitSize : -50, |
| 8 | - pageIsActive: !document.hidden, | |
| 9 | - onPageActive: function(){console.debug("Page active.")}, //override below | |
| 10 | - onPageInactive: function(){console.debug("Page inactive.")} //override below | |
| 12 | + pageIsActive: 'visible'===document.visibilityState, | |
| 13 | + changesSincePageHidden: 0, | |
| 14 | + notificationBubbleColor: 'white', | |
| 15 | + pageTitle: document.querySelector('head title') | |
| 11 | 16 | }; |
| 12 | - document.addEventListener('visibilitychange', function(ev){ | |
| 13 | - cs.pageIsActive = !document.hidden; | |
| 14 | - if(cs.pageIsActive) cs.onPageActive(); | |
| 15 | - else cs.onPageInactive(); | |
| 16 | - }, true); | |
| 17 | - | |
| 17 | + cs.pageTitleOrig = cs.pageTitle.innerText; | |
| 18 | 18 | const qs = (e)=>document.querySelector(e); |
| 19 | 19 | const argsToArray = function(args){ |
| 20 | 20 | return Array.prototype.slice.call(args,0); |
| 21 | 21 | }; |
| 22 | 22 | cs.reportError = function(/*msg args*/){ |
| @@ -82,13 +82,12 @@ | ||
| 82 | 82 | .catch(err=>this.reportError(err)) |
| 83 | 83 | }else{ |
| 84 | 84 | this.deleteMessageElem(id); |
| 85 | 85 | } |
| 86 | 86 | }; |
| 87 | - | |
| 88 | 87 | return cs; |
| 89 | - })(); | |
| 88 | + })()/*Chat initialization*/; | |
| 90 | 89 | /* State for paste and drag/drop */ |
| 91 | 90 | const BlobXferState = { |
| 92 | 91 | dropDetails: document.querySelector('#chat-drop-details'), |
| 93 | 92 | blob: undefined |
| 94 | 93 | }; |
| @@ -355,10 +354,20 @@ | ||
| 355 | 354 | }/*end messageToDOM()*/; |
| 356 | 355 | |
| 357 | 356 | /** Callback for poll() to inject new content into the page. */ |
| 358 | 357 | function newcontent(jx){ |
| 359 | 358 | var i; |
| 359 | + if('visible'===document.visibilityState){ | |
| 360 | + if(Chat.changesSincePageHidden){ | |
| 361 | + Chat.changesSincePageHidden = 0; | |
| 362 | + Chat.pageTitle.innerText = Chat.pageTitleOrig; | |
| 363 | + } | |
| 364 | + }else{ | |
| 365 | + Chat.changesSincePageHidden += jx.msgs.length; | |
| 366 | + Chat.pageTitle.innerText = '('+Chat.changesSincePageHidden+') '+ | |
| 367 | + Chat.pageTitleOrig; | |
| 368 | + } | |
| 360 | 369 | for(i=0; i<jx.msgs.length; ++i){ |
| 361 | 370 | const m = jx.msgs[i]; |
| 362 | 371 | if( m.msgid>Chat.mxMsg ) Chat.mxMsg = m.msgid; |
| 363 | 372 | if( m.mdel ){ |
| 364 | 373 | /* A record deletion notice. */ |
| 365 | 374 |
| --- src/chat.js | |
| +++ src/chat.js | |
| @@ -1,22 +1,22 @@ | |
| 1 | (function(){ |
| 2 | const form = document.querySelector('#chat-form'); |
| 3 | const F = window.fossil, D = F.dom; |
| 4 | const Chat = (function(){ |
| 5 | const cs = { |
| 6 | me: F.user.name, |
| 7 | mxMsg: F.config.chatInitSize ? -F.config.chatInitSize : -50, |
| 8 | pageIsActive: !document.hidden, |
| 9 | onPageActive: function(){console.debug("Page active.")}, //override below |
| 10 | onPageInactive: function(){console.debug("Page inactive.")} //override below |
| 11 | }; |
| 12 | document.addEventListener('visibilitychange', function(ev){ |
| 13 | cs.pageIsActive = !document.hidden; |
| 14 | if(cs.pageIsActive) cs.onPageActive(); |
| 15 | else cs.onPageInactive(); |
| 16 | }, true); |
| 17 | |
| 18 | const qs = (e)=>document.querySelector(e); |
| 19 | const argsToArray = function(args){ |
| 20 | return Array.prototype.slice.call(args,0); |
| 21 | }; |
| 22 | cs.reportError = function(/*msg args*/){ |
| @@ -82,13 +82,12 @@ | |
| 82 | .catch(err=>this.reportError(err)) |
| 83 | }else{ |
| 84 | this.deleteMessageElem(id); |
| 85 | } |
| 86 | }; |
| 87 | |
| 88 | return cs; |
| 89 | })(); |
| 90 | /* State for paste and drag/drop */ |
| 91 | const BlobXferState = { |
| 92 | dropDetails: document.querySelector('#chat-drop-details'), |
| 93 | blob: undefined |
| 94 | }; |
| @@ -355,10 +354,20 @@ | |
| 355 | }/*end messageToDOM()*/; |
| 356 | |
| 357 | /** Callback for poll() to inject new content into the page. */ |
| 358 | function newcontent(jx){ |
| 359 | var i; |
| 360 | for(i=0; i<jx.msgs.length; ++i){ |
| 361 | const m = jx.msgs[i]; |
| 362 | if( m.msgid>Chat.mxMsg ) Chat.mxMsg = m.msgid; |
| 363 | if( m.mdel ){ |
| 364 | /* A record deletion notice. */ |
| 365 |
| --- src/chat.js | |
| +++ src/chat.js | |
| @@ -1,22 +1,22 @@ | |
| 1 | /** |
| 2 | This file contains the client-side implementation of fossil's /chat |
| 3 | application. |
| 4 | */ |
| 5 | (function(){ |
| 6 | const form = document.querySelector('#chat-form'); |
| 7 | const F = window.fossil, D = F.dom; |
| 8 | const Chat = (function(){ |
| 9 | const cs = { |
| 10 | me: F.user.name, |
| 11 | mxMsg: F.config.chatInitSize ? -F.config.chatInitSize : -50, |
| 12 | pageIsActive: 'visible'===document.visibilityState, |
| 13 | changesSincePageHidden: 0, |
| 14 | notificationBubbleColor: 'white', |
| 15 | pageTitle: document.querySelector('head title') |
| 16 | }; |
| 17 | cs.pageTitleOrig = cs.pageTitle.innerText; |
| 18 | const qs = (e)=>document.querySelector(e); |
| 19 | const argsToArray = function(args){ |
| 20 | return Array.prototype.slice.call(args,0); |
| 21 | }; |
| 22 | cs.reportError = function(/*msg args*/){ |
| @@ -82,13 +82,12 @@ | |
| 82 | .catch(err=>this.reportError(err)) |
| 83 | }else{ |
| 84 | this.deleteMessageElem(id); |
| 85 | } |
| 86 | }; |
| 87 | return cs; |
| 88 | })()/*Chat initialization*/; |
| 89 | /* State for paste and drag/drop */ |
| 90 | const BlobXferState = { |
| 91 | dropDetails: document.querySelector('#chat-drop-details'), |
| 92 | blob: undefined |
| 93 | }; |
| @@ -355,10 +354,20 @@ | |
| 354 | }/*end messageToDOM()*/; |
| 355 | |
| 356 | /** Callback for poll() to inject new content into the page. */ |
| 357 | function newcontent(jx){ |
| 358 | var i; |
| 359 | if('visible'===document.visibilityState){ |
| 360 | if(Chat.changesSincePageHidden){ |
| 361 | Chat.changesSincePageHidden = 0; |
| 362 | Chat.pageTitle.innerText = Chat.pageTitleOrig; |
| 363 | } |
| 364 | }else{ |
| 365 | Chat.changesSincePageHidden += jx.msgs.length; |
| 366 | Chat.pageTitle.innerText = '('+Chat.changesSincePageHidden+') '+ |
| 367 | Chat.pageTitleOrig; |
| 368 | } |
| 369 | for(i=0; i<jx.msgs.length; ++i){ |
| 370 | const m = jx.msgs[i]; |
| 371 | if( m.msgid>Chat.mxMsg ) Chat.mxMsg = m.msgid; |
| 372 | if( m.mdel ){ |
| 373 | /* A record deletion notice. */ |
| 374 |