diff --git a/desktop/flow-typed/npm/electron_v22.0.0.js b/desktop/flow-typed/npm/electron_v22.0.0.js index 155bcce96..3ee002716 100644 --- a/desktop/flow-typed/npm/electron_v22.0.0.js +++ b/desktop/flow-typed/npm/electron_v22.0.0.js @@ -1,513 +1,539 @@ // @flow // flow-typed signature: f8bfa3876f1890f644b65b1ebd801ed8 // flow-typed version: <>/electron_v22.0.0/flow_v0.182.0 declare module 'electron' { declare export var app: App; declare type App = { quit(): void, whenReady(): Promise, hide(): void, show(): void, setName: (name: string) => void, setAppUserModelId: (id: string) => void, getVersion: () => string, + getPath: (name: + | 'home' + | 'appData' + | 'userData' + | 'sessionData' + | 'temp' + | 'exe' + | 'module' + | 'desktop' + | 'documents' + | 'downloads' + | 'music' + | 'pictures' + | 'videos' + | 'recent' + | 'logs' + | 'crashDumps' + ) => string, dock: Dock, isPackaged: boolean, name: string, on: >( event: T, listener: $ElementType, ) => void, removeListener: >( event: T, listener: $ElementType, ) => void, }; declare type AppEvents = { 'window-all-closed': () => void, 'activate': (event: Event, hasVisibleWindows: boolean) => void, 'quit': (event: Event, exitCode: number) => void, 'render-process-gone': ( event: Event, webContents: WebContents, details: { reason: string, exitCode: number, }, ) => void, 'child-process-gone': ( event: Event, details: { type: string, reason: string, exitCode: number, serviceName?: string, name?: string, }, ) => void, }; declare export class BrowserWindow { constructor(options?: { +width?: number, +height?: number, +x?: number, +y?: number, +useContentSize?: boolean, +center?: boolean, +minWidth?: number, +minHeight?: number, +maxWidth?: number, +maxHeight?: number, +resizable?: boolean, +movable?: boolean, +minimizable?: boolean, +maximizable?: boolean, +closable?: boolean, +focusable?: boolean, +alwaysOnTop?: boolean, +fullscreen?: boolean, +fullscreenable?: boolean, +simpleFullscreen?: boolean, +skipTaskbar?: boolean, +kiosk?: boolean, +title?: string, +icon?: string, +show?: boolean, +paintWhenInitiallyHidden?: boolean, +frame?: boolean, +parent?: BrowserWindow, +modal?: boolean, +acceptFirstMouse?: boolean, +disableAutoHideCursor?: boolean, +autoHideMenuBar?: boolean, +enableLargerThanScreen?: boolean, +backgroundColor?: string, +hasShadow?: boolean, +opacity?: number, +darkTheme?: boolean, +transparent?: boolean, +type?: string, +visualEffectState?: 'followWindow' | 'active' | 'inactive', +titleBarStyle?: | 'default' | 'hidden' | 'hiddenInset' | 'customButtonsOnHover', +trafficLightPosition?: { +x: number, +y: number }, +roundedCorners?: boolean, +fullscreenWindowTitle?: boolean, +thickFrame?: boolean, +vibrancy?: | 'appearance-based' | 'light' | 'dark' | 'titlebar' | 'selection' | 'menu' | 'popover' | 'sidebar' | 'medium-light' | 'ultra-dark' | 'header' | 'sheet' | 'window' | 'hud' | 'fullscreen-ui' | 'tooltip' | 'content' | 'under-window' | 'under-page', +zoomToPageWidth?: boolean, +tabbingIdentifier?: string, +webPreferences?: { +preload?: string, }, +titleBarOverlay?: | { +color?: string, +symbolColor?: string, +height?: number } | boolean, }): void; destroy(): void; close(): void; show(): void; hide(): void; maximize(): void; unmaximize(): void; isMaximized(): boolean; minimize(): void; loadURL( url: string, options?: { +userAgent?: string, +extraHeaders?: string, +baseURLForDataURL?: string, }, ): Promise; loadFile( filePath: string, options?: { +query?: { [string]: string }, +search?: string, +hash?: string, }, ): Promise; reload(): void; setMenu(menu: Menu | null): void; isDestroyed(): boolean; static getAllWindows(): $ReadOnlyArray; webContents: WebContents; on>( event: T, listener: $ElementType, ): void; removeListener>( event: T, listener: $ElementType, ): void; } declare type BrowserWindowEvents = { close: (event: Event) => void, closed: () => void, }; declare export type Event = { preventDefault: () => void, }; declare export var contextBridge: ContextBridge; declare type ContextBridge = { exposeInMainWorld(apiKey: string, api: mixed): void, }; declare export var autoUpdater: AutoUpdater; declare class AutoUpdater { setFeedURL(options: { +url: string, +headers?: { +[string]: string }, +serverType?: 'json' | 'default', }): void; getFeedURL(): string; checkForUpdates(): void; quitAndInstall(): void; on>( event: T, listener: $ElementType, ): void; removeListener>( event: T, listener: $ElementType, ): void; } declare type AutoUpdaterEvents = { 'error': Error => void, 'checking-for-update': () => void, 'update-available': () => void, 'update-not-available': () => void, 'update-downloaded': ( event: Event, releaseNotes?: string, releaseName: string, releaseDate?: Date, updateURL?: string, ) => void, }; declare class Dock { setBadge(text: string): void; getBadge(): string; hide(): void; show(): Promise; } declare export var ipcMain: IpcMain; declare type IpcMain = { on( channel: string, listener: (event: IpcMainEvent, ...args: $ReadOnlyArray) => mixed, ): void, removeListener( channel: string, listener: (...args: $ReadOnlyArray) => void, ): void, }; declare export type IpcMainEvent = { +processId: number, +frameId: number, returnValue: mixed, +sender: WebContents, +reply: (channel: string, ...args: $ReadOnlyArray) => void, }; declare export var ipcRenderer: IpcRenderer; declare type IpcRenderer = { on( channel: string, listener: (event: IpcRendererEvent, ...args: $ReadOnlyArray) => void, ): void, removeListener( channel: string, listener: (...args: $ReadOnlyArray) => void, ): void, send(channel: string, ...args: $ReadOnlyArray): void, sendSync(channel: string, ...args: $ReadOnlyArray): any, }; declare export type MenuItemConstructorOptions = { click?: () => void, label?: string, submenu?: $ReadOnlyArray, type?: 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio', role?: | 'undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'pasteAndMatchStyle' | 'delete' | 'selectAll' | 'reload' | 'forceReload' | 'toggleDevTools' | 'resetZoom' | 'zoomIn' | 'zoomOut' | 'toggleSpellChecker' | 'togglefullscreen' | 'window' | 'minimize' | 'close' | 'help' | 'about' | 'services' | 'hide' | 'hideOthers' | 'unhide' | 'quit' | 'showSubstitutions' | 'toggleSmartQuotes' | 'toggleSmartDashes' | 'toggleTextReplacement' | 'startSpeaking' | 'stopSpeaking' | 'zoom' | 'front' | 'appMenu' | 'fileMenu' | 'editMenu' | 'viewMenu' | 'shareMenu' | 'recentDocuments' | 'toggleTabBar' | 'selectNextTab' | 'selectPreviousTab' | 'mergeAllWindows' | 'clearRecentDocuments' | 'moveTabToNewWindow' | 'windowMenu', }; declare export class Menu { constructor(): void; static setApplicationMenu(menu: Menu | null): void; static buildFromTemplate( template: $ReadOnlyArray, ): Menu; } declare export var pushNotifications: PushNotifications; declare class PushNotifications { registerForAPNSNotifications(): Promise; unregisterForAPNSNotifications(): void; on>( event: T, listener: $ElementType, ): void; removeListener>( event: T, listener: $ElementType, ): void; } declare type PushNotificationsEvents = { 'received-apns-notification': ( event: Event, userInfo: {+[string]: mixed}, ) => void, }; declare export class Notification { constructor(options?: { +title?: string, +subtitle?: string, +body?: string, +silent?: boolean, +hasReply?: boolean, +timeoutType?: 'default' | 'never', +replyPlaceholder?: string, +sound?: string, +urgency?: 'normal' | 'critical' | 'low', +actions?: NotificationAction[], +closeButtonText?: string, +toastXml?: string, +icon?: string, }): void; static isSupported(): boolean; show(): void; close(): void; +title: string; +subtitle: string; +body: string; +replyPlaceholder: string; +sound: string; +closeButtonText: string; +silent: boolean; +hasReply: boolean; +urgency: 'normal' | 'critical' | 'low'; +timeoutType: 'default' | 'never'; +toastXml: string; on>( event: T, listener: $ElementType, ): void; removeListener>( event: T, listener: $ElementType, ): void; } declare type NotificationEvents = { show: (event: Event) => void, click: (event: Event) => void, close: (event: Event) => void, reply: (event: Event, reply: string) => void, action: (event: Event, index: number) => void, failed: (event: Event, error: string) => void, }; declare export var shell: Shell; declare type Shell = { openExternal( url: string, options?: { +activate?: boolean, +workingDirectory?: string }, ): Promise, }; declare export var systemPreferences: SystemPreferences; declare type SystemPreferences = { getUserDefault>( key: string, type: Type, ): $ElementType, }; + + declare export var dialog: Dialog; + declare type Dialog = { + +showErrorBox: (title: string, content: string) => void; + ... + }; + declare export type UserDefaultTypes = { string: string, boolean: boolean, integer: number, float: number, double: number, url: string, array: Array, dictionary: { [string]: mixed }, }; declare class WebContents { loadURL( url: string, options?: { +userAgent?: string, +extraHeaders?: string, +baseURLForDataURL?: string, }, ): Promise; loadFile( filePath: string, options?: { +query?: { [string]: string }, +search?: string, +hash?: string, }, ): Promise; canGoBack(): boolean; canGoForward(): boolean; clearHistory(): void; insertCSS(css: string, options?: { +cssOrigin?: string }): Promise; setWindowOpenHandler( handler: (details: { +url: string, +frameName: string, +features: string, +disposition: | 'default' | 'foreground-tab' | 'background-tab' | 'new-window' | 'save-to-disk' | 'other', }) => | { +action: 'deny' } | { +action: 'allow', +outlivesOpener?: boolean }, ): void; send(channel: string, ...args: $ReadOnlyArray): void; on>( event: T, listener: $ElementType, ): void; removeListener: >( event: T, listener: $ElementType, ) => void; inspectSharedWorker(): void; } declare type WebContentsEvents = { 'did-finish-load': () => void, 'did-fail-load': ( event: Event, errorCode: number, errorDescription: string, validatedURL: string, isMainFrame: boolean, frameProcessId: number, frameRoutingId: number, ) => void, 'did-navigate-in-page': ( event: Event, url: string, isMainFrame: boolean, frameProcessId: number, frameRoutingId: number, ) => void, }; declare export type IpcRendererEvent = { sender: IpcRenderer, senderId: number, ports: $ReadOnlyArray, }; } declare module 'electron/main' { declare export { app, BrowserWindow, + dialog, shell, Menu, ipcMain, systemPreferences, autoUpdater, pushNotifications, Notification, } from 'electron'; } declare module 'electron/renderer' { declare export { IpcRendererEvent, contextBridge, ipcRenderer, } from 'electron'; } diff --git a/desktop/src/handle-squirrel-event.js b/desktop/src/handle-squirrel-event.js index 1d77655c8..c86289993 100644 --- a/desktop/src/handle-squirrel-event.js +++ b/desktop/src/handle-squirrel-event.js @@ -1,51 +1,64 @@ // @flow import { spawn, execSync } from 'child_process'; -import { app } from 'electron'; +import { app, dialog } from 'electron'; +import fs from 'fs'; import path from 'path'; // Squirrel will start the app with additional flags during installing, // uninstalling and updating so we can for example create or delete shortcuts. // After handling some of these events the app will be closed. If this function // returns false, the app should start normally. export function handleSquirrelEvent(): boolean { if (process.argv.length === 1) { return false; } const updateExe = path.resolve(process.execPath, '..', '..', 'Update.exe'); const commExeName = path.basename(process.execPath); const spawnUpdate = (args: string[]) => { return spawn(updateExe, args, { detached: true }).on('close', app.quit); }; const squirrelEvent = process.argv[1]; + app.setName('Comm'); + switch (squirrelEvent) { case '--squirrel-install': case '--squirrel-updated': execSync( path.resolve(__dirname, '../assets/windows-runtime-installer.exe'), ); spawnUpdate(['--createShortcut', commExeName]); return true; case '--squirrel-uninstall': spawnUpdate(['--removeShortcut', commExeName]); + try { + fs.rmdirSync(app.getPath('userData'), { recursive: true }); + } catch (e) { + dialog.showErrorBox( + 'Failed to remove folder!', + `You might need to manually remove ${app.getPath( + 'userData', + )} folder.`, + ); + } return true; case '--squirrel-obsolete': app.quit(); return true; case '--squirrel-firstrun': return false; } return false; } export function isNormalStartup(): boolean { const squirrelEvent = process.argv[1]; return !squirrelEvent || squirrelEvent === '--squirrel-firstrun'; }