diff options
-rw-r--r-- | .all-contributorsrc | 56 | ||||
-rw-r--r-- | README.md | 114 | ||||
-rw-r--r-- | branding/screenshots/hero.png | bin | 352745 -> 321357 bytes | |||
-rw-r--r-- | build-helpers/images/win-app-ico.ico | bin | 4286 -> 162459 bytes | |||
-rw-r--r-- | next_release.md | 44 | ||||
-rw-r--r-- | package-lock.json | 2 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | src/api/apiBase.js | 21 | ||||
-rw-r--r-- | src/api/server/ServerApi.js | 23 | ||||
-rw-r--r-- | src/components/services/content/ServiceView.js | 30 | ||||
-rw-r--r-- | src/components/services/content/ServiceWebview.js | 5 | ||||
-rw-r--r-- | src/components/ui/FeatureList.js | 2 | ||||
-rw-r--r-- | src/config.js | 1 | ||||
-rw-r--r-- | src/lib/Menu.js | 3 | ||||
-rw-r--r-- | src/stores/AppStore.js | 6 | ||||
-rw-r--r-- | src/stores/FeaturesStore.js | 5 | ||||
-rw-r--r-- | src/stores/GlobalErrorStore.js | 45 | ||||
-rw-r--r-- | src/stores/ServicesStore.js | 3 | ||||
-rw-r--r-- | src/stores/UserStore.js | 13 | ||||
-rw-r--r-- | src/stores/lib/CachedRequest.js | 4 | ||||
-rw-r--r-- | src/styles/tabs.scss | 2 |
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 |
@@ -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 | |||
47 | Ferdi 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 | ||
14 | You can find the installers in the [latest release](https://github.com/getferdi/ferdi/releases) assets. | 67 | You 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 | ||
62 | Please 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). | 113 | Please 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 | ||
66 | The 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. | 117 | The 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 | |||
145 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): | 196 | Thanks 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 | ||
2 | Infos about the next release: | ||
3 | |||
4 | ## Beta | ||
5 | v5.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 | ||
15 | v5.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'; |
7 | import { | 7 | import { |
8 | LOCAL_SERVER, | 8 | LOCAL_SERVER, |
9 | SERVER_NOT_LOADED, | ||
9 | } from '../config'; | 10 | } from '../config'; |
10 | 11 | ||
11 | const apiBase = () => { | 12 | const 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 | ||
38 | export default apiBase; | 35 | export 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 | ||
15 | import { sleep } from '../../helpers/async-helpers'; | 15 | import { sleep } from '../../helpers/async-helpers'; |
16 | 16 | ||
17 | import { API } from '../../environment'; | 17 | import { RECIPES_PATH, SERVER_NOT_LOADED } from '../../config'; |
18 | import { RECIPES_PATH } from '../../config'; | ||
19 | import apiBase from '../apiBase'; | 18 | import apiBase from '../apiBase'; |
20 | import { prepareAuthRequest, sendAuthRequest } from '../utils/auth'; | 19 | import { prepareAuthRequest, sendAuthRequest } from '../utils/auth'; |
21 | 20 | ||
@@ -39,8 +38,6 @@ module.paths.unshift( | |||
39 | const { app } = remote; | 38 | const { app } = remote; |
40 | const { default: fetch } = remote.require('electron-fetch'); | 39 | const { default: fetch } = remote.require('electron-fetch'); |
41 | 40 | ||
42 | const SERVER_URL = API; | ||
43 | |||
44 | export default class ServerApi { | 41 | export 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'; | |||
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { observable, reaction } from 'mobx'; | 4 | import { observable, reaction } from 'mobx'; |
5 | import ElectronWebView from 'react-electron-web-view'; | 5 | import ElectronWebView from 'react-electron-web-view'; |
6 | import path from 'path'; | ||
6 | 7 | ||
7 | import ServiceModel from '../../../models/Service'; | 8 | import 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 | ||
114 | export const LOCAL_SERVER = 'You are using Ferdi without a server'; | 114 | export const LOCAL_SERVER = 'You are using Ferdi without a server'; |
115 | export 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 |
117 | if (process.env.FERDI_APPDATA_DIR != null) { | 118 | if (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'; | |||
5 | export default class GlobalErrorStore extends Store { | 5 | export 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 | ||