diff options
author | 2017-10-22 21:40:43 +0200 | |
---|---|---|
committer | 2017-10-22 21:40:43 +0200 | |
commit | a714bb5cc95c5908fbba89f9d91afca4f11aa8b5 (patch) | |
tree | eea6d8e440d7f323163f5fe6f4ea8f06ef3a5748 | |
parent | Added polish translation (diff) | |
parent | feature(Shortcuts): Add tab cycling with ctrl[+shift]+tab or ctrl+[pageup|pag... (diff) | |
download | ferdium-app-a714bb5cc95c5908fbba89f9d91afca4f11aa8b5.tar.gz ferdium-app-a714bb5cc95c5908fbba89f9d91afca4f11aa8b5.tar.zst ferdium-app-a714bb5cc95c5908fbba89f9d91afca4f11aa8b5.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-- | 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/locales/en-US.json | 1 | ||||
-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 |
17 files changed, 198 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/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/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/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 | } |