From a1b8f8f527191fcf1f31ad9f1099e75d8c177a13 Mon Sep 17 00:00:00 2001 From: Muffin Date: Fri, 18 Aug 2023 20:00:40 -0500 Subject: [PATCH] Finish update checker --- src-main/index.js | 2 +- src-main/settings.js | 14 +++ src-main/update-checker.js | 40 +++++-- src-main/windows/update.js | 74 ++++++++++--- src-preload/update.js | 7 ++ src-renderer/desktop-settings/index.html | 4 +- src-renderer/update/update.html | 130 +++++++++++++++++++---- 7 files changed, 224 insertions(+), 47 deletions(-) create mode 100644 src-preload/update.js diff --git a/src-main/index.js b/src-main/index.js index 6de6a210..b4cb30bd 100644 --- a/src-main/index.js +++ b/src-main/index.js @@ -8,7 +8,7 @@ if (!app.requestSingleInstanceLock()) { const openExternal = require('./open-external'); const BaseWindow = require('./windows/base'); const EditorWindow = require('./windows/editor'); -const checkForUpdates = require('./update-checker'); +const {checkForUpdates} = require('./update-checker'); require('./protocols'); require('./context-menu'); require('./shortcuts'); diff --git a/src-main/settings.js b/src-main/settings.js index 22fd960d..c0eeb15a 100644 --- a/src-main/settings.js +++ b/src-main/settings.js @@ -70,6 +70,20 @@ class Settings { this.data.updateChecker = updateChecker; } + get ignoredUpdate () { + return this.data.ignoredUpdate || null; + } + set ignoredUpdate (ignoredUpdate) { + this.data.ignoredUpdate = ignoredUpdate; + } + + get ignoredUpdateUntil () { + return this.data.ignoredUpdateUntil || 0; + } + set ignoredUpdateUntil (ignoredUpdateUntil) { + this.data.ignoredUpdateUntil = ignoredUpdateUntil; + } + get camera () { return this.data.camera || null; } diff --git a/src-main/update-checker.js b/src-main/update-checker.js index 42775e6b..199f5526 100644 --- a/src-main/update-checker.js +++ b/src-main/update-checker.js @@ -24,11 +24,6 @@ const fetchVersionJSON = () => new Promise((resolve, reject) => { }); response.on('end', () => { - data = JSON.stringify({ - latest: '1.99.0-fake-version', - yanked: '1.8.1' - }); - try { resolve(JSON.parse(data)); } catch (e) { @@ -53,14 +48,41 @@ const checkForUpdates = async () => { const latestVersion = json.latest; const yanked = json.yanked; + // Security updates can not be ignored. if (semverSatisfies(currentVersion, yanked)) { - UpdateWindow.updateAvailable(latestVersion, true); + UpdateWindow.updateAvailable(currentVersion, latestVersion, true); + return; + } + + if (settings.updateChecker === 'security') { + // Nothing further to check + return; + } + + const now = Date.now(); + const ignoredUpdate = settings.ignoredUpdate; + const ignoredUpdateUntil = settings.ignoredUpdateUntil * 1000; + if (ignoredUpdate === latestVersion && now < ignoredUpdateUntil) { + // This update was ignored return; } - if (settings.updateChecker === 'stable' && semverLt(currentVersion, latestVersion)) { - UpdateWindow.updateAvailable(latestVersion, false); + if (semverLt(currentVersion, latestVersion)) { + UpdateWindow.updateAvailable(currentVersion, latestVersion, false); } }; -module.exports = checkForUpdates; +/** + * @param {string} version + * @param {Date} until + */ +const ignoreUpdate = async (version, until) => { + settings.ignoredUpdate = version; + settings.ignoredUpdateUntil = Math.floor(until.getTime() / 1000); + await settings.save(); +}; + +module.exports = { + checkForUpdates, + ignoreUpdate +}; diff --git a/src-main/windows/update.js b/src-main/windows/update.js index 71392f04..8ec70dae 100644 --- a/src-main/windows/update.js +++ b/src-main/windows/update.js @@ -1,33 +1,81 @@ const BaseWindow = require('./base'); const {translate} = require('../l10n'); +const {APP_NAME} = require('../brand'); +const openExternal = require('../open-external'); class UpdateWindow extends BaseWindow { - constructor (latestVersion, isSecurity) { + constructor (currentVersion, latestVersion, security) { super(); - this.window.setTitle(translate('update.title')); + this.window.setTitle(`${translate('update.title')} - ${APP_NAME}`); - const params = new URLSearchParams(); - params.set('version', latestVersion); - params.set('security', isSecurity); + const ipc = this.window.webContents.ipc; - this.window.on('ready-to-show', () => { + ipc.on('get-info', (event) => { + event.returnValue = { + currentVersion, + latestVersion, + security + }; + }); + + ipc.handle('download', () => { + this.window.destroy(); + + const params = new URLSearchParams(); + params.set('from', currentVersion); + params.set('to', latestVersion); + openExternal(`https://desktop.turbowarp.org/update_available?${params}`); + }); + + const ignore = (permanently) => { + const SECOND = 1000; + const MINUTE = SECOND * 60; + const HOUR = MINUTE * 60; + + let until; + if (security) { + // Security updates can't be ignored. + until = new Date(0); + } else if (permanently) { + // 3000 ought to be enough years into the future... + until = new Date(3000, 0, 0); + } else { + until = new Date(); + until.setTime(until.getTime() + (HOUR * 6)); + } + + // Imported late due to circular dependency + const {ignoreUpdate} = require('../update-checker'); + ignoreUpdate(latestVersion, until); + }; + + ipc.handle('ignore', (event, permanently) => { + this.window.destroy(); + ignore(permanently); + }); + + this.window.on('close', () => { + ignore(false); + }); + + this.window.webContents.on('did-finish-load', () => { this.show(); - }) + }); - this.window.loadURL(`tw-update://./update.html?${params.toString()}`); + this.window.loadURL('tw-update://./update.html'); } getDimensions () { - return [500, 500]; + return [600, 500]; } - enableWebview () { - return true; + getPreload () { + return 'update'; } - static updateAvailable (latestVersion, isSecurity) { - new UpdateWindow(latestVersion, isSecurity); + static updateAvailable (currentVersion, latestVersion, isSecurity) { + new UpdateWindow(currentVersion, latestVersion, isSecurity); } } diff --git a/src-preload/update.js b/src-preload/update.js new file mode 100644 index 00000000..59394740 --- /dev/null +++ b/src-preload/update.js @@ -0,0 +1,7 @@ +const {contextBridge, ipcRenderer} = require('electron'); + +contextBridge.exposeInMainWorld('UpdatePreload', { + getInfo: () => ipcRenderer.sendSync('get-info'), + download: () => ipcRenderer.invoke('download'), + ignore: (permanently) => ipcRenderer.invoke('ignore', permanently) +}); diff --git a/src-renderer/desktop-settings/index.html b/src-renderer/desktop-settings/index.html index 763f428a..a617e826 100644 --- a/src-renderer/desktop-settings/index.html +++ b/src-renderer/desktop-settings/index.html @@ -49,16 +49,16 @@

Desktop Settings

diff --git a/src-renderer/update/update.html b/src-renderer/update/update.html index 646204a9..b9847a6a 100644 --- a/src-renderer/update/update.html +++ b/src-renderer/update/update.html @@ -13,22 +13,33 @@ main { padding: 20px; box-sizing: border-box; - width: 100%; - min-height: 100vh; + width: 100vw; + height: 100vh; border: 20px solid hsla(0, 100%, 65%, 1); display: flex; flex-direction: column; gap: 0.5rem; } - h1, p { + h1, h2, p { margin: 0; } + ul { + margin: 0.5rem 0; + } .update-log { width: 100%; flex-grow: 1; border: 0; + overflow: auto; + } + .loading, .error, .empty { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; } button { cursor: pointer; @@ -39,54 +50,129 @@ border: 1px solid hsla(0, 0%, 0%, 0.15); font-weight: bold; } - .download-update { + .download-button { color: black; background-color: #24cd11; + } + .ignore-button { + } label { cursor: pointer; } + + .if-security { + display: none; + } + .security .if-security { + display: initial; + } + .security .if-normal { + display: none; + }
-

An update is available!

+ + +

An update is available

+

A security update is available

-

TurboWarp Desktop is now available. Read the changelog below:

+

TurboWarp Desktop v1.2.3 is now available.

+

TurboWarp Desktop v1.2.3 is now available. This release contains security fixes. Updating is highly recommended.

-
+
+

Loading...

+
- - + + -