diff --git a/src/browser/components/MainPage.jsx b/src/browser/components/MainPage.jsx index 3899dcb2..0d59490d 100644 --- a/src/browser/components/MainPage.jsx +++ b/src/browser/components/MainPage.jsx @@ -39,6 +39,7 @@ export default class MainPage extends React.Component { this.state = { key, + sessionsExpired: new Array(this.props.teams.length), unreadCounts: new Array(this.props.teams.length), mentionCounts: new Array(this.props.teams.length), unreadAtActive: new Array(this.props.teams.length), @@ -56,8 +57,6 @@ export default class MainPage extends React.Component { this.handleOnTeamFocused = this.handleOnTeamFocused.bind(this); this.handleSelect = this.handleSelect.bind(this); this.handleTargetURLChange = this.handleTargetURLChange.bind(this); - this.handleUnreadCountChange = this.handleUnreadCountChange.bind(this); - this.handleUnreadCountTotalChange = this.handleUnreadCountTotalChange.bind(this); this.inputBlur = this.inputBlur.bind(this); this.markReadAtActive = this.markReadAtActive.bind(this); } @@ -173,11 +172,13 @@ export default class MainPage extends React.Component { this.handleOnTeamFocused(newKey); } - handleUnreadCountChange(index, unreadCount, mentionCount, isUnread, isMentioned) { + handleBadgeChange = (index, sessionExpired, unreadCount, mentionCount, isUnread, isMentioned) => { + const sessionsExpired = this.state.sessionsExpired; const unreadCounts = this.state.unreadCounts; const mentionCounts = this.state.mentionCounts; const unreadAtActive = this.state.unreadAtActive; const mentionAtActiveCounts = this.state.mentionAtActiveCounts; + sessionsExpired[index] = sessionExpired; unreadCounts[index] = unreadCount; mentionCounts[index] = mentionCount; @@ -189,12 +190,13 @@ export default class MainPage extends React.Component { } } this.setState({ + sessionsExpired, unreadCounts, mentionCounts, unreadAtActive, mentionAtActiveCounts, }); - this.handleUnreadCountTotalChange(); + this.handleBadgesChange(); } markReadAtActive(index) { @@ -206,11 +208,13 @@ export default class MainPage extends React.Component { unreadAtActive, mentionAtActiveCounts, }); - this.handleUnreadCountTotalChange(); + this.handleBadgesChange(); } - handleUnreadCountTotalChange() { - if (this.props.onUnreadCountChange) { + handleBadgesChange = () => { + if (this.props.onBadgeChange) { + const someSessionsExpired = this.state.sessionsExpired.some((sessionExpired) => sessionExpired); + let allUnreadCount = this.state.unreadCounts.reduce((prev, curr) => { return prev + curr; }, 0); @@ -219,13 +223,15 @@ export default class MainPage extends React.Component { allUnreadCount += 1; } }); + let allMentionCount = this.state.mentionCounts.reduce((prev, curr) => { return prev + curr; }, 0); this.state.mentionAtActiveCounts.forEach((count) => { allMentionCount += count; }); - this.props.onUnreadCountChange(allUnreadCount, allMentionCount); + + this.props.onBadgeChange(someSessionsExpired, allUnreadCount, allMentionCount); } } @@ -299,6 +305,7 @@ export default class MainPage extends React.Component { { - function handleUnreadCountChange(unreadCount, mentionCount, isUnread, isMentioned) { - self.handleUnreadCountChange(index, unreadCount, mentionCount, isUnread, isMentioned); + function handleBadgeChange(sessionExpired, unreadCount, mentionCount, isUnread, isMentioned) { + self.handleBadgeChange(index, sessionExpired, unreadCount, mentionCount, isUnread, isMentioned); } function handleNotificationClick() { self.handleSelect(index); @@ -340,7 +347,7 @@ export default class MainPage extends React.Component { src={teamUrl} name={team.name} onTargetURLChange={self.handleTargetURLChange} - onUnreadCountChange={handleUnreadCountChange} + onBadgeChange={handleBadgeChange} onNotificationClick={handleNotificationClick} ref={id} active={isActive} @@ -437,7 +444,7 @@ export default class MainPage extends React.Component { } MainPage.propTypes = { - onUnreadCountChange: PropTypes.func.isRequired, + onBadgeChange: PropTypes.func.isRequired, teams: PropTypes.array.isRequired, onTeamConfigChange: PropTypes.func.isRequired, initialIndex: PropTypes.number.isRequired, diff --git a/src/browser/components/MattermostView.jsx b/src/browser/components/MattermostView.jsx index 424c4507..74b987cb 100644 --- a/src/browser/components/MattermostView.jsx +++ b/src/browser/components/MattermostView.jsx @@ -66,9 +66,9 @@ export default class MattermostView extends React.Component { this.webviewRef = React.createRef(); } - handleUnreadCountChange(unreadCount, mentionCount, isUnread, isMentioned) { - if (this.props.onUnreadCountChange) { - this.props.onUnreadCountChange(unreadCount, mentionCount, isUnread, isMentioned); + handleUnreadCountChange(sessionExpired, unreadCount, mentionCount, isUnread, isMentioned) { + if (this.props.onBadgeChange) { + this.props.onBadgeChange(sessionExpired, unreadCount, mentionCount, isUnread, isMentioned); } } @@ -158,14 +158,13 @@ export default class MattermostView extends React.Component { isLoaded: true, }); break; - case 'onUnreadCountChange': { - const unreadCount = event.args[0]; - const mentionCount = event.args[1]; - - // isUnread and isMentioned is pulse flag. - const isUnread = event.args[2]; - const isMentioned = event.args[3]; - self.handleUnreadCountChange(unreadCount, mentionCount, isUnread, isMentioned); + case 'onBadgeChange': { + const sessionExpired = event.args[0]; + const unreadCount = event.args[1]; + const mentionCount = event.args[2]; + const isUnread = event.args[3]; + const isMentioned = event.args[4]; + self.handleUnreadCountChange(sessionExpired, unreadCount, mentionCount, isUnread, isMentioned); break; } @@ -326,7 +325,7 @@ MattermostView.propTypes = { name: PropTypes.string, id: PropTypes.string, onTargetURLChange: PropTypes.func, - onUnreadCountChange: PropTypes.func, + onBadgeChange: PropTypes.func, src: PropTypes.string, active: PropTypes.bool, withTab: PropTypes.bool, diff --git a/src/browser/components/TabBar.jsx b/src/browser/components/TabBar.jsx index 1df39088..06bcd50d 100644 --- a/src/browser/components/TabBar.jsx +++ b/src/browser/components/TabBar.jsx @@ -10,6 +10,8 @@ import PermissionRequestDialog from './PermissionRequestDialog.jsx'; export default class TabBar extends React.Component { // need "this" render() { const tabs = this.props.teams.map((team, index) => { + const sessionExpired = this.props.sessionsExpired[index]; + let unreadCount = 0; if (this.props.unreadCounts[index] > 0) { unreadCount = this.props.unreadCounts[index]; @@ -27,11 +29,16 @@ export default class TabBar extends React.Component { // need "this" } let badgeDiv; - if (mentionCount !== 0) { + if (sessionExpired) { + badgeDiv = ( +
{'•'}
+ ); + } else if (mentionCount !== 0) { badgeDiv = (
{mentionCount} -
); + + ); } const id = 'teamTabItem' + index; const requestingPermission = this.props.requestingPermission[index]; @@ -114,6 +121,7 @@ TabBar.propTypes = { id: PropTypes.string, onSelect: PropTypes.func, teams: PropTypes.array, + sessionsExpired: PropTypes.array, unreadCounts: PropTypes.array, unreadAtActive: PropTypes.array, mentionCounts: PropTypes.array, diff --git a/src/browser/css/components/TabBar.css b/src/browser/css/components/TabBar.css index 327a6a6d..d2905892 100644 --- a/src/browser/css/components/TabBar.css +++ b/src/browser/css/components/TabBar.css @@ -53,6 +53,11 @@ border-radius: 50%; } +.TabBar .TabBar-badge.TabBar-badge-nomention { + font-size: 22pt; + line-height: 18px; +} + .TabBar .teamTabItem-unread { font-weight: bold; } diff --git a/src/browser/index.jsx b/src/browser/index.jsx index 784c3ece..47c905ce 100644 --- a/src/browser/index.jsx +++ b/src/browser/index.jsx @@ -31,19 +31,23 @@ if (teams.length === 0) { window.location = 'settings.html'; } -function showUnreadBadgeWindows(unreadCount, mentionCount) { +function showBadgeWindows(sessionExpired, unreadCount, mentionCount) { function sendBadge(dataURL, description) { // window.setOverlayIcon() does't work with NativeImage across remote boundaries. // https://github.com/atom/electron/issues/4011 ipcRenderer.send('update-unread', { overlayDataURL: dataURL, description, + sessionExpired, unreadCount, mentionCount, }); } - if (mentionCount > 0) { + if (sessionExpired) { + const dataURL = createBadgeDataURL('•'); + sendBadge(dataURL, 'Session Expired: Please sign in to continue receiving notifications.'); + } else if (mentionCount > 0) { const dataURL = createBadgeDataURL(mentionCount.toString()); sendBadge(dataURL, 'You have unread mentions (' + mentionCount + ')'); } else if (unreadCount > 0 && AppConfig.data.showUnreadBadge) { @@ -54,8 +58,10 @@ function showUnreadBadgeWindows(unreadCount, mentionCount) { } } -function showUnreadBadgeOSX(unreadCount, mentionCount) { - if (mentionCount > 0) { +function showBadgeOSX(sessionExpired, unreadCount, mentionCount) { + if (sessionExpired) { + remote.app.dock.setBadge('•'); + } else if (mentionCount > 0) { remote.app.dock.setBadge(mentionCount.toString()); } else if (unreadCount > 0 && AppConfig.data.showUnreadBadge) { remote.app.dock.setBadge('•'); @@ -64,34 +70,39 @@ function showUnreadBadgeOSX(unreadCount, mentionCount) { } ipcRenderer.send('update-unread', { + sessionExpired, unreadCount, mentionCount, }); } -function showUnreadBadgeLinux(unreadCount, mentionCount) { +function showBadgeLinux(sessionExpired, unreadCount, mentionCount) { if (remote.app.isUnityRunning()) { - remote.app.setBadgeCount(mentionCount); + if (sessionExpired) { + remote.app.setBadgeCount(1); + } else { + remote.app.setBadgeCount(mentionCount); + } } ipcRenderer.send('update-unread', { + sessionExpired, unreadCount, mentionCount, }); } -function showUnreadBadge(unreadCount, mentionCount) { +function showBadge(sessionExpired, unreadCount, mentionCount) { switch (process.platform) { case 'win32': - showUnreadBadgeWindows(unreadCount, mentionCount); + showBadgeWindows(sessionExpired, unreadCount, mentionCount); break; case 'darwin': - showUnreadBadgeOSX(unreadCount, mentionCount); + showBadgeOSX(sessionExpired, unreadCount, mentionCount); break; case 'linux': - showUnreadBadgeLinux(unreadCount, mentionCount); + showBadgeLinux(sessionExpired, unreadCount, mentionCount); break; - default: } } @@ -168,7 +179,7 @@ ReactDOM.render( Log out => Count should be 0. + // LHS not found => Log out => Count should be 0, but session may be expired. if (document.getElementById('sidebar-left') === null) { - ipcRenderer.sendToHost('onUnreadCountChange', 0, 0, false, false); + const extraParam = (new URLSearchParams(window.location.search)).get('extra'); + const sessionExpired = extraParam === 'expired'; + + ipcRenderer.sendToHost('onBadgeChange', sessionExpired, 0, 0, false, false); + this.sessionExpired = sessionExpired; this.unreadCount = 0; this.mentionCount = 0; setTimeout(getUnreadCount, UNREAD_COUNT_INTERVAL); @@ -152,11 +156,12 @@ function getUnreadCount() { } } - if (this.unreadCount !== unreadCount || this.mentionCount !== mentionCount || isUnread || isMentioned) { - ipcRenderer.sendToHost('onUnreadCountChange', unreadCount, mentionCount, isUnread, isMentioned); + if (this.sessionExpired || this.unreadCount !== unreadCount || this.mentionCount !== mentionCount || isUnread || isMentioned) { + ipcRenderer.sendToHost('onBadgeChange', false, unreadCount, mentionCount, isUnread, isMentioned); } this.unreadCount = unreadCount; this.mentionCount = mentionCount; + this.sessionExpired = false; setTimeout(getUnreadCount, UNREAD_COUNT_INTERVAL); } setTimeout(getUnreadCount, UNREAD_COUNT_INTERVAL); diff --git a/src/main.js b/src/main.js index eca0ec98..93345a3d 100644 --- a/src/main.js +++ b/src/main.js @@ -528,7 +528,14 @@ app.on('ready', () => { } if (trayIcon && !trayIcon.isDestroyed()) { - if (arg.mentionCount > 0) { + if (arg.sessionExpired) { + // reuse the mention icon when the session is expired + trayIcon.setImage(trayImages.mention); + if (process.platform === 'darwin') { + trayIcon.setPressedImage(trayImages.clicked.mention); + } + trayIcon.setToolTip('Session Expired: Please sign in to continue receiving notifications.'); + } else if (arg.mentionCount > 0) { trayIcon.setImage(trayImages.mention); if (process.platform === 'darwin') { trayIcon.setPressedImage(trayImages.clicked.mention);