From 6ca22eb6a5f9e9bfd6dc3729997dda32d526e9bf Mon Sep 17 00:00:00 2001 From: herteleo Date: Sat, 14 Nov 2020 01:06:52 +0100 Subject: [PATCH] feat: improve update visibility + integrate auto-update for windows users (#11) * feat: integrate app update checker and automatic updates * fix: call remote update checker * feat: integrate auto-updater into ui * fix: correct update-checker-interval * refactor: remove unused interval --- package-lock.json | 101 ++++++++++++++++++++++++++----- package.json | 1 + src/background.js | 3 + src/components/AppButton.vue | 4 ++ src/components/AppIcon.vue | 21 +++++++ src/components/SideBarButton.vue | 14 ++++- src/components/TheSideBar.vue | 19 ++++++ src/components/UpdateChecker.vue | 75 ++++++++++++----------- src/store/index.js | 6 +- src/utils/icons.js | 1 + src/utils/updater.js | 47 ++++++++++++++ 11 files changed, 239 insertions(+), 53 deletions(-) create mode 100644 src/utils/updater.js diff --git a/package-lock.json b/package-lock.json index 7f56cb3..cf51a0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2065,6 +2065,11 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "@types/semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ==" + }, "@vue/babel-helper-vue-jsx-merge-props": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.0.0.tgz", @@ -3579,7 +3584,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -3772,8 +3776,7 @@ "at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" }, "atob": { "version": "2.1.2", @@ -6525,7 +6528,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, "requires": { "ms": "^2.1.1" } @@ -7280,6 +7282,77 @@ "integrity": "sha512-UfxhIvED++qLwWrAq9uYVcqF8FdeV9sU2S7qhiHYFODxzXRrd1GZRl/PjITHsTEejgibcWDraD8TQqoHb1aCBQ==", "dev": true }, + "electron-updater": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-4.3.5.tgz", + "integrity": "sha512-5jjN7ebvfj1cLI0VZMdCnJk6aC4bP+dy7ryBf21vArR0JzpRVk0OZHA2QBD+H5rm6ZSeDYHOY6+8PrMEqJ4wlQ==", + "requires": { + "@types/semver": "^7.3.1", + "builder-util-runtime": "8.7.2", + "fs-extra": "^9.0.1", + "js-yaml": "^3.14.0", + "lazy-val": "^1.0.4", + "lodash.isequal": "^4.5.0", + "semver": "^7.3.2" + }, + "dependencies": { + "builder-util-runtime": { + "version": "8.7.2", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.7.2.tgz", + "integrity": "sha512-xBqv+8bg6cfnzAQK1k3OGpfaHg+QkPgIgpEkXNhouZ0WiUkyZCftuRc2LYzQrLucFywpa14Xbc6+hTbpq83yRA==", + "requires": { + "debug": "^4.1.1", + "sax": "^1.2.4" + } + }, + "fs-extra": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", + "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + } + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + } + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + }, + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==" + } + } + }, "electron-window-state": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/electron-window-state/-/electron-window-state-5.0.3.tgz", @@ -7959,8 +8032,7 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { "version": "1.3.1", @@ -11165,8 +11237,7 @@ "lazy-val": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.4.tgz", - "integrity": "sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q==", - "dev": true + "integrity": "sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q==" }, "lazystream": { "version": "1.0.0", @@ -11343,6 +11414,11 @@ "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=", "dev": true }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", @@ -12067,8 +12143,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multicast-dns": { "version": "6.2.3", @@ -18799,8 +18874,7 @@ "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "schema-utils": { "version": "2.6.6", @@ -19698,8 +19772,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.16.1", diff --git a/package.json b/package.json index dae359e..8b5a0fb 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "date-fns": "^2.15.0", "deepmerge": "^4.2.2", "electron-dl": "^1.14.0", + "electron-updater": "^4.3.5", "electron-window-state": "^5.0.3", "is-url-relative-without-domain": "^2.0.0", "lodash-id": "^0.14.0", diff --git a/src/background.js b/src/background.js index 40c05cf..6acd107 100644 --- a/src/background.js +++ b/src/background.js @@ -2,6 +2,7 @@ import electronDl from 'electron-dl'; import windowStateKeeper from 'electron-window-state'; import * as path from 'path'; import { format as formatUrl } from 'url'; +import checkForUpdates from '@/utils/updater'; import { app, Menu, protocol, BrowserWindow, shell, @@ -76,6 +77,8 @@ function createMainWindow() { protocol: 'file', slashes: true, })); + + checkForUpdates(); } window.on('ready-to-show', () => { diff --git a/src/components/AppButton.vue b/src/components/AppButton.vue index 5273d1c..bb2419d 100644 --- a/src/components/AppButton.vue +++ b/src/components/AppButton.vue @@ -40,6 +40,10 @@ export default { border rounded; } +.button[disabled] { + @apply opacity-75; +} + .primary { @apply text-white bg-gray-600 border-gray-500 shadow; } diff --git a/src/components/AppIcon.vue b/src/components/AppIcon.vue index 00876ca..ec80bb3 100644 --- a/src/components/AppIcon.vue +++ b/src/components/AppIcon.vue @@ -5,6 +5,7 @@ [$style.icon]: true, [$style.inline]: inline, [$style[`size-${size}`]]: true, + [$style.spin]: spin, }" viewBox="0 0 24 24" > @@ -29,6 +30,10 @@ export default { type: Number, default: 4, }, + spin: { + type: Boolean, + default: false, + }, }, computed: { content() { @@ -62,4 +67,20 @@ export default { .size-8 { @apply w-8 h-8; } + +.spin { + animation-name: spin; + animation-duration: 1000ms; + animation-iteration-count: infinite; + animation-timing-function: linear; +} + +@keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/src/components/SideBarButton.vue b/src/components/SideBarButton.vue index 944cae6..aefff53 100644 --- a/src/components/SideBarButton.vue +++ b/src/components/SideBarButton.vue @@ -12,6 +12,10 @@ :face="icon" :size="6" /> +
diff --git a/src/components/TheSideBar.vue b/src/components/TheSideBar.vue index d775a4b..6cdf294 100644 --- a/src/components/TheSideBar.vue +++ b/src/components/TheSideBar.vue @@ -12,9 +12,11 @@ Menu @@ -33,12 +35,25 @@ export default { SideBarButton, TabsNav, }, + data() { + return { + showMenuBadge: false, + }; + }, computed: { displaysTabLabels() { const key = 'navigation.displayTabLabels'; return this.$store.getters['Settings/byKey'](key); }, }, + created() { + remote.app.on('app-update-available', (info) => { + if (this.$route.name !== 'home') { + this.showMenuBadge = true; + } + this.$store.commit('SET_UPDATE_INFO', info); + }); + }, methods: { showMenu() { const settingsMenu = remote.Menu.buildFromTemplate([ @@ -72,6 +87,10 @@ export default { click: () => this.$router.push({ name: 'settings' }), }, { type: 'separator' }, + { + label: 'Check for updates…', + click: () => remote.app.emit('app-update-check'), + }, { role: 'toggledevtools' }, ]); diff --git a/src/components/UpdateChecker.vue b/src/components/UpdateChecker.vue index 7048f29..108f143 100644 --- a/src/components/UpdateChecker.vue +++ b/src/components/UpdateChecker.vue @@ -1,6 +1,6 @@