diff options
author | Stefan Malzner <stefan@adlk.io> | 2017-10-22 22:38:13 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-22 22:38:13 +0200 |
commit | f072b3550d264e00a141003c5a00130427c8c906 (patch) | |
tree | b51fe393eca0034b4185dee69c01b63a3042e7bf | |
parent | [translation] French (fr) (diff) | |
parent | Merge pull request #62 from grzeswol/master (diff) | |
download | ferdium-app-f072b3550d264e00a141003c5a00130427c8c906.tar.gz ferdium-app-f072b3550d264e00a141003c5a00130427c8c906.tar.zst ferdium-app-f072b3550d264e00a141003c5a00130427c8c906.zip |
Merge branch 'develop' into master
-rw-r--r-- | .travis.yml | 21 | ||||
-rw-r--r-- | README.md | 7 | ||||
-rw-r--r-- | docs/linux.md | 11 | ||||
-rw-r--r-- | electron-builder.yml | 2 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | src/actions/service.js | 2 | ||||
-rw-r--r-- | src/components/settings/settings/EditSettingsForm.js | 1 | ||||
-rw-r--r-- | src/config.js | 10 | ||||
-rw-r--r-- | src/containers/settings/EditSettingsScreen.js | 23 | ||||
-rw-r--r-- | src/electron/Settings.js | 14 | ||||
-rw-r--r-- | src/electron/ipc-api/appIndicator.js | 45 | ||||
-rw-r--r-- | src/electron/ipc-api/settings.js | 9 | ||||
-rw-r--r-- | src/electron/ipc-api/tray.js | 48 | ||||
-rw-r--r-- | src/i18n/languages.js | 2 | ||||
-rw-r--r-- | src/i18n/locales/en-US.json | 1 | ||||
-rw-r--r-- | src/i18n/locales/pl-PL.json | 167 | ||||
-rw-r--r-- | src/i18n/locales/ru-RU.json | 168 | ||||
-rw-r--r-- | src/index.js | 26 | ||||
-rw-r--r-- | src/lib/Tray.js | 64 | ||||
-rw-r--r-- | src/stores/AppStore.js | 12 | ||||
-rw-r--r-- | src/stores/ServicesStore.js | 24 |
21 files changed, 536 insertions, 122 deletions
diff --git a/.travis.yml b/.travis.yml index b98db62a9..d9d9452af 100644 --- a/.travis.yml +++ b/.travis.yml | |||
@@ -1,34 +1,26 @@ | |||
1 | language: node_js | 1 | language: node_js |
2 | |||
3 | before_script: | 2 | before_script: |
4 | - yarn add global gulp-cli@1.2.2 | 3 | - yarn add global gulp-cli@1.2.2 |
5 | - yarn add global gulpjs/gulp#4.0 | 4 | - yarn add global gulpjs/gulp#4.0 |
6 | - yarn add global node-sass | 5 | - yarn add global node-sass |
7 | - yarn install | 6 | - yarn install |
8 | |||
9 | script: | 7 | script: |
10 | - yarn lint | 8 | - yarn lint |
11 | - yarn build | 9 | - travis_wait yarn build |
12 | |||
13 | node_js: | 10 | node_js: |
14 | - '7' | 11 | - '7' |
15 | |||
16 | os: osx | 12 | os: osx |
17 | |||
18 | osx_image: xcode8.3 | 13 | osx_image: xcode8.3 |
19 | |||
20 | cache: yarn | 14 | cache: yarn |
21 | |||
22 | notifications: | 15 | notifications: |
23 | email: false | 16 | email: false |
24 | slack: | 17 | slack: |
25 | secure: 0rWztugXppPLIqup6cJ0QplJqtZ4XYzN+qgdyY2ARyPbJkjihfp0qWOiEZfNWIuUCxX2bZXODaEb1Jod6mNfiCQdIs3pW8EUD/cVSDul8jBwXSTwTyAAz4pLejXu3ckHVIiXlAriLC6qqedh2Rl9oAH6JumRmuyb0UTAG0O3Btm3lGM3Cwo3JKt0Zpvly2nBlUI1waSiG11QSx5olq+EDiYvMCzW5mpulwRwnXaOdoIWGBFqnYTFoeS/rLi5IE56yvrYODJPl1e0VhW8Zn4WXiVG+qjlREkDFm4qg2u1SQhZQHRBgveRjSxSAblcG5h58NlkijMKBASWMpj2DjAfiDkGMYoRu1IVyHcFlAI8a+wcR6HlQzVsu4e6EFMyzx33vVVUWovwO+BcxVpME25BZn96eC8P6XE2ruOHahKstEt310dieZZRE/gteBokGh3utA2DV6002GSFYlwqqJ9q/5c5wyhD6cefxYSpzivOqCoiUAq3HW1Nahb4l+EVikTydFkLY0et3f/eV/kD/9yJfZJcttVSTL5Gv6gK4ROjPTJ/UPUkqsVBUdxVrnXiXL8SBESFsRHdHnSHMTkHh74dCrbyqot4pW38yLOmVATCEukm4Cd5N5wOUTGRA0nKon7/pCWoJg0wIH8N9FEtZbrNrD2FrkQbVgCJLXrC9jFpr34= | 18 | secure: NjEDG+6YvJvFNwRT8t8XyVR145m+Pb1pmYgdBeuhqtJbMAr0IOb0lLLW9ixKEsL1NU+0R58QGiG9qqY+lLnMNpDYjzluFo0gQtl2NJrULT4xUFDSu65XTwoutKyvj+hoCsHiwrSrO2dHTx3ZK2vsSueg+8jM/xss7dTLA6BcTYl14wTOU37PqFQZk9JYR+Dfq1Jjhy/mq4BiAsb/1clNIulkjmRjSm6R0XT4ZsZZfj0ifXhL4cLGsUv2n+iePiX6bLwZPFjXV1COYTBafbCu17gw3nRMdNMMTDLbwrXXdJZFS/EjFOPgOhwF7CkZ3kSpB2ZIcAJxG7iAUl5j+jHBXc5dafRbjzE4oYve1vPexLoV3NjV76uANUFkcli6eHYD0uJoUJGBRbRGWp+8Bbw9EcBsn4s3vbf5XqHX3S46zvGgqX+LyhyMJQtEG/iv+9XOsOql18ryyejij0z1K7DxpI0gLV1ATZCphY1Fyz1yZDGlYN4ej/Rl2P1Q3yXilweJRF7Ts04w4U9iuP1u598/w++CKSu4q4EeEuqT/hIeFQUKUkwCEsO4xa39vhLPaxKrG9UEUH8OXN+NPZyTAK/LKuIX7C56O1kwvWNMWlPmTcvsq2RghvNTwgSGUIO0EKZKrQYAEG3Y/veSt5CgZoNzLgc/6Xj+g7daxUo9heLy26A= |
26 | |||
27 | deploy: | 19 | deploy: |
28 | provider: s3 | 20 | provider: s3 |
29 | access_key_id: AKIAI6ZWIP2OWZUCXIGA | 21 | access_key_id: AKIAI6ZWIP2OWZUCXIGA |
30 | secret_access_key: | 22 | secret_access_key: |
31 | secure: NSST9RjAG6v57MQgFKXckah7k2TMcbozpMN7IAdBmyIvwDlRN6ELAMCynknXDSLE6b6LKyhsQ/i6ykSuZxVoHzRyY9z28lJhLkGqCeABqSAhcwQ6gWxetFXGqIV7o/oxTVMS3cDrUdkfUPCQRUgMO1ew0oV7e4HfqIiDYQMMWJY/HGr/LUgNqolrSLGB2GI38/I1nrhPHm3gwa/xYgKUNsO6plPS/YzC6oF/edstM8oO51Lfpq6+XmDMTUl9qq8GkUaRE4BwdGPG97FOA6Y4ONCeJ3xURkElwcfWab7oW3Mox7hj0Z8vot10cieIWEQjpRP+zO5O2NwUzFRH25FuQf4bbvgH4iWXpLan+qnJ9Ow6cl0lg4+8ESemwDCnKtTGb3ujagTH0S4KqBlwJ6sXFb9U2Diut4cEIT4k3rainjk+8ugIssuJq2TWfB40X49ymPw5BPjJfq2T4fOjx8OKzrBHQ1X6KJd8RhfEoLD3V5eToO5/l13uYOBrjSfyo6afvvUIraVNijSlnqYxPmJYnrLWZUUsTiHZFwSF+x2ffcYKs/tep9zqkZpyV4GhH17HcfuQpx4FUIXqMFmGLRj2uN7FweSVdfbsODhgpIwlpV7gMKONeSmEiFcCMwcRik1UK9off7TE6ZJPzX21BJ8QGM5j7Ot2tif2eGvAv+hUaXc= | 23 | secure: hhosIIS7M2j5D8ivNfVEy9jp6oI9x2YKzPS4yDzWutKbILoB2Ii7F6gnaj9l2I9HLX01FE5/jH69rZ5ftP3wmUuywYcsua+Cs5zCnkkjm65WBHnTf5wp91X/tgLtMJNRVWhkxCeVmY7Ijpotmi6rq3GbgCMe2Ok08SExwOdYiCuGWiG5QiIYI/XRPjoUCkP6k4KsZ27HOO2agyXzRRiCI0O2RsSrb41WD4SPlsIW8aECDSOCaF/lIm38o03Q+lX1PtfDjOz9nfu5UUPJDWJNE9rnsa9xbgnNS9qhg/bBOwhtN+21dYCdgScax25kqlnYfT3ZLxBdZSLeM0c0lElaxAdTV/EAYySpnXP2ErfD5sLqVwmcrImKzhGDjyWeQCSBRMC4xfor9taJpB0O0v7iRO7VxszJCYGoUgLAu8kvp2pqkt8s+3t5+JzWdXacHgbKXQkyQWBY1SQzatlqOAAa2wtRv1rk3Xb8czF+4CnJ8n4St4Voo7/pecMwC+KURPemwAEb40OHofj/aRlwgc/kmIV+VUBrPUro5+KJYoQz4zFCchuOa/W6fAN3R9RAn3m4nwxthxI2ckAVdbkJC5c100/NZhPzyfuS+FOLpQ2bbSYfHu/4D7Yji0Pn+Q9lysf27PnnK8m2Ol3eyh+t02CMs6FNW6Wq1YIqarEjF8ouQKE= |
32 | bucket: franz-travis | 24 | bucket: franz-travis |
33 | region: eu-central-1 | 25 | region: eu-central-1 |
34 | local_dir: out | 26 | local_dir: out |
@@ -37,9 +29,8 @@ deploy: | |||
37 | acl: public_read | 29 | acl: public_read |
38 | on: | 30 | on: |
39 | all_branches: true | 31 | all_branches: true |
40 | |||
41 | env: | 32 | env: |
42 | global: | 33 | global: |
43 | - secure: izVSi10ahT32qqS+Bl0NcKwX2BoCOIJWa2wX3itw9kJvIS4k34OhnzIDhLCa6MEjDdE9eg8jcA9qHmE05qbirLDec623K5Z73zJ+QyD0QTEs7WKNm9C+lc3THtu4NkvIMF4fVS+6uMBpclkuiG5SMOg2bhlSwtccvCrNP/+9pwUUX215S1M53OjGiQNkconWLDMceL9DHnBZT2Q4QHq55w8EKfNnxFHE996TVTLcoLBt8dUp6VCdcmzCGYiWpkD7q5rApX5iy5d9v2dETcvr329/Qgdi5jFj9g6Fvl9h+uE/BpUNnIyWst1r5S7sSTR6pFt5HzJv30T4bmFGz+z2+v/x4Sdrqez4Aa9onGjDNNau8pez1gtopf8vwpKNp8cnRTnRGdMMPRc+7lswfY8Cwa50NV/fxZqbzokBlmTr/t1d3vaxaeHM56c/9POKdwD/I8RYGONc2jDzAmeAJ1gi6Nt6PixTZhhIRc/221mJ3lTlewKPbRZF42/+L0zF/yNxYMQ25mUU+gTkeQ5+XDsZXAD0bOzMSnZ58cAj7qKftu4VrKpB+DmwWwKplLLwnKEzYqUiAnJt+S9yO8S+XFGdhDJqtbuOOlOeA7h/wYPKxanp2dzemU5WffeIrt7lDlFQra1cLUritOqk132daaWwpnDOccwGYTpwmazTvbjSDEU= | 34 | - secure: fddJzSmNYVX024jnhnFXEuAK1spEYi3y3RZdWaBtjQnzoObAxkcRW263JNpXQy+b7egnp2hSy8FvlQU+L967911F5Y70Pe3An4oI72hnS3DL4Njp2Dw5PwviwMA+X2ddWhzK4+k/JU6r8jBv1FGQ6ZjwSeaO/t8UKOsE8wDBFLRhnHqoR7QbM7zmKjzh/1oofunGbHsPOHmN4f7jBwSuSFTZltEENcQg3ZP++0NHU8UJdlpfqZOkro8v4AJMngAHeHlNtjwaAHdVv+6+kkwc4E/0Cy6YNyyBkbzipyngNY3GwnwzmNzvsfICD1TGklksjBlMQq7ld7eCiaYRNvyHVEmXJ17qlq7HhxkYgNy32hPRwb5Cv6o4M4tv8qS8UUk4W1RvBJ5fcmfZGQwGXPyQ/m85RJtrNfbYtr84jYcprTnSeji/9PuZv0f87dxELYm3DYmNUa1cgJqEdLUsEd0bMwUYNLnCSfu4ea2zxwir6LSBtJJCbGKxX87s5IOTrHkrWDe+PWd52v+UjQks7MBRlJnntTWo69Yy+ayXV1TnGVOHA5znHvPOvFlAF+y8tLGd4AGvehK1SAkf0+idmc9Q9xKk0QypT3ibjJui4D50p7sSajkzz3P2pUqOS/9HmjMfPMPN+Nl+48GU0CvB2aBGhdmp9vu54VaFzUaAGNGj4WI= |
44 | - secure: ZOcObe290rPRqlt8v+l7rWvVcKx+0AxVBHMwxu/S9V/PNV3U6yHUZUe6Ur5Y5MAW7WCFLCaKUa3kgyf0g2A1SnTdlwdQ+6t4Y7FyKjHx+AjR0E8WTTl782h0CVqPlGgjeJOpcy1p8yQAppugDvQ6Ov442Yf9f1QhXOWwCB/DTI7WzJPTqq35W5oFRZm5skhyrhZxFujX4OcC+pN7INwWF+u1mh7C0XbzmrlGvl0TK048u4IqFJkBeGOdrRzg0y6eV+tLDk6Ah+O1F5OeOFkHEQhwFpXjcNZ8zDjf3R2xS28+4oCLq2Iin/xKVUlDRg/qG5cXxKPvFteecnor6S65GU80ppYDSdhUhaJMdB1wZGuCogzKJ1s2DmmUv2TE633l+1NXebnQ/nfpVqNr54YqkxDyIA0WaDSAwo496xujdGZfja5Nxv2Ssm8WAfDAgajLYyhSpw7jaIIEw8Ov11XC+BnILU+4CQEKthSyBvEjVO8DtxOl9mOHYy+XTgi67nNi5xv3u1/kUOz1r3VHMyEAKJf1pBpFoOM5S9fpUWeS7rsXh+0mUsoKMDf38SLnQpFMvrygRY9gxAUrYfwupvKUug+p8HkTURo1W3k5oqwZIW12IAxbus7i6uTk4gdnx9fFF/Ljz4irkPPhhuVikT7zF1hvvHQjyhbwvIPQcHu+Ufg= | 35 | - secure: AjJvKhQ1jIloxogMdtOzJqovPQUBSA0lfHcRsmGdP8HIRKSRi9tKxCCgicTMpMWfvY7qtdexXBbl2/zl6cOhjfTYeAhNwwCg+dw7OVcE8LUn4E+gYZCYIKbNmmkVKsSckQd4h2IcyvqdqLwzjrEzdF95MoUI8WqdLwvQJLkoIaXju6ZT76FslGSUVXk58ZN7p2nr3kW8V7KclIzn/yyyYXE4bjBmS4djuvCReeSfSViCuX5CGT8avBb/IF/M5S7hcQVybmmalysOrranzSx0o9PPUIT9hHqqRpXW6iss2qVj+kCaFiC3ftlApVgizBoGcNAMA8N7hX8kkEjJSpiy7Vswuev9mVN9X94VwVZGyNvdYD8cKKxqTsfFDZDgefnuSYUhymKSBgM4yScYF6IPNJWFWJTugtVeMJ8ivqZhwJuD20nt6x7gGB1FS6m7axxRWeyp7h0FqWU9l6ZfmwHcRziVKNTk9BB4XIqco9M2wjV/YH321IGVwtVR5y6zty10+xk38TthCOidgBurFlMKbFKH5g9K5+84dhsCW0avMlJ0+QkgId0uAVyho+09Wx4cKqXLfobpznkUX+S0Um6G/NbAaUAU+SqBsm+X9CKFsPd/YJoxLdF7eBCG/3Fy4roKg3J4mBYeXe3wVnGft8Eeg0aNpOArMSStMY337UpdV80= |
45 | - secure: dNpyF1AwYIj08pUwT40oSWStGOq9L5pYCuNhQnqIpj6sKgOXg+tkLC2N6mtH93TjeF2OXnTcumjikgNrB+amZhecsiHW94WkRH/mstfuU33GlUX+cAvjt0XPxLtH7YaJTM7xQwQ0dSFS5I0ptSEC57cOoF0MoAWY8ZpDtBR8EDGTfvX+nbVA2un0swWOhfJBLKFe3hv4ODYMi3KelyGmSB0n8DSHpcRpDsFzUNvPuUdxbOebKi46S6SLNWXsl0m9ft3RZLF45HM3qmB+Su5PSgibL/h4fKNMIe2YUpfoXdPbVMh5mlTYoFoLB3Xdi//HabcKoNHLE4aJNkW6RXgy7ZAQJRuXiBPPFktqAgBGnkAFrrS3dtb6b4qfxqoPeXoGMi5ctAVEPBiMaqwZsAIyffokYZyRUX3Qy7dtXCXR1C92WxQc9/Vnv3IJkjpXC4tK68uzady4E+BozoWtGgcZE/w68U/melFeoyLvIPMO93KwciaTIsx5Ck9MGBC8QOEqpH0L2dKntsrihoKB4hCQhGJmx5y2ash0UUWMA2eS7L+Wfp0vU6RbIkgEqHTkb70VuP7pTNYWasBPx+/k1xAJqi6nsGmB2BjC03VQToWfHaLgOVs2tbeolvMKzAdItg668tDGIsXfbKjxwkbexuBkhNKNiUmYd3Ub5Ki4cwg2ObU= | 36 | - secure: WNQBUyNvjTwMFm6pPzNXZYRvgLCTgEm93vLX/0amtr6gT6N8ZsTLL5+Ht3+v51MUOsjEe6tCM4cLSh4wSuwWcSEsUjK0jiqknlpgKKl6xLeo+1t8u6BKSgTpipWqrSD24TbvMrFUyeQrqCGRdZc3Ax/F1ERD81SXcsrg2evCL8g8zsYjxSMXc44drKrvYi68s/5ALrI+oH3t2PYsGuuP1ipj5CbaizUHEa5d8TukHRl96lxoEKCQ4Sa8UXRPNQsdb3TdkVmIEPIoioWU6AMPweBWR6Ky994aKwp0wWn1adWP49v8skMYWbirENniSxShtztF/NYqPQFyoyh0WD/C/ZJPh04HlMxnmQPUROq+LxBFz8WBY1eHDmz6GxH1lDYzneTtlRa5K8izvs2+ROhpVmmKeOgWHaL1ZRMy8Cn3V88kadF7i1K9NnqB6ZPyynJJctj7o0af6Os9/ZPqWfqIOWWeXgfXVzj17xJADfh6Z9epW95hdKZjnIf9IqGAI8aYTqhVL8DKTJ+PSGhJIOEX+ERm+0U9gMlwllwjHCDhBe42zCGuLaWZ239yD1eacM0Ko7yUM+xobiiF0FlB8VI/nBOpGdeUKNLeUfikLHILWd04AVRCNaQU67GMOHekfWdGR8tEh9I/5Y6GJR0IQL5eGmDUjSN0u/Ovss4jSEBOaXo= |
@@ -14,11 +14,8 @@ Messaging app for WhatsApp, Slack, Telegram, HipChat, Hangouts and many many mor | |||
14 | 14 | ||
15 | ### Preparations | 15 | ### Preparations |
16 | 16 | ||
17 | #### Install OS Dependencies | 17 | #### Install Linux OS dependencies |
18 | ##### Linux (Debian/Ubuntu) | 18 | [Guide: Linux distribution specific dependencies](docs/linux.md) |
19 | ```bash | ||
20 | $ apt install libx11-dev libxext-dev libxss-dev libxkbfile-dev | ||
21 | ``` | ||
22 | 19 | ||
23 | #### Install yarn | 20 | #### Install yarn |
24 | ##### MacOS | 21 | ##### MacOS |
diff --git a/docs/linux.md b/docs/linux.md new file mode 100644 index 000000000..bd70ad324 --- /dev/null +++ b/docs/linux.md | |||
@@ -0,0 +1,11 @@ | |||
1 | # Linux distribution specific dependencies | ||
2 | |||
3 | ## Debian/Ubuntu | ||
4 | ```bash | ||
5 | $ apt install libx11-dev libxext-dev libxss-dev libxkbfile-dev | ||
6 | ``` | ||
7 | |||
8 | ## Fedora | ||
9 | ```bash | ||
10 | $ dnf-install libX11-devel libXext-devel libXScrnSaver-devel libxkbfile-devel | ||
11 | ``` | ||
diff --git a/electron-builder.yml b/electron-builder.yml index 80ef5405e..0a01a03d8 100644 --- a/electron-builder.yml +++ b/electron-builder.yml | |||
@@ -2,7 +2,7 @@ directories: | |||
2 | app: ./build | 2 | app: ./build |
3 | output: ./out | 3 | output: ./out |
4 | 4 | ||
5 | forceCodeSigning: true | 5 | # forceCodeSigning: true |
6 | 6 | ||
7 | compression: maximum | 7 | compression: maximum |
8 | 8 | ||
diff --git a/package.json b/package.json index 6521432de..36cea0ca4 100644 --- a/package.json +++ b/package.json | |||
@@ -18,6 +18,7 @@ | |||
18 | "prebuild": "gulp build", | 18 | "prebuild": "gulp build", |
19 | "build": "node_modules/.bin/electron-builder --publish onTag", | 19 | "build": "node_modules/.bin/electron-builder --publish onTag", |
20 | "rebuild": "node_modules/.bin/electron-rebuild", | 20 | "rebuild": "node_modules/.bin/electron-rebuild", |
21 | "precommit": "yarn lint", | ||
21 | "commit": "git-cz", | 22 | "commit": "git-cz", |
22 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s" | 23 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s" |
23 | }, | 24 | }, |
diff --git a/src/actions/service.js b/src/actions/service.js index 7f429ca32..cdd4bbf16 100644 --- a/src/actions/service.js +++ b/src/actions/service.js | |||
@@ -4,6 +4,8 @@ export default { | |||
4 | setActive: { | 4 | setActive: { |
5 | serviceId: PropTypes.string.isRequired, | 5 | serviceId: PropTypes.string.isRequired, |
6 | }, | 6 | }, |
7 | setActiveNext: {}, | ||
8 | setActivePrev: {}, | ||
7 | showAddServiceInterface: { | 9 | showAddServiceInterface: { |
8 | recipeId: PropTypes.string.isRequired, | 10 | recipeId: PropTypes.string.isRequired, |
9 | }, | 11 | }, |
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js index 02736dbb9..5675fecf4 100644 --- a/src/components/settings/settings/EditSettingsForm.js +++ b/src/components/settings/settings/EditSettingsForm.js | |||
@@ -115,6 +115,7 @@ export default class EditSettingsForm extends Component { | |||
115 | <h2>{intl.formatMessage(messages.headlineGeneral)}</h2> | 115 | <h2>{intl.formatMessage(messages.headlineGeneral)}</h2> |
116 | <Toggle field={form.$('autoLaunchOnStart')} /> | 116 | <Toggle field={form.$('autoLaunchOnStart')} /> |
117 | <Toggle field={form.$('runInBackground')} /> | 117 | <Toggle field={form.$('runInBackground')} /> |
118 | <Toggle field={form.$('enableSystemTray')} /> | ||
118 | {process.platform === 'win32' && ( | 119 | {process.platform === 'win32' && ( |
119 | <Toggle field={form.$('minimizeToSystemTray')} /> | 120 | <Toggle field={form.$('minimizeToSystemTray')} /> |
120 | )} | 121 | )} |
diff --git a/src/config.js b/src/config.js index acbf57f3c..0a4856ece 100644 --- a/src/config.js +++ b/src/config.js | |||
@@ -3,3 +3,13 @@ export const LOCAL_API = 'http://localhost:3000'; | |||
3 | export const DEV_API = 'https://dev.franzinfra.com'; | 3 | export const DEV_API = 'https://dev.franzinfra.com'; |
4 | export const LIVE_API = 'https://api.franzinfra.com'; | 4 | export const LIVE_API = 'https://api.franzinfra.com'; |
5 | export const GA_ID = 'UA-74126766-6'; | 5 | export const GA_ID = 'UA-74126766-6'; |
6 | |||
7 | export const DEFAULT_APP_SETTINGS = { | ||
8 | autoLaunchOnStart: true, | ||
9 | autoLaunchInBackground: false, | ||
10 | runInBackground: false, | ||
11 | enableSystemTray: true, | ||
12 | minimizeToSystemTray: false, | ||
13 | locale: 'en-us', // TODO: Replace with proper solution once translations are in | ||
14 | beta: false, | ||
15 | }; | ||
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js index 0e17cafce..6dc2175e1 100644 --- a/src/containers/settings/EditSettingsScreen.js +++ b/src/containers/settings/EditSettingsScreen.js | |||
@@ -9,6 +9,7 @@ import UserStore from '../../stores/UserStore'; | |||
9 | import Form from '../../lib/Form'; | 9 | import Form from '../../lib/Form'; |
10 | import languages from '../../i18n/languages'; | 10 | import languages from '../../i18n/languages'; |
11 | import { gaPage } from '../../lib/analytics'; | 11 | import { gaPage } from '../../lib/analytics'; |
12 | import { DEFAULT_APP_SETTINGS } from '../../config'; | ||
12 | 13 | ||
13 | 14 | ||
14 | import EditSettingsForm from '../../components/settings/settings/EditSettingsForm'; | 15 | import EditSettingsForm from '../../components/settings/settings/EditSettingsForm'; |
@@ -26,6 +27,10 @@ const messages = defineMessages({ | |||
26 | id: 'settings.app.form.runInBackground', | 27 | id: 'settings.app.form.runInBackground', |
27 | defaultMessage: '!!!Keep Franz in background when closing the window', | 28 | defaultMessage: '!!!Keep Franz in background when closing the window', |
28 | }, | 29 | }, |
30 | enableSystemTray: { | ||
31 | id: 'settings.app.form.enableSystemTray', | ||
32 | defaultMessage: '!!!Show Franz in system tray', | ||
33 | }, | ||
29 | minimizeToSystemTray: { | 34 | minimizeToSystemTray: { |
30 | id: 'settings.app.form.minimizeToSystemTray', | 35 | id: 'settings.app.form.minimizeToSystemTray', |
31 | defaultMessage: '!!!Minimize Franz to system tray', | 36 | defaultMessage: '!!!Minimize Franz to system tray', |
@@ -61,6 +66,7 @@ export default class EditSettingsScreen extends Component { | |||
61 | settings.update({ | 66 | settings.update({ |
62 | settings: { | 67 | settings: { |
63 | runInBackground: settingsData.runInBackground, | 68 | runInBackground: settingsData.runInBackground, |
69 | enableSystemTray: settingsData.enableSystemTray, | ||
64 | minimizeToSystemTray: settingsData.minimizeToSystemTray, | 70 | minimizeToSystemTray: settingsData.minimizeToSystemTray, |
65 | locale: settingsData.locale, | 71 | locale: settingsData.locale, |
66 | beta: settingsData.beta, | 72 | beta: settingsData.beta, |
@@ -91,33 +97,38 @@ export default class EditSettingsScreen extends Component { | |||
91 | autoLaunchOnStart: { | 97 | autoLaunchOnStart: { |
92 | label: intl.formatMessage(messages.autoLaunchOnStart), | 98 | label: intl.formatMessage(messages.autoLaunchOnStart), |
93 | value: app.autoLaunchOnStart, | 99 | value: app.autoLaunchOnStart, |
94 | default: true, | 100 | default: DEFAULT_APP_SETTINGS.autoLaunchOnStart, |
95 | }, | 101 | }, |
96 | autoLaunchInBackground: { | 102 | autoLaunchInBackground: { |
97 | label: intl.formatMessage(messages.autoLaunchInBackground), | 103 | label: intl.formatMessage(messages.autoLaunchInBackground), |
98 | value: app.launchInBackground, | 104 | value: app.launchInBackground, |
99 | default: false, | 105 | default: DEFAULT_APP_SETTINGS.autoLaunchInBackground, |
100 | }, | 106 | }, |
101 | runInBackground: { | 107 | runInBackground: { |
102 | label: intl.formatMessage(messages.runInBackground), | 108 | label: intl.formatMessage(messages.runInBackground), |
103 | value: settings.all.runInBackground, | 109 | value: settings.all.runInBackground, |
104 | default: true, | 110 | default: DEFAULT_APP_SETTINGS.runInBackground, |
111 | }, | ||
112 | enableSystemTray: { | ||
113 | label: intl.formatMessage(messages.enableSystemTray), | ||
114 | value: settings.all.enableSystemTray, | ||
115 | default: DEFAULT_APP_SETTINGS.enableSystemTray, | ||
105 | }, | 116 | }, |
106 | minimizeToSystemTray: { | 117 | minimizeToSystemTray: { |
107 | label: intl.formatMessage(messages.minimizeToSystemTray), | 118 | label: intl.formatMessage(messages.minimizeToSystemTray), |
108 | value: settings.all.minimizeToSystemTray, | 119 | value: settings.all.minimizeToSystemTray, |
109 | default: false, | 120 | default: DEFAULT_APP_SETTINGS.minimizeToSystemTray, |
110 | }, | 121 | }, |
111 | locale: { | 122 | locale: { |
112 | label: intl.formatMessage(messages.language), | 123 | label: intl.formatMessage(messages.language), |
113 | value: app.locale, | 124 | value: app.locale, |
114 | options, | 125 | options, |
115 | default: 'en-US', | 126 | default: DEFAULT_APP_SETTINGS.locale, |
116 | }, | 127 | }, |
117 | beta: { | 128 | beta: { |
118 | label: intl.formatMessage(messages.beta), | 129 | label: intl.formatMessage(messages.beta), |
119 | value: user.data.beta, | 130 | value: user.data.beta, |
120 | default: false, | 131 | default: DEFAULT_APP_SETTINGS.beta, |
121 | }, | 132 | }, |
122 | }, | 133 | }, |
123 | }; | 134 | }; |
diff --git a/src/electron/Settings.js b/src/electron/Settings.js index 049a08296..824b4c20c 100644 --- a/src/electron/Settings.js +++ b/src/electron/Settings.js | |||
@@ -1,5 +1,17 @@ | |||
1 | import { observable } from 'mobx'; | ||
2 | |||
3 | import { DEFAULT_APP_SETTINGS } from '../config'; | ||
4 | |||
1 | export default class Settings { | 5 | export default class Settings { |
2 | store = {}; | 6 | @observable store = { |
7 | autoLaunchOnStart: DEFAULT_APP_SETTINGS.autoLaunchOnStart, | ||
8 | autoLaunchInBackground: DEFAULT_APP_SETTINGS.autoLaunchInBackground, | ||
9 | runInBackground: DEFAULT_APP_SETTINGS.runInBackground, | ||
10 | enableSystemTray: DEFAULT_APP_SETTINGS.enableSystemTray, | ||
11 | minimizeToSystemTray: DEFAULT_APP_SETTINGS.minimizeToSystemTray, | ||
12 | locale: DEFAULT_APP_SETTINGS.locale, | ||
13 | beta: DEFAULT_APP_SETTINGS.beta, | ||
14 | }; | ||
3 | 15 | ||
4 | set(settings) { | 16 | set(settings) { |
5 | this.store = Object.assign(this.store, settings); | 17 | this.store = Object.assign(this.store, settings); |
diff --git a/src/electron/ipc-api/appIndicator.js b/src/electron/ipc-api/appIndicator.js index 576234d25..d31819068 100644 --- a/src/electron/ipc-api/appIndicator.js +++ b/src/electron/ipc-api/appIndicator.js | |||
@@ -1,12 +1,11 @@ | |||
1 | import { app, ipcMain, Tray, Menu } from 'electron'; | 1 | import { app, ipcMain } from 'electron'; |
2 | import path from 'path'; | 2 | import path from 'path'; |
3 | import { autorun } from 'mobx'; | ||
3 | 4 | ||
4 | const INDICATOR_TRAY_PLAIN = 'tray'; | ||
5 | const INDICATOR_TRAY_UNREAD = 'tray-unread'; | ||
6 | const INDICATOR_TASKBAR = 'taskbar'; | 5 | const INDICATOR_TASKBAR = 'taskbar'; |
7 | |||
8 | const FILE_EXTENSION = process.platform === 'win32' ? 'ico' : 'png'; | 6 | const FILE_EXTENSION = process.platform === 'win32' ? 'ico' : 'png'; |
9 | let trayIcon; | 7 | |
8 | let isTrayIconEnabled; | ||
10 | 9 | ||
11 | function getAsset(type, asset) { | 10 | function getAsset(type, asset) { |
12 | return path.join( | 11 | return path.join( |
@@ -15,26 +14,14 @@ function getAsset(type, asset) { | |||
15 | } | 14 | } |
16 | 15 | ||
17 | export default (params) => { | 16 | export default (params) => { |
18 | trayIcon = new Tray(getAsset('tray', INDICATOR_TRAY_PLAIN)); | 17 | autorun(() => { |
19 | const trayMenuTemplate = [ | 18 | isTrayIconEnabled = params.settings.get('enableSystemTray'); |
20 | { | ||
21 | label: 'Show Franz', | ||
22 | click() { | ||
23 | params.mainWindow.show(); | ||
24 | }, | ||
25 | }, { | ||
26 | label: 'Quit Franz', | ||
27 | click() { | ||
28 | app.quit(); | ||
29 | }, | ||
30 | }, | ||
31 | ]; | ||
32 | |||
33 | const trayMenu = Menu.buildFromTemplate(trayMenuTemplate); | ||
34 | trayIcon.setContextMenu(trayMenu); | ||
35 | 19 | ||
36 | trayIcon.on('click', () => { | 20 | if (!isTrayIconEnabled) { |
37 | params.mainWindow.show(); | 21 | params.trayIcon.hide(); |
22 | } else if (isTrayIconEnabled) { | ||
23 | params.trayIcon.show(); | ||
24 | } | ||
38 | }); | 25 | }); |
39 | 26 | ||
40 | ipcMain.on('updateAppIndicator', (event, args) => { | 27 | ipcMain.on('updateAppIndicator', (event, args) => { |
@@ -68,13 +55,7 @@ export default (params) => { | |||
68 | } | 55 | } |
69 | } | 56 | } |
70 | 57 | ||
71 | // Update system tray | 58 | // Update Tray |
72 | trayIcon.setImage(getAsset('tray', args.indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN)); | 59 | params.trayIcon.setIndicator(args.indicator); |
73 | |||
74 | if (process.platform === 'darwin') { | ||
75 | trayIcon.setPressedImage( | ||
76 | getAsset('tray', `${args.indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN}-active`), | ||
77 | ); | ||
78 | } | ||
79 | }); | 60 | }); |
80 | }; | 61 | }; |
diff --git a/src/electron/ipc-api/settings.js b/src/electron/ipc-api/settings.js index 1d7eafa6c..995b28fbd 100644 --- a/src/electron/ipc-api/settings.js +++ b/src/electron/ipc-api/settings.js | |||
@@ -1,10 +1,7 @@ | |||
1 | import { ipcMain } from 'electron'; | 1 | import { ipcMain } from 'electron'; |
2 | 2 | ||
3 | export default (params) => { | 3 | export default (params) => { |
4 | if (process.platform === 'darwin' || process.platform === 'win32') { | 4 | ipcMain.on('settings', (event, args) => { |
5 | // eslint-disable-next-line | 5 | params.settings.set(args); |
6 | ipcMain.on('settings', (event, args) => { | 6 | }); |
7 | params.settings.set(args); | ||
8 | }); | ||
9 | } | ||
10 | }; | 7 | }; |
diff --git a/src/electron/ipc-api/tray.js b/src/electron/ipc-api/tray.js deleted file mode 100644 index 43364c0ed..000000000 --- a/src/electron/ipc-api/tray.js +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | import { Tray, Menu, ipcMain } from 'electron'; | ||
2 | import path from 'path'; | ||
3 | |||
4 | const INDICATOR_PLAIN = 'franz-taskbar'; | ||
5 | const INDICATOR_UNREAD = 'franz-taskbar-unread'; | ||
6 | |||
7 | const FILE_EXTENSION = process.platform === 'win32' ? 'ico' : 'png'; | ||
8 | |||
9 | let trayIcon; | ||
10 | |||
11 | function getAsset(asset) { | ||
12 | return path.join( | ||
13 | __dirname, '..', '..', 'assets', 'images', 'tray', process.platform, `${asset}.${FILE_EXTENSION}`, | ||
14 | ); | ||
15 | } | ||
16 | |||
17 | export default (params) => { | ||
18 | // if (process.platform === 'win32' || process.platform === 'linux') { | ||
19 | trayIcon = new Tray(getAsset(INDICATOR_PLAIN)); | ||
20 | const trayMenuTemplate = [ | ||
21 | { | ||
22 | label: 'Show Franz', | ||
23 | click() { | ||
24 | params.mainWindow.show(); | ||
25 | }, | ||
26 | }, { | ||
27 | label: 'Quit Franz', | ||
28 | click() { | ||
29 | params.app.quit(); | ||
30 | }, | ||
31 | }, | ||
32 | ]; | ||
33 | |||
34 | const trayMenu = Menu.buildFromTemplate(trayMenuTemplate); | ||
35 | trayIcon.setContextMenu(trayMenu); | ||
36 | |||
37 | trayIcon.on('click', () => { | ||
38 | params.mainWindow.show(); | ||
39 | }); | ||
40 | |||
41 | ipcMain.on('updateTrayIconIndicator', (event, args) => { | ||
42 | trayIcon.setImage(getAsset(args.count !== 0 ? INDICATOR_UNREAD : INDICATOR_PLAIN)); | ||
43 | |||
44 | if (process.platform === 'darwin') { | ||
45 | trayIcon.setPressedImage(getAsset(`${args.count !== 0 ? INDICATOR_UNREAD : INDICATOR_PLAIN}-active`)); | ||
46 | } | ||
47 | }); | ||
48 | }; | ||
diff --git a/src/i18n/languages.js b/src/i18n/languages.js index 9b9fa9dfd..342815bc2 100644 --- a/src/i18n/languages.js +++ b/src/i18n/languages.js | |||
@@ -2,4 +2,6 @@ module.exports = { | |||
2 | 'en-US': 'English', | 2 | 'en-US': 'English', |
3 | 'fr': 'French', | 3 | 'fr': 'French', |
4 | // 'de-DE': 'Deutsch', | 4 | // 'de-DE': 'Deutsch', |
5 | 'pl-PL': 'Polish', | ||
6 | 'ru-RU': 'Русский', | ||
5 | }; | 7 | }; |
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index 194b8047c..b9ed51b83 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json | |||
@@ -126,6 +126,7 @@ | |||
126 | "settings.app.updateStatusUpToDate": "You are using the latest version of Franz", | 126 | "settings.app.updateStatusUpToDate": "You are using the latest version of Franz", |
127 | "settings.app.form.autoLaunchOnStart": "Launch Franz on start", | 127 | "settings.app.form.autoLaunchOnStart": "Launch Franz on start", |
128 | "settings.app.form.autoLaunchInBackground": "Open in background", | 128 | "settings.app.form.autoLaunchInBackground": "Open in background", |
129 | "settings.app.form.enableSystemTray": "Show Franz in system tray", | ||
129 | "settings.app.form.minimizeToSystemTray": "Minimize Franz to system tray", | 130 | "settings.app.form.minimizeToSystemTray": "Minimize Franz to system tray", |
130 | "settings.app.form.runInBackground": "Keep Franz in background when closing the window", | 131 | "settings.app.form.runInBackground": "Keep Franz in background when closing the window", |
131 | "settings.app.form.language": "Language", | 132 | "settings.app.form.language": "Language", |
diff --git a/src/i18n/locales/pl-PL.json b/src/i18n/locales/pl-PL.json new file mode 100644 index 000000000..1a8e9ad54 --- /dev/null +++ b/src/i18n/locales/pl-PL.json | |||
@@ -0,0 +1,167 @@ | |||
1 | { | ||
2 | "global.api.unhealthy": "Nie można połączyć się z usługą Franz", | ||
3 | "global.notConnectedToTheInternet": "Brak połączenia z Internetem.", | ||
4 | "welcome.signupButton": "Stwórz darmowe konto", | ||
5 | "welcome.loginButton": "Zaloguj się na swoje konto", | ||
6 | "welcome.slogan": "Komunikator który działa", | ||
7 | "login.headline": "Zaloguj się", | ||
8 | "login.email.label": "Adres email", | ||
9 | "login.password.label": "Hasło", | ||
10 | "login.submit.label": "Zaloguj się", | ||
11 | "login.invalidCredentials": "Adres email lub hasło są błędne", | ||
12 | "login.tokenExpired": "Twoja sesja wygasła, zaloguj się ponownie.", | ||
13 | "login.serverLogout": "Twoja sesja wygasła, zaloguj się ponownie.", | ||
14 | "login.link.signup": "Stwórz darmowe konto", | ||
15 | "login.link.password": "Zresetuj hasło", | ||
16 | "password.headline": "Zresetuj hasło", | ||
17 | "password.email.label": "Adres email", | ||
18 | "password.submit.label": "Wyślij", | ||
19 | "password.noUser": "Nie znaleziono użytkownika z takim adresem email", | ||
20 | "password.successInfo": "Sprawdź swoją skrzynkę email", | ||
21 | "password.link.signup": "Stwórz darmowe konto", | ||
22 | "password.link.login": "Zaloguj się na swoje konto", | ||
23 | "signup.headline": "Zarejestruj się", | ||
24 | "signup.firstname.label": "Imię", | ||
25 | "signup.lastname.label": "Nazwisko", | ||
26 | "signup.email.label": "Adres email", | ||
27 | "signup.company.label": "Firma", | ||
28 | "signup.password.label": "Hasło", | ||
29 | "signup.submit.label": "Stwórz konto", | ||
30 | "signup.link.login": "Masz już konto, zalogować się?", | ||
31 | "signup.emailDuplicate": "Użytkownik z takim adresem email już istnieje", | ||
32 | "signup.legal.info": "Poprzez utworzenie konta Franz akceptujesz", | ||
33 | "signup.legal.terms": "Warunki świadczenia usług", | ||
34 | "signup.legal.privacy": "Polityka prywatności", | ||
35 | "pricing.headline": "Wspomóż aplikację Franz", | ||
36 | "pricing.support.label": "Wybierz plan wsparcia", | ||
37 | "pricing.submit.label": "Chcę wspierać rozwój aplikacji Franz", | ||
38 | "pricing.link.skipPayment": "Nie chcę wspierać rozwoju aplikacji Franz.", | ||
39 | "import.headline": "Zaimportuj usługi Franz 4", | ||
40 | "import.notSupportedHeadline": "Usługi nie są jeszcze wspierane w Franz 5", | ||
41 | "import.submit.label": "Zaimportuj usługi", | ||
42 | "import.skip.label": "Chcę dodać usługi ręcznie", | ||
43 | "invite.submit.label": "Wyślij zaproszenia", | ||
44 | "invite.headline.friends": "Zaproś 3 znajomych lub kolegów z pracy", | ||
45 | "invite.name.label": "Nazwa", | ||
46 | "invite.email.label": "Adres email", | ||
47 | "invite.skip.label": "Chcę to zrobić później", | ||
48 | "subscription.submit.label": "Chcę wspierać rozwój aplikacji Franz", | ||
49 | "subscription.paymentSessionError": "Nie można wczytać formularza płatności", | ||
50 | "subscription.includedFeatures": "Płatne konto Franz Premium obejmuje", | ||
51 | "subscription.features.onpremise": "Dodawanie lokalnych/hostowanych usług takich jak HipChat", | ||
52 | "subscription.features.customServices": "Prywatne usługi dla Ciebie i Twojego zespołu", | ||
53 | "subscription.features.encryptedSync": "Szyfrowana synchronizacja sesji", | ||
54 | "subscription.features.vpn": "Wsprarcie Proxy i VPN", | ||
55 | "subscription.features.ads": "Brak reklam, na zawsze!", | ||
56 | "subscription.features.comingSoon": "wkrótce dostępne", | ||
57 | "infobar.servicesUpdated": "Twoje usługi zostały zaaktualizowane.", | ||
58 | "infobar.updateAvailable": "Aktualizacja aplikacji Franz jest dostępna.", | ||
59 | "infobar.buttonReloadServices": "Przeładuj usługi", | ||
60 | "infobar.buttonInstallUpdate": "Uruchom ponownie i zainstaluj aktualizacje", | ||
61 | "infobar.requiredRequestsFailed": "Nie można wczytać usług i informacji o użytkowniku", | ||
62 | "sidebar.settings": "Ustawienia", | ||
63 | "services.welcome": "Witaj w aplikcji Franz", | ||
64 | "services.getStarted": "Zacznij", | ||
65 | "settings.account.headline": "Konto", | ||
66 | "settings.account.headlineSubscription": "Twoja subskrypcja", | ||
67 | "settings.account.headlineUpgrade": "Ulepsz swoje konto i wspieraj aplikację Franz", | ||
68 | "settings.account.headlineInvoices": "Faktury", | ||
69 | "settings.account.manageSubscription.label": "Zarządzaj swoimi subskrypcjami", | ||
70 | "settings.account.accountType.basic": "Podstawowe konto", | ||
71 | "settings.account.accountType.premium": "Konto Premium", | ||
72 | "settings.account.account.editButton": "Edytuj konto", | ||
73 | "settings.account.invoiceDownload": "Pobieranie", | ||
74 | "settings.account.userInfoRequestFailed": "Nie można wczytać informacji o użytkowniku", | ||
75 | "settings.account.tryReloadUserInfoRequest": "Spróbuj ponownie", | ||
76 | "settings.account.headlineProfile": "Aktualizuj profil", | ||
77 | "settings.account.headlineAccount": "Informacje o koncie", | ||
78 | "settings.account.headlinePassword": "Zmiana hasła", | ||
79 | "settings.account.successInfo": "Zmiany zostały zapisane", | ||
80 | "settings.account.buttonSave": "Aktualizuj profil", | ||
81 | "settings.account.mining.thankyou": "Dziękuję za wsparcie aplikacji Franz mocą obliczeniową.", | ||
82 | "settings.account.mining.active": "Obecnie wykonujesz {hashes} operacji na sekundę.", | ||
83 | "settings.account.mining.moreInformation": "Dowiedz się więcej", | ||
84 | "settings.account.mining.cancel": "Anuluj kopanie", | ||
85 | "settings.navigation.availableServices": "Dostępne usługi", | ||
86 | "settings.navigation.yourServices": "Twoje usługi", | ||
87 | "settings.navigation.account": "Konto", | ||
88 | "settings.navigation.settings": "Ustawienia", | ||
89 | "settings.navigation.logout": "Wylogowanie", | ||
90 | "settings.recipes.headline": "Dostępne usługi", | ||
91 | "settings.recipes.mostPopular": "Najpopularniejsze", | ||
92 | "settings.recipes.all": "Wszystkie usługi", | ||
93 | "settings.recipes.dev": "Rozwojowe", | ||
94 | "settings.recipes.nothingFound": "Żadna usługa nie została znaleziona.", | ||
95 | "settings.recipes.servicesSuccessfulAddedInfo": "Usługa została dodana pomyślnie", | ||
96 | "settings.service.form.saveButton": "Zapisz usługę", | ||
97 | "settings.service.form.deleteButton": "Usuń usługę", | ||
98 | "settings.service.form.availableServices": "Dostępne usługi", | ||
99 | "settings.service.form.yourServices": "Twoje usługi", | ||
100 | "settings.service.form.addServiceHeadline": "Dodaj {name}", | ||
101 | "settings.service.form.editServiceHeadline": "Edytuj {name}", | ||
102 | "settings.service.form.tabHosted": "Hostowane", | ||
103 | "settings.service.form.tabOnPremise": "Hostowane lokalnie ⭐️", | ||
104 | "settings.service.form.customUrlValidationError": "Nie można zweryfikować spersonalizowanego {name} serwera.", | ||
105 | "settings.service.form.customUrlPremiumInfo": "Aby dodać usługi hostowane lokalnie, musisz posiadać konto Premium.", | ||
106 | "settings.service.form.customUrlUpgradeAccount": "Ulepsz swoje konto", | ||
107 | "settings.service.form.indirectMessageInfo": "Będziesz informowany o wszystkich nowych wiadomościach na kanale, nie tylko @username, @channel, @here, ...", | ||
108 | "settings.service.error.headline": "Błąd", | ||
109 | "settings.service.error.goBack": "Wróć do usług", | ||
110 | "settings.service.error.message": "Nie można wczytać przepisu usługi.", | ||
111 | "settings.services.tooltip.isDisabled": "Usługa jest nieaktywna", | ||
112 | "settings.services.tooltip.notificationsDisabled": "Powiadomienia są nieaktywne", | ||
113 | "settings.services.headline": "Twoje usługi", | ||
114 | "settings.services.noServicesAdded": "Nie dodałeś jeszcze żadnych usług.", | ||
115 | "settings.services.discoverServices": "Przeglądaj usługi", | ||
116 | "settings.services.updatedInfo": "Zmiany zostały zapisane", | ||
117 | "settings.services.deletedInfo": "Usługa została usunięta", | ||
118 | "settings.app.headline": "Ustawienia", | ||
119 | "settings.app.headlineGeneral": "Ogólne", | ||
120 | "settings.app.headlineLanguage": "Język", | ||
121 | "settings.app.headlineUpdates": "Aktualizacje", | ||
122 | "settings.app.buttonSearchForUpdate": "Sprawdź czy są dostęne aktualizacje", | ||
123 | "settings.app.buttonInstallUpdate": "Uruchom ponownie i zainstaluj aktualizacje", | ||
124 | "settings.app.updateStatusSearching": "Szukam aktualizacji", | ||
125 | "settings.app.updateStatusAvailable": "Dostępna aktualizacja, pobieram...", | ||
126 | "settings.app.updateStatusUpToDate": "Używasz najnowszej wersji aplikacji Franz", | ||
127 | "settings.app.form.autoLaunchOnStart": "Uruchom aplikację Franz przy starcie systemu", | ||
128 | "settings.app.form.autoLaunchInBackground": "Uruchom w tle", | ||
129 | "settings.app.form.minimizeToSystemTray": "Zminimalizuj aplikację Franz", | ||
130 | "settings.app.form.runInBackground": "Zachowaj aplikację Franz w tle po zamknięciu okna", | ||
131 | "settings.app.form.language": "Język", | ||
132 | "settings.app.form.beta": "Uwzględniaj wersje beta", | ||
133 | "settings.app.currentVersion": "Obecna wersja:", | ||
134 | "settings.service.form.name": "Nazwa", | ||
135 | "settings.service.form.enableService": "Aktywuj usługę", | ||
136 | "settings.service.form.enableNotification": "Aktywuj powiadomienia", | ||
137 | "settings.service.form.team": "Zespół", | ||
138 | "settings.service.form.customUrl": "Spersonalizowany serwer", | ||
139 | "settings.service.form.indirectMessages": "Pokaż ikonę wiadomości dla wszystkich nowych wiadomości", | ||
140 | "settings.user.form.firstname": "Imię", | ||
141 | "settings.user.form.lastname": "Nazwisko", | ||
142 | "settings.user.form.email": "Adres email", | ||
143 | "settings.user.form.currentPassword": "Obecne hasło", | ||
144 | "settings.user.form.newPassword": "Nowe hasło", | ||
145 | "settings.user.form.accountType.label": "Typ konta", | ||
146 | "settings.user.form.accountType.individual": "Prywatne", | ||
147 | "settings.user.form.accountType.non-profit": "Non-Profit", | ||
148 | "settings.user.form.accountType.company": "Firma", | ||
149 | "subscription.type.free": "za darmo", | ||
150 | "subscription.type.month": "miesiąc", | ||
151 | "subscription.type.year": "rok", | ||
152 | "subscription.type.mining": "Wspieraj aplikację Franz mocą obliczeniową", | ||
153 | "subscription.mining.headline": "Jak to działa?", | ||
154 | "subscription.mining.experimental": "eksperymentalne", | ||
155 | "subscription.mining.line1": "Włączając \"wspieraj mocą obliczeniową\", aplikacja Franz będzie używać około 20-50% mocy Twojego procesora aby kopać kryptowalutę Monero co jest równe około $5/rok.", | ||
156 | "subscription.mining.line2": "Będziemy dostosowywać zużycie procesora do stylu Twojej pracy tak aby nie zużywać baterii i nie spowalniać działania urządzenia.", | ||
157 | "subscription.mining.line3": "Tak długo jak kopanie będzie aktywne, będziesz mieć nielimitowany dostęp do wszystkich funkcji dostępnych w koncie Premium.", | ||
158 | "subscription.mining.moreInformation": "Dowiedz się więcej o tym planie.", | ||
159 | "subscriptionPopup.buttonCancel": "Anuluj", | ||
160 | "subscriptionPopup.buttonDone": "Zrobione", | ||
161 | "tabs.item.reload": "Przeładuj", | ||
162 | "tabs.item.edit": "Edytuj", | ||
163 | "tabs.item.disableNotifications": "Wyłącz powiadomienia", | ||
164 | "tabs.item.enableNotification": "Włącz powiadomienia", | ||
165 | "tabs.item.disableService": "Wyłącz usługę", | ||
166 | "tabs.item.deleteService": "Usuń usługę" | ||
167 | } | ||
diff --git a/src/i18n/locales/ru-RU.json b/src/i18n/locales/ru-RU.json new file mode 100644 index 000000000..44ced9e43 --- /dev/null +++ b/src/i18n/locales/ru-RU.json | |||
@@ -0,0 +1,168 @@ | |||
1 | { | ||
2 | "global.api.unhealthy": "Невозможно подключиться к сервисам Franz", | ||
3 | "global.notConnectedToTheInternet": "Нет Интернет-соединения", | ||
4 | "welcome.signupButton": "Создать аккаунт", | ||
5 | "welcome.loginButton": "Вход", | ||
6 | "welcome.slogan": "Общение, которое просто работает", | ||
7 | "login.headline": "Регистрация", | ||
8 | "login.email.label": "Email адрес", | ||
9 | "login.password.label": "Пароль", | ||
10 | "login.submit.label": "Регистрация", | ||
11 | "login.invalidCredentials": "Неправильный email или пароль", | ||
12 | "login.tokenExpired": "Сессия устарела, пожалуйста, войдите снова.", | ||
13 | "login.serverLogout": "Сессия устарела, пожалуйста, войдите снова.", | ||
14 | "login.link.signup": "Создать бесплатный аккаунт", | ||
15 | "login.link.password": "Восстановить пароль", | ||
16 | "password.headline": "Восстановление пароля", | ||
17 | "password.email.label": "Email адрес", | ||
18 | "password.submit.label": "Отправить", | ||
19 | "password.noUser": "Не найдено пользователя с таким email", | ||
20 | "password.successInfo": "Проверьте Ваш email", | ||
21 | "password.link.signup": "Создать аккаунт", | ||
22 | "password.link.login": "Вход", | ||
23 | "signup.headline": "Регистрация", | ||
24 | "signup.firstname.label": "Имя", | ||
25 | "signup.lastname.label": "Фамилия", | ||
26 | "signup.email.label": "Email адрес", | ||
27 | "signup.company.label": "Организация", | ||
28 | "signup.password.label": "Пароль", | ||
29 | "signup.submit.label": "Создать аккаунт", | ||
30 | "signup.link.login": "Уже есть аккаунт, войти?", | ||
31 | "signup.emailDuplicate": "Пользователь с указанным email уже существует", | ||
32 | "signup.legal.info": "Создавая аккаунт Franz, Вы принимаете", | ||
33 | "signup.legal.terms": "Условия обслуживания", | ||
34 | "signup.legal.privacy": "Политика конфиденциальности", | ||
35 | "pricing.headline": "Поддержать Franz", | ||
36 | "pricing.support.label": "Выберите план поддержки", | ||
37 | "pricing.submit.label": "Я хочу поддержать разработку Franz", | ||
38 | "pricing.link.skipPayment": "Я не хочу поддерживать разработку Franz.", | ||
39 | "import.headline": "Импортировать сервисы Franz 4", | ||
40 | "import.notSupportedHeadline": "Сервисы еще не поддержаны в Franz 5", | ||
41 | "import.submit.label": "Импортировать сервисы", | ||
42 | "import.skip.label": "Я хочу добавить сервисы вручную", | ||
43 | "invite.submit.label": "Выслать приглашения", | ||
44 | "invite.headline.friends": "Пригласите 3х друзей или коллег", | ||
45 | "invite.name.label": "Имя", | ||
46 | "invite.email.label": "Email адрес", | ||
47 | "invite.skip.label": "Я сделаю это позже", | ||
48 | "subscription.submit.label": "Я хочу поддержать разработку Franz", | ||
49 | "subscription.paymentSessionError": "Невозможно загрузить форму оплаты", | ||
50 | "subscription.includedFeatures": "Оплаченный Franz Премиум аккаунт включает", | ||
51 | "subscription.features.onpremise": "Добавить облачные службы или службы со своим хостингом типа HipChat", | ||
52 | "subscription.features.customServices": "Настраиваемые сервисы для Вас и Вашей команды", | ||
53 | "subscription.features.encryptedSync": "Шифрованная синхронизация сессии", | ||
54 | "subscription.features.vpn": "Поддержка прокси и VPN", | ||
55 | "subscription.features.ads": "Без рекламы, навсегда!", | ||
56 | "subscription.features.comingSoon": "следите за обновлениями", | ||
57 | "infobar.servicesUpdated": "Ваши сервисы были обновлены.", | ||
58 | "infobar.updateAvailable": "Доступно обновление Franz.", | ||
59 | "infobar.buttonReloadServices": "Перезагрузить сервисы", | ||
60 | "infobar.buttonInstallUpdate": "Перезапустить и обновить", | ||
61 | "infobar.requiredRequestsFailed": "Невозможно загрузить сервисы и информацию пользователя", | ||
62 | "sidebar.settings": "Настройки", | ||
63 | "services.welcome": "Добро пожаловать во Franz", | ||
64 | "services.getStarted": "Начать работу", | ||
65 | "settings.account.headline": "Аккаунт", | ||
66 | "settings.account.headlineSubscription": "Ваша подписка", | ||
67 | "settings.account.headlineUpgrade": "Улучшить аккаунт и поддержать Franz", | ||
68 | "settings.account.headlineInvoices": "Счета", | ||
69 | "settings.account.manageSubscription.label": "Управление подпиской", | ||
70 | "settings.account.accountType.basic": "Базовый аккаунт", | ||
71 | "settings.account.accountType.premium": "Премиум аккаунт", | ||
72 | "settings.account.account.editButton": "Редактировать аккаунт", | ||
73 | "settings.account.invoiceDownload": "Скачать", | ||
74 | "settings.account.userInfoRequestFailed": "Невозможно загрузить информацию пользователя", | ||
75 | "settings.account.tryReloadUserInfoRequest": "Попробовать снова", | ||
76 | "settings.account.headlineProfile": "Обновить профиль", | ||
77 | "settings.account.headlineAccount": "Информация аккаунта", | ||
78 | "settings.account.headlinePassword": "Сменить пароль", | ||
79 | "settings.account.successInfo": "Изменения сохранены", | ||
80 | "settings.account.buttonSave": "Сохранить изменения", | ||
81 | "settings.account.mining.thankyou": "Спасибо за поддержку Franz Вашими процессорными мощностями.", | ||
82 | "settings.account.mining.active": "Вы выполняете {hashes} вычислений в секунду.", | ||
83 | "settings.account.mining.moreInformation": "Больше информации", | ||
84 | "settings.account.mining.cancel": "Отменить майнинг", | ||
85 | "settings.navigation.availableServices": "Доступные сервисы", | ||
86 | "settings.navigation.yourServices": "Ваши сервисы", | ||
87 | "settings.navigation.account": "Аккаунт", | ||
88 | "settings.navigation.settings": "Настройки", | ||
89 | "settings.navigation.logout": "Выход", | ||
90 | "settings.recipes.headline": "Доступные сервисы", | ||
91 | "settings.recipes.mostPopular": "Популярные", | ||
92 | "settings.recipes.all": "Все сервисы", | ||
93 | "settings.recipes.dev": "Разработка", | ||
94 | "settings.recipes.nothingFound": "Ничего не найдено по Вашему запросу.", | ||
95 | "settings.recipes.servicesSuccessfulAddedInfo": "Сервис успешно добавлен", | ||
96 | "settings.service.form.saveButton": "Сохранить сервис", | ||
97 | "settings.service.form.deleteButton": "Удалить сервис", | ||
98 | "settings.service.form.availableServices": "Доступные сервисы", | ||
99 | "settings.service.form.yourServices": "Ваши сервисы", | ||
100 | "settings.service.form.addServiceHeadline": "Добавление {name}", | ||
101 | "settings.service.form.editServiceHeadline": "Редактирование {name}", | ||
102 | "settings.service.form.tabHosted": "Hosted", | ||
103 | "settings.service.form.tabOnPremise": "Свой хостинг ⭐️", | ||
104 | "settings.service.form.customUrlValidationError": "Невозможно проверить сервер {name}.", | ||
105 | "settings.service.form.customUrlPremiumInfo": "Для добавния сервиса на своем хостинге, необходим аккаунт Franz Premium.", | ||
106 | "settings.service.form.customUrlUpgradeAccount": "Улучшить аккаунт", | ||
107 | "settings.service.form.indirectMessageInfo": "Вы будете получать уведомления для всех сообщений, не только для @username, @channel, @here, ...", | ||
108 | "settings.service.error.headline": "Ошибка", | ||
109 | "settings.service.error.goBack": "Вернуться к сервисам", | ||
110 | "settings.service.error.message": "Невозможно загрузить рецепт сервиса.", | ||
111 | "settings.services.tooltip.isDisabled": "Сервис отключен", | ||
112 | "settings.services.tooltip.notificationsDisabled": "Уведомления отключены", | ||
113 | "settings.services.headline": "Ваши сервисы", | ||
114 | "settings.services.noServicesAdded": "У Вас пока нет сервисов", | ||
115 | "settings.services.discoverServices": "Найти сервисы", | ||
116 | "settings.services.updatedInfo": "Изменения сохранены", | ||
117 | "settings.services.deletedInfo": "Сервис удален", | ||
118 | "settings.app.headline": "Настройки", | ||
119 | "settings.app.headlineGeneral": "Общие", | ||
120 | "settings.app.headlineLanguage": "Язык", | ||
121 | "settings.app.headlineUpdates": "Обновления", | ||
122 | "settings.app.buttonSearchForUpdate": "Проверить обновления", | ||
123 | "settings.app.buttonInstallUpdate": "Перезапустить и обновить", | ||
124 | "settings.app.updateStatusSearching": "Поиск обновлений", | ||
125 | "settings.app.updateStatusAvailable": "Доступно обновление, загрука...", | ||
126 | "settings.app.updateStatusUpToDate": "Вы используете актуальную версию Franz", | ||
127 | "settings.app.form.autoLaunchOnStart": "Запускать Franz при старте", | ||
128 | "settings.app.form.autoLaunchInBackground": "Открывать в фоне", | ||
129 | "settings.app.form.enableSystemTray": "Показывать Franz в трее", | ||
130 | "settings.app.form.minimizeToSystemTray": "Сворачивать Franz в трей", | ||
131 | "settings.app.form.runInBackground": "Оставлять Franz в фоне при закрытии окна", | ||
132 | "settings.app.form.language": "Язык", | ||
133 | "settings.app.form.beta": "Включая бета версии", | ||
134 | "settings.app.currentVersion": "Текущая версия:", | ||
135 | "settings.service.form.name": "Название", | ||
136 | "settings.service.form.enableService": "Включить сервис", | ||
137 | "settings.service.form.enableNotification": "Включить уведомления", | ||
138 | "settings.service.form.team": "Команда", | ||
139 | "settings.service.form.customUrl": "Адрес сервера", | ||
140 | "settings.service.form.indirectMessages": "Показывать значок уведомлений для всех новых сообщений", | ||
141 | "settings.user.form.firstname": "Имя", | ||
142 | "settings.user.form.lastname": "Фамилия", | ||
143 | "settings.user.form.email": "Email", | ||
144 | "settings.user.form.currentPassword": "Текущий пароль", | ||
145 | "settings.user.form.newPassword": "Новый пароль", | ||
146 | "settings.user.form.accountType.label": "Тип аккаунта", | ||
147 | "settings.user.form.accountType.individual": "Индивидуальный", | ||
148 | "settings.user.form.accountType.non-profit": "Некоммерческий", | ||
149 | "settings.user.form.accountType.company": "Компания", | ||
150 | "subscription.type.free": "бесплатно", | ||
151 | "subscription.type.month": "месяц", | ||
152 | "subscription.type.year": "год", | ||
153 | "subscription.type.mining": "Поддерживать Franz, предоставляя процессорную мощность", | ||
154 | "subscription.mining.headline": "Как это работает?", | ||
155 | "subscription.mining.experimental": "экспериментально", | ||
156 | "subscription.mining.line1": "Включая \"Поддерживать Franz, предоставляя процессорную мощность\", Franz будет использовать 20-50% процессорного времени для майнинга криптовалюты Monero в примерном объеме 5$/год.", | ||
157 | "subscription.mining.line2": "Мы будем регулировать использование процессора, чтобы не садить батарею и не мешать Вашей работе", | ||
158 | "subscription.mining.line3": "Пока разрешен майнинг, Вам будут достуны все возможности Franz Premium без ограничений", | ||
159 | "subscription.mining.moreInformation": "Узнать больше об этом плане.", | ||
160 | "subscriptionPopup.buttonCancel": "Отмена", | ||
161 | "subscriptionPopup.buttonDone": "Готово", | ||
162 | "tabs.item.reload": "Перезагрузить", | ||
163 | "tabs.item.edit": "Редактировать", | ||
164 | "tabs.item.disableNotifications": "Отключить уведомления", | ||
165 | "tabs.item.enableNotification": "Включить уведомления", | ||
166 | "tabs.item.disableService": "Отключить сервис", | ||
167 | "tabs.item.deleteService": "Удалить сервис" | ||
168 | } | ||
diff --git a/src/index.js b/src/index.js index 3244c44ad..e7fa7da6d 100644 --- a/src/index.js +++ b/src/index.js | |||
@@ -2,16 +2,18 @@ import { app, BrowserWindow, shell } from 'electron'; | |||
2 | import fs from 'fs-extra'; | 2 | import fs from 'fs-extra'; |
3 | import path from 'path'; | 3 | import path from 'path'; |
4 | 4 | ||
5 | // eslint-disable-next-line | 5 | /* eslint-disable */ |
6 | if (require('electron-squirrel-startup')) app.quit(); | 6 | if (require('electron-squirrel-startup')) app.quit(); |
7 | 7 | ||
8 | import windowStateKeeper from 'electron-window-state'; // eslint-disable-line | 8 | import windowStateKeeper from 'electron-window-state'; |
9 | 9 | ||
10 | import { isDevMode, isWindows } from './environment'; // eslint-disable-line | 10 | import { isDevMode, isWindows } from './environment'; |
11 | import ipcApi from './electron/ipc-api'; // eslint-disable-line | 11 | import ipcApi from './electron/ipc-api'; |
12 | import Settings from './electron/Settings'; // eslint-disable-line | 12 | import Tray from './lib/Tray'; |
13 | import { appId } from './package.json'; // eslint-disable-line | 13 | import Settings from './electron/Settings'; |
14 | import './electron/exception'; // eslint-disable-line | 14 | import { appId } from './package.json'; |
15 | import './electron/exception'; | ||
16 | /* eslint-enable */ | ||
15 | 17 | ||
16 | // Keep a global reference of the window object, if you don't, the window will | 18 | // Keep a global reference of the window object, if you don't, the window will |
17 | // be closed automatically when the JavaScript object is garbage collected. | 19 | // be closed automatically when the JavaScript object is garbage collected. |
@@ -47,8 +49,11 @@ const createWindow = async () => { | |||
47 | autoHideMenuBar: true, | 49 | autoHideMenuBar: true, |
48 | }); | 50 | }); |
49 | 51 | ||
52 | // Initialize System Tray | ||
53 | const trayIcon = new Tray(mainWindow); | ||
54 | |||
50 | // Initialize ipcApi | 55 | // Initialize ipcApi |
51 | ipcApi({ mainWindow, settings }); | 56 | ipcApi({ mainWindow, settings, trayIcon }); |
52 | 57 | ||
53 | // Manage Window State | 58 | // Manage Window State |
54 | mainWindowState.manage(mainWindow); | 59 | mainWindowState.manage(mainWindow); |
@@ -85,6 +90,7 @@ const createWindow = async () => { | |||
85 | 90 | ||
86 | if (settings.get('minimizeToSystemTray')) { | 91 | if (settings.get('minimizeToSystemTray')) { |
87 | mainWindow.setSkipTaskbar(true); | 92 | mainWindow.setSkipTaskbar(true); |
93 | trayIcon.show(); | ||
88 | } | 94 | } |
89 | }); | 95 | }); |
90 | 96 | ||
@@ -102,6 +108,10 @@ const createWindow = async () => { | |||
102 | if (app.wasMaximized) { | 108 | if (app.wasMaximized) { |
103 | mainWindow.maximize(); | 109 | mainWindow.maximize(); |
104 | } | 110 | } |
111 | |||
112 | if (!settings.get('enableSystemTray')) { | ||
113 | trayIcon.hide(); | ||
114 | } | ||
105 | }); | 115 | }); |
106 | 116 | ||
107 | mainWindow.on('show', () => { | 117 | mainWindow.on('show', () => { |
diff --git a/src/lib/Tray.js b/src/lib/Tray.js new file mode 100644 index 000000000..631342b24 --- /dev/null +++ b/src/lib/Tray.js | |||
@@ -0,0 +1,64 @@ | |||
1 | import { app, Tray, Menu } from 'electron'; | ||
2 | import path from 'path'; | ||
3 | |||
4 | const FILE_EXTENSION = process.platform === 'win32' ? 'ico' : 'png'; | ||
5 | const INDICATOR_TRAY_PLAIN = 'tray'; | ||
6 | const INDICATOR_TRAY_UNREAD = 'tray-unread'; | ||
7 | |||
8 | function getAsset(type, asset) { | ||
9 | return path.join( | ||
10 | __dirname, '..', 'assets', 'images', type, process.platform, `${asset}.${FILE_EXTENSION}`, | ||
11 | ); | ||
12 | } | ||
13 | |||
14 | export default class TrayIcon { | ||
15 | mainWindow = null; | ||
16 | trayIcon = null; | ||
17 | |||
18 | constructor(mainWindow) { | ||
19 | this.mainWindow = mainWindow; | ||
20 | } | ||
21 | |||
22 | show() { | ||
23 | this.trayIcon = new Tray(getAsset('tray', INDICATOR_TRAY_PLAIN)); | ||
24 | const trayMenuTemplate = [ | ||
25 | { | ||
26 | label: 'Show Franz', | ||
27 | click() { | ||
28 | this.mainWindow.show(); | ||
29 | }, | ||
30 | }, { | ||
31 | label: 'Quit Franz', | ||
32 | click() { | ||
33 | app.quit(); | ||
34 | }, | ||
35 | }, | ||
36 | ]; | ||
37 | |||
38 | const trayMenu = Menu.buildFromTemplate(trayMenuTemplate); | ||
39 | this.trayIcon.setContextMenu(trayMenu); | ||
40 | |||
41 | this.trayIcon.on('click', () => { | ||
42 | this.mainWindow.show(); | ||
43 | }); | ||
44 | } | ||
45 | |||
46 | hide() { | ||
47 | if (this.trayIcon) { | ||
48 | this.trayIcon.destroy(); | ||
49 | this.trayIcon = null; | ||
50 | } | ||
51 | } | ||
52 | |||
53 | setIndicator(indicator) { | ||
54 | if (!this.trayIcon) return; | ||
55 | |||
56 | this.trayIcon.setImage(getAsset('tray', indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN)); | ||
57 | |||
58 | if (process.platform === 'darwin') { | ||
59 | this.trayIcon.setPressedImage( | ||
60 | getAsset('tray', `${indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN}-active`), | ||
61 | ); | ||
62 | } | ||
63 | } | ||
64 | } | ||
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index a5e0839f2..42ec25204 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js | |||
@@ -125,6 +125,18 @@ export default class AppStore extends Store { | |||
125 | this.actions.service.openDevToolsForActiveService(); | 125 | this.actions.service.openDevToolsForActiveService(); |
126 | }); | 126 | }); |
127 | 127 | ||
128 | // Set active the next service | ||
129 | key( | ||
130 | '⌘+pagedown, ctrl+pagedown, ⌘+shift+tab, ctrl+shift+tab', () => { | ||
131 | this.actions.service.setActiveNext(); | ||
132 | }); | ||
133 | |||
134 | // Set active the prev service | ||
135 | key( | ||
136 | '⌘+pageup, ctrl+pageup, ⌘+tab, ctrl+tab', () => { | ||
137 | this.actions.service.setActivePrev(); | ||
138 | }); | ||
139 | |||
128 | this.locale = this._getDefaultLocale(); | 140 | this.locale = this._getDefaultLocale(); |
129 | 141 | ||
130 | this._healthCheck(); | 142 | this._healthCheck(); |
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 77d2e7da4..19db05494 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js | |||
@@ -24,6 +24,8 @@ export default class ServicesStore extends Store { | |||
24 | 24 | ||
25 | // Register action handlers | 25 | // Register action handlers |
26 | this.actions.service.setActive.listen(this._setActive.bind(this)); | 26 | this.actions.service.setActive.listen(this._setActive.bind(this)); |
27 | this.actions.service.setActiveNext.listen(this._setActiveNext.bind(this)); | ||
28 | this.actions.service.setActivePrev.listen(this._setActivePrev.bind(this)); | ||
27 | this.actions.service.showAddServiceInterface.listen(this._showAddServiceInterface.bind(this)); | 29 | this.actions.service.showAddServiceInterface.listen(this._showAddServiceInterface.bind(this)); |
28 | this.actions.service.createService.listen(this._createService.bind(this)); | 30 | this.actions.service.createService.listen(this._createService.bind(this)); |
29 | this.actions.service.createFromLegacyService.listen(this._createFromLegacyService.bind(this)); | 31 | this.actions.service.createFromLegacyService.listen(this._createFromLegacyService.bind(this)); |
@@ -206,6 +208,24 @@ export default class ServicesStore extends Store { | |||
206 | service.isActive = true; | 208 | service.isActive = true; |
207 | } | 209 | } |
208 | 210 | ||
211 | @action _setActiveNext() { | ||
212 | const nextIndex = this._wrapIndex(this.enabled.findIndex(service => service.isActive), 1, this.enabled.length); | ||
213 | |||
214 | this.all.forEach((s, index) => { | ||
215 | this.all[index].isActive = false; | ||
216 | }); | ||
217 | this.enabled[nextIndex].isActive = true; | ||
218 | } | ||
219 | |||
220 | @action _setActivePrev() { | ||
221 | const prevIndex = this._wrapIndex(this.enabled.findIndex(service => service.isActive), -1, this.enabled.length); | ||
222 | |||
223 | this.all.forEach((s, index) => { | ||
224 | this.all[index].isActive = false; | ||
225 | }); | ||
226 | this.enabled[prevIndex].isActive = true; | ||
227 | } | ||
228 | |||
209 | @action _setUnreadMessageCount({ serviceId, count }) { | 229 | @action _setUnreadMessageCount({ serviceId, count }) { |
210 | const service = this.one(serviceId); | 230 | const service = this.one(serviceId); |
211 | 231 | ||
@@ -500,4 +520,8 @@ export default class ServicesStore extends Store { | |||
500 | _reorderAnalytics = debounce(() => { | 520 | _reorderAnalytics = debounce(() => { |
501 | gaEvent('Service', 'order'); | 521 | gaEvent('Service', 'order'); |
502 | }, 5000); | 522 | }, 5000); |
523 | |||
524 | _wrapIndex(index, delta, size) { | ||
525 | return (((index + delta) % size) + size) % size; | ||
526 | } | ||
503 | } | 527 | } |