aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Vijay Raghavan Aravamudhan <vraravam@users.noreply.github.com>2021-08-14 14:52:24 +0000
committerLibravatar GitHub <noreply@github.com>2021-08-14 20:22:24 +0530
commit8a37b92bc83db229a788008c5a6a68cf51216ed2 (patch)
tree1929798a3aa4089203668bd2b93dba497363eb5a /src
parentNew Crowdin updates (#1786) (diff)
downloadferdium-app-8a37b92bc83db229a788008c5a6a68cf51216ed2.tar.gz
ferdium-app-8a37b92bc83db229a788008c5a6a68cf51216ed2.tar.zst
ferdium-app-8a37b92bc83db229a788008c5a6a68cf51216ed2.zip
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/
Diffstat (limited to 'src')
-rw-r--r--src/components/settings/settings/EditSettingsForm.js8
-rw-r--r--src/components/ui/Link.js10
-rw-r--r--src/containers/settings/RecipesScreen.js3
-rw-r--r--src/environment.js7
-rw-r--r--src/helpers/url-helpers.js16
-rw-r--r--src/i18n/messages/src/components/settings/settings/EditSettingsForm.json140
-rw-r--r--src/i18n/messages/src/lib/Menu.json292
-rw-r--r--src/index.js9
-rw-r--r--src/lib/Menu.js19
-rw-r--r--src/stores/AppStore.js12
-rw-r--r--src/webview/contextMenuBuilder.js11
11 files changed, 264 insertions, 263 deletions
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';
12import Select from '../../ui/Select'; 12import Select from '../../ui/Select';
13import Input from '../../ui/Input'; 13import Input from '../../ui/Input';
14 14
15import { 15import { FRANZ_TRANSLATION, GITHUB_FRANZ_URL } from '../../../config';
16 FRANZ_TRANSLATION, 16import { DEFAULT_APP_SETTINGS, ferdiVersion, isMac, isWindows, lockFerdiShortcutKey, userDataPath, userDataRecipesPath } from '../../../environment';
17 GITHUB_FRANZ_URL, 17import { openPath } from '../../../helpers/url-helpers';
18} from '../../../config';
19import { DEFAULT_APP_SETTINGS, ferdiVersion, isMac, isWindows, lockFerdiShortcutKey, openPath, userDataPath, userDataRecipesPath } from '../../../environment';
20import globalMessages from '../../../i18n/globalMessages'; 18import globalMessages from '../../../i18n/globalMessages';
21 19
22const messages = defineMessages({ 20const 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 @@
1import { shell } from 'electron';
2import React, { Component } from 'react'; 1import React, { Component } from 'react';
3import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
4import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
@@ -7,15 +6,18 @@ import classnames from 'classnames';
7 6
8import { oneOrManyChildElements } from '../../prop-types'; 7import { oneOrManyChildElements } from '../../prop-types';
9import { matchRoute } from '../../helpers/routing-helpers'; 8import { matchRoute } from '../../helpers/routing-helpers';
9import { openExternalUrl } from '../../helpers/url-helpers';
10 10
11// TODO: create container component for this component 11// TODO: create container component for this component
12export default @inject('stores') @observer class Link extends Component { 12export default @inject('stores') @observer class Link extends Component {
13 onClick(e) { 13 onClick(e) {
14 if (this.props.disabled) e.preventDefault(); 14 if (this.props.disabled) {
15 else if (this.props.target === '_blank') {
16 e.preventDefault(); 15 e.preventDefault();
17 shell.openExternal(this.props.to); 16 } else if (this.props.target === '_blank') {
17 e.preventDefault();
18 openExternalUrl(this.props.to, true);
18 } 19 }
20 // Note: if neither of the above, then let the other onClick handlers process it
19 } 21 }
20 22
21 render() { 23 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';
12import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard'; 12import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard';
13import ErrorBoundary from '../../components/util/ErrorBoundary'; 13import ErrorBoundary from '../../components/util/ErrorBoundary';
14import { CUSTOM_WEBSITE_RECIPE_ID, FRANZ_DEV_DOCS } from '../../config'; 14import { CUSTOM_WEBSITE_RECIPE_ID, FRANZ_DEV_DOCS } from '../../config';
15import { asarRecipesPath, openPath, userDataRecipesPath } from '../../environment'; 15import { asarRecipesPath, userDataRecipesPath } from '../../environment';
16import { communityRecipesStore } from '../../features/communityRecipes'; 16import { communityRecipesStore } from '../../features/communityRecipes';
17import RecipePreview from '../../models/RecipePreview'; 17import RecipePreview from '../../models/RecipePreview';
18import AppStore from '../../stores/AppStore'; 18import AppStore from '../../stores/AppStore';
19import { openPath } from '../../helpers/url-helpers';
19 20
20export default @inject('stores', 'actions') @observer class RecipesScreen extends Component { 21export default @inject('stores', 'actions') @observer class RecipesScreen extends Component {
21 static propTypes = { 22 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 @@
1import os from 'os'; 1import os from 'os';
2import { join } from 'path'; 2import { join } from 'path';
3import { ensureDirSync } from 'fs-extra';
4 3
5import { is, api as electronApi } from 'electron-util'; 4import { is, api as electronApi } from 'electron-util';
6import { shell } from 'electron';
7 5
8import { DEFAULT_ACCENT_COLOR } from '@meetfranz/theme'; 6import { DEFAULT_ACCENT_COLOR } from '@meetfranz/theme';
9 7
@@ -65,11 +63,6 @@ export function asarRecipesPath(...segments) {
65 return join(asarPath(join(__dirname, 'recipes')), ...([segments].flat())); 63 return join(asarPath(join(__dirname, 'recipes')), ...([segments].flat()));
66} 64}
67 65
68export async function openPath(folderName) {
69 ensureDirSync(folderName);
70 shell.openPath(folderName);
71}
72
73export const useLiveAPI = process.env.USE_LIVE_API; 66export const useLiveAPI = process.env.USE_LIVE_API;
74const useLocalAPI = process.env.USE_LOCAL_API; 67const useLocalAPI = process.env.USE_LOCAL_API;
75 68
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 @@
1// This is taken from: https://benjamin-altpeter.de/shell-openexternal-dangers/
2
1import { URL } from 'url'; 3import { URL } from 'url';
4import { ensureDirSync } from 'fs-extra';
5import { shell } from 'electron';
2 6
3import { ALLOWED_PROTOCOLS } from '../config'; 7import { ALLOWED_PROTOCOLS } from '../config';
4 8
@@ -18,3 +22,15 @@ export function isValidExternalURL(url) {
18 22
19 return isAllowed; 23 return isAllowed;
20} 24}
25
26export async function openPath(folderName) {
27 ensureDirSync(folderName);
28 shell.openPath(folderName);
29}
30
31// TODO: Need to verify and fix/remove the skipping logic. Ideally, we should never skip this check
32export function openExternalUrl(url, skipValidityCheck = false) {
33 if (skipValidityCheck || isValidExternalURL(url)) {
34 shell.openExternal(url);
35 }
36}
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 @@
4 "defaultMessage": "!!!Settings", 4 "defaultMessage": "!!!Settings",
5 "file": "src/components/settings/settings/EditSettingsForm.js", 5 "file": "src/components/settings/settings/EditSettingsForm.js",
6 "start": { 6 "start": {
7 "line": 23, 7 "line": 21,
8 "column": 12 8 "column": 12
9 }, 9 },
10 "end": { 10 "end": {
11 "line": 26, 11 "line": 24,
12 "column": 3 12 "column": 3
13 } 13 }
14 }, 14 },
@@ -17,11 +17,11 @@
17 "defaultMessage": "!!!General", 17 "defaultMessage": "!!!General",
18 "file": "src/components/settings/settings/EditSettingsForm.js", 18 "file": "src/components/settings/settings/EditSettingsForm.js",
19 "start": { 19 "start": {
20 "line": 27, 20 "line": 25,
21 "column": 19 21 "column": 19
22 }, 22 },
23 "end": { 23 "end": {
24 "line": 30, 24 "line": 28,
25 "column": 3 25 "column": 3
26 } 26 }
27 }, 27 },
@@ -30,11 +30,11 @@
30 "defaultMessage": "!!!Sending telemetry data allows us to find errors in Ferdi - we will not send any personal information like your message data!", 30 "defaultMessage": "!!!Sending telemetry data allows us to find errors in Ferdi - we will not send any personal information like your message data!",
31 "file": "src/components/settings/settings/EditSettingsForm.js", 31 "file": "src/components/settings/settings/EditSettingsForm.js",
32 "start": { 32 "start": {
33 "line": 31, 33 "line": 29,
34 "column": 14 34 "column": 14
35 }, 35 },
36 "end": { 36 "end": {
37 "line": 34, 37 "line": 32,
38 "column": 3 38 "column": 3
39 } 39 }
40 }, 40 },
@@ -43,11 +43,11 @@
43 "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.", 43 "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.",
44 "file": "src/components/settings/settings/EditSettingsForm.js", 44 "file": "src/components/settings/settings/EditSettingsForm.js",
45 "start": { 45 "start": {
46 "line": 35, 46 "line": 33,
47 "column": 17 47 "column": 17
48 }, 48 },
49 "end": { 49 "end": {
50 "line": 38, 50 "line": 36,
51 "column": 3 51 "column": 3
52 } 52 }
53 }, 53 },
@@ -56,11 +56,11 @@
56 "defaultMessage": "!!!Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable", 56 "defaultMessage": "!!!Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable",
57 "file": "src/components/settings/settings/EditSettingsForm.js", 57 "file": "src/components/settings/settings/EditSettingsForm.js",
58 "start": { 58 "start": {
59 "line": 39, 59 "line": 37,
60 "column": 22 60 "column": 22
61 }, 61 },
62 "end": { 62 "end": {
63 "line": 42, 63 "line": 40,
64 "column": 3 64 "column": 3
65 } 65 }
66 }, 66 },
@@ -69,11 +69,11 @@
69 "defaultMessage": "!!!This server will be used for the \"Franz Todo\" feature. (default: https://app.franztodos.com)", 69 "defaultMessage": "!!!This server will be used for the \"Franz Todo\" feature. (default: https://app.franztodos.com)",
70 "file": "src/components/settings/settings/EditSettingsForm.js", 70 "file": "src/components/settings/settings/EditSettingsForm.js",
71 "start": { 71 "start": {
72 "line": 43, 72 "line": 41,
73 "column": 18 73 "column": 18
74 }, 74 },
75 "end": { 75 "end": {
76 "line": 46, 76 "line": 44,
77 "column": 3 77 "column": 3
78 } 78 }
79 }, 79 },
@@ -82,11 +82,11 @@
82 "defaultMessage": "!!!Password", 82 "defaultMessage": "!!!Password",
83 "file": "src/components/settings/settings/EditSettingsForm.js", 83 "file": "src/components/settings/settings/EditSettingsForm.js",
84 "start": { 84 "start": {
85 "line": 47, 85 "line": 45,
86 "column": 18 86 "column": 18
87 }, 87 },
88 "end": { 88 "end": {
89 "line": 50, 89 "line": 48,
90 "column": 3 90 "column": 3
91 } 91 }
92 }, 92 },
@@ -95,11 +95,11 @@
95 "defaultMessage": "!!!Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdi.", 95 "defaultMessage": "!!!Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdi.",
96 "file": "src/components/settings/settings/EditSettingsForm.js", 96 "file": "src/components/settings/settings/EditSettingsForm.js",
97 "start": { 97 "start": {
98 "line": 51, 98 "line": 49,
99 "column": 22 99 "column": 22
100 }, 100 },
101 "end": { 101 "end": {
102 "line": 54, 102 "line": 52,
103 "column": 3 103 "column": 3
104 } 104 }
105 }, 105 },
@@ -108,11 +108,11 @@
108 "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}.", 108 "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}.",
109 "file": "src/components/settings/settings/EditSettingsForm.js", 109 "file": "src/components/settings/settings/EditSettingsForm.js",
110 "start": { 110 "start": {
111 "line": 55, 111 "line": 53,
112 "column": 12 112 "column": 12
113 }, 113 },
114 "end": { 114 "end": {
115 "line": 58, 115 "line": 56,
116 "column": 3 116 "column": 3
117 } 117 }
118 }, 118 },
@@ -121,11 +121,11 @@
121 "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.", 121 "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.",
122 "file": "src/components/settings/settings/EditSettingsForm.js", 122 "file": "src/components/settings/settings/EditSettingsForm.js",
123 "start": { 123 "start": {
124 "line": 59, 124 "line": 57,
125 "column": 24 125 "column": 24
126 }, 126 },
127 "end": { 127 "end": {
128 "line": 62, 128 "line": 60,
129 "column": 3 129 "column": 3
130 } 130 }
131 }, 131 },
@@ -134,11 +134,11 @@
134 "defaultMessage": "!!!Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.", 134 "defaultMessage": "!!!Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.",
135 "file": "src/components/settings/settings/EditSettingsForm.js", 135 "file": "src/components/settings/settings/EditSettingsForm.js",
136 "start": { 136 "start": {
137 "line": 63, 137 "line": 61,
138 "column": 20 138 "column": 20
139 }, 139 },
140 "end": { 140 "end": {
141 "line": 66, 141 "line": 64,
142 "column": 3 142 "column": 3
143 } 143 }
144 }, 144 },
@@ -147,11 +147,11 @@
147 "defaultMessage": "!!!Language", 147 "defaultMessage": "!!!Language",
148 "file": "src/components/settings/settings/EditSettingsForm.js", 148 "file": "src/components/settings/settings/EditSettingsForm.js",
149 "start": { 149 "start": {
150 "line": 67, 150 "line": 65,
151 "column": 20 151 "column": 20
152 }, 152 },
153 "end": { 153 "end": {
154 "line": 70, 154 "line": 68,
155 "column": 3 155 "column": 3
156 } 156 }
157 }, 157 },
@@ -160,11 +160,11 @@
160 "defaultMessage": "!!!Updates", 160 "defaultMessage": "!!!Updates",
161 "file": "src/components/settings/settings/EditSettingsForm.js", 161 "file": "src/components/settings/settings/EditSettingsForm.js",
162 "start": { 162 "start": {
163 "line": 71, 163 "line": 69,
164 "column": 19 164 "column": 19
165 }, 165 },
166 "end": { 166 "end": {
167 "line": 74, 167 "line": 72,
168 "column": 3 168 "column": 3
169 } 169 }
170 }, 170 },
@@ -173,11 +173,11 @@
173 "defaultMessage": "!!!Appearance", 173 "defaultMessage": "!!!Appearance",
174 "file": "src/components/settings/settings/EditSettingsForm.js", 174 "file": "src/components/settings/settings/EditSettingsForm.js",
175 "start": { 175 "start": {
176 "line": 75, 176 "line": 73,
177 "column": 22 177 "column": 22
178 }, 178 },
179 "end": { 179 "end": {
180 "line": 78, 180 "line": 76,
181 "column": 3 181 "column": 3
182 } 182 }
183 }, 183 },
@@ -186,11 +186,11 @@
186 "defaultMessage": "!!!Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.", 186 "defaultMessage": "!!!Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.",
187 "file": "src/components/settings/settings/EditSettingsForm.js", 187 "file": "src/components/settings/settings/EditSettingsForm.js",
188 "start": { 188 "start": {
189 "line": 79, 189 "line": 77,
190 "column": 25 190 "column": 25
191 }, 191 },
192 "end": { 192 "end": {
193 "line": 82, 193 "line": 80,
194 "column": 3 194 "column": 3
195 } 195 }
196 }, 196 },
@@ -199,11 +199,11 @@
199 "defaultMessage": "!!!Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})", 199 "defaultMessage": "!!!Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})",
200 "file": "src/components/settings/settings/EditSettingsForm.js", 200 "file": "src/components/settings/settings/EditSettingsForm.js",
201 "start": { 201 "start": {
202 "line": 83, 202 "line": 81,
203 "column": 19 203 "column": 19
204 }, 204 },
205 "end": { 205 "end": {
206 "line": 86, 206 "line": 84,
207 "column": 3 207 "column": 3
208 } 208 }
209 }, 209 },
@@ -212,11 +212,11 @@
212 "defaultMessage": "!!!Privacy", 212 "defaultMessage": "!!!Privacy",
213 "file": "src/components/settings/settings/EditSettingsForm.js", 213 "file": "src/components/settings/settings/EditSettingsForm.js",
214 "start": { 214 "start": {
215 "line": 87, 215 "line": 85,
216 "column": 19 216 "column": 19
217 }, 217 },
218 "end": { 218 "end": {
219 "line": 90, 219 "line": 88,
220 "column": 3 220 "column": 3
221 } 221 }
222 }, 222 },
@@ -225,11 +225,11 @@
225 "defaultMessage": "!!!Advanced", 225 "defaultMessage": "!!!Advanced",
226 "file": "src/components/settings/settings/EditSettingsForm.js", 226 "file": "src/components/settings/settings/EditSettingsForm.js",
227 "start": { 227 "start": {
228 "line": 91, 228 "line": 89,
229 "column": 20 229 "column": 20
230 }, 230 },
231 "end": { 231 "end": {
232 "line": 94, 232 "line": 92,
233 "column": 3 233 "column": 3
234 } 234 }
235 }, 235 },
@@ -238,11 +238,11 @@
238 "defaultMessage": "!!!Help us to translate Ferdi into your language.", 238 "defaultMessage": "!!!Help us to translate Ferdi into your language.",
239 "file": "src/components/settings/settings/EditSettingsForm.js", 239 "file": "src/components/settings/settings/EditSettingsForm.js",
240 "start": { 240 "start": {
241 "line": 95, 241 "line": 93,
242 "column": 19 242 "column": 19
243 }, 243 },
244 "end": { 244 "end": {
245 "line": 98, 245 "line": 96,
246 "column": 3 246 "column": 3
247 } 247 }
248 }, 248 },
@@ -251,11 +251,11 @@
251 "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.", 251 "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.",
252 "file": "src/components/settings/settings/EditSettingsForm.js", 252 "file": "src/components/settings/settings/EditSettingsForm.js",
253 "start": { 253 "start": {
254 "line": 99, 254 "line": 97,
255 "column": 28 255 "column": 28
256 }, 256 },
257 "end": { 257 "end": {
258 "line": 102, 258 "line": 100,
259 "column": 3 259 "column": 3
260 } 260 }
261 }, 261 },
@@ -264,11 +264,11 @@
264 "defaultMessage": "!!!Cache", 264 "defaultMessage": "!!!Cache",
265 "file": "src/components/settings/settings/EditSettingsForm.js", 265 "file": "src/components/settings/settings/EditSettingsForm.js",
266 "start": { 266 "start": {
267 "line": 103, 267 "line": 101,
268 "column": 20 268 "column": 20
269 }, 269 },
270 "end": { 270 "end": {
271 "line": 106, 271 "line": 104,
272 "column": 3 272 "column": 3
273 } 273 }
274 }, 274 },
@@ -277,11 +277,11 @@
277 "defaultMessage": "!!!Ferdi cache is currently using {size} of disk space.", 277 "defaultMessage": "!!!Ferdi cache is currently using {size} of disk space.",
278 "file": "src/components/settings/settings/EditSettingsForm.js", 278 "file": "src/components/settings/settings/EditSettingsForm.js",
279 "start": { 279 "start": {
280 "line": 107, 280 "line": 105,
281 "column": 13 281 "column": 13
282 }, 282 },
283 "end": { 283 "end": {
284 "line": 110, 284 "line": 108,
285 "column": 3 285 "column": 3
286 } 286 }
287 }, 287 },
@@ -290,11 +290,11 @@
290 "defaultMessage": "!!!Couldn't clear all cache", 290 "defaultMessage": "!!!Couldn't clear all cache",
291 "file": "src/components/settings/settings/EditSettingsForm.js", 291 "file": "src/components/settings/settings/EditSettingsForm.js",
292 "start": { 292 "start": {
293 "line": 111, 293 "line": 109,
294 "column": 19 294 "column": 19
295 }, 295 },
296 "end": { 296 "end": {
297 "line": 114, 297 "line": 112,
298 "column": 3 298 "column": 3
299 } 299 }
300 }, 300 },
@@ -303,11 +303,11 @@
303 "defaultMessage": "!!!Clear cache", 303 "defaultMessage": "!!!Clear cache",
304 "file": "src/components/settings/settings/EditSettingsForm.js", 304 "file": "src/components/settings/settings/EditSettingsForm.js",
305 "start": { 305 "start": {
306 "line": 115, 306 "line": 113,
307 "column": 23 307 "column": 23
308 }, 308 },
309 "end": { 309 "end": {
310 "line": 118, 310 "line": 116,
311 "column": 3 311 "column": 3
312 } 312 }
313 }, 313 },
@@ -316,11 +316,11 @@
316 "defaultMessage": "!!!Ferdi Profile", 316 "defaultMessage": "!!!Ferdi Profile",
317 "file": "src/components/settings/settings/EditSettingsForm.js", 317 "file": "src/components/settings/settings/EditSettingsForm.js",
318 "start": { 318 "start": {
319 "line": 119, 319 "line": 117,
320 "column": 27 320 "column": 27
321 }, 321 },
322 "end": { 322 "end": {
323 "line": 122, 323 "line": 120,
324 "column": 3 324 "column": 3
325 } 325 }
326 }, 326 },
@@ -329,11 +329,11 @@
329 "defaultMessage": "!!!Open Profile folder", 329 "defaultMessage": "!!!Open Profile folder",
330 "file": "src/components/settings/settings/EditSettingsForm.js", 330 "file": "src/components/settings/settings/EditSettingsForm.js",
331 "start": { 331 "start": {
332 "line": 123, 332 "line": 121,
333 "column": 32 333 "column": 32
334 }, 334 },
335 "end": { 335 "end": {
336 "line": 126, 336 "line": 124,
337 "column": 3 337 "column": 3
338 } 338 }
339 }, 339 },
@@ -342,11 +342,11 @@
342 "defaultMessage": "!!!Open Service Recipes folder", 342 "defaultMessage": "!!!Open Service Recipes folder",
343 "file": "src/components/settings/settings/EditSettingsForm.js", 343 "file": "src/components/settings/settings/EditSettingsForm.js",
344 "start": { 344 "start": {
345 "line": 127, 345 "line": 125,
346 "column": 39 346 "column": 39
347 }, 347 },
348 "end": { 348 "end": {
349 "line": 130, 349 "line": 128,
350 "column": 3 350 "column": 3
351 } 351 }
352 }, 352 },
@@ -355,11 +355,11 @@
355 "defaultMessage": "!!!Check for updates", 355 "defaultMessage": "!!!Check for updates",
356 "file": "src/components/settings/settings/EditSettingsForm.js", 356 "file": "src/components/settings/settings/EditSettingsForm.js",
357 "start": { 357 "start": {
358 "line": 131, 358 "line": 129,
359 "column": 25 359 "column": 25
360 }, 360 },
361 "end": { 361 "end": {
362 "line": 134, 362 "line": 132,
363 "column": 3 363 "column": 3
364 } 364 }
365 }, 365 },
@@ -368,11 +368,11 @@
368 "defaultMessage": "!!!Restart & install update", 368 "defaultMessage": "!!!Restart & install update",
369 "file": "src/components/settings/settings/EditSettingsForm.js", 369 "file": "src/components/settings/settings/EditSettingsForm.js",
370 "start": { 370 "start": {
371 "line": 135, 371 "line": 133,
372 "column": 23 372 "column": 23
373 }, 373 },
374 "end": { 374 "end": {
375 "line": 138, 375 "line": 136,
376 "column": 3 376 "column": 3
377 } 377 }
378 }, 378 },
@@ -381,11 +381,11 @@
381 "defaultMessage": "!!!Is searching for update", 381 "defaultMessage": "!!!Is searching for update",
382 "file": "src/components/settings/settings/EditSettingsForm.js", 382 "file": "src/components/settings/settings/EditSettingsForm.js",
383 "start": { 383 "start": {
384 "line": 139, 384 "line": 137,
385 "column": 25 385 "column": 25
386 }, 386 },
387 "end": { 387 "end": {
388 "line": 142, 388 "line": 140,
389 "column": 3 389 "column": 3
390 } 390 }
391 }, 391 },
@@ -394,11 +394,11 @@
394 "defaultMessage": "!!!Update available, downloading...", 394 "defaultMessage": "!!!Update available, downloading...",
395 "file": "src/components/settings/settings/EditSettingsForm.js", 395 "file": "src/components/settings/settings/EditSettingsForm.js",
396 "start": { 396 "start": {
397 "line": 143, 397 "line": 141,
398 "column": 25 398 "column": 25
399 }, 399 },
400 "end": { 400 "end": {
401 "line": 146, 401 "line": 144,
402 "column": 3 402 "column": 3
403 } 403 }
404 }, 404 },
@@ -407,11 +407,11 @@
407 "defaultMessage": "!!!You are using the latest version of Ferdi", 407 "defaultMessage": "!!!You are using the latest version of Ferdi",
408 "file": "src/components/settings/settings/EditSettingsForm.js", 408 "file": "src/components/settings/settings/EditSettingsForm.js",
409 "start": { 409 "start": {
410 "line": 147, 410 "line": 145,
411 "column": 24 411 "column": 24
412 }, 412 },
413 "end": { 413 "end": {
414 "line": 150, 414 "line": 148,
415 "column": 3 415 "column": 3
416 } 416 }
417 }, 417 },
@@ -420,11 +420,11 @@
420 "defaultMessage": "!!!Current version:", 420 "defaultMessage": "!!!Current version:",
421 "file": "src/components/settings/settings/EditSettingsForm.js", 421 "file": "src/components/settings/settings/EditSettingsForm.js",
422 "start": { 422 "start": {
423 "line": 151, 423 "line": 149,
424 "column": 18 424 "column": 18
425 }, 425 },
426 "end": { 426 "end": {
427 "line": 154, 427 "line": 152,
428 "column": 3 428 "column": 3
429 } 429 }
430 }, 430 },
@@ -433,11 +433,11 @@
433 "defaultMessage": "!!!Changes require restart", 433 "defaultMessage": "!!!Changes require restart",
434 "file": "src/components/settings/settings/EditSettingsForm.js", 434 "file": "src/components/settings/settings/EditSettingsForm.js",
435 "start": { 435 "start": {
436 "line": 155, 436 "line": 153,
437 "column": 22 437 "column": 22
438 }, 438 },
439 "end": { 439 "end": {
440 "line": 158, 440 "line": 156,
441 "column": 3 441 "column": 3
442 } 442 }
443 }, 443 },
@@ -446,11 +446,11 @@
446 "defaultMessage": "!!!Official translations are English & German. All other languages are community based translations.", 446 "defaultMessage": "!!!Official translations are English & German. All other languages are community based translations.",
447 "file": "src/components/settings/settings/EditSettingsForm.js", 447 "file": "src/components/settings/settings/EditSettingsForm.js",
448 "start": { 448 "start": {
449 "line": 159, 449 "line": 157,
450 "column": 22 450 "column": 22
451 }, 451 },
452 "end": { 452 "end": {
453 "line": 162, 453 "line": 160,
454 "column": 3 454 "column": 3
455 } 455 }
456 } 456 }
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 @@
4 "defaultMessage": "!!!Edit", 4 "defaultMessage": "!!!Edit",
5 "file": "src/lib/Menu.js", 5 "file": "src/lib/Menu.js",
6 "start": { 6 "start": {
7 "line": 20, 7 "line": 19,
8 "column": 8 8 "column": 8
9 }, 9 },
10 "end": { 10 "end": {
11 "line": 23, 11 "line": 22,
12 "column": 3 12 "column": 3
13 } 13 }
14 }, 14 },
@@ -17,11 +17,11 @@
17 "defaultMessage": "!!!Undo", 17 "defaultMessage": "!!!Undo",
18 "file": "src/lib/Menu.js", 18 "file": "src/lib/Menu.js",
19 "start": { 19 "start": {
20 "line": 24, 20 "line": 23,
21 "column": 8 21 "column": 8
22 }, 22 },
23 "end": { 23 "end": {
24 "line": 27, 24 "line": 26,
25 "column": 3 25 "column": 3
26 } 26 }
27 }, 27 },
@@ -30,11 +30,11 @@
30 "defaultMessage": "!!!Redo", 30 "defaultMessage": "!!!Redo",
31 "file": "src/lib/Menu.js", 31 "file": "src/lib/Menu.js",
32 "start": { 32 "start": {
33 "line": 28, 33 "line": 27,
34 "column": 8 34 "column": 8
35 }, 35 },
36 "end": { 36 "end": {
37 "line": 31, 37 "line": 30,
38 "column": 3 38 "column": 3
39 } 39 }
40 }, 40 },
@@ -43,11 +43,11 @@
43 "defaultMessage": "!!!Cut", 43 "defaultMessage": "!!!Cut",
44 "file": "src/lib/Menu.js", 44 "file": "src/lib/Menu.js",
45 "start": { 45 "start": {
46 "line": 32, 46 "line": 31,
47 "column": 7 47 "column": 7
48 }, 48 },
49 "end": { 49 "end": {
50 "line": 35, 50 "line": 34,
51 "column": 3 51 "column": 3
52 } 52 }
53 }, 53 },
@@ -56,11 +56,11 @@
56 "defaultMessage": "!!!Copy", 56 "defaultMessage": "!!!Copy",
57 "file": "src/lib/Menu.js", 57 "file": "src/lib/Menu.js",
58 "start": { 58 "start": {
59 "line": 36, 59 "line": 35,
60 "column": 8 60 "column": 8
61 }, 61 },
62 "end": { 62 "end": {
63 "line": 39, 63 "line": 38,
64 "column": 3 64 "column": 3
65 } 65 }
66 }, 66 },
@@ -69,11 +69,11 @@
69 "defaultMessage": "!!!Paste", 69 "defaultMessage": "!!!Paste",
70 "file": "src/lib/Menu.js", 70 "file": "src/lib/Menu.js",
71 "start": { 71 "start": {
72 "line": 40, 72 "line": 39,
73 "column": 9 73 "column": 9
74 }, 74 },
75 "end": { 75 "end": {
76 "line": 43, 76 "line": 42,
77 "column": 3 77 "column": 3
78 } 78 }
79 }, 79 },
@@ -82,11 +82,11 @@
82 "defaultMessage": "!!!Paste And Match Style", 82 "defaultMessage": "!!!Paste And Match Style",
83 "file": "src/lib/Menu.js", 83 "file": "src/lib/Menu.js",
84 "start": { 84 "start": {
85 "line": 44, 85 "line": 43,
86 "column": 22 86 "column": 22
87 }, 87 },
88 "end": { 88 "end": {
89 "line": 47, 89 "line": 46,
90 "column": 3 90 "column": 3
91 } 91 }
92 }, 92 },
@@ -95,11 +95,11 @@
95 "defaultMessage": "!!!Delete", 95 "defaultMessage": "!!!Delete",
96 "file": "src/lib/Menu.js", 96 "file": "src/lib/Menu.js",
97 "start": { 97 "start": {
98 "line": 48, 98 "line": 47,
99 "column": 10 99 "column": 10
100 }, 100 },
101 "end": { 101 "end": {
102 "line": 51, 102 "line": 50,
103 "column": 3 103 "column": 3
104 } 104 }
105 }, 105 },
@@ -108,11 +108,11 @@
108 "defaultMessage": "!!!Select All", 108 "defaultMessage": "!!!Select All",
109 "file": "src/lib/Menu.js", 109 "file": "src/lib/Menu.js",
110 "start": { 110 "start": {
111 "line": 52, 111 "line": 51,
112 "column": 13 112 "column": 13
113 }, 113 },
114 "end": { 114 "end": {
115 "line": 55, 115 "line": 54,
116 "column": 3 116 "column": 3
117 } 117 }
118 }, 118 },
@@ -121,11 +121,11 @@
121 "defaultMessage": "!!!Find in Page", 121 "defaultMessage": "!!!Find in Page",
122 "file": "src/lib/Menu.js", 122 "file": "src/lib/Menu.js",
123 "start": { 123 "start": {
124 "line": 56, 124 "line": 55,
125 "column": 14 125 "column": 14
126 }, 126 },
127 "end": { 127 "end": {
128 "line": 59, 128 "line": 58,
129 "column": 3 129 "column": 3
130 } 130 }
131 }, 131 },
@@ -134,11 +134,11 @@
134 "defaultMessage": "!!!Speech", 134 "defaultMessage": "!!!Speech",
135 "file": "src/lib/Menu.js", 135 "file": "src/lib/Menu.js",
136 "start": { 136 "start": {
137 "line": 60, 137 "line": 59,
138 "column": 10 138 "column": 10
139 }, 139 },
140 "end": { 140 "end": {
141 "line": 63, 141 "line": 62,
142 "column": 3 142 "column": 3
143 } 143 }
144 }, 144 },
@@ -147,11 +147,11 @@
147 "defaultMessage": "!!!Start Speaking", 147 "defaultMessage": "!!!Start Speaking",
148 "file": "src/lib/Menu.js", 148 "file": "src/lib/Menu.js",
149 "start": { 149 "start": {
150 "line": 64, 150 "line": 63,
151 "column": 17 151 "column": 17
152 }, 152 },
153 "end": { 153 "end": {
154 "line": 67, 154 "line": 66,
155 "column": 3 155 "column": 3
156 } 156 }
157 }, 157 },
@@ -160,11 +160,11 @@
160 "defaultMessage": "!!!Stop Speaking", 160 "defaultMessage": "!!!Stop Speaking",
161 "file": "src/lib/Menu.js", 161 "file": "src/lib/Menu.js",
162 "start": { 162 "start": {
163 "line": 68, 163 "line": 67,
164 "column": 16 164 "column": 16
165 }, 165 },
166 "end": { 166 "end": {
167 "line": 71, 167 "line": 70,
168 "column": 3 168 "column": 3
169 } 169 }
170 }, 170 },
@@ -173,11 +173,11 @@
173 "defaultMessage": "!!!Start Dictation", 173 "defaultMessage": "!!!Start Dictation",
174 "file": "src/lib/Menu.js", 174 "file": "src/lib/Menu.js",
175 "start": { 175 "start": {
176 "line": 72, 176 "line": 71,
177 "column": 18 177 "column": 18
178 }, 178 },
179 "end": { 179 "end": {
180 "line": 75, 180 "line": 74,
181 "column": 3 181 "column": 3
182 } 182 }
183 }, 183 },
@@ -186,11 +186,11 @@
186 "defaultMessage": "!!!Emoji & Symbols", 186 "defaultMessage": "!!!Emoji & Symbols",
187 "file": "src/lib/Menu.js", 187 "file": "src/lib/Menu.js",
188 "start": { 188 "start": {
189 "line": 76, 189 "line": 75,
190 "column": 16 190 "column": 16
191 }, 191 },
192 "end": { 192 "end": {
193 "line": 79, 193 "line": 78,
194 "column": 3 194 "column": 3
195 } 195 }
196 }, 196 },
@@ -199,11 +199,11 @@
199 "defaultMessage": "!!!Open Quick Switch", 199 "defaultMessage": "!!!Open Quick Switch",
200 "file": "src/lib/Menu.js", 200 "file": "src/lib/Menu.js",
201 "start": { 201 "start": {
202 "line": 80, 202 "line": 79,
203 "column": 19 203 "column": 19
204 }, 204 },
205 "end": { 205 "end": {
206 "line": 83, 206 "line": 82,
207 "column": 3 207 "column": 3
208 } 208 }
209 }, 209 },
@@ -212,11 +212,11 @@
212 "defaultMessage": "!!!Back", 212 "defaultMessage": "!!!Back",
213 "file": "src/lib/Menu.js", 213 "file": "src/lib/Menu.js",
214 "start": { 214 "start": {
215 "line": 84, 215 "line": 83,
216 "column": 8 216 "column": 8
217 }, 217 },
218 "end": { 218 "end": {
219 "line": 87, 219 "line": 86,
220 "column": 3 220 "column": 3
221 } 221 }
222 }, 222 },
@@ -225,11 +225,11 @@
225 "defaultMessage": "!!!Forward", 225 "defaultMessage": "!!!Forward",
226 "file": "src/lib/Menu.js", 226 "file": "src/lib/Menu.js",
227 "start": { 227 "start": {
228 "line": 88, 228 "line": 87,
229 "column": 11 229 "column": 11
230 }, 230 },
231 "end": { 231 "end": {
232 "line": 91, 232 "line": 90,
233 "column": 3 233 "column": 3
234 } 234 }
235 }, 235 },
@@ -238,11 +238,11 @@
238 "defaultMessage": "!!!Actual Size", 238 "defaultMessage": "!!!Actual Size",
239 "file": "src/lib/Menu.js", 239 "file": "src/lib/Menu.js",
240 "start": { 240 "start": {
241 "line": 92, 241 "line": 91,
242 "column": 13 242 "column": 13
243 }, 243 },
244 "end": { 244 "end": {
245 "line": 95, 245 "line": 94,
246 "column": 3 246 "column": 3
247 } 247 }
248 }, 248 },
@@ -251,11 +251,11 @@
251 "defaultMessage": "!!!Zoom In", 251 "defaultMessage": "!!!Zoom In",
252 "file": "src/lib/Menu.js", 252 "file": "src/lib/Menu.js",
253 "start": { 253 "start": {
254 "line": 96, 254 "line": 95,
255 "column": 10 255 "column": 10
256 }, 256 },
257 "end": { 257 "end": {
258 "line": 99, 258 "line": 98,
259 "column": 3 259 "column": 3
260 } 260 }
261 }, 261 },
@@ -264,11 +264,11 @@
264 "defaultMessage": "!!!Zoom Out", 264 "defaultMessage": "!!!Zoom Out",
265 "file": "src/lib/Menu.js", 265 "file": "src/lib/Menu.js",
266 "start": { 266 "start": {
267 "line": 100, 267 "line": 99,
268 "column": 11 268 "column": 11
269 }, 269 },
270 "end": { 270 "end": {
271 "line": 103, 271 "line": 102,
272 "column": 3 272 "column": 3
273 } 273 }
274 }, 274 },
@@ -277,11 +277,11 @@
277 "defaultMessage": "!!!Toggle Full Screen", 277 "defaultMessage": "!!!Toggle Full Screen",
278 "file": "src/lib/Menu.js", 278 "file": "src/lib/Menu.js",
279 "start": { 279 "start": {
280 "line": 104, 280 "line": 103,
281 "column": 20 281 "column": 20
282 }, 282 },
283 "end": { 283 "end": {
284 "line": 107, 284 "line": 106,
285 "column": 3 285 "column": 3
286 } 286 }
287 }, 287 },
@@ -290,11 +290,11 @@
290 "defaultMessage": "!!!Toggle Dark Mode", 290 "defaultMessage": "!!!Toggle Dark Mode",
291 "file": "src/lib/Menu.js", 291 "file": "src/lib/Menu.js",
292 "start": { 292 "start": {
293 "line": 108, 293 "line": 107,
294 "column": 18 294 "column": 18
295 }, 295 },
296 "end": { 296 "end": {
297 "line": 111, 297 "line": 110,
298 "column": 3 298 "column": 3
299 } 299 }
300 }, 300 },
@@ -303,11 +303,11 @@
303 "defaultMessage": "!!!Toggle Developer Tools", 303 "defaultMessage": "!!!Toggle Developer Tools",
304 "file": "src/lib/Menu.js", 304 "file": "src/lib/Menu.js",
305 "start": { 305 "start": {
306 "line": 112, 306 "line": 111,
307 "column": 18 307 "column": 18
308 }, 308 },
309 "end": { 309 "end": {
310 "line": 115, 310 "line": 114,
311 "column": 3 311 "column": 3
312 } 312 }
313 }, 313 },
@@ -316,11 +316,11 @@
316 "defaultMessage": "!!!Toggle Todos Developer Tools", 316 "defaultMessage": "!!!Toggle Todos Developer Tools",
317 "file": "src/lib/Menu.js", 317 "file": "src/lib/Menu.js",
318 "start": { 318 "start": {
319 "line": 116, 319 "line": 115,
320 "column": 23 320 "column": 23
321 }, 321 },
322 "end": { 322 "end": {
323 "line": 119, 323 "line": 118,
324 "column": 3 324 "column": 3
325 } 325 }
326 }, 326 },
@@ -329,11 +329,11 @@
329 "defaultMessage": "!!!Toggle Service Developer Tools", 329 "defaultMessage": "!!!Toggle Service Developer Tools",
330 "file": "src/lib/Menu.js", 330 "file": "src/lib/Menu.js",
331 "start": { 331 "start": {
332 "line": 120, 332 "line": 119,
333 "column": 25 333 "column": 25
334 }, 334 },
335 "end": { 335 "end": {
336 "line": 123, 336 "line": 122,
337 "column": 3 337 "column": 3
338 } 338 }
339 }, 339 },
@@ -342,11 +342,11 @@
342 "defaultMessage": "!!!Reload Service", 342 "defaultMessage": "!!!Reload Service",
343 "file": "src/lib/Menu.js", 343 "file": "src/lib/Menu.js",
344 "start": { 344 "start": {
345 "line": 124, 345 "line": 123,
346 "column": 17 346 "column": 17
347 }, 347 },
348 "end": { 348 "end": {
349 "line": 127, 349 "line": 126,
350 "column": 3 350 "column": 3
351 } 351 }
352 }, 352 },
@@ -355,11 +355,11 @@
355 "defaultMessage": "!!!Reload Ferdi", 355 "defaultMessage": "!!!Reload Ferdi",
356 "file": "src/lib/Menu.js", 356 "file": "src/lib/Menu.js",
357 "start": { 357 "start": {
358 "line": 128, 358 "line": 127,
359 "column": 15 359 "column": 15
360 }, 360 },
361 "end": { 361 "end": {
362 "line": 131, 362 "line": 130,
363 "column": 3 363 "column": 3
364 } 364 }
365 }, 365 },
@@ -368,11 +368,11 @@
368 "defaultMessage": "!!!Lock Ferdi", 368 "defaultMessage": "!!!Lock Ferdi",
369 "file": "src/lib/Menu.js", 369 "file": "src/lib/Menu.js",
370 "start": { 370 "start": {
371 "line": 132, 371 "line": 131,
372 "column": 13 372 "column": 13
373 }, 373 },
374 "end": { 374 "end": {
375 "line": 135, 375 "line": 134,
376 "column": 3 376 "column": 3
377 } 377 }
378 }, 378 },
@@ -381,11 +381,11 @@
381 "defaultMessage": "!!!Reload ToDos", 381 "defaultMessage": "!!!Reload ToDos",
382 "file": "src/lib/Menu.js", 382 "file": "src/lib/Menu.js",
383 "start": { 383 "start": {
384 "line": 136, 384 "line": 135,
385 "column": 15 385 "column": 15
386 }, 386 },
387 "end": { 387 "end": {
388 "line": 139, 388 "line": 138,
389 "column": 3 389 "column": 3
390 } 390 }
391 }, 391 },
@@ -394,11 +394,11 @@
394 "defaultMessage": "!!!Minimize", 394 "defaultMessage": "!!!Minimize",
395 "file": "src/lib/Menu.js", 395 "file": "src/lib/Menu.js",
396 "start": { 396 "start": {
397 "line": 140, 397 "line": 139,
398 "column": 12 398 "column": 12
399 }, 399 },
400 "end": { 400 "end": {
401 "line": 143, 401 "line": 142,
402 "column": 3 402 "column": 3
403 } 403 }
404 }, 404 },
@@ -407,11 +407,11 @@
407 "defaultMessage": "!!!Close", 407 "defaultMessage": "!!!Close",
408 "file": "src/lib/Menu.js", 408 "file": "src/lib/Menu.js",
409 "start": { 409 "start": {
410 "line": 144, 410 "line": 143,
411 "column": 9 411 "column": 9
412 }, 412 },
413 "end": { 413 "end": {
414 "line": 147, 414 "line": 146,
415 "column": 3 415 "column": 3
416 } 416 }
417 }, 417 },
@@ -420,11 +420,11 @@
420 "defaultMessage": "!!!Learn More", 420 "defaultMessage": "!!!Learn More",
421 "file": "src/lib/Menu.js", 421 "file": "src/lib/Menu.js",
422 "start": { 422 "start": {
423 "line": 148, 423 "line": 147,
424 "column": 13 424 "column": 13
425 }, 425 },
426 "end": { 426 "end": {
427 "line": 151, 427 "line": 150,
428 "column": 3 428 "column": 3
429 } 429 }
430 }, 430 },
@@ -433,11 +433,11 @@
433 "defaultMessage": "!!!Changelog", 433 "defaultMessage": "!!!Changelog",
434 "file": "src/lib/Menu.js", 434 "file": "src/lib/Menu.js",
435 "start": { 435 "start": {
436 "line": 152, 436 "line": 151,
437 "column": 13 437 "column": 13
438 }, 438 },
439 "end": { 439 "end": {
440 "line": 155, 440 "line": 154,
441 "column": 3 441 "column": 3
442 } 442 }
443 }, 443 },
@@ -446,11 +446,11 @@
446 "defaultMessage": "!!!Import/Export Configuration Data", 446 "defaultMessage": "!!!Import/Export Configuration Data",
447 "file": "src/lib/Menu.js", 447 "file": "src/lib/Menu.js",
448 "start": { 448 "start": {
449 "line": 156, 449 "line": 155,
450 "column": 20 450 "column": 20
451 }, 451 },
452 "end": { 452 "end": {
453 "line": 159, 453 "line": 158,
454 "column": 3 454 "column": 3
455 } 455 }
456 }, 456 },
@@ -459,11 +459,11 @@
459 "defaultMessage": "!!!Support", 459 "defaultMessage": "!!!Support",
460 "file": "src/lib/Menu.js", 460 "file": "src/lib/Menu.js",
461 "start": { 461 "start": {
462 "line": 160, 462 "line": 159,
463 "column": 11 463 "column": 11
464 }, 464 },
465 "end": { 465 "end": {
466 "line": 163, 466 "line": 162,
467 "column": 3 467 "column": 3
468 } 468 }
469 }, 469 },
@@ -472,11 +472,11 @@
472 "defaultMessage": "!!!Copy Debug Information", 472 "defaultMessage": "!!!Copy Debug Information",
473 "file": "src/lib/Menu.js", 473 "file": "src/lib/Menu.js",
474 "start": { 474 "start": {
475 "line": 164, 475 "line": 163,
476 "column": 13 476 "column": 13
477 }, 477 },
478 "end": { 478 "end": {
479 "line": 167, 479 "line": 166,
480 "column": 3 480 "column": 3
481 } 481 }
482 }, 482 },
@@ -485,11 +485,11 @@
485 "defaultMessage": "!!!Publish Debug Information", 485 "defaultMessage": "!!!Publish Debug Information",
486 "file": "src/lib/Menu.js", 486 "file": "src/lib/Menu.js",
487 "start": { 487 "start": {
488 "line": 168, 488 "line": 167,
489 "column": 20 489 "column": 20
490 }, 490 },
491 "end": { 491 "end": {
492 "line": 171, 492 "line": 170,
493 "column": 3 493 "column": 3
494 } 494 }
495 }, 495 },
@@ -498,11 +498,11 @@
498 "defaultMessage": "!!!Ferdi Debug Information", 498 "defaultMessage": "!!!Ferdi Debug Information",
499 "file": "src/lib/Menu.js", 499 "file": "src/lib/Menu.js",
500 "start": { 500 "start": {
501 "line": 172, 501 "line": 171,
502 "column": 27 502 "column": 27
503 }, 503 },
504 "end": { 504 "end": {
505 "line": 175, 505 "line": 174,
506 "column": 3 506 "column": 3
507 } 507 }
508 }, 508 },
@@ -511,11 +511,11 @@
511 "defaultMessage": "!!!Your Debug Information has been copied to your clipboard.", 511 "defaultMessage": "!!!Your Debug Information has been copied to your clipboard.",
512 "file": "src/lib/Menu.js", 512 "file": "src/lib/Menu.js",
513 "start": { 513 "start": {
514 "line": 176, 514 "line": 175,
515 "column": 23 515 "column": 23
516 }, 516 },
517 "end": { 517 "end": {
518 "line": 179, 518 "line": 178,
519 "column": 3 519 "column": 3
520 } 520 }
521 }, 521 },
@@ -524,11 +524,11 @@
524 "defaultMessage": "!!!Unlock with Touch ID", 524 "defaultMessage": "!!!Unlock with Touch ID",
525 "file": "src/lib/Menu.js", 525 "file": "src/lib/Menu.js",
526 "start": { 526 "start": {
527 "line": 180, 527 "line": 179,
528 "column": 11 528 "column": 11
529 }, 529 },
530 "end": { 530 "end": {
531 "line": 183, 531 "line": 182,
532 "column": 3 532 "column": 3
533 } 533 }
534 }, 534 },
@@ -537,11 +537,11 @@
537 "defaultMessage": "!!!unlock via Touch ID", 537 "defaultMessage": "!!!unlock via Touch ID",
538 "file": "src/lib/Menu.js", 538 "file": "src/lib/Menu.js",
539 "start": { 539 "start": {
540 "line": 184, 540 "line": 183,
541 "column": 17 541 "column": 17
542 }, 542 },
543 "end": { 543 "end": {
544 "line": 187, 544 "line": 186,
545 "column": 3 545 "column": 3
546 } 546 }
547 }, 547 },
@@ -550,11 +550,11 @@
550 "defaultMessage": "!!!Terms of Service", 550 "defaultMessage": "!!!Terms of Service",
551 "file": "src/lib/Menu.js", 551 "file": "src/lib/Menu.js",
552 "start": { 552 "start": {
553 "line": 188, 553 "line": 187,
554 "column": 7 554 "column": 7
555 }, 555 },
556 "end": { 556 "end": {
557 "line": 191, 557 "line": 190,
558 "column": 3 558 "column": 3
559 } 559 }
560 }, 560 },
@@ -563,11 +563,11 @@
563 "defaultMessage": "!!!Privacy Statement", 563 "defaultMessage": "!!!Privacy Statement",
564 "file": "src/lib/Menu.js", 564 "file": "src/lib/Menu.js",
565 "start": { 565 "start": {
566 "line": 192, 566 "line": 191,
567 "column": 11 567 "column": 11
568 }, 568 },
569 "end": { 569 "end": {
570 "line": 195, 570 "line": 194,
571 "column": 3 571 "column": 3
572 } 572 }
573 }, 573 },
@@ -576,11 +576,11 @@
576 "defaultMessage": "!!!File", 576 "defaultMessage": "!!!File",
577 "file": "src/lib/Menu.js", 577 "file": "src/lib/Menu.js",
578 "start": { 578 "start": {
579 "line": 196, 579 "line": 195,
580 "column": 8 580 "column": 8
581 }, 581 },
582 "end": { 582 "end": {
583 "line": 199, 583 "line": 198,
584 "column": 3 584 "column": 3
585 } 585 }
586 }, 586 },
@@ -589,11 +589,11 @@
589 "defaultMessage": "!!!View", 589 "defaultMessage": "!!!View",
590 "file": "src/lib/Menu.js", 590 "file": "src/lib/Menu.js",
591 "start": { 591 "start": {
592 "line": 200, 592 "line": 199,
593 "column": 8 593 "column": 8
594 }, 594 },
595 "end": { 595 "end": {
596 "line": 203, 596 "line": 202,
597 "column": 3 597 "column": 3
598 } 598 }
599 }, 599 },
@@ -602,11 +602,11 @@
602 "defaultMessage": "!!!Services", 602 "defaultMessage": "!!!Services",
603 "file": "src/lib/Menu.js", 603 "file": "src/lib/Menu.js",
604 "start": { 604 "start": {
605 "line": 204, 605 "line": 203,
606 "column": 12 606 "column": 12
607 }, 607 },
608 "end": { 608 "end": {
609 "line": 207, 609 "line": 206,
610 "column": 3 610 "column": 3
611 } 611 }
612 }, 612 },
@@ -615,11 +615,11 @@
615 "defaultMessage": "!!!Window", 615 "defaultMessage": "!!!Window",
616 "file": "src/lib/Menu.js", 616 "file": "src/lib/Menu.js",
617 "start": { 617 "start": {
618 "line": 208, 618 "line": 207,
619 "column": 10 619 "column": 10
620 }, 620 },
621 "end": { 621 "end": {
622 "line": 211, 622 "line": 210,
623 "column": 3 623 "column": 3
624 } 624 }
625 }, 625 },
@@ -628,11 +628,11 @@
628 "defaultMessage": "!!!Help", 628 "defaultMessage": "!!!Help",
629 "file": "src/lib/Menu.js", 629 "file": "src/lib/Menu.js",
630 "start": { 630 "start": {
631 "line": 212, 631 "line": 211,
632 "column": 8 632 "column": 8
633 }, 633 },
634 "end": { 634 "end": {
635 "line": 215, 635 "line": 214,
636 "column": 3 636 "column": 3
637 } 637 }
638 }, 638 },
@@ -641,11 +641,11 @@
641 "defaultMessage": "!!!About Ferdi", 641 "defaultMessage": "!!!About Ferdi",
642 "file": "src/lib/Menu.js", 642 "file": "src/lib/Menu.js",
643 "start": { 643 "start": {
644 "line": 216, 644 "line": 215,
645 "column": 9 645 "column": 9
646 }, 646 },
647 "end": { 647 "end": {
648 "line": 219, 648 "line": 218,
649 "column": 3 649 "column": 3
650 } 650 }
651 }, 651 },
@@ -654,11 +654,11 @@
654 "defaultMessage": "!!!What's new?", 654 "defaultMessage": "!!!What's new?",
655 "file": "src/lib/Menu.js", 655 "file": "src/lib/Menu.js",
656 "start": { 656 "start": {
657 "line": 220, 657 "line": 219,
658 "column": 16 658 "column": 16
659 }, 659 },
660 "end": { 660 "end": {
661 "line": 223, 661 "line": 222,
662 "column": 3 662 "column": 3
663 } 663 }
664 }, 664 },
@@ -667,11 +667,11 @@
667 "defaultMessage": "!!!Settings", 667 "defaultMessage": "!!!Settings",
668 "file": "src/lib/Menu.js", 668 "file": "src/lib/Menu.js",
669 "start": { 669 "start": {
670 "line": 224, 670 "line": 223,
671 "column": 12 671 "column": 12
672 }, 672 },
673 "end": { 673 "end": {
674 "line": 227, 674 "line": 226,
675 "column": 3 675 "column": 3
676 } 676 }
677 }, 677 },
@@ -680,11 +680,11 @@
680 "defaultMessage": "!!!Check for updates", 680 "defaultMessage": "!!!Check for updates",
681 "file": "src/lib/Menu.js", 681 "file": "src/lib/Menu.js",
682 "start": { 682 "start": {
683 "line": 228, 683 "line": 227,
684 "column": 19 684 "column": 19
685 }, 685 },
686 "end": { 686 "end": {
687 "line": 231, 687 "line": 230,
688 "column": 3 688 "column": 3
689 } 689 }
690 }, 690 },
@@ -693,11 +693,11 @@
693 "defaultMessage": "!!!Hide", 693 "defaultMessage": "!!!Hide",
694 "file": "src/lib/Menu.js", 694 "file": "src/lib/Menu.js",
695 "start": { 695 "start": {
696 "line": 232, 696 "line": 231,
697 "column": 8 697 "column": 8
698 }, 698 },
699 "end": { 699 "end": {
700 "line": 235, 700 "line": 234,
701 "column": 3 701 "column": 3
702 } 702 }
703 }, 703 },
@@ -706,11 +706,11 @@
706 "defaultMessage": "!!!Hide Others", 706 "defaultMessage": "!!!Hide Others",
707 "file": "src/lib/Menu.js", 707 "file": "src/lib/Menu.js",
708 "start": { 708 "start": {
709 "line": 236, 709 "line": 235,
710 "column": 14 710 "column": 14
711 }, 711 },
712 "end": { 712 "end": {
713 "line": 239, 713 "line": 238,
714 "column": 3 714 "column": 3
715 } 715 }
716 }, 716 },
@@ -719,11 +719,11 @@
719 "defaultMessage": "!!!Unhide", 719 "defaultMessage": "!!!Unhide",
720 "file": "src/lib/Menu.js", 720 "file": "src/lib/Menu.js",
721 "start": { 721 "start": {
722 "line": 240, 722 "line": 239,
723 "column": 10 723 "column": 10
724 }, 724 },
725 "end": { 725 "end": {
726 "line": 243, 726 "line": 242,
727 "column": 3 727 "column": 3
728 } 728 }
729 }, 729 },
@@ -732,11 +732,11 @@
732 "defaultMessage": "!!!Auto-hide menu bar", 732 "defaultMessage": "!!!Auto-hide menu bar",
733 "file": "src/lib/Menu.js", 733 "file": "src/lib/Menu.js",
734 "start": { 734 "start": {
735 "line": 244, 735 "line": 243,
736 "column": 19 736 "column": 19
737 }, 737 },
738 "end": { 738 "end": {
739 "line": 247, 739 "line": 246,
740 "column": 3 740 "column": 3
741 } 741 }
742 }, 742 },
@@ -745,11 +745,11 @@
745 "defaultMessage": "!!!Quit", 745 "defaultMessage": "!!!Quit",
746 "file": "src/lib/Menu.js", 746 "file": "src/lib/Menu.js",
747 "start": { 747 "start": {
748 "line": 248, 748 "line": 247,
749 "column": 8 749 "column": 8
750 }, 750 },
751 "end": { 751 "end": {
752 "line": 251, 752 "line": 250,
753 "column": 3 753 "column": 3
754 } 754 }
755 }, 755 },
@@ -758,11 +758,11 @@
758 "defaultMessage": "!!!Add New Service...", 758 "defaultMessage": "!!!Add New Service...",
759 "file": "src/lib/Menu.js", 759 "file": "src/lib/Menu.js",
760 "start": { 760 "start": {
761 "line": 252, 761 "line": 251,
762 "column": 17 762 "column": 17
763 }, 763 },
764 "end": { 764 "end": {
765 "line": 255, 765 "line": 254,
766 "column": 3 766 "column": 3
767 } 767 }
768 }, 768 },
@@ -771,11 +771,11 @@
771 "defaultMessage": "!!!Add New Workspace...", 771 "defaultMessage": "!!!Add New Workspace...",
772 "file": "src/lib/Menu.js", 772 "file": "src/lib/Menu.js",
773 "start": { 773 "start": {
774 "line": 256, 774 "line": 255,
775 "column": 19 775 "column": 19
776 }, 776 },
777 "end": { 777 "end": {
778 "line": 259, 778 "line": 258,
779 "column": 3 779 "column": 3
780 } 780 }
781 }, 781 },
@@ -784,11 +784,11 @@
784 "defaultMessage": "!!!Open workspace drawer", 784 "defaultMessage": "!!!Open workspace drawer",
785 "file": "src/lib/Menu.js", 785 "file": "src/lib/Menu.js",
786 "start": { 786 "start": {
787 "line": 260, 787 "line": 259,
788 "column": 23 788 "column": 23
789 }, 789 },
790 "end": { 790 "end": {
791 "line": 263, 791 "line": 262,
792 "column": 3 792 "column": 3
793 } 793 }
794 }, 794 },
@@ -797,11 +797,11 @@
797 "defaultMessage": "!!!Close workspace drawer", 797 "defaultMessage": "!!!Close workspace drawer",
798 "file": "src/lib/Menu.js", 798 "file": "src/lib/Menu.js",
799 "start": { 799 "start": {
800 "line": 264, 800 "line": 263,
801 "column": 24 801 "column": 24
802 }, 802 },
803 "end": { 803 "end": {
804 "line": 267, 804 "line": 266,
805 "column": 3 805 "column": 3
806 } 806 }
807 }, 807 },
@@ -810,11 +810,11 @@
810 "defaultMessage": "!!!Activate next service...", 810 "defaultMessage": "!!!Activate next service...",
811 "file": "src/lib/Menu.js", 811 "file": "src/lib/Menu.js",
812 "start": { 812 "start": {
813 "line": 268, 813 "line": 267,
814 "column": 23 814 "column": 23
815 }, 815 },
816 "end": { 816 "end": {
817 "line": 271, 817 "line": 270,
818 "column": 3 818 "column": 3
819 } 819 }
820 }, 820 },
@@ -823,11 +823,11 @@
823 "defaultMessage": "!!!Activate previous service...", 823 "defaultMessage": "!!!Activate previous service...",
824 "file": "src/lib/Menu.js", 824 "file": "src/lib/Menu.js",
825 "start": { 825 "start": {
826 "line": 272, 826 "line": 271,
827 "column": 27 827 "column": 27
828 }, 828 },
829 "end": { 829 "end": {
830 "line": 275, 830 "line": 274,
831 "column": 3 831 "column": 3
832 } 832 }
833 }, 833 },
@@ -836,11 +836,11 @@
836 "defaultMessage": "!!!Disable notifications & audio", 836 "defaultMessage": "!!!Disable notifications & audio",
837 "file": "src/lib/Menu.js", 837 "file": "src/lib/Menu.js",
838 "start": { 838 "start": {
839 "line": 276, 839 "line": 275,
840 "column": 11 840 "column": 11
841 }, 841 },
842 "end": { 842 "end": {
843 "line": 279, 843 "line": 278,
844 "column": 3 844 "column": 3
845 } 845 }
846 }, 846 },
@@ -849,11 +849,11 @@
849 "defaultMessage": "!!!Enable notifications & audio", 849 "defaultMessage": "!!!Enable notifications & audio",
850 "file": "src/lib/Menu.js", 850 "file": "src/lib/Menu.js",
851 "start": { 851 "start": {
852 "line": 280, 852 "line": 279,
853 "column": 13 853 "column": 13
854 }, 854 },
855 "end": { 855 "end": {
856 "line": 283, 856 "line": 282,
857 "column": 3 857 "column": 3
858 } 858 }
859 }, 859 },
@@ -862,11 +862,11 @@
862 "defaultMessage": "!!!Workspaces", 862 "defaultMessage": "!!!Workspaces",
863 "file": "src/lib/Menu.js", 863 "file": "src/lib/Menu.js",
864 "start": { 864 "start": {
865 "line": 284, 865 "line": 283,
866 "column": 14 866 "column": 14
867 }, 867 },
868 "end": { 868 "end": {
869 "line": 287, 869 "line": 286,
870 "column": 3 870 "column": 3
871 } 871 }
872 }, 872 },
@@ -875,11 +875,11 @@
875 "defaultMessage": "!!!Default", 875 "defaultMessage": "!!!Default",
876 "file": "src/lib/Menu.js", 876 "file": "src/lib/Menu.js",
877 "start": { 877 "start": {
878 "line": 288, 878 "line": 287,
879 "column": 20 879 "column": 20
880 }, 880 },
881 "end": { 881 "end": {
882 "line": 291, 882 "line": 290,
883 "column": 3 883 "column": 3
884 } 884 }
885 }, 885 },
@@ -888,11 +888,11 @@
888 "defaultMessage": "!!!Todos", 888 "defaultMessage": "!!!Todos",
889 "file": "src/lib/Menu.js", 889 "file": "src/lib/Menu.js",
890 "start": { 890 "start": {
891 "line": 292, 891 "line": 291,
892 "column": 9 892 "column": 9
893 }, 893 },
894 "end": { 894 "end": {
895 "line": 295, 895 "line": 294,
896 "column": 3 896 "column": 3
897 } 897 }
898 }, 898 },
@@ -901,11 +901,11 @@
901 "defaultMessage": "!!!Open Todos drawer", 901 "defaultMessage": "!!!Open Todos drawer",
902 "file": "src/lib/Menu.js", 902 "file": "src/lib/Menu.js",
903 "start": { 903 "start": {
904 "line": 296, 904 "line": 295,
905 "column": 19 905 "column": 19
906 }, 906 },
907 "end": { 907 "end": {
908 "line": 299, 908 "line": 298,
909 "column": 3 909 "column": 3
910 } 910 }
911 }, 911 },
@@ -914,11 +914,11 @@
914 "defaultMessage": "!!!Close Todos drawer", 914 "defaultMessage": "!!!Close Todos drawer",
915 "file": "src/lib/Menu.js", 915 "file": "src/lib/Menu.js",
916 "start": { 916 "start": {
917 "line": 300, 917 "line": 299,
918 "column": 20 918 "column": 20
919 }, 919 },
920 "end": { 920 "end": {
921 "line": 303, 921 "line": 302,
922 "column": 3 922 "column": 3
923 } 923 }
924 }, 924 },
@@ -927,11 +927,11 @@
927 "defaultMessage": "!!!Enable Todos", 927 "defaultMessage": "!!!Enable Todos",
928 "file": "src/lib/Menu.js", 928 "file": "src/lib/Menu.js",
929 "start": { 929 "start": {
930 "line": 304, 930 "line": 303,
931 "column": 15 931 "column": 15
932 }, 932 },
933 "end": { 933 "end": {
934 "line": 307, 934 "line": 306,
935 "column": 3 935 "column": 3
936 } 936 }
937 }, 937 },
@@ -940,11 +940,11 @@
940 "defaultMessage": "!!!Home", 940 "defaultMessage": "!!!Home",
941 "file": "src/lib/Menu.js", 941 "file": "src/lib/Menu.js",
942 "start": { 942 "start": {
943 "line": 308, 943 "line": 307,
944 "column": 17 944 "column": 17
945 }, 945 },
946 "end": { 946 "end": {
947 "line": 311, 947 "line": 310,
948 "column": 3 948 "column": 3
949 } 949 }
950 } 950 }
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 @@
1/* eslint-disable import/first */ 1/* eslint-disable import/first */
2 2
3import { app, BrowserWindow, shell, ipcMain, session } from 'electron'; 3import { app, BrowserWindow, ipcMain, session } from 'electron';
4 4
5import { emptyDirSync, ensureFileSync } from 'fs-extra'; 5import { emptyDirSync, ensureFileSync } from 'fs-extra';
6import { join } from 'path'; 6import { join } from 'path';
@@ -34,7 +34,7 @@ import { appId } from './package.json'; // eslint-disable-line import/no-unresol
34import './electron/exception'; 34import './electron/exception';
35 35
36import { asarPath } from './helpers/asar-helpers'; 36import { asarPath } from './helpers/asar-helpers';
37import { isValidExternalURL } from './helpers/url-helpers'; 37import { openExternalUrl } from './helpers/url-helpers';
38import userAgent from './helpers/userAgent-helpers'; 38import userAgent from './helpers/userAgent-helpers';
39 39
40const debug = require('debug')('Ferdi:App'); 40const debug = require('debug')('Ferdi:App');
@@ -344,10 +344,7 @@ const createWindow = () => {
344 mainWindow.webContents.on('new-window', (e, url) => { 344 mainWindow.webContents.on('new-window', (e, url) => {
345 debug('Open url', url); 345 debug('Open url', url);
346 e.preventDefault(); 346 e.preventDefault();
347 347 openExternalUrl(url);
348 if (isValidExternalURL(url)) {
349 shell.openExternal(url);
350 }
351 }); 348 });
352 349
353 if (settings.get('startMinimized')) { 350 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 @@
1import { clipboard, shell } from 'electron'; 1import { clipboard } from 'electron';
2import { 2import { app, Menu, dialog, systemPreferences } from '@electron/remote';
3 app, Menu, dialog, systemPreferences,
4} from '@electron/remote';
5import { autorun, observable } from 'mobx'; 3import { autorun, observable } from 'mobx';
6import { defineMessages } from 'react-intl'; 4import { defineMessages } from 'react-intl';
7import { CUSTOM_WEBSITE_RECIPE_ID, GITHUB_FERDI_URL, LIVE_API_FERDI_WEBSITE } from '../config'; 5import { CUSTOM_WEBSITE_RECIPE_ID, GITHUB_FERDI_URL, LIVE_API_FERDI_WEBSITE } from '../config';
@@ -15,6 +13,7 @@ import { todoActions } from '../features/todos/actions';
15import { workspaceActions } from '../features/workspaces/actions'; 13import { workspaceActions } from '../features/workspaces/actions';
16import { workspaceStore } from '../features/workspaces/index'; 14import { workspaceStore } from '../features/workspaces/index';
17import apiBase, { termsBase } from '../api/apiBase'; 15import apiBase, { termsBase } from '../api/apiBase';
16import { openExternalUrl } from '../helpers/url-helpers';
18 17
19const menuItems = defineMessages({ 18const menuItems = defineMessages({
20 edit: { 19 edit: {
@@ -514,15 +513,15 @@ const _titleBarTemplateFactory = (intl, locked) => [
514 submenu: [ 513 submenu: [
515 { 514 {
516 label: intl.formatMessage(menuItems.learnMore), 515 label: intl.formatMessage(menuItems.learnMore),
517 click() { shell.openExternal(LIVE_API_FERDI_WEBSITE); }, 516 click() { openExternalUrl(LIVE_API_FERDI_WEBSITE, true); },
518 }, 517 },
519 { 518 {
520 label: intl.formatMessage(menuItems.changelog), 519 label: intl.formatMessage(menuItems.changelog),
521 click() { shell.openExternal(`${GITHUB_FERDI_URL}/ferdi/blob/master/CHANGELOG.md`); }, 520 click() { openExternalUrl(`${GITHUB_FERDI_URL}/ferdi/blob/master/CHANGELOG.md`, true); },
522 }, 521 },
523 { 522 {
524 label: intl.formatMessage(menuItems.importExportData), 523 label: intl.formatMessage(menuItems.importExportData),
525 click() { shell.openExternal(apiBase(false)); }, 524 click() { openExternalUrl(apiBase(false), true); },
526 enabled: !locked, 525 enabled: !locked,
527 }, 526 },
528 { 527 {
@@ -540,18 +539,18 @@ const _titleBarTemplateFactory = (intl, locked) => [
540 }, 539 },
541 { 540 {
542 label: intl.formatMessage(menuItems.support), 541 label: intl.formatMessage(menuItems.support),
543 click() { shell.openExternal(`${LIVE_API_FERDI_WEBSITE}/contact`); }, 542 click() { openExternalUrl(`${LIVE_API_FERDI_WEBSITE}/contact`, true); },
544 }, 543 },
545 { 544 {
546 type: 'separator', 545 type: 'separator',
547 }, 546 },
548 { 547 {
549 label: intl.formatMessage(menuItems.tos), 548 label: intl.formatMessage(menuItems.tos),
550 click() { shell.openExternal(`${termsBase()}/terms`); }, 549 click() { openExternalUrl(`${termsBase()}/terms`, true); },
551 }, 550 },
552 { 551 {
553 label: intl.formatMessage(menuItems.privacy), 552 label: intl.formatMessage(menuItems.privacy),
554 click() { shell.openExternal(`${termsBase()}/privacy`); }, 553 click() { openExternalUrl(`${termsBase()}/privacy`, true); },
555 }, 554 },
556 ], 555 ],
557 }, 556 },
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 @@
1import { ipcRenderer, shell } from 'electron'; 1import { ipcRenderer } from 'electron';
2import { 2import {
3 app, 3 app,
4 screen, 4 screen,
@@ -33,7 +33,7 @@ import {
33 getServiceIdsFromPartitions, 33 getServiceIdsFromPartitions,
34 removeServicePartitionDirectory, 34 removeServicePartitionDirectory,
35} from '../helpers/service-helpers'; 35} from '../helpers/service-helpers';
36import { isValidExternalURL } from '../helpers/url-helpers'; 36import { openExternalUrl } from '../helpers/url-helpers';
37import { sleep } from '../helpers/async-helpers'; 37import { sleep } from '../helpers/async-helpers';
38 38
39const debug = require('debug')('Ferdi:AppStore'); 39const debug = require('debug')('Ferdi:AppStore');
@@ -388,13 +388,9 @@ export default class AppStore extends Store {
388 } 388 }
389 } 389 }
390 390
391 // Ideally(?) this should be merged with the 'shell-helpers' functionality
391 @action _openExternalUrl({ url }) { 392 @action _openExternalUrl({ url }) {
392 const parsedUrl = new URL(url); 393 openExternalUrl(new URL(url));
393 debug('open external url', parsedUrl);
394
395 if (isValidExternalURL(url)) {
396 shell.openExternal(url);
397 }
398 } 394 }
399 395
400 @action _checkForUpdates() { 396 @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 @@
6 * 6 *
7 * Source: https://github.com/electron-userland/electron-spellchecker/blob/master/src/context-menu-builder.js 7 * Source: https://github.com/electron-userland/electron-spellchecker/blob/master/src/context-menu-builder.js
8 */ 8 */
9import { 9import { clipboard, ipcRenderer, nativeImage } from 'electron';
10 clipboard, ipcRenderer, nativeImage, shell,
11} from 'electron';
12import { Menu, MenuItem } from '@electron/remote'; 10import { Menu, MenuItem } from '@electron/remote';
13import { shortcutKey, isMac } from '../environment'; 11import { shortcutKey, isMac } from '../environment';
14 12
15import { SEARCH_ENGINE_NAMES, SEARCH_ENGINE_URLS } from '../config'; 13import { SEARCH_ENGINE_NAMES, SEARCH_ENGINE_URLS } from '../config';
14import { openExternalUrl } from '../helpers/url-helpers';
16 15
17const { URL } = require('url'); 16const { URL } = require('url');
18 17
@@ -170,7 +169,7 @@ module.exports = class ContextMenuBuilder {
170 const openLink = new MenuItem({ 169 const openLink = new MenuItem({
171 label: this.stringTable.openLinkUrl(), 170 label: this.stringTable.openLinkUrl(),
172 click: () => { 171 click: () => {
173 shell.openExternal(menuInfo.linkURL); 172 openExternalUrl(menuInfo.linkURL, true);
174 }, 173 },
175 }); 174 });
176 175
@@ -299,7 +298,7 @@ module.exports = class ContextMenuBuilder {
299 label: this.stringTable.searchWith({ searchEngine: SEARCH_ENGINE_NAMES[menuInfo.searchEngine] }), 298 label: this.stringTable.searchWith({ searchEngine: SEARCH_ENGINE_NAMES[menuInfo.searchEngine] }),
300 click: () => { 299 click: () => {
301 const url = SEARCH_ENGINE_URLS[menuInfo.searchEngine]({ searchTerm: encodeURIComponent(menuInfo.selectionText) }); 300 const url = SEARCH_ENGINE_URLS[menuInfo.searchEngine]({ searchTerm: encodeURIComponent(menuInfo.selectionText) });
302 shell.openExternal(url); 301 openExternalUrl(url, true);
303 }, 302 },
304 }); 303 });
305 304
@@ -555,7 +554,7 @@ module.exports = class ContextMenuBuilder {
555 label: this.stringTable.openInBrowser(), 554 label: this.stringTable.openInBrowser(),
556 enabled: true, 555 enabled: true,
557 click: () => { 556 click: () => {
558 shell.openExternal(menuInfo.pageURL); 557 openExternalUrl(menuInfo.pageURL, true);
559 }, 558 },
560 })); 559 }));
561 560