From f7dad729e4b776ec0ea7171d7e9163045764b060 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Thu, 15 Jan 2026 00:28:07 +0100 Subject: [PATCH] refactor(core): migrate web updater to Vue Signed-off-by: Ferdinand Thiessen --- build/frontend-legacy/webpack.modules.cjs | 1 + core/ajax/update.php | 1 - core/js/update.js | 160 ----------- core/src/update.ts | 20 ++ core/src/views/UpdaterAdmin.vue | 317 ++++++++++++++++++++++ core/src/views/UpdaterAdminCli.vue | 53 ++++ core/templates/update.admin.php | 60 ---- core/templates/update.php | 8 + core/templates/update.use-cli.php | 32 --- lib/base.php | 77 ++++-- 10 files changed, 452 insertions(+), 277 deletions(-) delete mode 100644 core/js/update.js create mode 100644 core/src/update.ts create mode 100644 core/src/views/UpdaterAdmin.vue create mode 100644 core/src/views/UpdaterAdminCli.vue delete mode 100644 core/templates/update.admin.php create mode 100644 core/templates/update.php delete mode 100644 core/templates/update.use-cli.php diff --git a/build/frontend-legacy/webpack.modules.cjs b/build/frontend-legacy/webpack.modules.cjs index 43405d97de0..a68a7a0e2da 100644 --- a/build/frontend-legacy/webpack.modules.cjs +++ b/build/frontend-legacy/webpack.modules.cjs @@ -29,6 +29,7 @@ module.exports = { public: path.join(__dirname, 'core/src', 'public.ts'), public_share_auth: path.join(__dirname, 'core/src', 'public-share-auth.ts'), 'twofactor-request-token': path.join(__dirname, 'core/src', 'twofactor-request-token.ts'), + update: path.join(__dirname, 'core/src', 'update.ts'), }, dashboard: { main: path.join(__dirname, 'apps/dashboard/src', 'main.js'), diff --git a/core/ajax/update.php b/core/ajax/update.php index 22bbdcff3e0..0a882929537 100644 --- a/core/ajax/update.php +++ b/core/ajax/update.php @@ -106,7 +106,6 @@ if (Util::needUpgrade()) { }); $updater->listen('\OC\Updater', 'failure', function ($message) use ($eventSource, $config): void { $eventSource->send('failure', $message); - $eventSource->close(); $config->setSystemValue('maintenance', false); }); $updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use ($eventSource, $l): void { diff --git a/core/js/update.js b/core/js/update.js deleted file mode 100644 index 382ad8414ac..00000000000 --- a/core/js/update.js +++ /dev/null @@ -1,160 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2014 ownCloud Inc. - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -(function() { - OC.Update = { - _started: false, - options: {}, - - /** - * Start the update process. - * - * @param $el progress list element - * @param options - */ - start: function($el, options) { - if (this._started) { - return - } - - this.options = options - let hasWarnings = false - - this.$el = $el - - this._started = true - - const self = this - - $(window).on('beforeunload.inprogress', function() { - return t('core', 'The update is in progress, leaving this page might interrupt the process in some environments.') - }) - - $('#update-progress-title').html(t( - 'core', - 'Update to {version}', - { - version: options.version, - }, - )) - - const updateEventSource = new OC.EventSource(OC.getRootPath() + '/core/ajax/update.php') - updateEventSource.listen('success', function(message) { - self.setMessage(message) - }) - updateEventSource.listen('notice', function(message) { - self.setPermanentMessage(message) - hasWarnings = true - }) - updateEventSource.listen('error', function(message) { - $('#update-progress-message').hide() - $('#update-progress-icon') - .addClass('icon-error-white') - .removeClass('icon-loading-dark') - message = message || t('core', 'An error occurred.') - $(window).off('beforeunload.inprogress') - self.setErrorMessage(message) - message = t('core', 'Please reload the page.') - $('

').append('' + message + '').appendTo($el) - updateEventSource.close() - }) - updateEventSource.listen('failure', function(message) { - $(window).off('beforeunload.inprogress') - $('#update-progress-message').hide() - $('#update-progress-icon') - .addClass('icon-error-white') - .removeClass('icon-loading-dark') - - self.setErrorMessage(message) - const updateUnsuccessful = $('

') - if (message === 'Exception: Updates between multiple major versions and downgrades are unsupported.') { - updateUnsuccessful.append(t('core', 'The update was unsuccessful. For more information check our forum post covering this issue.', { url: 'https://help.nextcloud.com/t/updates-between-multiple-major-versions-are-unsupported/7094' })) - } else if (OC.Update.options.productName === 'Nextcloud') { - updateUnsuccessful.append(t('core', 'The update was unsuccessful. ' - + 'Please report this issue to the ' - + 'Nextcloud community.')) - } - updateUnsuccessful.appendTo($el) - }) - updateEventSource.listen('done', function() { - $(window).off('beforeunload.inprogress') - - $('#update-progress-message').hide() - - $('#update-progress-icon') - .addClass('icon-checkmark-white') - .removeClass('icon-loading-dark') - - if (hasWarnings) { - $el.find('.update-show-detailed').before($('').on('click', function() { - window.location.reload() - })) - } else { - $el.find('.update-show-detailed').before($('

')) - - for (let i = 0; i <= 4; i++) { - self.updateCountdown(i, 4) - } - - setTimeout(function() { - window.location = window.location.href - window.location.reload() - }, 3000) - } - }) - }, - - updateCountdown: function(i, total) { - setTimeout(function() { - $('#redirect-countdown').text(n('core', 'The update was successful. Redirecting you to {productName} in %n second.', 'The update was successful. Redirecting you to {productName} in %n seconds.', i, OC.Update.options)) - }, (total - i) * 1000) - }, - - setMessage: function(message) { - $('#update-progress-message').html(message) - $('#update-progress-detailed') - .append('

' + message + '

') - }, - - setPermanentMessage: function(message) { - $('#update-progress-message').html(message) - $('#update-progress-message-warnings') - .show() - .append($('