Code cleanup, update eslint from webapp, add ts-prune (#1884)

This commit is contained in:
Devin Binnie
2021-12-03 16:01:49 -05:00
committed by GitHub
parent 875a0f8bfd
commit 73056d2649
19 changed files with 383 additions and 336 deletions

View File

@@ -7,11 +7,7 @@ export const CLOSE_TAB = 'close-tab';
export const OPEN_TAB = 'open-tab';
export const SET_ACTIVE_VIEW = 'set-active-view';
export const UPDATE_LAST_ACTIVE = 'update-last-active';
export const MARK_READ = 'mark-read';
export const FOCUS_BROWSERVIEW = 'focus-browserview';
export const ZOOM = 'zoom';
export const UNDO = 'undo';
export const REDO = 'redo';
export const HISTORY = 'history';
export const QUIT = 'quit';
@@ -34,8 +30,6 @@ export const LOAD_FAILED = 'load_fail';
export const MAXIMIZE_CHANGE = 'maximized_change';
export const OPEN_EXTERNAL = 'open_external';
export const DOUBLE_CLICK_ON_WINDOW = 'double_click';
export const SHOW_NEW_SERVER_MODAL = 'show_new_server_modal';
@@ -83,7 +77,6 @@ export const TOGGLE_LOADING_SCREEN_VISIBILITY = 'toggle-loading-screen-visibilit
export const SELECT_NEXT_TAB = 'select-next-tab';
export const SELECT_PREVIOUS_TAB = 'select-previous-tab';
export const ADD_SERVER = 'add-server';
export const FOCUS_THREE_DOT_MENU = 'focus-three-dot-menu';
export const LOADSCREEN_END = 'loadscreen-end';

View File

@@ -1,11 +1,6 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// channel types for managing permissions
export const REQUEST_PERMISSION_CHANNEL = 'request-permission';
export const GRANT_PERMISSION_CHANNEL = 'grant-permission';
export const DENY_PERMISSION_CHANNEL = 'deny-permission';
// Permission types that can be requested
export const BASIC_AUTH_PERMISSION = 'canBasicAuth';

View File

@@ -44,7 +44,6 @@ export function getDefaultTeamWithTabsFromTeam(team: Team) {
};
}
// TODO: Might need to move this out
export function getServerView(srv: MattermostServer, tab: Tab) {
switch (tab.name) {
case TAB_MESSAGING:
@@ -76,6 +75,5 @@ export function getTabDisplayName(tabType: TabType) {
}
export function canCloseTab(tabType: TabType) {
// TODO: maybe rework to make the property belong to the class somehow
return tabType !== TAB_MESSAGING;
}

View File

@@ -25,7 +25,7 @@ function createErrorReport(err: Error) {
}
function openDetachedExternal(url: string) {
const spawnOption = {detached: true, stdio: 'ignore' as any};
const spawnOption = {detached: true, stdio: 'ignore' as const};
switch (process.platform) {
case 'win32':
return spawn('cmd', ['/C', 'start', url], spawnOption);

View File

@@ -67,7 +67,7 @@ export default class UserActivityMonitor extends EventEmitter {
this.config = Object.assign({}, this.config, config);
// TODO: Node typings don't map Timeout to number, but then clearInterval requires a number?
// Node typings don't map Timeout to number, but then clearInterval requires a number?
this.systemIdleTimeIntervalID = setInterval(() => {
try {
this.updateIdleTime(electron.powerMonitor.getSystemIdleTime());

View File

@@ -36,7 +36,7 @@ const emitDropdown = (expired?: Map<string, boolean>, mentions?: Map<string, num
status.emitter.emit(UPDATE_DROPDOWN_MENTIONS, expired, mentions, unreads);
};
export const emitStatus = () => {
const emitStatus = () => {
const expired = anyExpired();
const mentions = totalMentions();
const unreads = anyUnreads();
@@ -65,28 +65,19 @@ export const updateBadge = () => {
emitBadge(expired, mentions, unreads);
};
export const getUnreads = (serverName: string) => {
const getUnreads = (serverName: string) => {
return status.unreads.get(serverName) || false;
};
export const getMentions = (serverName: string) => {
const getMentions = (serverName: string) => {
return status.mentions.get(serverName) || 0; // this might be undefined as a way to tell that we don't know as it might need to login still.
};
export const getIsExpired = (serverName: string) => {
const getIsExpired = (serverName: string) => {
return status.expired.get(serverName) || false;
};
export const anyMentions = () => {
for (const v of status.mentions.values()) {
if (v > 0) {
return v;
}
}
return false;
};
export const totalMentions = () => {
const totalMentions = () => {
let total = 0;
for (const v of status.mentions.values()) {
total += v;
@@ -94,7 +85,7 @@ export const totalMentions = () => {
return total;
};
export const anyUnreads = () => {
const anyUnreads = () => {
for (const v of status.unreads.values()) {
if (v) {
return v;
@@ -103,7 +94,7 @@ export const anyUnreads = () => {
return false;
};
export const anyExpired = () => {
const anyExpired = () => {
for (const v of status.expired.values()) {
if (v) {
return v;
@@ -113,11 +104,9 @@ export const anyExpired = () => {
};
// add any other event emitter methods if needed
export const on = (event: string, listener: (...args: any[]) => void) => {
status.emitter.on(event, listener);
};
export const on = status.emitter.on;
export const setSessionExpired = (serverName: string, expired: boolean) => {
const setSessionExpired = (serverName: string, expired: boolean) => {
const isExpired = Boolean(expired);
const old = status.expired.get(serverName);
status.expired.set(serverName, isExpired);

View File

@@ -1,201 +0,0 @@
// Copyright (c) 2015-2016 Yuya Ochiai
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// TODO: This needs to be rebuilt anyways, skipping TS migration for now
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-nocheck
import path from 'path';
import {app, BrowserWindow, BrowserWindowConstructorOptions, dialog, ipcMain, IpcMainEvent, shell} from 'electron';
import log from 'electron-log';
import {autoUpdater, CancellationToken} from 'electron-updater';
import semver from 'semver';
// eslint-disable-next-line no-magic-numbers
const UPDATER_INTERVAL_IN_MS = 48 * 60 * 60 * 1000; // 48 hours
autoUpdater.log = log;
autoUpdater.log.transports.file.level = 'info';
let updaterModal = null;
function createEventListener(win: BrowserWindow, eventName: string) {
return (event: IpcMainEvent) => {
if (event.sender === win.webContents) {
win.emit(eventName);
}
};
}
function createUpdaterModal(parentWindow: BrowserWindow, options: {linuxAppIcon: string; notifyOnly: boolean}) {
const windowWidth = 480;
const windowHeight = 280;
const windowOptions: BrowserWindowConstructorOptions = {
title: `${app.name} Updater`,
parent: parentWindow,
modal: true,
maximizable: false,
show: false,
width: windowWidth,
height: windowHeight,
resizable: false,
autoHideMenuBar: true,
backgroundColor: '#fff', // prevents blurry text: https://electronjs.org/docs/faq#the-font-looks-blurry-what-is-this-and-what-can-i-do
};
if (process.platform === 'linux') {
windowOptions.icon = options.linuxAppIcon;
}
const modal = new BrowserWindow(windowOptions);
modal.once('ready-to-show', () => {
modal.show();
});
let updaterURL = (global.isDev ? 'http://localhost:8080' : `file://${app.getAppPath()}`) + '/browser/updater.html';
if (options.notifyOnly) {
updaterURL += '?notifyOnly=true';
}
modal.loadURL(updaterURL);
for (const eventName of ['click-release-notes', 'click-skip', 'click-remind', 'click-install', 'click-download', 'click-cancel']) {
const listener = createEventListener(modal, eventName);
ipcMain.on(eventName, listener);
modal.on('closed', () => {
ipcMain.removeListener(eventName, listener);
});
}
return modal;
}
function isUpdateApplicable(now: Date, skippedVersion, updateInfo) {
const releaseTime = new Date(updateInfo.releaseDate).getTime();
// 48 hours after a new version is added to releases.mattermost.com, user receives a “New update is available” dialog
if (now.getTime() - releaseTime < UPDATER_INTERVAL_IN_MS) {
return false;
}
// If a version was skipped, compare version.
if (skippedVersion) {
return semver.gt(updateInfo.version, skippedVersion);
}
return true;
}
function downloadAndInstall(cancellationToken?: CancellationToken) {
autoUpdater.on('update-downloaded', () => {
global.willAppQuit = true;
autoUpdater.quitAndInstall();
});
autoUpdater.downloadUpdate(cancellationToken);
}
function initialize(appState, mainWindow, notifyOnly = false) {
autoUpdater.autoDownload = false; // To prevent upgrading on quit
const assetsDir = path.resolve(app.getAppPath(), 'assets');
autoUpdater.on('error', (err) => {
log.error('Error in autoUpdater:', err.message);
}).on('update-available', (info) => {
let cancellationToken = null;
if (isUpdateApplicable(new Date(), appState.skippedVersion, info)) {
updaterModal = createUpdaterModal(mainWindow, {
linuxAppIcon: path.join(assetsDir, 'appicon.png'),
notifyOnly,
});
updaterModal.on('closed', () => {
updaterModal = null;
});
updaterModal.on('click-skip', () => {
appState.skippedVersion = info.version;
updaterModal.close();
}).on('click-remind', () => {
appState.updateCheckedDate = new Date();
setTimeout(() => { // eslint-disable-line max-nested-callbacks
autoUpdater.checkForUpdates();
}, UPDATER_INTERVAL_IN_MS);
updaterModal.close();
}).on('click-install', () => {
updaterModal.webContents.send('start-download');
autoUpdater.signals.progress((data) => { // eslint-disable-line max-nested-callbacks
updaterModal.send('progress', Math.floor(data.percent));
log.info('progress:', data);
});
cancellationToken = new CancellationToken();
downloadAndInstall(cancellationToken);
}).on('click-download', () => {
shell.openExternal('https://about.mattermost.com/download/#mattermostApps');
}).on('click-release-notes', () => {
shell.openExternal(`https://github.com/mattermost/desktop/releases/v${info.version}`);
}).on('click-cancel', () => {
cancellationToken.cancel();
updaterModal.close();
});
updaterModal.focus();
} else if (autoUpdater.isManual) {
autoUpdater.emit('update-not-available');
}
}).on('update-not-available', () => {
if (autoUpdater.isManual) {
dialog.showMessageBox(mainWindow, {
type: 'info',
buttons: ['Close'],
title: 'Your Desktop App is up to date',
message: 'You have the latest version of the Mattermost Desktop App.',
});
}
setTimeout(() => {
autoUpdater.checkForUpdates();
}, UPDATER_INTERVAL_IN_MS);
});
}
function shouldCheckForUpdatesOnStart(updateCheckedDate: Date) {
if (updateCheckedDate) {
if (Date.now() - updateCheckedDate.getTime() < UPDATER_INTERVAL_IN_MS) {
return false;
}
}
return true;
}
function checkForUpdates(isManual = false) {
autoUpdater.isManual = isManual;
if (!updaterModal) {
autoUpdater.checkForUpdates();
}
}
class AutoUpdaterConfig {
data: {notifyOnly?: boolean};
constructor() {
this.data = {};
}
isNotifyOnly() {
if (process.platform === 'win32') {
return true;
}
if (this.data.notifyOnly === true) {
return true;
}
return false;
}
}
function loadConfig() {
return new AutoUpdaterConfig();
}
export default {
UPDATER_INTERVAL_IN_MS,
checkForUpdates,
shouldCheckForUpdatesOnStart,
initialize,
loadConfig,
};

View File

@@ -274,6 +274,6 @@ export function createTemplate(config: Config) {
}
export function createMenu(config: Config) {
// TODO: Electron is enforcing certain variables that it doesn't need
// Electron is enforcing certain variables that it doesn't need
return Menu.buildFromTemplate(createTemplate(config) as Array<MenuItemConstructorOptions | MenuItem>);
}

View File

@@ -35,6 +35,6 @@ export function createTemplate(config: CombinedConfig) {
}
export function createMenu(config: CombinedConfig) {
// TODO: Electron is enforcing certain variables that it doesn't need
// Electron is enforcing certain variables that it doesn't need
return Menu.buildFromTemplate(createTemplate(config) as Array<MenuItemConstructorOptions | MenuItem>);
}

View File

@@ -19,7 +19,7 @@ const defaultOptions = {
icon: appIconURL,
urgency: 'normal' as Notification['urgency'],
};
export const DEFAULT_WIN7 = 'Ding';
const DEFAULT_WIN7 = 'Ding';
export class Mention extends Notification {
customSound: string;

View File

@@ -37,11 +37,6 @@ export function getAdjustedWindowBoundaries(width: number, height: number, hasBa
}
export function getLocalURLString(urlPath: string, query?: Map<string, string>, isMain?: boolean) {
const localURL = getLocalURL(urlPath, query, isMain);
return localURL.href;
}
export function getLocalURL(urlPath: string, query?: Map<string, string>, isMain?: boolean) {
let pathname;
const processPath = isMain ? '' : '/renderer';
const mode = Utils.runMode();
@@ -61,7 +56,7 @@ export function getLocalURL(urlPath: string, query?: Map<string, string>, isMain
});
}
return localUrl;
return localUrl.href;
}
export function getLocalPreload(file: string) {

View File

@@ -165,7 +165,7 @@ export class MattermostView extends EventEmitter {
};
}
loadRetry = (loadURL: string, err: any) => {
loadRetry = (loadURL: string, err: Error) => {
this.retryLoad = setTimeout(this.retry(loadURL), RELOAD_INTERVAL);
WindowManager.sendToRenderer(LOAD_RETRY, this.tab.name, Date.now() + RELOAD_INTERVAL, err.toString(), loadURL.toString());
log.info(`[${Util.shorten(this.tab.name)}] failed loading ${loadURL}: ${err}, retrying in ${RELOAD_INTERVAL / SECOND} seconds`);
@@ -211,7 +211,6 @@ export class MattermostView extends EventEmitter {
hide = () => this.show(false);
setBounds = (boundaries: Electron.Rectangle) => {
// todo: review this, as it might not work properly with devtools/minimizing/resizing
this.view.setBounds(boundaries);
}

View File

@@ -446,7 +446,7 @@ export class ViewManager {
}
};
sendToAllViews = (channel: string, ...args: any[]) => {
sendToAllViews = (channel: string, ...args: unknown[]) => {
this.views.forEach((view) => view.view.webContents.send(channel, ...args));
}
}

View File

@@ -126,7 +126,7 @@ const generateNewWindowListener = (getServersFunction: () => TeamWithTabs[], spe
}
// Public download links case
// TODO: We might be handling different types differently in the future, for now
// We might be handling different types differently in the future, for now
// we are going to mimic the browser and just pop a new browser window for public links
if (parsedURL.pathname.match(/^(\/api\/v[3-4]\/public)*\/files\//)) {
shell.openExternal(details.url);
@@ -218,7 +218,7 @@ export const addWebContentsEventListeners = (mmview: MattermostView, getServersF
}
const willNavigate = generateWillNavigate(getServersFunction);
contents.on('will-navigate', willNavigate as (e: Event, u: string) => void); // TODO: Electron types don't include sender for some reason
contents.on('will-navigate', willNavigate as (e: Event, u: string) => void); // Electron types don't include sender for some reason
// handle custom login requests (oath, saml):
// 1. are we navigating to a supported local custom login path from the `/login` page?

View File

@@ -150,8 +150,6 @@ export function getMainWindow(ensureCreated?: boolean) {
return status.mainWindow;
}
export const on = status.mainWindow?.on;
function handleMaximizeMainWindow() {
sendToRenderer(MAXIMIZE_CHANGE, true);
}
@@ -204,15 +202,6 @@ export function sendToRenderer(channel: string, ...args: any[]) {
}
}
export function sendToAll(channel: string, ...args: any[]) {
sendToRenderer(channel, ...args);
if (status.settingsWindow) {
status.settingsWindow.webContents.send(channel, ...args);
}
// TODO: should we include popups?
}
export function sendToMattermostViews(channel: string, ...args: any[]) {
if (status.viewManager) {
status.viewManager.sendToAllViews(channel, ...args);
@@ -321,10 +310,6 @@ export async function setOverlayIcon(badgeText: string | undefined, description:
}
}
export function isMainWindow(window: BrowserWindow) {
return status.mainWindow && status.mainWindow === window;
}
export function handleDoubleClick(e: IpcMainEvent, windowType?: string) {
let action = 'Maximize';
if (process.platform === 'darwin') {
@@ -446,11 +431,6 @@ export function updateLoadingScreenDarkMode(darkMode: boolean) {
}
}
export function getViewNameByWebContentsId(webContentsId: number) {
const view = status.viewManager?.findViewByWebContent(webContentsId);
return view?.name;
}
export function getServerNameByWebContentsId(webContentsId: number) {
const view = status.viewManager?.findViewByWebContent(webContentsId);
return view?.tab.server.name;
@@ -497,7 +477,7 @@ export function sendToFind() {
}
}
export function handleHistory(event: IpcMainEvent, offset: number) {
function handleHistory(event: IpcMainEvent, offset: number) {
if (status.viewManager) {
const activeView = status.viewManager.getCurrentView();
if (activeView && activeView.view.webContents.canGoToOffset(offset)) {
@@ -606,7 +586,8 @@ function handleAppLoggedOut(event: IpcMainEvent, viewName: string) {
}
function handleGetViewName(event: IpcMainInvokeEvent) {
return getViewNameByWebContentsId(event.sender.id);
const view = status.viewManager?.findViewByWebContent(event.sender.id);
return view?.name;
}
function handleGetWebContentsId(event: IpcMainInvokeEvent) {
return event.sender.id;

View File

@@ -11,7 +11,7 @@ import hello from 'static/sounds/hello.mp3';
import ripple from 'static/sounds/ripple.mp3';
import upstairs from 'static/sounds/upstairs.mp3';
export const DEFAULT_WIN7 = 'Ding';
const DEFAULT_WIN7 = 'Ding';
const notificationSounds = new Map([
[DEFAULT_WIN7, ding],
['Bing', bing],