mirror of
https://github.com/finos/SymphonyElectron.git
synced 2025-02-25 18:55:29 -06:00
Typescript - Optimize protocol handler
This commit is contained in:
parent
152839972e
commit
36213a6a18
@ -5,7 +5,7 @@ import { LocaleType } from '../common/i18n';
|
||||
import { logger } from '../common/logger';
|
||||
import { activityDetection } from './activity-detection';
|
||||
import { config } from './config-handler';
|
||||
import { checkProtocolAction, setProtocolWindow } from './protocol-handler';
|
||||
import { protocolHandler } from './protocol-handler';
|
||||
import { screenSnippet } from './screen-snippet-handler';
|
||||
import { activate, handleKeyPress } from './window-actions';
|
||||
import { windowHandler } from './window-handler';
|
||||
@ -44,8 +44,7 @@ ipcMain.on(apiName.symphonyApi, (event: Electron.Event, arg: IApiArgs) => {
|
||||
}
|
||||
break;
|
||||
case apiCmds.registerProtocolHandler:
|
||||
setProtocolWindow(event.sender);
|
||||
checkProtocolAction();
|
||||
protocolHandler.setPreloadWebContents(event.sender);
|
||||
break;
|
||||
case apiCmds.badgeDataUrl:
|
||||
if (typeof arg.dataUrl === 'string' && typeof arg.count === 'number') {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { app } from 'electron';
|
||||
|
||||
import { buildNumber, clientVersion, version } from '../../package.json';
|
||||
import { isDevEnv, isMac } from '../common/env';
|
||||
import { logger } from '../common/logger';
|
||||
import { getCommandLineArgs } from '../common/utils';
|
||||
@ -9,11 +10,20 @@ import { setChromeFlags } from './chrome-flags';
|
||||
import { config } from './config-handler';
|
||||
import './dialog-handler';
|
||||
import './main-api-handler';
|
||||
import { protocolHandler } from './protocol-handler';
|
||||
import { SpellChecker } from './spell-check-handler';
|
||||
import { ICustomBrowserWindow, windowHandler } from './window-handler';
|
||||
|
||||
const allowMultiInstance: string | boolean = getCommandLineArgs(process.argv, '--multiInstance', true) || isDevEnv;
|
||||
|
||||
// on windows, we create the protocol handler via the installer
|
||||
// because electron leaves registry traces upon uninstallation
|
||||
if (isMac) {
|
||||
app.setAsDefaultProtocolClient('symphony');
|
||||
// Sets application version info that will be displayed in about app panel
|
||||
app.setAboutPanelOptions({ applicationVersion: `${clientVersion}-${version}`, version: buildNumber });
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function that init the application
|
||||
*/
|
||||
@ -52,7 +62,7 @@ if (!allowMultiInstance) {
|
||||
app.quit();
|
||||
} else {
|
||||
logger.info('Creating the first instance of the application');
|
||||
app.on('second-instance', (_event) => {
|
||||
app.on('second-instance', (_event, argv) => {
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
const mainWindow = windowHandler.getMainWindow();
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
@ -61,7 +71,7 @@ if (!allowMultiInstance) {
|
||||
mainWindow.restore();
|
||||
}
|
||||
mainWindow.focus();
|
||||
// TODO: Handle protocol action
|
||||
protocolHandler.processArgv(argv);
|
||||
}
|
||||
});
|
||||
startApplication();
|
||||
@ -87,6 +97,12 @@ app.on('quit', () => cleanUpAppCache());
|
||||
*/
|
||||
app.on('before-quit', () => windowHandler.willQuitApp = true);
|
||||
|
||||
/**
|
||||
* Is triggered when the application is launched
|
||||
* or clicking the application's dock or taskbar icon
|
||||
*
|
||||
* This event is emitted only on macOS at this moment
|
||||
*/
|
||||
app.on('activate', () => {
|
||||
const mainWindow: ICustomBrowserWindow | null = windowHandler.getMainWindow();
|
||||
if (!mainWindow || mainWindow.isDestroyed()) {
|
||||
@ -94,4 +110,11 @@ app.on('activate', () => {
|
||||
} else {
|
||||
mainWindow.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Validates and Sends protocol action
|
||||
*
|
||||
* This event is emitted only on macOS at this moment
|
||||
*/
|
||||
app.on('open-url', (_event, url) => protocolHandler.sendProtocol(url));
|
@ -1,127 +1,76 @@
|
||||
import * as url from 'url';
|
||||
|
||||
import { isMac } from '../common/env';
|
||||
import { logger } from '../common/logger';
|
||||
import { apiName } from '../common/api-interface';
|
||||
import { isMac, isWindowsOS } from '../common/env';
|
||||
import { getCommandLineArgs } from '../common/utils';
|
||||
import { windowHandler } from './window-handler';
|
||||
import { activate } from './window-actions';
|
||||
|
||||
let protocolWindow: Electron.WebContents;
|
||||
let protocolUrl: string | undefined;
|
||||
enum protocol {
|
||||
SymphonyProtocol = 'symphony://',
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches the protocol uri
|
||||
* @param {String} uri - the uri opened in the format 'symphony://...'
|
||||
*/
|
||||
const setProtocolUrl = (uri: string): void => {
|
||||
logger.info(`Setting the property protocol url to ${uri}`);
|
||||
protocolUrl = uri;
|
||||
};
|
||||
class ProtocolHandler {
|
||||
|
||||
/**
|
||||
* Processes a protocol uri
|
||||
* @param {String} uri - the uri opened in the format 'symphony://abc?def=ghi'
|
||||
*/
|
||||
export const processProtocolUri = (uri: string): void => {
|
||||
private static isValidProtocolUri = (uri: string): boolean => !!(uri && uri.startsWith(protocol.SymphonyProtocol));
|
||||
|
||||
logger.info(`Processing protocol action, uri ${uri}`);
|
||||
if (!protocolWindow) {
|
||||
logger.info(`protocol window not yet initialized, caching the uri ${uri}`);
|
||||
setProtocolUrl(uri);
|
||||
return;
|
||||
private preloadWebContents: Electron.WebContents | null = null;
|
||||
private protocolUri: string | null = null;
|
||||
|
||||
constructor() {
|
||||
this.processArgv();
|
||||
}
|
||||
|
||||
if (uri && uri.startsWith('symphony://')) {
|
||||
logger.info(`triggering the protocol action for the uri ${uri}`);
|
||||
protocolWindow.send('protocol-action', uri);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles a protocol action based on the current state of the app
|
||||
* @param uri
|
||||
* @param isAppAlreadyOpen {Boolean} whether the app is already open
|
||||
*/
|
||||
export const handleProtocolAction = (uri: string, isAppAlreadyOpen: boolean): void => {
|
||||
|
||||
if (!isAppAlreadyOpen) {
|
||||
|
||||
logger.info(`App started by protocol url ${uri}. We are caching this to be processed later!`);
|
||||
|
||||
// app is opened by the protocol url, cache the protocol url to be used later
|
||||
setProtocolUrl(uri);
|
||||
return;
|
||||
}
|
||||
|
||||
// This is needed for mac OS as it brings pop-outs to foreground
|
||||
// (if it has been previously focused) instead of main window
|
||||
if (isMac) {
|
||||
logger.info('Bringing the main window to foreground for focus and processing the protocol url (macOS)');
|
||||
const mainWindow = windowHandler.getMainWindow();
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
// windowMgr.activate(mainWindow.winName);
|
||||
/**
|
||||
* Stores the web contents of the preload
|
||||
*
|
||||
* @param webContents {Electron.WebContents}
|
||||
*/
|
||||
public setPreloadWebContents(webContents: Electron.WebContents): void {
|
||||
this.preloadWebContents = webContents;
|
||||
// check for cashed protocol uri and process it
|
||||
if (this.protocolUri) {
|
||||
this.sendProtocol(this.protocolUri);
|
||||
this.protocolUri = null;
|
||||
}
|
||||
}
|
||||
|
||||
// app is already open, so, just trigger the protocol action method
|
||||
logger.info(`App opened by protocol url ${uri}`);
|
||||
processProtocolUri(uri);
|
||||
};
|
||||
|
||||
/**
|
||||
* Processes protocol action for windows clients
|
||||
* @param argv {Array} an array of command line arguments
|
||||
* @param isAppAlreadyOpen {Boolean} whether the app is already open
|
||||
*/
|
||||
export const processProtocolArgv = (argv: string[], isAppAlreadyOpen: boolean): void => {
|
||||
|
||||
// In case of windows, we need to handle protocol handler
|
||||
// manually because electron doesn't emit
|
||||
// 'open-url' event on windows
|
||||
if (!(process.platform === 'win32')) {
|
||||
logger.info('This is windows, not processing protocol url through arguments');
|
||||
return;
|
||||
}
|
||||
|
||||
const protocolUri = getCommandLineArgs(argv, 'symphony://', false);
|
||||
logger.info(`Trying to process a protocol action for uri ${protocolUri}`);
|
||||
|
||||
if (protocolUri) {
|
||||
const parsedURL = url.parse(protocolUri);
|
||||
if (!parsedURL.protocol || !parsedURL.slashes) {
|
||||
/**
|
||||
* Sends the protocol uri to the web app to further process
|
||||
*
|
||||
* @param uri {String}
|
||||
* @param isAppRunning {Boolean} - whether the application is running
|
||||
*/
|
||||
public sendProtocol(uri: string, isAppRunning: boolean = true): void {
|
||||
if (!this.preloadWebContents || !isAppRunning) {
|
||||
this.protocolUri = uri;
|
||||
return;
|
||||
}
|
||||
logger.info(`Successfully parsed protocol url for ${parsedURL}`);
|
||||
handleProtocolAction(protocolUri, isAppAlreadyOpen);
|
||||
// This is needed for mac OS as it brings pop-outs to foreground
|
||||
// (if it has been previously focused) instead of main window
|
||||
if (isMac) activate(apiName.mainWindowName);
|
||||
|
||||
if (ProtocolHandler.isValidProtocolUri(uri)) {
|
||||
this.preloadWebContents.send('protocol-action', uri);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the protocol window
|
||||
* @param {Object} win - the renderer window
|
||||
*/
|
||||
export const setProtocolWindow = (win: Electron.WebContents): void => {
|
||||
logger.info(`Setting protocol window ${win}`);
|
||||
protocolWindow = win;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks to see if the app was opened by a uri
|
||||
*/
|
||||
export const checkProtocolAction = (): void => {
|
||||
logger.info('Checking if we have a cached protocol url');
|
||||
if (protocolUrl) {
|
||||
logger.info(`Found a cached protocol url (${protocolUrl}), processing it`);
|
||||
processProtocolUri(protocolUrl);
|
||||
logger.info('Resetting the protocol url to undefined post processing it');
|
||||
protocolUrl = undefined;
|
||||
/**
|
||||
* Handles protocol uri from process.argv
|
||||
*
|
||||
* @param argv {String[]} - data received from process.argv
|
||||
*/
|
||||
public processArgv(argv?: string[]): void {
|
||||
const protocolUriFromArgv = getCommandLineArgs(argv || process.argv, protocol.SymphonyProtocol, false);
|
||||
if (isWindowsOS && protocolUriFromArgv) {
|
||||
const parsedURL = url.parse(protocolUriFromArgv);
|
||||
if (!parsedURL.protocol || !parsedURL.slashes) {
|
||||
return;
|
||||
}
|
||||
this.sendProtocol(protocolUriFromArgv, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the protocol url set against an instance
|
||||
* @returns {*}
|
||||
*/
|
||||
export const getProtocolUrl = (): string | undefined => {
|
||||
logger.info(`Getting the property protocol url ${protocolUrl}`);
|
||||
return protocolUrl;
|
||||
};
|
||||
const protocolHandler = new ProtocolHandler();
|
||||
|
||||
export { protocolHandler };
|
@ -22,7 +22,7 @@ interface IClientLogMsg {
|
||||
|
||||
const MAX_LOG_QUEUE_LENGTH = 100;
|
||||
|
||||
export class Logger {
|
||||
class Logger {
|
||||
private readonly showInConsole: boolean = false;
|
||||
private readonly desiredLogLevel?: LogLevel;
|
||||
private readonly logQueue: ILogMsg[];
|
||||
|
Loading…
Reference in New Issue
Block a user