Enable noImplicitAny and kill off request (#457)
* Enable noImplicitAny * Switch from request to node-fetch * Fix node-fetch via patch-package * Add edge to handler * Pin node-fetch to v2
This commit is contained in:
committed by
GitHub
parent
c74fdb632b
commit
031ee44571
43
src/@types/global.d.ts
vendored
43
src/@types/global.d.ts
vendored
@@ -20,27 +20,26 @@ import AutoLaunch from "auto-launch";
|
||||
|
||||
import { AppLocalization } from "../language-helper";
|
||||
|
||||
// global type extensions need to use var for whatever reason
|
||||
/* eslint-disable no-var */
|
||||
declare global {
|
||||
namespace NodeJS {
|
||||
interface Global {
|
||||
mainWindow: BrowserWindow;
|
||||
appQuitting: boolean;
|
||||
appLocalization: AppLocalization;
|
||||
launcher: AutoLaunch;
|
||||
vectorConfig: Record<string, any>;
|
||||
trayConfig: {
|
||||
// eslint-disable-next-line camelcase
|
||||
icon_path: string;
|
||||
brand: string;
|
||||
};
|
||||
store: Store<{
|
||||
warnBeforeExit?: boolean;
|
||||
minimizeToTray?: boolean;
|
||||
spellCheckerEnabled?: boolean;
|
||||
autoHideMenuBar?: boolean;
|
||||
locale?: string | string[];
|
||||
disableHardwareAcceleration?: boolean;
|
||||
}>;
|
||||
}
|
||||
}
|
||||
var mainWindow: BrowserWindow | null;
|
||||
var appQuitting: boolean;
|
||||
var appLocalization: AppLocalization;
|
||||
var launcher: AutoLaunch;
|
||||
var vectorConfig: Record<string, any>;
|
||||
var trayConfig: {
|
||||
// eslint-disable-next-line camelcase
|
||||
icon_path: string;
|
||||
brand: string;
|
||||
};
|
||||
var store: Store<{
|
||||
warnBeforeExit?: boolean;
|
||||
minimizeToTray?: boolean;
|
||||
spellCheckerEnabled?: boolean;
|
||||
autoHideMenuBar?: boolean;
|
||||
locale?: string | string[];
|
||||
disableHardwareAcceleration?: boolean;
|
||||
}>;
|
||||
}
|
||||
/* eslint-enable no-var */
|
||||
|
||||
@@ -126,6 +126,8 @@ async function tryPaths(name: string, root: string, rawPaths: string[]): Promise
|
||||
throw new Error(`Failed to find ${name} files`);
|
||||
}
|
||||
|
||||
const homeserverProps = ['default_is_url', 'default_hs_url', 'default_server_name', 'default_server_config'] as const;
|
||||
|
||||
// Find the webapp resources and set up things that require them
|
||||
async function setupGlobals(): Promise<void> {
|
||||
// find the webapp asar.
|
||||
@@ -168,12 +170,14 @@ async function setupGlobals(): Promise<void> {
|
||||
// If the local config has a homeserver defined, don't use the homeserver from the build
|
||||
// config. This is to avoid a problem where Riot thinks there are multiple homeservers
|
||||
// defined, and panics as a result.
|
||||
const homeserverProps = ['default_is_url', 'default_hs_url', 'default_server_name', 'default_server_config'];
|
||||
if (Object.keys(localConfig).find(k => homeserverProps.includes(k))) {
|
||||
if (Object.keys(localConfig).find(k => homeserverProps.includes(<any>k))) {
|
||||
// Rip out all the homeserver options from the vector config
|
||||
global.vectorConfig = Object.keys(global.vectorConfig)
|
||||
.filter(k => !homeserverProps.includes(k))
|
||||
.reduce((obj, key) => {obj[key] = global.vectorConfig[key]; return obj;}, {});
|
||||
.filter(k => !homeserverProps.includes(<any>k))
|
||||
.reduce((obj, key) => {
|
||||
obj[key] = global.vectorConfig[key];
|
||||
return obj;
|
||||
}, {} as Omit<Partial<typeof global["vectorConfig"]>, keyof typeof homeserverProps>);
|
||||
}
|
||||
|
||||
global.vectorConfig = Object.assign(global.vectorConfig, localConfig);
|
||||
@@ -244,7 +248,7 @@ const warnBeforeExit = (event: Event, input: Input): void => {
|
||||
const exitShortcutPressed =
|
||||
input.type === 'keyDown' && exitShortcuts.some(shortcutFn => shortcutFn(input, process.platform));
|
||||
|
||||
if (shouldWarnBeforeExit && exitShortcutPressed) {
|
||||
if (shouldWarnBeforeExit && exitShortcutPressed && global.mainWindow) {
|
||||
const shouldCancelCloseRequest = dialog.showMessageBoxSync(global.mainWindow, {
|
||||
type: "question",
|
||||
buttons: [_t("Cancel"), _t("Close %(brand)s", {
|
||||
@@ -338,11 +342,11 @@ app.on('ready', async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const { default: installExt, REACT_DEVELOPER_TOOLS, REACT_PERF } = require('electron-devtools-installer');
|
||||
installExt(REACT_DEVELOPER_TOOLS)
|
||||
.then((name) => console.log(`Added Extension: ${name}`))
|
||||
.catch((err) => console.log('An error occurred: ', err));
|
||||
.then((name: string) => console.log(`Added Extension: ${name}`))
|
||||
.catch((err: unknown) => console.log('An error occurred: ', err));
|
||||
installExt(REACT_PERF)
|
||||
.then((name) => console.log(`Added Extension: ${name}`))
|
||||
.catch((err) => console.log('An error occurred: ', err));
|
||||
.then((name: string) => console.log(`Added Extension: ${name}`))
|
||||
.catch((err: unknown) => console.log('An error occurred: ', err));
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
@@ -446,6 +450,7 @@ app.on('ready', async () => {
|
||||
if (global.store.get('minimizeToTray', true)) tray.create(global.trayConfig);
|
||||
|
||||
global.mainWindow.once('ready-to-show', () => {
|
||||
if (!global.mainWindow) return;
|
||||
mainWindowState.manage(global.mainWindow);
|
||||
|
||||
if (!argv['hidden']) {
|
||||
@@ -469,12 +474,12 @@ app.on('ready', async () => {
|
||||
// behave, eg. Mail.app)
|
||||
e.preventDefault();
|
||||
|
||||
if (global.mainWindow.isFullScreen()) {
|
||||
global.mainWindow.once('leave-full-screen', () => global.mainWindow.hide());
|
||||
if (global.mainWindow?.isFullScreen()) {
|
||||
global.mainWindow.once('leave-full-screen', () => global.mainWindow?.hide());
|
||||
|
||||
global.mainWindow.setFullScreen(false);
|
||||
} else {
|
||||
global.mainWindow.hide();
|
||||
global.mainWindow?.hide();
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -484,9 +489,9 @@ app.on('ready', async () => {
|
||||
if (process.platform === 'win32') {
|
||||
// Handle forward/backward mouse buttons in Windows
|
||||
global.mainWindow.on('app-command', (e, cmd) => {
|
||||
if (cmd === 'browser-backward' && global.mainWindow.webContents.canGoBack()) {
|
||||
if (cmd === 'browser-backward' && global.mainWindow?.webContents.canGoBack()) {
|
||||
global.mainWindow.webContents.goBack();
|
||||
} else if (cmd === 'browser-forward' && global.mainWindow.webContents.canGoForward()) {
|
||||
} else if (cmd === 'browser-forward' && global.mainWindow?.webContents.canGoForward()) {
|
||||
global.mainWindow.webContents.goForward();
|
||||
}
|
||||
});
|
||||
@@ -508,7 +513,7 @@ app.on('window-all-closed', () => {
|
||||
});
|
||||
|
||||
app.on('activate', () => {
|
||||
global.mainWindow.show();
|
||||
global.mainWindow?.show();
|
||||
});
|
||||
|
||||
function beforeQuit(): void {
|
||||
|
||||
@@ -39,7 +39,7 @@ ipcMain.on('loudNotification', function(): void {
|
||||
if (process.platform === 'win32' && global.mainWindow && !global.mainWindow.isFocused() && !focusHandlerAttached) {
|
||||
global.mainWindow.flashFrame(true);
|
||||
global.mainWindow.once('focus', () => {
|
||||
global.mainWindow.flashFrame(false);
|
||||
global.mainWindow?.flashFrame(false);
|
||||
focusHandlerAttached = false;
|
||||
});
|
||||
focusHandlerAttached = true;
|
||||
|
||||
@@ -63,7 +63,7 @@ export function _t(text: string, variables: IVariables = {}): string {
|
||||
|
||||
type Component = () => void;
|
||||
|
||||
type TypedStore = Store<{ locale?: string[] }>;
|
||||
type TypedStore = Store<{ locale?: string | string[] }>;
|
||||
|
||||
export class AppLocalization {
|
||||
private static readonly STORE_KEY = "locale";
|
||||
|
||||
@@ -52,7 +52,7 @@ function processUrl(url: string): void {
|
||||
global.mainWindow.loadURL(urlToLoad.href);
|
||||
}
|
||||
|
||||
function readStore(): object {
|
||||
function readStore(): Record<string, string> {
|
||||
try {
|
||||
const s = fs.readFileSync(storePath, { encoding: "utf8" });
|
||||
const o = JSON.parse(s);
|
||||
@@ -62,7 +62,7 @@ function readStore(): object {
|
||||
}
|
||||
}
|
||||
|
||||
function writeStore(data: object): void {
|
||||
function writeStore(data: Record<string, string>): void {
|
||||
fs.writeFileSync(storePath, JSON.stringify(data));
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ export function recordSSOSession(sessionID: string): void {
|
||||
export function getProfileFromDeeplink(args: string[]): string | undefined {
|
||||
// check if we are passed a profile in the SSO callback url
|
||||
const deeplinkUrl = args.find(arg => arg.startsWith(PROTOCOL + '//'));
|
||||
if (deeplinkUrl && deeplinkUrl.includes(SEARCH_PARAM)) {
|
||||
if (deeplinkUrl?.includes(SEARCH_PARAM)) {
|
||||
const parsedUrl = new URL(deeplinkUrl);
|
||||
if (parsedUrl.protocol === PROTOCOL) {
|
||||
const ssoID = parsedUrl.searchParams.get(SEARCH_PARAM)!;
|
||||
|
||||
@@ -81,15 +81,12 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
// We do this here to ensure we get the path after --profile has been resolved
|
||||
const eventStorePath = path.join(app.getPath('userData'), 'EventStore');
|
||||
|
||||
const sendError = (id, e) => {
|
||||
const sendError = (id: string, e: Error) => {
|
||||
const error = {
|
||||
message: e.message,
|
||||
};
|
||||
|
||||
global.mainWindow.webContents.send('seshatReply', {
|
||||
id: id,
|
||||
error: error,
|
||||
});
|
||||
global.mainWindow?.webContents.send('seshatReply', { id, error });
|
||||
};
|
||||
|
||||
const args = payload.args || [];
|
||||
@@ -138,7 +135,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
|
||||
eventIndex = new Seshat(eventStorePath, { passphrase });
|
||||
} else {
|
||||
sendError(payload.id, e);
|
||||
sendError(payload.id, <Error>e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -153,7 +150,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
await index.shutdown();
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
sendError(payload.id, <Error>e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -182,7 +179,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
eventIndex?.addEvent(args[0], args[1]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
sendError(payload.id, <Error>e);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -191,7 +188,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex?.deleteEvent(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
sendError(payload.id, <Error>e);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -200,7 +197,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex?.commit();
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
sendError(payload.id, <Error>e);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -209,7 +206,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex?.search(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
sendError(payload.id, <Error>e);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -221,7 +218,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
ret = await eventIndex.addHistoricEvents(
|
||||
args[0], args[1], args[2]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
sendError(payload.id, <Error>e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -233,7 +230,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex.getStats();
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
sendError(payload.id, <Error>e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -245,7 +242,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex.removeCrawlerCheckpoint(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
sendError(payload.id, <Error>e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -257,7 +254,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex.addCrawlerCheckpoint(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
sendError(payload.id, <Error>e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -269,7 +266,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex.loadFileEvents(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
sendError(payload.id, <Error>e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -292,7 +289,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
await eventIndex.setUserVersion(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
sendError(payload.id, <Error>e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -304,7 +301,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex.getUserVersion();
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
sendError(payload.id, <Error>e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,12 +44,12 @@ export const Settings: Record<string, Setting> = {
|
||||
},
|
||||
"Electron.alwaysShowMenuBar": { // not supported on macOS
|
||||
async read(): Promise<any> {
|
||||
return !global.mainWindow.autoHideMenuBar;
|
||||
return !global.mainWindow!.autoHideMenuBar;
|
||||
},
|
||||
async write(value: any): Promise<void> {
|
||||
global.store.set('autoHideMenuBar', !value);
|
||||
global.mainWindow.autoHideMenuBar = !value;
|
||||
global.mainWindow.setMenuBarVisibility(value);
|
||||
global.mainWindow!.autoHideMenuBar = !value;
|
||||
global.mainWindow!.setMenuBarVisibility(value);
|
||||
},
|
||||
},
|
||||
"Electron.showTrayIcon": { // not supported on macOS
|
||||
|
||||
18
src/tray.ts
18
src/tray.ts
@@ -36,12 +36,12 @@ export function destroy(): void {
|
||||
}
|
||||
|
||||
function toggleWin(): void {
|
||||
if (global.mainWindow.isVisible() && !global.mainWindow.isMinimized() && global.mainWindow.isFocused()) {
|
||||
if (global.mainWindow?.isVisible() && !global.mainWindow.isMinimized() && global.mainWindow.isFocused()) {
|
||||
global.mainWindow.hide();
|
||||
} else {
|
||||
if (global.mainWindow.isMinimized()) global.mainWindow.restore();
|
||||
if (!global.mainWindow.isVisible()) global.mainWindow.show();
|
||||
global.mainWindow.focus();
|
||||
if (global.mainWindow?.isMinimized()) global.mainWindow.restore();
|
||||
if (!global.mainWindow?.isVisible()) global.mainWindow?.show();
|
||||
global.mainWindow?.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,11 +60,11 @@ export function create(config: IConfig): void {
|
||||
initApplicationMenu();
|
||||
trayIcon.on('click', toggleWin);
|
||||
|
||||
let lastFavicon = null;
|
||||
global.mainWindow.webContents.on('page-favicon-updated', async function(ev, favicons) {
|
||||
let lastFavicon: string | null = null;
|
||||
global.mainWindow?.webContents.on('page-favicon-updated', async function(ev, favicons) {
|
||||
if (!favicons || favicons.length <= 0 || !favicons[0].startsWith('data:')) {
|
||||
if (lastFavicon !== null) {
|
||||
global.mainWindow.setIcon(defaultIcon);
|
||||
global.mainWindow?.setIcon(defaultIcon);
|
||||
trayIcon?.setImage(defaultIcon);
|
||||
lastFavicon = null;
|
||||
}
|
||||
@@ -89,10 +89,10 @@ export function create(config: IConfig): void {
|
||||
}
|
||||
|
||||
trayIcon?.setImage(newFavicon);
|
||||
global.mainWindow.setIcon(newFavicon);
|
||||
global.mainWindow?.setIcon(newFavicon);
|
||||
});
|
||||
|
||||
global.mainWindow.webContents.on('page-title-updated', function(ev, title) {
|
||||
global.mainWindow?.webContents.on('page-title-updated', function(ev, title) {
|
||||
trayIcon?.setToolTip(title);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ export function buildMenuTemplate(): Menu {
|
||||
// in macOS the Preferences menu item goes in the first menu
|
||||
...(!isMac ? [{
|
||||
label: _t('Preferences'),
|
||||
click() { global.mainWindow.webContents.send('preferences'); },
|
||||
click() { global.mainWindow?.webContents.send('preferences'); },
|
||||
}] : []),
|
||||
{
|
||||
role: 'togglefullscreen',
|
||||
@@ -153,7 +153,7 @@ export function buildMenuTemplate(): Menu {
|
||||
{
|
||||
label: _t('Preferences') + '…',
|
||||
accelerator: 'Command+,', // Mac-only accelerator
|
||||
click() { global.mainWindow.webContents.send('preferences'); },
|
||||
click() { global.mainWindow?.webContents.send('preferences'); },
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{
|
||||
|
||||
@@ -31,7 +31,8 @@ import {
|
||||
} from 'electron';
|
||||
import url from 'url';
|
||||
import fs from 'fs';
|
||||
import request from 'request';
|
||||
import fetch from 'node-fetch';
|
||||
import { pipeline } from 'stream';
|
||||
import path from 'path';
|
||||
|
||||
import { _t } from './language-helper';
|
||||
@@ -154,7 +155,10 @@ function onLinkContextMenu(ev: Event, params: ContextMenuParams, webContents: We
|
||||
if (url.startsWith("data:")) {
|
||||
await writeNativeImage(filePath, nativeImage.createFromDataURL(url));
|
||||
} else {
|
||||
request.get(url).pipe(fs.createWriteStream(filePath));
|
||||
const resp = await fetch(url);
|
||||
if (!resp.ok) throw new Error(`unexpected response ${resp.statusText}`);
|
||||
if (!resp.body) throw new Error(`unexpected response has no body ${resp.statusText}`);
|
||||
pipeline(resp.body, fs.createWriteStream(filePath));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
@@ -224,7 +228,7 @@ function cutCopyPasteSelectContextMenus(params: ContextMenuParams): MenuItemCons
|
||||
return options;
|
||||
}
|
||||
|
||||
function onSelectedContextMenu(ev, params) {
|
||||
function onSelectedContextMenu(ev: Event, params: ContextMenuParams) {
|
||||
const items = cutCopyPasteSelectContextMenus(params);
|
||||
const popupMenu = Menu.buildFromTemplate(items);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user