From 8a37b92bc83db229a788008c5a6a68cf51216ed2 Mon Sep 17 00:00:00 2001 From: Vijay Raghavan Aravamudhan Date: Sat, 14 Aug 2021 14:52:24 +0000 Subject: Refactoring: Url helpers (#1789) These changes are mainly to ensure that 'shell.open*' invocations are only in a single file. * Moved 'openPath' into the 'url-helpers' file. * Extract 'openExternalUrl' into a common location in 'url-helpers' This is done so that we can then apply vetting rules to ensure that there is no security concern as described in https://benjamin-altpeter.de/shell-openexternal-dangers/ --- .../settings/settings/EditSettingsForm.js | 8 +- src/components/ui/Link.js | 10 +- src/containers/settings/RecipesScreen.js | 3 +- src/environment.js | 7 - src/helpers/url-helpers.js | 16 ++ .../settings/settings/EditSettingsForm.json | 140 +++++----- src/i18n/messages/src/lib/Menu.json | 292 ++++++++++----------- src/index.js | 9 +- src/lib/Menu.js | 19 +- src/stores/AppStore.js | 12 +- src/webview/contextMenuBuilder.js | 11 +- 11 files changed, 264 insertions(+), 263 deletions(-) (limited to 'src') diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js index 1df8c3527..41580ca78 100644 --- a/src/components/settings/settings/EditSettingsForm.js +++ b/src/components/settings/settings/EditSettingsForm.js @@ -12,11 +12,9 @@ import ToggleRaw from '../../ui/ToggleRaw'; import Select from '../../ui/Select'; import Input from '../../ui/Input'; -import { - FRANZ_TRANSLATION, - GITHUB_FRANZ_URL, -} from '../../../config'; -import { DEFAULT_APP_SETTINGS, ferdiVersion, isMac, isWindows, lockFerdiShortcutKey, openPath, userDataPath, userDataRecipesPath } from '../../../environment'; +import { FRANZ_TRANSLATION, GITHUB_FRANZ_URL } from '../../../config'; +import { DEFAULT_APP_SETTINGS, ferdiVersion, isMac, isWindows, lockFerdiShortcutKey, userDataPath, userDataRecipesPath } from '../../../environment'; +import { openPath } from '../../../helpers/url-helpers'; import globalMessages from '../../../i18n/globalMessages'; const messages = defineMessages({ diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js index fd14b7018..003211e5c 100644 --- a/src/components/ui/Link.js +++ b/src/components/ui/Link.js @@ -1,4 +1,3 @@ -import { shell } from 'electron'; import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { inject, observer } from 'mobx-react'; @@ -7,15 +6,18 @@ import classnames from 'classnames'; import { oneOrManyChildElements } from '../../prop-types'; import { matchRoute } from '../../helpers/routing-helpers'; +import { openExternalUrl } from '../../helpers/url-helpers'; // TODO: create container component for this component export default @inject('stores') @observer class Link extends Component { onClick(e) { - if (this.props.disabled) e.preventDefault(); - else if (this.props.target === '_blank') { + if (this.props.disabled) { e.preventDefault(); - shell.openExternal(this.props.to); + } else if (this.props.target === '_blank') { + e.preventDefault(); + openExternalUrl(this.props.to, true); } + // Note: if neither of the above, then let the other onClick handlers process it } render() { diff --git a/src/containers/settings/RecipesScreen.js b/src/containers/settings/RecipesScreen.js index 526e0a1a9..fa8245c6e 100644 --- a/src/containers/settings/RecipesScreen.js +++ b/src/containers/settings/RecipesScreen.js @@ -12,10 +12,11 @@ import UserStore from '../../stores/UserStore'; import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard'; import ErrorBoundary from '../../components/util/ErrorBoundary'; import { CUSTOM_WEBSITE_RECIPE_ID, FRANZ_DEV_DOCS } from '../../config'; -import { asarRecipesPath, openPath, userDataRecipesPath } from '../../environment'; +import { asarRecipesPath, userDataRecipesPath } from '../../environment'; import { communityRecipesStore } from '../../features/communityRecipes'; import RecipePreview from '../../models/RecipePreview'; import AppStore from '../../stores/AppStore'; +import { openPath } from '../../helpers/url-helpers'; export default @inject('stores', 'actions') @observer class RecipesScreen extends Component { static propTypes = { diff --git a/src/environment.js b/src/environment.js index 6332ad67b..f2a889be4 100644 --- a/src/environment.js +++ b/src/environment.js @@ -1,9 +1,7 @@ import os from 'os'; import { join } from 'path'; -import { ensureDirSync } from 'fs-extra'; import { is, api as electronApi } from 'electron-util'; -import { shell } from 'electron'; import { DEFAULT_ACCENT_COLOR } from '@meetfranz/theme'; @@ -65,11 +63,6 @@ export function asarRecipesPath(...segments) { return join(asarPath(join(__dirname, 'recipes')), ...([segments].flat())); } -export async function openPath(folderName) { - ensureDirSync(folderName); - shell.openPath(folderName); -} - export const useLiveAPI = process.env.USE_LIVE_API; const useLocalAPI = process.env.USE_LOCAL_API; diff --git a/src/helpers/url-helpers.js b/src/helpers/url-helpers.js index 972f9b79a..b0dc9afbb 100644 --- a/src/helpers/url-helpers.js +++ b/src/helpers/url-helpers.js @@ -1,4 +1,8 @@ +// This is taken from: https://benjamin-altpeter.de/shell-openexternal-dangers/ + import { URL } from 'url'; +import { ensureDirSync } from 'fs-extra'; +import { shell } from 'electron'; import { ALLOWED_PROTOCOLS } from '../config'; @@ -18,3 +22,15 @@ export function isValidExternalURL(url) { return isAllowed; } + +export async function openPath(folderName) { + ensureDirSync(folderName); + shell.openPath(folderName); +} + +// TODO: Need to verify and fix/remove the skipping logic. Ideally, we should never skip this check +export function openExternalUrl(url, skipValidityCheck = false) { + if (skipValidityCheck || isValidExternalURL(url)) { + shell.openExternal(url); + } +} diff --git a/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json b/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json index 2b9a00daf..da1581864 100644 --- a/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json +++ b/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Settings", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 23, + "line": 21, "column": 12 }, "end": { - "line": 26, + "line": 24, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!General", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 27, + "line": 25, "column": 19 }, "end": { - "line": 30, + "line": 28, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Sending telemetry data allows us to find errors in Ferdi - we will not send any personal information like your message data!", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 31, + "line": 29, "column": 14 }, "end": { - "line": 34, + "line": 32, "column": 3 } }, @@ -43,11 +43,11 @@ "defaultMessage": "!!!By default, Ferdi will keep all your services open and loaded in the background so they are ready when you want to use them. Service Hibernation will unload your services after a specified amount. This is useful to save RAM or keeping services from slowing down your computer.", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 35, + "line": 33, "column": 17 }, "end": { - "line": 38, + "line": 36, "column": 3 } }, @@ -56,11 +56,11 @@ "defaultMessage": "!!!Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 39, + "line": 37, "column": 22 }, "end": { - "line": 42, + "line": 40, "column": 3 } }, @@ -69,11 +69,11 @@ "defaultMessage": "!!!This server will be used for the \"Franz Todo\" feature. (default: https://app.franztodos.com)", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 43, + "line": 41, "column": 18 }, "end": { - "line": 46, + "line": 44, "column": 3 } }, @@ -82,11 +82,11 @@ "defaultMessage": "!!!Password", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 47, + "line": 45, "column": 18 }, "end": { - "line": 50, + "line": 48, "column": 3 } }, @@ -95,11 +95,11 @@ "defaultMessage": "!!!Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdi.", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 51, + "line": 49, "column": 22 }, "end": { - "line": 54, + "line": 52, "column": 3 } }, @@ -108,11 +108,11 @@ "defaultMessage": "!!!Password Lock allows you to keep your messages protected.\nUsing Password Lock, you will be prompted to enter your password everytime you start Ferdi or lock Ferdi yourself using the lock symbol in the bottom left corner or the shortcut {lockShortcut}.", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 55, + "line": 53, "column": 12 }, "end": { - "line": 58, + "line": 56, "column": 3 } }, @@ -121,11 +121,11 @@ "defaultMessage": "!!!Times in 24-Hour-Format. End time can be before start time (e.g. start 17:00, end 09:00) to enable Do-not-Disturb overnight.", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 59, + "line": 57, "column": 24 }, "end": { - "line": 62, + "line": 60, "column": 3 } }, @@ -134,11 +134,11 @@ "defaultMessage": "!!!Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 63, + "line": 61, "column": 20 }, "end": { - "line": 66, + "line": 64, "column": 3 } }, @@ -147,11 +147,11 @@ "defaultMessage": "!!!Language", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 67, + "line": 65, "column": 20 }, "end": { - "line": 70, + "line": 68, "column": 3 } }, @@ -160,11 +160,11 @@ "defaultMessage": "!!!Updates", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 71, + "line": 69, "column": 19 }, "end": { - "line": 74, + "line": 72, "column": 3 } }, @@ -173,11 +173,11 @@ "defaultMessage": "!!!Appearance", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 75, + "line": 73, "column": 22 }, "end": { - "line": 78, + "line": 76, "column": 3 } }, @@ -186,11 +186,11 @@ "defaultMessage": "!!!Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 79, + "line": 77, "column": 25 }, "end": { - "line": 82, + "line": 80, "column": 3 } }, @@ -199,11 +199,11 @@ "defaultMessage": "!!!Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 83, + "line": 81, "column": 19 }, "end": { - "line": 86, + "line": 84, "column": 3 } }, @@ -212,11 +212,11 @@ "defaultMessage": "!!!Privacy", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 87, + "line": 85, "column": 19 }, "end": { - "line": 90, + "line": 88, "column": 3 } }, @@ -225,11 +225,11 @@ "defaultMessage": "!!!Advanced", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 91, + "line": 89, "column": 20 }, "end": { - "line": 94, + "line": 92, "column": 3 } }, @@ -238,11 +238,11 @@ "defaultMessage": "!!!Help us to translate Ferdi into your language.", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 95, + "line": 93, "column": 19 }, "end": { - "line": 98, + "line": 96, "column": 3 } }, @@ -251,11 +251,11 @@ "defaultMessage": "!!!Ferdi uses your Mac's build-in spellchecker to check for typos. If you want to change the languages the spellchecker checks for, you can do so in your Mac's System Preferences.", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 99, + "line": 97, "column": 28 }, "end": { - "line": 102, + "line": 100, "column": 3 } }, @@ -264,11 +264,11 @@ "defaultMessage": "!!!Cache", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 103, + "line": 101, "column": 20 }, "end": { - "line": 106, + "line": 104, "column": 3 } }, @@ -277,11 +277,11 @@ "defaultMessage": "!!!Ferdi cache is currently using {size} of disk space.", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 107, + "line": 105, "column": 13 }, "end": { - "line": 110, + "line": 108, "column": 3 } }, @@ -290,11 +290,11 @@ "defaultMessage": "!!!Couldn't clear all cache", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 111, + "line": 109, "column": 19 }, "end": { - "line": 114, + "line": 112, "column": 3 } }, @@ -303,11 +303,11 @@ "defaultMessage": "!!!Clear cache", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 115, + "line": 113, "column": 23 }, "end": { - "line": 118, + "line": 116, "column": 3 } }, @@ -316,11 +316,11 @@ "defaultMessage": "!!!Ferdi Profile", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 119, + "line": 117, "column": 27 }, "end": { - "line": 122, + "line": 120, "column": 3 } }, @@ -329,11 +329,11 @@ "defaultMessage": "!!!Open Profile folder", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 123, + "line": 121, "column": 32 }, "end": { - "line": 126, + "line": 124, "column": 3 } }, @@ -342,11 +342,11 @@ "defaultMessage": "!!!Open Service Recipes folder", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 127, + "line": 125, "column": 39 }, "end": { - "line": 130, + "line": 128, "column": 3 } }, @@ -355,11 +355,11 @@ "defaultMessage": "!!!Check for updates", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 131, + "line": 129, "column": 25 }, "end": { - "line": 134, + "line": 132, "column": 3 } }, @@ -368,11 +368,11 @@ "defaultMessage": "!!!Restart & install update", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 135, + "line": 133, "column": 23 }, "end": { - "line": 138, + "line": 136, "column": 3 } }, @@ -381,11 +381,11 @@ "defaultMessage": "!!!Is searching for update", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 139, + "line": 137, "column": 25 }, "end": { - "line": 142, + "line": 140, "column": 3 } }, @@ -394,11 +394,11 @@ "defaultMessage": "!!!Update available, downloading...", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 143, + "line": 141, "column": 25 }, "end": { - "line": 146, + "line": 144, "column": 3 } }, @@ -407,11 +407,11 @@ "defaultMessage": "!!!You are using the latest version of Ferdi", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 147, + "line": 145, "column": 24 }, "end": { - "line": 150, + "line": 148, "column": 3 } }, @@ -420,11 +420,11 @@ "defaultMessage": "!!!Current version:", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 151, + "line": 149, "column": 18 }, "end": { - "line": 154, + "line": 152, "column": 3 } }, @@ -433,11 +433,11 @@ "defaultMessage": "!!!Changes require restart", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 155, + "line": 153, "column": 22 }, "end": { - "line": 158, + "line": 156, "column": 3 } }, @@ -446,11 +446,11 @@ "defaultMessage": "!!!Official translations are English & German. All other languages are community based translations.", "file": "src/components/settings/settings/EditSettingsForm.js", "start": { - "line": 159, + "line": 157, "column": 22 }, "end": { - "line": 162, + "line": 160, "column": 3 } } diff --git a/src/i18n/messages/src/lib/Menu.json b/src/i18n/messages/src/lib/Menu.json index e8fa0d10b..373c3a64b 100644 --- a/src/i18n/messages/src/lib/Menu.json +++ b/src/i18n/messages/src/lib/Menu.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Edit", "file": "src/lib/Menu.js", "start": { - "line": 20, + "line": 19, "column": 8 }, "end": { - "line": 23, + "line": 22, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!Undo", "file": "src/lib/Menu.js", "start": { - "line": 24, + "line": 23, "column": 8 }, "end": { - "line": 27, + "line": 26, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Redo", "file": "src/lib/Menu.js", "start": { - "line": 28, + "line": 27, "column": 8 }, "end": { - "line": 31, + "line": 30, "column": 3 } }, @@ -43,11 +43,11 @@ "defaultMessage": "!!!Cut", "file": "src/lib/Menu.js", "start": { - "line": 32, + "line": 31, "column": 7 }, "end": { - "line": 35, + "line": 34, "column": 3 } }, @@ -56,11 +56,11 @@ "defaultMessage": "!!!Copy", "file": "src/lib/Menu.js", "start": { - "line": 36, + "line": 35, "column": 8 }, "end": { - "line": 39, + "line": 38, "column": 3 } }, @@ -69,11 +69,11 @@ "defaultMessage": "!!!Paste", "file": "src/lib/Menu.js", "start": { - "line": 40, + "line": 39, "column": 9 }, "end": { - "line": 43, + "line": 42, "column": 3 } }, @@ -82,11 +82,11 @@ "defaultMessage": "!!!Paste And Match Style", "file": "src/lib/Menu.js", "start": { - "line": 44, + "line": 43, "column": 22 }, "end": { - "line": 47, + "line": 46, "column": 3 } }, @@ -95,11 +95,11 @@ "defaultMessage": "!!!Delete", "file": "src/lib/Menu.js", "start": { - "line": 48, + "line": 47, "column": 10 }, "end": { - "line": 51, + "line": 50, "column": 3 } }, @@ -108,11 +108,11 @@ "defaultMessage": "!!!Select All", "file": "src/lib/Menu.js", "start": { - "line": 52, + "line": 51, "column": 13 }, "end": { - "line": 55, + "line": 54, "column": 3 } }, @@ -121,11 +121,11 @@ "defaultMessage": "!!!Find in Page", "file": "src/lib/Menu.js", "start": { - "line": 56, + "line": 55, "column": 14 }, "end": { - "line": 59, + "line": 58, "column": 3 } }, @@ -134,11 +134,11 @@ "defaultMessage": "!!!Speech", "file": "src/lib/Menu.js", "start": { - "line": 60, + "line": 59, "column": 10 }, "end": { - "line": 63, + "line": 62, "column": 3 } }, @@ -147,11 +147,11 @@ "defaultMessage": "!!!Start Speaking", "file": "src/lib/Menu.js", "start": { - "line": 64, + "line": 63, "column": 17 }, "end": { - "line": 67, + "line": 66, "column": 3 } }, @@ -160,11 +160,11 @@ "defaultMessage": "!!!Stop Speaking", "file": "src/lib/Menu.js", "start": { - "line": 68, + "line": 67, "column": 16 }, "end": { - "line": 71, + "line": 70, "column": 3 } }, @@ -173,11 +173,11 @@ "defaultMessage": "!!!Start Dictation", "file": "src/lib/Menu.js", "start": { - "line": 72, + "line": 71, "column": 18 }, "end": { - "line": 75, + "line": 74, "column": 3 } }, @@ -186,11 +186,11 @@ "defaultMessage": "!!!Emoji & Symbols", "file": "src/lib/Menu.js", "start": { - "line": 76, + "line": 75, "column": 16 }, "end": { - "line": 79, + "line": 78, "column": 3 } }, @@ -199,11 +199,11 @@ "defaultMessage": "!!!Open Quick Switch", "file": "src/lib/Menu.js", "start": { - "line": 80, + "line": 79, "column": 19 }, "end": { - "line": 83, + "line": 82, "column": 3 } }, @@ -212,11 +212,11 @@ "defaultMessage": "!!!Back", "file": "src/lib/Menu.js", "start": { - "line": 84, + "line": 83, "column": 8 }, "end": { - "line": 87, + "line": 86, "column": 3 } }, @@ -225,11 +225,11 @@ "defaultMessage": "!!!Forward", "file": "src/lib/Menu.js", "start": { - "line": 88, + "line": 87, "column": 11 }, "end": { - "line": 91, + "line": 90, "column": 3 } }, @@ -238,11 +238,11 @@ "defaultMessage": "!!!Actual Size", "file": "src/lib/Menu.js", "start": { - "line": 92, + "line": 91, "column": 13 }, "end": { - "line": 95, + "line": 94, "column": 3 } }, @@ -251,11 +251,11 @@ "defaultMessage": "!!!Zoom In", "file": "src/lib/Menu.js", "start": { - "line": 96, + "line": 95, "column": 10 }, "end": { - "line": 99, + "line": 98, "column": 3 } }, @@ -264,11 +264,11 @@ "defaultMessage": "!!!Zoom Out", "file": "src/lib/Menu.js", "start": { - "line": 100, + "line": 99, "column": 11 }, "end": { - "line": 103, + "line": 102, "column": 3 } }, @@ -277,11 +277,11 @@ "defaultMessage": "!!!Toggle Full Screen", "file": "src/lib/Menu.js", "start": { - "line": 104, + "line": 103, "column": 20 }, "end": { - "line": 107, + "line": 106, "column": 3 } }, @@ -290,11 +290,11 @@ "defaultMessage": "!!!Toggle Dark Mode", "file": "src/lib/Menu.js", "start": { - "line": 108, + "line": 107, "column": 18 }, "end": { - "line": 111, + "line": 110, "column": 3 } }, @@ -303,11 +303,11 @@ "defaultMessage": "!!!Toggle Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 112, + "line": 111, "column": 18 }, "end": { - "line": 115, + "line": 114, "column": 3 } }, @@ -316,11 +316,11 @@ "defaultMessage": "!!!Toggle Todos Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 116, + "line": 115, "column": 23 }, "end": { - "line": 119, + "line": 118, "column": 3 } }, @@ -329,11 +329,11 @@ "defaultMessage": "!!!Toggle Service Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 120, + "line": 119, "column": 25 }, "end": { - "line": 123, + "line": 122, "column": 3 } }, @@ -342,11 +342,11 @@ "defaultMessage": "!!!Reload Service", "file": "src/lib/Menu.js", "start": { - "line": 124, + "line": 123, "column": 17 }, "end": { - "line": 127, + "line": 126, "column": 3 } }, @@ -355,11 +355,11 @@ "defaultMessage": "!!!Reload Ferdi", "file": "src/lib/Menu.js", "start": { - "line": 128, + "line": 127, "column": 15 }, "end": { - "line": 131, + "line": 130, "column": 3 } }, @@ -368,11 +368,11 @@ "defaultMessage": "!!!Lock Ferdi", "file": "src/lib/Menu.js", "start": { - "line": 132, + "line": 131, "column": 13 }, "end": { - "line": 135, + "line": 134, "column": 3 } }, @@ -381,11 +381,11 @@ "defaultMessage": "!!!Reload ToDos", "file": "src/lib/Menu.js", "start": { - "line": 136, + "line": 135, "column": 15 }, "end": { - "line": 139, + "line": 138, "column": 3 } }, @@ -394,11 +394,11 @@ "defaultMessage": "!!!Minimize", "file": "src/lib/Menu.js", "start": { - "line": 140, + "line": 139, "column": 12 }, "end": { - "line": 143, + "line": 142, "column": 3 } }, @@ -407,11 +407,11 @@ "defaultMessage": "!!!Close", "file": "src/lib/Menu.js", "start": { - "line": 144, + "line": 143, "column": 9 }, "end": { - "line": 147, + "line": 146, "column": 3 } }, @@ -420,11 +420,11 @@ "defaultMessage": "!!!Learn More", "file": "src/lib/Menu.js", "start": { - "line": 148, + "line": 147, "column": 13 }, "end": { - "line": 151, + "line": 150, "column": 3 } }, @@ -433,11 +433,11 @@ "defaultMessage": "!!!Changelog", "file": "src/lib/Menu.js", "start": { - "line": 152, + "line": 151, "column": 13 }, "end": { - "line": 155, + "line": 154, "column": 3 } }, @@ -446,11 +446,11 @@ "defaultMessage": "!!!Import/Export Configuration Data", "file": "src/lib/Menu.js", "start": { - "line": 156, + "line": 155, "column": 20 }, "end": { - "line": 159, + "line": 158, "column": 3 } }, @@ -459,11 +459,11 @@ "defaultMessage": "!!!Support", "file": "src/lib/Menu.js", "start": { - "line": 160, + "line": 159, "column": 11 }, "end": { - "line": 163, + "line": 162, "column": 3 } }, @@ -472,11 +472,11 @@ "defaultMessage": "!!!Copy Debug Information", "file": "src/lib/Menu.js", "start": { - "line": 164, + "line": 163, "column": 13 }, "end": { - "line": 167, + "line": 166, "column": 3 } }, @@ -485,11 +485,11 @@ "defaultMessage": "!!!Publish Debug Information", "file": "src/lib/Menu.js", "start": { - "line": 168, + "line": 167, "column": 20 }, "end": { - "line": 171, + "line": 170, "column": 3 } }, @@ -498,11 +498,11 @@ "defaultMessage": "!!!Ferdi Debug Information", "file": "src/lib/Menu.js", "start": { - "line": 172, + "line": 171, "column": 27 }, "end": { - "line": 175, + "line": 174, "column": 3 } }, @@ -511,11 +511,11 @@ "defaultMessage": "!!!Your Debug Information has been copied to your clipboard.", "file": "src/lib/Menu.js", "start": { - "line": 176, + "line": 175, "column": 23 }, "end": { - "line": 179, + "line": 178, "column": 3 } }, @@ -524,11 +524,11 @@ "defaultMessage": "!!!Unlock with Touch ID", "file": "src/lib/Menu.js", "start": { - "line": 180, + "line": 179, "column": 11 }, "end": { - "line": 183, + "line": 182, "column": 3 } }, @@ -537,11 +537,11 @@ "defaultMessage": "!!!unlock via Touch ID", "file": "src/lib/Menu.js", "start": { - "line": 184, + "line": 183, "column": 17 }, "end": { - "line": 187, + "line": 186, "column": 3 } }, @@ -550,11 +550,11 @@ "defaultMessage": "!!!Terms of Service", "file": "src/lib/Menu.js", "start": { - "line": 188, + "line": 187, "column": 7 }, "end": { - "line": 191, + "line": 190, "column": 3 } }, @@ -563,11 +563,11 @@ "defaultMessage": "!!!Privacy Statement", "file": "src/lib/Menu.js", "start": { - "line": 192, + "line": 191, "column": 11 }, "end": { - "line": 195, + "line": 194, "column": 3 } }, @@ -576,11 +576,11 @@ "defaultMessage": "!!!File", "file": "src/lib/Menu.js", "start": { - "line": 196, + "line": 195, "column": 8 }, "end": { - "line": 199, + "line": 198, "column": 3 } }, @@ -589,11 +589,11 @@ "defaultMessage": "!!!View", "file": "src/lib/Menu.js", "start": { - "line": 200, + "line": 199, "column": 8 }, "end": { - "line": 203, + "line": 202, "column": 3 } }, @@ -602,11 +602,11 @@ "defaultMessage": "!!!Services", "file": "src/lib/Menu.js", "start": { - "line": 204, + "line": 203, "column": 12 }, "end": { - "line": 207, + "line": 206, "column": 3 } }, @@ -615,11 +615,11 @@ "defaultMessage": "!!!Window", "file": "src/lib/Menu.js", "start": { - "line": 208, + "line": 207, "column": 10 }, "end": { - "line": 211, + "line": 210, "column": 3 } }, @@ -628,11 +628,11 @@ "defaultMessage": "!!!Help", "file": "src/lib/Menu.js", "start": { - "line": 212, + "line": 211, "column": 8 }, "end": { - "line": 215, + "line": 214, "column": 3 } }, @@ -641,11 +641,11 @@ "defaultMessage": "!!!About Ferdi", "file": "src/lib/Menu.js", "start": { - "line": 216, + "line": 215, "column": 9 }, "end": { - "line": 219, + "line": 218, "column": 3 } }, @@ -654,11 +654,11 @@ "defaultMessage": "!!!What's new?", "file": "src/lib/Menu.js", "start": { - "line": 220, + "line": 219, "column": 16 }, "end": { - "line": 223, + "line": 222, "column": 3 } }, @@ -667,11 +667,11 @@ "defaultMessage": "!!!Settings", "file": "src/lib/Menu.js", "start": { - "line": 224, + "line": 223, "column": 12 }, "end": { - "line": 227, + "line": 226, "column": 3 } }, @@ -680,11 +680,11 @@ "defaultMessage": "!!!Check for updates", "file": "src/lib/Menu.js", "start": { - "line": 228, + "line": 227, "column": 19 }, "end": { - "line": 231, + "line": 230, "column": 3 } }, @@ -693,11 +693,11 @@ "defaultMessage": "!!!Hide", "file": "src/lib/Menu.js", "start": { - "line": 232, + "line": 231, "column": 8 }, "end": { - "line": 235, + "line": 234, "column": 3 } }, @@ -706,11 +706,11 @@ "defaultMessage": "!!!Hide Others", "file": "src/lib/Menu.js", "start": { - "line": 236, + "line": 235, "column": 14 }, "end": { - "line": 239, + "line": 238, "column": 3 } }, @@ -719,11 +719,11 @@ "defaultMessage": "!!!Unhide", "file": "src/lib/Menu.js", "start": { - "line": 240, + "line": 239, "column": 10 }, "end": { - "line": 243, + "line": 242, "column": 3 } }, @@ -732,11 +732,11 @@ "defaultMessage": "!!!Auto-hide menu bar", "file": "src/lib/Menu.js", "start": { - "line": 244, + "line": 243, "column": 19 }, "end": { - "line": 247, + "line": 246, "column": 3 } }, @@ -745,11 +745,11 @@ "defaultMessage": "!!!Quit", "file": "src/lib/Menu.js", "start": { - "line": 248, + "line": 247, "column": 8 }, "end": { - "line": 251, + "line": 250, "column": 3 } }, @@ -758,11 +758,11 @@ "defaultMessage": "!!!Add New Service...", "file": "src/lib/Menu.js", "start": { - "line": 252, + "line": 251, "column": 17 }, "end": { - "line": 255, + "line": 254, "column": 3 } }, @@ -771,11 +771,11 @@ "defaultMessage": "!!!Add New Workspace...", "file": "src/lib/Menu.js", "start": { - "line": 256, + "line": 255, "column": 19 }, "end": { - "line": 259, + "line": 258, "column": 3 } }, @@ -784,11 +784,11 @@ "defaultMessage": "!!!Open workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 260, + "line": 259, "column": 23 }, "end": { - "line": 263, + "line": 262, "column": 3 } }, @@ -797,11 +797,11 @@ "defaultMessage": "!!!Close workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 264, + "line": 263, "column": 24 }, "end": { - "line": 267, + "line": 266, "column": 3 } }, @@ -810,11 +810,11 @@ "defaultMessage": "!!!Activate next service...", "file": "src/lib/Menu.js", "start": { - "line": 268, + "line": 267, "column": 23 }, "end": { - "line": 271, + "line": 270, "column": 3 } }, @@ -823,11 +823,11 @@ "defaultMessage": "!!!Activate previous service...", "file": "src/lib/Menu.js", "start": { - "line": 272, + "line": 271, "column": 27 }, "end": { - "line": 275, + "line": 274, "column": 3 } }, @@ -836,11 +836,11 @@ "defaultMessage": "!!!Disable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 276, + "line": 275, "column": 11 }, "end": { - "line": 279, + "line": 278, "column": 3 } }, @@ -849,11 +849,11 @@ "defaultMessage": "!!!Enable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 280, + "line": 279, "column": 13 }, "end": { - "line": 283, + "line": 282, "column": 3 } }, @@ -862,11 +862,11 @@ "defaultMessage": "!!!Workspaces", "file": "src/lib/Menu.js", "start": { - "line": 284, + "line": 283, "column": 14 }, "end": { - "line": 287, + "line": 286, "column": 3 } }, @@ -875,11 +875,11 @@ "defaultMessage": "!!!Default", "file": "src/lib/Menu.js", "start": { - "line": 288, + "line": 287, "column": 20 }, "end": { - "line": 291, + "line": 290, "column": 3 } }, @@ -888,11 +888,11 @@ "defaultMessage": "!!!Todos", "file": "src/lib/Menu.js", "start": { - "line": 292, + "line": 291, "column": 9 }, "end": { - "line": 295, + "line": 294, "column": 3 } }, @@ -901,11 +901,11 @@ "defaultMessage": "!!!Open Todos drawer", "file": "src/lib/Menu.js", "start": { - "line": 296, + "line": 295, "column": 19 }, "end": { - "line": 299, + "line": 298, "column": 3 } }, @@ -914,11 +914,11 @@ "defaultMessage": "!!!Close Todos drawer", "file": "src/lib/Menu.js", "start": { - "line": 300, + "line": 299, "column": 20 }, "end": { - "line": 303, + "line": 302, "column": 3 } }, @@ -927,11 +927,11 @@ "defaultMessage": "!!!Enable Todos", "file": "src/lib/Menu.js", "start": { - "line": 304, + "line": 303, "column": 15 }, "end": { - "line": 307, + "line": 306, "column": 3 } }, @@ -940,11 +940,11 @@ "defaultMessage": "!!!Home", "file": "src/lib/Menu.js", "start": { - "line": 308, + "line": 307, "column": 17 }, "end": { - "line": 311, + "line": 310, "column": 3 } } diff --git a/src/index.js b/src/index.js index f6573d8f5..563ad08ed 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ /* eslint-disable import/first */ -import { app, BrowserWindow, shell, ipcMain, session } from 'electron'; +import { app, BrowserWindow, ipcMain, session } from 'electron'; import { emptyDirSync, ensureFileSync } from 'fs-extra'; import { join } from 'path'; @@ -34,7 +34,7 @@ import { appId } from './package.json'; // eslint-disable-line import/no-unresol import './electron/exception'; import { asarPath } from './helpers/asar-helpers'; -import { isValidExternalURL } from './helpers/url-helpers'; +import { openExternalUrl } from './helpers/url-helpers'; import userAgent from './helpers/userAgent-helpers'; const debug = require('debug')('Ferdi:App'); @@ -344,10 +344,7 @@ const createWindow = () => { mainWindow.webContents.on('new-window', (e, url) => { debug('Open url', url); e.preventDefault(); - - if (isValidExternalURL(url)) { - shell.openExternal(url); - } + openExternalUrl(url); }); if (settings.get('startMinimized')) { diff --git a/src/lib/Menu.js b/src/lib/Menu.js index e4056e536..d34cfc4e6 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -1,7 +1,5 @@ -import { clipboard, shell } from 'electron'; -import { - app, Menu, dialog, systemPreferences, -} from '@electron/remote'; +import { clipboard } from 'electron'; +import { app, Menu, dialog, systemPreferences } from '@electron/remote'; import { autorun, observable } from 'mobx'; import { defineMessages } from 'react-intl'; import { CUSTOM_WEBSITE_RECIPE_ID, GITHUB_FERDI_URL, LIVE_API_FERDI_WEBSITE } from '../config'; @@ -15,6 +13,7 @@ import { todoActions } from '../features/todos/actions'; import { workspaceActions } from '../features/workspaces/actions'; import { workspaceStore } from '../features/workspaces/index'; import apiBase, { termsBase } from '../api/apiBase'; +import { openExternalUrl } from '../helpers/url-helpers'; const menuItems = defineMessages({ edit: { @@ -514,15 +513,15 @@ const _titleBarTemplateFactory = (intl, locked) => [ submenu: [ { label: intl.formatMessage(menuItems.learnMore), - click() { shell.openExternal(LIVE_API_FERDI_WEBSITE); }, + click() { openExternalUrl(LIVE_API_FERDI_WEBSITE, true); }, }, { label: intl.formatMessage(menuItems.changelog), - click() { shell.openExternal(`${GITHUB_FERDI_URL}/ferdi/blob/master/CHANGELOG.md`); }, + click() { openExternalUrl(`${GITHUB_FERDI_URL}/ferdi/blob/master/CHANGELOG.md`, true); }, }, { label: intl.formatMessage(menuItems.importExportData), - click() { shell.openExternal(apiBase(false)); }, + click() { openExternalUrl(apiBase(false), true); }, enabled: !locked, }, { @@ -540,18 +539,18 @@ const _titleBarTemplateFactory = (intl, locked) => [ }, { label: intl.formatMessage(menuItems.support), - click() { shell.openExternal(`${LIVE_API_FERDI_WEBSITE}/contact`); }, + click() { openExternalUrl(`${LIVE_API_FERDI_WEBSITE}/contact`, true); }, }, { type: 'separator', }, { label: intl.formatMessage(menuItems.tos), - click() { shell.openExternal(`${termsBase()}/terms`); }, + click() { openExternalUrl(`${termsBase()}/terms`, true); }, }, { label: intl.formatMessage(menuItems.privacy), - click() { shell.openExternal(`${termsBase()}/privacy`); }, + click() { openExternalUrl(`${termsBase()}/privacy`, true); }, }, ], }, diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 72ddc2927..9c8cce679 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -1,4 +1,4 @@ -import { ipcRenderer, shell } from 'electron'; +import { ipcRenderer } from 'electron'; import { app, screen, @@ -33,7 +33,7 @@ import { getServiceIdsFromPartitions, removeServicePartitionDirectory, } from '../helpers/service-helpers'; -import { isValidExternalURL } from '../helpers/url-helpers'; +import { openExternalUrl } from '../helpers/url-helpers'; import { sleep } from '../helpers/async-helpers'; const debug = require('debug')('Ferdi:AppStore'); @@ -388,13 +388,9 @@ export default class AppStore extends Store { } } + // Ideally(?) this should be merged with the 'shell-helpers' functionality @action _openExternalUrl({ url }) { - const parsedUrl = new URL(url); - debug('open external url', parsedUrl); - - if (isValidExternalURL(url)) { - shell.openExternal(url); - } + openExternalUrl(new URL(url)); } @action _checkForUpdates() { diff --git a/src/webview/contextMenuBuilder.js b/src/webview/contextMenuBuilder.js index 602ce06f5..126fa4086 100644 --- a/src/webview/contextMenuBuilder.js +++ b/src/webview/contextMenuBuilder.js @@ -6,13 +6,12 @@ * * Source: https://github.com/electron-userland/electron-spellchecker/blob/master/src/context-menu-builder.js */ -import { - clipboard, ipcRenderer, nativeImage, shell, -} from 'electron'; +import { clipboard, ipcRenderer, nativeImage } from 'electron'; import { Menu, MenuItem } from '@electron/remote'; import { shortcutKey, isMac } from '../environment'; import { SEARCH_ENGINE_NAMES, SEARCH_ENGINE_URLS } from '../config'; +import { openExternalUrl } from '../helpers/url-helpers'; const { URL } = require('url'); @@ -170,7 +169,7 @@ module.exports = class ContextMenuBuilder { const openLink = new MenuItem({ label: this.stringTable.openLinkUrl(), click: () => { - shell.openExternal(menuInfo.linkURL); + openExternalUrl(menuInfo.linkURL, true); }, }); @@ -299,7 +298,7 @@ module.exports = class ContextMenuBuilder { label: this.stringTable.searchWith({ searchEngine: SEARCH_ENGINE_NAMES[menuInfo.searchEngine] }), click: () => { const url = SEARCH_ENGINE_URLS[menuInfo.searchEngine]({ searchTerm: encodeURIComponent(menuInfo.selectionText) }); - shell.openExternal(url); + openExternalUrl(url, true); }, }); @@ -555,7 +554,7 @@ module.exports = class ContextMenuBuilder { label: this.stringTable.openInBrowser(), enabled: true, click: () => { - shell.openExternal(menuInfo.pageURL); + openExternalUrl(menuInfo.pageURL, true); }, })); -- cgit v1.2.3-54-g00ecf