aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.all-contributorsrc76
-rw-r--r--.gitmodules4
-rw-r--r--.travis.yml29
-rw-r--r--README.md116
-rw-r--r--appveyor.yml4
-rw-r--r--branding/screenshots/hero.pngbin352745 -> 321357 bytes
-rw-r--r--build-helpers/images/win-app-ico.icobin4286 -> 162459 bytes
-rw-r--r--next_release.md44
-rw-r--r--package-lock.json2
-rw-r--r--package.json2
m---------recipes0
-rw-r--r--src/api/apiBase.js21
-rw-r--r--src/api/server/ServerApi.js23
-rw-r--r--src/assets/themeInfo.json2
-rw-r--r--src/components/services/content/ServiceView.js30
-rw-r--r--src/components/services/content/ServiceWebview.js5
-rw-r--r--src/components/settings/settings/EditSettingsForm.js3
-rw-r--r--src/components/ui/FeatureList.js2
-rw-r--r--src/config.js13
-rw-r--r--src/containers/settings/EditSettingsScreen.js10
-rw-r--r--src/i18n/locales/defaultMessages.json169
-rw-r--r--src/i18n/locales/en-US.json1
-rw-r--r--src/i18n/messages/src/components/settings/settings/EditSettingsForm.json116
-rw-r--r--src/i18n/messages/src/containers/settings/EditSettingsScreen.json53
-rw-r--r--src/index.js13
-rw-r--r--src/lib/Menu.js3
m---------src/server0
-rw-r--r--src/stores/AppStore.js18
-rw-r--r--src/stores/FeaturesStore.js5
-rw-r--r--src/stores/GlobalErrorStore.js52
-rw-r--r--src/stores/ServicesStore.js8
-rw-r--r--src/stores/UIStore.js15
-rw-r--r--src/stores/UserStore.js13
-rw-r--r--src/stores/lib/CachedRequest.js4
-rw-r--r--src/styles/tabs.scss2
35 files changed, 595 insertions, 263 deletions
diff --git a/.all-contributorsrc b/.all-contributorsrc
index cd9704edf..832fcd243 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -1,6 +1,6 @@
1{ 1{
2 "projectName": "ferdi", 2 "projectName": "ferdi",
3 "projectOwner": "kytwb", 3 "projectOwner": "getferdi",
4 "repoType": "github", 4 "repoType": "github",
5 "repoHost": "https://github.com", 5 "repoHost": "https://github.com",
6 "files": [ 6 "files": [
@@ -63,7 +63,8 @@
63 "projectManagement", 63 "projectManagement",
64 "review", 64 "review",
65 "infra", 65 "infra",
66 "fundingFinding" 66 "fundingFinding",
67 "blog"
67 ] 68 ]
68 }, 69 },
69 { 70 {
@@ -158,7 +159,10 @@
158 "contributions": [ 159 "contributions": [
159 "bug", 160 "bug",
160 "code", 161 "code",
161 "translation" 162 "translation",
163 "content",
164 "doc",
165 "platform"
162 ] 166 ]
163 }, 167 },
164 { 168 {
@@ -172,6 +176,72 @@
172 "infra", 176 "infra",
173 "platform" 177 "platform"
174 ] 178 ]
179 },
180 {
181 "login": "Gaboris",
182 "name": "Gaboris",
183 "avatar_url": "https://avatars2.githubusercontent.com/u/9462372?v=4",
184 "profile": "https://github.com/Gaboris",
185 "contributions": [
186 "question",
187 "bug"
188 ]
189 },
190 {
191 "login": "incace",
192 "name": "Ce",
193 "avatar_url": "https://avatars1.githubusercontent.com/u/61343?v=4",
194 "profile": "http://www.cu3ed.com/",
195 "contributions": [
196 "bug"
197 ]
198 },
199 {
200 "login": "pztrn",
201 "name": "Stanislav N.",
202 "avatar_url": "https://avatars1.githubusercontent.com/u/869402?v=4",
203 "profile": "http://pztrn.name/",
204 "contributions": [
205 "bug"
206 ]
207 },
208 {
209 "login": "patrickcurl",
210 "name": "Patrick Curl",
211 "avatar_url": "https://avatars1.githubusercontent.com/u/1470061?v=4",
212 "profile": "http://www.patrickcurl.com",
213 "contributions": [
214 "ideas"
215 ]
216 },
217 {
218 "login": "Stanzilla",
219 "name": "Benjamin Staneck",
220 "avatar_url": "https://avatars3.githubusercontent.com/u/75278?v=4",
221 "profile": "https://github.com/Stanzilla",
222 "contributions": [
223 "design"
224 ]
225 },
226 {
227 "login": "ammarmalhas",
228 "name": "ammarmalhas",
229 "avatar_url": "https://avatars1.githubusercontent.com/u/57057209?v=4",
230 "profile": "https://github.com/ammarmalhas",
231 "contributions": [
232 "bug",
233 "security"
234 ]
235 },
236 {
237 "login": "steliyan",
238 "name": "Steliyan Stoyanov",
239 "avatar_url": "https://avatars1.githubusercontent.com/u/1850292?v=4",
240 "profile": "https://github.com/steliyan",
241 "contributions": [
242 "code",
243 "ideas"
244 ]
175 } 245 }
176 ], 246 ],
177 "contributorsPerLine": 6 247 "contributorsPerLine": 6
diff --git a/.gitmodules b/.gitmodules
index 00bc1d26d..d121d6c01 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,8 +1,8 @@
1[submodule "recipes"] 1[submodule "recipes"]
2 path = recipes 2 path = recipes
3 url = https://github.com/getferdi/recipes.git 3 url = git@github.com:getferdi/recipes.git
4 ignore = all 4 ignore = all
5[submodule "src/server"] 5[submodule "src/server"]
6 path = src/server 6 path = src/server
7 url = https://github.com/getferdi/internal-server.git 7 url = git@github.com:getferdi/internal-server.git
8 ignore = all 8 ignore = all
diff --git a/.travis.yml b/.travis.yml
index ff015b92c..ba8bc86ac 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,18 +1,25 @@
1matrix: 1matrix:
2 include: 2 include:
3 - os: linux 3 - os: linux
4 dist: xenial 4 dist: xenial
5 addons: 5 addons:
6 apt: 6 apt:
7 packages: 7 packages:
8 - libx11-dev 8 - libx11-dev
9 - libxext-dev 9 - libxext-dev
10 - libxss-dev 10 - libxss-dev
11 - libxkbfile-dev 11 - libxkbfile-dev
12 - os: osx 12 - os: osx
13 osx_image: xcode11 13 osx_image: xcode11
14 14
15language: node_js 15language: node_js
16# Handle git submodules yourself
17git:
18 submodules: false
19# Use sed to replace the SSH URL with the public URL, then initialize submodules
20before_install:
21 - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules; else sed -i '' 's/git@github.com:/https:\/\/github.com\//' .gitmodules; fi
22 - git submodule update --init --recursive
16install: 23install:
17 - echo do nothing 24 - echo do nothing
18before_script: 25before_script:
diff --git a/README.md b/README.md
index 285c80bb0..c2762a498 100644
--- a/README.md
+++ b/README.md
@@ -4,14 +4,67 @@
4 4
5# Ferdi 5# Ferdi
6 6
7[![Backers on Open Collective](https://opencollective.com/getferdi/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/getferdi/sponsors/badge.svg)](#sponsors) [![Build Status Windows](https://ci.appveyor.com/api/projects/status/2ckfbmoxp36fye5b?svg=true)](https://ci.appveyor.com/project/kytwb/ferdi) 7<p align="center">
8[![Build Status Mac & Linux](https://travis-ci.org/getferdi/ferdi.svg?branch=master)](https://travis-ci.org/getferdi/ferdi) 8<a href="#backers-via-opencollective"><img alt="Open Collective backers" src="https://img.shields.io/opencollective/backers/getferdi?logo=open-collective"></a>
9<a href="#sponsors-via-opencollective"><img alt="Open Collective sponsors" src="https://img.shields.io/opencollective/sponsors/getferdi?logo=open-collective"></a>
10<a href="https://ci.appveyor.com/project/kytwb/ferdi"><img alt="Build Status Windows" src="https://img.shields.io/appveyor/ci/kytwb/ferdi/master?logo=appveyor"></a>
11<a href="https://travis-ci.org/getferdi/ferdi"><img alt="Build Status Mac & Linux" src="https://img.shields.io/travis/getferdi/ferdi/master?logo=travis"></a>
12</p>
9 13
10🤴🏽 Hard-fork of [Franz](https://github.com/meetfranz/franz), adding awesome features and removing unwanted ones. 14🤴🏽 Hard-fork of [Franz](https://github.com/meetfranz/franz), adding awesome features and removing unwanted ones.
11 15
16### Table of contents
17
18<details>
19<summary>Ferdi</summary>
20<ul>
21<li><a href="#what-is-ferdi-">What is Ferdi ?</a></li>
22<li><a href="#what-ferdi-looks-like-">What Ferdi looks like ?</a></li>
23<li><a href="#download-ferdi">Download Ferdi</a>
24<ul>
25<li><a href="#or-use-homebrew-macos-only">Or use homebrew</a></li>
26</ul>
27</li>
28<li><a href="#ferdi-specific-features">Ferdi-specific Features</a></li>
29<li><a href="#development">Development</a></li>
30<ul>
31<li><a href="#install-os-dependencies">Install OS dependencies</a></li>
32<li><a href="#clone-repository-with-submodule">Clone repository with submodule</a></li>
33<li><a href="#install-dependencies">Install dependencies</a></li>
34<li><a href="#fix-native-modules-to-match-current-electron-node-version">Fix native modules to match current electron node version</a></li>
35<li><a href="#start-development-app">Start development app</a></li>
36<li><a href="#packaging">Packaging</a></li>
37<li><a href="#release">Release</a></li>
38</ul>
39<li><a href="#contributors-">Contributors ✨</a></li>
40<li><a href="#backers-via-opencollective">Backers via OpenCollective</a></li>
41<li><a href="#sponsors-via-opencollective">Sponsors via OpenCollective</a></li>
42</ul>
43</details>
44
45### What is Ferdi ?
46
47Ferdi is a messaging browser that allows you to combine your favorite messaging services into one application. It is based on Franz - a software already used by thousands of people - with the difference that Ferdi gives you many additonal features and doesn't restrict its usage! Ferdi is compatible with your existing Franz account so you can continue right where you left off. Find out more about Ferdi and its features on [getferdi.com](https://getferdi.com).
48
49### What Ferdi looks like ?
50
51<details>
52<summary>Screenshots</summary>
53<p align="center">
54<img alt="Keep all your messaging services in one place." src="./branding/screenshots/hero.png">
55<em>"Keep all your messaging services in one place."</em>
56<img alt="Order your services with Ferdi Workspaces." src="./branding/screenshots/workspaces.png">
57<em>"Order your services with Ferdi Workspaces."</em>
58<img alt="Always keep your Todo list open with Ferdi Todos." src="./branding/screenshots/todos.png">
59<em>"Always keep your Todo list open with Ferdi Todos."</em>
60<img alt="Supporting all your services." src="./branding/screenshots/service-store.png">
61<em>"Supporting all your services."</em>
62</p>
63</details>
64
12## Download Ferdi 65## Download Ferdi
13 66
14You can find the installers in the [latest release](https://github.com/getferdi/ferdi/releases) assets. 67You can find the installers in the [latest stable release](https://github.com/getferdi/ferdi/releases/latest) assets and [all the other release here](https://github.com/getferdi/ferdi/releases).
15 68
16### Or use homebrew (macOS only) 69### Or use homebrew (macOS only)
17 70
@@ -53,38 +106,36 @@ You can find the installers in the [latest release](https://github.com/getferdi/
53 106
54## Development 107## Development
55 108
56### Preparations 109### Install OS dependencies
57
58#### Install OS dependencies
59 110
60##### Node.js 111#### Node.js
61 112
62Please make sure you are running NodeJS v10 ([v10.16.3](https://nodejs.org/dist/v10.16.3/) suggested). Versions above will throw an errow when trying to install due to an [old fsevent dependency](https://github.com/fsevents/fsevents/issues/278). 113Please make sure you are running NodeJS v10 ([v10.16.3](https://nodejs.org/dist/v10.16.3/) suggested). Versions above will throw an errow when trying to install due to an [old fsevent dependency](https://github.com/fsevents/fsevents/issues/278).
63 114
64##### Git 115#### Git
65 116
66The version [2.23.0](https://github.com/git-for-windows/git/releases/tag/v2.23.0.windows.1) for Git is working fine for development. You can then use the console from Git to do the development procedure. 117The version [2.23.0](https://github.com/git-for-windows/git/releases/tag/v2.23.0.windows.1) for Git is working fine for development. You can then use the console from Git to do the development procedure.
67 118
68##### Debian/Ubuntu 119#### Debian/Ubuntu
69 120
70```bash 121```bash
71$ apt install libx11-dev libxext-dev libxss-dev libxkbfile-dev 122$ apt install libx11-dev libxext-dev libxss-dev libxkbfile-dev
72``` 123```
73 124
74##### Fedora 125#### Fedora
75 126
76```bash 127```bash
77$ dnf install libX11-devel libXext-devel libXScrnSaver-devel libxkbfile-devel 128$ dnf install libX11-devel libXext-devel libXScrnSaver-devel libxkbfile-devel
78``` 129```
79 130
80##### Windows 131#### Windows
81 132
82```bash 133```bash
83$ npm install --global windows-build-tools // Windows 10 134$ npm install --global windows-build-tools // Windows 10
84$ npm install --global windows-build-tools --vs2015 // Windows 7 135$ npm install --global windows-build-tools --vs2015 // Windows 7
85``` 136```
86 137
87#### Clone repository with submodule 138### Clone repository with submodule
88 139
89```bash 140```bash
90$ git clone https://github.com/getferdi/ferdi.git 141$ git clone https://github.com/getferdi/ferdi.git
@@ -145,34 +196,39 @@ When pushing a new tag, the CI builds will create a draft GitHub release and upl
145Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 196Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
146 197
147<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --> 198<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
148<!-- prettier-ignore-start --> 199<!-- prettier-ignore -->
149<!-- markdownlint-disable -->
150<table> 200<table>
151 <tr> 201 <tr>
152 <td align="center"><a href="https://vantezzen.io"><img src="https://avatars2.githubusercontent.com/u/10333196?v=4" width="40px;" alt="Bennett"/><br /><sub><b>Bennett</b></sub></a><br /><a href="https://github.com/kytwb/ferdi/commits?author=vantezzen" title="Code">💻</a> <a href="#design-vantezzen" title="Design">🎨</a> <a href="https://github.com/kytwb/ferdi/commits?author=vantezzen" title="Documentation">📖</a> <a href="#ideas-vantezzen" title="Ideas, Planning, & Feedback">🤔</a> <a href="#translation-vantezzen" title="Translation">🌍</a> <a href="#example-vantezzen" title="Examples">💡</a> <a href="https://github.com/kytwb/ferdi/issues?q=author%3Avantezzen" title="Bug reports">🐛</a> <a href="#content-vantezzen" title="Content">🖋</a> <a href="#infra-vantezzen" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#userTesting-vantezzen" title="User Testing">📓</a> <a href="#question-vantezzen" title="Answering Questions">💬</a> <a href="#projectManagement-vantezzen" title="Project Management">📆</a> <a href="#review-vantezzen" title="Reviewed Pull Requests">👀</a></td> 202 <td align="center"><a href="https://vantezzen.io"><img src="https://avatars2.githubusercontent.com/u/10333196?v=4" width="40px;" alt="Bennett"/><br /><sub><b>Bennett</b></sub></a><br /><a href="https://github.com/getferdi/ferdi/commits?author=vantezzen" title="Code">💻</a> <a href="#design-vantezzen" title="Design">🎨</a> <a href="https://github.com/getferdi/ferdi/commits?author=vantezzen" title="Documentation">📖</a> <a href="#ideas-vantezzen" title="Ideas, Planning, & Feedback">🤔</a> <a href="#translation-vantezzen" title="Translation">🌍</a> <a href="#example-vantezzen" title="Examples">💡</a> <a href="https://github.com/getferdi/ferdi/issues?q=author%3Avantezzen" title="Bug reports">🐛</a> <a href="#content-vantezzen" title="Content">🖋</a> <a href="#infra-vantezzen" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#userTesting-vantezzen" title="User Testing">📓</a> <a href="#question-vantezzen" title="Answering Questions">💬</a> <a href="#projectManagement-vantezzen" title="Project Management">📆</a> <a href="#review-vantezzen" title="Reviewed Pull Requests">👀</a></td>
153 <td align="center"><a href="http://www.adlk.io"><img src="https://avatars1.githubusercontent.com/u/3265004?v=4" width="40px;" alt="Stefan Malzner"/><br /><sub><b>Stefan Malzner</b></sub></a><br /><a href="https://github.com/kytwb/ferdi/commits?author=adlk" title="Code">💻</a> <a href="#content-adlk" title="Content">🖋</a> <a href="#design-adlk" title="Design">🎨</a> <a href="https://github.com/kytwb/ferdi/commits?author=adlk" title="Documentation">📖</a> <a href="#ideas-adlk" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-adlk" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#projectManagement-adlk" title="Project Management">📆</a> <a href="https://github.com/kytwb/ferdi/commits?author=adlk" title="Tests">⚠️</a> <a href="#translation-adlk" title="Translation">🌍</a></td> 203 <td align="center"><a href="http://www.adlk.io"><img src="https://avatars1.githubusercontent.com/u/3265004?v=4" width="40px;" alt="Stefan Malzner"/><br /><sub><b>Stefan Malzner</b></sub></a><br /><a href="https://github.com/getferdi/ferdi/commits?author=adlk" title="Code">💻</a> <a href="#content-adlk" title="Content">🖋</a> <a href="#design-adlk" title="Design">🎨</a> <a href="https://github.com/getferdi/ferdi/commits?author=adlk" title="Documentation">📖</a> <a href="#ideas-adlk" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-adlk" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#projectManagement-adlk" title="Project Management">📆</a> <a href="https://github.com/getferdi/ferdi/commits?author=adlk" title="Tests">⚠️</a> <a href="#translation-adlk" title="Translation">🌍</a></td>
154 <td align="center"><a href="https://twitter.com/kytwb"><img src="https://avatars0.githubusercontent.com/u/412895?v=4" width="40px;" alt="Amine Mouafik"/><br /><sub><b>Amine Mouafik</b></sub></a><br /><a href="#question-kytwb" title="Answering Questions">💬</a> <a href="https://github.com/kytwb/ferdi/commits?author=kytwb" title="Code">💻</a> <a href="https://github.com/kytwb/ferdi/commits?author=kytwb" title="Documentation">📖</a> <a href="#ideas-kytwb" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-kytwb" title="Maintenance">🚧</a> <a href="#platform-kytwb" title="Packaging/porting to new platform">📦</a> <a href="#projectManagement-kytwb" title="Project Management">📆</a> <a href="#review-kytwb" title="Reviewed Pull Requests">👀</a> <a href="#infra-kytwb" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#fundingFinding-kytwb" title="Funding Finding">🔍</a></td> 204 <td align="center"><a href="https://twitter.com/kytwb"><img src="https://avatars0.githubusercontent.com/u/412895?v=4" width="40px;" alt="Amine Mouafik"/><br /><sub><b>Amine Mouafik</b></sub></a><br /><a href="#question-kytwb" title="Answering Questions">💬</a> <a href="https://github.com/getferdi/ferdi/commits?author=kytwb" title="Code">💻</a> <a href="https://github.com/getferdi/ferdi/commits?author=kytwb" title="Documentation">📖</a> <a href="#ideas-kytwb" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-kytwb" title="Maintenance">🚧</a> <a href="#platform-kytwb" title="Packaging/porting to new platform">📦</a> <a href="#projectManagement-kytwb" title="Project Management">📆</a> <a href="#review-kytwb" title="Reviewed Pull Requests">👀</a> <a href="#infra-kytwb" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#fundingFinding-kytwb" title="Funding Finding">🔍</a> <a href="#blog-kytwb" title="Blogposts">📝</a></td>
155 <td align="center"><a href="http://seriesgt.com"><img src="https://avatars3.githubusercontent.com/u/5977640?v=4" width="40px;" alt="ZeroCool"/><br /><sub><b>ZeroCool</b></sub></a><br /><a href="https://github.com/kytwb/ferdi/commits?author=ZeroCool940711" title="Code">💻</a> <a href="#ideas-ZeroCool940711" title="Ideas, Planning, & Feedback">🤔</a></td> 205 <td align="center"><a href="http://seriesgt.com"><img src="https://avatars3.githubusercontent.com/u/5977640?v=4" width="40px;" alt="ZeroCool"/><br /><sub><b>ZeroCool</b></sub></a><br /><a href="https://github.com/getferdi/ferdi/commits?author=ZeroCool940711" title="Code">💻</a> <a href="#ideas-ZeroCool940711" title="Ideas, Planning, & Feedback">🤔</a></td>
156 <td align="center"><a href="https://github.com/rseitbekov"><img src="https://avatars2.githubusercontent.com/u/35684439?v=4" width="40px;" alt="rseitbekov"/><br /><sub><b>rseitbekov</b></sub></a><br /><a href="https://github.com/kytwb/ferdi/commits?author=rseitbekov" title="Code">💻</a></td> 206 <td align="center"><a href="https://github.com/rseitbekov"><img src="https://avatars2.githubusercontent.com/u/35684439?v=4" width="40px;" alt="rseitbekov"/><br /><sub><b>rseitbekov</b></sub></a><br /><a href="https://github.com/getferdi/ferdi/commits?author=rseitbekov" title="Code">💻</a></td>
157 <td align="center"><a href="https://djangogigs.com/developers/peter-bittner/"><img src="https://avatars2.githubusercontent.com/u/665072?v=4" width="40px;" alt="Peter Bittner"/><br /><sub><b>Peter Bittner</b></sub></a><br /><a href="#ideas-bittner" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/kytwb/ferdi/issues?q=author%3Abittner" title="Bug reports">🐛</a></td> 207 <td align="center"><a href="https://djangogigs.com/developers/peter-bittner/"><img src="https://avatars2.githubusercontent.com/u/665072?v=4" width="40px;" alt="Peter Bittner"/><br /><sub><b>Peter Bittner</b></sub></a><br /><a href="#ideas-bittner" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/getferdi/ferdi/issues?q=author%3Abittner" title="Bug reports">🐛</a></td>
158 </tr> 208 </tr>
159 <tr> 209 <tr>
160 <td align="center"><a href="https://github.com/justus-saul"><img src="https://avatars1.githubusercontent.com/u/5861826?v=4" width="40px;" alt="Justus Saul"/><br /><sub><b>Justus Saul</b></sub></a><br /><a href="https://github.com/kytwb/ferdi/issues?q=author%3Ajustus-saul" title="Bug reports">🐛</a> <a href="#ideas-justus-saul" title="Ideas, Planning, & Feedback">🤔</a></td> 210 <td align="center"><a href="https://github.com/justus-saul"><img src="https://avatars1.githubusercontent.com/u/5861826?v=4" width="40px;" alt="Justus Saul"/><br /><sub><b>Justus Saul</b></sub></a><br /><a href="https://github.com/getferdi/ferdi/issues?q=author%3Ajustus-saul" title="Bug reports">🐛</a> <a href="#ideas-justus-saul" title="Ideas, Planning, & Feedback">🤔</a></td>
161 <td align="center"><a href="https://github.com/igreil"><img src="https://avatars0.githubusercontent.com/u/17239151?v=4" width="40px;" alt="igreil"/><br /><sub><b>igreil</b></sub></a><br /><a href="#ideas-igreil" title="Ideas, Planning, & Feedback">🤔</a></td> 211 <td align="center"><a href="https://github.com/igreil"><img src="https://avatars0.githubusercontent.com/u/17239151?v=4" width="40px;" alt="igreil"/><br /><sub><b>igreil</b></sub></a><br /><a href="#ideas-igreil" title="Ideas, Planning, & Feedback">🤔</a></td>
162 <td align="center"><a href="http://marcolopes.eu"><img src="https://avatars1.githubusercontent.com/u/431889?v=4" width="40px;" alt="Marco Lopes"/><br /><sub><b>Marco Lopes</b></sub></a><br /><a href="#ideas-marcolopes" title="Ideas, Planning, & Feedback">🤔</a></td> 212 <td align="center"><a href="http://marcolopes.eu"><img src="https://avatars1.githubusercontent.com/u/431889?v=4" width="40px;" alt="Marco Lopes"/><br /><sub><b>Marco Lopes</b></sub></a><br /><a href="#ideas-marcolopes" title="Ideas, Planning, & Feedback">🤔</a></td>
163 <td align="center"><a href="https://github.com/dayzlun"><img src="https://avatars3.githubusercontent.com/u/17259690?v=4" width="40px;" alt="dayzlun"/><br /><sub><b>dayzlun</b></sub></a><br /><a href="https://github.com/kytwb/ferdi/issues?q=author%3Adayzlun" title="Bug reports">🐛</a></td> 213 <td align="center"><a href="https://github.com/dayzlun"><img src="https://avatars3.githubusercontent.com/u/17259690?v=4" width="40px;" alt="dayzlun"/><br /><sub><b>dayzlun</b></sub></a><br /><a href="https://github.com/getferdi/ferdi/issues?q=author%3Adayzlun" title="Bug reports">🐛</a></td>
164 <td align="center"><a href="https://twitter.com/tobigue_"><img src="https://avatars2.githubusercontent.com/u/1560152?v=4" width="40px;" alt="Tobias Günther"/><br /><sub><b>Tobias Günther</b></sub></a><br /><a href="#ideas-tobigue" title="Ideas, Planning, & Feedback">🤔</a></td> 214 <td align="center"><a href="https://twitter.com/tobigue_"><img src="https://avatars2.githubusercontent.com/u/1560152?v=4" width="40px;" alt="Tobias Günther"/><br /><sub><b>Tobias Günther</b></sub></a><br /><a href="#ideas-tobigue" title="Ideas, Planning, & Feedback">🤔</a></td>
165 <td align="center"><a href="https://github.com/AGCaesar"><img src="https://avatars3.githubusercontent.com/u/7844066?v=4" width="40px;" alt="AGCaesar"/><br /><sub><b>AGCaesar</b></sub></a><br /><a href="#platform-AGCaesar" title="Packaging/porting to new platform">📦</a></td> 215 <td align="center"><a href="https://github.com/AGCaesar"><img src="https://avatars3.githubusercontent.com/u/7844066?v=4" width="40px;" alt="AGCaesar"/><br /><sub><b>AGCaesar</b></sub></a><br /><a href="#platform-AGCaesar" title="Packaging/porting to new platform">📦</a></td>
166 </tr> 216 </tr>
167 <tr> 217 <tr>
168 <td align="center"><a href="https://github.com/Makazzz"><img src="https://avatars2.githubusercontent.com/u/49844464?v=4" width="40px;" alt="Makazzz"/><br /><sub><b>Makazzz</b></sub></a><br /><a href="https://github.com/kytwb/ferdi/issues?q=author%3AMakazzz" title="Bug reports">🐛</a> <a href="https://github.com/kytwb/ferdi/commits?author=Makazzz" title="Code">💻</a> <a href="#translation-Makazzz" title="Translation">🌍</a></td> 218 <td align="center"><a href="https://github.com/Makazzz"><img src="https://avatars2.githubusercontent.com/u/49844464?v=4" width="40px;" alt="Makazzz"/><br /><sub><b>Makazzz</b></sub></a><br /><a href="https://github.com/getferdi/ferdi/issues?q=author%3AMakazzz" title="Bug reports">🐛</a> <a href="https://github.com/getferdi/ferdi/commits?author=Makazzz" title="Code">💻</a> <a href="#translation-Makazzz" title="Translation">🌍</a> <a href="#content-Makazzz" title="Content">🖋</a> <a href="https://github.com/getferdi/ferdi/commits?author=Makazzz" title="Documentation">📖</a> <a href="#platform-Makazzz" title="Packaging/porting to new platform">📦</a></td>
169 <td align="center"><a href="https://github.com/xthursdayx"><img src="https://avatars0.githubusercontent.com/u/18044308?v=4" width="40px;" alt="xthursdayx"/><br /><sub><b>xthursdayx</b></sub></a><br /><a href="https://github.com/kytwb/ferdi/commits?author=xthursdayx" title="Code">💻</a> <a href="https://github.com/kytwb/ferdi/commits?author=xthursdayx" title="Documentation">📖</a> <a href="#infra-xthursdayx" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#platform-xthursdayx" title="Packaging/porting to new platform">📦</a></td> 219 <td align="center"><a href="https://github.com/xthursdayx"><img src="https://avatars0.githubusercontent.com/u/18044308?v=4" width="40px;" alt="xthursdayx"/><br /><sub><b>xthursdayx</b></sub></a><br /><a href="https://github.com/getferdi/ferdi/commits?author=xthursdayx" title="Code">💻</a> <a href="https://github.com/getferdi/ferdi/commits?author=xthursdayx" title="Documentation">📖</a> <a href="#infra-xthursdayx" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#platform-xthursdayx" title="Packaging/porting to new platform">📦</a></td>
220 <td align="center"><a href="https://github.com/Gaboris"><img src="https://avatars2.githubusercontent.com/u/9462372?v=4" width="40px;" alt="Gaboris"/><br /><sub><b>Gaboris</b></sub></a><br /><a href="#question-Gaboris" title="Answering Questions">💬</a> <a href="https://github.com/getferdi/ferdi/issues?q=author%3AGaboris" title="Bug reports">🐛</a></td>
221 <td align="center"><a href="http://www.cu3ed.com/"><img src="https://avatars1.githubusercontent.com/u/61343?v=4" width="40px;" alt="Ce"/><br /><sub><b>Ce</b></sub></a><br /><a href="https://github.com/getferdi/ferdi/issues?q=author%3Aincace" title="Bug reports">🐛</a></td>
222 <td align="center"><a href="http://pztrn.name/"><img src="https://avatars1.githubusercontent.com/u/869402?v=4" width="40px;" alt="Stanislav N."/><br /><sub><b>Stanislav N.</b></sub></a><br /><a href="https://github.com/getferdi/ferdi/issues?q=author%3Apztrn" title="Bug reports">🐛</a></td>
223 <td align="center"><a href="http://www.patrickcurl.com"><img src="https://avatars1.githubusercontent.com/u/1470061?v=4" width="40px;" alt="Patrick Curl"/><br /><sub><b>Patrick Curl</b></sub></a><br /><a href="#ideas-patrickcurl" title="Ideas, Planning, & Feedback">🤔</a></td>
224 </tr>
225 <tr>
226 <td align="center"><a href="https://github.com/Stanzilla"><img src="https://avatars3.githubusercontent.com/u/75278?v=4" width="40px;" alt="Benjamin Staneck"/><br /><sub><b>Benjamin Staneck</b></sub></a><br /><a href="#design-Stanzilla" title="Design">🎨</a></td>
227 <td align="center"><a href="https://github.com/ammarmalhas"><img src="https://avatars1.githubusercontent.com/u/57057209?v=4" width="40px;" alt="ammarmalhas"/><br /><sub><b>ammarmalhas</b></sub></a><br /><a href="https://github.com/getferdi/ferdi/issues?q=author%3Aammarmalhas" title="Bug reports">🐛</a> <a href="#security-ammarmalhas" title="Security">🛡️</a></td>
228 <td align="center"><a href="https://github.com/steliyan"><img src="https://avatars1.githubusercontent.com/u/1850292?v=4" width="40px;" alt="Steliyan Stoyanov"/><br /><sub><b>Steliyan Stoyanov</b></sub></a><br /><a href="https://github.com/getferdi/ferdi/commits?author=steliyan" title="Code">💻</a> <a href="#ideas-steliyan" title="Ideas, Planning, & Feedback">🤔</a></td>
170 </tr> 229 </tr>
171</table> 230</table>
172 231
173<!-- markdownlint-enable -->
174<!-- prettier-ignore-end -->
175
176<!-- ALL-CONTRIBUTORS-LIST:END --> 232<!-- ALL-CONTRIBUTORS-LIST:END -->
177 233
178<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --> 234<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
@@ -187,4 +243,8 @@ This project follows the [all-contributors](https://github.com/all-contributors/
187 243
188## Backers via OpenCollective 244## Backers via OpenCollective
189 245
190<a href="https://opencollective.com/getferdi#backers" target="_blank"><img src="https://opencollective.com/getferdi/backers.svg?width=890"></a> 246<a href="https://opencollective.com/getferdi#section-contribute" target="_blank"><img src="https://opencollective.com/getferdi/backers.svg?width=890"></a>
247
248## Sponsors via OpenCollective
249
250<a href="https://opencollective.com/getferdi#section-contribute" target="_blank"><img src="https://opencollective.com/getferdi/sponsors.svg?width=890"></a>
diff --git a/appveyor.yml b/appveyor.yml
index 1034565ed..5d2e0c6bd 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -4,6 +4,10 @@ environment:
4version: 5.0.1.{build} 4version: 5.0.1.{build}
5 5
6install: 6install:
7 - ps: $fileContent = "-----BEGIN RSA PRIVATE KEY-----`n"
8 - ps: $fileContent += $env:priv_key.Replace(' ', "`n")
9 - ps: $fileContent += "`n-----END RSA PRIVATE KEY-----`n"
10 - ps: Set-Content $env:userprofile\.ssh\id_rsa $fileContent
7 - git submodule update --init --recursive 11 - git submodule update --init --recursive
8 - ps: Install-Product node 10 12 - ps: Install-Product node 10
9 - npx lerna bootstrap 13 - npx lerna bootstrap
diff --git a/branding/screenshots/hero.png b/branding/screenshots/hero.png
index f21e2abb6..09f509ca7 100644
--- a/branding/screenshots/hero.png
+++ b/branding/screenshots/hero.png
Binary files differ
diff --git a/build-helpers/images/win-app-ico.ico b/build-helpers/images/win-app-ico.ico
index 658826324..3731f6425 100644
--- a/build-helpers/images/win-app-ico.ico
+++ b/build-helpers/images/win-app-ico.ico
Binary files differ
diff --git a/next_release.md b/next_release.md
new file mode 100644
index 000000000..0e4bc411b
--- /dev/null
+++ b/next_release.md
@@ -0,0 +1,44 @@
1# Next release
2Infos about the next release:
3
4## Beta
5v5.4.0-beta.5:
6- Updated translations
7- Remove "&" sign from window menu bar (#65)
8- Extend debug information
9- Use SSH for submodules
10- Move hibernation indicator to bottom left (#129 (comment))
11- Add fix for 1.1.1.1 hack (#146)
12- Fix darkmode not loading correctly (#158)
13
14## Minor
15v5.4.0
16
17### Features
18- **Merge Franz 5.4.0**
19- **Use Ferdi without an Account**: Simply choose "Use Ferdi without an Account" on the login screen
20- **Accent color**: Change Ferdi's accent color
21- **Darkmode**: Easily open and edit any service's `darkmode.css` through the new "Open darkmode.css" button
22- **Hibernation**: Activate service hibernation to save battery
23- **Smaller file size**: Ferdi is now 17% smaller
24- **Annoucements**: Always get notified about the latest features of Ferdi
25- **Navigation bar**: Add option to always show a service navigation bar
26
27### Minor changes
28- Sorting applications in QuickSwitch by last used
29- Add info about teams only being available on Franz servers
30- Add toggle to disable dark mode on per-service basis
31- Add toggle to disable universal Dark Mode
32- Improve switching between accounts
33- Extend debug information
34- Add fix for 1.1.1.1 hack (#146)
35
36### Bug fixes
37- Fix universal darkmode for WhatsApp and Threema QR Codes
38- Fix darkmode not activating on reload
39- Fix disabling/enabling service not correctly reloading webview (#116)
40- Remove "&" sign from window menu bar (#65)
41
42### Changes in building Ferdi
43- Update Building Node Version
44- Use SSH for submodules \ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 2cbbe8939..a5b797e14 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
1{ 1{
2 "name": "ferdi", 2 "name": "ferdi",
3 "version": "5.4.0-beta.2", 3 "version": "5.4.0-beta.5",
4 "lockfileVersion": 1, 4 "lockfileVersion": 1,
5 "requires": true, 5 "requires": true,
6 "dependencies": { 6 "dependencies": {
diff --git a/package.json b/package.json
index b26986270..6bafa0f2b 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
2 "name": "ferdi", 2 "name": "ferdi",
3 "productName": "Ferdi", 3 "productName": "Ferdi",
4 "appId": "com.kytwb.ferdi", 4 "appId": "com.kytwb.ferdi",
5 "version": "5.4.0-beta.3", 5 "version": "5.4.0-beta.5",
6 "description": "Messaging app for WhatsApp, Slack, Telegram, HipChat, Hangouts and many many more.", 6 "description": "Messaging app for WhatsApp, Slack, Telegram, HipChat, Hangouts and many many more.",
7 "copyright": "kytwb", 7 "copyright": "kytwb",
8 "main": "index.js", 8 "main": "index.js",
diff --git a/recipes b/recipes
Subproject 7aa76feba8bd94368d27bee556480313c636f94 Subproject f32213ebafaa63bc87202317580abb80d6e0586
diff --git a/src/api/apiBase.js b/src/api/apiBase.js
index 561b025f0..85dd0f3df 100644
--- a/src/api/apiBase.js
+++ b/src/api/apiBase.js
@@ -6,25 +6,19 @@ import {
6} from '../environment'; 6} from '../environment';
7import { 7import {
8 LOCAL_SERVER, 8 LOCAL_SERVER,
9 SERVER_NOT_LOADED,
9} from '../config'; 10} from '../config';
10 11
11const apiBase = () => { 12const apiBase = (withVersion = true) => {
12 let url; 13 let url;
13 14
14 if (!window.ferdi 15 if (!window.ferdi
15 || !window.ferdi.stores.settings 16 || !window.ferdi.stores.settings
16 || !window.ferdi.stores.settings.all 17 || !window.ferdi.stores.settings.all
17 || !window.ferdi.stores.settings.all.app.server) { 18 || !window.ferdi.stores.settings.all.app.server) {
18 // Stores have not yet been loaded - send invalid URL to force a retry when stores are loaded 19 // Stores have not yet been loaded - return SERVER_NOT_LOADED to force a retry when stores are loaded
19 // "Why 1.1.1.1 as the default, invalid URL?" 20 return SERVER_NOT_LOADED;
20 // 1.1.1.1 is the server for Cloudflare's DNS service and will be the same across most networks. 21 } if (window.ferdi.stores.settings.all.app.server === LOCAL_SERVER) {
21 // Using a random IP could result in unwanted connections, using localhost could unwantedly
22 // connect to local develoment servers.
23 // 1.1.1.1 also sends a status 400 response for invalid routes. Other servers may return status 401
24 // on some routes. This would result in Ferdi deleting its current authToken as it thinks it
25 // has gone invalid.
26 url = 'https://1.1.1.1';
27 } else if (window.ferdi.stores.settings.all.app.server === LOCAL_SERVER) {
28 // Use URL for local server 22 // Use URL for local server
29 url = `http://127.0.0.1:${window.ferdi.stores.requests.localServerPort}`; 23 url = `http://127.0.0.1:${window.ferdi.stores.requests.localServerPort}`;
30 } else { 24 } else {
@@ -32,7 +26,10 @@ const apiBase = () => {
32 url = window.ferdi.stores.settings.all.app.server; 26 url = window.ferdi.stores.settings.all.app.server;
33 } 27 }
34 28
35 return `${url}/${API_VERSION}`; 29 if (withVersion) {
30 return `${url}/${API_VERSION}`;
31 }
32 return url;
36}; 33};
37 34
38export default apiBase; 35export default apiBase;
diff --git a/src/api/server/ServerApi.js b/src/api/server/ServerApi.js
index a5d636b4e..164bc237b 100644
--- a/src/api/server/ServerApi.js
+++ b/src/api/server/ServerApi.js
@@ -14,8 +14,7 @@ import OrderModel from '../../models/Order';
14 14
15import { sleep } from '../../helpers/async-helpers'; 15import { sleep } from '../../helpers/async-helpers';
16 16
17import { API } from '../../environment'; 17import { RECIPES_PATH, SERVER_NOT_LOADED } from '../../config';
18import { RECIPES_PATH } from '../../config';
19import apiBase from '../apiBase'; 18import apiBase from '../apiBase';
20import { prepareAuthRequest, sendAuthRequest } from '../utils/auth'; 19import { prepareAuthRequest, sendAuthRequest } from '../utils/auth';
21 20
@@ -39,8 +38,6 @@ module.paths.unshift(
39const { app } = remote; 38const { app } = remote;
40const { default: fetch } = remote.require('electron-fetch'); 39const { default: fetch } = remote.require('electron-fetch');
41 40
42const SERVER_URL = API;
43
44export default class ServerApi { 41export default class ServerApi {
45 recipePreviews = []; 42 recipePreviews = [];
46 43
@@ -121,6 +118,10 @@ export default class ServerApi {
121 } 118 }
122 119
123 async userInfo() { 120 async userInfo() {
121 if (apiBase() === SERVER_NOT_LOADED) {
122 throw new Error('Server not loaded');
123 }
124
124 const request = await sendAuthRequest(`${apiBase()}/me`); 125 const request = await sendAuthRequest(`${apiBase()}/me`);
125 if (!request.ok) { 126 if (!request.ok) {
126 throw request; 127 throw request;
@@ -163,6 +164,10 @@ export default class ServerApi {
163 164
164 // Services 165 // Services
165 async getServices() { 166 async getServices() {
167 if (apiBase() === SERVER_NOT_LOADED) {
168 throw new Error('Server not loaded');
169 }
170
166 const request = await sendAuthRequest(`${apiBase()}/me/services`); 171 const request = await sendAuthRequest(`${apiBase()}/me/services`);
167 if (!request.ok) { 172 if (!request.ok) {
168 throw request; 173 throw request;
@@ -287,6 +292,10 @@ export default class ServerApi {
287 } 292 }
288 293
289 async getFeatures() { 294 async getFeatures() {
295 if (apiBase() === SERVER_NOT_LOADED) {
296 throw new Error('Server not loaded');
297 }
298
290 const request = await sendAuthRequest(`${apiBase()}/features`); 299 const request = await sendAuthRequest(`${apiBase()}/features`);
291 if (!request.ok) { 300 if (!request.ok) {
292 throw request; 301 throw request;
@@ -466,7 +475,11 @@ export default class ServerApi {
466 475
467 // Health Check 476 // Health Check
468 async healthCheck() { 477 async healthCheck() {
469 const request = await sendAuthRequest(`${SERVER_URL}/health`, { 478 if (apiBase() === SERVER_NOT_LOADED) {
479 throw new Error('Server not loaded');
480 }
481
482 const request = await sendAuthRequest(`${apiBase(false)}/health`, {
470 method: 'GET', 483 method: 'GET',
471 }, false); 484 }, false);
472 if (!request.ok) { 485 if (!request.ok) {
diff --git a/src/assets/themeInfo.json b/src/assets/themeInfo.json
index d6017de23..eaea65ca7 100644
--- a/src/assets/themeInfo.json
+++ b/src/assets/themeInfo.json
@@ -1 +1 @@
{"color":".theme__dark .app .sidebar .sidebar__button.is-muted, .theme__dark .app .sidebar .sidebar__button.is-active, .sidebar .sidebar__button.is-muted, .sidebar .sidebar__button.is-active, .settings .account .invoices .invoices__action button, .settings-navigation .settings-navigation__link.is-active .badge, a.button, a.link, .auth .welcome .button:hover, .auth .welcome .button__inverted, .franz-form .franz-form__radio.is-selected, .theme__dark .franz-form__button.franz-form__button--inverted, .franz-form__button.franz-form__button--inverted","border-left-color":".tab-item.is-active","border-color":".theme__dark .settings .premium-info, a.button, .franz-form .franz-form__radio.is-selected","background":".settings .settings__header, .settings .settings__close, .settings .settings__close:hover, .settings-navigation .settings-navigation__link.is-active, a.button:hover, .info-bar, .info-bar.info-bar--primary, .infobox.infobox--primary, .theme__dark .badge.badge--primary, .theme__dark .badge.badge--premium, .badge.badge--primary, .badge.badge--premium, .content-tabs .content-tabs__tabs .content-tabs__item.is-active, #electron-app-title-bar .toolbar-dropdown:not(.open) > .toolbar-button > button:hover, #electron-app-title-bar .list-item.selected .menu-item, #electron-app-title-bar .list-item.selected:focus .menu-item, .theme__dark .quick-switch .active, .franz-form .franz-form__toggle-wrapper .franz-form__toggle.is-active .franz-form__toggle-button, .theme__dark .franz-form__button, .theme__dark .franz-form__button:hover, .theme__dark .franz-form__button.franz-form__button--inverted:hover, .franz-form__button, .franz-form__button:hover, .franz-form__button.franz-form__button--inverted:hover","border-right-color":".settings .settings__header .separator"} \ No newline at end of file {"color":".theme__dark .app .sidebar .sidebar__button.is-muted, .theme__dark .app .sidebar .sidebar__button.is-active, .sidebar .sidebar__button.is-muted, .sidebar .sidebar__button.is-active, .settings .account .invoices .invoices__action button, .settings-navigation .settings-navigation__link.is-active .badge, a.button, button.button, a.link, button.link, .auth .welcome .button:hover, .auth .welcome .button__inverted, .franz-form .franz-form__radio.is-selected, .theme__dark .franz-form__button.franz-form__button--inverted, .franz-form__button.franz-form__button--inverted","border-left-color":".tab-item.is-active","border-color":".theme__dark .settings .premium-info, a.button, button.button, .franz-form .franz-form__radio.is-selected","background":".settings .settings__header, .settings .settings__close, .settings .settings__close:hover, .settings-navigation .settings-navigation__link.is-active, a.button:hover, button.button:hover, .info-bar, .info-bar.info-bar--primary, .infobox.infobox--primary, .theme__dark .badge.badge--primary, .theme__dark .badge.badge--premium, .badge.badge--primary, .badge.badge--premium, .content-tabs .content-tabs__tabs .content-tabs__item.is-active, #electron-app-title-bar .toolbar-dropdown:not(.open) > .toolbar-button > button:hover, #electron-app-title-bar .list-item.selected .menu-item, #electron-app-title-bar .list-item.selected:focus .menu-item, .theme__dark .quick-switch .active, .franz-form .franz-form__toggle-wrapper .franz-form__toggle.is-active .franz-form__toggle-button, .theme__dark .franz-form__button, .theme__dark .franz-form__button:hover, .theme__dark .franz-form__button.franz-form__button--inverted:hover, .franz-form__button, .franz-form__button:hover, .franz-form__button.franz-form__button--inverted:hover","border-right-color":".settings .settings__header .separator"} \ No newline at end of file
diff --git a/src/components/services/content/ServiceView.js b/src/components/services/content/ServiceView.js
index 49ee24361..1fff5ef7a 100644
--- a/src/components/services/content/ServiceView.js
+++ b/src/components/services/content/ServiceView.js
@@ -42,10 +42,10 @@ export default @inject('stores', 'actions') @observer class ServiceView extends
42 forceRepaint: false, 42 forceRepaint: false,
43 targetUrl: '', 43 targetUrl: '',
44 statusBarVisible: false, 44 statusBarVisible: false,
45 hibernate: false,
46 hibernationTimer: null,
47 }; 45 };
48 46
47 hibernationTimer = null;
48
49 autorunDisposer = null; 49 autorunDisposer = null;
50 50
51 forceRepaintTimeout = null; 51 forceRepaintTimeout = null;
@@ -73,15 +73,12 @@ export default @inject('stores', 'actions') @observer class ServiceView extends
73 // Service is inactive - start hibernation countdown 73 // Service is inactive - start hibernation countdown
74 this.startHibernationTimer(); 74 this.startHibernationTimer();
75 } else { 75 } else {
76 if (this.state.hibernationTimer) { 76 if (this.hibernationTimer) {
77 // Service is active but we have an active hibernation timer: Clear timeout 77 // Service is active but we have an active hibernation timer: Clear timeout
78 clearTimeout(this.state.hibernationTimer); 78 clearTimeout(this.hibernationTimer);
79 } 79 }
80 80
81 // Service is active, wake up service from hibernation 81 // Service is active, wake up service from hibernation
82 this.setState({
83 hibernate: false,
84 });
85 this.props.actions.service.setHibernation({ 82 this.props.actions.service.setHibernation({
86 serviceId: this.props.service.id, 83 serviceId: this.props.service.id,
87 hibernating: false, 84 hibernating: false,
@@ -90,16 +87,6 @@ export default @inject('stores', 'actions') @observer class ServiceView extends
90 }, 87 },
91 ); 88 );
92 89
93 // Store hibernation status to state, otherwise the webview won't get unloaded correctly
94 reaction(
95 () => this.props.service.isHibernating,
96 () => {
97 this.setState({
98 hibernate: this.props.service.isHibernating,
99 });
100 },
101 );
102
103 // Start hibernation counter if we are in background 90 // Start hibernation counter if we are in background
104 if (!this.props.service.isActive && this.props.stores.settings.all.app.hibernate) { 91 if (!this.props.service.isActive && this.props.stores.settings.all.app.hibernate) {
105 this.startHibernationTimer(); 92 this.startHibernationTimer();
@@ -126,18 +113,13 @@ export default @inject('stores', 'actions') @observer class ServiceView extends
126 const timerDuration = (Number(this.props.stores.settings.all.app.hibernationStrategy) || 300) * 1000; 113 const timerDuration = (Number(this.props.stores.settings.all.app.hibernationStrategy) || 300) * 1000;
127 114
128 const hibernationTimer = setTimeout(() => { 115 const hibernationTimer = setTimeout(() => {
129 this.setState({
130 hibernate: true,
131 });
132 this.props.actions.service.setHibernation({ 116 this.props.actions.service.setHibernation({
133 serviceId: this.props.service.id, 117 serviceId: this.props.service.id,
134 hibernating: true, 118 hibernating: true,
135 }); 119 });
136 }, timerDuration); 120 }, timerDuration);
137 121
138 this.setState({ 122 this.hibernationTimer = hibernationTimer;
139 hibernationTimer,
140 });
141 } 123 }
142 124
143 render() { 125 render() {
@@ -208,7 +190,7 @@ export default @inject('stores', 'actions') @observer class ServiceView extends
208 </Fragment> 190 </Fragment>
209 ) : ( 191 ) : (
210 <> 192 <>
211 {!this.state.hibernate ? ( 193 {!service.isHibernating ? (
212 <> 194 <>
213 {(service.recipe.id === CUSTOM_WEBSITE_ID || showServiceNavigationBar) && ( 195 {(service.recipe.id === CUSTOM_WEBSITE_ID || showServiceNavigationBar) && (
214 <WebControlsScreen service={service} /> 196 <WebControlsScreen service={service} />
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js
index e6ebb6afb..652647470 100644
--- a/src/components/services/content/ServiceWebview.js
+++ b/src/components/services/content/ServiceWebview.js
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { observable, reaction } from 'mobx'; 4import { observable, reaction } from 'mobx';
5import ElectronWebView from 'react-electron-web-view'; 5import ElectronWebView from 'react-electron-web-view';
6import path from 'path';
6 7
7import ServiceModel from '../../../models/Service'; 8import ServiceModel from '../../../models/Service';
8 9
@@ -51,6 +52,8 @@ class ServiceWebview extends Component {
51 setWebviewReference, 52 setWebviewReference,
52 } = this.props; 53 } = this.props;
53 54
55 const preloadScript = path.join(__dirname, '../../../', 'webview', 'recipe.js');
56
54 return ( 57 return (
55 <ElectronWebView 58 <ElectronWebView
56 ref={(webview) => { 59 ref={(webview) => {
@@ -61,7 +64,7 @@ class ServiceWebview extends Component {
61 }} 64 }}
62 autosize 65 autosize
63 src={service.url} 66 src={service.url}
64 preload="./webview/recipe.js" 67 preload={preloadScript}
65 partition={`persist:service-${service.id}`} 68 partition={`persist:service-${service.id}`}
66 onDidAttach={() => { 69 onDidAttach={() => {
67 setWebviewReference({ 70 setWebviewReference({
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index 2be5c4ed7..d567a47d1 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -12,6 +12,7 @@ import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer';
12import Input from '../../ui/Input'; 12import Input from '../../ui/Input';
13 13
14import { FRANZ_TRANSLATION } from '../../../config'; 14import { FRANZ_TRANSLATION } from '../../../config';
15import { isMac } from '../../../environment';
15 16
16function escapeHtml(unsafe) { 17function escapeHtml(unsafe) {
17 return unsafe 18 return unsafe
@@ -383,8 +384,10 @@ export default @observer class EditSettingsForm extends Component {
383 <Toggle field={form.$('showDisabledServices')} /> 384 <Toggle field={form.$('showDisabledServices')} />
384 <Toggle field={form.$('showMessageBadgeWhenMuted')} /> 385 <Toggle field={form.$('showMessageBadgeWhenMuted')} />
385 <Toggle field={form.$('darkMode')} /> 386 <Toggle field={form.$('darkMode')} />
387 {isMac && <Toggle field={form.$('adaptableDarkMode')} disabled={isDarkmodeEnabled} />}
386 {isDarkmodeEnabled && ( 388 {isDarkmodeEnabled && (
387 <> 389 <>
390 <Toggle field={form.$('adaptableDarkMode')} />
388 <Toggle field={form.$('universalDarkMode')} /> 391 <Toggle field={form.$('universalDarkMode')} />
389 <p 392 <p
390 className="settings__message" 393 className="settings__message"
diff --git a/src/components/ui/FeatureList.js b/src/components/ui/FeatureList.js
index 7ba8b54d7..f1039709c 100644
--- a/src/components/ui/FeatureList.js
+++ b/src/components/ui/FeatureList.js
@@ -72,7 +72,7 @@ export class FeatureList extends Component {
72 static propTypes = { 72 static propTypes = {
73 className: PropTypes.string, 73 className: PropTypes.string,
74 featureClassName: PropTypes.string, 74 featureClassName: PropTypes.string,
75 plan: PropTypes.oneOf(PLANS), 75 plan: PropTypes.oneOf(Object.values(PLANS)),
76 }; 76 };
77 77
78 static defaultProps = { 78 static defaultProps = {
diff --git a/src/config.js b/src/config.js
index 761d26eea..bd67aee6b 100644
--- a/src/config.js
+++ b/src/config.js
@@ -112,6 +112,19 @@ export const FILE_SYSTEM_SETTINGS_TYPES = [
112]; 112];
113 113
114export const LOCAL_SERVER = 'You are using Ferdi without a server'; 114export const LOCAL_SERVER = 'You are using Ferdi without a server';
115export const SERVER_NOT_LOADED = 'Ferdi::SERVER_NOT_LOADED';
116
117// Set app directory before loading user modules
118if (process.env.FERDI_APPDATA_DIR != null) {
119 app.setPath('appData', process.env.FERDI_APPDATA_DIR);
120 app.setPath('userData', path.join(app.getPath('appData')));
121} else if (process.env.PORTABLE_EXECUTABLE_DIR != null) {
122 app.setPath('appData', process.env.PORTABLE_EXECUTABLE_DIR, `${app.getName()}AppData`);
123 app.setPath('userData', path.join(app.getPath('appData'), `${app.getName()}AppData`));
124} else if (process.platform === 'win32') {
125 app.setPath('appData', process.env.APPDATA);
126 app.setPath('userData', path.join(app.getPath('appData'), app.getName()));
127}
115 128
116export const SETTINGS_PATH = path.join(app.getPath('userData'), 'config'); 129export const SETTINGS_PATH = path.join(app.getPath('userData'), 'config');
117 130
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js
index ddee82e45..07efbb881 100644
--- a/src/containers/settings/EditSettingsScreen.js
+++ b/src/containers/settings/EditSettingsScreen.js
@@ -98,6 +98,10 @@ const messages = defineMessages({
98 id: 'settings.app.form.darkMode', 98 id: 'settings.app.form.darkMode',
99 defaultMessage: '!!!Dark Mode', 99 defaultMessage: '!!!Dark Mode',
100 }, 100 },
101 adaptableDarkMode: {
102 id: 'settings.app.form.adaptableDarkMode',
103 defaultMessage: '!!!Enable adaptable Dark Mode',
104 },
101 universalDarkMode: { 105 universalDarkMode: {
102 id: 'settings.app.form.universalDarkMode', 106 id: 'settings.app.form.universalDarkMode',
103 defaultMessage: '!!!Enable universal Dark Mode', 107 defaultMessage: '!!!Enable universal Dark Mode',
@@ -180,6 +184,7 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
180 enableGPUAcceleration: settingsData.enableGPUAcceleration, 184 enableGPUAcceleration: settingsData.enableGPUAcceleration,
181 showDisabledServices: settingsData.showDisabledServices, 185 showDisabledServices: settingsData.showDisabledServices,
182 darkMode: settingsData.darkMode, 186 darkMode: settingsData.darkMode,
187 adaptableDarkMode: settingsData.adaptableDarkMode,
183 universalDarkMode: settingsData.universalDarkMode, 188 universalDarkMode: settingsData.universalDarkMode,
184 accentColor: settingsData.accentColor, 189 accentColor: settingsData.accentColor,
185 showMessageBadgeWhenMuted: settingsData.showMessageBadgeWhenMuted, 190 showMessageBadgeWhenMuted: settingsData.showMessageBadgeWhenMuted,
@@ -350,6 +355,11 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
350 value: settings.all.app.darkMode, 355 value: settings.all.app.darkMode,
351 default: DEFAULT_APP_SETTINGS.darkMode, 356 default: DEFAULT_APP_SETTINGS.darkMode,
352 }, 357 },
358 adaptableDarkMode: {
359 label: intl.formatMessage(messages.adaptableDarkMode),
360 value: settings.all.app.adaptableDarkMode,
361 default: DEFAULT_APP_SETTINGS.adaptableDarkMode,
362 },
353 universalDarkMode: { 363 universalDarkMode: {
354 label: intl.formatMessage(messages.universalDarkMode), 364 label: intl.formatMessage(messages.universalDarkMode),
355 value: settings.all.app.universalDarkMode, 365 value: settings.all.app.universalDarkMode,
diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json
index bb65ccdf2..10092cd9e 100644
--- a/src/i18n/locales/defaultMessages.json
+++ b/src/i18n/locales/defaultMessages.json
@@ -2608,377 +2608,377 @@
2608 "defaultMessage": "!!!Settings", 2608 "defaultMessage": "!!!Settings",
2609 "end": { 2609 "end": {
2610 "column": 3, 2610 "column": 3,
2611 "line": 29 2611 "line": 30
2612 }, 2612 },
2613 "file": "src/components/settings/settings/EditSettingsForm.js", 2613 "file": "src/components/settings/settings/EditSettingsForm.js",
2614 "id": "settings.app.headline", 2614 "id": "settings.app.headline",
2615 "start": { 2615 "start": {
2616 "column": 12, 2616 "column": 12,
2617 "line": 26 2617 "line": 27
2618 } 2618 }
2619 }, 2619 },
2620 { 2620 {
2621 "defaultMessage": "!!!General", 2621 "defaultMessage": "!!!General",
2622 "end": { 2622 "end": {
2623 "column": 3, 2623 "column": 3,
2624 "line": 33 2624 "line": 34
2625 }, 2625 },
2626 "file": "src/components/settings/settings/EditSettingsForm.js", 2626 "file": "src/components/settings/settings/EditSettingsForm.js",
2627 "id": "settings.app.headlineGeneral", 2627 "id": "settings.app.headlineGeneral",
2628 "start": { 2628 "start": {
2629 "column": 19, 2629 "column": 19,
2630 "line": 30 2630 "line": 31
2631 } 2631 }
2632 }, 2632 },
2633 { 2633 {
2634 "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.", 2634 "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.",
2635 "end": { 2635 "end": {
2636 "column": 3, 2636 "column": 3,
2637 "line": 37 2637 "line": 38
2638 }, 2638 },
2639 "file": "src/components/settings/settings/EditSettingsForm.js", 2639 "file": "src/components/settings/settings/EditSettingsForm.js",
2640 "id": "settings.app.hibernateInfo", 2640 "id": "settings.app.hibernateInfo",
2641 "start": { 2641 "start": {
2642 "column": 17, 2642 "column": 17,
2643 "line": 34 2643 "line": 35
2644 } 2644 }
2645 }, 2645 },
2646 { 2646 {
2647 "defaultMessage": "!!!We advice you to logout after changing your server as your settings might not be saved otherwise.", 2647 "defaultMessage": "!!!We advice you to logout after changing your server as your settings might not be saved otherwise.",
2648 "end": { 2648 "end": {
2649 "column": 3, 2649 "column": 3,
2650 "line": 41 2650 "line": 42
2651 }, 2651 },
2652 "file": "src/components/settings/settings/EditSettingsForm.js", 2652 "file": "src/components/settings/settings/EditSettingsForm.js",
2653 "id": "settings.app.serverInfo", 2653 "id": "settings.app.serverInfo",
2654 "start": { 2654 "start": {
2655 "column": 14, 2655 "column": 14,
2656 "line": 38 2656 "line": 39
2657 } 2657 }
2658 }, 2658 },
2659 { 2659 {
2660 "defaultMessage": "!!!You are using the official Franz Server for Ferdi.\nWe know that Ferdi allows you to use all its features for free but you are still using Franz's server resources - which Franz's creator has to pay for.\nPlease still consider [Link 1]paying for a Franz account[/Link] or [Link 2]using a self-hosted ferdi-server[/Link] (if you have the knowledge and resources to do so). \nBy using Ferdi, you still profit greatly from Franz's recipe store, server resources and its development.", 2660 "defaultMessage": "!!!You are using the official Franz Server for Ferdi.\nWe know that Ferdi allows you to use all its features for free but you are still using Franz's server resources - which Franz's creator has to pay for.\nPlease still consider [Link 1]paying for a Franz account[/Link] or [Link 2]using a self-hosted ferdi-server[/Link] (if you have the knowledge and resources to do so). \nBy using Ferdi, you still profit greatly from Franz's recipe store, server resources and its development.",
2661 "end": { 2661 "end": {
2662 "column": 3, 2662 "column": 3,
2663 "line": 45 2663 "line": 46
2664 }, 2664 },
2665 "file": "src/components/settings/settings/EditSettingsForm.js", 2665 "file": "src/components/settings/settings/EditSettingsForm.js",
2666 "id": "settings.app.serverMoneyInfo", 2666 "id": "settings.app.serverMoneyInfo",
2667 "start": { 2667 "start": {
2668 "column": 19, 2668 "column": 19,
2669 "line": 42 2669 "line": 43
2670 } 2670 }
2671 }, 2671 },
2672 { 2672 {
2673 "defaultMessage": "!!!This server will be used for the \"Franz Todo\" feature. (default: https://app.franztodos.com)", 2673 "defaultMessage": "!!!This server will be used for the \"Franz Todo\" feature. (default: https://app.franztodos.com)",
2674 "end": { 2674 "end": {
2675 "column": 3, 2675 "column": 3,
2676 "line": 49 2676 "line": 50
2677 }, 2677 },
2678 "file": "src/components/settings/settings/EditSettingsForm.js", 2678 "file": "src/components/settings/settings/EditSettingsForm.js",
2679 "id": "settings.app.todoServerInfo", 2679 "id": "settings.app.todoServerInfo",
2680 "start": { 2680 "start": {
2681 "column": 18, 2681 "column": 18,
2682 "line": 46 2682 "line": 47
2683 } 2683 }
2684 }, 2684 },
2685 { 2685 {
2686 "defaultMessage": "!!!Ferdi Lock Password", 2686 "defaultMessage": "!!!Ferdi Lock Password",
2687 "end": { 2687 "end": {
2688 "column": 3, 2688 "column": 3,
2689 "line": 53 2689 "line": 54
2690 }, 2690 },
2691 "file": "src/components/settings/settings/EditSettingsForm.js", 2691 "file": "src/components/settings/settings/EditSettingsForm.js",
2692 "id": "settings.app.lockedPassword", 2692 "id": "settings.app.lockedPassword",
2693 "start": { 2693 "start": {
2694 "column": 18, 2694 "column": 18,
2695 "line": 50 2695 "line": 51
2696 } 2696 }
2697 }, 2697 },
2698 { 2698 {
2699 "defaultMessage": "!!!Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdi.", 2699 "defaultMessage": "!!!Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdi.",
2700 "end": { 2700 "end": {
2701 "column": 3, 2701 "column": 3,
2702 "line": 57 2702 "line": 58
2703 }, 2703 },
2704 "file": "src/components/settings/settings/EditSettingsForm.js", 2704 "file": "src/components/settings/settings/EditSettingsForm.js",
2705 "id": "settings.app.lockedPasswordInfo", 2705 "id": "settings.app.lockedPasswordInfo",
2706 "start": { 2706 "start": {
2707 "column": 22, 2707 "column": 22,
2708 "line": 54 2708 "line": 55
2709 } 2709 }
2710 }, 2710 },
2711 { 2711 {
2712 "defaultMessage": "!!!Ferdi password lock allows you to keep your messages protected.\nUsing Ferdi 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 CMD/CTRL+Shift+L.", 2712 "defaultMessage": "!!!Ferdi password lock allows you to keep your messages protected.\nUsing Ferdi 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 CMD/CTRL+Shift+L.",
2713 "end": { 2713 "end": {
2714 "column": 3, 2714 "column": 3,
2715 "line": 61 2715 "line": 62
2716 }, 2716 },
2717 "file": "src/components/settings/settings/EditSettingsForm.js", 2717 "file": "src/components/settings/settings/EditSettingsForm.js",
2718 "id": "settings.app.lockInfo", 2718 "id": "settings.app.lockInfo",
2719 "start": { 2719 "start": {
2720 "column": 12, 2720 "column": 12,
2721 "line": 58 2721 "line": 59
2722 } 2722 }
2723 }, 2723 },
2724 { 2724 {
2725 "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.", 2725 "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.",
2726 "end": { 2726 "end": {
2727 "column": 3, 2727 "column": 3,
2728 "line": 65 2728 "line": 66
2729 }, 2729 },
2730 "file": "src/components/settings/settings/EditSettingsForm.js", 2730 "file": "src/components/settings/settings/EditSettingsForm.js",
2731 "id": "settings.app.scheduledDNDTimeInfo", 2731 "id": "settings.app.scheduledDNDTimeInfo",
2732 "start": { 2732 "start": {
2733 "column": 24, 2733 "column": 24,
2734 "line": 62 2734 "line": 63
2735 } 2735 }
2736 }, 2736 },
2737 { 2737 {
2738 "defaultMessage": "!!!Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.", 2738 "defaultMessage": "!!!Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.",
2739 "end": { 2739 "end": {
2740 "column": 3, 2740 "column": 3,
2741 "line": 69 2741 "line": 70
2742 }, 2742 },
2743 "file": "src/components/settings/settings/EditSettingsForm.js", 2743 "file": "src/components/settings/settings/EditSettingsForm.js",
2744 "id": "settings.app.scheduledDNDInfo", 2744 "id": "settings.app.scheduledDNDInfo",
2745 "start": { 2745 "start": {
2746 "column": 20, 2746 "column": 20,
2747 "line": 66 2747 "line": 67
2748 } 2748 }
2749 }, 2749 },
2750 { 2750 {
2751 "defaultMessage": "!!!Language", 2751 "defaultMessage": "!!!Language",
2752 "end": { 2752 "end": {
2753 "column": 3, 2753 "column": 3,
2754 "line": 73 2754 "line": 74
2755 }, 2755 },
2756 "file": "src/components/settings/settings/EditSettingsForm.js", 2756 "file": "src/components/settings/settings/EditSettingsForm.js",
2757 "id": "settings.app.headlineLanguage", 2757 "id": "settings.app.headlineLanguage",
2758 "start": { 2758 "start": {
2759 "column": 20, 2759 "column": 20,
2760 "line": 70 2760 "line": 71
2761 } 2761 }
2762 }, 2762 },
2763 { 2763 {
2764 "defaultMessage": "!!!Updates", 2764 "defaultMessage": "!!!Updates",
2765 "end": { 2765 "end": {
2766 "column": 3, 2766 "column": 3,
2767 "line": 77 2767 "line": 78
2768 }, 2768 },
2769 "file": "src/components/settings/settings/EditSettingsForm.js", 2769 "file": "src/components/settings/settings/EditSettingsForm.js",
2770 "id": "settings.app.headlineUpdates", 2770 "id": "settings.app.headlineUpdates",
2771 "start": { 2771 "start": {
2772 "column": 19, 2772 "column": 19,
2773 "line": 74 2773 "line": 75
2774 } 2774 }
2775 }, 2775 },
2776 { 2776 {
2777 "defaultMessage": "!!!Appearance", 2777 "defaultMessage": "!!!Appearance",
2778 "end": { 2778 "end": {
2779 "column": 3, 2779 "column": 3,
2780 "line": 81 2780 "line": 82
2781 }, 2781 },
2782 "file": "src/components/settings/settings/EditSettingsForm.js", 2782 "file": "src/components/settings/settings/EditSettingsForm.js",
2783 "id": "settings.app.headlineAppearance", 2783 "id": "settings.app.headlineAppearance",
2784 "start": { 2784 "start": {
2785 "column": 22, 2785 "column": 22,
2786 "line": 78 2786 "line": 79
2787 } 2787 }
2788 }, 2788 },
2789 { 2789 {
2790 "defaultMessage": "!!!Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.", 2790 "defaultMessage": "!!!Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.",
2791 "end": { 2791 "end": {
2792 "column": 3, 2792 "column": 3,
2793 "line": 85 2793 "line": 86
2794 }, 2794 },
2795 "file": "src/components/settings/settings/EditSettingsForm.js", 2795 "file": "src/components/settings/settings/EditSettingsForm.js",
2796 "id": "settings.app.universalDarkModeInfo", 2796 "id": "settings.app.universalDarkModeInfo",
2797 "start": { 2797 "start": {
2798 "column": 25, 2798 "column": 25,
2799 "line": 82 2799 "line": 83
2800 } 2800 }
2801 }, 2801 },
2802 { 2802 {
2803 "defaultMessage": "!!!Write your accent color in a CSS-compatible format. (Default: #7367f0)", 2803 "defaultMessage": "!!!Write your accent color in a CSS-compatible format. (Default: #7367f0)",
2804 "end": { 2804 "end": {
2805 "column": 3, 2805 "column": 3,
2806 "line": 89 2806 "line": 90
2807 }, 2807 },
2808 "file": "src/components/settings/settings/EditSettingsForm.js", 2808 "file": "src/components/settings/settings/EditSettingsForm.js",
2809 "id": "settings.app.accentColorInfo", 2809 "id": "settings.app.accentColorInfo",
2810 "start": { 2810 "start": {
2811 "column": 19, 2811 "column": 19,
2812 "line": 86 2812 "line": 87
2813 } 2813 }
2814 }, 2814 },
2815 { 2815 {
2816 "defaultMessage": "!!!Advanced", 2816 "defaultMessage": "!!!Advanced",
2817 "end": { 2817 "end": {
2818 "column": 3, 2818 "column": 3,
2819 "line": 93 2819 "line": 94
2820 }, 2820 },
2821 "file": "src/components/settings/settings/EditSettingsForm.js", 2821 "file": "src/components/settings/settings/EditSettingsForm.js",
2822 "id": "settings.app.headlineAdvanced", 2822 "id": "settings.app.headlineAdvanced",
2823 "start": { 2823 "start": {
2824 "column": 20, 2824 "column": 20,
2825 "line": 90 2825 "line": 91
2826 } 2826 }
2827 }, 2827 },
2828 { 2828 {
2829 "defaultMessage": "!!!Help us to translate Ferdi into your language.", 2829 "defaultMessage": "!!!Help us to translate Ferdi into your language.",
2830 "end": { 2830 "end": {
2831 "column": 3, 2831 "column": 3,
2832 "line": 97 2832 "line": 98
2833 }, 2833 },
2834 "file": "src/components/settings/settings/EditSettingsForm.js", 2834 "file": "src/components/settings/settings/EditSettingsForm.js",
2835 "id": "settings.app.translationHelp", 2835 "id": "settings.app.translationHelp",
2836 "start": { 2836 "start": {
2837 "column": 19, 2837 "column": 19,
2838 "line": 94 2838 "line": 95
2839 } 2839 }
2840 }, 2840 },
2841 { 2841 {
2842 "defaultMessage": "!!!Cache", 2842 "defaultMessage": "!!!Cache",
2843 "end": { 2843 "end": {
2844 "column": 3, 2844 "column": 3,
2845 "line": 101 2845 "line": 102
2846 }, 2846 },
2847 "file": "src/components/settings/settings/EditSettingsForm.js", 2847 "file": "src/components/settings/settings/EditSettingsForm.js",
2848 "id": "settings.app.subheadlineCache", 2848 "id": "settings.app.subheadlineCache",
2849 "start": { 2849 "start": {
2850 "column": 20, 2850 "column": 20,
2851 "line": 98 2851 "line": 99
2852 } 2852 }
2853 }, 2853 },
2854 { 2854 {
2855 "defaultMessage": "!!!Ferdi cache is currently using {size} of disk space.", 2855 "defaultMessage": "!!!Ferdi cache is currently using {size} of disk space.",
2856 "end": { 2856 "end": {
2857 "column": 3, 2857 "column": 3,
2858 "line": 105 2858 "line": 106
2859 }, 2859 },
2860 "file": "src/components/settings/settings/EditSettingsForm.js", 2860 "file": "src/components/settings/settings/EditSettingsForm.js",
2861 "id": "settings.app.cacheInfo", 2861 "id": "settings.app.cacheInfo",
2862 "start": { 2862 "start": {
2863 "column": 13, 2863 "column": 13,
2864 "line": 102 2864 "line": 103
2865 } 2865 }
2866 }, 2866 },
2867 { 2867 {
2868 "defaultMessage": "!!!Clear cache", 2868 "defaultMessage": "!!!Clear cache",
2869 "end": { 2869 "end": {
2870 "column": 3, 2870 "column": 3,
2871 "line": 109 2871 "line": 110
2872 }, 2872 },
2873 "file": "src/components/settings/settings/EditSettingsForm.js", 2873 "file": "src/components/settings/settings/EditSettingsForm.js",
2874 "id": "settings.app.buttonClearAllCache", 2874 "id": "settings.app.buttonClearAllCache",
2875 "start": { 2875 "start": {
2876 "column": 23, 2876 "column": 23,
2877 "line": 106 2877 "line": 107
2878 } 2878 }
2879 }, 2879 },
2880 { 2880 {
2881 "defaultMessage": "!!!Check for updates", 2881 "defaultMessage": "!!!Check for updates",
2882 "end": { 2882 "end": {
2883 "column": 3, 2883 "column": 3,
2884 "line": 113 2884 "line": 114
2885 }, 2885 },
2886 "file": "src/components/settings/settings/EditSettingsForm.js", 2886 "file": "src/components/settings/settings/EditSettingsForm.js",
2887 "id": "settings.app.buttonSearchForUpdate", 2887 "id": "settings.app.buttonSearchForUpdate",
2888 "start": { 2888 "start": {
2889 "column": 25, 2889 "column": 25,
2890 "line": 110 2890 "line": 111
2891 } 2891 }
2892 }, 2892 },
2893 { 2893 {
2894 "defaultMessage": "!!!Restart & install update", 2894 "defaultMessage": "!!!Restart & install update",
2895 "end": { 2895 "end": {
2896 "column": 3, 2896 "column": 3,
2897 "line": 117 2897 "line": 118
2898 }, 2898 },
2899 "file": "src/components/settings/settings/EditSettingsForm.js", 2899 "file": "src/components/settings/settings/EditSettingsForm.js",
2900 "id": "settings.app.buttonInstallUpdate", 2900 "id": "settings.app.buttonInstallUpdate",
2901 "start": { 2901 "start": {
2902 "column": 23, 2902 "column": 23,
2903 "line": 114 2903 "line": 115
2904 } 2904 }
2905 }, 2905 },
2906 { 2906 {
2907 "defaultMessage": "!!!Is searching for update", 2907 "defaultMessage": "!!!Is searching for update",
2908 "end": { 2908 "end": {
2909 "column": 3, 2909 "column": 3,
2910 "line": 121 2910 "line": 122
2911 }, 2911 },
2912 "file": "src/components/settings/settings/EditSettingsForm.js", 2912 "file": "src/components/settings/settings/EditSettingsForm.js",
2913 "id": "settings.app.updateStatusSearching", 2913 "id": "settings.app.updateStatusSearching",
2914 "start": { 2914 "start": {
2915 "column": 25, 2915 "column": 25,
2916 "line": 118 2916 "line": 119
2917 } 2917 }
2918 }, 2918 },
2919 { 2919 {
2920 "defaultMessage": "!!!Update available, downloading...", 2920 "defaultMessage": "!!!Update available, downloading...",
2921 "end": { 2921 "end": {
2922 "column": 3, 2922 "column": 3,
2923 "line": 125 2923 "line": 126
2924 }, 2924 },
2925 "file": "src/components/settings/settings/EditSettingsForm.js", 2925 "file": "src/components/settings/settings/EditSettingsForm.js",
2926 "id": "settings.app.updateStatusAvailable", 2926 "id": "settings.app.updateStatusAvailable",
2927 "start": { 2927 "start": {
2928 "column": 25, 2928 "column": 25,
2929 "line": 122 2929 "line": 123
2930 } 2930 }
2931 }, 2931 },
2932 { 2932 {
2933 "defaultMessage": "!!!You are using the latest version of Ferdi", 2933 "defaultMessage": "!!!You are using the latest version of Ferdi",
2934 "end": { 2934 "end": {
2935 "column": 3, 2935 "column": 3,
2936 "line": 129 2936 "line": 130
2937 }, 2937 },
2938 "file": "src/components/settings/settings/EditSettingsForm.js", 2938 "file": "src/components/settings/settings/EditSettingsForm.js",
2939 "id": "settings.app.updateStatusUpToDate", 2939 "id": "settings.app.updateStatusUpToDate",
2940 "start": { 2940 "start": {
2941 "column": 24, 2941 "column": 24,
2942 "line": 126 2942 "line": 127
2943 } 2943 }
2944 }, 2944 },
2945 { 2945 {
2946 "defaultMessage": "!!!Current version:", 2946 "defaultMessage": "!!!Current version:",
2947 "end": { 2947 "end": {
2948 "column": 3, 2948 "column": 3,
2949 "line": 133 2949 "line": 134
2950 }, 2950 },
2951 "file": "src/components/settings/settings/EditSettingsForm.js", 2951 "file": "src/components/settings/settings/EditSettingsForm.js",
2952 "id": "settings.app.currentVersion", 2952 "id": "settings.app.currentVersion",
2953 "start": { 2953 "start": {
2954 "column": 18, 2954 "column": 18,
2955 "line": 130 2955 "line": 131
2956 } 2956 }
2957 }, 2957 },
2958 { 2958 {
2959 "defaultMessage": "!!!Changes require restart", 2959 "defaultMessage": "!!!Changes require restart",
2960 "end": { 2960 "end": {
2961 "column": 3, 2961 "column": 3,
2962 "line": 137 2962 "line": 138
2963 }, 2963 },
2964 "file": "src/components/settings/settings/EditSettingsForm.js", 2964 "file": "src/components/settings/settings/EditSettingsForm.js",
2965 "id": "settings.app.restartRequired", 2965 "id": "settings.app.restartRequired",
2966 "start": { 2966 "start": {
2967 "column": 29, 2967 "column": 29,
2968 "line": 134 2968 "line": 135
2969 } 2969 }
2970 }, 2970 },
2971 { 2971 {
2972 "defaultMessage": "!!!Official translations are English & German. All other languages are community based translations.", 2972 "defaultMessage": "!!!Official translations are English & German. All other languages are community based translations.",
2973 "end": { 2973 "end": {
2974 "column": 3, 2974 "column": 3,
2975 "line": 141 2975 "line": 142
2976 }, 2976 },
2977 "file": "src/components/settings/settings/EditSettingsForm.js", 2977 "file": "src/components/settings/settings/EditSettingsForm.js",
2978 "id": "settings.app.languageDisclaimer", 2978 "id": "settings.app.languageDisclaimer",
2979 "start": { 2979 "start": {
2980 "column": 22, 2980 "column": 22,
2981 "line": 138 2981 "line": 139
2982 } 2982 }
2983 } 2983 }
2984 ], 2984 ],
@@ -4266,133 +4266,146 @@
4266 } 4266 }
4267 }, 4267 },
4268 { 4268 {
4269 "defaultMessage": "!!!Enable universal Dark Mode", 4269 "defaultMessage": "!!!Enable adaptable Dark Mode",
4270 "end": { 4270 "end": {
4271 "column": 3, 4271 "column": 3,
4272 "line": 104 4272 "line": 104
4273 }, 4273 },
4274 "file": "src/containers/settings/EditSettingsScreen.js", 4274 "file": "src/containers/settings/EditSettingsScreen.js",
4275 "id": "settings.app.form.universalDarkMode", 4275 "id": "settings.app.form.adaptableDarkMode",
4276 "start": { 4276 "start": {
4277 "column": 21, 4277 "column": 21,
4278 "line": 101 4278 "line": 101
4279 } 4279 }
4280 }, 4280 },
4281 { 4281 {
4282 "defaultMessage": "!!!Accent color", 4282 "defaultMessage": "!!!Enable universal Dark Mode",
4283 "end": { 4283 "end": {
4284 "column": 3, 4284 "column": 3,
4285 "line": 108 4285 "line": 108
4286 }, 4286 },
4287 "file": "src/containers/settings/EditSettingsScreen.js", 4287 "file": "src/containers/settings/EditSettingsScreen.js",
4288 "id": "settings.app.form.universalDarkMode",
4289 "start": {
4290 "column": 21,
4291 "line": 105
4292 }
4293 },
4294 {
4295 "defaultMessage": "!!!Accent color",
4296 "end": {
4297 "column": 3,
4298 "line": 112
4299 },
4300 "file": "src/containers/settings/EditSettingsScreen.js",
4288 "id": "settings.app.form.accentColor", 4301 "id": "settings.app.form.accentColor",
4289 "start": { 4302 "start": {
4290 "column": 15, 4303 "column": 15,
4291 "line": 105 4304 "line": 109
4292 } 4305 }
4293 }, 4306 },
4294 { 4307 {
4295 "defaultMessage": "!!!Display disabled services tabs", 4308 "defaultMessage": "!!!Display disabled services tabs",
4296 "end": { 4309 "end": {
4297 "column": 3, 4310 "column": 3,
4298 "line": 112 4311 "line": 116
4299 }, 4312 },
4300 "file": "src/containers/settings/EditSettingsScreen.js", 4313 "file": "src/containers/settings/EditSettingsScreen.js",
4301 "id": "settings.app.form.showDisabledServices", 4314 "id": "settings.app.form.showDisabledServices",
4302 "start": { 4315 "start": {
4303 "column": 24, 4316 "column": 24,
4304 "line": 109 4317 "line": 113
4305 } 4318 }
4306 }, 4319 },
4307 { 4320 {
4308 "defaultMessage": "!!!Show unread message badge when notifications are disabled", 4321 "defaultMessage": "!!!Show unread message badge when notifications are disabled",
4309 "end": { 4322 "end": {
4310 "column": 3, 4323 "column": 3,
4311 "line": 116 4324 "line": 120
4312 }, 4325 },
4313 "file": "src/containers/settings/EditSettingsScreen.js", 4326 "file": "src/containers/settings/EditSettingsScreen.js",
4314 "id": "settings.app.form.showMessagesBadgesWhenMuted", 4327 "id": "settings.app.form.showMessagesBadgesWhenMuted",
4315 "start": { 4328 "start": {
4316 "column": 29, 4329 "column": 29,
4317 "line": 113 4330 "line": 117
4318 } 4331 }
4319 }, 4332 },
4320 { 4333 {
4321 "defaultMessage": "!!!Enable spell checking", 4334 "defaultMessage": "!!!Enable spell checking",
4322 "end": { 4335 "end": {
4323 "column": 3, 4336 "column": 3,
4324 "line": 120 4337 "line": 124
4325 }, 4338 },
4326 "file": "src/containers/settings/EditSettingsScreen.js", 4339 "file": "src/containers/settings/EditSettingsScreen.js",
4327 "id": "settings.app.form.enableSpellchecking", 4340 "id": "settings.app.form.enableSpellchecking",
4328 "start": { 4341 "start": {
4329 "column": 23, 4342 "column": 23,
4330 "line": 117 4343 "line": 121
4331 } 4344 }
4332 }, 4345 },
4333 { 4346 {
4334 "defaultMessage": "!!!Enable GPU Acceleration", 4347 "defaultMessage": "!!!Enable GPU Acceleration",
4335 "end": { 4348 "end": {
4336 "column": 3, 4349 "column": 3,
4337 "line": 124 4350 "line": 128
4338 }, 4351 },
4339 "file": "src/containers/settings/EditSettingsScreen.js", 4352 "file": "src/containers/settings/EditSettingsScreen.js",
4340 "id": "settings.app.form.enableGPUAcceleration", 4353 "id": "settings.app.form.enableGPUAcceleration",
4341 "start": { 4354 "start": {
4342 "column": 25, 4355 "column": 25,
4343 "line": 121 4356 "line": 125
4344 } 4357 }
4345 }, 4358 },
4346 { 4359 {
4347 "defaultMessage": "!!!Include beta versions", 4360 "defaultMessage": "!!!Include beta versions",
4348 "end": { 4361 "end": {
4349 "column": 3, 4362 "column": 3,
4350 "line": 128 4363 "line": 132
4351 }, 4364 },
4352 "file": "src/containers/settings/EditSettingsScreen.js", 4365 "file": "src/containers/settings/EditSettingsScreen.js",
4353 "id": "settings.app.form.beta", 4366 "id": "settings.app.form.beta",
4354 "start": { 4367 "start": {
4355 "column": 8, 4368 "column": 8,
4356 "line": 125 4369 "line": 129
4357 } 4370 }
4358 }, 4371 },
4359 { 4372 {
4360 "defaultMessage": "!!!Disable updates", 4373 "defaultMessage": "!!!Disable updates",
4361 "end": { 4374 "end": {
4362 "column": 3, 4375 "column": 3,
4363 "line": 132 4376 "line": 136
4364 }, 4377 },
4365 "file": "src/containers/settings/EditSettingsScreen.js", 4378 "file": "src/containers/settings/EditSettingsScreen.js",
4366 "id": "settings.app.form.noUpdates", 4379 "id": "settings.app.form.noUpdates",
4367 "start": { 4380 "start": {
4368 "column": 13, 4381 "column": 13,
4369 "line": 129 4382 "line": 133
4370 } 4383 }
4371 }, 4384 },
4372 { 4385 {
4373 "defaultMessage": "!!!Enable Franz Todos", 4386 "defaultMessage": "!!!Enable Franz Todos",
4374 "end": { 4387 "end": {
4375 "column": 3, 4388 "column": 3,
4376 "line": 136 4389 "line": 140
4377 }, 4390 },
4378 "file": "src/containers/settings/EditSettingsScreen.js", 4391 "file": "src/containers/settings/EditSettingsScreen.js",
4379 "id": "settings.app.form.enableTodos", 4392 "id": "settings.app.form.enableTodos",
4380 "start": { 4393 "start": {
4381 "column": 15, 4394 "column": 15,
4382 "line": 133 4395 "line": 137
4383 } 4396 }
4384 }, 4397 },
4385 { 4398 {
4386 "defaultMessage": "!!!Keep all workspaces loaded", 4399 "defaultMessage": "!!!Keep all workspaces loaded",
4387 "end": { 4400 "end": {
4388 "column": 3, 4401 "column": 3,
4389 "line": 140 4402 "line": 144
4390 }, 4403 },
4391 "file": "src/containers/settings/EditSettingsScreen.js", 4404 "file": "src/containers/settings/EditSettingsScreen.js",
4392 "id": "settings.app.form.keepAllWorkspacesLoaded", 4405 "id": "settings.app.form.keepAllWorkspacesLoaded",
4393 "start": { 4406 "start": {
4394 "column": 27, 4407 "column": 27,
4395 "line": 137 4408 "line": 141
4396 } 4409 }
4397 } 4410 }
4398 ], 4411 ],
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json
index a34da1848..b7d81356e 100644
--- a/src/i18n/locales/en-US.json
+++ b/src/i18n/locales/en-US.json
@@ -255,6 +255,7 @@
255 "settings.app.cacheInfo": "Ferdi cache is currently using {size} of disk space.", 255 "settings.app.cacheInfo": "Ferdi cache is currently using {size} of disk space.",
256 "settings.app.currentVersion": "Current version:", 256 "settings.app.currentVersion": "Current version:",
257 "settings.app.form.accentColor": "Accent color", 257 "settings.app.form.accentColor": "Accent color",
258 "settings.app.form.adaptableDarkMode": "Enable adaptable Dark Mode",
258 "settings.app.form.autoLaunchInBackground": "Open in background", 259 "settings.app.form.autoLaunchInBackground": "Open in background",
259 "settings.app.form.autoLaunchOnStart": "Launch Ferdi on start", 260 "settings.app.form.autoLaunchOnStart": "Launch Ferdi on start",
260 "settings.app.form.beta": "Include beta versions", 261 "settings.app.form.beta": "Include beta versions",
diff --git a/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json b/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json
index 70c4fb87f..5bf9f0b31 100644
--- a/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json
+++ b/src/i18n/messages/src/components/settings/settings/EditSettingsForm.json
@@ -4,11 +4,11 @@
4 "defaultMessage": "!!!Settings", 4 "defaultMessage": "!!!Settings",
5 "file": "src/components/settings/settings/EditSettingsForm.js", 5 "file": "src/components/settings/settings/EditSettingsForm.js",
6 "start": { 6 "start": {
7 "line": 26, 7 "line": 27,
8 "column": 12 8 "column": 12
9 }, 9 },
10 "end": { 10 "end": {
11 "line": 29, 11 "line": 30,
12 "column": 3 12 "column": 3
13 } 13 }
14 }, 14 },
@@ -17,11 +17,11 @@
17 "defaultMessage": "!!!General", 17 "defaultMessage": "!!!General",
18 "file": "src/components/settings/settings/EditSettingsForm.js", 18 "file": "src/components/settings/settings/EditSettingsForm.js",
19 "start": { 19 "start": {
20 "line": 30, 20 "line": 31,
21 "column": 19 21 "column": 19
22 }, 22 },
23 "end": { 23 "end": {
24 "line": 33, 24 "line": 34,
25 "column": 3 25 "column": 3
26 } 26 }
27 }, 27 },
@@ -30,11 +30,11 @@
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.", 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", 31 "file": "src/components/settings/settings/EditSettingsForm.js",
32 "start": { 32 "start": {
33 "line": 34, 33 "line": 35,
34 "column": 17 34 "column": 17
35 }, 35 },
36 "end": { 36 "end": {
37 "line": 37, 37 "line": 38,
38 "column": 3 38 "column": 3
39 } 39 }
40 }, 40 },
@@ -43,11 +43,11 @@
43 "defaultMessage": "!!!We advice you to logout after changing your server as your settings might not be saved otherwise.", 43 "defaultMessage": "!!!We advice you to logout after changing your server as your settings might not be saved otherwise.",
44 "file": "src/components/settings/settings/EditSettingsForm.js", 44 "file": "src/components/settings/settings/EditSettingsForm.js",
45 "start": { 45 "start": {
46 "line": 38, 46 "line": 39,
47 "column": 14 47 "column": 14
48 }, 48 },
49 "end": { 49 "end": {
50 "line": 41, 50 "line": 42,
51 "column": 3 51 "column": 3
52 } 52 }
53 }, 53 },
@@ -56,11 +56,11 @@
56 "defaultMessage": "!!!You are using the official Franz Server for Ferdi.\nWe know that Ferdi allows you to use all its features for free but you are still using Franz's server resources - which Franz's creator has to pay for.\nPlease still consider [Link 1]paying for a Franz account[/Link] or [Link 2]using a self-hosted ferdi-server[/Link] (if you have the knowledge and resources to do so). \nBy using Ferdi, you still profit greatly from Franz's recipe store, server resources and its development.", 56 "defaultMessage": "!!!You are using the official Franz Server for Ferdi.\nWe know that Ferdi allows you to use all its features for free but you are still using Franz's server resources - which Franz's creator has to pay for.\nPlease still consider [Link 1]paying for a Franz account[/Link] or [Link 2]using a self-hosted ferdi-server[/Link] (if you have the knowledge and resources to do so). \nBy using Ferdi, you still profit greatly from Franz's recipe store, server resources and its development.",
57 "file": "src/components/settings/settings/EditSettingsForm.js", 57 "file": "src/components/settings/settings/EditSettingsForm.js",
58 "start": { 58 "start": {
59 "line": 42, 59 "line": 43,
60 "column": 19 60 "column": 19
61 }, 61 },
62 "end": { 62 "end": {
63 "line": 45, 63 "line": 46,
64 "column": 3 64 "column": 3
65 } 65 }
66 }, 66 },
@@ -69,11 +69,11 @@
69 "defaultMessage": "!!!This server will be used for the \"Franz Todo\" feature. (default: https://app.franztodos.com)", 69 "defaultMessage": "!!!This server will be used for the \"Franz Todo\" feature. (default: https://app.franztodos.com)",
70 "file": "src/components/settings/settings/EditSettingsForm.js", 70 "file": "src/components/settings/settings/EditSettingsForm.js",
71 "start": { 71 "start": {
72 "line": 46, 72 "line": 47,
73 "column": 18 73 "column": 18
74 }, 74 },
75 "end": { 75 "end": {
76 "line": 49, 76 "line": 50,
77 "column": 3 77 "column": 3
78 } 78 }
79 }, 79 },
@@ -82,11 +82,11 @@
82 "defaultMessage": "!!!Ferdi Lock Password", 82 "defaultMessage": "!!!Ferdi Lock Password",
83 "file": "src/components/settings/settings/EditSettingsForm.js", 83 "file": "src/components/settings/settings/EditSettingsForm.js",
84 "start": { 84 "start": {
85 "line": 50, 85 "line": 51,
86 "column": 18 86 "column": 18
87 }, 87 },
88 "end": { 88 "end": {
89 "line": 53, 89 "line": 54,
90 "column": 3 90 "column": 3
91 } 91 }
92 }, 92 },
@@ -95,11 +95,11 @@
95 "defaultMessage": "!!!Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdi.", 95 "defaultMessage": "!!!Please make sure to set a password you'll remember.\nIf you loose this password, you will have to reinstall Ferdi.",
96 "file": "src/components/settings/settings/EditSettingsForm.js", 96 "file": "src/components/settings/settings/EditSettingsForm.js",
97 "start": { 97 "start": {
98 "line": 54, 98 "line": 55,
99 "column": 22 99 "column": 22
100 }, 100 },
101 "end": { 101 "end": {
102 "line": 57, 102 "line": 58,
103 "column": 3 103 "column": 3
104 } 104 }
105 }, 105 },
@@ -108,11 +108,11 @@
108 "defaultMessage": "!!!Ferdi password lock allows you to keep your messages protected.\nUsing Ferdi 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 CMD/CTRL+Shift+L.", 108 "defaultMessage": "!!!Ferdi password lock allows you to keep your messages protected.\nUsing Ferdi 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 CMD/CTRL+Shift+L.",
109 "file": "src/components/settings/settings/EditSettingsForm.js", 109 "file": "src/components/settings/settings/EditSettingsForm.js",
110 "start": { 110 "start": {
111 "line": 58, 111 "line": 59,
112 "column": 12 112 "column": 12
113 }, 113 },
114 "end": { 114 "end": {
115 "line": 61, 115 "line": 62,
116 "column": 3 116 "column": 3
117 } 117 }
118 }, 118 },
@@ -121,11 +121,11 @@
121 "defaultMessage": "!!!Times in 24-Hour-Format. End time can be before start time (e.g. start 17:00, end 09:00) to enable Do-not-Disturb overnight.", 121 "defaultMessage": "!!!Times in 24-Hour-Format. End time can be before start time (e.g. start 17:00, end 09:00) to enable Do-not-Disturb overnight.",
122 "file": "src/components/settings/settings/EditSettingsForm.js", 122 "file": "src/components/settings/settings/EditSettingsForm.js",
123 "start": { 123 "start": {
124 "line": 62, 124 "line": 63,
125 "column": 24 125 "column": 24
126 }, 126 },
127 "end": { 127 "end": {
128 "line": 65, 128 "line": 66,
129 "column": 3 129 "column": 3
130 } 130 }
131 }, 131 },
@@ -134,11 +134,11 @@
134 "defaultMessage": "!!!Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.", 134 "defaultMessage": "!!!Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdi.",
135 "file": "src/components/settings/settings/EditSettingsForm.js", 135 "file": "src/components/settings/settings/EditSettingsForm.js",
136 "start": { 136 "start": {
137 "line": 66, 137 "line": 67,
138 "column": 20 138 "column": 20
139 }, 139 },
140 "end": { 140 "end": {
141 "line": 69, 141 "line": 70,
142 "column": 3 142 "column": 3
143 } 143 }
144 }, 144 },
@@ -147,11 +147,11 @@
147 "defaultMessage": "!!!Language", 147 "defaultMessage": "!!!Language",
148 "file": "src/components/settings/settings/EditSettingsForm.js", 148 "file": "src/components/settings/settings/EditSettingsForm.js",
149 "start": { 149 "start": {
150 "line": 70, 150 "line": 71,
151 "column": 20 151 "column": 20
152 }, 152 },
153 "end": { 153 "end": {
154 "line": 73, 154 "line": 74,
155 "column": 3 155 "column": 3
156 } 156 }
157 }, 157 },
@@ -160,11 +160,11 @@
160 "defaultMessage": "!!!Updates", 160 "defaultMessage": "!!!Updates",
161 "file": "src/components/settings/settings/EditSettingsForm.js", 161 "file": "src/components/settings/settings/EditSettingsForm.js",
162 "start": { 162 "start": {
163 "line": 74, 163 "line": 75,
164 "column": 19 164 "column": 19
165 }, 165 },
166 "end": { 166 "end": {
167 "line": 77, 167 "line": 78,
168 "column": 3 168 "column": 3
169 } 169 }
170 }, 170 },
@@ -173,11 +173,11 @@
173 "defaultMessage": "!!!Appearance", 173 "defaultMessage": "!!!Appearance",
174 "file": "src/components/settings/settings/EditSettingsForm.js", 174 "file": "src/components/settings/settings/EditSettingsForm.js",
175 "start": { 175 "start": {
176 "line": 78, 176 "line": 79,
177 "column": 22 177 "column": 22
178 }, 178 },
179 "end": { 179 "end": {
180 "line": 81, 180 "line": 82,
181 "column": 3 181 "column": 3
182 } 182 }
183 }, 183 },
@@ -186,11 +186,11 @@
186 "defaultMessage": "!!!Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.", 186 "defaultMessage": "!!!Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.",
187 "file": "src/components/settings/settings/EditSettingsForm.js", 187 "file": "src/components/settings/settings/EditSettingsForm.js",
188 "start": { 188 "start": {
189 "line": 82, 189 "line": 83,
190 "column": 25 190 "column": 25
191 }, 191 },
192 "end": { 192 "end": {
193 "line": 85, 193 "line": 86,
194 "column": 3 194 "column": 3
195 } 195 }
196 }, 196 },
@@ -199,11 +199,11 @@
199 "defaultMessage": "!!!Write your accent color in a CSS-compatible format. (Default: #7367f0)", 199 "defaultMessage": "!!!Write your accent color in a CSS-compatible format. (Default: #7367f0)",
200 "file": "src/components/settings/settings/EditSettingsForm.js", 200 "file": "src/components/settings/settings/EditSettingsForm.js",
201 "start": { 201 "start": {
202 "line": 86, 202 "line": 87,
203 "column": 19 203 "column": 19
204 }, 204 },
205 "end": { 205 "end": {
206 "line": 89, 206 "line": 90,
207 "column": 3 207 "column": 3
208 } 208 }
209 }, 209 },
@@ -212,11 +212,11 @@
212 "defaultMessage": "!!!Advanced", 212 "defaultMessage": "!!!Advanced",
213 "file": "src/components/settings/settings/EditSettingsForm.js", 213 "file": "src/components/settings/settings/EditSettingsForm.js",
214 "start": { 214 "start": {
215 "line": 90, 215 "line": 91,
216 "column": 20 216 "column": 20
217 }, 217 },
218 "end": { 218 "end": {
219 "line": 93, 219 "line": 94,
220 "column": 3 220 "column": 3
221 } 221 }
222 }, 222 },
@@ -225,11 +225,11 @@
225 "defaultMessage": "!!!Help us to translate Ferdi into your language.", 225 "defaultMessage": "!!!Help us to translate Ferdi into your language.",
226 "file": "src/components/settings/settings/EditSettingsForm.js", 226 "file": "src/components/settings/settings/EditSettingsForm.js",
227 "start": { 227 "start": {
228 "line": 94, 228 "line": 95,
229 "column": 19 229 "column": 19
230 }, 230 },
231 "end": { 231 "end": {
232 "line": 97, 232 "line": 98,
233 "column": 3 233 "column": 3
234 } 234 }
235 }, 235 },
@@ -238,11 +238,11 @@
238 "defaultMessage": "!!!Cache", 238 "defaultMessage": "!!!Cache",
239 "file": "src/components/settings/settings/EditSettingsForm.js", 239 "file": "src/components/settings/settings/EditSettingsForm.js",
240 "start": { 240 "start": {
241 "line": 98, 241 "line": 99,
242 "column": 20 242 "column": 20
243 }, 243 },
244 "end": { 244 "end": {
245 "line": 101, 245 "line": 102,
246 "column": 3 246 "column": 3
247 } 247 }
248 }, 248 },
@@ -251,11 +251,11 @@
251 "defaultMessage": "!!!Ferdi cache is currently using {size} of disk space.", 251 "defaultMessage": "!!!Ferdi cache is currently using {size} of disk space.",
252 "file": "src/components/settings/settings/EditSettingsForm.js", 252 "file": "src/components/settings/settings/EditSettingsForm.js",
253 "start": { 253 "start": {
254 "line": 102, 254 "line": 103,
255 "column": 13 255 "column": 13
256 }, 256 },
257 "end": { 257 "end": {
258 "line": 105, 258 "line": 106,
259 "column": 3 259 "column": 3
260 } 260 }
261 }, 261 },
@@ -264,11 +264,11 @@
264 "defaultMessage": "!!!Clear cache", 264 "defaultMessage": "!!!Clear cache",
265 "file": "src/components/settings/settings/EditSettingsForm.js", 265 "file": "src/components/settings/settings/EditSettingsForm.js",
266 "start": { 266 "start": {
267 "line": 106, 267 "line": 107,
268 "column": 23 268 "column": 23
269 }, 269 },
270 "end": { 270 "end": {
271 "line": 109, 271 "line": 110,
272 "column": 3 272 "column": 3
273 } 273 }
274 }, 274 },
@@ -277,11 +277,11 @@
277 "defaultMessage": "!!!Check for updates", 277 "defaultMessage": "!!!Check for updates",
278 "file": "src/components/settings/settings/EditSettingsForm.js", 278 "file": "src/components/settings/settings/EditSettingsForm.js",
279 "start": { 279 "start": {
280 "line": 110, 280 "line": 111,
281 "column": 25 281 "column": 25
282 }, 282 },
283 "end": { 283 "end": {
284 "line": 113, 284 "line": 114,
285 "column": 3 285 "column": 3
286 } 286 }
287 }, 287 },
@@ -290,11 +290,11 @@
290 "defaultMessage": "!!!Restart & install update", 290 "defaultMessage": "!!!Restart & install update",
291 "file": "src/components/settings/settings/EditSettingsForm.js", 291 "file": "src/components/settings/settings/EditSettingsForm.js",
292 "start": { 292 "start": {
293 "line": 114, 293 "line": 115,
294 "column": 23 294 "column": 23
295 }, 295 },
296 "end": { 296 "end": {
297 "line": 117, 297 "line": 118,
298 "column": 3 298 "column": 3
299 } 299 }
300 }, 300 },
@@ -303,11 +303,11 @@
303 "defaultMessage": "!!!Is searching for update", 303 "defaultMessage": "!!!Is searching for update",
304 "file": "src/components/settings/settings/EditSettingsForm.js", 304 "file": "src/components/settings/settings/EditSettingsForm.js",
305 "start": { 305 "start": {
306 "line": 118, 306 "line": 119,
307 "column": 25 307 "column": 25
308 }, 308 },
309 "end": { 309 "end": {
310 "line": 121, 310 "line": 122,
311 "column": 3 311 "column": 3
312 } 312 }
313 }, 313 },
@@ -316,11 +316,11 @@
316 "defaultMessage": "!!!Update available, downloading...", 316 "defaultMessage": "!!!Update available, downloading...",
317 "file": "src/components/settings/settings/EditSettingsForm.js", 317 "file": "src/components/settings/settings/EditSettingsForm.js",
318 "start": { 318 "start": {
319 "line": 122, 319 "line": 123,
320 "column": 25 320 "column": 25
321 }, 321 },
322 "end": { 322 "end": {
323 "line": 125, 323 "line": 126,
324 "column": 3 324 "column": 3
325 } 325 }
326 }, 326 },
@@ -329,11 +329,11 @@
329 "defaultMessage": "!!!You are using the latest version of Ferdi", 329 "defaultMessage": "!!!You are using the latest version of Ferdi",
330 "file": "src/components/settings/settings/EditSettingsForm.js", 330 "file": "src/components/settings/settings/EditSettingsForm.js",
331 "start": { 331 "start": {
332 "line": 126, 332 "line": 127,
333 "column": 24 333 "column": 24
334 }, 334 },
335 "end": { 335 "end": {
336 "line": 129, 336 "line": 130,
337 "column": 3 337 "column": 3
338 } 338 }
339 }, 339 },
@@ -342,11 +342,11 @@
342 "defaultMessage": "!!!Current version:", 342 "defaultMessage": "!!!Current version:",
343 "file": "src/components/settings/settings/EditSettingsForm.js", 343 "file": "src/components/settings/settings/EditSettingsForm.js",
344 "start": { 344 "start": {
345 "line": 130, 345 "line": 131,
346 "column": 18 346 "column": 18
347 }, 347 },
348 "end": { 348 "end": {
349 "line": 133, 349 "line": 134,
350 "column": 3 350 "column": 3
351 } 351 }
352 }, 352 },
@@ -355,11 +355,11 @@
355 "defaultMessage": "!!!Changes require restart", 355 "defaultMessage": "!!!Changes require restart",
356 "file": "src/components/settings/settings/EditSettingsForm.js", 356 "file": "src/components/settings/settings/EditSettingsForm.js",
357 "start": { 357 "start": {
358 "line": 134, 358 "line": 135,
359 "column": 29 359 "column": 29
360 }, 360 },
361 "end": { 361 "end": {
362 "line": 137, 362 "line": 138,
363 "column": 3 363 "column": 3
364 } 364 }
365 }, 365 },
@@ -368,11 +368,11 @@
368 "defaultMessage": "!!!Official translations are English & German. All other languages are community based translations.", 368 "defaultMessage": "!!!Official translations are English & German. All other languages are community based translations.",
369 "file": "src/components/settings/settings/EditSettingsForm.js", 369 "file": "src/components/settings/settings/EditSettingsForm.js",
370 "start": { 370 "start": {
371 "line": 138, 371 "line": 139,
372 "column": 22 372 "column": 22
373 }, 373 },
374 "end": { 374 "end": {
375 "line": 141, 375 "line": 142,
376 "column": 3 376 "column": 3
377 } 377 }
378 } 378 }
diff --git a/src/i18n/messages/src/containers/settings/EditSettingsScreen.json b/src/i18n/messages/src/containers/settings/EditSettingsScreen.json
index 5ec8fdba7..411e35dab 100644
--- a/src/i18n/messages/src/containers/settings/EditSettingsScreen.json
+++ b/src/i18n/messages/src/containers/settings/EditSettingsScreen.json
@@ -234,8 +234,8 @@
234 } 234 }
235 }, 235 },
236 { 236 {
237 "id": "settings.app.form.universalDarkMode", 237 "id": "settings.app.form.adaptableDarkMode",
238 "defaultMessage": "!!!Enable universal Dark Mode", 238 "defaultMessage": "!!!Enable adaptable Dark Mode",
239 "file": "src/containers/settings/EditSettingsScreen.js", 239 "file": "src/containers/settings/EditSettingsScreen.js",
240 "start": { 240 "start": {
241 "line": 101, 241 "line": 101,
@@ -247,15 +247,28 @@
247 } 247 }
248 }, 248 },
249 { 249 {
250 "id": "settings.app.form.universalDarkMode",
251 "defaultMessage": "!!!Enable universal Dark Mode",
252 "file": "src/containers/settings/EditSettingsScreen.js",
253 "start": {
254 "line": 105,
255 "column": 21
256 },
257 "end": {
258 "line": 108,
259 "column": 3
260 }
261 },
262 {
250 "id": "settings.app.form.accentColor", 263 "id": "settings.app.form.accentColor",
251 "defaultMessage": "!!!Accent color", 264 "defaultMessage": "!!!Accent color",
252 "file": "src/containers/settings/EditSettingsScreen.js", 265 "file": "src/containers/settings/EditSettingsScreen.js",
253 "start": { 266 "start": {
254 "line": 105, 267 "line": 109,
255 "column": 15 268 "column": 15
256 }, 269 },
257 "end": { 270 "end": {
258 "line": 108, 271 "line": 112,
259 "column": 3 272 "column": 3
260 } 273 }
261 }, 274 },
@@ -264,11 +277,11 @@
264 "defaultMessage": "!!!Display disabled services tabs", 277 "defaultMessage": "!!!Display disabled services tabs",
265 "file": "src/containers/settings/EditSettingsScreen.js", 278 "file": "src/containers/settings/EditSettingsScreen.js",
266 "start": { 279 "start": {
267 "line": 109, 280 "line": 113,
268 "column": 24 281 "column": 24
269 }, 282 },
270 "end": { 283 "end": {
271 "line": 112, 284 "line": 116,
272 "column": 3 285 "column": 3
273 } 286 }
274 }, 287 },
@@ -277,11 +290,11 @@
277 "defaultMessage": "!!!Show unread message badge when notifications are disabled", 290 "defaultMessage": "!!!Show unread message badge when notifications are disabled",
278 "file": "src/containers/settings/EditSettingsScreen.js", 291 "file": "src/containers/settings/EditSettingsScreen.js",
279 "start": { 292 "start": {
280 "line": 113, 293 "line": 117,
281 "column": 29 294 "column": 29
282 }, 295 },
283 "end": { 296 "end": {
284 "line": 116, 297 "line": 120,
285 "column": 3 298 "column": 3
286 } 299 }
287 }, 300 },
@@ -290,11 +303,11 @@
290 "defaultMessage": "!!!Enable spell checking", 303 "defaultMessage": "!!!Enable spell checking",
291 "file": "src/containers/settings/EditSettingsScreen.js", 304 "file": "src/containers/settings/EditSettingsScreen.js",
292 "start": { 305 "start": {
293 "line": 117, 306 "line": 121,
294 "column": 23 307 "column": 23
295 }, 308 },
296 "end": { 309 "end": {
297 "line": 120, 310 "line": 124,
298 "column": 3 311 "column": 3
299 } 312 }
300 }, 313 },
@@ -303,11 +316,11 @@
303 "defaultMessage": "!!!Enable GPU Acceleration", 316 "defaultMessage": "!!!Enable GPU Acceleration",
304 "file": "src/containers/settings/EditSettingsScreen.js", 317 "file": "src/containers/settings/EditSettingsScreen.js",
305 "start": { 318 "start": {
306 "line": 121, 319 "line": 125,
307 "column": 25 320 "column": 25
308 }, 321 },
309 "end": { 322 "end": {
310 "line": 124, 323 "line": 128,
311 "column": 3 324 "column": 3
312 } 325 }
313 }, 326 },
@@ -316,11 +329,11 @@
316 "defaultMessage": "!!!Include beta versions", 329 "defaultMessage": "!!!Include beta versions",
317 "file": "src/containers/settings/EditSettingsScreen.js", 330 "file": "src/containers/settings/EditSettingsScreen.js",
318 "start": { 331 "start": {
319 "line": 125, 332 "line": 129,
320 "column": 8 333 "column": 8
321 }, 334 },
322 "end": { 335 "end": {
323 "line": 128, 336 "line": 132,
324 "column": 3 337 "column": 3
325 } 338 }
326 }, 339 },
@@ -329,11 +342,11 @@
329 "defaultMessage": "!!!Disable updates", 342 "defaultMessage": "!!!Disable updates",
330 "file": "src/containers/settings/EditSettingsScreen.js", 343 "file": "src/containers/settings/EditSettingsScreen.js",
331 "start": { 344 "start": {
332 "line": 129, 345 "line": 133,
333 "column": 13 346 "column": 13
334 }, 347 },
335 "end": { 348 "end": {
336 "line": 132, 349 "line": 136,
337 "column": 3 350 "column": 3
338 } 351 }
339 }, 352 },
@@ -342,11 +355,11 @@
342 "defaultMessage": "!!!Enable Franz Todos", 355 "defaultMessage": "!!!Enable Franz Todos",
343 "file": "src/containers/settings/EditSettingsScreen.js", 356 "file": "src/containers/settings/EditSettingsScreen.js",
344 "start": { 357 "start": {
345 "line": 133, 358 "line": 137,
346 "column": 15 359 "column": 15
347 }, 360 },
348 "end": { 361 "end": {
349 "line": 136, 362 "line": 140,
350 "column": 3 363 "column": 3
351 } 364 }
352 }, 365 },
@@ -355,11 +368,11 @@
355 "defaultMessage": "!!!Keep all workspaces loaded", 368 "defaultMessage": "!!!Keep all workspaces loaded",
356 "file": "src/containers/settings/EditSettingsScreen.js", 369 "file": "src/containers/settings/EditSettingsScreen.js",
357 "start": { 370 "start": {
358 "line": 137, 371 "line": 141,
359 "column": 27 372 "column": 27
360 }, 373 },
361 "end": { 374 "end": {
362 "line": 140, 375 "line": 144,
363 "column": 3 376 "column": 3
364 } 377 }
365 } 378 }
diff --git a/src/index.js b/src/index.js
index 87aa6357b..3453b46f7 100644
--- a/src/index.js
+++ b/src/index.js
@@ -9,9 +9,16 @@ import fs from 'fs-extra';
9import path from 'path'; 9import path from 'path';
10import windowStateKeeper from 'electron-window-state'; 10import windowStateKeeper from 'electron-window-state';
11 11
12if (process.platform === 'win32') { 12// Set app directory before loading user modules
13 app.setPath('appData', process.env.LOCALAPPDATA); 13if (process.env.FERDI_APPDATA_DIR != null) {
14 app.setPath('userData', path.join(process.env.LOCALAPPDATA, app.getName())); 14 app.setPath('appData', process.env.FERDI_APPDATA_DIR);
15 app.setPath('userData', path.join(app.getPath('appData')));
16} else if (process.env.PORTABLE_EXECUTABLE_DIR != null) {
17 app.setPath('appData', process.env.PORTABLE_EXECUTABLE_DIR, `${app.getName()}AppData`);
18 app.setPath('userData', path.join(app.getPath('appData'), `${app.getName()}AppData`));
19} else if (process.platform === 'win32') {
20 app.setPath('appData', process.env.APPDATA);
21 app.setPath('userData', path.join(app.getPath('appData'), app.getName()));
15} 22}
16 23
17if (isDevMode) { 24if (isDevMode) {
diff --git a/src/lib/Menu.js b/src/lib/Menu.js
index f3fbb0c73..826fe843f 100644
--- a/src/lib/Menu.js
+++ b/src/lib/Menu.js
@@ -678,7 +678,8 @@ const _titleBarTemplateFactory = intl => [
678 ], 678 ],
679 }, 679 },
680 { 680 {
681 label: '&?', 681 label: '?',
682 accelerator: 'Alt+?',
682 submenu: [ 683 submenu: [
683 { 684 {
684 label: intl.formatMessage(menuItems.learnMore), 685 label: intl.formatMessage(menuItems.learnMore),
diff --git a/src/server b/src/server
Subproject b5973cdc4cdd60e61d2fba25a317bb4d216a0d1 Subproject 8249d625bbd80498ae18257a52e480d0ebb368c
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js
index 59b100b55..0756a05eb 100644
--- a/src/stores/AppStore.js
+++ b/src/stores/AppStore.js
@@ -181,7 +181,9 @@ export default class AppStore extends Store {
181 181
182 this.locale = this._getDefaultLocale(); 182 this.locale = this._getDefaultLocale();
183 183
184 this._healthCheck(); 184 setTimeout(() => {
185 this._healthCheck();
186 }, 1000);
185 187
186 this.isSystemDarkModeEnabled = systemPreferences.isDarkMode(); 188 this.isSystemDarkModeEnabled = systemPreferences.isDarkMode();
187 189
@@ -227,6 +229,9 @@ export default class AppStore extends Store {
227 } 229 }
228 230
229 @computed get debugInfo() { 231 @computed get debugInfo() {
232 const settings = JSON.parse(JSON.stringify(this.stores.settings.app));
233 settings.lockedPassword = '******';
234
230 return { 235 return {
231 host: { 236 host: {
232 platform: process.platform, 237 platform: process.platform,
@@ -238,19 +243,20 @@ export default class AppStore extends Store {
238 electron: process.versions.electron, 243 electron: process.versions.electron,
239 installedRecipes: this.stores.recipes.all.map(recipe => ({ id: recipe.id, version: recipe.version })), 244 installedRecipes: this.stores.recipes.all.map(recipe => ({ id: recipe.id, version: recipe.version })),
240 devRecipes: this.stores.recipePreviews.dev.map(recipe => ({ id: recipe.id, version: recipe.version })), 245 devRecipes: this.stores.recipePreviews.dev.map(recipe => ({ id: recipe.id, version: recipe.version })),
241 services: this.stores.services.all.map(service => ({ 246 services: this.stores.services.all.map(service => ({
242 id: service.id, 247 id: service.id,
243 recipe: service.recipe.id, 248 recipe: service.recipe.id,
244 isAttached: service.isAttached, 249 isAttached: service.isAttached,
245 isActive: service.isActive, 250 isActive: service.isActive,
246 isEnabled: service.isEnabled, 251 isEnabled: service.isEnabled,
247 isHibernating: service.isHibernating, 252 isHibernating: service.isHibernating,
248 hasCrashed: service.hasCrashed, 253 hasCrashed: service.hasCrashed,
249 isDarkModeEnabled: service.isDarkModeEnabled, 254 isDarkModeEnabled: service.isDarkModeEnabled,
250 })), 255 })),
256 messages: this.stores.globalError.messages,
251 workspaces: this.stores.workspaces.workspaces.map(workspace => ({ id: workspace.id, services: workspace.services })), 257 workspaces: this.stores.workspaces.workspaces.map(workspace => ({ id: workspace.id, services: workspace.services })),
252 windowSettings: readJsonSync(path.join(app.getPath('userData'), 'window-state.json')), 258 windowSettings: readJsonSync(path.join(app.getPath('userData'), 'window-state.json')),
253 settings: this.stores.settings.app, 259 settings,
254 features: this.stores.features.features, 260 features: this.stores.features.features,
255 user: this.stores.user.data.id, 261 user: this.stores.user.data.id,
256 }, 262 },
diff --git a/src/stores/FeaturesStore.js b/src/stores/FeaturesStore.js
index ab5d762c7..780cde3a7 100644
--- a/src/stores/FeaturesStore.js
+++ b/src/stores/FeaturesStore.js
@@ -57,7 +57,10 @@ export default class FeaturesStore extends Store {
57 _updateFeatures = () => { 57 _updateFeatures = () => {
58 const features = Object.assign({}, DEFAULT_FEATURES_CONFIG); 58 const features = Object.assign({}, DEFAULT_FEATURES_CONFIG);
59 if (this.stores.user.isLoggedIn) { 59 if (this.stores.user.isLoggedIn) {
60 const requestResult = this.featuresRequest.execute().result; 60 let requestResult = {};
61 try {
62 requestResult = this.featuresRequest.execute().result;
63 } catch (e) {} // eslint-disable-line no-empty
61 Object.assign(features, requestResult); 64 Object.assign(features, requestResult);
62 } 65 }
63 runInAction('FeaturesStore::_updateFeatures', () => { 66 runInAction('FeaturesStore::_updateFeatures', () => {
diff --git a/src/stores/GlobalErrorStore.js b/src/stores/GlobalErrorStore.js
index 8bdafb68c..aacaa247f 100644
--- a/src/stores/GlobalErrorStore.js
+++ b/src/stores/GlobalErrorStore.js
@@ -5,14 +5,54 @@ import Request from './lib/Request';
5export default class GlobalErrorStore extends Store { 5export default class GlobalErrorStore extends Store {
6 @observable error = null; 6 @observable error = null;
7 7
8 @observable messages = [];
9
8 @observable response = {}; 10 @observable response = {};
9 11
10 constructor(...args) { 12 constructor(...args) {
11 super(...args); 13 super(...args);
12 14
15 window.onerror = (...errorArgs) => {
16 this._handleConsoleError.call(this, ['error', ...errorArgs]);
17 };
18
19 const origConsoleError = console.error;
20 window.console.error = (...errorArgs) => {
21 this._handleConsoleError.call(this, ['error', ...errorArgs]);
22 origConsoleError.apply(this, errorArgs);
23 };
24
25 const origConsoleLog = console.log;
26 window.console.log = (...logArgs) => {
27 this._handleConsoleError.call(this, ['log', ...logArgs]);
28 origConsoleLog.apply(this, logArgs);
29 };
30
31 const origConsoleInfo = console.info;
32 window.console.info = (...infoArgs) => {
33 this._handleConsoleError.call(this, ['info', ...infoArgs]);
34 origConsoleInfo.apply(this, infoArgs);
35 };
36
13 Request.registerHook(this._handleRequests); 37 Request.registerHook(this._handleRequests);
14 } 38 }
15 39
40 _handleConsoleError(type, error, url, line) {
41 if (typeof type === 'object' && type.length && type.length >= 1) {
42 this.messages.push({
43 type: type[0],
44 info: type,
45 });
46 } else {
47 this.messages.push({
48 type,
49 error,
50 url,
51 line,
52 });
53 }
54 }
55
16 _handleRequests = action(async (request) => { 56 _handleRequests = action(async (request) => {
17 if (request.isError) { 57 if (request.isError) {
18 this.error = request.error; 58 this.error = request.error;
@@ -28,6 +68,18 @@ export default class GlobalErrorStore extends Store {
28 // this.actions.user.logout({ serverLogout: true }); 68 // this.actions.user.logout({ serverLogout: true });
29 } 69 }
30 } 70 }
71
72 this.messages.push({
73 type: 'error',
74 request: {
75 result: request.result,
76 wasExecuted: request.wasExecuted,
77 method: request._method,
78 },
79 error: this.error,
80 response: this.response,
81 server: window.ferdi.stores.settings.app.server,
82 });
31 } else { 83 } else {
32 window.ferdi.stores.app.authRequestFailed = false; 84 window.ferdi.stores.app.authRequestFailed = false;
33 } 85 }
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index 934a8a6e0..3dd601bc3 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -116,6 +116,11 @@ export default class ServicesStore extends Store {
116 ); 116 );
117 117
118 reaction( 118 reaction(
119 () => this.stores.settings.app.adaptableDarkMode,
120 () => this._shareSettingsWithServiceProcess(),
121 );
122
123 reaction(
119 () => this.stores.settings.app.universalDarkMode, 124 () => this.stores.settings.app.universalDarkMode,
120 () => this._shareSettingsWithServiceProcess(), 125 () => this._shareSettingsWithServiceProcess(),
121 ); 126 );
@@ -585,7 +590,8 @@ export default class ServicesStore extends Store {
585 590
586 service.resetMessageCount(); 591 service.resetMessageCount();
587 592
588 service.webview.loadURL(service.url); 593 // service.webview.loadURL(service.url);
594 service.webview.reload();
589 } 595 }
590 596
591 @action _reloadActive() { 597 @action _reloadActive() {
diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js
index 9680c5bcc..44bc7c974 100644
--- a/src/stores/UIStore.js
+++ b/src/stores/UIStore.js
@@ -5,12 +5,18 @@ import {
5 reaction, 5 reaction,
6} from 'mobx'; 6} from 'mobx';
7import { theme } from '@meetfranz/theme'; 7import { theme } from '@meetfranz/theme';
8import { remote } from 'electron';
8 9
9import Store from './lib/Store'; 10import Store from './lib/Store';
11import { isMac } from '../environment';
12
13const { systemPreferences } = remote;
10 14
11export default class UIStore extends Store { 15export default class UIStore extends Store {
12 @observable showServicesUpdatedInfoBar = false; 16 @observable showServicesUpdatedInfoBar = false;
13 17
18 @observable isOsDarkThemeActive = isMac ? systemPreferences.isDarkMode() : false;
19
14 constructor(...args) { 20 constructor(...args) {
15 super(...args); 21 super(...args);
16 22
@@ -18,6 +24,13 @@ export default class UIStore extends Store {
18 this.actions.ui.openSettings.listen(this._openSettings.bind(this)); 24 this.actions.ui.openSettings.listen(this._openSettings.bind(this));
19 this.actions.ui.closeSettings.listen(this._closeSettings.bind(this)); 25 this.actions.ui.closeSettings.listen(this._closeSettings.bind(this));
20 this.actions.ui.toggleServiceUpdatedInfoBar.listen(this._toggleServiceUpdatedInfoBar.bind(this)); 26 this.actions.ui.toggleServiceUpdatedInfoBar.listen(this._toggleServiceUpdatedInfoBar.bind(this));
27
28 // Listen for theme change on MacOS
29 if (isMac) {
30 systemPreferences.subscribeNotification('AppleInterfaceThemeChangedNotification', () => {
31 this.isOsDarkThemeActive = systemPreferences.isDarkMode();
32 });
33 }
21 } 34 }
22 35
23 setup() { 36 setup() {
@@ -35,7 +48,7 @@ export default class UIStore extends Store {
35 } 48 }
36 49
37 @computed get isDarkThemeActive() { 50 @computed get isDarkThemeActive() {
38 return this.stores.settings.all.app.darkMode; 51 return this.stores.settings.all.app.darkMode || (this.stores.settings.all.app.adaptableDarkMode && this.isOsDarkThemeActive);
39 } 52 }
40 53
41 @computed get theme() { 54 @computed get theme() {
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js
index d6a2e5fde..ec0b0cf8d 100644
--- a/src/stores/UserStore.js
+++ b/src/stores/UserStore.js
@@ -348,7 +348,12 @@ export default class UserStore extends Store {
348 // Reactions 348 // Reactions
349 async _getUserData() { 349 async _getUserData() {
350 if (this.isLoggedIn) { 350 if (this.isLoggedIn) {
351 const data = await this.getUserInfoRequest.execute()._promise; 351 let data;
352 try {
353 data = await this.getUserInfoRequest.execute()._promise;
354 } catch (e) {
355 return false;
356 }
352 357
353 // We need to set the beta flag for the SettingsStore 358 // We need to set the beta flag for the SettingsStore
354 this.actions.settings.update({ 359 this.actions.settings.update({
@@ -408,7 +413,11 @@ export default class UserStore extends Store {
408 } 413 }
409 414
410 async _migrateUserLocale() { 415 async _migrateUserLocale() {
411 await this.getUserInfoRequest._promise; 416 try {
417 await this.getUserInfoRequest._promise;
418 } catch (e) {
419 return false;
420 }
412 421
413 if (!this.data.locale) { 422 if (!this.data.locale) {
414 debug('Migrate "locale" to user data'); 423 debug('Migrate "locale" to user data');
diff --git a/src/stores/lib/CachedRequest.js b/src/stores/lib/CachedRequest.js
index ac8b2bd81..31c7ce241 100644
--- a/src/stores/lib/CachedRequest.js
+++ b/src/stores/lib/CachedRequest.js
@@ -39,7 +39,7 @@ export default class CachedRequest extends Request {
39 }), 0); 39 }), 0);
40 40
41 // Issue api call & save it as promise that is handled to update the results of the operation 41 // Issue api call & save it as promise that is handled to update the results of the operation
42 this._promise = new Promise((resolve, reject) => { 42 this._promise = new Promise((resolve) => {
43 this._api[this._method](...callArgs) 43 this._api[this._method](...callArgs)
44 .then((result) => { 44 .then((result) => {
45 setTimeout(action(() => { 45 setTimeout(action(() => {
@@ -63,7 +63,7 @@ export default class CachedRequest extends Request {
63 this.wasExecuted = true; 63 this.wasExecuted = true;
64 this._isWaitingForResponse = false; 64 this._isWaitingForResponse = false;
65 this._triggerHooks(); 65 this._triggerHooks();
66 reject(error); 66 // reject(error);
67 }), 1); 67 }), 1);
68 })); 68 }));
69 }); 69 });
diff --git a/src/styles/tabs.scss b/src/styles/tabs.scss
index e500830ed..5bd0555d2 100644
--- a/src/styles/tabs.scss
+++ b/src/styles/tabs.scss
@@ -72,6 +72,8 @@
72 font-size: 0px; 72 font-size: 0px;
73 min-height: 10px; 73 min-height: 10px;
74 min-width: 10px; 74 min-width: 10px;
75 right: auto;
76 left: 8px;
75 } 77 }
76 } 78 }
77 79