diff --git a/i18n/translations/de.json b/i18n/translations/de.json index c908051e..3dfe78e8 100644 --- a/i18n/translations/de.json +++ b/i18n/translations/de.json @@ -66,6 +66,7 @@ "updateNewVersionReady": "Neue Version steht bereit!", "updateRestart": "Starten Sie die App zum Anwenden der Aktualisierung neu.", "updateLater": "Später", + "downloadUpdateLater": "Später", "updateRestartAndUpdate": "Neu starten und aktualisieren", "updateUpToDate": "Sie sind auf dem neuesten Stand!", "updateLatest": "Sie benutzen bereits die neueste Version von Grape.", diff --git a/i18n/translations/en.json b/i18n/translations/en.json index 3239c73a..b816ec73 100644 --- a/i18n/translations/en.json +++ b/i18n/translations/en.json @@ -66,6 +66,7 @@ "updateNewVersionReady": "New version is ready!", "updateRestart": "Restart the app to apply the update.", "updateLater": "Later", + "downloadUpdateLater": "Later", "updateRestartAndUpdate": "Restart and update", "updateUpToDate": "You're up to date!", "updateLatest": "You're already using the latest version of Grape.", diff --git a/i18n/translations/pl.json b/i18n/translations/pl.json index 63f9a4a4..20c48b0f 100644 --- a/i18n/translations/pl.json +++ b/i18n/translations/pl.json @@ -66,6 +66,7 @@ "updateNewVersionReady": "Nowa wersja jest gotowa!", "updateRestart": "Zrestartuj aplikację, aby zastosować aktualizację.", "updateLater": "Później", + "downloadUpdateLater": "Później", "updateRestartAndUpdate": "Restart i aktualizacja", "updateUpToDate": "Jesteś na bieżąco!", "updateLatest": "Używasz już najnowszej wersji Grape.", diff --git a/src/app/autoUpdate/available.js b/src/app/autoUpdate/available.js index c85f15b2..3fcc04be 100644 --- a/src/app/autoUpdate/available.js +++ b/src/app/autoUpdate/available.js @@ -3,6 +3,7 @@ import { dialog, shell } from 'electron' import { autoUpdater } from 'electron-updater' import state from '../../state' +import resetUpdateTimer from './resetUpdateTimer' import { isWindowsStore } from '../../constants' const messages = { @@ -18,6 +19,10 @@ const messages = { id: 'updateCancel', defaultMessage: 'Cancel', }, + later: { + id: 'downloadUpdateLater', + defaultMessage: 'Later', + }, update: { id: 'updateUpdateGrape', defaultMessage: 'Update Grape', @@ -29,6 +34,39 @@ export default () => { const { formatMessage } = require('../../i18n') autoUpdater.on('update-available', () => { + if (state.checkingForUpdateAutomatically) { + dialog + .showMessageBox({ + type: 'question', + title: formatMessage(messages.newVersionAvailable), + message: formatMessage(messages.install), + buttons: [ + formatMessage(messages.later), + formatMessage(messages.update), + ], + }) + .then(({ response }) => { + if (response === 0) { + resetUpdateTimer(true) + return + } + + if (response === 1) { + if (isWindowsStore) { + shell.openExternal( + 'ms-windows-store://pdp/?ProductId=9P28KPMR8L2Z', + ) + return + } + + resetUpdateTimer(true) + autoUpdater.downloadUpdate() + } + }) + + return + } + if (state.isInitialUpdateCheck) return dialog diff --git a/src/app/autoUpdate/checkForUpdateAutomatically.js b/src/app/autoUpdate/checkForUpdateAutomatically.js new file mode 100644 index 00000000..bdc680fe --- /dev/null +++ b/src/app/autoUpdate/checkForUpdateAutomatically.js @@ -0,0 +1,14 @@ +import { autoUpdater } from 'electron-updater' + +// eslint-disable-next-line import/no-cycle +import resetUpdateTimer from './resetUpdateTimer' +import state from '../../state' + +export default () => { + state.checkingForUpdateAutomatically = true + autoUpdater.autoDownload = false + autoUpdater.checkForUpdates().then(() => { + state.checkingForUpdateAutomatically = false + if (!state.shouldCheckUpdateLater) resetUpdateTimer() + }) +} diff --git a/src/app/autoUpdate/downloaded.js b/src/app/autoUpdate/downloaded.js index e944b154..f03f7565 100644 --- a/src/app/autoUpdate/downloaded.js +++ b/src/app/autoUpdate/downloaded.js @@ -1,53 +1,12 @@ -// eslint-disable-next-line import/no-extraneous-dependencies -import { Menu, dialog } from 'electron' import { autoUpdater } from 'electron-updater' import state from '../../state' -import quitAndInstall from './quitAndInstall' -import { getMenuTemplate } from '../menu' - -const messages = { - newVersion: { - id: 'updateNewVersionReady', - defaultMessage: 'New version is ready!', - }, - restart: { - id: 'updateRestart', - defaultMessage: 'Restart the app to apply the update.', - }, - later: { - id: 'updateLater', - defaultMessage: 'Later', - }, - restartAndUpdate: { - id: 'updateRestartAndUpdate', - defaultMessage: 'Restart and update', - }, -} +import onUpdateDownloaded from './onUpdateDownloaded' export default () => { - // eslint-disable-next-line global-require - const { formatMessage } = require('../../i18n') - autoUpdater.on('update-downloaded', () => { state.isUpdateDownloaded = true - Menu.setApplicationMenu(Menu.buildFromTemplate(getMenuTemplate())) - - dialog - .showMessageBox({ - type: 'info', - title: formatMessage(messages.newVersion), - message: formatMessage(messages.restart), - buttons: [ - formatMessage(messages.later), - formatMessage(messages.restartAndUpdate), - ], - }) - .then(({ response }) => { - if (response === 1) { - quitAndInstall() - } - }) + onUpdateDownloaded() }) } diff --git a/src/app/autoUpdate/notAvailable.js b/src/app/autoUpdate/notAvailable.js index b160d7d2..a22bbb4e 100644 --- a/src/app/autoUpdate/notAvailable.js +++ b/src/app/autoUpdate/notAvailable.js @@ -24,6 +24,8 @@ export default () => { const { formatMessage } = require('../../i18n') autoUpdater.on('update-not-available', () => { + if (state.checkingForUpdateAutomatically) return + if (!state.isInitialUpdateChecked) { state.isInitialUpdateChecked = true return diff --git a/src/app/autoUpdate/onUpdateDownloaded.js b/src/app/autoUpdate/onUpdateDownloaded.js new file mode 100644 index 00000000..62be934a --- /dev/null +++ b/src/app/autoUpdate/onUpdateDownloaded.js @@ -0,0 +1,47 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { Menu, dialog } from 'electron' + +import quitAndInstall from './quitAndInstall' +import { getMenuTemplate } from '../menu' + +const messages = { + newVersion: { + id: 'updateNewVersionReady', + defaultMessage: 'New version is ready!', + }, + restart: { + id: 'updateRestart', + defaultMessage: 'Restart the app to apply the update.', + }, + later: { + id: 'updateLater', + defaultMessage: 'Later', + }, + restartAndUpdate: { + id: 'updateRestartAndUpdate', + defaultMessage: 'Restart and update', + }, +} + +export default () => { + // eslint-disable-next-line global-require + const { formatMessage } = require('../../i18n') + + Menu.setApplicationMenu(Menu.buildFromTemplate(getMenuTemplate())) + + dialog + .showMessageBox({ + type: 'info', + title: formatMessage(messages.newVersion), + message: formatMessage(messages.restart), + buttons: [ + formatMessage(messages.later), + formatMessage(messages.restartAndUpdate), + ], + }) + .then(({ response }) => { + if (response === 1) { + quitAndInstall() + } + }) +} diff --git a/src/app/autoUpdate/resetUpdateTimer.js b/src/app/autoUpdate/resetUpdateTimer.js new file mode 100644 index 00000000..6a2745ba --- /dev/null +++ b/src/app/autoUpdate/resetUpdateTimer.js @@ -0,0 +1,15 @@ +// eslint-disable-next-line import/no-cycle +import startUpdateTimer from './startUpdateTimer' +import state from '../../state' + +export default checkForUpdateLater => { + state.updateCounter = 0 + state.shouldCheckUpdateLater = false + + if (checkForUpdateLater) { + state.shouldCheckUpdateLater = true + } + + clearInterval(state.updateInterval) + startUpdateTimer() +} diff --git a/src/app/autoUpdate/startUpdateTimer.js b/src/app/autoUpdate/startUpdateTimer.js new file mode 100644 index 00000000..fe81678c --- /dev/null +++ b/src/app/autoUpdate/startUpdateTimer.js @@ -0,0 +1,33 @@ +// eslint-disable-next-line import/no-cycle +import checkForUpdateAutomatically from './checkForUpdateAutomatically' +import onUpdateDownloaded from './onUpdateDownloaded' +import state from '../../state' +import { delays } from '../../constants' + +export default () => { + if (state.isUpdateDownloaded) { + onUpdateDownloaded() + return + } + + state.updateInterval = setInterval(() => { + if (!state.checkingForUpdateAutomatically) { + if (state.shouldCheckUpdateLater) { + if (state.updateCounter === delays.checkLaterDelay) { + checkForUpdateAutomatically() + return + } + + state.updateCounter += 1 + return + } + + if (state.updateCounter === delays.defaultDelay) { + checkForUpdateAutomatically() + return + } + + state.updateCounter += 1 + } + }, 1000) +} diff --git a/src/app/initApp.js b/src/app/initApp.js index 1889993d..e78db4ef 100644 --- a/src/app/initApp.js +++ b/src/app/initApp.js @@ -26,6 +26,7 @@ import state from '../state' import { images, isDevelopment, isMas, isWindowsStore } from '../constants' import { getOsType, getChatUrl } from '../utils' import showMainWindow from './menu/actions/showMainWindow' +import startUpdateTimer from './autoUpdate/startUpdateTimer' const { trayIcon, @@ -47,6 +48,7 @@ const messages = { export default url => { if (getOsType !== 'linux' && !isMas && !isWindowsStore) autoUpdate() global.store = store.get() || env + startUpdateTimer() const { width, height } = screen.getPrimaryDisplay().workAreaSize diff --git a/src/constants/delays.js b/src/constants/delays.js new file mode 100644 index 00000000..8cc76133 --- /dev/null +++ b/src/constants/delays.js @@ -0,0 +1,4 @@ +export default { + defaultDelay: 10800, // 3 hours in seconds + checkLaterDelay: 86400, // 24 hours in seconds +} diff --git a/src/constants/index.js b/src/constants/index.js index 6ebfd8a9..8d6b9d15 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -5,5 +5,15 @@ import isDevelopment from './isDevelopment' import isMas from './isMas' import isMac from './isMac' import isWindowsStore from './isWindowsStore' +import delays from './delays' -export { blobs, images, pages, isDevelopment, isMas, isMac, isWindowsStore } +export { + blobs, + images, + pages, + isDevelopment, + isMas, + isMac, + isWindowsStore, + delays, +} diff --git a/src/i18n/de.js b/src/i18n/de.js index 4929dc5a..fda00c11 100644 --- a/src/i18n/de.js +++ b/src/i18n/de.js @@ -72,6 +72,7 @@ export default { "updateNewVersionReady": "Neue Version steht bereit!", "updateRestart": "Starten Sie die App zum Anwenden der Aktualisierung neu.", "updateLater": "Später", + "downloadUpdateLater": "Später", "updateRestartAndUpdate": "Neu starten und aktualisieren", "updateUpToDate": "Sie sind auf dem neuesten Stand!", "updateLatest": "Sie benutzen bereits die neueste Version von Grape.", diff --git a/src/i18n/en.js b/src/i18n/en.js index 87344e79..c63de1c2 100644 --- a/src/i18n/en.js +++ b/src/i18n/en.js @@ -72,6 +72,7 @@ export default { "updateNewVersionReady": "New version is ready!", "updateRestart": "Restart the app to apply the update.", "updateLater": "Later", + "downloadUpdateLater": "Later", "updateRestartAndUpdate": "Restart and update", "updateUpToDate": "You're up to date!", "updateLatest": "You're already using the latest version of Grape.", diff --git a/src/i18n/pl.js b/src/i18n/pl.js index 03d0cbe6..aa54f08b 100644 --- a/src/i18n/pl.js +++ b/src/i18n/pl.js @@ -72,6 +72,7 @@ export default { "updateNewVersionReady": "Nowa wersja jest gotowa!", "updateRestart": "Zrestartuj aplikację, aby zastosować aktualizację.", "updateLater": "Później", + "downloadUpdateLater": "Później", "updateRestartAndUpdate": "Restart i aktualizacja", "updateUpToDate": "Jesteś na bieżąco!", "updateLatest": "Używasz już najnowszej wersji Grape.", diff --git a/src/state/index.js b/src/state/index.js index 773829a3..0d7cbd38 100644 --- a/src/state/index.js +++ b/src/state/index.js @@ -2,4 +2,8 @@ export default { isChatOpened: false, isUpdateDownloaded: false, isInitialUpdateChecked: false, + checkingForUpdateAutomatically: false, + updateCounter: 0, + shouldCheckUpdateLater: false, + updateInterval: null, }