aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Markus Hatvan <markus_hatvan@aon.at>2021-09-13 14:45:46 +0200
committerLibravatar GitHub <noreply@github.com>2021-09-13 14:45:46 +0200
commit537697a6e9757f118d09d9e76362ba1ff617e2c6 (patch)
treebc55447115e385137684e84697a8c15d2199b8d5
parentBumped up version to: 5.6.3-nightly.0 [skip ci] (diff)
downloadferdium-app-537697a6e9757f118d09d9e76362ba1ff617e2c6.tar.gz
ferdium-app-537697a6e9757f118d09d9e76362ba1ff617e2c6.tar.zst
ferdium-app-537697a6e9757f118d09d9e76362ba1ff617e2c6.zip
chore: upgrade intl dependencies (#1920)
-rw-r--r--.eslintrc31
-rw-r--r--babel.config.json12
-rw-r--r--package-lock.json943
-rw-r--r--package.json11
-rw-r--r--src/I18n.js10
-rw-r--r--src/components/AppUpdateInfoBar.js16
-rw-r--r--src/components/auth/AuthLayout.js12
-rw-r--r--src/components/auth/ChangeServer.js79
-rw-r--r--src/components/auth/Import.js43
-rw-r--r--src/components/auth/Invite.js52
-rw-r--r--src/components/auth/Locked.js97
-rw-r--r--src/components/auth/Login.js132
-rw-r--r--src/components/auth/Password.js77
-rw-r--r--src/components/auth/SetupAssistant.js18
-rw-r--r--src/components/auth/Signup.js127
-rw-r--r--src/components/auth/Welcome.js57
-rw-r--r--src/components/layout/AppLayout.js18
-rw-r--r--src/components/layout/Sidebar.js108
-rw-r--r--src/components/services/content/ConnectionLostBanner.js16
-rw-r--r--src/components/services/content/ErrorHandlers/WebviewErrorHandler.js38
-rw-r--r--src/components/services/content/ServiceDisabled.js17
-rw-r--r--src/components/services/content/ServiceView.js43
-rw-r--r--src/components/services/content/Services.js103
-rw-r--r--src/components/services/content/WebviewCrashHandler.js26
-rw-r--r--src/components/services/tabs/TabItem.js46
-rw-r--r--src/components/services/tabs/Tabbar.js20
-rw-r--r--src/components/settings/SettingsLayout.js13
-rw-r--r--src/components/settings/account/AccountDashboard.js37
-rw-r--r--src/components/settings/navigation/SettingsNavigation.js49
-rw-r--r--src/components/settings/recipes/RecipeItem.js17
-rw-r--r--src/components/settings/recipes/RecipesDashboard.js83
-rw-r--r--src/components/settings/services/EditServiceForm.js157
-rw-r--r--src/components/settings/services/ServiceError.js26
-rw-r--r--src/components/settings/services/ServiceItem.js48
-rw-r--r--src/components/settings/services/ServicesDashboard.js52
-rw-r--r--src/components/settings/settings/EditSettingsForm.js527
-rw-r--r--src/components/settings/supportFerdi/SupportFerdiDashboard.js141
-rw-r--r--src/components/settings/team/TeamDashboard.js54
-rw-r--r--src/components/settings/user/EditUserForm.js39
-rw-r--r--src/components/ui/AppLoader/index.js10
-rw-r--r--src/components/ui/Button.js14
-rw-r--r--src/components/ui/FAB.js17
-rw-r--r--src/components/ui/FeatureList.js44
-rw-r--r--src/components/ui/FullscreenLoader/index.js23
-rw-r--r--src/components/ui/ImageUpload.js13
-rw-r--r--src/components/ui/InfoBar.js13
-rw-r--r--src/components/ui/Infobox.js13
-rw-r--r--src/components/ui/Input.js25
-rw-r--r--src/components/ui/Link.js14
-rw-r--r--src/components/ui/Loader.js17
-rw-r--r--src/components/ui/Modal/index.js19
-rw-r--r--src/components/ui/Radio.js26
-rw-r--r--src/components/ui/SearchInput.js30
-rw-r--r--src/components/ui/Select.js30
-rw-r--r--src/components/ui/Slider.js104
-rw-r--r--src/components/ui/StatusBarTargetUrl.js14
-rw-r--r--src/components/ui/Tabs/Tabs.js5
-rw-r--r--src/components/ui/Toggle.js20
-rw-r--r--src/components/ui/ToggleRaw.js20
-rw-r--r--src/components/ui/WebviewLoader/index.js16
-rw-r--r--src/components/util/ErrorBoundary/index.js19
-rw-r--r--src/containers/auth/AuthLayoutContainer.js3
-rw-r--r--src/containers/auth/ChangeServerScreen.js11
-rw-r--r--src/containers/auth/ImportScreen.js4
-rw-r--r--src/containers/auth/InviteScreen.js13
-rw-r--r--src/containers/auth/LockedScreen.js6
-rw-r--r--src/containers/auth/LoginScreen.js8
-rw-r--r--src/containers/auth/PasswordScreen.js4
-rw-r--r--src/containers/auth/SetupAssistantScreen.js3
-rw-r--r--src/containers/auth/SignupScreen.js8
-rw-r--r--src/containers/auth/WelcomeScreen.js6
-rw-r--r--src/containers/layout/AppLayoutContainer.js3
-rw-r--r--src/containers/settings/AccountScreen.js11
-rw-r--r--src/containers/settings/EditServiceScreen.js121
-rw-r--r--src/containers/settings/EditSettingsScreen.js166
-rw-r--r--src/containers/settings/EditUserScreen.js60
-rw-r--r--src/containers/settings/InviteScreen.js8
-rw-r--r--src/containers/settings/RecipesScreen.js92
-rw-r--r--src/containers/settings/ServicesScreen.js17
-rw-r--r--src/containers/settings/SettingsWindow.js21
-rw-r--r--src/containers/settings/SupportScreen.js9
-rw-r--r--src/containers/settings/TeamScreen.js11
-rw-r--r--src/features/basicAuth/Component.js41
-rw-r--r--src/features/nightlyBuilds/Component.js26
-rw-r--r--src/features/publishDebugInfo/Component.js94
-rw-r--r--src/features/quickSwitch/Component.js67
-rw-r--r--src/features/webControls/components/WebControls.js20
-rw-r--r--src/features/workspaces/components/CreateWorkspaceForm.js21
-rw-r--r--src/features/workspaces/components/EditWorkspaceForm.js34
-rw-r--r--src/features/workspaces/components/WorkspaceDrawer.js54
-rw-r--r--src/features/workspaces/components/WorkspaceDrawerItem.js21
-rw-r--r--src/features/workspaces/components/WorkspaceItem.js14
-rw-r--r--src/features/workspaces/components/WorkspaceSwitchingIndicator.js12
-rw-r--r--src/features/workspaces/components/WorkspacesDashboard.js26
-rw-r--r--src/helpers/validation-helpers.js50
-rw-r--r--src/i18n/apply-branding.js9
-rw-r--r--src/i18n/globalMessages.js38
-rw-r--r--src/i18n/locales/defaultMessages.json6862
-rw-r--r--src/i18n/locales/en-US.json115
-rw-r--r--src/i18n/manage-translations.js9
-rw-r--r--src/i18n/messages/src/components/AppUpdateInfoBar.json41
-rw-r--r--src/i18n/messages/src/components/auth/ChangeServer.json67
-rw-r--r--src/i18n/messages/src/components/auth/Import.json54
-rw-r--r--src/i18n/messages/src/components/auth/Invite.json93
-rw-r--r--src/i18n/messages/src/components/auth/Locked.json106
-rw-r--r--src/i18n/messages/src/components/auth/Login.json171
-rw-r--r--src/i18n/messages/src/components/auth/Password.json80
-rw-r--r--src/i18n/messages/src/components/auth/ServiceAssistant.json93
-rw-r--r--src/i18n/messages/src/components/auth/SetupAssistant.json54
-rw-r--r--src/i18n/messages/src/components/auth/Signup.json171
-rw-r--r--src/i18n/messages/src/components/auth/Welcome.json41
-rw-r--r--src/i18n/messages/src/components/layout/AppLayout.json54
-rw-r--r--src/i18n/messages/src/components/layout/Sidebar.json106
-rw-r--r--src/i18n/messages/src/components/services/content/ConnectionBanner.json67
-rw-r--r--src/i18n/messages/src/components/services/content/ConnectionLost.json67
-rw-r--r--src/i18n/messages/src/components/services/content/ConnectionLostBanner.json41
-rw-r--r--src/i18n/messages/src/components/services/content/ErrorHandlers/WebviewErrorHandler.json67
-rw-r--r--src/i18n/messages/src/components/services/content/ServiceDisabled.json28
-rw-r--r--src/i18n/messages/src/components/services/content/Services.json67
-rw-r--r--src/i18n/messages/src/components/services/content/WebControls.json67
-rw-r--r--src/i18n/messages/src/components/services/content/WebviewCrashHandler.json54
-rw-r--r--src/i18n/messages/src/components/services/tabs/TabItem.json171
-rw-r--r--src/i18n/messages/src/components/settings/SettingsLayout.json15
-rw-r--r--src/i18n/messages/src/components/settings/account/AccountDashboard.json158
-rw-r--r--src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json93
-rw-r--r--src/i18n/messages/src/components/settings/recipes/RecipesDashboard.json171
-rw-r--r--src/i18n/messages/src/components/settings/services/EditServiceForm.json340
-rw-r--r--src/i18n/messages/src/components/settings/services/ServiceError.json54
-rw-r--r--src/i18n/messages/src/components/settings/services/ServiceItem.json41
-rw-r--r--src/i18n/messages/src/components/settings/services/ServicesDashboard.json119
-rw-r--r--src/i18n/messages/src/components/settings/settings/EditSettingsForm.json444
-rw-r--r--src/i18n/messages/src/components/settings/supportFerdi/SupportFerdiDashboard.json197
-rw-r--r--src/i18n/messages/src/components/settings/team/TeamDashboard.json93
-rw-r--r--src/i18n/messages/src/components/settings/user/EditUserForm.json80
-rw-r--r--src/i18n/messages/src/components/ui/FeatureList.json145
-rw-r--r--src/i18n/messages/src/components/ui/InfoBar.json15
-rw-r--r--src/i18n/messages/src/components/ui/Infobox.json15
-rw-r--r--src/i18n/messages/src/components/ui/Input.json15
-rw-r--r--src/i18n/messages/src/components/ui/WebviewLoader/index.json15
-rw-r--r--src/i18n/messages/src/components/util/ErrorBoundary/index.json28
-rw-r--r--src/i18n/messages/src/containers/settings/EditServiceScreen.json249
-rw-r--r--src/i18n/messages/src/containers/settings/EditSettingsScreen.json600
-rw-r--r--src/i18n/messages/src/containers/settings/EditUserScreen.json119
-rw-r--r--src/i18n/messages/src/features/basicAuth/Component.json15
-rw-r--r--src/i18n/messages/src/features/debugger/Component.json15
-rw-r--r--src/i18n/messages/src/features/nightlyBuilds/Component.json41
-rw-r--r--src/i18n/messages/src/features/publishDebugInfo/Component.json93
-rw-r--r--src/i18n/messages/src/features/quickSwitch/Component.json41
-rw-r--r--src/i18n/messages/src/features/recipeConnectionLost/components/WebControls.json67
-rw-r--r--src/i18n/messages/src/features/webControls/components/WebControls.json67
-rw-r--r--src/i18n/messages/src/features/workspaces/components/CreateWorkspaceForm.json28
-rw-r--r--src/i18n/messages/src/features/workspaces/components/EditWorkspaceForm.json119
-rw-r--r--src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json67
-rw-r--r--src/i18n/messages/src/features/workspaces/components/WorkspaceDrawerItem.json28
-rw-r--r--src/i18n/messages/src/features/workspaces/components/WorkspaceSwitchingIndicator.json15
-rw-r--r--src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json106
-rw-r--r--src/i18n/messages/src/helpers/validation-helpers.json67
-rw-r--r--src/i18n/messages/src/i18n/globalMessages.json236
-rw-r--r--src/i18n/messages/src/lib/Menu.json912
-rw-r--r--src/lib/Menu.js145
-rw-r--r--src/routes.js3
161 files changed, 3117 insertions, 15713 deletions
diff --git a/.eslintrc b/.eslintrc
index 47811e7be..121f28eda 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -2,23 +2,16 @@
2 "root": true, 2 "root": true,
3 "parser": "@babel/eslint-parser", 3 "parser": "@babel/eslint-parser",
4 "extends": "eslint-config-airbnb", 4 "extends": "eslint-config-airbnb",
5 "plugins": [ 5 "plugins": ["jest"],
6 "jest"
7 ],
8 "overrides": [ 6 "overrides": [
9 { 7 {
10 "files": [ 8 "files": ["**/*.ts", "**/*.tsx"],
11 "**/*.ts",
12 "**/*.tsx"
13 ],
14 "env": { 9 "env": {
15 "browser": true, 10 "browser": true,
16 "es6": true, 11 "es6": true,
17 "node": true 12 "node": true
18 }, 13 },
19 "extends": [ 14 "extends": ["airbnb-typescript"],
20 "airbnb-typescript"
21 ],
22 "parser": "@typescript-eslint/parser", 15 "parser": "@typescript-eslint/parser",
23 "parserOptions": { 16 "parserOptions": {
24 "ecmaFeatures": { 17 "ecmaFeatures": {
@@ -28,9 +21,7 @@
28 "sourceType": "module", 21 "sourceType": "module",
29 "project": "./tsconfig.json" 22 "project": "./tsconfig.json"
30 }, 23 },
31 "plugins": [ 24 "plugins": ["@typescript-eslint"],
32 "@typescript-eslint"
33 ],
34 "rules": { 25 "rules": {
35 // eslint 26 // eslint
36 "arrow-parens": 0, 27 "arrow-parens": 0,
@@ -79,13 +70,9 @@
79 "jsx-a11y/label-has-for": [ 70 "jsx-a11y/label-has-for": [
80 2, 71 2,
81 { 72 {
82 "components": [ 73 "components": ["Label"],
83 "Label"
84 ],
85 "required": { 74 "required": {
86 "every": [ 75 "every": ["id"]
87 "id"
88 ]
89 }, 76 },
90 "allowChildren": false 77 "allowChildren": false
91 } 78 }
@@ -126,10 +113,7 @@
126 "no-console": [ 113 "no-console": [
127 1, 114 1,
128 { 115 {
129 "allow": [ 116 "allow": ["warn", "error"]
130 "warn",
131 "error"
132 ]
133 } 117 }
134 ], 118 ],
135 "no-param-reassign": 1, 119 "no-param-reassign": 1,
@@ -152,6 +136,7 @@
152 "react/jsx-no-bind": 1, 136 "react/jsx-no-bind": 1,
153 "react/jsx-props-no-spreading": 0, 137 "react/jsx-props-no-spreading": 0,
154 "react/prefer-stateless-function": 1, 138 "react/prefer-stateless-function": 1,
139 "react/prop-types": 0,
155 "react/static-property-placement": 0, 140 "react/static-property-placement": 0,
156 "react/state-in-constructor": 1, 141 "react/state-in-constructor": 1,
157 "react/sort-comp": 0, 142 "react/sort-comp": 0,
diff --git a/babel.config.json b/babel.config.json
index 034e51ce5..d24207a8c 100644
--- a/babel.config.json
+++ b/babel.config.json
@@ -1,8 +1,5 @@
1{ 1{
2 "babelrcRoots": [ 2 "babelrcRoots": [".", "packages/*"],
3 ".",
4 "packages/*"
5 ],
6 "presets": [ 3 "presets": [
7 [ 4 [
8 "@babel/preset-env", 5 "@babel/preset-env",
@@ -31,11 +28,10 @@
31 "@babel/proposal-throw-expressions", 28 "@babel/proposal-throw-expressions",
32 "@babel/syntax-dynamic-import", 29 "@babel/syntax-dynamic-import",
33 [ 30 [
34 "react-intl", 31 "formatjs",
35 { 32 {
36 "messagesDir": "./src/i18n/messages/", 33 "idInterpolationPattern": "[sha512:contenthash:base64:6]",
37 "enforceDescriptions": false, 34 "ast": true
38 "extractSourceLocation": true
39 } 35 }
40 ], 36 ],
41 [ 37 [
diff --git a/package-lock.json b/package-lock.json
index 8188513d5..56dd732c2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2488,6 +2488,233 @@
2488 } 2488 }
2489 } 2489 }
2490 }, 2490 },
2491 "@formatjs/cli": {
2492 "version": "4.2.33",
2493 "resolved": "https://registry.npmjs.org/@formatjs/cli/-/cli-4.2.33.tgz",
2494 "integrity": "sha512-4Lg+KZ5QhXgF6+zjHyZlxMG8I0D3m3PZyrj3hRl97vdZ6rAWKVFWw8fkTO/iyhUCP2iC47Eh9r+ZTgGARX9Teg==",
2495 "dev": true,
2496 "requires": {
2497 "@formatjs/icu-messageformat-parser": "2.0.11",
2498 "@formatjs/ts-transformer": "3.4.10",
2499 "@types/estree": "^0.0.50",
2500 "@types/fs-extra": "^9.0.1",
2501 "@types/json-stable-stringify": "^1.0.32",
2502 "@types/node": "14",
2503 "@vue/compiler-core": "^3.0.5",
2504 "@vue/compiler-sfc": "^3.0.5",
2505 "chalk": "^4.0.0",
2506 "commander": "8",
2507 "fast-glob": "^3.2.7",
2508 "fs-extra": "10",
2509 "json-stable-stringify": "^1.0.1",
2510 "loud-rejection": "^2.2.0",
2511 "tslib": "^2.1.0",
2512 "typescript": "4"
2513 },
2514 "dependencies": {
2515 "ansi-styles": {
2516 "version": "4.3.0",
2517 "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
2518 "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
2519 "dev": true,
2520 "requires": {
2521 "color-convert": "^2.0.1"
2522 }
2523 },
2524 "chalk": {
2525 "version": "4.1.2",
2526 "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
2527 "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
2528 "dev": true,
2529 "requires": {
2530 "ansi-styles": "^4.1.0",
2531 "supports-color": "^7.1.0"
2532 }
2533 },
2534 "color-convert": {
2535 "version": "2.0.1",
2536 "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
2537 "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
2538 "dev": true,
2539 "requires": {
2540 "color-name": "~1.1.4"
2541 }
2542 },
2543 "color-name": {
2544 "version": "1.1.4",
2545 "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
2546 "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
2547 "dev": true
2548 },
2549 "commander": {
2550 "version": "8.2.0",
2551 "resolved": "https://registry.npmjs.org/commander/-/commander-8.2.0.tgz",
2552 "integrity": "sha512-LLKxDvHeL91/8MIyTAD5BFMNtoIwztGPMiM/7Bl8rIPmHCZXRxmSWr91h57dpOpnQ6jIUqEWdXE/uBYMfiVZDA==",
2553 "dev": true
2554 },
2555 "has-flag": {
2556 "version": "4.0.0",
2557 "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
2558 "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
2559 "dev": true
2560 },
2561 "supports-color": {
2562 "version": "7.2.0",
2563 "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
2564 "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
2565 "dev": true,
2566 "requires": {
2567 "has-flag": "^4.0.0"
2568 }
2569 },
2570 "typescript": {
2571 "version": "4.4.3",
2572 "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz",
2573 "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==",
2574 "dev": true
2575 }
2576 }
2577 },
2578 "@formatjs/ecma402-abstract": {
2579 "version": "1.9.8",
2580 "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.9.8.tgz",
2581 "integrity": "sha512-2U4n11bLmTij/k4ePCEFKJILPYwdMcJTdnKVBi+JMWBgu5O1N+XhCazlE6QXqVO1Agh2Doh0b/9Jf1mSmSVfhA==",
2582 "requires": {
2583 "@formatjs/intl-localematcher": "0.2.20",
2584 "tslib": "^2.1.0"
2585 }
2586 },
2587 "@formatjs/fast-memoize": {
2588 "version": "1.2.0",
2589 "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-1.2.0.tgz",
2590 "integrity": "sha512-fObitP9Tlc31SKrPHgkPgQpGo4+4yXfQQITTCNH8AZdEqB7Mq4nPrjpUL/tNGN3lEeJcFxDbi0haX8HM7QvQ8w==",
2591 "requires": {
2592 "tslib": "^2.1.0"
2593 }
2594 },
2595 "@formatjs/icu-messageformat-parser": {
2596 "version": "2.0.11",
2597 "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.0.11.tgz",
2598 "integrity": "sha512-5mWb8U8aulYGwnDZWrr+vdgn5PilvtrqQYQ1pvpgzQes/osi85TwmL2GqTGLlKIvBKD2XNA61kAqXYY95w4LWg==",
2599 "requires": {
2600 "@formatjs/ecma402-abstract": "1.9.8",
2601 "@formatjs/icu-skeleton-parser": "1.2.12",
2602 "tslib": "^2.1.0"
2603 }
2604 },
2605 "@formatjs/icu-skeleton-parser": {
2606 "version": "1.2.12",
2607 "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.2.12.tgz",
2608 "integrity": "sha512-DTFxWmEA02ZNW6fsYjGYSADvtrqqjCYF7DSgCmMfaaE0gLP4pCdAgOPE+lkXXU+jP8iCw/YhMT2Seyk/C5lBWg==",
2609 "requires": {
2610 "@formatjs/ecma402-abstract": "1.9.8",
2611 "tslib": "^2.1.0"
2612 }
2613 },
2614 "@formatjs/intl": {
2615 "version": "1.14.1",
2616 "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-1.14.1.tgz",
2617 "integrity": "sha512-mtL8oBgFwTu0GHFnxaF93fk/zNzNkPzl+27Fwg5AZ88pWHWb7037dpODzoCBnaIVk4FBO5emUn/6jI9Byj8hOw==",
2618 "requires": {
2619 "@formatjs/ecma402-abstract": "1.9.8",
2620 "@formatjs/fast-memoize": "1.2.0",
2621 "@formatjs/icu-messageformat-parser": "2.0.11",
2622 "@formatjs/intl-displaynames": "5.2.3",
2623 "@formatjs/intl-listformat": "6.3.3",
2624 "intl-messageformat": "9.9.1",
2625 "tslib": "^2.1.0"
2626 }
2627 },
2628 "@formatjs/intl-displaynames": {
2629 "version": "5.2.3",
2630 "resolved": "https://registry.npmjs.org/@formatjs/intl-displaynames/-/intl-displaynames-5.2.3.tgz",
2631 "integrity": "sha512-5BmhSurLbfgdeo0OBcNPPkIS8ikMMYaHe2NclxEQZqcMvrnQzNMNnUE2dDF5vZx+mkvKq77aQYzpc8RfqVsRCQ==",
2632 "requires": {
2633 "@formatjs/ecma402-abstract": "1.9.8",
2634 "@formatjs/intl-localematcher": "0.2.20",
2635 "tslib": "^2.1.0"
2636 }
2637 },
2638 "@formatjs/intl-listformat": {
2639 "version": "6.3.3",
2640 "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-6.3.3.tgz",
2641 "integrity": "sha512-3nzAKgVS5rePDa5HiH0OwZgAhqxLtzlMc9Pg4QgajRHSP1TqFiMmQnnn52wd3+xVTb7cjZVm3JBnTv51/MhTOg==",
2642 "requires": {
2643 "@formatjs/ecma402-abstract": "1.9.8",
2644 "@formatjs/intl-localematcher": "0.2.20",
2645 "tslib": "^2.1.0"
2646 }
2647 },
2648 "@formatjs/intl-localematcher": {
2649 "version": "0.2.20",
2650 "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.20.tgz",
2651 "integrity": "sha512-/Ro85goRZnCojzxOegANFYL0LaDIpdPjAukR7xMTjOtRx+3yyjR0ifGTOW3/Kjhmab3t6GnyHBYWZSudxEOxPA==",
2652 "requires": {
2653 "tslib": "^2.1.0"
2654 }
2655 },
2656 "@formatjs/ts-transformer": {
2657 "version": "3.4.10",
2658 "resolved": "https://registry.npmjs.org/@formatjs/ts-transformer/-/ts-transformer-3.4.10.tgz",
2659 "integrity": "sha512-5fu8x+8CtyrFe8zdwHvFsYLx9TEPjeJSODRS1ZJxkMVpTBHaNsPqsPkN1TuTk5x3+tSczxXmN1LGrAzUxNN3nQ==",
2660 "dev": true,
2661 "requires": {
2662 "@formatjs/icu-messageformat-parser": "2.0.11",
2663 "chalk": "^4.0.0",
2664 "tslib": "^2.1.0"
2665 },
2666 "dependencies": {
2667 "ansi-styles": {
2668 "version": "4.3.0",
2669 "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
2670 "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
2671 "dev": true,
2672 "requires": {
2673 "color-convert": "^2.0.1"
2674 }
2675 },
2676 "chalk": {
2677 "version": "4.1.2",
2678 "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
2679 "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
2680 "dev": true,
2681 "requires": {
2682 "ansi-styles": "^4.1.0",
2683 "supports-color": "^7.1.0"
2684 }
2685 },
2686 "color-convert": {
2687 "version": "2.0.1",
2688 "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
2689 "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
2690 "dev": true,
2691 "requires": {
2692 "color-name": "~1.1.4"
2693 }
2694 },
2695 "color-name": {
2696 "version": "1.1.4",
2697 "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
2698 "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
2699 "dev": true
2700 },
2701 "has-flag": {
2702 "version": "4.0.0",
2703 "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
2704 "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
2705 "dev": true
2706 },
2707 "supports-color": {
2708 "version": "7.2.0",
2709 "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
2710 "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
2711 "dev": true,
2712 "requires": {
2713 "has-flag": "^4.0.0"
2714 }
2715 }
2716 }
2717 },
2491 "@hapi/hoek": { 2718 "@hapi/hoek": {
2492 "version": "9.2.0", 2719 "version": "9.2.0",
2493 "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz", 2720 "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz",
@@ -6414,6 +6641,15 @@
6414 "@babel/types": "^7.0.0" 6641 "@babel/types": "^7.0.0"
6415 } 6642 }
6416 }, 6643 },
6644 "@types/babel__helper-plugin-utils": {
6645 "version": "7.10.0",
6646 "resolved": "https://registry.npmjs.org/@types/babel__helper-plugin-utils/-/babel__helper-plugin-utils-7.10.0.tgz",
6647 "integrity": "sha512-60YtHzhQ9HAkToHVV+TB4VLzBn9lrfgrsOjiJMtbv/c1jPdekBxaByd6DMsGBzROXWoIL6U3lEFvvbu69RkUoA==",
6648 "dev": true,
6649 "requires": {
6650 "@types/babel__core": "*"
6651 }
6652 },
6417 "@types/babel__template": { 6653 "@types/babel__template": {
6418 "version": "7.4.1", 6654 "version": "7.4.1",
6419 "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", 6655 "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz",
@@ -6472,6 +6708,12 @@
6472 "integrity": "sha512-vwNP+pzkI1ipznek2fCA4xj1kQyL9EJcfdBezD9eToe9eP2IgT3WLEBrVqiXal34LOyiAs8xCQKwugEYOKcMkw==", 6708 "integrity": "sha512-vwNP+pzkI1ipznek2fCA4xj1kQyL9EJcfdBezD9eToe9eP2IgT3WLEBrVqiXal34LOyiAs8xCQKwugEYOKcMkw==",
6473 "dev": true 6709 "dev": true
6474 }, 6710 },
6711 "@types/estree": {
6712 "version": "0.0.50",
6713 "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz",
6714 "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==",
6715 "dev": true
6716 },
6475 "@types/expect.js": { 6717 "@types/expect.js": {
6476 "version": "0.3.29", 6718 "version": "0.3.29",
6477 "resolved": "https://registry.npmjs.org/@types/expect.js/-/expect.js-0.3.29.tgz", 6719 "resolved": "https://registry.npmjs.org/@types/expect.js/-/expect.js-0.3.29.tgz",
@@ -6506,6 +6748,15 @@
6506 "@types/node": "*" 6748 "@types/node": "*"
6507 } 6749 }
6508 }, 6750 },
6751 "@types/hoist-non-react-statics": {
6752 "version": "3.3.1",
6753 "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
6754 "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
6755 "requires": {
6756 "@types/react": "*",
6757 "hoist-non-react-statics": "^3.3.0"
6758 }
6759 },
6509 "@types/html-minifier-terser": { 6760 "@types/html-minifier-terser": {
6510 "version": "5.1.2", 6761 "version": "5.1.2",
6511 "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz", 6762 "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz",
@@ -6542,6 +6793,12 @@
6542 "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", 6793 "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==",
6543 "dev": true 6794 "dev": true
6544 }, 6795 },
6796 "@types/json-stable-stringify": {
6797 "version": "1.0.33",
6798 "resolved": "https://registry.npmjs.org/@types/json-stable-stringify/-/json-stable-stringify-1.0.33.tgz",
6799 "integrity": "sha512-qEWiQff6q2tA5gcJGWwzplQcXdJtm+0oy6IHGHzlOf3eFAkGE/FIPXZK9ofWgNSHVp8AFFI33PJJshS0ei3Gvw==",
6800 "dev": true
6801 },
6545 "@types/json5": { 6802 "@types/json5": {
6546 "version": "0.0.29", 6803 "version": "0.0.29",
6547 "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", 6804 "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -6625,14 +6882,12 @@
6625 "@types/prop-types": { 6882 "@types/prop-types": {
6626 "version": "15.7.4", 6883 "version": "15.7.4",
6627 "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", 6884 "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz",
6628 "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", 6885 "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ=="
6629 "dev": true
6630 }, 6886 },
6631 "@types/react": { 6887 "@types/react": {
6632 "version": "16.14.6", 6888 "version": "16.14.6",
6633 "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.6.tgz", 6889 "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.6.tgz",
6634 "integrity": "sha512-Ol/aFKune+P0FSFKIgf+XbhGzYGyz0p7g5befSt4rmbzfGLaZR0q7jPew9k7d3bvrcuaL8dPy9Oz3XGZmf9n+w==", 6890 "integrity": "sha512-Ol/aFKune+P0FSFKIgf+XbhGzYGyz0p7g5befSt4rmbzfGLaZR0q7jPew9k7d3bvrcuaL8dPy9Oz3XGZmf9n+w==",
6635 "dev": true,
6636 "requires": { 6891 "requires": {
6637 "@types/prop-types": "*", 6892 "@types/prop-types": "*",
6638 "@types/scheduler": "*", 6893 "@types/scheduler": "*",
@@ -6657,8 +6912,7 @@
6657 "@types/scheduler": { 6912 "@types/scheduler": {
6658 "version": "0.16.2", 6913 "version": "0.16.2",
6659 "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", 6914 "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
6660 "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", 6915 "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
6661 "dev": true
6662 }, 6916 },
6663 "@types/semver": { 6917 "@types/semver": {
6664 "version": "7.3.8", 6918 "version": "7.3.8",
@@ -7011,6 +7265,121 @@
7011 "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", 7265 "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==",
7012 "dev": true 7266 "dev": true
7013 }, 7267 },
7268 "@vue/compiler-core": {
7269 "version": "3.2.11",
7270 "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.11.tgz",
7271 "integrity": "sha512-bcbsLx5XyQg8WDDEGwmpX0BfEfv82wIs9fWFelpyVhNRGMaABvUTalYINyfhVT+jOqNaD4JBhJiVKd/8TmsHWg==",
7272 "dev": true,
7273 "requires": {
7274 "@babel/parser": "^7.15.0",
7275 "@babel/types": "^7.15.0",
7276 "@vue/shared": "3.2.11",
7277 "estree-walker": "^2.0.2",
7278 "source-map": "^0.6.1"
7279 },
7280 "dependencies": {
7281 "source-map": {
7282 "version": "0.6.1",
7283 "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
7284 "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
7285 "dev": true
7286 }
7287 }
7288 },
7289 "@vue/compiler-dom": {
7290 "version": "3.2.11",
7291 "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.11.tgz",
7292 "integrity": "sha512-DNvhUHI/1Hn0/+ZYDYGAuDGasUm+XHKC3FE4GqkNCTO/fcLaJMRg/7eT1m1lkc7jPffUwwfh1rZru5mwzOjrNw==",
7293 "dev": true,
7294 "requires": {
7295 "@vue/compiler-core": "3.2.11",
7296 "@vue/shared": "3.2.11"
7297 }
7298 },
7299 "@vue/compiler-sfc": {
7300 "version": "3.2.11",
7301 "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.11.tgz",
7302 "integrity": "sha512-cUIaS8mgJrQ6yucj2AupWAwBRITK3W/a8wCOn9g5fJGtOl8h4APY8vN3lzP8HIJDyEeRF3I8SfRhL+oX97kSnw==",
7303 "dev": true,
7304 "requires": {
7305 "@babel/parser": "^7.15.0",
7306 "@babel/types": "^7.15.0",
7307 "@types/estree": "^0.0.48",
7308 "@vue/compiler-core": "3.2.11",
7309 "@vue/compiler-dom": "3.2.11",
7310 "@vue/compiler-ssr": "3.2.11",
7311 "@vue/ref-transform": "3.2.11",
7312 "@vue/shared": "3.2.11",
7313 "consolidate": "^0.16.0",
7314 "estree-walker": "^2.0.2",
7315 "hash-sum": "^2.0.0",
7316 "lru-cache": "^5.1.1",
7317 "magic-string": "^0.25.7",
7318 "merge-source-map": "^1.1.0",
7319 "postcss": "^8.1.10",
7320 "postcss-modules": "^4.0.0",
7321 "postcss-selector-parser": "^6.0.4",
7322 "source-map": "^0.6.1"
7323 },
7324 "dependencies": {
7325 "@types/estree": {
7326 "version": "0.0.48",
7327 "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.48.tgz",
7328 "integrity": "sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew==",
7329 "dev": true
7330 },
7331 "lru-cache": {
7332 "version": "5.1.1",
7333 "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
7334 "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
7335 "dev": true,
7336 "requires": {
7337 "yallist": "^3.0.2"
7338 }
7339 },
7340 "source-map": {
7341 "version": "0.6.1",
7342 "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
7343 "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
7344 "dev": true
7345 },
7346 "yallist": {
7347 "version": "3.1.1",
7348 "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
7349 "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
7350 "dev": true
7351 }
7352 }
7353 },
7354 "@vue/compiler-ssr": {
7355 "version": "3.2.11",
7356 "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.11.tgz",
7357 "integrity": "sha512-+ptAdUlFDij+Z0VGCbRRkxQlNev5LkbZAntvkxrFjc08CTMhZmiV4Js48n2hAmuSXaKNEpmGkDGU26c/vf1+xw==",
7358 "dev": true,
7359 "requires": {
7360 "@vue/compiler-dom": "3.2.11",
7361 "@vue/shared": "3.2.11"
7362 }
7363 },
7364 "@vue/ref-transform": {
7365 "version": "3.2.11",
7366 "resolved": "https://registry.npmjs.org/@vue/ref-transform/-/ref-transform-3.2.11.tgz",
7367 "integrity": "sha512-7rX0YsfYb7+1PeKPME1tQyUQcQgt0sIXRRnPD1Vw8Zs2KIo90YLy9CrvwalcRCxGw0ScsjBEhVjJtWIT79TElg==",
7368 "dev": true,
7369 "requires": {
7370 "@babel/parser": "^7.15.0",
7371 "@vue/compiler-core": "3.2.11",
7372 "@vue/shared": "3.2.11",
7373 "estree-walker": "^2.0.2",
7374 "magic-string": "^0.25.7"
7375 }
7376 },
7377 "@vue/shared": {
7378 "version": "3.2.11",
7379 "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.11.tgz",
7380 "integrity": "sha512-ovfXAsSsCvV9JVceWjkqC/7OF5HbgLOtCWjCIosmPGG8lxbPuavhIxRH1dTx4Dg9xLgRTNLvI3pVxG4ItQZekg==",
7381 "dev": true
7382 },
7014 "@webassemblyjs/ast": { 7383 "@webassemblyjs/ast": {
7015 "version": "1.9.0", 7384 "version": "1.9.0",
7016 "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", 7385 "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
@@ -8105,6 +8474,12 @@
8105 "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", 8474 "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz",
8106 "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=" 8475 "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8="
8107 }, 8476 },
8477 "array-find-index": {
8478 "version": "1.0.2",
8479 "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
8480 "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
8481 "dev": true
8482 },
8108 "array-flatten": { 8483 "array-flatten": {
8109 "version": "2.1.2", 8484 "version": "2.1.2",
8110 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", 8485 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
@@ -8543,6 +8918,86 @@
8543 "object.assign": "^4.1.0" 8918 "object.assign": "^4.1.0"
8544 } 8919 }
8545 }, 8920 },
8921 "babel-plugin-formatjs": {
8922 "version": "10.3.8",
8923 "resolved": "https://registry.npmjs.org/babel-plugin-formatjs/-/babel-plugin-formatjs-10.3.8.tgz",
8924 "integrity": "sha512-pLryt/Q5zmoQWRrybzwiaZ9i0M9I1JJwshHqOuyxn+MlqcxArp2N0E7/X9fhIC1X9yEdDV0zfGbY00J+krmZzQ==",
8925 "dev": true,
8926 "requires": {
8927 "@babel/core": "^7.10.4",
8928 "@babel/helper-plugin-utils": "^7.10.4",
8929 "@babel/plugin-syntax-jsx": "7",
8930 "@babel/traverse": "7",
8931 "@babel/types": "^7.12.11",
8932 "@formatjs/icu-messageformat-parser": "2.0.11",
8933 "@formatjs/ts-transformer": "3.4.10",
8934 "@types/babel__core": "^7.1.7",
8935 "@types/babel__helper-plugin-utils": "^7.10.0",
8936 "tslib": "^2.1.0"
8937 },
8938 "dependencies": {
8939 "@formatjs/ts-transformer": {
8940 "version": "3.4.10",
8941 "resolved": "https://registry.npmjs.org/@formatjs/ts-transformer/-/ts-transformer-3.4.10.tgz",
8942 "integrity": "sha512-5fu8x+8CtyrFe8zdwHvFsYLx9TEPjeJSODRS1ZJxkMVpTBHaNsPqsPkN1TuTk5x3+tSczxXmN1LGrAzUxNN3nQ==",
8943 "dev": true,
8944 "requires": {
8945 "@formatjs/icu-messageformat-parser": "2.0.11",
8946 "chalk": "^4.0.0",
8947 "tslib": "^2.1.0"
8948 }
8949 },
8950 "ansi-styles": {
8951 "version": "4.3.0",
8952 "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
8953 "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
8954 "dev": true,
8955 "requires": {
8956 "color-convert": "^2.0.1"
8957 }
8958 },
8959 "chalk": {
8960 "version": "4.1.2",
8961 "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
8962 "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
8963 "dev": true,
8964 "requires": {
8965 "ansi-styles": "^4.1.0",
8966 "supports-color": "^7.1.0"
8967 }
8968 },
8969 "color-convert": {
8970 "version": "2.0.1",
8971 "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
8972 "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
8973 "dev": true,
8974 "requires": {
8975 "color-name": "~1.1.4"
8976 }
8977 },
8978 "color-name": {
8979 "version": "1.1.4",
8980 "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
8981 "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
8982 "dev": true
8983 },
8984 "has-flag": {
8985 "version": "4.0.0",
8986 "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
8987 "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
8988 "dev": true
8989 },
8990 "supports-color": {
8991 "version": "7.2.0",
8992 "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
8993 "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
8994 "dev": true,
8995 "requires": {
8996 "has-flag": "^4.0.0"
8997 }
8998 }
8999 }
9000 },
8546 "babel-plugin-istanbul": { 9001 "babel-plugin-istanbul": {
8547 "version": "6.0.0", 9002 "version": "6.0.0",
8548 "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", 9003 "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz",
@@ -8606,38 +9061,6 @@
8606 "@babel/helper-define-polyfill-provider": "^0.2.2" 9061 "@babel/helper-define-polyfill-provider": "^0.2.2"
8607 } 9062 }
8608 }, 9063 },
8609 "babel-plugin-react-intl": {
8610 "version": "3.5.1",
8611 "resolved": "https://registry.npmjs.org/babel-plugin-react-intl/-/babel-plugin-react-intl-3.5.1.tgz",
8612 "integrity": "sha512-1jlEJCSmLaJM4tjIKpu64UZ833COCHmwR77bFJDOye+zlwf80uR1b8p41l4tClx1QsrfI+qV6w/5AiPYQgaMUQ==",
8613 "dev": true,
8614 "requires": {
8615 "@babel/core": "^7.4.5",
8616 "@babel/helper-plugin-utils": "^7.0.0",
8617 "@types/babel__core": "^7.1.2",
8618 "fs-extra": "^8.0.1",
8619 "intl-messageformat-parser": "^1.8.1"
8620 },
8621 "dependencies": {
8622 "fs-extra": {
8623 "version": "8.1.0",
8624 "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
8625 "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
8626 "dev": true,
8627 "requires": {
8628 "graceful-fs": "^4.2.0",
8629 "jsonfile": "^4.0.0",
8630 "universalify": "^0.1.0"
8631 }
8632 },
8633 "intl-messageformat-parser": {
8634 "version": "1.8.1",
8635 "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.8.1.tgz",
8636 "integrity": "sha512-IMSCKVf0USrM/959vj3xac7s8f87sc+80Y/ipBzdKy4ifBv5Gsj2tZ41EAaURVg01QU71fYr77uA8Meh6kELbg==",
8637 "dev": true
8638 }
8639 }
8640 },
8641 "babel-preset-current-node-syntax": { 9064 "babel-preset-current-node-syntax": {
8642 "version": "1.0.1", 9065 "version": "1.0.1",
8643 "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", 9066 "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
@@ -9921,6 +10344,31 @@
9921 "node-addon-api": "*", 10344 "node-addon-api": "*",
9922 "rimraf": "^2.4.0", 10345 "rimraf": "^2.4.0",
9923 "underscore": "^1.6.0" 10346 "underscore": "^1.6.0"
10347 },
10348 "dependencies": {
10349 "rimraf": {
10350 "version": "2.7.1",
10351 "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
10352 "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
10353 "requires": {
10354 "glob": "^7.1.3"
10355 },
10356 "dependencies": {
10357 "glob": {
10358 "version": "7.1.7",
10359 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
10360 "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
10361 "requires": {
10362 "fs.realpath": "^1.0.0",
10363 "inflight": "^1.0.4",
10364 "inherits": "2",
10365 "minimatch": "^3.0.4",
10366 "once": "^1.3.0",
10367 "path-is-absolute": "^1.0.0"
10368 }
10369 }
10370 }
10371 }
9924 } 10372 }
9925 }, 10373 },
9926 "clean-css": { 10374 "clean-css": {
@@ -10807,6 +11255,15 @@
10807 "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", 11255 "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
10808 "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" 11256 "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
10809 }, 11257 },
11258 "consolidate": {
11259 "version": "0.16.0",
11260 "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.16.0.tgz",
11261 "integrity": "sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ==",
11262 "dev": true,
11263 "requires": {
11264 "bluebird": "^3.7.2"
11265 }
11266 },
10810 "constants-browserify": { 11267 "constants-browserify": {
10811 "version": "1.0.0", 11268 "version": "1.0.0",
10812 "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", 11269 "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
@@ -11282,6 +11739,31 @@
11282 "mkdirp": "^0.5.1", 11739 "mkdirp": "^0.5.1",
11283 "rimraf": "^2.5.4", 11740 "rimraf": "^2.5.4",
11284 "run-queue": "^1.0.0" 11741 "run-queue": "^1.0.0"
11742 },
11743 "dependencies": {
11744 "glob": {
11745 "version": "7.1.7",
11746 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
11747 "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
11748 "dev": true,
11749 "requires": {
11750 "fs.realpath": "^1.0.0",
11751 "inflight": "^1.0.4",
11752 "inherits": "2",
11753 "minimatch": "^3.0.4",
11754 "once": "^1.3.0",
11755 "path-is-absolute": "^1.0.0"
11756 }
11757 },
11758 "rimraf": {
11759 "version": "2.7.1",
11760 "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
11761 "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
11762 "dev": true,
11763 "requires": {
11764 "glob": "^7.1.3"
11765 }
11766 }
11285 } 11767 }
11286 }, 11768 },
11287 "copy-descriptor": { 11769 "copy-descriptor": {
@@ -11609,6 +12091,12 @@
11609 "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", 12091 "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==",
11610 "dev": true 12092 "dev": true
11611 }, 12093 },
12094 "cssesc": {
12095 "version": "3.0.0",
12096 "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
12097 "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
12098 "dev": true
12099 },
11612 "csso": { 12100 "csso": {
11613 "version": "4.2.0", 12101 "version": "4.2.0",
11614 "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", 12102 "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz",
@@ -11646,6 +12134,15 @@
11646 "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz", 12134 "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz",
11647 "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==" 12135 "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw=="
11648 }, 12136 },
12137 "currently-unhandled": {
12138 "version": "0.4.1",
12139 "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
12140 "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
12141 "dev": true,
12142 "requires": {
12143 "array-find-index": "^1.0.1"
12144 }
12145 },
11649 "cyclist": { 12146 "cyclist": {
11650 "version": "1.0.1", 12147 "version": "1.0.1",
11651 "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", 12148 "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
@@ -12024,6 +12521,15 @@
12024 "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", 12521 "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
12025 "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", 12522 "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
12026 "dev": true 12523 "dev": true
12524 },
12525 "rimraf": {
12526 "version": "2.7.1",
12527 "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
12528 "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
12529 "dev": true,
12530 "requires": {
12531 "glob": "^7.1.3"
12532 }
12027 } 12533 }
12028 } 12534 }
12029 }, 12535 },
@@ -14001,6 +14507,12 @@
14001 "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 14507 "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
14002 "dev": true 14508 "dev": true
14003 }, 14509 },
14510 "estree-walker": {
14511 "version": "2.0.2",
14512 "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
14513 "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
14514 "dev": true
14515 },
14004 "esutils": { 14516 "esutils": {
14005 "version": "2.0.3", 14517 "version": "2.0.3",
14006 "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 14518 "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -15177,6 +15689,31 @@
15177 "inherits": "~2.0.0", 15689 "inherits": "~2.0.0",
15178 "mkdirp": ">=0.5 0", 15690 "mkdirp": ">=0.5 0",
15179 "rimraf": "2" 15691 "rimraf": "2"
15692 },
15693 "dependencies": {
15694 "glob": {
15695 "version": "7.1.7",
15696 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
15697 "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
15698 "optional": true,
15699 "requires": {
15700 "fs.realpath": "^1.0.0",
15701 "inflight": "^1.0.4",
15702 "inherits": "2",
15703 "minimatch": "^3.0.4",
15704 "once": "^1.3.0",
15705 "path-is-absolute": "^1.0.0"
15706 }
15707 },
15708 "rimraf": {
15709 "version": "2.7.1",
15710 "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
15711 "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
15712 "optional": true,
15713 "requires": {
15714 "glob": "^7.1.3"
15715 }
15716 }
15180 } 15717 }
15181 }, 15718 },
15182 "function-bind": { 15719 "function-bind": {
@@ -15238,6 +15775,15 @@
15238 } 15775 }
15239 } 15776 }
15240 }, 15777 },
15778 "generic-names": {
15779 "version": "2.0.1",
15780 "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-2.0.1.tgz",
15781 "integrity": "sha512-kPCHWa1m9wGG/OwQpeweTwM/PYiQLrUIxXbt/P4Nic3LbGjCP0YwrALHW1uNLKZ0LIMg+RF+XRlj2ekT9ZlZAQ==",
15782 "dev": true,
15783 "requires": {
15784 "loader-utils": "^1.1.0"
15785 }
15786 },
15241 "gensync": { 15787 "gensync": {
15242 "version": "1.0.0-beta.2", 15788 "version": "1.0.0-beta.2",
15243 "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", 15789 "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -16440,6 +16986,12 @@
16440 } 16986 }
16441 } 16987 }
16442 }, 16988 },
16989 "hash-sum": {
16990 "version": "2.0.0",
16991 "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz",
16992 "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==",
16993 "dev": true
16994 },
16443 "hash.js": { 16995 "hash.js": {
16444 "version": "1.1.7", 16996 "version": "1.1.7",
16445 "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", 16997 "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
@@ -16848,6 +17400,18 @@
16848 "safer-buffer": ">= 2.1.2 < 3" 17400 "safer-buffer": ">= 2.1.2 < 3"
16849 } 17401 }
16850 }, 17402 },
17403 "icss-replace-symbols": {
17404 "version": "1.1.0",
17405 "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
17406 "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=",
17407 "dev": true
17408 },
17409 "icss-utils": {
17410 "version": "5.1.0",
17411 "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
17412 "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
17413 "dev": true
17414 },
16851 "ieee754": { 17415 "ieee754": {
16852 "version": "1.2.1", 17416 "version": "1.2.1",
16853 "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 17417 "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -17214,30 +17778,14 @@
17214 "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", 17778 "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
17215 "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" 17779 "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA=="
17216 }, 17780 },
17217 "intl-format-cache": {
17218 "version": "2.2.9",
17219 "resolved": "https://registry.npmjs.org/intl-format-cache/-/intl-format-cache-2.2.9.tgz",
17220 "integrity": "sha512-Zv/u8wRpekckv0cLkwpVdABYST4hZNTDaX7reFetrYTJwxExR2VyTqQm+l0WmL0Qo8Mjb9Tf33qnfj0T7pjxdQ=="
17221 },
17222 "intl-messageformat": { 17781 "intl-messageformat": {
17223 "version": "2.2.0", 17782 "version": "9.9.1",
17224 "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-2.2.0.tgz", 17783 "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-9.9.1.tgz",
17225 "integrity": "sha1-NFvNRt5jC3aDMwwuUhd/9eq0hPw=", 17784 "integrity": "sha512-cuzS/XKHn//hvKka77JKU2dseiVY2dofQjIOZv6ZFxFt4Z9sPXnZ7KQ9Ak2r+4XBCjI04MqJ1PhKs/3X22AkfA==",
17226 "requires": { 17785 "requires": {
17227 "intl-messageformat-parser": "1.4.0" 17786 "@formatjs/fast-memoize": "1.2.0",
17228 } 17787 "@formatjs/icu-messageformat-parser": "2.0.11",
17229 }, 17788 "tslib": "^2.1.0"
17230 "intl-messageformat-parser": {
17231 "version": "1.4.0",
17232 "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.4.0.tgz",
17233 "integrity": "sha1-tD1FqXRoytvkQzHXS7Ho3qRPwHU="
17234 },
17235 "intl-relativeformat": {
17236 "version": "2.2.0",
17237 "resolved": "https://registry.npmjs.org/intl-relativeformat/-/intl-relativeformat-2.2.0.tgz",
17238 "integrity": "sha512-4bV/7kSKaPEmu6ArxXf9xjv1ny74Zkwuey8Pm01NH4zggPP7JHwg2STk8Y3JdspCKRDriwIyLRfEXnj2ZLr4Bw==",
17239 "requires": {
17240 "intl-messageformat": "^2.0.0"
17241 } 17789 }
17242 }, 17790 },
17243 "invariant": { 17791 "invariant": {
@@ -20505,6 +21053,16 @@
20505 "js-tokens": "^3.0.0 || ^4.0.0" 21053 "js-tokens": "^3.0.0 || ^4.0.0"
20506 } 21054 }
20507 }, 21055 },
21056 "loud-rejection": {
21057 "version": "2.2.0",
21058 "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-2.2.0.tgz",
21059 "integrity": "sha512-S0FayMXku80toa5sZ6Ro4C+s+EtFDCsyJNG/AzFMfX3AxD5Si4dZsgzm/kKnbOxHl5Cv8jBlno8+3XYIh2pNjQ==",
21060 "dev": true,
21061 "requires": {
21062 "currently-unhandled": "^0.4.1",
21063 "signal-exit": "^3.0.2"
21064 }
21065 },
20508 "lower-case": { 21066 "lower-case": {
20509 "version": "1.1.4", 21067 "version": "1.1.4",
20510 "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", 21068 "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
@@ -20574,6 +21132,15 @@
20574 } 21132 }
20575 } 21133 }
20576 }, 21134 },
21135 "magic-string": {
21136 "version": "0.25.7",
21137 "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
21138 "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
21139 "dev": true,
21140 "requires": {
21141 "sourcemap-codec": "^1.4.4"
21142 }
21143 },
20577 "make-dir": { 21144 "make-dir": {
20578 "version": "2.1.0", 21145 "version": "2.1.0",
20579 "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", 21146 "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
@@ -20879,6 +21446,23 @@
20879 "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", 21446 "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
20880 "dev": true 21447 "dev": true
20881 }, 21448 },
21449 "merge-source-map": {
21450 "version": "1.1.0",
21451 "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz",
21452 "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==",
21453 "dev": true,
21454 "requires": {
21455 "source-map": "^0.6.1"
21456 },
21457 "dependencies": {
21458 "source-map": {
21459 "version": "0.6.1",
21460 "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
21461 "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
21462 "dev": true
21463 }
21464 }
21465 },
20882 "merge-stream": { 21466 "merge-stream": {
20883 "version": "2.0.0", 21467 "version": "2.0.0",
20884 "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", 21468 "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -21686,6 +22270,31 @@
21686 "mkdirp": "^0.5.1", 22270 "mkdirp": "^0.5.1",
21687 "rimraf": "^2.5.4", 22271 "rimraf": "^2.5.4",
21688 "run-queue": "^1.0.3" 22272 "run-queue": "^1.0.3"
22273 },
22274 "dependencies": {
22275 "glob": {
22276 "version": "7.1.7",
22277 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
22278 "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
22279 "dev": true,
22280 "requires": {
22281 "fs.realpath": "^1.0.0",
22282 "inflight": "^1.0.4",
22283 "inherits": "2",
22284 "minimatch": "^3.0.4",
22285 "once": "^1.3.0",
22286 "path-is-absolute": "^1.0.0"
22287 }
22288 },
22289 "rimraf": {
22290 "version": "2.7.1",
22291 "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
22292 "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
22293 "dev": true,
22294 "requires": {
22295 "glob": "^7.1.3"
22296 }
22297 }
21689 } 22298 }
21690 }, 22299 },
21691 "ms": { 22300 "ms": {
@@ -22010,6 +22619,15 @@
22010 "path-is-absolute": "^1.0.0" 22619 "path-is-absolute": "^1.0.0"
22011 } 22620 }
22012 }, 22621 },
22622 "rimraf": {
22623 "version": "2.7.1",
22624 "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
22625 "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
22626 "optional": true,
22627 "requires": {
22628 "glob": "^7.1.3"
22629 }
22630 },
22013 "semver": { 22631 "semver": {
22014 "version": "5.3.0", 22632 "version": "5.3.0",
22015 "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", 22633 "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
@@ -22150,6 +22768,19 @@
22150 "tar": "^4" 22768 "tar": "^4"
22151 }, 22769 },
22152 "dependencies": { 22770 "dependencies": {
22771 "glob": {
22772 "version": "7.1.7",
22773 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
22774 "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
22775 "requires": {
22776 "fs.realpath": "^1.0.0",
22777 "inflight": "^1.0.4",
22778 "inherits": "2",
22779 "minimatch": "^3.0.4",
22780 "once": "^1.3.0",
22781 "path-is-absolute": "^1.0.0"
22782 }
22783 },
22153 "nopt": { 22784 "nopt": {
22154 "version": "4.0.3", 22785 "version": "4.0.3",
22155 "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", 22786 "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
@@ -22159,6 +22790,14 @@
22159 "osenv": "^0.1.4" 22790 "osenv": "^0.1.4"
22160 } 22791 }
22161 }, 22792 },
22793 "rimraf": {
22794 "version": "2.7.1",
22795 "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
22796 "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
22797 "requires": {
22798 "glob": "^7.1.3"
22799 }
22800 },
22162 "semver": { 22801 "semver": {
22163 "version": "5.7.1", 22802 "version": "5.7.1",
22164 "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 22803 "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
@@ -22335,6 +22974,17 @@
22335 "semver": "^5.7.1", 22974 "semver": "^5.7.1",
22336 "tar": "^4.4.12", 22975 "tar": "^4.4.12",
22337 "which": "^1.3.1" 22976 "which": "^1.3.1"
22977 },
22978 "dependencies": {
22979 "rimraf": {
22980 "version": "2.7.1",
22981 "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
22982 "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
22983 "dev": true,
22984 "requires": {
22985 "glob": "^7.1.3"
22986 }
22987 }
22338 } 22988 }
22339 }, 22989 },
22340 "nopt": { 22990 "nopt": {
@@ -23619,6 +24269,84 @@
23619 "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", 24269 "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
23620 "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" 24270 "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
23621 }, 24271 },
24272 "postcss": {
24273 "version": "8.3.6",
24274 "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.6.tgz",
24275 "integrity": "sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A==",
24276 "dev": true,
24277 "requires": {
24278 "colorette": "^1.2.2",
24279 "nanoid": "^3.1.23",
24280 "source-map-js": "^0.6.2"
24281 }
24282 },
24283 "postcss-modules": {
24284 "version": "4.2.2",
24285 "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.2.2.tgz",
24286 "integrity": "sha512-/H08MGEmaalv/OU8j6bUKi/kZr2kqGF6huAW8m9UAgOLWtpFdhA14+gPBoymtqyv+D4MLsmqaF2zvIegdCxJXg==",
24287 "dev": true,
24288 "requires": {
24289 "generic-names": "^2.0.1",
24290 "icss-replace-symbols": "^1.1.0",
24291 "lodash.camelcase": "^4.3.0",
24292 "postcss-modules-extract-imports": "^3.0.0",
24293 "postcss-modules-local-by-default": "^4.0.0",
24294 "postcss-modules-scope": "^3.0.0",
24295 "postcss-modules-values": "^4.0.0",
24296 "string-hash": "^1.1.1"
24297 }
24298 },
24299 "postcss-modules-extract-imports": {
24300 "version": "3.0.0",
24301 "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
24302 "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
24303 "dev": true
24304 },
24305 "postcss-modules-local-by-default": {
24306 "version": "4.0.0",
24307 "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz",
24308 "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==",
24309 "dev": true,
24310 "requires": {
24311 "icss-utils": "^5.0.0",
24312 "postcss-selector-parser": "^6.0.2",
24313 "postcss-value-parser": "^4.1.0"
24314 }
24315 },
24316 "postcss-modules-scope": {
24317 "version": "3.0.0",
24318 "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz",
24319 "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==",
24320 "dev": true,
24321 "requires": {
24322 "postcss-selector-parser": "^6.0.4"
24323 }
24324 },
24325 "postcss-modules-values": {
24326 "version": "4.0.0",
24327 "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz",
24328 "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==",
24329 "dev": true,
24330 "requires": {
24331 "icss-utils": "^5.0.0"
24332 }
24333 },
24334 "postcss-selector-parser": {
24335 "version": "6.0.6",
24336 "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz",
24337 "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==",
24338 "dev": true,
24339 "requires": {
24340 "cssesc": "^3.0.0",
24341 "util-deprecate": "^1.0.2"
24342 }
24343 },
24344 "postcss-value-parser": {
24345 "version": "4.1.0",
24346 "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
24347 "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==",
24348 "dev": true
24349 },
23622 "prelude-ls": { 24350 "prelude-ls": {
23623 "version": "1.2.1", 24351 "version": "1.2.1",
23624 "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 24352 "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -24577,48 +25305,30 @@
24577 } 25305 }
24578 }, 25306 },
24579 "react-intl": { 25307 "react-intl": {
24580 "version": "2.7.2", 25308 "version": "5.20.10",
24581 "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-2.7.2.tgz", 25309 "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-5.20.10.tgz",
24582 "integrity": "sha512-3dcNGLqEw2FKkX+1L2WYLgjP0MVJkvWuVd1uLcnwifIQe8JQvnd9Bss4hb4Gvg/YhBIRcs4LM6C2bAgyklucjw==", 25310 "integrity": "sha512-zy0ZQhpjkGsKcK1BFo2HbGM/q8GBVovzoXZGQ76DowR0yr6UzQuPLkrlIrObL2zxIYiDaxaz+hUJaoa2a1xqOQ==",
24583 "requires": { 25311 "requires": {
24584 "hoist-non-react-statics": "^2.5.5", 25312 "@formatjs/ecma402-abstract": "1.9.8",
24585 "intl-format-cache": "^2.0.5", 25313 "@formatjs/icu-messageformat-parser": "2.0.11",
24586 "intl-messageformat": "^2.1.0", 25314 "@formatjs/intl": "1.14.1",
24587 "intl-relativeformat": "^2.1.0", 25315 "@formatjs/intl-displaynames": "5.2.3",
24588 "invariant": "^2.1.1" 25316 "@formatjs/intl-listformat": "6.3.3",
24589 }, 25317 "@types/hoist-non-react-statics": "^3.3.1",
24590 "dependencies": { 25318 "@types/react": "17",
24591 "hoist-non-react-statics": { 25319 "hoist-non-react-statics": "^3.3.2",
24592 "version": "2.5.5", 25320 "intl-messageformat": "9.9.1",
24593 "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", 25321 "tslib": "^2.1.0"
24594 "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
24595 }
24596 }
24597 },
24598 "react-intl-translations-manager": {
24599 "version": "5.0.3",
24600 "resolved": "https://registry.npmjs.org/react-intl-translations-manager/-/react-intl-translations-manager-5.0.3.tgz",
24601 "integrity": "sha512-EfBeugnOGFcdUbQyY9TqBMbuauQ8wm73ZqFr0UqCljhbXl7YDHQcVzclWFRkVmlUffzxitLQFhAZEVVeRNQSwA==",
24602 "dev": true,
24603 "requires": {
24604 "chalk": "^2.3.2",
24605 "glob": "^7.1.2",
24606 "json-stable-stringify": "^1.0.1",
24607 "mkdirp": "^0.5.1"
24608 }, 25322 },
24609 "dependencies": { 25323 "dependencies": {
24610 "glob": { 25324 "@types/react": {
24611 "version": "7.1.7", 25325 "version": "17.0.20",
24612 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", 25326 "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.20.tgz",
24613 "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", 25327 "integrity": "sha512-wWZrPlihslrPpcKyCSlmIlruakxr57/buQN1RjlIeaaTWDLtJkTtRW429MoQJergvVKc4IWBpRhWw7YNh/7GVA==",
24614 "dev": true,
24615 "requires": { 25328 "requires": {
24616 "fs.realpath": "^1.0.0", 25329 "@types/prop-types": "*",
24617 "inflight": "^1.0.4", 25330 "@types/scheduler": "*",
24618 "inherits": "2", 25331 "csstype": "^3.0.2"
24619 "minimatch": "^3.0.4",
24620 "once": "^1.3.0",
24621 "path-is-absolute": "^1.0.0"
24622 } 25332 }
24623 } 25333 }
24624 } 25334 }
@@ -25567,9 +26277,10 @@
25567 "dev": true 26277 "dev": true
25568 }, 26278 },
25569 "rimraf": { 26279 "rimraf": {
25570 "version": "2.7.1", 26280 "version": "3.0.2",
25571 "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", 26281 "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
25572 "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", 26282 "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
26283 "dev": true,
25573 "requires": { 26284 "requires": {
25574 "glob": "^7.1.3" 26285 "glob": "^7.1.3"
25575 }, 26286 },
@@ -25578,6 +26289,7 @@
25578 "version": "7.1.7", 26289 "version": "7.1.7",
25579 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", 26290 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
25580 "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", 26291 "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
26292 "dev": true,
25581 "requires": { 26293 "requires": {
25582 "fs.realpath": "^1.0.0", 26294 "fs.realpath": "^1.0.0",
25583 "inflight": "^1.0.4", 26295 "inflight": "^1.0.4",
@@ -26522,6 +27234,12 @@
26522 "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 27234 "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
26523 "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 27235 "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
26524 }, 27236 },
27237 "source-map-js": {
27238 "version": "0.6.2",
27239 "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz",
27240 "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==",
27241 "dev": true
27242 },
26525 "source-map-resolve": { 27243 "source-map-resolve": {
26526 "version": "0.5.3", 27244 "version": "0.5.3",
26527 "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", 27245 "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
@@ -26557,6 +27275,12 @@
26557 "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", 27275 "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
26558 "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" 27276 "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw=="
26559 }, 27277 },
27278 "sourcemap-codec": {
27279 "version": "1.4.8",
27280 "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
27281 "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
27282 "dev": true
27283 },
26560 "sparkles": { 27284 "sparkles": {
26561 "version": "1.0.1", 27285 "version": "1.0.1",
26562 "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", 27286 "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz",
@@ -26961,6 +27685,12 @@
26961 "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", 27685 "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
26962 "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" 27686 "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
26963 }, 27687 },
27688 "string-hash": {
27689 "version": "1.1.3",
27690 "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz",
27691 "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=",
27692 "dev": true
27693 },
26964 "string-length": { 27694 "string-length": {
26965 "version": "4.0.2", 27695 "version": "4.0.2",
26966 "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", 27696 "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
@@ -27503,6 +28233,17 @@
27503 "ssri": "^6.0.1", 28233 "ssri": "^6.0.1",
27504 "unique-filename": "^1.1.1", 28234 "unique-filename": "^1.1.1",
27505 "y18n": "^4.0.0" 28235 "y18n": "^4.0.0"
28236 },
28237 "dependencies": {
28238 "rimraf": {
28239 "version": "2.7.1",
28240 "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
28241 "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
28242 "dev": true,
28243 "requires": {
28244 "glob": "^7.1.3"
28245 }
28246 }
27506 } 28247 }
27507 }, 28248 },
27508 "glob": { 28249 "glob": {
diff --git a/package.json b/package.json
index f4ee15e34..f95116218 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,9 @@
26 "test": "jest", 26 "test": "jest",
27 "test:watch": "jest --watch", 27 "test:watch": "jest --watch",
28 "lint": "eslint \"{src,scripts,packages,uidev}/**/*.{js,jsx,ts,tsx}\" --quiet --fix", 28 "lint": "eslint \"{src,scripts,packages,uidev}/**/*.{js,jsx,ts,tsx}\" --quiet --fix",
29 "manage-translations": "node ./src/i18n/manage-translations.js", 29 "extract": "formatjs extract 'src/**/*.{js,ts}' --out-file temp.json --flatten --id-interpolation-pattern '[sha512:contenthash:base64:6]'",
30 "compile": "formatjs compile 'temp.json' --out-file src/i18n/locales/en-US.json",
31 "manage-translations": "npm run extract && npm run compile && rimraf temp.json",
30 "prebuild": "preval-build-info-cli && gulp build", 32 "prebuild": "preval-build-info-cli && gulp build",
31 "build": "electron-builder", 33 "build": "electron-builder",
32 "commit": "git-cz", 34 "commit": "git-cz",
@@ -114,7 +116,7 @@
114 "react-dom": "16.14.0", 116 "react-dom": "16.14.0",
115 "react-dropzone": "11.3.4", 117 "react-dropzone": "11.3.4",
116 "react-electron-web-view": "2.0.1", 118 "react-electron-web-view": "2.0.1",
117 "react-intl": "2.7.2", 119 "react-intl": "5.20.10",
118 "react-jss": "8.6.1", 120 "react-jss": "8.6.1",
119 "react-loader": "2.4.7", 121 "react-loader": "2.4.7",
120 "react-modal": "3.14.3", 122 "react-modal": "3.14.3",
@@ -146,6 +148,7 @@
146 "@babel/register": "7.15.3", 148 "@babel/register": "7.15.3",
147 "@commitlint/cli": "13.1.0", 149 "@commitlint/cli": "13.1.0",
148 "@commitlint/config-conventional": "13.1.0", 150 "@commitlint/config-conventional": "13.1.0",
151 "@formatjs/cli": "4.2.33",
149 "@tsconfig/node14": "1.0.1", 152 "@tsconfig/node14": "1.0.1",
150 "@types/color": "3.0.2", 153 "@types/color": "3.0.2",
151 "@types/du": "1.0.1", 154 "@types/du": "1.0.1",
@@ -163,7 +166,7 @@
163 "@typescript-eslint/eslint-plugin": "4.30.0", 166 "@typescript-eslint/eslint-plugin": "4.30.0",
164 "@typescript-eslint/parser": "4.29.1", 167 "@typescript-eslint/parser": "4.29.1",
165 "all-contributors-cli": "6.20.0", 168 "all-contributors-cli": "6.20.0",
166 "babel-plugin-react-intl": "3.5.1", 169 "babel-plugin-formatjs": "10.3.8",
167 "commitizen": "4.2.4", 170 "commitizen": "4.2.4",
168 "concurrently": "6.2.1", 171 "concurrently": "6.2.1",
169 "conventional-changelog-cli": "2.1.1", 172 "conventional-changelog-cli": "2.1.1",
@@ -205,7 +208,7 @@
205 "node-abi": "2.30.0", 208 "node-abi": "2.30.0",
206 "prettier": "2.3.2", 209 "prettier": "2.3.2",
207 "preval-build-info": "1.0.3", 210 "preval-build-info": "1.0.3",
208 "react-intl-translations-manager": "5.0.3", 211 "rimraf": "3.0.2",
209 "sass": "1.37.5", 212 "sass": "1.37.5",
210 "simple-git": "2.45.0", 213 "simple-git": "2.45.0",
211 "terser": "4.8.0", 214 "terser": "4.8.0",
diff --git a/src/I18n.js b/src/I18n.js
index 13513fe73..6fb4cdc61 100644
--- a/src/I18n.js
+++ b/src/I18n.js
@@ -8,7 +8,9 @@ import translations from './i18n/translations';
8import UserStore from './stores/UserStore'; 8import UserStore from './stores/UserStore';
9import AppStore from './stores/AppStore'; 9import AppStore from './stores/AppStore';
10 10
11export default @inject('stores') @observer class I18N extends Component { 11@inject('stores')
12@observer
13class I18N extends Component {
12 componentDidUpdate() { 14 componentDidUpdate() {
13 window.ferdi.menu.rebuild(); 15 window.ferdi.menu.rebuild();
14 } 16 }
@@ -19,7 +21,9 @@ export default @inject('stores') @observer class I18N extends Component {
19 return ( 21 return (
20 <IntlProvider 22 <IntlProvider
21 {...{ locale, key: locale, messages: translations[locale] }} 23 {...{ locale, key: locale, messages: translations[locale] }}
22 ref={(intlProvider) => { window.ferdi.intl = intlProvider ? intlProvider.getChildContext().intl : null; }} 24 ref={intlProvider => {
25 window.ferdi.intl = intlProvider ? intlProvider.state.intl : null;
26 }}
23 > 27 >
24 {children} 28 {children}
25 </IntlProvider> 29 </IntlProvider>
@@ -34,3 +38,5 @@ I18N.wrappedComponent.propTypes = {
34 }).isRequired, 38 }).isRequired,
35 children: oneOrManyChildElements.isRequired, 39 children: oneOrManyChildElements.isRequired,
36}; 40};
41
42export default I18N;
diff --git a/src/components/AppUpdateInfoBar.js b/src/components/AppUpdateInfoBar.js
index 30804262a..9dc86bd1d 100644
--- a/src/components/AppUpdateInfoBar.js
+++ b/src/components/AppUpdateInfoBar.js
@@ -1,6 +1,6 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { defineMessages, intlShape } from 'react-intl'; 3import { defineMessages, injectIntl } from 'react-intl';
4 4
5import InfoBar from './ui/InfoBar'; 5import InfoBar from './ui/InfoBar';
6import { GITHUB_FERDI_URL } from '../config'; 6import { GITHUB_FERDI_URL } from '../config';
@@ -9,15 +9,15 @@ import { openExternalUrl } from '../helpers/url-helpers';
9const messages = defineMessages({ 9const messages = defineMessages({
10 updateAvailable: { 10 updateAvailable: {
11 id: 'infobar.updateAvailable', 11 id: 'infobar.updateAvailable',
12 defaultMessage: '!!!A new update for Ferdi is available.', 12 defaultMessage: 'A new update for Ferdi is available.',
13 }, 13 },
14 changelog: { 14 changelog: {
15 id: 'infobar.buttonChangelog', 15 id: 'infobar.buttonChangelog',
16 defaultMessage: '!!!Changelog', 16 defaultMessage: 'Changelog',
17 }, 17 },
18 buttonInstallUpdate: { 18 buttonInstallUpdate: {
19 id: 'infobar.buttonInstallUpdate', 19 id: 'infobar.buttonInstallUpdate',
20 defaultMessage: '!!!Restart & install update', 20 defaultMessage: 'Restart & install update',
21 }, 21 },
22}); 22});
23 23
@@ -27,12 +27,8 @@ class AppUpdateInfoBar extends Component {
27 onHide: PropTypes.func.isRequired, 27 onHide: PropTypes.func.isRequired,
28 }; 28 };
29 29
30 static contextTypes = {
31 intl: intlShape,
32 };
33
34 render() { 30 render() {
35 const { intl } = this.context; 31 const { intl } = this.props;
36 const { onInstallUpdate, onHide } = this.props; 32 const { onInstallUpdate, onHide } = this.props;
37 33
38 return ( 34 return (
@@ -61,4 +57,4 @@ class AppUpdateInfoBar extends Component {
61 } 57 }
62} 58}
63 59
64export default AppUpdateInfoBar; 60export default injectIntl(AppUpdateInfoBar);
diff --git a/src/components/auth/AuthLayout.js b/src/components/auth/AuthLayout.js
index 8235932c2..3e2b75731 100644
--- a/src/components/auth/AuthLayout.js
+++ b/src/components/auth/AuthLayout.js
@@ -1,9 +1,9 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { intlShape } from 'react-intl';
5import { TitleBar } from 'electron-react-titlebar'; 4import { TitleBar } from 'electron-react-titlebar';
6 5
6import { injectIntl } from 'react-intl';
7import Link from '../ui/Link'; 7import Link from '../ui/Link';
8import InfoBar from '../ui/InfoBar'; 8import InfoBar from '../ui/InfoBar';
9 9
@@ -17,7 +17,6 @@ import { isWindows } from '../../environment';
17import AppUpdateInfoBar from '../AppUpdateInfoBar'; 17import AppUpdateInfoBar from '../AppUpdateInfoBar';
18import { GITHUB_FERDI_URL } from '../../config'; 18import { GITHUB_FERDI_URL } from '../../config';
19 19
20export default
21@observer 20@observer
22class AuthLayout extends Component { 21class AuthLayout extends Component {
23 static propTypes = { 22 static propTypes = {
@@ -36,10 +35,6 @@ class AuthLayout extends Component {
36 shouldShowAppUpdateInfoBar: true, 35 shouldShowAppUpdateInfoBar: true,
37 }; 36 };
38 37
39 static contextTypes = {
40 intl: intlShape,
41 };
42
43 render() { 38 render() {
44 const { 39 const {
45 children, 40 children,
@@ -52,7 +47,8 @@ class AuthLayout extends Component {
52 installAppUpdate, 47 installAppUpdate,
53 appUpdateIsDownloaded, 48 appUpdateIsDownloaded,
54 } = this.props; 49 } = this.props;
55 const { intl } = this.context; 50
51 const { intl } = this.props;
56 52
57 return ( 53 return (
58 <> 54 <>
@@ -108,3 +104,5 @@ class AuthLayout extends Component {
108 ); 104 );
109 } 105 }
110} 106}
107
108export default injectIntl(AuthLayout);
diff --git a/src/components/auth/ChangeServer.js b/src/components/auth/ChangeServer.js
index 8e8a7af32..b98fb50f7 100644
--- a/src/components/auth/ChangeServer.js
+++ b/src/components/auth/ChangeServer.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import Form from '../../lib/Form'; 5import Form from '../../lib/Form';
6import Input from '../ui/Input'; 6import Input from '../ui/Input';
7import Select from '../ui/Select'; 7import Select from '../ui/Select';
@@ -14,56 +14,65 @@ import globalMessages from '../../i18n/globalMessages';
14const messages = defineMessages({ 14const messages = defineMessages({
15 headline: { 15 headline: {
16 id: 'changeserver.headline', 16 id: 'changeserver.headline',
17 defaultMessage: '!!!Change server', 17 defaultMessage: 'Change server',
18 }, 18 },
19 label: { 19 label: {
20 id: 'changeserver.label', 20 id: 'changeserver.label',
21 defaultMessage: '!!!Server', 21 defaultMessage: 'Server',
22 }, 22 },
23 warning: { 23 warning: {
24 id: 'changeserver.warning', 24 id: 'changeserver.warning',
25 defaultMessage: '!!!Extra settings offered by Ferdi will not be saved', 25 defaultMessage: 'Extra settings offered by Ferdi will not be saved',
26 }, 26 },
27 customServerLabel: { 27 customServerLabel: {
28 id: 'changeserver.customServerLabel', 28 id: 'changeserver.customServerLabel',
29 defaultMessage: '!!!Custom server', 29 defaultMessage: 'Custom server',
30 }, 30 },
31 urlError: { 31 urlError: {
32 id: 'changeserver.urlError', 32 id: 'changeserver.urlError',
33 defaultMessage: '!!!Enter a valid URL', 33 defaultMessage: 'Enter a valid URL',
34 }, 34 },
35}); 35});
36 36
37export default @observer class ChangeServer extends Component { 37@observer
38class ChangeServer extends Component {
38 static propTypes = { 39 static propTypes = {
39 onSubmit: PropTypes.func.isRequired, 40 onSubmit: PropTypes.func.isRequired,
40 server: PropTypes.string.isRequired, 41 server: PropTypes.string.isRequired,
41 }; 42 };
42 43
43 static contextTypes = { 44 ferdiServer = LIVE_FERDI_API;
44 intl: intlShape,
45 };
46
47 ferdiServer=LIVE_FERDI_API;
48 45
49 franzServer=LIVE_FRANZ_API; 46 franzServer = LIVE_FRANZ_API;
50 47
51 defaultServers=[this.franzServer, this.ferdiServer]; 48 defaultServers = [this.franzServer, this.ferdiServer];
52 49
53 form = new Form({ 50 form = new Form(
54 fields: { 51 {
55 server: { 52 fields: {
56 label: this.context.intl.formatMessage(messages.label), 53 server: {
57 value: this.props.server, 54 label: this.props.intl.formatMessage(messages.label),
58 options: [{ value: this.ferdiServer, label: 'Ferdi' }, { value: this.franzServer, label: 'Franz' }, { value: this.defaultServers.includes(this.props.server) ? '' : this.props.server, label: 'Custom' }], 55 value: this.props.server,
59 }, 56 options: [
60 customServer: { 57 { value: this.ferdiServer, label: 'Ferdi' },
61 label: this.context.intl.formatMessage(messages.customServerLabel), 58 { value: this.franzServer, label: 'Franz' },
62 value: '', 59 {
63 validators: [url, required], 60 value: this.defaultServers.includes(this.props.server)
61 ? ''
62 : this.props.server,
63 label: 'Custom',
64 },
65 ],
66 },
67 customServer: {
68 label: this.props.intl.formatMessage(messages.customServerLabel),
69 value: '',
70 validators: [url, required],
71 },
64 }, 72 },
65 }, 73 },
66 }, this.context.intl); 74 this.props.intl,
75 );
67 76
68 componentDidMount() { 77 componentDidMount() {
69 if (this.defaultServers.includes(this.props.server)) { 78 if (this.defaultServers.includes(this.props.server)) {
@@ -77,13 +86,13 @@ export default @observer class ChangeServer extends Component {
77 submit(e) { 86 submit(e) {
78 e.preventDefault(); 87 e.preventDefault();
79 this.form.submit({ 88 this.form.submit({
80 onSuccess: (form) => { 89 onSuccess: form => {
81 if (!this.defaultServers.includes(form.values().server)) { 90 if (!this.defaultServers.includes(form.values().server)) {
82 form.$('server').onChange(form.values().customServer); 91 form.$('server').onChange(form.values().customServer);
83 } 92 }
84 this.props.onSubmit(form.values()); 93 this.props.onSubmit(form.values());
85 }, 94 },
86 onError: (form) => { 95 onError: form => {
87 if (this.defaultServers.includes(form.values().server)) { 96 if (this.defaultServers.includes(form.values().server)) {
88 this.props.onSubmit(form.values()); 97 this.props.onSubmit(form.values());
89 } 98 }
@@ -93,23 +102,21 @@ export default @observer class ChangeServer extends Component {
93 102
94 render() { 103 render() {
95 const { form } = this; 104 const { form } = this;
96 const { intl } = this.context; 105 const { intl } = this.props;
97 return ( 106 return (
98 <div className="auth__container"> 107 <div className="auth__container">
99 <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}> 108 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
100 <h1>{intl.formatMessage(messages.headline)}</h1> 109 <h1>{intl.formatMessage(messages.headline)}</h1>
101 {form.$('server').value === this.franzServer 110 {form.$('server').value === this.franzServer && (
102 && (
103 <Infobox type="warning"> 111 <Infobox type="warning">
104 {intl.formatMessage(messages.warning)} 112 {intl.formatMessage(messages.warning)}
105 </Infobox> 113 </Infobox>
106 )} 114 )}
107 <Select field={form.$('server')} /> 115 <Select field={form.$('server')} />
108 {!this.defaultServers.includes(form.$('server').value) 116 {!this.defaultServers.includes(form.$('server').value) && (
109 && (
110 <Input 117 <Input
111 placeholder="Custom Server" 118 placeholder="Custom Server"
112 onChange={(e) => this.submit(e)} 119 onChange={e => this.submit(e)}
113 field={form.$('customServer')} 120 field={form.$('customServer')}
114 /> 121 />
115 )} 122 )}
@@ -123,3 +130,5 @@ export default @observer class ChangeServer extends Component {
123 ); 130 );
124 } 131 }
125} 132}
133
134export default injectIntl(ChangeServer);
diff --git a/src/components/auth/Import.js b/src/components/auth/Import.js
index 3073cad73..44cb7e791 100644
--- a/src/components/auth/Import.js
+++ b/src/components/auth/Import.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import { Link } from 'react-router'; 5import { Link } from 'react-router';
6import classnames from 'classnames'; 6import classnames from 'classnames';
7 7
@@ -12,23 +12,22 @@ import Button from '../ui/Button';
12const messages = defineMessages({ 12const messages = defineMessages({
13 headline: { 13 headline: {
14 id: 'import.headline', 14 id: 'import.headline',
15 defaultMessage: '!!!Import your Ferdi 4 services', 15 defaultMessage: 'Import your Ferdi 4 services',
16 }, 16 },
17 notSupportedHeadline: { 17 notSupportedHeadline: {
18 id: 'import.notSupportedHeadline', 18 id: 'import.notSupportedHeadline',
19 defaultMessage: '!!!Services not yet supported in Ferdi 5', 19 defaultMessage: 'Services not yet supported in Ferdi 5',
20 }, 20 },
21 submitButtonLabel: { 21 submitButtonLabel: {
22 id: 'import.submit.label', 22 id: 'import.submit.label',
23 defaultMessage: '!!!Import {count} services', 23 defaultMessage: 'Import {count} services',
24 }, 24 },
25 skipButtonLabel: { 25 skipButtonLabel: {
26 id: 'import.skip.label', 26 id: 'import.skip.label',
27 defaultMessage: '!!!I want to add services manually', 27 defaultMessage: 'I want to add services manually',
28 }, 28 },
29}); 29});
30 30
31export default
32@observer 31@observer
33class Import extends Component { 32class Import extends Component {
34 static propTypes = { 33 static propTypes = {
@@ -38,17 +37,13 @@ class Import extends Component {
38 inviteRoute: PropTypes.string.isRequired, 37 inviteRoute: PropTypes.string.isRequired,
39 }; 38 };
40 39
41 static contextTypes = {
42 intl: intlShape,
43 };
44
45 componentDidMount() { 40 componentDidMount() {
46 const config = { 41 const config = {
47 fields: { 42 fields: {
48 import: [ 43 import: [
49 ...this.props.services 44 ...this.props.services
50 .filter((s) => s.recipe) 45 .filter(s => s.recipe)
51 .map((s) => ({ 46 .map(s => ({
52 fields: { 47 fields: {
53 add: { 48 add: {
54 default: true, 49 default: true,
@@ -60,20 +55,20 @@ class Import extends Component {
60 }, 55 },
61 }; 56 };
62 57
63 this.form = new Form(config, this.context.intl); 58 this.form = new Form(config, this.props.intl);
64 } 59 }
65 60
66 submit(e) { 61 submit(e) {
67 const { services } = this.props; 62 const { services } = this.props;
68 e.preventDefault(); 63 e.preventDefault();
69 this.form.submit({ 64 this.form.submit({
70 onSuccess: (form) => { 65 onSuccess: form => {
71 const servicesImport = form 66 const servicesImport = form
72 .values() 67 .values()
73 .import.map( 68 .import.map(
74 (value, i) => !value.add || services.filter((s) => s.recipe)[i], 69 (value, i) => !value.add || services.filter(s => s.recipe)[i],
75 ) 70 )
76 .filter((s) => typeof s !== 'boolean'); 71 .filter(s => typeof s !== 'boolean');
77 72
78 this.props.onSubmit({ services: servicesImport }); 73 this.props.onSubmit({ services: servicesImport });
79 }, 74 },
@@ -82,18 +77,18 @@ class Import extends Component {
82 } 77 }
83 78
84 render() { 79 render() {
85 const { intl } = this.context; 80 const { intl } = this.props;
86 const { services, isSubmitting, inviteRoute } = this.props; 81 const { services, isSubmitting, inviteRoute } = this.props;
87 82
88 const availableServices = services.filter((s) => s.recipe); 83 const availableServices = services.filter(s => s.recipe);
89 const unavailableServices = services.filter((s) => !s.recipe); 84 const unavailableServices = services.filter(s => !s.recipe);
90 85
91 return ( 86 return (
92 <div className="auth__scroll-container"> 87 <div className="auth__scroll-container">
93 <div className="auth__container auth__container--signup"> 88 <div className="auth__container auth__container--signup">
94 <form 89 <form
95 className="franz-form auth__form" 90 className="franz-form auth__form"
96 onSubmit={(e) => this.submit(e)} 91 onSubmit={e => this.submit(e)}
97 > 92 >
98 <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> 93 <img src="./assets/images/logo.svg" className="auth__logo" alt="" />
99 <h1>{intl.formatMessage(messages.headline)}</h1> 94 <h1>{intl.formatMessage(messages.headline)}</h1>
@@ -107,8 +102,8 @@ class Import extends Component {
107 <td className="service-table__column-icon"> 102 <td className="service-table__column-icon">
108 <img 103 <img
109 src={ 104 src={
110 availableServices[i].custom_icon 105 availableServices[i].custom_icon ||
111 || availableServices[i].recipe.icons.svg 106 availableServices[i].recipe.icons.svg
112 } 107 }
113 className={classnames({ 108 className={classnames({
114 'service-table__icon': true, 109 'service-table__icon': true,
@@ -133,7 +128,7 @@ class Import extends Component {
133 </strong> 128 </strong>
134 <p> 129 <p>
135 {services 130 {services
136 .filter((s) => !s.recipe) 131 .filter(s => !s.recipe)
137 .map((service, i) => ( 132 .map((service, i) => (
138 <span key={service.id}> 133 <span key={service.id}>
139 {service.name !== '' ? service.name : service.service} 134 {service.name !== '' ? service.name : service.service}
@@ -170,3 +165,5 @@ class Import extends Component {
170 ); 165 );
171 } 166 }
172} 167}
168
169export default injectIntl(Import);
diff --git a/src/components/auth/Invite.js b/src/components/auth/Invite.js
index 4b4d63a6b..519691ede 100644
--- a/src/components/auth/Invite.js
+++ b/src/components/auth/Invite.js
@@ -1,7 +1,7 @@
1import React, { Component, Fragment } from 'react'; 1import React, { Component, Fragment } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import { Link } from 'react-router'; 5import { Link } from 'react-router';
6import classnames from 'classnames'; 6import classnames from 'classnames';
7 7
@@ -15,35 +15,34 @@ import Button from '../ui/Button';
15const messages = defineMessages({ 15const messages = defineMessages({
16 settingsHeadline: { 16 settingsHeadline: {
17 id: 'settings.invite.headline', 17 id: 'settings.invite.headline',
18 defaultMessage: '!!!Invite Friends', 18 defaultMessage: 'Invite Friends',
19 }, 19 },
20 headline: { 20 headline: {
21 id: 'invite.headline.friends', 21 id: 'invite.headline.friends',
22 defaultMessage: '!!!Invite 3 of your friends or colleagues', 22 defaultMessage: 'Invite 3 of your friends or colleagues',
23 }, 23 },
24 nameLabel: { 24 nameLabel: {
25 id: 'invite.name.label', 25 id: 'invite.name.label',
26 defaultMessage: '!!!Name', 26 defaultMessage: 'Name',
27 }, 27 },
28 emailLabel: { 28 emailLabel: {
29 id: 'invite.email.label', 29 id: 'invite.email.label',
30 defaultMessage: '!!!Email address', 30 defaultMessage: 'Email address',
31 }, 31 },
32 submitButtonLabel: { 32 submitButtonLabel: {
33 id: 'invite.submit.label', 33 id: 'invite.submit.label',
34 defaultMessage: '!!!Send invites', 34 defaultMessage: 'Send invites',
35 }, 35 },
36 skipButtonLabel: { 36 skipButtonLabel: {
37 id: 'invite.skip.label', 37 id: 'invite.skip.label',
38 defaultMessage: '!!!I want to do this later', 38 defaultMessage: 'I want to do this later',
39 }, 39 },
40 inviteSuccessInfo: { 40 inviteSuccessInfo: {
41 id: 'invite.successInfo', 41 id: 'invite.successInfo',
42 defaultMessage: '!!!Invitations sent successfully', 42 defaultMessage: 'Invitations sent successfully',
43 }, 43 },
44}); 44});
45 45
46export default
47@observer 46@observer
48class Invite extends Component { 47class Invite extends Component {
49 static propTypes = { 48 static propTypes = {
@@ -59,10 +58,6 @@ class Invite extends Component {
59 isLoadingInvite: false, 58 isLoadingInvite: false,
60 }; 59 };
61 60
62 static contextTypes = {
63 intl: intlShape,
64 };
65
66 state = { showSuccessInfo: false }; 61 state = { showSuccessInfo: false };
67 62
68 componentDidMount() { 63 componentDidMount() {
@@ -73,8 +68,8 @@ class Invite extends Component {
73 ...Array(3).fill({ 68 ...Array(3).fill({
74 fields: { 69 fields: {
75 name: { 70 name: {
76 label: this.context.intl.formatMessage(messages.nameLabel), 71 label: this.props.intl.formatMessage(messages.nameLabel),
77 placeholder: this.context.intl.formatMessage( 72 placeholder: this.props.intl.formatMessage(
78 messages.nameLabel, 73 messages.nameLabel,
79 ), 74 ),
80 onChange: () => { 75 onChange: () => {
@@ -83,8 +78,8 @@ class Invite extends Component {
83 // related: ['invite.0.email'], // path accepted but does not work 78 // related: ['invite.0.email'], // path accepted but does not work
84 }, 79 },
85 email: { 80 email: {
86 label: this.context.intl.formatMessage(messages.emailLabel), 81 label: this.props.intl.formatMessage(messages.emailLabel),
87 placeholder: this.context.intl.formatMessage( 82 placeholder: this.props.intl.formatMessage(
88 messages.emailLabel, 83 messages.emailLabel,
89 ), 84 ),
90 onChange: () => { 85 onChange: () => {
@@ -97,7 +92,7 @@ class Invite extends Component {
97 ], 92 ],
98 }, 93 },
99 }, 94 },
100 this.context.intl, 95 this.props.intl,
101 ); 96 );
102 97
103 document.querySelector('input:first-child').focus(); 98 document.querySelector('input:first-child').focus();
@@ -107,7 +102,7 @@ class Invite extends Component {
107 e.preventDefault(); 102 e.preventDefault();
108 103
109 this.form.submit({ 104 this.form.submit({
110 onSuccess: (form) => { 105 onSuccess: form => {
111 this.props.onSubmit({ invites: form.values().invite }); 106 this.props.onSubmit({ invites: form.values().invite });
112 107
113 this.form.clear(); 108 this.form.clear();
@@ -121,13 +116,13 @@ class Invite extends Component {
121 116
122 render() { 117 render() {
123 const { form } = this; 118 const { form } = this;
124 const { intl } = this.context; 119 const { intl } = this.props;
125 const { embed, isInviteSuccessful, isLoadingInvite } = this.props; 120 const { embed, isInviteSuccessful, isLoadingInvite } = this.props;
126 121
127 const atLeastOneEmailAddress = form 122 const atLeastOneEmailAddress = form
128 .$('invite') 123 .$('invite')
129 .map((invite) => invite.$('email').value) 124 .map(invite => invite.$('email').value)
130 .some((emailValue) => emailValue.trim() !== ''); 125 .some(emailValue => emailValue.trim() !== '');
131 126
132 const sendButtonClassName = classnames({ 127 const sendButtonClassName = classnames({
133 auth__button: true, 128 auth__button: true,
@@ -148,17 +143,14 @@ class Invite extends Component {
148 </Appear> 143 </Appear>
149 )} 144 )}
150 145
151 <form 146 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
152 className="franz-form auth__form"
153 onSubmit={(e) => this.submit(e)}
154 >
155 {!embed && ( 147 {!embed && (
156 <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> 148 <img src="./assets/images/logo.svg" className="auth__logo" alt="" />
157 )} 149 )}
158 <h1 className={embed && 'invite__embed'}> 150 <h1 className={embed && 'invite__embed'}>
159 {intl.formatMessage(messages.headline)} 151 {intl.formatMessage(messages.headline)}
160 </h1> 152 </h1>
161 {form.$('invite').map((invite) => ( 153 {form.$('invite').map(invite => (
162 <div className="grid" key={invite.key}> 154 <div className="grid" key={invite.key}>
163 <div className="grid__row"> 155 <div className="grid__row">
164 <Input field={invite.$('name')} showLabel={false} /> 156 <Input field={invite.$('name')} showLabel={false} />
@@ -193,9 +185,7 @@ class Invite extends Component {
193 > 185 >
194 {embed && ( 186 {embed && (
195 <div className="settings__header"> 187 <div className="settings__header">
196 <h1> 188 <h1>{this.props.intl.formatMessage(messages.settingsHeadline)}</h1>
197 {this.context.intl.formatMessage(messages.settingsHeadline)}
198 </h1>
199 </div> 189 </div>
200 )} 190 )}
201 {!embed ? ( 191 {!embed ? (
@@ -207,3 +197,5 @@ class Invite extends Component {
207 ); 197 );
208 } 198 }
209} 199}
200
201export default injectIntl(Invite);
diff --git a/src/components/auth/Locked.js b/src/components/auth/Locked.js
index 2ad8a2409..a507ba140 100644
--- a/src/components/auth/Locked.js
+++ b/src/components/auth/Locked.js
@@ -2,7 +2,7 @@ import { systemPreferences } from '@electron/remote';
2import React, { Component } from 'react'; 2import React, { Component } from 'react';
3import PropTypes from 'prop-types'; 3import PropTypes from 'prop-types';
4import { observer } from 'mobx-react'; 4import { observer } from 'mobx-react';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6 6
7import Form from '../../lib/Form'; 7import Form from '../../lib/Form';
8import Input from '../ui/Input'; 8import Input from '../ui/Input';
@@ -15,39 +15,41 @@ import { globalError as globalErrorPropType } from '../../prop-types';
15const messages = defineMessages({ 15const messages = defineMessages({
16 headline: { 16 headline: {
17 id: 'locked.headline', 17 id: 'locked.headline',
18 defaultMessage: '!!!Locked', 18 defaultMessage: 'Locked',
19 }, 19 },
20 info: { 20 info: {
21 id: 'locked.info', 21 id: 'locked.info',
22 defaultMessage: '!!!Ferdi is currently locked. Please unlock Ferdi with your password to see your messages.', 22 defaultMessage:
23 'Ferdi is currently locked. Please unlock Ferdi with your password to see your messages.',
23 }, 24 },
24 touchId: { 25 touchId: {
25 id: 'locked.touchId', 26 id: 'locked.touchId',
26 defaultMessage: '!!!Unlock with Touch ID', 27 defaultMessage: 'Unlock with Touch ID',
27 }, 28 },
28 touchIdPrompt: { 29 touchIdPrompt: {
29 id: 'locked.touchIdPrompt', 30 id: 'locked.touchIdPrompt',
30 defaultMessage: '!!!unlock via Touch ID', 31 defaultMessage: 'unlock via Touch ID',
31 }, 32 },
32 passwordLabel: { 33 passwordLabel: {
33 id: 'locked.password.label', 34 id: 'locked.password.label',
34 defaultMessage: '!!!Password', 35 defaultMessage: 'Password',
35 }, 36 },
36 submitButtonLabel: { 37 submitButtonLabel: {
37 id: 'locked.submit.label', 38 id: 'locked.submit.label',
38 defaultMessage: '!!!Unlock', 39 defaultMessage: 'Unlock',
39 }, 40 },
40 unlockWithPassword: { 41 unlockWithPassword: {
41 id: 'locked.unlockWithPassword', 42 id: 'locked.unlockWithPassword',
42 defaultMessage: '!!!Unlock with Password', 43 defaultMessage: 'Unlock with Password',
43 }, 44 },
44 invalidCredentials: { 45 invalidCredentials: {
45 id: 'locked.invalidCredentials', 46 id: 'locked.invalidCredentials',
46 defaultMessage: '!!!Password invalid', 47 defaultMessage: 'Password invalid',
47 }, 48 },
48}); 49});
49 50
50export default @observer class Locked extends Component { 51@observer
52class Locked extends Component {
51 static propTypes = { 53 static propTypes = {
52 onSubmit: PropTypes.func.isRequired, 54 onSubmit: PropTypes.func.isRequired,
53 unlock: PropTypes.func.isRequired, 55 unlock: PropTypes.func.isRequired,
@@ -56,62 +58,57 @@ export default @observer class Locked extends Component {
56 error: globalErrorPropType.isRequired, 58 error: globalErrorPropType.isRequired,
57 }; 59 };
58 60
59 static contextTypes = { 61 form = new Form(
60 intl: intlShape, 62 {
61 }; 63 fields: {
62 64 password: {
63 form = new Form({ 65 label: this.props.intl.formatMessage(messages.passwordLabel),
64 fields: { 66 value: '',
65 password: { 67 type: 'password',
66 label: this.context.intl.formatMessage(messages.passwordLabel), 68 },
67 value: '',
68 type: 'password',
69 }, 69 },
70 }, 70 },
71 }, this.context.intl); 71 this.props.intl,
72 );
72 73
73 submit(e) { 74 submit(e) {
74 e.preventDefault(); 75 e.preventDefault();
75 this.form.submit({ 76 this.form.submit({
76 onSuccess: (form) => { 77 onSuccess: form => {
77 this.props.onSubmit(form.values()); 78 this.props.onSubmit(form.values());
78 }, 79 },
79 onError: () => { }, 80 onError: () => {},
80 }); 81 });
81 } 82 }
82 83
83 touchIdUnlock() { 84 touchIdUnlock() {
84 const { intl } = this.context; 85 const { intl } = this.props;
85 86
86 systemPreferences.promptTouchID(intl.formatMessage(messages.touchIdPrompt)).then(() => { 87 systemPreferences
87 this.props.unlock(); 88 .promptTouchID(intl.formatMessage(messages.touchIdPrompt))
88 }); 89 .then(() => {
90 this.props.unlock();
91 });
89 } 92 }
90 93
91 render() { 94 render() {
92 const { form } = this; 95 const { form } = this;
93 const { intl } = this.context; 96 const { intl } = this.props;
94 const { 97 const { isSubmitting, error, useTouchIdToUnlock } = this.props;
95 isSubmitting,
96 error,
97 useTouchIdToUnlock,
98 } = this.props;
99 98
100 const touchIdEnabled = isMac ? (useTouchIdToUnlock && systemPreferences.canPromptTouchID()) : false; 99 const touchIdEnabled = isMac
101 const submitButtonLabel = touchIdEnabled ? intl.formatMessage(messages.unlockWithPassword) : intl.formatMessage(messages.submitButtonLabel); 100 ? useTouchIdToUnlock && systemPreferences.canPromptTouchID()
101 : false;
102 const submitButtonLabel = touchIdEnabled
103 ? intl.formatMessage(messages.unlockWithPassword)
104 : intl.formatMessage(messages.submitButtonLabel);
102 105
103 return ( 106 return (
104 <div className="auth__container"> 107 <div className="auth__container">
105 <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}> 108 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
106 <img 109 <img src="./assets/images/logo.svg" className="auth__logo" alt="" />
107 src="./assets/images/logo.svg"
108 className="auth__logo"
109 alt=""
110 />
111 <h1>{intl.formatMessage(messages.headline)}</h1> 110 <h1>{intl.formatMessage(messages.headline)}</h1>
112 <Infobox type="warning"> 111 <Infobox type="warning">{intl.formatMessage(messages.info)}</Infobox>
113 {intl.formatMessage(messages.info)}
114 </Infobox>
115 112
116 {touchIdEnabled && ( 113 {touchIdEnabled && (
117 <> 114 <>
@@ -125,13 +122,11 @@ export default @observer class Locked extends Component {
125 </> 122 </>
126 )} 123 )}
127 124
128 <Input 125 <Input field={form.$('password')} showPasswordToggle focus />
129 field={form.$('password')}
130 showPasswordToggle
131 focus
132 />
133 {error.code === 'invalid-credentials' && ( 126 {error.code === 'invalid-credentials' && (
134 <p className="error-message center">{intl.formatMessage(messages.invalidCredentials)}</p> 127 <p className="error-message center">
128 {intl.formatMessage(messages.invalidCredentials)}
129 </p>
135 )} 130 )}
136 {isSubmitting ? ( 131 {isSubmitting ? (
137 <Button 132 <Button
@@ -153,3 +148,5 @@ export default @observer class Locked extends Component {
153 ); 148 );
154 } 149 }
155} 150}
151
152export default injectIntl(Locked);
diff --git a/src/components/auth/Login.js b/src/components/auth/Login.js
index 9e6a8d046..a47834e19 100644
--- a/src/components/auth/Login.js
+++ b/src/components/auth/Login.js
@@ -2,7 +2,7 @@
2import React, { Component } from 'react'; 2import React, { Component } from 'react';
3import PropTypes from 'prop-types'; 3import PropTypes from 'prop-types';
4import { observer, inject } from 'mobx-react'; 4import { observer, inject } from 'mobx-react';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6 6
7import { LIVE_FRANZ_API } from '../../config'; 7import { LIVE_FRANZ_API } from '../../config';
8import { API_VERSION, isDevMode, useLiveAPI } from '../../environment'; 8import { API_VERSION, isDevMode, useLiveAPI } from '../../environment';
@@ -19,59 +19,61 @@ import { globalError as globalErrorPropType } from '../../prop-types';
19const messages = defineMessages({ 19const messages = defineMessages({
20 headline: { 20 headline: {
21 id: 'login.headline', 21 id: 'login.headline',
22 defaultMessage: '!!!Sign in', 22 defaultMessage: 'Sign in',
23 }, 23 },
24 emailLabel: { 24 emailLabel: {
25 id: 'login.email.label', 25 id: 'login.email.label',
26 defaultMessage: '!!!Email address', 26 defaultMessage: 'Email address',
27 }, 27 },
28 passwordLabel: { 28 passwordLabel: {
29 id: 'login.password.label', 29 id: 'login.password.label',
30 defaultMessage: '!!!Password', 30 defaultMessage: 'Password',
31 }, 31 },
32 submitButtonLabel: { 32 submitButtonLabel: {
33 id: 'login.submit.label', 33 id: 'login.submit.label',
34 defaultMessage: '!!!Sign in', 34 defaultMessage: 'Sign in',
35 }, 35 },
36 invalidCredentials: { 36 invalidCredentials: {
37 id: 'login.invalidCredentials', 37 id: 'login.invalidCredentials',
38 defaultMessage: '!!!Email or password not valid', 38 defaultMessage: 'Email or password not valid',
39 }, 39 },
40 customServerQuestion: { 40 customServerQuestion: {
41 id: 'login.customServerQuestion', 41 id: 'login.customServerQuestion',
42 defaultMessage: '!!!Using a Franz account to log in?', 42 defaultMessage: 'Using a Franz account to log in?',
43 }, 43 },
44 customServerSuggestion: { 44 customServerSuggestion: {
45 id: 'login.customServerSuggestion', 45 id: 'login.customServerSuggestion',
46 defaultMessage: '!!!Try importing your Franz account into Ferdi', 46 defaultMessage: 'Try importing your Franz account into Ferdi',
47 }, 47 },
48 tokenExpired: { 48 tokenExpired: {
49 id: 'login.tokenExpired', 49 id: 'login.tokenExpired',
50 defaultMessage: '!!!Your session expired, please login again.', 50 defaultMessage: 'Your session expired, please login again.',
51 }, 51 },
52 serverLogout: { 52 serverLogout: {
53 id: 'login.serverLogout', 53 id: 'login.serverLogout',
54 defaultMessage: '!!!Your session expired, please login again.', 54 defaultMessage: 'Your session expired, please login again.',
55 }, 55 },
56 signupLink: { 56 signupLink: {
57 id: 'login.link.signup', 57 id: 'login.link.signup',
58 defaultMessage: '!!!Create a free account', 58 defaultMessage: 'Create a free account',
59 }, 59 },
60 changeServer: { 60 changeServer: {
61 id: 'login.changeServer', 61 id: 'login.changeServer',
62 defaultMessage: '!!!Change server', 62 defaultMessage: 'Change server',
63 }, 63 },
64 serverless: { 64 serverless: {
65 id: 'services.serverless', 65 id: 'services.serverless',
66 defaultMessage: '!!!Use Ferdi without an Account', 66 defaultMessage: 'Use Ferdi without an Account',
67 }, 67 },
68 passwordLink: { 68 passwordLink: {
69 id: 'login.link.password', 69 id: 'login.link.password',
70 defaultMessage: '!!!Forgot password', 70 defaultMessage: 'Forgot password',
71 }, 71 },
72}); 72});
73 73
74export default @inject('actions') @observer class Login extends Component { 74@inject('actions')
75@observer
76class Login extends Component {
75 static propTypes = { 77 static propTypes = {
76 onSubmit: PropTypes.func.isRequired, 78 onSubmit: PropTypes.func.isRequired,
77 isSubmitting: PropTypes.bool.isRequired, 79 isSubmitting: PropTypes.bool.isRequired,
@@ -84,35 +86,34 @@ export default @inject('actions') @observer class Login extends Component {
84 actions: PropTypes.object.isRequired, 86 actions: PropTypes.object.isRequired,
85 }; 87 };
86 88
87 static contextTypes = { 89 form = new Form(
88 intl: intlShape, 90 {
89 }; 91 fields: {
90 92 email: {
91 form = new Form({ 93 label: this.props.intl.formatMessage(messages.emailLabel),
92 fields: { 94 value: '',
93 email: { 95 validators: [required, email],
94 label: this.context.intl.formatMessage(messages.emailLabel), 96 },
95 value: '', 97 password: {
96 validators: [required, email], 98 label: this.props.intl.formatMessage(messages.passwordLabel),
97 }, 99 value: '',
98 password: { 100 validators: [required],
99 label: this.context.intl.formatMessage(messages.passwordLabel), 101 type: 'password',
100 value: '', 102 },
101 validators: [required],
102 type: 'password',
103 }, 103 },
104 }, 104 },
105 }, this.context.intl); 105 this.props.intl,
106 );
106 107
107 emailField = null; 108 emailField = null;
108 109
109 submit(e) { 110 submit(e) {
110 e.preventDefault(); 111 e.preventDefault();
111 this.form.submit({ 112 this.form.submit({
112 onSuccess: (form) => { 113 onSuccess: form => {
113 this.props.onSubmit(form.values()); 114 this.props.onSubmit(form.values());
114 }, 115 },
115 onError: () => { }, 116 onError: () => {},
116 }); 117 });
117 } 118 }
118 119
@@ -122,7 +123,7 @@ export default @inject('actions') @observer class Login extends Component {
122 123
123 render() { 124 render() {
124 const { form } = this; 125 const { form } = this;
125 const { intl } = this.context; 126 const { intl } = this.props;
126 const { 127 const {
127 isSubmitting, 128 isSubmitting,
128 isTokenExpired, 129 isTokenExpired,
@@ -135,42 +136,47 @@ export default @inject('actions') @observer class Login extends Component {
135 136
136 return ( 137 return (
137 <div className="auth__container"> 138 <div className="auth__container">
138 <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}> 139 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
139 <img 140 <img src="./assets/images/logo.svg" className="auth__logo" alt="" />
140 src="./assets/images/logo.svg"
141 className="auth__logo"
142 alt=""
143 />
144 <h1>{intl.formatMessage(messages.headline)}</h1> 141 <h1>{intl.formatMessage(messages.headline)}</h1>
145 {isDevMode && !useLiveAPI && ( 142 {isDevMode && !useLiveAPI && (
146 <Infobox type="warning"> 143 <Infobox type="warning">
147 In Dev Mode your data is not persistent. Please use the live app for accessing the production API. 144 In Dev Mode your data is not persistent. Please use the live app
145 for accessing the production API.
148 </Infobox> 146 </Infobox>
149 )} 147 )}
150 {isTokenExpired && ( 148 {isTokenExpired && (
151 <p className="error-message center">{intl.formatMessage(messages.tokenExpired)}</p> 149 <p className="error-message center">
150 {intl.formatMessage(messages.tokenExpired)}
151 </p>
152 )} 152 )}
153 {isServerLogout && ( 153 {isServerLogout && (
154 <p className="error-message center">{intl.formatMessage(messages.serverLogout)}</p> 154 <p className="error-message center">
155 {intl.formatMessage(messages.serverLogout)}
156 </p>
155 )} 157 )}
156 <Input 158 <Input
157 field={form.$('email')} 159 field={form.$('email')}
158 ref={(element) => { this.emailField = element; }} 160 ref={element => {
161 this.emailField = element;
162 }}
159 focus 163 focus
160 /> 164 />
161 <Input 165 <Input field={form.$('password')} showPasswordToggle />
162 field={form.$('password')}
163 showPasswordToggle
164 />
165 {error.code === 'invalid-credentials' && ( 166 {error.code === 'invalid-credentials' && (
166 <> 167 <>
167 <p className="error-message center">{intl.formatMessage(messages.invalidCredentials)}</p> 168 <p className="error-message center">
168 { window.ferdi.stores.settings.all.app.server !== LIVE_FRANZ_API && ( 169 {intl.formatMessage(messages.invalidCredentials)}
170 </p>
171 {window.ferdi.stores.settings.all.app.server !==
172 LIVE_FRANZ_API && (
169 <p className="error-message center"> 173 <p className="error-message center">
170 {intl.formatMessage(messages.customServerQuestion)} 174 {intl.formatMessage(messages.customServerQuestion)}{' '}
171 {' '}
172 <Link 175 <Link
173 to={`${window.ferdi.stores.settings.all.app.server.replace(API_VERSION, '')}/import`} 176 to={`${window.ferdi.stores.settings.all.app.server.replace(
177 API_VERSION,
178 '',
179 )}/import`}
174 target="_blank" 180 target="_blank"
175 style={{ cursor: 'pointer', textDecoration: 'underline' }} 181 style={{ cursor: 'pointer', textDecoration: 'underline' }}
176 > 182 >
@@ -197,12 +203,22 @@ export default @inject('actions') @observer class Login extends Component {
197 )} 203 )}
198 </form> 204 </form>
199 <div className="auth__links"> 205 <div className="auth__links">
200 <Link to={changeServerRoute}>{intl.formatMessage(messages.changeServer)}</Link> 206 <Link to={changeServerRoute}>
201 <a onClick={this.useLocalServer.bind(this)}>{intl.formatMessage(messages.serverless)}</a> 207 {intl.formatMessage(messages.changeServer)}
202 <Link to={signupRoute}>{intl.formatMessage(messages.signupLink)}</Link> 208 </Link>
203 <Link to={passwordRoute}>{intl.formatMessage(messages.passwordLink)}</Link> 209 <a onClick={this.useLocalServer.bind(this)}>
210 {intl.formatMessage(messages.serverless)}
211 </a>
212 <Link to={signupRoute}>
213 {intl.formatMessage(messages.signupLink)}
214 </Link>
215 <Link to={passwordRoute}>
216 {intl.formatMessage(messages.passwordLink)}
217 </Link>
204 </div> 218 </div>
205 </div> 219 </div>
206 ); 220 );
207 } 221 }
208} 222}
223
224export default injectIntl(Login);
diff --git a/src/components/auth/Password.js b/src/components/auth/Password.js
index 1be2097bd..74346b382 100644
--- a/src/components/auth/Password.js
+++ b/src/components/auth/Password.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5 5
6import Form from '../../lib/Form'; 6import Form from '../../lib/Form';
7import { required, email } from '../../helpers/validation-helpers'; 7import { required, email } from '../../helpers/validation-helpers';
@@ -14,31 +14,32 @@ import globalMessages from '../../i18n/globalMessages';
14const messages = defineMessages({ 14const messages = defineMessages({
15 headline: { 15 headline: {
16 id: 'password.headline', 16 id: 'password.headline',
17 defaultMessage: '!!!Forgot password', 17 defaultMessage: 'Forgot password',
18 }, 18 },
19 emailLabel: { 19 emailLabel: {
20 id: 'password.email.label', 20 id: 'password.email.label',
21 defaultMessage: '!!!Email address', 21 defaultMessage: 'Email address',
22 }, 22 },
23 successInfo: { 23 successInfo: {
24 id: 'password.successInfo', 24 id: 'password.successInfo',
25 defaultMessage: '!!!Your new password was sent to your email address', 25 defaultMessage: 'Your new password was sent to your email address',
26 }, 26 },
27 noUser: { 27 noUser: {
28 id: 'password.noUser', 28 id: 'password.noUser',
29 defaultMessage: '!!!No user affiliated with that email address', 29 defaultMessage: 'No user affiliated with that email address',
30 }, 30 },
31 signupLink: { 31 signupLink: {
32 id: 'password.link.signup', 32 id: 'password.link.signup',
33 defaultMessage: '!!!Create a free account', 33 defaultMessage: 'Create a free account',
34 }, 34 },
35 loginLink: { 35 loginLink: {
36 id: 'password.link.login', 36 id: 'password.link.login',
37 defaultMessage: '!!!Sign in to your account', 37 defaultMessage: 'Sign in to your account',
38 }, 38 },
39}); 39});
40 40
41export default @observer class Password extends Component { 41@observer
42class Password extends Component {
42 static propTypes = { 43 static propTypes = {
43 onSubmit: PropTypes.func.isRequired, 44 onSubmit: PropTypes.func.isRequired,
44 isSubmitting: PropTypes.bool.isRequired, 45 isSubmitting: PropTypes.bool.isRequired,
@@ -47,24 +48,23 @@ export default @observer class Password extends Component {
47 status: MobxPropTypes.arrayOrObservableArray.isRequired, 48 status: MobxPropTypes.arrayOrObservableArray.isRequired,
48 }; 49 };
49 50
50 static contextTypes = { 51 form = new Form(
51 intl: intlShape, 52 {
52 }; 53 fields: {
53 54 email: {
54 form = new Form({ 55 label: this.props.intl.formatMessage(messages.emailLabel),
55 fields: { 56 value: '',
56 email: { 57 validators: [required, email],
57 label: this.context.intl.formatMessage(messages.emailLabel), 58 },
58 value: '',
59 validators: [required, email],
60 }, 59 },
61 }, 60 },
62 }, this.context.intl); 61 this.props.intl,
62 );
63 63
64 submit(e) { 64 submit(e) {
65 e.preventDefault(); 65 e.preventDefault();
66 this.form.submit({ 66 this.form.submit({
67 onSuccess: (form) => { 67 onSuccess: form => {
68 this.props.onSubmit(form.values()); 68 this.props.onSubmit(form.values());
69 }, 69 },
70 onError: () => {}, 70 onError: () => {},
@@ -73,37 +73,24 @@ export default @observer class Password extends Component {
73 73
74 render() { 74 render() {
75 const { form } = this; 75 const { form } = this;
76 const { intl } = this.context; 76 const { intl } = this.props;
77 const { 77 const { isSubmitting, signupRoute, loginRoute, status } = this.props;
78 isSubmitting,
79 signupRoute,
80 loginRoute,
81 status,
82 } = this.props;
83 78
84 return ( 79 return (
85 <div className="auth__container"> 80 <div className="auth__container">
86 <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}> 81 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
87 <img 82 <img src="./assets/images/logo.svg" className="auth__logo" alt="" />
88 src="./assets/images/logo.svg"
89 className="auth__logo"
90 alt=""
91 />
92 <h1>{intl.formatMessage(messages.headline)}</h1> 83 <h1>{intl.formatMessage(messages.headline)}</h1>
93 {status.length > 0 && status.includes('sent') && ( 84 {status.length > 0 && status.includes('sent') && (
94 <Infobox 85 <Infobox type="success" icon="checkbox-marked-circle-outline">
95 type="success"
96 icon="checkbox-marked-circle-outline"
97 >
98 {intl.formatMessage(messages.successInfo)} 86 {intl.formatMessage(messages.successInfo)}
99 </Infobox> 87 </Infobox>
100 )} 88 )}
101 <Input 89 <Input field={form.$('email')} focus />
102 field={form.$('email')}
103 focus
104 />
105 {status.length > 0 && status.includes('no-user') && ( 90 {status.length > 0 && status.includes('no-user') && (
106 <p className="error-message center">{intl.formatMessage(messages.noUser)}</p> 91 <p className="error-message center">
92 {intl.formatMessage(messages.noUser)}
93 </p>
107 )} 94 )}
108 {isSubmitting ? ( 95 {isSubmitting ? (
109 <Button 96 <Button
@@ -123,9 +110,13 @@ export default @observer class Password extends Component {
123 </form> 110 </form>
124 <div className="auth__links"> 111 <div className="auth__links">
125 <Link to={loginRoute}>{intl.formatMessage(messages.loginLink)}</Link> 112 <Link to={loginRoute}>{intl.formatMessage(messages.loginLink)}</Link>
126 <Link to={signupRoute}>{intl.formatMessage(messages.signupLink)}</Link> 113 <Link to={signupRoute}>
114 {intl.formatMessage(messages.signupLink)}
115 </Link>
127 </div> 116 </div>
128 </div> 117 </div>
129 ); 118 );
130 } 119 }
131} 120}
121
122export default injectIntl(Password);
diff --git a/src/components/auth/SetupAssistant.js b/src/components/auth/SetupAssistant.js
index ded36bbe7..299c40c63 100644
--- a/src/components/auth/SetupAssistant.js
+++ b/src/components/auth/SetupAssistant.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import injectSheet from 'react-jss'; 5import injectSheet from 'react-jss';
6import classnames from 'classnames'; 6import classnames from 'classnames';
7 7
@@ -19,20 +19,20 @@ const SLACK_ID = 'slack';
19const messages = defineMessages({ 19const messages = defineMessages({
20 headline: { 20 headline: {
21 id: 'setupAssistant.headline', 21 id: 'setupAssistant.headline',
22 defaultMessage: "!!!Let's get started", 22 defaultMessage: "Let's get started",
23 }, 23 },
24 subHeadline: { 24 subHeadline: {
25 id: 'setupAssistant.subheadline', 25 id: 'setupAssistant.subheadline',
26 defaultMessage: 26 defaultMessage:
27 '!!!Choose from our most used services and get back on top of your messaging now.', 27 'Choose from our most used services and get back on top of your messaging now.',
28 }, 28 },
29 submitButtonLabel: { 29 submitButtonLabel: {
30 id: 'setupAssistant.submit.label', 30 id: 'setupAssistant.submit.label',
31 defaultMessage: "!!!Let's go", 31 defaultMessage: "Let's go",
32 }, 32 },
33 inviteSuccessInfo: { 33 inviteSuccessInfo: {
34 id: 'invite.successInfo', 34 id: 'invite.successInfo',
35 defaultMessage: '!!!Invitations sent successfully', 35 defaultMessage: 'Invitations sent successfully',
36 }, 36 },
37}); 37});
38 38
@@ -145,10 +145,6 @@ class SetupAssistant extends Component {
145 isInviteSuccessful: false, 145 isInviteSuccessful: false,
146 }; 146 };
147 147
148 static contextTypes = {
149 intl: intlShape,
150 };
151
152 state = { 148 state = {
153 services: [ 149 services: [
154 { 150 {
@@ -189,7 +185,7 @@ class SetupAssistant extends Component {
189 } 185 }
190 186
191 render() { 187 render() {
192 const { intl } = this.context; 188 const { intl } = this.props;
193 const { 189 const {
194 classes, 190 classes,
195 isInviteSuccessful, 191 isInviteSuccessful,
@@ -330,4 +326,4 @@ class SetupAssistant extends Component {
330 } 326 }
331} 327}
332 328
333export default SetupAssistant; 329export default injectIntl(SetupAssistant);
diff --git a/src/components/auth/Signup.js b/src/components/auth/Signup.js
index 6fb41a164..4d39835a2 100644
--- a/src/components/auth/Signup.js
+++ b/src/components/auth/Signup.js
@@ -2,7 +2,7 @@
2import React, { Component } from 'react'; 2import React, { Component } from 'react';
3import PropTypes from 'prop-types'; 3import PropTypes from 'prop-types';
4import { observer, inject } from 'mobx-react'; 4import { observer, inject } from 'mobx-react';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6 6
7import { isDevMode, useLiveAPI } from '../../environment'; 7import { isDevMode, useLiveAPI } from '../../environment';
8import Form from '../../lib/Form'; 8import Form from '../../lib/Form';
@@ -19,63 +19,65 @@ import { termsBase } from '../../api/apiBase';
19const messages = defineMessages({ 19const messages = defineMessages({
20 headline: { 20 headline: {
21 id: 'signup.headline', 21 id: 'signup.headline',
22 defaultMessage: '!!!Sign up', 22 defaultMessage: 'Sign up',
23 }, 23 },
24 firstnameLabel: { 24 firstnameLabel: {
25 id: 'signup.firstname.label', 25 id: 'signup.firstname.label',
26 defaultMessage: '!!!Firstname', 26 defaultMessage: 'Firstname',
27 }, 27 },
28 lastnameLabel: { 28 lastnameLabel: {
29 id: 'signup.lastname.label', 29 id: 'signup.lastname.label',
30 defaultMessage: '!!!Lastname', 30 defaultMessage: 'Lastname',
31 }, 31 },
32 emailLabel: { 32 emailLabel: {
33 id: 'signup.email.label', 33 id: 'signup.email.label',
34 defaultMessage: '!!!Email address', 34 defaultMessage: 'Email address',
35 }, 35 },
36 // companyLabel: { 36 // companyLabel: {
37 // id: 'signup.company.label', 37 // id: 'signup.company.label',
38 // defaultMessage: '!!!Company', 38 // defaultMessage: 'Company',
39 // }, 39 // },
40 passwordLabel: { 40 passwordLabel: {
41 id: 'signup.password.label', 41 id: 'signup.password.label',
42 defaultMessage: '!!!Password', 42 defaultMessage: 'Password',
43 }, 43 },
44 legalInfo: { 44 legalInfo: {
45 id: 'signup.legal.info', 45 id: 'signup.legal.info',
46 defaultMessage: '!!!By creating a Ferdi account you accept the', 46 defaultMessage: 'By creating a Ferdi account you accept the',
47 }, 47 },
48 terms: { 48 terms: {
49 id: 'signup.legal.terms', 49 id: 'signup.legal.terms',
50 defaultMessage: '!!!Terms of service', 50 defaultMessage: 'Terms of service',
51 }, 51 },
52 privacy: { 52 privacy: {
53 id: 'signup.legal.privacy', 53 id: 'signup.legal.privacy',
54 defaultMessage: '!!!Privacy Statement', 54 defaultMessage: 'Privacy Statement',
55 }, 55 },
56 submitButtonLabel: { 56 submitButtonLabel: {
57 id: 'signup.submit.label', 57 id: 'signup.submit.label',
58 defaultMessage: '!!!Create account', 58 defaultMessage: 'Create account',
59 }, 59 },
60 loginLink: { 60 loginLink: {
61 id: 'signup.link.login', 61 id: 'signup.link.login',
62 defaultMessage: '!!!Already have an account, sign in?', 62 defaultMessage: 'Already have an account, sign in?',
63 }, 63 },
64 changeServer: { 64 changeServer: {
65 id: 'login.changeServer', 65 id: 'login.changeServer',
66 defaultMessage: '!!!Change server', 66 defaultMessage: 'Change server',
67 }, 67 },
68 serverless: { 68 serverless: {
69 id: 'services.serverless', 69 id: 'services.serverless',
70 defaultMessage: '!!!Use Ferdi without an Account', 70 defaultMessage: 'Use Ferdi without an Account',
71 }, 71 },
72 emailDuplicate: { 72 emailDuplicate: {
73 id: 'signup.emailDuplicate', 73 id: 'signup.emailDuplicate',
74 defaultMessage: '!!!A user with that email address already exists', 74 defaultMessage: 'A user with that email address already exists',
75 }, 75 },
76}); 76});
77 77
78export default @inject('actions') @observer class Signup extends Component { 78@inject('actions')
79@observer
80class Signup extends Component {
79 static propTypes = { 81 static propTypes = {
80 onSubmit: PropTypes.func.isRequired, 82 onSubmit: PropTypes.func.isRequired,
81 isSubmitting: PropTypes.bool.isRequired, 83 isSubmitting: PropTypes.bool.isRequired,
@@ -85,40 +87,39 @@ export default @inject('actions') @observer class Signup extends Component {
85 actions: PropTypes.object.isRequired, 87 actions: PropTypes.object.isRequired,
86 }; 88 };
87 89
88 static contextTypes = { 90 form = new Form(
89 intl: intlShape, 91 {
90 }; 92 fields: {
91 93 firstname: {
92 form = new Form({ 94 label: this.props.intl.formatMessage(messages.firstnameLabel),
93 fields: { 95 value: '',
94 firstname: { 96 validators: [required],
95 label: this.context.intl.formatMessage(messages.firstnameLabel), 97 },
96 value: '', 98 lastname: {
97 validators: [required], 99 label: this.props.intl.formatMessage(messages.lastnameLabel),
98 }, 100 value: '',
99 lastname: { 101 validators: [required],
100 label: this.context.intl.formatMessage(messages.lastnameLabel), 102 },
101 value: '', 103 email: {
102 validators: [required], 104 label: this.props.intl.formatMessage(messages.emailLabel),
103 }, 105 value: '',
104 email: { 106 validators: [required, email],
105 label: this.context.intl.formatMessage(messages.emailLabel), 107 },
106 value: '', 108 password: {
107 validators: [required, email], 109 label: this.props.intl.formatMessage(messages.passwordLabel),
108 }, 110 value: '',
109 password: { 111 validators: [required, minLength(6)],
110 label: this.context.intl.formatMessage(messages.passwordLabel), 112 type: 'password',
111 value: '', 113 },
112 validators: [required, minLength(6)],
113 type: 'password',
114 }, 114 },
115 }, 115 },
116 }, this.context.intl); 116 this.props.intl,
117 );
117 118
118 submit(e) { 119 submit(e) {
119 e.preventDefault(); 120 e.preventDefault();
120 this.form.submit({ 121 this.form.submit({
121 onSuccess: (form) => { 122 onSuccess: form => {
122 this.props.onSubmit(form.values()); 123 this.props.onSubmit(form.values());
123 }, 124 },
124 onError: () => {}, 125 onError: () => {},
@@ -131,24 +132,22 @@ export default @inject('actions') @observer class Signup extends Component {
131 132
132 render() { 133 render() {
133 const { form } = this; 134 const { form } = this;
134 const { intl } = this.context; 135 const { intl } = this.props;
135 const { 136 const { isSubmitting, loginRoute, error, changeServerRoute } = this.props;
136 isSubmitting, loginRoute, error, changeServerRoute,
137 } = this.props;
138 137
139 return ( 138 return (
140 <div className="auth__scroll-container"> 139 <div className="auth__scroll-container">
141 <div className="auth__container auth__container--signup"> 140 <div className="auth__container auth__container--signup">
142 <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}> 141 <form
143 <img 142 className="franz-form auth__form"
144 src="./assets/images/logo.svg" 143 onSubmit={e => this.submit(e)}
145 className="auth__logo" 144 >
146 alt="" 145 <img src="./assets/images/logo.svg" className="auth__logo" alt="" />
147 />
148 <h1>{intl.formatMessage(messages.headline)}</h1> 146 <h1>{intl.formatMessage(messages.headline)}</h1>
149 {isDevMode && !useLiveAPI && ( 147 {isDevMode && !useLiveAPI && (
150 <Infobox type="warning"> 148 <Infobox type="warning">
151 In Dev Mode your data is not persistent. Please use the live app for accesing the production API. 149 In Dev Mode your data is not persistent. Please use the live app
150 for accesing the production API.
152 </Infobox> 151 </Infobox>
153 )} 152 )}
154 <div className="grid__row"> 153 <div className="grid__row">
@@ -162,7 +161,9 @@ export default @inject('actions') @observer class Signup extends Component {
162 scorePassword 161 scorePassword
163 /> 162 />
164 {error.code === 'email-duplicate' && ( 163 {error.code === 'email-duplicate' && (
165 <p className="error-message center">{intl.formatMessage(messages.emailDuplicate)}</p> 164 <p className="error-message center">
165 {intl.formatMessage(messages.emailDuplicate)}
166 </p>
166 )} 167 )}
167 {isSubmitting ? ( 168 {isSubmitting ? (
168 <Button 169 <Button
@@ -200,12 +201,20 @@ export default @inject('actions') @observer class Signup extends Component {
200 </p> 201 </p>
201 </form> 202 </form>
202 <div className="auth__links"> 203 <div className="auth__links">
203 <Link to={changeServerRoute}>{intl.formatMessage(messages.changeServer)}</Link> 204 <Link to={changeServerRoute}>
204 <a onClick={this.useLocalServer.bind(this)}>{intl.formatMessage(messages.serverless)}</a> 205 {intl.formatMessage(messages.changeServer)}
205 <Link to={loginRoute}>{intl.formatMessage(messages.loginLink)}</Link> 206 </Link>
207 <a onClick={this.useLocalServer.bind(this)}>
208 {intl.formatMessage(messages.serverless)}
209 </a>
210 <Link to={loginRoute}>
211 {intl.formatMessage(messages.loginLink)}
212 </Link>
206 </div> 213 </div>
207 </div> 214 </div>
208 </div> 215 </div>
209 ); 216 );
210 } 217 }
211} 218}
219
220export default injectIntl(Signup);
diff --git a/src/components/auth/Welcome.js b/src/components/auth/Welcome.js
index cb522e26e..2d2e2ab28 100644
--- a/src/components/auth/Welcome.js
+++ b/src/components/auth/Welcome.js
@@ -2,7 +2,7 @@
2import React, { Component } from 'react'; 2import React, { Component } from 'react';
3import PropTypes from 'prop-types'; 3import PropTypes from 'prop-types';
4import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; 4import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6import serverlessLogin from '../../helpers/serverless-helpers'; 6import serverlessLogin from '../../helpers/serverless-helpers';
7 7
8import Link from '../ui/Link'; 8import Link from '../ui/Link';
@@ -10,19 +10,21 @@ import Link from '../ui/Link';
10const messages = defineMessages({ 10const messages = defineMessages({
11 signupButton: { 11 signupButton: {
12 id: 'welcome.signupButton', 12 id: 'welcome.signupButton',
13 defaultMessage: '!!!Create a free account', 13 defaultMessage: 'Create a free account',
14 }, 14 },
15 loginButton: { 15 loginButton: {
16 id: 'welcome.loginButton', 16 id: 'welcome.loginButton',
17 defaultMessage: '!!!Login to your account', 17 defaultMessage: 'Login to your account',
18 }, 18 },
19 serverless: { 19 serverless: {
20 id: 'services.serverless', 20 id: 'services.serverless',
21 defaultMessage: '!!!Use Ferdi without an Account', 21 defaultMessage: 'Use Ferdi without an Account',
22 }, 22 },
23}); 23});
24 24
25export default @inject('actions') @observer class Login extends Component { 25@inject('actions')
26@observer
27class Login extends Component {
26 static propTypes = { 28 static propTypes = {
27 loginRoute: PropTypes.string.isRequired, 29 loginRoute: PropTypes.string.isRequired,
28 signupRoute: PropTypes.string.isRequired, 30 signupRoute: PropTypes.string.isRequired,
@@ -31,27 +33,22 @@ export default @inject('actions') @observer class Login extends Component {
31 actions: PropTypes.object.isRequired, 33 actions: PropTypes.object.isRequired,
32 }; 34 };
33 35
34 static contextTypes = {
35 intl: intlShape,
36 };
37
38 useLocalServer() { 36 useLocalServer() {
39 serverlessLogin(this.props.actions); 37 serverlessLogin(this.props.actions);
40 } 38 }
41 39
42 render() { 40 render() {
43 const { intl } = this.context; 41 const { intl } = this.props;
44 const { 42 const { loginRoute, signupRoute, changeServerRoute, recipes } = this.props;
45 loginRoute,
46 signupRoute,
47 changeServerRoute,
48 recipes,
49 } = this.props;
50 43
51 return ( 44 return (
52 <div className="welcome"> 45 <div className="welcome">
53 <div className="welcome__content"> 46 <div className="welcome__content">
54 <img src="./assets/images/logo.svg" className="welcome__logo" alt="" /> 47 <img
48 src="./assets/images/logo.svg"
49 className="welcome__logo"
50 alt=""
51 />
55 {/* <img src="./assets/images/welcome.png" className="welcome__services" alt="" /> */} 52 {/* <img src="./assets/images/welcome.png" className="welcome__services" alt="" /> */}
56 <div className="welcome__text"> 53 <div className="welcome__text">
57 <h1>Ferdi</h1> 54 <h1>Ferdi</h1>
@@ -73,27 +70,21 @@ export default @inject('actions') @observer class Login extends Component {
73 <br /> 70 <br />
74 71
75 <Link to={changeServerRoute}> 72 <Link to={changeServerRoute}>
76 <span style={{ 73 <span
77 textAlign: 'center', 74 style={{
78 width: '100%', 75 textAlign: 'center',
79 cursor: 'pointer', 76 width: '100%',
80 }} 77 cursor: 'pointer',
78 }}
81 > 79 >
82 Change server 80 Change server
83 </span> 81 </span>
84 </Link> 82 </Link>
85 </div> 83 </div>
86 <div className="welcome__featured-services"> 84 <div className="welcome__featured-services">
87 {recipes.map((recipe) => ( 85 {recipes.map(recipe => (
88 <div 86 <div key={recipe.id} className="welcome__featured-service">
89 key={recipe.id} 87 <img key={recipe.id} src={recipe.icons.svg} alt="" />
90 className="welcome__featured-service"
91 >
92 <img
93 key={recipe.id}
94 src={recipe.icons.svg}
95 alt=""
96 />
97 </div> 88 </div>
98 ))} 89 ))}
99 </div> 90 </div>
@@ -101,3 +92,5 @@ export default @inject('actions') @observer class Login extends Component {
101 ); 92 );
102 } 93 }
103} 94}
95
96export default injectIntl(Login);
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js
index e6e5d40fe..83e037083 100644
--- a/src/components/layout/AppLayout.js
+++ b/src/components/layout/AppLayout.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import { TitleBar } from 'electron-react-titlebar'; 5import { TitleBar } from 'electron-react-titlebar';
6import injectSheet from 'react-jss'; 6import injectSheet from 'react-jss';
7 7
@@ -27,20 +27,20 @@ function createMarkup(HTMLString) {
27const messages = defineMessages({ 27const messages = defineMessages({
28 servicesUpdated: { 28 servicesUpdated: {
29 id: 'infobar.servicesUpdated', 29 id: 'infobar.servicesUpdated',
30 defaultMessage: '!!!Your services have been updated.', 30 defaultMessage: 'Your services have been updated.',
31 }, 31 },
32 buttonReloadServices: { 32 buttonReloadServices: {
33 id: 'infobar.buttonReloadServices', 33 id: 'infobar.buttonReloadServices',
34 defaultMessage: '!!!Reload services', 34 defaultMessage: 'Reload services',
35 }, 35 },
36 requiredRequestsFailed: { 36 requiredRequestsFailed: {
37 id: 'infobar.requiredRequestsFailed', 37 id: 'infobar.requiredRequestsFailed',
38 defaultMessage: '!!!Could not load services and user information', 38 defaultMessage: 'Could not load services and user information',
39 }, 39 },
40 authRequestFailed: { 40 authRequestFailed: {
41 id: 'infobar.authRequestFailed', 41 id: 'infobar.authRequestFailed',
42 defaultMessage: 42 defaultMessage:
43 '!!!There were errors while trying to perform an authenticated request. Please try logging out and back in if this error persists.', 43 'There were errors while trying to perform an authenticated request. Please try logging out and back in if this error persists.',
44 }, 44 },
45}); 45});
46 46
@@ -94,10 +94,6 @@ class AppLayout extends Component {
94 children: [], 94 children: [],
95 }; 95 };
96 96
97 static contextTypes = {
98 intl: intlShape,
99 };
100
101 render() { 97 render() {
102 const { 98 const {
103 classes, 99 classes,
@@ -119,7 +115,7 @@ class AppLayout extends Component {
119 areRequiredRequestsLoading, 115 areRequiredRequestsLoading,
120 } = this.props; 116 } = this.props;
121 117
122 const { intl } = this.context; 118 const { intl } = this.props;
123 119
124 return ( 120 return (
125 <ErrorBoundary> 121 <ErrorBoundary>
@@ -213,4 +209,4 @@ class AppLayout extends Component {
213 } 209 }
214} 210}
215 211
216export default AppLayout; 212export default injectIntl(AppLayout);
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js
index 1ee7733b9..87233f7ca 100644
--- a/src/components/layout/Sidebar.js
+++ b/src/components/layout/Sidebar.js
@@ -1,12 +1,19 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import ReactTooltip from 'react-tooltip'; 3import ReactTooltip from 'react-tooltip';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import { inject, observer } from 'mobx-react'; 5import { inject, observer } from 'mobx-react';
6import { Link } from 'react-router'; 6import { Link } from 'react-router';
7 7
8import Tabbar from '../services/tabs/Tabbar'; 8import Tabbar from '../services/tabs/Tabbar';
9import { settingsShortcutKey, lockFerdiShortcutKey, todosToggleShortcutKey, workspaceToggleShortcutKey, addNewServiceShortcutKey, muteFerdiShortcutKey } from '../../environment'; 9import {
10 settingsShortcutKey,
11 lockFerdiShortcutKey,
12 todosToggleShortcutKey,
13 workspaceToggleShortcutKey,
14 addNewServiceShortcutKey,
15 muteFerdiShortcutKey,
16} from '../../environment';
10import { workspaceStore } from '../../features/workspaces'; 17import { workspaceStore } from '../../features/workspaces';
11import { todosStore } from '../../features/todos'; 18import { todosStore } from '../../features/todos';
12import { todoActions } from '../../features/todos/actions'; 19import { todoActions } from '../../features/todos/actions';
@@ -17,39 +24,41 @@ import globalMessages from '../../i18n/globalMessages';
17const messages = defineMessages({ 24const messages = defineMessages({
18 addNewService: { 25 addNewService: {
19 id: 'sidebar.addNewService', 26 id: 'sidebar.addNewService',
20 defaultMessage: '!!!Add new service', 27 defaultMessage: 'Add new service',
21 }, 28 },
22 mute: { 29 mute: {
23 id: 'sidebar.muteApp', 30 id: 'sidebar.muteApp',
24 defaultMessage: '!!!Disable notifications & audio', 31 defaultMessage: 'Disable notifications & audio',
25 }, 32 },
26 unmute: { 33 unmute: {
27 id: 'sidebar.unmuteApp', 34 id: 'sidebar.unmuteApp',
28 defaultMessage: '!!!Enable notifications & audio', 35 defaultMessage: 'Enable notifications & audio',
29 }, 36 },
30 openWorkspaceDrawer: { 37 openWorkspaceDrawer: {
31 id: 'sidebar.openWorkspaceDrawer', 38 id: 'sidebar.openWorkspaceDrawer',
32 defaultMessage: '!!!Open workspace drawer', 39 defaultMessage: 'Open workspace drawer',
33 }, 40 },
34 closeWorkspaceDrawer: { 41 closeWorkspaceDrawer: {
35 id: 'sidebar.closeWorkspaceDrawer', 42 id: 'sidebar.closeWorkspaceDrawer',
36 defaultMessage: '!!!Close workspace drawer', 43 defaultMessage: 'Close workspace drawer',
37 }, 44 },
38 openTodosDrawer: { 45 openTodosDrawer: {
39 id: 'sidebar.openTodosDrawer', 46 id: 'sidebar.openTodosDrawer',
40 defaultMessage: '!!!Open Ferdi Todos', 47 defaultMessage: 'Open Ferdi Todos',
41 }, 48 },
42 closeTodosDrawer: { 49 closeTodosDrawer: {
43 id: 'sidebar.closeTodosDrawer', 50 id: 'sidebar.closeTodosDrawer',
44 defaultMessage: '!!!Close Ferdi Todos', 51 defaultMessage: 'Close Ferdi Todos',
45 }, 52 },
46 lockFerdi: { 53 lockFerdi: {
47 id: 'sidebar.lockFerdi', 54 id: 'sidebar.lockFerdi',
48 defaultMessage: '!!!Lock Ferdi', 55 defaultMessage: 'Lock Ferdi',
49 }, 56 },
50}); 57});
51 58
52export default @inject('stores', 'actions') @observer class Sidebar extends Component { 59@inject('stores', 'actions')
60@observer
61class Sidebar extends Component {
53 static propTypes = { 62 static propTypes = {
54 openSettings: PropTypes.func.isRequired, 63 openSettings: PropTypes.func.isRequired,
55 closeSettings: PropTypes.func.isRequired, 64 closeSettings: PropTypes.func.isRequired,
@@ -79,10 +88,6 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp
79 }).isRequired, 88 }).isRequired,
80 }; 89 };
81 90
82 static contextTypes = {
83 intl: intlShape,
84 };
85
86 state = { 91 state = {
87 tooltipEnabled: true, 92 tooltipEnabled: true,
88 }; 93 };
@@ -115,14 +120,14 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp
115 actions, 120 actions,
116 isTodosServiceActive, 121 isTodosServiceActive,
117 } = this.props; 122 } = this.props;
118 const { intl } = this.context; 123 const { intl } = this.props;
119 const todosToggleMessage = ( 124 const todosToggleMessage = todosStore.isTodosPanelVisible
120 todosStore.isTodosPanelVisible ? messages.closeTodosDrawer : messages.openTodosDrawer 125 ? messages.closeTodosDrawer
121 ); 126 : messages.openTodosDrawer;
122 127
123 const workspaceToggleMessage = ( 128 const workspaceToggleMessage = isWorkspaceDrawerOpen
124 isWorkspaceDrawerOpen ? messages.closeWorkspaceDrawer : messages.openWorkspaceDrawer 129 ? messages.closeWorkspaceDrawer
125 ); 130 : messages.openWorkspaceDrawer;
126 const isLoggedIn = Boolean(localStorage.getItem('authToken')); 131 const isLoggedIn = Boolean(localStorage.getItem('authToken'));
127 132
128 return ( 133 return (
@@ -133,9 +138,9 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp
133 disableToolTip={() => this.disableToolTip()} 138 disableToolTip={() => this.disableToolTip()}
134 useVerticalStyle={stores.settings.all.app.useVerticalStyle} 139 useVerticalStyle={stores.settings.all.app.useVerticalStyle}
135 /> 140 />
136 { isLoggedIn ? ( 141 {isLoggedIn ? (
137 <> 142 <>
138 { stores.settings.all.app.lockingFeatureEnabled ? ( 143 {stores.settings.all.app.lockingFeatureEnabled ? (
139 <button 144 <button
140 type="button" 145 type="button"
141 className="sidebar__button" 146 className="sidebar__button"
@@ -147,12 +152,15 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp
147 }, 152 },
148 }); 153 });
149 }} 154 }}
150 data-tip={`${intl.formatMessage(messages.lockFerdi)} (${lockFerdiShortcutKey(false)})`} 155 data-tip={`${intl.formatMessage(
156 messages.lockFerdi,
157 )} (${lockFerdiShortcutKey(false)})`}
151 > 158 >
152 <i className="mdi mdi-lock" /> 159 <i className="mdi mdi-lock" />
153 </button> 160 </button>
154 ) : null} 161 ) : null}
155 {todosStore.isFeatureEnabled && todosStore.isFeatureEnabledByUser ? ( 162 {todosStore.isFeatureEnabled &&
163 todosStore.isFeatureEnabledByUser ? (
156 <button 164 <button
157 type="button" 165 type="button"
158 onClick={() => { 166 onClick={() => {
@@ -160,12 +168,16 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp
160 this.updateToolTip(); 168 this.updateToolTip();
161 }} 169 }}
162 disabled={isTodosServiceActive} 170 disabled={isTodosServiceActive}
163 className={`sidebar__button sidebar__button--todos ${todosStore.isTodosPanelVisible ? 'is-active' : ''}`} 171 className={`sidebar__button sidebar__button--todos ${
164 data-tip={`${intl.formatMessage(todosToggleMessage)} (${todosToggleShortcutKey(false)})`} 172 todosStore.isTodosPanelVisible ? 'is-active' : ''
173 }`}
174 data-tip={`${intl.formatMessage(
175 todosToggleMessage,
176 )} (${todosToggleShortcutKey(false)})`}
165 > 177 >
166 <i className="mdi mdi-check-all" /> 178 <i className="mdi mdi-check-all" />
167 </button> 179 </button>
168 ) : null} 180 ) : null}
169 {workspaceStore.isFeatureEnabled ? ( 181 {workspaceStore.isFeatureEnabled ? (
170 <button 182 <button
171 type="button" 183 type="button"
@@ -173,8 +185,12 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp
173 toggleWorkspaceDrawer(); 185 toggleWorkspaceDrawer();
174 this.updateToolTip(); 186 this.updateToolTip();
175 }} 187 }}
176 className={`sidebar__button sidebar__button--workspaces ${isWorkspaceDrawerOpen ? 'is-active' : ''}`} 188 className={`sidebar__button sidebar__button--workspaces ${
177 data-tip={`${intl.formatMessage(workspaceToggleMessage)} (${workspaceToggleShortcutKey(false)})`} 189 isWorkspaceDrawerOpen ? 'is-active' : ''
190 }`}
191 data-tip={`${intl.formatMessage(
192 workspaceToggleMessage,
193 )} (${workspaceToggleShortcutKey(false)})`}
178 > 194 >
179 <i className="mdi mdi-view-grid" /> 195 <i className="mdi mdi-view-grid" />
180 </button> 196 </button>
@@ -185,8 +201,12 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp
185 toggleMuteApp(); 201 toggleMuteApp();
186 this.updateToolTip(); 202 this.updateToolTip();
187 }} 203 }}
188 className={`sidebar__button sidebar__button--audio ${isAppMuted ? 'is-muted' : ''}`} 204 className={`sidebar__button sidebar__button--audio ${
189 data-tip={`${intl.formatMessage(isAppMuted ? messages.unmute : messages.mute)} (${muteFerdiShortcutKey(false)})`} 205 isAppMuted ? 'is-muted' : ''
206 }`}
207 data-tip={`${intl.formatMessage(
208 isAppMuted ? messages.unmute : messages.mute,
209 )} (${muteFerdiShortcutKey(false)})`}
190 > 210 >
191 <i className={`mdi mdi-bell${isAppMuted ? '-off' : ''}`} /> 211 <i className={`mdi mdi-bell${isAppMuted ? '-off' : ''}`} />
192 </button> 212 </button>
@@ -194,7 +214,9 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp
194 type="button" 214 type="button"
195 onClick={() => openSettings({ path: 'recipes' })} 215 onClick={() => openSettings({ path: 'recipes' })}
196 className="sidebar__button sidebar__button--new-service" 216 className="sidebar__button sidebar__button--new-service"
197 data-tip={`${intl.formatMessage(messages.addNewService)} (${addNewServiceShortcutKey(false)})`} 217 data-tip={`${intl.formatMessage(
218 messages.addNewService,
219 )} (${addNewServiceShortcutKey(false)})`}
198 > 220 >
199 <i className="mdi mdi-plus-box" /> 221 <i className="mdi mdi-plus-box" />
200 </button> 222 </button>
@@ -212,15 +234,17 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp
212 type="button" 234 type="button"
213 onClick={() => openSettings({ path: 'app' })} 235 onClick={() => openSettings({ path: 'app' })}
214 className="sidebar__button sidebar__button--settings" 236 className="sidebar__button sidebar__button--settings"
215 data-tip={`${intl.formatMessage(globalMessages.settings)} (${settingsShortcutKey(false)})`} 237 data-tip={`${intl.formatMessage(
238 globalMessages.settings,
239 )} (${settingsShortcutKey(false)})`}
216 > 240 >
217 <i className="mdi mdi-cog" /> 241 <i className="mdi mdi-cog" />
218 { (this.props.stores.app.updateStatus === this.props.stores.app.updateStatusTypes.AVAILABLE 242 {(this.props.stores.app.updateStatus ===
219 || this.props.stores.app.updateStatus === this.props.stores.app.updateStatusTypes.DOWNLOADED) && ( 243 this.props.stores.app.updateStatusTypes.AVAILABLE ||
220 <span className="update-available"> 244 this.props.stores.app.updateStatus ===
221 245 this.props.stores.app.updateStatusTypes.DOWNLOADED) && (
222 </span> 246 <span className="update-available">•</span>
223 ) } 247 )}
224 </button> 248 </button>
225 {this.state.tooltipEnabled && ( 249 {this.state.tooltipEnabled && (
226 <ReactTooltip place="right" type="dark" effect="solid" /> 250 <ReactTooltip place="right" type="dark" effect="solid" />
@@ -229,3 +253,5 @@ export default @inject('stores', 'actions') @observer class Sidebar extends Comp
229 ); 253 );
230 } 254 }
231} 255}
256
257export default injectIntl(Sidebar);
diff --git a/src/components/services/content/ConnectionLostBanner.js b/src/components/services/content/ConnectionLostBanner.js
index ebe863333..423edb3c7 100644
--- a/src/components/services/content/ConnectionLostBanner.js
+++ b/src/components/services/content/ConnectionLostBanner.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import injectSheet from 'react-jss'; 4import injectSheet from 'react-jss';
5import { Icon } from '@meetfranz/ui'; 5import { Icon } from '@meetfranz/ui';
6import { intlShape, defineMessages } from 'react-intl'; 6import { defineMessages, injectIntl } from 'react-intl';
7 7
8import { mdiAlert } from '@mdi/js'; 8import { mdiAlert } from '@mdi/js';
9import { LIVE_API_FERDI_WEBSITE } from '../../../config'; 9import { LIVE_API_FERDI_WEBSITE } from '../../../config';
@@ -12,15 +12,15 @@ import { LIVE_API_FERDI_WEBSITE } from '../../../config';
12const messages = defineMessages({ 12const messages = defineMessages({
13 text: { 13 text: {
14 id: 'connectionLostBanner.message', 14 id: 'connectionLostBanner.message',
15 defaultMessage: '!!!Oh no! Ferdi lost the connection to {name}.', 15 defaultMessage: 'Oh no! Ferdi lost the connection to {name}.',
16 }, 16 },
17 moreInformation: { 17 moreInformation: {
18 id: 'connectionLostBanner.informationLink', 18 id: 'connectionLostBanner.informationLink',
19 defaultMessage: '!!!What happened?', 19 defaultMessage: 'What happened?',
20 }, 20 },
21 cta: { 21 cta: {
22 id: 'connectionLostBanner.cta', 22 id: 'connectionLostBanner.cta',
23 defaultMessage: '!!!Reload Service', 23 defaultMessage: 'Reload Service',
24 }, 24 },
25}); 25});
26 26
@@ -78,16 +78,12 @@ class ConnectionLostBanner extends Component {
78 reload: PropTypes.func.isRequired, 78 reload: PropTypes.func.isRequired,
79 }; 79 };
80 80
81 static contextTypes = {
82 intl: intlShape,
83 };
84
85 inputRef = React.createRef(); 81 inputRef = React.createRef();
86 82
87 render() { 83 render() {
88 const { classes, name, reload } = this.props; 84 const { classes, name, reload } = this.props;
89 85
90 const { intl } = this.context; 86 const { intl } = this.props;
91 87
92 return ( 88 return (
93 <div className={classes.root}> 89 <div className={classes.root}>
@@ -110,4 +106,4 @@ class ConnectionLostBanner extends Component {
110 } 106 }
111} 107}
112 108
113export default ConnectionLostBanner; 109export default injectIntl(ConnectionLostBanner);
diff --git a/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js b/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js
index 36e0ac418..41d84c0b0 100644
--- a/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js
+++ b/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import injectSheet from 'react-jss'; 5import injectSheet from 'react-jss';
6 6
7import Button from '../../../ui/Button'; 7import Button from '../../../ui/Button';
@@ -11,27 +11,29 @@ import styles from './styles';
11const messages = defineMessages({ 11const messages = defineMessages({
12 headline: { 12 headline: {
13 id: 'service.errorHandler.headline', 13 id: 'service.errorHandler.headline',
14 defaultMessage: '!!!Oh no!', 14 defaultMessage: 'Oh no!',
15 }, 15 },
16 text: { 16 text: {
17 id: 'service.errorHandler.text', 17 id: 'service.errorHandler.text',
18 defaultMessage: '!!!{name} has failed to load.', 18 defaultMessage: '{name} has failed to load.',
19 }, 19 },
20 action: { 20 action: {
21 id: 'service.errorHandler.action', 21 id: 'service.errorHandler.action',
22 defaultMessage: '!!!Reload {name}', 22 defaultMessage: 'Reload {name}',
23 }, 23 },
24 editAction: { 24 editAction: {
25 id: 'service.errorHandler.editAction', 25 id: 'service.errorHandler.editAction',
26 defaultMessage: '!!!Edit {name}', 26 defaultMessage: 'Edit {name}',
27 }, 27 },
28 errorMessage: { 28 errorMessage: {
29 id: 'service.errorHandler.message', 29 id: 'service.errorHandler.message',
30 defaultMessage: '!!!Error:', 30 defaultMessage: 'Error:',
31 }, 31 },
32}); 32});
33 33
34export default @injectSheet(styles) @observer class WebviewErrorHandler extends Component { 34@injectSheet(styles)
35@observer
36class WebviewErrorHandler extends Component {
35 static propTypes = { 37 static propTypes = {
36 name: PropTypes.string.isRequired, 38 name: PropTypes.string.isRequired,
37 reload: PropTypes.func.isRequired, 39 reload: PropTypes.func.isRequired,
@@ -40,30 +42,16 @@ export default @injectSheet(styles) @observer class WebviewErrorHandler extends
40 classes: PropTypes.object.isRequired, 42 classes: PropTypes.object.isRequired,
41 }; 43 };
42 44
43 static contextTypes = {
44 intl: intlShape,
45 };
46
47 render() { 45 render() {
48 const { 46 const { name, reload, edit, errorMessage, classes } = this.props;
49 name, 47 const { intl } = this.props;
50 reload,
51 edit,
52 errorMessage,
53 classes,
54 } = this.props;
55 const { intl } = this.context;
56 48
57 return ( 49 return (
58 <div className={classes.component}> 50 <div className={classes.component}>
59 <h1>{intl.formatMessage(messages.headline)}</h1> 51 <h1>{intl.formatMessage(messages.headline)}</h1>
60 <p>{intl.formatMessage(messages.text, { name })}</p> 52 <p>{intl.formatMessage(messages.text, { name })}</p>
61 <p> 53 <p>
62 <strong> 54 <strong>{intl.formatMessage(messages.errorMessage)}:</strong>{' '}
63 {intl.formatMessage(messages.errorMessage)}
64 :
65 </strong>
66 {' '}
67 {errorMessage} 55 {errorMessage}
68 </p> 56 </p>
69 <div className={classes.buttonContainer}> 57 <div className={classes.buttonContainer}>
@@ -82,3 +70,5 @@ export default @injectSheet(styles) @observer class WebviewErrorHandler extends
82 ); 70 );
83 } 71 }
84} 72}
73
74export default injectIntl(WebviewErrorHandler);
diff --git a/src/components/services/content/ServiceDisabled.js b/src/components/services/content/ServiceDisabled.js
index d0f12256e..e59ed58bd 100644
--- a/src/components/services/content/ServiceDisabled.js
+++ b/src/components/services/content/ServiceDisabled.js
@@ -1,38 +1,35 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5 5
6import Button from '../../ui/Button'; 6import Button from '../../ui/Button';
7 7
8const messages = defineMessages({ 8const messages = defineMessages({
9 headline: { 9 headline: {
10 id: 'service.disabledHandler.headline', 10 id: 'service.disabledHandler.headline',
11 defaultMessage: '!!!{name} is disabled', 11 defaultMessage: '{name} is disabled',
12 }, 12 },
13 action: { 13 action: {
14 id: 'service.disabledHandler.action', 14 id: 'service.disabledHandler.action',
15 defaultMessage: '!!!Enable {name}', 15 defaultMessage: 'Enable {name}',
16 }, 16 },
17}); 17});
18 18
19export default @observer class ServiceDisabled extends Component { 19@observer
20class ServiceDisabled extends Component {
20 static propTypes = { 21 static propTypes = {
21 name: PropTypes.string.isRequired, 22 name: PropTypes.string.isRequired,
22 enable: PropTypes.func.isRequired, 23 enable: PropTypes.func.isRequired,
23 }; 24 };
24 25
25 static contextTypes = {
26 intl: intlShape,
27 };
28
29 countdownInterval = null; 26 countdownInterval = null;
30 27
31 countdownIntervalTimeout = 1000; 28 countdownIntervalTimeout = 1000;
32 29
33 render() { 30 render() {
34 const { name, enable } = this.props; 31 const { name, enable } = this.props;
35 const { intl } = this.context; 32 const { intl } = this.props;
36 33
37 return ( 34 return (
38 <div className="services__info-layer"> 35 <div className="services__info-layer">
@@ -46,3 +43,5 @@ export default @observer class ServiceDisabled extends Component {
46 ); 43 );
47 } 44 }
48} 45}
46
47export default injectIntl(ServiceDisabled);
diff --git a/src/components/services/content/ServiceView.js b/src/components/services/content/ServiceView.js
index 3fc084ff0..fa866e153 100644
--- a/src/components/services/content/ServiceView.js
+++ b/src/components/services/content/ServiceView.js
@@ -15,7 +15,9 @@ import SettingsStore from '../../../stores/SettingsStore';
15import WebControlsScreen from '../../../features/webControls/containers/WebControlsScreen'; 15import WebControlsScreen from '../../../features/webControls/containers/WebControlsScreen';
16import { CUSTOM_WEBSITE_RECIPE_ID } from '../../../config'; 16import { CUSTOM_WEBSITE_RECIPE_ID } from '../../../config';
17 17
18export default @inject('stores', 'actions') @observer class ServiceView extends Component { 18@inject('stores', 'actions')
19@observer
20class ServiceView extends Component {
19 static propTypes = { 21 static propTypes = {
20 service: PropTypes.instanceOf(ServiceModel).isRequired, 22 service: PropTypes.instanceOf(ServiceModel).isRequired,
21 setWebviewReference: PropTypes.func.isRequired, 23 setWebviewReference: PropTypes.func.isRequired,
@@ -63,7 +65,7 @@ export default @inject('stores', 'actions') @observer class ServiceView extends
63 clearTimeout(this.hibernationTimer); 65 clearTimeout(this.hibernationTimer);
64 } 66 }
65 67
66 updateTargetUrl = (event) => { 68 updateTargetUrl = event => {
67 let visible = true; 69 let visible = true;
68 if (event.url === '' || event.url === '#') { 70 if (event.url === '' || event.url === '#') {
69 visible = false; 71 visible = false;
@@ -86,11 +88,12 @@ export default @inject('stores', 'actions') @observer class ServiceView extends
86 isSpellcheckerEnabled, 88 isSpellcheckerEnabled,
87 } = this.props; 89 } = this.props;
88 90
89 const { 91 const { navigationBarBehaviour } = stores.settings.app;
90 navigationBarBehaviour,
91 } = stores.settings.app;
92 92
93 const showNavBar = navigationBarBehaviour === 'always' || (navigationBarBehaviour === 'custom' && service.recipe.id === CUSTOM_WEBSITE_RECIPE_ID); 93 const showNavBar =
94 navigationBarBehaviour === 'always' ||
95 (navigationBarBehaviour === 'custom' &&
96 service.recipe.id === CUSTOM_WEBSITE_RECIPE_ID);
94 97
95 const webviewClasses = classnames({ 98 const webviewClasses = classnames({
96 services__webview: true, 99 services__webview: true,
@@ -101,9 +104,7 @@ export default @inject('stores', 'actions') @observer class ServiceView extends
101 104
102 let statusBar = null; 105 let statusBar = null;
103 if (this.state.statusBarVisible) { 106 if (this.state.statusBarVisible) {
104 statusBar = ( 107 statusBar = <StatusBarTargetUrl text={this.state.targetUrl} />;
105 <StatusBarTargetUrl text={this.state.targetUrl} />
106 );
107 } 108 }
108 109
109 return ( 110 return (
@@ -117,11 +118,11 @@ export default @inject('stores', 'actions') @observer class ServiceView extends
117 reload={reload} 118 reload={reload}
118 /> 119 />
119 )} 120 )}
120 {service.isEnabled && service.isLoading && service.isFirstLoad && !service.isServiceAccessRestricted && ( 121 {service.isEnabled &&
121 <WebviewLoader 122 service.isLoading &&
122 loaded={false} 123 service.isFirstLoad &&
123 name={service.name} 124 !service.isServiceAccessRestricted && (
124 /> 125 <WebviewLoader loaded={false} name={service.name} />
125 )} 126 )}
126 {service.isError && ( 127 {service.isError && (
127 <WebviewErrorHandler 128 <WebviewErrorHandler
@@ -147,9 +148,7 @@ export default @inject('stores', 'actions') @observer class ServiceView extends
147 <> 148 <>
148 {!service.isHibernating ? ( 149 {!service.isHibernating ? (
149 <> 150 <>
150 {showNavBar && ( 151 {showNavBar && <WebControlsScreen service={service} />}
151 <WebControlsScreen service={service} />
152 )}
153 <ServiceWebview 152 <ServiceWebview
154 service={service} 153 service={service}
155 setWebviewReference={setWebviewReference} 154 setWebviewReference={setWebviewReference}
@@ -159,9 +158,11 @@ export default @inject('stores', 'actions') @observer class ServiceView extends
159 </> 158 </>
160 ) : ( 159 ) : (
161 <div> 160 <div>
162 <span role="img" aria-label="Sleeping Emoji">😴</span> 161 <span role="img" aria-label="Sleeping Emoji">
163 {' '} 162 😴
164 This service is currently hibernating. If this page doesn&#x27;t close soon, please try reloading Ferdi. 163 </span>{' '}
164 This service is currently hibernating. If this page doesn&#x27;t
165 close soon, please try reloading Ferdi.
165 </div> 166 </div>
166 )} 167 )}
167 </> 168 </>
@@ -171,3 +172,5 @@ export default @inject('stores', 'actions') @observer class ServiceView extends
171 ); 172 );
172 } 173 }
173} 174}
175
176export default ServiceView;
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js
index bb93ff7d4..fb43fb816 100644
--- a/src/components/services/content/Services.js
+++ b/src/components/services/content/Services.js
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react';
4import { Link } from 'react-router'; 4import { Link } from 'react-router';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6import Confetti from 'react-confetti'; 6import Confetti from 'react-confetti';
7import ms from 'ms'; 7import ms from 'ms';
8import injectSheet from 'react-jss'; 8import injectSheet from 'react-jss';
@@ -14,23 +14,24 @@ import serverlessLogin from '../../../helpers/serverless-helpers';
14const messages = defineMessages({ 14const messages = defineMessages({
15 welcome: { 15 welcome: {
16 id: 'services.welcome', 16 id: 'services.welcome',
17 defaultMessage: '!!!Welcome to Ferdi', 17 defaultMessage: 'Welcome to Ferdi',
18 }, 18 },
19 getStarted: { 19 getStarted: {
20 id: 'services.getStarted', 20 id: 'services.getStarted',
21 defaultMessage: '!!!Get started', 21 defaultMessage: 'Get started',
22 }, 22 },
23 login: { 23 login: {
24 id: 'services.login', 24 id: 'services.login',
25 defaultMessage: '!!!Please login to use Ferdi.', 25 defaultMessage: 'Please login to use Ferdi.',
26 }, 26 },
27 serverless: { 27 serverless: {
28 id: 'services.serverless', 28 id: 'services.serverless',
29 defaultMessage: '!!!Use Ferdi without an Account', 29 defaultMessage: 'Use Ferdi without an Account',
30 }, 30 },
31 serverInfo: { 31 serverInfo: {
32 id: 'services.serverInfo', 32 id: 'services.serverInfo',
33 defaultMessage: '!!!Optionally, you can change your Ferdi server by clicking the cog in the bottom left corner. If you are switching over (from one of the hosted servers) to using Ferdi without an account, please be informed that you can export your data from that server and subsequently import it using the Help menu to resurrect all your workspaces and configured services!', 33 defaultMessage:
34 'Optionally, you can change your Ferdi server by clicking the cog in the bottom left corner. If you are switching over (from one of the hosted servers) to using Ferdi without an account, please be informed that you can export your data from that server and subsequently import it using the Help menu to resurrect all your workspaces and configured services!',
34 }, 35 },
35}); 36});
36 37
@@ -43,7 +44,10 @@ const styles = {
43 }, 44 },
44}; 45};
45 46
46export default @injectSheet(styles) @inject('actions') @observer class Services extends Component { 47@injectSheet(styles)
48@inject('actions')
49@observer
50class Services extends Component {
47 static propTypes = { 51 static propTypes = {
48 services: MobxPropTypes.arrayOrObservableArray, 52 services: MobxPropTypes.arrayOrObservableArray,
49 setWebviewReference: PropTypes.func.isRequired, 53 setWebviewReference: PropTypes.func.isRequired,
@@ -63,10 +67,6 @@ export default @injectSheet(styles) @inject('actions') @observer class Services
63 services: [], 67 services: [],
64 }; 68 };
65 69
66 static contextTypes = {
67 intl: intlShape,
68 };
69
70 state = { 70 state = {
71 showConfetti: true, 71 showConfetti: true,
72 }; 72 };
@@ -112,11 +112,9 @@ export default @injectSheet(styles) @inject('actions') @observer class Services
112 isSpellcheckerEnabled, 112 isSpellcheckerEnabled,
113 } = this.props; 113 } = this.props;
114 114
115 const { 115 const { showConfetti } = this.state;
116 showConfetti,
117 } = this.state;
118 116
119 const { intl } = this.context; 117 const { intl } = this.props;
120 const isLoggedIn = Boolean(localStorage.getItem('authToken')); 118 const isLoggedIn = Boolean(localStorage.getItem('authToken'));
121 119
122 return ( 120 return (
@@ -131,25 +129,28 @@ export default @injectSheet(styles) @inject('actions') @observer class Services
131 </div> 129 </div>
132 )} 130 )}
133 {services.length === 0 && ( 131 {services.length === 0 && (
134 <Appear 132 <Appear timeout={1500} transitionName="slideUp">
135 timeout={1500}
136 transitionName="slideUp"
137 >
138 <div className="services__no-service"> 133 <div className="services__no-service">
139 <img src="./assets/images/logo.svg" alt="Logo" style={{ maxHeight: '50vh' }} /> 134 <img
135 src="./assets/images/logo.svg"
136 alt="Logo"
137 style={{ maxHeight: '50vh' }}
138 />
140 <h1>{intl.formatMessage(messages.welcome)}</h1> 139 <h1>{intl.formatMessage(messages.welcome)}</h1>
141 { !isLoggedIn && ( 140 {!isLoggedIn && (
142 <> 141 <>
143 <p>{intl.formatMessage(messages.login)}</p> 142 <p>{intl.formatMessage(messages.login)}</p>
144 <p>{intl.formatMessage(messages.serverInfo)}</p> 143 <p>{intl.formatMessage(messages.serverInfo)}</p>
145 </> 144 </>
146 ) } 145 )}
147 <Appear 146 <Appear timeout={300} transitionName="slideUp">
148 timeout={300} 147 <Link
149 transitionName="slideUp" 148 to={isLoggedIn ? '/settings/recipes' : '/auth/welcome'}
150 > 149 className="button"
151 <Link to={isLoggedIn ? '/settings/recipes' : '/auth/welcome'} className="button"> 150 >
152 { isLoggedIn ? intl.formatMessage(messages.getStarted) : 'Login' } 151 {isLoggedIn
152 ? intl.formatMessage(messages.getStarted)
153 : 'Login'}
153 </Link> 154 </Link>
154 {!isLoggedIn && ( 155 {!isLoggedIn && (
155 <button 156 <button
@@ -167,27 +168,33 @@ export default @injectSheet(styles) @inject('actions') @observer class Services
167 </div> 168 </div>
168 </Appear> 169 </Appear>
169 )} 170 )}
170 {services.filter((service) => !service.isTodosService).map((service) => ( 171 {services
171 <ServiceView 172 .filter(service => !service.isTodosService)
172 key={service.id} 173 .map(service => (
173 service={service} 174 <ServiceView
174 handleIPCMessage={handleIPCMessage} 175 key={service.id}
175 setWebviewReference={setWebviewReference} 176 service={service}
176 detachService={detachService} 177 handleIPCMessage={handleIPCMessage}
177 openWindow={openWindow} 178 setWebviewReference={setWebviewReference}
178 reload={() => reload({ serviceId: service.id })} 179 detachService={detachService}
179 edit={() => openSettings({ path: `services/edit/${service.id}` })} 180 openWindow={openWindow}
180 enable={() => update({ 181 reload={() => reload({ serviceId: service.id })}
181 serviceId: service.id, 182 edit={() => openSettings({ path: `services/edit/${service.id}` })}
182 serviceData: { 183 enable={() =>
183 isEnabled: true, 184 update({
184 }, 185 serviceId: service.id,
185 redirect: false, 186 serviceData: {
186 })} 187 isEnabled: true,
187 isSpellcheckerEnabled={isSpellcheckerEnabled} 188 },
188 /> 189 redirect: false,
189 ))} 190 })
191 }
192 isSpellcheckerEnabled={isSpellcheckerEnabled}
193 />
194 ))}
190 </div> 195 </div>
191 ); 196 );
192 } 197 }
193} 198}
199
200export default injectIntl(Services);
diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.js
index 10ff0bbbb..a332602be 100644
--- a/src/components/services/content/WebviewCrashHandler.js
+++ b/src/components/services/content/WebviewCrashHandler.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import ms from 'ms'; 5import ms from 'ms';
6 6
7import Button from '../../ui/Button'; 7import Button from '../../ui/Button';
@@ -9,35 +9,33 @@ import Button from '../../ui/Button';
9const messages = defineMessages({ 9const messages = defineMessages({
10 headline: { 10 headline: {
11 id: 'service.crashHandler.headline', 11 id: 'service.crashHandler.headline',
12 defaultMessage: '!!!Oh no!', 12 defaultMessage: 'Oh no!',
13 }, 13 },
14 text: { 14 text: {
15 id: 'service.crashHandler.text', 15 id: 'service.crashHandler.text',
16 defaultMessage: '!!!{name} has caused an error.', 16 defaultMessage: '{name} has caused an error.',
17 }, 17 },
18 action: { 18 action: {
19 id: 'service.crashHandler.action', 19 id: 'service.crashHandler.action',
20 defaultMessage: '!!!Reload {name}', 20 defaultMessage: 'Reload {name}',
21 }, 21 },
22 autoReload: { 22 autoReload: {
23 id: 'service.crashHandler.autoReload', 23 id: 'service.crashHandler.autoReload',
24 defaultMessage: '!!!Trying to automatically restore {name} in {seconds} seconds', 24 defaultMessage:
25 'Trying to automatically restore {name} in {seconds} seconds',
25 }, 26 },
26}); 27});
27 28
28export default @observer class WebviewCrashHandler extends Component { 29@observer
30class WebviewCrashHandler extends Component {
29 static propTypes = { 31 static propTypes = {
30 name: PropTypes.string.isRequired, 32 name: PropTypes.string.isRequired,
31 reload: PropTypes.func.isRequired, 33 reload: PropTypes.func.isRequired,
32 }; 34 };
33 35
34 static contextTypes = {
35 intl: intlShape,
36 };
37
38 state = { 36 state = {
39 countdown: ms('10s'), 37 countdown: ms('10s'),
40 } 38 };
41 39
42 countdownInterval = null; 40 countdownInterval = null;
43 41
@@ -47,7 +45,7 @@ export default @observer class WebviewCrashHandler extends Component {
47 const { reload } = this.props; 45 const { reload } = this.props;
48 46
49 this.countdownInterval = setInterval(() => { 47 this.countdownInterval = setInterval(() => {
50 this.setState((prevState) => ({ 48 this.setState(prevState => ({
51 countdown: prevState.countdown - this.countdownIntervalTimeout, 49 countdown: prevState.countdown - this.countdownIntervalTimeout,
52 })); 50 }));
53 51
@@ -60,7 +58,7 @@ export default @observer class WebviewCrashHandler extends Component {
60 58
61 render() { 59 render() {
62 const { name, reload } = this.props; 60 const { name, reload } = this.props;
63 const { intl } = this.context; 61 const { intl } = this.props;
64 62
65 return ( 63 return (
66 <div className="services__info-layer"> 64 <div className="services__info-layer">
@@ -82,3 +80,5 @@ export default @observer class WebviewCrashHandler extends Component {
82 ); 80 );
83 } 81 }
84} 82}
83
84export default injectIntl(WebviewCrashHandler);
diff --git a/src/components/services/tabs/TabItem.js b/src/components/services/tabs/TabItem.js
index e5892be5d..b1a3ffbbb 100644
--- a/src/components/services/tabs/TabItem.js
+++ b/src/components/services/tabs/TabItem.js
@@ -1,6 +1,6 @@
1import { Menu, dialog, app, getCurrentWindow } from '@electron/remote'; 1import { Menu, dialog, app, getCurrentWindow } from '@electron/remote';
2import React, { Component } from 'react'; 2import React, { Component } from 'react';
3import { defineMessages, intlShape } from 'react-intl'; 3import { defineMessages, injectIntl } from 'react-intl';
4import PropTypes from 'prop-types'; 4import PropTypes from 'prop-types';
5import { observer } from 'mobx-react'; 5import { observer } from 'mobx-react';
6import classnames from 'classnames'; 6import classnames from 'classnames';
@@ -20,56 +20,55 @@ const IS_SERVICE_DEBUGGING_ENABLED = (
20const messages = defineMessages({ 20const messages = defineMessages({
21 reload: { 21 reload: {
22 id: 'tabs.item.reload', 22 id: 'tabs.item.reload',
23 defaultMessage: '!!!Reload', 23 defaultMessage: 'Reload',
24 }, 24 },
25 disableNotifications: { 25 disableNotifications: {
26 id: 'tabs.item.disableNotifications', 26 id: 'tabs.item.disableNotifications',
27 defaultMessage: '!!!Disable notifications', 27 defaultMessage: 'Disable notifications',
28 }, 28 },
29 enableNotifications: { 29 enableNotifications: {
30 id: 'tabs.item.enableNotification', 30 id: 'tabs.item.enableNotification',
31 defaultMessage: '!!!Enable notifications', 31 defaultMessage: 'Enable notifications',
32 }, 32 },
33 disableAudio: { 33 disableAudio: {
34 id: 'tabs.item.disableAudio', 34 id: 'tabs.item.disableAudio',
35 defaultMessage: '!!!Disable audio', 35 defaultMessage: 'Disable audio',
36 }, 36 },
37 enableAudio: { 37 enableAudio: {
38 id: 'tabs.item.enableAudio', 38 id: 'tabs.item.enableAudio',
39 defaultMessage: '!!!Enable audio', 39 defaultMessage: 'Enable audio',
40 }, 40 },
41 enableDarkMode: { 41 enableDarkMode: {
42 id: 'tabs.item.enableDarkMode', 42 id: 'tabs.item.enableDarkMode',
43 defaultMessage: '!!!Enable Dark mode', 43 defaultMessage: 'Enable Dark mode',
44 }, 44 },
45 disableDarkMode: { 45 disableDarkMode: {
46 id: 'tabs.item.disableDarkMode', 46 id: 'tabs.item.disableDarkMode',
47 defaultMessage: '!!!Disable Dark mode', 47 defaultMessage: 'Disable Dark mode',
48 }, 48 },
49 disableService: { 49 disableService: {
50 id: 'tabs.item.disableService', 50 id: 'tabs.item.disableService',
51 defaultMessage: '!!!Disable Service', 51 defaultMessage: 'Disable Service',
52 }, 52 },
53 enableService: { 53 enableService: {
54 id: 'tabs.item.enableService', 54 id: 'tabs.item.enableService',
55 defaultMessage: '!!!Enable Service', 55 defaultMessage: 'Enable Service',
56 }, 56 },
57 hibernateService: { 57 hibernateService: {
58 id: 'tabs.item.hibernateService', 58 id: 'tabs.item.hibernateService',
59 defaultMessage: '!!!Hibernate Service', 59 defaultMessage: 'Hibernate Service',
60 }, 60 },
61 wakeUpService: { 61 wakeUpService: {
62 id: 'tabs.item.wakeUpService', 62 id: 'tabs.item.wakeUpService',
63 defaultMessage: '!!!Wake Up Service', 63 defaultMessage: 'Wake Up Service',
64 }, 64 },
65 deleteService: { 65 deleteService: {
66 id: 'tabs.item.deleteService', 66 id: 'tabs.item.deleteService',
67 defaultMessage: '!!!Delete Service', 67 defaultMessage: 'Delete Service',
68 }, 68 },
69 confirmDeleteService: { 69 confirmDeleteService: {
70 id: 'tabs.item.confirmDeleteService', 70 id: 'tabs.item.confirmDeleteService',
71 defaultMessage: 71 defaultMessage: 'Do you really want to delete the {serviceName} service?',
72 '!!!Do you really want to delete the {serviceName} service?',
73 }, 72 },
74}); 73});
75 74
@@ -134,10 +133,6 @@ class TabItem extends Component {
134 showMessageBadgesEvenWhenMuted: PropTypes.bool.isRequired, 133 showMessageBadgesEvenWhenMuted: PropTypes.bool.isRequired,
135 }; 134 };
136 135
137 static contextTypes = {
138 intl: intlShape,
139 };
140
141 @observable isPolled = false; 136 @observable isPolled = false;
142 137
143 @observable isPollAnswered = false; 138 @observable isPollAnswered = false;
@@ -185,7 +180,7 @@ class TabItem extends Component {
185 showMessageBadgeWhenMutedSetting, 180 showMessageBadgeWhenMutedSetting,
186 showMessageBadgesEvenWhenMuted, 181 showMessageBadgesEvenWhenMuted,
187 } = this.props; 182 } = this.props;
188 const { intl } = this.context; 183 const { intl } = this.props;
189 184
190 const menuTemplate = [ 185 const menuTemplate = [
191 { 186 {
@@ -256,7 +251,10 @@ class TabItem extends Component {
256 detail: intl.formatMessage(messages.confirmDeleteService, { 251 detail: intl.formatMessage(messages.confirmDeleteService, {
257 serviceName: service.name || service.recipe.name, 252 serviceName: service.name || service.recipe.name,
258 }), 253 }),
259 buttons: [intl.formatMessage(globalMessages.yes), intl.formatMessage(globalMessages.no)], 254 buttons: [
255 intl.formatMessage(globalMessages.yes),
256 intl.formatMessage(globalMessages.no),
257 ],
260 }); 258 });
261 if (selection === 0) { 259 if (selection === 0) {
262 deleteService(); 260 deleteService();
@@ -304,7 +302,9 @@ class TabItem extends Component {
304 onClick={clickHandler} 302 onClick={clickHandler}
305 onContextMenu={() => menu.popup(getCurrentWindow())} 303 onContextMenu={() => menu.popup(getCurrentWindow())}
306 data-tip={`${service.name} ${ 304 data-tip={`${service.name} ${
307 shortcutIndex <= 9 ? `(${cmdOrCtrlShortcutKey(false)}+${shortcutIndex})` : '' 305 shortcutIndex <= 9
306 ? `(${cmdOrCtrlShortcutKey(false)}+${shortcutIndex})`
307 : ''
308 }`} 308 }`}
309 > 309 >
310 <img src={service.icon} className="tab-item__icon" alt="" /> 310 <img src={service.icon} className="tab-item__icon" alt="" />
@@ -332,4 +332,4 @@ class TabItem extends Component {
332 } 332 }
333} 333}
334 334
335export default SortableElement(TabItem); 335export default injectIntl(SortableElement(TabItem));
diff --git a/src/components/services/tabs/Tabbar.js b/src/components/services/tabs/Tabbar.js
index c1421a2b1..a77799819 100644
--- a/src/components/services/tabs/Tabbar.js
+++ b/src/components/services/tabs/Tabbar.js
@@ -4,7 +4,8 @@ import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4 4
5import TabBarSortableList from './TabBarSortableList'; 5import TabBarSortableList from './TabBarSortableList';
6 6
7export default @observer class TabBar extends Component { 7@observer
8class TabBar extends Component {
8 static propTypes = { 9 static propTypes = {
9 services: MobxPropTypes.arrayOrObservableArray.isRequired, 10 services: MobxPropTypes.arrayOrObservableArray.isRequired,
10 setActive: PropTypes.func.isRequired, 11 setActive: PropTypes.func.isRequired,
@@ -26,16 +27,13 @@ export default @observer class TabBar extends Component {
26 }; 27 };
27 28
28 onSortEnd = ({ oldIndex, newIndex }) => { 29 onSortEnd = ({ oldIndex, newIndex }) => {
29 const { 30 const { enableToolTip, reorder } = this.props;
30 enableToolTip,
31 reorder,
32 } = this.props;
33 31
34 enableToolTip(); 32 enableToolTip();
35 reorder({ oldIndex, newIndex }); 33 reorder({ oldIndex, newIndex });
36 }; 34 };
37 35
38 shouldPreventSorting = (event) => event.target.tagName !== 'LI'; 36 shouldPreventSorting = event => event.target.tagName !== 'LI';
39 37
40 toggleService = ({ serviceId, isEnabled }) => { 38 toggleService = ({ serviceId, isEnabled }) => {
41 const { updateService } = this.props; 39 const { updateService } = this.props;
@@ -102,10 +100,10 @@ export default @observer class TabBar extends Component {
102 toggleAudio={toggleAudio} 100 toggleAudio={toggleAudio}
103 toggleDarkMode={toggleDarkMode} 101 toggleDarkMode={toggleDarkMode}
104 deleteService={deleteService} 102 deleteService={deleteService}
105 disableService={(args) => this.disableService(args)} 103 disableService={args => this.disableService(args)}
106 enableService={(args) => this.enableService(args)} 104 enableService={args => this.enableService(args)}
107 hibernateService={(args) => this.hibernateService(args)} 105 hibernateService={args => this.hibernateService(args)}
108 wakeUpService={(args) => this.wakeUpService(args)} 106 wakeUpService={args => this.wakeUpService(args)}
109 openSettings={openSettings} 107 openSettings={openSettings}
110 distance={20} 108 distance={20}
111 axis={axis} 109 axis={axis}
@@ -118,3 +116,5 @@ export default @observer class TabBar extends Component {
118 ); 116 );
119 } 117 }
120} 118}
119
120export default TabBar;
diff --git a/src/components/settings/SettingsLayout.js b/src/components/settings/SettingsLayout.js
index 5b3b754fa..0574b3765 100644
--- a/src/components/settings/SettingsLayout.js
+++ b/src/components/settings/SettingsLayout.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5 5
6import ErrorBoundary from '../util/ErrorBoundary'; 6import ErrorBoundary from '../util/ErrorBoundary';
7import { oneOrManyChildElements } from '../../prop-types'; 7import { oneOrManyChildElements } from '../../prop-types';
@@ -10,11 +10,10 @@ import Appear from '../ui/effects/Appear';
10const messages = defineMessages({ 10const messages = defineMessages({
11 closeSettings: { 11 closeSettings: {
12 id: 'settings.app.closeSettings', 12 id: 'settings.app.closeSettings',
13 defaultMessage: '!!!Close settings', 13 defaultMessage: 'Close settings',
14 }, 14 },
15}); 15});
16 16
17export default
18@observer 17@observer
19class SettingsLayout extends Component { 18class SettingsLayout extends Component {
20 static propTypes = { 19 static propTypes = {
@@ -23,10 +22,6 @@ class SettingsLayout extends Component {
23 closeSettings: PropTypes.func.isRequired, 22 closeSettings: PropTypes.func.isRequired,
24 }; 23 };
25 24
26 static contextTypes = {
27 intl: intlShape,
28 };
29
30 componentDidMount() { 25 componentDidMount() {
31 document.addEventListener('keydown', this.handleKeyDown.bind(this), false); 26 document.addEventListener('keydown', this.handleKeyDown.bind(this), false);
32 } 27 }
@@ -49,7 +44,7 @@ class SettingsLayout extends Component {
49 render() { 44 render() {
50 const { navigation, children, closeSettings } = this.props; 45 const { navigation, children, closeSettings } = this.props;
51 46
52 const { intl } = this.context; 47 const { intl } = this.props;
53 48
54 return ( 49 return (
55 <Appear transitionName="fadeIn-fast"> 50 <Appear transitionName="fadeIn-fast">
@@ -77,3 +72,5 @@ class SettingsLayout extends Component {
77 ); 72 );
78 } 73 }
79} 74}
75
76export default injectIntl(SettingsLayout);
diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js
index ef7748343..933d47d12 100644
--- a/src/components/settings/account/AccountDashboard.js
+++ b/src/components/settings/account/AccountDashboard.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import ReactTooltip from 'react-tooltip'; 5import ReactTooltip from 'react-tooltip';
6import { H1, H2 } from '@meetfranz/ui'; 6import { H1, H2 } from '@meetfranz/ui';
7 7
@@ -13,7 +13,7 @@ import { LOCAL_SERVER, LIVE_FRANZ_API } from '../../../config';
13const messages = defineMessages({ 13const messages = defineMessages({
14 headline: { 14 headline: {
15 id: 'settings.account.headline', 15 id: 'settings.account.headline',
16 defaultMessage: '!!!Account', 16 defaultMessage: 'Account',
17 }, 17 },
18 headlineDangerZone: { 18 headlineDangerZone: {
19 id: 'settings.account.headlineDangerZone', 19 id: 'settings.account.headlineDangerZone',
@@ -21,7 +21,7 @@ const messages = defineMessages({
21 }, 21 },
22 accountEditButton: { 22 accountEditButton: {
23 id: 'settings.account.account.editButton', 23 id: 'settings.account.account.editButton',
24 defaultMessage: '!!!Edit Account', 24 defaultMessage: 'Edit Account',
25 }, 25 },
26 invoicesButton: { 26 invoicesButton: {
27 id: 'settings.account.headlineInvoices', 27 id: 'settings.account.headlineInvoices',
@@ -29,29 +29,29 @@ const messages = defineMessages({
29 }, 29 },
30 userInfoRequestFailed: { 30 userInfoRequestFailed: {
31 id: 'settings.account.userInfoRequestFailed', 31 id: 'settings.account.userInfoRequestFailed',
32 defaultMessage: '!!!Could not load user information', 32 defaultMessage: 'Could not load user information',
33 }, 33 },
34 tryReloadUserInfoRequest: { 34 tryReloadUserInfoRequest: {
35 id: 'settings.account.tryReloadUserInfoRequest', 35 id: 'settings.account.tryReloadUserInfoRequest',
36 defaultMessage: '!!!Try again', 36 defaultMessage: 'Try again',
37 }, 37 },
38 deleteAccount: { 38 deleteAccount: {
39 id: 'settings.account.deleteAccount', 39 id: 'settings.account.deleteAccount',
40 defaultMessage: '!!!Delete account', 40 defaultMessage: 'Delete account',
41 }, 41 },
42 deleteInfo: { 42 deleteInfo: {
43 id: 'settings.account.deleteInfo', 43 id: 'settings.account.deleteInfo',
44 defaultMessage: 44 defaultMessage:
45 "!!!If you don't need your Ferdi account any longer, you can delete your account and all related data here.", 45 "If you don't need your Ferdi account any longer, you can delete your account and all related data here.",
46 }, 46 },
47 deleteEmailSent: { 47 deleteEmailSent: {
48 id: 'settings.account.deleteEmailSent', 48 id: 'settings.account.deleteEmailSent',
49 defaultMessage: 49 defaultMessage:
50 '!!!You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!', 50 'You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!',
51 }, 51 },
52 yourLicense: { 52 yourLicense: {
53 id: 'settings.account.yourLicense', 53 id: 'settings.account.yourLicense',
54 defaultMessage: '!!!Your Franz License:', 54 defaultMessage: 'Your Franz License:',
55 }, 55 },
56 accountUnavailable: { 56 accountUnavailable: {
57 id: 'settings.account.accountUnavailable', 57 id: 'settings.account.accountUnavailable',
@@ -59,7 +59,8 @@ const messages = defineMessages({
59 }, 59 },
60 accountUnavailableInfo: { 60 accountUnavailableInfo: {
61 id: 'settings.account.accountUnavailableInfo', 61 id: 'settings.account.accountUnavailableInfo',
62 defaultMessage: 'You are using Ferdi without an account. If you want to use Ferdi with an account and keep your services synchronized across installations, please select a server in the Settings tab then login.', 62 defaultMessage:
63 'You are using Ferdi without an account. If you want to use Ferdi with an account and keep your services synchronized across installations, please select a server in the Settings tab then login.',
63 }, 64 },
64}); 65});
65 66
@@ -78,10 +79,6 @@ class AccountDashboard extends Component {
78 server: PropTypes.string.isRequired, 79 server: PropTypes.string.isRequired,
79 }; 80 };
80 81
81 static contextTypes = {
82 intl: intlShape,
83 };
84
85 render() { 82 render() {
86 const { 83 const {
87 user, 84 user,
@@ -95,7 +92,7 @@ class AccountDashboard extends Component {
95 openInvoices, 92 openInvoices,
96 server, 93 server,
97 } = this.props; 94 } = this.props;
98 const { intl } = this.context; 95 const { intl } = this.props;
99 96
100 const isUsingWithoutAccount = server === LOCAL_SERVER; 97 const isUsingWithoutAccount = server === LOCAL_SERVER;
101 const isUsingFranzServer = server === LIVE_FRANZ_API; 98 const isUsingFranzServer = server === LIVE_FRANZ_API;
@@ -182,9 +179,7 @@ class AccountDashboard extends Component {
182 <div className="account"> 179 <div className="account">
183 <div className="account__box"> 180 <div className="account__box">
184 <H2>{intl.formatMessage(messages.yourLicense)}</H2> 181 <H2>{intl.formatMessage(messages.yourLicense)}</H2>
185 <p> 182 <p>Franz</p>
186 Franz
187 </p>
188 <div className="manage-user-links"> 183 <div className="manage-user-links">
189 <Button 184 <Button
190 label={intl.formatMessage( 185 label={intl.formatMessage(
@@ -203,7 +198,9 @@ class AccountDashboard extends Component {
203 {isUsingFranzServer && ( 198 {isUsingFranzServer && (
204 <div className="account franz-form"> 199 <div className="account franz-form">
205 <div className="account__box"> 200 <div className="account__box">
206 <H2>{intl.formatMessage(messages.headlineDangerZone)}</H2> 201 <H2>
202 {intl.formatMessage(messages.headlineDangerZone)}
203 </H2>
207 {!isDeleteAccountSuccessful && ( 204 {!isDeleteAccountSuccessful && (
208 <div className="account__subscription"> 205 <div className="account__subscription">
209 <p>{intl.formatMessage(messages.deleteInfo)}</p> 206 <p>{intl.formatMessage(messages.deleteInfo)}</p>
@@ -232,4 +229,4 @@ class AccountDashboard extends Component {
232 } 229 }
233} 230}
234 231
235export default AccountDashboard; 232export default injectIntl(AccountDashboard);
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js
index 0a5ace586..72c7faa66 100644
--- a/src/components/settings/navigation/SettingsNavigation.js
+++ b/src/components/settings/navigation/SettingsNavigation.js
@@ -1,6 +1,6 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { defineMessages, intlShape } from 'react-intl'; 3import { defineMessages, injectIntl } from 'react-intl';
4import { inject, observer } from 'mobx-react'; 4import { inject, observer } from 'mobx-react';
5import { RouterStore } from 'mobx-react-router'; 5import { RouterStore } from 'mobx-react-router';
6 6
@@ -15,35 +15,37 @@ import globalMessages from '../../../i18n/globalMessages';
15const messages = defineMessages({ 15const messages = defineMessages({
16 availableServices: { 16 availableServices: {
17 id: 'settings.navigation.availableServices', 17 id: 'settings.navigation.availableServices',
18 defaultMessage: '!!!Available services', 18 defaultMessage: 'Available services',
19 }, 19 },
20 yourServices: { 20 yourServices: {
21 id: 'settings.navigation.yourServices', 21 id: 'settings.navigation.yourServices',
22 defaultMessage: '!!!Your services', 22 defaultMessage: 'Your services',
23 }, 23 },
24 yourWorkspaces: { 24 yourWorkspaces: {
25 id: 'settings.navigation.yourWorkspaces', 25 id: 'settings.navigation.yourWorkspaces',
26 defaultMessage: '!!!Your workspaces', 26 defaultMessage: 'Your workspaces',
27 }, 27 },
28 account: { 28 account: {
29 id: 'settings.navigation.account', 29 id: 'settings.navigation.account',
30 defaultMessage: '!!!Account', 30 defaultMessage: 'Account',
31 }, 31 },
32 team: { 32 team: {
33 id: 'settings.navigation.team', 33 id: 'settings.navigation.team',
34 defaultMessage: '!!!Manage Team', 34 defaultMessage: 'Manage Team',
35 }, 35 },
36 supportFerdi: { 36 supportFerdi: {
37 id: 'settings.navigation.supportFerdi', 37 id: 'settings.navigation.supportFerdi',
38 defaultMessage: '!!!About Ferdi', 38 defaultMessage: 'About Ferdi',
39 }, 39 },
40 logout: { 40 logout: {
41 id: 'settings.navigation.logout', 41 id: 'settings.navigation.logout',
42 defaultMessage: '!!!Logout', 42 defaultMessage: 'Logout',
43 }, 43 },
44}); 44});
45 45
46export default @inject('stores', 'actions') @observer class SettingsNavigation extends Component { 46@inject('stores', 'actions')
47@observer
48class SettingsNavigation extends Component {
47 static propTypes = { 49 static propTypes = {
48 stores: PropTypes.shape({ 50 stores: PropTypes.shape({
49 ui: PropTypes.instanceOf(UIStore).isRequired, 51 ui: PropTypes.instanceOf(UIStore).isRequired,
@@ -58,13 +60,10 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e
58 workspaceCount: PropTypes.number.isRequired, 60 workspaceCount: PropTypes.number.isRequired,
59 }; 61 };
60 62
61 static contextTypes = {
62 intl: intlShape,
63 };
64
65 handleLoginLogout() { 63 handleLoginLogout() {
66 const isLoggedIn = Boolean(localStorage.getItem('authToken')); 64 const isLoggedIn = Boolean(localStorage.getItem('authToken'));
67 const isUsingWithoutAccount = this.props.stores.settings.app.server === LOCAL_SERVER; 65 const isUsingWithoutAccount =
66 this.props.stores.settings.app.server === LOCAL_SERVER;
68 67
69 if (isLoggedIn) { 68 if (isLoggedIn) {
70 // Remove current auth token 69 // Remove current auth token
@@ -82,7 +81,9 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e
82 this.props.stores.user.isLoggingOut = true; 81 this.props.stores.user.isLoggingOut = true;
83 } 82 }
84 83
85 this.props.stores.router.push(isLoggedIn ? '/auth/logout' : '/auth/welcome'); 84 this.props.stores.router.push(
85 isLoggedIn ? '/auth/logout' : '/auth/welcome',
86 );
86 87
87 if (isLoggedIn) { 88 if (isLoggedIn) {
88 // Reload Ferdi, otherwise many settings won't sync correctly with the server 89 // Reload Ferdi, otherwise many settings won't sync correctly with the server
@@ -93,7 +94,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e
93 94
94 render() { 95 render() {
95 const { serviceCount, workspaceCount, stores } = this.props; 96 const { serviceCount, workspaceCount, stores } = this.props;
96 const { intl } = this.context; 97 const { intl } = this.props;
97 const isLoggedIn = Boolean(localStorage.getItem('authToken')); 98 const isLoggedIn = Boolean(localStorage.getItem('authToken'));
98 const isUsingWithoutAccount = stores.settings.app.server === LOCAL_SERVER; 99 const isUsingWithoutAccount = stores.settings.app.server === LOCAL_SERVER;
99 const isUsingFranzServer = stores.settings.app.server === LIVE_FRANZ_API; 100 const isUsingFranzServer = stores.settings.app.server === LIVE_FRANZ_API;
@@ -113,11 +114,8 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e
113 activeClassName="is-active" 114 activeClassName="is-active"
114 disabled={!isLoggedIn} 115 disabled={!isLoggedIn}
115 > 116 >
116 {intl.formatMessage(messages.yourServices)} 117 {intl.formatMessage(messages.yourServices)}{' '}
117 {' '} 118 <span className="badge">{serviceCount}</span>
118 <span className="badge">
119 {serviceCount}
120 </span>
121 </Link> 119 </Link>
122 {workspaceStore.isFeatureEnabled ? ( 120 {workspaceStore.isFeatureEnabled ? (
123 <Link 121 <Link
@@ -126,8 +124,7 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e
126 activeClassName="is-active" 124 activeClassName="is-active"
127 disabled={!isLoggedIn} 125 disabled={!isLoggedIn}
128 > 126 >
129 {intl.formatMessage(messages.yourWorkspaces)} 127 {intl.formatMessage(messages.yourWorkspaces)}{' '}
130 {' '}
131 <span className="badge">{workspaceCount}</span> 128 <span className="badge">{workspaceCount}</span>
132 </Link> 129 </Link>
133 ) : null} 130 ) : null}
@@ -172,9 +169,13 @@ export default @inject('stores', 'actions') @observer class SettingsNavigation e
172 className="settings-navigation__link" 169 className="settings-navigation__link"
173 onClick={this.handleLoginLogout.bind(this)} 170 onClick={this.handleLoginLogout.bind(this)}
174 > 171 >
175 { isLoggedIn && !isUsingWithoutAccount ? intl.formatMessage(messages.logout) : 'Login'} 172 {isLoggedIn && !isUsingWithoutAccount
173 ? intl.formatMessage(messages.logout)
174 : 'Login'}
176 </button> 175 </button>
177 </div> 176 </div>
178 ); 177 );
179 } 178 }
180} 179}
180
181export default injectIntl(SettingsNavigation);
diff --git a/src/components/settings/recipes/RecipeItem.js b/src/components/settings/recipes/RecipeItem.js
index 55f415bd5..ca188aa99 100644
--- a/src/components/settings/recipes/RecipeItem.js
+++ b/src/components/settings/recipes/RecipeItem.js
@@ -4,7 +4,8 @@ import { observer } from 'mobx-react';
4 4
5import RecipePreviewModel from '../../../models/RecipePreview'; 5import RecipePreviewModel from '../../../models/RecipePreview';
6 6
7export default @observer class RecipeItem extends Component { 7@observer
8class RecipeItem extends Component {
8 static propTypes = { 9 static propTypes = {
9 recipe: PropTypes.instanceOf(RecipePreviewModel).isRequired, 10 recipe: PropTypes.instanceOf(RecipePreviewModel).isRequired,
10 onClick: PropTypes.func.isRequired, 11 onClick: PropTypes.func.isRequired,
@@ -14,19 +15,11 @@ export default @observer class RecipeItem extends Component {
14 const { recipe, onClick } = this.props; 15 const { recipe, onClick } = this.props;
15 16
16 return ( 17 return (
17 <button 18 <button type="button" className="recipe-teaser" onClick={onClick}>
18 type="button"
19 className="recipe-teaser"
20 onClick={onClick}
21 >
22 {recipe.isDevRecipe && ( 19 {recipe.isDevRecipe && (
23 <span className="recipe-teaser__dev-badge">dev</span> 20 <span className="recipe-teaser__dev-badge">dev</span>
24 )} 21 )}
25 <img 22 <img src={recipe.icons.svg} className="recipe-teaser__icon" alt="" />
26 src={recipe.icons.svg}
27 className="recipe-teaser__icon"
28 alt=""
29 />
30 <span className="recipe-teaser__label">{recipe.name}</span> 23 <span className="recipe-teaser__label">{recipe.name}</span>
31 {recipe.aliases && recipe.aliases.length > 0 && ( 24 {recipe.aliases && recipe.aliases.length > 0 && (
32 <span className="recipe-teaser__alias_label"> 25 <span className="recipe-teaser__alias_label">
@@ -37,3 +30,5 @@ export default @observer class RecipeItem extends Component {
37 ); 30 );
38 } 31 }
39} 32}
33
34export default RecipeItem;
diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.js
index 44ff2d0d7..e620abf93 100644
--- a/src/components/settings/recipes/RecipesDashboard.js
+++ b/src/components/settings/recipes/RecipesDashboard.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import { Link } from 'react-router'; 5import { Link } from 'react-router';
6 6
7import { Button, Input } from '@meetfranz/forms'; 7import { Button, Input } from '@meetfranz/forms';
@@ -18,55 +18,56 @@ import RecipePreview from '../../../models/RecipePreview';
18const messages = defineMessages({ 18const messages = defineMessages({
19 headline: { 19 headline: {
20 id: 'settings.recipes.headline', 20 id: 'settings.recipes.headline',
21 defaultMessage: '!!!Available Services', 21 defaultMessage: 'Available Services',
22 }, 22 },
23 searchService: { 23 searchService: {
24 id: 'settings.searchService', 24 id: 'settings.searchService',
25 defaultMessage: '!!!Search service', 25 defaultMessage: 'Search service',
26 }, 26 },
27 allRecipes: { 27 allRecipes: {
28 id: 'settings.recipes.all', 28 id: 'settings.recipes.all',
29 defaultMessage: '!!!All services', 29 defaultMessage: 'All services',
30 }, 30 },
31 customRecipes: { 31 customRecipes: {
32 id: 'settings.recipes.custom', 32 id: 'settings.recipes.custom',
33 defaultMessage: '!!!Custom Services', 33 defaultMessage: 'Custom Services',
34 }, 34 },
35 nothingFound: { 35 nothingFound: {
36 id: 'settings.recipes.nothingFound', 36 id: 'settings.recipes.nothingFound',
37 defaultMessage: '!!!Sorry, but no service matched your search term - but you can still probably add it using the "Custom Website" option. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.', 37 defaultMessage:
38 'Sorry, but no service matched your search term - but you can still probably add it using the "Custom Website" option. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.',
38 }, 39 },
39 servicesSuccessfulAddedInfo: { 40 servicesSuccessfulAddedInfo: {
40 id: 'settings.recipes.servicesSuccessfulAddedInfo', 41 id: 'settings.recipes.servicesSuccessfulAddedInfo',
41 defaultMessage: '!!!Service successfully added', 42 defaultMessage: 'Service successfully added',
42 }, 43 },
43 missingService: { 44 missingService: {
44 id: 'settings.recipes.missingService', 45 id: 'settings.recipes.missingService',
45 defaultMessage: '!!!Missing a service?', 46 defaultMessage: 'Missing a service?',
46 }, 47 },
47 customRecipeIntro: { 48 customRecipeIntro: {
48 id: 'settings.recipes.customService.intro', 49 id: 'settings.recipes.customService.intro',
49 defaultMessage: '!!!To add a custom service, copy the recipe folder into:', 50 defaultMessage: 'To add a custom service, copy the recipe folder into:',
50 }, 51 },
51 openFolder: { 52 openFolder: {
52 id: 'settings.recipes.customService.openFolder', 53 id: 'settings.recipes.customService.openFolder',
53 defaultMessage: '!!!Open directory', 54 defaultMessage: 'Open directory',
54 }, 55 },
55 openDevDocs: { 56 openDevDocs: {
56 id: 'settings.recipes.customService.openDevDocs', 57 id: 'settings.recipes.customService.openDevDocs',
57 defaultMessage: '!!!Developer Documentation', 58 defaultMessage: 'Developer Documentation',
58 }, 59 },
59 headlineCustomRecipes: { 60 headlineCustomRecipes: {
60 id: 'settings.recipes.customService.headline.customRecipes', 61 id: 'settings.recipes.customService.headline.customRecipes',
61 defaultMessage: '!!!Custom 3rd Party Recipes', 62 defaultMessage: 'Custom 3rd Party Recipes',
62 }, 63 },
63 headlineCommunityRecipes: { 64 headlineCommunityRecipes: {
64 id: 'settings.recipes.customService.headline.communityRecipes', 65 id: 'settings.recipes.customService.headline.communityRecipes',
65 defaultMessage: '!!!Community 3rd Party Recipes', 66 defaultMessage: 'Community 3rd Party Recipes',
66 }, 67 },
67 headlineDevRecipes: { 68 headlineDevRecipes: {
68 id: 'settings.recipes.customService.headline.devRecipes', 69 id: 'settings.recipes.customService.headline.devRecipes',
69 defaultMessage: '!!!Your Development Service Recipes', 70 defaultMessage: 'Your Development Service Recipes',
70 }, 71 },
71}); 72});
72 73
@@ -81,7 +82,8 @@ const styles = {
81 marginTop: 20, 82 marginTop: 20,
82 83
83 '& > div': { 84 '& > div': {
84 fontFamily: 'SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace', 85 fontFamily:
86 'SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace',
85 }, 87 },
86 }, 88 },
87 actionContainer: { 89 actionContainer: {
@@ -98,7 +100,9 @@ const styles = {
98 }, 100 },
99}; 101};
100 102
101export default @injectSheet(styles) @observer class RecipesDashboard extends Component { 103@injectSheet(styles)
104@observer
105class RecipesDashboard extends Component {
102 static propTypes = { 106 static propTypes = {
103 recipes: MobxPropTypes.arrayOrObservableArray.isRequired, 107 recipes: MobxPropTypes.arrayOrObservableArray.isRequired,
104 customWebsiteRecipe: PropTypes.instanceOf(RecipePreview).isRequired, 108 customWebsiteRecipe: PropTypes.instanceOf(RecipePreview).isRequired,
@@ -118,10 +122,6 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com
118 static defaultProps = { 122 static defaultProps = {
119 searchNeedle: '', 123 searchNeedle: '',
120 recipeFilter: 'all', 124 recipeFilter: 'all',
121 }
122
123 static contextTypes = {
124 intl: intlShape,
125 }; 125 };
126 126
127 render() { 127 render() {
@@ -140,7 +140,7 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com
140 openDevDocs, 140 openDevDocs,
141 classes, 141 classes,
142 } = this.props; 142 } = this.props;
143 const { intl } = this.context; 143 const { intl } = this.props;
144 144
145 const communityRecipes = recipes.filter(r => !r.isDevRecipe); 145 const communityRecipes = recipes.filter(r => !r.isDevRecipe);
146 const devRecipes = recipes.filter(r => r.isDevRecipe); 146 const devRecipes = recipes.filter(r => r.isDevRecipe);
@@ -188,9 +188,13 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com
188 > 188 >
189 {intl.formatMessage(messages.customRecipes)} 189 {intl.formatMessage(messages.customRecipes)}
190 </Link> 190 </Link>
191 <a href={FRANZ_SERVICE_REQUEST} target="_blank" className="link recipes__service-request" rel="noreferrer"> 191 <a
192 {intl.formatMessage(messages.missingService)} 192 href={FRANZ_SERVICE_REQUEST}
193 {' '} 193 target="_blank"
194 className="link recipes__service-request"
195 rel="noreferrer"
196 >
197 {intl.formatMessage(messages.missingService)}{' '}
194 <i className="mdi mdi-open-in-new" /> 198 <i className="mdi mdi-open-in-new" />
195 </a> 199 </a>
196 </div> 200 </div>
@@ -201,13 +205,9 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com
201 <> 205 <>
202 {recipeFilter === 'dev' && ( 206 {recipeFilter === 'dev' && (
203 <> 207 <>
204 <H2> 208 <H2>{intl.formatMessage(messages.headlineCustomRecipes)}</H2>
205 {intl.formatMessage(messages.headlineCustomRecipes)}
206 </H2>
207 <div className={classes.devRecipeIntroContainer}> 209 <div className={classes.devRecipeIntroContainer}>
208 <p> 210 <p>{intl.formatMessage(messages.customRecipeIntro)}</p>
209 {intl.formatMessage(messages.customRecipeIntro)}
210 </p>
211 <Input 211 <Input
212 value={recipeDirectory} 212 value={recipeDirectory}
213 className={classes.path} 213 className={classes.path}
@@ -238,12 +238,19 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com
238 <img src="./assets/images/emoji/dontknow.png" alt="" /> 238 <img src="./assets/images/emoji/dontknow.png" alt="" />
239 </span> 239 </span>
240 240
241 <p className="settings__empty-state-text">{intl.formatMessage(messages.nothingFound)}</p> 241 <p className="settings__empty-state-text">
242 {intl.formatMessage(messages.nothingFound)}
243 </p>
242 244
243 <RecipeItem 245 <RecipeItem
244 key={customWebsiteRecipe.id} 246 key={customWebsiteRecipe.id}
245 recipe={customWebsiteRecipe} 247 recipe={customWebsiteRecipe}
246 onClick={() => isLoggedIn && showAddServiceInterface({ recipeId: customWebsiteRecipe.id })} 248 onClick={() =>
249 isLoggedIn &&
250 showAddServiceInterface({
251 recipeId: customWebsiteRecipe.id,
252 })
253 }
247 /> 254 />
248 </div> 255 </div>
249 )} 256 )}
@@ -251,7 +258,10 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com
251 <RecipeItem 258 <RecipeItem
252 key={recipe.id} 259 key={recipe.id}
253 recipe={recipe} 260 recipe={recipe}
254 onClick={() => isLoggedIn && showAddServiceInterface({ recipeId: recipe.id })} 261 onClick={() =>
262 isLoggedIn &&
263 showAddServiceInterface({ recipeId: recipe.id })
264 }
255 /> 265 />
256 ))} 266 ))}
257 </div> 267 </div>
@@ -263,7 +273,10 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com
263 <RecipeItem 273 <RecipeItem
264 key={recipe.id} 274 key={recipe.id}
265 recipe={recipe} 275 recipe={recipe}
266 onClick={() => isLoggedIn && showAddServiceInterface({ recipeId: recipe.id })} 276 onClick={() =>
277 isLoggedIn &&
278 showAddServiceInterface({ recipeId: recipe.id })
279 }
267 /> 280 />
268 ))} 281 ))}
269 </div> 282 </div>
@@ -276,3 +289,5 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com
276 ); 289 );
277 } 290 }
278} 291}
292
293export default injectIntl(RecipesDashboard);
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index c41cdd56a..3fbb57cbb 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { Link } from 'react-router'; 4import { Link } from 'react-router';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6import normalizeUrl from 'normalize-url'; 6import normalizeUrl from 'normalize-url';
7 7
8import Form from '../../../lib/Form'; 8import Form from '../../../lib/Form';
@@ -22,111 +22,117 @@ import globalMessages from '../../../i18n/globalMessages';
22const messages = defineMessages({ 22const messages = defineMessages({
23 saveService: { 23 saveService: {
24 id: 'settings.service.form.saveButton', 24 id: 'settings.service.form.saveButton',
25 defaultMessage: '!!!Save service', 25 defaultMessage: 'Save service',
26 }, 26 },
27 deleteService: { 27 deleteService: {
28 id: 'settings.service.form.deleteButton', 28 id: 'settings.service.form.deleteButton',
29 defaultMessage: '!!!Delete Service', 29 defaultMessage: 'Delete Service',
30 }, 30 },
31 openDarkmodeCss: { 31 openDarkmodeCss: {
32 id: 'settings.service.form.openDarkmodeCss', 32 id: 'settings.service.form.openDarkmodeCss',
33 defaultMessage: '!!!Open darkmode.css', 33 defaultMessage: 'Open darkmode.css',
34 }, 34 },
35 openUserCss: { 35 openUserCss: {
36 id: 'settings.service.form.openUserCss', 36 id: 'settings.service.form.openUserCss',
37 defaultMessage: '!!!Open user.css', 37 defaultMessage: 'Open user.css',
38 }, 38 },
39 openUserJs: { 39 openUserJs: {
40 id: 'settings.service.form.openUserJs', 40 id: 'settings.service.form.openUserJs',
41 defaultMessage: '!!!Open user.js', 41 defaultMessage: 'Open user.js',
42 }, 42 },
43 recipeFileInfo: { 43 recipeFileInfo: {
44 id: 'settings.service.form.recipeFileInfo', 44 id: 'settings.service.form.recipeFileInfo',
45 defaultMessage: '!!!Your user files will be inserted into the webpage so you can customize services in any way you like. User files are only stored locally and are not transferred to other computers using the same account.', 45 defaultMessage:
46 'Your user files will be inserted into the webpage so you can customize services in any way you like. User files are only stored locally and are not transferred to other computers using the same account.',
46 }, 47 },
47 availableServices: { 48 availableServices: {
48 id: 'settings.service.form.availableServices', 49 id: 'settings.service.form.availableServices',
49 defaultMessage: '!!!Available services', 50 defaultMessage: 'Available services',
50 }, 51 },
51 yourServices: { 52 yourServices: {
52 id: 'settings.service.form.yourServices', 53 id: 'settings.service.form.yourServices',
53 defaultMessage: '!!!Your services', 54 defaultMessage: 'Your services',
54 }, 55 },
55 addServiceHeadline: { 56 addServiceHeadline: {
56 id: 'settings.service.form.addServiceHeadline', 57 id: 'settings.service.form.addServiceHeadline',
57 defaultMessage: '!!!Add {name}', 58 defaultMessage: 'Add {name}',
58 }, 59 },
59 editServiceHeadline: { 60 editServiceHeadline: {
60 id: 'settings.service.form.editServiceHeadline', 61 id: 'settings.service.form.editServiceHeadline',
61 defaultMessage: '!!!Edit {name}', 62 defaultMessage: 'Edit {name}',
62 }, 63 },
63 tabHosted: { 64 tabHosted: {
64 id: 'settings.service.form.tabHosted', 65 id: 'settings.service.form.tabHosted',
65 defaultMessage: '!!!Hosted', 66 defaultMessage: 'Hosted',
66 }, 67 },
67 tabOnPremise: { 68 tabOnPremise: {
68 id: 'settings.service.form.tabOnPremise', 69 id: 'settings.service.form.tabOnPremise',
69 defaultMessage: '!!!Self hosted ⭐️', 70 defaultMessage: 'Self hosted ⭐️',
70 }, 71 },
71 useHostedService: { 72 useHostedService: {
72 id: 'settings.service.form.useHostedService', 73 id: 'settings.service.form.useHostedService',
73 defaultMessage: '!!!Use the hosted {name} service.', 74 defaultMessage: 'Use the hosted {name} service.',
74 }, 75 },
75 customUrlValidationError: { 76 customUrlValidationError: {
76 id: 'settings.service.form.customUrlValidationError', 77 id: 'settings.service.form.customUrlValidationError',
77 defaultMessage: '!!!Could not validate custom {name} server.', 78 defaultMessage: 'Could not validate custom {name} server.',
78 }, 79 },
79 indirectMessageInfo: { 80 indirectMessageInfo: {
80 id: 'settings.service.form.indirectMessageInfo', 81 id: 'settings.service.form.indirectMessageInfo',
81 defaultMessage: '!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...', 82 defaultMessage:
83 'You will be notified about all new messages in a channel, not just @username, @channel, @here, ...',
82 }, 84 },
83 isMutedInfo: { 85 isMutedInfo: {
84 id: 'settings.service.form.isMutedInfo', 86 id: 'settings.service.form.isMutedInfo',
85 defaultMessage: '!!!When disabled, all notification sounds and audio playback are muted', 87 defaultMessage:
88 'When disabled, all notification sounds and audio playback are muted',
86 }, 89 },
87 isHibernationEnabledInfo: { 90 isHibernationEnabledInfo: {
88 id: 'settings.service.form.isHibernatedEnabledInfo', 91 id: 'settings.service.form.isHibernatedEnabledInfo',
89 defaultMessage: '!!!When enabled, a service will be shut down after a period of time to save system resources.', 92 defaultMessage:
93 'When enabled, a service will be shut down after a period of time to save system resources.',
90 }, 94 },
91 headlineNotifications: { 95 headlineNotifications: {
92 id: 'settings.service.form.headlineNotifications', 96 id: 'settings.service.form.headlineNotifications',
93 defaultMessage: '!!!Notifications', 97 defaultMessage: 'Notifications',
94 }, 98 },
95 headlineBadges: { 99 headlineBadges: {
96 id: 'settings.service.form.headlineBadges', 100 id: 'settings.service.form.headlineBadges',
97 defaultMessage: '!!!Unread message badges', 101 defaultMessage: 'Unread message badges',
98 }, 102 },
99 headlineGeneral: { 103 headlineGeneral: {
100 id: 'settings.service.form.headlineGeneral', 104 id: 'settings.service.form.headlineGeneral',
101 defaultMessage: '!!!General', 105 defaultMessage: 'General',
102 }, 106 },
103 headlineDarkReaderSettings: { 107 headlineDarkReaderSettings: {
104 id: 'settings.service.form.headlineDarkReaderSettings', 108 id: 'settings.service.form.headlineDarkReaderSettings',
105 defaultMessage: '!!!Dark Reader Settings', 109 defaultMessage: 'Dark Reader Settings',
106 }, 110 },
107 iconDelete: { 111 iconDelete: {
108 id: 'settings.service.form.iconDelete', 112 id: 'settings.service.form.iconDelete',
109 defaultMessage: '!!!Delete', 113 defaultMessage: 'Delete',
110 }, 114 },
111 iconUpload: { 115 iconUpload: {
112 id: 'settings.service.form.iconUpload', 116 id: 'settings.service.form.iconUpload',
113 defaultMessage: '!!!Drop your image, or click here', 117 defaultMessage: 'Drop your image, or click here',
114 }, 118 },
115 headlineProxy: { 119 headlineProxy: {
116 id: 'settings.service.form.proxy.headline', 120 id: 'settings.service.form.proxy.headline',
117 defaultMessage: '!!!HTTP/HTTPS Proxy Settings', 121 defaultMessage: 'HTTP/HTTPS Proxy Settings',
118 }, 122 },
119 proxyRestartInfo: { 123 proxyRestartInfo: {
120 id: 'settings.service.form.proxy.restartInfo', 124 id: 'settings.service.form.proxy.restartInfo',
121 defaultMessage: '!!!Please restart Ferdi after changing proxy Settings.', 125 defaultMessage: 'Please restart Ferdi after changing proxy Settings.',
122 }, 126 },
123 proxyInfo: { 127 proxyInfo: {
124 id: 'settings.service.form.proxy.info', 128 id: 'settings.service.form.proxy.info',
125 defaultMessage: '!!!Proxy settings will not be synchronized with the Ferdi servers.', 129 defaultMessage:
130 'Proxy settings will not be synchronized with the Ferdi servers.',
126 }, 131 },
127}); 132});
128 133
129export default @observer class EditServiceForm extends Component { 134@observer
135class EditServiceForm extends Component {
130 static propTypes = { 136 static propTypes = {
131 recipe: PropTypes.instanceOf(Recipe).isRequired, 137 recipe: PropTypes.instanceOf(Recipe).isRequired,
132 service(props, propName) { 138 service(props, propName) {
@@ -151,20 +157,16 @@ export default @observer class EditServiceForm extends Component {
151 service: {}, 157 service: {},
152 }; 158 };
153 159
154 static contextTypes = {
155 intl: intlShape,
156 };
157
158 state = { 160 state = {
159 isValidatingCustomUrl: false, 161 isValidatingCustomUrl: false,
160 } 162 };
161 163
162 submit(e) { 164 submit(e) {
163 const { recipe } = this.props; 165 const { recipe } = this.props;
164 166
165 e.preventDefault(); 167 e.preventDefault();
166 this.props.form.submit({ 168 this.props.form.submit({
167 onSuccess: async (form) => { 169 onSuccess: async form => {
168 const values = form.values(); 170 const values = form.values();
169 let isValid = true; 171 let isValid = true;
170 172
@@ -176,7 +178,10 @@ export default @observer class EditServiceForm extends Component {
176 if (recipe.validateUrl && values.customUrl) { 178 if (recipe.validateUrl && values.customUrl) {
177 this.setState({ isValidatingCustomUrl: true }); 179 this.setState({ isValidatingCustomUrl: true });
178 try { 180 try {
179 values.customUrl = normalizeUrl(values.customUrl, { stripWWW: false, removeTrailingSlash: false }); 181 values.customUrl = normalizeUrl(values.customUrl, {
182 stripWWW: false,
183 removeTrailingSlash: false,
184 });
180 isValid = await recipe.validateUrl(values.customUrl); 185 isValid = await recipe.validateUrl(values.customUrl);
181 } catch (err) { 186 } catch (err) {
182 console.warn('ValidateURL', err); 187 console.warn('ValidateURL', err);
@@ -208,7 +213,7 @@ export default @observer class EditServiceForm extends Component {
208 openRecipeFile, 213 openRecipeFile,
209 isProxyFeatureEnabled, 214 isProxyFeatureEnabled,
210 } = this.props; 215 } = this.props;
211 const { intl } = this.context; 216 const { intl } = this.props;
212 217
213 const { isValidatingCustomUrl } = this.state; 218 const { isValidatingCustomUrl } = this.state;
214 219
@@ -236,7 +241,8 @@ export default @observer class EditServiceForm extends Component {
236 activeTabIndex = 2; 241 activeTabIndex = 2;
237 } 242 }
238 243
239 const requiresUserInput = !recipe.hasHostedOption && (recipe.hasTeamId || recipe.hasCustomUrl); 244 const requiresUserInput =
245 !recipe.hasHostedOption && (recipe.hasTeamId || recipe.hasCustomUrl);
240 246
241 return ( 247 return (
242 <div className="settings__main"> 248 <div className="settings__main">
@@ -254,29 +260,27 @@ export default @observer class EditServiceForm extends Component {
254 </span> 260 </span>
255 <span className="separator" /> 261 <span className="separator" />
256 <span className="settings__header-item"> 262 <span className="settings__header-item">
257 {action === 'add' ? ( 263 {action === 'add'
258 intl.formatMessage(messages.addServiceHeadline, { 264 ? intl.formatMessage(messages.addServiceHeadline, {
259 name: recipe.name, 265 name: recipe.name,
260 }) 266 })
261 ) : ( 267 : intl.formatMessage(messages.editServiceHeadline, {
262 intl.formatMessage(messages.editServiceHeadline, {
263 name: service.name !== '' ? service.name : recipe.name, 268 name: service.name !== '' ? service.name : recipe.name,
264 }) 269 })}
265 )}
266 </span> 270 </span>
267 </div> 271 </div>
268 <div className="settings__body"> 272 <div className="settings__body">
269 <form onSubmit={(e) => this.submit(e)} id="form"> 273 <form onSubmit={e => this.submit(e)} id="form">
270 <div className="service-name"> 274 <div className="service-name">
271 <Input field={form.$('name')} focus /> 275 <Input field={form.$('name')} focus />
272 </div> 276 </div>
273 {(recipe.hasTeamId || recipe.hasCustomUrl) && ( 277 {(recipe.hasTeamId || recipe.hasCustomUrl) && (
274 <Tabs 278 <Tabs active={activeTabIndex}>
275 active={activeTabIndex}
276 >
277 {recipe.hasHostedOption && ( 279 {recipe.hasHostedOption && (
278 <TabItem title={recipe.name}> 280 <TabItem title={recipe.name}>
279 {intl.formatMessage(messages.useHostedService, { name: recipe.name })} 281 {intl.formatMessage(messages.useHostedService, {
282 name: recipe.name,
283 })}
280 </TabItem> 284 </TabItem>
281 )} 285 )}
282 {recipe.hasTeamId && ( 286 {recipe.hasTeamId && (
@@ -293,7 +297,9 @@ export default @observer class EditServiceForm extends Component {
293 <Input field={form.$('customUrl')} /> 297 <Input field={form.$('customUrl')} />
294 {form.error === 'url-validation-error' && ( 298 {form.error === 'url-validation-error' && (
295 <p className="franz-form__error"> 299 <p className="franz-form__error">
296 {intl.formatMessage(messages.customUrlValidationError, { name: recipe.name })} 300 {intl.formatMessage(messages.customUrlValidationError, {
301 name: recipe.name,
302 })}
297 </p> 303 </p>
298 )} 304 )}
299 </TabItem> 305 </TabItem>
@@ -326,13 +332,16 @@ export default @observer class EditServiceForm extends Component {
326 <div className="settings__settings-group"> 332 <div className="settings__settings-group">
327 <h3>{intl.formatMessage(messages.headlineBadges)}</h3> 333 <h3>{intl.formatMessage(messages.headlineBadges)}</h3>
328 <Toggle field={form.$('isBadgeEnabled')} /> 334 <Toggle field={form.$('isBadgeEnabled')} />
329 {recipe.hasIndirectMessages && form.$('isBadgeEnabled').value && ( 335 {recipe.hasIndirectMessages &&
330 <> 336 form.$('isBadgeEnabled').value && (
331 <Toggle field={form.$('isIndirectMessageBadgeEnabled')} /> 337 <>
332 <p className="settings__help indented__help"> 338 <Toggle
333 {intl.formatMessage(messages.indirectMessageInfo)} 339 field={form.$('isIndirectMessageBadgeEnabled')}
334 </p> 340 />
335 </> 341 <p className="settings__help indented__help">
342 {intl.formatMessage(messages.indirectMessageInfo)}
343 </p>
344 </>
336 )} 345 )}
337 </div> 346 </div>
338 347
@@ -344,15 +353,18 @@ export default @observer class EditServiceForm extends Component {
344 {intl.formatMessage(messages.isHibernationEnabledInfo)} 353 {intl.formatMessage(messages.isHibernationEnabledInfo)}
345 </p> 354 </p>
346 <Toggle field={form.$('isDarkModeEnabled')} /> 355 <Toggle field={form.$('isDarkModeEnabled')} />
347 {form.$('isDarkModeEnabled').value 356 {form.$('isDarkModeEnabled').value && (
348 && ( 357 <>
349 <> 358 <h3>
350 <h3>{intl.formatMessage(messages.headlineDarkReaderSettings)}</h3> 359 {intl.formatMessage(
351 <Slider field={form.$('darkReaderBrightness')} /> 360 messages.headlineDarkReaderSettings,
352 <Slider field={form.$('darkReaderContrast')} /> 361 )}
353 <Slider field={form.$('darkReaderSepia')} /> 362 </h3>
354 </> 363 <Slider field={form.$('darkReaderBrightness')} />
355 )} 364 <Slider field={form.$('darkReaderContrast')} />
365 <Slider field={form.$('darkReaderSepia')} />
366 </>
367 )}
356 </div> 368 </div>
357 </div> 369 </div>
358 <div className="service-icon"> 370 <div className="service-icon">
@@ -381,7 +393,10 @@ export default @observer class EditServiceForm extends Component {
381 <> 393 <>
382 <div className="grid"> 394 <div className="grid">
383 <div className="grid__row"> 395 <div className="grid__row">
384 <Input field={form.$('proxy.host')} className="proxyHost" /> 396 <Input
397 field={form.$('proxy.host')}
398 className="proxyHost"
399 />
385 <Input field={form.$('proxy.port')} /> 400 <Input field={form.$('proxy.port')} />
386 </div> 401 </div>
387 </div> 402 </div>
@@ -409,7 +424,9 @@ export default @observer class EditServiceForm extends Component {
409 424
410 <div className="user-agent"> 425 <div className="user-agent">
411 <Input field={form.$('userAgentPref')} /> 426 <Input field={form.$('userAgentPref')} />
412 <p className="settings__help">{intl.formatMessage(globalMessages.userAgentHelp)}</p> 427 <p className="settings__help">
428 {intl.formatMessage(globalMessages.userAgentHelp)}
429 </p>
413 </div> 430 </div>
414 </form> 431 </form>
415 432
@@ -464,7 +481,9 @@ export default @observer class EditServiceForm extends Component {
464 type="submit" 481 type="submit"
465 label={intl.formatMessage(messages.saveService)} 482 label={intl.formatMessage(messages.saveService)}
466 htmlForm="form" 483 htmlForm="form"
467 disabled={action !== 'edit' && (form.isPristine && requiresUserInput)} 484 disabled={
485 action !== 'edit' && form.isPristine && requiresUserInput
486 }
468 /> 487 />
469 )} 488 )}
470 </div> 489 </div>
@@ -472,3 +491,5 @@ export default @observer class EditServiceForm extends Component {
472 ); 491 );
473 } 492 }
474} 493}
494
495export default injectIntl(EditServiceForm);
diff --git a/src/components/settings/services/ServiceError.js b/src/components/settings/services/ServiceError.js
index 3cfc080d6..d16d76db2 100644
--- a/src/components/settings/services/ServiceError.js
+++ b/src/components/settings/services/ServiceError.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import { observer } from 'mobx-react'; 2import { observer } from 'mobx-react';
3import { Link } from 'react-router'; 3import { Link } from 'react-router';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5 5
6import Infobox from '../../ui/Infobox'; 6import Infobox from '../../ui/Infobox';
7import Button from '../../ui/Button'; 7import Button from '../../ui/Button';
@@ -9,29 +9,26 @@ import Button from '../../ui/Button';
9const messages = defineMessages({ 9const messages = defineMessages({
10 headline: { 10 headline: {
11 id: 'settings.service.error.headline', 11 id: 'settings.service.error.headline',
12 defaultMessage: '!!!Error', 12 defaultMessage: 'Error',
13 }, 13 },
14 goBack: { 14 goBack: {
15 id: 'settings.service.error.goBack', 15 id: 'settings.service.error.goBack',
16 defaultMessage: '!!!Back to services', 16 defaultMessage: 'Back to services',
17 }, 17 },
18 availableServices: { 18 availableServices: {
19 id: 'settings.service.form.availableServices', 19 id: 'settings.service.form.availableServices',
20 defaultMessage: '!!!Available services', 20 defaultMessage: 'Available services',
21 }, 21 },
22 errorMessage: { 22 errorMessage: {
23 id: 'settings.service.error.message', 23 id: 'settings.service.error.message',
24 defaultMessage: '!!!Could not load service recipe.', 24 defaultMessage: 'Could not load service recipe.',
25 }, 25 },
26}); 26});
27 27
28export default @observer class ServiceError extends Component { 28@observer
29 static contextTypes = { 29class ServiceError extends Component {
30 intl: intlShape,
31 };
32
33 render() { 30 render() {
34 const { intl } = this.context; 31 const { intl } = this.props;
35 32
36 return ( 33 return (
37 <div className="settings__main"> 34 <div className="settings__main">
@@ -47,10 +44,7 @@ export default @observer class ServiceError extends Component {
47 </span> 44 </span>
48 </div> 45 </div>
49 <div className="settings__body"> 46 <div className="settings__body">
50 <Infobox 47 <Infobox type="danger" icon="alert">
51 type="danger"
52 icon="alert"
53 >
54 {intl.formatMessage(messages.errorMessage)} 48 {intl.formatMessage(messages.errorMessage)}
55 </Infobox> 49 </Infobox>
56 </div> 50 </div>
@@ -65,3 +59,5 @@ export default @observer class ServiceError extends Component {
65 ); 59 );
66 } 60 }
67} 61}
62
63export default injectIntl(ServiceError);
diff --git a/src/components/settings/services/ServiceItem.js b/src/components/settings/services/ServiceItem.js
index ebc618a00..4916e4ecc 100644
--- a/src/components/settings/services/ServiceItem.js
+++ b/src/components/settings/services/ServiceItem.js
@@ -1,6 +1,6 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { defineMessages, intlShape } from 'react-intl'; 3import { defineMessages, injectIntl } from 'react-intl';
4import ReactTooltip from 'react-tooltip'; 4import ReactTooltip from 'react-tooltip';
5import { observer } from 'mobx-react'; 5import { observer } from 'mobx-react';
6import classnames from 'classnames'; 6import classnames from 'classnames';
@@ -10,35 +10,32 @@ import ServiceModel from '../../../models/Service';
10const messages = defineMessages({ 10const messages = defineMessages({
11 tooltipIsDisabled: { 11 tooltipIsDisabled: {
12 id: 'settings.services.tooltip.isDisabled', 12 id: 'settings.services.tooltip.isDisabled',
13 defaultMessage: '!!!Service is disabled', 13 defaultMessage: 'Service is disabled',
14 }, 14 },
15 tooltipNotificationsDisabled: { 15 tooltipNotificationsDisabled: {
16 id: 'settings.services.tooltip.notificationsDisabled', 16 id: 'settings.services.tooltip.notificationsDisabled',
17 defaultMessage: '!!!Notifications are disabled', 17 defaultMessage: 'Notifications are disabled',
18 }, 18 },
19 tooltipIsMuted: { 19 tooltipIsMuted: {
20 id: 'settings.services.tooltip.isMuted', 20 id: 'settings.services.tooltip.isMuted',
21 defaultMessage: '!!!All sounds are muted', 21 defaultMessage: 'All sounds are muted',
22 }, 22 },
23}); 23});
24 24
25export default @observer class ServiceItem extends Component { 25@observer
26class ServiceItem extends Component {
26 static propTypes = { 27 static propTypes = {
27 service: PropTypes.instanceOf(ServiceModel).isRequired, 28 service: PropTypes.instanceOf(ServiceModel).isRequired,
28 goToServiceForm: PropTypes.func.isRequired, 29 goToServiceForm: PropTypes.func.isRequired,
29 }; 30 };
30 31
31 static contextTypes = {
32 intl: intlShape,
33 };
34
35 render() { 32 render() {
36 const { 33 const {
37 service, 34 service,
38 // toggleAction, 35 // toggleAction,
39 goToServiceForm, 36 goToServiceForm,
40 } = this.props; 37 } = this.props;
41 const { intl } = this.context; 38 const { intl } = this.props;
42 39
43 return ( 40 return (
44 <tr 41 <tr
@@ -47,10 +44,7 @@ export default @observer class ServiceItem extends Component {
47 'service-table__row--disabled': !service.isEnabled, 44 'service-table__row--disabled': !service.isEnabled,
48 })} 45 })}
49 > 46 >
50 <td 47 <td className="service-table__column-icon" onClick={goToServiceForm}>
51 className="service-table__column-icon"
52 onClick={goToServiceForm}
53 >
54 <img 48 <img
55 src={service.icon} 49 src={service.icon}
56 className={classnames({ 50 className={classnames({
@@ -60,16 +54,10 @@ export default @observer class ServiceItem extends Component {
60 alt="" 54 alt=""
61 /> 55 />
62 </td> 56 </td>
63 <td 57 <td className="service-table__column-name" onClick={goToServiceForm}>
64 className="service-table__column-name"
65 onClick={goToServiceForm}
66 >
67 {service.name !== '' ? service.name : service.recipe.name} 58 {service.name !== '' ? service.name : service.recipe.name}
68 </td> 59 </td>
69 <td 60 <td className="service-table__column-info" onClick={goToServiceForm}>
70 className="service-table__column-info"
71 onClick={goToServiceForm}
72 >
73 {service.isMuted && ( 61 {service.isMuted && (
74 <span 62 <span
75 className="mdi mdi-bell-off" 63 className="mdi mdi-bell-off"
@@ -77,10 +65,7 @@ export default @observer class ServiceItem extends Component {
77 /> 65 />
78 )} 66 )}
79 </td> 67 </td>
80 <td 68 <td className="service-table__column-info" onClick={goToServiceForm}>
81 className="service-table__column-info"
82 onClick={goToServiceForm}
83 >
84 {!service.isEnabled && ( 69 {!service.isEnabled && (
85 <span 70 <span
86 className="mdi mdi-power" 71 className="mdi mdi-power"
@@ -88,14 +73,13 @@ export default @observer class ServiceItem extends Component {
88 /> 73 />
89 )} 74 )}
90 </td> 75 </td>
91 <td 76 <td className="service-table__column-info" onClick={goToServiceForm}>
92 className="service-table__column-info"
93 onClick={goToServiceForm}
94 >
95 {!service.isNotificationEnabled && ( 77 {!service.isNotificationEnabled && (
96 <span 78 <span
97 className="mdi mdi-message-bulleted-off" 79 className="mdi mdi-message-bulleted-off"
98 data-tip={intl.formatMessage(messages.tooltipNotificationsDisabled)} 80 data-tip={intl.formatMessage(
81 messages.tooltipNotificationsDisabled,
82 )}
99 /> 83 />
100 )} 84 )}
101 <ReactTooltip place="top" type="dark" effect="solid" /> 85 <ReactTooltip place="top" type="dark" effect="solid" />
@@ -104,3 +88,5 @@ export default @observer class ServiceItem extends Component {
104 ); 88 );
105 } 89 }
106} 90}
91
92export default injectIntl(ServiceItem);
diff --git a/src/components/settings/services/ServicesDashboard.js b/src/components/settings/services/ServicesDashboard.js
index 11d3eaa79..847f2ea06 100644
--- a/src/components/settings/services/ServicesDashboard.js
+++ b/src/components/settings/services/ServicesDashboard.js
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { Link } from 'react-router'; 4import { Link } from 'react-router';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6 6
7import SearchInput from '../../ui/SearchInput'; 7import SearchInput from '../../ui/SearchInput';
8import Infobox from '../../ui/Infobox'; 8import Infobox from '../../ui/Infobox';
@@ -14,43 +14,45 @@ import Appear from '../../ui/effects/Appear';
14const messages = defineMessages({ 14const messages = defineMessages({
15 headline: { 15 headline: {
16 id: 'settings.services.headline', 16 id: 'settings.services.headline',
17 defaultMessage: '!!!Your services', 17 defaultMessage: 'Your services',
18 }, 18 },
19 searchService: { 19 searchService: {
20 id: 'settings.searchService', 20 id: 'settings.searchService',
21 defaultMessage: '!!!Search service', 21 defaultMessage: 'Search service',
22 }, 22 },
23 noServicesAdded: { 23 noServicesAdded: {
24 id: 'settings.services.noServicesAdded', 24 id: 'settings.services.noServicesAdded',
25 defaultMessage: '!!!Start by adding a service.', 25 defaultMessage: 'Start by adding a service.',
26 }, 26 },
27 noServiceFound: { 27 noServiceFound: {
28 id: 'settings.recipes.nothingFound', 28 id: 'settings.recipes.nothingFound',
29 defaultMessage: '!!!Sorry, but no service matched your search term. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.', 29 defaultMessage:
30 'Sorry, but no service matched your search term. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.',
30 }, 31 },
31 discoverServices: { 32 discoverServices: {
32 id: 'settings.services.discoverServices', 33 id: 'settings.services.discoverServices',
33 defaultMessage: '!!!Discover services', 34 defaultMessage: 'Discover services',
34 }, 35 },
35 servicesRequestFailed: { 36 servicesRequestFailed: {
36 id: 'settings.services.servicesRequestFailed', 37 id: 'settings.services.servicesRequestFailed',
37 defaultMessage: '!!!Could not load your services', 38 defaultMessage: 'Could not load your services',
38 }, 39 },
39 tryReloadServices: { 40 tryReloadServices: {
40 id: 'settings.account.tryReloadServices', 41 id: 'settings.account.tryReloadServices',
41 defaultMessage: '!!!Try again', 42 defaultMessage: 'Try again',
42 }, 43 },
43 updatedInfo: { 44 updatedInfo: {
44 id: 'settings.services.updatedInfo', 45 id: 'settings.services.updatedInfo',
45 defaultMessage: '!!!Your changes have been saved', 46 defaultMessage: 'Your changes have been saved',
46 }, 47 },
47 deletedInfo: { 48 deletedInfo: {
48 id: 'settings.services.deletedInfo', 49 id: 'settings.services.deletedInfo',
49 defaultMessage: '!!!Service has been deleted', 50 defaultMessage: 'Service has been deleted',
50 }, 51 },
51}); 52});
52 53
53export default @observer class ServicesDashboard extends Component { 54@observer
55class ServicesDashboard extends Component {
54 static propTypes = { 56 static propTypes = {
55 services: MobxPropTypes.arrayOrObservableArray.isRequired, 57 services: MobxPropTypes.arrayOrObservableArray.isRequired,
56 isLoading: PropTypes.bool.isRequired, 58 isLoading: PropTypes.bool.isRequired,
@@ -68,10 +70,6 @@ export default @observer class ServicesDashboard extends Component {
68 searchNeedle: '', 70 searchNeedle: '',
69 }; 71 };
70 72
71 static contextTypes = {
72 intl: intlShape,
73 };
74
75 render() { 73 render() {
76 const { 74 const {
77 services, 75 services,
@@ -85,7 +83,7 @@ export default @observer class ServicesDashboard extends Component {
85 status, 83 status,
86 searchNeedle, 84 searchNeedle,
87 } = this.props; 85 } = this.props;
88 const { intl } = this.context; 86 const { intl } = this.props;
89 87
90 return ( 88 return (
91 <div className="settings__main"> 89 <div className="settings__main">
@@ -96,7 +94,7 @@ export default @observer class ServicesDashboard extends Component {
96 {(services.length !== 0 || searchNeedle) && !isLoading && ( 94 {(services.length !== 0 || searchNeedle) && !isLoading && (
97 <SearchInput 95 <SearchInput
98 placeholder={intl.formatMessage(messages.searchService)} 96 placeholder={intl.formatMessage(messages.searchService)}
99 onChange={(needle) => filterServices({ needle })} 97 onChange={needle => filterServices({ needle })}
100 onReset={() => resetFilter()} 98 onReset={() => resetFilter()}
101 autoFocus 99 autoFocus
102 /> 100 />
@@ -145,7 +143,9 @@ export default @observer class ServicesDashboard extends Component {
145 </span> 143 </span>
146 {intl.formatMessage(messages.noServicesAdded)} 144 {intl.formatMessage(messages.noServicesAdded)}
147 </p> 145 </p>
148 <Link to="/settings/recipes" className="button">{intl.formatMessage(messages.discoverServices)}</Link> 146 <Link to="/settings/recipes" className="button">
147 {intl.formatMessage(messages.discoverServices)}
148 </Link>
149 </div> 149 </div>
150 )} 150 )}
151 {!isLoading && services.length === 0 && searchNeedle && ( 151 {!isLoading && services.length === 0 && searchNeedle && (
@@ -163,12 +163,16 @@ export default @observer class ServicesDashboard extends Component {
163 ) : ( 163 ) : (
164 <table className="service-table"> 164 <table className="service-table">
165 <tbody> 165 <tbody>
166 {services.map((service) => ( 166 {services.map(service => (
167 <ServiceItem 167 <ServiceItem
168 key={service.id} 168 key={service.id}
169 service={service} 169 service={service}
170 toggleAction={() => toggleService({ serviceId: service.id })} 170 toggleAction={() =>
171 goToServiceForm={() => goTo(`/settings/services/edit/${service.id}`)} 171 toggleService({ serviceId: service.id })
172 }
173 goToServiceForm={() =>
174 goTo(`/settings/services/edit/${service.id}`)
175 }
172 /> 176 />
173 ))} 177 ))}
174 </tbody> 178 </tbody>
@@ -176,12 +180,12 @@ export default @observer class ServicesDashboard extends Component {
176 )} 180 )}
177 181
178 <FAB> 182 <FAB>
179 <Link to="/settings/recipes"> 183 <Link to="/settings/recipes">+</Link>
180 +
181 </Link>
182 </FAB> 184 </FAB>
183 </div> 185 </div>
184 </div> 186 </div>
185 ); 187 );
186 } 188 }
187} 189}
190
191export default injectIntl(ServicesDashboard);
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index 6a919b902..0a468e342 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -3,7 +3,7 @@ import React, { Component } from 'react';
3import PropTypes from 'prop-types'; 3import PropTypes from 'prop-types';
4import { observer } from 'mobx-react'; 4import { observer } from 'mobx-react';
5import prettyBytes from 'pretty-bytes'; 5import prettyBytes from 'pretty-bytes';
6import { defineMessages, intlShape } from 'react-intl'; 6import { defineMessages, injectIntl } from 'react-intl';
7 7
8import Form from '../../../lib/Form'; 8import Form from '../../../lib/Form';
9import Button from '../../ui/Button'; 9import Button from '../../ui/Button';
@@ -13,154 +13,173 @@ import Select from '../../ui/Select';
13import Input from '../../ui/Input'; 13import Input from '../../ui/Input';
14 14
15import { FRANZ_TRANSLATION, GITHUB_FRANZ_URL } from '../../../config'; 15import { FRANZ_TRANSLATION, GITHUB_FRANZ_URL } from '../../../config';
16import { DEFAULT_APP_SETTINGS, ferdiVersion, isMac, isWindows, lockFerdiShortcutKey, userDataPath, userDataRecipesPath } from '../../../environment'; 16import {
17 DEFAULT_APP_SETTINGS,
18 ferdiVersion,
19 isMac,
20 isWindows,
21 lockFerdiShortcutKey,
22 userDataPath,
23 userDataRecipesPath,
24} from '../../../environment';
17import { openPath } from '../../../helpers/url-helpers'; 25import { openPath } from '../../../helpers/url-helpers';
18import globalMessages from '../../../i18n/globalMessages'; 26import globalMessages from '../../../i18n/globalMessages';
19 27
20const messages = defineMessages({ 28const messages = defineMessages({
21 headlineGeneral: { 29 headlineGeneral: {
22 id: 'settings.app.headlineGeneral', 30 id: 'settings.app.headlineGeneral',
23 defaultMessage: '!!!General', 31 defaultMessage: 'General',
24 }, 32 },
25 sentryInfo: { 33 sentryInfo: {
26 id: 'settings.app.sentryInfo', 34 id: 'settings.app.sentryInfo',
27 defaultMessage: '!!!Sending telemetry data allows us to find errors in Ferdi - we will not send any personal information like your message data!', 35 defaultMessage:
36 'Sending telemetry data allows us to find errors in Ferdi - we will not send any personal information like your message data!',
28 }, 37 },
29 hibernateInfo: { 38 hibernateInfo: {
30 id: 'settings.app.hibernateInfo', 39 id: 'settings.app.hibernateInfo',
31 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.', 40 defaultMessage:
41 '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.',
32 }, 42 },
33 inactivityLockInfo: { 43 inactivityLockInfo: {
34 id: 'settings.app.inactivityLockInfo', 44 id: 'settings.app.inactivityLockInfo',
35 defaultMessage: '!!!Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable', 45 defaultMessage:
46 'Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable',
36 }, 47 },
37 todoServerInfo: { 48 todoServerInfo: {
38 id: 'settings.app.todoServerInfo', 49 id: 'settings.app.todoServerInfo',
39 defaultMessage: '!!!This server will be used for the "Franz Todo" feature. (default: https://app.franztodos.com)', 50 defaultMessage:
51 'This server will be used for the "Franz Todo" feature. (default: https://app.franztodos.com)',
40 }, 52 },
41 lockedPassword: { 53 lockedPassword: {
42 id: 'settings.app.lockedPassword', 54 id: 'settings.app.lockedPassword',
43 defaultMessage: '!!!Password', 55 defaultMessage: 'Password',
44 }, 56 },
45 lockedPasswordInfo: { 57 lockedPasswordInfo: {
46 id: 'settings.app.lockedPasswordInfo', 58 id: 'settings.app.lockedPasswordInfo',
47 defaultMessage: '!!!Please make sure to set a password you\'ll remember.\nIf you loose this password, you will have to reinstall Ferdi.', 59 defaultMessage:
60 "Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdi.",
48 }, 61 },
49 lockInfo: { 62 lockInfo: {
50 id: 'settings.app.lockInfo', 63 id: 'settings.app.lockInfo',
51 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}.', 64 defaultMessage:
65 '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}.',
52 }, 66 },
53 scheduledDNDTimeInfo: { 67 scheduledDNDTimeInfo: {
54 id: 'settings.app.scheduledDNDTimeInfo', 68 id: 'settings.app.scheduledDNDTimeInfo',
55 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.', 69 defaultMessage:
70 '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.',
56 }, 71 },
57 scheduledDNDInfo: { 72 scheduledDNDInfo: {
58 id: 'settings.app.scheduledDNDInfo', 73 id: 'settings.app.scheduledDNDInfo',
59 defaultMessage: '!!!Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.', 74 defaultMessage:
75 'Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.',
60 }, 76 },
61 headlineLanguage: { 77 headlineLanguage: {
62 id: 'settings.app.headlineLanguage', 78 id: 'settings.app.headlineLanguage',
63 defaultMessage: '!!!Language', 79 defaultMessage: 'Language',
64 }, 80 },
65 headlineUpdates: { 81 headlineUpdates: {
66 id: 'settings.app.headlineUpdates', 82 id: 'settings.app.headlineUpdates',
67 defaultMessage: '!!!Updates', 83 defaultMessage: 'Updates',
68 }, 84 },
69 headlineAppearance: { 85 headlineAppearance: {
70 id: 'settings.app.headlineAppearance', 86 id: 'settings.app.headlineAppearance',
71 defaultMessage: '!!!Appearance', 87 defaultMessage: 'Appearance',
72 }, 88 },
73 universalDarkModeInfo: { 89 universalDarkModeInfo: {
74 id: 'settings.app.universalDarkModeInfo', 90 id: 'settings.app.universalDarkModeInfo',
75 defaultMessage: '!!!Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.', 91 defaultMessage:
92 'Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.',
76 }, 93 },
77 accentColorInfo: { 94 accentColorInfo: {
78 id: 'settings.app.accentColorInfo', 95 id: 'settings.app.accentColorInfo',
79 defaultMessage: '!!!Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})', 96 defaultMessage:
97 'Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})',
80 }, 98 },
81 headlinePrivacy: { 99 headlinePrivacy: {
82 id: 'settings.app.headlinePrivacy', 100 id: 'settings.app.headlinePrivacy',
83 defaultMessage: '!!!Privacy', 101 defaultMessage: 'Privacy',
84 }, 102 },
85 headlineAdvanced: { 103 headlineAdvanced: {
86 id: 'settings.app.headlineAdvanced', 104 id: 'settings.app.headlineAdvanced',
87 defaultMessage: '!!!Advanced', 105 defaultMessage: 'Advanced',
88 }, 106 },
89 translationHelp: { 107 translationHelp: {
90 id: 'settings.app.translationHelp', 108 id: 'settings.app.translationHelp',
91 defaultMessage: '!!!Help us to translate Ferdi into your language.', 109 defaultMessage: 'Help us to translate Ferdi into your language.',
92 }, 110 },
93 spellCheckerLanguageInfo: { 111 spellCheckerLanguageInfo: {
94 id: 'settings.app.spellCheckerLanguageInfo', 112 id: 'settings.app.spellCheckerLanguageInfo',
95 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.', 113 defaultMessage:
114 "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.",
96 }, 115 },
97 subheadlineCache: { 116 subheadlineCache: {
98 id: 'settings.app.subheadlineCache', 117 id: 'settings.app.subheadlineCache',
99 defaultMessage: '!!!Cache', 118 defaultMessage: 'Cache',
100 }, 119 },
101 cacheInfo: { 120 cacheInfo: {
102 id: 'settings.app.cacheInfo', 121 id: 'settings.app.cacheInfo',
103 defaultMessage: '!!!Ferdi cache is currently using {size} of disk space.', 122 defaultMessage: 'Ferdi cache is currently using {size} of disk space.',
104 }, 123 },
105 cacheNotCleared: { 124 cacheNotCleared: {
106 id: 'settings.app.cacheNotCleared', 125 id: 'settings.app.cacheNotCleared',
107 defaultMessage: '!!!Couldn\'t clear all cache', 126 defaultMessage: "Couldn't clear all cache",
108 }, 127 },
109 buttonClearAllCache: { 128 buttonClearAllCache: {
110 id: 'settings.app.buttonClearAllCache', 129 id: 'settings.app.buttonClearAllCache',
111 defaultMessage: '!!!Clear cache', 130 defaultMessage: 'Clear cache',
112 }, 131 },
113 subheadlineFerdiProfile: { 132 subheadlineFerdiProfile: {
114 id: 'settings.app.subheadlineFerdiProfile', 133 id: 'settings.app.subheadlineFerdiProfile',
115 defaultMessage: '!!!Ferdi Profile', 134 defaultMessage: 'Ferdi Profile',
116 }, 135 },
117 buttonOpenFerdiProfileFolder: { 136 buttonOpenFerdiProfileFolder: {
118 id: 'settings.app.buttonOpenFerdiProfileFolder', 137 id: 'settings.app.buttonOpenFerdiProfileFolder',
119 defaultMessage: '!!!Open Profile folder', 138 defaultMessage: 'Open Profile folder',
120 }, 139 },
121 buttonOpenFerdiServiceRecipesFolder: { 140 buttonOpenFerdiServiceRecipesFolder: {
122 id: 'settings.app.buttonOpenFerdiServiceRecipesFolder', 141 id: 'settings.app.buttonOpenFerdiServiceRecipesFolder',
123 defaultMessage: '!!!Open Service Recipes folder', 142 defaultMessage: 'Open Service Recipes folder',
124 }, 143 },
125 buttonSearchForUpdate: { 144 buttonSearchForUpdate: {
126 id: 'settings.app.buttonSearchForUpdate', 145 id: 'settings.app.buttonSearchForUpdate',
127 defaultMessage: '!!!Check for updates', 146 defaultMessage: 'Check for updates',
128 }, 147 },
129 buttonInstallUpdate: { 148 buttonInstallUpdate: {
130 id: 'settings.app.buttonInstallUpdate', 149 id: 'settings.app.buttonInstallUpdate',
131 defaultMessage: '!!!Restart & install update', 150 defaultMessage: 'Restart & install update',
132 }, 151 },
133 updateStatusSearching: { 152 updateStatusSearching: {
134 id: 'settings.app.updateStatusSearching', 153 id: 'settings.app.updateStatusSearching',
135 defaultMessage: '!!!Is searching for update', 154 defaultMessage: 'Is searching for update',
136 }, 155 },
137 updateStatusAvailable: { 156 updateStatusAvailable: {
138 id: 'settings.app.updateStatusAvailable', 157 id: 'settings.app.updateStatusAvailable',
139 defaultMessage: '!!!Update available, downloading...', 158 defaultMessage: 'Update available, downloading...',
140 }, 159 },
141 updateStatusUpToDate: { 160 updateStatusUpToDate: {
142 id: 'settings.app.updateStatusUpToDate', 161 id: 'settings.app.updateStatusUpToDate',
143 defaultMessage: '!!!You are using the latest version of Ferdi', 162 defaultMessage: 'You are using the latest version of Ferdi',
144 }, 163 },
145 currentVersion: { 164 currentVersion: {
146 id: 'settings.app.currentVersion', 165 id: 'settings.app.currentVersion',
147 defaultMessage: '!!!Current version:', 166 defaultMessage: 'Current version:',
148 }, 167 },
149 appRestartRequired: { 168 appRestartRequired: {
150 id: 'settings.app.restartRequired', 169 id: 'settings.app.restartRequired',
151 defaultMessage: '!!!Changes require restart', 170 defaultMessage: 'Changes require restart',
152 }, 171 },
153 languageDisclaimer: { 172 languageDisclaimer: {
154 id: 'settings.app.languageDisclaimer', 173 id: 'settings.app.languageDisclaimer',
155 defaultMessage: '!!!Official translations are English & German. All other languages are community based translations.', 174 defaultMessage:
175 'Official translations are English & German. All other languages are community based translations.',
156 }, 176 },
157}); 177});
158 178
159const Hr = () => ( 179const Hr = () => <hr style={{ marginBottom: 20 }} />;
160 <hr style={{ marginBottom: 20 }} />
161);
162 180
163export default @observer class EditSettingsForm extends Component { 181@observer
182class EditSettingsForm extends Component {
164 static propTypes = { 183 static propTypes = {
165 checkForUpdates: PropTypes.func.isRequired, 184 checkForUpdates: PropTypes.func.isRequired,
166 installUpdate: PropTypes.func.isRequired, 185 installUpdate: PropTypes.func.isRequired,
@@ -184,14 +203,10 @@ export default @observer class EditSettingsForm extends Component {
184 isOnline: PropTypes.bool.isRequired, 203 isOnline: PropTypes.bool.isRequired,
185 }; 204 };
186 205
187 static contextTypes = {
188 intl: intlShape,
189 };
190
191 state = { 206 state = {
192 activeSetttingsTab: 'general', 207 activeSetttingsTab: 'general',
193 clearCacheButtonClicked: false, 208 clearCacheButtonClicked: false,
194 } 209 };
195 210
196 setActiveSettingsTab(tab) { 211 setActiveSettingsTab(tab) {
197 this.setState({ 212 this.setState({
@@ -199,14 +214,14 @@ export default @observer class EditSettingsForm extends Component {
199 }); 214 });
200 } 215 }
201 216
202 onClearCacheClicked=() => { 217 onClearCacheClicked = () => {
203 this.setState({ clearCacheButtonClicked: true }); 218 this.setState({ clearCacheButtonClicked: true });
204 } 219 };
205 220
206 submit(e) { 221 submit(e) {
207 e.preventDefault(); 222 e.preventDefault();
208 this.props.form.submit({ 223 this.props.form.submit({
209 onSuccess: (form) => { 224 onSuccess: form => {
210 const values = form.values(); 225 const values = form.values();
211 this.props.onSubmit(values); 226 this.props.onSubmit(values);
212 }, 227 },
@@ -236,7 +251,7 @@ export default @observer class EditSettingsForm extends Component {
236 hasAddedTodosAsService, 251 hasAddedTodosAsService,
237 isOnline, 252 isOnline,
238 } = this.props; 253 } = this.props;
239 const { intl } = this.context; 254 const { intl } = this.props;
240 255
241 let updateButtonLabelMessage = messages.buttonSearchForUpdate; 256 let updateButtonLabelMessage = messages.buttonSearchForUpdate;
242 if (isCheckingForUpdates) { 257 if (isCheckingForUpdates) {
@@ -247,10 +262,8 @@ export default @observer class EditSettingsForm extends Component {
247 updateButtonLabelMessage = messages.buttonSearchForUpdate; 262 updateButtonLabelMessage = messages.buttonSearchForUpdate;
248 } 263 }
249 264
250 const { 265 const { lockingFeatureEnabled, scheduledDNDEnabled } =
251 lockingFeatureEnabled, 266 window.ferdi.stores.settings.all.app;
252 scheduledDNDEnabled,
253 } = window.ferdi.stores.settings.all.app;
254 267
255 let cacheSize; 268 let cacheSize;
256 let notCleared; 269 let notCleared;
@@ -258,7 +271,10 @@ export default @observer class EditSettingsForm extends Component {
258 const cacheSizeBytes = getCacheSize(); 271 const cacheSizeBytes = getCacheSize();
259 if (typeof cacheSizeBytes === 'number') { 272 if (typeof cacheSizeBytes === 'number') {
260 cacheSize = prettyBytes(cacheSizeBytes); 273 cacheSize = prettyBytes(cacheSizeBytes);
261 notCleared = this.state.clearCacheButtonClicked && isClearingAllCache === false && cacheSizeBytes !== 0; 274 notCleared =
275 this.state.clearCacheButtonClicked &&
276 isClearingAllCache === false &&
277 cacheSizeBytes !== 0;
262 } else { 278 } else {
263 cacheSize = '…'; 279 cacheSize = '…';
264 notCleared = false; 280 notCleared = false;
@@ -275,58 +291,94 @@ export default @observer class EditSettingsForm extends Component {
275 </div> 291 </div>
276 <div className="settings__body"> 292 <div className="settings__body">
277 <form 293 <form
278 onSubmit={(e) => this.submit(e)} 294 onSubmit={e => this.submit(e)}
279 onChange={(e) => this.submit(e)} 295 onChange={e => this.submit(e)}
280 id="form" 296 id="form"
281 > 297 >
282 {/* Titles */} 298 {/* Titles */}
283 <div className="recipes__navigation"> 299 <div className="recipes__navigation">
284 <h2 300 <h2
285 id="general" 301 id="general"
286 className={this.state.activeSetttingsTab === 'general' ? 'badge badge--primary' : 'badge'} 302 className={
287 onClick={() => { this.setActiveSettingsTab('general'); }} 303 this.state.activeSetttingsTab === 'general'
304 ? 'badge badge--primary'
305 : 'badge'
306 }
307 onClick={() => {
308 this.setActiveSettingsTab('general');
309 }}
288 > 310 >
289 {intl.formatMessage(messages.headlineGeneral)} 311 {intl.formatMessage(messages.headlineGeneral)}
290 </h2> 312 </h2>
291 <h2 313 <h2
292 id="appearance" 314 id="appearance"
293 className={this.state.activeSetttingsTab === 'appearance' ? 'badge badge--primary' : 'badge'} 315 className={
294 onClick={() => { this.setActiveSettingsTab('appearance'); }} 316 this.state.activeSetttingsTab === 'appearance'
317 ? 'badge badge--primary'
318 : 'badge'
319 }
320 onClick={() => {
321 this.setActiveSettingsTab('appearance');
322 }}
295 > 323 >
296 {intl.formatMessage(messages.headlineAppearance)} 324 {intl.formatMessage(messages.headlineAppearance)}
297 </h2> 325 </h2>
298 <h2 326 <h2
299 id="privacy" 327 id="privacy"
300 className={this.state.activeSetttingsTab === 'privacy' ? 'badge badge--primary' : 'badge'} 328 className={
301 onClick={() => { this.setActiveSettingsTab('privacy'); }} 329 this.state.activeSetttingsTab === 'privacy'
330 ? 'badge badge--primary'
331 : 'badge'
332 }
333 onClick={() => {
334 this.setActiveSettingsTab('privacy');
335 }}
302 > 336 >
303 {intl.formatMessage(messages.headlinePrivacy)} 337 {intl.formatMessage(messages.headlinePrivacy)}
304 </h2> 338 </h2>
305 <h2 339 <h2
306 id="language" 340 id="language"
307 className={this.state.activeSetttingsTab === 'language' ? 'badge badge--primary' : 'badge'} 341 className={
308 onClick={() => { this.setActiveSettingsTab('language'); }} 342 this.state.activeSetttingsTab === 'language'
343 ? 'badge badge--primary'
344 : 'badge'
345 }
346 onClick={() => {
347 this.setActiveSettingsTab('language');
348 }}
309 > 349 >
310 {intl.formatMessage(messages.headlineLanguage)} 350 {intl.formatMessage(messages.headlineLanguage)}
311 </h2> 351 </h2>
312 <h2 352 <h2
313 id="advanced" 353 id="advanced"
314 className={this.state.activeSetttingsTab === 'advanced' ? 'badge badge--primary' : 'badge'} 354 className={
315 onClick={() => { this.setActiveSettingsTab('advanced'); }} 355 this.state.activeSetttingsTab === 'advanced'
356 ? 'badge badge--primary'
357 : 'badge'
358 }
359 onClick={() => {
360 this.setActiveSettingsTab('advanced');
361 }}
316 > 362 >
317 {intl.formatMessage(messages.headlineAdvanced)} 363 {intl.formatMessage(messages.headlineAdvanced)}
318 </h2> 364 </h2>
319 <h2 365 <h2
320 id="updates" 366 id="updates"
321 className={this.state.activeSetttingsTab === 'updates' ? 'badge badge--primary' : 'badge'} 367 className={
322 onClick={() => { this.setActiveSettingsTab('updates'); }} 368 this.state.activeSetttingsTab === 'updates'
369 ? 'badge badge--primary'
370 : 'badge'
371 }
372 onClick={() => {
373 this.setActiveSettingsTab('updates');
374 }}
323 > 375 >
324 {intl.formatMessage(messages.headlineUpdates)} 376 {intl.formatMessage(messages.headlineUpdates)}
325 </h2> 377 </h2>
326 </div> 378 </div>
327 379
328 {/* General */} 380 {/* General */}
329 { this.state.activeSetttingsTab === 'general' && ( 381 {this.state.activeSetttingsTab === 'general' && (
330 <div> 382 <div>
331 <Toggle field={form.$('autoLaunchOnStart')} /> 383 <Toggle field={form.$('autoLaunchOnStart')} />
332 <Toggle field={form.$('runInBackground')} /> 384 <Toggle field={form.$('runInBackground')} />
@@ -334,12 +386,8 @@ export default @observer class EditSettingsForm extends Component {
334 <Toggle field={form.$('enableSystemTray')} /> 386 <Toggle field={form.$('enableSystemTray')} />
335 <Toggle field={form.$('reloadAfterResume')} /> 387 <Toggle field={form.$('reloadAfterResume')} />
336 <Toggle field={form.$('startMinimized')} /> 388 <Toggle field={form.$('startMinimized')} />
337 {isWindows && ( 389 {isWindows && <Toggle field={form.$('minimizeToSystemTray')} />}
338 <Toggle field={form.$('minimizeToSystemTray')} /> 390 {isWindows && <Toggle field={form.$('closeToSystemTray')} />}
339 )}
340 {isWindows && (
341 <Toggle field={form.$('closeToSystemTray')} />
342 )}
343 <Select field={form.$('navigationBarBehaviour')} /> 391 <Select field={form.$('navigationBarBehaviour')} />
344 392
345 <Hr /> 393 <Hr />
@@ -349,12 +397,13 @@ export default @observer class EditSettingsForm extends Component {
349 <p 397 <p
350 className="settings__message" 398 className="settings__message"
351 style={{ 399 style={{
352 borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', 400 borderTop: 0,
401 marginTop: 0,
402 paddingTop: 0,
403 marginBottom: '2rem',
353 }} 404 }}
354 > 405 >
355 <span> 406 <span>{intl.formatMessage(messages.hibernateInfo)}</span>
356 { intl.formatMessage(messages.hibernateInfo) }
357 </span>
358 </p> 407 </p>
359 408
360 <Select field={form.$('wakeUpStrategy')} /> 409 <Select field={form.$('wakeUpStrategy')} />
@@ -374,20 +423,24 @@ export default @observer class EditSettingsForm extends Component {
374 {isTodosActivated && ( 423 {isTodosActivated && (
375 <div> 424 <div>
376 <Select field={form.$('predefinedTodoServer')} /> 425 <Select field={form.$('predefinedTodoServer')} />
377 {form.$('predefinedTodoServer').value === 'isUsingCustomTodoService' && ( 426 {form.$('predefinedTodoServer').value ===
427 'isUsingCustomTodoService' && (
378 <div> 428 <div>
379 <Input 429 <Input
380 placeholder="Todo Server" 430 placeholder="Todo Server"
381 onChange={(e) => this.submit(e)} 431 onChange={e => this.submit(e)}
382 field={form.$('customTodoServer')} 432 field={form.$('customTodoServer')}
383 /> 433 />
384 <p 434 <p
385 className="settings__message" 435 className="settings__message"
386 style={{ 436 style={{
387 borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', 437 borderTop: 0,
438 marginTop: 0,
439 paddingTop: 0,
440 marginBottom: '2rem',
388 }} 441 }}
389 > 442 >
390 { intl.formatMessage(messages.todoServerInfo) } 443 {intl.formatMessage(messages.todoServerInfo)}
391 </p> 444 </p>
392 </div> 445 </div>
393 )} 446 )}
@@ -400,56 +453,58 @@ export default @observer class EditSettingsForm extends Component {
400 <Toggle field={form.$('scheduledDNDEnabled')} /> 453 <Toggle field={form.$('scheduledDNDEnabled')} />
401 {scheduledDNDEnabled && ( 454 {scheduledDNDEnabled && (
402 <> 455 <>
403 <div style={{ 456 <div
404 display: 'flex', 457 style={{
405 justifyContent: 'center', 458 display: 'flex',
406 }} 459 justifyContent: 'center',
407 >
408 <div style={{
409 padding: '0 1rem',
410 width: '100%',
411 }} 460 }}
461 >
462 <div
463 style={{
464 padding: '0 1rem',
465 width: '100%',
466 }}
412 > 467 >
413 <Input 468 <Input
414 placeholder="17:00" 469 placeholder="17:00"
415 onChange={(e) => this.submit(e)} 470 onChange={e => this.submit(e)}
416 field={form.$('scheduledDNDStart')} 471 field={form.$('scheduledDNDStart')}
417 type="time" 472 type="time"
418 /> 473 />
419 </div> 474 </div>
420 <div style={{ 475 <div
421 padding: '0 1rem', 476 style={{
422 width: '100%', 477 padding: '0 1rem',
423 }} 478 width: '100%',
479 }}
424 > 480 >
425 <Input 481 <Input
426 placeholder="09:00" 482 placeholder="09:00"
427 onChange={(e) => this.submit(e)} 483 onChange={e => this.submit(e)}
428 field={form.$('scheduledDNDEnd')} 484 field={form.$('scheduledDNDEnd')}
429 type="time" 485 type="time"
430 /> 486 />
431 </div> 487 </div>
432 </div> 488 </div>
433 <p> 489 <p>{intl.formatMessage(messages.scheduledDNDTimeInfo)}</p>
434 { intl.formatMessage(messages.scheduledDNDTimeInfo) }
435 </p>
436 </> 490 </>
437 )} 491 )}
438 <p 492 <p
439 className="settings__message" 493 className="settings__message"
440 style={{ 494 style={{
441 borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', 495 borderTop: 0,
496 marginTop: 0,
497 paddingTop: 0,
498 marginBottom: '2rem',
442 }} 499 }}
443 > 500 >
444 <span> 501 <span>{intl.formatMessage(messages.scheduledDNDInfo)}</span>
445 { intl.formatMessage(messages.scheduledDNDInfo) }
446 </span>
447 </p> 502 </p>
448 </div> 503 </div>
449 )} 504 )}
450 505
451 {/* Appearance */} 506 {/* Appearance */}
452 { this.state.activeSetttingsTab === 'appearance' && ( 507 {this.state.activeSetttingsTab === 'appearance' && (
453 <div> 508 <div>
454 <Toggle field={form.$('showDisabledServices')} /> 509 <Toggle field={form.$('showDisabledServices')} />
455 <Toggle field={form.$('showMessageBadgeWhenMuted')} /> 510 <Toggle field={form.$('showMessageBadgeWhenMuted')} />
@@ -459,21 +514,26 @@ export default @observer class EditSettingsForm extends Component {
459 <Hr /> 514 <Hr />
460 515
461 <Toggle field={form.$('adaptableDarkMode')} /> 516 <Toggle field={form.$('adaptableDarkMode')} />
462 {!isAdaptableDarkModeEnabled && <Toggle field={form.$('darkMode')} />} 517 {!isAdaptableDarkModeEnabled && (
518 <Toggle field={form.$('darkMode')} />
519 )}
463 {(isDarkmodeEnabled || isAdaptableDarkModeEnabled) && ( 520 {(isDarkmodeEnabled || isAdaptableDarkModeEnabled) && (
464 <> 521 <>
465 <Toggle field={form.$('universalDarkMode')} /> 522 <Toggle field={form.$('universalDarkMode')} />
466 <p 523 <p
467 className="settings__message" 524 className="settings__message"
468 style={{ 525 style={{
469 borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', 526 borderTop: 0,
470 }} 527 marginTop: 0,
471 > 528 paddingTop: 0,
472 <span> 529 marginBottom: '2rem',
473 { intl.formatMessage(messages.universalDarkModeInfo) } 530 }}
474 </span> 531 >
475 </p> 532 <span>
476 </> 533 {intl.formatMessage(messages.universalDarkModeInfo)}
534 </span>
535 </p>
536 </>
477 )} 537 )}
478 538
479 <Hr /> 539 <Hr />
@@ -491,23 +551,25 @@ export default @observer class EditSettingsForm extends Component {
491 551
492 <Input 552 <Input
493 placeholder="Accent Color" 553 placeholder="Accent Color"
494 onChange={(e) => this.submit(e)} 554 onChange={e => this.submit(e)}
495 field={form.$('accentColor')} 555 field={form.$('accentColor')}
496 /> 556 />
497 <p> 557 <p>
498 {intl.formatMessage(messages.accentColorInfo, 558 {intl.formatMessage(messages.accentColorInfo, {
499 { defaultAccentColor: DEFAULT_APP_SETTINGS.accentColor })} 559 defaultAccentColor: DEFAULT_APP_SETTINGS.accentColor,
560 })}
500 </p> 561 </p>
501 </div> 562 </div>
502 )} 563 )}
503 564
504 {/* Privacy */} 565 {/* Privacy */}
505 { this.state.activeSetttingsTab === 'privacy' && ( 566 {this.state.activeSetttingsTab === 'privacy' && (
506 <div> 567 <div>
507 <Toggle field={form.$('privateNotifications')} /> 568 <Toggle field={form.$('privateNotifications')} />
508 <Toggle field={form.$('clipboardNotifications')} /> 569 <Toggle field={form.$('clipboardNotifications')} />
509 {(isWindows || isMac) && ( 570 {(isWindows || isMac) && (
510 <Toggle field={form.$('notifyTaskBarOnMessage')} />)} 571 <Toggle field={form.$('notifyTaskBarOnMessage')} />
572 )}
511 573
512 <Hr /> 574 <Hr />
513 575
@@ -516,8 +578,12 @@ export default @observer class EditSettingsForm extends Component {
516 <Hr /> 578 <Hr />
517 579
518 <Toggle field={form.$('sentry')} /> 580 <Toggle field={form.$('sentry')} />
519 <p className="settings__help">{intl.formatMessage(messages.sentryInfo)}</p> 581 <p className="settings__help">
520 <p className="settings__help">{intl.formatMessage(messages.appRestartRequired)}</p> 582 {intl.formatMessage(messages.sentryInfo)}
583 </p>
584 <p className="settings__help">
585 {intl.formatMessage(messages.appRestartRequired)}
586 </p>
521 587
522 <Hr /> 588 <Hr />
523 589
@@ -530,57 +596,60 @@ export default @observer class EditSettingsForm extends Component {
530 596
531 <Input 597 <Input
532 placeholder={intl.formatMessage(messages.lockedPassword)} 598 placeholder={intl.formatMessage(messages.lockedPassword)}
533 onChange={(e) => this.submit(e)} 599 onChange={e => this.submit(e)}
534 field={form.$('lockedPassword')} 600 field={form.$('lockedPassword')}
535 type="password" 601 type="password"
536 scorePassword 602 scorePassword
537 showPasswordToggle 603 showPasswordToggle
538 /> 604 />
539 <p> 605 <p>{intl.formatMessage(messages.lockedPasswordInfo)}</p>
540 { intl.formatMessage(messages.lockedPasswordInfo) }
541 </p>
542 606
543 <Input 607 <Input
544 placeholder="Lock after inactivity" 608 placeholder="Lock after inactivity"
545 onChange={(e) => this.submit(e)} 609 onChange={e => this.submit(e)}
546 field={form.$('inactivityLock')} 610 field={form.$('inactivityLock')}
547 autoFocus 611 autoFocus
548 /> 612 />
549 <p> 613 <p>{intl.formatMessage(messages.inactivityLockInfo)}</p>
550 { intl.formatMessage(messages.inactivityLockInfo) }
551 </p>
552 </> 614 </>
553 )} 615 )}
554 <p 616 <p
555 className="settings__message" 617 className="settings__message"
556 style={{ 618 style={{
557 borderTop: 0, marginTop: 0, paddingTop: 0, marginBottom: '2rem', 619 borderTop: 0,
620 marginTop: 0,
621 paddingTop: 0,
622 marginBottom: '2rem',
558 }} 623 }}
559 > 624 >
560 <span> 625 <span>
561 { intl.formatMessage(messages.lockInfo, { lockShortcut: `${lockFerdiShortcutKey(false)}` }) } 626 {intl.formatMessage(messages.lockInfo, {
627 lockShortcut: `${lockFerdiShortcutKey(false)}`,
628 })}
562 </span> 629 </span>
563 </p> 630 </p>
564 </div> 631 </div>
565 )} 632 )}
566 633
567 {/* Language */} 634 {/* Language */}
568 { this.state.activeSetttingsTab === 'language' && ( 635 {this.state.activeSetttingsTab === 'language' && (
569 <div> 636 <div>
570 <Select field={form.$('locale')} showLabel={false} /> 637 <Select field={form.$('locale')} showLabel={false} />
571 638
572 <Hr /> 639 <Hr />
573 640
574 <Toggle 641 <Toggle field={form.$('enableSpellchecking')} />
575 field={form.$('enableSpellchecking')}
576 />
577 {!isMac && form.$('enableSpellchecking').value && ( 642 {!isMac && form.$('enableSpellchecking').value && (
578 <Select field={form.$('spellcheckerLanguage')} /> 643 <Select field={form.$('spellcheckerLanguage')} />
579 )} 644 )}
580 {isMac && form.$('enableSpellchecking').value && ( 645 {isMac && form.$('enableSpellchecking').value && (
581 <p className="settings__help">{intl.formatMessage(messages.spellCheckerLanguageInfo)}</p> 646 <p className="settings__help">
647 {intl.formatMessage(messages.spellCheckerLanguageInfo)}
648 </p>
582 )} 649 )}
583 <p className="settings__help">{intl.formatMessage(messages.appRestartRequired)}</p> 650 <p className="settings__help">
651 {intl.formatMessage(messages.appRestartRequired)}
652 </p>
584 653
585 <Hr /> 654 <Hr />
586 655
@@ -590,52 +659,54 @@ export default @observer class EditSettingsForm extends Component {
590 className="link" 659 className="link"
591 rel="noreferrer" 660 rel="noreferrer"
592 > 661 >
593 {intl.formatMessage(messages.translationHelp)} 662 {intl.formatMessage(messages.translationHelp)}{' '}
594 {' '}
595 <i className="mdi mdi-open-in-new" /> 663 <i className="mdi mdi-open-in-new" />
596 </a> 664 </a>
597 </div> 665 </div>
598 )} 666 )}
599 667
600 {/* Advanced */} 668 {/* Advanced */}
601 { this.state.activeSetttingsTab === 'advanced' && ( 669 {this.state.activeSetttingsTab === 'advanced' && (
602 <div> 670 <div>
603 <Toggle field={form.$('enableGPUAcceleration')} /> 671 <Toggle field={form.$('enableGPUAcceleration')} />
604 <p className="settings__help indented__help">{intl.formatMessage(messages.appRestartRequired)}</p> 672 <p className="settings__help indented__help">
673 {intl.formatMessage(messages.appRestartRequired)}
674 </p>
605 675
606 <Hr /> 676 <Hr />
607 677
608 <Input 678 <Input
609 placeholder="User Agent" 679 placeholder="User Agent"
610 onChange={(e) => this.submit(e)} 680 onChange={e => this.submit(e)}
611 field={form.$('userAgentPref')} 681 field={form.$('userAgentPref')}
612 /> 682 />
613 <p className="settings__help">{intl.formatMessage(globalMessages.userAgentHelp)}</p> 683 <p className="settings__help">
614 <p className="settings__help">{intl.formatMessage(messages.appRestartRequired)}</p> 684 {intl.formatMessage(globalMessages.userAgentHelp)}
685 </p>
686 <p className="settings__help">
687 {intl.formatMessage(messages.appRestartRequired)}
688 </p>
615 689
616 <Hr /> 690 <Hr />
617 691
618 <div className="settings__settings-group"> 692 <div className="settings__settings-group">
619 <h3> 693 <h3>{intl.formatMessage(messages.subheadlineCache)}</h3>
620 {intl.formatMessage(messages.subheadlineCache)}
621 </h3>
622 <p> 694 <p>
623 {intl.formatMessage(messages.cacheInfo, { 695 {intl.formatMessage(messages.cacheInfo, {
624 size: cacheSize, 696 size: cacheSize,
625 })} 697 })}
626 </p> 698 </p>
627 { 699 {notCleared && (
628 notCleared && ( 700 <p>{intl.formatMessage(messages.cacheNotCleared)}</p>
629 <p> 701 )}
630 {intl.formatMessage(messages.cacheNotCleared)}
631 </p>
632 )
633 }
634 <p> 702 <p>
635 <Button 703 <Button
636 buttonType="secondary" 704 buttonType="secondary"
637 label={intl.formatMessage(messages.buttonClearAllCache)} 705 label={intl.formatMessage(messages.buttonClearAllCache)}
638 onClick={() => { onClearAllCache(); this.onClearCacheClicked(); }} 706 onClick={() => {
707 onClearAllCache();
708 this.onClearCacheClicked();
709 }}
639 disabled={isClearingAllCache} 710 disabled={isClearingAllCache}
640 loaded={!isClearingAllCache} 711 loaded={!isClearingAllCache}
641 /> 712 />
@@ -652,13 +723,17 @@ export default @observer class EditSettingsForm extends Component {
652 <div className="settings__open-settings-file-container"> 723 <div className="settings__open-settings-file-container">
653 <Button 724 <Button
654 buttonType="secondary" 725 buttonType="secondary"
655 label={intl.formatMessage(messages.buttonOpenFerdiProfileFolder)} 726 label={intl.formatMessage(
727 messages.buttonOpenFerdiProfileFolder,
728 )}
656 className="settings__open-settings-file-button" 729 className="settings__open-settings-file-button"
657 onClick={() => openPath(profileFolder)} 730 onClick={() => openPath(profileFolder)}
658 /> 731 />
659 <Button 732 <Button
660 buttonType="secondary" 733 buttonType="secondary"
661 label={intl.formatMessage(messages.buttonOpenFerdiServiceRecipesFolder)} 734 label={intl.formatMessage(
735 messages.buttonOpenFerdiServiceRecipesFolder,
736 )}
662 className="settings__open-settings-file-button" 737 className="settings__open-settings-file-button"
663 onClick={() => openPath(recipeFolder)} 738 onClick={() => openPath(recipeFolder)}
664 /> 739 />
@@ -669,66 +744,78 @@ export default @observer class EditSettingsForm extends Component {
669 )} 744 )}
670 745
671 {/* Updates */} 746 {/* Updates */}
672 { this.state.activeSetttingsTab === 'updates' && ( 747 {this.state.activeSetttingsTab === 'updates' && (
673 <div>
674 <Toggle field={form.$('automaticUpdates')} />
675 {automaticUpdates && (
676 <div> 748 <div>
677 <Toggle field={form.$('beta')} /> 749 <Toggle field={form.$('automaticUpdates')} />
678 <ToggleRaw 750 {automaticUpdates && (
679 field={{ 751 <div>
680 value: isNightlyEnabled, 752 <Toggle field={form.$('beta')} />
681 id: 'nightly', 753 <ToggleRaw
682 label: 'Include nightly versions', 754 field={{
683 name: 'Nightly builds', 755 value: isNightlyEnabled,
684 }} 756 id: 'nightly',
685 onChange={window.ferdi.features.nightlyBuilds.toggleFeature} 757 label: 'Include nightly versions',
686 /> 758 name: 'Nightly builds',
687 {updateIsReadyToInstall ? ( 759 }}
688 <Button 760 onChange={
689 label={intl.formatMessage(messages.buttonInstallUpdate)} 761 window.ferdi.features.nightlyBuilds.toggleFeature
690 onClick={installUpdate} 762 }
691 /> 763 />
692 ) : ( 764 {updateIsReadyToInstall ? (
693 <Button 765 <Button
694 buttonType="secondary" 766 label={intl.formatMessage(messages.buttonInstallUpdate)}
695 label={intl.formatMessage(updateButtonLabelMessage)} 767 onClick={installUpdate}
696 onClick={checkForUpdates} 768 />
697 disabled={!automaticUpdates || isCheckingForUpdates || isUpdateAvailable || !isOnline} 769 ) : (
698 loaded={!isCheckingForUpdates || !isUpdateAvailable} 770 <Button
699 /> 771 buttonType="secondary"
772 label={intl.formatMessage(updateButtonLabelMessage)}
773 onClick={checkForUpdates}
774 disabled={
775 !automaticUpdates ||
776 isCheckingForUpdates ||
777 isUpdateAvailable ||
778 !isOnline
779 }
780 loaded={!isCheckingForUpdates || !isUpdateAvailable}
781 />
782 )}
783 <br />
784 </div>
785 )}
786 {intl.formatMessage(messages.currentVersion)} {ferdiVersion}
787 {noUpdateAvailable && (
788 <>
789 <br />
790 <br />
791 {intl.formatMessage(messages.updateStatusUpToDate)}
792 </>
700 )} 793 )}
701 <br /> 794 <p className="settings__message">
795 <span className="mdi mdi-github-face" />
796 <span>
797 Ferdi is based on{' '}
798 <a
799 href={`${GITHUB_FRANZ_URL}/franz`}
800 target="_blank"
801 rel="noreferrer"
802 >
803 Franz
804 </a>
805 , a project published under the{' '}
806 <a
807 href={`${GITHUB_FRANZ_URL}/franz/blob/master/LICENSE`}
808 target="_blank"
809 rel="noreferrer"
810 >
811 Apache-2.0 License
812 </a>
813 </span>
814 <br />
815 <span className="mdi mdi-information" />
816 {intl.formatMessage(messages.languageDisclaimer)}
817 </p>
702 </div> 818 </div>
703 )}
704 {intl.formatMessage(messages.currentVersion)}
705 {' '}
706 {ferdiVersion}
707 {noUpdateAvailable && (
708 <>
709 <br />
710 <br />
711 {intl.formatMessage(messages.updateStatusUpToDate)}
712 </>
713 )}
714 <p className="settings__message">
715 <span className="mdi mdi-github-face" />
716 <span>
717
718 Ferdi is based on
719 {' '}
720 <a href={`${GITHUB_FRANZ_URL}/franz`} target="_blank" rel="noreferrer">Franz</a>
721
722 , a project published
723 under the
724 {' '}
725 <a href={`${GITHUB_FRANZ_URL}/franz/blob/master/LICENSE`} target="_blank" rel="noreferrer">Apache-2.0 License</a>
726 </span>
727 <br />
728 <span className="mdi mdi-information" />
729 {intl.formatMessage(messages.languageDisclaimer)}
730 </p>
731 </div>
732 )} 819 )}
733 </form> 820 </form>
734 </div> 821 </div>
@@ -736,3 +823,5 @@ export default @observer class EditSettingsForm extends Component {
736 ); 823 );
737 } 824 }
738} 825}
826
827export default injectIntl(EditSettingsForm);
diff --git a/src/components/settings/supportFerdi/SupportFerdiDashboard.js b/src/components/settings/supportFerdi/SupportFerdiDashboard.js
index b84e06739..c4d4bd72f 100644
--- a/src/components/settings/supportFerdi/SupportFerdiDashboard.js
+++ b/src/components/settings/supportFerdi/SupportFerdiDashboard.js
@@ -1,76 +1,77 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import { defineMessages, FormattedHTMLMessage, intlShape } from 'react-intl'; 2import { defineMessages, injectIntl } from 'react-intl';
3import { BrowserWindow } from '@electron/remote'; 3import { BrowserWindow } from '@electron/remote';
4import InfoBar from '../../ui/InfoBar'; 4import InfoBar from '../../ui/InfoBar';
5 5
6const messages = defineMessages({ 6const messages = defineMessages({
7 headline: { 7 headline: {
8 id: 'settings.supportFerdi.headline', 8 id: 'settings.supportFerdi.headline',
9 defaultMessage: '!!!About Ferdi', 9 defaultMessage: 'About Ferdi',
10 }, 10 },
11 title: { 11 title: {
12 id: 'settings.supportFerdi.title', 12 id: 'settings.supportFerdi.title',
13 defaultMessage: '!!!Do you like Ferdi?', 13 defaultMessage: 'Do you like Ferdi?',
14 }, 14 },
15 aboutIntro: { 15 aboutIntro: {
16 id: 'settings.supportFerdi.aboutIntro', 16 id: 'settings.supportFerdi.aboutIntro',
17 defaultMessage: '!!!<p>Ferdi is an open-source and a community-lead application.</p><p>Thanks to the people who make this possbile:</p>', 17 defaultMessage:
18 '<p>Ferdi is an open-source and a community-lead application.</p><p>Thanks to the people who make this possbile:</p>',
18 }, 19 },
19 textListContributors: { 20 textListContributors: {
20 id: 'settings.supportFerdi.textListContributors', 21 id: 'settings.supportFerdi.textListContributors',
21 defaultMessage: '!!!Full list of contributor', 22 defaultMessage: 'Full list of contributor',
22 }, 23 },
23 textListContributorsHere: { 24 textListContributorsHere: {
24 id: 'settings.supportFerdi.textListContributorsHere', 25 id: 'settings.supportFerdi.textListContributorsHere',
25 defaultMessage: '!!!here', 26 defaultMessage: 'here',
26 }, 27 },
27 textVolunteers: { 28 textVolunteers: {
28 id: 'settings.supportFerdi.textVolunteers', 29 id: 'settings.supportFerdi.textVolunteers',
29 defaultMessage: '!!!The development of Ferdi is done by volunteers. People who use Ferdi like you. They maintain, fix, and improve Ferdi in their spare time.', 30 defaultMessage:
31 'The development of Ferdi is done by volunteers. People who use Ferdi like you. They maintain, fix, and improve Ferdi in their spare time.',
30 }, 32 },
31 textSupportWelcome: { 33 textSupportWelcome: {
32 id: 'settings.supportFerdi.textSupportWelcome', 34 id: 'settings.supportFerdi.textSupportWelcome',
33 defaultMessage: '!!!Support is always welcome. You can find a list of the help we need', 35 defaultMessage:
36 'Support is always welcome. You can find a list of the help we need',
34 }, 37 },
35 textSupportWelcomeHere: { 38 textSupportWelcomeHere: {
36 id: 'settings.supportFerdi.textSupportWelcomeHere', 39 id: 'settings.supportFerdi.textSupportWelcomeHere',
37 defaultMessage: '!!!here', 40 defaultMessage: 'here',
38 }, 41 },
39 textExpenses: { 42 textExpenses: {
40 id: 'settings.supportFerdi.textExpenses', 43 id: 'settings.supportFerdi.textExpenses',
41 defaultMessage: '!!!While volunteers do most of the work, we still need to pay for servers and certificates. As a community, we are fully transparent on funds we collect and spend - see our', 44 defaultMessage:
45 'While volunteers do most of the work, we still need to pay for servers and certificates. As a community, we are fully transparent on funds we collect and spend - see our',
42 }, 46 },
43 textOpenCollective: { 47 textOpenCollective: {
44 id: 'settings.supportFerdi.textOpenCollective', 48 id: 'settings.supportFerdi.textOpenCollective',
45 defaultMessage: '!!!Open Collective', 49 defaultMessage: 'Open Collective',
46 }, 50 },
47 textDonation: { 51 textDonation: {
48 id: 'settings.supportFerdi.textDonation', 52 id: 'settings.supportFerdi.textDonation',
49 defaultMessage: '!!!If you feel like supporting Ferdi development with a donation, you can do so on both,', 53 defaultMessage:
54 'If you feel like supporting Ferdi development with a donation, you can do so on both,',
50 }, 55 },
51 textDonationAnd: { 56 textDonationAnd: {
52 id: 'settings.supportFerdi.textDonationAnd', 57 id: 'settings.supportFerdi.textDonationAnd',
53 defaultMessage: '!!!and', 58 defaultMessage: 'and',
54 }, 59 },
55 textGitHubSponsors: { 60 textGitHubSponsors: {
56 id: 'settings.supportFerdi.textGitHubSponsors', 61 id: 'settings.supportFerdi.textGitHubSponsors',
57 defaultMessage: '!!!GitHub Sponsors', 62 defaultMessage: 'GitHub Sponsors',
58 }, 63 },
59 openSurvey: { 64 openSurvey: {
60 id: 'settings.supportFerdi.openSurvey', 65 id: 'settings.supportFerdi.openSurvey',
61 defaultMessage: '!!!Open Survey', 66 defaultMessage: 'Open Survey',
62 }, 67 },
63 bannerText: { 68 bannerText: {
64 id: 'settings.supportFerdi.bannerText', 69 id: 'settings.supportFerdi.bannerText',
65 defaultMessage: '!!!Do you want to help us improve Ferdi?', 70 defaultMessage: 'Do you want to help us improve Ferdi?',
66 }, 71 },
67}); 72});
68 73
69class SupportFerdiDashboard extends Component { 74class SupportFerdiDashboard extends Component {
70 static contextTypes = {
71 intl: intlShape,
72 };
73
74 openSurveyWindow() { 75 openSurveyWindow() {
75 let win = new BrowserWindow({ width: 670, height: 400 }); 76 let win = new BrowserWindow({ width: 670, height: 400 });
76 win.on('closed', () => { 77 win.on('closed', () => {
@@ -81,7 +82,9 @@ class SupportFerdiDashboard extends Component {
81 } 82 }
82 83
83 render() { 84 render() {
84 const { intl } = this.context; 85 const { intl } = this.props;
86
87 const aboutIntro = intl.formatMessage(messages.aboutIntro);
85 88
86 return ( 89 return (
87 <div className="settings__main"> 90 <div className="settings__main">
@@ -94,22 +97,67 @@ class SupportFerdiDashboard extends Component {
94 <h1>{intl.formatMessage(messages.title)}</h1> 97 <h1>{intl.formatMessage(messages.title)}</h1>
95 <div> 98 <div>
96 <p className="settings__support-badges"> 99 <p className="settings__support-badges">
97 <a href="https://github.com/getferdi/ferdi" target="_blank" rel="noreferrer"><img alt="GitHub Stars" src="https://img.shields.io/github/stars/getferdi/ferdi?style=social" /></a> 100 <a
98 <a href="https://twitter.com/getferdi/" target="_blank" rel="noreferrer"><img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/getferdi?label=Follow&style=social" /></a> 101 href="https://github.com/getferdi/ferdi"
99 <a href="https://opencollective.com/getferdi#section-contributors" target="_blank" rel="noreferrer"><img alt="Open Collective backers" src="https://img.shields.io/opencollective/backers/getferdi?logo=open-collective" /></a> 102 target="_blank"
100 <a href="https://opencollective.com/getferdi#section-contributors" target="_blank" rel="noreferrer"><img alt="Open Collective sponsors" src="https://img.shields.io/opencollective/sponsors/getferdi?logo=open-collective" /></a> 103 rel="noreferrer"
104 >
105 <img
106 alt="GitHub Stars"
107 src="https://img.shields.io/github/stars/getferdi/ferdi?style=social"
108 />
109 </a>
110 <a
111 href="https://twitter.com/getferdi/"
112 target="_blank"
113 rel="noreferrer"
114 >
115 <img
116 alt="Twitter Follow"
117 src="https://img.shields.io/twitter/follow/getferdi?label=Follow&style=social"
118 />
119 </a>
120 <a
121 href="https://opencollective.com/getferdi#section-contributors"
122 target="_blank"
123 rel="noreferrer"
124 >
125 <img
126 alt="Open Collective backers"
127 src="https://img.shields.io/opencollective/backers/getferdi?logo=open-collective"
128 />
129 </a>
130 <a
131 href="https://opencollective.com/getferdi#section-contributors"
132 target="_blank"
133 rel="noreferrer"
134 >
135 <img
136 alt="Open Collective sponsors"
137 src="https://img.shields.io/opencollective/sponsors/getferdi?logo=open-collective"
138 />
139 </a>
101 </p> 140 </p>
102 <FormattedHTMLMessage {...messages.aboutIntro} /> 141 <span dangerouslySetInnerHTML={{ __html: aboutIntro }} />
103 <br /> 142 <br />
104 <br /> 143 <br />
105 <p> 144 <p>
106 <a href="#contributors-via-opencollective"> 145 <a href="#contributors-via-opencollective">
107 <img alt="GitHub contributors (non-exhaustive)" width="100%" src="https://opencollective.com/getferdi/contributors.svg?width=642&button=false" /> 146 <img
147 alt="GitHub contributors (non-exhaustive)"
148 width="100%"
149 src="https://opencollective.com/getferdi/contributors.svg?width=642&button=false"
150 />
108 </a> 151 </a>
109 </p> 152 </p>
110 <p> 153 <p>
111 {intl.formatMessage(messages.textListContributors)} 154 {intl.formatMessage(messages.textListContributors)}
112 <a href="https://github.com/getferdi/ferdi#contributors-" target="_blank" className="link" rel="noreferrer"> 155 <a
156 href="https://github.com/getferdi/ferdi#contributors-"
157 target="_blank"
158 className="link"
159 rel="noreferrer"
160 >
113 {' '} 161 {' '}
114 {intl.formatMessage(messages.textListContributorsHere)} 162 {intl.formatMessage(messages.textListContributorsHere)}
115 <i className="mdi mdi-open-in-new" /> 163 <i className="mdi mdi-open-in-new" />
@@ -117,12 +165,15 @@ class SupportFerdiDashboard extends Component {
117 <br /> 165 <br />
118 <br /> 166 <br />
119 </p> 167 </p>
120 <p> 168 <p>{intl.formatMessage(messages.textVolunteers)}</p>
121 {intl.formatMessage(messages.textVolunteers)}
122 </p>
123 <p> 169 <p>
124 {intl.formatMessage(messages.textSupportWelcome)} 170 {intl.formatMessage(messages.textSupportWelcome)}
125 <a href="https://help.getferdi.com/general/support" target="_blank" className="link" rel="noreferrer"> 171 <a
172 href="https://help.getferdi.com/general/support"
173 target="_blank"
174 className="link"
175 rel="noreferrer"
176 >
126 {' '} 177 {' '}
127 {intl.formatMessage(messages.textSupportWelcomeHere)} 178 {intl.formatMessage(messages.textSupportWelcomeHere)}
128 <i className="mdi mdi-open-in-new" /> 179 <i className="mdi mdi-open-in-new" />
@@ -130,7 +181,12 @@ class SupportFerdiDashboard extends Component {
130 </p> 181 </p>
131 <p> 182 <p>
132 {intl.formatMessage(messages.textExpenses)} 183 {intl.formatMessage(messages.textExpenses)}
133 <a href="https://opencollective.com/getferdi#section-budget" target="_blank" className="link" rel="noreferrer"> 184 <a
185 href="https://opencollective.com/getferdi#section-budget"
186 target="_blank"
187 className="link"
188 rel="noreferrer"
189 >
134 {' '} 190 {' '}
135 {intl.formatMessage(messages.textOpenCollective)} 191 {intl.formatMessage(messages.textOpenCollective)}
136 <i className="mdi mdi-open-in-new" /> 192 <i className="mdi mdi-open-in-new" />
@@ -138,14 +194,23 @@ class SupportFerdiDashboard extends Component {
138 </p> 194 </p>
139 <p> 195 <p>
140 {intl.formatMessage(messages.textDonation)} 196 {intl.formatMessage(messages.textDonation)}
141 <a href="https://opencollective.com/getferdi#section-contribute" target="_blank" className="link" rel="noreferrer"> 197 <a
198 href="https://opencollective.com/getferdi#section-contribute"
199 target="_blank"
200 className="link"
201 rel="noreferrer"
202 >
142 {' '} 203 {' '}
143 {intl.formatMessage(messages.textOpenCollective)} 204 {intl.formatMessage(messages.textOpenCollective)}
144 <i className="mdi mdi-open-in-new" /> 205 <i className="mdi mdi-open-in-new" />
145 </a> 206 </a>{' '}
146 {' '}
147 {intl.formatMessage(messages.textDonationAnd)} 207 {intl.formatMessage(messages.textDonationAnd)}
148 <a href="https://github.com/sponsors/getferdi" target="_blank" className="link" rel="noreferrer"> 208 <a
209 href="https://github.com/sponsors/getferdi"
210 target="_blank"
211 className="link"
212 rel="noreferrer"
213 >
149 {' '} 214 {' '}
150 {intl.formatMessage(messages.textGitHubSponsors)} 215 {intl.formatMessage(messages.textGitHubSponsors)}
151 <i className="mdi mdi-open-in-new" /> 216 <i className="mdi mdi-open-in-new" />
@@ -166,4 +231,4 @@ class SupportFerdiDashboard extends Component {
166 } 231 }
167} 232}
168 233
169export default SupportFerdiDashboard; 234export default injectIntl(SupportFerdiDashboard);
diff --git a/src/components/settings/team/TeamDashboard.js b/src/components/settings/team/TeamDashboard.js
index 437225058..176365fa8 100644
--- a/src/components/settings/team/TeamDashboard.js
+++ b/src/components/settings/team/TeamDashboard.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import ReactTooltip from 'react-tooltip'; 5import ReactTooltip from 'react-tooltip';
6import injectSheet from 'react-jss'; 6import injectSheet from 'react-jss';
7import classnames from 'classnames'; 7import classnames from 'classnames';
@@ -14,31 +14,34 @@ import { LIVE_FRANZ_API } from '../../../config';
14const messages = defineMessages({ 14const messages = defineMessages({
15 headline: { 15 headline: {
16 id: 'settings.team.headline', 16 id: 'settings.team.headline',
17 defaultMessage: '!!!Team', 17 defaultMessage: 'Team',
18 }, 18 },
19 contentHeadline: { 19 contentHeadline: {
20 id: 'settings.team.contentHeadline', 20 id: 'settings.team.contentHeadline',
21 defaultMessage: '!!!Franz Team Management', 21 defaultMessage: 'Franz Team Management',
22 }, 22 },
23 intro: { 23 intro: {
24 id: 'settings.team.intro', 24 id: 'settings.team.intro',
25 defaultMessage: '!!!Your are currently using Franz Servers, which is why you have access to Team Management.', 25 defaultMessage:
26 'Your are currently using Franz Servers, which is why you have access to Team Management.',
26 }, 27 },
27 copy: { 28 copy: {
28 id: 'settings.team.copy', 29 id: 'settings.team.copy',
29 defaultMessage: '!!!Franz\'s Team Management allows you to manage Franz Subscriptions for multiple users. Please keep in mind that having a Franz Premium subscription will give you no advantages in using Ferdi: The only reason you still have access to Team Management is so you can manage your legacy Franz Teams and so that you don\'t loose any functionality in managing your account.', 30 defaultMessage:
31 "Franz's Team Management allows you to manage Franz Subscriptions for multiple users. Please keep in mind that having a Franz Premium subscription will give you no advantages in using Ferdi: The only reason you still have access to Team Management is so you can manage your legacy Franz Teams and so that you don't loose any functionality in managing your account.",
30 }, 32 },
31 manageButton: { 33 manageButton: {
32 id: 'settings.team.manageAction', 34 id: 'settings.team.manageAction',
33 defaultMessage: '!!!Manage your Team on meetfranz.com', 35 defaultMessage: 'Manage your Team on meetfranz.com',
34 }, 36 },
35 teamsUnavailable: { 37 teamsUnavailable: {
36 id: 'settings.team.teamsUnavailable', 38 id: 'settings.team.teamsUnavailable',
37 defaultMessage: '!!!Teams are unavailable', 39 defaultMessage: 'Teams are unavailable',
38 }, 40 },
39 teamsUnavailableInfo: { 41 teamsUnavailableInfo: {
40 id: 'settings.team.teamsUnavailableInfo', 42 id: 'settings.team.teamsUnavailableInfo',
41 defaultMessage: '!!!Teams are currently only available when using the Franz Server and after paying for Franz Professional. Please change your server to https://api.franzinfra.com to use teams.', 43 defaultMessage:
44 'Teams are currently only available when using the Franz Server and after paying for Franz Professional. Please change your server to https://api.franzinfra.com to use teams.',
42 }, 45 },
43}); 46});
44 47
@@ -87,7 +90,9 @@ const styles = {
87 }, 90 },
88}; 91};
89 92
90export default @injectSheet(styles) @observer class TeamDashboard extends Component { 93@injectSheet(styles)
94@observer
95class TeamDashboard extends Component {
91 static propTypes = { 96 static propTypes = {
92 isLoading: PropTypes.bool.isRequired, 97 isLoading: PropTypes.bool.isRequired,
93 userInfoRequestFailed: PropTypes.bool.isRequired, 98 userInfoRequestFailed: PropTypes.bool.isRequired,
@@ -97,10 +102,6 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon
97 server: PropTypes.string.isRequired, 102 server: PropTypes.string.isRequired,
98 }; 103 };
99 104
100 static contextTypes = {
101 intl: intlShape,
102 };
103
104 render() { 105 render() {
105 const { 106 const {
106 isLoading, 107 isLoading,
@@ -110,7 +111,7 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon
110 classes, 111 classes,
111 server, 112 server,
112 } = this.props; 113 } = this.props;
113 const { intl } = this.context; 114 const { intl } = this.props;
114 115
115 if (server === LIVE_FRANZ_API) { 116 if (server === LIVE_FRANZ_API) {
116 return ( 117 return (
@@ -121,9 +122,7 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon
121 </span> 122 </span>
122 </div> 123 </div>
123 <div className="settings__body"> 124 <div className="settings__body">
124 {isLoading && ( 125 {isLoading && <Loader />}
125 <Loader />
126 )}
127 126
128 {!isLoading && userInfoRequestFailed && ( 127 {!isLoading && userInfoRequestFailed && (
129 <Infobox 128 <Infobox
@@ -142,20 +141,24 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon
142 {!isLoading && ( 141 {!isLoading && (
143 <> 142 <>
144 <> 143 <>
145 <h1 className={classnames({ 144 <h1
146 [classes.headline]: true, 145 className={classnames({
147 [classes.headlineWithSpacing]: true, 146 [classes.headline]: true,
148 })} 147 [classes.headlineWithSpacing]: true,
148 })}
149 > 149 >
150 {intl.formatMessage(messages.contentHeadline)} 150 {intl.formatMessage(messages.contentHeadline)}
151
152 </h1> 151 </h1>
153 <div className={classes.container}> 152 <div className={classes.container}>
154 <div className={classes.content}> 153 <div className={classes.content}>
155 <p>{intl.formatMessage(messages.intro)}</p> 154 <p>{intl.formatMessage(messages.intro)}</p>
156 <p>{intl.formatMessage(messages.copy)}</p> 155 <p>{intl.formatMessage(messages.copy)}</p>
157 </div> 156 </div>
158 <img className={classes.image} src="https://cdn.franzinfra.com/announcements/assets/teams.png" alt="Ferdi for Teams" /> 157 <img
158 className={classes.image}
159 src="https://cdn.franzinfra.com/announcements/assets/teams.png"
160 alt="Ferdi for Teams"
161 />
159 </div> 162 </div>
160 <div className={classes.buttonContainer}> 163 <div className={classes.buttonContainer}>
161 <Button 164 <Button
@@ -188,7 +191,8 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon
188 <p 191 <p
189 className="settings__message" 192 className="settings__message"
190 style={{ 193 style={{
191 borderTop: 0, marginTop: 0, 194 borderTop: 0,
195 marginTop: 0,
192 }} 196 }}
193 > 197 >
194 {intl.formatMessage(messages.teamsUnavailableInfo)} 198 {intl.formatMessage(messages.teamsUnavailableInfo)}
@@ -198,3 +202,5 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon
198 ); 202 );
199 } 203 }
200} 204}
205
206export default injectIntl(TeamDashboard);
diff --git a/src/components/settings/user/EditUserForm.js b/src/components/settings/user/EditUserForm.js
index db78acb69..4067881b8 100644
--- a/src/components/settings/user/EditUserForm.js
+++ b/src/components/settings/user/EditUserForm.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import { Link } from 'react-router'; 5import { Link } from 'react-router';
6import { Input } from '@meetfranz/forms'; 6import { Input } from '@meetfranz/forms';
7 7
@@ -14,31 +14,32 @@ import Infobox from '../../ui/Infobox';
14const messages = defineMessages({ 14const messages = defineMessages({
15 headline: { 15 headline: {
16 id: 'settings.account.headline', 16 id: 'settings.account.headline',
17 defaultMessage: '!!!Account', 17 defaultMessage: 'Account',
18 }, 18 },
19 headlineProfile: { 19 headlineProfile: {
20 id: 'settings.account.headlineProfile', 20 id: 'settings.account.headlineProfile',
21 defaultMessage: '!!!Update Profile', 21 defaultMessage: 'Update Profile',
22 }, 22 },
23 headlineAccount: { 23 headlineAccount: {
24 id: 'settings.account.headlineAccount', 24 id: 'settings.account.headlineAccount',
25 defaultMessage: '!!!Account Information', 25 defaultMessage: 'Account Information',
26 }, 26 },
27 headlinePassword: { 27 headlinePassword: {
28 id: 'settings.account.headlinePassword', 28 id: 'settings.account.headlinePassword',
29 defaultMessage: '!!!Change Password', 29 defaultMessage: 'Change Password',
30 }, 30 },
31 successInfo: { 31 successInfo: {
32 id: 'settings.account.successInfo', 32 id: 'settings.account.successInfo',
33 defaultMessage: '!!!Your changes have been saved', 33 defaultMessage: 'Your changes have been saved',
34 }, 34 },
35 buttonSave: { 35 buttonSave: {
36 id: 'settings.account.buttonSave', 36 id: 'settings.account.buttonSave',
37 defaultMessage: '!!!Update profile', 37 defaultMessage: 'Update profile',
38 }, 38 },
39}); 39});
40 40
41export default @observer class EditUserForm extends Component { 41@observer
42class EditUserForm extends Component {
42 static propTypes = { 43 static propTypes = {
43 status: MobxPropTypes.observableArray.isRequired, 44 status: MobxPropTypes.observableArray.isRequired,
44 form: PropTypes.instanceOf(Form).isRequired, 45 form: PropTypes.instanceOf(Form).isRequired,
@@ -46,14 +47,10 @@ export default @observer class EditUserForm extends Component {
46 isSaving: PropTypes.bool.isRequired, 47 isSaving: PropTypes.bool.isRequired,
47 }; 48 };
48 49
49 static contextTypes = {
50 intl: intlShape,
51 };
52
53 submit(e) { 50 submit(e) {
54 e.preventDefault(); 51 e.preventDefault();
55 this.props.form.submit({ 52 this.props.form.submit({
56 onSuccess: (form) => { 53 onSuccess: form => {
57 const values = form.values(); 54 const values = form.values();
58 this.props.onSubmit(values); 55 this.props.onSubmit(values);
59 }, 56 },
@@ -68,7 +65,7 @@ export default @observer class EditUserForm extends Component {
68 form, 65 form,
69 isSaving, 66 isSaving,
70 } = this.props; 67 } = this.props;
71 const { intl } = this.context; 68 const { intl } = this.props;
72 69
73 return ( 70 return (
74 <div className="settings__main"> 71 <div className="settings__main">
@@ -84,12 +81,9 @@ export default @observer class EditUserForm extends Component {
84 </span> 81 </span>
85 </div> 82 </div>
86 <div className="settings__body"> 83 <div className="settings__body">
87 <form onSubmit={(e) => this.submit(e)} id="form"> 84 <form onSubmit={e => this.submit(e)} id="form">
88 {status.length > 0 && status.includes('data-updated') && ( 85 {status.length > 0 && status.includes('data-updated') && (
89 <Infobox 86 <Infobox type="success" icon="checkbox-marked-circle-outline">
90 type="success"
91 icon="checkbox-marked-circle-outline"
92 >
93 {intl.formatMessage(messages.successInfo)} 87 {intl.formatMessage(messages.successInfo)}
94 </Infobox> 88 </Infobox>
95 )} 89 )}
@@ -104,10 +98,7 @@ export default @observer class EditUserForm extends Component {
104 <Input field={form.$('organization')} /> 98 <Input field={form.$('organization')} />
105 )} 99 )}
106 <h2>{intl.formatMessage(messages.headlinePassword)}</h2> 100 <h2>{intl.formatMessage(messages.headlinePassword)}</h2>
107 <Input 101 <Input {...form.$('oldPassword').bind()} showPasswordToggle />
108 {...form.$('oldPassword').bind()}
109 showPasswordToggle
110 />
111 <Input 102 <Input
112 {...form.$('newPassword').bind()} 103 {...form.$('newPassword').bind()}
113 showPasswordToggle 104 showPasswordToggle
@@ -137,3 +128,5 @@ export default @observer class EditUserForm extends Component {
137 ); 128 );
138 } 129 }
139} 130}
131
132export default injectIntl(EditUserForm);
diff --git a/src/components/ui/AppLoader/index.js b/src/components/ui/AppLoader/index.js
index bbfd5de28..fa4a719ab 100644
--- a/src/components/ui/AppLoader/index.js
+++ b/src/components/ui/AppLoader/index.js
@@ -19,7 +19,9 @@ const textList = shuffleArray([
19 'Fixing bugs', 19 'Fixing bugs',
20]); 20]);
21 21
22export default @injectSheet(styles) @withTheme class AppLoader extends Component { 22@injectSheet(styles)
23@withTheme
24class AppLoader extends Component {
23 static propTypes = { 25 static propTypes = {
24 classes: PropTypes.object.isRequired, 26 classes: PropTypes.object.isRequired,
25 theme: PropTypes.object.isRequired, 27 theme: PropTypes.object.isRequired,
@@ -28,7 +30,7 @@ export default @injectSheet(styles) @withTheme class AppLoader extends Component
28 30
29 static defaultProps = { 31 static defaultProps = {
30 texts: textList, 32 texts: textList,
31 } 33 };
32 34
33 state = { 35 state = {
34 step: 0, 36 step: 0,
@@ -38,7 +40,7 @@ export default @injectSheet(styles) @withTheme class AppLoader extends Component
38 40
39 componentDidMount() { 41 componentDidMount() {
40 this.interval = setInterval(() => { 42 this.interval = setInterval(() => {
41 this.setState((prevState) => ({ 43 this.setState(prevState => ({
42 step: prevState.step === textList.length - 1 ? 0 : prevState.step + 1, 44 step: prevState.step === textList.length - 1 ? 0 : prevState.step + 1,
43 })); 45 }));
44 }, 2500); 46 }, 2500);
@@ -73,3 +75,5 @@ export default @injectSheet(styles) @withTheme class AppLoader extends Component
73 ); 75 );
74 } 76 }
75} 77}
78
79export default AppLoader;
diff --git a/src/components/ui/Button.js b/src/components/ui/Button.js
index 5066b9c06..f6c9fd3d3 100644
--- a/src/components/ui/Button.js
+++ b/src/components/ui/Button.js
@@ -4,7 +4,9 @@ import { observer, inject } from 'mobx-react';
4import Loader from 'react-loader'; 4import Loader from 'react-loader';
5import classnames from 'classnames'; 5import classnames from 'classnames';
6 6
7export default @inject('stores') @observer class Button extends Component { 7@inject('stores')
8@observer
9class Button extends Component {
8 static propTypes = { 10 static propTypes = {
9 className: PropTypes.string, 11 className: PropTypes.string,
10 label: PropTypes.string.isRequired, 12 label: PropTypes.string.isRequired,
@@ -26,7 +28,7 @@ export default @inject('stores') @observer class Button extends Component {
26 static defaultProps = { 28 static defaultProps = {
27 className: null, 29 className: null,
28 disabled: false, 30 disabled: false,
29 onClick: () => { }, 31 onClick: () => {},
30 type: 'button', 32 type: 'button',
31 buttonType: '', 33 buttonType: '',
32 loaded: true, 34 loaded: true,
@@ -76,7 +78,11 @@ export default @inject('stores') @observer class Button extends Component {
76 loaded={loaded} 78 loaded={loaded}
77 lines={10} 79 lines={10}
78 scale={0.4} 80 scale={0.4}
79 color={buttonType !== 'secondary' ? '#FFF' : this.props.stores.settings.app.accentColor} 81 color={
82 buttonType !== 'secondary'
83 ? '#FFF'
84 : this.props.stores.settings.app.accentColor
85 }
80 component="span" 86 component="span"
81 /> 87 />
82 {label} 88 {label}
@@ -85,3 +91,5 @@ export default @inject('stores') @observer class Button extends Component {
85 ); 91 );
86 } 92 }
87} 93}
94
95export default Button;
diff --git a/src/components/ui/FAB.js b/src/components/ui/FAB.js
index 633edbe2c..a3aa06bc9 100644
--- a/src/components/ui/FAB.js
+++ b/src/components/ui/FAB.js
@@ -8,7 +8,8 @@ import classnames from 'classnames';
8 8
9import { oneOrManyChildElements } from '../../prop-types'; 9import { oneOrManyChildElements } from '../../prop-types';
10 10
11export default @observer class Button extends Component { 11@observer
12class Button extends Component {
12 static propTypes = { 13 static propTypes = {
13 className: PropTypes.string, 14 className: PropTypes.string,
14 disabled: PropTypes.bool, 15 disabled: PropTypes.bool,
@@ -21,7 +22,7 @@ export default @observer class Button extends Component {
21 static defaultProps = { 22 static defaultProps = {
22 className: null, 23 className: null,
23 disabled: false, 24 disabled: false,
24 onClick: () => { }, 25 onClick: () => {},
25 type: 'button', 26 type: 'button',
26 htmlForm: '', 27 htmlForm: '',
27 }; 28 };
@@ -29,14 +30,8 @@ export default @observer class Button extends Component {
29 element = null; 30 element = null;
30 31
31 render() { 32 render() {
32 const { 33 const { className, disabled, onClick, type, children, htmlForm } =
33 className, 34 this.props;
34 disabled,
35 onClick,
36 type,
37 children,
38 htmlForm,
39 } = this.props;
40 35
41 const buttonProps = { 36 const buttonProps = {
42 className: classnames({ 37 className: classnames({
@@ -66,3 +61,5 @@ export default @observer class Button extends Component {
66 ); 61 );
67 } 62 }
68} 63}
64
65export default Button;
diff --git a/src/components/ui/FeatureList.js b/src/components/ui/FeatureList.js
index cf2664830..14e7ec3c4 100644
--- a/src/components/ui/FeatureList.js
+++ b/src/components/ui/FeatureList.js
@@ -1,53 +1,53 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { defineMessages, intlShape } from 'react-intl'; 3import { defineMessages, injectIntl } from 'react-intl';
4 4
5import { FeatureItem } from './FeatureItem'; 5import { FeatureItem } from './FeatureItem';
6 6
7const messages = defineMessages({ 7const messages = defineMessages({
8 availableRecipes: { 8 availableRecipes: {
9 id: 'pricing.features.recipes', 9 id: 'pricing.features.recipes',
10 defaultMessage: '!!!Choose from more than 70 Services', // TODO: Make this dynamic 10 defaultMessage: 'Choose from more than 70 Services', // TODO: Make this dynamic
11 }, 11 },
12 accountSync: { 12 accountSync: {
13 id: 'pricing.features.accountSync', 13 id: 'pricing.features.accountSync',
14 defaultMessage: '!!!Account Synchronisation', 14 defaultMessage: 'Account Synchronisation',
15 }, 15 },
16 desktopNotifications: { 16 desktopNotifications: {
17 id: 'pricing.features.desktopNotifications', 17 id: 'pricing.features.desktopNotifications',
18 defaultMessage: '!!!Desktop Notifications', 18 defaultMessage: 'Desktop Notifications',
19 }, 19 },
20 unlimitedServices: { 20 unlimitedServices: {
21 id: 'pricing.features.unlimitedServices', 21 id: 'pricing.features.unlimitedServices',
22 defaultMessage: '!!!Add unlimited services', 22 defaultMessage: 'Add unlimited services',
23 }, 23 },
24 spellchecker: { 24 spellchecker: {
25 id: 'pricing.features.spellchecker', 25 id: 'pricing.features.spellchecker',
26 defaultMessage: '!!!Spellchecker support', 26 defaultMessage: 'Spellchecker support',
27 }, 27 },
28 workspaces: { 28 workspaces: {
29 id: 'pricing.features.workspaces', 29 id: 'pricing.features.workspaces',
30 defaultMessage: '!!!Workspaces', 30 defaultMessage: 'Workspaces',
31 }, 31 },
32 customWebsites: { 32 customWebsites: {
33 id: 'pricing.features.customWebsites', 33 id: 'pricing.features.customWebsites',
34 defaultMessage: '!!!Add Custom Websites', 34 defaultMessage: 'Add Custom Websites',
35 }, 35 },
36 onPremise: { 36 onPremise: {
37 id: 'pricing.features.onPremise', 37 id: 'pricing.features.onPremise',
38 defaultMessage: '!!!On-premise & other Hosted Services', 38 defaultMessage: 'On-premise & other Hosted Services',
39 }, 39 },
40 thirdPartyServices: { 40 thirdPartyServices: {
41 id: 'pricing.features.thirdPartyServices', 41 id: 'pricing.features.thirdPartyServices',
42 defaultMessage: '!!!Install 3rd party services', 42 defaultMessage: 'Install 3rd party services',
43 }, 43 },
44 serviceProxies: { 44 serviceProxies: {
45 id: 'pricing.features.serviceProxies', 45 id: 'pricing.features.serviceProxies',
46 defaultMessage: '!!!Service Proxies', 46 defaultMessage: 'Service Proxies',
47 }, 47 },
48 teamManagement: { 48 teamManagement: {
49 id: 'pricing.features.teamManagement', 49 id: 'pricing.features.teamManagement',
50 defaultMessage: '!!!Team Management', 50 defaultMessage: 'Team Management',
51 }, 51 },
52}); 52});
53 53
@@ -60,18 +60,11 @@ export class FeatureList extends Component {
60 static defaultProps = { 60 static defaultProps = {
61 className: '', 61 className: '',
62 featureClassName: '', 62 featureClassName: '',
63 }
64
65 static contextTypes = {
66 intl: intlShape,
67 }; 63 };
68 64
69 render() { 65 render() {
70 const { 66 const { className, featureClassName } = this.props;
71 className, 67 const { intl } = this.props;
72 featureClassName,
73 } = this.props;
74 const { intl } = this.context;
75 68
76 const features = [ 69 const features = [
77 messages.availableRecipes, 70 messages.availableRecipes,
@@ -92,10 +85,15 @@ export class FeatureList extends Component {
92 85
93 return ( 86 return (
94 <ul className={className}> 87 <ul className={className}>
95 {features.map((feature) => <FeatureItem name={intl.formatMessage(feature)} className={featureClassName} />)} 88 {features.map(feature => (
89 <FeatureItem
90 name={intl.formatMessage(feature)}
91 className={featureClassName}
92 />
93 ))}
96 </ul> 94 </ul>
97 ); 95 );
98 } 96 }
99} 97}
100 98
101export default FeatureList; 99export default injectIntl(FeatureList);
diff --git a/src/components/ui/FullscreenLoader/index.js b/src/components/ui/FullscreenLoader/index.js
index 2952cd96b..ab5e2f365 100644
--- a/src/components/ui/FullscreenLoader/index.js
+++ b/src/components/ui/FullscreenLoader/index.js
@@ -8,7 +8,10 @@ import Loader from '../Loader';
8 8
9import styles from './styles'; 9import styles from './styles';
10 10
11export default @withTheme @injectSheet(styles) @observer class FullscreenLoader extends Component { 11@withTheme
12@injectSheet(styles)
13@observer
14class FullscreenLoader extends Component {
12 static propTypes = { 15 static propTypes = {
13 className: PropTypes.string, 16 className: PropTypes.string,
14 title: PropTypes.string.isRequired, 17 title: PropTypes.string.isRequired,
@@ -25,14 +28,8 @@ export default @withTheme @injectSheet(styles) @observer class FullscreenLoader
25 }; 28 };
26 29
27 render() { 30 render() {
28 const { 31 const { classes, title, children, spinnerColor, className, theme } =
29 classes, 32 this.props;
30 title,
31 children,
32 spinnerColor,
33 className,
34 theme,
35 } = this.props;
36 33
37 return ( 34 return (
38 <div className={classes.wrapper}> 35 <div className={classes.wrapper}>
@@ -44,13 +41,11 @@ export default @withTheme @injectSheet(styles) @observer class FullscreenLoader
44 > 41 >
45 <h1 className={classes.title}>{title}</h1> 42 <h1 className={classes.title}>{title}</h1>
46 <Loader color={spinnerColor || theme.colorFullscreenLoaderSpinner} /> 43 <Loader color={spinnerColor || theme.colorFullscreenLoaderSpinner} />
47 {children && ( 44 {children && <div className={classes.content}>{children}</div>}
48 <div className={classes.content}>
49 {children}
50 </div>
51 )}
52 </div> 45 </div>
53 </div> 46 </div>
54 ); 47 );
55 } 48 }
56} 49}
50
51export default FullscreenLoader;
diff --git a/src/components/ui/ImageUpload.js b/src/components/ui/ImageUpload.js
index bb4ea0565..8ea31ca40 100644
--- a/src/components/ui/ImageUpload.js
+++ b/src/components/ui/ImageUpload.js
@@ -6,7 +6,8 @@ import classnames from 'classnames';
6import Dropzone from 'react-dropzone'; 6import Dropzone from 'react-dropzone';
7import { isWindows } from '../../environment'; 7import { isWindows } from '../../environment';
8 8
9export default @observer class ImageUpload extends Component { 9@observer
10class ImageUpload extends Component {
10 static propTypes = { 11 static propTypes = {
11 field: PropTypes.instanceOf(Field).isRequired, 12 field: PropTypes.instanceOf(Field).isRequired,
12 className: PropTypes.string, 13 className: PropTypes.string,
@@ -29,7 +30,7 @@ export default @observer class ImageUpload extends Component {
29 onDrop(acceptedFiles) { 30 onDrop(acceptedFiles) {
30 const { field } = this.props; 31 const { field } = this.props;
31 32
32 acceptedFiles.forEach((file) => { 33 acceptedFiles.forEach(file => {
33 const imgPath = isWindows ? file.path.replace(/\\/g, '/') : file.path; 34 const imgPath = isWindows ? file.path.replace(/\\/g, '/') : file.path;
34 this.setState({ 35 this.setState({
35 path: imgPath, 36 path: imgPath,
@@ -42,9 +43,7 @@ export default @observer class ImageUpload extends Component {
42 } 43 }
43 44
44 render() { 45 render() {
45 const { 46 const { field, className, multiple, textDelete, textUpload } = this.props;
46 field, className, multiple, textDelete, textUpload,
47 } = this.props;
48 47
49 const cssClasses = classnames({ 48 const cssClasses = classnames({
50 'image-upload__dropzone': true, 49 'image-upload__dropzone': true,
@@ -86,7 +85,7 @@ export default @observer class ImageUpload extends Component {
86 </> 85 </>
87 ) : ( 86 ) : (
88 <Dropzone 87 <Dropzone
89 ref={(node) => { 88 ref={node => {
90 this.dropzoneRef = node; 89 this.dropzoneRef = node;
91 }} 90 }}
92 onDrop={this.onDrop.bind(this)} 91 onDrop={this.onDrop.bind(this)}
@@ -107,3 +106,5 @@ export default @observer class ImageUpload extends Component {
107 ); 106 );
108 } 107 }
109} 108}
109
110export default ImageUpload;
diff --git a/src/components/ui/InfoBar.js b/src/components/ui/InfoBar.js
index bd2af2296..f5cbad48b 100644
--- a/src/components/ui/InfoBar.js
+++ b/src/components/ui/InfoBar.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5import Loader from 'react-loader'; 5import Loader from 'react-loader';
6import { defineMessages, intlShape } from 'react-intl'; 6import { defineMessages, injectIntl } from 'react-intl';
7 7
8// import { oneOrManyChildElements } from '../../prop-types'; 8// import { oneOrManyChildElements } from '../../prop-types';
9import Appear from './effects/Appear'; 9import Appear from './effects/Appear';
@@ -11,11 +11,10 @@ import Appear from './effects/Appear';
11const messages = defineMessages({ 11const messages = defineMessages({
12 hide: { 12 hide: {
13 id: 'infobar.hide', 13 id: 'infobar.hide',
14 defaultMessage: '!!!Hide', 14 defaultMessage: 'Hide',
15 }, 15 },
16}); 16});
17 17
18export default
19@observer 18@observer
20class InfoBar extends Component { 19class InfoBar extends Component {
21 static propTypes = { 20 static propTypes = {
@@ -42,10 +41,6 @@ class InfoBar extends Component {
42 onHide: () => null, 41 onHide: () => null,
43 }; 42 };
44 43
45 static contextTypes = {
46 intl: intlShape,
47 };
48
49 render() { 44 render() {
50 const { 45 const {
51 children, 46 children,
@@ -59,7 +54,7 @@ class InfoBar extends Component {
59 onHide, 54 onHide,
60 } = this.props; 55 } = this.props;
61 56
62 const { intl } = this.context; 57 const { intl } = this.props;
63 58
64 let transitionName = 'slideUp'; 59 let transitionName = 'slideUp';
65 if (position === 'top') { 60 if (position === 'top') {
@@ -103,3 +98,5 @@ class InfoBar extends Component {
103 ); 98 );
104 } 99 }
105} 100}
101
102export default injectIntl(InfoBar);
diff --git a/src/components/ui/Infobox.js b/src/components/ui/Infobox.js
index 73b48b957..13ae2303b 100644
--- a/src/components/ui/Infobox.js
+++ b/src/components/ui/Infobox.js
@@ -3,16 +3,15 @@ import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5import Loader from 'react-loader'; 5import Loader from 'react-loader';
6import { defineMessages, intlShape } from 'react-intl'; 6import { defineMessages, injectIntl } from 'react-intl';
7 7
8const messages = defineMessages({ 8const messages = defineMessages({
9 dismiss: { 9 dismiss: {
10 id: 'infobox.dismiss', 10 id: 'infobox.dismiss',
11 defaultMessage: '!!!Dismiss', 11 defaultMessage: 'Dismiss',
12 }, 12 },
13}); 13});
14 14
15export default
16@observer 15@observer
17class Infobox extends Component { 16class Infobox extends Component {
18 static propTypes = { 17 static propTypes = {
@@ -38,10 +37,6 @@ class Infobox extends Component {
38 onSeen: () => null, 37 onSeen: () => null,
39 }; 38 };
40 39
41 static contextTypes = {
42 intl: intlShape,
43 };
44
45 state = { 40 state = {
46 dismissed: false, 41 dismissed: false,
47 }; 42 };
@@ -63,7 +58,7 @@ class Infobox extends Component {
63 onDismiss, 58 onDismiss,
64 } = this.props; 59 } = this.props;
65 60
66 const { intl } = this.context; 61 const { intl } = this.props;
67 62
68 if (this.state.dismissed) { 63 if (this.state.dismissed) {
69 return null; 64 return null;
@@ -106,3 +101,5 @@ class Infobox extends Component {
106 ); 101 );
107 } 102 }
108} 103}
104
105export default injectIntl(Infobox);
diff --git a/src/components/ui/Input.js b/src/components/ui/Input.js
index 7417fef1c..335367f03 100644
--- a/src/components/ui/Input.js
+++ b/src/components/ui/Input.js
@@ -3,18 +3,17 @@ import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { Field } from 'mobx-react-form'; 4import { Field } from 'mobx-react-form';
5import classnames from 'classnames'; 5import classnames from 'classnames';
6import { defineMessages, intlShape } from 'react-intl'; 6import { defineMessages, injectIntl } from 'react-intl';
7 7
8import { scorePassword as scorePasswordFunc } from '../../helpers/password-helpers'; 8import { scorePassword as scorePasswordFunc } from '../../helpers/password-helpers';
9 9
10const messages = defineMessages({ 10const messages = defineMessages({
11 passwordToggle: { 11 passwordToggle: {
12 id: 'settings.app.form.passwordToggle', 12 id: 'settings.app.form.passwordToggle',
13 defaultMessage: '!!!Password toggle', 13 defaultMessage: 'Password toggle',
14 }, 14 },
15}); 15});
16 16
17export default
18@observer 17@observer
19class Input extends Component { 18class Input extends Component {
20 static propTypes = { 19 static propTypes = {
@@ -38,10 +37,6 @@ class Input extends Component {
38 suffix: '', 37 suffix: '',
39 }; 38 };
40 39
41 static contextTypes = {
42 intl: intlShape,
43 };
44
45 state = { 40 state = {
46 showPassword: false, 41 showPassword: false,
47 passwordScore: 0, 42 passwordScore: 0,
@@ -82,7 +77,7 @@ class Input extends Component {
82 77
83 const { passwordScore } = this.state; 78 const { passwordScore } = this.state;
84 79
85 const { intl } = this.context; 80 const { intl } = this.props;
86 81
87 let { type } = field; 82 let { type } = field;
88 if (type === 'password' && this.state.showPassword) { 83 if (type === 'password' && this.state.showPassword) {
@@ -106,10 +101,10 @@ class Input extends Component {
106 name={field.name} 101 name={field.name}
107 value={field.value} 102 value={field.value}
108 placeholder={field.placeholder} 103 placeholder={field.placeholder}
109 onChange={(e) => this.onChange(e)} 104 onChange={e => this.onChange(e)}
110 onBlur={field.onBlur} 105 onBlur={field.onBlur}
111 onFocus={field.onFocus} 106 onFocus={field.onFocus}
112 ref={(element) => { 107 ref={element => {
113 this.inputElement = element; 108 this.inputElement = element;
114 }} 109 }}
115 disabled={field.disabled} 110 disabled={field.disabled}
@@ -124,9 +119,11 @@ class Input extends Component {
124 'mdi-eye': !this.state.showPassword, 119 'mdi-eye': !this.state.showPassword,
125 'mdi-eye-off': this.state.showPassword, 120 'mdi-eye-off': this.state.showPassword,
126 })} 121 })}
127 onClick={() => this.setState((prevState) => ({ 122 onClick={() =>
128 showPassword: !prevState.showPassword, 123 this.setState(prevState => ({
129 }))} 124 showPassword: !prevState.showPassword,
125 }))
126 }
130 tabIndex={-1} 127 tabIndex={-1}
131 aria-label={intl.formatMessage(messages.passwordToggle)} 128 aria-label={intl.formatMessage(messages.passwordToggle)}
132 /> 129 />
@@ -154,3 +151,5 @@ class Input extends Component {
154 ); 151 );
155 } 152 }
156} 153}
154
155export default injectIntl(Input);
diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js
index 003211e5c..94db3f842 100644
--- a/src/components/ui/Link.js
+++ b/src/components/ui/Link.js
@@ -9,7 +9,9 @@ import { matchRoute } from '../../helpers/routing-helpers';
9import { openExternalUrl } from '../../helpers/url-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 { 12@inject('stores')
13@observer
14class Link extends Component {
13 onClick(e) { 15 onClick(e) {
14 if (this.props.disabled) { 16 if (this.props.disabled) {
15 e.preventDefault(); 17 e.preventDefault();
@@ -50,7 +52,7 @@ export default @inject('stores') @observer class Link extends Component {
50 href={router.history.createHref(to)} 52 href={router.history.createHref(to)}
51 className={linkClasses} 53 className={linkClasses}
52 style={style} 54 style={style}
53 onClick={(e) => this.onClick(e)} 55 onClick={e => this.onClick(e)}
54 > 56 >
55 {children} 57 {children}
56 </a> 58 </a>
@@ -62,10 +64,8 @@ Link.wrappedComponent.propTypes = {
62 stores: PropTypes.shape({ 64 stores: PropTypes.shape({
63 router: PropTypes.instanceOf(RouterStore).isRequired, 65 router: PropTypes.instanceOf(RouterStore).isRequired,
64 }).isRequired, 66 }).isRequired,
65 children: PropTypes.oneOfType([ 67 children: PropTypes.oneOfType([oneOrManyChildElements, PropTypes.string])
66 oneOrManyChildElements, 68 .isRequired,
67 PropTypes.string,
68 ]).isRequired,
69 to: PropTypes.string.isRequired, 69 to: PropTypes.string.isRequired,
70 className: PropTypes.string, 70 className: PropTypes.string,
71 activeClassName: PropTypes.string, 71 activeClassName: PropTypes.string,
@@ -83,3 +83,5 @@ Link.wrappedComponent.defaultProps = {
83 target: '', 83 target: '',
84 style: {}, 84 style: {},
85}; 85};
86
87export default Link;
diff --git a/src/components/ui/Loader.js b/src/components/ui/Loader.js
index 4d7113aa1..46c1390bf 100644
--- a/src/components/ui/Loader.js
+++ b/src/components/ui/Loader.js
@@ -5,7 +5,9 @@ import Loader from 'react-loader';
5 5
6import { oneOrManyChildElements } from '../../prop-types'; 6import { oneOrManyChildElements } from '../../prop-types';
7 7
8export default @inject('stores') @observer class LoaderComponent extends Component { 8@inject('stores')
9@observer
10class LoaderComponent extends Component {
9 static propTypes = { 11 static propTypes = {
10 children: oneOrManyChildElements, 12 children: oneOrManyChildElements,
11 loaded: PropTypes.bool, 13 loaded: PropTypes.bool,
@@ -28,13 +30,12 @@ export default @inject('stores') @observer class LoaderComponent extends Compone
28 }; 30 };
29 31
30 render() { 32 render() {
31 const { 33 const { children, loaded, className } = this.props;
32 children,
33 loaded,
34 className,
35 } = this.props;
36 34
37 const color = this.props.color !== 'ACCENT' ? this.props.color : this.props.stores.settings.app.accentColor; 35 const color =
36 this.props.color !== 'ACCENT'
37 ? this.props.color
38 : this.props.stores.settings.app.accentColor;
38 39
39 return ( 40 return (
40 <Loader 41 <Loader
@@ -51,3 +52,5 @@ export default @inject('stores') @observer class LoaderComponent extends Compone
51 ); 52 );
52 } 53 }
53} 54}
55
56export default LoaderComponent;
diff --git a/src/components/ui/Modal/index.js b/src/components/ui/Modal/index.js
index a9fa0cd1b..9e6830b0c 100644
--- a/src/components/ui/Modal/index.js
+++ b/src/components/ui/Modal/index.js
@@ -10,7 +10,8 @@ import styles from './styles';
10 10
11// ReactModal.setAppElement('#root'); 11// ReactModal.setAppElement('#root');
12 12
13export default @injectCSS(styles) class Modal extends Component { 13@injectCSS(styles)
14class Modal extends Component {
14 static propTypes = { 15 static propTypes = {
15 children: PropTypes.node.isRequired, 16 children: PropTypes.node.isRequired,
16 className: PropTypes.string, 17 className: PropTypes.string,
@@ -20,14 +21,14 @@ export default @injectCSS(styles) class Modal extends Component {
20 close: PropTypes.func.isRequired, 21 close: PropTypes.func.isRequired,
21 shouldCloseOnOverlayClick: PropTypes.bool, 22 shouldCloseOnOverlayClick: PropTypes.bool,
22 showClose: PropTypes.bool, 23 showClose: PropTypes.bool,
23 } 24 };
24 25
25 static defaultProps = { 26 static defaultProps = {
26 className: null, 27 className: null,
27 portal: 'modal-portal', 28 portal: 'modal-portal',
28 shouldCloseOnOverlayClick: false, 29 shouldCloseOnOverlayClick: false,
29 showClose: true, 30 showClose: true,
30 } 31 };
31 32
32 render() { 33 render() {
33 const { 34 const {
@@ -56,18 +57,14 @@ export default @injectCSS(styles) class Modal extends Component {
56 appElement={document.getElementById('root')} 57 appElement={document.getElementById('root')}
57 > 58 >
58 {showClose && close && ( 59 {showClose && close && (
59 <button 60 <button type="button" className={classes.close} onClick={close}>
60 type="button"
61 className={classes.close}
62 onClick={close}
63 >
64 <Icon icon={mdiClose} size={1.5} /> 61 <Icon icon={mdiClose} size={1.5} />
65 </button> 62 </button>
66 )} 63 )}
67 <div className={classes.content}> 64 <div className={classes.content}>{children}</div>
68 {children}
69 </div>
70 </ReactModal> 65 </ReactModal>
71 ); 66 );
72 } 67 }
73} 68}
69
70export default Modal;
diff --git a/src/components/ui/Radio.js b/src/components/ui/Radio.js
index e77714eb7..65a777ff1 100644
--- a/src/components/ui/Radio.js
+++ b/src/components/ui/Radio.js
@@ -4,7 +4,8 @@ import { observer } from 'mobx-react';
4import { Field } from 'mobx-react-form'; 4import { Field } from 'mobx-react-form';
5import classnames from 'classnames'; 5import classnames from 'classnames';
6 6
7export default @observer class Radio extends Component { 7@observer
8class Radio extends Component {
8 static propTypes = { 9 static propTypes = {
9 field: PropTypes.instanceOf(Field).isRequired, 10 field: PropTypes.instanceOf(Field).isRequired,
10 className: PropTypes.string, 11 className: PropTypes.string,
@@ -31,11 +32,7 @@ export default @observer class Radio extends Component {
31 } 32 }
32 33
33 render() { 34 render() {
34 const { 35 const { field, className, showLabel } = this.props;
35 field,
36 className,
37 showLabel,
38 } = this.props;
39 36
40 return ( 37 return (
41 <div 38 <div
@@ -46,15 +43,12 @@ export default @observer class Radio extends Component {
46 })} 43 })}
47 > 44 >
48 {field.label && showLabel && ( 45 {field.label && showLabel && (
49 <label 46 <label className="franz-form__label" htmlFor={field.name}>
50 className="franz-form__label"
51 htmlFor={field.name}
52 >
53 {field.label} 47 {field.label}
54 </label> 48 </label>
55 )} 49 )}
56 <div className="franz-form__radio-wrapper"> 50 <div className="franz-form__radio-wrapper">
57 {field.options.map((type) => ( 51 {field.options.map(type => (
58 <label 52 <label
59 key={type.value} 53 key={type.value}
60 htmlFor={`${field.id}-${type.value}`} 54 htmlFor={`${field.id}-${type.value}`}
@@ -75,14 +69,10 @@ export default @observer class Radio extends Component {
75 </label> 69 </label>
76 ))} 70 ))}
77 </div> 71 </div>
78 {field.error && ( 72 {field.error && <div className="franz-form__error">{field.error}</div>}
79 <div
80 className="franz-form__error"
81 >
82 {field.error}
83 </div>
84 )}
85 </div> 73 </div>
86 ); 74 );
87 } 75 }
88} 76}
77
78export default Radio;
diff --git a/src/components/ui/SearchInput.js b/src/components/ui/SearchInput.js
index 0b25734dd..2d760beab 100644
--- a/src/components/ui/SearchInput.js
+++ b/src/components/ui/SearchInput.js
@@ -4,7 +4,8 @@ import { observer } from 'mobx-react';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5import { debounce } from 'lodash'; 5import { debounce } from 'lodash';
6 6
7export default @observer class SearchInput extends Component { 7@observer
8class SearchInput extends Component {
8 static propTypes = { 9 static propTypes = {
9 value: PropTypes.string, 10 value: PropTypes.string,
10 placeholder: PropTypes.string, 11 placeholder: PropTypes.string,
@@ -27,7 +28,7 @@ export default @observer class SearchInput extends Component {
27 onChange: () => null, 28 onChange: () => null,
28 onReset: () => null, 29 onReset: () => null,
29 autoFocus: false, 30 autoFocus: false,
30 } 31 };
31 32
32 input = null; 33 input = null;
33 34
@@ -38,7 +39,10 @@ export default @observer class SearchInput extends Component {
38 value: props.value, 39 value: props.value,
39 }; 40 };
40 41
41 this.throttledOnChange = debounce(this.throttledOnChange, this.props.throttleDelay); 42 this.throttledOnChange = debounce(
43 this.throttledOnChange,
44 this.props.throttleDelay,
45 );
42 } 46 }
43 47
44 componentDidMount() { 48 componentDidMount() {
@@ -80,24 +84,18 @@ export default @observer class SearchInput extends Component {
80 const { value } = this.state; 84 const { value } = this.state;
81 85
82 return ( 86 return (
83 <div 87 <div className={classnames([className, 'search-input'])}>
84 className={classnames([ 88 <label htmlFor={name} className="mdi mdi-magnify">
85 className,
86 'search-input',
87 ])}
88 >
89 <label
90 htmlFor={name}
91 className="mdi mdi-magnify"
92 >
93 <input 89 <input
94 name={name} 90 name={name}
95 id={name} 91 id={name}
96 type="text" 92 type="text"
97 placeholder={placeholder} 93 placeholder={placeholder}
98 value={value} 94 value={value}
99 onChange={(e) => this.onChange(e)} 95 onChange={e => this.onChange(e)}
100 ref={(ref) => { this.input = ref; }} 96 ref={ref => {
97 this.input = ref;
98 }}
101 /> 99 />
102 </label> 100 </label>
103 {value.length > 0 && ( 101 {value.length > 0 && (
@@ -110,3 +108,5 @@ export default @observer class SearchInput extends Component {
110 ); 108 );
111 } 109 }
112} 110}
111
112export default SearchInput;
diff --git a/src/components/ui/Select.js b/src/components/ui/Select.js
index e7a5eafa8..15b4c28e7 100644
--- a/src/components/ui/Select.js
+++ b/src/components/ui/Select.js
@@ -4,7 +4,8 @@ import { observer } from 'mobx-react';
4import { Field } from 'mobx-react-form'; 4import { Field } from 'mobx-react-form';
5import classnames from 'classnames'; 5import classnames from 'classnames';
6 6
7export default @observer class Select extends Component { 7@observer
8class Select extends Component {
8 static propTypes = { 9 static propTypes = {
9 field: PropTypes.instanceOf(Field).isRequired, 10 field: PropTypes.instanceOf(Field).isRequired,
10 className: PropTypes.string, 11 className: PropTypes.string,
@@ -43,13 +44,7 @@ export default @observer class Select extends Component {
43 } 44 }
44 45
45 render() { 46 render() {
46 const { 47 const { field, className, showLabel, disabled, multiple } = this.props;
47 field,
48 className,
49 showLabel,
50 disabled,
51 multiple,
52 } = this.props;
53 48
54 let selected = field.value; 49 let selected = field.value;
55 50
@@ -74,15 +69,12 @@ export default @observer class Select extends Component {
74 })} 69 })}
75 > 70 >
76 {field.label && showLabel && ( 71 {field.label && showLabel && (
77 <label 72 <label className="franz-form__label" htmlFor={field.name}>
78 className="franz-form__label"
79 htmlFor={field.name}
80 >
81 {field.label} 73 {field.label}
82 </label> 74 </label>
83 )} 75 )}
84 <select 76 <select
85 onChange={multiple ? (e) => this.multipleChange(e) : field.onChange} 77 onChange={multiple ? e => this.multipleChange(e) : field.onChange}
86 id={field.id} 78 id={field.id}
87 defaultValue={selected} 79 defaultValue={selected}
88 className="franz-form__select" 80 className="franz-form__select"
@@ -90,7 +82,7 @@ export default @observer class Select extends Component {
90 multiple={multiple} 82 multiple={multiple}
91 ref={this.element} 83 ref={this.element}
92 > 84 >
93 {field.options.map((type) => ( 85 {field.options.map(type => (
94 <option 86 <option
95 key={type.value} 87 key={type.value}
96 value={type.value} 88 value={type.value}
@@ -100,14 +92,10 @@ export default @observer class Select extends Component {
100 </option> 92 </option>
101 ))} 93 ))}
102 </select> 94 </select>
103 {field.error && ( 95 {field.error && <div className="franz-form__error">{field.error}</div>}
104 <div
105 className="franz-form__error"
106 >
107 {field.error}
108 </div>
109 )}
110 </div> 96 </div>
111 ); 97 );
112 } 98 }
113} 99}
100
101export default Select;
diff --git a/src/components/ui/Slider.js b/src/components/ui/Slider.js
index f344449a0..6f17eae00 100644
--- a/src/components/ui/Slider.js
+++ b/src/components/ui/Slider.js
@@ -4,62 +4,64 @@ import { observer } from 'mobx-react';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5import { Field } from 'mobx-react-form'; 5import { Field } from 'mobx-react-form';
6 6
7export default @observer class Slider extends Component { 7@observer
8 static propTypes = { 8class Slider extends Component {
9 field: PropTypes.instanceOf(Field).isRequired, 9 static propTypes = {
10 className: PropTypes.string, 10 field: PropTypes.instanceOf(Field).isRequired,
11 showLabel: PropTypes.bool, 11 className: PropTypes.string,
12 disabled: PropTypes.bool, 12 showLabel: PropTypes.bool,
13 }; 13 disabled: PropTypes.bool,
14 };
14 15
15 static defaultProps = { 16 static defaultProps = {
16 className: '', 17 className: '',
17 showLabel: true, 18 showLabel: true,
18 disabled: false, 19 disabled: false,
19 }; 20 };
20 21
21 onChange(e) { 22 onChange(e) {
22 const { field } = this.props; 23 const { field } = this.props;
23 24
24 field.onChange(e); 25 field.onChange(e);
25 } 26 }
26
27 render() {
28 const {
29 field,
30 className,
31 showLabel,
32 disabled,
33 } = this.props;
34 27
35 if (field.value === '' && field.default !== '') { 28 render() {
36 field.value = field.default; 29 const { field, className, showLabel, disabled } = this.props;
37 }
38 30
39 return ( 31 if (field.value === '' && field.default !== '') {
40 <div 32 field.value = field.default;
41 className={classnames([ 33 }
42 'franz-form__field',
43 'franz-form__slider-wrapper',
44 className,
45 ])}
46 >
47 <div className="slider-container">
48 <input
49 className="slider"
50 type="range"
51 id={field.id}
52 name={field.name}
53 value={field.value}
54 min="1"
55 max="100"
56 onChange={(e) => (!disabled ? this.onChange(e) : null)}
57 />
58 </div>
59 34
60 {field.error && <div className={field.error}>{field.error}</div>} 35 return (
61 {field.label && showLabel && <label className="franz-form__label" htmlFor={field.id}>{field.label}</label>} 36 <div
37 className={classnames([
38 'franz-form__field',
39 'franz-form__slider-wrapper',
40 className,
41 ])}
42 >
43 <div className="slider-container">
44 <input
45 className="slider"
46 type="range"
47 id={field.id}
48 name={field.name}
49 value={field.value}
50 min="1"
51 max="100"
52 onChange={e => (!disabled ? this.onChange(e) : null)}
53 />
62 </div> 54 </div>
63 ); 55
64 } 56 {field.error && <div className={field.error}>{field.error}</div>}
57 {field.label && showLabel && (
58 <label className="franz-form__label" htmlFor={field.id}>
59 {field.label}
60 </label>
61 )}
62 </div>
63 );
64 }
65} 65}
66
67export default Slider;
diff --git a/src/components/ui/StatusBarTargetUrl.js b/src/components/ui/StatusBarTargetUrl.js
index 6fc50fe5c..ff4e8c795 100644
--- a/src/components/ui/StatusBarTargetUrl.js
+++ b/src/components/ui/StatusBarTargetUrl.js
@@ -5,7 +5,8 @@ import classnames from 'classnames';
5 5
6import Appear from './effects/Appear'; 6import Appear from './effects/Appear';
7 7
8export default @observer class StatusBarTargetUrl extends Component { 8@observer
9class StatusBarTargetUrl extends Component {
9 static propTypes = { 10 static propTypes = {
10 className: PropTypes.string, 11 className: PropTypes.string,
11 text: PropTypes.string, 12 text: PropTypes.string,
@@ -17,10 +18,7 @@ export default @observer class StatusBarTargetUrl extends Component {
17 }; 18 };
18 19
19 render() { 20 render() {
20 const { 21 const { className, text } = this.props;
21 className,
22 text,
23 } = this.props;
24 22
25 return ( 23 return (
26 <Appear 24 <Appear
@@ -29,10 +27,10 @@ export default @observer class StatusBarTargetUrl extends Component {
29 [`${className}`]: true, 27 [`${className}`]: true,
30 })} 28 })}
31 > 29 >
32 <div className="status-bar-target-url__content"> 30 <div className="status-bar-target-url__content">{text}</div>
33 {text}
34 </div>
35 </Appear> 31 </Appear>
36 ); 32 );
37 } 33 }
38} 34}
35
36export default StatusBarTargetUrl;
diff --git a/src/components/ui/Tabs/Tabs.js b/src/components/ui/Tabs/Tabs.js
index 56c76f215..195398708 100644
--- a/src/components/ui/Tabs/Tabs.js
+++ b/src/components/ui/Tabs/Tabs.js
@@ -5,7 +5,6 @@ import classnames from 'classnames';
5 5
6import { oneOrManyChildElements } from '../../../prop-types'; 6import { oneOrManyChildElements } from '../../../prop-types';
7 7
8export default
9@observer 8@observer
10class Tab extends Component { 9class Tab extends Component {
11 constructor(props) { 10 constructor(props) {
@@ -28,7 +27,7 @@ class Tab extends Component {
28 27
29 render() { 28 render() {
30 const { children: childElements } = this.props; 29 const { children: childElements } = this.props;
31 const children = childElements.filter((c) => !!c); 30 const children = childElements.filter(c => !!c);
32 31
33 if (children.length === 1) { 32 if (children.length === 1) {
34 return <div>{children}</div>; 33 return <div>{children}</div>;
@@ -69,3 +68,5 @@ class Tab extends Component {
69 ); 68 );
70 } 69 }
71} 70}
71
72export default Tab;
diff --git a/src/components/ui/Toggle.js b/src/components/ui/Toggle.js
index 14330e5c7..bd7bc242d 100644
--- a/src/components/ui/Toggle.js
+++ b/src/components/ui/Toggle.js
@@ -4,7 +4,8 @@ import { observer } from 'mobx-react';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5import { Field } from 'mobx-react-form'; 5import { Field } from 'mobx-react-form';
6 6
7export default @observer class Toggle extends Component { 7@observer
8class Toggle extends Component {
8 static propTypes = { 9 static propTypes = {
9 field: PropTypes.instanceOf(Field).isRequired, 10 field: PropTypes.instanceOf(Field).isRequired,
10 className: PropTypes.string, 11 className: PropTypes.string,
@@ -25,12 +26,7 @@ export default @observer class Toggle extends Component {
25 } 26 }
26 27
27 render() { 28 render() {
28 const { 29 const { field, className, showLabel, disabled } = this.props;
29 field,
30 className,
31 showLabel,
32 disabled,
33 } = this.props;
34 30
35 if (field.value === '' && field.default !== '') { 31 if (field.value === '' && field.default !== '') {
36 field.value = field.default; 32 field.value = field.default;
@@ -59,12 +55,18 @@ export default @observer class Toggle extends Component {
59 name={field.name} 55 name={field.name}
60 value={field.name} 56 value={field.name}
61 checked={field.value} 57 checked={field.value}
62 onChange={(e) => (!disabled ? this.onChange(e) : null)} 58 onChange={e => (!disabled ? this.onChange(e) : null)}
63 /> 59 />
64 </label> 60 </label>
65 {field.error && <div className={field.error}>{field.error}</div>} 61 {field.error && <div className={field.error}>{field.error}</div>}
66 {field.label && showLabel && <label className="franz-form__label" htmlFor={field.id}>{field.label}</label>} 62 {field.label && showLabel && (
63 <label className="franz-form__label" htmlFor={field.id}>
64 {field.label}
65 </label>
66 )}
67 </div> 67 </div>
68 ); 68 );
69 } 69 }
70} 70}
71
72export default Toggle;
diff --git a/src/components/ui/ToggleRaw.js b/src/components/ui/ToggleRaw.js
index 4700127d4..1fde879ac 100644
--- a/src/components/ui/ToggleRaw.js
+++ b/src/components/ui/ToggleRaw.js
@@ -6,7 +6,8 @@ import PropTypes from 'prop-types';
6import { observer } from 'mobx-react'; 6import { observer } from 'mobx-react';
7import classnames from 'classnames'; 7import classnames from 'classnames';
8 8
9export default @observer class ToggleRaw extends Component { 9@observer
10class ToggleRaw extends Component {
10 static propTypes = { 11 static propTypes = {
11 onChange: PropTypes.func.isRequired, 12 onChange: PropTypes.func.isRequired,
12 field: PropTypes.shape({ 13 field: PropTypes.shape({
@@ -34,12 +35,7 @@ export default @observer class ToggleRaw extends Component {
34 } 35 }
35 36
36 render() { 37 render() {
37 const { 38 const { field, className, showLabel, disabled } = this.props;
38 field,
39 className,
40 showLabel,
41 disabled,
42 } = this.props;
43 39
44 return ( 40 return (
45 <div 41 <div
@@ -64,12 +60,18 @@ export default @observer class ToggleRaw extends Component {
64 name={field.name} 60 name={field.name}
65 value={field.name} 61 value={field.name}
66 checked={field.value} 62 checked={field.value}
67 onChange={(e) => (!disabled ? this.onChange(e) : null)} 63 onChange={e => (!disabled ? this.onChange(e) : null)}
68 /> 64 />
69 </label> 65 </label>
70 {field.error && <div className={field.error}>{field.error}</div>} 66 {field.error && <div className={field.error}>{field.error}</div>}
71 {field.label && showLabel && <label className="franz-form__label" htmlFor={field.id}>{field.label}</label>} 67 {field.label && showLabel && (
68 <label className="franz-form__label" htmlFor={field.id}>
69 {field.label}
70 </label>
71 )}
72 </div> 72 </div>
73 ); 73 );
74 } 74 }
75} 75}
76
77export default ToggleRaw;
diff --git a/src/components/ui/WebviewLoader/index.js b/src/components/ui/WebviewLoader/index.js
index c58d69374..8f4499e7b 100644
--- a/src/components/ui/WebviewLoader/index.js
+++ b/src/components/ui/WebviewLoader/index.js
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import injectSheet from 'react-jss'; 4import injectSheet from 'react-jss';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6 6
7import FullscreenLoader from '../FullscreenLoader'; 7import FullscreenLoader from '../FullscreenLoader';
8import styles from './styles'; 8import styles from './styles';
@@ -10,23 +10,21 @@ import styles from './styles';
10const messages = defineMessages({ 10const messages = defineMessages({
11 loading: { 11 loading: {
12 id: 'service.webviewLoader.loading', 12 id: 'service.webviewLoader.loading',
13 defaultMessage: '!!!Loading {service}', 13 defaultMessage: 'Loading {service}',
14 }, 14 },
15}); 15});
16 16
17export default @injectSheet(styles) @observer class WebviewLoader extends Component { 17@injectSheet(styles)
18@observer
19class WebviewLoader extends Component {
18 static propTypes = { 20 static propTypes = {
19 name: PropTypes.string.isRequired, 21 name: PropTypes.string.isRequired,
20 classes: PropTypes.object.isRequired, 22 classes: PropTypes.object.isRequired,
21 }; 23 };
22 24
23 static contextTypes = {
24 intl: intlShape,
25 };
26
27 render() { 25 render() {
28 const { classes, name } = this.props; 26 const { classes, name } = this.props;
29 const { intl } = this.context; 27 const { intl } = this.props;
30 return ( 28 return (
31 <FullscreenLoader 29 <FullscreenLoader
32 className={classes.component} 30 className={classes.component}
@@ -35,3 +33,5 @@ export default @injectSheet(styles) @observer class WebviewLoader extends Compon
35 ); 33 );
36 } 34 }
37} 35}
36
37export default injectIntl(WebviewLoader);
diff --git a/src/components/util/ErrorBoundary/index.js b/src/components/util/ErrorBoundary/index.js
index 5db0db226..9c789e981 100644
--- a/src/components/util/ErrorBoundary/index.js
+++ b/src/components/util/ErrorBoundary/index.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import injectSheet from 'react-jss'; 3import injectSheet from 'react-jss';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5 5
6import Button from '../../ui/Button'; 6import Button from '../../ui/Button';
7 7
@@ -10,26 +10,23 @@ import styles from './styles';
10const messages = defineMessages({ 10const messages = defineMessages({
11 headline: { 11 headline: {
12 id: 'app.errorHandler.headline', 12 id: 'app.errorHandler.headline',
13 defaultMessage: '!!!Something went wrong.', 13 defaultMessage: 'Something went wrong.',
14 }, 14 },
15 action: { 15 action: {
16 id: 'app.errorHandler.action', 16 id: 'app.errorHandler.action',
17 defaultMessage: '!!!Reload', 17 defaultMessage: 'Reload',
18 }, 18 },
19}); 19});
20 20
21export default @injectSheet(styles) class ErrorBoundary extends Component { 21@injectSheet(styles)
22class ErrorBoundary extends Component {
22 state = { 23 state = {
23 hasError: false, 24 hasError: false,
24 } 25 };
25 26
26 static propTypes = { 27 static propTypes = {
27 classes: PropTypes.object.isRequired, 28 classes: PropTypes.object.isRequired,
28 children: PropTypes.node.isRequired, 29 children: PropTypes.node.isRequired,
29 }
30
31 static contextTypes = {
32 intl: intlShape,
33 }; 30 };
34 31
35 componentDidCatch() { 32 componentDidCatch() {
@@ -38,7 +35,7 @@ export default @injectSheet(styles) class ErrorBoundary extends Component {
38 35
39 render() { 36 render() {
40 const { classes } = this.props; 37 const { classes } = this.props;
41 const { intl } = this.context; 38 const { intl } = this.props;
42 39
43 if (this.state.hasError) { 40 if (this.state.hasError) {
44 return ( 41 return (
@@ -58,3 +55,5 @@ export default @injectSheet(styles) class ErrorBoundary extends Component {
58 return this.props.children; 55 return this.props.children;
59 } 56 }
60} 57}
58
59export default injectIntl(ErrorBoundary);
diff --git a/src/containers/auth/AuthLayoutContainer.js b/src/containers/auth/AuthLayoutContainer.js
index a0d50ab54..7673ab9c7 100644
--- a/src/containers/auth/AuthLayoutContainer.js
+++ b/src/containers/auth/AuthLayoutContainer.js
@@ -14,7 +14,6 @@ import AppLoader from '../../components/ui/AppLoader';
14import { oneOrManyChildElements } from '../../prop-types'; 14import { oneOrManyChildElements } from '../../prop-types';
15import FeaturesStore from '../../stores/FeaturesStore'; 15import FeaturesStore from '../../stores/FeaturesStore';
16 16
17export default
18@inject('stores', 'actions') 17@inject('stores', 'actions')
19@observer 18@observer
20class AuthLayoutContainer extends Component { 19class AuthLayoutContainer extends Component {
@@ -85,3 +84,5 @@ AuthLayoutContainer.wrappedComponent.propTypes = {
85 settings: PropTypes.instanceOf(SettingsStore).isRequired, 84 settings: PropTypes.instanceOf(SettingsStore).isRequired,
86 }).isRequired, 85 }).isRequired,
87}; 86};
87
88export default AuthLayoutContainer;
diff --git a/src/containers/auth/ChangeServerScreen.js b/src/containers/auth/ChangeServerScreen.js
index 28ecc0198..94fc98b61 100644
--- a/src/containers/auth/ChangeServerScreen.js
+++ b/src/containers/auth/ChangeServerScreen.js
@@ -5,7 +5,9 @@ import { RouterStore } from 'mobx-react-router';
5import ChangeServer from '../../components/auth/ChangeServer'; 5import ChangeServer from '../../components/auth/ChangeServer';
6import SettingsStore from '../../stores/SettingsStore'; 6import SettingsStore from '../../stores/SettingsStore';
7 7
8export default @inject('stores', 'actions') @observer class ChangeServerScreen extends Component { 8@inject('stores', 'actions')
9@observer
10class ChangeServerScreen extends Component {
9 constructor(props) { 11 constructor(props) {
10 super(props); 12 super(props);
11 13
@@ -28,12 +30,7 @@ export default @inject('stores', 'actions') @observer class ChangeServerScreen e
28 const { stores } = this.props; 30 const { stores } = this.props;
29 const { server } = stores.settings.all.app; 31 const { server } = stores.settings.all.app;
30 32
31 return ( 33 return <ChangeServer onSubmit={this.onSubmit} server={server} />;
32 <ChangeServer
33 onSubmit={this.onSubmit}
34 server={server}
35 />
36 );
37 } 34 }
38} 35}
39 36
diff --git a/src/containers/auth/ImportScreen.js b/src/containers/auth/ImportScreen.js
index 9143ef616..ff2854f6e 100644
--- a/src/containers/auth/ImportScreen.js
+++ b/src/containers/auth/ImportScreen.js
@@ -5,7 +5,9 @@ import { RouterStore } from 'mobx-react-router';
5import Import from '../../components/auth/Import'; 5import Import from '../../components/auth/Import';
6import UserStore from '../../stores/UserStore'; 6import UserStore from '../../stores/UserStore';
7 7
8export default @inject('stores', 'actions') @observer class ImportScreen extends Component { 8@inject('stores', 'actions')
9@observer
10class ImportScreen extends Component {
9 render() { 11 render() {
10 const { actions, stores } = this.props; 12 const { actions, stores } = this.props;
11 13
diff --git a/src/containers/auth/InviteScreen.js b/src/containers/auth/InviteScreen.js
index 66afaf7e1..d9d52a57c 100644
--- a/src/containers/auth/InviteScreen.js
+++ b/src/containers/auth/InviteScreen.js
@@ -3,16 +3,13 @@ import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4import Invite from '../../components/auth/Invite'; 4import Invite from '../../components/auth/Invite';
5 5
6export default @inject('stores', 'actions') @observer class InviteScreen extends Component { 6@inject('stores', 'actions')
7@observer
8class InviteScreen extends Component {
7 render() { 9 render() {
8 const { actions } = this.props; 10 const { actions } = this.props;
9 11
10 return ( 12 return <Invite onSubmit={actions.user.invite} embed={false} />;
11 <Invite
12 onSubmit={actions.user.invite}
13 embed={false}
14 />
15 );
16 } 13 }
17} 14}
18 15
@@ -23,3 +20,5 @@ InviteScreen.wrappedComponent.propTypes = {
23 }).isRequired, 20 }).isRequired,
24 }).isRequired, 21 }).isRequired,
25}; 22};
23
24export default InviteScreen;
diff --git a/src/containers/auth/LockedScreen.js b/src/containers/auth/LockedScreen.js
index 4e97c6573..87205c4b9 100644
--- a/src/containers/auth/LockedScreen.js
+++ b/src/containers/auth/LockedScreen.js
@@ -7,10 +7,12 @@ import SettingsStore from '../../stores/SettingsStore';
7import { hash } from '../../helpers/password-helpers'; 7import { hash } from '../../helpers/password-helpers';
8import UserStore from '../../stores/UserStore'; 8import UserStore from '../../stores/UserStore';
9 9
10export default @inject('stores', 'actions') @observer class LockedScreen extends Component { 10@inject('stores', 'actions')
11@observer
12class LockedScreen extends Component {
11 state = { 13 state = {
12 error: false, 14 error: false,
13 } 15 };
14 16
15 constructor(props) { 17 constructor(props) {
16 super(props); 18 super(props);
diff --git a/src/containers/auth/LoginScreen.js b/src/containers/auth/LoginScreen.js
index e636f99e0..d24eb1d22 100644
--- a/src/containers/auth/LoginScreen.js
+++ b/src/containers/auth/LoginScreen.js
@@ -6,7 +6,9 @@ import UserStore from '../../stores/UserStore';
6 6
7import { globalError as globalErrorPropType } from '../../prop-types'; 7import { globalError as globalErrorPropType } from '../../prop-types';
8 8
9export default @inject('stores', 'actions') @observer class LoginScreen extends Component { 9@inject('stores', 'actions')
10@observer
11class LoginScreen extends Component {
10 static propTypes = { 12 static propTypes = {
11 error: globalErrorPropType.isRequired, 13 error: globalErrorPropType.isRequired,
12 }; 14 };
@@ -18,7 +20,9 @@ export default @inject('stores', 'actions') @observer class LoginScreen extends
18 onSubmit={actions.user.login} 20 onSubmit={actions.user.login}
19 isSubmitting={stores.user.loginRequest.isExecuting} 21 isSubmitting={stores.user.loginRequest.isExecuting}
20 isTokenExpired={stores.user.isTokenExpired} 22 isTokenExpired={stores.user.isTokenExpired}
21 isServerLogout={stores.user.logoutReason === stores.user.logoutReasonTypes.SERVER} 23 isServerLogout={
24 stores.user.logoutReason === stores.user.logoutReasonTypes.SERVER
25 }
22 signupRoute={stores.user.signupRoute} 26 signupRoute={stores.user.signupRoute}
23 passwordRoute={stores.user.passwordRoute} 27 passwordRoute={stores.user.passwordRoute}
24 changeServerRoute={stores.user.changeServerRoute} 28 changeServerRoute={stores.user.changeServerRoute}
diff --git a/src/containers/auth/PasswordScreen.js b/src/containers/auth/PasswordScreen.js
index 9c6732f1a..47f6dfd01 100644
--- a/src/containers/auth/PasswordScreen.js
+++ b/src/containers/auth/PasswordScreen.js
@@ -4,7 +4,9 @@ import { inject, observer } from 'mobx-react';
4import Password from '../../components/auth/Password'; 4import Password from '../../components/auth/Password';
5import UserStore from '../../stores/UserStore'; 5import UserStore from '../../stores/UserStore';
6 6
7export default @inject('stores', 'actions') @observer class PasswordScreen extends Component { 7@inject('stores', 'actions')
8@observer
9class PasswordScreen extends Component {
8 render() { 10 render() {
9 const { actions, stores } = this.props; 11 const { actions, stores } = this.props;
10 12
diff --git a/src/containers/auth/SetupAssistantScreen.js b/src/containers/auth/SetupAssistantScreen.js
index d7036969a..efda2e9d2 100644
--- a/src/containers/auth/SetupAssistantScreen.js
+++ b/src/containers/auth/SetupAssistantScreen.js
@@ -14,7 +14,6 @@ import ServicesStore from '../../stores/ServicesStore';
14import RecipesStore from '../../stores/RecipesStore'; 14import RecipesStore from '../../stores/RecipesStore';
15import UserStore from '../../stores/UserStore'; 15import UserStore from '../../stores/UserStore';
16 16
17export default
18@inject('stores', 'actions') 17@inject('stores', 'actions')
19@observer 18@observer
20class SetupAssistantScreen extends Component { 19class SetupAssistantScreen extends Component {
@@ -134,3 +133,5 @@ SetupAssistantScreen.wrappedComponent.propTypes = {
134 recipe: PropTypes.instanceOf(RecipesStore).isRequired, 133 recipe: PropTypes.instanceOf(RecipesStore).isRequired,
135 }).isRequired, 134 }).isRequired,
136}; 135};
136
137export default SetupAssistantScreen;
diff --git a/src/containers/auth/SignupScreen.js b/src/containers/auth/SignupScreen.js
index 38c5dfb43..b20a7fd62 100644
--- a/src/containers/auth/SignupScreen.js
+++ b/src/containers/auth/SignupScreen.js
@@ -8,7 +8,9 @@ import FeaturesStore from '../../stores/FeaturesStore';
8 8
9import { globalError as globalErrorPropType } from '../../prop-types'; 9import { globalError as globalErrorPropType } from '../../prop-types';
10 10
11export default @inject('stores', 'actions') @observer class SignupScreen extends Component { 11@inject('stores', 'actions')
12@observer
13class SignupScreen extends Component {
12 static propTypes = { 14 static propTypes = {
13 error: globalErrorPropType.isRequired, 15 error: globalErrorPropType.isRequired,
14 }; 16 };
@@ -24,7 +26,7 @@ export default @inject('stores', 'actions') @observer class SignupScreen extends
24 26
25 return ( 27 return (
26 <Signup 28 <Signup
27 onSubmit={(values) => this.onSignup(values)} 29 onSubmit={values => this.onSignup(values)}
28 isSubmitting={stores.user.signupRequest.isExecuting} 30 isSubmitting={stores.user.signupRequest.isExecuting}
29 loginRoute={stores.user.loginRoute} 31 loginRoute={stores.user.loginRoute}
30 changeServerRoute={stores.user.changeServerRoute} 32 changeServerRoute={stores.user.changeServerRoute}
@@ -43,3 +45,5 @@ SignupScreen.wrappedComponent.propTypes = {
43 features: PropTypes.instanceOf(FeaturesStore).isRequired, 45 features: PropTypes.instanceOf(FeaturesStore).isRequired,
44 }).isRequired, 46 }).isRequired,
45}; 47};
48
49export default SignupScreen;
diff --git a/src/containers/auth/WelcomeScreen.js b/src/containers/auth/WelcomeScreen.js
index bfcc880d0..d169e5f0f 100644
--- a/src/containers/auth/WelcomeScreen.js
+++ b/src/containers/auth/WelcomeScreen.js
@@ -6,7 +6,9 @@ import Welcome from '../../components/auth/Welcome';
6import UserStore from '../../stores/UserStore'; 6import UserStore from '../../stores/UserStore';
7import RecipePreviewsStore from '../../stores/RecipePreviewsStore'; 7import RecipePreviewsStore from '../../stores/RecipePreviewsStore';
8 8
9export default @inject('stores', 'actions') @observer class LoginScreen extends Component { 9@inject('stores', 'actions')
10@observer
11class LoginScreen extends Component {
10 render() { 12 render() {
11 const { user, recipePreviews } = this.props.stores; 13 const { user, recipePreviews } = this.props.stores;
12 14
@@ -27,3 +29,5 @@ LoginScreen.wrappedComponent.propTypes = {
27 recipePreviews: PropTypes.instanceOf(RecipePreviewsStore).isRequired, 29 recipePreviews: PropTypes.instanceOf(RecipePreviewsStore).isRequired,
28 }).isRequired, 30 }).isRequired,
29}; 31};
32
33export default LoginScreen;
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js
index 83a25168b..3e92b0610 100644
--- a/src/containers/layout/AppLayoutContainer.js
+++ b/src/containers/layout/AppLayoutContainer.js
@@ -25,7 +25,6 @@ import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawe
25import { workspaceStore } from '../../features/workspaces'; 25import { workspaceStore } from '../../features/workspaces';
26import WorkspacesStore from '../../features/workspaces/store'; 26import WorkspacesStore from '../../features/workspaces/store';
27 27
28export default
29@inject('stores', 'actions') 28@inject('stores', 'actions')
30@observer 29@observer
31class AppLayoutContainer extends Component { 30class AppLayoutContainer extends Component {
@@ -199,3 +198,5 @@ AppLayoutContainer.wrappedComponent.propTypes = {
199 }).isRequired, 198 }).isRequired,
200 children: oneOrManyChildElements, 199 children: oneOrManyChildElements,
201}; 200};
201
202export default AppLayoutContainer;
diff --git a/src/containers/settings/AccountScreen.js b/src/containers/settings/AccountScreen.js
index 8d92b01be..cc3929656 100644
--- a/src/containers/settings/AccountScreen.js
+++ b/src/containers/settings/AccountScreen.js
@@ -12,7 +12,6 @@ import ErrorBoundary from '../../components/util/ErrorBoundary';
12import { LIVE_FRANZ_API } from '../../config'; 12import { LIVE_FRANZ_API } from '../../config';
13import { WEBSITE } from '../../environment'; 13import { WEBSITE } from '../../environment';
14 14
15export default
16@inject('stores', 'actions') 15@inject('stores', 'actions')
17@observer 16@observer
18class AccountScreen extends Component { 17class AccountScreen extends Component {
@@ -58,16 +57,16 @@ class AccountScreen extends Component {
58 user={user.data} 57 user={user.data}
59 isLoading={isLoadingUserInfo} 58 isLoading={isLoadingUserInfo}
60 userInfoRequestFailed={ 59 userInfoRequestFailed={
61 user.getUserInfoRequest.wasExecuted 60 user.getUserInfoRequest.wasExecuted &&
62 && user.getUserInfoRequest.isError 61 user.getUserInfoRequest.isError
63 } 62 }
64 retryUserInfoRequest={() => this.reloadData()} 63 retryUserInfoRequest={() => this.reloadData()}
65 onCloseSubscriptionWindow={() => this.onCloseWindow()} 64 onCloseSubscriptionWindow={() => this.onCloseWindow()}
66 deleteAccount={userActions.delete} 65 deleteAccount={userActions.delete}
67 isLoadingDeleteAccount={user.deleteAccountRequest.isExecuting} 66 isLoadingDeleteAccount={user.deleteAccountRequest.isExecuting}
68 isDeleteAccountSuccessful={ 67 isDeleteAccountSuccessful={
69 user.deleteAccountRequest.wasExecuted 68 user.deleteAccountRequest.wasExecuted &&
70 && !user.deleteAccountRequest.isError 69 !user.deleteAccountRequest.isError
71 } 70 }
72 openEditAccount={() => this.handleWebsiteLink('/user/profile')} 71 openEditAccount={() => this.handleWebsiteLink('/user/profile')}
73 openInvoices={() => this.handleWebsiteLink('/user/invoices')} 72 openInvoices={() => this.handleWebsiteLink('/user/invoices')}
@@ -89,3 +88,5 @@ AccountScreen.wrappedComponent.propTypes = {
89 user: PropTypes.instanceOf(UserStore).isRequired, 88 user: PropTypes.instanceOf(UserStore).isRequired,
90 }).isRequired, 89 }).isRequired,
91}; 90};
91
92export default AccountScreen;
diff --git a/src/containers/settings/EditServiceScreen.js b/src/containers/settings/EditServiceScreen.js
index c880e97ae..12e7b9e95 100644
--- a/src/containers/settings/EditServiceScreen.js
+++ b/src/containers/settings/EditServiceScreen.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5 5
6import { RouterStore } from 'mobx-react-router'; 6import { RouterStore } from 'mobx-react-router';
7import UserStore from '../../stores/UserStore'; 7import UserStore from '../../stores/UserStore';
@@ -27,87 +27,85 @@ import globalMessages from '../../i18n/globalMessages';
27const messages = defineMessages({ 27const messages = defineMessages({
28 name: { 28 name: {
29 id: 'settings.service.form.name', 29 id: 'settings.service.form.name',
30 defaultMessage: '!!!Name', 30 defaultMessage: 'Name',
31 }, 31 },
32 enableService: { 32 enableService: {
33 id: 'settings.service.form.enableService', 33 id: 'settings.service.form.enableService',
34 defaultMessage: '!!!Enable service', 34 defaultMessage: 'Enable service',
35 }, 35 },
36 enableHibernation: { 36 enableHibernation: {
37 id: 'settings.service.form.enableHibernation', 37 id: 'settings.service.form.enableHibernation',
38 defaultMessage: '!!!Enable hibernation', 38 defaultMessage: 'Enable hibernation',
39 }, 39 },
40 enableNotification: { 40 enableNotification: {
41 id: 'settings.service.form.enableNotification', 41 id: 'settings.service.form.enableNotification',
42 defaultMessage: '!!!Enable Notifications', 42 defaultMessage: 'Enable Notifications',
43 }, 43 },
44 enableBadge: { 44 enableBadge: {
45 id: 'settings.service.form.enableBadge', 45 id: 'settings.service.form.enableBadge',
46 defaultMessage: '!!!Show unread message badges', 46 defaultMessage: 'Show unread message badges',
47 }, 47 },
48 enableAudio: { 48 enableAudio: {
49 id: 'settings.service.form.enableAudio', 49 id: 'settings.service.form.enableAudio',
50 defaultMessage: '!!!Enable audio', 50 defaultMessage: 'Enable audio',
51 }, 51 },
52 team: { 52 team: {
53 id: 'settings.service.form.team', 53 id: 'settings.service.form.team',
54 defaultMessage: '!!!Team', 54 defaultMessage: 'Team',
55 }, 55 },
56 customUrl: { 56 customUrl: {
57 id: 'settings.service.form.customUrl', 57 id: 'settings.service.form.customUrl',
58 defaultMessage: '!!!Service URL', 58 defaultMessage: 'Service URL',
59 }, 59 },
60 indirectMessages: { 60 indirectMessages: {
61 id: 'settings.service.form.indirectMessages', 61 id: 'settings.service.form.indirectMessages',
62 defaultMessage: '!!!Show message badge for all new messages', 62 defaultMessage: 'Show message badge for all new messages',
63 }, 63 },
64 icon: { 64 icon: {
65 id: 'settings.service.form.icon', 65 id: 'settings.service.form.icon',
66 defaultMessage: '!!!Custom icon', 66 defaultMessage: 'Custom icon',
67 }, 67 },
68 enableDarkMode: { 68 enableDarkMode: {
69 id: 'settings.service.form.enableDarkMode', 69 id: 'settings.service.form.enableDarkMode',
70 defaultMessage: '!!!Enable Dark Mode', 70 defaultMessage: 'Enable Dark Mode',
71 }, 71 },
72 darkReaderBrightness: { 72 darkReaderBrightness: {
73 id: 'settings.service.form.darkReaderBrightness', 73 id: 'settings.service.form.darkReaderBrightness',
74 defaultMessage: '!!!Dark Reader Brightness', 74 defaultMessage: 'Dark Reader Brightness',
75 }, 75 },
76 darkReaderContrast: { 76 darkReaderContrast: {
77 id: 'settings.service.form.darkReaderContrast', 77 id: 'settings.service.form.darkReaderContrast',
78 defaultMessage: '!!!Dark Reader Contrast', 78 defaultMessage: 'Dark Reader Contrast',
79 }, 79 },
80 darkReaderSepia: { 80 darkReaderSepia: {
81 id: 'settings.service.form.darkReaderSepia', 81 id: 'settings.service.form.darkReaderSepia',
82 defaultMessage: '!!!Dark Reader Sepia', 82 defaultMessage: 'Dark Reader Sepia',
83 }, 83 },
84 enableProxy: { 84 enableProxy: {
85 id: 'settings.service.form.proxy.isEnabled', 85 id: 'settings.service.form.proxy.isEnabled',
86 defaultMessage: '!!!Use Proxy', 86 defaultMessage: 'Use Proxy',
87 }, 87 },
88 proxyHost: { 88 proxyHost: {
89 id: 'settings.service.form.proxy.host', 89 id: 'settings.service.form.proxy.host',
90 defaultMessage: '!!!Proxy Host/IP', 90 defaultMessage: 'Proxy Host/IP',
91 }, 91 },
92 proxyPort: { 92 proxyPort: {
93 id: 'settings.service.form.proxy.port', 93 id: 'settings.service.form.proxy.port',
94 defaultMessage: '!!!Port', 94 defaultMessage: 'Port',
95 }, 95 },
96 proxyUser: { 96 proxyUser: {
97 id: 'settings.service.form.proxy.user', 97 id: 'settings.service.form.proxy.user',
98 defaultMessage: '!!!User', 98 defaultMessage: 'User',
99 }, 99 },
100 proxyPassword: { 100 proxyPassword: {
101 id: 'settings.service.form.proxy.password', 101 id: 'settings.service.form.proxy.password',
102 defaultMessage: '!!!Password', 102 defaultMessage: 'Password',
103 }, 103 },
104}); 104});
105 105
106export default @inject('stores', 'actions') @observer class EditServiceScreen extends Component { 106@inject('stores', 'actions')
107 static contextTypes = { 107@observer
108 intl: intlShape, 108class EditServiceScreen extends Component {
109 };
110
111 onSubmit(data) { 109 onSubmit(data) {
112 const { action } = this.props.router.params; 110 const { action } = this.props.router.params;
113 const { recipes, services } = this.props.stores; 111 const { recipes, services } = this.props.stores;
@@ -132,27 +130,31 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
132 } 130 }
133 131
134 prepareForm(recipe, service, proxy) { 132 prepareForm(recipe, service, proxy) {
135 const { 133 const { intl } = this.props;
136 intl,
137 } = this.context;
138 134
139 const { 135 const { stores, router } = this.props;
140 stores,
141 router,
142 } = this.props;
143 136
144 const { action } = router.params; 137 const { action } = router.params;
145 138
146 let defaultSpellcheckerLanguage = SPELLCHECKER_LOCALES[stores.settings.app.spellcheckerLanguage]; 139 let defaultSpellcheckerLanguage =
140 SPELLCHECKER_LOCALES[stores.settings.app.spellcheckerLanguage];
147 141
148 if (stores.settings.app.spellcheckerLanguage === 'automatic') { 142 if (stores.settings.app.spellcheckerLanguage === 'automatic') {
149 defaultSpellcheckerLanguage = intl.formatMessage(globalMessages.spellcheckerAutomaticDetectionShort); 143 defaultSpellcheckerLanguage = intl.formatMessage(
144 globalMessages.spellcheckerAutomaticDetectionShort,
145 );
150 } 146 }
151 147
152 const spellcheckerLanguage = getSelectOptions({ 148 const spellcheckerLanguage = getSelectOptions({
153 locales: SPELLCHECKER_LOCALES, 149 locales: SPELLCHECKER_LOCALES,
154 resetToDefaultText: intl.formatMessage(globalMessages.spellcheckerSystemDefault, { default: defaultSpellcheckerLanguage }), 150 resetToDefaultText: intl.formatMessage(
155 automaticDetectionText: stores.settings.app.spellcheckerLanguage !== 'automatic' ? intl.formatMessage(globalMessages.spellcheckerAutomaticDetection) : '', 151 globalMessages.spellcheckerSystemDefault,
152 { default: defaultSpellcheckerLanguage },
153 ),
154 automaticDetectionText:
155 stores.settings.app.spellcheckerLanguage !== 'automatic'
156 ? intl.formatMessage(globalMessages.spellcheckerAutomaticDetection)
157 : '',
156 }); 158 });
157 159
158 const config = { 160 const config = {
@@ -169,7 +171,10 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
169 }, 171 },
170 isHibernationEnabled: { 172 isHibernationEnabled: {
171 label: intl.formatMessage(messages.enableHibernation), 173 label: intl.formatMessage(messages.enableHibernation),
172 value: action !== 'edit' ? recipe.autoHibernate : service.isHibernationEnabled, 174 value:
175 action !== 'edit'
176 ? recipe.autoHibernate
177 : service.isHibernationEnabled,
173 default: true, 178 default: true,
174 }, 179 },
175 isNotificationEnabled: { 180 isNotificationEnabled: {
@@ -200,17 +205,23 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
200 }, 205 },
201 darkReaderBrightness: { 206 darkReaderBrightness: {
202 label: intl.formatMessage(messages.darkReaderBrightness), 207 label: intl.formatMessage(messages.darkReaderBrightness),
203 value: service.darkReaderSettings ? service.darkReaderSettings.brightness : undefined, 208 value: service.darkReaderSettings
209 ? service.darkReaderSettings.brightness
210 : undefined,
204 default: 100, 211 default: 100,
205 }, 212 },
206 darkReaderContrast: { 213 darkReaderContrast: {
207 label: intl.formatMessage(messages.darkReaderContrast), 214 label: intl.formatMessage(messages.darkReaderContrast),
208 value: service.darkReaderSettings ? service.darkReaderSettings.contrast : undefined, 215 value: service.darkReaderSettings
216 ? service.darkReaderSettings.contrast
217 : undefined,
209 default: 90, 218 default: 90,
210 }, 219 },
211 darkReaderSepia: { 220 darkReaderSepia: {
212 label: intl.formatMessage(messages.darkReaderSepia), 221 label: intl.formatMessage(messages.darkReaderSepia),
213 value: service.darkReaderSettings ? service.darkReaderSettings.sepia : undefined, 222 value: service.darkReaderSettings
223 ? service.darkReaderSettings.sepia
224 : undefined,
214 default: 10, 225 default: 10,
215 }, 226 },
216 spellcheckerLanguage: { 227 spellcheckerLanguage: {
@@ -252,7 +263,10 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
252 // More fine grained and use case specific validation rules 263 // More fine grained and use case specific validation rules
253 if (recipe.hasTeamId && recipe.hasCustomUrl) { 264 if (recipe.hasTeamId && recipe.hasCustomUrl) {
254 config.fields.team.validators = [oneRequired(['team', 'customUrl'])]; 265 config.fields.team.validators = [oneRequired(['team', 'customUrl'])];
255 config.fields.customUrl.validators = [url, oneRequired(['team', 'customUrl'])]; 266 config.fields.customUrl.validators = [
267 url,
268 oneRequired(['team', 'customUrl']),
269 ];
256 } 270 }
257 271
258 // If a service can be hosted and has a teamId or customUrl 272 // If a service can be hosted and has a teamId or customUrl
@@ -344,9 +358,7 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
344 } 358 }
345 359
346 render() { 360 render() {
347 const { 361 const { recipes, services, user } = this.props.stores;
348 recipes, services, user,
349 } = this.props.stores;
350 const { action } = this.props.router.params; 362 const { action } = this.props.router.params;
351 363
352 let recipe; 364 let recipe;
@@ -358,9 +370,7 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
358 370
359 // TODO: render error message when recipe is `null` 371 // TODO: render error message when recipe is `null`
360 if (!recipe) { 372 if (!recipe) {
361 return ( 373 return <ServiceError />;
362 <ServiceError />
363 );
364 } 374 }
365 } else { 375 } else {
366 service = services.activeSettings; 376 service = services.activeSettings;
@@ -372,13 +382,11 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
372 } 382 }
373 383
374 if (isLoading) { 384 if (isLoading) {
375 return (<div>Loading...</div>); 385 return <div>Loading...</div>;
376 } 386 }
377 387
378 if (!recipe) { 388 if (!recipe) {
379 return ( 389 return <div>something went wrong</div>;
380 <div>something went wrong</div>
381 );
382 } 390 }
383 391
384 const form = this.prepareForm(recipe, service, proxyFeature); 392 const form = this.prepareForm(recipe, service, proxyFeature);
@@ -392,11 +400,14 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
392 user={user.data} 400 user={user.data}
393 form={form} 401 form={form}
394 status={services.actionStatus} 402 status={services.actionStatus}
395 isSaving={services.updateServiceRequest.isExecuting || services.createServiceRequest.isExecuting} 403 isSaving={
404 services.updateServiceRequest.isExecuting ||
405 services.createServiceRequest.isExecuting
406 }
396 isDeleting={services.deleteServiceRequest.isExecuting} 407 isDeleting={services.deleteServiceRequest.isExecuting}
397 onSubmit={(d) => this.onSubmit(d)} 408 onSubmit={d => this.onSubmit(d)}
398 onDelete={() => this.deleteService()} 409 onDelete={() => this.deleteService()}
399 openRecipeFile={(file) => this.openRecipeFile(file)} 410 openRecipeFile={file => this.openRecipeFile(file)}
400 isProxyFeatureEnabled={proxyFeature.isEnabled} 411 isProxyFeatureEnabled={proxyFeature.isEnabled}
401 /> 412 />
402 </ErrorBoundary> 413 </ErrorBoundary>
@@ -417,3 +428,5 @@ EditServiceScreen.wrappedComponent.propTypes = {
417 service: PropTypes.instanceOf(ServicesStore).isRequired, 428 service: PropTypes.instanceOf(ServicesStore).isRequired,
418 }).isRequired, 429 }).isRequired,
419}; 430};
431
432export default injectIntl(EditServiceScreen);
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js
index 09244bc3c..8834aa1ae 100644
--- a/src/containers/settings/EditSettingsScreen.js
+++ b/src/containers/settings/EditSettingsScreen.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5 5
6import AppStore from '../../stores/AppStore'; 6import AppStore from '../../stores/AppStore';
7import SettingsStore from '../../stores/SettingsStore'; 7import SettingsStore from '../../stores/SettingsStore';
@@ -10,8 +10,15 @@ import TodosStore from '../../features/todos/store';
10import Form from '../../lib/Form'; 10import Form from '../../lib/Form';
11import { APP_LOCALES, SPELLCHECKER_LOCALES } from '../../i18n/languages'; 11import { APP_LOCALES, SPELLCHECKER_LOCALES } from '../../i18n/languages';
12import { 12import {
13 HIBERNATION_STRATEGIES, SIDEBAR_WIDTH, ICON_SIZES, NAVIGATION_BAR_BEHAVIOURS, SEARCH_ENGINE_NAMES, TODO_APPS, 13 HIBERNATION_STRATEGIES,
14 DEFAULT_SETTING_KEEP_ALL_WORKSPACES_LOADED, DEFAULT_IS_FEATURE_ENABLED_BY_USER, WAKE_UP_STRATEGIES, 14 SIDEBAR_WIDTH,
15 ICON_SIZES,
16 NAVIGATION_BAR_BEHAVIOURS,
17 SEARCH_ENGINE_NAMES,
18 TODO_APPS,
19 DEFAULT_SETTING_KEEP_ALL_WORKSPACES_LOADED,
20 DEFAULT_IS_FEATURE_ENABLED_BY_USER,
21 WAKE_UP_STRATEGIES,
15} from '../../config'; 22} from '../../config';
16import { DEFAULT_APP_SETTINGS, isMac } from '../../environment'; 23import { DEFAULT_APP_SETTINGS, isMac } from '../../environment';
17 24
@@ -31,195 +38,193 @@ const debug = require('debug')('Ferdi:EditSettingsScreen');
31const messages = defineMessages({ 38const messages = defineMessages({
32 autoLaunchOnStart: { 39 autoLaunchOnStart: {
33 id: 'settings.app.form.autoLaunchOnStart', 40 id: 'settings.app.form.autoLaunchOnStart',
34 defaultMessage: '!!!Launch Ferdi on start', 41 defaultMessage: 'Launch Ferdi on start',
35 }, 42 },
36 autoLaunchInBackground: { 43 autoLaunchInBackground: {
37 id: 'settings.app.form.autoLaunchInBackground', 44 id: 'settings.app.form.autoLaunchInBackground',
38 defaultMessage: '!!!Open in background', 45 defaultMessage: 'Open in background',
39 }, 46 },
40 runInBackground: { 47 runInBackground: {
41 id: 'settings.app.form.runInBackground', 48 id: 'settings.app.form.runInBackground',
42 defaultMessage: '!!!Keep Ferdi in background when closing the window', 49 defaultMessage: 'Keep Ferdi in background when closing the window',
43 }, 50 },
44 startMinimized: { 51 startMinimized: {
45 id: 'settings.app.form.startMinimized', 52 id: 'settings.app.form.startMinimized',
46 defaultMessage: '!!!Start minimized', 53 defaultMessage: 'Start minimized',
47 }, 54 },
48 confirmOnQuit: { 55 confirmOnQuit: {
49 id: 'settings.app.form.confirmOnQuit', 56 id: 'settings.app.form.confirmOnQuit',
50 defaultMessage: '!!!Confirm when quitting Ferdi', 57 defaultMessage: 'Confirm when quitting Ferdi',
51 }, 58 },
52 enableSystemTray: { 59 enableSystemTray: {
53 id: 'settings.app.form.enableSystemTray', 60 id: 'settings.app.form.enableSystemTray',
54 defaultMessage: '!!!Always show Ferdi in System Tray', 61 defaultMessage: 'Always show Ferdi in System Tray',
55 }, 62 },
56 enableMenuBar: { 63 enableMenuBar: {
57 id: 'settings.app.form.enableMenuBar', 64 id: 'settings.app.form.enableMenuBar',
58 defaultMessage: '!!!Always show Ferdi in Menu Bar', 65 defaultMessage: 'Always show Ferdi in Menu Bar',
59 }, 66 },
60 reloadAfterResume: { 67 reloadAfterResume: {
61 id: 'settings.app.form.reloadAfterResume', 68 id: 'settings.app.form.reloadAfterResume',
62 defaultMessage: '!!!Reload Ferdi after system resume', 69 defaultMessage: 'Reload Ferdi after system resume',
63 }, 70 },
64 minimizeToSystemTray: { 71 minimizeToSystemTray: {
65 id: 'settings.app.form.minimizeToSystemTray', 72 id: 'settings.app.form.minimizeToSystemTray',
66 defaultMessage: '!!!Minimize Ferdi to system tray', 73 defaultMessage: 'Minimize Ferdi to system tray',
67 }, 74 },
68 closeToSystemTray: { 75 closeToSystemTray: {
69 id: 'settings.app.form.closeToSystemTray', 76 id: 'settings.app.form.closeToSystemTray',
70 defaultMessage: '!!!Close Ferdi to system tray', 77 defaultMessage: 'Close Ferdi to system tray',
71 }, 78 },
72 privateNotifications: { 79 privateNotifications: {
73 id: 'settings.app.form.privateNotifications', 80 id: 'settings.app.form.privateNotifications',
74 defaultMessage: '!!!Don\'t show message content in notifications', 81 defaultMessage: "Don't show message content in notifications",
75 }, 82 },
76 clipboardNotifications: { 83 clipboardNotifications: {
77 id: 'settings.app.form.clipboardNotifications', 84 id: 'settings.app.form.clipboardNotifications',
78 defaultMessage: '!!!Don\'t show notifications for clipboard events', 85 defaultMessage: "Don't show notifications for clipboard events",
79 }, 86 },
80 notifyTaskBarOnMessage: { 87 notifyTaskBarOnMessage: {
81 id: 'settings.app.form.notifyTaskBarOnMessage', 88 id: 'settings.app.form.notifyTaskBarOnMessage',
82 defaultMessage: '!!!Notify TaskBar/Dock on new message', 89 defaultMessage: 'Notify TaskBar/Dock on new message',
83 }, 90 },
84 navigationBarBehaviour: { 91 navigationBarBehaviour: {
85 id: 'settings.app.form.navigationBarBehaviour', 92 id: 'settings.app.form.navigationBarBehaviour',
86 defaultMessage: '!!!Navigation bar behaviour', 93 defaultMessage: 'Navigation bar behaviour',
87 }, 94 },
88 searchEngine: { 95 searchEngine: {
89 id: 'settings.app.form.searchEngine', 96 id: 'settings.app.form.searchEngine',
90 defaultMessage: '!!!Search engine', 97 defaultMessage: 'Search engine',
91 }, 98 },
92 sentry: { 99 sentry: {
93 id: 'settings.app.form.sentry', 100 id: 'settings.app.form.sentry',
94 defaultMessage: '!!!Send telemetry data', 101 defaultMessage: 'Send telemetry data',
95 }, 102 },
96 hibernateOnStartup: { 103 hibernateOnStartup: {
97 id: 'settings.app.form.hibernateOnStartup', 104 id: 'settings.app.form.hibernateOnStartup',
98 defaultMessage: '!!!Keep services in hibernation on startup', 105 defaultMessage: 'Keep services in hibernation on startup',
99 }, 106 },
100 hibernationStrategy: { 107 hibernationStrategy: {
101 id: 'settings.app.form.hibernationStrategy', 108 id: 'settings.app.form.hibernationStrategy',
102 defaultMessage: '!!!Hibernation strategy', 109 defaultMessage: 'Hibernation strategy',
103 }, 110 },
104 wakeUpStrategy: { 111 wakeUpStrategy: {
105 id: 'settings.app.form.wakeUpStrategy', 112 id: 'settings.app.form.wakeUpStrategy',
106 defaultMessage: '!!!Wake up strategy', 113 defaultMessage: 'Wake up strategy',
107 }, 114 },
108 predefinedTodoServer: { 115 predefinedTodoServer: {
109 id: 'settings.app.form.predefinedTodoServer', 116 id: 'settings.app.form.predefinedTodoServer',
110 defaultMessage: '!!!Todo Server', 117 defaultMessage: 'Todo Server',
111 }, 118 },
112 customTodoServer: { 119 customTodoServer: {
113 id: 'settings.app.form.customTodoServer', 120 id: 'settings.app.form.customTodoServer',
114 defaultMessage: '!!!Custom TodoServer', 121 defaultMessage: 'Custom TodoServer',
115 }, 122 },
116 enableLock: { 123 enableLock: {
117 id: 'settings.app.form.enableLock', 124 id: 'settings.app.form.enableLock',
118 defaultMessage: '!!!Enable Password Lock', 125 defaultMessage: 'Enable Password Lock',
119 }, 126 },
120 lockPassword: { 127 lockPassword: {
121 id: 'settings.app.form.lockPassword', 128 id: 'settings.app.form.lockPassword',
122 defaultMessage: '!!!Password', 129 defaultMessage: 'Password',
123 }, 130 },
124 useTouchIdToUnlock: { 131 useTouchIdToUnlock: {
125 id: 'settings.app.form.useTouchIdToUnlock', 132 id: 'settings.app.form.useTouchIdToUnlock',
126 defaultMessage: '!!!Allow using Touch ID to unlock', 133 defaultMessage: 'Allow using Touch ID to unlock',
127 }, 134 },
128 inactivityLock: { 135 inactivityLock: {
129 id: 'settings.app.form.inactivityLock', 136 id: 'settings.app.form.inactivityLock',
130 defaultMessage: '!!!Lock after inactivity', 137 defaultMessage: 'Lock after inactivity',
131 }, 138 },
132 scheduledDNDEnabled: { 139 scheduledDNDEnabled: {
133 id: 'settings.app.form.scheduledDNDEnabled', 140 id: 'settings.app.form.scheduledDNDEnabled',
134 defaultMessage: '!!!Enable scheduled Do-not-Disturb', 141 defaultMessage: 'Enable scheduled Do-not-Disturb',
135 }, 142 },
136 scheduledDNDStart: { 143 scheduledDNDStart: {
137 id: 'settings.app.form.scheduledDNDStart', 144 id: 'settings.app.form.scheduledDNDStart',
138 defaultMessage: '!!!From', 145 defaultMessage: 'From',
139 }, 146 },
140 scheduledDNDEnd: { 147 scheduledDNDEnd: {
141 id: 'settings.app.form.scheduledDNDEnd', 148 id: 'settings.app.form.scheduledDNDEnd',
142 defaultMessage: '!!!To', 149 defaultMessage: 'To',
143 }, 150 },
144 language: { 151 language: {
145 id: 'settings.app.form.language', 152 id: 'settings.app.form.language',
146 defaultMessage: '!!!Language', 153 defaultMessage: 'Language',
147 }, 154 },
148 darkMode: { 155 darkMode: {
149 id: 'settings.app.form.darkMode', 156 id: 'settings.app.form.darkMode',
150 defaultMessage: '!!!Dark Mode', 157 defaultMessage: 'Dark Mode',
151 }, 158 },
152 adaptableDarkMode: { 159 adaptableDarkMode: {
153 id: 'settings.app.form.adaptableDarkMode', 160 id: 'settings.app.form.adaptableDarkMode',
154 defaultMessage: '!!!Synchronize dark mode with my OS\'s dark mode setting', 161 defaultMessage: "Synchronize dark mode with my OS's dark mode setting",
155 }, 162 },
156 universalDarkMode: { 163 universalDarkMode: {
157 id: 'settings.app.form.universalDarkMode', 164 id: 'settings.app.form.universalDarkMode',
158 defaultMessage: '!!!Enable universal Dark Mode', 165 defaultMessage: 'Enable universal Dark Mode',
159 }, 166 },
160 serviceRibbonWidth: { 167 serviceRibbonWidth: {
161 id: 'settings.app.form.serviceRibbonWidth', 168 id: 'settings.app.form.serviceRibbonWidth',
162 defaultMessage: '!!!Sidebar width', 169 defaultMessage: 'Sidebar width',
163 }, 170 },
164 iconSize: { 171 iconSize: {
165 id: 'settings.app.form.iconSize', 172 id: 'settings.app.form.iconSize',
166 defaultMessage: '!!!Service icon size', 173 defaultMessage: 'Service icon size',
167 }, 174 },
168 useVerticalStyle: { 175 useVerticalStyle: {
169 id: 'settings.app.form.useVerticalStyle', 176 id: 'settings.app.form.useVerticalStyle',
170 defaultMessage: '!!!Use horizontal style', 177 defaultMessage: 'Use horizontal style',
171 }, 178 },
172 alwaysShowWorkspaces: { 179 alwaysShowWorkspaces: {
173 id: 'settings.app.form.alwaysShowWorkspaces', 180 id: 'settings.app.form.alwaysShowWorkspaces',
174 defaultMessage: '!!!Always show workspace drawer', 181 defaultMessage: 'Always show workspace drawer',
175 }, 182 },
176 accentColor: { 183 accentColor: {
177 id: 'settings.app.form.accentColor', 184 id: 'settings.app.form.accentColor',
178 defaultMessage: '!!!Accent color', 185 defaultMessage: 'Accent color',
179 }, 186 },
180 showDisabledServices: { 187 showDisabledServices: {
181 id: 'settings.app.form.showDisabledServices', 188 id: 'settings.app.form.showDisabledServices',
182 defaultMessage: '!!!Display disabled services tabs', 189 defaultMessage: 'Display disabled services tabs',
183 }, 190 },
184 showMessageBadgeWhenMuted: { 191 showMessageBadgeWhenMuted: {
185 id: 'settings.app.form.showMessagesBadgesWhenMuted', 192 id: 'settings.app.form.showMessagesBadgesWhenMuted',
186 defaultMessage: '!!!Show unread message badge when notifications are disabled', 193 defaultMessage: 'Show unread message badge when notifications are disabled',
187 }, 194 },
188 showDragArea: { 195 showDragArea: {
189 id: 'settings.app.form.showDragArea', 196 id: 'settings.app.form.showDragArea',
190 defaultMessage: '!!!Show draggable area on window', 197 defaultMessage: 'Show draggable area on window',
191 }, 198 },
192 enableSpellchecking: { 199 enableSpellchecking: {
193 id: 'settings.app.form.enableSpellchecking', 200 id: 'settings.app.form.enableSpellchecking',
194 defaultMessage: '!!!Enable spell checking', 201 defaultMessage: 'Enable spell checking',
195 }, 202 },
196 enableGPUAcceleration: { 203 enableGPUAcceleration: {
197 id: 'settings.app.form.enableGPUAcceleration', 204 id: 'settings.app.form.enableGPUAcceleration',
198 defaultMessage: '!!!Enable GPU Acceleration', 205 defaultMessage: 'Enable GPU Acceleration',
199 }, 206 },
200 beta: { 207 beta: {
201 id: 'settings.app.form.beta', 208 id: 'settings.app.form.beta',
202 defaultMessage: '!!!Include beta versions', 209 defaultMessage: 'Include beta versions',
203 }, 210 },
204 automaticUpdates: { 211 automaticUpdates: {
205 id: 'settings.app.form.automaticUpdates', 212 id: 'settings.app.form.automaticUpdates',
206 defaultMessage: '!!!Enable updates', 213 defaultMessage: 'Enable updates',
207 }, 214 },
208 enableTodos: { 215 enableTodos: {
209 id: 'settings.app.form.enableTodos', 216 id: 'settings.app.form.enableTodos',
210 defaultMessage: '!!!Enable Franz Todos', 217 defaultMessage: 'Enable Franz Todos',
211 }, 218 },
212 keepAllWorkspacesLoaded: { 219 keepAllWorkspacesLoaded: {
213 id: 'settings.app.form.keepAllWorkspacesLoaded', 220 id: 'settings.app.form.keepAllWorkspacesLoaded',
214 defaultMessage: '!!!Keep all workspaces loaded', 221 defaultMessage: 'Keep all workspaces loaded',
215 }, 222 },
216}); 223});
217 224
218export default @inject('stores', 'actions') @observer class EditSettingsScreen extends Component { 225@inject('stores', 'actions')
219 static contextTypes = { 226@observer
220 intl: intlShape, 227class EditSettingsScreen extends Component {
221 };
222
223 constructor(props) { 228 constructor(props) {
224 super(props); 229 super(props);
225 230
@@ -288,7 +293,9 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
288 useVerticalStyle: Boolean(settingsData.useVerticalStyle), 293 useVerticalStyle: Boolean(settingsData.useVerticalStyle),
289 alwaysShowWorkspaces: Boolean(settingsData.alwaysShowWorkspaces), 294 alwaysShowWorkspaces: Boolean(settingsData.alwaysShowWorkspaces),
290 accentColor: settingsData.accentColor, 295 accentColor: settingsData.accentColor,
291 showMessageBadgeWhenMuted: Boolean(settingsData.showMessageBadgeWhenMuted), 296 showMessageBadgeWhenMuted: Boolean(
297 settingsData.showMessageBadgeWhenMuted,
298 ),
292 showDragArea: Boolean(settingsData.showDragArea), 299 showDragArea: Boolean(settingsData.showDragArea),
293 enableSpellchecking: Boolean(settingsData.enableSpellchecking), 300 enableSpellchecking: Boolean(settingsData.enableSpellchecking),
294 spellcheckerLanguage: settingsData.spellcheckerLanguage, 301 spellcheckerLanguage: settingsData.spellcheckerLanguage,
@@ -309,24 +316,27 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
309 316
310 if (workspaces.isFeatureActive) { 317 if (workspaces.isFeatureActive) {
311 const { keepAllWorkspacesLoaded } = workspaces.settings; 318 const { keepAllWorkspacesLoaded } = workspaces.settings;
312 if (Boolean(keepAllWorkspacesLoaded) !== Boolean(settingsData.keepAllWorkspacesLoaded)) { 319 if (
320 Boolean(keepAllWorkspacesLoaded) !==
321 Boolean(settingsData.keepAllWorkspacesLoaded)
322 ) {
313 workspaceActions.toggleKeepAllWorkspacesLoadedSetting(); 323 workspaceActions.toggleKeepAllWorkspacesLoadedSetting();
314 } 324 }
315 } 325 }
316 326
317 if (todos.isFeatureActive) { 327 if (todos.isFeatureActive) {
318 const { isFeatureEnabledByUser } = todos.settings; 328 const { isFeatureEnabledByUser } = todos.settings;
319 if (Boolean(isFeatureEnabledByUser) !== Boolean(settingsData.enableTodos)) { 329 if (
330 Boolean(isFeatureEnabledByUser) !== Boolean(settingsData.enableTodos)
331 ) {
320 todosActions.toggleTodosFeatureVisibility(); 332 todosActions.toggleTodosFeatureVisibility();
321 } 333 }
322 } 334 }
323 } 335 }
324 336
325 prepareForm() { 337 prepareForm() {
326 const { 338 const { app, settings, user, todos, workspaces } = this.props.stores;
327 app, settings, user, todos, workspaces, 339 const { intl } = this.props;
328 } = this.props.stores;
329 const { intl } = this.context;
330 const { lockedPassword } = this.state; 340 const { lockedPassword } = this.state;
331 341
332 const locales = getSelectOptions({ 342 const locales = getSelectOptions({
@@ -370,7 +380,9 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
370 380
371 const spellcheckingLanguages = getSelectOptions({ 381 const spellcheckingLanguages = getSelectOptions({
372 locales: SPELLCHECKER_LOCALES, 382 locales: SPELLCHECKER_LOCALES,
373 automaticDetectionText: this.context.intl.formatMessage(globalMessages.spellcheckerAutomaticDetection), 383 automaticDetectionText: intl.formatMessage(
384 globalMessages.spellcheckerAutomaticDetection,
385 ),
374 }); 386 });
375 387
376 const config = { 388 const config = {
@@ -401,7 +413,9 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
401 default: DEFAULT_APP_SETTINGS.confirmOnQuit, 413 default: DEFAULT_APP_SETTINGS.confirmOnQuit,
402 }, 414 },
403 enableSystemTray: { 415 enableSystemTray: {
404 label: intl.formatMessage(isMac ? messages.enableMenuBar : messages.enableSystemTray), 416 label: intl.formatMessage(
417 isMac ? messages.enableMenuBar : messages.enableSystemTray,
418 ),
405 value: settings.all.app.enableSystemTray, 419 value: settings.all.app.enableSystemTray,
406 default: DEFAULT_APP_SETTINGS.enableSystemTray, 420 default: DEFAULT_APP_SETTINGS.enableSystemTray,
407 }, 421 },
@@ -637,23 +651,15 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
637 } 651 }
638 652
639 render() { 653 render() {
640 const { 654 const { app, todos, workspaces, services } = this.props.stores;
641 app,
642 todos,
643 workspaces,
644 services,
645 } = this.props.stores;
646 const { 655 const {
647 updateStatus, 656 updateStatus,
648 updateStatusTypes, 657 updateStatusTypes,
649 isClearingAllCache, 658 isClearingAllCache,
650 lockingFeatureEnabled, 659 lockingFeatureEnabled,
651 } = app; 660 } = app;
652 const { 661 const { checkForUpdates, installUpdate, clearAllCache } =
653 checkForUpdates, 662 this.props.actions.app;
654 installUpdate,
655 clearAllCache,
656 } = this.props.actions.app;
657 const form = this.prepareForm(); 663 const form = this.prepareForm();
658 664
659 return ( 665 return (
@@ -666,7 +672,7 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
666 isUpdateAvailable={updateStatus === updateStatusTypes.AVAILABLE} 672 isUpdateAvailable={updateStatus === updateStatusTypes.AVAILABLE}
667 noUpdateAvailable={updateStatus === updateStatusTypes.NOT_AVAILABLE} 673 noUpdateAvailable={updateStatus === updateStatusTypes.NOT_AVAILABLE}
668 updateIsReadyToInstall={updateStatus === updateStatusTypes.DOWNLOADED} 674 updateIsReadyToInstall={updateStatus === updateStatusTypes.DOWNLOADED}
669 onSubmit={(d) => this.onSubmit(d)} 675 onSubmit={d => this.onSubmit(d)}
670 getCacheSize={() => app.cacheSize} 676 getCacheSize={() => app.cacheSize}
671 isClearingAllCache={isClearingAllCache} 677 isClearingAllCache={isClearingAllCache}
672 onClearAllCache={clearAllCache} 678 onClearAllCache={clearAllCache}
@@ -675,9 +681,13 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
675 lockingFeatureEnabled={lockingFeatureEnabled} 681 lockingFeatureEnabled={lockingFeatureEnabled}
676 automaticUpdates={this.props.stores.settings.app.automaticUpdates} 682 automaticUpdates={this.props.stores.settings.app.automaticUpdates}
677 isDarkmodeEnabled={this.props.stores.settings.app.darkMode} 683 isDarkmodeEnabled={this.props.stores.settings.app.darkMode}
678 isAdaptableDarkModeEnabled={this.props.stores.settings.app.adaptableDarkMode} 684 isAdaptableDarkModeEnabled={
685 this.props.stores.settings.app.adaptableDarkMode
686 }
679 isTodosActivated={this.props.stores.todos.isFeatureEnabledByUser} 687 isTodosActivated={this.props.stores.todos.isFeatureEnabledByUser}
680 isUsingCustomTodoService={this.props.stores.todos.isUsingCustomTodoService} 688 isUsingCustomTodoService={
689 this.props.stores.todos.isUsingCustomTodoService
690 }
681 isNightlyEnabled={this.props.stores.settings.app.nightly} 691 isNightlyEnabled={this.props.stores.settings.app.nightly}
682 hasAddedTodosAsService={services.isTodosServiceAdded} 692 hasAddedTodosAsService={services.isTodosServiceAdded}
683 isOnline={app.isOnline} 693 isOnline={app.isOnline}
@@ -704,3 +714,5 @@ EditSettingsScreen.wrappedComponent.propTypes = {
704 workspaces: PropTypes.instanceOf(WorkspacesStore).isRequired, 714 workspaces: PropTypes.instanceOf(WorkspacesStore).isRequired,
705 }).isRequired, 715 }).isRequired,
706}; 716};
717
718export default injectIntl(EditSettingsScreen);
diff --git a/src/containers/settings/EditUserScreen.js b/src/containers/settings/EditUserScreen.js
index 820b5e4d3..92ef94c29 100644
--- a/src/containers/settings/EditUserScreen.js
+++ b/src/containers/settings/EditUserScreen.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5 5
6import UserStore from '../../stores/UserStore'; 6import UserStore from '../../stores/UserStore';
7import Form from '../../lib/Form'; 7import Form from '../../lib/Form';
@@ -13,47 +13,45 @@ import { required, email, minLength } from '../../helpers/validation-helpers';
13const messages = defineMessages({ 13const messages = defineMessages({
14 firstname: { 14 firstname: {
15 id: 'settings.user.form.firstname', 15 id: 'settings.user.form.firstname',
16 defaultMessage: '!!!Firstname', 16 defaultMessage: 'Firstname',
17 }, 17 },
18 lastname: { 18 lastname: {
19 id: 'settings.user.form.lastname', 19 id: 'settings.user.form.lastname',
20 defaultMessage: '!!!Lastname', 20 defaultMessage: 'Lastname',
21 }, 21 },
22 email: { 22 email: {
23 id: 'settings.user.form.email', 23 id: 'settings.user.form.email',
24 defaultMessage: '!!!Email', 24 defaultMessage: 'Email',
25 }, 25 },
26 accountTypeLabel: { 26 accountTypeLabel: {
27 id: 'settings.user.form.accountType.label', 27 id: 'settings.user.form.accountType.label',
28 defaultMessage: '!!!Account type', 28 defaultMessage: 'Account type',
29 }, 29 },
30 accountTypeIndividual: { 30 accountTypeIndividual: {
31 id: 'settings.user.form.accountType.individual', 31 id: 'settings.user.form.accountType.individual',
32 defaultMessage: '!!!Individual', 32 defaultMessage: 'Individual',
33 }, 33 },
34 accountTypeNonProfit: { 34 accountTypeNonProfit: {
35 id: 'settings.user.form.accountType.non-profit', 35 id: 'settings.user.form.accountType.non-profit',
36 defaultMessage: '!!!Non-Profit', 36 defaultMessage: 'Non-Profit',
37 }, 37 },
38 accountTypeCompany: { 38 accountTypeCompany: {
39 id: 'settings.user.form.accountType.company', 39 id: 'settings.user.form.accountType.company',
40 defaultMessage: '!!!Company', 40 defaultMessage: 'Company',
41 }, 41 },
42 currentPassword: { 42 currentPassword: {
43 id: 'settings.user.form.currentPassword', 43 id: 'settings.user.form.currentPassword',
44 defaultMessage: '!!!Current password', 44 defaultMessage: 'Current password',
45 }, 45 },
46 newPassword: { 46 newPassword: {
47 id: 'settings.user.form.newPassword', 47 id: 'settings.user.form.newPassword',
48 defaultMessage: '!!!New password', 48 defaultMessage: 'New password',
49 }, 49 },
50}); 50});
51 51
52export default @inject('stores', 'actions') @observer class EditUserScreen extends Component { 52@inject('stores', 'actions')
53 static contextTypes = { 53@observer
54 intl: intlShape, 54class EditUserScreen extends Component {
55 };
56
57 componentWillUnmount() { 55 componentWillUnmount() {
58 this.props.actions.user.resetStatus(); 56 this.props.actions.user.resetStatus();
59 } 57 }
@@ -67,7 +65,7 @@ export default @inject('stores', 'actions') @observer class EditUserScreen exten
67 } 65 }
68 66
69 prepareForm(user) { 67 prepareForm(user) {
70 const { intl } = this.context; 68 const { intl } = this.props;
71 69
72 const config = { 70 const config = {
73 fields: { 71 fields: {
@@ -93,16 +91,20 @@ export default @inject('stores', 'actions') @observer class EditUserScreen exten
93 value: user.accountType, 91 value: user.accountType,
94 validators: [required], 92 validators: [required],
95 label: intl.formatMessage(messages.accountTypeLabel), 93 label: intl.formatMessage(messages.accountTypeLabel),
96 options: [{ 94 options: [
97 value: 'individual', 95 {
98 label: intl.formatMessage(messages.accountTypeIndividual), 96 value: 'individual',
99 }, { 97 label: intl.formatMessage(messages.accountTypeIndividual),
100 value: 'non-profit', 98 },
101 label: intl.formatMessage(messages.accountTypeNonProfit), 99 {
102 }, { 100 value: 'non-profit',
103 value: 'company', 101 label: intl.formatMessage(messages.accountTypeNonProfit),
104 label: intl.formatMessage(messages.accountTypeCompany), 102 },
105 }], 103 {
104 value: 'company',
105 label: intl.formatMessage(messages.accountTypeCompany),
106 },
107 ],
106 }, 108 },
107 organization: { 109 organization: {
108 label: intl.formatMessage(messages.accountTypeCompany), 110 label: intl.formatMessage(messages.accountTypeCompany),
@@ -129,7 +131,7 @@ export default @inject('stores', 'actions') @observer class EditUserScreen exten
129 const { user } = this.props.stores; 131 const { user } = this.props.stores;
130 132
131 if (user.getUserInfoRequest.isExecuting) { 133 if (user.getUserInfoRequest.isExecuting) {
132 return (<div>Loading...</div>); 134 return <div>Loading...</div>;
133 } 135 }
134 136
135 const form = this.prepareForm(user.data); 137 const form = this.prepareForm(user.data);
@@ -141,7 +143,7 @@ export default @inject('stores', 'actions') @observer class EditUserScreen exten
141 status={user.actionStatus} 143 status={user.actionStatus}
142 form={form} 144 form={form}
143 isSaving={user.updateUserInfoRequest.isExecuting} 145 isSaving={user.updateUserInfoRequest.isExecuting}
144 onSubmit={(d) => this.onSubmit(d)} 146 onSubmit={d => this.onSubmit(d)}
145 /> 147 />
146 </ErrorBoundary> 148 </ErrorBoundary>
147 ); 149 );
@@ -156,3 +158,5 @@ EditUserScreen.wrappedComponent.propTypes = {
156 user: PropTypes.instanceOf(UserStore).isRequired, 158 user: PropTypes.instanceOf(UserStore).isRequired,
157 }).isRequired, 159 }).isRequired,
158}; 160};
161
162export default injectIntl(EditUserScreen);
diff --git a/src/containers/settings/InviteScreen.js b/src/containers/settings/InviteScreen.js
index 4fdaef08b..f17f6390c 100644
--- a/src/containers/settings/InviteScreen.js
+++ b/src/containers/settings/InviteScreen.js
@@ -6,7 +6,9 @@ import Invite from '../../components/auth/Invite';
6import ErrorBoundary from '../../components/util/ErrorBoundary'; 6import ErrorBoundary from '../../components/util/ErrorBoundary';
7import UserStore from '../../stores/UserStore'; 7import UserStore from '../../stores/UserStore';
8 8
9export default @inject('stores', 'actions') @observer class InviteScreen extends Component { 9@inject('stores', 'actions')
10@observer
11class InviteScreen extends Component {
10 componentWillUnmount() { 12 componentWillUnmount() {
11 this.props.stores.user.inviteRequest.reset(); 13 this.props.stores.user.inviteRequest.reset();
12 } 14 }
@@ -20,7 +22,9 @@ export default @inject('stores', 'actions') @observer class InviteScreen extends
20 <Invite 22 <Invite
21 onSubmit={actions.user.invite} 23 onSubmit={actions.user.invite}
22 isLoadingInvite={user.inviteRequest.isExecuting} 24 isLoadingInvite={user.inviteRequest.isExecuting}
23 isInviteSuccessful={user.inviteRequest.wasExecuted && !user.inviteRequest.isError} 25 isInviteSuccessful={
26 user.inviteRequest.wasExecuted && !user.inviteRequest.isError
27 }
24 embed 28 embed
25 /> 29 />
26 </ErrorBoundary> 30 </ErrorBoundary>
diff --git a/src/containers/settings/RecipesScreen.js b/src/containers/settings/RecipesScreen.js
index 784052bbe..06ddabe4c 100644
--- a/src/containers/settings/RecipesScreen.js
+++ b/src/containers/settings/RecipesScreen.js
@@ -18,7 +18,9 @@ import RecipePreview from '../../models/RecipePreview';
18import AppStore from '../../stores/AppStore'; 18import AppStore from '../../stores/AppStore';
19import { openPath } from '../../helpers/url-helpers'; 19import { openPath } from '../../helpers/url-helpers';
20 20
21export default @inject('stores', 'actions') @observer class RecipesScreen extends Component { 21@inject('stores', 'actions')
22@observer
23class RecipesScreen extends Component {
22 static propTypes = { 24 static propTypes = {
23 params: PropTypes.shape({ 25 params: PropTypes.shape({
24 filter: PropTypes.string, 26 filter: PropTypes.string,
@@ -75,25 +77,32 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
75 } 77 }
76 78
77 _sortByName(recipe1, recipe2) { 79 _sortByName(recipe1, recipe2) {
78 if (recipe1.name.toLowerCase() < recipe2.name.toLowerCase()) { return -1; } 80 if (recipe1.name.toLowerCase() < recipe2.name.toLowerCase()) {
79 if (recipe1.name.toLowerCase() > recipe2.name.toLowerCase()) { return 1; } 81 return -1;
82 }
83 if (recipe1.name.toLowerCase() > recipe2.name.toLowerCase()) {
84 return 1;
85 }
80 return 0; 86 return 0;
81 } 87 }
82 88
83 prepareRecipes(recipes) { 89 prepareRecipes(recipes) {
84 return recipes 90 return (
85 // Filter out duplicate recipes 91 recipes
86 .filter((recipe, index, self) => { 92 // Filter out duplicate recipes
87 const ids = self.map((rec) => rec.id); 93 .filter((recipe, index, self) => {
88 return ids.indexOf(recipe.id) === index; 94 const ids = self.map(rec => rec.id);
89 95 return ids.indexOf(recipe.id) === index;
90 // Sort alphabetically 96
91 }).sort(this._sortByName); 97 // Sort alphabetically
98 })
99 .sort(this._sortByName)
100 );
92 } 101 }
93 102
94 // Create an array of RecipePreviews from an array of recipe objects 103 // Create an array of RecipePreviews from an array of recipe objects
95 createPreviews(recipes) { 104 createPreviews(recipes) {
96 return recipes.map((recipe) => new RecipePreview(recipe)); 105 return recipes.map(recipe => new RecipePreview(recipe));
97 } 106 }
98 107
99 resetSearch() { 108 resetSearch() {
@@ -101,16 +110,9 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
101 } 110 }
102 111
103 render() { 112 render() {
104 const { 113 const { recipePreviews, recipes, services } = this.props.stores;
105 recipePreviews,
106 recipes,
107 services,
108 } = this.props.stores;
109 114
110 const { 115 const { app: appActions, service: serviceActions } = this.props.actions;
111 app: appActions,
112 service: serviceActions,
113 } = this.props.actions;
114 116
115 const { filter } = { filter: 'all', ...this.props.params }; 117 const { filter } = { filter: 'all', ...this.props.params };
116 let recipeFilter; 118 let recipeFilter;
@@ -125,21 +127,33 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
125 } 127 }
126 recipeFilter = recipeFilter.sort(this._sortByName); 128 recipeFilter = recipeFilter.sort(this._sortByName);
127 129
128 const allRecipes = this.state.needle ? this.prepareRecipes([ 130 const allRecipes = this.state.needle
129 // All search recipes from server 131 ? this.prepareRecipes([
130 ...recipePreviews.searchResults, 132 // All search recipes from server
131 // All search recipes from local recipes 133 ...recipePreviews.searchResults,
132 ...this.createPreviews( 134 // All search recipes from local recipes
133 this.customRecipes 135 ...this.createPreviews(
134 .filter((service) => service.name.toLowerCase().includes(this.state.needle.toLowerCase()) || (service.aliases || []).some(alias => alias.toLowerCase().includes(this.state.needle.toLowerCase()))), 136 this.customRecipes.filter(
135 ), 137 service =>
136 ]).sort(this._sortByName) : recipeFilter; 138 service.name
137 139 .toLowerCase()
138 const customWebsiteRecipe = recipePreviews.all.find((service) => service.id === CUSTOM_WEBSITE_RECIPE_ID); 140 .includes(this.state.needle.toLowerCase()) ||
141 (service.aliases || []).some(alias =>
142 alias.toLowerCase().includes(this.state.needle.toLowerCase()),
143 ),
144 ),
145 ),
146 ]).sort(this._sortByName)
147 : recipeFilter;
148
149 const customWebsiteRecipe = recipePreviews.all.find(
150 service => service.id === CUSTOM_WEBSITE_RECIPE_ID,
151 );
139 152
140 const isLoading = recipePreviews.allRecipePreviewsRequest.isExecuting 153 const isLoading =
141 || recipes.installRecipeRequest.isExecuting 154 recipePreviews.allRecipePreviewsRequest.isExecuting ||
142 || recipePreviews.searchRecipePreviewsRequest.isExecuting; 155 recipes.installRecipeRequest.isExecuting ||
156 recipePreviews.searchRecipePreviewsRequest.isExecuting;
143 157
144 const recipeDirectory = userDataRecipesPath('dev'); 158 const recipeDirectory = userDataRecipesPath('dev');
145 159
@@ -151,14 +165,16 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
151 isLoading={isLoading} 165 isLoading={isLoading}
152 addedServiceCount={services.all.length} 166 addedServiceCount={services.all.length}
153 showAddServiceInterface={serviceActions.showAddServiceInterface} 167 showAddServiceInterface={serviceActions.showAddServiceInterface}
154 searchRecipes={(e) => this.searchRecipes(e)} 168 searchRecipes={e => this.searchRecipes(e)}
155 resetSearch={() => this.resetSearch()} 169 resetSearch={() => this.resetSearch()}
156 searchNeedle={this.state.needle} 170 searchNeedle={this.state.needle}
157 serviceStatus={services.actionStatus} 171 serviceStatus={services.actionStatus}
158 recipeFilter={filter} 172 recipeFilter={filter}
159 recipeDirectory={recipeDirectory} 173 recipeDirectory={recipeDirectory}
160 openRecipeDirectory={() => openPath(recipeDirectory)} 174 openRecipeDirectory={() => openPath(recipeDirectory)}
161 openDevDocs={() => appActions.openExternalUrl({ url: FRANZ_DEV_DOCS })} 175 openDevDocs={() =>
176 appActions.openExternalUrl({ url: FRANZ_DEV_DOCS })
177 }
162 /> 178 />
163 </ErrorBoundary> 179 </ErrorBoundary>
164 ); 180 );
@@ -180,3 +196,5 @@ RecipesScreen.wrappedComponent.propTypes = {
180 }).isRequired, 196 }).isRequired,
181 }).isRequired, 197 }).isRequired,
182}; 198};
199
200export default RecipesScreen;
diff --git a/src/containers/settings/ServicesScreen.js b/src/containers/settings/ServicesScreen.js
index eb2b1bcb5..c9dfc68d0 100644
--- a/src/containers/settings/ServicesScreen.js
+++ b/src/containers/settings/ServicesScreen.js
@@ -10,7 +10,9 @@ import ServiceStore from '../../stores/ServicesStore';
10import ServicesDashboard from '../../components/settings/services/ServicesDashboard'; 10import ServicesDashboard from '../../components/settings/services/ServicesDashboard';
11import ErrorBoundary from '../../components/util/ErrorBoundary'; 11import ErrorBoundary from '../../components/util/ErrorBoundary';
12 12
13export default @inject('stores', 'actions') @observer class ServicesScreen extends Component { 13@inject('stores', 'actions')
14@observer
15class ServicesScreen extends Component {
14 componentWillUnmount() { 16 componentWillUnmount() {
15 this.props.actions.service.resetFilter(); 17 this.props.actions.service.resetFilter();
16 this.props.actions.service.resetStatus(); 18 this.props.actions.service.resetStatus();
@@ -23,11 +25,7 @@ export default @inject('stores', 'actions') @observer class ServicesScreen exten
23 25
24 render() { 26 render() {
25 const { user, services, router } = this.props.stores; 27 const { user, services, router } = this.props.stores;
26 const { 28 const { toggleService, filter, resetFilter } = this.props.actions.service;
27 toggleService,
28 filter,
29 resetFilter,
30 } = this.props.actions.service;
31 const isLoading = services.allServicesRequest.isExecuting; 29 const isLoading = services.allServicesRequest.isExecuting;
32 30
33 let allServices = services.all; 31 let allServices = services.all;
@@ -47,7 +45,10 @@ export default @inject('stores', 'actions') @observer class ServicesScreen exten
47 filterServices={filter} 45 filterServices={filter}
48 resetFilter={resetFilter} 46 resetFilter={resetFilter}
49 goTo={router.push} 47 goTo={router.push}
50 servicesRequestFailed={services.allServicesRequest.wasExecuted && services.allServicesRequest.isError} 48 servicesRequestFailed={
49 services.allServicesRequest.wasExecuted &&
50 services.allServicesRequest.isError
51 }
51 retryServicesRequest={() => services.allServicesRequest.reload()} 52 retryServicesRequest={() => services.allServicesRequest.reload()}
52 searchNeedle={services.filterNeedle} 53 searchNeedle={services.filterNeedle}
53 /> 54 />
@@ -66,3 +67,5 @@ ServicesScreen.wrappedComponent.propTypes = {
66 service: PropTypes.instanceOf(ServiceStore).isRequired, 67 service: PropTypes.instanceOf(ServiceStore).isRequired,
67 }).isRequired, 68 }).isRequired,
68}; 69};
70
71export default ServicesScreen;
diff --git a/src/containers/settings/SettingsWindow.js b/src/containers/settings/SettingsWindow.js
index 9bb64b6fe..58e73f2f3 100644
--- a/src/containers/settings/SettingsWindow.js
+++ b/src/containers/settings/SettingsWindow.js
@@ -11,7 +11,9 @@ import ErrorBoundary from '../../components/util/ErrorBoundary';
11import { workspaceStore } from '../../features/workspaces'; 11import { workspaceStore } from '../../features/workspaces';
12import UIStore from '../../stores/UIStore'; 12import UIStore from '../../stores/UIStore';
13 13
14export default @inject('stores', 'actions') @observer class SettingsContainer extends Component { 14@inject('stores', 'actions')
15@observer
16class SettingsContainer extends Component {
15 portalRoot = document.querySelector('#portalContainer'); 17 portalRoot = document.querySelector('#portalContainer');
16 18
17 el = document.createElement('div'); 19 el = document.createElement('div');
@@ -36,16 +38,11 @@ export default @inject('stores', 'actions') @observer class SettingsContainer ex
36 ); 38 );
37 39
38 return ReactDOM.createPortal( 40 return ReactDOM.createPortal(
39 ( 41 <ErrorBoundary>
40 <ErrorBoundary> 42 <Layout navigation={navigation} closeSettings={closeSettings}>
41 <Layout 43 {children}
42 navigation={navigation} 44 </Layout>
43 closeSettings={closeSettings} 45 </ErrorBoundary>,
44 >
45 {children}
46 </Layout>
47 </ErrorBoundary>
48 ),
49 this.el, 46 this.el,
50 ); 47 );
51 } 48 }
@@ -60,3 +57,5 @@ SettingsContainer.wrappedComponent.propTypes = {
60 ui: PropTypes.instanceOf(UIStore).isRequired, 57 ui: PropTypes.instanceOf(UIStore).isRequired,
61 }).isRequired, 58 }).isRequired,
62}; 59};
60
61export default SettingsContainer;
diff --git a/src/containers/settings/SupportScreen.js b/src/containers/settings/SupportScreen.js
index 7d3b22f19..646f672ce 100644
--- a/src/containers/settings/SupportScreen.js
+++ b/src/containers/settings/SupportScreen.js
@@ -6,7 +6,8 @@ import SupportFerdi from '../../components/settings/supportFerdi/SupportFerdiDas
6import ErrorBoundary from '../../components/util/ErrorBoundary'; 6import ErrorBoundary from '../../components/util/ErrorBoundary';
7import AppStore from '../../stores/AppStore'; 7import AppStore from '../../stores/AppStore';
8 8
9export default @inject('actions') class SupportScreen extends Component { 9@inject('actions')
10class SupportScreen extends Component {
10 constructor(props) { 11 constructor(props) {
11 super(props); 12 super(props);
12 13
@@ -20,9 +21,7 @@ export default @inject('actions') class SupportScreen extends Component {
20 render() { 21 render() {
21 return ( 22 return (
22 <ErrorBoundary> 23 <ErrorBoundary>
23 <SupportFerdi 24 <SupportFerdi openLink={this.openLink} />
24 openLink={this.openLink}
25 />
26 </ErrorBoundary> 25 </ErrorBoundary>
27 ); 26 );
28 } 27 }
@@ -33,3 +32,5 @@ SupportScreen.wrappedComponent.propTypes = {
33 app: PropTypes.instanceOf(AppStore).isRequired, 32 app: PropTypes.instanceOf(AppStore).isRequired,
34 }).isRequired, 33 }).isRequired,
35}; 34};
35
36export default SupportScreen;
diff --git a/src/containers/settings/TeamScreen.js b/src/containers/settings/TeamScreen.js
index 10c2e36ef..ea447469b 100644
--- a/src/containers/settings/TeamScreen.js
+++ b/src/containers/settings/TeamScreen.js
@@ -10,7 +10,9 @@ import TeamDashboard from '../../components/settings/team/TeamDashboard';
10import ErrorBoundary from '../../components/util/ErrorBoundary'; 10import ErrorBoundary from '../../components/util/ErrorBoundary';
11import { DEV_API_FRANZ_WEBSITE } from '../../config'; 11import { DEV_API_FRANZ_WEBSITE } from '../../config';
12 12
13export default @inject('stores', 'actions') @observer class TeamScreen extends Component { 13@inject('stores', 'actions')
14@observer
15class TeamScreen extends Component {
14 handleWebsiteLink(route) { 16 handleWebsiteLink(route) {
15 const { actions, stores } = this.props; 17 const { actions, stores } = this.props;
16 18
@@ -29,7 +31,10 @@ export default @inject('stores', 'actions') @observer class TeamScreen extends C
29 <ErrorBoundary> 31 <ErrorBoundary>
30 <TeamDashboard 32 <TeamDashboard
31 isLoading={isLoadingUserInfo} 33 isLoading={isLoadingUserInfo}
32 userInfoRequestFailed={user.getUserInfoRequest.wasExecuted && user.getUserInfoRequest.isError} 34 userInfoRequestFailed={
35 user.getUserInfoRequest.wasExecuted &&
36 user.getUserInfoRequest.isError
37 }
33 retryUserInfoRequest={() => this.reloadData()} 38 retryUserInfoRequest={() => this.reloadData()}
34 openTeamManagement={() => this.handleWebsiteLink('/user/team')} 39 openTeamManagement={() => this.handleWebsiteLink('/user/team')}
35 server={server} 40 server={server}
@@ -50,3 +55,5 @@ TeamScreen.wrappedComponent.propTypes = {
50 user: PropTypes.instanceOf(UserStore).isRequired, 55 user: PropTypes.instanceOf(UserStore).isRequired,
51 }).isRequired, 56 }).isRequired,
52}; 57};
58
59export default TeamScreen;
diff --git a/src/features/basicAuth/Component.js b/src/features/basicAuth/Component.js
index a9601836b..3cf937f98 100644
--- a/src/features/basicAuth/Component.js
+++ b/src/features/basicAuth/Component.js
@@ -2,19 +2,14 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import injectSheet from 'react-jss'; 3import injectSheet from 'react-jss';
4import { observer } from 'mobx-react'; 4import { observer } from 'mobx-react';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6import classnames from 'classnames'; 6import classnames from 'classnames';
7 7
8import Modal from '../../components/ui/Modal'; 8import Modal from '../../components/ui/Modal';
9import Input from '../../components/ui/Input'; 9import Input from '../../components/ui/Input';
10import Button from '../../components/ui/Button'; 10import Button from '../../components/ui/Button';
11 11
12import { 12import { state, resetState, sendCredentials, cancelLogin } from './store';
13 state,
14 resetState,
15 sendCredentials,
16 cancelLogin,
17} from './store';
18import Form from './Form'; 13import Form from './Form';
19 14
20import styles from './styles'; 15import styles from './styles';
@@ -23,17 +18,15 @@ import globalMessages from '../../i18n/globalMessages';
23const messages = defineMessages({ 18const messages = defineMessages({
24 signIn: { 19 signIn: {
25 id: 'feature.basicAuth.signIn', 20 id: 'feature.basicAuth.signIn',
26 defaultMessage: '!!!Sign In', 21 defaultMessage: 'Sign In',
27 }, 22 },
28}); 23});
29 24
30export default @injectSheet(styles) @observer class BasicAuthModal extends Component { 25@injectSheet(styles)
26@observer
27class BasicAuthModal extends Component {
31 static propTypes = { 28 static propTypes = {
32 classes: PropTypes.object.isRequired, 29 classes: PropTypes.object.isRequired,
33 }
34
35 static contextTypes = {
36 intl: intlShape,
37 }; 30 };
38 31
39 submit(e) { 32 submit(e) {
@@ -56,20 +49,15 @@ export default @injectSheet(styles) @observer class BasicAuthModal extends Compo
56 } 49 }
57 50
58 render() { 51 render() {
59 const { 52 const { classes } = this.props;
60 classes,
61 } = this.props;
62 53
63 const { 54 const { isModalVisible, authInfo } = state;
64 isModalVisible,
65 authInfo,
66 } = state;
67 55
68 if (!authInfo) { 56 if (!authInfo) {
69 return null; 57 return null;
70 } 58 }
71 59
72 const { intl } = this.context; 60 const { intl } = this.props;
73 61
74 return ( 62 return (
75 <Modal 63 <Modal
@@ -89,10 +77,7 @@ export default @injectSheet(styles) @observer class BasicAuthModal extends Compo
89 onSubmit={this.submit.bind(this)} 77 onSubmit={this.submit.bind(this)}
90 className={classnames('franz-form', classes.form)} 78 className={classnames('franz-form', classes.form)}
91 > 79 >
92 <Input 80 <Input field={Form.$('user')} showLabel={false} />
93 field={Form.$('user')}
94 showLabel={false}
95 />
96 <Input 81 <Input
97 field={Form.$('password')} 82 field={Form.$('password')}
98 showLabel={false} 83 showLabel={false}
@@ -105,13 +90,11 @@ export default @injectSheet(styles) @observer class BasicAuthModal extends Compo
105 buttonType="secondary" 90 buttonType="secondary"
106 onClick={this.cancel.bind(this)} 91 onClick={this.cancel.bind(this)}
107 /> 92 />
108 <Button 93 <Button type="submit" label={intl.formatMessage(messages.signIn)} />
109 type="submit"
110 label={intl.formatMessage(messages.signIn)}
111 />
112 </div> 94 </div>
113 </form> 95 </form>
114 </Modal> 96 </Modal>
115 ); 97 );
116 } 98 }
117} 99}
100export default injectIntl(BasicAuthModal);
diff --git a/src/features/nightlyBuilds/Component.js b/src/features/nightlyBuilds/Component.js
index e43287db5..814d529d9 100644
--- a/src/features/nightlyBuilds/Component.js
+++ b/src/features/nightlyBuilds/Component.js
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, inject } from 'mobx-react'; 3import { observer, inject } from 'mobx-react';
4import injectSheet from 'react-jss'; 4import injectSheet from 'react-jss';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6import { H1 } from '@meetfranz/ui'; 6import { H1 } from '@meetfranz/ui';
7 7
8import Modal from '../../components/ui/Modal'; 8import Modal from '../../components/ui/Modal';
@@ -16,15 +16,16 @@ import globalMessages from '../../i18n/globalMessages';
16const messages = defineMessages({ 16const messages = defineMessages({
17 title: { 17 title: {
18 id: 'feature.nightlyBuilds.title', 18 id: 'feature.nightlyBuilds.title',
19 defaultMessage: '!!!Nightly Builds', 19 defaultMessage: 'Nightly Builds',
20 }, 20 },
21 info: { 21 info: {
22 id: 'feature.nightlyBuilds.info', 22 id: 'feature.nightlyBuilds.info',
23 defaultMessage: '!!!Nightly builds are highly experimental versions of Ferdi that may contain unpolished or uncompleted features. These nightly builds are mainly used by developers to test their newly developed features and how they will perform in the final build. If you don\'t know what you are doing, we suggest not activating nightly builds.', 23 defaultMessage:
24 "Nightly builds are highly experimental versions of Ferdi that may contain unpolished or uncompleted features. These nightly builds are mainly used by developers to test their newly developed features and how they will perform in the final build. If you don't know what you are doing, we suggest not activating nightly builds.",
24 }, 25 },
25 activate: { 26 activate: {
26 id: 'feature.nightlyBuilds.activate', 27 id: 'feature.nightlyBuilds.activate',
27 defaultMessage: '!!!Activate', 28 defaultMessage: 'Activate',
28 }, 29 },
29}); 30});
30 31
@@ -52,11 +53,10 @@ const styles = () => ({
52 }, 53 },
53}); 54});
54 55
55export default @injectSheet(styles) @inject('stores', 'actions') @observer class NightlyBuildsModal extends Component { 56@injectSheet(styles)
56 static contextTypes = { 57@inject('stores', 'actions')
57 intl: intlShape, 58@observer
58 }; 59class NightlyBuildsModal extends Component {
59
60 close() { 60 close() {
61 ModalState.isModalVisible = false; 61 ModalState.isModalVisible = false;
62 62
@@ -84,11 +84,9 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class
84 render() { 84 render() {
85 const { isModalVisible } = ModalState; 85 const { isModalVisible } = ModalState;
86 86
87 const { 87 const { classes } = this.props;
88 classes,
89 } = this.props;
90 88
91 const { intl } = this.context; 89 const { intl } = this.props;
92 90
93 return ( 91 return (
94 <Modal 92 <Modal
@@ -132,3 +130,5 @@ NightlyBuildsModal.wrappedComponent.propTypes = {
132 }).isRequired, 130 }).isRequired,
133 classes: PropTypes.object.isRequired, 131 classes: PropTypes.object.isRequired,
134}; 132};
133
134export default injectIntl(NightlyBuildsModal);
diff --git a/src/features/publishDebugInfo/Component.js b/src/features/publishDebugInfo/Component.js
index 5387bd358..5b5036752 100644
--- a/src/features/publishDebugInfo/Component.js
+++ b/src/features/publishDebugInfo/Component.js
@@ -2,7 +2,7 @@ import { H1 } from '@meetfranz/ui';
2import { inject, observer } from 'mobx-react'; 2import { inject, observer } from 'mobx-react';
3import PropTypes from 'prop-types'; 3import PropTypes from 'prop-types';
4import React, { Component } from 'react'; 4import React, { Component } from 'react';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6import injectSheet from 'react-jss'; 6import injectSheet from 'react-jss';
7import { state as ModalState } from './store'; 7import { state as ModalState } from './store';
8import { sendAuthRequest } from '../../api/utils/auth'; 8import { sendAuthRequest } from '../../api/utils/auth';
@@ -18,35 +18,37 @@ const debug = require('debug')('Ferdi:feature:publishDebugInfo');
18const messages = defineMessages({ 18const messages = defineMessages({
19 title: { 19 title: {
20 id: 'feature.publishDebugInfo.title', 20 id: 'feature.publishDebugInfo.title',
21 defaultMessage: '!!!Publish debug information', 21 defaultMessage: 'Publish debug information',
22 }, 22 },
23 info: { 23 info: {
24 id: 'feature.publishDebugInfo.info', 24 id: 'feature.publishDebugInfo.info',
25 defaultMessage: '!!!Publishing your debug information helps us find issues and errors in Ferdi. By publishing your debug information you accept Ferdi Debugger\'s privacy policy and terms of service', 25 defaultMessage:
26 "Publishing your debug information helps us find issues and errors in Ferdi. By publishing your debug information you accept Ferdi Debugger's privacy policy and terms of service",
26 }, 27 },
27 error: { 28 error: {
28 id: 'feature.publishDebugInfo.error', 29 id: 'feature.publishDebugInfo.error',
29 defaultMessage: '!!!There was an error while trying to publish the debug information. Please try again later or view the console for more information.', 30 defaultMessage:
31 'There was an error while trying to publish the debug information. Please try again later or view the console for more information.',
30 }, 32 },
31 privacy: { 33 privacy: {
32 id: 'feature.publishDebugInfo.privacy', 34 id: 'feature.publishDebugInfo.privacy',
33 defaultMessage: '!!!Privacy policy', 35 defaultMessage: 'Privacy policy',
34 }, 36 },
35 terms: { 37 terms: {
36 id: 'feature.publishDebugInfo.terms', 38 id: 'feature.publishDebugInfo.terms',
37 defaultMessage: '!!!Terms of service', 39 defaultMessage: 'Terms of service',
38 }, 40 },
39 publish: { 41 publish: {
40 id: 'feature.publishDebugInfo.publish', 42 id: 'feature.publishDebugInfo.publish',
41 defaultMessage: '!!!Accept and publish', 43 defaultMessage: 'Accept and publish',
42 }, 44 },
43 published: { 45 published: {
44 id: 'feature.publishDebugInfo.published', 46 id: 'feature.publishDebugInfo.published',
45 defaultMessage: '!!!Your debug log was published and is now availible at', 47 defaultMessage: 'Your debug log was published and is now availible at',
46 }, 48 },
47}); 49});
48 50
49const styles = (theme) => ({ 51const styles = theme => ({
50 container: { 52 container: {
51 minWidth: '70vw', 53 minWidth: '70vw',
52 }, 54 },
@@ -69,7 +71,8 @@ const styles = (theme) => ({
69 width: '100%', 71 width: '100%',
70 72
71 '& div': { 73 '& div': {
72 fontFamily: 'SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace', 74 fontFamily:
75 'SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace',
73 }, 76 },
74 77
75 '& input': { 78 '& input': {
@@ -81,20 +84,19 @@ const styles = (theme) => ({
81 }, 84 },
82}); 85});
83 86
84export default @injectSheet(styles) @inject('stores', 'actions') @observer class PublishDebugLogModal extends Component { 87@injectSheet(styles)
88@inject('stores', 'actions')
89@observer
90class PublishDebugLogModal extends Component {
85 static propTypes = { 91 static propTypes = {
86 classes: PropTypes.object.isRequired, 92 classes: PropTypes.object.isRequired,
87 }; 93 };
88 94
89 static contextTypes = {
90 intl: intlShape,
91 };
92
93 state = { 95 state = {
94 log: null, 96 log: null,
95 error: false, 97 error: false,
96 isSendingLog: false, 98 isSendingLog: false,
97 } 99 };
98 100
99 // Close this modal 101 // Close this modal
100 close() { 102 close() {
@@ -109,12 +111,16 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class
109 111
110 const debugInfo = JSON.stringify(this.props.stores.app.debugInfo); 112 const debugInfo = JSON.stringify(this.props.stores.app.debugInfo);
111 113
112 const request = await sendAuthRequest(`${DEBUG_API}/create`, { 114 const request = await sendAuthRequest(
113 method: 'POST', 115 `${DEBUG_API}/create`,
114 body: JSON.stringify({ 116 {
115 log: debugInfo, 117 method: 'POST',
116 }), 118 body: JSON.stringify({
117 }, false); 119 log: debugInfo,
120 }),
121 },
122 false,
123 );
118 124
119 debug(`debugInfo: publishing status: ${request.status}`); 125 debug(`debugInfo: publishing status: ${request.status}`);
120 if (request.status === 200) { 126 if (request.status === 200) {
@@ -140,17 +146,11 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class
140 render() { 146 render() {
141 const { isModalVisible } = ModalState; 147 const { isModalVisible } = ModalState;
142 148
143 const { 149 const { classes } = this.props;
144 classes,
145 } = this.props;
146 150
147 const { 151 const { log, error, isSendingLog } = this.state;
148 log,
149 error,
150 isSendingLog,
151 } = this.state;
152 152
153 const { intl } = this.context; 153 const { intl } = this.props;
154 154
155 return ( 155 return (
156 <Modal 156 <Modal
@@ -159,12 +159,12 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class
159 close={() => this.close()} 159 close={() => this.close()}
160 > 160 >
161 <div className={classes.container}> 161 <div className={classes.container}>
162 <H1> 162 <H1>{intl.formatMessage(messages.title)}</H1>
163 {intl.formatMessage(messages.title)} 163 {log && (
164 </H1>
165 { log && (
166 <> 164 <>
167 <p className={classes.info}>{intl.formatMessage(messages.published)}</p> 165 <p className={classes.info}>
166 {intl.formatMessage(messages.published)}
167 </p>
168 <Input 168 <Input
169 className={classes.url} 169 className={classes.url}
170 showLabel={false} 170 showLabel={false}
@@ -184,12 +184,24 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class
184 184
185 {!log && !error && ( 185 {!log && !error && (
186 <> 186 <>
187 <p className={classes.info}>{intl.formatMessage(messages.info)}</p> 187 <p className={classes.info}>
188 188 {intl.formatMessage(messages.info)}
189 <a href={`${DEBUG_API}/privacy.html`} target="_blank" className={classes.link} rel="noreferrer"> 189 </p>
190
191 <a
192 href={`${DEBUG_API}/privacy.html`}
193 target="_blank"
194 className={classes.link}
195 rel="noreferrer"
196 >
190 {intl.formatMessage(messages.privacy)} 197 {intl.formatMessage(messages.privacy)}
191 </a> 198 </a>
192 <a href={`${DEBUG_API}/terms.html`} target="_blank" className={classes.link} rel="noreferrer"> 199 <a
200 href={`${DEBUG_API}/terms.html`}
201 target="_blank"
202 className={classes.link}
203 rel="noreferrer"
204 >
193 {intl.formatMessage(messages.terms)} 205 {intl.formatMessage(messages.terms)}
194 </a> 206 </a>
195 207
@@ -216,3 +228,5 @@ PublishDebugLogModal.wrappedComponent.propTypes = {
216 service: PropTypes.instanceOf(ServicesStore).isRequired, 228 service: PropTypes.instanceOf(ServicesStore).isRequired,
217 }).isRequired, 229 }).isRequired,
218}; 230};
231
232export default injectIntl(PublishDebugLogModal);
diff --git a/src/features/quickSwitch/Component.js b/src/features/quickSwitch/Component.js
index 78d5d94a0..df2bf968d 100644
--- a/src/features/quickSwitch/Component.js
+++ b/src/features/quickSwitch/Component.js
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
4import { observer, inject } from 'mobx-react'; 4import { observer, inject } from 'mobx-react';
5import { reaction } from 'mobx'; 5import { reaction } from 'mobx';
6import injectSheet from 'react-jss'; 6import injectSheet from 'react-jss';
7import { defineMessages, intlShape } from 'react-intl'; 7import { defineMessages, injectIntl } from 'react-intl';
8import { Input } from '@meetfranz/forms'; 8import { Input } from '@meetfranz/forms';
9import { H1 } from '@meetfranz/ui'; 9import { H1 } from '@meetfranz/ui';
10 10
@@ -16,19 +16,20 @@ import ServicesStore from '../../stores/ServicesStore';
16const messages = defineMessages({ 16const messages = defineMessages({
17 title: { 17 title: {
18 id: 'feature.quickSwitch.title', 18 id: 'feature.quickSwitch.title',
19 defaultMessage: '!!!QuickSwitch', 19 defaultMessage: 'QuickSwitch',
20 }, 20 },
21 search: { 21 search: {
22 id: 'feature.quickSwitch.search', 22 id: 'feature.quickSwitch.search',
23 defaultMessage: '!!!Search...', 23 defaultMessage: 'Search...',
24 }, 24 },
25 info: { 25 info: {
26 id: 'feature.quickSwitch.info', 26 id: 'feature.quickSwitch.info',
27 defaultMessage: '!!!Select a service with TAB, ↑ and ↓. Open a service with ENTER.', 27 defaultMessage:
28 'Select a service with TAB, ↑ and ↓. Open a service with ENTER.',
28 }, 29 },
29}); 30});
30 31
31const styles = (theme) => ({ 32const styles = theme => ({
32 modal: { 33 modal: {
33 width: '80%', 34 width: '80%',
34 maxWidth: 600, 35 maxWidth: 600,
@@ -80,20 +81,19 @@ const styles = (theme) => ({
80 }, 81 },
81}); 82});
82 83
83export default @injectSheet(styles) @inject('stores', 'actions') @observer class QuickSwitchModal extends Component { 84@injectSheet(styles)
85@inject('stores', 'actions')
86@observer
87class QuickSwitchModal extends Component {
84 static propTypes = { 88 static propTypes = {
85 classes: PropTypes.object.isRequired, 89 classes: PropTypes.object.isRequired,
86 }; 90 };
87 91
88 static contextTypes = {
89 intl: intlShape,
90 };
91
92 state = { 92 state = {
93 selected: 0, 93 selected: 0,
94 search: '', 94 search: '',
95 wasPrevVisible: false, 95 wasPrevVisible: false,
96 } 96 };
97 97
98 ARROW_DOWN = 40; 98 ARROW_DOWN = 40;
99 99
@@ -118,9 +118,7 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class
118 this.openService = this.openService.bind(this); 118 this.openService = this.openService.bind(this);
119 119
120 reaction( 120 reaction(
121 () => ( 121 () => ModalState.isModalVisible,
122 ModalState.isModalVisible
123 ),
124 () => { 122 () => {
125 this._handleVisibilityChange(); 123 this._handleVisibilityChange();
126 }, 124 },
@@ -140,10 +138,17 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class
140 // Get currently shown services 138 // Get currently shown services
141 services() { 139 services() {
142 let services = []; 140 let services = [];
143 if (this.state.search && compact(invoke(this.state.search, 'match', /^[a-z0-9]/i)).length > 0) { 141 if (
142 this.state.search &&
143 compact(invoke(this.state.search, 'match', /^[a-z0-9]/i)).length > 0
144 ) {
144 // Apply simple search algorythm to list of all services 145 // Apply simple search algorythm to list of all services
145 services = this.props.stores.services.allDisplayed; 146 services = this.props.stores.services.allDisplayed;
146 services = services.filter((service) => service.name.toLowerCase().search(this.state.search.toLowerCase()) !== -1); 147 services = services.filter(
148 service =>
149 service.name.toLowerCase().search(this.state.search.toLowerCase()) !==
150 -1,
151 );
147 } else { 152 } else {
148 // Add the currently active service first 153 // Add the currently active service first
149 const currentService = this.props.stores.services.active; 154 const currentService = this.props.stores.services.active;
@@ -186,14 +191,14 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class
186 // Change the selected service 191 // Change the selected service
187 // factor should be -1 or 1 192 // factor should be -1 or 1
188 changeSelected(factor) { 193 changeSelected(factor) {
189 this.setState((state) => { 194 this.setState(state => {
190 let newSelected = state.selected + factor; 195 let newSelected = state.selected + factor;
191 const services = this.services().length; 196 const services = this.services().length;
192 197
193 // Roll around when on edge of list 198 // Roll around when on edge of list
194 if (state.selected < 1 && factor === -1) { 199 if (state.selected < 1 && factor === -1) {
195 newSelected = services - 1; 200 newSelected = services - 1;
196 } else if ((state.selected >= (services - 1)) && factor === 1) { 201 } else if (state.selected >= services - 1 && factor === 1) {
197 newSelected = 0; 202 newSelected = 0;
198 } 203 }
199 204
@@ -286,17 +291,13 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class
286 render() { 291 render() {
287 const { isModalVisible } = ModalState; 292 const { isModalVisible } = ModalState;
288 293
289 const { 294 const { openService } = this;
290 openService,
291 } = this;
292 295
293 const { 296 const { classes } = this.props;
294 classes,
295 } = this.props;
296 297
297 const services = this.services(); 298 const services = this.services();
298 299
299 const { intl } = this.context; 300 const { intl } = this.props;
300 301
301 return ( 302 return (
302 <Modal 303 <Modal
@@ -318,12 +319,16 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class
318 </div> 319 </div>
319 320
320 <div className={classes.services}> 321 <div className={classes.services}>
321 { services.map((service, index) => ( 322 {services.map((service, index) => (
322 <div 323 <div
323 className={`${classes.service} ${this.state.selected === index ? `${classes.activeService} active` : ''} service`} 324 className={`${classes.service} ${
325 this.state.selected === index
326 ? `${classes.activeService} active`
327 : ''
328 } service`}
324 onClick={() => openService(index)} 329 onClick={() => openService(index)}
325 key={service.id} 330 key={service.id}
326 ref={(el) => { 331 ref={el => {
327 this.serviceElements[index] = el; 332 this.serviceElements[index] = el;
328 }} 333 }}
329 > 334 >
@@ -332,9 +337,7 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class
332 className={classes.serviceIcon} 337 className={classes.serviceIcon}
333 alt={service.recipe.name} 338 alt={service.recipe.name}
334 /> 339 />
335 <div> 340 <div>{service.name}</div>
336 { service.name }
337 </div>
338 </div> 341 </div>
339 ))} 342 ))}
340 </div> 343 </div>
@@ -356,3 +359,5 @@ QuickSwitchModal.wrappedComponent.propTypes = {
356 service: PropTypes.instanceOf(ServicesStore).isRequired, 359 service: PropTypes.instanceOf(ServicesStore).isRequired,
357 }).isRequired, 360 }).isRequired,
358}; 361};
362
363export default injectIntl(QuickSwitchModal);
diff --git a/src/features/webControls/components/WebControls.js b/src/features/webControls/components/WebControls.js
index bebf52c08..97fa20dcc 100644
--- a/src/features/webControls/components/WebControls.js
+++ b/src/features/webControls/components/WebControls.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import injectSheet from 'react-jss'; 4import injectSheet from 'react-jss';
5import { Icon } from '@meetfranz/ui'; 5import { Icon } from '@meetfranz/ui';
6import { defineMessages, intlShape } from 'react-intl'; 6import { defineMessages, injectIntl } from 'react-intl';
7 7
8import { 8import {
9 mdiReload, 9 mdiReload,
@@ -16,23 +16,23 @@ import {
16const messages = defineMessages({ 16const messages = defineMessages({
17 goHome: { 17 goHome: {
18 id: 'webControls.goHome', 18 id: 'webControls.goHome',
19 defaultMessage: '!!!Home', 19 defaultMessage: 'Home',
20 }, 20 },
21 openInBrowser: { 21 openInBrowser: {
22 id: 'webControls.openInBrowser', 22 id: 'webControls.openInBrowser',
23 defaultMessage: '!!!Open in Browser', 23 defaultMessage: 'Open in Browser',
24 }, 24 },
25 back: { 25 back: {
26 id: 'webControls.back', 26 id: 'webControls.back',
27 defaultMessage: '!!!Back', 27 defaultMessage: 'Back',
28 }, 28 },
29 forward: { 29 forward: {
30 id: 'webControls.forward', 30 id: 'webControls.forward',
31 defaultMessage: '!!!Forward', 31 defaultMessage: 'Forward',
32 }, 32 },
33 reload: { 33 reload: {
34 id: 'webControls.reload', 34 id: 'webControls.reload',
35 defaultMessage: '!!!Reload', 35 defaultMessage: 'Reload',
36 }, 36 },
37}); 37});
38 38
@@ -109,10 +109,6 @@ class WebControls extends Component {
109 navigate: PropTypes.func.isRequired, 109 navigate: PropTypes.func.isRequired,
110 }; 110 };
111 111
112 static contextTypes = {
113 intl: intlShape,
114 };
115
116 static getDerivedStateFromProps(props, state) { 112 static getDerivedStateFromProps(props, state) {
117 const { url } = props; 113 const { url } = props;
118 const { editUrl } = state; 114 const { editUrl } = state;
@@ -148,7 +144,7 @@ class WebControls extends Component {
148 144
149 const { inputUrl, editUrl } = this.state; 145 const { inputUrl, editUrl } = this.state;
150 146
151 const { intl } = this.context; 147 const { intl } = this.props;
152 148
153 return ( 149 return (
154 <div className={classes.root}> 150 <div className={classes.root}>
@@ -241,4 +237,4 @@ class WebControls extends Component {
241 } 237 }
242} 238}
243 239
244export default WebControls; 240export default injectIntl(WebControls);
diff --git a/src/features/workspaces/components/CreateWorkspaceForm.js b/src/features/workspaces/components/CreateWorkspaceForm.js
index 15b97121d..c9b05b87f 100644
--- a/src/features/workspaces/components/CreateWorkspaceForm.js
+++ b/src/features/workspaces/components/CreateWorkspaceForm.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import { Input, Button } from '@meetfranz/forms'; 5import { Input, Button } from '@meetfranz/forms';
6import injectSheet from 'react-jss'; 6import injectSheet from 'react-jss';
7import Form from '../../../lib/Form'; 7import Form from '../../../lib/Form';
@@ -11,11 +11,11 @@ import { workspaceStore } from '../index';
11const messages = defineMessages({ 11const messages = defineMessages({
12 submitButton: { 12 submitButton: {
13 id: 'settings.workspace.add.form.submitButton', 13 id: 'settings.workspace.add.form.submitButton',
14 defaultMessage: '!!!Create workspace', 14 defaultMessage: 'Create workspace',
15 }, 15 },
16 name: { 16 name: {
17 id: 'settings.workspace.add.form.name', 17 id: 'settings.workspace.add.form.name',
18 defaultMessage: '!!!Name', 18 defaultMessage: 'Name',
19 }, 19 },
20}); 20});
21 21
@@ -32,12 +32,9 @@ const styles = () => ({
32 }, 32 },
33}); 33});
34 34
35@injectSheet(styles) @observer 35@injectSheet(styles)
36@observer
36class CreateWorkspaceForm extends Component { 37class CreateWorkspaceForm extends Component {
37 static contextTypes = {
38 intl: intlShape,
39 };
40
41 static propTypes = { 38 static propTypes = {
42 classes: PropTypes.object.isRequired, 39 classes: PropTypes.object.isRequired,
43 isSubmitting: PropTypes.bool.isRequired, 40 isSubmitting: PropTypes.bool.isRequired,
@@ -45,7 +42,7 @@ class CreateWorkspaceForm extends Component {
45 }; 42 };
46 43
47 form = (() => { 44 form = (() => {
48 const { intl } = this.context; 45 const { intl } = this.props;
49 return new Form({ 46 return new Form({
50 fields: { 47 fields: {
51 name: { 48 name: {
@@ -61,7 +58,7 @@ class CreateWorkspaceForm extends Component {
61 submitForm() { 58 submitForm() {
62 const { form } = this; 59 const { form } = this;
63 form.submit({ 60 form.submit({
64 onSuccess: async (f) => { 61 onSuccess: async f => {
65 const { onSubmit } = this.props; 62 const { onSubmit } = this.props;
66 const values = f.values(); 63 const values = f.values();
67 onSubmit(values); 64 onSubmit(values);
@@ -70,7 +67,7 @@ class CreateWorkspaceForm extends Component {
70 } 67 }
71 68
72 render() { 69 render() {
73 const { intl } = this.context; 70 const { intl } = this.props;
74 const { classes, isSubmitting } = this.props; 71 const { classes, isSubmitting } = this.props;
75 const { form } = this; 72 const { form } = this;
76 return ( 73 return (
@@ -95,4 +92,4 @@ class CreateWorkspaceForm extends Component {
95 } 92 }
96} 93}
97 94
98export default CreateWorkspaceForm; 95export default injectIntl(CreateWorkspaceForm);
diff --git a/src/features/workspaces/components/EditWorkspaceForm.js b/src/features/workspaces/components/EditWorkspaceForm.js
index c97d4bd9c..cae95e9ed 100644
--- a/src/features/workspaces/components/EditWorkspaceForm.js
+++ b/src/features/workspaces/components/EditWorkspaceForm.js
@@ -1,7 +1,7 @@
1import React, { Component, Fragment } from 'react'; 1import React, { Component, Fragment } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import { Link } from 'react-router'; 5import { Link } from 'react-router';
6import { Input, Button } from '@meetfranz/forms'; 6import { Input, Button } from '@meetfranz/forms';
7import injectSheet from 'react-jss'; 7import injectSheet from 'react-jss';
@@ -20,40 +20,40 @@ import Toggle from '../../../components/ui/Toggle';
20const messages = defineMessages({ 20const messages = defineMessages({
21 buttonDelete: { 21 buttonDelete: {
22 id: 'settings.workspace.form.buttonDelete', 22 id: 'settings.workspace.form.buttonDelete',
23 defaultMessage: '!!!Delete workspace', 23 defaultMessage: 'Delete workspace',
24 }, 24 },
25 buttonSave: { 25 buttonSave: {
26 id: 'settings.workspace.form.buttonSave', 26 id: 'settings.workspace.form.buttonSave',
27 defaultMessage: '!!!Save workspace', 27 defaultMessage: 'Save workspace',
28 }, 28 },
29 name: { 29 name: {
30 id: 'settings.workspace.form.name', 30 id: 'settings.workspace.form.name',
31 defaultMessage: '!!!Name', 31 defaultMessage: 'Name',
32 }, 32 },
33 yourWorkspaces: { 33 yourWorkspaces: {
34 id: 'settings.workspace.form.yourWorkspaces', 34 id: 'settings.workspace.form.yourWorkspaces',
35 defaultMessage: '!!!Your workspaces', 35 defaultMessage: 'Your workspaces',
36 }, 36 },
37 keepLoaded: { 37 keepLoaded: {
38 id: 'settings.workspace.form.keepLoaded', 38 id: 'settings.workspace.form.keepLoaded',
39 defaultMessage: '!!!Keep this workspace loaded*', 39 defaultMessage: 'Keep this workspace loaded*',
40 }, 40 },
41 keepLoadedInfo: { 41 keepLoadedInfo: {
42 id: 'settings.workspace.form.keepLoadedInfo', 42 id: 'settings.workspace.form.keepLoadedInfo',
43 defaultMessage: 43 defaultMessage:
44 '!!!*This option will be overwritten by the global "Keep all workspaces loaded" option.', 44 '*This option will be overwritten by the global "Keep all workspaces loaded" option.',
45 }, 45 },
46 servicesInWorkspaceHeadline: { 46 servicesInWorkspaceHeadline: {
47 id: 'settings.workspace.form.servicesInWorkspaceHeadline', 47 id: 'settings.workspace.form.servicesInWorkspaceHeadline',
48 defaultMessage: '!!!Services in this Workspace', 48 defaultMessage: 'Services in this Workspace',
49 }, 49 },
50 noServicesAdded: { 50 noServicesAdded: {
51 id: 'settings.services.noServicesAdded', 51 id: 'settings.services.noServicesAdded',
52 defaultMessage: '!!!Start by adding a service.', 52 defaultMessage: 'Start by adding a service.',
53 }, 53 },
54 discoverServices: { 54 discoverServices: {
55 id: 'settings.services.discoverServices', 55 id: 'settings.services.discoverServices',
56 defaultMessage: '!!!Discover services', 56 defaultMessage: 'Discover services',
57 }, 57 },
58}); 58});
59 59
@@ -72,10 +72,6 @@ const styles = () => ({
72@injectSheet(styles) 72@injectSheet(styles)
73@observer 73@observer
74class EditWorkspaceForm extends Component { 74class EditWorkspaceForm extends Component {
75 static contextTypes = {
76 intl: intlShape,
77 };
78
79 static propTypes = { 75 static propTypes = {
80 classes: PropTypes.object.isRequired, 76 classes: PropTypes.object.isRequired,
81 onDelete: PropTypes.func.isRequired, 77 onDelete: PropTypes.func.isRequired,
@@ -97,7 +93,7 @@ class EditWorkspaceForm extends Component {
97 } 93 }
98 94
99 prepareWorkspaceForm(workspace) { 95 prepareWorkspaceForm(workspace) {
100 const { intl } = this.context; 96 const { intl } = this.props;
101 return new Form({ 97 return new Form({
102 fields: { 98 fields: {
103 name: { 99 name: {
@@ -120,7 +116,7 @@ class EditWorkspaceForm extends Component {
120 116
121 save(form) { 117 save(form) {
122 form.submit({ 118 form.submit({
123 onSuccess: async (f) => { 119 onSuccess: async f => {
124 const { onSave } = this.props; 120 const { onSave } = this.props;
125 const values = f.values(); 121 const values = f.values();
126 onSave(values); 122 onSave(values);
@@ -146,7 +142,7 @@ class EditWorkspaceForm extends Component {
146 } 142 }
147 143
148 render() { 144 render() {
149 const { intl } = this.context; 145 const { intl } = this.props;
150 const { 146 const {
151 classes, 147 classes,
152 workspace, 148 workspace,
@@ -194,7 +190,7 @@ class EditWorkspaceForm extends Component {
194 </div> 190 </div>
195 ) : ( 191 ) : (
196 <> 192 <>
197 {services.map((s) => ( 193 {services.map(s => (
198 <WorkspaceServiceListItem 194 <WorkspaceServiceListItem
199 key={s.id} 195 key={s.id}
200 service={s} 196 service={s}
@@ -233,4 +229,4 @@ class EditWorkspaceForm extends Component {
233 } 229 }
234} 230}
235 231
236export default EditWorkspaceForm; 232export default injectIntl(EditWorkspaceForm);
diff --git a/src/features/workspaces/components/WorkspaceDrawer.js b/src/features/workspaces/components/WorkspaceDrawer.js
index 1138f23d7..03a829a64 100644
--- a/src/features/workspaces/components/WorkspaceDrawer.js
+++ b/src/features/workspaces/components/WorkspaceDrawer.js
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import injectSheet from 'react-jss'; 4import injectSheet from 'react-jss';
5import { defineMessages, intlShape } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6import { H1, Icon } from '@meetfranz/ui'; 6import { H1, Icon } from '@meetfranz/ui';
7import ReactTooltip from 'react-tooltip'; 7import ReactTooltip from 'react-tooltip';
8 8
@@ -14,27 +14,27 @@ import { workspaceStore } from '../index';
14const messages = defineMessages({ 14const messages = defineMessages({
15 headline: { 15 headline: {
16 id: 'workspaceDrawer.headline', 16 id: 'workspaceDrawer.headline',
17 defaultMessage: '!!!Workspaces', 17 defaultMessage: 'Workspaces',
18 }, 18 },
19 allServices: { 19 allServices: {
20 id: 'workspaceDrawer.allServices', 20 id: 'workspaceDrawer.allServices',
21 defaultMessage: '!!!All services', 21 defaultMessage: 'All services',
22 }, 22 },
23 workspacesSettingsTooltip: { 23 workspacesSettingsTooltip: {
24 id: 'workspaceDrawer.workspacesSettingsTooltip', 24 id: 'workspaceDrawer.workspacesSettingsTooltip',
25 defaultMessage: '!!!Workspaces settings', 25 defaultMessage: 'Workspaces settings',
26 }, 26 },
27 workspaceFeatureInfo: { 27 workspaceFeatureInfo: {
28 id: 'workspaceDrawer.workspaceFeatureInfo', 28 id: 'workspaceDrawer.workspaceFeatureInfo',
29 defaultMessage: '!!!Info about workspace feature', 29 defaultMessage: 'Info about workspace feature',
30 }, 30 },
31 addNewWorkspaceLabel: { 31 addNewWorkspaceLabel: {
32 id: 'workspaceDrawer.addNewWorkspaceLabel', 32 id: 'workspaceDrawer.addNewWorkspaceLabel',
33 defaultMessage: '!!!add new workspace', 33 defaultMessage: 'add new workspace',
34 }, 34 },
35}); 35});
36 36
37const styles = (theme) => ({ 37const styles = theme => ({
38 drawer: { 38 drawer: {
39 background: theme.workspaces.drawer.background, 39 background: theme.workspaces.drawer.background,
40 width: `${theme.workspaces.drawer.width}px`, 40 width: `${theme.workspaces.drawer.width}px`,
@@ -85,34 +85,26 @@ const styles = (theme) => ({
85 }, 85 },
86}); 86});
87 87
88@injectSheet(styles) @observer 88@injectSheet(styles)
89@observer
89class WorkspaceDrawer extends Component { 90class WorkspaceDrawer extends Component {
90 static propTypes = { 91 static propTypes = {
91 classes: PropTypes.object.isRequired, 92 classes: PropTypes.object.isRequired,
92 getServicesForWorkspace: PropTypes.func.isRequired, 93 getServicesForWorkspace: PropTypes.func.isRequired,
93 }; 94 };
94 95
95 static contextTypes = {
96 intl: intlShape,
97 };
98
99 componentDidMount() { 96 componentDidMount() {
100 ReactTooltip.rebuild(); 97 ReactTooltip.rebuild();
101 } 98 }
102 99
103 render() { 100 render() {
104 const { 101 const { classes, getServicesForWorkspace } = this.props;
105 classes, 102 const { intl } = this.props;
106 getServicesForWorkspace, 103 const { activeWorkspace, isSwitchingWorkspace, nextWorkspace, workspaces } =
107 } = this.props; 104 workspaceStore;
108 const { intl } = this.context; 105 const actualWorkspace = isSwitchingWorkspace
109 const { 106 ? nextWorkspace
110 activeWorkspace, 107 : activeWorkspace;
111 isSwitchingWorkspace,
112 nextWorkspace,
113 workspaces,
114 } = workspaceStore;
115 const actualWorkspace = isSwitchingWorkspace ? nextWorkspace : activeWorkspace;
116 return ( 108 return (
117 <div className={`${classes.drawer} workspaces-drawer`}> 109 <div className={`${classes.drawer} workspaces-drawer`}>
118 <H1 className={classes.headline}> 110 <H1 className={classes.headline}>
@@ -122,7 +114,9 @@ class WorkspaceDrawer extends Component {
122 onClick={() => { 114 onClick={() => {
123 workspaceActions.openWorkspaceSettings(); 115 workspaceActions.openWorkspaceSettings();
124 }} 116 }}
125 data-tip={`${intl.formatMessage(messages.workspacesSettingsTooltip)}`} 117 data-tip={`${intl.formatMessage(
118 messages.workspacesSettingsTooltip,
119 )}`}
126 > 120 >
127 <Icon 121 <Icon
128 icon={mdiSettings} 122 icon={mdiSettings}
@@ -152,7 +146,9 @@ class WorkspaceDrawer extends Component {
152 workspaceActions.activate({ workspace }); 146 workspaceActions.activate({ workspace });
153 workspaceActions.toggleWorkspaceDrawer(); 147 workspaceActions.toggleWorkspaceDrawer();
154 }} 148 }}
155 onContextMenuEditClick={() => workspaceActions.edit({ workspace })} 149 onContextMenuEditClick={() =>
150 workspaceActions.edit({ workspace })
151 }
156 services={getServicesForWorkspace(workspace)} 152 services={getServicesForWorkspace(workspace)}
157 shortcutIndex={index + 1} 153 shortcutIndex={index + 1}
158 /> 154 />
@@ -168,9 +164,7 @@ class WorkspaceDrawer extends Component {
168 size={1} 164 size={1}
169 className={classes.workspacesSettingsButtonIcon} 165 className={classes.workspacesSettingsButtonIcon}
170 /> 166 />
171 <span> 167 <span>{intl.formatMessage(messages.addNewWorkspaceLabel)}</span>
172 {intl.formatMessage(messages.addNewWorkspaceLabel)}
173 </span>
174 </div> 168 </div>
175 </div> 169 </div>
176 <ReactTooltip place="right" type="dark" effect="solid" /> 170 <ReactTooltip place="right" type="dark" effect="solid" />
@@ -179,4 +173,4 @@ class WorkspaceDrawer extends Component {
179 } 173 }
180} 174}
181 175
182export default WorkspaceDrawer; 176export default injectIntl(WorkspaceDrawer);
diff --git a/src/features/workspaces/components/WorkspaceDrawerItem.js b/src/features/workspaces/components/WorkspaceDrawerItem.js
index 252158364..82e1b81a4 100644
--- a/src/features/workspaces/components/WorkspaceDrawerItem.js
+++ b/src/features/workspaces/components/WorkspaceDrawerItem.js
@@ -4,17 +4,17 @@ import PropTypes from 'prop-types';
4import { observer } from 'mobx-react'; 4import { observer } from 'mobx-react';
5import injectSheet from 'react-jss'; 5import injectSheet from 'react-jss';
6import classnames from 'classnames'; 6import classnames from 'classnames';
7import { defineMessages, intlShape } from 'react-intl'; 7import { defineMessages, injectIntl } from 'react-intl';
8import { altKey, cmdOrCtrlShortcutKey } from '../../../environment'; 8import { altKey, cmdOrCtrlShortcutKey } from '../../../environment';
9 9
10const messages = defineMessages({ 10const messages = defineMessages({
11 noServicesAddedYet: { 11 noServicesAddedYet: {
12 id: 'workspaceDrawer.item.noServicesAddedYet', 12 id: 'workspaceDrawer.item.noServicesAddedYet',
13 defaultMessage: '!!!No services added yet', 13 defaultMessage: 'No services added yet',
14 }, 14 },
15 contextMenuEdit: { 15 contextMenuEdit: {
16 id: 'workspaceDrawer.item.contextMenuEdit', 16 id: 'workspaceDrawer.item.contextMenuEdit',
17 defaultMessage: '!!!edit', 17 defaultMessage: 'edit',
18 }, 18 },
19}); 19});
20 20
@@ -82,10 +82,6 @@ class WorkspaceDrawerItem extends Component {
82 onContextMenuEditClick: null, 82 onContextMenuEditClick: null,
83 }; 83 };
84 84
85 static contextTypes = {
86 intl: intlShape,
87 };
88
89 render() { 85 render() {
90 const { 86 const {
91 classes, 87 classes,
@@ -96,7 +92,8 @@ class WorkspaceDrawerItem extends Component {
96 services, 92 services,
97 shortcutIndex, 93 shortcutIndex,
98 } = this.props; 94 } = this.props;
99 const { intl } = this.context; 95
96 const { intl } = this.props;
100 97
101 const contextMenuTemplate = [ 98 const contextMenuTemplate = [
102 { 99 {
@@ -125,7 +122,11 @@ class WorkspaceDrawerItem extends Component {
125 onContextMenuEditClick && contextMenu.popup(getCurrentWindow()) 122 onContextMenuEditClick && contextMenu.popup(getCurrentWindow())
126 } 123 }
127 data-tip={`${ 124 data-tip={`${
128 shortcutIndex <= 9 ? `(${cmdOrCtrlShortcutKey(false)}+${altKey(false)}+${shortcutIndex})` : '' 125 shortcutIndex <= 9
126 ? `(${cmdOrCtrlShortcutKey(false)}+${altKey(
127 false,
128 )}+${shortcutIndex})`
129 : ''
129 }`} 130 }`}
130 > 131 >
131 <span 132 <span
@@ -151,4 +152,4 @@ class WorkspaceDrawerItem extends Component {
151 } 152 }
152} 153}
153 154
154export default WorkspaceDrawerItem; 155export default injectIntl(WorkspaceDrawerItem);
diff --git a/src/features/workspaces/components/WorkspaceItem.js b/src/features/workspaces/components/WorkspaceItem.js
index 85fc02d51..ec7b19add 100644
--- a/src/features/workspaces/components/WorkspaceItem.js
+++ b/src/features/workspaces/components/WorkspaceItem.js
@@ -1,12 +1,11 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { intlShape } from 'react-intl';
4import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
5import injectSheet from 'react-jss'; 4import injectSheet from 'react-jss';
6 5
7import Workspace from '../models/Workspace'; 6import Workspace from '../models/Workspace';
8 7
9const styles = (theme) => ({ 8const styles = theme => ({
10 row: { 9 row: {
11 height: theme.workspaces.settings.listItems.height, 10 height: theme.workspaces.settings.listItems.height,
12 borderBottom: `1px solid ${theme.workspaces.settings.listItems.borderColor}`, 11 borderBottom: `1px solid ${theme.workspaces.settings.listItems.borderColor}`,
@@ -17,7 +16,8 @@ const styles = (theme) => ({
17 columnName: {}, 16 columnName: {},
18}); 17});
19 18
20@injectSheet(styles) @observer 19@injectSheet(styles)
20@observer
21class WorkspaceItem extends Component { 21class WorkspaceItem extends Component {
22 static propTypes = { 22 static propTypes = {
23 classes: PropTypes.object.isRequired, 23 classes: PropTypes.object.isRequired,
@@ -25,18 +25,12 @@ class WorkspaceItem extends Component {
25 onItemClick: PropTypes.func.isRequired, 25 onItemClick: PropTypes.func.isRequired,
26 }; 26 };
27 27
28 static contextTypes = {
29 intl: intlShape,
30 };
31
32 render() { 28 render() {
33 const { classes, workspace, onItemClick } = this.props; 29 const { classes, workspace, onItemClick } = this.props;
34 30
35 return ( 31 return (
36 <tr className={classes.row}> 32 <tr className={classes.row}>
37 <td onClick={() => onItemClick(workspace)}> 33 <td onClick={() => onItemClick(workspace)}>{workspace.name}</td>
38 {workspace.name}
39 </td>
40 </tr> 34 </tr>
41 ); 35 );
42 } 36 }
diff --git a/src/features/workspaces/components/WorkspaceSwitchingIndicator.js b/src/features/workspaces/components/WorkspaceSwitchingIndicator.js
index c8ec0bc4c..33a82cf4b 100644
--- a/src/features/workspaces/components/WorkspaceSwitchingIndicator.js
+++ b/src/features/workspaces/components/WorkspaceSwitchingIndicator.js
@@ -4,14 +4,14 @@ import { observer } from 'mobx-react';
4import injectSheet from 'react-jss'; 4import injectSheet from 'react-jss';
5import classnames from 'classnames'; 5import classnames from 'classnames';
6import { Loader } from '@meetfranz/ui'; 6import { Loader } from '@meetfranz/ui';
7import { defineMessages, intlShape } from 'react-intl'; 7import { defineMessages, injectIntl } from 'react-intl';
8 8
9import { workspaceStore } from '../index'; 9import { workspaceStore } from '../index';
10 10
11const messages = defineMessages({ 11const messages = defineMessages({
12 switchingTo: { 12 switchingTo: {
13 id: 'workspaces.switchingIndicator.switchingTo', 13 id: 'workspaces.switchingIndicator.switchingTo',
14 defaultMessage: '!!!Switching to', 14 defaultMessage: 'Switching to',
15 }, 15 },
16}); 16});
17 17
@@ -61,13 +61,9 @@ class WorkspaceSwitchingIndicator extends Component {
61 theme: PropTypes.object.isRequired, 61 theme: PropTypes.object.isRequired,
62 }; 62 };
63 63
64 static contextTypes = {
65 intl: intlShape,
66 };
67
68 render() { 64 render() {
69 const { classes, theme } = this.props; 65 const { classes, theme } = this.props;
70 const { intl } = this.context; 66 const { intl } = this.props;
71 const { isSwitchingWorkspace, nextWorkspace } = workspaceStore; 67 const { isSwitchingWorkspace, nextWorkspace } = workspaceStore;
72 if (!isSwitchingWorkspace) return null; 68 if (!isSwitchingWorkspace) return null;
73 const nextWorkspaceName = nextWorkspace 69 const nextWorkspaceName = nextWorkspace
@@ -89,4 +85,4 @@ class WorkspaceSwitchingIndicator extends Component {
89 } 85 }
90} 86}
91 87
92export default WorkspaceSwitchingIndicator; 88export default injectIntl(WorkspaceSwitchingIndicator);
diff --git a/src/features/workspaces/components/WorkspacesDashboard.js b/src/features/workspaces/components/WorkspacesDashboard.js
index 5f34204f1..fd279f896 100644
--- a/src/features/workspaces/components/WorkspacesDashboard.js
+++ b/src/features/workspaces/components/WorkspacesDashboard.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import injectSheet from 'react-jss'; 5import injectSheet from 'react-jss';
6import { Infobox } from '@meetfranz/ui'; 6import { Infobox } from '@meetfranz/ui';
7 7
@@ -16,35 +16,35 @@ import UIStore from '../../../stores/UIStore';
16const messages = defineMessages({ 16const messages = defineMessages({
17 headline: { 17 headline: {
18 id: 'settings.workspaces.headline', 18 id: 'settings.workspaces.headline',
19 defaultMessage: '!!!Your workspaces', 19 defaultMessage: 'Your workspaces',
20 }, 20 },
21 noServicesAdded: { 21 noServicesAdded: {
22 id: 'settings.workspaces.noWorkspacesAdded', 22 id: 'settings.workspaces.noWorkspacesAdded',
23 defaultMessage: "!!!You haven't created any workspaces yet.", 23 defaultMessage: "You haven't created any workspaces yet.",
24 }, 24 },
25 workspacesRequestFailed: { 25 workspacesRequestFailed: {
26 id: 'settings.workspaces.workspacesRequestFailed', 26 id: 'settings.workspaces.workspacesRequestFailed',
27 defaultMessage: '!!!Could not load your workspaces', 27 defaultMessage: 'Could not load your workspaces',
28 }, 28 },
29 tryReloadWorkspaces: { 29 tryReloadWorkspaces: {
30 id: 'settings.workspaces.tryReloadWorkspaces', 30 id: 'settings.workspaces.tryReloadWorkspaces',
31 defaultMessage: '!!!Try again', 31 defaultMessage: 'Try again',
32 }, 32 },
33 updatedInfo: { 33 updatedInfo: {
34 id: 'settings.workspaces.updatedInfo', 34 id: 'settings.workspaces.updatedInfo',
35 defaultMessage: '!!!Your changes have been saved', 35 defaultMessage: 'Your changes have been saved',
36 }, 36 },
37 deletedInfo: { 37 deletedInfo: {
38 id: 'settings.workspaces.deletedInfo', 38 id: 'settings.workspaces.deletedInfo',
39 defaultMessage: '!!!Workspace has been deleted', 39 defaultMessage: 'Workspace has been deleted',
40 }, 40 },
41 workspaceFeatureInfo: { 41 workspaceFeatureInfo: {
42 id: 'settings.workspaces.workspaceFeatureInfo', 42 id: 'settings.workspaces.workspaceFeatureInfo',
43 defaultMessage: '!!!Info about workspace feature', 43 defaultMessage: 'Info about workspace feature',
44 }, 44 },
45 workspaceFeatureHeadline: { 45 workspaceFeatureHeadline: {
46 id: 'settings.workspaces.workspaceFeatureHeadline', 46 id: 'settings.workspaces.workspaceFeatureHeadline',
47 defaultMessage: '!!!Less is More: Introducing Ferdi Workspaces', 47 defaultMessage: 'Less is More: Introducing Ferdi Workspaces',
48 }, 48 },
49}); 49});
50 50
@@ -83,10 +83,6 @@ class WorkspacesDashboard extends Component {
83 workspaces: MobxPropTypes.arrayOrObservableArray.isRequired, 83 workspaces: MobxPropTypes.arrayOrObservableArray.isRequired,
84 }; 84 };
85 85
86 static contextTypes = {
87 intl: intlShape,
88 };
89
90 render() { 86 render() {
91 const { 87 const {
92 classes, 88 classes,
@@ -99,7 +95,7 @@ class WorkspacesDashboard extends Component {
99 workspaces, 95 workspaces,
100 } = this.props; 96 } = this.props;
101 97
102 const { intl } = this.context; 98 const { intl } = this.props;
103 99
104 return ( 100 return (
105 <div className="settings__main"> 101 <div className="settings__main">
@@ -193,7 +189,7 @@ class WorkspacesDashboard extends Component {
193 } 189 }
194} 190}
195 191
196export default WorkspacesDashboard; 192export default injectIntl(WorkspacesDashboard);
197 193
198WorkspacesDashboard.wrappedComponent.propTypes = { 194WorkspacesDashboard.wrappedComponent.propTypes = {
199 stores: PropTypes.shape({ 195 stores: PropTypes.shape({
diff --git a/src/helpers/validation-helpers.js b/src/helpers/validation-helpers.js
index 116f19905..569b13bb0 100644
--- a/src/helpers/validation-helpers.js
+++ b/src/helpers/validation-helpers.js
@@ -4,35 +4,41 @@ import isEmail from 'validator/lib/isEmail';
4const messages = defineMessages({ 4const messages = defineMessages({
5 required: { 5 required: {
6 id: 'validation.required', 6 id: 'validation.required',
7 defaultMessage: '!!!Field is required', 7 defaultMessage: 'Field is required',
8 }, 8 },
9 email: { 9 email: {
10 id: 'validation.email', 10 id: 'validation.email',
11 defaultMessage: '!!!Email not valid', 11 defaultMessage: 'Email not valid',
12 }, 12 },
13 url: { 13 url: {
14 id: 'validation.url', 14 id: 'validation.url',
15 defaultMessage: '!!!Not a valid URL', 15 defaultMessage: 'Not a valid URL',
16 }, 16 },
17 minLength: { 17 minLength: {
18 id: 'validation.minLength', 18 id: 'validation.minLength',
19 defaultMessage: '!!!Too few characters', 19 defaultMessage: 'Too few characters',
20 }, 20 },
21 oneRequired: { 21 oneRequired: {
22 id: 'validation.oneRequired', 22 id: 'validation.oneRequired',
23 defaultMessage: '!!!At least one is required', 23 defaultMessage: 'At least one is required',
24 }, 24 },
25}); 25});
26 26
27export function required({ field }) { 27export function required({ field }) {
28 const isValid = (field.value.trim() !== ''); 28 const isValid = field.value.trim() !== '';
29 return [isValid, window.ferdi.intl.formatMessage(messages.required, { field: field.label })]; 29 return [
30 isValid,
31 window.ferdi.intl.formatMessage(messages.required, { field: field.label }),
32 ];
30} 33}
31 34
32export function email({ field }) { 35export function email({ field }) {
33 const value = field.value.trim(); 36 const value = field.value.trim();
34 const isValid = isEmail(value); 37 const isValid = isEmail(value);
35 return [isValid, window.ferdi.intl.formatMessage(messages.email, { field: field.label })]; 38 return [
39 isValid,
40 window.ferdi.intl.formatMessage(messages.email, { field: field.label }),
41 ];
36} 42}
37 43
38export function url({ field }) { 44export function url({ field }) {
@@ -41,12 +47,19 @@ export function url({ field }) {
41 47
42 if (value !== '') { 48 if (value !== '') {
43 // eslint-disable-next-line 49 // eslint-disable-next-line
44 isValid = Boolean(value.match(/(^|[\s.:;?\-\]<(])(https?:\/\/[-\w;/?:@&=+$|_.!~*|'()[\]%#,☺]+[\w/#](\(\))?)(?=$|[\s',|().:;?\-[\]>)])/i)); 50 isValid = Boolean(
51 value.match(
52 /(^|[\s.:;?\-\]<(])(https?:\/\/[-\w;/?:@&=+$|_.!~*|'()[\]%#,☺]+[\w/#](\(\))?)(?=$|[\s',|().:;?\-[\]>)])/i,
53 ),
54 );
45 } else { 55 } else {
46 isValid = true; 56 isValid = true;
47 } 57 }
48 58
49 return [isValid, window.ferdi.intl.formatMessage(messages.url, { field: field.label })]; 59 return [
60 isValid,
61 window.ferdi.intl.formatMessage(messages.url, { field: field.label }),
62 ];
50} 63}
51 64
52export function minLength(length) { 65export function minLength(length) {
@@ -55,13 +68,24 @@ export function minLength(length) {
55 if (field.touched) { 68 if (field.touched) {
56 isValid = field.value.length >= length; 69 isValid = field.value.length >= length;
57 } 70 }
58 return [isValid, window.ferdi.intl.formatMessage(messages.minLength, { field: field.label, length })]; 71 return [
72 isValid,
73 window.ferdi.intl.formatMessage(messages.minLength, {
74 field: field.label,
75 length,
76 }),
77 ];
59 }; 78 };
60} 79}
61 80
62export function oneRequired(targets) { 81export function oneRequired(targets) {
63 return ({ field, form }) => { 82 return ({ field, form }) => {
64 const invalidFields = targets.filter((target) => form.$(target).value === ''); 83 const invalidFields = targets.filter(target => form.$(target).value === '');
65 return [targets.length !== invalidFields.length, window.ferdi.intl.formatMessage(messages.required, { field: field.label })]; 84 return [
85 targets.length !== invalidFields.length,
86 window.ferdi.intl.formatMessage(messages.required, {
87 field: field.label,
88 }),
89 ];
66 }; 90 };
67} 91}
diff --git a/src/i18n/apply-branding.js b/src/i18n/apply-branding.js
index 40a07ded0..7aeabc4af 100644
--- a/src/i18n/apply-branding.js
+++ b/src/i18n/apply-branding.js
@@ -21,12 +21,7 @@ const ignore = [
21]; 21];
22 22
23// Files to ignore when applying branding 23// Files to ignore when applying branding
24const ignoreFiles = [ 24const ignoreFiles = ['.DS_Store', '.', '..'];
25 'defaultMessages.json',
26 '.DS_Store',
27 '.',
28 '..',
29];
30 25
31// What to replace 26// What to replace
32const replace = { 27const replace = {
@@ -49,7 +44,7 @@ const replaceStr = (str, find, replaceWith) => {
49 return str; 44 return str;
50}; 45};
51 46
52files.forEach(async (file) => { 47files.forEach(async file => {
53 if (ignoreFiles.includes(file)) return; 48 if (ignoreFiles.includes(file)) return;
54 49
55 // Read locale data 50 // Read locale data
diff --git a/src/i18n/globalMessages.js b/src/i18n/globalMessages.js
index 66fce8d0f..bc3c559bf 100644
--- a/src/i18n/globalMessages.js
+++ b/src/i18n/globalMessages.js
@@ -3,75 +3,75 @@ import { defineMessages } from 'react-intl';
3export default defineMessages({ 3export default defineMessages({
4 APIUnhealthy: { 4 APIUnhealthy: {
5 id: 'global.api.unhealthy', 5 id: 'global.api.unhealthy',
6 defaultMessage: '!!!Can\'t connect to Ferdi Online Services', 6 defaultMessage: "Can't connect to Ferdi Online Services",
7 }, 7 },
8 notConnectedToTheInternet: { 8 notConnectedToTheInternet: {
9 id: 'global.notConnectedToTheInternet', 9 id: 'global.notConnectedToTheInternet',
10 defaultMessage: '!!!You are not connected to the internet.', 10 defaultMessage: 'You are not connected to the internet.',
11 }, 11 },
12 spellcheckerLanguage: { 12 spellcheckerLanguage: {
13 id: 'global.spellchecking.language', 13 id: 'global.spellchecking.language',
14 defaultMessage: '!!!Spell checking language', 14 defaultMessage: 'Spell checking language',
15 }, 15 },
16 spellcheckerSystemDefault: { 16 spellcheckerSystemDefault: {
17 id: 'global.spellchecker.useDefault', 17 id: 'global.spellchecker.useDefault',
18 defaultMessage: '!!!Use System Default ({default})', 18 defaultMessage: 'Use System Default ({default})',
19 }, 19 },
20 spellcheckerAutomaticDetection: { 20 spellcheckerAutomaticDetection: {
21 id: 'global.spellchecking.autodetect', 21 id: 'global.spellchecking.autodetect',
22 defaultMessage: '!!!Detect language automatically', 22 defaultMessage: 'Detect language automatically',
23 }, 23 },
24 spellcheckerAutomaticDetectionShort: { 24 spellcheckerAutomaticDetectionShort: {
25 id: 'global.spellchecking.autodetect.short', 25 id: 'global.spellchecking.autodetect.short',
26 defaultMessage: '!!!Automatic', 26 defaultMessage: 'Automatic',
27 }, 27 },
28 userAgentPref: { 28 userAgentPref: {
29 id: 'global.userAgentPref', 29 id: 'global.userAgentPref',
30 defaultMessage: '!!!User Agent', 30 defaultMessage: 'User Agent',
31 }, 31 },
32 userAgentHelp: { 32 userAgentHelp: {
33 id: 'global.userAgentHelp', 33 id: 'global.userAgentHelp',
34 defaultMessage: "!!!Use 'https://whatmyuseragent.com/' (to discover) or 'https://developers.whatismybrowser.com/useragents/explore/' (to choose) your desired user agent and copy-paste it here.", 34 defaultMessage:
35 "Use 'https://whatmyuseragent.com/' (to discover) or 'https://developers.whatismybrowser.com/useragents/explore/' (to choose) your desired user agent and copy-paste it here.",
35 }, 36 },
36 yes: { 37 yes: {
37 id: 'global.yes', 38 id: 'global.yes',
38 defaultMessage: '!!!Yes', 39 defaultMessage: 'Yes',
39 }, 40 },
40 no: { 41 no: {
41 id: 'global.no', 42 id: 'global.no',
42 defaultMessage: '!!!No', 43 defaultMessage: 'No',
43 }, 44 },
44 ok: { 45 ok: {
45 id: 'global.ok', 46 id: 'global.ok',
46 defaultMessage: '!!!Ok', 47 defaultMessage: 'Ok',
47 }, 48 },
48 cancel: { 49 cancel: {
49 id: 'global.cancel', 50 id: 'global.cancel',
50 defaultMessage: '!!!Cancel', 51 defaultMessage: 'Cancel',
51 }, 52 },
52 save: { 53 save: {
53 id: 'global.save', 54 id: 'global.save',
54 defaultMessage: '!!!Save', 55 defaultMessage: 'Save',
55 }, 56 },
56 submit: { 57 submit: {
57 id: 'global.submit', 58 id: 'global.submit',
58 defaultMessage: '!!!Submit', 59 defaultMessage: 'Submit',
59 }, 60 },
60 quit: { 61 quit: {
61 id: 'global.quit', 62 id: 'global.quit',
62 defaultMessage: '!!!Quit', 63 defaultMessage: 'Quit',
63 }, 64 },
64 quitConfirmation: { 65 quitConfirmation: {
65 id: 'global.quitConfirmation', 66 id: 'global.quitConfirmation',
66 defaultMessage: 67 defaultMessage: 'Do you really want to quit Ferdi?',
67 '!!!Do you really want to quit Ferdi?',
68 }, 68 },
69 settings: { 69 settings: {
70 id: 'global.settings', 70 id: 'global.settings',
71 defaultMessage: '!!!Settings', 71 defaultMessage: 'Settings',
72 }, 72 },
73 edit: { 73 edit: {
74 id: 'global.edit', 74 id: 'global.edit',
75 defaultMessage: '!!!Edit', 75 defaultMessage: 'Edit',
76 }, 76 },
77}); 77});
diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json
deleted file mode 100644
index 3a41c66f6..000000000
--- a/src/i18n/locales/defaultMessages.json
+++ /dev/null
@@ -1,6862 +0,0 @@
1[
2 {
3 "descriptors": [
4 {
5 "defaultMessage": "!!!A new update for Ferdi is available.",
6 "end": {
7 "column": 3,
8 "line": 13
9 },
10 "file": "src/components/AppUpdateInfoBar.js",
11 "id": "infobar.updateAvailable",
12 "start": {
13 "column": 19,
14 "line": 10
15 }
16 },
17 {
18 "defaultMessage": "!!!Changelog",
19 "end": {
20 "column": 3,
21 "line": 17
22 },
23 "file": "src/components/AppUpdateInfoBar.js",
24 "id": "infobar.buttonChangelog",
25 "start": {
26 "column": 13,
27 "line": 14
28 }
29 },
30 {
31 "defaultMessage": "!!!Restart & install update",
32 "end": {
33 "column": 3,
34 "line": 21
35 },
36 "file": "src/components/AppUpdateInfoBar.js",
37 "id": "infobar.buttonInstallUpdate",
38 "start": {
39 "column": 23,
40 "line": 18
41 }
42 }
43 ],
44 "path": "src/components/AppUpdateInfoBar.json"
45 },
46 {
47 "descriptors": [
48 {
49 "defaultMessage": "!!!Change server",
50 "end": {
51 "column": 3,
52 "line": 18
53 },
54 "file": "src/components/auth/ChangeServer.js",
55 "id": "changeserver.headline",
56 "start": {
57 "column": 12,
58 "line": 15
59 }
60 },
61 {
62 "defaultMessage": "!!!Server",
63 "end": {
64 "column": 3,
65 "line": 22
66 },
67 "file": "src/components/auth/ChangeServer.js",
68 "id": "changeserver.label",
69 "start": {
70 "column": 9,
71 "line": 19
72 }
73 },
74 {
75 "defaultMessage": "!!!Extra settings offered by Ferdi will not be saved",
76 "end": {
77 "column": 3,
78 "line": 26
79 },
80 "file": "src/components/auth/ChangeServer.js",
81 "id": "changeserver.warning",
82 "start": {
83 "column": 11,
84 "line": 23
85 }
86 },
87 {
88 "defaultMessage": "!!!Custom server",
89 "end": {
90 "column": 3,
91 "line": 30
92 },
93 "file": "src/components/auth/ChangeServer.js",
94 "id": "changeserver.customServerLabel",
95 "start": {
96 "column": 21,
97 "line": 27
98 }
99 },
100 {
101 "defaultMessage": "!!!Enter a valid URL",
102 "end": {
103 "column": 3,
104 "line": 34
105 },
106 "file": "src/components/auth/ChangeServer.js",
107 "id": "changeserver.urlError",
108 "start": {
109 "column": 12,
110 "line": 31
111 }
112 }
113 ],
114 "path": "src/components/auth/ChangeServer.json"
115 },
116 {
117 "descriptors": [
118 {
119 "defaultMessage": "!!!Import your Ferdi 4 services",
120 "end": {
121 "column": 3,
122 "line": 16
123 },
124 "file": "src/components/auth/Import.js",
125 "id": "import.headline",
126 "start": {
127 "column": 12,
128 "line": 13
129 }
130 },
131 {
132 "defaultMessage": "!!!Services not yet supported in Ferdi 5",
133 "end": {
134 "column": 3,
135 "line": 20
136 },
137 "file": "src/components/auth/Import.js",
138 "id": "import.notSupportedHeadline",
139 "start": {
140 "column": 24,
141 "line": 17
142 }
143 },
144 {
145 "defaultMessage": "!!!Import {count} services",
146 "end": {
147 "column": 3,
148 "line": 24
149 },
150 "file": "src/components/auth/Import.js",
151 "id": "import.submit.label",
152 "start": {
153 "column": 21,
154 "line": 21
155 }
156 },
157 {
158 "defaultMessage": "!!!I want to add services manually",
159 "end": {
160 "column": 3,
161 "line": 28
162 },
163 "file": "src/components/auth/Import.js",
164 "id": "import.skip.label",
165 "start": {
166 "column": 19,
167 "line": 25
168 }
169 }
170 ],
171 "path": "src/components/auth/Import.json"
172 },
173 {
174 "descriptors": [
175 {
176 "defaultMessage": "!!!Invite Friends",
177 "end": {
178 "column": 3,
179 "line": 19
180 },
181 "file": "src/components/auth/Invite.js",
182 "id": "settings.invite.headline",
183 "start": {
184 "column": 20,
185 "line": 16
186 }
187 },
188 {
189 "defaultMessage": "!!!Invite 3 of your friends or colleagues",
190 "end": {
191 "column": 3,
192 "line": 23
193 },
194 "file": "src/components/auth/Invite.js",
195 "id": "invite.headline.friends",
196 "start": {
197 "column": 12,
198 "line": 20
199 }
200 },
201 {
202 "defaultMessage": "!!!Name",
203 "end": {
204 "column": 3,
205 "line": 27
206 },
207 "file": "src/components/auth/Invite.js",
208 "id": "invite.name.label",
209 "start": {
210 "column": 13,
211 "line": 24
212 }
213 },
214 {
215 "defaultMessage": "!!!Email address",
216 "end": {
217 "column": 3,
218 "line": 31
219 },
220 "file": "src/components/auth/Invite.js",
221 "id": "invite.email.label",
222 "start": {
223 "column": 14,
224 "line": 28
225 }
226 },
227 {
228 "defaultMessage": "!!!Send invites",
229 "end": {
230 "column": 3,
231 "line": 35
232 },
233 "file": "src/components/auth/Invite.js",
234 "id": "invite.submit.label",
235 "start": {
236 "column": 21,
237 "line": 32
238 }
239 },
240 {
241 "defaultMessage": "!!!I want to do this later",
242 "end": {
243 "column": 3,
244 "line": 39
245 },
246 "file": "src/components/auth/Invite.js",
247 "id": "invite.skip.label",
248 "start": {
249 "column": 19,
250 "line": 36
251 }
252 },
253 {
254 "defaultMessage": "!!!Invitations sent successfully",
255 "end": {
256 "column": 3,
257 "line": 43
258 },
259 "file": "src/components/auth/Invite.js",
260 "id": "invite.successInfo",
261 "start": {
262 "column": 21,
263 "line": 40
264 }
265 }
266 ],
267 "path": "src/components/auth/Invite.json"
268 },
269 {
270 "descriptors": [
271 {
272 "defaultMessage": "!!!Locked",
273 "end": {
274 "column": 3,
275 "line": 19
276 },
277 "file": "src/components/auth/Locked.js",
278 "id": "locked.headline",
279 "start": {
280 "column": 12,
281 "line": 16
282 }
283 },
284 {
285 "defaultMessage": "!!!Ferdi is currently locked. Please unlock Ferdi with your password to see your messages.",
286 "end": {
287 "column": 3,
288 "line": 23
289 },
290 "file": "src/components/auth/Locked.js",
291 "id": "locked.info",
292 "start": {
293 "column": 8,
294 "line": 20
295 }
296 },
297 {
298 "defaultMessage": "!!!Unlock with Touch ID",
299 "end": {
300 "column": 3,
301 "line": 27
302 },
303 "file": "src/components/auth/Locked.js",
304 "id": "locked.touchId",
305 "start": {
306 "column": 11,
307 "line": 24
308 }
309 },
310 {
311 "defaultMessage": "!!!unlock via Touch ID",
312 "end": {
313 "column": 3,
314 "line": 31
315 },
316 "file": "src/components/auth/Locked.js",
317 "id": "locked.touchIdPrompt",
318 "start": {
319 "column": 17,
320 "line": 28
321 }
322 },
323 {
324 "defaultMessage": "!!!Password",
325 "end": {
326 "column": 3,
327 "line": 35
328 },
329 "file": "src/components/auth/Locked.js",
330 "id": "locked.password.label",
331 "start": {
332 "column": 17,
333 "line": 32
334 }
335 },
336 {
337 "defaultMessage": "!!!Unlock",
338 "end": {
339 "column": 3,
340 "line": 39
341 },
342 "file": "src/components/auth/Locked.js",
343 "id": "locked.submit.label",
344 "start": {
345 "column": 21,
346 "line": 36
347 }
348 },
349 {
350 "defaultMessage": "!!!Unlock with Password",
351 "end": {
352 "column": 3,
353 "line": 43
354 },
355 "file": "src/components/auth/Locked.js",
356 "id": "locked.unlockWithPassword",
357 "start": {
358 "column": 22,
359 "line": 40
360 }
361 },
362 {
363 "defaultMessage": "!!!Password invalid",
364 "end": {
365 "column": 3,
366 "line": 47
367 },
368 "file": "src/components/auth/Locked.js",
369 "id": "locked.invalidCredentials",
370 "start": {
371 "column": 22,
372 "line": 44
373 }
374 }
375 ],
376 "path": "src/components/auth/Locked.json"
377 },
378 {
379 "descriptors": [
380 {
381 "defaultMessage": "!!!Sign in",
382 "end": {
383 "column": 3,
384 "line": 23
385 },
386 "file": "src/components/auth/Login.js",
387 "id": "login.headline",
388 "start": {
389 "column": 12,
390 "line": 20
391 }
392 },
393 {
394 "defaultMessage": "!!!Email address",
395 "end": {
396 "column": 3,
397 "line": 27
398 },
399 "file": "src/components/auth/Login.js",
400 "id": "login.email.label",
401 "start": {
402 "column": 14,
403 "line": 24
404 }
405 },
406 {
407 "defaultMessage": "!!!Password",
408 "end": {
409 "column": 3,
410 "line": 31
411 },
412 "file": "src/components/auth/Login.js",
413 "id": "login.password.label",
414 "start": {
415 "column": 17,
416 "line": 28
417 }
418 },
419 {
420 "defaultMessage": "!!!Sign in",
421 "end": {
422 "column": 3,
423 "line": 35
424 },
425 "file": "src/components/auth/Login.js",
426 "id": "login.submit.label",
427 "start": {
428 "column": 21,
429 "line": 32
430 }
431 },
432 {
433 "defaultMessage": "!!!Email or password not valid",
434 "end": {
435 "column": 3,
436 "line": 39
437 },
438 "file": "src/components/auth/Login.js",
439 "id": "login.invalidCredentials",
440 "start": {
441 "column": 22,
442 "line": 36
443 }
444 },
445 {
446 "defaultMessage": "!!!Using a Franz account to log in?",
447 "end": {
448 "column": 3,
449 "line": 43
450 },
451 "file": "src/components/auth/Login.js",
452 "id": "login.customServerQuestion",
453 "start": {
454 "column": 24,
455 "line": 40
456 }
457 },
458 {
459 "defaultMessage": "!!!Try importing your Franz account into Ferdi",
460 "end": {
461 "column": 3,
462 "line": 47
463 },
464 "file": "src/components/auth/Login.js",
465 "id": "login.customServerSuggestion",
466 "start": {
467 "column": 26,
468 "line": 44
469 }
470 },
471 {
472 "defaultMessage": "!!!Your session expired, please login again.",
473 "end": {
474 "column": 3,
475 "line": 51
476 },
477 "file": "src/components/auth/Login.js",
478 "id": "login.tokenExpired",
479 "start": {
480 "column": 16,
481 "line": 48
482 }
483 },
484 {
485 "defaultMessage": "!!!Your session expired, please login again.",
486 "end": {
487 "column": 3,
488 "line": 55
489 },
490 "file": "src/components/auth/Login.js",
491 "id": "login.serverLogout",
492 "start": {
493 "column": 16,
494 "line": 52
495 }
496 },
497 {
498 "defaultMessage": "!!!Create a free account",
499 "end": {
500 "column": 3,
501 "line": 59
502 },
503 "file": "src/components/auth/Login.js",
504 "id": "login.link.signup",
505 "start": {
506 "column": 14,
507 "line": 56
508 }
509 },
510 {
511 "defaultMessage": "!!!Change server",
512 "end": {
513 "column": 3,
514 "line": 63
515 },
516 "file": "src/components/auth/Login.js",
517 "id": "login.changeServer",
518 "start": {
519 "column": 16,
520 "line": 60
521 }
522 },
523 {
524 "defaultMessage": "!!!Use Ferdi without an Account",
525 "end": {
526 "column": 3,
527 "line": 67
528 },
529 "file": "src/components/auth/Login.js",
530 "id": "services.serverless",
531 "start": {
532 "column": 14,
533 "line": 64
534 }
535 },
536 {
537 "defaultMessage": "!!!Forgot password",
538 "end": {
539 "column": 3,
540 "line": 71
541 },
542 "file": "src/components/auth/Login.js",
543 "id": "login.link.password",
544 "start": {
545 "column": 16,
546 "line": 68
547 }
548 }
549 ],
550 "path": "src/components/auth/Login.json"
551 },
552 {
553 "descriptors": [
554 {
555 "defaultMessage": "!!!Forgot password",
556 "end": {
557 "column": 3,
558 "line": 18
559 },
560 "file": "src/components/auth/Password.js",
561 "id": "password.headline",
562 "start": {
563 "column": 12,
564 "line": 15
565 }
566 },
567 {
568 "defaultMessage": "!!!Email address",
569 "end": {
570 "column": 3,
571 "line": 22
572 },
573 "file": "src/components/auth/Password.js",
574 "id": "password.email.label",
575 "start": {
576 "column": 14,
577 "line": 19
578 }
579 },
580 {
581 "defaultMessage": "!!!Your new password was sent to your email address",
582 "end": {
583 "column": 3,
584 "line": 26
585 },
586 "file": "src/components/auth/Password.js",
587 "id": "password.successInfo",
588 "start": {
589 "column": 15,
590 "line": 23
591 }
592 },
593 {
594 "defaultMessage": "!!!No user affiliated with that email address",
595 "end": {
596 "column": 3,
597 "line": 30
598 },
599 "file": "src/components/auth/Password.js",
600 "id": "password.noUser",
601 "start": {
602 "column": 10,
603 "line": 27
604 }
605 },
606 {
607 "defaultMessage": "!!!Create a free account",
608 "end": {
609 "column": 3,
610 "line": 34
611 },
612 "file": "src/components/auth/Password.js",
613 "id": "password.link.signup",
614 "start": {
615 "column": 14,
616 "line": 31
617 }
618 },
619 {
620 "defaultMessage": "!!!Sign in to your account",
621 "end": {
622 "column": 3,
623 "line": 38
624 },
625 "file": "src/components/auth/Password.js",
626 "id": "password.link.login",
627 "start": {
628 "column": 13,
629 "line": 35
630 }
631 }
632 ],
633 "path": "src/components/auth/Password.json"
634 },
635 {
636 "descriptors": [
637 {
638 "defaultMessage": "!!!Invite Friends",
639 "end": {
640 "column": 3,
641 "line": 19
642 },
643 "file": "src/components/auth/ServiceAssistant.js",
644 "id": "settings.invite.headline",
645 "start": {
646 "column": 20,
647 "line": 16
648 }
649 },
650 {
651 "defaultMessage": "!!!Invite 3 of your friends or colleagues",
652 "end": {
653 "column": 3,
654 "line": 23
655 },
656 "file": "src/components/auth/ServiceAssistant.js",
657 "id": "invite.headline.friends",
658 "start": {
659 "column": 12,
660 "line": 20
661 }
662 },
663 {
664 "defaultMessage": "!!!Name",
665 "end": {
666 "column": 3,
667 "line": 27
668 },
669 "file": "src/components/auth/ServiceAssistant.js",
670 "id": "invite.name.label",
671 "start": {
672 "column": 13,
673 "line": 24
674 }
675 },
676 {
677 "defaultMessage": "!!!Email address",
678 "end": {
679 "column": 3,
680 "line": 31
681 },
682 "file": "src/components/auth/ServiceAssistant.js",
683 "id": "invite.email.label",
684 "start": {
685 "column": 14,
686 "line": 28
687 }
688 },
689 {
690 "defaultMessage": "!!!Send invites",
691 "end": {
692 "column": 3,
693 "line": 35
694 },
695 "file": "src/components/auth/ServiceAssistant.js",
696 "id": "invite.submit.label",
697 "start": {
698 "column": 21,
699 "line": 32
700 }
701 },
702 {
703 "defaultMessage": "!!!I want to do this later",
704 "end": {
705 "column": 3,
706 "line": 39
707 },
708 "file": "src/components/auth/ServiceAssistant.js",
709 "id": "invite.skip.label",
710 "start": {
711 "column": 19,
712 "line": 36
713 }
714 },
715 {
716 "defaultMessage": "!!!Invitations sent successfully",
717 "end": {
718 "column": 3,
719 "line": 43
720 },
721 "file": "src/components/auth/ServiceAssistant.js",
722 "id": "invite.successInfo",
723 "start": {
724 "column": 21,
725 "line": 40
726 }
727 }
728 ],
729 "path": "src/components/auth/ServiceAssistant.json"
730 },
731 {
732 "descriptors": [
733 {
734 "defaultMessage": "!!!Let's get started",
735 "end": {
736 "column": 3,
737 "line": 23
738 },
739 "file": "src/components/auth/SetupAssistant.js",
740 "id": "setupAssistant.headline",
741 "start": {
742 "column": 12,
743 "line": 20
744 }
745 },
746 {
747 "defaultMessage": "!!!Choose from our most used services and get back on top of your messaging now.",
748 "end": {
749 "column": 3,
750 "line": 28
751 },
752 "file": "src/components/auth/SetupAssistant.js",
753 "id": "setupAssistant.subheadline",
754 "start": {
755 "column": 15,
756 "line": 24
757 }
758 },
759 {
760 "defaultMessage": "!!!Let's go",
761 "end": {
762 "column": 3,
763 "line": 32
764 },
765 "file": "src/components/auth/SetupAssistant.js",
766 "id": "setupAssistant.submit.label",
767 "start": {
768 "column": 21,
769 "line": 29
770 }
771 },
772 {
773 "defaultMessage": "!!!Invitations sent successfully",
774 "end": {
775 "column": 3,
776 "line": 36
777 },
778 "file": "src/components/auth/SetupAssistant.js",
779 "id": "invite.successInfo",
780 "start": {
781 "column": 21,
782 "line": 33
783 }
784 }
785 ],
786 "path": "src/components/auth/SetupAssistant.json"
787 },
788 {
789 "descriptors": [
790 {
791 "defaultMessage": "!!!Sign up",
792 "end": {
793 "column": 3,
794 "line": 23
795 },
796 "file": "src/components/auth/Signup.js",
797 "id": "signup.headline",
798 "start": {
799 "column": 12,
800 "line": 20
801 }
802 },
803 {
804 "defaultMessage": "!!!Firstname",
805 "end": {
806 "column": 3,
807 "line": 27
808 },
809 "file": "src/components/auth/Signup.js",
810 "id": "signup.firstname.label",
811 "start": {
812 "column": 18,
813 "line": 24
814 }
815 },
816 {
817 "defaultMessage": "!!!Lastname",
818 "end": {
819 "column": 3,
820 "line": 31
821 },
822 "file": "src/components/auth/Signup.js",
823 "id": "signup.lastname.label",
824 "start": {
825 "column": 17,
826 "line": 28
827 }
828 },
829 {
830 "defaultMessage": "!!!Email address",
831 "end": {
832 "column": 3,
833 "line": 35
834 },
835 "file": "src/components/auth/Signup.js",
836 "id": "signup.email.label",
837 "start": {
838 "column": 14,
839 "line": 32
840 }
841 },
842 {
843 "defaultMessage": "!!!Password",
844 "end": {
845 "column": 3,
846 "line": 43
847 },
848 "file": "src/components/auth/Signup.js",
849 "id": "signup.password.label",
850 "start": {
851 "column": 17,
852 "line": 40
853 }
854 },
855 {
856 "defaultMessage": "!!!By creating a Ferdi account you accept the",
857 "end": {
858 "column": 3,
859 "line": 47
860 },
861 "file": "src/components/auth/Signup.js",
862 "id": "signup.legal.info",
863 "start": {
864 "column": 13,
865 "line": 44
866 }
867 },
868 {
869 "defaultMessage": "!!!Terms of service",
870 "end": {
871 "column": 3,
872 "line": 51
873 },
874 "file": "src/components/auth/Signup.js",
875 "id": "signup.legal.terms",
876 "start": {
877 "column": 9,
878 "line": 48
879 }
880 },
881 {
882 "defaultMessage": "!!!Privacy Statement",
883 "end": {
884 "column": 3,
885 "line": 55
886 },
887 "file": "src/components/auth/Signup.js",
888 "id": "signup.legal.privacy",
889 "start": {
890 "column": 11,
891 "line": 52
892 }
893 },
894 {
895 "defaultMessage": "!!!Create account",
896 "end": {
897 "column": 3,
898 "line": 59
899 },
900 "file": "src/components/auth/Signup.js",
901 "id": "signup.submit.label",
902 "start": {
903 "column": 21,
904 "line": 56
905 }
906 },
907 {
908 "defaultMessage": "!!!Already have an account, sign in?",
909 "end": {
910 "column": 3,
911 "line": 63
912 },
913 "file": "src/components/auth/Signup.js",
914 "id": "signup.link.login",
915 "start": {
916 "column": 13,
917 "line": 60
918 }
919 },
920 {
921 "defaultMessage": "!!!Change server",
922 "end": {
923 "column": 3,
924 "line": 67
925 },
926 "file": "src/components/auth/Signup.js",
927 "id": "login.changeServer",
928 "start": {
929 "column": 16,
930 "line": 64
931 }
932 },
933 {
934 "defaultMessage": "!!!Use Ferdi without an Account",
935 "end": {
936 "column": 3,
937 "line": 71
938 },
939 "file": "src/components/auth/Signup.js",
940 "id": "services.serverless",
941 "start": {
942 "column": 14,
943 "line": 68
944 }
945 },
946 {
947 "defaultMessage": "!!!A user with that email address already exists",
948 "end": {
949 "column": 3,
950 "line": 75
951 },
952 "file": "src/components/auth/Signup.js",
953 "id": "signup.emailDuplicate",
954 "start": {
955 "column": 18,
956 "line": 72
957 }
958 }
959 ],
960 "path": "src/components/auth/Signup.json"
961 },
962 {
963 "descriptors": [
964 {
965 "defaultMessage": "!!!Create a free account",
966 "end": {
967 "column": 3,
968 "line": 14
969 },
970 "file": "src/components/auth/Welcome.js",
971 "id": "welcome.signupButton",
972 "start": {
973 "column": 16,
974 "line": 11
975 }
976 },
977 {
978 "defaultMessage": "!!!Login to your account",
979 "end": {
980 "column": 3,
981 "line": 18
982 },
983 "file": "src/components/auth/Welcome.js",
984 "id": "welcome.loginButton",
985 "start": {
986 "column": 15,
987 "line": 15
988 }
989 },
990 {
991 "defaultMessage": "!!!Use Ferdi without an Account",
992 "end": {
993 "column": 3,
994 "line": 22
995 },
996 "file": "src/components/auth/Welcome.js",
997 "id": "services.serverless",
998 "start": {
999 "column": 14,
1000 "line": 19
1001 }
1002 }
1003 ],
1004 "path": "src/components/auth/Welcome.json"
1005 },
1006 {
1007 "descriptors": [
1008 {
1009 "defaultMessage": "!!!Your services have been updated.",
1010 "end": {
1011 "column": 3,
1012 "line": 31
1013 },
1014 "file": "src/components/layout/AppLayout.js",
1015 "id": "infobar.servicesUpdated",
1016 "start": {
1017 "column": 19,
1018 "line": 28
1019 }
1020 },
1021 {
1022 "defaultMessage": "!!!Reload services",
1023 "end": {
1024 "column": 3,
1025 "line": 35
1026 },
1027 "file": "src/components/layout/AppLayout.js",
1028 "id": "infobar.buttonReloadServices",
1029 "start": {
1030 "column": 24,
1031 "line": 32
1032 }
1033 },
1034 {
1035 "defaultMessage": "!!!Could not load services and user information",
1036 "end": {
1037 "column": 3,
1038 "line": 39
1039 },
1040 "file": "src/components/layout/AppLayout.js",
1041 "id": "infobar.requiredRequestsFailed",
1042 "start": {
1043 "column": 26,
1044 "line": 36
1045 }
1046 },
1047 {
1048 "defaultMessage": "!!!There were errors while trying to perform an authenticated request. Please try logging out and back in if this error persists.",
1049 "end": {
1050 "column": 3,
1051 "line": 44
1052 },
1053 "file": "src/components/layout/AppLayout.js",
1054 "id": "infobar.authRequestFailed",
1055 "start": {
1056 "column": 21,
1057 "line": 40
1058 }
1059 }
1060 ],
1061 "path": "src/components/layout/AppLayout.json"
1062 },
1063 {
1064 "descriptors": [
1065 {
1066 "defaultMessage": "!!!Add new service",
1067 "end": {
1068 "column": 3,
1069 "line": 21
1070 },
1071 "file": "src/components/layout/Sidebar.js",
1072 "id": "sidebar.addNewService",
1073 "start": {
1074 "column": 17,
1075 "line": 18
1076 }
1077 },
1078 {
1079 "defaultMessage": "!!!Disable notifications & audio",
1080 "end": {
1081 "column": 3,
1082 "line": 25
1083 },
1084 "file": "src/components/layout/Sidebar.js",
1085 "id": "sidebar.muteApp",
1086 "start": {
1087 "column": 8,
1088 "line": 22
1089 }
1090 },
1091 {
1092 "defaultMessage": "!!!Enable notifications & audio",
1093 "end": {
1094 "column": 3,
1095 "line": 29
1096 },
1097 "file": "src/components/layout/Sidebar.js",
1098 "id": "sidebar.unmuteApp",
1099 "start": {
1100 "column": 10,
1101 "line": 26
1102 }
1103 },
1104 {
1105 "defaultMessage": "!!!Open workspace drawer",
1106 "end": {
1107 "column": 3,
1108 "line": 33
1109 },
1110 "file": "src/components/layout/Sidebar.js",
1111 "id": "sidebar.openWorkspaceDrawer",
1112 "start": {
1113 "column": 23,
1114 "line": 30
1115 }
1116 },
1117 {
1118 "defaultMessage": "!!!Close workspace drawer",
1119 "end": {
1120 "column": 3,
1121 "line": 37
1122 },
1123 "file": "src/components/layout/Sidebar.js",
1124 "id": "sidebar.closeWorkspaceDrawer",
1125 "start": {
1126 "column": 24,
1127 "line": 34
1128 }
1129 },
1130 {
1131 "defaultMessage": "!!!Open Ferdi Todos",
1132 "end": {
1133 "column": 3,
1134 "line": 41
1135 },
1136 "file": "src/components/layout/Sidebar.js",
1137 "id": "sidebar.openTodosDrawer",
1138 "start": {
1139 "column": 19,
1140 "line": 38
1141 }
1142 },
1143 {
1144 "defaultMessage": "!!!Close Ferdi Todos",
1145 "end": {
1146 "column": 3,
1147 "line": 45
1148 },
1149 "file": "src/components/layout/Sidebar.js",
1150 "id": "sidebar.closeTodosDrawer",
1151 "start": {
1152 "column": 20,
1153 "line": 42
1154 }
1155 },
1156 {
1157 "defaultMessage": "!!!Lock Ferdi",
1158 "end": {
1159 "column": 3,
1160 "line": 49
1161 },
1162 "file": "src/components/layout/Sidebar.js",
1163 "id": "sidebar.lockFerdi",
1164 "start": {
1165 "column": 13,
1166 "line": 46
1167 }
1168 }
1169 ],
1170 "path": "src/components/layout/Sidebar.json"
1171 },
1172 {
1173 "descriptors": [
1174 {
1175 "defaultMessage": "!!!Home",
1176 "end": {
1177 "column": 3,
1178 "line": 16
1179 },
1180 "file": "src/components/services/content/ConnectionBanner.js",
1181 "id": "webControls.goHome",
1182 "start": {
1183 "column": 10,
1184 "line": 13
1185 }
1186 },
1187 {
1188 "defaultMessage": "!!!Open in Browser",
1189 "end": {
1190 "column": 3,
1191 "line": 20
1192 },
1193 "file": "src/components/services/content/ConnectionBanner.js",
1194 "id": "webControls.openInBrowser",
1195 "start": {
1196 "column": 17,
1197 "line": 17
1198 }
1199 },
1200 {
1201 "defaultMessage": "!!!Back",
1202 "end": {
1203 "column": 3,
1204 "line": 24
1205 },
1206 "file": "src/components/services/content/ConnectionBanner.js",
1207 "id": "webControls.back",
1208 "start": {
1209 "column": 8,
1210 "line": 21
1211 }
1212 },
1213 {
1214 "defaultMessage": "!!!Forward",
1215 "end": {
1216 "column": 3,
1217 "line": 28
1218 },
1219 "file": "src/components/services/content/ConnectionBanner.js",
1220 "id": "webControls.forward",
1221 "start": {
1222 "column": 11,
1223 "line": 25
1224 }
1225 },
1226 {
1227 "defaultMessage": "!!!Reload",
1228 "end": {
1229 "column": 3,
1230 "line": 32
1231 },
1232 "file": "src/components/services/content/ConnectionBanner.js",
1233 "id": "webControls.reload",
1234 "start": {
1235 "column": 10,
1236 "line": 29
1237 }
1238 }
1239 ],
1240 "path": "src/components/services/content/ConnectionBanner.json"
1241 },
1242 {
1243 "descriptors": [
1244 {
1245 "defaultMessage": "!!!Home",
1246 "end": {
1247 "column": 3,
1248 "line": 16
1249 },
1250 "file": "src/components/services/content/ConnectionLost.js",
1251 "id": "webControls.goHome",
1252 "start": {
1253 "column": 10,
1254 "line": 13
1255 }
1256 },
1257 {
1258 "defaultMessage": "!!!Open in Browser",
1259 "end": {
1260 "column": 3,
1261 "line": 20
1262 },
1263 "file": "src/components/services/content/ConnectionLost.js",
1264 "id": "webControls.openInBrowser",
1265 "start": {
1266 "column": 17,
1267 "line": 17
1268 }
1269 },
1270 {
1271 "defaultMessage": "!!!Back",
1272 "end": {
1273 "column": 3,
1274 "line": 24
1275 },
1276 "file": "src/components/services/content/ConnectionLost.js",
1277 "id": "webControls.back",
1278 "start": {
1279 "column": 8,
1280 "line": 21
1281 }
1282 },
1283 {
1284 "defaultMessage": "!!!Forward",
1285 "end": {
1286 "column": 3,
1287 "line": 28
1288 },
1289 "file": "src/components/services/content/ConnectionLost.js",
1290 "id": "webControls.forward",
1291 "start": {
1292 "column": 11,
1293 "line": 25
1294 }
1295 },
1296 {
1297 "defaultMessage": "!!!Reload",
1298 "end": {
1299 "column": 3,
1300 "line": 32
1301 },
1302 "file": "src/components/services/content/ConnectionLost.js",
1303 "id": "webControls.reload",
1304 "start": {
1305 "column": 10,
1306 "line": 29
1307 }
1308 }
1309 ],
1310 "path": "src/components/services/content/ConnectionLost.json"
1311 },
1312 {
1313 "descriptors": [
1314 {
1315 "defaultMessage": "!!!Oh no! Ferdi lost the connection to {name}.",
1316 "end": {
1317 "column": 3,
1318 "line": 16
1319 },
1320 "file": "src/components/services/content/ConnectionLostBanner.js",
1321 "id": "connectionLostBanner.message",
1322 "start": {
1323 "column": 8,
1324 "line": 13
1325 }
1326 },
1327 {
1328 "defaultMessage": "!!!What happened?",
1329 "end": {
1330 "column": 3,
1331 "line": 20
1332 },
1333 "file": "src/components/services/content/ConnectionLostBanner.js",
1334 "id": "connectionLostBanner.informationLink",
1335 "start": {
1336 "column": 19,
1337 "line": 17
1338 }
1339 },
1340 {
1341 "defaultMessage": "!!!Reload Service",
1342 "end": {
1343 "column": 3,
1344 "line": 24
1345 },
1346 "file": "src/components/services/content/ConnectionLostBanner.js",
1347 "id": "connectionLostBanner.cta",
1348 "start": {
1349 "column": 7,
1350 "line": 21
1351 }
1352 }
1353 ],
1354 "path": "src/components/services/content/ConnectionLostBanner.json"
1355 },
1356 {
1357 "descriptors": [
1358 {
1359 "defaultMessage": "!!!Oh no!",
1360 "end": {
1361 "column": 3,
1362 "line": 15
1363 },
1364 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
1365 "id": "service.errorHandler.headline",
1366 "start": {
1367 "column": 12,
1368 "line": 12
1369 }
1370 },
1371 {
1372 "defaultMessage": "!!!{name} has failed to load.",
1373 "end": {
1374 "column": 3,
1375 "line": 19
1376 },
1377 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
1378 "id": "service.errorHandler.text",
1379 "start": {
1380 "column": 8,
1381 "line": 16
1382 }
1383 },
1384 {
1385 "defaultMessage": "!!!Reload {name}",
1386 "end": {
1387 "column": 3,
1388 "line": 23
1389 },
1390 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
1391 "id": "service.errorHandler.action",
1392 "start": {
1393 "column": 10,
1394 "line": 20
1395 }
1396 },
1397 {
1398 "defaultMessage": "!!!Edit {name}",
1399 "end": {
1400 "column": 3,
1401 "line": 27
1402 },
1403 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
1404 "id": "service.errorHandler.editAction",
1405 "start": {
1406 "column": 14,
1407 "line": 24
1408 }
1409 },
1410 {
1411 "defaultMessage": "!!!Error:",
1412 "end": {
1413 "column": 3,
1414 "line": 31
1415 },
1416 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
1417 "id": "service.errorHandler.message",
1418 "start": {
1419 "column": 16,
1420 "line": 28
1421 }
1422 }
1423 ],
1424 "path": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.json"
1425 },
1426 {
1427 "descriptors": [
1428 {
1429 "defaultMessage": "!!!{name} is disabled",
1430 "end": {
1431 "column": 3,
1432 "line": 12
1433 },
1434 "file": "src/components/services/content/ServiceDisabled.js",
1435 "id": "service.disabledHandler.headline",
1436 "start": {
1437 "column": 12,
1438 "line": 9
1439 }
1440 },
1441 {
1442 "defaultMessage": "!!!Enable {name}",
1443 "end": {
1444 "column": 3,
1445 "line": 16
1446 },
1447 "file": "src/components/services/content/ServiceDisabled.js",
1448 "id": "service.disabledHandler.action",
1449 "start": {
1450 "column": 10,
1451 "line": 13
1452 }
1453 }
1454 ],
1455 "path": "src/components/services/content/ServiceDisabled.json"
1456 },
1457 {
1458 "descriptors": [
1459 {
1460 "defaultMessage": "!!!Welcome to Ferdi",
1461 "end": {
1462 "column": 3,
1463 "line": 18
1464 },
1465 "file": "src/components/services/content/Services.js",
1466 "id": "services.welcome",
1467 "start": {
1468 "column": 11,
1469 "line": 15
1470 }
1471 },
1472 {
1473 "defaultMessage": "!!!Get started",
1474 "end": {
1475 "column": 3,
1476 "line": 22
1477 },
1478 "file": "src/components/services/content/Services.js",
1479 "id": "services.getStarted",
1480 "start": {
1481 "column": 14,
1482 "line": 19
1483 }
1484 },
1485 {
1486 "defaultMessage": "!!!Please login to use Ferdi.",
1487 "end": {
1488 "column": 3,
1489 "line": 26
1490 },
1491 "file": "src/components/services/content/Services.js",
1492 "id": "services.login",
1493 "start": {
1494 "column": 9,
1495 "line": 23
1496 }
1497 },
1498 {
1499 "defaultMessage": "!!!Use Ferdi without an Account",
1500 "end": {
1501 "column": 3,
1502 "line": 30
1503 },
1504 "file": "src/components/services/content/Services.js",
1505 "id": "services.serverless",
1506 "start": {
1507 "column": 14,
1508 "line": 27
1509 }
1510 },
1511 {
1512 "defaultMessage": "!!!Optionally, you can change your Ferdi server by clicking the cog in the bottom left corner. If you are switching over (from one of the hosted servers) to using Ferdi without an account, please be informed that you can export your data from that server and subsequently import it using the Help menu to resurrect all your workspaces and configured services!",
1513 "end": {
1514 "column": 3,
1515 "line": 34
1516 },
1517 "file": "src/components/services/content/Services.js",
1518 "id": "services.serverInfo",
1519 "start": {
1520 "column": 14,
1521 "line": 31
1522 }
1523 }
1524 ],
1525 "path": "src/components/services/content/Services.json"
1526 },
1527 {
1528 "descriptors": [
1529 {
1530 "defaultMessage": "!!!Home",
1531 "end": {
1532 "column": 3,
1533 "line": 16
1534 },
1535 "file": "src/components/services/content/WebControls.js",
1536 "id": "webControls.goHome",
1537 "start": {
1538 "column": 10,
1539 "line": 13
1540 }
1541 },
1542 {
1543 "defaultMessage": "!!!Open in Browser",
1544 "end": {
1545 "column": 3,
1546 "line": 20
1547 },
1548 "file": "src/components/services/content/WebControls.js",
1549 "id": "webControls.openInBrowser",
1550 "start": {
1551 "column": 17,
1552 "line": 17
1553 }
1554 },
1555 {
1556 "defaultMessage": "!!!Back",
1557 "end": {
1558 "column": 3,
1559 "line": 24
1560 },
1561 "file": "src/components/services/content/WebControls.js",
1562 "id": "webControls.back",
1563 "start": {
1564 "column": 8,
1565 "line": 21
1566 }
1567 },
1568 {
1569 "defaultMessage": "!!!Forward",
1570 "end": {
1571 "column": 3,
1572 "line": 28
1573 },
1574 "file": "src/components/services/content/WebControls.js",
1575 "id": "webControls.forward",
1576 "start": {
1577 "column": 11,
1578 "line": 25
1579 }
1580 },
1581 {
1582 "defaultMessage": "!!!Reload",
1583 "end": {
1584 "column": 3,
1585 "line": 32
1586 },
1587 "file": "src/components/services/content/WebControls.js",
1588 "id": "webControls.reload",
1589 "start": {
1590 "column": 10,
1591 "line": 29
1592 }
1593 }
1594 ],
1595 "path": "src/components/services/content/WebControls.json"
1596 },
1597 {
1598 "descriptors": [
1599 {
1600 "defaultMessage": "!!!Oh no!",
1601 "end": {
1602 "column": 3,
1603 "line": 13
1604 },
1605 "file": "src/components/services/content/WebviewCrashHandler.js",
1606 "id": "service.crashHandler.headline",
1607 "start": {
1608 "column": 12,
1609 "line": 10
1610 }
1611 },
1612 {
1613 "defaultMessage": "!!!{name} has caused an error.",
1614 "end": {
1615 "column": 3,
1616 "line": 17
1617 },
1618 "file": "src/components/services/content/WebviewCrashHandler.js",
1619 "id": "service.crashHandler.text",
1620 "start": {
1621 "column": 8,
1622 "line": 14
1623 }
1624 },
1625 {
1626 "defaultMessage": "!!!Reload {name}",
1627 "end": {
1628 "column": 3,
1629 "line": 21
1630 },
1631 "file": "src/components/services/content/WebviewCrashHandler.js",
1632 "id": "service.crashHandler.action",
1633 "start": {
1634 "column": 10,
1635 "line": 18
1636 }
1637 },
1638 {
1639 "defaultMessage": "!!!Trying to automatically restore {name} in {seconds} seconds",
1640 "end": {
1641 "column": 3,
1642 "line": 25
1643 },
1644 "file": "src/components/services/content/WebviewCrashHandler.js",
1645 "id": "service.crashHandler.autoReload",
1646 "start": {
1647 "column": 14,
1648 "line": 22
1649 }
1650 }
1651 ],
1652 "path": "src/components/services/content/WebviewCrashHandler.json"
1653 },
1654 {
1655 "descriptors": [
1656 {
1657 "defaultMessage": "!!!Reload",
1658 "end": {
1659 "column": 3,
1660 "line": 24
1661 },
1662 "file": "src/components/services/tabs/TabItem.js",
1663 "id": "tabs.item.reload",
1664 "start": {
1665 "column": 10,
1666 "line": 21
1667 }
1668 },
1669 {
1670 "defaultMessage": "!!!Disable notifications",
1671 "end": {
1672 "column": 3,
1673 "line": 28
1674 },
1675 "file": "src/components/services/tabs/TabItem.js",
1676 "id": "tabs.item.disableNotifications",
1677 "start": {
1678 "column": 24,
1679 "line": 25
1680 }
1681 },
1682 {
1683 "defaultMessage": "!!!Enable notifications",
1684 "end": {
1685 "column": 3,
1686 "line": 32
1687 },
1688 "file": "src/components/services/tabs/TabItem.js",
1689 "id": "tabs.item.enableNotification",
1690 "start": {
1691 "column": 23,
1692 "line": 29
1693 }
1694 },
1695 {
1696 "defaultMessage": "!!!Disable audio",
1697 "end": {
1698 "column": 3,
1699 "line": 36
1700 },
1701 "file": "src/components/services/tabs/TabItem.js",
1702 "id": "tabs.item.disableAudio",
1703 "start": {
1704 "column": 16,
1705 "line": 33
1706 }
1707 },
1708 {
1709 "defaultMessage": "!!!Enable audio",
1710 "end": {
1711 "column": 3,
1712 "line": 40
1713 },
1714 "file": "src/components/services/tabs/TabItem.js",
1715 "id": "tabs.item.enableAudio",
1716 "start": {
1717 "column": 15,
1718 "line": 37
1719 }
1720 },
1721 {
1722 "defaultMessage": "!!!Enable Dark mode",
1723 "end": {
1724 "column": 3,
1725 "line": 44
1726 },
1727 "file": "src/components/services/tabs/TabItem.js",
1728 "id": "tabs.item.enableDarkMode",
1729 "start": {
1730 "column": 18,
1731 "line": 41
1732 }
1733 },
1734 {
1735 "defaultMessage": "!!!Disable Dark mode",
1736 "end": {
1737 "column": 3,
1738 "line": 48
1739 },
1740 "file": "src/components/services/tabs/TabItem.js",
1741 "id": "tabs.item.disableDarkMode",
1742 "start": {
1743 "column": 19,
1744 "line": 45
1745 }
1746 },
1747 {
1748 "defaultMessage": "!!!Disable Service",
1749 "end": {
1750 "column": 3,
1751 "line": 52
1752 },
1753 "file": "src/components/services/tabs/TabItem.js",
1754 "id": "tabs.item.disableService",
1755 "start": {
1756 "column": 18,
1757 "line": 49
1758 }
1759 },
1760 {
1761 "defaultMessage": "!!!Enable Service",
1762 "end": {
1763 "column": 3,
1764 "line": 56
1765 },
1766 "file": "src/components/services/tabs/TabItem.js",
1767 "id": "tabs.item.enableService",
1768 "start": {
1769 "column": 17,
1770 "line": 53
1771 }
1772 },
1773 {
1774 "defaultMessage": "!!!Hibernate Service",
1775 "end": {
1776 "column": 3,
1777 "line": 60
1778 },
1779 "file": "src/components/services/tabs/TabItem.js",
1780 "id": "tabs.item.hibernateService",
1781 "start": {
1782 "column": 20,
1783 "line": 57
1784 }
1785 },
1786 {
1787 "defaultMessage": "!!!Wake Up Service",
1788 "end": {
1789 "column": 3,
1790 "line": 64
1791 },
1792 "file": "src/components/services/tabs/TabItem.js",
1793 "id": "tabs.item.wakeUpService",
1794 "start": {
1795 "column": 17,
1796 "line": 61
1797 }
1798 },
1799 {
1800 "defaultMessage": "!!!Delete Service",
1801 "end": {
1802 "column": 3,
1803 "line": 68
1804 },
1805 "file": "src/components/services/tabs/TabItem.js",
1806 "id": "tabs.item.deleteService",
1807 "start": {
1808 "column": 17,
1809 "line": 65
1810 }
1811 },
1812 {
1813 "defaultMessage": "!!!Do you really want to delete the {serviceName} service?",
1814 "end": {
1815 "column": 3,
1816 "line": 73
1817 },
1818 "file": "src/components/services/tabs/TabItem.js",
1819 "id": "tabs.item.confirmDeleteService",
1820 "start": {
1821 "column": 24,
1822 "line": 69
1823 }
1824 }
1825 ],
1826 "path": "src/components/services/tabs/TabItem.json"
1827 },
1828 {
1829 "descriptors": [
1830 {
1831 "defaultMessage": "!!!Account",
1832 "end": {
1833 "column": 3,
1834 "line": 17
1835 },
1836 "file": "src/components/settings/account/AccountDashboard.js",
1837 "id": "settings.account.headline",
1838 "start": {
1839 "column": 12,
1840 "line": 14
1841 }
1842 },
1843 {
1844 "defaultMessage": "!!Danger Zone",
1845 "end": {
1846 "column": 3,
1847 "line": 21
1848 },
1849 "file": "src/components/settings/account/AccountDashboard.js",
1850 "id": "settings.account.headlineDangerZone",
1851 "start": {
1852 "column": 22,
1853 "line": 18
1854 }
1855 },
1856 {
1857 "defaultMessage": "!!!Edit Account",
1858 "end": {
1859 "column": 3,
1860 "line": 25
1861 },
1862 "file": "src/components/settings/account/AccountDashboard.js",
1863 "id": "settings.account.account.editButton",
1864 "start": {
1865 "column": 21,
1866 "line": 22
1867 }
1868 },
1869 {
1870 "defaultMessage": "!!Invoices",
1871 "end": {
1872 "column": 3,
1873 "line": 29
1874 },
1875 "file": "src/components/settings/account/AccountDashboard.js",
1876 "id": "settings.account.headlineInvoices",
1877 "start": {
1878 "column": 18,
1879 "line": 26
1880 }
1881 },
1882 {
1883 "defaultMessage": "!!!Could not load user information",
1884 "end": {
1885 "column": 3,
1886 "line": 33
1887 },
1888 "file": "src/components/settings/account/AccountDashboard.js",
1889 "id": "settings.account.userInfoRequestFailed",
1890 "start": {
1891 "column": 25,
1892 "line": 30
1893 }
1894 },
1895 {
1896 "defaultMessage": "!!!Try again",
1897 "end": {
1898 "column": 3,
1899 "line": 37
1900 },
1901 "file": "src/components/settings/account/AccountDashboard.js",
1902 "id": "settings.account.tryReloadUserInfoRequest",
1903 "start": {
1904 "column": 28,
1905 "line": 34
1906 }
1907 },
1908 {
1909 "defaultMessage": "!!!Delete account",
1910 "end": {
1911 "column": 3,
1912 "line": 41
1913 },
1914 "file": "src/components/settings/account/AccountDashboard.js",
1915 "id": "settings.account.deleteAccount",
1916 "start": {
1917 "column": 17,
1918 "line": 38
1919 }
1920 },
1921 {
1922 "defaultMessage": "!!!If you don't need your Ferdi account any longer, you can delete your account and all related data here.",
1923 "end": {
1924 "column": 3,
1925 "line": 46
1926 },
1927 "file": "src/components/settings/account/AccountDashboard.js",
1928 "id": "settings.account.deleteInfo",
1929 "start": {
1930 "column": 14,
1931 "line": 42
1932 }
1933 },
1934 {
1935 "defaultMessage": "!!!You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!",
1936 "end": {
1937 "column": 3,
1938 "line": 51
1939 },
1940 "file": "src/components/settings/account/AccountDashboard.js",
1941 "id": "settings.account.deleteEmailSent",
1942 "start": {
1943 "column": 19,
1944 "line": 47
1945 }
1946 },
1947 {
1948 "defaultMessage": "!!!Your Franz License:",
1949 "end": {
1950 "column": 3,
1951 "line": 55
1952 },
1953 "file": "src/components/settings/account/AccountDashboard.js",
1954 "id": "settings.account.yourLicense",
1955 "start": {
1956 "column": 15,
1957 "line": 52
1958 }
1959 },
1960 {
1961 "defaultMessage": "Account is unavailable",
1962 "end": {
1963 "column": 3,
1964 "line": 59
1965 },
1966 "file": "src/components/settings/account/AccountDashboard.js",
1967 "id": "settings.account.accountUnavailable",
1968 "start": {
1969 "column": 22,
1970 "line": 56
1971 }
1972 },
1973 {
1974 "defaultMessage": "You are using Ferdi without an account. If you want to use Ferdi with an account and keep your services synchronized across installations, please select a server in the Settings tab then login.",
1975 "end": {
1976 "column": 3,
1977 "line": 63
1978 },
1979 "file": "src/components/settings/account/AccountDashboard.js",
1980 "id": "settings.account.accountUnavailableInfo",
1981 "start": {
1982 "column": 26,
1983 "line": 60
1984 }
1985 }
1986 ],
1987 "path": "src/components/settings/account/AccountDashboard.json"
1988 },
1989 {
1990 "descriptors": [
1991 {
1992 "defaultMessage": "!!!Available services",
1993 "end": {
1994 "column": 3,
1995 "line": 19
1996 },
1997 "file": "src/components/settings/navigation/SettingsNavigation.js",
1998 "id": "settings.navigation.availableServices",
1999 "start": {
2000 "column": 21,
2001 "line": 16
2002 }
2003 },
2004 {
2005 "defaultMessage": "!!!Your services",
2006 "end": {
2007 "column": 3,
2008 "line": 23
2009 },
2010 "file": "src/components/settings/navigation/SettingsNavigation.js",
2011 "id": "settings.navigation.yourServices",
2012 "start": {
2013 "column": 16,
2014 "line": 20
2015 }
2016 },
2017 {
2018 "defaultMessage": "!!!Your workspaces",
2019 "end": {
2020 "column": 3,
2021 "line": 27
2022 },
2023 "file": "src/components/settings/navigation/SettingsNavigation.js",
2024 "id": "settings.navigation.yourWorkspaces",
2025 "start": {
2026 "column": 18,
2027 "line": 24
2028 }
2029 },
2030 {
2031 "defaultMessage": "!!!Account",
2032 "end": {
2033 "column": 3,
2034 "line": 31
2035 },
2036 "file": "src/components/settings/navigation/SettingsNavigation.js",
2037 "id": "settings.navigation.account",
2038 "start": {
2039 "column": 11,
2040 "line": 28
2041 }
2042 },
2043 {
2044 "defaultMessage": "!!!Manage Team",
2045 "end": {
2046 "column": 3,
2047 "line": 35
2048 },
2049 "file": "src/components/settings/navigation/SettingsNavigation.js",
2050 "id": "settings.navigation.team",
2051 "start": {
2052 "column": 8,
2053 "line": 32
2054 }
2055 },
2056 {
2057 "defaultMessage": "!!!About Ferdi",
2058 "end": {
2059 "column": 3,
2060 "line": 39
2061 },
2062 "file": "src/components/settings/navigation/SettingsNavigation.js",
2063 "id": "settings.navigation.supportFerdi",
2064 "start": {
2065 "column": 16,
2066 "line": 36
2067 }
2068 },
2069 {
2070 "defaultMessage": "!!!Logout",
2071 "end": {
2072 "column": 3,
2073 "line": 43
2074 },
2075 "file": "src/components/settings/navigation/SettingsNavigation.js",
2076 "id": "settings.navigation.logout",
2077 "start": {
2078 "column": 10,
2079 "line": 40
2080 }
2081 }
2082 ],
2083 "path": "src/components/settings/navigation/SettingsNavigation.json"
2084 },
2085 {
2086 "descriptors": [
2087 {
2088 "defaultMessage": "!!!Available Services",
2089 "end": {
2090 "column": 3,
2091 "line": 22
2092 },
2093 "file": "src/components/settings/recipes/RecipesDashboard.js",
2094 "id": "settings.recipes.headline",
2095 "start": {
2096 "column": 12,
2097 "line": 19
2098 }
2099 },
2100 {
2101 "defaultMessage": "!!!Search service",
2102 "end": {
2103 "column": 3,
2104 "line": 26
2105 },
2106 "file": "src/components/settings/recipes/RecipesDashboard.js",
2107 "id": "settings.searchService",
2108 "start": {
2109 "column": 17,
2110 "line": 23
2111 }
2112 },
2113 {
2114 "defaultMessage": "!!!All services",
2115 "end": {
2116 "column": 3,
2117 "line": 30
2118 },
2119 "file": "src/components/settings/recipes/RecipesDashboard.js",
2120 "id": "settings.recipes.all",
2121 "start": {
2122 "column": 14,
2123 "line": 27
2124 }
2125 },
2126 {
2127 "defaultMessage": "!!!Custom Services",
2128 "end": {
2129 "column": 3,
2130 "line": 34
2131 },
2132 "file": "src/components/settings/recipes/RecipesDashboard.js",
2133 "id": "settings.recipes.custom",
2134 "start": {
2135 "column": 17,
2136 "line": 31
2137 }
2138 },
2139 {
2140 "defaultMessage": "!!!Sorry, but no service matched your search term - but you can still probably add it using the \"Custom Website\" option. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.",
2141 "end": {
2142 "column": 3,
2143 "line": 38
2144 },
2145 "file": "src/components/settings/recipes/RecipesDashboard.js",
2146 "id": "settings.recipes.nothingFound",
2147 "start": {
2148 "column": 16,
2149 "line": 35
2150 }
2151 },
2152 {
2153 "defaultMessage": "!!!Service successfully added",
2154 "end": {
2155 "column": 3,
2156 "line": 42
2157 },
2158 "file": "src/components/settings/recipes/RecipesDashboard.js",
2159 "id": "settings.recipes.servicesSuccessfulAddedInfo",
2160 "start": {
2161 "column": 31,
2162 "line": 39
2163 }
2164 },
2165 {
2166 "defaultMessage": "!!!Missing a service?",
2167 "end": {
2168 "column": 3,
2169 "line": 46
2170 },
2171 "file": "src/components/settings/recipes/RecipesDashboard.js",
2172 "id": "settings.recipes.missingService",
2173 "start": {
2174 "column": 18,
2175 "line": 43
2176 }
2177 },
2178 {
2179 "defaultMessage": "!!!To add a custom service, copy the recipe folder into:",
2180 "end": {
2181 "column": 3,
2182 "line": 50
2183 },
2184 "file": "src/components/settings/recipes/RecipesDashboard.js",
2185 "id": "settings.recipes.customService.intro",
2186 "start": {
2187 "column": 21,
2188 "line": 47
2189 }
2190 },
2191 {
2192 "defaultMessage": "!!!Open directory",
2193 "end": {
2194 "column": 3,
2195 "line": 54
2196 },
2197 "file": "src/components/settings/recipes/RecipesDashboard.js",
2198 "id": "settings.recipes.customService.openFolder",
2199 "start": {
2200 "column": 14,
2201 "line": 51
2202 }
2203 },
2204 {
2205 "defaultMessage": "!!!Developer Documentation",
2206 "end": {
2207 "column": 3,
2208 "line": 58
2209 },
2210 "file": "src/components/settings/recipes/RecipesDashboard.js",
2211 "id": "settings.recipes.customService.openDevDocs",
2212 "start": {
2213 "column": 15,
2214 "line": 55
2215 }
2216 },
2217 {
2218 "defaultMessage": "!!!Custom 3rd Party Recipes",
2219 "end": {
2220 "column": 3,
2221 "line": 62
2222 },
2223 "file": "src/components/settings/recipes/RecipesDashboard.js",
2224 "id": "settings.recipes.customService.headline.customRecipes",
2225 "start": {
2226 "column": 25,
2227 "line": 59
2228 }
2229 },
2230 {
2231 "defaultMessage": "!!!Community 3rd Party Recipes",
2232 "end": {
2233 "column": 3,
2234 "line": 66
2235 },
2236 "file": "src/components/settings/recipes/RecipesDashboard.js",
2237 "id": "settings.recipes.customService.headline.communityRecipes",
2238 "start": {
2239 "column": 28,
2240 "line": 63
2241 }
2242 },
2243 {
2244 "defaultMessage": "!!!Your Development Service Recipes",
2245 "end": {
2246 "column": 3,
2247 "line": 70
2248 },
2249 "file": "src/components/settings/recipes/RecipesDashboard.js",
2250 "id": "settings.recipes.customService.headline.devRecipes",
2251 "start": {
2252 "column": 22,
2253 "line": 67
2254 }
2255 }
2256 ],
2257 "path": "src/components/settings/recipes/RecipesDashboard.json"
2258 },
2259 {
2260 "descriptors": [
2261 {
2262 "defaultMessage": "!!!Save service",
2263 "end": {
2264 "column": 3,
2265 "line": 26
2266 },
2267 "file": "src/components/settings/services/EditServiceForm.js",
2268 "id": "settings.service.form.saveButton",
2269 "start": {
2270 "column": 15,
2271 "line": 23
2272 }
2273 },
2274 {
2275 "defaultMessage": "!!!Delete Service",
2276 "end": {
2277 "column": 3,
2278 "line": 30
2279 },
2280 "file": "src/components/settings/services/EditServiceForm.js",
2281 "id": "settings.service.form.deleteButton",
2282 "start": {
2283 "column": 17,
2284 "line": 27
2285 }
2286 },
2287 {
2288 "defaultMessage": "!!!Open darkmode.css",
2289 "end": {
2290 "column": 3,
2291 "line": 34
2292 },
2293 "file": "src/components/settings/services/EditServiceForm.js",
2294 "id": "settings.service.form.openDarkmodeCss",
2295 "start": {
2296 "column": 19,
2297 "line": 31
2298 }
2299 },
2300 {
2301 "defaultMessage": "!!!Open user.css",
2302 "end": {
2303 "column": 3,
2304 "line": 38
2305 },
2306 "file": "src/components/settings/services/EditServiceForm.js",
2307 "id": "settings.service.form.openUserCss",
2308 "start": {
2309 "column": 15,
2310 "line": 35
2311 }
2312 },
2313 {
2314 "defaultMessage": "!!!Open user.js",
2315 "end": {
2316 "column": 3,
2317 "line": 42
2318 },
2319 "file": "src/components/settings/services/EditServiceForm.js",
2320 "id": "settings.service.form.openUserJs",
2321 "start": {
2322 "column": 14,
2323 "line": 39
2324 }
2325 },
2326 {
2327 "defaultMessage": "!!!Your user files will be inserted into the webpage so you can customize services in any way you like. User files are only stored locally and are not transferred to other computers using the same account.",
2328 "end": {
2329 "column": 3,
2330 "line": 46
2331 },
2332 "file": "src/components/settings/services/EditServiceForm.js",
2333 "id": "settings.service.form.recipeFileInfo",
2334 "start": {
2335 "column": 18,
2336 "line": 43
2337 }
2338 },
2339 {
2340 "defaultMessage": "!!!Available services",
2341 "end": {
2342 "column": 3,
2343 "line": 50
2344 },
2345 "file": "src/components/settings/services/EditServiceForm.js",
2346 "id": "settings.service.form.availableServices",
2347 "start": {
2348 "column": 21,
2349 "line": 47
2350 }
2351 },
2352 {
2353 "defaultMessage": "!!!Your services",
2354 "end": {
2355 "column": 3,
2356 "line": 54
2357 },
2358 "file": "src/components/settings/services/EditServiceForm.js",
2359 "id": "settings.service.form.yourServices",
2360 "start": {
2361 "column": 16,
2362 "line": 51
2363 }
2364 },
2365 {
2366 "defaultMessage": "!!!Add {name}",
2367 "end": {
2368 "column": 3,
2369 "line": 58
2370 },
2371 "file": "src/components/settings/services/EditServiceForm.js",
2372 "id": "settings.service.form.addServiceHeadline",
2373 "start": {
2374 "column": 22,
2375 "line": 55
2376 }
2377 },
2378 {
2379 "defaultMessage": "!!!Edit {name}",
2380 "end": {
2381 "column": 3,
2382 "line": 62
2383 },
2384 "file": "src/components/settings/services/EditServiceForm.js",
2385 "id": "settings.service.form.editServiceHeadline",
2386 "start": {
2387 "column": 23,
2388 "line": 59
2389 }
2390 },
2391 {
2392 "defaultMessage": "!!!Hosted",
2393 "end": {
2394 "column": 3,
2395 "line": 66
2396 },
2397 "file": "src/components/settings/services/EditServiceForm.js",
2398 "id": "settings.service.form.tabHosted",
2399 "start": {
2400 "column": 13,
2401 "line": 63
2402 }
2403 },
2404 {
2405 "defaultMessage": "!!!Self hosted ⭐️",
2406 "end": {
2407 "column": 3,
2408 "line": 70
2409 },
2410 "file": "src/components/settings/services/EditServiceForm.js",
2411 "id": "settings.service.form.tabOnPremise",
2412 "start": {
2413 "column": 16,
2414 "line": 67
2415 }
2416 },
2417 {
2418 "defaultMessage": "!!!Use the hosted {name} service.",
2419 "end": {
2420 "column": 3,
2421 "line": 74
2422 },
2423 "file": "src/components/settings/services/EditServiceForm.js",
2424 "id": "settings.service.form.useHostedService",
2425 "start": {
2426 "column": 20,
2427 "line": 71
2428 }
2429 },
2430 {
2431 "defaultMessage": "!!!Could not validate custom {name} server.",
2432 "end": {
2433 "column": 3,
2434 "line": 78
2435 },
2436 "file": "src/components/settings/services/EditServiceForm.js",
2437 "id": "settings.service.form.customUrlValidationError",
2438 "start": {
2439 "column": 28,
2440 "line": 75
2441 }
2442 },
2443 {
2444 "defaultMessage": "!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...",
2445 "end": {
2446 "column": 3,
2447 "line": 82
2448 },
2449 "file": "src/components/settings/services/EditServiceForm.js",
2450 "id": "settings.service.form.indirectMessageInfo",
2451 "start": {
2452 "column": 23,
2453 "line": 79
2454 }
2455 },
2456 {
2457 "defaultMessage": "!!!When disabled, all notification sounds and audio playback are muted",
2458 "end": {
2459 "column": 3,
2460 "line": 86
2461 },
2462 "file": "src/components/settings/services/EditServiceForm.js",
2463 "id": "settings.service.form.isMutedInfo",
2464 "start": {
2465 "column": 15,
2466 "line": 83
2467 }
2468 },
2469 {
2470 "defaultMessage": "!!!When enabled, a service will be shut down after a period of time to save system resources.",
2471 "end": {
2472 "column": 3,
2473 "line": 90
2474 },
2475 "file": "src/components/settings/services/EditServiceForm.js",
2476 "id": "settings.service.form.isHibernatedEnabledInfo",
2477 "start": {
2478 "column": 28,
2479 "line": 87
2480 }
2481 },
2482 {
2483 "defaultMessage": "!!!Notifications",
2484 "end": {
2485 "column": 3,
2486 "line": 94
2487 },
2488 "file": "src/components/settings/services/EditServiceForm.js",
2489 "id": "settings.service.form.headlineNotifications",
2490 "start": {
2491 "column": 25,
2492 "line": 91
2493 }
2494 },
2495 {
2496 "defaultMessage": "!!!Unread message badges",
2497 "end": {
2498 "column": 3,
2499 "line": 98
2500 },
2501 "file": "src/components/settings/services/EditServiceForm.js",
2502 "id": "settings.service.form.headlineBadges",
2503 "start": {
2504 "column": 18,
2505 "line": 95
2506 }
2507 },
2508 {
2509 "defaultMessage": "!!!General",
2510 "end": {
2511 "column": 3,
2512 "line": 102
2513 },
2514 "file": "src/components/settings/services/EditServiceForm.js",
2515 "id": "settings.service.form.headlineGeneral",
2516 "start": {
2517 "column": 19,
2518 "line": 99
2519 }
2520 },
2521 {
2522 "defaultMessage": "!!!Dark Reader Settings",
2523 "end": {
2524 "column": 3,
2525 "line": 106
2526 },
2527 "file": "src/components/settings/services/EditServiceForm.js",
2528 "id": "settings.service.form.headlineDarkReaderSettings",
2529 "start": {
2530 "column": 30,
2531 "line": 103
2532 }
2533 },
2534 {
2535 "defaultMessage": "!!!Delete",
2536 "end": {
2537 "column": 3,
2538 "line": 110
2539 },
2540 "file": "src/components/settings/services/EditServiceForm.js",
2541 "id": "settings.service.form.iconDelete",
2542 "start": {
2543 "column": 14,
2544 "line": 107
2545 }
2546 },
2547 {
2548 "defaultMessage": "!!!Drop your image, or click here",
2549 "end": {
2550 "column": 3,
2551 "line": 114
2552 },
2553 "file": "src/components/settings/services/EditServiceForm.js",
2554 "id": "settings.service.form.iconUpload",
2555 "start": {
2556 "column": 14,
2557 "line": 111
2558 }
2559 },
2560 {
2561 "defaultMessage": "!!!HTTP/HTTPS Proxy Settings",
2562 "end": {
2563 "column": 3,
2564 "line": 118
2565 },
2566 "file": "src/components/settings/services/EditServiceForm.js",
2567 "id": "settings.service.form.proxy.headline",
2568 "start": {
2569 "column": 17,
2570 "line": 115
2571 }
2572 },
2573 {
2574 "defaultMessage": "!!!Please restart Ferdi after changing proxy Settings.",
2575 "end": {
2576 "column": 3,
2577 "line": 122
2578 },
2579 "file": "src/components/settings/services/EditServiceForm.js",
2580 "id": "settings.service.form.proxy.restartInfo",
2581 "start": {
2582 "column": 20,
2583 "line": 119
2584 }
2585 },
2586 {
2587 "defaultMessage": "!!!Proxy settings will not be synchronized with the Ferdi servers.",
2588 "end": {
2589 "column": 3,
2590 "line": 126
2591 },
2592 "file": "src/components/settings/services/EditServiceForm.js",
2593 "id": "settings.service.form.proxy.info",
2594 "start": {
2595 "column": 13,
2596 "line": 123
2597 }
2598 }
2599 ],
2600 "path": "src/components/settings/services/EditServiceForm.json"
2601 },
2602 {
2603 "descriptors": [
2604 {
2605 "defaultMessage": "!!!Error",
2606 "end": {
2607 "column": 3,
2608 "line": 13
2609 },
2610 "file": "src/components/settings/services/ServiceError.js",
2611 "id": "settings.service.error.headline",
2612 "start": {
2613 "column": 12,
2614 "line": 10
2615 }
2616 },
2617 {
2618 "defaultMessage": "!!!Back to services",
2619 "end": {
2620 "column": 3,
2621 "line": 17
2622 },
2623 "file": "src/components/settings/services/ServiceError.js",
2624 "id": "settings.service.error.goBack",
2625 "start": {
2626 "column": 10,
2627 "line": 14
2628 }
2629 },
2630 {
2631 "defaultMessage": "!!!Available services",
2632 "end": {
2633 "column": 3,
2634 "line": 21
2635 },
2636 "file": "src/components/settings/services/ServiceError.js",
2637 "id": "settings.service.form.availableServices",
2638 "start": {
2639 "column": 21,
2640 "line": 18
2641 }
2642 },
2643 {
2644 "defaultMessage": "!!!Could not load service recipe.",
2645 "end": {
2646 "column": 3,
2647 "line": 25
2648 },
2649 "file": "src/components/settings/services/ServiceError.js",
2650 "id": "settings.service.error.message",
2651 "start": {
2652 "column": 16,
2653 "line": 22
2654 }
2655 }
2656 ],
2657 "path": "src/components/settings/services/ServiceError.json"
2658 },
2659 {
2660 "descriptors": [
2661 {
2662 "defaultMessage": "!!!Service is disabled",
2663 "end": {
2664 "column": 3,
2665 "line": 14
2666 },
2667 "file": "src/components/settings/services/ServiceItem.js",
2668 "id": "settings.services.tooltip.isDisabled",
2669 "start": {
2670 "column": 21,
2671 "line": 11
2672 }
2673 },
2674 {
2675 "defaultMessage": "!!!Notifications are disabled",
2676 "end": {
2677 "column": 3,
2678 "line": 18
2679 },
2680 "file": "src/components/settings/services/ServiceItem.js",
2681 "id": "settings.services.tooltip.notificationsDisabled",
2682 "start": {
2683 "column": 32,
2684 "line": 15
2685 }
2686 },
2687 {
2688 "defaultMessage": "!!!All sounds are muted",
2689 "end": {
2690 "column": 3,
2691 "line": 22
2692 },
2693 "file": "src/components/settings/services/ServiceItem.js",
2694 "id": "settings.services.tooltip.isMuted",
2695 "start": {
2696 "column": 18,
2697 "line": 19
2698 }
2699 }
2700 ],
2701 "path": "src/components/settings/services/ServiceItem.json"
2702 },
2703 {
2704 "descriptors": [
2705 {
2706 "defaultMessage": "!!!Your services",
2707 "end": {
2708 "column": 3,
2709 "line": 18
2710 },
2711 "file": "src/components/settings/services/ServicesDashboard.js",
2712 "id": "settings.services.headline",
2713 "start": {
2714 "column": 12,
2715 "line": 15
2716 }
2717 },
2718 {
2719 "defaultMessage": "!!!Search service",
2720 "end": {
2721 "column": 3,
2722 "line": 22
2723 },
2724 "file": "src/components/settings/services/ServicesDashboard.js",
2725 "id": "settings.searchService",
2726 "start": {
2727 "column": 17,
2728 "line": 19
2729 }
2730 },
2731 {
2732 "defaultMessage": "!!!Start by adding a service.",
2733 "end": {
2734 "column": 3,
2735 "line": 26
2736 },
2737 "file": "src/components/settings/services/ServicesDashboard.js",
2738 "id": "settings.services.noServicesAdded",
2739 "start": {
2740 "column": 19,
2741 "line": 23
2742 }
2743 },
2744 {
2745 "defaultMessage": "!!!Sorry, but no service matched your search term. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.",
2746 "end": {
2747 "column": 3,
2748 "line": 30
2749 },
2750 "file": "src/components/settings/services/ServicesDashboard.js",
2751 "id": "settings.recipes.nothingFound",
2752 "start": {
2753 "column": 18,
2754 "line": 27
2755 }
2756 },
2757 {
2758 "defaultMessage": "!!!Discover services",
2759 "end": {
2760 "column": 3,
2761 "line": 34
2762 },
2763 "file": "src/components/settings/services/ServicesDashboard.js",
2764 "id": "settings.services.discoverServices",
2765 "start": {
2766 "column": 20,
2767 "line": 31
2768 }
2769 },
2770 {
2771 "defaultMessage": "!!!Could not load your services",
2772 "end": {
2773 "column": 3,
2774 "line": 38
2775 },
2776 "file": "src/components/settings/services/ServicesDashboard.js",
2777 "id": "settings.services.servicesRequestFailed",
2778 "start": {
2779 "column": 25,
2780 "line": 35
2781 }
2782 },
2783 {
2784 "defaultMessage": "!!!Try again",
2785 "end": {
2786 "column": 3,
2787 "line": 42
2788 },
2789 "file": "src/components/settings/services/ServicesDashboard.js",
2790 "id": "settings.account.tryReloadServices",
2791 "start": {
2792 "column": 21,
2793 "line": 39
2794 }
2795 },
2796 {
2797 "defaultMessage": "!!!Your changes have been saved",
2798 "end": {
2799 "column": 3,
2800 "line": 46
2801 },
2802 "file": "src/components/settings/services/ServicesDashboard.js",
2803 "id": "settings.services.updatedInfo",
2804 "start": {
2805 "column": 15,
2806 "line": 43
2807 }
2808 },
2809 {
2810 "defaultMessage": "!!!Service has been deleted",
2811 "end": {
2812 "column": 3,
2813 "line": 50
2814 },
2815 "file": "src/components/settings/services/ServicesDashboard.js",
2816 "id": "settings.services.deletedInfo",
2817 "start": {
2818 "column": 15,
2819 "line": 47
2820 }
2821 }
2822 ],
2823 "path": "src/components/settings/services/ServicesDashboard.json"
2824 },
2825 {
2826 "descriptors": [
2827 {
2828 "defaultMessage": "!!!General",
2829 "end": {
2830 "column": 3,
2831 "line": 24
2832 },
2833 "file": "src/components/settings/settings/EditSettingsForm.js",
2834 "id": "settings.app.headlineGeneral",
2835 "start": {
2836 "column": 19,
2837 "line": 21
2838 }
2839 },
2840 {
2841 "defaultMessage": "!!!Sending telemetry data allows us to find errors in Ferdi - we will not send any personal information like your message data!",
2842 "end": {
2843 "column": 3,
2844 "line": 28
2845 },
2846 "file": "src/components/settings/settings/EditSettingsForm.js",
2847 "id": "settings.app.sentryInfo",
2848 "start": {
2849 "column": 14,
2850 "line": 25
2851 }
2852 },
2853 {
2854 "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.",
2855 "end": {
2856 "column": 3,
2857 "line": 32
2858 },
2859 "file": "src/components/settings/settings/EditSettingsForm.js",
2860 "id": "settings.app.hibernateInfo",
2861 "start": {
2862 "column": 17,
2863 "line": 29
2864 }
2865 },
2866 {
2867 "defaultMessage": "!!!Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable",
2868 "end": {
2869 "column": 3,
2870 "line": 36
2871 },
2872 "file": "src/components/settings/settings/EditSettingsForm.js",
2873 "id": "settings.app.inactivityLockInfo",
2874 "start": {
2875 "column": 22,
2876 "line": 33
2877 }
2878 },
2879 {
2880 "defaultMessage": "!!!This server will be used for the \"Franz Todo\" feature. (default: https://app.franztodos.com)",
2881 "end": {
2882 "column": 3,
2883 "line": 40
2884 },
2885 "file": "src/components/settings/settings/EditSettingsForm.js",
2886 "id": "settings.app.todoServerInfo",
2887 "start": {
2888 "column": 18,
2889 "line": 37
2890 }
2891 },
2892 {
2893 "defaultMessage": "!!!Password",
2894 "end": {
2895 "column": 3,
2896 "line": 44
2897 },
2898 "file": "src/components/settings/settings/EditSettingsForm.js",
2899 "id": "settings.app.lockedPassword",
2900 "start": {
2901 "column": 18,
2902 "line": 41
2903 }
2904 },
2905 {
2906 "defaultMessage": "!!!Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdi.",
2907 "end": {
2908 "column": 3,
2909 "line": 48
2910 },
2911 "file": "src/components/settings/settings/EditSettingsForm.js",
2912 "id": "settings.app.lockedPasswordInfo",
2913 "start": {
2914 "column": 22,
2915 "line": 45
2916 }
2917 },
2918 {
2919 "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}.",
2920 "end": {
2921 "column": 3,
2922 "line": 52
2923 },
2924 "file": "src/components/settings/settings/EditSettingsForm.js",
2925 "id": "settings.app.lockInfo",
2926 "start": {
2927 "column": 12,
2928 "line": 49
2929 }
2930 },
2931 {
2932 "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.",
2933 "end": {
2934 "column": 3,
2935 "line": 56
2936 },
2937 "file": "src/components/settings/settings/EditSettingsForm.js",
2938 "id": "settings.app.scheduledDNDTimeInfo",
2939 "start": {
2940 "column": 24,
2941 "line": 53
2942 }
2943 },
2944 {
2945 "defaultMessage": "!!!Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.",
2946 "end": {
2947 "column": 3,
2948 "line": 60
2949 },
2950 "file": "src/components/settings/settings/EditSettingsForm.js",
2951 "id": "settings.app.scheduledDNDInfo",
2952 "start": {
2953 "column": 20,
2954 "line": 57
2955 }
2956 },
2957 {
2958 "defaultMessage": "!!!Language",
2959 "end": {
2960 "column": 3,
2961 "line": 64
2962 },
2963 "file": "src/components/settings/settings/EditSettingsForm.js",
2964 "id": "settings.app.headlineLanguage",
2965 "start": {
2966 "column": 20,
2967 "line": 61
2968 }
2969 },
2970 {
2971 "defaultMessage": "!!!Updates",
2972 "end": {
2973 "column": 3,
2974 "line": 68
2975 },
2976 "file": "src/components/settings/settings/EditSettingsForm.js",
2977 "id": "settings.app.headlineUpdates",
2978 "start": {
2979 "column": 19,
2980 "line": 65
2981 }
2982 },
2983 {
2984 "defaultMessage": "!!!Appearance",
2985 "end": {
2986 "column": 3,
2987 "line": 72
2988 },
2989 "file": "src/components/settings/settings/EditSettingsForm.js",
2990 "id": "settings.app.headlineAppearance",
2991 "start": {
2992 "column": 22,
2993 "line": 69
2994 }
2995 },
2996 {
2997 "defaultMessage": "!!!Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.",
2998 "end": {
2999 "column": 3,
3000 "line": 76
3001 },
3002 "file": "src/components/settings/settings/EditSettingsForm.js",
3003 "id": "settings.app.universalDarkModeInfo",
3004 "start": {
3005 "column": 25,
3006 "line": 73
3007 }
3008 },
3009 {
3010 "defaultMessage": "!!!Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})",
3011 "end": {
3012 "column": 3,
3013 "line": 80
3014 },
3015 "file": "src/components/settings/settings/EditSettingsForm.js",
3016 "id": "settings.app.accentColorInfo",
3017 "start": {
3018 "column": 19,
3019 "line": 77
3020 }
3021 },
3022 {
3023 "defaultMessage": "!!!Privacy",
3024 "end": {
3025 "column": 3,
3026 "line": 84
3027 },
3028 "file": "src/components/settings/settings/EditSettingsForm.js",
3029 "id": "settings.app.headlinePrivacy",
3030 "start": {
3031 "column": 19,
3032 "line": 81
3033 }
3034 },
3035 {
3036 "defaultMessage": "!!!Advanced",
3037 "end": {
3038 "column": 3,
3039 "line": 88
3040 },
3041 "file": "src/components/settings/settings/EditSettingsForm.js",
3042 "id": "settings.app.headlineAdvanced",
3043 "start": {
3044 "column": 20,
3045 "line": 85
3046 }
3047 },
3048 {
3049 "defaultMessage": "!!!Help us to translate Ferdi into your language.",
3050 "end": {
3051 "column": 3,
3052 "line": 92
3053 },
3054 "file": "src/components/settings/settings/EditSettingsForm.js",
3055 "id": "settings.app.translationHelp",
3056 "start": {
3057 "column": 19,
3058 "line": 89
3059 }
3060 },
3061 {
3062 "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.",
3063 "end": {
3064 "column": 3,
3065 "line": 96
3066 },
3067 "file": "src/components/settings/settings/EditSettingsForm.js",
3068 "id": "settings.app.spellCheckerLanguageInfo",
3069 "start": {
3070 "column": 28,
3071 "line": 93
3072 }
3073 },
3074 {
3075 "defaultMessage": "!!!Cache",
3076 "end": {
3077 "column": 3,
3078 "line": 100
3079 },
3080 "file": "src/components/settings/settings/EditSettingsForm.js",
3081 "id": "settings.app.subheadlineCache",
3082 "start": {
3083 "column": 20,
3084 "line": 97
3085 }
3086 },
3087 {
3088 "defaultMessage": "!!!Ferdi cache is currently using {size} of disk space.",
3089 "end": {
3090 "column": 3,
3091 "line": 104
3092 },
3093 "file": "src/components/settings/settings/EditSettingsForm.js",
3094 "id": "settings.app.cacheInfo",
3095 "start": {
3096 "column": 13,
3097 "line": 101
3098 }
3099 },
3100 {
3101 "defaultMessage": "!!!Couldn't clear all cache",
3102 "end": {
3103 "column": 3,
3104 "line": 108
3105 },
3106 "file": "src/components/settings/settings/EditSettingsForm.js",
3107 "id": "settings.app.cacheNotCleared",
3108 "start": {
3109 "column": 19,
3110 "line": 105
3111 }
3112 },
3113 {
3114 "defaultMessage": "!!!Clear cache",
3115 "end": {
3116 "column": 3,
3117 "line": 112
3118 },
3119 "file": "src/components/settings/settings/EditSettingsForm.js",
3120 "id": "settings.app.buttonClearAllCache",
3121 "start": {
3122 "column": 23,
3123 "line": 109
3124 }
3125 },
3126 {
3127 "defaultMessage": "!!!Ferdi Profile",
3128 "end": {
3129 "column": 3,
3130 "line": 116
3131 },
3132 "file": "src/components/settings/settings/EditSettingsForm.js",
3133 "id": "settings.app.subheadlineFerdiProfile",
3134 "start": {
3135 "column": 27,
3136 "line": 113
3137 }
3138 },
3139 {
3140 "defaultMessage": "!!!Open Profile folder",
3141 "end": {
3142 "column": 3,
3143 "line": 120
3144 },
3145 "file": "src/components/settings/settings/EditSettingsForm.js",
3146 "id": "settings.app.buttonOpenFerdiProfileFolder",
3147 "start": {
3148 "column": 32,
3149 "line": 117
3150 }
3151 },
3152 {
3153 "defaultMessage": "!!!Open Service Recipes folder",
3154 "end": {
3155 "column": 3,
3156 "line": 124
3157 },
3158 "file": "src/components/settings/settings/EditSettingsForm.js",
3159 "id": "settings.app.buttonOpenFerdiServiceRecipesFolder",
3160 "start": {
3161 "column": 39,
3162 "line": 121
3163 }
3164 },
3165 {
3166 "defaultMessage": "!!!Check for updates",
3167 "end": {
3168 "column": 3,
3169 "line": 128
3170 },
3171 "file": "src/components/settings/settings/EditSettingsForm.js",
3172 "id": "settings.app.buttonSearchForUpdate",
3173 "start": {
3174 "column": 25,
3175 "line": 125
3176 }
3177 },
3178 {
3179 "defaultMessage": "!!!Restart & install update",
3180 "end": {
3181 "column": 3,
3182 "line": 132
3183 },
3184 "file": "src/components/settings/settings/EditSettingsForm.js",
3185 "id": "settings.app.buttonInstallUpdate",
3186 "start": {
3187 "column": 23,
3188 "line": 129
3189 }
3190 },
3191 {
3192 "defaultMessage": "!!!Is searching for update",
3193 "end": {
3194 "column": 3,
3195 "line": 136
3196 },
3197 "file": "src/components/settings/settings/EditSettingsForm.js",
3198 "id": "settings.app.updateStatusSearching",
3199 "start": {
3200 "column": 25,
3201 "line": 133
3202 }
3203 },
3204 {
3205 "defaultMessage": "!!!Update available, downloading...",
3206 "end": {
3207 "column": 3,
3208 "line": 140
3209 },
3210 "file": "src/components/settings/settings/EditSettingsForm.js",
3211 "id": "settings.app.updateStatusAvailable",
3212 "start": {
3213 "column": 25,
3214 "line": 137
3215 }
3216 },
3217 {
3218 "defaultMessage": "!!!You are using the latest version of Ferdi",
3219 "end": {
3220 "column": 3,
3221 "line": 144
3222 },
3223 "file": "src/components/settings/settings/EditSettingsForm.js",
3224 "id": "settings.app.updateStatusUpToDate",
3225 "start": {
3226 "column": 24,
3227 "line": 141
3228 }
3229 },
3230 {
3231 "defaultMessage": "!!!Current version:",
3232 "end": {
3233 "column": 3,
3234 "line": 148
3235 },
3236 "file": "src/components/settings/settings/EditSettingsForm.js",
3237 "id": "settings.app.currentVersion",
3238 "start": {
3239 "column": 18,
3240 "line": 145
3241 }
3242 },
3243 {
3244 "defaultMessage": "!!!Changes require restart",
3245 "end": {
3246 "column": 3,
3247 "line": 152
3248 },
3249 "file": "src/components/settings/settings/EditSettingsForm.js",
3250 "id": "settings.app.restartRequired",
3251 "start": {
3252 "column": 22,
3253 "line": 149
3254 }
3255 },
3256 {
3257 "defaultMessage": "!!!Official translations are English & German. All other languages are community based translations.",
3258 "end": {
3259 "column": 3,
3260 "line": 156
3261 },
3262 "file": "src/components/settings/settings/EditSettingsForm.js",
3263 "id": "settings.app.languageDisclaimer",
3264 "start": {
3265 "column": 22,
3266 "line": 153
3267 }
3268 }
3269 ],
3270 "path": "src/components/settings/settings/EditSettingsForm.json"
3271 },
3272 {
3273 "descriptors": [
3274 {
3275 "defaultMessage": "!!!Close settings",
3276 "end": {
3277 "column": 3,
3278 "line": 14
3279 },
3280 "file": "src/components/settings/SettingsLayout.js",
3281 "id": "settings.app.closeSettings",
3282 "start": {
3283 "column": 17,
3284 "line": 11
3285 }
3286 }
3287 ],
3288 "path": "src/components/settings/SettingsLayout.json"
3289 },
3290 {
3291 "descriptors": [
3292 {
3293 "defaultMessage": "!!!About Ferdi",
3294 "end": {
3295 "column": 3,
3296 "line": 10
3297 },
3298 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3299 "id": "settings.supportFerdi.headline",
3300 "start": {
3301 "column": 12,
3302 "line": 7
3303 }
3304 },
3305 {
3306 "defaultMessage": "!!!Do you like Ferdi?",
3307 "end": {
3308 "column": 3,
3309 "line": 14
3310 },
3311 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3312 "id": "settings.supportFerdi.title",
3313 "start": {
3314 "column": 9,
3315 "line": 11
3316 }
3317 },
3318 {
3319 "defaultMessage": "!!!<p>Ferdi is an open-source and a community-lead application.</p><p>Thanks to the people who make this possbile:</p>",
3320 "end": {
3321 "column": 3,
3322 "line": 18
3323 },
3324 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3325 "id": "settings.supportFerdi.aboutIntro",
3326 "start": {
3327 "column": 14,
3328 "line": 15
3329 }
3330 },
3331 {
3332 "defaultMessage": "!!!Full list of contributor",
3333 "end": {
3334 "column": 3,
3335 "line": 22
3336 },
3337 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3338 "id": "settings.supportFerdi.textListContributors",
3339 "start": {
3340 "column": 24,
3341 "line": 19
3342 }
3343 },
3344 {
3345 "defaultMessage": "!!!here",
3346 "end": {
3347 "column": 3,
3348 "line": 26
3349 },
3350 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3351 "id": "settings.supportFerdi.textListContributorsHere",
3352 "start": {
3353 "column": 28,
3354 "line": 23
3355 }
3356 },
3357 {
3358 "defaultMessage": "!!!The development of Ferdi is done by volunteers. People who use Ferdi like you. They maintain, fix, and improve Ferdi in their spare time.",
3359 "end": {
3360 "column": 3,
3361 "line": 30
3362 },
3363 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3364 "id": "settings.supportFerdi.textVolunteers",
3365 "start": {
3366 "column": 18,
3367 "line": 27
3368 }
3369 },
3370 {
3371 "defaultMessage": "!!!Support is always welcome. You can find a list of the help we need",
3372 "end": {
3373 "column": 3,
3374 "line": 34
3375 },
3376 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3377 "id": "settings.supportFerdi.textSupportWelcome",
3378 "start": {
3379 "column": 22,
3380 "line": 31
3381 }
3382 },
3383 {
3384 "defaultMessage": "!!!here",
3385 "end": {
3386 "column": 3,
3387 "line": 38
3388 },
3389 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3390 "id": "settings.supportFerdi.textSupportWelcomeHere",
3391 "start": {
3392 "column": 26,
3393 "line": 35
3394 }
3395 },
3396 {
3397 "defaultMessage": "!!!While volunteers do most of the work, we still need to pay for servers and certificates. As a community, we are fully transparent on funds we collect and spend - see our",
3398 "end": {
3399 "column": 3,
3400 "line": 42
3401 },
3402 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3403 "id": "settings.supportFerdi.textExpenses",
3404 "start": {
3405 "column": 16,
3406 "line": 39
3407 }
3408 },
3409 {
3410 "defaultMessage": "!!!Open Collective",
3411 "end": {
3412 "column": 3,
3413 "line": 46
3414 },
3415 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3416 "id": "settings.supportFerdi.textOpenCollective",
3417 "start": {
3418 "column": 22,
3419 "line": 43
3420 }
3421 },
3422 {
3423 "defaultMessage": "!!!If you feel like supporting Ferdi development with a donation, you can do so on both,",
3424 "end": {
3425 "column": 3,
3426 "line": 50
3427 },
3428 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3429 "id": "settings.supportFerdi.textDonation",
3430 "start": {
3431 "column": 16,
3432 "line": 47
3433 }
3434 },
3435 {
3436 "defaultMessage": "!!!and",
3437 "end": {
3438 "column": 3,
3439 "line": 54
3440 },
3441 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3442 "id": "settings.supportFerdi.textDonationAnd",
3443 "start": {
3444 "column": 19,
3445 "line": 51
3446 }
3447 },
3448 {
3449 "defaultMessage": "!!!GitHub Sponsors",
3450 "end": {
3451 "column": 3,
3452 "line": 58
3453 },
3454 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3455 "id": "settings.supportFerdi.textGitHubSponsors",
3456 "start": {
3457 "column": 22,
3458 "line": 55
3459 }
3460 },
3461 {
3462 "defaultMessage": "!!!Open Survey",
3463 "end": {
3464 "column": 3,
3465 "line": 62
3466 },
3467 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3468 "id": "settings.supportFerdi.openSurvey",
3469 "start": {
3470 "column": 14,
3471 "line": 59
3472 }
3473 },
3474 {
3475 "defaultMessage": "!!!Do you want to help us improve Ferdi?",
3476 "end": {
3477 "column": 3,
3478 "line": 66
3479 },
3480 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
3481 "id": "settings.supportFerdi.bannerText",
3482 "start": {
3483 "column": 14,
3484 "line": 63
3485 }
3486 }
3487 ],
3488 "path": "src/components/settings/supportFerdi/SupportFerdiDashboard.json"
3489 },
3490 {
3491 "descriptors": [
3492 {
3493 "defaultMessage": "!!!Team",
3494 "end": {
3495 "column": 3,
3496 "line": 18
3497 },
3498 "file": "src/components/settings/team/TeamDashboard.js",
3499 "id": "settings.team.headline",
3500 "start": {
3501 "column": 12,
3502 "line": 15
3503 }
3504 },
3505 {
3506 "defaultMessage": "!!!Franz Team Management",
3507 "end": {
3508 "column": 3,
3509 "line": 22
3510 },
3511 "file": "src/components/settings/team/TeamDashboard.js",
3512 "id": "settings.team.contentHeadline",
3513 "start": {
3514 "column": 19,
3515 "line": 19
3516 }
3517 },
3518 {
3519 "defaultMessage": "!!!Your are currently using Franz Servers, which is why you have access to Team Management.",
3520 "end": {
3521 "column": 3,
3522 "line": 26
3523 },
3524 "file": "src/components/settings/team/TeamDashboard.js",
3525 "id": "settings.team.intro",
3526 "start": {
3527 "column": 9,
3528 "line": 23
3529 }
3530 },
3531 {
3532 "defaultMessage": "!!!Franz's Team Management allows you to manage Franz Subscriptions for multiple users. Please keep in mind that having a Franz Premium subscription will give you no advantages in using Ferdi: The only reason you still have access to Team Management is so you can manage your legacy Franz Teams and so that you don't loose any functionality in managing your account.",
3533 "end": {
3534 "column": 3,
3535 "line": 30
3536 },
3537 "file": "src/components/settings/team/TeamDashboard.js",
3538 "id": "settings.team.copy",
3539 "start": {
3540 "column": 8,
3541 "line": 27
3542 }
3543 },
3544 {
3545 "defaultMessage": "!!!Manage your Team on meetfranz.com",
3546 "end": {
3547 "column": 3,
3548 "line": 34
3549 },
3550 "file": "src/components/settings/team/TeamDashboard.js",
3551 "id": "settings.team.manageAction",
3552 "start": {
3553 "column": 16,
3554 "line": 31
3555 }
3556 },
3557 {
3558 "defaultMessage": "!!!Teams are unavailable",
3559 "end": {
3560 "column": 3,
3561 "line": 38
3562 },
3563 "file": "src/components/settings/team/TeamDashboard.js",
3564 "id": "settings.team.teamsUnavailable",
3565 "start": {
3566 "column": 20,
3567 "line": 35
3568 }
3569 },
3570 {
3571 "defaultMessage": "!!!Teams are currently only available when using the Franz Server and after paying for Franz Professional. Please change your server to https://api.franzinfra.com to use teams.",
3572 "end": {
3573 "column": 3,
3574 "line": 42
3575 },
3576 "file": "src/components/settings/team/TeamDashboard.js",
3577 "id": "settings.team.teamsUnavailableInfo",
3578 "start": {
3579 "column": 24,
3580 "line": 39
3581 }
3582 }
3583 ],
3584 "path": "src/components/settings/team/TeamDashboard.json"
3585 },
3586 {
3587 "descriptors": [
3588 {
3589 "defaultMessage": "!!!Account",
3590 "end": {
3591 "column": 3,
3592 "line": 18
3593 },
3594 "file": "src/components/settings/user/EditUserForm.js",
3595 "id": "settings.account.headline",
3596 "start": {
3597 "column": 12,
3598 "line": 15
3599 }
3600 },
3601 {
3602 "defaultMessage": "!!!Update Profile",
3603 "end": {
3604 "column": 3,
3605 "line": 22
3606 },
3607 "file": "src/components/settings/user/EditUserForm.js",
3608 "id": "settings.account.headlineProfile",
3609 "start": {
3610 "column": 19,
3611 "line": 19
3612 }
3613 },
3614 {
3615 "defaultMessage": "!!!Account Information",
3616 "end": {
3617 "column": 3,
3618 "line": 26
3619 },
3620 "file": "src/components/settings/user/EditUserForm.js",
3621 "id": "settings.account.headlineAccount",
3622 "start": {
3623 "column": 19,
3624 "line": 23
3625 }
3626 },
3627 {
3628 "defaultMessage": "!!!Change Password",
3629 "end": {
3630 "column": 3,
3631 "line": 30
3632 },
3633 "file": "src/components/settings/user/EditUserForm.js",
3634 "id": "settings.account.headlinePassword",
3635 "start": {
3636 "column": 20,
3637 "line": 27
3638 }
3639 },
3640 {
3641 "defaultMessage": "!!!Your changes have been saved",
3642 "end": {
3643 "column": 3,
3644 "line": 34
3645 },
3646 "file": "src/components/settings/user/EditUserForm.js",
3647 "id": "settings.account.successInfo",
3648 "start": {
3649 "column": 15,
3650 "line": 31
3651 }
3652 },
3653 {
3654 "defaultMessage": "!!!Update profile",
3655 "end": {
3656 "column": 3,
3657 "line": 38
3658 },
3659 "file": "src/components/settings/user/EditUserForm.js",
3660 "id": "settings.account.buttonSave",
3661 "start": {
3662 "column": 14,
3663 "line": 35
3664 }
3665 }
3666 ],
3667 "path": "src/components/settings/user/EditUserForm.json"
3668 },
3669 {
3670 "descriptors": [
3671 {
3672 "defaultMessage": "!!!Choose from more than 70 Services",
3673 "end": {
3674 "column": 3,
3675 "line": 11
3676 },
3677 "file": "src/components/ui/FeatureList.js",
3678 "id": "pricing.features.recipes",
3679 "start": {
3680 "column": 20,
3681 "line": 8
3682 }
3683 },
3684 {
3685 "defaultMessage": "!!!Account Synchronisation",
3686 "end": {
3687 "column": 3,
3688 "line": 15
3689 },
3690 "file": "src/components/ui/FeatureList.js",
3691 "id": "pricing.features.accountSync",
3692 "start": {
3693 "column": 15,
3694 "line": 12
3695 }
3696 },
3697 {
3698 "defaultMessage": "!!!Desktop Notifications",
3699 "end": {
3700 "column": 3,
3701 "line": 19
3702 },
3703 "file": "src/components/ui/FeatureList.js",
3704 "id": "pricing.features.desktopNotifications",
3705 "start": {
3706 "column": 24,
3707 "line": 16
3708 }
3709 },
3710 {
3711 "defaultMessage": "!!!Add unlimited services",
3712 "end": {
3713 "column": 3,
3714 "line": 23
3715 },
3716 "file": "src/components/ui/FeatureList.js",
3717 "id": "pricing.features.unlimitedServices",
3718 "start": {
3719 "column": 21,
3720 "line": 20
3721 }
3722 },
3723 {
3724 "defaultMessage": "!!!Spellchecker support",
3725 "end": {
3726 "column": 3,
3727 "line": 27
3728 },
3729 "file": "src/components/ui/FeatureList.js",
3730 "id": "pricing.features.spellchecker",
3731 "start": {
3732 "column": 16,
3733 "line": 24
3734 }
3735 },
3736 {
3737 "defaultMessage": "!!!Workspaces",
3738 "end": {
3739 "column": 3,
3740 "line": 31
3741 },
3742 "file": "src/components/ui/FeatureList.js",
3743 "id": "pricing.features.workspaces",
3744 "start": {
3745 "column": 14,
3746 "line": 28
3747 }
3748 },
3749 {
3750 "defaultMessage": "!!!Add Custom Websites",
3751 "end": {
3752 "column": 3,
3753 "line": 35
3754 },
3755 "file": "src/components/ui/FeatureList.js",
3756 "id": "pricing.features.customWebsites",
3757 "start": {
3758 "column": 18,
3759 "line": 32
3760 }
3761 },
3762 {
3763 "defaultMessage": "!!!On-premise & other Hosted Services",
3764 "end": {
3765 "column": 3,
3766 "line": 39
3767 },
3768 "file": "src/components/ui/FeatureList.js",
3769 "id": "pricing.features.onPremise",
3770 "start": {
3771 "column": 13,
3772 "line": 36
3773 }
3774 },
3775 {
3776 "defaultMessage": "!!!Install 3rd party services",
3777 "end": {
3778 "column": 3,
3779 "line": 43
3780 },
3781 "file": "src/components/ui/FeatureList.js",
3782 "id": "pricing.features.thirdPartyServices",
3783 "start": {
3784 "column": 22,
3785 "line": 40
3786 }
3787 },
3788 {
3789 "defaultMessage": "!!!Service Proxies",
3790 "end": {
3791 "column": 3,
3792 "line": 47
3793 },
3794 "file": "src/components/ui/FeatureList.js",
3795 "id": "pricing.features.serviceProxies",
3796 "start": {
3797 "column": 18,
3798 "line": 44
3799 }
3800 },
3801 {
3802 "defaultMessage": "!!!Team Management",
3803 "end": {
3804 "column": 3,
3805 "line": 51
3806 },
3807 "file": "src/components/ui/FeatureList.js",
3808 "id": "pricing.features.teamManagement",
3809 "start": {
3810 "column": 18,
3811 "line": 48
3812 }
3813 }
3814 ],
3815 "path": "src/components/ui/FeatureList.json"
3816 },
3817 {
3818 "descriptors": [
3819 {
3820 "defaultMessage": "!!!Hide",
3821 "end": {
3822 "column": 3,
3823 "line": 15
3824 },
3825 "file": "src/components/ui/InfoBar.js",
3826 "id": "infobar.hide",
3827 "start": {
3828 "column": 8,
3829 "line": 12
3830 }
3831 }
3832 ],
3833 "path": "src/components/ui/InfoBar.json"
3834 },
3835 {
3836 "descriptors": [
3837 {
3838 "defaultMessage": "!!!Dismiss",
3839 "end": {
3840 "column": 3,
3841 "line": 12
3842 },
3843 "file": "src/components/ui/Infobox.js",
3844 "id": "infobox.dismiss",
3845 "start": {
3846 "column": 11,
3847 "line": 9
3848 }
3849 }
3850 ],
3851 "path": "src/components/ui/Infobox.json"
3852 },
3853 {
3854 "descriptors": [
3855 {
3856 "defaultMessage": "!!!Password toggle",
3857 "end": {
3858 "column": 3,
3859 "line": 14
3860 },
3861 "file": "src/components/ui/Input.js",
3862 "id": "settings.app.form.passwordToggle",
3863 "start": {
3864 "column": 18,
3865 "line": 11
3866 }
3867 }
3868 ],
3869 "path": "src/components/ui/Input.json"
3870 },
3871 {
3872 "descriptors": [
3873 {
3874 "defaultMessage": "!!!Loading {service}",
3875 "end": {
3876 "column": 3,
3877 "line": 14
3878 },
3879 "file": "src/components/ui/WebviewLoader/index.js",
3880 "id": "service.webviewLoader.loading",
3881 "start": {
3882 "column": 11,
3883 "line": 11
3884 }
3885 }
3886 ],
3887 "path": "src/components/ui/WebviewLoader/index.json"
3888 },
3889 {
3890 "descriptors": [
3891 {
3892 "defaultMessage": "!!!Something went wrong.",
3893 "end": {
3894 "column": 3,
3895 "line": 14
3896 },
3897 "file": "src/components/util/ErrorBoundary/index.js",
3898 "id": "app.errorHandler.headline",
3899 "start": {
3900 "column": 12,
3901 "line": 11
3902 }
3903 },
3904 {
3905 "defaultMessage": "!!!Reload",
3906 "end": {
3907 "column": 3,
3908 "line": 18
3909 },
3910 "file": "src/components/util/ErrorBoundary/index.js",
3911 "id": "app.errorHandler.action",
3912 "start": {
3913 "column": 10,
3914 "line": 15
3915 }
3916 }
3917 ],
3918 "path": "src/components/util/ErrorBoundary/index.json"
3919 },
3920 {
3921 "descriptors": [
3922 {
3923 "defaultMessage": "!!!Name",
3924 "end": {
3925 "column": 3,
3926 "line": 31
3927 },
3928 "file": "src/containers/settings/EditServiceScreen.js",
3929 "id": "settings.service.form.name",
3930 "start": {
3931 "column": 8,
3932 "line": 28
3933 }
3934 },
3935 {
3936 "defaultMessage": "!!!Enable service",
3937 "end": {
3938 "column": 3,
3939 "line": 35
3940 },
3941 "file": "src/containers/settings/EditServiceScreen.js",
3942 "id": "settings.service.form.enableService",
3943 "start": {
3944 "column": 17,
3945 "line": 32
3946 }
3947 },
3948 {
3949 "defaultMessage": "!!!Enable hibernation",
3950 "end": {
3951 "column": 3,
3952 "line": 39
3953 },
3954 "file": "src/containers/settings/EditServiceScreen.js",
3955 "id": "settings.service.form.enableHibernation",
3956 "start": {
3957 "column": 21,
3958 "line": 36
3959 }
3960 },
3961 {
3962 "defaultMessage": "!!!Enable Notifications",
3963 "end": {
3964 "column": 3,
3965 "line": 43
3966 },
3967 "file": "src/containers/settings/EditServiceScreen.js",
3968 "id": "settings.service.form.enableNotification",
3969 "start": {
3970 "column": 22,
3971 "line": 40
3972 }
3973 },
3974 {
3975 "defaultMessage": "!!!Show unread message badges",
3976 "end": {
3977 "column": 3,
3978 "line": 47
3979 },
3980 "file": "src/containers/settings/EditServiceScreen.js",
3981 "id": "settings.service.form.enableBadge",
3982 "start": {
3983 "column": 15,
3984 "line": 44
3985 }
3986 },
3987 {
3988 "defaultMessage": "!!!Enable audio",
3989 "end": {
3990 "column": 3,
3991 "line": 51
3992 },
3993 "file": "src/containers/settings/EditServiceScreen.js",
3994 "id": "settings.service.form.enableAudio",
3995 "start": {
3996 "column": 15,
3997 "line": 48
3998 }
3999 },
4000 {
4001 "defaultMessage": "!!!Team",
4002 "end": {
4003 "column": 3,
4004 "line": 55
4005 },
4006 "file": "src/containers/settings/EditServiceScreen.js",
4007 "id": "settings.service.form.team",
4008 "start": {
4009 "column": 8,
4010 "line": 52
4011 }
4012 },
4013 {
4014 "defaultMessage": "!!!Service URL",
4015 "end": {
4016 "column": 3,
4017 "line": 59
4018 },
4019 "file": "src/containers/settings/EditServiceScreen.js",
4020 "id": "settings.service.form.customUrl",
4021 "start": {
4022 "column": 13,
4023 "line": 56
4024 }
4025 },
4026 {
4027 "defaultMessage": "!!!Show message badge for all new messages",
4028 "end": {
4029 "column": 3,
4030 "line": 63
4031 },
4032 "file": "src/containers/settings/EditServiceScreen.js",
4033 "id": "settings.service.form.indirectMessages",
4034 "start": {
4035 "column": 20,
4036 "line": 60
4037 }
4038 },
4039 {
4040 "defaultMessage": "!!!Custom icon",
4041 "end": {
4042 "column": 3,
4043 "line": 67
4044 },
4045 "file": "src/containers/settings/EditServiceScreen.js",
4046 "id": "settings.service.form.icon",
4047 "start": {
4048 "column": 8,
4049 "line": 64
4050 }
4051 },
4052 {
4053 "defaultMessage": "!!!Enable Dark Mode",
4054 "end": {
4055 "column": 3,
4056 "line": 71
4057 },
4058 "file": "src/containers/settings/EditServiceScreen.js",
4059 "id": "settings.service.form.enableDarkMode",
4060 "start": {
4061 "column": 18,
4062 "line": 68
4063 }
4064 },
4065 {
4066 "defaultMessage": "!!!Dark Reader Brightness",
4067 "end": {
4068 "column": 3,
4069 "line": 75
4070 },
4071 "file": "src/containers/settings/EditServiceScreen.js",
4072 "id": "settings.service.form.darkReaderBrightness",
4073 "start": {
4074 "column": 24,
4075 "line": 72
4076 }
4077 },
4078 {
4079 "defaultMessage": "!!!Dark Reader Contrast",
4080 "end": {
4081 "column": 3,
4082 "line": 79
4083 },
4084 "file": "src/containers/settings/EditServiceScreen.js",
4085 "id": "settings.service.form.darkReaderContrast",
4086 "start": {
4087 "column": 22,
4088 "line": 76
4089 }
4090 },
4091 {
4092 "defaultMessage": "!!!Dark Reader Sepia",
4093 "end": {
4094 "column": 3,
4095 "line": 83
4096 },
4097 "file": "src/containers/settings/EditServiceScreen.js",
4098 "id": "settings.service.form.darkReaderSepia",
4099 "start": {
4100 "column": 19,
4101 "line": 80
4102 }
4103 },
4104 {
4105 "defaultMessage": "!!!Use Proxy",
4106 "end": {
4107 "column": 3,
4108 "line": 87
4109 },
4110 "file": "src/containers/settings/EditServiceScreen.js",
4111 "id": "settings.service.form.proxy.isEnabled",
4112 "start": {
4113 "column": 15,
4114 "line": 84
4115 }
4116 },
4117 {
4118 "defaultMessage": "!!!Proxy Host/IP",
4119 "end": {
4120 "column": 3,
4121 "line": 91
4122 },
4123 "file": "src/containers/settings/EditServiceScreen.js",
4124 "id": "settings.service.form.proxy.host",
4125 "start": {
4126 "column": 13,
4127 "line": 88
4128 }
4129 },
4130 {
4131 "defaultMessage": "!!!Port",
4132 "end": {
4133 "column": 3,
4134 "line": 95
4135 },
4136 "file": "src/containers/settings/EditServiceScreen.js",
4137 "id": "settings.service.form.proxy.port",
4138 "start": {
4139 "column": 13,
4140 "line": 92
4141 }
4142 },
4143 {
4144 "defaultMessage": "!!!User",
4145 "end": {
4146 "column": 3,
4147 "line": 99
4148 },
4149 "file": "src/containers/settings/EditServiceScreen.js",
4150 "id": "settings.service.form.proxy.user",
4151 "start": {
4152 "column": 13,
4153 "line": 96
4154 }
4155 },
4156 {
4157 "defaultMessage": "!!!Password",
4158 "end": {
4159 "column": 3,
4160 "line": 103
4161 },
4162 "file": "src/containers/settings/EditServiceScreen.js",
4163 "id": "settings.service.form.proxy.password",
4164 "start": {
4165 "column": 17,
4166 "line": 100
4167 }
4168 }
4169 ],
4170 "path": "src/containers/settings/EditServiceScreen.json"
4171 },
4172 {
4173 "descriptors": [
4174 {
4175 "defaultMessage": "!!!Launch Ferdi on start",
4176 "end": {
4177 "column": 3,
4178 "line": 35
4179 },
4180 "file": "src/containers/settings/EditSettingsScreen.js",
4181 "id": "settings.app.form.autoLaunchOnStart",
4182 "start": {
4183 "column": 21,
4184 "line": 32
4185 }
4186 },
4187 {
4188 "defaultMessage": "!!!Open in background",
4189 "end": {
4190 "column": 3,
4191 "line": 39
4192 },
4193 "file": "src/containers/settings/EditSettingsScreen.js",
4194 "id": "settings.app.form.autoLaunchInBackground",
4195 "start": {
4196 "column": 26,
4197 "line": 36
4198 }
4199 },
4200 {
4201 "defaultMessage": "!!!Keep Ferdi in background when closing the window",
4202 "end": {
4203 "column": 3,
4204 "line": 43
4205 },
4206 "file": "src/containers/settings/EditSettingsScreen.js",
4207 "id": "settings.app.form.runInBackground",
4208 "start": {
4209 "column": 19,
4210 "line": 40
4211 }
4212 },
4213 {
4214 "defaultMessage": "!!!Start minimized",
4215 "end": {
4216 "column": 3,
4217 "line": 47
4218 },
4219 "file": "src/containers/settings/EditSettingsScreen.js",
4220 "id": "settings.app.form.startMinimized",
4221 "start": {
4222 "column": 18,
4223 "line": 44
4224 }
4225 },
4226 {
4227 "defaultMessage": "!!!Confirm when quitting Ferdi",
4228 "end": {
4229 "column": 3,
4230 "line": 51
4231 },
4232 "file": "src/containers/settings/EditSettingsScreen.js",
4233 "id": "settings.app.form.confirmOnQuit",
4234 "start": {
4235 "column": 17,
4236 "line": 48
4237 }
4238 },
4239 {
4240 "defaultMessage": "!!!Always show Ferdi in System Tray",
4241 "end": {
4242 "column": 3,
4243 "line": 55
4244 },
4245 "file": "src/containers/settings/EditSettingsScreen.js",
4246 "id": "settings.app.form.enableSystemTray",
4247 "start": {
4248 "column": 20,
4249 "line": 52
4250 }
4251 },
4252 {
4253 "defaultMessage": "!!!Always show Ferdi in Menu Bar",
4254 "end": {
4255 "column": 3,
4256 "line": 59
4257 },
4258 "file": "src/containers/settings/EditSettingsScreen.js",
4259 "id": "settings.app.form.enableMenuBar",
4260 "start": {
4261 "column": 17,
4262 "line": 56
4263 }
4264 },
4265 {
4266 "defaultMessage": "!!!Reload Ferdi after system resume",
4267 "end": {
4268 "column": 3,
4269 "line": 63
4270 },
4271 "file": "src/containers/settings/EditSettingsScreen.js",
4272 "id": "settings.app.form.reloadAfterResume",
4273 "start": {
4274 "column": 21,
4275 "line": 60
4276 }
4277 },
4278 {
4279 "defaultMessage": "!!!Minimize Ferdi to system tray",
4280 "end": {
4281 "column": 3,
4282 "line": 67
4283 },
4284 "file": "src/containers/settings/EditSettingsScreen.js",
4285 "id": "settings.app.form.minimizeToSystemTray",
4286 "start": {
4287 "column": 24,
4288 "line": 64
4289 }
4290 },
4291 {
4292 "defaultMessage": "!!!Close Ferdi to system tray",
4293 "end": {
4294 "column": 3,
4295 "line": 71
4296 },
4297 "file": "src/containers/settings/EditSettingsScreen.js",
4298 "id": "settings.app.form.closeToSystemTray",
4299 "start": {
4300 "column": 21,
4301 "line": 68
4302 }
4303 },
4304 {
4305 "defaultMessage": "!!!Don't show message content in notifications",
4306 "end": {
4307 "column": 3,
4308 "line": 75
4309 },
4310 "file": "src/containers/settings/EditSettingsScreen.js",
4311 "id": "settings.app.form.privateNotifications",
4312 "start": {
4313 "column": 24,
4314 "line": 72
4315 }
4316 },
4317 {
4318 "defaultMessage": "!!!Don't show notifications for clipboard events",
4319 "end": {
4320 "column": 3,
4321 "line": 79
4322 },
4323 "file": "src/containers/settings/EditSettingsScreen.js",
4324 "id": "settings.app.form.clipboardNotifications",
4325 "start": {
4326 "column": 26,
4327 "line": 76
4328 }
4329 },
4330 {
4331 "defaultMessage": "!!!Notify TaskBar/Dock on new message",
4332 "end": {
4333 "column": 3,
4334 "line": 83
4335 },
4336 "file": "src/containers/settings/EditSettingsScreen.js",
4337 "id": "settings.app.form.notifyTaskBarOnMessage",
4338 "start": {
4339 "column": 26,
4340 "line": 80
4341 }
4342 },
4343 {
4344 "defaultMessage": "!!!Navigation bar behaviour",
4345 "end": {
4346 "column": 3,
4347 "line": 87
4348 },
4349 "file": "src/containers/settings/EditSettingsScreen.js",
4350 "id": "settings.app.form.navigationBarBehaviour",
4351 "start": {
4352 "column": 26,
4353 "line": 84
4354 }
4355 },
4356 {
4357 "defaultMessage": "!!!Search engine",
4358 "end": {
4359 "column": 3,
4360 "line": 91
4361 },
4362 "file": "src/containers/settings/EditSettingsScreen.js",
4363 "id": "settings.app.form.searchEngine",
4364 "start": {
4365 "column": 16,
4366 "line": 88
4367 }
4368 },
4369 {
4370 "defaultMessage": "!!!Send telemetry data",
4371 "end": {
4372 "column": 3,
4373 "line": 95
4374 },
4375 "file": "src/containers/settings/EditSettingsScreen.js",
4376 "id": "settings.app.form.sentry",
4377 "start": {
4378 "column": 10,
4379 "line": 92
4380 }
4381 },
4382 {
4383 "defaultMessage": "!!!Keep services in hibernation on startup",
4384 "end": {
4385 "column": 3,
4386 "line": 99
4387 },
4388 "file": "src/containers/settings/EditSettingsScreen.js",
4389 "id": "settings.app.form.hibernateOnStartup",
4390 "start": {
4391 "column": 22,
4392 "line": 96
4393 }
4394 },
4395 {
4396 "defaultMessage": "!!!Hibernation strategy",
4397 "end": {
4398 "column": 3,
4399 "line": 103
4400 },
4401 "file": "src/containers/settings/EditSettingsScreen.js",
4402 "id": "settings.app.form.hibernationStrategy",
4403 "start": {
4404 "column": 23,
4405 "line": 100
4406 }
4407 },
4408 {
4409 "defaultMessage": "!!!Wake up strategy",
4410 "end": {
4411 "column": 3,
4412 "line": 107
4413 },
4414 "file": "src/containers/settings/EditSettingsScreen.js",
4415 "id": "settings.app.form.wakeUpStrategy",
4416 "start": {
4417 "column": 18,
4418 "line": 104
4419 }
4420 },
4421 {
4422 "defaultMessage": "!!!Todo Server",
4423 "end": {
4424 "column": 3,
4425 "line": 111
4426 },
4427 "file": "src/containers/settings/EditSettingsScreen.js",
4428 "id": "settings.app.form.predefinedTodoServer",
4429 "start": {
4430 "column": 24,
4431 "line": 108
4432 }
4433 },
4434 {
4435 "defaultMessage": "!!!Custom TodoServer",
4436 "end": {
4437 "column": 3,
4438 "line": 115
4439 },
4440 "file": "src/containers/settings/EditSettingsScreen.js",
4441 "id": "settings.app.form.customTodoServer",
4442 "start": {
4443 "column": 20,
4444 "line": 112
4445 }
4446 },
4447 {
4448 "defaultMessage": "!!!Enable Password Lock",
4449 "end": {
4450 "column": 3,
4451 "line": 119
4452 },
4453 "file": "src/containers/settings/EditSettingsScreen.js",
4454 "id": "settings.app.form.enableLock",
4455 "start": {
4456 "column": 14,
4457 "line": 116
4458 }
4459 },
4460 {
4461 "defaultMessage": "!!!Password",
4462 "end": {
4463 "column": 3,
4464 "line": 123
4465 },
4466 "file": "src/containers/settings/EditSettingsScreen.js",
4467 "id": "settings.app.form.lockPassword",
4468 "start": {
4469 "column": 16,
4470 "line": 120
4471 }
4472 },
4473 {
4474 "defaultMessage": "!!!Allow using Touch ID to unlock",
4475 "end": {
4476 "column": 3,
4477 "line": 127
4478 },
4479 "file": "src/containers/settings/EditSettingsScreen.js",
4480 "id": "settings.app.form.useTouchIdToUnlock",
4481 "start": {
4482 "column": 22,
4483 "line": 124
4484 }
4485 },
4486 {
4487 "defaultMessage": "!!!Lock after inactivity",
4488 "end": {
4489 "column": 3,
4490 "line": 131
4491 },
4492 "file": "src/containers/settings/EditSettingsScreen.js",
4493 "id": "settings.app.form.inactivityLock",
4494 "start": {
4495 "column": 18,
4496 "line": 128
4497 }
4498 },
4499 {
4500 "defaultMessage": "!!!Enable scheduled Do-not-Disturb",
4501 "end": {
4502 "column": 3,
4503 "line": 135
4504 },
4505 "file": "src/containers/settings/EditSettingsScreen.js",
4506 "id": "settings.app.form.scheduledDNDEnabled",
4507 "start": {
4508 "column": 23,
4509 "line": 132
4510 }
4511 },
4512 {
4513 "defaultMessage": "!!!From",
4514 "end": {
4515 "column": 3,
4516 "line": 139
4517 },
4518 "file": "src/containers/settings/EditSettingsScreen.js",
4519 "id": "settings.app.form.scheduledDNDStart",
4520 "start": {
4521 "column": 21,
4522 "line": 136
4523 }
4524 },
4525 {
4526 "defaultMessage": "!!!To",
4527 "end": {
4528 "column": 3,
4529 "line": 143
4530 },
4531 "file": "src/containers/settings/EditSettingsScreen.js",
4532 "id": "settings.app.form.scheduledDNDEnd",
4533 "start": {
4534 "column": 19,
4535 "line": 140
4536 }
4537 },
4538 {
4539 "defaultMessage": "!!!Language",
4540 "end": {
4541 "column": 3,
4542 "line": 147
4543 },
4544 "file": "src/containers/settings/EditSettingsScreen.js",
4545 "id": "settings.app.form.language",
4546 "start": {
4547 "column": 12,
4548 "line": 144
4549 }
4550 },
4551 {
4552 "defaultMessage": "!!!Dark Mode",
4553 "end": {
4554 "column": 3,
4555 "line": 151
4556 },
4557 "file": "src/containers/settings/EditSettingsScreen.js",
4558 "id": "settings.app.form.darkMode",
4559 "start": {
4560 "column": 12,
4561 "line": 148
4562 }
4563 },
4564 {
4565 "defaultMessage": "!!!Synchronize dark mode with my OS's dark mode setting",
4566 "end": {
4567 "column": 3,
4568 "line": 155
4569 },
4570 "file": "src/containers/settings/EditSettingsScreen.js",
4571 "id": "settings.app.form.adaptableDarkMode",
4572 "start": {
4573 "column": 21,
4574 "line": 152
4575 }
4576 },
4577 {
4578 "defaultMessage": "!!!Enable universal Dark Mode",
4579 "end": {
4580 "column": 3,
4581 "line": 159
4582 },
4583 "file": "src/containers/settings/EditSettingsScreen.js",
4584 "id": "settings.app.form.universalDarkMode",
4585 "start": {
4586 "column": 21,
4587 "line": 156
4588 }
4589 },
4590 {
4591 "defaultMessage": "!!!Sidebar width",
4592 "end": {
4593 "column": 3,
4594 "line": 163
4595 },
4596 "file": "src/containers/settings/EditSettingsScreen.js",
4597 "id": "settings.app.form.serviceRibbonWidth",
4598 "start": {
4599 "column": 22,
4600 "line": 160
4601 }
4602 },
4603 {
4604 "defaultMessage": "!!!Service icon size",
4605 "end": {
4606 "column": 3,
4607 "line": 167
4608 },
4609 "file": "src/containers/settings/EditSettingsScreen.js",
4610 "id": "settings.app.form.iconSize",
4611 "start": {
4612 "column": 12,
4613 "line": 164
4614 }
4615 },
4616 {
4617 "defaultMessage": "!!!Use horizontal style",
4618 "end": {
4619 "column": 3,
4620 "line": 171
4621 },
4622 "file": "src/containers/settings/EditSettingsScreen.js",
4623 "id": "settings.app.form.useVerticalStyle",
4624 "start": {
4625 "column": 20,
4626 "line": 168
4627 }
4628 },
4629 {
4630 "defaultMessage": "!!!Always show workspace drawer",
4631 "end": {
4632 "column": 3,
4633 "line": 175
4634 },
4635 "file": "src/containers/settings/EditSettingsScreen.js",
4636 "id": "settings.app.form.alwaysShowWorkspaces",
4637 "start": {
4638 "column": 24,
4639 "line": 172
4640 }
4641 },
4642 {
4643 "defaultMessage": "!!!Accent color",
4644 "end": {
4645 "column": 3,
4646 "line": 179
4647 },
4648 "file": "src/containers/settings/EditSettingsScreen.js",
4649 "id": "settings.app.form.accentColor",
4650 "start": {
4651 "column": 15,
4652 "line": 176
4653 }
4654 },
4655 {
4656 "defaultMessage": "!!!Display disabled services tabs",
4657 "end": {
4658 "column": 3,
4659 "line": 183
4660 },
4661 "file": "src/containers/settings/EditSettingsScreen.js",
4662 "id": "settings.app.form.showDisabledServices",
4663 "start": {
4664 "column": 24,
4665 "line": 180
4666 }
4667 },
4668 {
4669 "defaultMessage": "!!!Show unread message badge when notifications are disabled",
4670 "end": {
4671 "column": 3,
4672 "line": 187
4673 },
4674 "file": "src/containers/settings/EditSettingsScreen.js",
4675 "id": "settings.app.form.showMessagesBadgesWhenMuted",
4676 "start": {
4677 "column": 29,
4678 "line": 184
4679 }
4680 },
4681 {
4682 "defaultMessage": "!!!Show draggable area on window",
4683 "end": {
4684 "column": 3,
4685 "line": 191
4686 },
4687 "file": "src/containers/settings/EditSettingsScreen.js",
4688 "id": "settings.app.form.showDragArea",
4689 "start": {
4690 "column": 16,
4691 "line": 188
4692 }
4693 },
4694 {
4695 "defaultMessage": "!!!Enable spell checking",
4696 "end": {
4697 "column": 3,
4698 "line": 195
4699 },
4700 "file": "src/containers/settings/EditSettingsScreen.js",
4701 "id": "settings.app.form.enableSpellchecking",
4702 "start": {
4703 "column": 23,
4704 "line": 192
4705 }
4706 },
4707 {
4708 "defaultMessage": "!!!Enable GPU Acceleration",
4709 "end": {
4710 "column": 3,
4711 "line": 199
4712 },
4713 "file": "src/containers/settings/EditSettingsScreen.js",
4714 "id": "settings.app.form.enableGPUAcceleration",
4715 "start": {
4716 "column": 25,
4717 "line": 196
4718 }
4719 },
4720 {
4721 "defaultMessage": "!!!Include beta versions",
4722 "end": {
4723 "column": 3,
4724 "line": 203
4725 },
4726 "file": "src/containers/settings/EditSettingsScreen.js",
4727 "id": "settings.app.form.beta",
4728 "start": {
4729 "column": 8,
4730 "line": 200
4731 }
4732 },
4733 {
4734 "defaultMessage": "!!!Enable updates",
4735 "end": {
4736 "column": 3,
4737 "line": 207
4738 },
4739 "file": "src/containers/settings/EditSettingsScreen.js",
4740 "id": "settings.app.form.automaticUpdates",
4741 "start": {
4742 "column": 20,
4743 "line": 204
4744 }
4745 },
4746 {
4747 "defaultMessage": "!!!Enable Franz Todos",
4748 "end": {
4749 "column": 3,
4750 "line": 211
4751 },
4752 "file": "src/containers/settings/EditSettingsScreen.js",
4753 "id": "settings.app.form.enableTodos",
4754 "start": {
4755 "column": 15,
4756 "line": 208
4757 }
4758 },
4759 {
4760 "defaultMessage": "!!!Keep all workspaces loaded",
4761 "end": {
4762 "column": 3,
4763 "line": 215
4764 },
4765 "file": "src/containers/settings/EditSettingsScreen.js",
4766 "id": "settings.app.form.keepAllWorkspacesLoaded",
4767 "start": {
4768 "column": 27,
4769 "line": 212
4770 }
4771 }
4772 ],
4773 "path": "src/containers/settings/EditSettingsScreen.json"
4774 },
4775 {
4776 "descriptors": [
4777 {
4778 "defaultMessage": "!!!Firstname",
4779 "end": {
4780 "column": 3,
4781 "line": 17
4782 },
4783 "file": "src/containers/settings/EditUserScreen.js",
4784 "id": "settings.user.form.firstname",
4785 "start": {
4786 "column": 13,
4787 "line": 14
4788 }
4789 },
4790 {
4791 "defaultMessage": "!!!Lastname",
4792 "end": {
4793 "column": 3,
4794 "line": 21
4795 },
4796 "file": "src/containers/settings/EditUserScreen.js",
4797 "id": "settings.user.form.lastname",
4798 "start": {
4799 "column": 12,
4800 "line": 18
4801 }
4802 },
4803 {
4804 "defaultMessage": "!!!Email",
4805 "end": {
4806 "column": 3,
4807 "line": 25
4808 },
4809 "file": "src/containers/settings/EditUserScreen.js",
4810 "id": "settings.user.form.email",
4811 "start": {
4812 "column": 9,
4813 "line": 22
4814 }
4815 },
4816 {
4817 "defaultMessage": "!!!Account type",
4818 "end": {
4819 "column": 3,
4820 "line": 29
4821 },
4822 "file": "src/containers/settings/EditUserScreen.js",
4823 "id": "settings.user.form.accountType.label",
4824 "start": {
4825 "column": 20,
4826 "line": 26
4827 }
4828 },
4829 {
4830 "defaultMessage": "!!!Individual",
4831 "end": {
4832 "column": 3,
4833 "line": 33
4834 },
4835 "file": "src/containers/settings/EditUserScreen.js",
4836 "id": "settings.user.form.accountType.individual",
4837 "start": {
4838 "column": 25,
4839 "line": 30
4840 }
4841 },
4842 {
4843 "defaultMessage": "!!!Non-Profit",
4844 "end": {
4845 "column": 3,
4846 "line": 37
4847 },
4848 "file": "src/containers/settings/EditUserScreen.js",
4849 "id": "settings.user.form.accountType.non-profit",
4850 "start": {
4851 "column": 24,
4852 "line": 34
4853 }
4854 },
4855 {
4856 "defaultMessage": "!!!Company",
4857 "end": {
4858 "column": 3,
4859 "line": 41
4860 },
4861 "file": "src/containers/settings/EditUserScreen.js",
4862 "id": "settings.user.form.accountType.company",
4863 "start": {
4864 "column": 22,
4865 "line": 38
4866 }
4867 },
4868 {
4869 "defaultMessage": "!!!Current password",
4870 "end": {
4871 "column": 3,
4872 "line": 45
4873 },
4874 "file": "src/containers/settings/EditUserScreen.js",
4875 "id": "settings.user.form.currentPassword",
4876 "start": {
4877 "column": 19,
4878 "line": 42
4879 }
4880 },
4881 {
4882 "defaultMessage": "!!!New password",
4883 "end": {
4884 "column": 3,
4885 "line": 49
4886 },
4887 "file": "src/containers/settings/EditUserScreen.js",
4888 "id": "settings.user.form.newPassword",
4889 "start": {
4890 "column": 15,
4891 "line": 46
4892 }
4893 }
4894 ],
4895 "path": "src/containers/settings/EditUserScreen.json"
4896 },
4897 {
4898 "descriptors": [
4899 {
4900 "defaultMessage": "!!!Sign In",
4901 "end": {
4902 "column": 3,
4903 "line": 27
4904 },
4905 "file": "src/features/basicAuth/Component.js",
4906 "id": "feature.basicAuth.signIn",
4907 "start": {
4908 "column": 10,
4909 "line": 24
4910 }
4911 }
4912 ],
4913 "path": "src/features/basicAuth/Component.json"
4914 },
4915 {
4916 "descriptors": [
4917 {
4918 "defaultMessage": "!!!Publish debugging information",
4919 "end": {
4920 "column": 3,
4921 "line": 19
4922 },
4923 "file": "src/features/debugger/Component.js",
4924 "id": "feature.debugger.title",
4925 "start": {
4926 "column": 9,
4927 "line": 16
4928 }
4929 }
4930 ],
4931 "path": "src/features/debugger/Component.json"
4932 },
4933 {
4934 "descriptors": [
4935 {
4936 "defaultMessage": "!!!Nightly Builds",
4937 "end": {
4938 "column": 3,
4939 "line": 20
4940 },
4941 "file": "src/features/nightlyBuilds/Component.js",
4942 "id": "feature.nightlyBuilds.title",
4943 "start": {
4944 "column": 9,
4945 "line": 17
4946 }
4947 },
4948 {
4949 "defaultMessage": "!!!Nightly builds are highly experimental versions of Ferdi that may contain unpolished or uncompleted features. These nightly builds are mainly used by developers to test their newly developed features and how they will perform in the final build. If you don't know what you are doing, we suggest not activating nightly builds.",
4950 "end": {
4951 "column": 3,
4952 "line": 24
4953 },
4954 "file": "src/features/nightlyBuilds/Component.js",
4955 "id": "feature.nightlyBuilds.info",
4956 "start": {
4957 "column": 8,
4958 "line": 21
4959 }
4960 },
4961 {
4962 "defaultMessage": "!!!Activate",
4963 "end": {
4964 "column": 3,
4965 "line": 28
4966 },
4967 "file": "src/features/nightlyBuilds/Component.js",
4968 "id": "feature.nightlyBuilds.activate",
4969 "start": {
4970 "column": 12,
4971 "line": 25
4972 }
4973 }
4974 ],
4975 "path": "src/features/nightlyBuilds/Component.json"
4976 },
4977 {
4978 "descriptors": [
4979 {
4980 "defaultMessage": "!!!Publish debug information",
4981 "end": {
4982 "column": 3,
4983 "line": 22
4984 },
4985 "file": "src/features/publishDebugInfo/Component.js",
4986 "id": "feature.publishDebugInfo.title",
4987 "start": {
4988 "column": 9,
4989 "line": 19
4990 }
4991 },
4992 {
4993 "defaultMessage": "!!!Publishing your debug information helps us find issues and errors in Ferdi. By publishing your debug information you accept Ferdi Debugger's privacy policy and terms of service",
4994 "end": {
4995 "column": 3,
4996 "line": 26
4997 },
4998 "file": "src/features/publishDebugInfo/Component.js",
4999 "id": "feature.publishDebugInfo.info",
5000 "start": {
5001 "column": 8,
5002 "line": 23
5003 }
5004 },
5005 {
5006 "defaultMessage": "!!!There was an error while trying to publish the debug information. Please try again later or view the console for more information.",
5007 "end": {
5008 "column": 3,
5009 "line": 30
5010 },
5011 "file": "src/features/publishDebugInfo/Component.js",
5012 "id": "feature.publishDebugInfo.error",
5013 "start": {
5014 "column": 9,
5015 "line": 27
5016 }
5017 },
5018 {
5019 "defaultMessage": "!!!Privacy policy",
5020 "end": {
5021 "column": 3,
5022 "line": 34
5023 },
5024 "file": "src/features/publishDebugInfo/Component.js",
5025 "id": "feature.publishDebugInfo.privacy",
5026 "start": {
5027 "column": 11,
5028 "line": 31
5029 }
5030 },
5031 {
5032 "defaultMessage": "!!!Terms of service",
5033 "end": {
5034 "column": 3,
5035 "line": 38
5036 },
5037 "file": "src/features/publishDebugInfo/Component.js",
5038 "id": "feature.publishDebugInfo.terms",
5039 "start": {
5040 "column": 9,
5041 "line": 35
5042 }
5043 },
5044 {
5045 "defaultMessage": "!!!Accept and publish",
5046 "end": {
5047 "column": 3,
5048 "line": 42
5049 },
5050 "file": "src/features/publishDebugInfo/Component.js",
5051 "id": "feature.publishDebugInfo.publish",
5052 "start": {
5053 "column": 11,
5054 "line": 39
5055 }
5056 },
5057 {
5058 "defaultMessage": "!!!Your debug log was published and is now availible at",
5059 "end": {
5060 "column": 3,
5061 "line": 46
5062 },
5063 "file": "src/features/publishDebugInfo/Component.js",
5064 "id": "feature.publishDebugInfo.published",
5065 "start": {
5066 "column": 13,
5067 "line": 43
5068 }
5069 }
5070 ],
5071 "path": "src/features/publishDebugInfo/Component.json"
5072 },
5073 {
5074 "descriptors": [
5075 {
5076 "defaultMessage": "!!!QuickSwitch",
5077 "end": {
5078 "column": 3,
5079 "line": 20
5080 },
5081 "file": "src/features/quickSwitch/Component.js",
5082 "id": "feature.quickSwitch.title",
5083 "start": {
5084 "column": 9,
5085 "line": 17
5086 }
5087 },
5088 {
5089 "defaultMessage": "!!!Search...",
5090 "end": {
5091 "column": 3,
5092 "line": 24
5093 },
5094 "file": "src/features/quickSwitch/Component.js",
5095 "id": "feature.quickSwitch.search",
5096 "start": {
5097 "column": 10,
5098 "line": 21
5099 }
5100 },
5101 {
5102 "defaultMessage": "!!!Select a service with TAB, ↑ and ↓. Open a service with ENTER.",
5103 "end": {
5104 "column": 3,
5105 "line": 28
5106 },
5107 "file": "src/features/quickSwitch/Component.js",
5108 "id": "feature.quickSwitch.info",
5109 "start": {
5110 "column": 8,
5111 "line": 25
5112 }
5113 }
5114 ],
5115 "path": "src/features/quickSwitch/Component.json"
5116 },
5117 {
5118 "descriptors": [
5119 {
5120 "defaultMessage": "!!!Home",
5121 "end": {
5122 "column": 3,
5123 "line": 16
5124 },
5125 "file": "src/features/recipeConnectionLost/components/WebControls.js",
5126 "id": "webControls.goHome",
5127 "start": {
5128 "column": 10,
5129 "line": 13
5130 }
5131 },
5132 {
5133 "defaultMessage": "!!!Open in Browser",
5134 "end": {
5135 "column": 3,
5136 "line": 20
5137 },
5138 "file": "src/features/recipeConnectionLost/components/WebControls.js",
5139 "id": "webControls.openInBrowser",
5140 "start": {
5141 "column": 17,
5142 "line": 17
5143 }
5144 },
5145 {
5146 "defaultMessage": "!!!Back",
5147 "end": {
5148 "column": 3,
5149 "line": 24
5150 },
5151 "file": "src/features/recipeConnectionLost/components/WebControls.js",
5152 "id": "webControls.back",
5153 "start": {
5154 "column": 8,
5155 "line": 21
5156 }
5157 },
5158 {
5159 "defaultMessage": "!!!Forward",
5160 "end": {
5161 "column": 3,
5162 "line": 28
5163 },
5164 "file": "src/features/recipeConnectionLost/components/WebControls.js",
5165 "id": "webControls.forward",
5166 "start": {
5167 "column": 11,
5168 "line": 25
5169 }
5170 },
5171 {
5172 "defaultMessage": "!!!Reload",
5173 "end": {
5174 "column": 3,
5175 "line": 32
5176 },
5177 "file": "src/features/recipeConnectionLost/components/WebControls.js",
5178 "id": "webControls.reload",
5179 "start": {
5180 "column": 10,
5181 "line": 29
5182 }
5183 }
5184 ],
5185 "path": "src/features/recipeConnectionLost/components/WebControls.json"
5186 },
5187 {
5188 "descriptors": [
5189 {
5190 "defaultMessage": "!!!Home",
5191 "end": {
5192 "column": 3,
5193 "line": 20
5194 },
5195 "file": "src/features/webControls/components/WebControls.js",
5196 "id": "webControls.goHome",
5197 "start": {
5198 "column": 10,
5199 "line": 17
5200 }
5201 },
5202 {
5203 "defaultMessage": "!!!Open in Browser",
5204 "end": {
5205 "column": 3,
5206 "line": 24
5207 },
5208 "file": "src/features/webControls/components/WebControls.js",
5209 "id": "webControls.openInBrowser",
5210 "start": {
5211 "column": 17,
5212 "line": 21
5213 }
5214 },
5215 {
5216 "defaultMessage": "!!!Back",
5217 "end": {
5218 "column": 3,
5219 "line": 28
5220 },
5221 "file": "src/features/webControls/components/WebControls.js",
5222 "id": "webControls.back",
5223 "start": {
5224 "column": 8,
5225 "line": 25
5226 }
5227 },
5228 {
5229 "defaultMessage": "!!!Forward",
5230 "end": {
5231 "column": 3,
5232 "line": 32
5233 },
5234 "file": "src/features/webControls/components/WebControls.js",
5235 "id": "webControls.forward",
5236 "start": {
5237 "column": 11,
5238 "line": 29
5239 }
5240 },
5241 {
5242 "defaultMessage": "!!!Reload",
5243 "end": {
5244 "column": 3,
5245 "line": 36
5246 },
5247 "file": "src/features/webControls/components/WebControls.js",
5248 "id": "webControls.reload",
5249 "start": {
5250 "column": 10,
5251 "line": 33
5252 }
5253 }
5254 ],
5255 "path": "src/features/webControls/components/WebControls.json"
5256 },
5257 {
5258 "descriptors": [
5259 {
5260 "defaultMessage": "!!!Create workspace",
5261 "end": {
5262 "column": 3,
5263 "line": 15
5264 },
5265 "file": "src/features/workspaces/components/CreateWorkspaceForm.js",
5266 "id": "settings.workspace.add.form.submitButton",
5267 "start": {
5268 "column": 16,
5269 "line": 12
5270 }
5271 },
5272 {
5273 "defaultMessage": "!!!Name",
5274 "end": {
5275 "column": 3,
5276 "line": 19
5277 },
5278 "file": "src/features/workspaces/components/CreateWorkspaceForm.js",
5279 "id": "settings.workspace.add.form.name",
5280 "start": {
5281 "column": 8,
5282 "line": 16
5283 }
5284 }
5285 ],
5286 "path": "src/features/workspaces/components/CreateWorkspaceForm.json"
5287 },
5288 {
5289 "descriptors": [
5290 {
5291 "defaultMessage": "!!!Delete workspace",
5292 "end": {
5293 "column": 3,
5294 "line": 24
5295 },
5296 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
5297 "id": "settings.workspace.form.buttonDelete",
5298 "start": {
5299 "column": 16,
5300 "line": 21
5301 }
5302 },
5303 {
5304 "defaultMessage": "!!!Save workspace",
5305 "end": {
5306 "column": 3,
5307 "line": 28
5308 },
5309 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
5310 "id": "settings.workspace.form.buttonSave",
5311 "start": {
5312 "column": 14,
5313 "line": 25
5314 }
5315 },
5316 {
5317 "defaultMessage": "!!!Name",
5318 "end": {
5319 "column": 3,
5320 "line": 32
5321 },
5322 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
5323 "id": "settings.workspace.form.name",
5324 "start": {
5325 "column": 8,
5326 "line": 29
5327 }
5328 },
5329 {
5330 "defaultMessage": "!!!Your workspaces",
5331 "end": {
5332 "column": 3,
5333 "line": 36
5334 },
5335 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
5336 "id": "settings.workspace.form.yourWorkspaces",
5337 "start": {
5338 "column": 18,
5339 "line": 33
5340 }
5341 },
5342 {
5343 "defaultMessage": "!!!Keep this workspace loaded*",
5344 "end": {
5345 "column": 3,
5346 "line": 40
5347 },
5348 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
5349 "id": "settings.workspace.form.keepLoaded",
5350 "start": {
5351 "column": 14,
5352 "line": 37
5353 }
5354 },
5355 {
5356 "defaultMessage": "!!!*This option will be overwritten by the global \"Keep all workspaces loaded\" option.",
5357 "end": {
5358 "column": 3,
5359 "line": 45
5360 },
5361 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
5362 "id": "settings.workspace.form.keepLoadedInfo",
5363 "start": {
5364 "column": 18,
5365 "line": 41
5366 }
5367 },
5368 {
5369 "defaultMessage": "!!!Services in this Workspace",
5370 "end": {
5371 "column": 3,
5372 "line": 49
5373 },
5374 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
5375 "id": "settings.workspace.form.servicesInWorkspaceHeadline",
5376 "start": {
5377 "column": 31,
5378 "line": 46
5379 }
5380 },
5381 {
5382 "defaultMessage": "!!!Start by adding a service.",
5383 "end": {
5384 "column": 3,
5385 "line": 53
5386 },
5387 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
5388 "id": "settings.services.noServicesAdded",
5389 "start": {
5390 "column": 19,
5391 "line": 50
5392 }
5393 },
5394 {
5395 "defaultMessage": "!!!Discover services",
5396 "end": {
5397 "column": 3,
5398 "line": 57
5399 },
5400 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
5401 "id": "settings.services.discoverServices",
5402 "start": {
5403 "column": 20,
5404 "line": 54
5405 }
5406 }
5407 ],
5408 "path": "src/features/workspaces/components/EditWorkspaceForm.json"
5409 },
5410 {
5411 "descriptors": [
5412 {
5413 "defaultMessage": "!!!Workspaces",
5414 "end": {
5415 "column": 3,
5416 "line": 18
5417 },
5418 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
5419 "id": "workspaceDrawer.headline",
5420 "start": {
5421 "column": 12,
5422 "line": 15
5423 }
5424 },
5425 {
5426 "defaultMessage": "!!!All services",
5427 "end": {
5428 "column": 3,
5429 "line": 22
5430 },
5431 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
5432 "id": "workspaceDrawer.allServices",
5433 "start": {
5434 "column": 15,
5435 "line": 19
5436 }
5437 },
5438 {
5439 "defaultMessage": "!!!Workspaces settings",
5440 "end": {
5441 "column": 3,
5442 "line": 26
5443 },
5444 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
5445 "id": "workspaceDrawer.workspacesSettingsTooltip",
5446 "start": {
5447 "column": 29,
5448 "line": 23
5449 }
5450 },
5451 {
5452 "defaultMessage": "!!!Info about workspace feature",
5453 "end": {
5454 "column": 3,
5455 "line": 30
5456 },
5457 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
5458 "id": "workspaceDrawer.workspaceFeatureInfo",
5459 "start": {
5460 "column": 24,
5461 "line": 27
5462 }
5463 },
5464 {
5465 "defaultMessage": "!!!add new workspace",
5466 "end": {
5467 "column": 3,
5468 "line": 34
5469 },
5470 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
5471 "id": "workspaceDrawer.addNewWorkspaceLabel",
5472 "start": {
5473 "column": 24,
5474 "line": 31
5475 }
5476 }
5477 ],
5478 "path": "src/features/workspaces/components/WorkspaceDrawer.json"
5479 },
5480 {
5481 "descriptors": [
5482 {
5483 "defaultMessage": "!!!No services added yet",
5484 "end": {
5485 "column": 3,
5486 "line": 14
5487 },
5488 "file": "src/features/workspaces/components/WorkspaceDrawerItem.js",
5489 "id": "workspaceDrawer.item.noServicesAddedYet",
5490 "start": {
5491 "column": 22,
5492 "line": 11
5493 }
5494 },
5495 {
5496 "defaultMessage": "!!!edit",
5497 "end": {
5498 "column": 3,
5499 "line": 18
5500 },
5501 "file": "src/features/workspaces/components/WorkspaceDrawerItem.js",
5502 "id": "workspaceDrawer.item.contextMenuEdit",
5503 "start": {
5504 "column": 19,
5505 "line": 15
5506 }
5507 }
5508 ],
5509 "path": "src/features/workspaces/components/WorkspaceDrawerItem.json"
5510 },
5511 {
5512 "descriptors": [
5513 {
5514 "defaultMessage": "!!!Your workspaces",
5515 "end": {
5516 "column": 3,
5517 "line": 20
5518 },
5519 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
5520 "id": "settings.workspaces.headline",
5521 "start": {
5522 "column": 12,
5523 "line": 17
5524 }
5525 },
5526 {
5527 "defaultMessage": "!!!You haven't created any workspaces yet.",
5528 "end": {
5529 "column": 3,
5530 "line": 24
5531 },
5532 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
5533 "id": "settings.workspaces.noWorkspacesAdded",
5534 "start": {
5535 "column": 19,
5536 "line": 21
5537 }
5538 },
5539 {
5540 "defaultMessage": "!!!Could not load your workspaces",
5541 "end": {
5542 "column": 3,
5543 "line": 28
5544 },
5545 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
5546 "id": "settings.workspaces.workspacesRequestFailed",
5547 "start": {
5548 "column": 27,
5549 "line": 25
5550 }
5551 },
5552 {
5553 "defaultMessage": "!!!Try again",
5554 "end": {
5555 "column": 3,
5556 "line": 32
5557 },
5558 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
5559 "id": "settings.workspaces.tryReloadWorkspaces",
5560 "start": {
5561 "column": 23,
5562 "line": 29
5563 }
5564 },
5565 {
5566 "defaultMessage": "!!!Your changes have been saved",
5567 "end": {
5568 "column": 3,
5569 "line": 36
5570 },
5571 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
5572 "id": "settings.workspaces.updatedInfo",
5573 "start": {
5574 "column": 15,
5575 "line": 33
5576 }
5577 },
5578 {
5579 "defaultMessage": "!!!Workspace has been deleted",
5580 "end": {
5581 "column": 3,
5582 "line": 40
5583 },
5584 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
5585 "id": "settings.workspaces.deletedInfo",
5586 "start": {
5587 "column": 15,
5588 "line": 37
5589 }
5590 },
5591 {
5592 "defaultMessage": "!!!Info about workspace feature",
5593 "end": {
5594 "column": 3,
5595 "line": 44
5596 },
5597 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
5598 "id": "settings.workspaces.workspaceFeatureInfo",
5599 "start": {
5600 "column": 24,
5601 "line": 41
5602 }
5603 },
5604 {
5605 "defaultMessage": "!!!Less is More: Introducing Ferdi Workspaces",
5606 "end": {
5607 "column": 3,
5608 "line": 48
5609 },
5610 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
5611 "id": "settings.workspaces.workspaceFeatureHeadline",
5612 "start": {
5613 "column": 28,
5614 "line": 45
5615 }
5616 }
5617 ],
5618 "path": "src/features/workspaces/components/WorkspacesDashboard.json"
5619 },
5620 {
5621 "descriptors": [
5622 {
5623 "defaultMessage": "!!!Switching to",
5624 "end": {
5625 "column": 3,
5626 "line": 15
5627 },
5628 "file": "src/features/workspaces/components/WorkspaceSwitchingIndicator.js",
5629 "id": "workspaces.switchingIndicator.switchingTo",
5630 "start": {
5631 "column": 15,
5632 "line": 12
5633 }
5634 }
5635 ],
5636 "path": "src/features/workspaces/components/WorkspaceSwitchingIndicator.json"
5637 },
5638 {
5639 "descriptors": [
5640 {
5641 "defaultMessage": "!!!Field is required",
5642 "end": {
5643 "column": 3,
5644 "line": 8
5645 },
5646 "file": "src/helpers/validation-helpers.js",
5647 "id": "validation.required",
5648 "start": {
5649 "column": 12,
5650 "line": 5
5651 }
5652 },
5653 {
5654 "defaultMessage": "!!!Email not valid",
5655 "end": {
5656 "column": 3,
5657 "line": 12
5658 },
5659 "file": "src/helpers/validation-helpers.js",
5660 "id": "validation.email",
5661 "start": {
5662 "column": 9,
5663 "line": 9
5664 }
5665 },
5666 {
5667 "defaultMessage": "!!!Not a valid URL",
5668 "end": {
5669 "column": 3,
5670 "line": 16
5671 },
5672 "file": "src/helpers/validation-helpers.js",
5673 "id": "validation.url",
5674 "start": {
5675 "column": 7,
5676 "line": 13
5677 }
5678 },
5679 {
5680 "defaultMessage": "!!!Too few characters",
5681 "end": {
5682 "column": 3,
5683 "line": 20
5684 },
5685 "file": "src/helpers/validation-helpers.js",
5686 "id": "validation.minLength",
5687 "start": {
5688 "column": 13,
5689 "line": 17
5690 }
5691 },
5692 {
5693 "defaultMessage": "!!!At least one is required",
5694 "end": {
5695 "column": 3,
5696 "line": 24
5697 },
5698 "file": "src/helpers/validation-helpers.js",
5699 "id": "validation.oneRequired",
5700 "start": {
5701 "column": 15,
5702 "line": 21
5703 }
5704 }
5705 ],
5706 "path": "src/helpers/validation-helpers.json"
5707 },
5708 {
5709 "descriptors": [
5710 {
5711 "defaultMessage": "!!!Can't connect to Ferdi Online Services",
5712 "end": {
5713 "column": 3,
5714 "line": 7
5715 },
5716 "file": "src/i18n/globalMessages.js",
5717 "id": "global.api.unhealthy",
5718 "start": {
5719 "column": 16,
5720 "line": 4
5721 }
5722 },
5723 {
5724 "defaultMessage": "!!!You are not connected to the internet.",
5725 "end": {
5726 "column": 3,
5727 "line": 11
5728 },
5729 "file": "src/i18n/globalMessages.js",
5730 "id": "global.notConnectedToTheInternet",
5731 "start": {
5732 "column": 29,
5733 "line": 8
5734 }
5735 },
5736 {
5737 "defaultMessage": "!!!Spell checking language",
5738 "end": {
5739 "column": 3,
5740 "line": 15
5741 },
5742 "file": "src/i18n/globalMessages.js",
5743 "id": "global.spellchecking.language",
5744 "start": {
5745 "column": 24,
5746 "line": 12
5747 }
5748 },
5749 {
5750 "defaultMessage": "!!!Use System Default ({default})",
5751 "end": {
5752 "column": 3,
5753 "line": 19
5754 },
5755 "file": "src/i18n/globalMessages.js",
5756 "id": "global.spellchecker.useDefault",
5757 "start": {
5758 "column": 29,
5759 "line": 16
5760 }
5761 },
5762 {
5763 "defaultMessage": "!!!Detect language automatically",
5764 "end": {
5765 "column": 3,
5766 "line": 23
5767 },
5768 "file": "src/i18n/globalMessages.js",
5769 "id": "global.spellchecking.autodetect",
5770 "start": {
5771 "column": 34,
5772 "line": 20
5773 }
5774 },
5775 {
5776 "defaultMessage": "!!!Automatic",
5777 "end": {
5778 "column": 3,
5779 "line": 27
5780 },
5781 "file": "src/i18n/globalMessages.js",
5782 "id": "global.spellchecking.autodetect.short",
5783 "start": {
5784 "column": 39,
5785 "line": 24
5786 }
5787 },
5788 {
5789 "defaultMessage": "!!!User Agent",
5790 "end": {
5791 "column": 3,
5792 "line": 31
5793 },
5794 "file": "src/i18n/globalMessages.js",
5795 "id": "global.userAgentPref",
5796 "start": {
5797 "column": 17,
5798 "line": 28
5799 }
5800 },
5801 {
5802 "defaultMessage": "!!!Use 'https://whatmyuseragent.com/' (to discover) or 'https://developers.whatismybrowser.com/useragents/explore/' (to choose) your desired user agent and copy-paste it here.",
5803 "end": {
5804 "column": 3,
5805 "line": 35
5806 },
5807 "file": "src/i18n/globalMessages.js",
5808 "id": "global.userAgentHelp",
5809 "start": {
5810 "column": 17,
5811 "line": 32
5812 }
5813 },
5814 {
5815 "defaultMessage": "!!!Yes",
5816 "end": {
5817 "column": 3,
5818 "line": 39
5819 },
5820 "file": "src/i18n/globalMessages.js",
5821 "id": "global.yes",
5822 "start": {
5823 "column": 7,
5824 "line": 36
5825 }
5826 },
5827 {
5828 "defaultMessage": "!!!No",
5829 "end": {
5830 "column": 3,
5831 "line": 43
5832 },
5833 "file": "src/i18n/globalMessages.js",
5834 "id": "global.no",
5835 "start": {
5836 "column": 6,
5837 "line": 40
5838 }
5839 },
5840 {
5841 "defaultMessage": "!!!Ok",
5842 "end": {
5843 "column": 3,
5844 "line": 47
5845 },
5846 "file": "src/i18n/globalMessages.js",
5847 "id": "global.ok",
5848 "start": {
5849 "column": 6,
5850 "line": 44
5851 }
5852 },
5853 {
5854 "defaultMessage": "!!!Cancel",
5855 "end": {
5856 "column": 3,
5857 "line": 51
5858 },
5859 "file": "src/i18n/globalMessages.js",
5860 "id": "global.cancel",
5861 "start": {
5862 "column": 10,
5863 "line": 48
5864 }
5865 },
5866 {
5867 "defaultMessage": "!!!Save",
5868 "end": {
5869 "column": 3,
5870 "line": 55
5871 },
5872 "file": "src/i18n/globalMessages.js",
5873 "id": "global.save",
5874 "start": {
5875 "column": 8,
5876 "line": 52
5877 }
5878 },
5879 {
5880 "defaultMessage": "!!!Submit",
5881 "end": {
5882 "column": 3,
5883 "line": 59
5884 },
5885 "file": "src/i18n/globalMessages.js",
5886 "id": "global.submit",
5887 "start": {
5888 "column": 10,
5889 "line": 56
5890 }
5891 },
5892 {
5893 "defaultMessage": "!!!Quit",
5894 "end": {
5895 "column": 3,
5896 "line": 63
5897 },
5898 "file": "src/i18n/globalMessages.js",
5899 "id": "global.quit",
5900 "start": {
5901 "column": 8,
5902 "line": 60
5903 }
5904 },
5905 {
5906 "defaultMessage": "!!!Do you really want to quit Ferdi?",
5907 "end": {
5908 "column": 3,
5909 "line": 68
5910 },
5911 "file": "src/i18n/globalMessages.js",
5912 "id": "global.quitConfirmation",
5913 "start": {
5914 "column": 20,
5915 "line": 64
5916 }
5917 },
5918 {
5919 "defaultMessage": "!!!Settings",
5920 "end": {
5921 "column": 3,
5922 "line": 72
5923 },
5924 "file": "src/i18n/globalMessages.js",
5925 "id": "global.settings",
5926 "start": {
5927 "column": 12,
5928 "line": 69
5929 }
5930 },
5931 {
5932 "defaultMessage": "!!!Edit",
5933 "end": {
5934 "column": 3,
5935 "line": 76
5936 },
5937 "file": "src/i18n/globalMessages.js",
5938 "id": "global.edit",
5939 "start": {
5940 "column": 8,
5941 "line": 73
5942 }
5943 }
5944 ],
5945 "path": "src/i18n/globalMessages.json"
5946 },
5947 {
5948 "descriptors": [
5949 {
5950 "defaultMessage": "!!!Edit",
5951 "end": {
5952 "column": 3,
5953 "line": 35
5954 },
5955 "file": "src/lib/Menu.js",
5956 "id": "menu.edit",
5957 "start": {
5958 "column": 8,
5959 "line": 32
5960 }
5961 },
5962 {
5963 "defaultMessage": "!!!Undo",
5964 "end": {
5965 "column": 3,
5966 "line": 39
5967 },
5968 "file": "src/lib/Menu.js",
5969 "id": "menu.edit.undo",
5970 "start": {
5971 "column": 8,
5972 "line": 36
5973 }
5974 },
5975 {
5976 "defaultMessage": "!!!Redo",
5977 "end": {
5978 "column": 3,
5979 "line": 43
5980 },
5981 "file": "src/lib/Menu.js",
5982 "id": "menu.edit.redo",
5983 "start": {
5984 "column": 8,
5985 "line": 40
5986 }
5987 },
5988 {
5989 "defaultMessage": "!!!Cut",
5990 "end": {
5991 "column": 3,
5992 "line": 47
5993 },
5994 "file": "src/lib/Menu.js",
5995 "id": "menu.edit.cut",
5996 "start": {
5997 "column": 7,
5998 "line": 44
5999 }
6000 },
6001 {
6002 "defaultMessage": "!!!Copy",
6003 "end": {
6004 "column": 3,
6005 "line": 51
6006 },
6007 "file": "src/lib/Menu.js",
6008 "id": "menu.edit.copy",
6009 "start": {
6010 "column": 8,
6011 "line": 48
6012 }
6013 },
6014 {
6015 "defaultMessage": "!!!Paste",
6016 "end": {
6017 "column": 3,
6018 "line": 55
6019 },
6020 "file": "src/lib/Menu.js",
6021 "id": "menu.edit.paste",
6022 "start": {
6023 "column": 9,
6024 "line": 52
6025 }
6026 },
6027 {
6028 "defaultMessage": "!!!Paste And Match Style",
6029 "end": {
6030 "column": 3,
6031 "line": 59
6032 },
6033 "file": "src/lib/Menu.js",
6034 "id": "menu.edit.pasteAndMatchStyle",
6035 "start": {
6036 "column": 22,
6037 "line": 56
6038 }
6039 },
6040 {
6041 "defaultMessage": "!!!Delete",
6042 "end": {
6043 "column": 3,
6044 "line": 63
6045 },
6046 "file": "src/lib/Menu.js",
6047 "id": "menu.edit.delete",
6048 "start": {
6049 "column": 10,
6050 "line": 60
6051 }
6052 },
6053 {
6054 "defaultMessage": "!!!Select All",
6055 "end": {
6056 "column": 3,
6057 "line": 67
6058 },
6059 "file": "src/lib/Menu.js",
6060 "id": "menu.edit.selectAll",
6061 "start": {
6062 "column": 13,
6063 "line": 64
6064 }
6065 },
6066 {
6067 "defaultMessage": "!!!Find in Page",
6068 "end": {
6069 "column": 3,
6070 "line": 71
6071 },
6072 "file": "src/lib/Menu.js",
6073 "id": "menu.edit.findInPage",
6074 "start": {
6075 "column": 14,
6076 "line": 68
6077 }
6078 },
6079 {
6080 "defaultMessage": "!!!Speech",
6081 "end": {
6082 "column": 3,
6083 "line": 75
6084 },
6085 "file": "src/lib/Menu.js",
6086 "id": "menu.edit.speech",
6087 "start": {
6088 "column": 10,
6089 "line": 72
6090 }
6091 },
6092 {
6093 "defaultMessage": "!!!Start Speaking",
6094 "end": {
6095 "column": 3,
6096 "line": 79
6097 },
6098 "file": "src/lib/Menu.js",
6099 "id": "menu.edit.startSpeaking",
6100 "start": {
6101 "column": 17,
6102 "line": 76
6103 }
6104 },
6105 {
6106 "defaultMessage": "!!!Stop Speaking",
6107 "end": {
6108 "column": 3,
6109 "line": 83
6110 },
6111 "file": "src/lib/Menu.js",
6112 "id": "menu.edit.stopSpeaking",
6113 "start": {
6114 "column": 16,
6115 "line": 80
6116 }
6117 },
6118 {
6119 "defaultMessage": "!!!Start Dictation",
6120 "end": {
6121 "column": 3,
6122 "line": 87
6123 },
6124 "file": "src/lib/Menu.js",
6125 "id": "menu.edit.startDictation",
6126 "start": {
6127 "column": 18,
6128 "line": 84
6129 }
6130 },
6131 {
6132 "defaultMessage": "!!!Emoji & Symbols",
6133 "end": {
6134 "column": 3,
6135 "line": 91
6136 },
6137 "file": "src/lib/Menu.js",
6138 "id": "menu.edit.emojiSymbols",
6139 "start": {
6140 "column": 16,
6141 "line": 88
6142 }
6143 },
6144 {
6145 "defaultMessage": "!!!Open Quick Switch",
6146 "end": {
6147 "column": 3,
6148 "line": 95
6149 },
6150 "file": "src/lib/Menu.js",
6151 "id": "menu.view.openQuickSwitch",
6152 "start": {
6153 "column": 19,
6154 "line": 92
6155 }
6156 },
6157 {
6158 "defaultMessage": "!!!Back",
6159 "end": {
6160 "column": 3,
6161 "line": 99
6162 },
6163 "file": "src/lib/Menu.js",
6164 "id": "menu.view.back",
6165 "start": {
6166 "column": 8,
6167 "line": 96
6168 }
6169 },
6170 {
6171 "defaultMessage": "!!!Forward",
6172 "end": {
6173 "column": 3,
6174 "line": 103
6175 },
6176 "file": "src/lib/Menu.js",
6177 "id": "menu.view.forward",
6178 "start": {
6179 "column": 11,
6180 "line": 100
6181 }
6182 },
6183 {
6184 "defaultMessage": "!!!Actual Size",
6185 "end": {
6186 "column": 3,
6187 "line": 107
6188 },
6189 "file": "src/lib/Menu.js",
6190 "id": "menu.view.resetZoom",
6191 "start": {
6192 "column": 13,
6193 "line": 104
6194 }
6195 },
6196 {
6197 "defaultMessage": "!!!Zoom In",
6198 "end": {
6199 "column": 3,
6200 "line": 111
6201 },
6202 "file": "src/lib/Menu.js",
6203 "id": "menu.view.zoomIn",
6204 "start": {
6205 "column": 10,
6206 "line": 108
6207 }
6208 },
6209 {
6210 "defaultMessage": "!!!Zoom Out",
6211 "end": {
6212 "column": 3,
6213 "line": 115
6214 },
6215 "file": "src/lib/Menu.js",
6216 "id": "menu.view.zoomOut",
6217 "start": {
6218 "column": 11,
6219 "line": 112
6220 }
6221 },
6222 {
6223 "defaultMessage": "!!!Toggle Full Screen",
6224 "end": {
6225 "column": 3,
6226 "line": 119
6227 },
6228 "file": "src/lib/Menu.js",
6229 "id": "menu.view.toggleFullScreen",
6230 "start": {
6231 "column": 20,
6232 "line": 116
6233 }
6234 },
6235 {
6236 "defaultMessage": "!!!Toggle Dark Mode",
6237 "end": {
6238 "column": 3,
6239 "line": 123
6240 },
6241 "file": "src/lib/Menu.js",
6242 "id": "menu.view.toggleDarkMode",
6243 "start": {
6244 "column": 18,
6245 "line": 120
6246 }
6247 },
6248 {
6249 "defaultMessage": "!!!Toggle Developer Tools",
6250 "end": {
6251 "column": 3,
6252 "line": 127
6253 },
6254 "file": "src/lib/Menu.js",
6255 "id": "menu.view.toggleDevTools",
6256 "start": {
6257 "column": 18,
6258 "line": 124
6259 }
6260 },
6261 {
6262 "defaultMessage": "!!!Toggle Todos Developer Tools",
6263 "end": {
6264 "column": 3,
6265 "line": 131
6266 },
6267 "file": "src/lib/Menu.js",
6268 "id": "menu.view.toggleTodosDevTools",
6269 "start": {
6270 "column": 23,
6271 "line": 128
6272 }
6273 },
6274 {
6275 "defaultMessage": "!!!Toggle Service Developer Tools",
6276 "end": {
6277 "column": 3,
6278 "line": 135
6279 },
6280 "file": "src/lib/Menu.js",
6281 "id": "menu.view.toggleServiceDevTools",
6282 "start": {
6283 "column": 25,
6284 "line": 132
6285 }
6286 },
6287 {
6288 "defaultMessage": "!!!Reload Service",
6289 "end": {
6290 "column": 3,
6291 "line": 139
6292 },
6293 "file": "src/lib/Menu.js",
6294 "id": "menu.view.reloadService",
6295 "start": {
6296 "column": 17,
6297 "line": 136
6298 }
6299 },
6300 {
6301 "defaultMessage": "!!!Reload Ferdi",
6302 "end": {
6303 "column": 3,
6304 "line": 143
6305 },
6306 "file": "src/lib/Menu.js",
6307 "id": "menu.view.reloadFerdi",
6308 "start": {
6309 "column": 15,
6310 "line": 140
6311 }
6312 },
6313 {
6314 "defaultMessage": "!!!Lock Ferdi",
6315 "end": {
6316 "column": 3,
6317 "line": 147
6318 },
6319 "file": "src/lib/Menu.js",
6320 "id": "menu.view.lockFerdi",
6321 "start": {
6322 "column": 13,
6323 "line": 144
6324 }
6325 },
6326 {
6327 "defaultMessage": "!!!Reload ToDos",
6328 "end": {
6329 "column": 3,
6330 "line": 151
6331 },
6332 "file": "src/lib/Menu.js",
6333 "id": "menu.view.reloadTodos",
6334 "start": {
6335 "column": 15,
6336 "line": 148
6337 }
6338 },
6339 {
6340 "defaultMessage": "!!!Minimize",
6341 "end": {
6342 "column": 3,
6343 "line": 155
6344 },
6345 "file": "src/lib/Menu.js",
6346 "id": "menu.window.minimize",
6347 "start": {
6348 "column": 12,
6349 "line": 152
6350 }
6351 },
6352 {
6353 "defaultMessage": "!!!Close",
6354 "end": {
6355 "column": 3,
6356 "line": 159
6357 },
6358 "file": "src/lib/Menu.js",
6359 "id": "menu.window.close",
6360 "start": {
6361 "column": 9,
6362 "line": 156
6363 }
6364 },
6365 {
6366 "defaultMessage": "!!!Learn More",
6367 "end": {
6368 "column": 3,
6369 "line": 163
6370 },
6371 "file": "src/lib/Menu.js",
6372 "id": "menu.help.learnMore",
6373 "start": {
6374 "column": 13,
6375 "line": 160
6376 }
6377 },
6378 {
6379 "defaultMessage": "!!!Changelog",
6380 "end": {
6381 "column": 3,
6382 "line": 167
6383 },
6384 "file": "src/lib/Menu.js",
6385 "id": "menu.help.changelog",
6386 "start": {
6387 "column": 13,
6388 "line": 164
6389 }
6390 },
6391 {
6392 "defaultMessage": "!!!Import/Export Configuration Data",
6393 "end": {
6394 "column": 3,
6395 "line": 171
6396 },
6397 "file": "src/lib/Menu.js",
6398 "id": "menu.help.importExportData",
6399 "start": {
6400 "column": 20,
6401 "line": 168
6402 }
6403 },
6404 {
6405 "defaultMessage": "!!!Support",
6406 "end": {
6407 "column": 3,
6408 "line": 175
6409 },
6410 "file": "src/lib/Menu.js",
6411 "id": "menu.help.support",
6412 "start": {
6413 "column": 11,
6414 "line": 172
6415 }
6416 },
6417 {
6418 "defaultMessage": "!!!Copy Debug Information",
6419 "end": {
6420 "column": 3,
6421 "line": 179
6422 },
6423 "file": "src/lib/Menu.js",
6424 "id": "menu.help.debugInfo",
6425 "start": {
6426 "column": 13,
6427 "line": 176
6428 }
6429 },
6430 {
6431 "defaultMessage": "!!!Publish Debug Information",
6432 "end": {
6433 "column": 3,
6434 "line": 183
6435 },
6436 "file": "src/lib/Menu.js",
6437 "id": "menu.help.publishDebugInfo",
6438 "start": {
6439 "column": 20,
6440 "line": 180
6441 }
6442 },
6443 {
6444 "defaultMessage": "!!!Ferdi Debug Information",
6445 "end": {
6446 "column": 3,
6447 "line": 187
6448 },
6449 "file": "src/lib/Menu.js",
6450 "id": "menu.help.debugInfoCopiedHeadline",
6451 "start": {
6452 "column": 27,
6453 "line": 184
6454 }
6455 },
6456 {
6457 "defaultMessage": "!!!Your Debug Information has been copied to your clipboard.",
6458 "end": {
6459 "column": 3,
6460 "line": 192
6461 },
6462 "file": "src/lib/Menu.js",
6463 "id": "menu.help.debugInfoCopiedBody",
6464 "start": {
6465 "column": 23,
6466 "line": 188
6467 }
6468 },
6469 {
6470 "defaultMessage": "!!!Unlock with Touch ID",
6471 "end": {
6472 "column": 3,
6473 "line": 196
6474 },
6475 "file": "src/lib/Menu.js",
6476 "id": "locked.touchId",
6477 "start": {
6478 "column": 11,
6479 "line": 193
6480 }
6481 },
6482 {
6483 "defaultMessage": "!!!unlock via Touch ID",
6484 "end": {
6485 "column": 3,
6486 "line": 200
6487 },
6488 "file": "src/lib/Menu.js",
6489 "id": "locked.touchIdPrompt",
6490 "start": {
6491 "column": 17,
6492 "line": 197
6493 }
6494 },
6495 {
6496 "defaultMessage": "!!!Terms of Service",
6497 "end": {
6498 "column": 3,
6499 "line": 204
6500 },
6501 "file": "src/lib/Menu.js",
6502 "id": "menu.help.tos",
6503 "start": {
6504 "column": 7,
6505 "line": 201
6506 }
6507 },
6508 {
6509 "defaultMessage": "!!!Privacy Statement",
6510 "end": {
6511 "column": 3,
6512 "line": 208
6513 },
6514 "file": "src/lib/Menu.js",
6515 "id": "menu.help.privacy",
6516 "start": {
6517 "column": 11,
6518 "line": 205
6519 }
6520 },
6521 {
6522 "defaultMessage": "!!!File",
6523 "end": {
6524 "column": 3,
6525 "line": 212
6526 },
6527 "file": "src/lib/Menu.js",
6528 "id": "menu.file",
6529 "start": {
6530 "column": 8,
6531 "line": 209
6532 }
6533 },
6534 {
6535 "defaultMessage": "!!!View",
6536 "end": {
6537 "column": 3,
6538 "line": 216
6539 },
6540 "file": "src/lib/Menu.js",
6541 "id": "menu.view",
6542 "start": {
6543 "column": 8,
6544 "line": 213
6545 }
6546 },
6547 {
6548 "defaultMessage": "!!!Services",
6549 "end": {
6550 "column": 3,
6551 "line": 220
6552 },
6553 "file": "src/lib/Menu.js",
6554 "id": "menu.services",
6555 "start": {
6556 "column": 12,
6557 "line": 217
6558 }
6559 },
6560 {
6561 "defaultMessage": "!!!Window",
6562 "end": {
6563 "column": 3,
6564 "line": 224
6565 },
6566 "file": "src/lib/Menu.js",
6567 "id": "menu.window",
6568 "start": {
6569 "column": 10,
6570 "line": 221
6571 }
6572 },
6573 {
6574 "defaultMessage": "!!!Help",
6575 "end": {
6576 "column": 3,
6577 "line": 228
6578 },
6579 "file": "src/lib/Menu.js",
6580 "id": "menu.help",
6581 "start": {
6582 "column": 8,
6583 "line": 225
6584 }
6585 },
6586 {
6587 "defaultMessage": "!!!About Ferdi",
6588 "end": {
6589 "column": 3,
6590 "line": 232
6591 },
6592 "file": "src/lib/Menu.js",
6593 "id": "menu.app.about",
6594 "start": {
6595 "column": 9,
6596 "line": 229
6597 }
6598 },
6599 {
6600 "defaultMessage": "!!!Check for updates",
6601 "end": {
6602 "column": 3,
6603 "line": 236
6604 },
6605 "file": "src/lib/Menu.js",
6606 "id": "menu.app.checkForUpdates",
6607 "start": {
6608 "column": 19,
6609 "line": 233
6610 }
6611 },
6612 {
6613 "defaultMessage": "!!!Hide",
6614 "end": {
6615 "column": 3,
6616 "line": 240
6617 },
6618 "file": "src/lib/Menu.js",
6619 "id": "menu.app.hide",
6620 "start": {
6621 "column": 8,
6622 "line": 237
6623 }
6624 },
6625 {
6626 "defaultMessage": "!!!Hide Others",
6627 "end": {
6628 "column": 3,
6629 "line": 244
6630 },
6631 "file": "src/lib/Menu.js",
6632 "id": "menu.app.hideOthers",
6633 "start": {
6634 "column": 14,
6635 "line": 241
6636 }
6637 },
6638 {
6639 "defaultMessage": "!!!Unhide",
6640 "end": {
6641 "column": 3,
6642 "line": 248
6643 },
6644 "file": "src/lib/Menu.js",
6645 "id": "menu.app.unhide",
6646 "start": {
6647 "column": 10,
6648 "line": 245
6649 }
6650 },
6651 {
6652 "defaultMessage": "!!!Auto-hide menu bar",
6653 "end": {
6654 "column": 3,
6655 "line": 252
6656 },
6657 "file": "src/lib/Menu.js",
6658 "id": "menu.app.autohideMenuBar",
6659 "start": {
6660 "column": 19,
6661 "line": 249
6662 }
6663 },
6664 {
6665 "defaultMessage": "!!!Add New Service...",
6666 "end": {
6667 "column": 3,
6668 "line": 256
6669 },
6670 "file": "src/lib/Menu.js",
6671 "id": "menu.services.addNewService",
6672 "start": {
6673 "column": 17,
6674 "line": 253
6675 }
6676 },
6677 {
6678 "defaultMessage": "!!!Add New Workspace...",
6679 "end": {
6680 "column": 3,
6681 "line": 260
6682 },
6683 "file": "src/lib/Menu.js",
6684 "id": "menu.workspaces.addNewWorkspace",
6685 "start": {
6686 "column": 19,
6687 "line": 257
6688 }
6689 },
6690 {
6691 "defaultMessage": "!!!Open workspace drawer",
6692 "end": {
6693 "column": 3,
6694 "line": 264
6695 },
6696 "file": "src/lib/Menu.js",
6697 "id": "menu.workspaces.openWorkspaceDrawer",
6698 "start": {
6699 "column": 23,
6700 "line": 261
6701 }
6702 },
6703 {
6704 "defaultMessage": "!!!Close workspace drawer",
6705 "end": {
6706 "column": 3,
6707 "line": 268
6708 },
6709 "file": "src/lib/Menu.js",
6710 "id": "menu.workspaces.closeWorkspaceDrawer",
6711 "start": {
6712 "column": 24,
6713 "line": 265
6714 }
6715 },
6716 {
6717 "defaultMessage": "!!!Activate next service...",
6718 "end": {
6719 "column": 3,
6720 "line": 272
6721 },
6722 "file": "src/lib/Menu.js",
6723 "id": "menu.services.setNextServiceActive",
6724 "start": {
6725 "column": 23,
6726 "line": 269
6727 }
6728 },
6729 {
6730 "defaultMessage": "!!!Activate previous service...",
6731 "end": {
6732 "column": 3,
6733 "line": 276
6734 },
6735 "file": "src/lib/Menu.js",
6736 "id": "menu.services.activatePreviousService",
6737 "start": {
6738 "column": 27,
6739 "line": 273
6740 }
6741 },
6742 {
6743 "defaultMessage": "!!!Disable notifications & audio",
6744 "end": {
6745 "column": 3,
6746 "line": 280
6747 },
6748 "file": "src/lib/Menu.js",
6749 "id": "sidebar.muteApp",
6750 "start": {
6751 "column": 11,
6752 "line": 277
6753 }
6754 },
6755 {
6756 "defaultMessage": "!!!Enable notifications & audio",
6757 "end": {
6758 "column": 3,
6759 "line": 284
6760 },
6761 "file": "src/lib/Menu.js",
6762 "id": "sidebar.unmuteApp",
6763 "start": {
6764 "column": 13,
6765 "line": 281
6766 }
6767 },
6768 {
6769 "defaultMessage": "!!!Workspaces",
6770 "end": {
6771 "column": 3,
6772 "line": 288
6773 },
6774 "file": "src/lib/Menu.js",
6775 "id": "menu.workspaces",
6776 "start": {
6777 "column": 14,
6778 "line": 285
6779 }
6780 },
6781 {
6782 "defaultMessage": "!!!Default",
6783 "end": {
6784 "column": 3,
6785 "line": 292
6786 },
6787 "file": "src/lib/Menu.js",
6788 "id": "menu.workspaces.defaultWorkspace",
6789 "start": {
6790 "column": 20,
6791 "line": 289
6792 }
6793 },
6794 {
6795 "defaultMessage": "!!!Todos",
6796 "end": {
6797 "column": 3,
6798 "line": 296
6799 },
6800 "file": "src/lib/Menu.js",
6801 "id": "menu.todos",
6802 "start": {
6803 "column": 9,
6804 "line": 293
6805 }
6806 },
6807 {
6808 "defaultMessage": "!!!Open Todos drawer",
6809 "end": {
6810 "column": 3,
6811 "line": 300
6812 },
6813 "file": "src/lib/Menu.js",
6814 "id": "menu.Todoss.openTodosDrawer",
6815 "start": {
6816 "column": 19,
6817 "line": 297
6818 }
6819 },
6820 {
6821 "defaultMessage": "!!!Close Todos drawer",
6822 "end": {
6823 "column": 3,
6824 "line": 304
6825 },
6826 "file": "src/lib/Menu.js",
6827 "id": "menu.Todoss.closeTodosDrawer",
6828 "start": {
6829 "column": 20,
6830 "line": 301
6831 }
6832 },
6833 {
6834 "defaultMessage": "!!!Enable Todos",
6835 "end": {
6836 "column": 3,
6837 "line": 308
6838 },
6839 "file": "src/lib/Menu.js",
6840 "id": "menu.todos.enableTodos",
6841 "start": {
6842 "column": 15,
6843 "line": 305
6844 }
6845 },
6846 {
6847 "defaultMessage": "!!!Home",
6848 "end": {
6849 "column": 3,
6850 "line": 312
6851 },
6852 "file": "src/lib/Menu.js",
6853 "id": "menu.services.goHome",
6854 "start": {
6855 "column": 17,
6856 "line": 309
6857 }
6858 }
6859 ],
6860 "path": "src/lib/Menu.json"
6861 }
6862] \ No newline at end of file
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json
index be9bbb961..158022419 100644
--- a/src/i18n/locales/en-US.json
+++ b/src/i18n/locales/en-US.json
@@ -1,6 +1,6 @@
1{ 1{
2 "app.errorHandler.action": "Reload", 2 "app.errorHandler.action": "Reload",
3 "app.errorHandler.headline": "Something went wrong", 3 "app.errorHandler.headline": "Something went wrong.",
4 "changeserver.customServerLabel": "Custom server", 4 "changeserver.customServerLabel": "Custom server",
5 "changeserver.headline": "Change server", 5 "changeserver.headline": "Change server",
6 "changeserver.label": "Server", 6 "changeserver.label": "Server",
@@ -10,7 +10,6 @@
10 "connectionLostBanner.informationLink": "What happened?", 10 "connectionLostBanner.informationLink": "What happened?",
11 "connectionLostBanner.message": "Oh no! Ferdi lost the connection to {name}.", 11 "connectionLostBanner.message": "Oh no! Ferdi lost the connection to {name}.",
12 "feature.basicAuth.signIn": "Sign In", 12 "feature.basicAuth.signIn": "Sign In",
13 "feature.debugger.title": "Publish debugging information",
14 "feature.nightlyBuilds.activate": "Activate", 13 "feature.nightlyBuilds.activate": "Activate",
15 "feature.nightlyBuilds.info": "Nightly builds are highly experimental versions of Ferdi that may contain unpolished or uncompleted features. These nightly builds are mainly used by developers to test their newly developed features and how they will perform in the final build. If you don't know what you are doing, we suggest not activating nightly builds.", 14 "feature.nightlyBuilds.info": "Nightly builds are highly experimental versions of Ferdi that may contain unpolished or uncompleted features. These nightly builds are mainly used by developers to test their newly developed features and how they will perform in the final build. If you don't know what you are doing, we suggest not activating nightly builds.",
16 "feature.nightlyBuilds.title": "Nightly Builds", 15 "feature.nightlyBuilds.title": "Nightly Builds",
@@ -24,7 +23,7 @@
24 "feature.quickSwitch.info": "Select a service with TAB, ↑ and ↓. Open a service with ENTER.", 23 "feature.quickSwitch.info": "Select a service with TAB, ↑ and ↓. Open a service with ENTER.",
25 "feature.quickSwitch.search": "Search...", 24 "feature.quickSwitch.search": "Search...",
26 "feature.quickSwitch.title": "QuickSwitch", 25 "feature.quickSwitch.title": "QuickSwitch",
27 "global.api.unhealthy": "Can't connect to Ferdi online services", 26 "global.api.unhealthy": "Can't connect to Ferdi Online Services",
28 "global.cancel": "Cancel", 27 "global.cancel": "Cancel",
29 "global.edit": "Edit", 28 "global.edit": "Edit",
30 "global.no": "No", 29 "global.no": "No",
@@ -45,9 +44,9 @@
45 "import.headline": "Import your Ferdi 4 services", 44 "import.headline": "Import your Ferdi 4 services",
46 "import.notSupportedHeadline": "Services not yet supported in Ferdi 5", 45 "import.notSupportedHeadline": "Services not yet supported in Ferdi 5",
47 "import.skip.label": "I want to add services manually", 46 "import.skip.label": "I want to add services manually",
48 "import.submit.label": "Import services", 47 "import.submit.label": "Import {count} services",
49 "infobar.authRequestFailed": "There were errors while trying to perform an authenticated request. Please try logging out and back in if this error persists.", 48 "infobar.authRequestFailed": "There were errors while trying to perform an authenticated request. Please try logging out and back in if this error persists.",
50 "infobar.buttonChangelog": "What is new?", 49 "infobar.buttonChangelog": "Changelog",
51 "infobar.buttonInstallUpdate": "Restart & install update", 50 "infobar.buttonInstallUpdate": "Restart & install update",
52 "infobar.buttonReloadServices": "Reload services", 51 "infobar.buttonReloadServices": "Reload services",
53 "infobar.hide": "Hide", 52 "infobar.hide": "Hide",
@@ -75,7 +74,7 @@
75 "login.email.label": "Email address", 74 "login.email.label": "Email address",
76 "login.headline": "Sign in", 75 "login.headline": "Sign in",
77 "login.invalidCredentials": "Email or password not valid", 76 "login.invalidCredentials": "Email or password not valid",
78 "login.link.password": "Reset password", 77 "login.link.password": "Forgot password",
79 "login.link.signup": "Create a free account", 78 "login.link.signup": "Create a free account",
80 "login.password.label": "Password", 79 "login.password.label": "Password",
81 "login.serverLogout": "Your session expired, please login again.", 80 "login.serverLogout": "Your session expired, please login again.",
@@ -117,10 +116,10 @@
117 "menu.help.support": "Support", 116 "menu.help.support": "Support",
118 "menu.help.tos": "Terms of Service", 117 "menu.help.tos": "Terms of Service",
119 "menu.services": "Services", 118 "menu.services": "Services",
120 "menu.services.activatePreviousService": "Activate previous service", 119 "menu.services.activatePreviousService": "Activate previous service...",
121 "menu.services.addNewService": "Add New Service", 120 "menu.services.addNewService": "Add New Service...",
122 "menu.services.goHome": "Home", 121 "menu.services.goHome": "Home",
123 "menu.services.setNextServiceActive": "Activate next service", 122 "menu.services.setNextServiceActive": "Activate next service...",
124 "menu.todos": "Todos", 123 "menu.todos": "Todos",
125 "menu.todos.enableTodos": "Enable Todos", 124 "menu.todos.enableTodos": "Enable Todos",
126 "menu.view": "View", 125 "menu.view": "View",
@@ -145,14 +144,14 @@
145 "menu.workspaces": "Workspaces", 144 "menu.workspaces": "Workspaces",
146 "menu.workspaces.addNewWorkspace": "Add New Workspace...", 145 "menu.workspaces.addNewWorkspace": "Add New Workspace...",
147 "menu.workspaces.closeWorkspaceDrawer": "Close workspace drawer", 146 "menu.workspaces.closeWorkspaceDrawer": "Close workspace drawer",
148 "menu.workspaces.defaultWorkspace": "All services", 147 "menu.workspaces.defaultWorkspace": "Default",
149 "menu.workspaces.openWorkspaceDrawer": "Open workspace drawer", 148 "menu.workspaces.openWorkspaceDrawer": "Open workspace drawer",
150 "password.email.label": "Email address", 149 "password.email.label": "Email address",
151 "password.headline": "Reset password", 150 "password.headline": "Forgot password",
152 "password.link.login": "Sign in to your account", 151 "password.link.login": "Sign in to your account",
153 "password.link.signup": "Create a free account", 152 "password.link.signup": "Create a free account",
154 "password.noUser": "No user with that email address was found", 153 "password.noUser": "No user affiliated with that email address",
155 "password.successInfo": "Please check your email", 154 "password.successInfo": "Your new password was sent to your email address",
156 "pricing.features.accountSync": "Account Synchronisation", 155 "pricing.features.accountSync": "Account Synchronisation",
157 "pricing.features.customWebsites": "Add Custom Websites", 156 "pricing.features.customWebsites": "Add Custom Websites",
158 "pricing.features.desktopNotifications": "Desktop Notifications", 157 "pricing.features.desktopNotifications": "Desktop Notifications",
@@ -173,7 +172,7 @@
173 "service.errorHandler.action": "Reload {name}", 172 "service.errorHandler.action": "Reload {name}",
174 "service.errorHandler.editAction": "Edit {name}", 173 "service.errorHandler.editAction": "Edit {name}",
175 "service.errorHandler.headline": "Oh no!", 174 "service.errorHandler.headline": "Oh no!",
176 "service.errorHandler.message": "Error", 175 "service.errorHandler.message": "Error:",
177 "service.errorHandler.text": "{name} has failed to load.", 176 "service.errorHandler.text": "{name} has failed to load.",
178 "service.webviewLoader.loading": "Loading {service}", 177 "service.webviewLoader.loading": "Loading {service}",
179 "services.getStarted": "Get started", 178 "services.getStarted": "Get started",
@@ -181,7 +180,7 @@
181 "services.serverInfo": "Optionally, you can change your Ferdi server by clicking the cog in the bottom left corner. If you are switching over (from one of the hosted servers) to using Ferdi without an account, please be informed that you can export your data from that server and subsequently import it using the Help menu to resurrect all your workspaces and configured services!", 180 "services.serverInfo": "Optionally, you can change your Ferdi server by clicking the cog in the bottom left corner. If you are switching over (from one of the hosted servers) to using Ferdi without an account, please be informed that you can export your data from that server and subsequently import it using the Help menu to resurrect all your workspaces and configured services!",
182 "services.serverless": "Use Ferdi without an Account", 181 "services.serverless": "Use Ferdi without an Account",
183 "services.welcome": "Welcome to Ferdi", 182 "services.welcome": "Welcome to Ferdi",
184 "settings.account.account.editButton": "Edit account", 183 "settings.account.account.editButton": "Edit Account",
185 "settings.account.accountUnavailable": "Account is unavailable", 184 "settings.account.accountUnavailable": "Account is unavailable",
186 "settings.account.accountUnavailableInfo": "You are using Ferdi without an account. If you want to use Ferdi with an account and keep your services synchronized across installations, please select a server in the Settings tab then login.", 185 "settings.account.accountUnavailableInfo": "You are using Ferdi without an account. If you want to use Ferdi with an account and keep your services synchronized across installations, please select a server in the Settings tab then login.",
187 "settings.account.buttonSave": "Update profile", 186 "settings.account.buttonSave": "Update profile",
@@ -189,16 +188,16 @@
189 "settings.account.deleteEmailSent": "You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!", 188 "settings.account.deleteEmailSent": "You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!",
190 "settings.account.deleteInfo": "If you don't need your Ferdi account any longer, you can delete your account and all related data here.", 189 "settings.account.deleteInfo": "If you don't need your Ferdi account any longer, you can delete your account and all related data here.",
191 "settings.account.headline": "Account", 190 "settings.account.headline": "Account",
192 "settings.account.headlineAccount": "Account information", 191 "settings.account.headlineAccount": "Account Information",
193 "settings.account.headlineDangerZone": "Danger Zone", 192 "settings.account.headlineDangerZone": "!!Danger Zone",
194 "settings.account.headlineInvoices": "Invoices", 193 "settings.account.headlineInvoices": "!!Invoices",
195 "settings.account.headlinePassword": "Change password", 194 "settings.account.headlinePassword": "Change Password",
196 "settings.account.headlineProfile": "Update profile", 195 "settings.account.headlineProfile": "Update Profile",
197 "settings.account.successInfo": "Your changes have been saved", 196 "settings.account.successInfo": "Your changes have been saved",
198 "settings.account.tryReloadServices": "Try again", 197 "settings.account.tryReloadServices": "Try again",
199 "settings.account.tryReloadUserInfoRequest": "Try again", 198 "settings.account.tryReloadUserInfoRequest": "Try again",
200 "settings.account.userInfoRequestFailed": "Could not load user information", 199 "settings.account.userInfoRequestFailed": "Could not load user information",
201 "settings.account.yourLicense": "Your Ferdi License", 200 "settings.account.yourLicense": "Your Ferdi License:",
202 "settings.app.accentColorInfo": "Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})", 201 "settings.app.accentColorInfo": "Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})",
203 "settings.app.buttonClearAllCache": "Clear cache", 202 "settings.app.buttonClearAllCache": "Clear cache",
204 "settings.app.buttonInstallUpdate": "Restart & install update", 203 "settings.app.buttonInstallUpdate": "Restart & install update",
@@ -219,13 +218,13 @@
219 "settings.app.form.clipboardNotifications": "Don't show notifications for clipboard events", 218 "settings.app.form.clipboardNotifications": "Don't show notifications for clipboard events",
220 "settings.app.form.closeToSystemTray": "Close Ferdi to system tray", 219 "settings.app.form.closeToSystemTray": "Close Ferdi to system tray",
221 "settings.app.form.confirmOnQuit": "Confirm when quitting Ferdi", 220 "settings.app.form.confirmOnQuit": "Confirm when quitting Ferdi",
222 "settings.app.form.customTodoServer": "Custom Todo Server", 221 "settings.app.form.customTodoServer": "Custom TodoServer",
223 "settings.app.form.darkMode": "Enable dark mode", 222 "settings.app.form.darkMode": "Dark Mode",
224 "settings.app.form.enableGPUAcceleration": "Enable GPU Acceleration", 223 "settings.app.form.enableGPUAcceleration": "Enable GPU Acceleration",
225 "settings.app.form.enableLock": "Enable Password Lock", 224 "settings.app.form.enableLock": "Enable Password Lock",
226 "settings.app.form.enableMenuBar": "Always show Ferdi in Menu Bar", 225 "settings.app.form.enableMenuBar": "Always show Ferdi in Menu Bar",
227 "settings.app.form.enableSpellchecking": "Enable spell checking", 226 "settings.app.form.enableSpellchecking": "Enable spell checking",
228 "settings.app.form.enableSystemTray": "Show Ferdi in system tray", 227 "settings.app.form.enableSystemTray": "Always show Ferdi in System Tray",
229 "settings.app.form.enableTodos": "Enable Ferdi Todos", 228 "settings.app.form.enableTodos": "Enable Ferdi Todos",
230 "settings.app.form.hibernateOnStartup": "Keep services in hibernation on startup", 229 "settings.app.form.hibernateOnStartup": "Keep services in hibernation on startup",
231 "settings.app.form.hibernationStrategy": "Hibernation strategy", 230 "settings.app.form.hibernationStrategy": "Hibernation strategy",
@@ -253,7 +252,7 @@
253 "settings.app.form.showMessagesBadgesWhenMuted": "Show unread message badge when notifications are disabled", 252 "settings.app.form.showMessagesBadgesWhenMuted": "Show unread message badge when notifications are disabled",
254 "settings.app.form.startMinimized": "Start minimized", 253 "settings.app.form.startMinimized": "Start minimized",
255 "settings.app.form.universalDarkMode": "Enable universal Dark Mode", 254 "settings.app.form.universalDarkMode": "Enable universal Dark Mode",
256 "settings.app.form.useTouchIdToUnlock": "Allow using TouchID to unlock Ferdi", 255 "settings.app.form.useTouchIdToUnlock": "Allow using Touch ID to unlock",
257 "settings.app.form.useVerticalStyle": "Use horizontal style", 256 "settings.app.form.useVerticalStyle": "Use horizontal style",
258 "settings.app.form.wakeUpStrategy": "Wake up strategy", 257 "settings.app.form.wakeUpStrategy": "Wake up strategy",
259 "settings.app.headlineAdvanced": "Advanced", 258 "settings.app.headlineAdvanced": "Advanced",
@@ -265,9 +264,9 @@
265 "settings.app.hibernateInfo": "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.", 264 "settings.app.hibernateInfo": "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.",
266 "settings.app.inactivityLockInfo": "Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable", 265 "settings.app.inactivityLockInfo": "Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable",
267 "settings.app.languageDisclaimer": "Official translations are English & German. All other languages are community based translations.", 266 "settings.app.languageDisclaimer": "Official translations are English & German. All other languages are community based translations.",
268 "settings.app.lockInfo": "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}.", 267 "settings.app.lockInfo": "Password Lock allows you to keep your messages protected. Using 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}.",
269 "settings.app.lockedPassword": "Password", 268 "settings.app.lockedPassword": "Password",
270 "settings.app.lockedPasswordInfo": "Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdi.", 269 "settings.app.lockedPasswordInfo": "Please make sure to set a password you'll remember. If you loose this password, you will have to reinstall Ferdi.",
271 "settings.app.restartRequired": "Changes require restart", 270 "settings.app.restartRequired": "Changes require restart",
272 "settings.app.scheduledDNDInfo": "Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.", 271 "settings.app.scheduledDNDInfo": "Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.",
273 "settings.app.scheduledDNDTimeInfo": "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.", 272 "settings.app.scheduledDNDTimeInfo": "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.",
@@ -275,7 +274,7 @@
275 "settings.app.spellCheckerLanguageInfo": "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.", 274 "settings.app.spellCheckerLanguageInfo": "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.",
276 "settings.app.subheadlineCache": "Cache", 275 "settings.app.subheadlineCache": "Cache",
277 "settings.app.subheadlineFerdiProfile": "Ferdi Profile", 276 "settings.app.subheadlineFerdiProfile": "Ferdi Profile",
278 "settings.app.todoServerInfo": "This server will be used for the \"Ferdi Todo\" feature.", 277 "settings.app.todoServerInfo": "This server will be used for the \"Franz Todo\" feature. (default: https://app.franztodos.com)",
279 "settings.app.translationHelp": "Help us to translate Ferdi into your language.", 278 "settings.app.translationHelp": "Help us to translate Ferdi into your language.",
280 "settings.app.universalDarkModeInfo": "Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.", 279 "settings.app.universalDarkModeInfo": "Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.",
281 "settings.app.updateStatusAvailable": "Update available, downloading...", 280 "settings.app.updateStatusAvailable": "Update available, downloading...",
@@ -294,12 +293,12 @@
294 "settings.recipes.customService.headline.communityRecipes": "Community 3rd Party Recipes", 293 "settings.recipes.customService.headline.communityRecipes": "Community 3rd Party Recipes",
295 "settings.recipes.customService.headline.customRecipes": "Custom 3rd Party Recipes", 294 "settings.recipes.customService.headline.customRecipes": "Custom 3rd Party Recipes",
296 "settings.recipes.customService.headline.devRecipes": "Your Development Service Recipes", 295 "settings.recipes.customService.headline.devRecipes": "Your Development Service Recipes",
297 "settings.recipes.customService.intro": "To add a custom service, copy the service recipe to:", 296 "settings.recipes.customService.intro": "To add a custom service, copy the recipe folder into:",
298 "settings.recipes.customService.openDevDocs": "Developer Documentation", 297 "settings.recipes.customService.openDevDocs": "Developer Documentation",
299 "settings.recipes.customService.openFolder": "Open folder", 298 "settings.recipes.customService.openFolder": "Open directory",
300 "settings.recipes.headline": "Available services", 299 "settings.recipes.headline": "Available Services",
301 "settings.recipes.missingService": "Missing a service?", 300 "settings.recipes.missingService": "Missing a service?",
302 "settings.recipes.nothingFound": "Sorry, but no service matched your search term - but you can still probably add it using the \"Custom Website\" option. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.", 301 "settings.recipes.nothingFound": "Sorry, but no service matched your search term. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.",
303 "settings.recipes.servicesSuccessfulAddedInfo": "Service successfully added", 302 "settings.recipes.servicesSuccessfulAddedInfo": "Service successfully added",
304 "settings.searchService": "Search service", 303 "settings.searchService": "Search service",
305 "settings.service.error.goBack": "Back to services", 304 "settings.service.error.goBack": "Back to services",
@@ -307,18 +306,18 @@
307 "settings.service.error.message": "Could not load service recipe.", 306 "settings.service.error.message": "Could not load service recipe.",
308 "settings.service.form.addServiceHeadline": "Add {name}", 307 "settings.service.form.addServiceHeadline": "Add {name}",
309 "settings.service.form.availableServices": "Available services", 308 "settings.service.form.availableServices": "Available services",
310 "settings.service.form.customUrl": "Custom server", 309 "settings.service.form.customUrl": "Service URL",
311 "settings.service.form.customUrlValidationError": "Could not validate custom {name} server.", 310 "settings.service.form.customUrlValidationError": "Could not validate custom {name} server.",
312 "settings.service.form.darkReaderBrightness": "Dark Reader Brightness", 311 "settings.service.form.darkReaderBrightness": "Dark Reader Brightness",
313 "settings.service.form.darkReaderContrast": "Dark Reader Contrast", 312 "settings.service.form.darkReaderContrast": "Dark Reader Contrast",
314 "settings.service.form.darkReaderSepia": "Dark Reader Sepia", 313 "settings.service.form.darkReaderSepia": "Dark Reader Sepia",
315 "settings.service.form.deleteButton": "Delete service", 314 "settings.service.form.deleteButton": "Delete Service",
316 "settings.service.form.editServiceHeadline": "Edit {name}", 315 "settings.service.form.editServiceHeadline": "Edit {name}",
317 "settings.service.form.enableAudio": "Enable audio", 316 "settings.service.form.enableAudio": "Enable audio",
318 "settings.service.form.enableBadge": "Show unread message badges", 317 "settings.service.form.enableBadge": "Show unread message badges",
319 "settings.service.form.enableDarkMode": "Enable Dark Mode", 318 "settings.service.form.enableDarkMode": "Enable Dark Mode",
320 "settings.service.form.enableHibernation": "Enable hibernation", 319 "settings.service.form.enableHibernation": "Enable hibernation",
321 "settings.service.form.enableNotification": "Enable notifications", 320 "settings.service.form.enableNotification": "Enable Notifications",
322 "settings.service.form.enableService": "Enable service", 321 "settings.service.form.enableService": "Enable service",
323 "settings.service.form.headlineBadges": "Unread message badges", 322 "settings.service.form.headlineBadges": "Unread message badges",
324 "settings.service.form.headlineDarkReaderSettings": "Dark Reader Settings", 323 "settings.service.form.headlineDarkReaderSettings": "Dark Reader Settings",
@@ -337,12 +336,12 @@
337 "settings.service.form.openUserJs": "Open user.js", 336 "settings.service.form.openUserJs": "Open user.js",
338 "settings.service.form.proxy.headline": "HTTP/HTTPS Proxy Settings", 337 "settings.service.form.proxy.headline": "HTTP/HTTPS Proxy Settings",
339 "settings.service.form.proxy.host": "Proxy Host/IP", 338 "settings.service.form.proxy.host": "Proxy Host/IP",
340 "settings.service.form.proxy.info": "Proxy settings will not synced with the Ferdi servers.", 339 "settings.service.form.proxy.info": "Proxy settings will not be synchronized with the Ferdi servers.",
341 "settings.service.form.proxy.isEnabled": "Use Proxy", 340 "settings.service.form.proxy.isEnabled": "Use Proxy",
342 "settings.service.form.proxy.password": "Password (optional)", 341 "settings.service.form.proxy.password": "Password",
343 "settings.service.form.proxy.port": "Port", 342 "settings.service.form.proxy.port": "Port",
344 "settings.service.form.proxy.restartInfo": "Please restart Ferdi after changing proxy Settings.", 343 "settings.service.form.proxy.restartInfo": "Please restart Ferdi after changing proxy Settings.",
345 "settings.service.form.proxy.user": "User (optional)", 344 "settings.service.form.proxy.user": "User",
346 "settings.service.form.recipeFileInfo": "Your user files will be inserted into the webpage so you can customize services in any way you like. User files are only stored locally and are not transferred to other computers using the same account.", 345 "settings.service.form.recipeFileInfo": "Your user files will be inserted into the webpage so you can customize services in any way you like. User files are only stored locally and are not transferred to other computers using the same account.",
347 "settings.service.form.saveButton": "Save service", 346 "settings.service.form.saveButton": "Save service",
348 "settings.service.form.tabHosted": "Hosted", 347 "settings.service.form.tabHosted": "Hosted",
@@ -362,12 +361,12 @@
362 "settings.supportFerdi.aboutIntro": "<p>Ferdi is an open-source and a community-lead application.</p><p>Thanks to the people who make this possbile:</p>", 361 "settings.supportFerdi.aboutIntro": "<p>Ferdi is an open-source and a community-lead application.</p><p>Thanks to the people who make this possbile:</p>",
363 "settings.supportFerdi.bannerText": "Do you want to help us improve Ferdi?", 362 "settings.supportFerdi.bannerText": "Do you want to help us improve Ferdi?",
364 "settings.supportFerdi.headline": "About Ferdi", 363 "settings.supportFerdi.headline": "About Ferdi",
365 "settings.supportFerdi.openSurvey": "Open survey", 364 "settings.supportFerdi.openSurvey": "Open Survey",
366 "settings.supportFerdi.textDonation": "If you feel like supporting Ferdi development with a donation, you can do so on both,", 365 "settings.supportFerdi.textDonation": "If you feel like supporting Ferdi development with a donation, you can do so on both,",
367 "settings.supportFerdi.textDonationAnd": "and", 366 "settings.supportFerdi.textDonationAnd": "and",
368 "settings.supportFerdi.textExpenses": "While volunteers do most of the work, we still need to pay for servers and certificates. As a community, we are fully transparent on funds we collect and spend - see our", 367 "settings.supportFerdi.textExpenses": "While volunteers do most of the work, we still need to pay for servers and certificates. As a community, we are fully transparent on funds we collect and spend - see our",
369 "settings.supportFerdi.textGitHubSponsors": "GitHub Sponsors", 368 "settings.supportFerdi.textGitHubSponsors": "GitHub Sponsors",
370 "settings.supportFerdi.textListContributors": "Full list of contributors", 369 "settings.supportFerdi.textListContributors": "Full list of contributor",
371 "settings.supportFerdi.textListContributorsHere": "here", 370 "settings.supportFerdi.textListContributorsHere": "here",
372 "settings.supportFerdi.textOpenCollective": "Open Collective", 371 "settings.supportFerdi.textOpenCollective": "Open Collective",
373 "settings.supportFerdi.textSupportWelcome": "Support is always welcome. You can find a list of the help we need", 372 "settings.supportFerdi.textSupportWelcome": "Support is always welcome. You can find a list of the help we need",
@@ -377,7 +376,7 @@
377 "settings.team.contentHeadline": "Franz Team Management", 376 "settings.team.contentHeadline": "Franz Team Management",
378 "settings.team.copy": "Franz's Team Management allows you to manage Franz Subscriptions for multiple users. Please keep in mind that having a Franz Premium subscription will give you no advantages in using Ferdi: The only reason you still have access to Team Management is so you can manage your legacy Franz Teams and so that you don't loose any functionality in managing your account.", 377 "settings.team.copy": "Franz's Team Management allows you to manage Franz Subscriptions for multiple users. Please keep in mind that having a Franz Premium subscription will give you no advantages in using Ferdi: The only reason you still have access to Team Management is so you can manage your legacy Franz Teams and so that you don't loose any functionality in managing your account.",
379 "settings.team.headline": "Team", 378 "settings.team.headline": "Team",
380 "settings.team.intro": "You are currently using Franz Servers, which is why you have access to Team Management.", 379 "settings.team.intro": "Your are currently using Franz Servers, which is why you have access to Team Management.",
381 "settings.team.manageAction": "Manage your Team on meetfranz.com", 380 "settings.team.manageAction": "Manage your Team on meetfranz.com",
382 "settings.team.teamsUnavailable": "Teams are unavailable", 381 "settings.team.teamsUnavailable": "Teams are unavailable",
383 "settings.team.teamsUnavailableInfo": "Teams are currently only available when using the Franz Server and after paying for Franz Professional. Please change your server to https://api.franzinfra.com to use teams.", 382 "settings.team.teamsUnavailableInfo": "Teams are currently only available when using the Franz Server and after paying for Franz Professional. Please change your server to https://api.franzinfra.com to use teams.",
@@ -387,8 +386,8 @@
387 "settings.user.form.accountType.non-profit": "Non-Profit", 386 "settings.user.form.accountType.non-profit": "Non-Profit",
388 "settings.user.form.currentPassword": "Current password", 387 "settings.user.form.currentPassword": "Current password",
389 "settings.user.form.email": "Email", 388 "settings.user.form.email": "Email",
390 "settings.user.form.firstname": "First Name", 389 "settings.user.form.firstname": "Firstname",
391 "settings.user.form.lastname": "Last Name", 390 "settings.user.form.lastname": "Lastname",
392 "settings.user.form.newPassword": "New password", 391 "settings.user.form.newPassword": "New password",
393 "settings.workspace.add.form.name": "Name", 392 "settings.workspace.add.form.name": "Name",
394 "settings.workspace.add.form.submitButton": "Create workspace", 393 "settings.workspace.add.form.submitButton": "Create workspace",
@@ -405,7 +404,7 @@
405 "settings.workspaces.tryReloadWorkspaces": "Try again", 404 "settings.workspaces.tryReloadWorkspaces": "Try again",
406 "settings.workspaces.updatedInfo": "Your changes have been saved", 405 "settings.workspaces.updatedInfo": "Your changes have been saved",
407 "settings.workspaces.workspaceFeatureHeadline": "Less is More: Introducing Ferdi Workspaces", 406 "settings.workspaces.workspaceFeatureHeadline": "Less is More: Introducing Ferdi Workspaces",
408 "settings.workspaces.workspaceFeatureInfo": "Ferdi Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.", 407 "settings.workspaces.workspaceFeatureInfo": "Info about workspace feature",
409 "settings.workspaces.workspacesRequestFailed": "Could not load your workspaces", 408 "settings.workspaces.workspacesRequestFailed": "Could not load your workspaces",
410 "setupAssistant.headline": "Let's get started", 409 "setupAssistant.headline": "Let's get started",
411 "setupAssistant.subheadline": "Choose from our most used services and get back on top of your messaging now.", 410 "setupAssistant.subheadline": "Choose from our most used services and get back on top of your messaging now.",
@@ -420,9 +419,9 @@
420 "sidebar.unmuteApp": "Enable notifications & audio", 419 "sidebar.unmuteApp": "Enable notifications & audio",
421 "signup.email.label": "Email address", 420 "signup.email.label": "Email address",
422 "signup.emailDuplicate": "A user with that email address already exists", 421 "signup.emailDuplicate": "A user with that email address already exists",
423 "signup.firstname.label": "First Name", 422 "signup.firstname.label": "Firstname",
424 "signup.headline": "Sign up", 423 "signup.headline": "Sign up",
425 "signup.lastname.label": "Last Name", 424 "signup.lastname.label": "Lastname",
426 "signup.legal.info": "By creating a Ferdi account you accept the", 425 "signup.legal.info": "By creating a Ferdi account you accept the",
427 "signup.legal.privacy": "Privacy Statement", 426 "signup.legal.privacy": "Privacy Statement",
428 "signup.legal.terms": "Terms of service", 427 "signup.legal.terms": "Terms of service",
@@ -430,23 +429,23 @@
430 "signup.password.label": "Password", 429 "signup.password.label": "Password",
431 "signup.submit.label": "Create account", 430 "signup.submit.label": "Create account",
432 "tabs.item.confirmDeleteService": "Do you really want to delete the {serviceName} service?", 431 "tabs.item.confirmDeleteService": "Do you really want to delete the {serviceName} service?",
433 "tabs.item.deleteService": "Delete service", 432 "tabs.item.deleteService": "Delete Service",
434 "tabs.item.disableAudio": "Disable audio", 433 "tabs.item.disableAudio": "Disable audio",
435 "tabs.item.disableDarkMode": "Disable Dark mode", 434 "tabs.item.disableDarkMode": "Disable Dark mode",
436 "tabs.item.disableNotifications": "Disable notifications", 435 "tabs.item.disableNotifications": "Disable notifications",
437 "tabs.item.disableService": "Disable service", 436 "tabs.item.disableService": "Disable Service",
438 "tabs.item.enableAudio": "Enable audio", 437 "tabs.item.enableAudio": "Enable audio",
439 "tabs.item.enableDarkMode": "Enable Dark mode", 438 "tabs.item.enableDarkMode": "Enable Dark mode",
440 "tabs.item.enableNotification": "Enable notifications", 439 "tabs.item.enableNotification": "Enable notifications",
441 "tabs.item.enableService": "Enable service", 440 "tabs.item.enableService": "Enable Service",
442 "tabs.item.hibernateService": "Hibernate service", 441 "tabs.item.hibernateService": "Hibernate Service",
443 "tabs.item.reload": "Reload", 442 "tabs.item.reload": "Reload",
444 "tabs.item.wakeUpService": "Wake up service", 443 "tabs.item.wakeUpService": "Wake Up Service",
445 "validation.email": "{field} is not valid", 444 "validation.email": "Email not valid",
446 "validation.minLength": "{field} should be at least {length} characters long", 445 "validation.minLength": "Too few characters",
447 "validation.oneRequired": "At least one is required", 446 "validation.oneRequired": "At least one is required",
448 "validation.required": "{field} is required", 447 "validation.required": "Field is required",
449 "validation.url": "{field} is not a valid URL", 448 "validation.url": "Not a valid URL",
450 "webControls.back": "Back", 449 "webControls.back": "Back",
451 "webControls.forward": "Forward", 450 "webControls.forward": "Forward",
452 "webControls.goHome": "Home", 451 "webControls.goHome": "Home",
@@ -454,12 +453,12 @@
454 "webControls.reload": "Reload", 453 "webControls.reload": "Reload",
455 "welcome.loginButton": "Login to your account", 454 "welcome.loginButton": "Login to your account",
456 "welcome.signupButton": "Create a free account", 455 "welcome.signupButton": "Create a free account",
457 "workspaceDrawer.addNewWorkspaceLabel": "Add new workspace", 456 "workspaceDrawer.addNewWorkspaceLabel": "add new workspace",
458 "workspaceDrawer.allServices": "All services", 457 "workspaceDrawer.allServices": "All services",
459 "workspaceDrawer.headline": "Workspaces", 458 "workspaceDrawer.headline": "Workspaces",
460 "workspaceDrawer.item.contextMenuEdit": "edit", 459 "workspaceDrawer.item.contextMenuEdit": "edit",
461 "workspaceDrawer.item.noServicesAddedYet": "No services added yet", 460 "workspaceDrawer.item.noServicesAddedYet": "No services added yet",
462 "workspaceDrawer.workspaceFeatureInfo": "<p>Ferdi Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.</p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.</p>", 461 "workspaceDrawer.workspaceFeatureInfo": "Info about workspace feature",
463 "workspaceDrawer.workspacesSettingsTooltip": "Edit workspaces settings", 462 "workspaceDrawer.workspacesSettingsTooltip": "Workspaces settings",
464 "workspaces.switchingIndicator.switchingTo": "Switching to" 463 "workspaces.switchingIndicator.switchingTo": "Switching to"
465} 464}
diff --git a/src/i18n/manage-translations.js b/src/i18n/manage-translations.js
deleted file mode 100644
index ee64c9c09..000000000
--- a/src/i18n/manage-translations.js
+++ /dev/null
@@ -1,9 +0,0 @@
1require('@babel/register');
2const manageTranslations = require('react-intl-translations-manager').default;
3
4manageTranslations({
5 messagesDirectory: 'src/i18n/messages',
6 translationsDirectory: 'src/i18n/locales',
7 singleMessagesFile: true,
8 languages: ['en-US'],
9});
diff --git a/src/i18n/messages/src/components/AppUpdateInfoBar.json b/src/i18n/messages/src/components/AppUpdateInfoBar.json
deleted file mode 100644
index b99eaff67..000000000
--- a/src/i18n/messages/src/components/AppUpdateInfoBar.json
+++ /dev/null
@@ -1,41 +0,0 @@
1[
2 {
3 "id": "infobar.updateAvailable",
4 "defaultMessage": "!!!A new update for Ferdi is available.",
5 "file": "src/components/AppUpdateInfoBar.js",
6 "start": {
7 "line": 10,
8 "column": 19
9 },
10 "end": {
11 "line": 13,
12 "column": 3
13 }
14 },
15 {
16 "id": "infobar.buttonChangelog",
17 "defaultMessage": "!!!Changelog",
18 "file": "src/components/AppUpdateInfoBar.js",
19 "start": {
20 "line": 14,
21 "column": 13
22 },
23 "end": {
24 "line": 17,
25 "column": 3
26 }
27 },
28 {
29 "id": "infobar.buttonInstallUpdate",
30 "defaultMessage": "!!!Restart & install update",
31 "file": "src/components/AppUpdateInfoBar.js",
32 "start": {
33 "line": 18,
34 "column": 23
35 },
36 "end": {
37 "line": 21,
38 "column": 3
39 }
40 }
41] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/ChangeServer.json b/src/i18n/messages/src/components/auth/ChangeServer.json
deleted file mode 100644
index 87e0b5857..000000000
--- a/src/i18n/messages/src/components/auth/ChangeServer.json
+++ /dev/null
@@ -1,67 +0,0 @@
1[
2 {
3 "id": "changeserver.headline",
4 "defaultMessage": "!!!Change server",
5 "file": "src/components/auth/ChangeServer.js",
6 "start": {
7 "line": 15,
8 "column": 12
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 },
15 {
16 "id": "changeserver.label",
17 "defaultMessage": "!!!Server",
18 "file": "src/components/auth/ChangeServer.js",
19 "start": {
20 "line": 19,
21 "column": 9
22 },
23 "end": {
24 "line": 22,
25 "column": 3
26 }
27 },
28 {
29 "id": "changeserver.warning",
30 "defaultMessage": "!!!Extra settings offered by Ferdi will not be saved",
31 "file": "src/components/auth/ChangeServer.js",
32 "start": {
33 "line": 23,
34 "column": 11
35 },
36 "end": {
37 "line": 26,
38 "column": 3
39 }
40 },
41 {
42 "id": "changeserver.customServerLabel",
43 "defaultMessage": "!!!Custom server",
44 "file": "src/components/auth/ChangeServer.js",
45 "start": {
46 "line": 27,
47 "column": 21
48 },
49 "end": {
50 "line": 30,
51 "column": 3
52 }
53 },
54 {
55 "id": "changeserver.urlError",
56 "defaultMessage": "!!!Enter a valid URL",
57 "file": "src/components/auth/ChangeServer.js",
58 "start": {
59 "line": 31,
60 "column": 12
61 },
62 "end": {
63 "line": 34,
64 "column": 3
65 }
66 }
67] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/Import.json b/src/i18n/messages/src/components/auth/Import.json
deleted file mode 100644
index 98ae2e61f..000000000
--- a/src/i18n/messages/src/components/auth/Import.json
+++ /dev/null
@@ -1,54 +0,0 @@
1[
2 {
3 "id": "import.headline",
4 "defaultMessage": "!!!Import your Ferdi 4 services",
5 "file": "src/components/auth/Import.js",
6 "start": {
7 "line": 13,
8 "column": 12
9 },
10 "end": {
11 "line": 16,
12 "column": 3
13 }
14 },
15 {
16 "id": "import.notSupportedHeadline",
17 "defaultMessage": "!!!Services not yet supported in Ferdi 5",
18 "file": "src/components/auth/Import.js",
19 "start": {
20 "line": 17,
21 "column": 24
22 },
23 "end": {
24 "line": 20,
25 "column": 3
26 }
27 },
28 {
29 "id": "import.submit.label",
30 "defaultMessage": "!!!Import {count} services",
31 "file": "src/components/auth/Import.js",
32 "start": {
33 "line": 21,
34 "column": 21
35 },
36 "end": {
37 "line": 24,
38 "column": 3
39 }
40 },
41 {
42 "id": "import.skip.label",
43 "defaultMessage": "!!!I want to add services manually",
44 "file": "src/components/auth/Import.js",
45 "start": {
46 "line": 25,
47 "column": 19
48 },
49 "end": {
50 "line": 28,
51 "column": 3
52 }
53 }
54] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/Invite.json b/src/i18n/messages/src/components/auth/Invite.json
deleted file mode 100644
index 57c9bddcf..000000000
--- a/src/i18n/messages/src/components/auth/Invite.json
+++ /dev/null
@@ -1,93 +0,0 @@
1[
2 {
3 "id": "settings.invite.headline",
4 "defaultMessage": "!!!Invite Friends",
5 "file": "src/components/auth/Invite.js",
6 "start": {
7 "line": 16,
8 "column": 20
9 },
10 "end": {
11 "line": 19,
12 "column": 3
13 }
14 },
15 {
16 "id": "invite.headline.friends",
17 "defaultMessage": "!!!Invite 3 of your friends or colleagues",
18 "file": "src/components/auth/Invite.js",
19 "start": {
20 "line": 20,
21 "column": 12
22 },
23 "end": {
24 "line": 23,
25 "column": 3
26 }
27 },
28 {
29 "id": "invite.name.label",
30 "defaultMessage": "!!!Name",
31 "file": "src/components/auth/Invite.js",
32 "start": {
33 "line": 24,
34 "column": 13
35 },
36 "end": {
37 "line": 27,
38 "column": 3
39 }
40 },
41 {
42 "id": "invite.email.label",
43 "defaultMessage": "!!!Email address",
44 "file": "src/components/auth/Invite.js",
45 "start": {
46 "line": 28,
47 "column": 14
48 },
49 "end": {
50 "line": 31,
51 "column": 3
52 }
53 },
54 {
55 "id": "invite.submit.label",
56 "defaultMessage": "!!!Send invites",
57 "file": "src/components/auth/Invite.js",
58 "start": {
59 "line": 32,
60 "column": 21
61 },
62 "end": {
63 "line": 35,
64 "column": 3
65 }
66 },
67 {
68 "id": "invite.skip.label",
69 "defaultMessage": "!!!I want to do this later",
70 "file": "src/components/auth/Invite.js",
71 "start": {
72 "line": 36,
73 "column": 19
74 },
75 "end": {
76 "line": 39,
77 "column": 3
78 }
79 },
80 {
81 "id": "invite.successInfo",
82 "defaultMessage": "!!!Invitations sent successfully",
83 "file": "src/components/auth/Invite.js",
84 "start": {
85 "line": 40,
86 "column": 21
87 },
88 "end": {
89 "line": 43,
90 "column": 3
91 }
92 }
93] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/Locked.json b/src/i18n/messages/src/components/auth/Locked.json
deleted file mode 100644
index a871d6fc8..000000000
--- a/src/i18n/messages/src/components/auth/Locked.json
+++ /dev/null
@@ -1,106 +0,0 @@
1[
2 {
3 "id": "locked.headline",
4 "defaultMessage": "!!!Locked",
5 "file": "src/components/auth/Locked.js",
6 "start": {
7 "line": 16,
8 "column": 12
9 },
10 "end": {
11 "line": 19,
12 "column": 3
13 }
14 },
15 {
16 "id": "locked.info",
17 "defaultMessage": "!!!Ferdi is currently locked. Please unlock Ferdi with your password to see your messages.",
18 "file": "src/components/auth/Locked.js",
19 "start": {
20 "line": 20,
21 "column": 8
22 },
23 "end": {
24 "line": 23,
25 "column": 3
26 }
27 },
28 {
29 "id": "locked.touchId",
30 "defaultMessage": "!!!Unlock with Touch ID",
31 "file": "src/components/auth/Locked.js",
32 "start": {
33 "line": 24,
34 "column": 11
35 },
36 "end": {
37 "line": 27,
38 "column": 3
39 }
40 },
41 {
42 "id": "locked.touchIdPrompt",
43 "defaultMessage": "!!!unlock via Touch ID",
44 "file": "src/components/auth/Locked.js",
45 "start": {
46 "line": 28,
47 "column": 17
48 },
49 "end": {
50 "line": 31,
51 "column": 3
52 }
53 },
54 {
55 "id": "locked.password.label",
56 "defaultMessage": "!!!Password",
57 "file": "src/components/auth/Locked.js",
58 "start": {
59 "line": 32,
60 "column": 17
61 },
62 "end": {
63 "line": 35,
64 "column": 3
65 }
66 },
67 {
68 "id": "locked.submit.label",
69 "defaultMessage": "!!!Unlock",
70 "file": "src/components/auth/Locked.js",
71 "start": {
72 "line": 36,
73 "column": 21
74 },
75 "end": {
76 "line": 39,
77 "column": 3
78 }
79 },
80 {
81 "id": "locked.unlockWithPassword",
82 "defaultMessage": "!!!Unlock with Password",
83 "file": "src/components/auth/Locked.js",
84 "start": {
85 "line": 40,
86 "column": 22
87 },
88 "end": {
89 "line": 43,
90 "column": 3
91 }
92 },
93 {
94 "id": "locked.invalidCredentials",
95 "defaultMessage": "!!!Password invalid",
96 "file": "src/components/auth/Locked.js",
97 "start": {
98 "line": 44,
99 "column": 22
100 },
101 "end": {
102 "line": 47,
103 "column": 3
104 }
105 }
106] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/Login.json b/src/i18n/messages/src/components/auth/Login.json
deleted file mode 100644
index 275b04478..000000000
--- a/src/i18n/messages/src/components/auth/Login.json
+++ /dev/null
@@ -1,171 +0,0 @@
1[
2 {
3 "id": "login.headline",
4 "defaultMessage": "!!!Sign in",
5 "file": "src/components/auth/Login.js",
6 "start": {
7 "line": 20,
8 "column": 12
9 },
10 "end": {
11 "line": 23,
12 "column": 3
13 }
14 },
15 {
16 "id": "login.email.label",
17 "defaultMessage": "!!!Email address",
18 "file": "src/components/auth/Login.js",
19 "start": {
20 "line": 24,
21 "column": 14
22 },
23 "end": {
24 "line": 27,
25 "column": 3
26 }
27 },
28 {
29 "id": "login.password.label",
30 "defaultMessage": "!!!Password",
31 "file": "src/components/auth/Login.js",
32 "start": {
33 "line": 28,
34 "column": 17
35 },
36 "end": {
37 "line": 31,
38 "column": 3
39 }
40 },
41 {
42 "id": "login.submit.label",
43 "defaultMessage": "!!!Sign in",
44 "file": "src/components/auth/Login.js",
45 "start": {
46 "line": 32,
47 "column": 21
48 },
49 "end": {
50 "line": 35,
51 "column": 3
52 }
53 },
54 {
55 "id": "login.invalidCredentials",
56 "defaultMessage": "!!!Email or password not valid",
57 "file": "src/components/auth/Login.js",
58 "start": {
59 "line": 36,
60 "column": 22
61 },
62 "end": {
63 "line": 39,
64 "column": 3
65 }
66 },
67 {
68 "id": "login.customServerQuestion",
69 "defaultMessage": "!!!Using a Franz account to log in?",
70 "file": "src/components/auth/Login.js",
71 "start": {
72 "line": 40,
73 "column": 24
74 },
75 "end": {
76 "line": 43,
77 "column": 3
78 }
79 },
80 {
81 "id": "login.customServerSuggestion",
82 "defaultMessage": "!!!Try importing your Franz account into Ferdi",
83 "file": "src/components/auth/Login.js",
84 "start": {
85 "line": 44,
86 "column": 26
87 },
88 "end": {
89 "line": 47,
90 "column": 3
91 }
92 },
93 {
94 "id": "login.tokenExpired",
95 "defaultMessage": "!!!Your session expired, please login again.",
96 "file": "src/components/auth/Login.js",
97 "start": {
98 "line": 48,
99 "column": 16
100 },
101 "end": {
102 "line": 51,
103 "column": 3
104 }
105 },
106 {
107 "id": "login.serverLogout",
108 "defaultMessage": "!!!Your session expired, please login again.",
109 "file": "src/components/auth/Login.js",
110 "start": {
111 "line": 52,
112 "column": 16
113 },
114 "end": {
115 "line": 55,
116 "column": 3
117 }
118 },
119 {
120 "id": "login.link.signup",
121 "defaultMessage": "!!!Create a free account",
122 "file": "src/components/auth/Login.js",
123 "start": {
124 "line": 56,
125 "column": 14
126 },
127 "end": {
128 "line": 59,
129 "column": 3
130 }
131 },
132 {
133 "id": "login.changeServer",
134 "defaultMessage": "!!!Change server",
135 "file": "src/components/auth/Login.js",
136 "start": {
137 "line": 60,
138 "column": 16
139 },
140 "end": {
141 "line": 63,
142 "column": 3
143 }
144 },
145 {
146 "id": "services.serverless",
147 "defaultMessage": "!!!Use Ferdi without an Account",
148 "file": "src/components/auth/Login.js",
149 "start": {
150 "line": 64,
151 "column": 14
152 },
153 "end": {
154 "line": 67,
155 "column": 3
156 }
157 },
158 {
159 "id": "login.link.password",
160 "defaultMessage": "!!!Forgot password",
161 "file": "src/components/auth/Login.js",
162 "start": {
163 "line": 68,
164 "column": 16
165 },
166 "end": {
167 "line": 71,
168 "column": 3
169 }
170 }
171] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/Password.json b/src/i18n/messages/src/components/auth/Password.json
deleted file mode 100644
index 336ba42ef..000000000
--- a/src/i18n/messages/src/components/auth/Password.json
+++ /dev/null
@@ -1,80 +0,0 @@
1[
2 {
3 "id": "password.headline",
4 "defaultMessage": "!!!Forgot password",
5 "file": "src/components/auth/Password.js",
6 "start": {
7 "line": 15,
8 "column": 12
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 },
15 {
16 "id": "password.email.label",
17 "defaultMessage": "!!!Email address",
18 "file": "src/components/auth/Password.js",
19 "start": {
20 "line": 19,
21 "column": 14
22 },
23 "end": {
24 "line": 22,
25 "column": 3
26 }
27 },
28 {
29 "id": "password.successInfo",
30 "defaultMessage": "!!!Your new password was sent to your email address",
31 "file": "src/components/auth/Password.js",
32 "start": {
33 "line": 23,
34 "column": 15
35 },
36 "end": {
37 "line": 26,
38 "column": 3
39 }
40 },
41 {
42 "id": "password.noUser",
43 "defaultMessage": "!!!No user affiliated with that email address",
44 "file": "src/components/auth/Password.js",
45 "start": {
46 "line": 27,
47 "column": 10
48 },
49 "end": {
50 "line": 30,
51 "column": 3
52 }
53 },
54 {
55 "id": "password.link.signup",
56 "defaultMessage": "!!!Create a free account",
57 "file": "src/components/auth/Password.js",
58 "start": {
59 "line": 31,
60 "column": 14
61 },
62 "end": {
63 "line": 34,
64 "column": 3
65 }
66 },
67 {
68 "id": "password.link.login",
69 "defaultMessage": "!!!Sign in to your account",
70 "file": "src/components/auth/Password.js",
71 "start": {
72 "line": 35,
73 "column": 13
74 },
75 "end": {
76 "line": 38,
77 "column": 3
78 }
79 }
80] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/ServiceAssistant.json b/src/i18n/messages/src/components/auth/ServiceAssistant.json
deleted file mode 100644
index 9170fc183..000000000
--- a/src/i18n/messages/src/components/auth/ServiceAssistant.json
+++ /dev/null
@@ -1,93 +0,0 @@
1[
2 {
3 "id": "settings.invite.headline",
4 "defaultMessage": "!!!Invite Friends",
5 "file": "src/components/auth/ServiceAssistant.js",
6 "start": {
7 "line": 16,
8 "column": 20
9 },
10 "end": {
11 "line": 19,
12 "column": 3
13 }
14 },
15 {
16 "id": "invite.headline.friends",
17 "defaultMessage": "!!!Invite 3 of your friends or colleagues",
18 "file": "src/components/auth/ServiceAssistant.js",
19 "start": {
20 "line": 20,
21 "column": 12
22 },
23 "end": {
24 "line": 23,
25 "column": 3
26 }
27 },
28 {
29 "id": "invite.name.label",
30 "defaultMessage": "!!!Name",
31 "file": "src/components/auth/ServiceAssistant.js",
32 "start": {
33 "line": 24,
34 "column": 13
35 },
36 "end": {
37 "line": 27,
38 "column": 3
39 }
40 },
41 {
42 "id": "invite.email.label",
43 "defaultMessage": "!!!Email address",
44 "file": "src/components/auth/ServiceAssistant.js",
45 "start": {
46 "line": 28,
47 "column": 14
48 },
49 "end": {
50 "line": 31,
51 "column": 3
52 }
53 },
54 {
55 "id": "invite.submit.label",
56 "defaultMessage": "!!!Send invites",
57 "file": "src/components/auth/ServiceAssistant.js",
58 "start": {
59 "line": 32,
60 "column": 21
61 },
62 "end": {
63 "line": 35,
64 "column": 3
65 }
66 },
67 {
68 "id": "invite.skip.label",
69 "defaultMessage": "!!!I want to do this later",
70 "file": "src/components/auth/ServiceAssistant.js",
71 "start": {
72 "line": 36,
73 "column": 19
74 },
75 "end": {
76 "line": 39,
77 "column": 3
78 }
79 },
80 {
81 "id": "invite.successInfo",
82 "defaultMessage": "!!!Invitations sent successfully",
83 "file": "src/components/auth/ServiceAssistant.js",
84 "start": {
85 "line": 40,
86 "column": 21
87 },
88 "end": {
89 "line": 43,
90 "column": 3
91 }
92 }
93] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/SetupAssistant.json b/src/i18n/messages/src/components/auth/SetupAssistant.json
deleted file mode 100644
index 108adab26..000000000
--- a/src/i18n/messages/src/components/auth/SetupAssistant.json
+++ /dev/null
@@ -1,54 +0,0 @@
1[
2 {
3 "id": "setupAssistant.headline",
4 "defaultMessage": "!!!Let's get started",
5 "file": "src/components/auth/SetupAssistant.js",
6 "start": {
7 "line": 20,
8 "column": 12
9 },
10 "end": {
11 "line": 23,
12 "column": 3
13 }
14 },
15 {
16 "id": "setupAssistant.subheadline",
17 "defaultMessage": "!!!Choose from our most used services and get back on top of your messaging now.",
18 "file": "src/components/auth/SetupAssistant.js",
19 "start": {
20 "line": 24,
21 "column": 15
22 },
23 "end": {
24 "line": 28,
25 "column": 3
26 }
27 },
28 {
29 "id": "setupAssistant.submit.label",
30 "defaultMessage": "!!!Let's go",
31 "file": "src/components/auth/SetupAssistant.js",
32 "start": {
33 "line": 29,
34 "column": 21
35 },
36 "end": {
37 "line": 32,
38 "column": 3
39 }
40 },
41 {
42 "id": "invite.successInfo",
43 "defaultMessage": "!!!Invitations sent successfully",
44 "file": "src/components/auth/SetupAssistant.js",
45 "start": {
46 "line": 33,
47 "column": 21
48 },
49 "end": {
50 "line": 36,
51 "column": 3
52 }
53 }
54] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/Signup.json b/src/i18n/messages/src/components/auth/Signup.json
deleted file mode 100644
index 4a32628ef..000000000
--- a/src/i18n/messages/src/components/auth/Signup.json
+++ /dev/null
@@ -1,171 +0,0 @@
1[
2 {
3 "id": "signup.headline",
4 "defaultMessage": "!!!Sign up",
5 "file": "src/components/auth/Signup.js",
6 "start": {
7 "line": 20,
8 "column": 12
9 },
10 "end": {
11 "line": 23,
12 "column": 3
13 }
14 },
15 {
16 "id": "signup.firstname.label",
17 "defaultMessage": "!!!Firstname",
18 "file": "src/components/auth/Signup.js",
19 "start": {
20 "line": 24,
21 "column": 18
22 },
23 "end": {
24 "line": 27,
25 "column": 3
26 }
27 },
28 {
29 "id": "signup.lastname.label",
30 "defaultMessage": "!!!Lastname",
31 "file": "src/components/auth/Signup.js",
32 "start": {
33 "line": 28,
34 "column": 17
35 },
36 "end": {
37 "line": 31,
38 "column": 3
39 }
40 },
41 {
42 "id": "signup.email.label",
43 "defaultMessage": "!!!Email address",
44 "file": "src/components/auth/Signup.js",
45 "start": {
46 "line": 32,
47 "column": 14
48 },
49 "end": {
50 "line": 35,
51 "column": 3
52 }
53 },
54 {
55 "id": "signup.password.label",
56 "defaultMessage": "!!!Password",
57 "file": "src/components/auth/Signup.js",
58 "start": {
59 "line": 40,
60 "column": 17
61 },
62 "end": {
63 "line": 43,
64 "column": 3
65 }
66 },
67 {
68 "id": "signup.legal.info",
69 "defaultMessage": "!!!By creating a Ferdi account you accept the",
70 "file": "src/components/auth/Signup.js",
71 "start": {
72 "line": 44,
73 "column": 13
74 },
75 "end": {
76 "line": 47,
77 "column": 3
78 }
79 },
80 {
81 "id": "signup.legal.terms",
82 "defaultMessage": "!!!Terms of service",
83 "file": "src/components/auth/Signup.js",
84 "start": {
85 "line": 48,
86 "column": 9
87 },
88 "end": {
89 "line": 51,
90 "column": 3
91 }
92 },
93 {
94 "id": "signup.legal.privacy",
95 "defaultMessage": "!!!Privacy Statement",
96 "file": "src/components/auth/Signup.js",
97 "start": {
98 "line": 52,
99 "column": 11
100 },
101 "end": {
102 "line": 55,
103 "column": 3
104 }
105 },
106 {
107 "id": "signup.submit.label",
108 "defaultMessage": "!!!Create account",
109 "file": "src/components/auth/Signup.js",
110 "start": {
111 "line": 56,
112 "column": 21
113 },
114 "end": {
115 "line": 59,
116 "column": 3
117 }
118 },
119 {
120 "id": "signup.link.login",
121 "defaultMessage": "!!!Already have an account, sign in?",
122 "file": "src/components/auth/Signup.js",
123 "start": {
124 "line": 60,
125 "column": 13
126 },
127 "end": {
128 "line": 63,
129 "column": 3
130 }
131 },
132 {
133 "id": "login.changeServer",
134 "defaultMessage": "!!!Change server",
135 "file": "src/components/auth/Signup.js",
136 "start": {
137 "line": 64,
138 "column": 16
139 },
140 "end": {
141 "line": 67,
142 "column": 3
143 }
144 },
145 {
146 "id": "services.serverless",
147 "defaultMessage": "!!!Use Ferdi without an Account",
148 "file": "src/components/auth/Signup.js",
149 "start": {
150 "line": 68,
151 "column": 14
152 },
153 "end": {
154 "line": 71,
155 "column": 3
156 }
157 },
158 {
159 "id": "signup.emailDuplicate",
160 "defaultMessage": "!!!A user with that email address already exists",
161 "file": "src/components/auth/Signup.js",
162 "start": {
163 "line": 72,
164 "column": 18
165 },
166 "end": {
167 "line": 75,
168 "column": 3
169 }
170 }
171] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/auth/Welcome.json b/src/i18n/messages/src/components/auth/Welcome.json
deleted file mode 100644
index 3f0c1e5c2..000000000
--- a/src/i18n/messages/src/components/auth/Welcome.json
+++ /dev/null
@@ -1,41 +0,0 @@
1[
2 {
3 "id": "welcome.signupButton",
4 "defaultMessage": "!!!Create a free account",
5 "file": "src/components/auth/Welcome.js",
6 "start": {
7 "line": 11,
8 "column": 16
9 },
10 "end": {
11 "line": 14,
12 "column": 3
13 }
14 },
15 {
16 "id": "welcome.loginButton",
17 "defaultMessage": "!!!Login to your account",
18 "file": "src/components/auth/Welcome.js",
19 "start": {
20 "line": 15,
21 "column": 15
22 },
23 "end": {
24 "line": 18,
25 "column": 3
26 }
27 },
28 {
29 "id": "services.serverless",
30 "defaultMessage": "!!!Use Ferdi without an Account",
31 "file": "src/components/auth/Welcome.js",
32 "start": {
33 "line": 19,
34 "column": 14
35 },
36 "end": {
37 "line": 22,
38 "column": 3
39 }
40 }
41] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/layout/AppLayout.json b/src/i18n/messages/src/components/layout/AppLayout.json
deleted file mode 100644
index 807490a4f..000000000
--- a/src/i18n/messages/src/components/layout/AppLayout.json
+++ /dev/null
@@ -1,54 +0,0 @@
1[
2 {
3 "id": "infobar.servicesUpdated",
4 "defaultMessage": "!!!Your services have been updated.",
5 "file": "src/components/layout/AppLayout.js",
6 "start": {
7 "line": 28,
8 "column": 19
9 },
10 "end": {
11 "line": 31,
12 "column": 3
13 }
14 },
15 {
16 "id": "infobar.buttonReloadServices",
17 "defaultMessage": "!!!Reload services",
18 "file": "src/components/layout/AppLayout.js",
19 "start": {
20 "line": 32,
21 "column": 24
22 },
23 "end": {
24 "line": 35,
25 "column": 3
26 }
27 },
28 {
29 "id": "infobar.requiredRequestsFailed",
30 "defaultMessage": "!!!Could not load services and user information",
31 "file": "src/components/layout/AppLayout.js",
32 "start": {
33 "line": 36,
34 "column": 26
35 },
36 "end": {
37 "line": 39,
38 "column": 3
39 }
40 },
41 {
42 "id": "infobar.authRequestFailed",
43 "defaultMessage": "!!!There were errors while trying to perform an authenticated request. Please try logging out and back in if this error persists.",
44 "file": "src/components/layout/AppLayout.js",
45 "start": {
46 "line": 40,
47 "column": 21
48 },
49 "end": {
50 "line": 44,
51 "column": 3
52 }
53 }
54] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/layout/Sidebar.json b/src/i18n/messages/src/components/layout/Sidebar.json
deleted file mode 100644
index 9bc435f12..000000000
--- a/src/i18n/messages/src/components/layout/Sidebar.json
+++ /dev/null
@@ -1,106 +0,0 @@
1[
2 {
3 "id": "sidebar.addNewService",
4 "defaultMessage": "!!!Add new service",
5 "file": "src/components/layout/Sidebar.js",
6 "start": {
7 "line": 18,
8 "column": 17
9 },
10 "end": {
11 "line": 21,
12 "column": 3
13 }
14 },
15 {
16 "id": "sidebar.muteApp",
17 "defaultMessage": "!!!Disable notifications & audio",
18 "file": "src/components/layout/Sidebar.js",
19 "start": {
20 "line": 22,
21 "column": 8
22 },
23 "end": {
24 "line": 25,
25 "column": 3
26 }
27 },
28 {
29 "id": "sidebar.unmuteApp",
30 "defaultMessage": "!!!Enable notifications & audio",
31 "file": "src/components/layout/Sidebar.js",
32 "start": {
33 "line": 26,
34 "column": 10
35 },
36 "end": {
37 "line": 29,
38 "column": 3
39 }
40 },
41 {
42 "id": "sidebar.openWorkspaceDrawer",
43 "defaultMessage": "!!!Open workspace drawer",
44 "file": "src/components/layout/Sidebar.js",
45 "start": {
46 "line": 30,
47 "column": 23
48 },
49 "end": {
50 "line": 33,
51 "column": 3
52 }
53 },
54 {
55 "id": "sidebar.closeWorkspaceDrawer",
56 "defaultMessage": "!!!Close workspace drawer",
57 "file": "src/components/layout/Sidebar.js",
58 "start": {
59 "line": 34,
60 "column": 24
61 },
62 "end": {
63 "line": 37,
64 "column": 3
65 }
66 },
67 {
68 "id": "sidebar.openTodosDrawer",
69 "defaultMessage": "!!!Open Ferdi Todos",
70 "file": "src/components/layout/Sidebar.js",
71 "start": {
72 "line": 38,
73 "column": 19
74 },
75 "end": {
76 "line": 41,
77 "column": 3
78 }
79 },
80 {
81 "id": "sidebar.closeTodosDrawer",
82 "defaultMessage": "!!!Close Ferdi Todos",
83 "file": "src/components/layout/Sidebar.js",
84 "start": {
85 "line": 42,
86 "column": 20
87 },
88 "end": {
89 "line": 45,
90 "column": 3
91 }
92 },
93 {
94 "id": "sidebar.lockFerdi",
95 "defaultMessage": "!!!Lock Ferdi",
96 "file": "src/components/layout/Sidebar.js",
97 "start": {
98 "line": 46,
99 "column": 13
100 },
101 "end": {
102 "line": 49,
103 "column": 3
104 }
105 }
106] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/content/ConnectionBanner.json b/src/i18n/messages/src/components/services/content/ConnectionBanner.json
deleted file mode 100644
index 1047c28b5..000000000
--- a/src/i18n/messages/src/components/services/content/ConnectionBanner.json
+++ /dev/null
@@ -1,67 +0,0 @@
1[
2 {
3 "id": "webControls.goHome",
4 "defaultMessage": "!!!Home",
5 "file": "src/components/services/content/ConnectionBanner.js",
6 "start": {
7 "line": 13,
8 "column": 10
9 },
10 "end": {
11 "line": 16,
12 "column": 3
13 }
14 },
15 {
16 "id": "webControls.openInBrowser",
17 "defaultMessage": "!!!Open in Browser",
18 "file": "src/components/services/content/ConnectionBanner.js",
19 "start": {
20 "line": 17,
21 "column": 17
22 },
23 "end": {
24 "line": 20,
25 "column": 3
26 }
27 },
28 {
29 "id": "webControls.back",
30 "defaultMessage": "!!!Back",
31 "file": "src/components/services/content/ConnectionBanner.js",
32 "start": {
33 "line": 21,
34 "column": 8
35 },
36 "end": {
37 "line": 24,
38 "column": 3
39 }
40 },
41 {
42 "id": "webControls.forward",
43 "defaultMessage": "!!!Forward",
44 "file": "src/components/services/content/ConnectionBanner.js",
45 "start": {
46 "line": 25,
47 "column": 11
48 },
49 "end": {
50 "line": 28,
51 "column": 3
52 }
53 },
54 {
55 "id": "webControls.reload",
56 "defaultMessage": "!!!Reload",
57 "file": "src/components/services/content/ConnectionBanner.js",
58 "start": {
59 "line": 29,
60 "column": 10
61 },
62 "end": {
63 "line": 32,
64 "column": 3
65 }
66 }
67] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/content/ConnectionLost.json b/src/i18n/messages/src/components/services/content/ConnectionLost.json
deleted file mode 100644
index ee3f7a4ba..000000000
--- a/src/i18n/messages/src/components/services/content/ConnectionLost.json
+++ /dev/null
@@ -1,67 +0,0 @@
1[
2 {
3 "id": "webControls.goHome",
4 "defaultMessage": "!!!Home",
5 "file": "src/components/services/content/ConnectionLost.js",
6 "start": {
7 "line": 13,
8 "column": 10
9 },
10 "end": {
11 "line": 16,
12 "column": 3
13 }
14 },
15 {
16 "id": "webControls.openInBrowser",
17 "defaultMessage": "!!!Open in Browser",
18 "file": "src/components/services/content/ConnectionLost.js",
19 "start": {
20 "line": 17,
21 "column": 17
22 },
23 "end": {
24 "line": 20,
25 "column": 3
26 }
27 },
28 {
29 "id": "webControls.back",
30 "defaultMessage": "!!!Back",
31 "file": "src/components/services/content/ConnectionLost.js",
32 "start": {
33 "line": 21,
34 "column": 8
35 },
36 "end": {
37 "line": 24,
38 "column": 3
39 }
40 },
41 {
42 "id": "webControls.forward",
43 "defaultMessage": "!!!Forward",
44 "file": "src/components/services/content/ConnectionLost.js",
45 "start": {
46 "line": 25,
47 "column": 11
48 },
49 "end": {
50 "line": 28,
51 "column": 3
52 }
53 },
54 {
55 "id": "webControls.reload",
56 "defaultMessage": "!!!Reload",
57 "file": "src/components/services/content/ConnectionLost.js",
58 "start": {
59 "line": 29,
60 "column": 10
61 },
62 "end": {
63 "line": 32,
64 "column": 3
65 }
66 }
67] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/content/ConnectionLostBanner.json b/src/i18n/messages/src/components/services/content/ConnectionLostBanner.json
deleted file mode 100644
index 6805b4d67..000000000
--- a/src/i18n/messages/src/components/services/content/ConnectionLostBanner.json
+++ /dev/null
@@ -1,41 +0,0 @@
1[
2 {
3 "id": "connectionLostBanner.message",
4 "defaultMessage": "!!!Oh no! Ferdi lost the connection to {name}.",
5 "file": "src/components/services/content/ConnectionLostBanner.js",
6 "start": {
7 "line": 13,
8 "column": 8
9 },
10 "end": {
11 "line": 16,
12 "column": 3
13 }
14 },
15 {
16 "id": "connectionLostBanner.informationLink",
17 "defaultMessage": "!!!What happened?",
18 "file": "src/components/services/content/ConnectionLostBanner.js",
19 "start": {
20 "line": 17,
21 "column": 19
22 },
23 "end": {
24 "line": 20,
25 "column": 3
26 }
27 },
28 {
29 "id": "connectionLostBanner.cta",
30 "defaultMessage": "!!!Reload Service",
31 "file": "src/components/services/content/ConnectionLostBanner.js",
32 "start": {
33 "line": 21,
34 "column": 7
35 },
36 "end": {
37 "line": 24,
38 "column": 3
39 }
40 }
41] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/content/ErrorHandlers/WebviewErrorHandler.json b/src/i18n/messages/src/components/services/content/ErrorHandlers/WebviewErrorHandler.json
deleted file mode 100644
index c8fe802df..000000000
--- a/src/i18n/messages/src/components/services/content/ErrorHandlers/WebviewErrorHandler.json
+++ /dev/null
@@ -1,67 +0,0 @@
1[
2 {
3 "id": "service.errorHandler.headline",
4 "defaultMessage": "!!!Oh no!",
5 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
6 "start": {
7 "line": 12,
8 "column": 12
9 },
10 "end": {
11 "line": 15,
12 "column": 3
13 }
14 },
15 {
16 "id": "service.errorHandler.text",
17 "defaultMessage": "!!!{name} has failed to load.",
18 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
19 "start": {
20 "line": 16,
21 "column": 8
22 },
23 "end": {
24 "line": 19,
25 "column": 3
26 }
27 },
28 {
29 "id": "service.errorHandler.action",
30 "defaultMessage": "!!!Reload {name}",
31 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
32 "start": {
33 "line": 20,
34 "column": 10
35 },
36 "end": {
37 "line": 23,
38 "column": 3
39 }
40 },
41 {
42 "id": "service.errorHandler.editAction",
43 "defaultMessage": "!!!Edit {name}",
44 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
45 "start": {
46 "line": 24,
47 "column": 14
48 },
49 "end": {
50 "line": 27,
51 "column": 3
52 }
53 },
54 {
55 "id": "service.errorHandler.message",
56 "defaultMessage": "!!!Error:",
57 "file": "src/components/services/content/ErrorHandlers/WebviewErrorHandler.js",
58 "start": {
59 "line": 28,
60 "column": 16
61 },
62 "end": {
63 "line": 31,
64 "column": 3
65 }
66 }
67] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/content/ServiceDisabled.json b/src/i18n/messages/src/components/services/content/ServiceDisabled.json
deleted file mode 100644
index 8bfad28c7..000000000
--- a/src/i18n/messages/src/components/services/content/ServiceDisabled.json
+++ /dev/null
@@ -1,28 +0,0 @@
1[
2 {
3 "id": "service.disabledHandler.headline",
4 "defaultMessage": "!!!{name} is disabled",
5 "file": "src/components/services/content/ServiceDisabled.js",
6 "start": {
7 "line": 9,
8 "column": 12
9 },
10 "end": {
11 "line": 12,
12 "column": 3
13 }
14 },
15 {
16 "id": "service.disabledHandler.action",
17 "defaultMessage": "!!!Enable {name}",
18 "file": "src/components/services/content/ServiceDisabled.js",
19 "start": {
20 "line": 13,
21 "column": 10
22 },
23 "end": {
24 "line": 16,
25 "column": 3
26 }
27 }
28] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/content/Services.json b/src/i18n/messages/src/components/services/content/Services.json
deleted file mode 100644
index 304c93f3c..000000000
--- a/src/i18n/messages/src/components/services/content/Services.json
+++ /dev/null
@@ -1,67 +0,0 @@
1[
2 {
3 "id": "services.welcome",
4 "defaultMessage": "!!!Welcome to Ferdi",
5 "file": "src/components/services/content/Services.js",
6 "start": {
7 "line": 15,
8 "column": 11
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 },
15 {
16 "id": "services.getStarted",
17 "defaultMessage": "!!!Get started",
18 "file": "src/components/services/content/Services.js",
19 "start": {
20 "line": 19,
21 "column": 14
22 },
23 "end": {
24 "line": 22,
25 "column": 3
26 }
27 },
28 {
29 "id": "services.login",
30 "defaultMessage": "!!!Please login to use Ferdi.",
31 "file": "src/components/services/content/Services.js",
32 "start": {
33 "line": 23,
34 "column": 9
35 },
36 "end": {
37 "line": 26,
38 "column": 3
39 }
40 },
41 {
42 "id": "services.serverless",
43 "defaultMessage": "!!!Use Ferdi without an Account",
44 "file": "src/components/services/content/Services.js",
45 "start": {
46 "line": 27,
47 "column": 14
48 },
49 "end": {
50 "line": 30,
51 "column": 3
52 }
53 },
54 {
55 "id": "services.serverInfo",
56 "defaultMessage": "!!!Optionally, you can change your Ferdi server by clicking the cog in the bottom left corner. If you are switching over (from one of the hosted servers) to using Ferdi without an account, please be informed that you can export your data from that server and subsequently import it using the Help menu to resurrect all your workspaces and configured services!",
57 "file": "src/components/services/content/Services.js",
58 "start": {
59 "line": 31,
60 "column": 14
61 },
62 "end": {
63 "line": 34,
64 "column": 3
65 }
66 }
67] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/content/WebControls.json b/src/i18n/messages/src/components/services/content/WebControls.json
deleted file mode 100644
index 5af5143d0..000000000
--- a/src/i18n/messages/src/components/services/content/WebControls.json
+++ /dev/null
@@ -1,67 +0,0 @@
1[
2 {
3 "id": "webControls.goHome",
4 "defaultMessage": "!!!Home",
5 "file": "src/components/services/content/WebControls.js",
6 "start": {
7 "line": 13,
8 "column": 10
9 },
10 "end": {
11 "line": 16,
12 "column": 3
13 }
14 },
15 {
16 "id": "webControls.openInBrowser",
17 "defaultMessage": "!!!Open in Browser",
18 "file": "src/components/services/content/WebControls.js",
19 "start": {
20 "line": 17,
21 "column": 17
22 },
23 "end": {
24 "line": 20,
25 "column": 3
26 }
27 },
28 {
29 "id": "webControls.back",
30 "defaultMessage": "!!!Back",
31 "file": "src/components/services/content/WebControls.js",
32 "start": {
33 "line": 21,
34 "column": 8
35 },
36 "end": {
37 "line": 24,
38 "column": 3
39 }
40 },
41 {
42 "id": "webControls.forward",
43 "defaultMessage": "!!!Forward",
44 "file": "src/components/services/content/WebControls.js",
45 "start": {
46 "line": 25,
47 "column": 11
48 },
49 "end": {
50 "line": 28,
51 "column": 3
52 }
53 },
54 {
55 "id": "webControls.reload",
56 "defaultMessage": "!!!Reload",
57 "file": "src/components/services/content/WebControls.js",
58 "start": {
59 "line": 29,
60 "column": 10
61 },
62 "end": {
63 "line": 32,
64 "column": 3
65 }
66 }
67] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/content/WebviewCrashHandler.json b/src/i18n/messages/src/components/services/content/WebviewCrashHandler.json
deleted file mode 100644
index c3d6c41a5..000000000
--- a/src/i18n/messages/src/components/services/content/WebviewCrashHandler.json
+++ /dev/null
@@ -1,54 +0,0 @@
1[
2 {
3 "id": "service.crashHandler.headline",
4 "defaultMessage": "!!!Oh no!",
5 "file": "src/components/services/content/WebviewCrashHandler.js",
6 "start": {
7 "line": 10,
8 "column": 12
9 },
10 "end": {
11 "line": 13,
12 "column": 3
13 }
14 },
15 {
16 "id": "service.crashHandler.text",
17 "defaultMessage": "!!!{name} has caused an error.",
18 "file": "src/components/services/content/WebviewCrashHandler.js",
19 "start": {
20 "line": 14,
21 "column": 8
22 },
23 "end": {
24 "line": 17,
25 "column": 3
26 }
27 },
28 {
29 "id": "service.crashHandler.action",
30 "defaultMessage": "!!!Reload {name}",
31 "file": "src/components/services/content/WebviewCrashHandler.js",
32 "start": {
33 "line": 18,
34 "column": 10
35 },
36 "end": {
37 "line": 21,
38 "column": 3
39 }
40 },
41 {
42 "id": "service.crashHandler.autoReload",
43 "defaultMessage": "!!!Trying to automatically restore {name} in {seconds} seconds",
44 "file": "src/components/services/content/WebviewCrashHandler.js",
45 "start": {
46 "line": 22,
47 "column": 14
48 },
49 "end": {
50 "line": 25,
51 "column": 3
52 }
53 }
54] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/services/tabs/TabItem.json b/src/i18n/messages/src/components/services/tabs/TabItem.json
deleted file mode 100644
index de854f1e1..000000000
--- a/src/i18n/messages/src/components/services/tabs/TabItem.json
+++ /dev/null
@@ -1,171 +0,0 @@
1[
2 {
3 "id": "tabs.item.reload",
4 "defaultMessage": "!!!Reload",
5 "file": "src/components/services/tabs/TabItem.js",
6 "start": {
7 "line": 21,
8 "column": 10
9 },
10 "end": {
11 "line": 24,
12 "column": 3
13 }
14 },
15 {
16 "id": "tabs.item.disableNotifications",
17 "defaultMessage": "!!!Disable notifications",
18 "file": "src/components/services/tabs/TabItem.js",
19 "start": {
20 "line": 25,
21 "column": 24
22 },
23 "end": {
24 "line": 28,
25 "column": 3
26 }
27 },
28 {
29 "id": "tabs.item.enableNotification",
30 "defaultMessage": "!!!Enable notifications",
31 "file": "src/components/services/tabs/TabItem.js",
32 "start": {
33 "line": 29,
34 "column": 23
35 },
36 "end": {
37 "line": 32,
38 "column": 3
39 }
40 },
41 {
42 "id": "tabs.item.disableAudio",
43 "defaultMessage": "!!!Disable audio",
44 "file": "src/components/services/tabs/TabItem.js",
45 "start": {
46 "line": 33,
47 "column": 16
48 },
49 "end": {
50 "line": 36,
51 "column": 3
52 }
53 },
54 {
55 "id": "tabs.item.enableAudio",
56 "defaultMessage": "!!!Enable audio",
57 "file": "src/components/services/tabs/TabItem.js",
58 "start": {
59 "line": 37,
60 "column": 15
61 },
62 "end": {
63 "line": 40,
64 "column": 3
65 }
66 },
67 {
68 "id": "tabs.item.enableDarkMode",
69 "defaultMessage": "!!!Enable Dark mode",
70 "file": "src/components/services/tabs/TabItem.js",
71 "start": {
72 "line": 41,
73 "column": 18
74 },
75 "end": {
76 "line": 44,
77 "column": 3
78 }
79 },
80 {
81 "id": "tabs.item.disableDarkMode",
82 "defaultMessage": "!!!Disable Dark mode",
83 "file": "src/components/services/tabs/TabItem.js",
84 "start": {
85 "line": 45,
86 "column": 19
87 },
88 "end": {
89 "line": 48,
90 "column": 3
91 }
92 },
93 {
94 "id": "tabs.item.disableService",
95 "defaultMessage": "!!!Disable Service",
96 "file": "src/components/services/tabs/TabItem.js",
97 "start": {
98 "line": 49,
99 "column": 18
100 },
101 "end": {
102 "line": 52,
103 "column": 3
104 }
105 },
106 {
107 "id": "tabs.item.enableService",
108 "defaultMessage": "!!!Enable Service",
109 "file": "src/components/services/tabs/TabItem.js",
110 "start": {
111 "line": 53,
112 "column": 17
113 },
114 "end": {
115 "line": 56,
116 "column": 3
117 }
118 },
119 {
120 "id": "tabs.item.hibernateService",
121 "defaultMessage": "!!!Hibernate Service",
122 "file": "src/components/services/tabs/TabItem.js",
123 "start": {
124 "line": 57,
125 "column": 20
126 },
127 "end": {
128 "line": 60,
129 "column": 3
130 }
131 },
132 {
133 "id": "tabs.item.wakeUpService",
134 "defaultMessage": "!!!Wake Up Service",
135 "file": "src/components/services/tabs/TabItem.js",
136 "start": {
137 "line": 61,
138 "column": 17
139 },
140 "end": {
141 "line": 64,
142 "column": 3
143 }
144 },
145 {
146 "id": "tabs.item.deleteService",
147 "defaultMessage": "!!!Delete Service",
148 "file": "src/components/services/tabs/TabItem.js",
149 "start": {
150 "line": 65,
151 "column": 17
152 },
153 "end": {
154 "line": 68,
155 "column": 3
156 }
157 },
158 {
159 "id": "tabs.item.confirmDeleteService",
160 "defaultMessage": "!!!Do you really want to delete the {serviceName} service?",
161 "file": "src/components/services/tabs/TabItem.js",
162 "start": {
163 "line": 69,
164 "column": 24
165 },
166 "end": {
167 "line": 73,
168 "column": 3
169 }
170 }
171] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/SettingsLayout.json b/src/i18n/messages/src/components/settings/SettingsLayout.json
deleted file mode 100644
index 99337a315..000000000
--- a/src/i18n/messages/src/components/settings/SettingsLayout.json
+++ /dev/null
@@ -1,15 +0,0 @@
1[
2 {
3 "id": "settings.app.closeSettings",
4 "defaultMessage": "!!!Close settings",
5 "file": "src/components/settings/SettingsLayout.js",
6 "start": {
7 "line": 11,
8 "column": 17
9 },
10 "end": {
11 "line": 14,
12 "column": 3
13 }
14 }
15] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/account/AccountDashboard.json b/src/i18n/messages/src/components/settings/account/AccountDashboard.json
deleted file mode 100644
index b0cc2dcc7..000000000
--- a/src/i18n/messages/src/components/settings/account/AccountDashboard.json
+++ /dev/null
@@ -1,158 +0,0 @@
1[
2 {
3 "id": "settings.account.headline",
4 "defaultMessage": "!!!Account",
5 "file": "src/components/settings/account/AccountDashboard.js",
6 "start": {
7 "line": 14,
8 "column": 12
9 },
10 "end": {
11 "line": 17,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.account.headlineDangerZone",
17 "defaultMessage": "!!Danger Zone",
18 "file": "src/components/settings/account/AccountDashboard.js",
19 "start": {
20 "line": 18,
21 "column": 22
22 },
23 "end": {
24 "line": 21,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.account.account.editButton",
30 "defaultMessage": "!!!Edit Account",
31 "file": "src/components/settings/account/AccountDashboard.js",
32 "start": {
33 "line": 22,
34 "column": 21
35 },
36 "end": {
37 "line": 25,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.account.headlineInvoices",
43 "defaultMessage": "!!Invoices",
44 "file": "src/components/settings/account/AccountDashboard.js",
45 "start": {
46 "line": 26,
47 "column": 18
48 },
49 "end": {
50 "line": 29,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.account.userInfoRequestFailed",
56 "defaultMessage": "!!!Could not load user information",
57 "file": "src/components/settings/account/AccountDashboard.js",
58 "start": {
59 "line": 30,
60 "column": 25
61 },
62 "end": {
63 "line": 33,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.account.tryReloadUserInfoRequest",
69 "defaultMessage": "!!!Try again",
70 "file": "src/components/settings/account/AccountDashboard.js",
71 "start": {
72 "line": 34,
73 "column": 28
74 },
75 "end": {
76 "line": 37,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.account.deleteAccount",
82 "defaultMessage": "!!!Delete account",
83 "file": "src/components/settings/account/AccountDashboard.js",
84 "start": {
85 "line": 38,
86 "column": 17
87 },
88 "end": {
89 "line": 41,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.account.deleteInfo",
95 "defaultMessage": "!!!If you don't need your Ferdi account any longer, you can delete your account and all related data here.",
96 "file": "src/components/settings/account/AccountDashboard.js",
97 "start": {
98 "line": 42,
99 "column": 14
100 },
101 "end": {
102 "line": 46,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.account.deleteEmailSent",
108 "defaultMessage": "!!!You have received an email with a link to confirm your account deletion. Your account and data cannot be restored!",
109 "file": "src/components/settings/account/AccountDashboard.js",
110 "start": {
111 "line": 47,
112 "column": 19
113 },
114 "end": {
115 "line": 51,
116 "column": 3
117 }
118 },
119 {
120 "id": "settings.account.yourLicense",
121 "defaultMessage": "!!!Your Franz License:",
122 "file": "src/components/settings/account/AccountDashboard.js",
123 "start": {
124 "line": 52,
125 "column": 15
126 },
127 "end": {
128 "line": 55,
129 "column": 3
130 }
131 },
132 {
133 "id": "settings.account.accountUnavailable",
134 "defaultMessage": "Account is unavailable",
135 "file": "src/components/settings/account/AccountDashboard.js",
136 "start": {
137 "line": 56,
138 "column": 22
139 },
140 "end": {
141 "line": 59,
142 "column": 3
143 }
144 },
145 {
146 "id": "settings.account.accountUnavailableInfo",
147 "defaultMessage": "You are using Ferdi without an account. If you want to use Ferdi with an account and keep your services synchronized across installations, please select a server in the Settings tab then login.",
148 "file": "src/components/settings/account/AccountDashboard.js",
149 "start": {
150 "line": 60,
151 "column": 26
152 },
153 "end": {
154 "line": 63,
155 "column": 3
156 }
157 }
158] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json b/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json
deleted file mode 100644
index 2029ad7af..000000000
--- a/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json
+++ /dev/null
@@ -1,93 +0,0 @@
1[
2 {
3 "id": "settings.navigation.availableServices",
4 "defaultMessage": "!!!Available services",
5 "file": "src/components/settings/navigation/SettingsNavigation.js",
6 "start": {
7 "line": 16,
8 "column": 21
9 },
10 "end": {
11 "line": 19,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.navigation.yourServices",
17 "defaultMessage": "!!!Your services",
18 "file": "src/components/settings/navigation/SettingsNavigation.js",
19 "start": {
20 "line": 20,
21 "column": 16
22 },
23 "end": {
24 "line": 23,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.navigation.yourWorkspaces",
30 "defaultMessage": "!!!Your workspaces",
31 "file": "src/components/settings/navigation/SettingsNavigation.js",
32 "start": {
33 "line": 24,
34 "column": 18
35 },
36 "end": {
37 "line": 27,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.navigation.account",
43 "defaultMessage": "!!!Account",
44 "file": "src/components/settings/navigation/SettingsNavigation.js",
45 "start": {
46 "line": 28,
47 "column": 11
48 },
49 "end": {
50 "line": 31,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.navigation.team",
56 "defaultMessage": "!!!Manage Team",
57 "file": "src/components/settings/navigation/SettingsNavigation.js",
58 "start": {
59 "line": 32,
60 "column": 8
61 },
62 "end": {
63 "line": 35,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.navigation.supportFerdi",
69 "defaultMessage": "!!!About Ferdi",
70 "file": "src/components/settings/navigation/SettingsNavigation.js",
71 "start": {
72 "line": 36,
73 "column": 16
74 },
75 "end": {
76 "line": 39,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.navigation.logout",
82 "defaultMessage": "!!!Logout",
83 "file": "src/components/settings/navigation/SettingsNavigation.js",
84 "start": {
85 "line": 40,
86 "column": 10
87 },
88 "end": {
89 "line": 43,
90 "column": 3
91 }
92 }
93] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/recipes/RecipesDashboard.json b/src/i18n/messages/src/components/settings/recipes/RecipesDashboard.json
deleted file mode 100644
index 7ab2916f5..000000000
--- a/src/i18n/messages/src/components/settings/recipes/RecipesDashboard.json
+++ /dev/null
@@ -1,171 +0,0 @@
1[
2 {
3 "id": "settings.recipes.headline",
4 "defaultMessage": "!!!Available Services",
5 "file": "src/components/settings/recipes/RecipesDashboard.js",
6 "start": {
7 "line": 19,
8 "column": 12
9 },
10 "end": {
11 "line": 22,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.searchService",
17 "defaultMessage": "!!!Search service",
18 "file": "src/components/settings/recipes/RecipesDashboard.js",
19 "start": {
20 "line": 23,
21 "column": 17
22 },
23 "end": {
24 "line": 26,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.recipes.all",
30 "defaultMessage": "!!!All services",
31 "file": "src/components/settings/recipes/RecipesDashboard.js",
32 "start": {
33 "line": 27,
34 "column": 14
35 },
36 "end": {
37 "line": 30,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.recipes.custom",
43 "defaultMessage": "!!!Custom Services",
44 "file": "src/components/settings/recipes/RecipesDashboard.js",
45 "start": {
46 "line": 31,
47 "column": 17
48 },
49 "end": {
50 "line": 34,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.recipes.nothingFound",
56 "defaultMessage": "!!!Sorry, but no service matched your search term - but you can still probably add it using the \"Custom Website\" option. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.",
57 "file": "src/components/settings/recipes/RecipesDashboard.js",
58 "start": {
59 "line": 35,
60 "column": 16
61 },
62 "end": {
63 "line": 38,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.recipes.servicesSuccessfulAddedInfo",
69 "defaultMessage": "!!!Service successfully added",
70 "file": "src/components/settings/recipes/RecipesDashboard.js",
71 "start": {
72 "line": 39,
73 "column": 31
74 },
75 "end": {
76 "line": 42,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.recipes.missingService",
82 "defaultMessage": "!!!Missing a service?",
83 "file": "src/components/settings/recipes/RecipesDashboard.js",
84 "start": {
85 "line": 43,
86 "column": 18
87 },
88 "end": {
89 "line": 46,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.recipes.customService.intro",
95 "defaultMessage": "!!!To add a custom service, copy the recipe folder into:",
96 "file": "src/components/settings/recipes/RecipesDashboard.js",
97 "start": {
98 "line": 47,
99 "column": 21
100 },
101 "end": {
102 "line": 50,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.recipes.customService.openFolder",
108 "defaultMessage": "!!!Open directory",
109 "file": "src/components/settings/recipes/RecipesDashboard.js",
110 "start": {
111 "line": 51,
112 "column": 14
113 },
114 "end": {
115 "line": 54,
116 "column": 3
117 }
118 },
119 {
120 "id": "settings.recipes.customService.openDevDocs",
121 "defaultMessage": "!!!Developer Documentation",
122 "file": "src/components/settings/recipes/RecipesDashboard.js",
123 "start": {
124 "line": 55,
125 "column": 15
126 },
127 "end": {
128 "line": 58,
129 "column": 3
130 }
131 },
132 {
133 "id": "settings.recipes.customService.headline.customRecipes",
134 "defaultMessage": "!!!Custom 3rd Party Recipes",
135 "file": "src/components/settings/recipes/RecipesDashboard.js",
136 "start": {
137 "line": 59,
138 "column": 25
139 },
140 "end": {
141 "line": 62,
142 "column": 3
143 }
144 },
145 {
146 "id": "settings.recipes.customService.headline.communityRecipes",
147 "defaultMessage": "!!!Community 3rd Party Recipes",
148 "file": "src/components/settings/recipes/RecipesDashboard.js",
149 "start": {
150 "line": 63,
151 "column": 28
152 },
153 "end": {
154 "line": 66,
155 "column": 3
156 }
157 },
158 {
159 "id": "settings.recipes.customService.headline.devRecipes",
160 "defaultMessage": "!!!Your Development Service Recipes",
161 "file": "src/components/settings/recipes/RecipesDashboard.js",
162 "start": {
163 "line": 67,
164 "column": 22
165 },
166 "end": {
167 "line": 70,
168 "column": 3
169 }
170 }
171] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/services/EditServiceForm.json b/src/i18n/messages/src/components/settings/services/EditServiceForm.json
deleted file mode 100644
index d7830f198..000000000
--- a/src/i18n/messages/src/components/settings/services/EditServiceForm.json
+++ /dev/null
@@ -1,340 +0,0 @@
1[
2 {
3 "id": "settings.service.form.saveButton",
4 "defaultMessage": "!!!Save service",
5 "file": "src/components/settings/services/EditServiceForm.js",
6 "start": {
7 "line": 23,
8 "column": 15
9 },
10 "end": {
11 "line": 26,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.service.form.deleteButton",
17 "defaultMessage": "!!!Delete Service",
18 "file": "src/components/settings/services/EditServiceForm.js",
19 "start": {
20 "line": 27,
21 "column": 17
22 },
23 "end": {
24 "line": 30,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.service.form.openDarkmodeCss",
30 "defaultMessage": "!!!Open darkmode.css",
31 "file": "src/components/settings/services/EditServiceForm.js",
32 "start": {
33 "line": 31,
34 "column": 19
35 },
36 "end": {
37 "line": 34,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.service.form.openUserCss",
43 "defaultMessage": "!!!Open user.css",
44 "file": "src/components/settings/services/EditServiceForm.js",
45 "start": {
46 "line": 35,
47 "column": 15
48 },
49 "end": {
50 "line": 38,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.service.form.openUserJs",
56 "defaultMessage": "!!!Open user.js",
57 "file": "src/components/settings/services/EditServiceForm.js",
58 "start": {
59 "line": 39,
60 "column": 14
61 },
62 "end": {
63 "line": 42,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.service.form.recipeFileInfo",
69 "defaultMessage": "!!!Your user files will be inserted into the webpage so you can customize services in any way you like. User files are only stored locally and are not transferred to other computers using the same account.",
70 "file": "src/components/settings/services/EditServiceForm.js",
71 "start": {
72 "line": 43,
73 "column": 18
74 },
75 "end": {
76 "line": 46,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.service.form.availableServices",
82 "defaultMessage": "!!!Available services",
83 "file": "src/components/settings/services/EditServiceForm.js",
84 "start": {
85 "line": 47,
86 "column": 21
87 },
88 "end": {
89 "line": 50,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.service.form.yourServices",
95 "defaultMessage": "!!!Your services",
96 "file": "src/components/settings/services/EditServiceForm.js",
97 "start": {
98 "line": 51,
99 "column": 16
100 },
101 "end": {
102 "line": 54,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.service.form.addServiceHeadline",
108 "defaultMessage": "!!!Add {name}",
109 "file": "src/components/settings/services/EditServiceForm.js",
110 "start": {
111 "line": 55,
112 "column": 22
113 },
114 "end": {
115 "line": 58,
116 "column": 3
117 }
118 },
119 {
120 "id": "settings.service.form.editServiceHeadline",
121 "defaultMessage": "!!!Edit {name}",
122 "file": "src/components/settings/services/EditServiceForm.js",
123 "start": {
124 "line": 59,
125 "column": 23
126 },
127 "end": {
128 "line": 62,
129 "column": 3
130 }
131 },
132 {
133 "id": "settings.service.form.tabHosted",
134 "defaultMessage": "!!!Hosted",
135 "file": "src/components/settings/services/EditServiceForm.js",
136 "start": {
137 "line": 63,
138 "column": 13
139 },
140 "end": {
141 "line": 66,
142 "column": 3
143 }
144 },
145 {
146 "id": "settings.service.form.tabOnPremise",
147 "defaultMessage": "!!!Self hosted ⭐️",
148 "file": "src/components/settings/services/EditServiceForm.js",
149 "start": {
150 "line": 67,
151 "column": 16
152 },
153 "end": {
154 "line": 70,
155 "column": 3
156 }
157 },
158 {
159 "id": "settings.service.form.useHostedService",
160 "defaultMessage": "!!!Use the hosted {name} service.",
161 "file": "src/components/settings/services/EditServiceForm.js",
162 "start": {
163 "line": 71,
164 "column": 20
165 },
166 "end": {
167 "line": 74,
168 "column": 3
169 }
170 },
171 {
172 "id": "settings.service.form.customUrlValidationError",
173 "defaultMessage": "!!!Could not validate custom {name} server.",
174 "file": "src/components/settings/services/EditServiceForm.js",
175 "start": {
176 "line": 75,
177 "column": 28
178 },
179 "end": {
180 "line": 78,
181 "column": 3
182 }
183 },
184 {
185 "id": "settings.service.form.indirectMessageInfo",
186 "defaultMessage": "!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...",
187 "file": "src/components/settings/services/EditServiceForm.js",
188 "start": {
189 "line": 79,
190 "column": 23
191 },
192 "end": {
193 "line": 82,
194 "column": 3
195 }
196 },
197 {
198 "id": "settings.service.form.isMutedInfo",
199 "defaultMessage": "!!!When disabled, all notification sounds and audio playback are muted",
200 "file": "src/components/settings/services/EditServiceForm.js",
201 "start": {
202 "line": 83,
203 "column": 15
204 },
205 "end": {
206 "line": 86,
207 "column": 3
208 }
209 },
210 {
211 "id": "settings.service.form.isHibernatedEnabledInfo",
212 "defaultMessage": "!!!When enabled, a service will be shut down after a period of time to save system resources.",
213 "file": "src/components/settings/services/EditServiceForm.js",
214 "start": {
215 "line": 87,
216 "column": 28
217 },
218 "end": {
219 "line": 90,
220 "column": 3
221 }
222 },
223 {
224 "id": "settings.service.form.headlineNotifications",
225 "defaultMessage": "!!!Notifications",
226 "file": "src/components/settings/services/EditServiceForm.js",
227 "start": {
228 "line": 91,
229 "column": 25
230 },
231 "end": {
232 "line": 94,
233 "column": 3
234 }
235 },
236 {
237 "id": "settings.service.form.headlineBadges",
238 "defaultMessage": "!!!Unread message badges",
239 "file": "src/components/settings/services/EditServiceForm.js",
240 "start": {
241 "line": 95,
242 "column": 18
243 },
244 "end": {
245 "line": 98,
246 "column": 3
247 }
248 },
249 {
250 "id": "settings.service.form.headlineGeneral",
251 "defaultMessage": "!!!General",
252 "file": "src/components/settings/services/EditServiceForm.js",
253 "start": {
254 "line": 99,
255 "column": 19
256 },
257 "end": {
258 "line": 102,
259 "column": 3
260 }
261 },
262 {
263 "id": "settings.service.form.headlineDarkReaderSettings",
264 "defaultMessage": "!!!Dark Reader Settings",
265 "file": "src/components/settings/services/EditServiceForm.js",
266 "start": {
267 "line": 103,
268 "column": 30
269 },
270 "end": {
271 "line": 106,
272 "column": 3
273 }
274 },
275 {
276 "id": "settings.service.form.iconDelete",
277 "defaultMessage": "!!!Delete",
278 "file": "src/components/settings/services/EditServiceForm.js",
279 "start": {
280 "line": 107,
281 "column": 14
282 },
283 "end": {
284 "line": 110,
285 "column": 3
286 }
287 },
288 {
289 "id": "settings.service.form.iconUpload",
290 "defaultMessage": "!!!Drop your image, or click here",
291 "file": "src/components/settings/services/EditServiceForm.js",
292 "start": {
293 "line": 111,
294 "column": 14
295 },
296 "end": {
297 "line": 114,
298 "column": 3
299 }
300 },
301 {
302 "id": "settings.service.form.proxy.headline",
303 "defaultMessage": "!!!HTTP/HTTPS Proxy Settings",
304 "file": "src/components/settings/services/EditServiceForm.js",
305 "start": {
306 "line": 115,
307 "column": 17
308 },
309 "end": {
310 "line": 118,
311 "column": 3
312 }
313 },
314 {
315 "id": "settings.service.form.proxy.restartInfo",
316 "defaultMessage": "!!!Please restart Ferdi after changing proxy Settings.",
317 "file": "src/components/settings/services/EditServiceForm.js",
318 "start": {
319 "line": 119,
320 "column": 20
321 },
322 "end": {
323 "line": 122,
324 "column": 3
325 }
326 },
327 {
328 "id": "settings.service.form.proxy.info",
329 "defaultMessage": "!!!Proxy settings will not be synchronized with the Ferdi servers.",
330 "file": "src/components/settings/services/EditServiceForm.js",
331 "start": {
332 "line": 123,
333 "column": 13
334 },
335 "end": {
336 "line": 126,
337 "column": 3
338 }
339 }
340] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/services/ServiceError.json b/src/i18n/messages/src/components/settings/services/ServiceError.json
deleted file mode 100644
index 648fc5b3e..000000000
--- a/src/i18n/messages/src/components/settings/services/ServiceError.json
+++ /dev/null
@@ -1,54 +0,0 @@
1[
2 {
3 "id": "settings.service.error.headline",
4 "defaultMessage": "!!!Error",
5 "file": "src/components/settings/services/ServiceError.js",
6 "start": {
7 "line": 10,
8 "column": 12
9 },
10 "end": {
11 "line": 13,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.service.error.goBack",
17 "defaultMessage": "!!!Back to services",
18 "file": "src/components/settings/services/ServiceError.js",
19 "start": {
20 "line": 14,
21 "column": 10
22 },
23 "end": {
24 "line": 17,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.service.form.availableServices",
30 "defaultMessage": "!!!Available services",
31 "file": "src/components/settings/services/ServiceError.js",
32 "start": {
33 "line": 18,
34 "column": 21
35 },
36 "end": {
37 "line": 21,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.service.error.message",
43 "defaultMessage": "!!!Could not load service recipe.",
44 "file": "src/components/settings/services/ServiceError.js",
45 "start": {
46 "line": 22,
47 "column": 16
48 },
49 "end": {
50 "line": 25,
51 "column": 3
52 }
53 }
54] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/services/ServiceItem.json b/src/i18n/messages/src/components/settings/services/ServiceItem.json
deleted file mode 100644
index ffea8b9e1..000000000
--- a/src/i18n/messages/src/components/settings/services/ServiceItem.json
+++ /dev/null
@@ -1,41 +0,0 @@
1[
2 {
3 "id": "settings.services.tooltip.isDisabled",
4 "defaultMessage": "!!!Service is disabled",
5 "file": "src/components/settings/services/ServiceItem.js",
6 "start": {
7 "line": 11,
8 "column": 21
9 },
10 "end": {
11 "line": 14,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.services.tooltip.notificationsDisabled",
17 "defaultMessage": "!!!Notifications are disabled",
18 "file": "src/components/settings/services/ServiceItem.js",
19 "start": {
20 "line": 15,
21 "column": 32
22 },
23 "end": {
24 "line": 18,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.services.tooltip.isMuted",
30 "defaultMessage": "!!!All sounds are muted",
31 "file": "src/components/settings/services/ServiceItem.js",
32 "start": {
33 "line": 19,
34 "column": 18
35 },
36 "end": {
37 "line": 22,
38 "column": 3
39 }
40 }
41] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/services/ServicesDashboard.json b/src/i18n/messages/src/components/settings/services/ServicesDashboard.json
deleted file mode 100644
index 7e7c5d67e..000000000
--- a/src/i18n/messages/src/components/settings/services/ServicesDashboard.json
+++ /dev/null
@@ -1,119 +0,0 @@
1[
2 {
3 "id": "settings.services.headline",
4 "defaultMessage": "!!!Your services",
5 "file": "src/components/settings/services/ServicesDashboard.js",
6 "start": {
7 "line": 15,
8 "column": 12
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.searchService",
17 "defaultMessage": "!!!Search service",
18 "file": "src/components/settings/services/ServicesDashboard.js",
19 "start": {
20 "line": 19,
21 "column": 17
22 },
23 "end": {
24 "line": 22,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.services.noServicesAdded",
30 "defaultMessage": "!!!Start by adding a service.",
31 "file": "src/components/settings/services/ServicesDashboard.js",
32 "start": {
33 "line": 23,
34 "column": 19
35 },
36 "end": {
37 "line": 26,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.recipes.nothingFound",
43 "defaultMessage": "!!!Sorry, but no service matched your search term. Please note that the website might show more services that have been added to Ferdi since the version that you are currently on. To get those new services, please consider upgrading to a newer version of Ferdi.",
44 "file": "src/components/settings/services/ServicesDashboard.js",
45 "start": {
46 "line": 27,
47 "column": 18
48 },
49 "end": {
50 "line": 30,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.services.discoverServices",
56 "defaultMessage": "!!!Discover services",
57 "file": "src/components/settings/services/ServicesDashboard.js",
58 "start": {
59 "line": 31,
60 "column": 20
61 },
62 "end": {
63 "line": 34,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.services.servicesRequestFailed",
69 "defaultMessage": "!!!Could not load your services",
70 "file": "src/components/settings/services/ServicesDashboard.js",
71 "start": {
72 "line": 35,
73 "column": 25
74 },
75 "end": {
76 "line": 38,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.account.tryReloadServices",
82 "defaultMessage": "!!!Try again",
83 "file": "src/components/settings/services/ServicesDashboard.js",
84 "start": {
85 "line": 39,
86 "column": 21
87 },
88 "end": {
89 "line": 42,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.services.updatedInfo",
95 "defaultMessage": "!!!Your changes have been saved",
96 "file": "src/components/settings/services/ServicesDashboard.js",
97 "start": {
98 "line": 43,
99 "column": 15
100 },
101 "end": {
102 "line": 46,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.services.deletedInfo",
108 "defaultMessage": "!!!Service has been deleted",
109 "file": "src/components/settings/services/ServicesDashboard.js",
110 "start": {
111 "line": 47,
112 "column": 15
113 },
114 "end": {
115 "line": 50,
116 "column": 3
117 }
118 }
119] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json b/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json
deleted file mode 100644
index c281ebff3..000000000
--- a/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json
+++ /dev/null
@@ -1,444 +0,0 @@
1[
2 {
3 "id": "settings.app.headlineGeneral",
4 "defaultMessage": "!!!General",
5 "file": "src/components/settings/settings/EditSettingsForm.js",
6 "start": {
7 "line": 21,
8 "column": 19
9 },
10 "end": {
11 "line": 24,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.app.sentryInfo",
17 "defaultMessage": "!!!Sending telemetry data allows us to find errors in Ferdi - we will not send any personal information like your message data!",
18 "file": "src/components/settings/settings/EditSettingsForm.js",
19 "start": {
20 "line": 25,
21 "column": 14
22 },
23 "end": {
24 "line": 28,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.app.hibernateInfo",
30 "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.",
31 "file": "src/components/settings/settings/EditSettingsForm.js",
32 "start": {
33 "line": 29,
34 "column": 17
35 },
36 "end": {
37 "line": 32,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.app.inactivityLockInfo",
43 "defaultMessage": "!!!Minutes of inactivity, after which Ferdi should automatically lock. Use 0 to disable",
44 "file": "src/components/settings/settings/EditSettingsForm.js",
45 "start": {
46 "line": 33,
47 "column": 22
48 },
49 "end": {
50 "line": 36,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.app.todoServerInfo",
56 "defaultMessage": "!!!This server will be used for the \"Franz Todo\" feature. (default: https://app.franztodos.com)",
57 "file": "src/components/settings/settings/EditSettingsForm.js",
58 "start": {
59 "line": 37,
60 "column": 18
61 },
62 "end": {
63 "line": 40,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.app.lockedPassword",
69 "defaultMessage": "!!!Password",
70 "file": "src/components/settings/settings/EditSettingsForm.js",
71 "start": {
72 "line": 41,
73 "column": 18
74 },
75 "end": {
76 "line": 44,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.app.lockedPasswordInfo",
82 "defaultMessage": "!!!Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdi.",
83 "file": "src/components/settings/settings/EditSettingsForm.js",
84 "start": {
85 "line": 45,
86 "column": 22
87 },
88 "end": {
89 "line": 48,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.app.lockInfo",
95 "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}.",
96 "file": "src/components/settings/settings/EditSettingsForm.js",
97 "start": {
98 "line": 49,
99 "column": 12
100 },
101 "end": {
102 "line": 52,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.app.scheduledDNDTimeInfo",
108 "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.",
109 "file": "src/components/settings/settings/EditSettingsForm.js",
110 "start": {
111 "line": 53,
112 "column": 24
113 },
114 "end": {
115 "line": 56,
116 "column": 3
117 }
118 },
119 {
120 "id": "settings.app.scheduledDNDInfo",
121 "defaultMessage": "!!!Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.",
122 "file": "src/components/settings/settings/EditSettingsForm.js",
123 "start": {
124 "line": 57,
125 "column": 20
126 },
127 "end": {
128 "line": 60,
129 "column": 3
130 }
131 },
132 {
133 "id": "settings.app.headlineLanguage",
134 "defaultMessage": "!!!Language",
135 "file": "src/components/settings/settings/EditSettingsForm.js",
136 "start": {
137 "line": 61,
138 "column": 20
139 },
140 "end": {
141 "line": 64,
142 "column": 3
143 }
144 },
145 {
146 "id": "settings.app.headlineUpdates",
147 "defaultMessage": "!!!Updates",
148 "file": "src/components/settings/settings/EditSettingsForm.js",
149 "start": {
150 "line": 65,
151 "column": 19
152 },
153 "end": {
154 "line": 68,
155 "column": 3
156 }
157 },
158 {
159 "id": "settings.app.headlineAppearance",
160 "defaultMessage": "!!!Appearance",
161 "file": "src/components/settings/settings/EditSettingsForm.js",
162 "start": {
163 "line": 69,
164 "column": 22
165 },
166 "end": {
167 "line": 72,
168 "column": 3
169 }
170 },
171 {
172 "id": "settings.app.universalDarkModeInfo",
173 "defaultMessage": "!!!Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.",
174 "file": "src/components/settings/settings/EditSettingsForm.js",
175 "start": {
176 "line": 73,
177 "column": 25
178 },
179 "end": {
180 "line": 76,
181 "column": 3
182 }
183 },
184 {
185 "id": "settings.app.accentColorInfo",
186 "defaultMessage": "!!!Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})",
187 "file": "src/components/settings/settings/EditSettingsForm.js",
188 "start": {
189 "line": 77,
190 "column": 19
191 },
192 "end": {
193 "line": 80,
194 "column": 3
195 }
196 },
197 {
198 "id": "settings.app.headlinePrivacy",
199 "defaultMessage": "!!!Privacy",
200 "file": "src/components/settings/settings/EditSettingsForm.js",
201 "start": {
202 "line": 81,
203 "column": 19
204 },
205 "end": {
206 "line": 84,
207 "column": 3
208 }
209 },
210 {
211 "id": "settings.app.headlineAdvanced",
212 "defaultMessage": "!!!Advanced",
213 "file": "src/components/settings/settings/EditSettingsForm.js",
214 "start": {
215 "line": 85,
216 "column": 20
217 },
218 "end": {
219 "line": 88,
220 "column": 3
221 }
222 },
223 {
224 "id": "settings.app.translationHelp",
225 "defaultMessage": "!!!Help us to translate Ferdi into your language.",
226 "file": "src/components/settings/settings/EditSettingsForm.js",
227 "start": {
228 "line": 89,
229 "column": 19
230 },
231 "end": {
232 "line": 92,
233 "column": 3
234 }
235 },
236 {
237 "id": "settings.app.spellCheckerLanguageInfo",
238 "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.",
239 "file": "src/components/settings/settings/EditSettingsForm.js",
240 "start": {
241 "line": 93,
242 "column": 28
243 },
244 "end": {
245 "line": 96,
246 "column": 3
247 }
248 },
249 {
250 "id": "settings.app.subheadlineCache",
251 "defaultMessage": "!!!Cache",
252 "file": "src/components/settings/settings/EditSettingsForm.js",
253 "start": {
254 "line": 97,
255 "column": 20
256 },
257 "end": {
258 "line": 100,
259 "column": 3
260 }
261 },
262 {
263 "id": "settings.app.cacheInfo",
264 "defaultMessage": "!!!Ferdi cache is currently using {size} of disk space.",
265 "file": "src/components/settings/settings/EditSettingsForm.js",
266 "start": {
267 "line": 101,
268 "column": 13
269 },
270 "end": {
271 "line": 104,
272 "column": 3
273 }
274 },
275 {
276 "id": "settings.app.cacheNotCleared",
277 "defaultMessage": "!!!Couldn't clear all cache",
278 "file": "src/components/settings/settings/EditSettingsForm.js",
279 "start": {
280 "line": 105,
281 "column": 19
282 },
283 "end": {
284 "line": 108,
285 "column": 3
286 }
287 },
288 {
289 "id": "settings.app.buttonClearAllCache",
290 "defaultMessage": "!!!Clear cache",
291 "file": "src/components/settings/settings/EditSettingsForm.js",
292 "start": {
293 "line": 109,
294 "column": 23
295 },
296 "end": {
297 "line": 112,
298 "column": 3
299 }
300 },
301 {
302 "id": "settings.app.subheadlineFerdiProfile",
303 "defaultMessage": "!!!Ferdi Profile",
304 "file": "src/components/settings/settings/EditSettingsForm.js",
305 "start": {
306 "line": 113,
307 "column": 27
308 },
309 "end": {
310 "line": 116,
311 "column": 3
312 }
313 },
314 {
315 "id": "settings.app.buttonOpenFerdiProfileFolder",
316 "defaultMessage": "!!!Open Profile folder",
317 "file": "src/components/settings/settings/EditSettingsForm.js",
318 "start": {
319 "line": 117,
320 "column": 32
321 },
322 "end": {
323 "line": 120,
324 "column": 3
325 }
326 },
327 {
328 "id": "settings.app.buttonOpenFerdiServiceRecipesFolder",
329 "defaultMessage": "!!!Open Service Recipes folder",
330 "file": "src/components/settings/settings/EditSettingsForm.js",
331 "start": {
332 "line": 121,
333 "column": 39
334 },
335 "end": {
336 "line": 124,
337 "column": 3
338 }
339 },
340 {
341 "id": "settings.app.buttonSearchForUpdate",
342 "defaultMessage": "!!!Check for updates",
343 "file": "src/components/settings/settings/EditSettingsForm.js",
344 "start": {
345 "line": 125,
346 "column": 25
347 },
348 "end": {
349 "line": 128,
350 "column": 3
351 }
352 },
353 {
354 "id": "settings.app.buttonInstallUpdate",
355 "defaultMessage": "!!!Restart & install update",
356 "file": "src/components/settings/settings/EditSettingsForm.js",
357 "start": {
358 "line": 129,
359 "column": 23
360 },
361 "end": {
362 "line": 132,
363 "column": 3
364 }
365 },
366 {
367 "id": "settings.app.updateStatusSearching",
368 "defaultMessage": "!!!Is searching for update",
369 "file": "src/components/settings/settings/EditSettingsForm.js",
370 "start": {
371 "line": 133,
372 "column": 25
373 },
374 "end": {
375 "line": 136,
376 "column": 3
377 }
378 },
379 {
380 "id": "settings.app.updateStatusAvailable",
381 "defaultMessage": "!!!Update available, downloading...",
382 "file": "src/components/settings/settings/EditSettingsForm.js",
383 "start": {
384 "line": 137,
385 "column": 25
386 },
387 "end": {
388 "line": 140,
389 "column": 3
390 }
391 },
392 {
393 "id": "settings.app.updateStatusUpToDate",
394 "defaultMessage": "!!!You are using the latest version of Ferdi",
395 "file": "src/components/settings/settings/EditSettingsForm.js",
396 "start": {
397 "line": 141,
398 "column": 24
399 },
400 "end": {
401 "line": 144,
402 "column": 3
403 }
404 },
405 {
406 "id": "settings.app.currentVersion",
407 "defaultMessage": "!!!Current version:",
408 "file": "src/components/settings/settings/EditSettingsForm.js",
409 "start": {
410 "line": 145,
411 "column": 18
412 },
413 "end": {
414 "line": 148,
415 "column": 3
416 }
417 },
418 {
419 "id": "settings.app.restartRequired",
420 "defaultMessage": "!!!Changes require restart",
421 "file": "src/components/settings/settings/EditSettingsForm.js",
422 "start": {
423 "line": 149,
424 "column": 22
425 },
426 "end": {
427 "line": 152,
428 "column": 3
429 }
430 },
431 {
432 "id": "settings.app.languageDisclaimer",
433 "defaultMessage": "!!!Official translations are English & German. All other languages are community based translations.",
434 "file": "src/components/settings/settings/EditSettingsForm.js",
435 "start": {
436 "line": 153,
437 "column": 22
438 },
439 "end": {
440 "line": 156,
441 "column": 3
442 }
443 }
444] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/supportFerdi/SupportFerdiDashboard.json b/src/i18n/messages/src/components/settings/supportFerdi/SupportFerdiDashboard.json
deleted file mode 100644
index e63c2801f..000000000
--- a/src/i18n/messages/src/components/settings/supportFerdi/SupportFerdiDashboard.json
+++ /dev/null
@@ -1,197 +0,0 @@
1[
2 {
3 "id": "settings.supportFerdi.headline",
4 "defaultMessage": "!!!About Ferdi",
5 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
6 "start": {
7 "line": 7,
8 "column": 12
9 },
10 "end": {
11 "line": 10,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.supportFerdi.title",
17 "defaultMessage": "!!!Do you like Ferdi?",
18 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
19 "start": {
20 "line": 11,
21 "column": 9
22 },
23 "end": {
24 "line": 14,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.supportFerdi.aboutIntro",
30 "defaultMessage": "!!!<p>Ferdi is an open-source and a community-lead application.</p><p>Thanks to the people who make this possbile:</p>",
31 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
32 "start": {
33 "line": 15,
34 "column": 14
35 },
36 "end": {
37 "line": 18,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.supportFerdi.textListContributors",
43 "defaultMessage": "!!!Full list of contributor",
44 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
45 "start": {
46 "line": 19,
47 "column": 24
48 },
49 "end": {
50 "line": 22,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.supportFerdi.textListContributorsHere",
56 "defaultMessage": "!!!here",
57 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
58 "start": {
59 "line": 23,
60 "column": 28
61 },
62 "end": {
63 "line": 26,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.supportFerdi.textVolunteers",
69 "defaultMessage": "!!!The development of Ferdi is done by volunteers. People who use Ferdi like you. They maintain, fix, and improve Ferdi in their spare time.",
70 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
71 "start": {
72 "line": 27,
73 "column": 18
74 },
75 "end": {
76 "line": 30,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.supportFerdi.textSupportWelcome",
82 "defaultMessage": "!!!Support is always welcome. You can find a list of the help we need",
83 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
84 "start": {
85 "line": 31,
86 "column": 22
87 },
88 "end": {
89 "line": 34,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.supportFerdi.textSupportWelcomeHere",
95 "defaultMessage": "!!!here",
96 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
97 "start": {
98 "line": 35,
99 "column": 26
100 },
101 "end": {
102 "line": 38,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.supportFerdi.textExpenses",
108 "defaultMessage": "!!!While volunteers do most of the work, we still need to pay for servers and certificates. As a community, we are fully transparent on funds we collect and spend - see our",
109 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
110 "start": {
111 "line": 39,
112 "column": 16
113 },
114 "end": {
115 "line": 42,
116 "column": 3
117 }
118 },
119 {
120 "id": "settings.supportFerdi.textOpenCollective",
121 "defaultMessage": "!!!Open Collective",
122 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
123 "start": {
124 "line": 43,
125 "column": 22
126 },
127 "end": {
128 "line": 46,
129 "column": 3
130 }
131 },
132 {
133 "id": "settings.supportFerdi.textDonation",
134 "defaultMessage": "!!!If you feel like supporting Ferdi development with a donation, you can do so on both,",
135 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
136 "start": {
137 "line": 47,
138 "column": 16
139 },
140 "end": {
141 "line": 50,
142 "column": 3
143 }
144 },
145 {
146 "id": "settings.supportFerdi.textDonationAnd",
147 "defaultMessage": "!!!and",
148 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
149 "start": {
150 "line": 51,
151 "column": 19
152 },
153 "end": {
154 "line": 54,
155 "column": 3
156 }
157 },
158 {
159 "id": "settings.supportFerdi.textGitHubSponsors",
160 "defaultMessage": "!!!GitHub Sponsors",
161 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
162 "start": {
163 "line": 55,
164 "column": 22
165 },
166 "end": {
167 "line": 58,
168 "column": 3
169 }
170 },
171 {
172 "id": "settings.supportFerdi.openSurvey",
173 "defaultMessage": "!!!Open Survey",
174 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
175 "start": {
176 "line": 59,
177 "column": 14
178 },
179 "end": {
180 "line": 62,
181 "column": 3
182 }
183 },
184 {
185 "id": "settings.supportFerdi.bannerText",
186 "defaultMessage": "!!!Do you want to help us improve Ferdi?",
187 "file": "src/components/settings/supportFerdi/SupportFerdiDashboard.js",
188 "start": {
189 "line": 63,
190 "column": 14
191 },
192 "end": {
193 "line": 66,
194 "column": 3
195 }
196 }
197] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/team/TeamDashboard.json b/src/i18n/messages/src/components/settings/team/TeamDashboard.json
deleted file mode 100644
index ac42ad98a..000000000
--- a/src/i18n/messages/src/components/settings/team/TeamDashboard.json
+++ /dev/null
@@ -1,93 +0,0 @@
1[
2 {
3 "id": "settings.team.headline",
4 "defaultMessage": "!!!Team",
5 "file": "src/components/settings/team/TeamDashboard.js",
6 "start": {
7 "line": 15,
8 "column": 12
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.team.contentHeadline",
17 "defaultMessage": "!!!Franz Team Management",
18 "file": "src/components/settings/team/TeamDashboard.js",
19 "start": {
20 "line": 19,
21 "column": 19
22 },
23 "end": {
24 "line": 22,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.team.intro",
30 "defaultMessage": "!!!Your are currently using Franz Servers, which is why you have access to Team Management.",
31 "file": "src/components/settings/team/TeamDashboard.js",
32 "start": {
33 "line": 23,
34 "column": 9
35 },
36 "end": {
37 "line": 26,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.team.copy",
43 "defaultMessage": "!!!Franz's Team Management allows you to manage Franz Subscriptions for multiple users. Please keep in mind that having a Franz Premium subscription will give you no advantages in using Ferdi: The only reason you still have access to Team Management is so you can manage your legacy Franz Teams and so that you don't loose any functionality in managing your account.",
44 "file": "src/components/settings/team/TeamDashboard.js",
45 "start": {
46 "line": 27,
47 "column": 8
48 },
49 "end": {
50 "line": 30,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.team.manageAction",
56 "defaultMessage": "!!!Manage your Team on meetfranz.com",
57 "file": "src/components/settings/team/TeamDashboard.js",
58 "start": {
59 "line": 31,
60 "column": 16
61 },
62 "end": {
63 "line": 34,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.team.teamsUnavailable",
69 "defaultMessage": "!!!Teams are unavailable",
70 "file": "src/components/settings/team/TeamDashboard.js",
71 "start": {
72 "line": 35,
73 "column": 20
74 },
75 "end": {
76 "line": 38,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.team.teamsUnavailableInfo",
82 "defaultMessage": "!!!Teams are currently only available when using the Franz Server and after paying for Franz Professional. Please change your server to https://api.franzinfra.com to use teams.",
83 "file": "src/components/settings/team/TeamDashboard.js",
84 "start": {
85 "line": 39,
86 "column": 24
87 },
88 "end": {
89 "line": 42,
90 "column": 3
91 }
92 }
93] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/settings/user/EditUserForm.json b/src/i18n/messages/src/components/settings/user/EditUserForm.json
deleted file mode 100644
index 3a59f8681..000000000
--- a/src/i18n/messages/src/components/settings/user/EditUserForm.json
+++ /dev/null
@@ -1,80 +0,0 @@
1[
2 {
3 "id": "settings.account.headline",
4 "defaultMessage": "!!!Account",
5 "file": "src/components/settings/user/EditUserForm.js",
6 "start": {
7 "line": 15,
8 "column": 12
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.account.headlineProfile",
17 "defaultMessage": "!!!Update Profile",
18 "file": "src/components/settings/user/EditUserForm.js",
19 "start": {
20 "line": 19,
21 "column": 19
22 },
23 "end": {
24 "line": 22,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.account.headlineAccount",
30 "defaultMessage": "!!!Account Information",
31 "file": "src/components/settings/user/EditUserForm.js",
32 "start": {
33 "line": 23,
34 "column": 19
35 },
36 "end": {
37 "line": 26,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.account.headlinePassword",
43 "defaultMessage": "!!!Change Password",
44 "file": "src/components/settings/user/EditUserForm.js",
45 "start": {
46 "line": 27,
47 "column": 20
48 },
49 "end": {
50 "line": 30,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.account.successInfo",
56 "defaultMessage": "!!!Your changes have been saved",
57 "file": "src/components/settings/user/EditUserForm.js",
58 "start": {
59 "line": 31,
60 "column": 15
61 },
62 "end": {
63 "line": 34,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.account.buttonSave",
69 "defaultMessage": "!!!Update profile",
70 "file": "src/components/settings/user/EditUserForm.js",
71 "start": {
72 "line": 35,
73 "column": 14
74 },
75 "end": {
76 "line": 38,
77 "column": 3
78 }
79 }
80] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/ui/FeatureList.json b/src/i18n/messages/src/components/ui/FeatureList.json
deleted file mode 100644
index eb4bc483b..000000000
--- a/src/i18n/messages/src/components/ui/FeatureList.json
+++ /dev/null
@@ -1,145 +0,0 @@
1[
2 {
3 "id": "pricing.features.recipes",
4 "defaultMessage": "!!!Choose from more than 70 Services",
5 "file": "src/components/ui/FeatureList.js",
6 "start": {
7 "line": 8,
8 "column": 20
9 },
10 "end": {
11 "line": 11,
12 "column": 3
13 }
14 },
15 {
16 "id": "pricing.features.accountSync",
17 "defaultMessage": "!!!Account Synchronisation",
18 "file": "src/components/ui/FeatureList.js",
19 "start": {
20 "line": 12,
21 "column": 15
22 },
23 "end": {
24 "line": 15,
25 "column": 3
26 }
27 },
28 {
29 "id": "pricing.features.desktopNotifications",
30 "defaultMessage": "!!!Desktop Notifications",
31 "file": "src/components/ui/FeatureList.js",
32 "start": {
33 "line": 16,
34 "column": 24
35 },
36 "end": {
37 "line": 19,
38 "column": 3
39 }
40 },
41 {
42 "id": "pricing.features.unlimitedServices",
43 "defaultMessage": "!!!Add unlimited services",
44 "file": "src/components/ui/FeatureList.js",
45 "start": {
46 "line": 20,
47 "column": 21
48 },
49 "end": {
50 "line": 23,
51 "column": 3
52 }
53 },
54 {
55 "id": "pricing.features.spellchecker",
56 "defaultMessage": "!!!Spellchecker support",
57 "file": "src/components/ui/FeatureList.js",
58 "start": {
59 "line": 24,
60 "column": 16
61 },
62 "end": {
63 "line": 27,
64 "column": 3
65 }
66 },
67 {
68 "id": "pricing.features.workspaces",
69 "defaultMessage": "!!!Workspaces",
70 "file": "src/components/ui/FeatureList.js",
71 "start": {
72 "line": 28,
73 "column": 14
74 },
75 "end": {
76 "line": 31,
77 "column": 3
78 }
79 },
80 {
81 "id": "pricing.features.customWebsites",
82 "defaultMessage": "!!!Add Custom Websites",
83 "file": "src/components/ui/FeatureList.js",
84 "start": {
85 "line": 32,
86 "column": 18
87 },
88 "end": {
89 "line": 35,
90 "column": 3
91 }
92 },
93 {
94 "id": "pricing.features.onPremise",
95 "defaultMessage": "!!!On-premise & other Hosted Services",
96 "file": "src/components/ui/FeatureList.js",
97 "start": {
98 "line": 36,
99 "column": 13
100 },
101 "end": {
102 "line": 39,
103 "column": 3
104 }
105 },
106 {
107 "id": "pricing.features.thirdPartyServices",
108 "defaultMessage": "!!!Install 3rd party services",
109 "file": "src/components/ui/FeatureList.js",
110 "start": {
111 "line": 40,
112 "column": 22
113 },
114 "end": {
115 "line": 43,
116 "column": 3
117 }
118 },
119 {
120 "id": "pricing.features.serviceProxies",
121 "defaultMessage": "!!!Service Proxies",
122 "file": "src/components/ui/FeatureList.js",
123 "start": {
124 "line": 44,
125 "column": 18
126 },
127 "end": {
128 "line": 47,
129 "column": 3
130 }
131 },
132 {
133 "id": "pricing.features.teamManagement",
134 "defaultMessage": "!!!Team Management",
135 "file": "src/components/ui/FeatureList.js",
136 "start": {
137 "line": 48,
138 "column": 18
139 },
140 "end": {
141 "line": 51,
142 "column": 3
143 }
144 }
145] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/ui/InfoBar.json b/src/i18n/messages/src/components/ui/InfoBar.json
deleted file mode 100644
index a6a629c71..000000000
--- a/src/i18n/messages/src/components/ui/InfoBar.json
+++ /dev/null
@@ -1,15 +0,0 @@
1[
2 {
3 "id": "infobar.hide",
4 "defaultMessage": "!!!Hide",
5 "file": "src/components/ui/InfoBar.js",
6 "start": {
7 "line": 12,
8 "column": 8
9 },
10 "end": {
11 "line": 15,
12 "column": 3
13 }
14 }
15] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/ui/Infobox.json b/src/i18n/messages/src/components/ui/Infobox.json
deleted file mode 100644
index 296c2ad3e..000000000
--- a/src/i18n/messages/src/components/ui/Infobox.json
+++ /dev/null
@@ -1,15 +0,0 @@
1[
2 {
3 "id": "infobox.dismiss",
4 "defaultMessage": "!!!Dismiss",
5 "file": "src/components/ui/Infobox.js",
6 "start": {
7 "line": 9,
8 "column": 11
9 },
10 "end": {
11 "line": 12,
12 "column": 3
13 }
14 }
15] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/ui/Input.json b/src/i18n/messages/src/components/ui/Input.json
deleted file mode 100644
index 6240badfb..000000000
--- a/src/i18n/messages/src/components/ui/Input.json
+++ /dev/null
@@ -1,15 +0,0 @@
1[
2 {
3 "id": "settings.app.form.passwordToggle",
4 "defaultMessage": "!!!Password toggle",
5 "file": "src/components/ui/Input.js",
6 "start": {
7 "line": 11,
8 "column": 18
9 },
10 "end": {
11 "line": 14,
12 "column": 3
13 }
14 }
15] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/ui/WebviewLoader/index.json b/src/i18n/messages/src/components/ui/WebviewLoader/index.json
deleted file mode 100644
index 9caabef25..000000000
--- a/src/i18n/messages/src/components/ui/WebviewLoader/index.json
+++ /dev/null
@@ -1,15 +0,0 @@
1[
2 {
3 "id": "service.webviewLoader.loading",
4 "defaultMessage": "!!!Loading {service}",
5 "file": "src/components/ui/WebviewLoader/index.js",
6 "start": {
7 "line": 11,
8 "column": 11
9 },
10 "end": {
11 "line": 14,
12 "column": 3
13 }
14 }
15] \ No newline at end of file
diff --git a/src/i18n/messages/src/components/util/ErrorBoundary/index.json b/src/i18n/messages/src/components/util/ErrorBoundary/index.json
deleted file mode 100644
index 43c323031..000000000
--- a/src/i18n/messages/src/components/util/ErrorBoundary/index.json
+++ /dev/null
@@ -1,28 +0,0 @@
1[
2 {
3 "id": "app.errorHandler.headline",
4 "defaultMessage": "!!!Something went wrong.",
5 "file": "src/components/util/ErrorBoundary/index.js",
6 "start": {
7 "line": 11,
8 "column": 12
9 },
10 "end": {
11 "line": 14,
12 "column": 3
13 }
14 },
15 {
16 "id": "app.errorHandler.action",
17 "defaultMessage": "!!!Reload",
18 "file": "src/components/util/ErrorBoundary/index.js",
19 "start": {
20 "line": 15,
21 "column": 10
22 },
23 "end": {
24 "line": 18,
25 "column": 3
26 }
27 }
28] \ No newline at end of file
diff --git a/src/i18n/messages/src/containers/settings/EditServiceScreen.json b/src/i18n/messages/src/containers/settings/EditServiceScreen.json
deleted file mode 100644
index 6744a9ff3..000000000
--- a/src/i18n/messages/src/containers/settings/EditServiceScreen.json
+++ /dev/null
@@ -1,249 +0,0 @@
1[
2 {
3 "id": "settings.service.form.name",
4 "defaultMessage": "!!!Name",
5 "file": "src/containers/settings/EditServiceScreen.js",
6 "start": {
7 "line": 28,
8 "column": 8
9 },
10 "end": {
11 "line": 31,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.service.form.enableService",
17 "defaultMessage": "!!!Enable service",
18 "file": "src/containers/settings/EditServiceScreen.js",
19 "start": {
20 "line": 32,
21 "column": 17
22 },
23 "end": {
24 "line": 35,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.service.form.enableHibernation",
30 "defaultMessage": "!!!Enable hibernation",
31 "file": "src/containers/settings/EditServiceScreen.js",
32 "start": {
33 "line": 36,
34 "column": 21
35 },
36 "end": {
37 "line": 39,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.service.form.enableNotification",
43 "defaultMessage": "!!!Enable Notifications",
44 "file": "src/containers/settings/EditServiceScreen.js",
45 "start": {
46 "line": 40,
47 "column": 22
48 },
49 "end": {
50 "line": 43,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.service.form.enableBadge",
56 "defaultMessage": "!!!Show unread message badges",
57 "file": "src/containers/settings/EditServiceScreen.js",
58 "start": {
59 "line": 44,
60 "column": 15
61 },
62 "end": {
63 "line": 47,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.service.form.enableAudio",
69 "defaultMessage": "!!!Enable audio",
70 "file": "src/containers/settings/EditServiceScreen.js",
71 "start": {
72 "line": 48,
73 "column": 15
74 },
75 "end": {
76 "line": 51,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.service.form.team",
82 "defaultMessage": "!!!Team",
83 "file": "src/containers/settings/EditServiceScreen.js",
84 "start": {
85 "line": 52,
86 "column": 8
87 },
88 "end": {
89 "line": 55,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.service.form.customUrl",
95 "defaultMessage": "!!!Service URL",
96 "file": "src/containers/settings/EditServiceScreen.js",
97 "start": {
98 "line": 56,
99 "column": 13
100 },
101 "end": {
102 "line": 59,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.service.form.indirectMessages",
108 "defaultMessage": "!!!Show message badge for all new messages",
109 "file": "src/containers/settings/EditServiceScreen.js",
110 "start": {
111 "line": 60,
112 "column": 20
113 },
114 "end": {
115 "line": 63,
116 "column": 3
117 }
118 },
119 {
120 "id": "settings.service.form.icon",
121 "defaultMessage": "!!!Custom icon",
122 "file": "src/containers/settings/EditServiceScreen.js",
123 "start": {
124 "line": 64,
125 "column": 8
126 },
127 "end": {
128 "line": 67,
129 "column": 3
130 }
131 },
132 {
133 "id": "settings.service.form.enableDarkMode",
134 "defaultMessage": "!!!Enable Dark Mode",
135 "file": "src/containers/settings/EditServiceScreen.js",
136 "start": {
137 "line": 68,
138 "column": 18
139 },
140 "end": {
141 "line": 71,
142 "column": 3
143 }
144 },
145 {
146 "id": "settings.service.form.darkReaderBrightness",
147 "defaultMessage": "!!!Dark Reader Brightness",
148 "file": "src/containers/settings/EditServiceScreen.js",
149 "start": {
150 "line": 72,
151 "column": 24
152 },
153 "end": {
154 "line": 75,
155 "column": 3
156 }
157 },
158 {
159 "id": "settings.service.form.darkReaderContrast",
160 "defaultMessage": "!!!Dark Reader Contrast",
161 "file": "src/containers/settings/EditServiceScreen.js",
162 "start": {
163 "line": 76,
164 "column": 22
165 },
166 "end": {
167 "line": 79,
168 "column": 3
169 }
170 },
171 {
172 "id": "settings.service.form.darkReaderSepia",
173 "defaultMessage": "!!!Dark Reader Sepia",
174 "file": "src/containers/settings/EditServiceScreen.js",
175 "start": {
176 "line": 80,
177 "column": 19
178 },
179 "end": {
180 "line": 83,
181 "column": 3
182 }
183 },
184 {
185 "id": "settings.service.form.proxy.isEnabled",
186 "defaultMessage": "!!!Use Proxy",
187 "file": "src/containers/settings/EditServiceScreen.js",
188 "start": {
189 "line": 84,
190 "column": 15
191 },
192 "end": {
193 "line": 87,
194 "column": 3
195 }
196 },
197 {
198 "id": "settings.service.form.proxy.host",
199 "defaultMessage": "!!!Proxy Host/IP",
200 "file": "src/containers/settings/EditServiceScreen.js",
201 "start": {
202 "line": 88,
203 "column": 13
204 },
205 "end": {
206 "line": 91,
207 "column": 3
208 }
209 },
210 {
211 "id": "settings.service.form.proxy.port",
212 "defaultMessage": "!!!Port",
213 "file": "src/containers/settings/EditServiceScreen.js",
214 "start": {
215 "line": 92,
216 "column": 13
217 },
218 "end": {
219 "line": 95,
220 "column": 3
221 }
222 },
223 {
224 "id": "settings.service.form.proxy.user",
225 "defaultMessage": "!!!User",
226 "file": "src/containers/settings/EditServiceScreen.js",
227 "start": {
228 "line": 96,
229 "column": 13
230 },
231 "end": {
232 "line": 99,
233 "column": 3
234 }
235 },
236 {
237 "id": "settings.service.form.proxy.password",
238 "defaultMessage": "!!!Password",
239 "file": "src/containers/settings/EditServiceScreen.js",
240 "start": {
241 "line": 100,
242 "column": 17
243 },
244 "end": {
245 "line": 103,
246 "column": 3
247 }
248 }
249] \ No newline at end of file
diff --git a/src/i18n/messages/src/containers/settings/EditSettingsScreen.json b/src/i18n/messages/src/containers/settings/EditSettingsScreen.json
deleted file mode 100644
index b0087e5dd..000000000
--- a/src/i18n/messages/src/containers/settings/EditSettingsScreen.json
+++ /dev/null
@@ -1,600 +0,0 @@
1[
2 {
3 "id": "settings.app.form.autoLaunchOnStart",
4 "defaultMessage": "!!!Launch Ferdi on start",
5 "file": "src/containers/settings/EditSettingsScreen.js",
6 "start": {
7 "line": 32,
8 "column": 21
9 },
10 "end": {
11 "line": 35,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.app.form.autoLaunchInBackground",
17 "defaultMessage": "!!!Open in background",
18 "file": "src/containers/settings/EditSettingsScreen.js",
19 "start": {
20 "line": 36,
21 "column": 26
22 },
23 "end": {
24 "line": 39,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.app.form.runInBackground",
30 "defaultMessage": "!!!Keep Ferdi in background when closing the window",
31 "file": "src/containers/settings/EditSettingsScreen.js",
32 "start": {
33 "line": 40,
34 "column": 19
35 },
36 "end": {
37 "line": 43,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.app.form.startMinimized",
43 "defaultMessage": "!!!Start minimized",
44 "file": "src/containers/settings/EditSettingsScreen.js",
45 "start": {
46 "line": 44,
47 "column": 18
48 },
49 "end": {
50 "line": 47,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.app.form.confirmOnQuit",
56 "defaultMessage": "!!!Confirm when quitting Ferdi",
57 "file": "src/containers/settings/EditSettingsScreen.js",
58 "start": {
59 "line": 48,
60 "column": 17
61 },
62 "end": {
63 "line": 51,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.app.form.enableSystemTray",
69 "defaultMessage": "!!!Always show Ferdi in System Tray",
70 "file": "src/containers/settings/EditSettingsScreen.js",
71 "start": {
72 "line": 52,
73 "column": 20
74 },
75 "end": {
76 "line": 55,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.app.form.enableMenuBar",
82 "defaultMessage": "!!!Always show Ferdi in Menu Bar",
83 "file": "src/containers/settings/EditSettingsScreen.js",
84 "start": {
85 "line": 56,
86 "column": 17
87 },
88 "end": {
89 "line": 59,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.app.form.reloadAfterResume",
95 "defaultMessage": "!!!Reload Ferdi after system resume",
96 "file": "src/containers/settings/EditSettingsScreen.js",
97 "start": {
98 "line": 60,
99 "column": 21
100 },
101 "end": {
102 "line": 63,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.app.form.minimizeToSystemTray",
108 "defaultMessage": "!!!Minimize Ferdi to system tray",
109 "file": "src/containers/settings/EditSettingsScreen.js",
110 "start": {
111 "line": 64,
112 "column": 24
113 },
114 "end": {
115 "line": 67,
116 "column": 3
117 }
118 },
119 {
120 "id": "settings.app.form.closeToSystemTray",
121 "defaultMessage": "!!!Close Ferdi to system tray",
122 "file": "src/containers/settings/EditSettingsScreen.js",
123 "start": {
124 "line": 68,
125 "column": 21
126 },
127 "end": {
128 "line": 71,
129 "column": 3
130 }
131 },
132 {
133 "id": "settings.app.form.privateNotifications",
134 "defaultMessage": "!!!Don't show message content in notifications",
135 "file": "src/containers/settings/EditSettingsScreen.js",
136 "start": {
137 "line": 72,
138 "column": 24
139 },
140 "end": {
141 "line": 75,
142 "column": 3
143 }
144 },
145 {
146 "id": "settings.app.form.clipboardNotifications",
147 "defaultMessage": "!!!Don't show notifications for clipboard events",
148 "file": "src/containers/settings/EditSettingsScreen.js",
149 "start": {
150 "line": 76,
151 "column": 26
152 },
153 "end": {
154 "line": 79,
155 "column": 3
156 }
157 },
158 {
159 "id": "settings.app.form.notifyTaskBarOnMessage",
160 "defaultMessage": "!!!Notify TaskBar/Dock on new message",
161 "file": "src/containers/settings/EditSettingsScreen.js",
162 "start": {
163 "line": 80,
164 "column": 26
165 },
166 "end": {
167 "line": 83,
168 "column": 3
169 }
170 },
171 {
172 "id": "settings.app.form.navigationBarBehaviour",
173 "defaultMessage": "!!!Navigation bar behaviour",
174 "file": "src/containers/settings/EditSettingsScreen.js",
175 "start": {
176 "line": 84,
177 "column": 26
178 },
179 "end": {
180 "line": 87,
181 "column": 3
182 }
183 },
184 {
185 "id": "settings.app.form.searchEngine",
186 "defaultMessage": "!!!Search engine",
187 "file": "src/containers/settings/EditSettingsScreen.js",
188 "start": {
189 "line": 88,
190 "column": 16
191 },
192 "end": {
193 "line": 91,
194 "column": 3
195 }
196 },
197 {
198 "id": "settings.app.form.sentry",
199 "defaultMessage": "!!!Send telemetry data",
200 "file": "src/containers/settings/EditSettingsScreen.js",
201 "start": {
202 "line": 92,
203 "column": 10
204 },
205 "end": {
206 "line": 95,
207 "column": 3
208 }
209 },
210 {
211 "id": "settings.app.form.hibernateOnStartup",
212 "defaultMessage": "!!!Keep services in hibernation on startup",
213 "file": "src/containers/settings/EditSettingsScreen.js",
214 "start": {
215 "line": 96,
216 "column": 22
217 },
218 "end": {
219 "line": 99,
220 "column": 3
221 }
222 },
223 {
224 "id": "settings.app.form.hibernationStrategy",
225 "defaultMessage": "!!!Hibernation strategy",
226 "file": "src/containers/settings/EditSettingsScreen.js",
227 "start": {
228 "line": 100,
229 "column": 23
230 },
231 "end": {
232 "line": 103,
233 "column": 3
234 }
235 },
236 {
237 "id": "settings.app.form.wakeUpStrategy",
238 "defaultMessage": "!!!Wake up strategy",
239 "file": "src/containers/settings/EditSettingsScreen.js",
240 "start": {
241 "line": 104,
242 "column": 18
243 },
244 "end": {
245 "line": 107,
246 "column": 3
247 }
248 },
249 {
250 "id": "settings.app.form.predefinedTodoServer",
251 "defaultMessage": "!!!Todo Server",
252 "file": "src/containers/settings/EditSettingsScreen.js",
253 "start": {
254 "line": 108,
255 "column": 24
256 },
257 "end": {
258 "line": 111,
259 "column": 3
260 }
261 },
262 {
263 "id": "settings.app.form.customTodoServer",
264 "defaultMessage": "!!!Custom TodoServer",
265 "file": "src/containers/settings/EditSettingsScreen.js",
266 "start": {
267 "line": 112,
268 "column": 20
269 },
270 "end": {
271 "line": 115,
272 "column": 3
273 }
274 },
275 {
276 "id": "settings.app.form.enableLock",
277 "defaultMessage": "!!!Enable Password Lock",
278 "file": "src/containers/settings/EditSettingsScreen.js",
279 "start": {
280 "line": 116,
281 "column": 14
282 },
283 "end": {
284 "line": 119,
285 "column": 3
286 }
287 },
288 {
289 "id": "settings.app.form.lockPassword",
290 "defaultMessage": "!!!Password",
291 "file": "src/containers/settings/EditSettingsScreen.js",
292 "start": {
293 "line": 120,
294 "column": 16
295 },
296 "end": {
297 "line": 123,
298 "column": 3
299 }
300 },
301 {
302 "id": "settings.app.form.useTouchIdToUnlock",
303 "defaultMessage": "!!!Allow using Touch ID to unlock",
304 "file": "src/containers/settings/EditSettingsScreen.js",
305 "start": {
306 "line": 124,
307 "column": 22
308 },
309 "end": {
310 "line": 127,
311 "column": 3
312 }
313 },
314 {
315 "id": "settings.app.form.inactivityLock",
316 "defaultMessage": "!!!Lock after inactivity",
317 "file": "src/containers/settings/EditSettingsScreen.js",
318 "start": {
319 "line": 128,
320 "column": 18
321 },
322 "end": {
323 "line": 131,
324 "column": 3
325 }
326 },
327 {
328 "id": "settings.app.form.scheduledDNDEnabled",
329 "defaultMessage": "!!!Enable scheduled Do-not-Disturb",
330 "file": "src/containers/settings/EditSettingsScreen.js",
331 "start": {
332 "line": 132,
333 "column": 23
334 },
335 "end": {
336 "line": 135,
337 "column": 3
338 }
339 },
340 {
341 "id": "settings.app.form.scheduledDNDStart",
342 "defaultMessage": "!!!From",
343 "file": "src/containers/settings/EditSettingsScreen.js",
344 "start": {
345 "line": 136,
346 "column": 21
347 },
348 "end": {
349 "line": 139,
350 "column": 3
351 }
352 },
353 {
354 "id": "settings.app.form.scheduledDNDEnd",
355 "defaultMessage": "!!!To",
356 "file": "src/containers/settings/EditSettingsScreen.js",
357 "start": {
358 "line": 140,
359 "column": 19
360 },
361 "end": {
362 "line": 143,
363 "column": 3
364 }
365 },
366 {
367 "id": "settings.app.form.language",
368 "defaultMessage": "!!!Language",
369 "file": "src/containers/settings/EditSettingsScreen.js",
370 "start": {
371 "line": 144,
372 "column": 12
373 },
374 "end": {
375 "line": 147,
376 "column": 3
377 }
378 },
379 {
380 "id": "settings.app.form.darkMode",
381 "defaultMessage": "!!!Dark Mode",
382 "file": "src/containers/settings/EditSettingsScreen.js",
383 "start": {
384 "line": 148,
385 "column": 12
386 },
387 "end": {
388 "line": 151,
389 "column": 3
390 }
391 },
392 {
393 "id": "settings.app.form.adaptableDarkMode",
394 "defaultMessage": "!!!Synchronize dark mode with my OS's dark mode setting",
395 "file": "src/containers/settings/EditSettingsScreen.js",
396 "start": {
397 "line": 152,
398 "column": 21
399 },
400 "end": {
401 "line": 155,
402 "column": 3
403 }
404 },
405 {
406 "id": "settings.app.form.universalDarkMode",
407 "defaultMessage": "!!!Enable universal Dark Mode",
408 "file": "src/containers/settings/EditSettingsScreen.js",
409 "start": {
410 "line": 156,
411 "column": 21
412 },
413 "end": {
414 "line": 159,
415 "column": 3
416 }
417 },
418 {
419 "id": "settings.app.form.serviceRibbonWidth",
420 "defaultMessage": "!!!Sidebar width",
421 "file": "src/containers/settings/EditSettingsScreen.js",
422 "start": {
423 "line": 160,
424 "column": 22
425 },
426 "end": {
427 "line": 163,
428 "column": 3
429 }
430 },
431 {
432 "id": "settings.app.form.iconSize",
433 "defaultMessage": "!!!Service icon size",
434 "file": "src/containers/settings/EditSettingsScreen.js",
435 "start": {
436 "line": 164,
437 "column": 12
438 },
439 "end": {
440 "line": 167,
441 "column": 3
442 }
443 },
444 {
445 "id": "settings.app.form.useVerticalStyle",
446 "defaultMessage": "!!!Use horizontal style",
447 "file": "src/containers/settings/EditSettingsScreen.js",
448 "start": {
449 "line": 168,
450 "column": 20
451 },
452 "end": {
453 "line": 171,
454 "column": 3
455 }
456 },
457 {
458 "id": "settings.app.form.alwaysShowWorkspaces",
459 "defaultMessage": "!!!Always show workspace drawer",
460 "file": "src/containers/settings/EditSettingsScreen.js",
461 "start": {
462 "line": 172,
463 "column": 24
464 },
465 "end": {
466 "line": 175,
467 "column": 3
468 }
469 },
470 {
471 "id": "settings.app.form.accentColor",
472 "defaultMessage": "!!!Accent color",
473 "file": "src/containers/settings/EditSettingsScreen.js",
474 "start": {
475 "line": 176,
476 "column": 15
477 },
478 "end": {
479 "line": 179,
480 "column": 3
481 }
482 },
483 {
484 "id": "settings.app.form.showDisabledServices",
485 "defaultMessage": "!!!Display disabled services tabs",
486 "file": "src/containers/settings/EditSettingsScreen.js",
487 "start": {
488 "line": 180,
489 "column": 24
490 },
491 "end": {
492 "line": 183,
493 "column": 3
494 }
495 },
496 {
497 "id": "settings.app.form.showMessagesBadgesWhenMuted",
498 "defaultMessage": "!!!Show unread message badge when notifications are disabled",
499 "file": "src/containers/settings/EditSettingsScreen.js",
500 "start": {
501 "line": 184,
502 "column": 29
503 },
504 "end": {
505 "line": 187,
506 "column": 3
507 }
508 },
509 {
510 "id": "settings.app.form.showDragArea",
511 "defaultMessage": "!!!Show draggable area on window",
512 "file": "src/containers/settings/EditSettingsScreen.js",
513 "start": {
514 "line": 188,
515 "column": 16
516 },
517 "end": {
518 "line": 191,
519 "column": 3
520 }
521 },
522 {
523 "id": "settings.app.form.enableSpellchecking",
524 "defaultMessage": "!!!Enable spell checking",
525 "file": "src/containers/settings/EditSettingsScreen.js",
526 "start": {
527 "line": 192,
528 "column": 23
529 },
530 "end": {
531 "line": 195,
532 "column": 3
533 }
534 },
535 {
536 "id": "settings.app.form.enableGPUAcceleration",
537 "defaultMessage": "!!!Enable GPU Acceleration",
538 "file": "src/containers/settings/EditSettingsScreen.js",
539 "start": {
540 "line": 196,
541 "column": 25
542 },
543 "end": {
544 "line": 199,
545 "column": 3
546 }
547 },
548 {
549 "id": "settings.app.form.beta",
550 "defaultMessage": "!!!Include beta versions",
551 "file": "src/containers/settings/EditSettingsScreen.js",
552 "start": {
553 "line": 200,
554 "column": 8
555 },
556 "end": {
557 "line": 203,
558 "column": 3
559 }
560 },
561 {
562 "id": "settings.app.form.automaticUpdates",
563 "defaultMessage": "!!!Enable updates",
564 "file": "src/containers/settings/EditSettingsScreen.js",
565 "start": {
566 "line": 204,
567 "column": 20
568 },
569 "end": {
570 "line": 207,
571 "column": 3
572 }
573 },
574 {
575 "id": "settings.app.form.enableTodos",
576 "defaultMessage": "!!!Enable Franz Todos",
577 "file": "src/containers/settings/EditSettingsScreen.js",
578 "start": {
579 "line": 208,
580 "column": 15
581 },
582 "end": {
583 "line": 211,
584 "column": 3
585 }
586 },
587 {
588 "id": "settings.app.form.keepAllWorkspacesLoaded",
589 "defaultMessage": "!!!Keep all workspaces loaded",
590 "file": "src/containers/settings/EditSettingsScreen.js",
591 "start": {
592 "line": 212,
593 "column": 27
594 },
595 "end": {
596 "line": 215,
597 "column": 3
598 }
599 }
600] \ No newline at end of file
diff --git a/src/i18n/messages/src/containers/settings/EditUserScreen.json b/src/i18n/messages/src/containers/settings/EditUserScreen.json
deleted file mode 100644
index 70ff29945..000000000
--- a/src/i18n/messages/src/containers/settings/EditUserScreen.json
+++ /dev/null
@@ -1,119 +0,0 @@
1[
2 {
3 "id": "settings.user.form.firstname",
4 "defaultMessage": "!!!Firstname",
5 "file": "src/containers/settings/EditUserScreen.js",
6 "start": {
7 "line": 14,
8 "column": 13
9 },
10 "end": {
11 "line": 17,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.user.form.lastname",
17 "defaultMessage": "!!!Lastname",
18 "file": "src/containers/settings/EditUserScreen.js",
19 "start": {
20 "line": 18,
21 "column": 12
22 },
23 "end": {
24 "line": 21,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.user.form.email",
30 "defaultMessage": "!!!Email",
31 "file": "src/containers/settings/EditUserScreen.js",
32 "start": {
33 "line": 22,
34 "column": 9
35 },
36 "end": {
37 "line": 25,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.user.form.accountType.label",
43 "defaultMessage": "!!!Account type",
44 "file": "src/containers/settings/EditUserScreen.js",
45 "start": {
46 "line": 26,
47 "column": 20
48 },
49 "end": {
50 "line": 29,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.user.form.accountType.individual",
56 "defaultMessage": "!!!Individual",
57 "file": "src/containers/settings/EditUserScreen.js",
58 "start": {
59 "line": 30,
60 "column": 25
61 },
62 "end": {
63 "line": 33,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.user.form.accountType.non-profit",
69 "defaultMessage": "!!!Non-Profit",
70 "file": "src/containers/settings/EditUserScreen.js",
71 "start": {
72 "line": 34,
73 "column": 24
74 },
75 "end": {
76 "line": 37,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.user.form.accountType.company",
82 "defaultMessage": "!!!Company",
83 "file": "src/containers/settings/EditUserScreen.js",
84 "start": {
85 "line": 38,
86 "column": 22
87 },
88 "end": {
89 "line": 41,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.user.form.currentPassword",
95 "defaultMessage": "!!!Current password",
96 "file": "src/containers/settings/EditUserScreen.js",
97 "start": {
98 "line": 42,
99 "column": 19
100 },
101 "end": {
102 "line": 45,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.user.form.newPassword",
108 "defaultMessage": "!!!New password",
109 "file": "src/containers/settings/EditUserScreen.js",
110 "start": {
111 "line": 46,
112 "column": 15
113 },
114 "end": {
115 "line": 49,
116 "column": 3
117 }
118 }
119] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/basicAuth/Component.json b/src/i18n/messages/src/features/basicAuth/Component.json
deleted file mode 100644
index fea1b0838..000000000
--- a/src/i18n/messages/src/features/basicAuth/Component.json
+++ /dev/null
@@ -1,15 +0,0 @@
1[
2 {
3 "id": "feature.basicAuth.signIn",
4 "defaultMessage": "!!!Sign In",
5 "file": "src/features/basicAuth/Component.js",
6 "start": {
7 "line": 24,
8 "column": 10
9 },
10 "end": {
11 "line": 27,
12 "column": 3
13 }
14 }
15] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/debugger/Component.json b/src/i18n/messages/src/features/debugger/Component.json
deleted file mode 100644
index 86a5a05f4..000000000
--- a/src/i18n/messages/src/features/debugger/Component.json
+++ /dev/null
@@ -1,15 +0,0 @@
1[
2 {
3 "id": "feature.debugger.title",
4 "defaultMessage": "!!!Publish debugging information",
5 "file": "src/features/debugger/Component.js",
6 "start": {
7 "line": 16,
8 "column": 9
9 },
10 "end": {
11 "line": 19,
12 "column": 3
13 }
14 }
15] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/nightlyBuilds/Component.json b/src/i18n/messages/src/features/nightlyBuilds/Component.json
deleted file mode 100644
index 0b2eab354..000000000
--- a/src/i18n/messages/src/features/nightlyBuilds/Component.json
+++ /dev/null
@@ -1,41 +0,0 @@
1[
2 {
3 "id": "feature.nightlyBuilds.title",
4 "defaultMessage": "!!!Nightly Builds",
5 "file": "src/features/nightlyBuilds/Component.js",
6 "start": {
7 "line": 17,
8 "column": 9
9 },
10 "end": {
11 "line": 20,
12 "column": 3
13 }
14 },
15 {
16 "id": "feature.nightlyBuilds.info",
17 "defaultMessage": "!!!Nightly builds are highly experimental versions of Ferdi that may contain unpolished or uncompleted features. These nightly builds are mainly used by developers to test their newly developed features and how they will perform in the final build. If you don't know what you are doing, we suggest not activating nightly builds.",
18 "file": "src/features/nightlyBuilds/Component.js",
19 "start": {
20 "line": 21,
21 "column": 8
22 },
23 "end": {
24 "line": 24,
25 "column": 3
26 }
27 },
28 {
29 "id": "feature.nightlyBuilds.activate",
30 "defaultMessage": "!!!Activate",
31 "file": "src/features/nightlyBuilds/Component.js",
32 "start": {
33 "line": 25,
34 "column": 12
35 },
36 "end": {
37 "line": 28,
38 "column": 3
39 }
40 }
41] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/publishDebugInfo/Component.json b/src/i18n/messages/src/features/publishDebugInfo/Component.json
deleted file mode 100644
index 4d07a4794..000000000
--- a/src/i18n/messages/src/features/publishDebugInfo/Component.json
+++ /dev/null
@@ -1,93 +0,0 @@
1[
2 {
3 "id": "feature.publishDebugInfo.title",
4 "defaultMessage": "!!!Publish debug information",
5 "file": "src/features/publishDebugInfo/Component.js",
6 "start": {
7 "line": 19,
8 "column": 9
9 },
10 "end": {
11 "line": 22,
12 "column": 3
13 }
14 },
15 {
16 "id": "feature.publishDebugInfo.info",
17 "defaultMessage": "!!!Publishing your debug information helps us find issues and errors in Ferdi. By publishing your debug information you accept Ferdi Debugger's privacy policy and terms of service",
18 "file": "src/features/publishDebugInfo/Component.js",
19 "start": {
20 "line": 23,
21 "column": 8
22 },
23 "end": {
24 "line": 26,
25 "column": 3
26 }
27 },
28 {
29 "id": "feature.publishDebugInfo.error",
30 "defaultMessage": "!!!There was an error while trying to publish the debug information. Please try again later or view the console for more information.",
31 "file": "src/features/publishDebugInfo/Component.js",
32 "start": {
33 "line": 27,
34 "column": 9
35 },
36 "end": {
37 "line": 30,
38 "column": 3
39 }
40 },
41 {
42 "id": "feature.publishDebugInfo.privacy",
43 "defaultMessage": "!!!Privacy policy",
44 "file": "src/features/publishDebugInfo/Component.js",
45 "start": {
46 "line": 31,
47 "column": 11
48 },
49 "end": {
50 "line": 34,
51 "column": 3
52 }
53 },
54 {
55 "id": "feature.publishDebugInfo.terms",
56 "defaultMessage": "!!!Terms of service",
57 "file": "src/features/publishDebugInfo/Component.js",
58 "start": {
59 "line": 35,
60 "column": 9
61 },
62 "end": {
63 "line": 38,
64 "column": 3
65 }
66 },
67 {
68 "id": "feature.publishDebugInfo.publish",
69 "defaultMessage": "!!!Accept and publish",
70 "file": "src/features/publishDebugInfo/Component.js",
71 "start": {
72 "line": 39,
73 "column": 11
74 },
75 "end": {
76 "line": 42,
77 "column": 3
78 }
79 },
80 {
81 "id": "feature.publishDebugInfo.published",
82 "defaultMessage": "!!!Your debug log was published and is now availible at",
83 "file": "src/features/publishDebugInfo/Component.js",
84 "start": {
85 "line": 43,
86 "column": 13
87 },
88 "end": {
89 "line": 46,
90 "column": 3
91 }
92 }
93] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/quickSwitch/Component.json b/src/i18n/messages/src/features/quickSwitch/Component.json
deleted file mode 100644
index e112bedc1..000000000
--- a/src/i18n/messages/src/features/quickSwitch/Component.json
+++ /dev/null
@@ -1,41 +0,0 @@
1[
2 {
3 "id": "feature.quickSwitch.title",
4 "defaultMessage": "!!!QuickSwitch",
5 "file": "src/features/quickSwitch/Component.js",
6 "start": {
7 "line": 17,
8 "column": 9
9 },
10 "end": {
11 "line": 20,
12 "column": 3
13 }
14 },
15 {
16 "id": "feature.quickSwitch.search",
17 "defaultMessage": "!!!Search...",
18 "file": "src/features/quickSwitch/Component.js",
19 "start": {
20 "line": 21,
21 "column": 10
22 },
23 "end": {
24 "line": 24,
25 "column": 3
26 }
27 },
28 {
29 "id": "feature.quickSwitch.info",
30 "defaultMessage": "!!!Select a service with TAB, ↑ and ↓. Open a service with ENTER.",
31 "file": "src/features/quickSwitch/Component.js",
32 "start": {
33 "line": 25,
34 "column": 8
35 },
36 "end": {
37 "line": 28,
38 "column": 3
39 }
40 }
41] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/recipeConnectionLost/components/WebControls.json b/src/i18n/messages/src/features/recipeConnectionLost/components/WebControls.json
deleted file mode 100644
index f3bcaf345..000000000
--- a/src/i18n/messages/src/features/recipeConnectionLost/components/WebControls.json
+++ /dev/null
@@ -1,67 +0,0 @@
1[
2 {
3 "id": "webControls.goHome",
4 "defaultMessage": "!!!Home",
5 "file": "src/features/recipeConnectionLost/components/WebControls.js",
6 "start": {
7 "line": 13,
8 "column": 10
9 },
10 "end": {
11 "line": 16,
12 "column": 3
13 }
14 },
15 {
16 "id": "webControls.openInBrowser",
17 "defaultMessage": "!!!Open in Browser",
18 "file": "src/features/recipeConnectionLost/components/WebControls.js",
19 "start": {
20 "line": 17,
21 "column": 17
22 },
23 "end": {
24 "line": 20,
25 "column": 3
26 }
27 },
28 {
29 "id": "webControls.back",
30 "defaultMessage": "!!!Back",
31 "file": "src/features/recipeConnectionLost/components/WebControls.js",
32 "start": {
33 "line": 21,
34 "column": 8
35 },
36 "end": {
37 "line": 24,
38 "column": 3
39 }
40 },
41 {
42 "id": "webControls.forward",
43 "defaultMessage": "!!!Forward",
44 "file": "src/features/recipeConnectionLost/components/WebControls.js",
45 "start": {
46 "line": 25,
47 "column": 11
48 },
49 "end": {
50 "line": 28,
51 "column": 3
52 }
53 },
54 {
55 "id": "webControls.reload",
56 "defaultMessage": "!!!Reload",
57 "file": "src/features/recipeConnectionLost/components/WebControls.js",
58 "start": {
59 "line": 29,
60 "column": 10
61 },
62 "end": {
63 "line": 32,
64 "column": 3
65 }
66 }
67] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/webControls/components/WebControls.json b/src/i18n/messages/src/features/webControls/components/WebControls.json
deleted file mode 100644
index 7676ec0b1..000000000
--- a/src/i18n/messages/src/features/webControls/components/WebControls.json
+++ /dev/null
@@ -1,67 +0,0 @@
1[
2 {
3 "id": "webControls.goHome",
4 "defaultMessage": "!!!Home",
5 "file": "src/features/webControls/components/WebControls.js",
6 "start": {
7 "line": 17,
8 "column": 10
9 },
10 "end": {
11 "line": 20,
12 "column": 3
13 }
14 },
15 {
16 "id": "webControls.openInBrowser",
17 "defaultMessage": "!!!Open in Browser",
18 "file": "src/features/webControls/components/WebControls.js",
19 "start": {
20 "line": 21,
21 "column": 17
22 },
23 "end": {
24 "line": 24,
25 "column": 3
26 }
27 },
28 {
29 "id": "webControls.back",
30 "defaultMessage": "!!!Back",
31 "file": "src/features/webControls/components/WebControls.js",
32 "start": {
33 "line": 25,
34 "column": 8
35 },
36 "end": {
37 "line": 28,
38 "column": 3
39 }
40 },
41 {
42 "id": "webControls.forward",
43 "defaultMessage": "!!!Forward",
44 "file": "src/features/webControls/components/WebControls.js",
45 "start": {
46 "line": 29,
47 "column": 11
48 },
49 "end": {
50 "line": 32,
51 "column": 3
52 }
53 },
54 {
55 "id": "webControls.reload",
56 "defaultMessage": "!!!Reload",
57 "file": "src/features/webControls/components/WebControls.js",
58 "start": {
59 "line": 33,
60 "column": 10
61 },
62 "end": {
63 "line": 36,
64 "column": 3
65 }
66 }
67] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/workspaces/components/CreateWorkspaceForm.json b/src/i18n/messages/src/features/workspaces/components/CreateWorkspaceForm.json
deleted file mode 100644
index 1aabfb520..000000000
--- a/src/i18n/messages/src/features/workspaces/components/CreateWorkspaceForm.json
+++ /dev/null
@@ -1,28 +0,0 @@
1[
2 {
3 "id": "settings.workspace.add.form.submitButton",
4 "defaultMessage": "!!!Create workspace",
5 "file": "src/features/workspaces/components/CreateWorkspaceForm.js",
6 "start": {
7 "line": 12,
8 "column": 16
9 },
10 "end": {
11 "line": 15,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.workspace.add.form.name",
17 "defaultMessage": "!!!Name",
18 "file": "src/features/workspaces/components/CreateWorkspaceForm.js",
19 "start": {
20 "line": 16,
21 "column": 8
22 },
23 "end": {
24 "line": 19,
25 "column": 3
26 }
27 }
28] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/workspaces/components/EditWorkspaceForm.json b/src/i18n/messages/src/features/workspaces/components/EditWorkspaceForm.json
deleted file mode 100644
index 804e30070..000000000
--- a/src/i18n/messages/src/features/workspaces/components/EditWorkspaceForm.json
+++ /dev/null
@@ -1,119 +0,0 @@
1[
2 {
3 "id": "settings.workspace.form.buttonDelete",
4 "defaultMessage": "!!!Delete workspace",
5 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
6 "start": {
7 "line": 21,
8 "column": 16
9 },
10 "end": {
11 "line": 24,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.workspace.form.buttonSave",
17 "defaultMessage": "!!!Save workspace",
18 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
19 "start": {
20 "line": 25,
21 "column": 14
22 },
23 "end": {
24 "line": 28,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.workspace.form.name",
30 "defaultMessage": "!!!Name",
31 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
32 "start": {
33 "line": 29,
34 "column": 8
35 },
36 "end": {
37 "line": 32,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.workspace.form.yourWorkspaces",
43 "defaultMessage": "!!!Your workspaces",
44 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
45 "start": {
46 "line": 33,
47 "column": 18
48 },
49 "end": {
50 "line": 36,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.workspace.form.keepLoaded",
56 "defaultMessage": "!!!Keep this workspace loaded*",
57 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
58 "start": {
59 "line": 37,
60 "column": 14
61 },
62 "end": {
63 "line": 40,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.workspace.form.keepLoadedInfo",
69 "defaultMessage": "!!!*This option will be overwritten by the global \"Keep all workspaces loaded\" option.",
70 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
71 "start": {
72 "line": 41,
73 "column": 18
74 },
75 "end": {
76 "line": 45,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.workspace.form.servicesInWorkspaceHeadline",
82 "defaultMessage": "!!!Services in this Workspace",
83 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
84 "start": {
85 "line": 46,
86 "column": 31
87 },
88 "end": {
89 "line": 49,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.services.noServicesAdded",
95 "defaultMessage": "!!!Start by adding a service.",
96 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
97 "start": {
98 "line": 50,
99 "column": 19
100 },
101 "end": {
102 "line": 53,
103 "column": 3
104 }
105 },
106 {
107 "id": "settings.services.discoverServices",
108 "defaultMessage": "!!!Discover services",
109 "file": "src/features/workspaces/components/EditWorkspaceForm.js",
110 "start": {
111 "line": 54,
112 "column": 20
113 },
114 "end": {
115 "line": 57,
116 "column": 3
117 }
118 }
119] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json b/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json
deleted file mode 100644
index 431f12710..000000000
--- a/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json
+++ /dev/null
@@ -1,67 +0,0 @@
1[
2 {
3 "id": "workspaceDrawer.headline",
4 "defaultMessage": "!!!Workspaces",
5 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
6 "start": {
7 "line": 15,
8 "column": 12
9 },
10 "end": {
11 "line": 18,
12 "column": 3
13 }
14 },
15 {
16 "id": "workspaceDrawer.allServices",
17 "defaultMessage": "!!!All services",
18 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
19 "start": {
20 "line": 19,
21 "column": 15
22 },
23 "end": {
24 "line": 22,
25 "column": 3
26 }
27 },
28 {
29 "id": "workspaceDrawer.workspacesSettingsTooltip",
30 "defaultMessage": "!!!Workspaces settings",
31 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
32 "start": {
33 "line": 23,
34 "column": 29
35 },
36 "end": {
37 "line": 26,
38 "column": 3
39 }
40 },
41 {
42 "id": "workspaceDrawer.workspaceFeatureInfo",
43 "defaultMessage": "!!!Info about workspace feature",
44 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
45 "start": {
46 "line": 27,
47 "column": 24
48 },
49 "end": {
50 "line": 30,
51 "column": 3
52 }
53 },
54 {
55 "id": "workspaceDrawer.addNewWorkspaceLabel",
56 "defaultMessage": "!!!add new workspace",
57 "file": "src/features/workspaces/components/WorkspaceDrawer.js",
58 "start": {
59 "line": 31,
60 "column": 24
61 },
62 "end": {
63 "line": 34,
64 "column": 3
65 }
66 }
67] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawerItem.json b/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawerItem.json
deleted file mode 100644
index 737dee59b..000000000
--- a/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawerItem.json
+++ /dev/null
@@ -1,28 +0,0 @@
1[
2 {
3 "id": "workspaceDrawer.item.noServicesAddedYet",
4 "defaultMessage": "!!!No services added yet",
5 "file": "src/features/workspaces/components/WorkspaceDrawerItem.js",
6 "start": {
7 "line": 11,
8 "column": 22
9 },
10 "end": {
11 "line": 14,
12 "column": 3
13 }
14 },
15 {
16 "id": "workspaceDrawer.item.contextMenuEdit",
17 "defaultMessage": "!!!edit",
18 "file": "src/features/workspaces/components/WorkspaceDrawerItem.js",
19 "start": {
20 "line": 15,
21 "column": 19
22 },
23 "end": {
24 "line": 18,
25 "column": 3
26 }
27 }
28] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/workspaces/components/WorkspaceSwitchingIndicator.json b/src/i18n/messages/src/features/workspaces/components/WorkspaceSwitchingIndicator.json
deleted file mode 100644
index 4f3e6d55c..000000000
--- a/src/i18n/messages/src/features/workspaces/components/WorkspaceSwitchingIndicator.json
+++ /dev/null
@@ -1,15 +0,0 @@
1[
2 {
3 "id": "workspaces.switchingIndicator.switchingTo",
4 "defaultMessage": "!!!Switching to",
5 "file": "src/features/workspaces/components/WorkspaceSwitchingIndicator.js",
6 "start": {
7 "line": 12,
8 "column": 15
9 },
10 "end": {
11 "line": 15,
12 "column": 3
13 }
14 }
15] \ No newline at end of file
diff --git a/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json b/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json
deleted file mode 100644
index 39c9c30fb..000000000
--- a/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json
+++ /dev/null
@@ -1,106 +0,0 @@
1[
2 {
3 "id": "settings.workspaces.headline",
4 "defaultMessage": "!!!Your workspaces",
5 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
6 "start": {
7 "line": 17,
8 "column": 12
9 },
10 "end": {
11 "line": 20,
12 "column": 3
13 }
14 },
15 {
16 "id": "settings.workspaces.noWorkspacesAdded",
17 "defaultMessage": "!!!You haven't created any workspaces yet.",
18 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
19 "start": {
20 "line": 21,
21 "column": 19
22 },
23 "end": {
24 "line": 24,
25 "column": 3
26 }
27 },
28 {
29 "id": "settings.workspaces.workspacesRequestFailed",
30 "defaultMessage": "!!!Could not load your workspaces",
31 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
32 "start": {
33 "line": 25,
34 "column": 27
35 },
36 "end": {
37 "line": 28,
38 "column": 3
39 }
40 },
41 {
42 "id": "settings.workspaces.tryReloadWorkspaces",
43 "defaultMessage": "!!!Try again",
44 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
45 "start": {
46 "line": 29,
47 "column": 23
48 },
49 "end": {
50 "line": 32,
51 "column": 3
52 }
53 },
54 {
55 "id": "settings.workspaces.updatedInfo",
56 "defaultMessage": "!!!Your changes have been saved",
57 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
58 "start": {
59 "line": 33,
60 "column": 15
61 },
62 "end": {
63 "line": 36,
64 "column": 3
65 }
66 },
67 {
68 "id": "settings.workspaces.deletedInfo",
69 "defaultMessage": "!!!Workspace has been deleted",
70 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
71 "start": {
72 "line": 37,
73 "column": 15
74 },
75 "end": {
76 "line": 40,
77 "column": 3
78 }
79 },
80 {
81 "id": "settings.workspaces.workspaceFeatureInfo",
82 "defaultMessage": "!!!Info about workspace feature",
83 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
84 "start": {
85 "line": 41,
86 "column": 24
87 },
88 "end": {
89 "line": 44,
90 "column": 3
91 }
92 },
93 {
94 "id": "settings.workspaces.workspaceFeatureHeadline",
95 "defaultMessage": "!!!Less is More: Introducing Ferdi Workspaces",
96 "file": "src/features/workspaces/components/WorkspacesDashboard.js",
97 "start": {
98 "line": 45,
99 "column": 28
100 },
101 "end": {
102 "line": 48,
103 "column": 3
104 }
105 }
106] \ No newline at end of file
diff --git a/src/i18n/messages/src/helpers/validation-helpers.json b/src/i18n/messages/src/helpers/validation-helpers.json
deleted file mode 100644
index 6be1d33e9..000000000
--- a/src/i18n/messages/src/helpers/validation-helpers.json
+++ /dev/null
@@ -1,67 +0,0 @@
1[
2 {
3 "id": "validation.required",
4 "defaultMessage": "!!!Field is required",
5 "file": "src/helpers/validation-helpers.js",
6 "start": {
7 "line": 5,
8 "column": 12
9 },
10 "end": {
11 "line": 8,
12 "column": 3
13 }
14 },
15 {
16 "id": "validation.email",
17 "defaultMessage": "!!!Email not valid",
18 "file": "src/helpers/validation-helpers.js",
19 "start": {
20 "line": 9,
21 "column": 9
22 },
23 "end": {
24 "line": 12,
25 "column": 3
26 }
27 },
28 {
29 "id": "validation.url",
30 "defaultMessage": "!!!Not a valid URL",
31 "file": "src/helpers/validation-helpers.js",
32 "start": {
33 "line": 13,
34 "column": 7
35 },
36 "end": {
37 "line": 16,
38 "column": 3
39 }
40 },
41 {
42 "id": "validation.minLength",
43 "defaultMessage": "!!!Too few characters",
44 "file": "src/helpers/validation-helpers.js",
45 "start": {
46 "line": 17,
47 "column": 13
48 },
49 "end": {
50 "line": 20,
51 "column": 3
52 }
53 },
54 {
55 "id": "validation.oneRequired",
56 "defaultMessage": "!!!At least one is required",
57 "file": "src/helpers/validation-helpers.js",
58 "start": {
59 "line": 21,
60 "column": 15
61 },
62 "end": {
63 "line": 24,
64 "column": 3
65 }
66 }
67] \ No newline at end of file
diff --git a/src/i18n/messages/src/i18n/globalMessages.json b/src/i18n/messages/src/i18n/globalMessages.json
deleted file mode 100644
index bc1ec7397..000000000
--- a/src/i18n/messages/src/i18n/globalMessages.json
+++ /dev/null
@@ -1,236 +0,0 @@
1[
2 {
3 "id": "global.api.unhealthy",
4 "defaultMessage": "!!!Can't connect to Ferdi Online Services",
5 "file": "src/i18n/globalMessages.js",
6 "start": {
7 "line": 4,
8 "column": 16
9 },
10 "end": {
11 "line": 7,
12 "column": 3
13 }
14 },
15 {
16 "id": "global.notConnectedToTheInternet",
17 "defaultMessage": "!!!You are not connected to the internet.",
18 "file": "src/i18n/globalMessages.js",
19 "start": {
20 "line": 8,
21 "column": 29
22 },
23 "end": {
24 "line": 11,
25 "column": 3
26 }
27 },
28 {
29 "id": "global.spellchecking.language",
30 "defaultMessage": "!!!Spell checking language",
31 "file": "src/i18n/globalMessages.js",
32 "start": {
33 "line": 12,
34 "column": 24
35 },
36 "end": {
37 "line": 15,
38 "column": 3
39 }
40 },
41 {
42 "id": "global.spellchecker.useDefault",
43 "defaultMessage": "!!!Use System Default ({default})",
44 "file": "src/i18n/globalMessages.js",
45 "start": {
46 "line": 16,
47 "column": 29
48 },
49 "end": {
50 "line": 19,
51 "column": 3
52 }
53 },
54 {
55 "id": "global.spellchecking.autodetect",
56 "defaultMessage": "!!!Detect language automatically",
57 "file": "src/i18n/globalMessages.js",
58 "start": {
59 "line": 20,
60 "column": 34
61 },
62 "end": {
63 "line": 23,
64 "column": 3
65 }
66 },
67 {
68 "id": "global.spellchecking.autodetect.short",
69 "defaultMessage": "!!!Automatic",
70 "file": "src/i18n/globalMessages.js",
71 "start": {
72 "line": 24,
73 "column": 39
74 },
75 "end": {
76 "line": 27,
77 "column": 3
78 }
79 },
80 {
81 "id": "global.userAgentPref",
82 "defaultMessage": "!!!User Agent",
83 "file": "src/i18n/globalMessages.js",
84 "start": {
85 "line": 28,
86 "column": 17
87 },
88 "end": {
89 "line": 31,
90 "column": 3
91 }
92 },
93 {
94 "id": "global.userAgentHelp",
95 "defaultMessage": "!!!Use 'https://whatmyuseragent.com/' (to discover) or 'https://developers.whatismybrowser.com/useragents/explore/' (to choose) your desired user agent and copy-paste it here.",
96 "file": "src/i18n/globalMessages.js",
97 "start": {
98 "line": 32,
99 "column": 17
100 },
101 "end": {
102 "line": 35,
103 "column": 3
104 }
105 },
106 {
107 "id": "global.yes",
108 "defaultMessage": "!!!Yes",
109 "file": "src/i18n/globalMessages.js",
110 "start": {
111 "line": 36,
112 "column": 7
113 },
114 "end": {
115 "line": 39,
116 "column": 3
117 }
118 },
119 {
120 "id": "global.no",
121 "defaultMessage": "!!!No",
122 "file": "src/i18n/globalMessages.js",
123 "start": {
124 "line": 40,
125 "column": 6
126 },
127 "end": {
128 "line": 43,
129 "column": 3
130 }
131 },
132 {
133 "id": "global.ok",
134 "defaultMessage": "!!!Ok",
135 "file": "src/i18n/globalMessages.js",
136 "start": {
137 "line": 44,
138 "column": 6
139 },
140 "end": {
141 "line": 47,
142 "column": 3
143 }
144 },
145 {
146 "id": "global.cancel",
147 "defaultMessage": "!!!Cancel",
148 "file": "src/i18n/globalMessages.js",
149 "start": {
150 "line": 48,
151 "column": 10
152 },
153 "end": {
154 "line": 51,
155 "column": 3
156 }
157 },
158 {
159 "id": "global.save",
160 "defaultMessage": "!!!Save",
161 "file": "src/i18n/globalMessages.js",
162 "start": {
163 "line": 52,
164 "column": 8
165 },
166 "end": {
167 "line": 55,
168 "column": 3
169 }
170 },
171 {
172 "id": "global.submit",
173 "defaultMessage": "!!!Submit",
174 "file": "src/i18n/globalMessages.js",
175 "start": {
176 "line": 56,
177 "column": 10
178 },
179 "end": {
180 "line": 59,
181 "column": 3
182 }
183 },
184 {
185 "id": "global.quit",
186 "defaultMessage": "!!!Quit",
187 "file": "src/i18n/globalMessages.js",
188 "start": {
189 "line": 60,
190 "column": 8
191 },
192 "end": {
193 "line": 63,
194 "column": 3
195 }
196 },
197 {
198 "id": "global.quitConfirmation",
199 "defaultMessage": "!!!Do you really want to quit Ferdi?",
200 "file": "src/i18n/globalMessages.js",
201 "start": {
202 "line": 64,
203 "column": 20
204 },
205 "end": {
206 "line": 68,
207 "column": 3
208 }
209 },
210 {
211 "id": "global.settings",
212 "defaultMessage": "!!!Settings",
213 "file": "src/i18n/globalMessages.js",
214 "start": {
215 "line": 69,
216 "column": 12
217 },
218 "end": {
219 "line": 72,
220 "column": 3
221 }
222 },
223 {
224 "id": "global.edit",
225 "defaultMessage": "!!!Edit",
226 "file": "src/i18n/globalMessages.js",
227 "start": {
228 "line": 73,
229 "column": 8
230 },
231 "end": {
232 "line": 76,
233 "column": 3
234 }
235 }
236] \ No newline at end of file
diff --git a/src/i18n/messages/src/lib/Menu.json b/src/i18n/messages/src/lib/Menu.json
deleted file mode 100644
index 35f2e3b7b..000000000
--- a/src/i18n/messages/src/lib/Menu.json
+++ /dev/null
@@ -1,912 +0,0 @@
1[
2 {
3 "id": "menu.edit",
4 "defaultMessage": "!!!Edit",
5 "file": "src/lib/Menu.js",
6 "start": {
7 "line": 32,
8 "column": 8
9 },
10 "end": {
11 "line": 35,
12 "column": 3
13 }
14 },
15 {
16 "id": "menu.edit.undo",
17 "defaultMessage": "!!!Undo",
18 "file": "src/lib/Menu.js",
19 "start": {
20 "line": 36,
21 "column": 8
22 },
23 "end": {
24 "line": 39,
25 "column": 3
26 }
27 },
28 {
29 "id": "menu.edit.redo",
30 "defaultMessage": "!!!Redo",
31 "file": "src/lib/Menu.js",
32 "start": {
33 "line": 40,
34 "column": 8
35 },
36 "end": {
37 "line": 43,
38 "column": 3
39 }
40 },
41 {
42 "id": "menu.edit.cut",
43 "defaultMessage": "!!!Cut",
44 "file": "src/lib/Menu.js",
45 "start": {
46 "line": 44,
47 "column": 7
48 },
49 "end": {
50 "line": 47,
51 "column": 3
52 }
53 },
54 {
55 "id": "menu.edit.copy",
56 "defaultMessage": "!!!Copy",
57 "file": "src/lib/Menu.js",
58 "start": {
59 "line": 48,
60 "column": 8
61 },
62 "end": {
63 "line": 51,
64 "column": 3
65 }
66 },
67 {
68 "id": "menu.edit.paste",
69 "defaultMessage": "!!!Paste",
70 "file": "src/lib/Menu.js",
71 "start": {
72 "line": 52,
73 "column": 9
74 },
75 "end": {
76 "line": 55,
77 "column": 3
78 }
79 },
80 {
81 "id": "menu.edit.pasteAndMatchStyle",
82 "defaultMessage": "!!!Paste And Match Style",
83 "file": "src/lib/Menu.js",
84 "start": {
85 "line": 56,
86 "column": 22
87 },
88 "end": {
89 "line": 59,
90 "column": 3
91 }
92 },
93 {
94 "id": "menu.edit.delete",
95 "defaultMessage": "!!!Delete",
96 "file": "src/lib/Menu.js",
97 "start": {
98 "line": 60,
99 "column": 10
100 },
101 "end": {
102 "line": 63,
103 "column": 3
104 }
105 },
106 {
107 "id": "menu.edit.selectAll",
108 "defaultMessage": "!!!Select All",
109 "file": "src/lib/Menu.js",
110 "start": {
111 "line": 64,
112 "column": 13
113 },
114 "end": {
115 "line": 67,
116 "column": 3
117 }
118 },
119 {
120 "id": "menu.edit.findInPage",
121 "defaultMessage": "!!!Find in Page",
122 "file": "src/lib/Menu.js",
123 "start": {
124 "line": 68,
125 "column": 14
126 },
127 "end": {
128 "line": 71,
129 "column": 3
130 }
131 },
132 {
133 "id": "menu.edit.speech",
134 "defaultMessage": "!!!Speech",
135 "file": "src/lib/Menu.js",
136 "start": {
137 "line": 72,
138 "column": 10
139 },
140 "end": {
141 "line": 75,
142 "column": 3
143 }
144 },
145 {
146 "id": "menu.edit.startSpeaking",
147 "defaultMessage": "!!!Start Speaking",
148 "file": "src/lib/Menu.js",
149 "start": {
150 "line": 76,
151 "column": 17
152 },
153 "end": {
154 "line": 79,
155 "column": 3
156 }
157 },
158 {
159 "id": "menu.edit.stopSpeaking",
160 "defaultMessage": "!!!Stop Speaking",
161 "file": "src/lib/Menu.js",
162 "start": {
163 "line": 80,
164 "column": 16
165 },
166 "end": {
167 "line": 83,
168 "column": 3
169 }
170 },
171 {
172 "id": "menu.edit.startDictation",
173 "defaultMessage": "!!!Start Dictation",
174 "file": "src/lib/Menu.js",
175 "start": {
176 "line": 84,
177 "column": 18
178 },
179 "end": {
180 "line": 87,
181 "column": 3
182 }
183 },
184 {
185 "id": "menu.edit.emojiSymbols",
186 "defaultMessage": "!!!Emoji & Symbols",
187 "file": "src/lib/Menu.js",
188 "start": {
189 "line": 88,
190 "column": 16
191 },
192 "end": {
193 "line": 91,
194 "column": 3
195 }
196 },
197 {
198 "id": "menu.view.openQuickSwitch",
199 "defaultMessage": "!!!Open Quick Switch",
200 "file": "src/lib/Menu.js",
201 "start": {
202 "line": 92,
203 "column": 19
204 },
205 "end": {
206 "line": 95,
207 "column": 3
208 }
209 },
210 {
211 "id": "menu.view.back",
212 "defaultMessage": "!!!Back",
213 "file": "src/lib/Menu.js",
214 "start": {
215 "line": 96,
216 "column": 8
217 },
218 "end": {
219 "line": 99,
220 "column": 3
221 }
222 },
223 {
224 "id": "menu.view.forward",
225 "defaultMessage": "!!!Forward",
226 "file": "src/lib/Menu.js",
227 "start": {
228 "line": 100,
229 "column": 11
230 },
231 "end": {
232 "line": 103,
233 "column": 3
234 }
235 },
236 {
237 "id": "menu.view.resetZoom",
238 "defaultMessage": "!!!Actual Size",
239 "file": "src/lib/Menu.js",
240 "start": {
241 "line": 104,
242 "column": 13
243 },
244 "end": {
245 "line": 107,
246 "column": 3
247 }
248 },
249 {
250 "id": "menu.view.zoomIn",
251 "defaultMessage": "!!!Zoom In",
252 "file": "src/lib/Menu.js",
253 "start": {
254 "line": 108,
255 "column": 10
256 },
257 "end": {
258 "line": 111,
259 "column": 3
260 }
261 },
262 {
263 "id": "menu.view.zoomOut",
264 "defaultMessage": "!!!Zoom Out",
265 "file": "src/lib/Menu.js",
266 "start": {
267 "line": 112,
268 "column": 11
269 },
270 "end": {
271 "line": 115,
272 "column": 3
273 }
274 },
275 {
276 "id": "menu.view.toggleFullScreen",
277 "defaultMessage": "!!!Toggle Full Screen",
278 "file": "src/lib/Menu.js",
279 "start": {
280 "line": 116,
281 "column": 20
282 },
283 "end": {
284 "line": 119,
285 "column": 3
286 }
287 },
288 {
289 "id": "menu.view.toggleDarkMode",
290 "defaultMessage": "!!!Toggle Dark Mode",
291 "file": "src/lib/Menu.js",
292 "start": {
293 "line": 120,
294 "column": 18
295 },
296 "end": {
297 "line": 123,
298 "column": 3
299 }
300 },
301 {
302 "id": "menu.view.toggleDevTools",
303 "defaultMessage": "!!!Toggle Developer Tools",
304 "file": "src/lib/Menu.js",
305 "start": {
306 "line": 124,
307 "column": 18
308 },
309 "end": {
310 "line": 127,
311 "column": 3
312 }
313 },
314 {
315 "id": "menu.view.toggleTodosDevTools",
316 "defaultMessage": "!!!Toggle Todos Developer Tools",
317 "file": "src/lib/Menu.js",
318 "start": {
319 "line": 128,
320 "column": 23
321 },
322 "end": {
323 "line": 131,
324 "column": 3
325 }
326 },
327 {
328 "id": "menu.view.toggleServiceDevTools",
329 "defaultMessage": "!!!Toggle Service Developer Tools",
330 "file": "src/lib/Menu.js",
331 "start": {
332 "line": 132,
333 "column": 25
334 },
335 "end": {
336 "line": 135,
337 "column": 3
338 }
339 },
340 {
341 "id": "menu.view.reloadService",
342 "defaultMessage": "!!!Reload Service",
343 "file": "src/lib/Menu.js",
344 "start": {
345 "line": 136,
346 "column": 17
347 },
348 "end": {
349 "line": 139,
350 "column": 3
351 }
352 },
353 {
354 "id": "menu.view.reloadFerdi",
355 "defaultMessage": "!!!Reload Ferdi",
356 "file": "src/lib/Menu.js",
357 "start": {
358 "line": 140,
359 "column": 15
360 },
361 "end": {
362 "line": 143,
363 "column": 3
364 }
365 },
366 {
367 "id": "menu.view.lockFerdi",
368 "defaultMessage": "!!!Lock Ferdi",
369 "file": "src/lib/Menu.js",
370 "start": {
371 "line": 144,
372 "column": 13
373 },
374 "end": {
375 "line": 147,
376 "column": 3
377 }
378 },
379 {
380 "id": "menu.view.reloadTodos",
381 "defaultMessage": "!!!Reload ToDos",
382 "file": "src/lib/Menu.js",
383 "start": {
384 "line": 148,
385 "column": 15
386 },
387 "end": {
388 "line": 151,
389 "column": 3
390 }
391 },
392 {
393 "id": "menu.window.minimize",
394 "defaultMessage": "!!!Minimize",
395 "file": "src/lib/Menu.js",
396 "start": {
397 "line": 152,
398 "column": 12
399 },
400 "end": {
401 "line": 155,
402 "column": 3
403 }
404 },
405 {
406 "id": "menu.window.close",
407 "defaultMessage": "!!!Close",
408 "file": "src/lib/Menu.js",
409 "start": {
410 "line": 156,
411 "column": 9
412 },
413 "end": {
414 "line": 159,
415 "column": 3
416 }
417 },
418 {
419 "id": "menu.help.learnMore",
420 "defaultMessage": "!!!Learn More",
421 "file": "src/lib/Menu.js",
422 "start": {
423 "line": 160,
424 "column": 13
425 },
426 "end": {
427 "line": 163,
428 "column": 3
429 }
430 },
431 {
432 "id": "menu.help.changelog",
433 "defaultMessage": "!!!Changelog",
434 "file": "src/lib/Menu.js",
435 "start": {
436 "line": 164,
437 "column": 13
438 },
439 "end": {
440 "line": 167,
441 "column": 3
442 }
443 },
444 {
445 "id": "menu.help.importExportData",
446 "defaultMessage": "!!!Import/Export Configuration Data",
447 "file": "src/lib/Menu.js",
448 "start": {
449 "line": 168,
450 "column": 20
451 },
452 "end": {
453 "line": 171,
454 "column": 3
455 }
456 },
457 {
458 "id": "menu.help.support",
459 "defaultMessage": "!!!Support",
460 "file": "src/lib/Menu.js",
461 "start": {
462 "line": 172,
463 "column": 11
464 },
465 "end": {
466 "line": 175,
467 "column": 3
468 }
469 },
470 {
471 "id": "menu.help.debugInfo",
472 "defaultMessage": "!!!Copy Debug Information",
473 "file": "src/lib/Menu.js",
474 "start": {
475 "line": 176,
476 "column": 13
477 },
478 "end": {
479 "line": 179,
480 "column": 3
481 }
482 },
483 {
484 "id": "menu.help.publishDebugInfo",
485 "defaultMessage": "!!!Publish Debug Information",
486 "file": "src/lib/Menu.js",
487 "start": {
488 "line": 180,
489 "column": 20
490 },
491 "end": {
492 "line": 183,
493 "column": 3
494 }
495 },
496 {
497 "id": "menu.help.debugInfoCopiedHeadline",
498 "defaultMessage": "!!!Ferdi Debug Information",
499 "file": "src/lib/Menu.js",
500 "start": {
501 "line": 184,
502 "column": 27
503 },
504 "end": {
505 "line": 187,
506 "column": 3
507 }
508 },
509 {
510 "id": "menu.help.debugInfoCopiedBody",
511 "defaultMessage": "!!!Your Debug Information has been copied to your clipboard.",
512 "file": "src/lib/Menu.js",
513 "start": {
514 "line": 188,
515 "column": 23
516 },
517 "end": {
518 "line": 192,
519 "column": 3
520 }
521 },
522 {
523 "id": "locked.touchId",
524 "defaultMessage": "!!!Unlock with Touch ID",
525 "file": "src/lib/Menu.js",
526 "start": {
527 "line": 193,
528 "column": 11
529 },
530 "end": {
531 "line": 196,
532 "column": 3
533 }
534 },
535 {
536 "id": "locked.touchIdPrompt",
537 "defaultMessage": "!!!unlock via Touch ID",
538 "file": "src/lib/Menu.js",
539 "start": {
540 "line": 197,
541 "column": 17
542 },
543 "end": {
544 "line": 200,
545 "column": 3
546 }
547 },
548 {
549 "id": "menu.help.tos",
550 "defaultMessage": "!!!Terms of Service",
551 "file": "src/lib/Menu.js",
552 "start": {
553 "line": 201,
554 "column": 7
555 },
556 "end": {
557 "line": 204,
558 "column": 3
559 }
560 },
561 {
562 "id": "menu.help.privacy",
563 "defaultMessage": "!!!Privacy Statement",
564 "file": "src/lib/Menu.js",
565 "start": {
566 "line": 205,
567 "column": 11
568 },
569 "end": {
570 "line": 208,
571 "column": 3
572 }
573 },
574 {
575 "id": "menu.file",
576 "defaultMessage": "!!!File",
577 "file": "src/lib/Menu.js",
578 "start": {
579 "line": 209,
580 "column": 8
581 },
582 "end": {
583 "line": 212,
584 "column": 3
585 }
586 },
587 {
588 "id": "menu.view",
589 "defaultMessage": "!!!View",
590 "file": "src/lib/Menu.js",
591 "start": {
592 "line": 213,
593 "column": 8
594 },
595 "end": {
596 "line": 216,
597 "column": 3
598 }
599 },
600 {
601 "id": "menu.services",
602 "defaultMessage": "!!!Services",
603 "file": "src/lib/Menu.js",
604 "start": {
605 "line": 217,
606 "column": 12
607 },
608 "end": {
609 "line": 220,
610 "column": 3
611 }
612 },
613 {
614 "id": "menu.window",
615 "defaultMessage": "!!!Window",
616 "file": "src/lib/Menu.js",
617 "start": {
618 "line": 221,
619 "column": 10
620 },
621 "end": {
622 "line": 224,
623 "column": 3
624 }
625 },
626 {
627 "id": "menu.help",
628 "defaultMessage": "!!!Help",
629 "file": "src/lib/Menu.js",
630 "start": {
631 "line": 225,
632 "column": 8
633 },
634 "end": {
635 "line": 228,
636 "column": 3
637 }
638 },
639 {
640 "id": "menu.app.about",
641 "defaultMessage": "!!!About Ferdi",
642 "file": "src/lib/Menu.js",
643 "start": {
644 "line": 229,
645 "column": 9
646 },
647 "end": {
648 "line": 232,
649 "column": 3
650 }
651 },
652 {
653 "id": "menu.app.checkForUpdates",
654 "defaultMessage": "!!!Check for updates",
655 "file": "src/lib/Menu.js",
656 "start": {
657 "line": 233,
658 "column": 19
659 },
660 "end": {
661 "line": 236,
662 "column": 3
663 }
664 },
665 {
666 "id": "menu.app.hide",
667 "defaultMessage": "!!!Hide",
668 "file": "src/lib/Menu.js",
669 "start": {
670 "line": 237,
671 "column": 8
672 },
673 "end": {
674 "line": 240,
675 "column": 3
676 }
677 },
678 {
679 "id": "menu.app.hideOthers",
680 "defaultMessage": "!!!Hide Others",
681 "file": "src/lib/Menu.js",
682 "start": {
683 "line": 241,
684 "column": 14
685 },
686 "end": {
687 "line": 244,
688 "column": 3
689 }
690 },
691 {
692 "id": "menu.app.unhide",
693 "defaultMessage": "!!!Unhide",
694 "file": "src/lib/Menu.js",
695 "start": {
696 "line": 245,
697 "column": 10
698 },
699 "end": {
700 "line": 248,
701 "column": 3
702 }
703 },
704 {
705 "id": "menu.app.autohideMenuBar",
706 "defaultMessage": "!!!Auto-hide menu bar",
707 "file": "src/lib/Menu.js",
708 "start": {
709 "line": 249,
710 "column": 19
711 },
712 "end": {
713 "line": 252,
714 "column": 3
715 }
716 },
717 {
718 "id": "menu.services.addNewService",
719 "defaultMessage": "!!!Add New Service...",
720 "file": "src/lib/Menu.js",
721 "start": {
722 "line": 253,
723 "column": 17
724 },
725 "end": {
726 "line": 256,
727 "column": 3
728 }
729 },
730 {
731 "id": "menu.workspaces.addNewWorkspace",
732 "defaultMessage": "!!!Add New Workspace...",
733 "file": "src/lib/Menu.js",
734 "start": {
735 "line": 257,
736 "column": 19
737 },
738 "end": {
739 "line": 260,
740 "column": 3
741 }
742 },
743 {
744 "id": "menu.workspaces.openWorkspaceDrawer",
745 "defaultMessage": "!!!Open workspace drawer",
746 "file": "src/lib/Menu.js",
747 "start": {
748 "line": 261,
749 "column": 23
750 },
751 "end": {
752 "line": 264,
753 "column": 3
754 }
755 },
756 {
757 "id": "menu.workspaces.closeWorkspaceDrawer",
758 "defaultMessage": "!!!Close workspace drawer",
759 "file": "src/lib/Menu.js",
760 "start": {
761 "line": 265,
762 "column": 24
763 },
764 "end": {
765 "line": 268,
766 "column": 3
767 }
768 },
769 {
770 "id": "menu.services.setNextServiceActive",
771 "defaultMessage": "!!!Activate next service...",
772 "file": "src/lib/Menu.js",
773 "start": {
774 "line": 269,
775 "column": 23
776 },
777 "end": {
778 "line": 272,
779 "column": 3
780 }
781 },
782 {
783 "id": "menu.services.activatePreviousService",
784 "defaultMessage": "!!!Activate previous service...",
785 "file": "src/lib/Menu.js",
786 "start": {
787 "line": 273,
788 "column": 27
789 },
790 "end": {
791 "line": 276,
792 "column": 3
793 }
794 },
795 {
796 "id": "sidebar.muteApp",
797 "defaultMessage": "!!!Disable notifications & audio",
798 "file": "src/lib/Menu.js",
799 "start": {
800 "line": 277,
801 "column": 11
802 },
803 "end": {
804 "line": 280,
805 "column": 3
806 }
807 },
808 {
809 "id": "sidebar.unmuteApp",
810 "defaultMessage": "!!!Enable notifications & audio",
811 "file": "src/lib/Menu.js",
812 "start": {
813 "line": 281,
814 "column": 13
815 },
816 "end": {
817 "line": 284,
818 "column": 3
819 }
820 },
821 {
822 "id": "menu.workspaces",
823 "defaultMessage": "!!!Workspaces",
824 "file": "src/lib/Menu.js",
825 "start": {
826 "line": 285,
827 "column": 14
828 },
829 "end": {
830 "line": 288,
831 "column": 3
832 }
833 },
834 {
835 "id": "menu.workspaces.defaultWorkspace",
836 "defaultMessage": "!!!Default",
837 "file": "src/lib/Menu.js",
838 "start": {
839 "line": 289,
840 "column": 20
841 },
842 "end": {
843 "line": 292,
844 "column": 3
845 }
846 },
847 {
848 "id": "menu.todos",
849 "defaultMessage": "!!!Todos",
850 "file": "src/lib/Menu.js",
851 "start": {
852 "line": 293,
853 "column": 9
854 },
855 "end": {
856 "line": 296,
857 "column": 3
858 }
859 },
860 {
861 "id": "menu.Todoss.openTodosDrawer",
862 "defaultMessage": "!!!Open Todos drawer",
863 "file": "src/lib/Menu.js",
864 "start": {
865 "line": 297,
866 "column": 19
867 },
868 "end": {
869 "line": 300,
870 "column": 3
871 }
872 },
873 {
874 "id": "menu.Todoss.closeTodosDrawer",
875 "defaultMessage": "!!!Close Todos drawer",
876 "file": "src/lib/Menu.js",
877 "start": {
878 "line": 301,
879 "column": 20
880 },
881 "end": {
882 "line": 304,
883 "column": 3
884 }
885 },
886 {
887 "id": "menu.todos.enableTodos",
888 "defaultMessage": "!!!Enable Todos",
889 "file": "src/lib/Menu.js",
890 "start": {
891 "line": 305,
892 "column": 15
893 },
894 "end": {
895 "line": 308,
896 "column": 3
897 }
898 },
899 {
900 "id": "menu.services.goHome",
901 "defaultMessage": "!!!Home",
902 "file": "src/lib/Menu.js",
903 "start": {
904 "line": 309,
905 "column": 17
906 },
907 "end": {
908 "line": 312,
909 "column": 3
910 }
911 }
912] \ No newline at end of file
diff --git a/src/lib/Menu.js b/src/lib/Menu.js
index 5dae56544..d7f3dbecf 100644
--- a/src/lib/Menu.js
+++ b/src/lib/Menu.js
@@ -31,284 +31,283 @@ import globalMessages from '../i18n/globalMessages';
31const menuItems = defineMessages({ 31const menuItems = defineMessages({
32 edit: { 32 edit: {
33 id: 'menu.edit', 33 id: 'menu.edit',
34 defaultMessage: '!!!Edit', 34 defaultMessage: 'Edit',
35 }, 35 },
36 undo: { 36 undo: {
37 id: 'menu.edit.undo', 37 id: 'menu.edit.undo',
38 defaultMessage: '!!!Undo', 38 defaultMessage: 'Undo',
39 }, 39 },
40 redo: { 40 redo: {
41 id: 'menu.edit.redo', 41 id: 'menu.edit.redo',
42 defaultMessage: '!!!Redo', 42 defaultMessage: 'Redo',
43 }, 43 },
44 cut: { 44 cut: {
45 id: 'menu.edit.cut', 45 id: 'menu.edit.cut',
46 defaultMessage: '!!!Cut', 46 defaultMessage: 'Cut',
47 }, 47 },
48 copy: { 48 copy: {
49 id: 'menu.edit.copy', 49 id: 'menu.edit.copy',
50 defaultMessage: '!!!Copy', 50 defaultMessage: 'Copy',
51 }, 51 },
52 paste: { 52 paste: {
53 id: 'menu.edit.paste', 53 id: 'menu.edit.paste',
54 defaultMessage: '!!!Paste', 54 defaultMessage: 'Paste',
55 }, 55 },
56 pasteAndMatchStyle: { 56 pasteAndMatchStyle: {
57 id: 'menu.edit.pasteAndMatchStyle', 57 id: 'menu.edit.pasteAndMatchStyle',
58 defaultMessage: '!!!Paste And Match Style', 58 defaultMessage: 'Paste And Match Style',
59 }, 59 },
60 delete: { 60 delete: {
61 id: 'menu.edit.delete', 61 id: 'menu.edit.delete',
62 defaultMessage: '!!!Delete', 62 defaultMessage: 'Delete',
63 }, 63 },
64 selectAll: { 64 selectAll: {
65 id: 'menu.edit.selectAll', 65 id: 'menu.edit.selectAll',
66 defaultMessage: '!!!Select All', 66 defaultMessage: 'Select All',
67 }, 67 },
68 findInPage: { 68 findInPage: {
69 id: 'menu.edit.findInPage', 69 id: 'menu.edit.findInPage',
70 defaultMessage: '!!!Find in Page', 70 defaultMessage: 'Find in Page',
71 }, 71 },
72 speech: { 72 speech: {
73 id: 'menu.edit.speech', 73 id: 'menu.edit.speech',
74 defaultMessage: '!!!Speech', 74 defaultMessage: 'Speech',
75 }, 75 },
76 startSpeaking: { 76 startSpeaking: {
77 id: 'menu.edit.startSpeaking', 77 id: 'menu.edit.startSpeaking',
78 defaultMessage: '!!!Start Speaking', 78 defaultMessage: 'Start Speaking',
79 }, 79 },
80 stopSpeaking: { 80 stopSpeaking: {
81 id: 'menu.edit.stopSpeaking', 81 id: 'menu.edit.stopSpeaking',
82 defaultMessage: '!!!Stop Speaking', 82 defaultMessage: 'Stop Speaking',
83 }, 83 },
84 startDictation: { 84 startDictation: {
85 id: 'menu.edit.startDictation', 85 id: 'menu.edit.startDictation',
86 defaultMessage: '!!!Start Dictation', 86 defaultMessage: 'Start Dictation',
87 }, 87 },
88 emojiSymbols: { 88 emojiSymbols: {
89 id: 'menu.edit.emojiSymbols', 89 id: 'menu.edit.emojiSymbols',
90 defaultMessage: '!!!Emoji & Symbols', 90 defaultMessage: 'Emoji & Symbols',
91 }, 91 },
92 openQuickSwitch: { 92 openQuickSwitch: {
93 id: 'menu.view.openQuickSwitch', 93 id: 'menu.view.openQuickSwitch',
94 defaultMessage: '!!!Open Quick Switch', 94 defaultMessage: 'Open Quick Switch',
95 }, 95 },
96 back: { 96 back: {
97 id: 'menu.view.back', 97 id: 'menu.view.back',
98 defaultMessage: '!!!Back', 98 defaultMessage: 'Back',
99 }, 99 },
100 forward: { 100 forward: {
101 id: 'menu.view.forward', 101 id: 'menu.view.forward',
102 defaultMessage: '!!!Forward', 102 defaultMessage: 'Forward',
103 }, 103 },
104 resetZoom: { 104 resetZoom: {
105 id: 'menu.view.resetZoom', 105 id: 'menu.view.resetZoom',
106 defaultMessage: '!!!Actual Size', 106 defaultMessage: 'Actual Size',
107 }, 107 },
108 zoomIn: { 108 zoomIn: {
109 id: 'menu.view.zoomIn', 109 id: 'menu.view.zoomIn',
110 defaultMessage: '!!!Zoom In', 110 defaultMessage: 'Zoom In',
111 }, 111 },
112 zoomOut: { 112 zoomOut: {
113 id: 'menu.view.zoomOut', 113 id: 'menu.view.zoomOut',
114 defaultMessage: '!!!Zoom Out', 114 defaultMessage: 'Zoom Out',
115 }, 115 },
116 toggleFullScreen: { 116 toggleFullScreen: {
117 id: 'menu.view.toggleFullScreen', 117 id: 'menu.view.toggleFullScreen',
118 defaultMessage: '!!!Toggle Full Screen', 118 defaultMessage: 'Toggle Full Screen',
119 }, 119 },
120 toggleDarkMode: { 120 toggleDarkMode: {
121 id: 'menu.view.toggleDarkMode', 121 id: 'menu.view.toggleDarkMode',
122 defaultMessage: '!!!Toggle Dark Mode', 122 defaultMessage: 'Toggle Dark Mode',
123 }, 123 },
124 toggleDevTools: { 124 toggleDevTools: {
125 id: 'menu.view.toggleDevTools', 125 id: 'menu.view.toggleDevTools',
126 defaultMessage: '!!!Toggle Developer Tools', 126 defaultMessage: 'Toggle Developer Tools',
127 }, 127 },
128 toggleTodosDevTools: { 128 toggleTodosDevTools: {
129 id: 'menu.view.toggleTodosDevTools', 129 id: 'menu.view.toggleTodosDevTools',
130 defaultMessage: '!!!Toggle Todos Developer Tools', 130 defaultMessage: 'Toggle Todos Developer Tools',
131 }, 131 },
132 toggleServiceDevTools: { 132 toggleServiceDevTools: {
133 id: 'menu.view.toggleServiceDevTools', 133 id: 'menu.view.toggleServiceDevTools',
134 defaultMessage: '!!!Toggle Service Developer Tools', 134 defaultMessage: 'Toggle Service Developer Tools',
135 }, 135 },
136 reloadService: { 136 reloadService: {
137 id: 'menu.view.reloadService', 137 id: 'menu.view.reloadService',
138 defaultMessage: '!!!Reload Service', 138 defaultMessage: 'Reload Service',
139 }, 139 },
140 reloadFerdi: { 140 reloadFerdi: {
141 id: 'menu.view.reloadFerdi', 141 id: 'menu.view.reloadFerdi',
142 defaultMessage: '!!!Reload Ferdi', 142 defaultMessage: 'Reload Ferdi',
143 }, 143 },
144 lockFerdi: { 144 lockFerdi: {
145 id: 'menu.view.lockFerdi', 145 id: 'menu.view.lockFerdi',
146 defaultMessage: '!!!Lock Ferdi', 146 defaultMessage: 'Lock Ferdi',
147 }, 147 },
148 reloadTodos: { 148 reloadTodos: {
149 id: 'menu.view.reloadTodos', 149 id: 'menu.view.reloadTodos',
150 defaultMessage: '!!!Reload ToDos', 150 defaultMessage: 'Reload ToDos',
151 }, 151 },
152 minimize: { 152 minimize: {
153 id: 'menu.window.minimize', 153 id: 'menu.window.minimize',
154 defaultMessage: '!!!Minimize', 154 defaultMessage: 'Minimize',
155 }, 155 },
156 close: { 156 close: {
157 id: 'menu.window.close', 157 id: 'menu.window.close',
158 defaultMessage: '!!!Close', 158 defaultMessage: 'Close',
159 }, 159 },
160 learnMore: { 160 learnMore: {
161 id: 'menu.help.learnMore', 161 id: 'menu.help.learnMore',
162 defaultMessage: '!!!Learn More', 162 defaultMessage: 'Learn More',
163 }, 163 },
164 changelog: { 164 changelog: {
165 id: 'menu.help.changelog', 165 id: 'menu.help.changelog',
166 defaultMessage: '!!!Changelog', 166 defaultMessage: 'Changelog',
167 }, 167 },
168 importExportData: { 168 importExportData: {
169 id: 'menu.help.importExportData', 169 id: 'menu.help.importExportData',
170 defaultMessage: '!!!Import/Export Configuration Data', 170 defaultMessage: 'Import/Export Configuration Data',
171 }, 171 },
172 support: { 172 support: {
173 id: 'menu.help.support', 173 id: 'menu.help.support',
174 defaultMessage: '!!!Support', 174 defaultMessage: 'Support',
175 }, 175 },
176 debugInfo: { 176 debugInfo: {
177 id: 'menu.help.debugInfo', 177 id: 'menu.help.debugInfo',
178 defaultMessage: '!!!Copy Debug Information', 178 defaultMessage: 'Copy Debug Information',
179 }, 179 },
180 publishDebugInfo: { 180 publishDebugInfo: {
181 id: 'menu.help.publishDebugInfo', 181 id: 'menu.help.publishDebugInfo',
182 defaultMessage: '!!!Publish Debug Information', 182 defaultMessage: 'Publish Debug Information',
183 }, 183 },
184 debugInfoCopiedHeadline: { 184 debugInfoCopiedHeadline: {
185 id: 'menu.help.debugInfoCopiedHeadline', 185 id: 'menu.help.debugInfoCopiedHeadline',
186 defaultMessage: '!!!Ferdi Debug Information', 186 defaultMessage: 'Ferdi Debug Information',
187 }, 187 },
188 debugInfoCopiedBody: { 188 debugInfoCopiedBody: {
189 id: 'menu.help.debugInfoCopiedBody', 189 id: 'menu.help.debugInfoCopiedBody',
190 defaultMessage: 190 defaultMessage: 'Your Debug Information has been copied to your clipboard.',
191 '!!!Your Debug Information has been copied to your clipboard.',
192 }, 191 },
193 touchId: { 192 touchId: {
194 id: 'locked.touchId', 193 id: 'locked.touchId',
195 defaultMessage: '!!!Unlock with Touch ID', 194 defaultMessage: 'Unlock with Touch ID',
196 }, 195 },
197 touchIdPrompt: { 196 touchIdPrompt: {
198 id: 'locked.touchIdPrompt', 197 id: 'locked.touchIdPrompt',
199 defaultMessage: '!!!unlock via Touch ID', 198 defaultMessage: 'unlock via Touch ID',
200 }, 199 },
201 tos: { 200 tos: {
202 id: 'menu.help.tos', 201 id: 'menu.help.tos',
203 defaultMessage: '!!!Terms of Service', 202 defaultMessage: 'Terms of Service',
204 }, 203 },
205 privacy: { 204 privacy: {
206 id: 'menu.help.privacy', 205 id: 'menu.help.privacy',
207 defaultMessage: '!!!Privacy Statement', 206 defaultMessage: 'Privacy Statement',
208 }, 207 },
209 file: { 208 file: {
210 id: 'menu.file', 209 id: 'menu.file',
211 defaultMessage: '!!!File', 210 defaultMessage: 'File',
212 }, 211 },
213 view: { 212 view: {
214 id: 'menu.view', 213 id: 'menu.view',
215 defaultMessage: '!!!View', 214 defaultMessage: 'View',
216 }, 215 },
217 services: { 216 services: {
218 id: 'menu.services', 217 id: 'menu.services',
219 defaultMessage: '!!!Services', 218 defaultMessage: 'Services',
220 }, 219 },
221 window: { 220 window: {
222 id: 'menu.window', 221 id: 'menu.window',
223 defaultMessage: '!!!Window', 222 defaultMessage: 'Window',
224 }, 223 },
225 help: { 224 help: {
226 id: 'menu.help', 225 id: 'menu.help',
227 defaultMessage: '!!!Help', 226 defaultMessage: 'Help',
228 }, 227 },
229 about: { 228 about: {
230 id: 'menu.app.about', 229 id: 'menu.app.about',
231 defaultMessage: '!!!About Ferdi', 230 defaultMessage: 'About Ferdi',
232 }, 231 },
233 checkForUpdates: { 232 checkForUpdates: {
234 id: 'menu.app.checkForUpdates', 233 id: 'menu.app.checkForUpdates',
235 defaultMessage: '!!!Check for updates', 234 defaultMessage: 'Check for updates',
236 }, 235 },
237 hide: { 236 hide: {
238 id: 'menu.app.hide', 237 id: 'menu.app.hide',
239 defaultMessage: '!!!Hide', 238 defaultMessage: 'Hide',
240 }, 239 },
241 hideOthers: { 240 hideOthers: {
242 id: 'menu.app.hideOthers', 241 id: 'menu.app.hideOthers',
243 defaultMessage: '!!!Hide Others', 242 defaultMessage: 'Hide Others',
244 }, 243 },
245 unhide: { 244 unhide: {
246 id: 'menu.app.unhide', 245 id: 'menu.app.unhide',
247 defaultMessage: '!!!Unhide', 246 defaultMessage: 'Unhide',
248 }, 247 },
249 autohideMenuBar: { 248 autohideMenuBar: {
250 id: 'menu.app.autohideMenuBar', 249 id: 'menu.app.autohideMenuBar',
251 defaultMessage: '!!!Auto-hide menu bar', 250 defaultMessage: 'Auto-hide menu bar',
252 }, 251 },
253 addNewService: { 252 addNewService: {
254 id: 'menu.services.addNewService', 253 id: 'menu.services.addNewService',
255 defaultMessage: '!!!Add New Service...', 254 defaultMessage: 'Add New Service...',
256 }, 255 },
257 addNewWorkspace: { 256 addNewWorkspace: {
258 id: 'menu.workspaces.addNewWorkspace', 257 id: 'menu.workspaces.addNewWorkspace',
259 defaultMessage: '!!!Add New Workspace...', 258 defaultMessage: 'Add New Workspace...',
260 }, 259 },
261 openWorkspaceDrawer: { 260 openWorkspaceDrawer: {
262 id: 'menu.workspaces.openWorkspaceDrawer', 261 id: 'menu.workspaces.openWorkspaceDrawer',
263 defaultMessage: '!!!Open workspace drawer', 262 defaultMessage: 'Open workspace drawer',
264 }, 263 },
265 closeWorkspaceDrawer: { 264 closeWorkspaceDrawer: {
266 id: 'menu.workspaces.closeWorkspaceDrawer', 265 id: 'menu.workspaces.closeWorkspaceDrawer',
267 defaultMessage: '!!!Close workspace drawer', 266 defaultMessage: 'Close workspace drawer',
268 }, 267 },
269 activateNextService: { 268 activateNextService: {
270 id: 'menu.services.setNextServiceActive', 269 id: 'menu.services.setNextServiceActive',
271 defaultMessage: '!!!Activate next service...', 270 defaultMessage: 'Activate next service...',
272 }, 271 },
273 activatePreviousService: { 272 activatePreviousService: {
274 id: 'menu.services.activatePreviousService', 273 id: 'menu.services.activatePreviousService',
275 defaultMessage: '!!!Activate previous service...', 274 defaultMessage: 'Activate previous service...',
276 }, 275 },
277 muteApp: { 276 muteApp: {
278 id: 'sidebar.muteApp', 277 id: 'sidebar.muteApp',
279 defaultMessage: '!!!Disable notifications & audio', 278 defaultMessage: 'Disable notifications & audio',
280 }, 279 },
281 unmuteApp: { 280 unmuteApp: {
282 id: 'sidebar.unmuteApp', 281 id: 'sidebar.unmuteApp',
283 defaultMessage: '!!!Enable notifications & audio', 282 defaultMessage: 'Enable notifications & audio',
284 }, 283 },
285 workspaces: { 284 workspaces: {
286 id: 'menu.workspaces', 285 id: 'menu.workspaces',
287 defaultMessage: '!!!Workspaces', 286 defaultMessage: 'Workspaces',
288 }, 287 },
289 defaultWorkspace: { 288 defaultWorkspace: {
290 id: 'menu.workspaces.defaultWorkspace', 289 id: 'menu.workspaces.defaultWorkspace',
291 defaultMessage: '!!!Default', 290 defaultMessage: 'Default',
292 }, 291 },
293 todos: { 292 todos: {
294 id: 'menu.todos', 293 id: 'menu.todos',
295 defaultMessage: '!!!Todos', 294 defaultMessage: 'Todos',
296 }, 295 },
297 openTodosDrawer: { 296 openTodosDrawer: {
298 id: 'menu.Todoss.openTodosDrawer', 297 id: 'menu.Todoss.openTodosDrawer',
299 defaultMessage: '!!!Open Todos drawer', 298 defaultMessage: 'Open Todos drawer',
300 }, 299 },
301 closeTodosDrawer: { 300 closeTodosDrawer: {
302 id: 'menu.Todoss.closeTodosDrawer', 301 id: 'menu.Todoss.closeTodosDrawer',
303 defaultMessage: '!!!Close Todos drawer', 302 defaultMessage: 'Close Todos drawer',
304 }, 303 },
305 enableTodos: { 304 enableTodos: {
306 id: 'menu.todos.enableTodos', 305 id: 'menu.todos.enableTodos',
307 defaultMessage: '!!!Enable Todos', 306 defaultMessage: 'Enable Todos',
308 }, 307 },
309 serviceGoHome: { 308 serviceGoHome: {
310 id: 'menu.services.goHome', 309 id: 'menu.services.goHome',
311 defaultMessage: '!!!Home', 310 defaultMessage: 'Home',
312 }, 311 },
313}); 312});
314 313
@@ -557,7 +556,7 @@ const _titleBarTemplateFactory = (intl, locked) => [
557 }, 556 },
558]; 557];
559 558
560export default class FranzMenu { 559class FranzMenu {
561 @observable currentTemplate = []; 560 @observable currentTemplate = [];
562 561
563 constructor(stores, actions) { 562 constructor(stores, actions) {
@@ -1126,3 +1125,5 @@ export default class FranzMenu {
1126 return name; 1125 return name;
1127 } 1126 }
1128} 1127}
1128
1129export default FranzMenu;
diff --git a/src/routes.js b/src/routes.js
index 4d32a59e0..502ea86f5 100644
--- a/src/routes.js
+++ b/src/routes.js
@@ -30,7 +30,6 @@ import { WORKSPACES_ROUTES } from './features/workspaces/constants';
30 30
31import SettingsStore from './stores/SettingsStore'; 31import SettingsStore from './stores/SettingsStore';
32 32
33export default
34@inject('stores', 'actions') 33@inject('stores', 'actions')
35@observer 34@observer
36class Routes extends Component { 35class Routes extends Component {
@@ -95,3 +94,5 @@ Routes.wrappedComponent.propTypes = {
95 }).isRequired, 94 }).isRequired,
96 history: PropTypes.any.isRequired, 95 history: PropTypes.any.isRequired,
97}; 96};
97
98export default Routes;