aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.all-contributorsrc56
-rw-r--r--README.md114
-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
-rw-r--r--src/api/apiBase.js21
-rw-r--r--src/api/server/ServerApi.js23
-rw-r--r--src/components/services/content/ServiceView.js30
-rw-r--r--src/components/services/content/ServiceWebview.js5
-rw-r--r--src/components/ui/FeatureList.js2
-rw-r--r--src/config.js1
-rw-r--r--src/lib/Menu.js3
-rw-r--r--src/stores/AppStore.js6
-rw-r--r--src/stores/FeaturesStore.js5
-rw-r--r--src/stores/GlobalErrorStore.js45
-rw-r--r--src/stores/ServicesStore.js3
-rw-r--r--src/stores/UserStore.js13
-rw-r--r--src/stores/lib/CachedRequest.js4
-rw-r--r--src/styles/tabs.scss2
21 files changed, 285 insertions, 96 deletions
diff --git a/.all-contributorsrc b/.all-contributorsrc
index cd9704edf..89c1d6f2a 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,52 @@
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 ]
175 } 225 }
176 ], 226 ],
177 "contributorsPerLine": 6 227 "contributorsPerLine": 6
diff --git a/README.md b/README.md
index 285c80bb0..44ab84831 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,37 @@ 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>
170 </tr> 227 </tr>
171</table> 228</table>
172 229
173<!-- markdownlint-enable -->
174<!-- prettier-ignore-end -->
175
176<!-- ALL-CONTRIBUTORS-LIST:END --> 230<!-- ALL-CONTRIBUTORS-LIST:END -->
177 231
178<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --> 232<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
@@ -187,4 +241,8 @@ This project follows the [all-contributors](https://github.com/all-contributors/
187 241
188## Backers via OpenCollective 242## Backers via OpenCollective
189 243
190<a href="https://opencollective.com/getferdi#backers" target="_blank"><img src="https://opencollective.com/getferdi/backers.svg?width=890"></a> 244<a href="https://opencollective.com/getferdi#section-contribute" target="_blank"><img src="https://opencollective.com/getferdi/backers.svg?width=890"></a>
245
246## Sponsors via OpenCollective
247
248<a href="https://opencollective.com/getferdi#section-contribute" target="_blank"><img src="https://opencollective.com/getferdi/sponsors.svg?width=890"></a>
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/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/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/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 a7389b8bc..bd67aee6b 100644
--- a/src/config.js
+++ b/src/config.js
@@ -112,6 +112,7 @@ 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';
115 116
116// Set app directory before loading user modules 117// Set app directory before loading user modules
117if (process.env.FERDI_APPDATA_DIR != null) { 118if (process.env.FERDI_APPDATA_DIR != null) {
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/stores/AppStore.js b/src/stores/AppStore.js
index 894c19347..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
@@ -251,7 +253,7 @@ export default class AppStore extends Store {
251 hasCrashed: service.hasCrashed, 253 hasCrashed: service.hasCrashed,
252 isDarkModeEnabled: service.isDarkModeEnabled, 254 isDarkModeEnabled: service.isDarkModeEnabled,
253 })), 255 })),
254 errors: this.stores.globalError.errors, 256 messages: this.stores.globalError.messages,
255 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 })),
256 windowSettings: readJsonSync(path.join(app.getPath('userData'), 'window-state.json')), 258 windowSettings: readJsonSync(path.join(app.getPath('userData'), 'window-state.json')),
257 settings, 259 settings,
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 09c215c3e..aacaa247f 100644
--- a/src/stores/GlobalErrorStore.js
+++ b/src/stores/GlobalErrorStore.js
@@ -5,30 +5,52 @@ 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 errors = []; 8 @observable messages = [];
9 9
10 @observable response = {}; 10 @observable response = {};
11 11
12 constructor(...args) { 12 constructor(...args) {
13 super(...args); 13 super(...args);
14 14
15 window.onerror = this._handleConsoleError.bind(this); 15 window.onerror = (...errorArgs) => {
16 this._handleConsoleError.call(this, ['error', ...errorArgs]);
17 };
16 18
17 const origConsoleError = console.error; 19 const origConsoleError = console.error;
18 console.error = (...errorArgs) => { 20 window.console.error = (...errorArgs) => {
19 this._handleConsoleError.call(this, errorArgs); 21 this._handleConsoleError.call(this, ['error', ...errorArgs]);
20 origConsoleError.apply(this, errorArgs); 22 origConsoleError.apply(this, errorArgs);
21 }; 23 };
22 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
23 Request.registerHook(this._handleRequests); 37 Request.registerHook(this._handleRequests);
24 } 38 }
25 39
26 _handleConsoleError(error, url, line) { 40 _handleConsoleError(type, error, url, line) {
27 this.errors.push({ 41 if (typeof type === 'object' && type.length && type.length >= 1) {
28 error, 42 this.messages.push({
29 url, 43 type: type[0],
30 line, 44 info: type,
31 }); 45 });
46 } else {
47 this.messages.push({
48 type,
49 error,
50 url,
51 line,
52 });
53 }
32 } 54 }
33 55
34 _handleRequests = action(async (request) => { 56 _handleRequests = action(async (request) => {
@@ -47,7 +69,8 @@ export default class GlobalErrorStore extends Store {
47 } 69 }
48 } 70 }
49 71
50 this.errors.push({ 72 this.messages.push({
73 type: 'error',
51 request: { 74 request: {
52 result: request.result, 75 result: request.result,
53 wasExecuted: request.wasExecuted, 76 wasExecuted: request.wasExecuted,
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index 934a8a6e0..f65faa5a5 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -585,7 +585,8 @@ export default class ServicesStore extends Store {
585 585
586 service.resetMessageCount(); 586 service.resetMessageCount();
587 587
588 service.webview.loadURL(service.url); 588 // service.webview.loadURL(service.url);
589 service.webview.reload();
589 } 590 }
590 591
591 @action _reloadActive() { 592 @action _reloadActive() {
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