Clean up appState module, move to common, simplify events (#2676)

* Refactor appState into class, simplify events

* Move appState to common module, make case for object consistent

* Naming change

* Update name
This commit is contained in:
Devin Binnie
2023-04-14 12:09:33 -04:00
committed by GitHub
parent c0dddd88ee
commit 1428ba694b
13 changed files with 132 additions and 156 deletions

82
src/common/appState.ts Normal file
View File

@@ -0,0 +1,82 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {EventEmitter} from 'events';
import {UPDATE_APPSTATE, UPDATE_APPSTATE_TOTALS, UPDATE_APPSTATE_FOR_VIEW_ID} from 'common/communication';
import ServerManager from 'common/servers/serverManager';
import {Logger} from 'common/log';
const log = new Logger('AppState');
export class AppState extends EventEmitter {
private expired: Map<string, boolean>;
private mentions: Map<string, number>;
private unreads: Map<string, boolean>;
constructor() {
super();
this.expired = new Map();
this.mentions = new Map();
this.unreads = new Map();
}
updateExpired = (viewId: string, expired: boolean) => {
ServerManager.getViewLog(viewId, 'AppState').silly('updateExpired', expired);
this.unreads.set(viewId, expired);
this.emitStatusForView(viewId);
}
updateMentions = (viewId: string, mentions: number) => {
ServerManager.getViewLog(viewId, 'AppState').silly('updateMentions', mentions);
this.mentions.set(viewId, mentions);
this.emitStatusForView(viewId);
};
updateUnreads = (viewId: string, unreads: boolean) => {
ServerManager.getViewLog(viewId, 'AppState').silly('updateUnreads', unreads);
this.unreads.set(viewId, unreads);
this.emitStatusForView(viewId);
};
clear = (viewId: string) => {
ServerManager.getViewLog(viewId, 'AppState').silly('clear');
this.expired.delete(viewId);
this.mentions.delete(viewId);
this.unreads.delete(viewId);
}
emitStatus = () => {
log.silly('emitStatus');
this.emit(UPDATE_APPSTATE,
this.expired,
this.mentions,
this.unreads,
);
this.emit(UPDATE_APPSTATE_TOTALS,
[...this.expired.values()].some((value) => value),
[...this.mentions.values()].reduce((total, value) => total + value, 0),
[...this.unreads.values()].some((value) => value),
);
};
private emitStatusForView = (viewId: string) => {
this.emit(UPDATE_APPSTATE_FOR_VIEW_ID,
viewId,
this.expired.get(viewId) || false,
this.mentions.get(viewId) || 0,
this.unreads.get(viewId) || false,
);
this.emitStatus();
};
}
const appState = new AppState();
export default appState;

View File

@@ -60,8 +60,6 @@ export const UPDATE_MENTIONS = 'update_mentions';
export const IS_UNREAD = 'is_unread'; export const IS_UNREAD = 'is_unread';
export const UNREAD_RESULT = 'unread_result'; export const UNREAD_RESULT = 'unread_result';
export const SESSION_EXPIRED = 'session_expired'; export const SESSION_EXPIRED = 'session_expired';
export const UPDATE_TRAY = 'update_tray';
export const UPDATE_BADGE = 'update_badge';
export const SET_VIEW_OPTIONS = 'set-view-name'; export const SET_VIEW_OPTIONS = 'set-view-name';
export const REACT_APP_INITIALIZED = 'react-app-initialized'; export const REACT_APP_INITIALIZED = 'react-app-initialized';
@@ -82,7 +80,6 @@ export const LOADSCREEN_END = 'loadscreen-end';
export const OPEN_TEAMS_DROPDOWN = 'open-teams-dropdown'; export const OPEN_TEAMS_DROPDOWN = 'open-teams-dropdown';
export const CLOSE_TEAMS_DROPDOWN = 'close-teams-dropdown'; export const CLOSE_TEAMS_DROPDOWN = 'close-teams-dropdown';
export const UPDATE_TEAMS_DROPDOWN = 'update-teams-dropdown'; export const UPDATE_TEAMS_DROPDOWN = 'update-teams-dropdown';
export const UPDATE_DROPDOWN_MENTIONS = 'update-dropdown-mentions';
export const REQUEST_TEAMS_DROPDOWN_INFO = 'request-teams-dropdown-info'; export const REQUEST_TEAMS_DROPDOWN_INFO = 'request-teams-dropdown-info';
export const RECEIVE_DROPDOWN_MENU_SIZE = 'receive-dropdown-menu-size'; export const RECEIVE_DROPDOWN_MENU_SIZE = 'receive-dropdown-menu-size';
@@ -167,3 +164,7 @@ export const UPDATE_TAB_ORDER = 'update-tab-order';
export const GET_LAST_ACTIVE = 'get-last-active'; export const GET_LAST_ACTIVE = 'get-last-active';
export const GET_ORDERED_SERVERS = 'get-ordered-servers'; export const GET_ORDERED_SERVERS = 'get-ordered-servers';
export const GET_ORDERED_TABS_FOR_SERVER = 'get-ordered-tabs-for-server'; export const GET_ORDERED_TABS_FOR_SERVER = 'get-ordered-tabs-for-server';
export const UPDATE_APPSTATE = 'update-appstate';
export const UPDATE_APPSTATE_TOTALS = 'update-appstate-totals';
export const UPDATE_APPSTATE_FOR_VIEW_ID = 'update-appstate-for-view-id';

View File

@@ -129,7 +129,7 @@ jest.mock('main/app/utils', () => ({
initCookieManager: jest.fn(), initCookieManager: jest.fn(),
updateServerInfos: jest.fn(), updateServerInfos: jest.fn(),
})); }));
jest.mock('main/appState', () => ({ jest.mock('common/appState', () => ({
on: jest.fn(), on: jest.fn(),
})); }));
jest.mock('main/AppVersionManager', () => ({})); jest.mock('main/AppVersionManager', () => ({}));

View File

@@ -1,126 +0,0 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import events from 'events';
import {ipcMain} from 'electron';
import {UPDATE_MENTIONS, UPDATE_TRAY, UPDATE_BADGE, SESSION_EXPIRED, UPDATE_DROPDOWN_MENTIONS} from 'common/communication';
import ServerManager from 'common/servers/serverManager';
import WindowManager from './windows/windowManager';
const status = {
unreads: new Map<string, boolean>(),
mentions: new Map<string, number>(),
expired: new Map<string, boolean>(),
emitter: new events.EventEmitter(),
};
const emitMentions = (viewId: string) => {
const newMentions = getMentions(viewId);
const newUnreads = getUnreads(viewId);
const isExpired = getIsExpired(viewId);
WindowManager.sendToRenderer(UPDATE_MENTIONS, viewId, newMentions, newUnreads, isExpired);
ServerManager.getViewLog(viewId, 'AppState').silly('emitMentions', {isExpired, newMentions, newUnreads});
emitStatus();
};
const emitTray = (expired?: boolean, mentions?: number, unreads?: boolean) => {
status.emitter.emit(UPDATE_TRAY, expired, Boolean(mentions), unreads);
};
const emitBadge = (expired?: boolean, mentions?: number, unreads?: boolean) => {
status.emitter.emit(UPDATE_BADGE, expired, mentions, unreads);
};
const emitDropdown = (expired?: Map<string, boolean>, mentions?: Map<string, number>, unreads?: Map<string, boolean>) => {
status.emitter.emit(UPDATE_DROPDOWN_MENTIONS, expired, mentions, unreads);
};
const emitStatus = () => {
const expired = anyExpired();
const mentions = totalMentions();
const unreads = anyUnreads();
emitTray(expired, mentions, unreads);
emitBadge(expired, mentions, unreads);
emitDropdown(status.expired, status.mentions, status.unreads);
};
export const updateMentions = (viewId: string, mentions: number, unreads?: boolean) => {
if (typeof unreads !== 'undefined') {
status.unreads.set(viewId, Boolean(unreads));
}
status.mentions.set(viewId, mentions || 0);
emitMentions(viewId);
};
export const updateUnreads = (viewId: string, unreads: boolean) => {
status.unreads.set(viewId, Boolean(unreads));
emitMentions(viewId);
};
export const updateBadge = () => {
const expired = anyExpired();
const mentions = totalMentions();
const unreads = anyUnreads();
emitBadge(expired, mentions, unreads);
};
const getUnreads = (viewId: string) => {
return status.unreads.get(viewId) || false;
};
const getMentions = (viewId: string) => {
return status.mentions.get(viewId) || 0; // this might be undefined as a way to tell that we don't know as it might need to login still.
};
const getIsExpired = (viewId: string) => {
return status.expired.get(viewId) || false;
};
const totalMentions = () => {
let total = 0;
for (const v of status.mentions.values()) {
total += v;
}
return total;
};
const anyUnreads = () => {
for (const v of status.unreads.values()) {
if (v) {
return v;
}
}
return false;
};
const anyExpired = () => {
for (const v of status.expired.values()) {
if (v) {
return v;
}
}
return false;
};
// add any other event emitter methods if needed
export const on = status.emitter.on.bind(status.emitter);
const setSessionExpired = (viewId: string, expired: boolean) => {
const isExpired = Boolean(expired);
const old = status.expired.get(viewId);
status.expired.set(viewId, isExpired);
if (typeof old !== 'undefined' && old !== isExpired) {
emitTray();
}
emitMentions(viewId);
};
ipcMain.on(SESSION_EXPIRED, (event, isExpired, viewId) => {
if (isExpired) {
ServerManager.getViewLog(viewId, 'AppState').debug('SESSION_EXPIRED', isExpired);
}
setSessionExpired(viewId, isExpired);
});

View File

@@ -19,8 +19,8 @@ jest.mock('electron', () => ({
}, },
})); }));
jest.mock('./appState', () => ({ jest.mock('common/appState', () => ({
updateBadge: jest.fn(), emitStatus: jest.fn(),
})); }));
jest.mock('./windows/mainWindow', () => ({ jest.mock('./windows/mainWindow', () => ({
get: jest.fn(), get: jest.fn(),

View File

@@ -4,12 +4,12 @@
import {BrowserWindow, app, nativeImage} from 'electron'; import {BrowserWindow, app, nativeImage} from 'electron';
import {UPDATE_BADGE} from 'common/communication'; import AppState from 'common/appState';
import {UPDATE_APPSTATE_TOTALS} from 'common/communication';
import {Logger} from 'common/log'; import {Logger} from 'common/log';
import {localizeMessage} from 'main/i18nManager'; import {localizeMessage} from 'main/i18nManager';
import * as AppState from './appState';
import MainWindow from './windows/mainWindow'; import MainWindow from './windows/mainWindow';
const log = new Logger('Badge'); const log = new Logger('Badge');
@@ -128,9 +128,9 @@ function showBadge(sessionExpired: boolean, mentionCount: number, showUnreadBadg
export function setUnreadBadgeSetting(showUnreadBadge: boolean) { export function setUnreadBadgeSetting(showUnreadBadge: boolean) {
showUnreadBadgeSetting = showUnreadBadge; showUnreadBadgeSetting = showUnreadBadge;
AppState.updateBadge(); AppState.emitStatus();
} }
export function setupBadge() { export function setupBadge() {
AppState.on(UPDATE_BADGE, showBadge); AppState.on(UPDATE_APPSTATE_TOTALS, showBadge);
} }

View File

@@ -5,14 +5,13 @@ import path from 'path';
import {app, nativeImage, Tray, systemPreferences, nativeTheme} from 'electron'; import {app, nativeImage, Tray, systemPreferences, nativeTheme} from 'electron';
import {UPDATE_TRAY} from 'common/communication'; import AppState from 'common/appState';
import {UPDATE_APPSTATE_TOTALS} from 'common/communication';
import {localizeMessage} from 'main/i18nManager'; import {localizeMessage} from 'main/i18nManager';
import MainWindow from 'main/windows/mainWindow'; import MainWindow from 'main/windows/mainWindow';
import WindowManager from 'main/windows/windowManager'; import WindowManager from 'main/windows/windowManager';
import * as AppState from '../appState';
const assetsDir = path.resolve(app.getAppPath(), 'assets'); const assetsDir = path.resolve(app.getAppPath(), 'assets');
let trayImages: Record<string, Electron.NativeImage>; let trayImages: Record<string, Electron.NativeImage>;
@@ -102,8 +101,8 @@ export function setupTray(iconTheme: string) {
WindowManager.restoreMain(); WindowManager.restoreMain();
}); });
AppState.on(UPDATE_TRAY, (anyExpired, anyMentions, anyUnreads) => { AppState.on(UPDATE_APPSTATE_TOTALS, (anyExpired: boolean, anyMentions: number, anyUnreads: boolean) => {
if (anyMentions) { if (anyMentions > 0) {
setTray('mention', localizeMessage('main.tray.tray.mention', 'You have been mentioned')); setTray('mention', localizeMessage('main.tray.tray.mention', 'You have been mentioned'));
} else if (anyUnreads) { } else if (anyUnreads) {
setTray('unread', localizeMessage('main.tray.tray.unread', 'You have unread channels')); setTray('unread', localizeMessage('main.tray.tray.unread', 'You have unread channels'));

View File

@@ -3,6 +3,7 @@
'use strict'; 'use strict';
import AppState from 'common/appState';
import {LOAD_FAILED, TOGGLE_BACK_BUTTON, UPDATE_TARGET_URL} from 'common/communication'; import {LOAD_FAILED, TOGGLE_BACK_BUTTON, UPDATE_TARGET_URL} from 'common/communication';
import {MattermostServer} from 'common/servers/MattermostServer'; import {MattermostServer} from 'common/servers/MattermostServer';
import MessagingTabView from 'common/tabs/MessagingTabView'; import MessagingTabView from 'common/tabs/MessagingTabView';
@@ -10,7 +11,6 @@ import MessagingTabView from 'common/tabs/MessagingTabView';
import MainWindow from '../windows/mainWindow'; import MainWindow from '../windows/mainWindow';
import * as WindowManager from '../windows/windowManager'; import * as WindowManager from '../windows/windowManager';
import ContextMenu from '../contextMenu'; import ContextMenu from '../contextMenu';
import * as appState from '../appState';
import Utils from '../utils'; import Utils from '../utils';
import {MattermostView} from './MattermostView'; import {MattermostView} from './MattermostView';
@@ -45,7 +45,8 @@ jest.mock('../windows/mainWindow', () => ({
jest.mock('../windows/windowManager', () => ({ jest.mock('../windows/windowManager', () => ({
sendToRenderer: jest.fn(), sendToRenderer: jest.fn(),
})); }));
jest.mock('../appState', () => ({ jest.mock('common/appState', () => ({
clear: jest.fn(),
updateMentions: jest.fn(), updateMentions: jest.fn(),
})); }));
jest.mock('./webContentEvents', () => ({ jest.mock('./webContentEvents', () => ({
@@ -374,7 +375,7 @@ describe('main/views/MattermostView', () => {
const mattermostView = new MattermostView(tabView, {}, {}); const mattermostView = new MattermostView(tabView, {}, {});
mattermostView.view.webContents.destroy = jest.fn(); mattermostView.view.webContents.destroy = jest.fn();
mattermostView.destroy(); mattermostView.destroy();
expect(appState.updateMentions).toBeCalledWith(mattermostView.tab.id, 0, false); expect(AppState.clear).toBeCalledWith(mattermostView.tab.id);
}); });
it('should clear outstanding timeouts', () => { it('should clear outstanding timeouts', () => {
@@ -472,12 +473,12 @@ describe('main/views/MattermostView', () => {
it('should parse mentions from title', () => { it('should parse mentions from title', () => {
mattermostView.updateMentionsFromTitle('(7) Mattermost'); mattermostView.updateMentionsFromTitle('(7) Mattermost');
expect(appState.updateMentions).toHaveBeenCalledWith(mattermostView.tab.id, 7); expect(AppState.updateMentions).toHaveBeenCalledWith(mattermostView.tab.id, 7);
}); });
it('should parse unreads from title', () => { it('should parse unreads from title', () => {
mattermostView.updateMentionsFromTitle('* Mattermost'); mattermostView.updateMentionsFromTitle('* Mattermost');
expect(appState.updateMentions).toHaveBeenCalledWith(mattermostView.tab.id, 0); expect(AppState.updateMentions).toHaveBeenCalledWith(mattermostView.tab.id, 0);
}); });
}); });
}); });

View File

@@ -8,6 +8,7 @@ import {EventEmitter} from 'events';
import {RELOAD_INTERVAL, MAX_SERVER_RETRIES, SECOND, MAX_LOADING_SCREEN_SECONDS} from 'common/utils/constants'; import {RELOAD_INTERVAL, MAX_SERVER_RETRIES, SECOND, MAX_LOADING_SCREEN_SECONDS} from 'common/utils/constants';
import urlUtils from 'common/utils/url'; import urlUtils from 'common/utils/url';
import AppState from 'common/appState';
import { import {
LOAD_RETRY, LOAD_RETRY,
LOAD_SUCCESS, LOAD_SUCCESS,
@@ -29,7 +30,6 @@ import WindowManager from 'main/windows/windowManager';
import ContextMenu from '../contextMenu'; import ContextMenu from '../contextMenu';
import {getWindowBoundaries, getLocalPreload, composeUserAgent, shouldHaveBackBar} from '../utils'; import {getWindowBoundaries, getLocalPreload, composeUserAgent, shouldHaveBackBar} from '../utils';
import * as appState from '../appState';
import WebContentsEventManager from './webContentEvents'; import WebContentsEventManager from './webContentEvents';
@@ -237,7 +237,7 @@ export class MattermostView extends EventEmitter {
destroy = () => { destroy = () => {
WebContentsEventManager.removeWebContentsListeners(this.webContentsId); WebContentsEventManager.removeWebContentsListeners(this.webContentsId);
appState.updateMentions(this.id, 0, false); AppState.clear(this.id);
MainWindow.get()?.removeBrowserView(this.view); MainWindow.get()?.removeBrowserView(this.view);
// workaround to eliminate zombie processes // workaround to eliminate zombie processes
@@ -353,7 +353,7 @@ export class MattermostView extends EventEmitter {
const results = resultsIterator.next(); // we are only interested in the first set const results = resultsIterator.next(); // we are only interested in the first set
const mentions = (results && results.value && parseInt(results.value[MENTIONS_GROUP], 10)) || 0; const mentions = (results && results.value && parseInt(results.value[MENTIONS_GROUP], 10)) || 0;
appState.updateMentions(this.id, mentions); AppState.updateMentions(this.id, mentions);
} }
// if favicon is null, it will affect appState, but won't be memoized // if favicon is null, it will affect appState, but won't be memoized

View File

@@ -5,12 +5,13 @@ import {BrowserView, ipcMain, IpcMainEvent} from 'electron';
import {CombinedConfig, MattermostTeam} from 'types/config'; import {CombinedConfig, MattermostTeam} from 'types/config';
import AppState from 'common/appState';
import { import {
CLOSE_TEAMS_DROPDOWN, CLOSE_TEAMS_DROPDOWN,
EMIT_CONFIGURATION, EMIT_CONFIGURATION,
OPEN_TEAMS_DROPDOWN, OPEN_TEAMS_DROPDOWN,
UPDATE_TEAMS_DROPDOWN, UPDATE_TEAMS_DROPDOWN,
UPDATE_DROPDOWN_MENTIONS, UPDATE_APPSTATE,
REQUEST_TEAMS_DROPDOWN_INFO, REQUEST_TEAMS_DROPDOWN_INFO,
RECEIVE_DROPDOWN_MENU_SIZE, RECEIVE_DROPDOWN_MENU_SIZE,
SET_ACTIVE_VIEW, SET_ACTIVE_VIEW,
@@ -23,7 +24,6 @@ import ServerManager from 'common/servers/serverManager';
import {getLocalPreload, getLocalURLString} from 'main/utils'; import {getLocalPreload, getLocalURLString} from 'main/utils';
import * as AppState from '../appState';
import WindowManager from '../windows/windowManager'; import WindowManager from '../windows/windowManager';
import MainWindow from '../windows/mainWindow'; import MainWindow from '../windows/mainWindow';
@@ -71,7 +71,7 @@ export default class TeamDropdownView {
ipcMain.on(REQUEST_TEAMS_DROPDOWN_INFO, this.updateDropdown); ipcMain.on(REQUEST_TEAMS_DROPDOWN_INFO, this.updateDropdown);
ipcMain.on(RECEIVE_DROPDOWN_MENU_SIZE, this.handleReceivedMenuSize); ipcMain.on(RECEIVE_DROPDOWN_MENU_SIZE, this.handleReceivedMenuSize);
ipcMain.on(SET_ACTIVE_VIEW, this.updateActiveTeam); ipcMain.on(SET_ACTIVE_VIEW, this.updateActiveTeam);
AppState.on(UPDATE_DROPDOWN_MENTIONS, this.updateMentions); AppState.on(UPDATE_APPSTATE, this.updateMentions);
ServerManager.on(SERVERS_UPDATE, this.updateServers); ServerManager.on(SERVERS_UPDATE, this.updateServers);
} }

View File

@@ -107,7 +107,7 @@ jest.mock('./modalManager', () => ({
isModalDisplayed: jest.fn(), isModalDisplayed: jest.fn(),
})); }));
jest.mock('./webContentEvents', () => ({})); jest.mock('./webContentEvents', () => ({}));
jest.mock('../appState', () => ({})); jest.mock('common/appState', () => ({}));
describe('main/views/viewManager', () => { describe('main/views/viewManager', () => {
describe('loadView', () => { describe('loadView', () => {

View File

@@ -3,6 +3,7 @@
import {BrowserView, dialog, ipcMain, IpcMainEvent, IpcMainInvokeEvent} from 'electron'; import {BrowserView, dialog, ipcMain, IpcMainEvent, IpcMainInvokeEvent} from 'electron';
import AppState from 'common/appState';
import {SECOND, TAB_BAR_HEIGHT} from 'common/utils/constants'; import {SECOND, TAB_BAR_HEIGHT} from 'common/utils/constants';
import { import {
UPDATE_TARGET_URL, UPDATE_TARGET_URL,
@@ -23,6 +24,7 @@ import {
UNREAD_RESULT, UNREAD_RESULT,
HISTORY, HISTORY,
GET_VIEW_INFO_FOR_TEST, GET_VIEW_INFO_FOR_TEST,
SESSION_EXPIRED,
} from 'common/communication'; } from 'common/communication';
import Config from 'common/config'; import Config from 'common/config';
import {Logger} from 'common/log'; import {Logger} from 'common/log';
@@ -35,7 +37,6 @@ import {TabView, TAB_MESSAGING} from 'common/tabs/TabView';
import {localizeMessage} from 'main/i18nManager'; import {localizeMessage} from 'main/i18nManager';
import MainWindow from 'main/windows/mainWindow'; import MainWindow from 'main/windows/mainWindow';
import * as appState from '../appState';
import {getLocalURLString, getLocalPreload} from '../utils'; import {getLocalURLString, getLocalPreload} from '../utils';
import {MattermostView} from './MattermostView'; import {MattermostView} from './MattermostView';
@@ -66,6 +67,7 @@ export class ViewManager {
ipcMain.on(APP_LOGGED_OUT, this.handleAppLoggedOut); ipcMain.on(APP_LOGGED_OUT, this.handleAppLoggedOut);
ipcMain.on(RELOAD_CURRENT_VIEW, this.handleReloadCurrentView); ipcMain.on(RELOAD_CURRENT_VIEW, this.handleReloadCurrentView);
ipcMain.on(UNREAD_RESULT, this.handleFaviconIsUnread); ipcMain.on(UNREAD_RESULT, this.handleFaviconIsUnread);
ipcMain.on(SESSION_EXPIRED, this.handleSessionExpired);
ServerManager.on(SERVERS_UPDATE, this.handleReloadConfiguration); ServerManager.on(SERVERS_UPDATE, this.handleReloadConfiguration);
} }
@@ -521,7 +523,13 @@ export class ViewManager {
private handleFaviconIsUnread = (e: Event, favicon: string, viewId: string, result: boolean) => { private handleFaviconIsUnread = (e: Event, favicon: string, viewId: string, result: boolean) => {
log.silly('handleFaviconIsUnread', {favicon, viewId, result}); log.silly('handleFaviconIsUnread', {favicon, viewId, result});
appState.updateUnreads(viewId, result); AppState.updateUnreads(viewId, result);
}
private handleSessionExpired = (event: IpcMainEvent, isExpired: boolean, viewId: string) => {
ServerManager.getViewLog(viewId, 'ViewManager').debug('handleSessionExpired', isExpired);
AppState.updateExpired(viewId, isExpired);
} }
/** /**

View File

@@ -11,7 +11,8 @@ import {app, BrowserWindow, BrowserWindowConstructorOptions, dialog, Event, glob
import {SavedWindowState} from 'types/mainWindow'; import {SavedWindowState} from 'types/mainWindow';
import {SELECT_NEXT_TAB, SELECT_PREVIOUS_TAB, GET_FULL_SCREEN_STATUS, FOCUS_THREE_DOT_MENU, SERVERS_UPDATE} from 'common/communication'; import AppState from 'common/appState';
import {SELECT_NEXT_TAB, SELECT_PREVIOUS_TAB, GET_FULL_SCREEN_STATUS, FOCUS_THREE_DOT_MENU, SERVERS_UPDATE, UPDATE_APPSTATE_FOR_VIEW_ID, UPDATE_MENTIONS} from 'common/communication';
import Config from 'common/config'; import Config from 'common/config';
import {Logger} from 'common/log'; import {Logger} from 'common/log';
import ServerManager from 'common/servers/serverManager'; import ServerManager from 'common/servers/serverManager';
@@ -42,6 +43,8 @@ export class MainWindow {
ipcMain.handle(GET_FULL_SCREEN_STATUS, () => this.win?.isFullScreen()); ipcMain.handle(GET_FULL_SCREEN_STATUS, () => this.win?.isFullScreen());
ServerManager.on(SERVERS_UPDATE, this.handleUpdateConfig); ServerManager.on(SERVERS_UPDATE, this.handleUpdateConfig);
AppState.on(UPDATE_APPSTATE_FOR_VIEW_ID, this.handleUpdateAppStateForViewId);
} }
init = () => { init = () => {
@@ -331,6 +334,14 @@ export class MainWindow {
private handleUpdateConfig = () => { private handleUpdateConfig = () => {
this.win?.webContents.send(SERVERS_UPDATE); this.win?.webContents.send(SERVERS_UPDATE);
} }
/**
* App State update handler
*/
private handleUpdateAppStateForViewId = (viewId: string, isExpired: boolean, newMentions: number, newUnreads: boolean) => {
this.win?.webContents.send(UPDATE_MENTIONS, viewId, newMentions, newUnreads, isExpired);
}
} }
const mainWindow = new MainWindow(); const mainWindow = new MainWindow();