From da6799442863b56ae5cabf3ea4afac20c06fb4f8 Mon Sep 17 00:00:00 2001 From: Vlad Arama Date: Thu, 23 Nov 2023 14:29:23 -0500 Subject: [PATCH] implement async fetching of extensions This commit allows the fetching of the verified status to be performed asynchronously during the search to avoid causing a performance hit. The verified (or unverified) icons will pop in asynchronously when the fetching is done. The following has been added: - `verified-filled` icon for verified extensions - `verified` icon for unverified extensions (unfilled verified) - `question` icon for extensions with an unknown verification status (appears before the fetching is completed) A small cleanup has also been performed with the creation of the following functions: - `fetchVerifiedStatus` - `updateExtensions` Signed-off-by: Vlad Arama --- .../src/browser/vsx-extension.tsx | 8 ++- .../src/browser/vsx-extensions-model.ts | 68 ++++++++++++------- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/packages/vsx-registry/src/browser/vsx-extension.tsx b/packages/vsx-registry/src/browser/vsx-extension.tsx index 88ec8017dbb28..8e33019909e93 100644 --- a/packages/vsx-registry/src/browser/vsx-extension.tsx +++ b/packages/vsx-registry/src/browser/vsx-extension.tsx @@ -512,7 +512,13 @@ export class VSXExtensionComponent{description}
- {verified ? : undefined} + {verified === true ? ( + + ) : verified === false ? ( + + ) : ( + + )} {publisher}
{this.renderAction(this.props.host)} diff --git a/packages/vsx-registry/src/browser/vsx-extensions-model.ts b/packages/vsx-registry/src/browser/vsx-extensions-model.ts index dcf7ef87a09d2..10b4ee145652d 100644 --- a/packages/vsx-registry/src/browser/vsx-extensions-model.ts +++ b/packages/vsx-registry/src/browser/vsx-extensions-model.ts @@ -28,7 +28,7 @@ import { PreferenceInspectionScope, PreferenceService } from '@theia/core/lib/br import { WorkspaceService } from '@theia/workspace/lib/browser'; import { RecommendedExtensions } from './recommended-extensions/recommended-extensions-preference-contribution'; import URI from '@theia/core/lib/common/uri'; -import { VSXExtensionRaw, VSXResponseError, VSXSearchOptions } from '@theia/ovsx-client/lib/ovsx-types'; +import { OVSXClient, VSXAllVersions, VSXExtensionRaw, VSXResponseError, VSXSearchEntry, VSXSearchOptions } from '@theia/ovsx-client/lib/ovsx-types'; import { OVSXClientProvider } from '../common/ovsx-client-provider'; import { RequestContext, RequestService } from '@theia/core/shared/@theia/request'; import { OVSXApiFilter } from '@theia/ovsx-client'; @@ -213,11 +213,11 @@ export class VSXExtensionsModel { }); } - protected doUpdateSearchResult(param: VSXSearchOptions, token: CancellationToken): Promise { + protected async doUpdateSearchResult(param: VSXSearchOptions, token: CancellationToken): Promise { return this.doChange(async () => { - const searchResult = new Set(); + const fetchPromisesArray: Promise[] = []; + this._searchResult = new Set(); if (!param.query) { - this._searchResult = searchResult; return; } const client = await this.clientProvider(); @@ -232,30 +232,52 @@ export class VSXExtensionsModel { if (!allVersions) { continue; } - const res = await client.query({ extensionId: id, extensionVersion: allVersions.version, includeAllVersions: true }); - let verified = res.extensions?.[0].verified; - if (!verified) { - if (res.extensions?.[0].publishedBy.loginName === 'open-vsx') { - verified = true; - } - } - if (!this.preferences.get('extensions.onlyShowVerifiedExtensions') || verified) { - this.setExtension(id).update(Object.assign(data, { - publisher: data.namespace, - downloadUrl: data.files.download, - iconUrl: data.files.icon, - readmeUrl: data.files.readme, - licenseUrl: data.files.license, - version: allVersions.version, - verified: verified - })); - searchResult.add(id); + if (this.preferences.get('extensions.onlyShowVerifiedExtensions')) { + const verified = await this.fetchVerifiedStatus(id, client, allVersions); + this.updateExtensions(data, id, allVersions, !!verified); + } else { + this.updateExtensions(data, id, allVersions); + const fetchPromise = this.fetchVerifiedStatus(id, client, allVersions).then(verified => { + let extension = this.getExtension(id); + extension = this.setExtension(id); + extension.update(Object.assign({ + verified: verified + })); + }); + fetchPromisesArray.push(fetchPromise); } } - this._searchResult = searchResult; + Promise.all(fetchPromisesArray).then(async () => this.doChange(async () => { + await this.initialized; + })); }, token); } + protected async fetchVerifiedStatus(id: string, client: OVSXClient, allVersions: VSXAllVersions): Promise { + const res = await client.query({ extensionId: id, extensionVersion: allVersions.version, includeAllVersions: true }); + let verified = res.extensions?.[0].verified; + if (!verified && res.extensions?.[0].publishedBy.loginName === 'open-vsx') { + verified = true; + } + return verified; + } + + protected updateExtensions(data: VSXSearchEntry, id: string, allVersions: VSXAllVersions, verified?: boolean): void { + if (!this.preferences.get('extensions.onlyShowVerifiedExtensions') || verified) { + const extension = this.setExtension(id); + extension.update(Object.assign(data, { + publisher: data.namespace, + downloadUrl: data.files.download, + iconUrl: data.files.icon, + readmeUrl: data.files.readme, + licenseUrl: data.files.license, + version: allVersions.version, + verified: verified + })); + this._searchResult.add(id); + } + } + protected async updateInstalled(): Promise { const prevInstalled = this._installed; return this.doChange(async () => {