Handling Cli args to support passing URLs to open via cli

This commit is contained in:
Manoj Vivek 2023-01-22 11:19:34 +05:30
parent 4e059de740
commit 0cb6907676
8 changed files with 175 additions and 21 deletions

View file

@ -1 +1,2 @@
declare module '*.mp3'; declare module '*.mp3';
declare module 'electron-args';

View file

@ -109,6 +109,7 @@
"bluebird": "^3.7.2", "bluebird": "^3.7.2",
"browser-sync": "^2.27.10", "browser-sync": "^2.27.10",
"classnames": "^2.3.1", "classnames": "^2.3.1",
"electron-args": "^0.1.0",
"electron-debug": "^3.2.0", "electron-debug": "^3.2.0",
"electron-log": "^4.4.8", "electron-log": "^4.4.8",
"electron-store": "^8.0.2", "electron-store": "^8.0.2",

View file

@ -14,6 +14,10 @@ export const PREVIEW_LAYOUTS = {
export type PreviewLayout = export type PreviewLayout =
typeof PREVIEW_LAYOUTS[keyof typeof PREVIEW_LAYOUTS]; typeof PREVIEW_LAYOUTS[keyof typeof PREVIEW_LAYOUTS];
export interface OpenUrlArgs {
url: string;
}
export const IPC_MAIN_CHANNELS = { export const IPC_MAIN_CHANNELS = {
APP_META: 'app-meta', APP_META: 'app-meta',
PERMISSION_REQUEST: 'permission-request', PERMISSION_REQUEST: 'permission-request',
@ -21,6 +25,7 @@ export const IPC_MAIN_CHANNELS = {
AUTH_REQUEST: 'auth-request', AUTH_REQUEST: 'auth-request',
AUTH_RESPONSE: 'auth-response', AUTH_RESPONSE: 'auth-response',
OPEN_EXTERNAL: 'open-external', OPEN_EXTERNAL: 'open-external',
OPEN_URL: 'open-url',
} as const; } as const;
export type Channels = typeof IPC_MAIN_CHANNELS[keyof typeof IPC_MAIN_CHANNELS]; export type Channels = typeof IPC_MAIN_CHANNELS[keyof typeof IPC_MAIN_CHANNELS];

View file

@ -0,0 +1,36 @@
import parseArgs from 'electron-args';
let binaryName = 'ResponsivelyApp';
if (process.platform === 'darwin') {
binaryName =
'/Applications/ResponsivelyApp.app/Contents/MacOS/ResponsivelyApp';
}
if (process.platform === 'win32') {
binaryName = 'ResponsivelyApp.exe';
}
const cli = parseArgs(
`
ResponsivelyApp
Usage
$ ${binaryName} [path]
Options
--help show help
--version show version
Examples
$ ${binaryName} https://example.com
$ ${binaryName} /path/to/index.html
`,
{
alias: {
h: 'help',
},
}
);
export default cli;

View file

@ -12,9 +12,10 @@ import path from 'path';
import { app, BrowserWindow, shell, ipcMain, screen } from 'electron'; import { app, BrowserWindow, shell, ipcMain, screen } from 'electron';
import { autoUpdater } from 'electron-updater'; import { autoUpdater } from 'electron-updater';
import log from 'electron-log'; import log from 'electron-log';
import cli from './cli';
import { IPC_MAIN_CHANNELS } from '../common/constants'; import { IPC_MAIN_CHANNELS } from '../common/constants';
import MenuBuilder from './menu'; import MenuBuilder from './menu';
import { resolveHtmlPath } from './util'; import { isValidCliArgURL, resolveHtmlPath } from './util';
import { BROWSER_SYNC_HOST, initInstance } from './browser-sync'; import { BROWSER_SYNC_HOST, initInstance } from './browser-sync';
import store from '../store'; import store from '../store';
import { initWebviewContextMenu } from './webview-context-menu/register'; import { initWebviewContextMenu } from './webview-context-menu/register';
@ -102,6 +103,12 @@ const createWindow = async () => {
mainWindow.on('ready-to-show', async () => { mainWindow.on('ready-to-show', async () => {
await initInstance(); await initInstance();
if (isValidCliArgURL(cli.input[0])) {
mainWindow?.webContents.send(IPC_MAIN_CHANNELS.OPEN_URL, {
url: cli.input[0],
});
}
if (!mainWindow) { if (!mainWindow) {
throw new Error('"mainWindow" is not defined'); throw new Error('"mainWindow" is not defined');
} }

View file

@ -11,3 +11,25 @@ export function resolveHtmlPath(htmlFileName: string) {
} }
return `file://${path.resolve(__dirname, '../renderer/', htmlFileName)}`; return `file://${path.resolve(__dirname, '../renderer/', htmlFileName)}`;
} }
export function isValidCliArgURL(arg?: string): boolean {
if (arg == null || arg === '') {
return false;
}
try {
const url = new URL(arg);
if (
url.protocol === 'http:' ||
url.protocol === 'https:' ||
url.protocol === 'file:'
) {
return true;
}
// eslint-disable-next-line no-console
console.warn('Protocol not supported', url.protocol);
} catch (e) {
// eslint-disable-next-line no-console
console.warn('Not a valid URL', arg, e);
}
return false;
}

View file

@ -1,9 +1,15 @@
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import cx from 'classnames'; import cx from 'classnames';
import { IPC_MAIN_CHANNELS } from 'common/constants'; import { IPC_MAIN_CHANNELS, OpenUrlArgs } from 'common/constants';
import { AuthRequestArgs } from 'main/http-basic-auth'; import { AuthRequestArgs } from 'main/http-basic-auth';
import { PermissionRequestArg } from 'main/web-permissions/PermissionsManager'; import { PermissionRequestArg } from 'main/web-permissions/PermissionsManager';
import { KeyboardEventHandler, useEffect, useRef, useState } from 'react'; import {
KeyboardEventHandler,
useCallback,
useEffect,
useRef,
useState,
} from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import Button from 'renderer/components/Button'; import Button from 'renderer/components/Button';
import { webViewPubSub } from 'renderer/lib/pubsub'; import { webViewPubSub } from 'renderer/lib/pubsub';
@ -43,6 +49,25 @@ const AddressBar = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [address]); }, [address]);
const dispatchAddress = useCallback(
(url?: string) => {
let newAddress = url ?? typedAddress;
if (newAddress.indexOf('://') === -1) {
let protocol = 'https://';
if (
typedAddress.indexOf('localhost') !== -1 ||
typedAddress.indexOf('127.0.0.1') !== -1
) {
protocol = 'http://';
}
newAddress = protocol + typedAddress;
}
dispatch(setAddress(newAddress));
},
[dispatch, typedAddress]
);
useEffect(() => { useEffect(() => {
window.electron.ipcRenderer.on<PermissionRequestArg>( window.electron.ipcRenderer.on<PermissionRequestArg>(
IPC_MAIN_CHANNELS.PERMISSION_REQUEST, IPC_MAIN_CHANNELS.PERMISSION_REQUEST,
@ -57,12 +82,25 @@ const AddressBar = () => {
setAuthRequest(args); setAuthRequest(args);
} }
); );
window.electron.ipcRenderer.on<OpenUrlArgs>(
IPC_MAIN_CHANNELS.OPEN_URL,
(args) => {
dispatchAddress(args.url);
}
);
return () => { return () => {
window.electron.ipcRenderer.removeAllListeners( window.electron.ipcRenderer.removeAllListeners(
IPC_MAIN_CHANNELS.PERMISSION_REQUEST IPC_MAIN_CHANNELS.PERMISSION_REQUEST
); );
window.electron.ipcRenderer.removeAllListeners(
IPC_MAIN_CHANNELS.AUTH_REQUEST
);
window.electron.ipcRenderer.removeAllListeners(
IPC_MAIN_CHANNELS.OPEN_URL
);
}; };
}, []); }, [dispatchAddress]);
useEffect(() => { useEffect(() => {
if (homepage !== window.electron.store.get('homepage')) { if (homepage !== window.electron.store.get('homepage')) {
@ -81,22 +119,6 @@ const AddressBar = () => {
setPermissionRequest(null); setPermissionRequest(null);
}; };
const dispatchAddress = (url?: string) => {
let newAddress = url ?? typedAddress;
if (newAddress.indexOf('://') === -1) {
let protocol = 'https://';
if (
typedAddress.indexOf('localhost') !== -1 ||
typedAddress.indexOf('127.0.0.1') !== -1
) {
protocol = 'http://';
}
newAddress = protocol + typedAddress;
}
dispatch(setAddress(newAddress));
};
const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = () => { const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = () => {
if (!isSuggesting) { if (!isSuggesting) {
setIsSuggesting(true); setIsSuggesting(true);

View file

@ -3868,11 +3868,24 @@ camelcase-css@^2.0.1:
resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
camelcase-keys@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-3.0.0.tgz#fc0c6c360363f7377e3793b9a16bccf1070c1ca4"
integrity sha512-U4E6A6aFyYnNW+tDt5/yIUKQURKXe3WMFPfX4FxrQFcwZ/R08AUk1xWcUtlr7oq6CV07Ji+aa69V2g7BSpblnQ==
dependencies:
camelcase "^3.0.0"
map-obj "^1.0.0"
camelcase@^1.2.1: camelcase@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
integrity sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g== integrity sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==
camelcase@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
integrity sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==
camelcase@^5.0.0, camelcase@^5.3.1: camelcase@^5.0.0, camelcase@^5.3.1:
version "5.3.1" version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
@ -4686,7 +4699,15 @@ debug@^3.2.7:
dependencies: dependencies:
ms "^2.1.1" ms "^2.1.1"
decamelize@^1.0.0, decamelize@^1.2.0: decamelize-keys@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8"
integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==
dependencies:
decamelize "^1.1.0"
map-obj "^1.0.0"
decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
@ -5174,6 +5195,17 @@ ejs@^3.1.7:
dependencies: dependencies:
jake "^10.8.5" jake "^10.8.5"
electron-args@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/electron-args/-/electron-args-0.1.0.tgz#90da262798f0a825aa00a2ebe943f2ba3c118f3b"
integrity sha512-CUehTgU4W8QAe+P5YWDORku1+GRMlj5XcUdzvmtmRU3scV84W/+8iJrEVOn/ARhBWlhKvS7i7T3SazLwfSlXAQ==
dependencies:
camelcase-keys "^3.0.0"
decamelize-keys "^1.1.0"
electron-is-dev "^0.1.2"
minimist "^1.2.0"
redent "^2.0.0"
electron-builder@^23.3.3: electron-builder@^23.3.3:
version "23.6.0" version "23.6.0"
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-23.6.0.tgz#c79050cbdce90ed96c5feb67c34e9e0a21b5331b" resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-23.6.0.tgz#c79050cbdce90ed96c5feb67c34e9e0a21b5331b"
@ -5215,6 +5247,11 @@ electron-is-accelerator@^0.1.0:
resolved "https://registry.yarnpkg.com/electron-is-accelerator/-/electron-is-accelerator-0.1.2.tgz#509e510c26a56b55e17f863a4b04e111846ab27b" resolved "https://registry.yarnpkg.com/electron-is-accelerator/-/electron-is-accelerator-0.1.2.tgz#509e510c26a56b55e17f863a4b04e111846ab27b"
integrity sha512-fLGSAjXZtdn1sbtZxx52+krefmtNuVwnJCV2gNiVt735/ARUboMl8jnNC9fZEqQdlAv2ZrETfmBUsoQci5evJA== integrity sha512-fLGSAjXZtdn1sbtZxx52+krefmtNuVwnJCV2gNiVt735/ARUboMl8jnNC9fZEqQdlAv2ZrETfmBUsoQci5evJA==
electron-is-dev@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-0.1.2.tgz#8a1043e32b3a1da1c3f553dce28ce764246167e3"
integrity sha512-T5WJFw6Go4UuTlnmy/4gcDW1jJKQRqGeIzff02K0jbKUwAOuQX1Kt9VWLTE4reVDlXgM5Qp6Mu7CegX/0jhnHw==
electron-is-dev@^1.1.0: electron-is-dev@^1.1.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-1.2.0.tgz#2e5cea0a1b3ccf1c86f577cee77363ef55deb05e" resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-1.2.0.tgz#2e5cea0a1b3ccf1c86f577cee77363ef55deb05e"
@ -7335,6 +7372,11 @@ imurmurhash@^0.1.4:
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
indent-string@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
integrity sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==
indent-string@^4.0.0: indent-string@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
@ -9061,6 +9103,11 @@ map-cache@^0.2.0, map-cache@^0.2.2:
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==
map-obj@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==
map-visit@^1.0.0: map-visit@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
@ -11104,6 +11151,14 @@ rechoir@^0.7.0:
dependencies: dependencies:
resolve "^1.9.0" resolve "^1.9.0"
redent@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa"
integrity sha512-XNwrTx77JQCEMXTeb8movBKuK75MgH0RZkujNuDKCezemx/voapl9i2gCSi8WWm8+ox5ycJi1gxF22fR7c0Ciw==
dependencies:
indent-string "^3.0.0"
strip-indent "^2.0.0"
redent@^3.0.0: redent@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
@ -12344,6 +12399,11 @@ strip-final-newline@^3.0.0:
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd"
integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==
strip-indent@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
integrity sha512-RsSNPLpq6YUL7QYy44RnPVTn/lcVZtb48Uof3X5JLbF4zD/Gs7ZFDv2HWol+leoQN2mT86LAzSshGfkTlSOpsA==
strip-indent@^3.0.0: strip-indent@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"