[MM-47706] Remove exposure of the ipcRenderer methods in the desktop app and only expose specific endpoints (#2387)
This commit is contained in:
@@ -9,13 +9,63 @@ import {ipcRenderer, contextBridge} from 'electron';
|
||||
import {
|
||||
GET_LANGUAGE_INFORMATION,
|
||||
RETRIEVED_LANGUAGE_INFORMATION,
|
||||
QUIT,
|
||||
GET_VIEW_NAME,
|
||||
GET_VIEW_WEBCONTENTS_ID,
|
||||
OPEN_APP_MENU,
|
||||
CLOSE_TEAMS_DROPDOWN,
|
||||
OPEN_TEAMS_DROPDOWN,
|
||||
SWITCH_TAB,
|
||||
CLOSE_TAB,
|
||||
WINDOW_CLOSE,
|
||||
WINDOW_MINIMIZE,
|
||||
WINDOW_MAXIMIZE,
|
||||
WINDOW_RESTORE,
|
||||
DOUBLE_CLICK_ON_WINDOW,
|
||||
FOCUS_BROWSERVIEW,
|
||||
RELOAD_CURRENT_VIEW,
|
||||
CLOSE_DOWNLOADS_DROPDOWN,
|
||||
CLOSE_DOWNLOADS_DROPDOWN_MENU,
|
||||
OPEN_DOWNLOADS_DROPDOWN,
|
||||
HISTORY,
|
||||
CHECK_FOR_UPDATES,
|
||||
UPDATE_CONFIGURATION,
|
||||
UPDATE_TEAMS,
|
||||
GET_CONFIGURATION,
|
||||
GET_DARK_MODE,
|
||||
REQUEST_HAS_DOWNLOADS,
|
||||
GET_FULL_SCREEN_STATUS,
|
||||
GET_AVAILABLE_SPELL_CHECKER_LANGUAGES,
|
||||
GET_AVAILABLE_LANGUAGES,
|
||||
GET_LOCAL_CONFIGURATION,
|
||||
GET_DOWNLOAD_LOCATION,
|
||||
RELOAD_CONFIGURATION,
|
||||
DARK_MODE_CHANGE,
|
||||
LOAD_RETRY,
|
||||
LOAD_SUCCESS,
|
||||
LOAD_FAILED,
|
||||
SET_ACTIVE_VIEW,
|
||||
MAXIMIZE_CHANGE,
|
||||
PLAY_SOUND,
|
||||
MODAL_OPEN,
|
||||
MODAL_CLOSE,
|
||||
TOGGLE_BACK_BUTTON,
|
||||
UPDATE_MENTIONS,
|
||||
SHOW_DOWNLOADS_DROPDOWN_BUTTON_BADGE,
|
||||
HIDE_DOWNLOADS_DROPDOWN_BUTTON_BADGE,
|
||||
UPDATE_DOWNLOADS_DROPDOWN,
|
||||
APP_MENU_WILL_CLOSE,
|
||||
FOCUS_THREE_DOT_MENU,
|
||||
} from 'common/communication';
|
||||
|
||||
contextBridge.exposeInMainWorld('ipcRenderer', {
|
||||
send: ipcRenderer.send,
|
||||
on: (channel, listener) => ipcRenderer.on(channel, (_, ...args) => listener(null, ...args)),
|
||||
invoke: ipcRenderer.invoke,
|
||||
});
|
||||
console.log('Preload initialized');
|
||||
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
contextBridge.exposeInMainWorld('testHelper', {
|
||||
getViewName: () => ipcRenderer.invoke(GET_VIEW_NAME),
|
||||
getWebContentsId: () => ipcRenderer.invoke(GET_VIEW_WEBCONTENTS_ID),
|
||||
});
|
||||
}
|
||||
|
||||
contextBridge.exposeInMainWorld('process', {
|
||||
platform: process.platform,
|
||||
@@ -29,6 +79,64 @@ contextBridge.exposeInMainWorld('timers', {
|
||||
setImmediate,
|
||||
});
|
||||
|
||||
contextBridge.exposeInMainWorld('desktop', {
|
||||
quit: (reason, stack) => ipcRenderer.send(QUIT, reason, stack),
|
||||
openAppMenu: () => ipcRenderer.send(OPEN_APP_MENU),
|
||||
closeTeamsDropdown: () => ipcRenderer.send(CLOSE_TEAMS_DROPDOWN),
|
||||
openTeamsDropdown: () => ipcRenderer.send(OPEN_TEAMS_DROPDOWN),
|
||||
switchTab: (serverName, tabName) => ipcRenderer.send(SWITCH_TAB, serverName, tabName),
|
||||
closeTab: (serverName, tabName) => ipcRenderer.send(CLOSE_TAB, serverName, tabName),
|
||||
closeWindow: () => ipcRenderer.send(WINDOW_CLOSE),
|
||||
minimizeWindow: () => ipcRenderer.send(WINDOW_MINIMIZE),
|
||||
maximizeWindow: () => ipcRenderer.send(WINDOW_MAXIMIZE),
|
||||
restoreWindow: () => ipcRenderer.send(WINDOW_RESTORE),
|
||||
doubleClickOnWindow: (windowName) => ipcRenderer.send(DOUBLE_CLICK_ON_WINDOW, windowName),
|
||||
focusBrowserView: () => ipcRenderer.send(FOCUS_BROWSERVIEW),
|
||||
reloadCurrentView: () => ipcRenderer.send(RELOAD_CURRENT_VIEW),
|
||||
closeDownloadsDropdown: () => ipcRenderer.send(CLOSE_DOWNLOADS_DROPDOWN),
|
||||
closeDownloadsDropdownMenu: () => ipcRenderer.send(CLOSE_DOWNLOADS_DROPDOWN_MENU),
|
||||
openDownloadsDropdown: () => ipcRenderer.send(OPEN_DOWNLOADS_DROPDOWN),
|
||||
goBack: () => ipcRenderer.send(HISTORY, -1),
|
||||
checkForUpdates: () => ipcRenderer.send(CHECK_FOR_UPDATES),
|
||||
updateConfiguration: (saveQueueItems) => ipcRenderer.send(UPDATE_CONFIGURATION, saveQueueItems),
|
||||
|
||||
updateTeams: (updatedTeams) => ipcRenderer.invoke(UPDATE_TEAMS, updatedTeams),
|
||||
getConfiguration: (option) => ipcRenderer.invoke(GET_CONFIGURATION, option),
|
||||
getVersion: () => ipcRenderer.invoke('get-app-version'),
|
||||
getDarkMode: () => ipcRenderer.invoke(GET_DARK_MODE),
|
||||
requestHasDownloads: () => ipcRenderer.invoke(REQUEST_HAS_DOWNLOADS),
|
||||
getFullScreenStatus: () => ipcRenderer.invoke(GET_FULL_SCREEN_STATUS),
|
||||
getAvailableSpellCheckerLanguages: () => ipcRenderer.invoke(GET_AVAILABLE_SPELL_CHECKER_LANGUAGES),
|
||||
getAvailableLanguages: () => ipcRenderer.invoke(GET_AVAILABLE_LANGUAGES),
|
||||
getLocalConfiguration: (option) => ipcRenderer.invoke(GET_LOCAL_CONFIGURATION, option),
|
||||
getDownloadLocation: (downloadLocation) => ipcRenderer.invoke(GET_DOWNLOAD_LOCATION, downloadLocation),
|
||||
|
||||
onSynchronizeConfig: (listener) => ipcRenderer.on('synchronize-config', () => listener()),
|
||||
onReloadConfiguration: (listener) => ipcRenderer.on(RELOAD_CONFIGURATION, () => listener()),
|
||||
onDarkModeChange: (listener) => ipcRenderer.on(DARK_MODE_CHANGE, (_, darkMode) => listener(darkMode)),
|
||||
onLoadRetry: (listener) => ipcRenderer.on(LOAD_RETRY, (_, viewName, retry, err, loadUrl) => listener(viewName, retry, err, loadUrl)),
|
||||
onLoadSuccess: (listener) => ipcRenderer.on(LOAD_SUCCESS, (_, viewName) => listener(viewName)),
|
||||
onLoadFailed: (listener) => ipcRenderer.on(LOAD_FAILED, (_, viewName, err, loadUrl) => listener(viewName, err, loadUrl)),
|
||||
onSetActiveView: (listener) => ipcRenderer.on(SET_ACTIVE_VIEW, (_, serverName, tabName) => listener(serverName, tabName)),
|
||||
onMaximizeChange: (listener) => ipcRenderer.on(MAXIMIZE_CHANGE, (_, maximize) => listener(maximize)),
|
||||
onEnterFullScreen: (listener) => ipcRenderer.on('enter-full-screen', () => listener()),
|
||||
onLeaveFullScreen: (listener) => ipcRenderer.on('leave-full-screen', () => listener()),
|
||||
onPlaySound: (listener) => ipcRenderer.on(PLAY_SOUND, (_, soundName) => listener(soundName)),
|
||||
onModalOpen: (listener) => ipcRenderer.on(MODAL_OPEN, () => listener()),
|
||||
onModalClose: (listener) => ipcRenderer.on(MODAL_CLOSE, () => listener()),
|
||||
onToggleBackButton: (listener) => ipcRenderer.on(TOGGLE_BACK_BUTTON, (_, showExtraBar) => listener(showExtraBar)),
|
||||
onUpdateMentions: (listener) => ipcRenderer.on(UPDATE_MENTIONS, (_event, view, mentions, unreads, isExpired) => listener(view, mentions, unreads, isExpired)),
|
||||
onCloseTeamsDropdown: (listener) => ipcRenderer.on(CLOSE_TEAMS_DROPDOWN, () => listener()),
|
||||
onOpenTeamsDropdown: (listener) => ipcRenderer.on(OPEN_TEAMS_DROPDOWN, () => listener()),
|
||||
onCloseDownloadsDropdown: (listener) => ipcRenderer.on(CLOSE_DOWNLOADS_DROPDOWN, () => listener()),
|
||||
onOpenDownloadsDropdown: (listener) => ipcRenderer.on(OPEN_DOWNLOADS_DROPDOWN, () => listener()),
|
||||
onShowDownloadsDropdownButtonBadge: (listener) => ipcRenderer.on(SHOW_DOWNLOADS_DROPDOWN_BUTTON_BADGE, () => listener()),
|
||||
onHideDownloadsDropdownButtonBadge: (listener) => ipcRenderer.on(HIDE_DOWNLOADS_DROPDOWN_BUTTON_BADGE, () => listener()),
|
||||
onUpdateDownloadsDropdown: (listener) => ipcRenderer.on(UPDATE_DOWNLOADS_DROPDOWN, (_, downloads) => listener(downloads)),
|
||||
onAppMenuWillClose: (listener) => ipcRenderer.on(APP_MENU_WILL_CLOSE, () => listener()),
|
||||
onFocusThreeDotMenu: (listener) => ipcRenderer.on(FOCUS_THREE_DOT_MENU, () => listener()),
|
||||
});
|
||||
|
||||
window.addEventListener('message', async (event) => {
|
||||
switch (event.data.type) {
|
||||
case GET_LANGUAGE_INFORMATION:
|
||||
|
@@ -9,49 +9,12 @@ import React, {Fragment} from 'react';
|
||||
import {Container, Row} from 'react-bootstrap';
|
||||
import {DropResult} from 'react-beautiful-dnd';
|
||||
import {injectIntl, IntlShape} from 'react-intl';
|
||||
import {IpcRendererEvent} from 'electron/renderer';
|
||||
|
||||
import {TeamWithTabs} from 'types/config';
|
||||
import {DownloadedItems} from 'types/downloads';
|
||||
|
||||
import {getTabViewName} from 'common/tabs/TabView';
|
||||
|
||||
import {
|
||||
FOCUS_BROWSERVIEW,
|
||||
MAXIMIZE_CHANGE,
|
||||
DARK_MODE_CHANGE,
|
||||
HISTORY,
|
||||
LOAD_RETRY,
|
||||
LOAD_SUCCESS,
|
||||
LOAD_FAILED,
|
||||
WINDOW_CLOSE,
|
||||
WINDOW_MINIMIZE,
|
||||
WINDOW_RESTORE,
|
||||
WINDOW_MAXIMIZE,
|
||||
DOUBLE_CLICK_ON_WINDOW,
|
||||
PLAY_SOUND,
|
||||
MODAL_OPEN,
|
||||
MODAL_CLOSE,
|
||||
SET_ACTIVE_VIEW,
|
||||
UPDATE_MENTIONS,
|
||||
TOGGLE_BACK_BUTTON,
|
||||
FOCUS_THREE_DOT_MENU,
|
||||
GET_FULL_SCREEN_STATUS,
|
||||
CLOSE_TEAMS_DROPDOWN,
|
||||
OPEN_TEAMS_DROPDOWN,
|
||||
SWITCH_TAB,
|
||||
CLOSE_TAB,
|
||||
RELOAD_CURRENT_VIEW,
|
||||
CLOSE_DOWNLOADS_DROPDOWN,
|
||||
OPEN_DOWNLOADS_DROPDOWN,
|
||||
SHOW_DOWNLOADS_DROPDOWN_BUTTON_BADGE,
|
||||
HIDE_DOWNLOADS_DROPDOWN_BUTTON_BADGE,
|
||||
UPDATE_DOWNLOADS_DROPDOWN,
|
||||
REQUEST_HAS_DOWNLOADS,
|
||||
CLOSE_DOWNLOADS_DROPDOWN_MENU,
|
||||
APP_MENU_WILL_CLOSE,
|
||||
} from 'common/communication';
|
||||
|
||||
import restoreButton from '../../assets/titlebar/chrome-restore.svg';
|
||||
import maximizeButton from '../../assets/titlebar/chrome-maximize.svg';
|
||||
import minimizeButton from '../../assets/titlebar/chrome-minimize.svg';
|
||||
@@ -90,7 +53,7 @@ type State = {
|
||||
activeServerName?: string;
|
||||
activeTabName?: string;
|
||||
sessionsExpired: Record<string, boolean>;
|
||||
unreadCounts: Record<string, number>;
|
||||
unreadCounts: Record<string, boolean>;
|
||||
mentionCounts: Record<string, number>;
|
||||
maximized: boolean;
|
||||
tabViewStatus: Map<string, TabViewStatus>;
|
||||
@@ -160,7 +123,7 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
|
||||
async requestDownloadsLength() {
|
||||
try {
|
||||
const hasDownloads = await window.ipcRenderer.invoke(REQUEST_HAS_DOWNLOADS);
|
||||
const hasDownloads = await window.desktop.requestHasDownloads();
|
||||
this.setState({
|
||||
hasDownloads,
|
||||
});
|
||||
@@ -174,7 +137,7 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
this.requestDownloadsLength();
|
||||
|
||||
// set page on retry
|
||||
window.ipcRenderer.on(LOAD_RETRY, (_, viewName, retry, err, loadUrl) => {
|
||||
window.desktop.onLoadRetry((viewName, retry, err, loadUrl) => {
|
||||
console.log(`${viewName}: failed to load ${err}, but retrying`);
|
||||
const statusValue = {
|
||||
status: Status.RETRY,
|
||||
@@ -187,11 +150,11 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
this.updateTabStatus(viewName, statusValue);
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(LOAD_SUCCESS, (_, viewName) => {
|
||||
window.desktop.onLoadSuccess((viewName) => {
|
||||
this.updateTabStatus(viewName, {status: Status.DONE});
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(LOAD_FAILED, (_, viewName, err, loadUrl) => {
|
||||
window.desktop.onLoadFailed((viewName, err, loadUrl) => {
|
||||
console.log(`${viewName}: failed to load ${err}`);
|
||||
const statusValue = {
|
||||
status: Status.FAILED,
|
||||
@@ -203,39 +166,39 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
this.updateTabStatus(viewName, statusValue);
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(DARK_MODE_CHANGE, (_, darkMode) => {
|
||||
window.desktop.onDarkModeChange((darkMode) => {
|
||||
this.setState({darkMode});
|
||||
});
|
||||
|
||||
// can't switch tabs sequentially for some reason...
|
||||
window.ipcRenderer.on(SET_ACTIVE_VIEW, (event, serverName, tabName) => {
|
||||
window.desktop.onSetActiveView((serverName, tabName) => {
|
||||
this.setState({activeServerName: serverName, activeTabName: tabName});
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(MAXIMIZE_CHANGE, this.handleMaximizeState);
|
||||
window.desktop.onMaximizeChange(this.handleMaximizeState);
|
||||
|
||||
window.ipcRenderer.on('enter-full-screen', () => this.handleFullScreenState(true));
|
||||
window.ipcRenderer.on('leave-full-screen', () => this.handleFullScreenState(false));
|
||||
window.desktop.onEnterFullScreen(() => this.handleFullScreenState(true));
|
||||
window.desktop.onLeaveFullScreen(() => this.handleFullScreenState(false));
|
||||
|
||||
window.ipcRenderer.invoke(GET_FULL_SCREEN_STATUS).then((fullScreenStatus) => this.handleFullScreenState(fullScreenStatus));
|
||||
window.desktop.getFullScreenStatus().then((fullScreenStatus) => this.handleFullScreenState(fullScreenStatus));
|
||||
|
||||
window.ipcRenderer.on(PLAY_SOUND, (_event, soundName) => {
|
||||
window.desktop.onPlaySound((soundName) => {
|
||||
playSound(soundName);
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(MODAL_OPEN, () => {
|
||||
window.desktop.onModalOpen(() => {
|
||||
this.setState({modalOpen: true});
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(MODAL_CLOSE, () => {
|
||||
window.desktop.onModalClose(() => {
|
||||
this.setState({modalOpen: false});
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(TOGGLE_BACK_BUTTON, (event, showExtraBar) => {
|
||||
window.desktop.onToggleBackButton((showExtraBar) => {
|
||||
this.setState({showExtraBar});
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(UPDATE_MENTIONS, (_event, view, mentions, unreads, isExpired) => {
|
||||
window.desktop.onUpdateMentions((view, mentions, unreads, isExpired) => {
|
||||
const {unreadCounts, mentionCounts, sessionsExpired} = this.state;
|
||||
|
||||
const newMentionCounts = {...mentionCounts};
|
||||
@@ -250,40 +213,40 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
this.setState({unreadCounts: newUnreads, mentionCounts: newMentionCounts, sessionsExpired: expired});
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(CLOSE_TEAMS_DROPDOWN, () => {
|
||||
window.desktop.onCloseTeamsDropdown(() => {
|
||||
this.setState({isMenuOpen: false});
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(OPEN_TEAMS_DROPDOWN, () => {
|
||||
window.desktop.onOpenTeamsDropdown(() => {
|
||||
this.setState({isMenuOpen: true});
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(CLOSE_DOWNLOADS_DROPDOWN, () => {
|
||||
window.desktop.onCloseDownloadsDropdown(() => {
|
||||
this.setState({isDownloadsDropdownOpen: false});
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(OPEN_DOWNLOADS_DROPDOWN, () => {
|
||||
window.desktop.onOpenDownloadsDropdown(() => {
|
||||
this.setState({isDownloadsDropdownOpen: true});
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(SHOW_DOWNLOADS_DROPDOWN_BUTTON_BADGE, () => {
|
||||
window.desktop.onShowDownloadsDropdownButtonBadge(() => {
|
||||
this.setState({showDownloadsBadge: true});
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(HIDE_DOWNLOADS_DROPDOWN_BUTTON_BADGE, () => {
|
||||
window.desktop.onHideDownloadsDropdownButtonBadge(() => {
|
||||
this.setState({showDownloadsBadge: false});
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(UPDATE_DOWNLOADS_DROPDOWN, (event, downloads: DownloadedItems) => {
|
||||
window.desktop.onUpdateDownloadsDropdown((downloads: DownloadedItems) => {
|
||||
this.setState({
|
||||
hasDownloads: (Object.values(downloads)?.length || 0) > 0,
|
||||
});
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(APP_MENU_WILL_CLOSE, this.unFocusThreeDotsButton);
|
||||
window.desktop.onAppMenuWillClose(this.unFocusThreeDotsButton);
|
||||
|
||||
if (window.process.platform !== 'darwin') {
|
||||
window.ipcRenderer.on(FOCUS_THREE_DOT_MENU, this.focusThreeDotsButton);
|
||||
window.desktop.onFocusThreeDotMenu(this.focusThreeDotsButton);
|
||||
}
|
||||
|
||||
window.addEventListener('click', this.handleCloseDropdowns);
|
||||
@@ -294,11 +257,11 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
handleCloseDropdowns = () => {
|
||||
window.ipcRenderer.send(CLOSE_TEAMS_DROPDOWN);
|
||||
window.desktop.closeTeamsDropdown();
|
||||
this.closeDownloadsDropdown();
|
||||
}
|
||||
|
||||
handleMaximizeState = (_: IpcRendererEvent, maximized: boolean) => {
|
||||
handleMaximizeState = (maximized: boolean) => {
|
||||
this.setState({maximized});
|
||||
}
|
||||
|
||||
@@ -307,11 +270,17 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
handleSelectTab = (name: string) => {
|
||||
window.ipcRenderer.send(SWITCH_TAB, this.state.activeServerName, name);
|
||||
if (!this.state.activeServerName) {
|
||||
return;
|
||||
}
|
||||
window.desktop.switchTab(this.state.activeServerName, name);
|
||||
}
|
||||
|
||||
handleCloseTab = (name: string) => {
|
||||
window.ipcRenderer.send(CLOSE_TAB, this.state.activeServerName, name);
|
||||
if (!this.state.activeServerName) {
|
||||
return;
|
||||
}
|
||||
window.desktop.closeTab(this.state.activeServerName, name);
|
||||
}
|
||||
|
||||
handleDragAndDrop = async (dropResult: DropResult) => {
|
||||
@@ -338,21 +307,21 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
|
||||
handleClose = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
e.stopPropagation(); // since it is our button, the event goes into MainPage's onclick event, getting focus back.
|
||||
window.ipcRenderer.send(WINDOW_CLOSE);
|
||||
window.desktop.closeWindow();
|
||||
}
|
||||
|
||||
handleMinimize = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
e.stopPropagation();
|
||||
window.ipcRenderer.send(WINDOW_MINIMIZE);
|
||||
window.desktop.minimizeWindow();
|
||||
}
|
||||
|
||||
handleMaximize = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
e.stopPropagation();
|
||||
window.ipcRenderer.send(WINDOW_MAXIMIZE);
|
||||
window.desktop.maximizeWindow();
|
||||
}
|
||||
|
||||
handleRestore = () => {
|
||||
window.ipcRenderer.send(WINDOW_RESTORE);
|
||||
window.desktop.restoreWindow();
|
||||
}
|
||||
|
||||
openMenu = () => {
|
||||
@@ -360,16 +329,16 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
handleDoubleClick = () => {
|
||||
window.ipcRenderer.send(DOUBLE_CLICK_ON_WINDOW);
|
||||
window.desktop.doubleClickOnWindow();
|
||||
}
|
||||
|
||||
focusOnWebView = () => {
|
||||
window.ipcRenderer.send(FOCUS_BROWSERVIEW);
|
||||
window.desktop.focusBrowserView();
|
||||
this.handleCloseDropdowns();
|
||||
}
|
||||
|
||||
reloadCurrentView = () => {
|
||||
window.ipcRenderer.send(RELOAD_CURRENT_VIEW);
|
||||
window.desktop.reloadCurrentView();
|
||||
}
|
||||
|
||||
showHideDownloadsBadge(value = false) {
|
||||
@@ -377,12 +346,12 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
closeDownloadsDropdown() {
|
||||
window.ipcRenderer.send(CLOSE_DOWNLOADS_DROPDOWN);
|
||||
window.ipcRenderer.send(CLOSE_DOWNLOADS_DROPDOWN_MENU);
|
||||
window.desktop.closeDownloadsDropdown();
|
||||
window.desktop.closeDownloadsDropdownMenu();
|
||||
}
|
||||
|
||||
openDownloadsDropdown() {
|
||||
window.ipcRenderer.send(OPEN_DOWNLOADS_DROPDOWN);
|
||||
window.desktop.openDownloadsDropdown();
|
||||
}
|
||||
|
||||
focusThreeDotsButton = () => {
|
||||
@@ -497,12 +466,12 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
}
|
||||
return sum + this.state.mentionCounts[key];
|
||||
}, 0);
|
||||
const totalUnreadCount = Object.keys(this.state.unreadCounts).reduce((sum, key) => {
|
||||
const hasAnyUnreads = Object.keys(this.state.unreadCounts).reduce((sum, key) => {
|
||||
if (this.state.activeServerName && key.match(serverMatch)) {
|
||||
return sum;
|
||||
}
|
||||
return sum + this.state.unreadCounts[key];
|
||||
}, 0);
|
||||
return sum || this.state.unreadCounts[key];
|
||||
}, false);
|
||||
const topRow = (
|
||||
<Row
|
||||
className={topBarClassName}
|
||||
@@ -536,7 +505,7 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
isDisabled={this.state.modalOpen}
|
||||
activeServerName={this.state.activeServerName}
|
||||
totalMentionCount={totalMentionCount}
|
||||
hasUnreads={totalUnreadCount > 0}
|
||||
hasUnreads={hasAnyUnreads}
|
||||
isMenuOpen={this.state.isMenuOpen}
|
||||
darkMode={this.state.darkMode}
|
||||
/>
|
||||
@@ -586,7 +555,7 @@ class MainPage extends React.PureComponent<Props, State> {
|
||||
darkMode={this.state.darkMode}
|
||||
show={this.state.showExtraBar}
|
||||
goBack={() => {
|
||||
window.ipcRenderer.send(HISTORY, -1);
|
||||
window.desktop.goBack();
|
||||
}}
|
||||
/>
|
||||
<Row>
|
||||
|
@@ -12,28 +12,16 @@ import {FormattedMessage, injectIntl, IntlShape} from 'react-intl';
|
||||
import ReactSelect, {ActionMeta, MultiValue} from 'react-select';
|
||||
|
||||
import {CombinedConfig, LocalConfiguration} from 'types/config';
|
||||
import {SaveQueueItem} from 'types/settings';
|
||||
import {DeepPartial} from 'types/utils';
|
||||
|
||||
import {localeTranslations} from 'common/utils/constants';
|
||||
|
||||
import {
|
||||
GET_LOCAL_CONFIGURATION,
|
||||
UPDATE_CONFIGURATION,
|
||||
DOUBLE_CLICK_ON_WINDOW,
|
||||
GET_DOWNLOAD_LOCATION,
|
||||
RELOAD_CONFIGURATION,
|
||||
GET_AVAILABLE_SPELL_CHECKER_LANGUAGES,
|
||||
CHECK_FOR_UPDATES,
|
||||
GET_AVAILABLE_LANGUAGES,
|
||||
} from 'common/communication';
|
||||
|
||||
import AutoSaveIndicator, {SavingState} from './AutoSaveIndicator';
|
||||
|
||||
const CONFIG_TYPE_UPDATES = 'updates';
|
||||
const CONFIG_TYPE_APP_OPTIONS = 'appOptions';
|
||||
|
||||
type ConfigType = typeof CONFIG_TYPE_UPDATES | typeof CONFIG_TYPE_APP_OPTIONS;
|
||||
|
||||
type Props = {
|
||||
intl: IntlShape;
|
||||
}
|
||||
@@ -54,12 +42,6 @@ type SavingStateItems = {
|
||||
updates: SavingState;
|
||||
}
|
||||
|
||||
type SaveQueueItem = {
|
||||
configType: ConfigType;
|
||||
key: keyof CombinedConfig;
|
||||
data: CombinedConfig[keyof CombinedConfig];
|
||||
}
|
||||
|
||||
class SettingsPage extends React.PureComponent<Props, State> {
|
||||
trayIconThemeRef: React.RefObject<HTMLDivElement>;
|
||||
downloadLocationRef: React.RefObject<HTMLInputElement>;
|
||||
@@ -125,18 +107,18 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.ipcRenderer.on(RELOAD_CONFIGURATION, () => {
|
||||
window.desktop.onReloadConfiguration(() => {
|
||||
this.updateSaveState();
|
||||
this.getConfig();
|
||||
});
|
||||
|
||||
window.ipcRenderer.invoke(GET_AVAILABLE_SPELL_CHECKER_LANGUAGES).then((languages: string[]) => {
|
||||
window.desktop.getAvailableSpellCheckerLanguages().then((languages: string[]) => {
|
||||
const availableSpellcheckerLanguages = languages.filter((language) => localeTranslations[language]).map((language) => ({label: localeTranslations[language], value: language}));
|
||||
availableSpellcheckerLanguages.sort((a, b) => a.label.localeCompare(b.label));
|
||||
this.setState({availableSpellcheckerLanguages});
|
||||
});
|
||||
|
||||
window.ipcRenderer.invoke(GET_AVAILABLE_LANGUAGES).then((languages: string[]) => {
|
||||
window.desktop.getAvailableLanguages().then((languages: string[]) => {
|
||||
const availableLanguages = languages.filter((language) => localeTranslations[language]).map((language) => ({label: localeTranslations[language], value: language}));
|
||||
availableLanguages.sort((a, b) => a.label.localeCompare(b.label));
|
||||
this.setState({availableLanguages});
|
||||
@@ -144,8 +126,8 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
getConfig = () => {
|
||||
window.ipcRenderer.invoke(GET_LOCAL_CONFIGURATION).then((config) => {
|
||||
this.setState({ready: true, maximized: false, ...this.convertConfigDataToState(config, this.state) as Omit<State, 'ready'>});
|
||||
window.desktop.getLocalConfiguration().then((config) => {
|
||||
this.setState({ready: true, maximized: false, ...this.convertConfigDataToState(config as Partial<LocalConfiguration>, this.state) as Omit<State, 'ready'>});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -159,7 +141,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
||||
return newState;
|
||||
}
|
||||
|
||||
saveSetting = (configType: ConfigType, {key, data}: {key: keyof CombinedConfig; data: CombinedConfig[keyof CombinedConfig]}) => {
|
||||
saveSetting = (configType: 'updates' | 'appOptions', {key, data}: {key: keyof CombinedConfig; data: CombinedConfig[keyof CombinedConfig]}) => {
|
||||
this.saveQueue.push({
|
||||
configType,
|
||||
key,
|
||||
@@ -177,7 +159,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
||||
this.savingIsDebounced = true;
|
||||
setTimeout(() => {
|
||||
this.savingIsDebounced = false;
|
||||
window.ipcRenderer.send(UPDATE_CONFIGURATION, this.saveQueue.splice(0, this.saveQueue.length));
|
||||
window.desktop.updateConfiguration(this.saveQueue.splice(0, this.saveQueue.length));
|
||||
}, 500);
|
||||
}
|
||||
|
||||
@@ -353,7 +335,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
checkForUpdates = () => {
|
||||
window.ipcRenderer.send(CHECK_FOR_UPDATES);
|
||||
window.desktop.checkForUpdates();
|
||||
}
|
||||
|
||||
handleChangeSpellCheckerLocales = (value: MultiValue<{label: string; value: string}>, actionMeta: ActionMeta<{label: string; value: string}>) => {
|
||||
@@ -402,7 +384,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
||||
|
||||
selectDownloadLocation = () => {
|
||||
if (!this.state.userOpenedDownloadDialog) {
|
||||
window.ipcRenderer.invoke(GET_DOWNLOAD_LOCATION, this.state.downloadLocation).then((result) => this.saveDownloadLocation(result));
|
||||
window.desktop.getDownloadLocation(this.state.downloadLocation).then((result) => this.saveDownloadLocation(result));
|
||||
this.setState({userOpenedDownloadDialog: true});
|
||||
}
|
||||
this.setState({userOpenedDownloadDialog: false});
|
||||
@@ -434,7 +416,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
handleDoubleClick = () => {
|
||||
window.ipcRenderer.send(DOUBLE_CLICK_ON_WINDOW, 'settings');
|
||||
window.desktop.doubleClickOnWindow('settings');
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@@ -21,7 +21,7 @@ type Props = {
|
||||
onCloseTab: (name: string) => void;
|
||||
tabs: Tab[];
|
||||
sessionsExpired: Record<string, boolean>;
|
||||
unreadCounts: Record<string, number>;
|
||||
unreadCounts: Record<string, boolean>;
|
||||
mentionCounts: Record<string, number>;
|
||||
onDrop: (result: DropResult) => void;
|
||||
tabsDisabled?: boolean;
|
||||
|
@@ -5,8 +5,6 @@ import classNames from 'classnames';
|
||||
import React, {useEffect} from 'react';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
|
||||
import {CLOSE_TEAMS_DROPDOWN, OPEN_TEAMS_DROPDOWN} from 'common/communication';
|
||||
|
||||
import '../css/components/TeamDropdownButton.scss';
|
||||
|
||||
type Props = {
|
||||
@@ -31,7 +29,11 @@ const TeamDropdownButton: React.FC<Props> = (props: Props) => {
|
||||
const handleToggleButton = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
window.ipcRenderer.send(isMenuOpen ? CLOSE_TEAMS_DROPDOWN : OPEN_TEAMS_DROPDOWN);
|
||||
if (isMenuOpen) {
|
||||
window.desktop.closeTeamsDropdown();
|
||||
} else {
|
||||
window.desktop.openTeamsDropdown();
|
||||
}
|
||||
};
|
||||
|
||||
let badgeDiv: React.ReactNode;
|
||||
|
@@ -10,8 +10,6 @@ import ReactDOM from 'react-dom';
|
||||
|
||||
import {CombinedConfig, Team} from 'types/config';
|
||||
|
||||
import {GET_CONFIGURATION, UPDATE_TEAMS, QUIT, RELOAD_CONFIGURATION, OPEN_APP_MENU} from 'common/communication';
|
||||
|
||||
import MainPage from './components/MainPage';
|
||||
import IntlProvider from './intl_provider';
|
||||
|
||||
@@ -28,11 +26,11 @@ class Root extends React.PureComponent<Record<string, never>, State> {
|
||||
async componentDidMount() {
|
||||
await this.setInitialConfig();
|
||||
|
||||
window.ipcRenderer.on('synchronize-config', () => {
|
||||
window.desktop.onSynchronizeConfig(() => {
|
||||
this.reloadConfig();
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(RELOAD_CONFIGURATION, () => {
|
||||
window.desktop.onReloadConfiguration(() => {
|
||||
this.reloadConfig();
|
||||
});
|
||||
|
||||
@@ -84,7 +82,7 @@ class Root extends React.PureComponent<Record<string, never>, State> {
|
||||
};
|
||||
|
||||
teamConfigChange = async (updatedTeams: Team[]) => {
|
||||
window.ipcRenderer.invoke(UPDATE_TEAMS, updatedTeams).then(() => {
|
||||
window.desktop.updateTeams(updatedTeams).then(() => {
|
||||
this.reloadConfig();
|
||||
});
|
||||
};
|
||||
@@ -97,20 +95,20 @@ class Root extends React.PureComponent<Record<string, never>, State> {
|
||||
requestConfig = async (exitOnError?: boolean) => {
|
||||
// todo: should we block?
|
||||
try {
|
||||
const configRequest = await window.ipcRenderer.invoke(GET_CONFIGURATION);
|
||||
const configRequest = await window.desktop.getConfiguration() as CombinedConfig;
|
||||
return configRequest;
|
||||
} catch (err: any) {
|
||||
console.log(`there was an error with the config: ${err}`);
|
||||
if (exitOnError) {
|
||||
window.ipcRenderer.send(QUIT, `unable to load configuration: ${err}`, err.stack);
|
||||
window.desktop.quit(`unable to load configuration: ${err}`, err.stack);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return undefined;
|
||||
};
|
||||
|
||||
openMenu = () => {
|
||||
if (window.process.platform !== 'darwin') {
|
||||
window.ipcRenderer.send(OPEN_APP_MENU);
|
||||
window.desktop.openAppMenu();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +132,7 @@ class Root extends React.PureComponent<Record<string, never>, State> {
|
||||
);
|
||||
}
|
||||
}
|
||||
window.ipcRenderer.invoke('get-app-version').then(({name, version}) => {
|
||||
window.desktop.getVersion().then(({name, version}) => {
|
||||
// eslint-disable-next-line no-undef
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
|
@@ -9,8 +9,6 @@ import 'renderer/css/settings.css';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import {DARK_MODE_CHANGE, GET_DARK_MODE} from 'common/communication';
|
||||
|
||||
import darkStyles from 'renderer/css/lazy/settings-dark.lazy.css';
|
||||
|
||||
import SettingsPage from './components/SettingsPage';
|
||||
@@ -24,8 +22,8 @@ const setDarkMode = (darkMode: boolean) => {
|
||||
}
|
||||
};
|
||||
|
||||
window.ipcRenderer.on(DARK_MODE_CHANGE, (_, darkMode) => setDarkMode(darkMode));
|
||||
window.ipcRenderer.invoke(GET_DARK_MODE).then(setDarkMode);
|
||||
window.desktop.onDarkModeChange((darkMode) => setDarkMode(darkMode));
|
||||
window.desktop.getDarkMode().then(setDarkMode);
|
||||
|
||||
const start = async () => {
|
||||
ReactDOM.render(
|
||||
|
10
src/types/settings.ts
Normal file
10
src/types/settings.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {CombinedConfig} from './config';
|
||||
|
||||
export type SaveQueueItem = {
|
||||
configType: 'updates' | 'appOptions';
|
||||
key: keyof CombinedConfig;
|
||||
data: CombinedConfig[keyof CombinedConfig];
|
||||
};
|
@@ -3,6 +3,10 @@
|
||||
|
||||
import {ipcRenderer} from 'electron/renderer';
|
||||
|
||||
import {CombinedConfig, LocalConfiguration, Team} from './config';
|
||||
import {DownloadedItems} from './downloads';
|
||||
import {SaveQueueItem} from './settings';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
ipcRenderer: {
|
||||
@@ -23,5 +27,62 @@ declare global {
|
||||
mas: {
|
||||
getThumbnailLocation: (location: string) => Promise<string>;
|
||||
};
|
||||
desktop: {
|
||||
quit: (reason: string, stack: string) => void;
|
||||
openAppMenu: () => void;
|
||||
closeTeamsDropdown: () => void;
|
||||
openTeamsDropdown: () => void;
|
||||
switchTab: (serverName: string, tabName: string) => void;
|
||||
closeTab: (serverName: string, tabName: string) => void;
|
||||
closeWindow: () => void;
|
||||
minimizeWindow: () => void;
|
||||
maximizeWindow: () => void;
|
||||
restoreWindow: () => void;
|
||||
doubleClickOnWindow: (windowName?: string) => void;
|
||||
focusBrowserView: () => void;
|
||||
reloadCurrentView: () => void;
|
||||
closeDownloadsDropdown: () => void;
|
||||
closeDownloadsDropdownMenu: () => void;
|
||||
openDownloadsDropdown: () => void;
|
||||
goBack: () => void;
|
||||
checkForUpdates: () => void;
|
||||
updateConfiguration: (saveQueueItems: SaveQueueItem[]) => void;
|
||||
|
||||
updateTeams: (updatedTeams: Team[]) => Promise<void>;
|
||||
getConfiguration: (option?: keyof CombinedConfig) => Promise<CombinedConfig[keyof CombinedConfig] | CombinedConfig>;
|
||||
getVersion: () => Promise<{name: string; version: string}>;
|
||||
getDarkMode: () => Promise<boolean>;
|
||||
requestHasDownloads: () => Promise<boolean>;
|
||||
getFullScreenStatus: () => Promise<boolean>;
|
||||
getAvailableSpellCheckerLanguages: () => Promise<string[]>;
|
||||
getAvailableLanguages: () => Promise<string[]>;
|
||||
getLocalConfiguration: (option?: keyof LocalConfiguration) => Promise<LocalConfiguration[keyof LocalConfiguration] | Partial<LocalConfiguration>>;
|
||||
getDownloadLocation: (downloadLocation?: string) => Promise<string>;
|
||||
|
||||
onSynchronizeConfig: (listener: () => void) => void;
|
||||
onReloadConfiguration: (listener: () => void) => void;
|
||||
onDarkModeChange: (listener: (darkMode: boolean) => void) => void;
|
||||
onLoadRetry: (listener: (viewName: string, retry: Date, err: string, loadUrl: string) => void) => void;
|
||||
onLoadSuccess: (listener: (viewName: string) => void) => void;
|
||||
onLoadFailed: (listener: (viewName: string, err: string, loadUrl: string) => void) => void;
|
||||
onSetActiveView: (listener: (serverName: string, tabName: string) => void) => void;
|
||||
onMaximizeChange: (listener: (maximize: boolean) => void) => void;
|
||||
onEnterFullScreen: (listener: () => void) => void;
|
||||
onLeaveFullScreen: (listener: () => void) => void;
|
||||
onPlaySound: (listener: (soundName: string) => void) => void;
|
||||
onModalOpen: (listener: () => void) => void;
|
||||
onModalClose: (listener: () => void) => void;
|
||||
onToggleBackButton: (listener: (showExtraBar: boolean) => void) => void;
|
||||
onUpdateMentions: (listener: (view: string, mentions: number, unreads: boolean, isExpired: boolean) => void) => void;
|
||||
onCloseTeamsDropdown: (listener: () => void) => void;
|
||||
onOpenTeamsDropdown: (listener: () => void) => void;
|
||||
onCloseDownloadsDropdown: (listener: () => void) => void;
|
||||
onOpenDownloadsDropdown: (listener: () => void) => void;
|
||||
onShowDownloadsDropdownButtonBadge: (listener: () => void) => void;
|
||||
onHideDownloadsDropdownButtonBadge: (listener: () => void) => void;
|
||||
onUpdateDownloadsDropdown: (listener: (downloads: DownloadedItems) => void) => void;
|
||||
onAppMenuWillClose: (listener: () => void) => void;
|
||||
onFocusThreeDotMenu: (listener: () => void) => void;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user