From 6e1f8a08b39b9fcc2810356a7e69e65d6e61d13f Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 20 Jan 2025 00:21:38 -0800 Subject: [PATCH] void manual updates --- src/vs/code/electron-main/app.ts | 8 ++- .../electron-main/abstractUpdateService.ts | 25 +++++---- .../void/browser/void.contribution.ts | 3 + .../platform/void/common/voidUpdateService.ts | 55 +++++++++++++++++++ .../electron-main/voidUpdateMainService.ts | 48 ++++++++++++++++ .../contrib/void/browser/void.contribution.ts | 3 + .../contrib/void/browser/voidUpdateActions.ts | 42 ++++++++++++++ 7 files changed, 173 insertions(+), 11 deletions(-) create mode 100644 src/vs/platform/void/common/voidUpdateService.ts create mode 100644 src/vs/platform/void/electron-main/voidUpdateMainService.ts create mode 100644 src/vs/workbench/contrib/void/browser/voidUpdateActions.ts diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 1a027000..f9c50efa 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -124,7 +124,8 @@ import { ExtensionSignatureVerificationService, IExtensionSignatureVerificationS import { LLMMessageChannel } from '../../platform/void/electron-main/llmMessageChannel.js'; import { IMetricsService } from '../../platform/void/common/metricsService.js'; import { MetricsMainService } from '../../platform/void/electron-main/metricsMainService.js'; - +import { VoidMainUpdateService } from '../../platform/void/electron-main/voidUpdateMainService.js'; +import { IVoidUpdateService } from '../../platform/void/common/voidUpdateService.js'; /** * The main VS Code application. There will only ever be one instance, * even if the user starts many instances (e.g. from the command line). @@ -1107,6 +1108,7 @@ export class CodeApplication extends Disposable { // Void main process services (required for services with a channel for comm between browser and electron-main (node)) services.set(IMetricsService, new SyncDescriptor(MetricsMainService, undefined, false)); + services.set(IVoidUpdateService, new SyncDescriptor(VoidMainUpdateService, undefined, false)); // Default Extensions Profile Init services.set(IExtensionsProfileScannerService, new SyncDescriptor(ExtensionsProfileScannerService, undefined, true)); @@ -1245,6 +1247,10 @@ export class CodeApplication extends Disposable { // Void - use loggerChannel as reference const metricsChannel = ProxyChannel.fromService(accessor.get(IMetricsService), disposables); mainProcessElectronServer.registerChannel('void-channel-metrics', metricsChannel); + + const voidUpdatesChannel = ProxyChannel.fromService(accessor.get(IVoidUpdateService), disposables); + mainProcessElectronServer.registerChannel('void-channel-update', voidUpdatesChannel); + const llmMessageChannel = new LLMMessageChannel(accessor.get(IMetricsService)); mainProcessElectronServer.registerChannel('void-channel-llmMessageService', llmMessageChannel); diff --git a/src/vs/platform/update/electron-main/abstractUpdateService.ts b/src/vs/platform/update/electron-main/abstractUpdateService.ts index 90fdc074..92707e34 100644 --- a/src/vs/platform/update/electron-main/abstractUpdateService.ts +++ b/src/vs/platform/update/electron-main/abstractUpdateService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { timeout } from '../../../base/common/async.js'; +// import { timeout } from '../../../base/common/async.js'; import { CancellationToken } from '../../../base/common/cancellation.js'; import { Emitter, Event } from '../../../base/common/event.js'; import { IConfigurationService } from '../../configuration/common/configuration.js'; @@ -75,8 +75,8 @@ export abstract class AbstractUpdateService implements IUpdateService { protected async initialize(): Promise { if (!this.environmentMainService.isBuilt) { console.log('is NOT built, canceling update service') - // this.setState(State.Disabled(DisablementReason.NotBuilt)); - // return; // updates are never enabled when running out of sources + this.setState(State.Disabled(DisablementReason.NotBuilt)); + return; // updates are never enabled when running out of sources } console.log('is built, continuing with update service') @@ -87,17 +87,22 @@ export abstract class AbstractUpdateService implements IUpdateService { return; } - this.setState(State.Idle(this.getUpdateType())); + this.setState(State.Disabled(DisablementReason.ManuallyDisabled)); + + + // Void - temporarily disabled while we figure out how to do this the right way + + // this.setState(State.Idle(this.getUpdateType())); // start checking for updates after 10 seconds - this.scheduleCheckForUpdates(10 * 1000).then(undefined, err => this.logService.error(err)); + // this.scheduleCheckForUpdates(10 * 1000).then(undefined, err => this.logService.error(err)); } - private async scheduleCheckForUpdates(delay = 60 * 60 * 1000): Promise { - await timeout(delay); - await this.checkForUpdates(false); - return await this.scheduleCheckForUpdates(60 * 60 * 1000); - } + // private async scheduleCheckForUpdates(delay = 60 * 60 * 1000): Promise { + // await timeout(delay); + // await this.checkForUpdates(false); + // return await this.scheduleCheckForUpdates(60 * 60 * 1000); + // } async checkForUpdates(explicit: boolean): Promise { this.logService.trace('update#checkForUpdates, state = ', this.state.type); diff --git a/src/vs/platform/void/browser/void.contribution.ts b/src/vs/platform/void/browser/void.contribution.ts index 1b3cddd2..276d6e72 100644 --- a/src/vs/platform/void/browser/void.contribution.ts +++ b/src/vs/platform/void/browser/void.contribution.ts @@ -16,3 +16,6 @@ import '../common/refreshModelService.js' // metrics import '../common/metricsService.js' + +// updates +import '../common/voidUpdateService.js' diff --git a/src/vs/platform/void/common/voidUpdateService.ts b/src/vs/platform/void/common/voidUpdateService.ts new file mode 100644 index 00000000..5ba02fde --- /dev/null +++ b/src/vs/platform/void/common/voidUpdateService.ts @@ -0,0 +1,55 @@ +/*-------------------------------------------------------------------------------------- + * Copyright 2025 Glass Devtools, Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information. + *--------------------------------------------------------------------------------------*/ + +import { createDecorator } from '../../instantiation/common/instantiation.js'; +import { ProxyChannel } from '../../../base/parts/ipc/common/ipc.js'; +import { IMainProcessService } from '../../ipc/common/mainProcessService.js'; +import { InstantiationType, registerSingleton } from '../../instantiation/common/extensions.js'; +import { INotificationService, Severity } from '../../notification/common/notification.js'; + + + +export interface IVoidUpdateService { + readonly _serviceBrand: undefined; + check: () => Promise<{ message: string } | null>; +} + + +export const IVoidUpdateService = createDecorator('VoidUpdateService'); + + +// implemented by calling channel +export class VoidUpdateService implements IVoidUpdateService { + + readonly _serviceBrand: undefined; + private readonly voidUpdateService: IVoidUpdateService; + + constructor( + @IMainProcessService mainProcessService: IMainProcessService, // (only usable on client side) + @INotificationService private readonly notifService: INotificationService, + ) { + // creates an IPC proxy to use metricsMainService.ts + this.voidUpdateService = ProxyChannel.toService(mainProcessService.getChannel('void-channel-update')); + } + + + + // anything transmitted over a channel must be async even if it looks like it doesn't have to be + check: IVoidUpdateService['check'] = async () => { + const res = await this.voidUpdateService.check() + const message = res?.message + + this.notifService.notify({ + severity: Severity.Info, + message: message ?? 'This is a very old version of void, please download the latest version! [Void Editor](https://voideditor.com/download-beta)! ', + }) + + return res + } +} + +registerSingleton(IVoidUpdateService, VoidUpdateService, InstantiationType.Eager); + + diff --git a/src/vs/platform/void/electron-main/voidUpdateMainService.ts b/src/vs/platform/void/electron-main/voidUpdateMainService.ts new file mode 100644 index 00000000..b8ca462e --- /dev/null +++ b/src/vs/platform/void/electron-main/voidUpdateMainService.ts @@ -0,0 +1,48 @@ +/*-------------------------------------------------------------------------------------- + * Copyright 2025 Glass Devtools, Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information. + *--------------------------------------------------------------------------------------*/ + +import { Disposable } from '../../../base/common/lifecycle.js'; +import { IEnvironmentMainService } from '../../environment/electron-main/environmentMainService.js'; + +import { IProductService } from '../../product/common/productService.js'; + +import { IVoidUpdateService } from '../common/voidUpdateService.js'; + + + +export class VoidMainUpdateService extends Disposable implements IVoidUpdateService { + _serviceBrand: undefined; + + constructor( + @IProductService private readonly _productService: IProductService, + @IEnvironmentMainService private readonly _envMainService: IEnvironmentMainService, + ) { + super() + } + + async check() { + const isDevMode = !this._envMainService.isBuilt // found in abstractUpdateService.ts + if (isDevMode) { + console.log('Checking for updates in dev mode') + // return { message: `` } + } + + try { + const res = await fetch(`https://updates.voideditor.dev/api/v0/${this._productService.commit}`) + const resJSON = await res.json() + if (!resJSON) return null + + const { downloadMessage } = resJSON ?? {} + if (!downloadMessage) return null + + const after = downloadMessage + return { message: after } + } + catch (e) { + return null + } + } +} + diff --git a/src/vs/workbench/contrib/void/browser/void.contribution.ts b/src/vs/workbench/contrib/void/browser/void.contribution.ts index 1ab6ebd6..ebb17358 100644 --- a/src/vs/workbench/contrib/void/browser/void.contribution.ts +++ b/src/vs/workbench/contrib/void/browser/void.contribution.ts @@ -26,3 +26,6 @@ import './voidSettingsPane.js' // register css import './media/void.css' + +// update (frontend part, also see platform/) +import './voidUpdateActions.js' diff --git a/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts b/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts new file mode 100644 index 00000000..cd8b9dde --- /dev/null +++ b/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts @@ -0,0 +1,42 @@ +/*-------------------------------------------------------------------------------------- + * Copyright 2025 Glass Devtools, Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information. + *--------------------------------------------------------------------------------------*/ + +import { Disposable } from '../../../../base/common/lifecycle.js'; +import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js'; +import { localize2 } from '../../../../nls.js'; +import { Action2, registerAction2 } from '../../../../platform/actions/common/actions.js'; +import { IVoidUpdateService } from '../../../../platform/void/common/voidUpdateService.js'; +import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js'; + + + +// Action +registerAction2(class extends Action2 { + constructor() { + super({ + f1: true, + id: 'void.voidCheckUpdate', + title: localize2('voidCheckUpdate', 'Void: Check for Updates'), + }); + } + async run(accessor: ServicesAccessor): Promise { + + const voidUpdateService = accessor.get(IVoidUpdateService) + voidUpdateService.check() + + } +}) + +// on mount +class VoidUpdateWorkbenchContribution extends Disposable implements IWorkbenchContribution { + static readonly ID = 'workbench.contrib.void.voidUpdate' + constructor( + @IVoidUpdateService private readonly voidUpdateService: IVoidUpdateService + ) { + super() + setTimeout(() => { this.voidUpdateService.check() }, 5 * 1000) + } +} +registerWorkbenchContribution2(VoidUpdateWorkbenchContribution.ID, VoidUpdateWorkbenchContribution, WorkbenchPhase.BlockRestore);