mirror of
https://github.com/CringeStudios/element-desktop.git
synced 2025-01-18 23:44:59 +01:00
parent
d1f488a094
commit
e50e04c507
54
src/@types/keytar.d.ts
vendored
Normal file
54
src/@types/keytar.d.ts
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Based on https://github.com/atom/node-keytar/blob/master/keytar.d.ts because keytar is a hak-dependency and not a normal one
|
||||||
|
// Definitions by: Milan Burda <https://github.com/miniak>, Brendan Forster <https://github.com/shiftkey>, Hari Juturu <https://github.com/juturu>
|
||||||
|
// Adapted from DefinitelyTyped: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/keytar/index.d.ts
|
||||||
|
|
||||||
|
declare module "keytar" {
|
||||||
|
/**
|
||||||
|
* Get the stored password for the service and account.
|
||||||
|
*
|
||||||
|
* @param service The string service name.
|
||||||
|
* @param account The string account name.
|
||||||
|
*
|
||||||
|
* @returns A promise for the password string.
|
||||||
|
*/
|
||||||
|
export function getPassword(service: string, account: string): Promise<string | null>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the password for the service and account to the keychain.
|
||||||
|
*
|
||||||
|
* @param service The string service name.
|
||||||
|
* @param account The string account name.
|
||||||
|
* @param password The string password.
|
||||||
|
*
|
||||||
|
* @returns A promise for the set password completion.
|
||||||
|
*/
|
||||||
|
export function setPassword(service: string, account: string, password: string): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the stored password for the service and account.
|
||||||
|
*
|
||||||
|
* @param service The string service name.
|
||||||
|
* @param account The string account name.
|
||||||
|
*
|
||||||
|
* @returns A promise for the deletion status. True on success.
|
||||||
|
*/
|
||||||
|
export function deletePassword(service: string, account: string): Promise<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a password for the service in the keychain.
|
||||||
|
*
|
||||||
|
* @param service The string service name.
|
||||||
|
*
|
||||||
|
* @returns A promise for the password string.
|
||||||
|
*/
|
||||||
|
export function findPassword(service: string): Promise<string | null>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all accounts and passwords for `service` in the keychain.
|
||||||
|
*
|
||||||
|
* @param service The string service name.
|
||||||
|
*
|
||||||
|
* @returns A promise for the array of found credentials.
|
||||||
|
*/
|
||||||
|
export function findCredentials(service: string): Promise<Array<{ account: string, password: string}>>;
|
||||||
|
}
|
145
src/@types/matrix-seshat.d.ts
vendored
Normal file
145
src/@types/matrix-seshat.d.ts
vendored
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 New Vector Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare module "matrix-seshat" {
|
||||||
|
interface IConfig {
|
||||||
|
language?: string;
|
||||||
|
passphrase?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
interface IMatrixEvent {
|
||||||
|
event_id: string;
|
||||||
|
sender: string;
|
||||||
|
room_id: string;
|
||||||
|
origin_server_ts: number;
|
||||||
|
content: Record<string, any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IMatrixProfile {
|
||||||
|
displayname?: string;
|
||||||
|
avatar_url?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISearchArgs {
|
||||||
|
searchTerm: number;
|
||||||
|
limit: number;
|
||||||
|
before_limit: number;
|
||||||
|
after_limit: number;
|
||||||
|
order_by_recency: boolean;
|
||||||
|
next_batch?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISearchContext {
|
||||||
|
events_before: IMatrixEvent[];
|
||||||
|
events_after: IMatrixEvent[];
|
||||||
|
profile_info: { [userId: string]: IMatrixProfile };
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISearchResult {
|
||||||
|
next_batch: string;
|
||||||
|
count: number;
|
||||||
|
results: Array<{
|
||||||
|
rank: number;
|
||||||
|
result: IMatrixEvent;
|
||||||
|
context: ISearchContext;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
/* eslint-enable camelcase */
|
||||||
|
|
||||||
|
interface ICheckpoint {
|
||||||
|
roomId: string;
|
||||||
|
token: string;
|
||||||
|
fullCrawl: boolean;
|
||||||
|
direction: "b" | "f";
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IDatabaseStats {
|
||||||
|
size: number;
|
||||||
|
eventCount: number;
|
||||||
|
roomCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ILoadArgs {
|
||||||
|
roomId: string;
|
||||||
|
limit: number;
|
||||||
|
fromEvent: string;
|
||||||
|
direction: "b" | "f";
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ILoadResult {
|
||||||
|
event: IMatrixEvent;
|
||||||
|
matrixProfile: IMatrixProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Seshat {
|
||||||
|
constructor(path: string, config?: IConfig);
|
||||||
|
public addEvent(matrixEvent: IMatrixEvent, profile?: IMatrixProfile): void;
|
||||||
|
public deleteEvent(eventId: string): Promise<boolean>;
|
||||||
|
public commit(force?: boolean): Promise<number>;
|
||||||
|
public commitSync(wait?: boolean, force?: boolean): number;
|
||||||
|
public reload(): void;
|
||||||
|
public search(args: ISearchArgs): Promise<ISearchResult>;
|
||||||
|
public searchSync(
|
||||||
|
term: string,
|
||||||
|
limit?: number,
|
||||||
|
beforeLimit?: number,
|
||||||
|
afterLimit?: number,
|
||||||
|
orderByRecency?: boolean,
|
||||||
|
): ISearchResult;
|
||||||
|
public addHistoricEventsSync(
|
||||||
|
events: IMatrixEvent[],
|
||||||
|
newCheckpoint?: ICheckpoint,
|
||||||
|
oldCheckpoint?: ICheckpoint,
|
||||||
|
): boolean;
|
||||||
|
public addHistoricEvents(
|
||||||
|
events: IMatrixEvent[],
|
||||||
|
newCheckpoint?: ICheckpoint,
|
||||||
|
oldCheckpoint?: ICheckpoint,
|
||||||
|
): Promise<boolean>;
|
||||||
|
public addCrawlerCheckpoint(checkpoint: ICheckpoint): Promise<void>;
|
||||||
|
public removeCrawlerCheckpoint(checkpoint: ICheckpoint): Promise<void>;
|
||||||
|
public loadCheckpoints(): Promise<ICheckpoint[]>;
|
||||||
|
public getSize(): Promise<number>;
|
||||||
|
public getStats(): Promise<IDatabaseStats>;
|
||||||
|
public delete(): Promise<void>;
|
||||||
|
public shutdown(): Promise<void>;
|
||||||
|
public changePassphrase(newPassphrase: string): Promise<void>;
|
||||||
|
public isEmpty(): Promise<boolean>;
|
||||||
|
public isRoomIndexed(roomId: string): Promise<boolean>;
|
||||||
|
public getUserVersion(): Promise<number>;
|
||||||
|
public setUserVersion(version: number): Promise<void>;
|
||||||
|
public loadFileEvents(args: ILoadArgs): Promise<ILoadResult[]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IRecoveryInfo {
|
||||||
|
totalEvents: number;
|
||||||
|
reindexedEvents: number;
|
||||||
|
done: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SeshatRecovery {
|
||||||
|
constructor(path: string, config?: IConfig);
|
||||||
|
public info(): IRecoveryInfo;
|
||||||
|
public getUserVersion(): Promise<number>;
|
||||||
|
public shutdown(): Promise<void>;
|
||||||
|
public reindex(): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ReindexError extends Error {
|
||||||
|
constructor(message?: string);
|
||||||
|
}
|
||||||
|
}
|
@ -39,18 +39,26 @@ import crypto from "crypto";
|
|||||||
import { URL } from "url";
|
import { URL } from "url";
|
||||||
import minimist from "minimist";
|
import minimist from "minimist";
|
||||||
|
|
||||||
|
import type * as Keytar from "keytar"; // Hak dependency type
|
||||||
|
import type {
|
||||||
|
Seshat as SeshatType,
|
||||||
|
SeshatRecovery as SeshatRecoveryType,
|
||||||
|
ReindexError as ReindexErrorType,
|
||||||
|
} from "matrix-seshat"; // Hak dependency type
|
||||||
import * as tray from "./tray";
|
import * as tray from "./tray";
|
||||||
import { buildMenuTemplate } from './vectormenu';
|
import { buildMenuTemplate } from './vectormenu';
|
||||||
import webContentsHandler from './webcontents-handler';
|
import webContentsHandler from './webcontents-handler';
|
||||||
import * as updater from './updater';
|
import * as updater from './updater';
|
||||||
import { getProfileFromDeeplink, protocolInit, recordSSOSession } from './protocol';
|
import { getProfileFromDeeplink, protocolInit, recordSSOSession } from './protocol';
|
||||||
import { _t, AppLocalization } from './language-helper';
|
import { _t, AppLocalization } from './language-helper';
|
||||||
|
import Input = Electron.Input;
|
||||||
|
import IpcMainEvent = Electron.IpcMainEvent;
|
||||||
|
|
||||||
const argv = minimist(process.argv, {
|
const argv = minimist(process.argv, {
|
||||||
alias: { help: "h" },
|
alias: { help: "h" },
|
||||||
});
|
});
|
||||||
|
|
||||||
let keytar;
|
let keytar: typeof Keytar;
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
keytar = require('keytar');
|
keytar = require('keytar');
|
||||||
@ -63,9 +71,9 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let seshatSupported = false;
|
let seshatSupported = false;
|
||||||
let Seshat;
|
let Seshat: typeof SeshatType;
|
||||||
let SeshatRecovery;
|
let SeshatRecovery: typeof SeshatRecoveryType;
|
||||||
let ReindexError;
|
let ReindexError: typeof ReindexErrorType;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
@ -84,13 +92,18 @@ try {
|
|||||||
|
|
||||||
// Things we need throughout the file but need to be created
|
// Things we need throughout the file but need to be created
|
||||||
// async to are initialised in setupGlobals()
|
// async to are initialised in setupGlobals()
|
||||||
let asarPath;
|
let asarPath: string;
|
||||||
let resPath;
|
let resPath: string;
|
||||||
let vectorConfig;
|
let iconPath: string;
|
||||||
let iconPath;
|
|
||||||
let trayConfig;
|
let vectorConfig: Record<string, any>;
|
||||||
let launcher;
|
let trayConfig: {
|
||||||
let appLocalization;
|
// eslint-disable-next-line camelcase
|
||||||
|
icon_path: string;
|
||||||
|
brand: string;
|
||||||
|
};
|
||||||
|
let launcher: AutoLaunch;
|
||||||
|
let appLocalization: AppLocalization;
|
||||||
|
|
||||||
if (argv["help"]) {
|
if (argv["help"]) {
|
||||||
console.log("Options:");
|
console.log("Options:");
|
||||||
@ -108,12 +121,12 @@ if (argv["help"]) {
|
|||||||
// Electron creates the user data directory (with just an empty 'Dictionaries' directory...)
|
// Electron creates the user data directory (with just an empty 'Dictionaries' directory...)
|
||||||
// as soon as the app path is set, so pick a random path in it that must exist if it's a
|
// as soon as the app path is set, so pick a random path in it that must exist if it's a
|
||||||
// real user data directory.
|
// real user data directory.
|
||||||
function isRealUserDataDir(d) {
|
function isRealUserDataDir(d: string): boolean {
|
||||||
return fs.existsSync(path.join(d, 'IndexedDB'));
|
return fs.existsSync(path.join(d, 'IndexedDB'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we are passed a profile in the SSO callback url
|
// check if we are passed a profile in the SSO callback url
|
||||||
let userDataPath;
|
let userDataPath: string;
|
||||||
|
|
||||||
const userDataPathInProtocol = getProfileFromDeeplink(argv["_"]);
|
const userDataPathInProtocol = getProfileFromDeeplink(argv["_"]);
|
||||||
if (userDataPathInProtocol) {
|
if (userDataPathInProtocol) {
|
||||||
@ -143,7 +156,7 @@ if (userDataPathInProtocol) {
|
|||||||
}
|
}
|
||||||
app.setPath('userData', userDataPath);
|
app.setPath('userData', userDataPath);
|
||||||
|
|
||||||
async function tryPaths(name, root, rawPaths) {
|
async function tryPaths(name: string, root: string, rawPaths: string[]): Promise<string> {
|
||||||
// Make everything relative to root
|
// Make everything relative to root
|
||||||
const paths = rawPaths.map(p => path.join(root, p));
|
const paths = rawPaths.map(p => path.join(root, p));
|
||||||
|
|
||||||
@ -162,7 +175,7 @@ async function tryPaths(name, root, rawPaths) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find the webapp resources and set up things that require them
|
// Find the webapp resources and set up things that require them
|
||||||
async function setupGlobals() {
|
async function setupGlobals(): Promise<void> {
|
||||||
// find the webapp asar.
|
// find the webapp asar.
|
||||||
asarPath = await tryPaths("webapp", __dirname, [
|
asarPath = await tryPaths("webapp", __dirname, [
|
||||||
// If run from the source checkout, this will be in the directory above
|
// If run from the source checkout, this will be in the directory above
|
||||||
@ -245,9 +258,9 @@ async function setupGlobals() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function moveAutoLauncher() {
|
async function moveAutoLauncher(): Promise<void> {
|
||||||
// Look for an auto-launcher under 'Riot' and if we find one, port it's
|
// Look for an auto-launcher under 'Riot' and if we find one, port it's
|
||||||
// enabled/disbaledp-ness over to the new 'Element' launcher
|
// enabled/disabled-ness over to the new 'Element' launcher
|
||||||
if (!vectorConfig.brand || vectorConfig.brand === 'Element') {
|
if (!vectorConfig.brand || vectorConfig.brand === 'Element') {
|
||||||
const oldLauncher = new AutoLaunch({
|
const oldLauncher = new AutoLaunch({
|
||||||
name: 'Riot',
|
name: 'Riot',
|
||||||
@ -274,18 +287,18 @@ const store = new Store<{
|
|||||||
disableHardwareAcceleration?: boolean;
|
disableHardwareAcceleration?: boolean;
|
||||||
}>({ name: "electron-config" });
|
}>({ name: "electron-config" });
|
||||||
|
|
||||||
let eventIndex = null;
|
let eventIndex: SeshatType = null;
|
||||||
|
|
||||||
let mainWindow = null;
|
let mainWindow: BrowserWindow = null;
|
||||||
global.appQuitting = false;
|
global.appQuitting = false;
|
||||||
|
|
||||||
const exitShortcuts = [
|
const exitShortcuts: Array<(input: Input, platform: string) => boolean> = [
|
||||||
(input, platform) => platform !== 'darwin' && input.alt && input.key.toUpperCase() === 'F4',
|
(input, platform) => platform !== 'darwin' && input.alt && input.key.toUpperCase() === 'F4',
|
||||||
(input, platform) => platform !== 'darwin' && input.control && input.key.toUpperCase() === 'Q',
|
(input, platform) => platform !== 'darwin' && input.control && input.key.toUpperCase() === 'Q',
|
||||||
(input, platform) => platform === 'darwin' && input.meta && input.key.toUpperCase() === 'Q',
|
(input, platform) => platform === 'darwin' && input.meta && input.key.toUpperCase() === 'Q',
|
||||||
];
|
];
|
||||||
|
|
||||||
const warnBeforeExit = (event, input) => {
|
const warnBeforeExit = (event: Event, input: Input): void => {
|
||||||
const shouldWarnBeforeExit = store.get('warnBeforeExit', true);
|
const shouldWarnBeforeExit = store.get('warnBeforeExit', true);
|
||||||
const exitShortcutPressed =
|
const exitShortcutPressed =
|
||||||
input.type === 'keyDown' && exitShortcuts.some(shortcutFn => shortcutFn(input, process.platform));
|
input.type === 'keyDown' && exitShortcuts.some(shortcutFn => shortcutFn(input, process.platform));
|
||||||
@ -305,14 +318,14 @@ const warnBeforeExit = (event, input) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteContents = async (p) => {
|
const deleteContents = async (p: string): Promise<void> => {
|
||||||
for (const entry of await afs.readdir(p)) {
|
for (const entry of await afs.readdir(p)) {
|
||||||
const curPath = path.join(p, entry);
|
const curPath = path.join(p, entry);
|
||||||
await afs.unlink(curPath);
|
await afs.unlink(curPath);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function randomArray(size) {
|
async function randomArray(size: number): Promise<string> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
crypto.randomBytes(size, (err, buf) => {
|
crypto.randomBytes(size, (err, buf) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -330,12 +343,12 @@ async function randomArray(size) {
|
|||||||
// no other way to catch this error).
|
// no other way to catch this error).
|
||||||
// Assuming we generally run from the console when developing,
|
// Assuming we generally run from the console when developing,
|
||||||
// this is far preferable.
|
// this is far preferable.
|
||||||
process.on('uncaughtException', function(error) {
|
process.on('uncaughtException', function(error: Error): void {
|
||||||
console.log('Unhandled exception', error);
|
console.log('Unhandled exception', error);
|
||||||
});
|
});
|
||||||
|
|
||||||
let focusHandlerAttached = false;
|
let focusHandlerAttached = false;
|
||||||
ipcMain.on('setBadgeCount', function(ev, count) {
|
ipcMain.on('setBadgeCount', function(_ev: IpcMainEvent, count: number): void {
|
||||||
if (process.platform !== 'win32') {
|
if (process.platform !== 'win32') {
|
||||||
// only set badgeCount on Mac/Linux, the docs say that only those platforms support it but turns out Electron
|
// only set badgeCount on Mac/Linux, the docs say that only those platforms support it but turns out Electron
|
||||||
// has some Windows support too, and in some Windows environments this leads to two badges rendering atop
|
// has some Windows support too, and in some Windows environments this leads to two badges rendering atop
|
||||||
@ -347,7 +360,7 @@ ipcMain.on('setBadgeCount', function(ev, count) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on('loudNotification', function() {
|
ipcMain.on('loudNotification', function(): void {
|
||||||
if (process.platform === 'win32' && mainWindow && !mainWindow.isFocused() && !focusHandlerAttached) {
|
if (process.platform === 'win32' && mainWindow && !mainWindow.isFocused() && !focusHandlerAttached) {
|
||||||
mainWindow.flashFrame(true);
|
mainWindow.flashFrame(true);
|
||||||
mainWindow.once('focus', () => {
|
mainWindow.once('focus', () => {
|
||||||
@ -358,8 +371,8 @@ ipcMain.on('loudNotification', function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let powerSaveBlockerId = null;
|
let powerSaveBlockerId: number = null;
|
||||||
ipcMain.on('app_onAction', function(ev, payload) {
|
ipcMain.on('app_onAction', function(_ev: IpcMainEvent, payload) {
|
||||||
switch (payload.action) {
|
switch (payload.action) {
|
||||||
case 'call_state':
|
case 'call_state':
|
||||||
if (powerSaveBlockerId !== null && powerSaveBlocker.isStarted(powerSaveBlockerId)) {
|
if (powerSaveBlockerId !== null && powerSaveBlocker.isStarted(powerSaveBlockerId)) {
|
||||||
@ -376,11 +389,11 @@ ipcMain.on('app_onAction', function(ev, payload) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on('ipcCall', async function(ev, payload) {
|
ipcMain.on('ipcCall', async function(_ev: IpcMainEvent, payload) {
|
||||||
if (!mainWindow) return;
|
if (!mainWindow) return;
|
||||||
|
|
||||||
const args = payload.args || [];
|
const args = payload.args || [];
|
||||||
let ret;
|
let ret: any;
|
||||||
|
|
||||||
switch (payload.name) {
|
switch (payload.name) {
|
||||||
case 'getUpdateFeedUrl':
|
case 'getUpdateFeedUrl':
|
||||||
@ -542,7 +555,7 @@ ipcMain.on('ipcCall', async function(ev, payload) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const seshatDefaultPassphrase = "DEFAULT_PASSPHRASE";
|
const seshatDefaultPassphrase = "DEFAULT_PASSPHRASE";
|
||||||
async function getOrCreatePassphrase(key) {
|
async function getOrCreatePassphrase(key: string): Promise<string> {
|
||||||
if (keytar) {
|
if (keytar) {
|
||||||
try {
|
try {
|
||||||
const storedPassphrase = await keytar.getPassword("element.io", key);
|
const storedPassphrase = await keytar.getPassword("element.io", key);
|
||||||
@ -561,7 +574,7 @@ async function getOrCreatePassphrase(key) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ipcMain.on('seshat', async function(ev, payload) {
|
ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||||
if (!mainWindow) return;
|
if (!mainWindow) return;
|
||||||
|
|
||||||
const sendError = (id, e) => {
|
const sendError = (id, e) => {
|
||||||
@ -576,7 +589,7 @@ ipcMain.on('seshat', async function(ev, payload) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const args = payload.args || [];
|
const args = payload.args || [];
|
||||||
let ret;
|
let ret: any;
|
||||||
|
|
||||||
switch (payload.name) {
|
switch (payload.name) {
|
||||||
case 'supportsEventIndexing':
|
case 'supportsEventIndexing':
|
||||||
@ -913,7 +926,7 @@ app.on('ready', async () => {
|
|||||||
target[target.length - 1] = 'index.html';
|
target[target.length - 1] = 'index.html';
|
||||||
}
|
}
|
||||||
|
|
||||||
let baseDir;
|
let baseDir: string;
|
||||||
if (target[1] === 'webapp') {
|
if (target[1] === 'webapp') {
|
||||||
baseDir = asarPath;
|
baseDir = asarPath;
|
||||||
} else {
|
} else {
|
||||||
@ -1048,7 +1061,7 @@ app.on('activate', () => {
|
|||||||
mainWindow.show();
|
mainWindow.show();
|
||||||
});
|
});
|
||||||
|
|
||||||
function beforeQuit() {
|
function beforeQuit(): void {
|
||||||
global.appQuitting = true;
|
global.appQuitting = true;
|
||||||
if (mainWindow) {
|
if (mainWindow) {
|
||||||
mainWindow.webContents.send('before-quit');
|
mainWindow.webContents.send('before-quit');
|
||||||
|
@ -80,7 +80,7 @@ export function recordSSOSession(sessionID: string): void {
|
|||||||
writeStore(store);
|
writeStore(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProfileFromDeeplink(args): string | undefined {
|
export function getProfileFromDeeplink(args: string[]): string | undefined {
|
||||||
// check if we are passed a profile in the SSO callback url
|
// check if we are passed a profile in the SSO callback url
|
||||||
const deeplinkUrl = args.find(arg => arg.startsWith(PROTOCOL + '//'));
|
const deeplinkUrl = args.find(arg => arg.startsWith(PROTOCOL + '//'));
|
||||||
if (deeplinkUrl && deeplinkUrl.includes(SEARCH_PARAM)) {
|
if (deeplinkUrl && deeplinkUrl.includes(SEARCH_PARAM)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user