From 34263031b2e92b0c5ea30e22e2d0147726605e49 Mon Sep 17 00:00:00 2001 From: julieg18 Date: Thu, 2 Nov 2023 17:25:04 -0500 Subject: [PATCH 1/2] Add Setup Studio module --- extension/src/setup/index.ts | 120 +++++-------------------------- extension/src/setup/studio.ts | 129 ++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 103 deletions(-) create mode 100644 extension/src/setup/studio.ts diff --git a/extension/src/setup/index.ts b/extension/src/setup/index.ts index 51cb74b011..142626bfb6 100644 --- a/extension/src/setup/index.ts +++ b/extension/src/setup/index.ts @@ -16,7 +16,7 @@ import { WebviewMessages } from './webview/messages' import { validateTokenInput } from './inputBox' import { findPythonBinForInstall } from './autoInstall' import { run, runWithRecheck, runWorkspace } from './runner' -import { isStudioAccessToken } from './token' +import { Studio } from './studio' import { PYTHON_EXTENSION_ACTION, pickFocusedProjects, @@ -51,13 +51,7 @@ import { createFileSystemWatcher } from '../fileSystem/watcher' import { EventName } from '../telemetry/constants' import { WorkspaceScale } from '../telemetry/collect' import { gitPath } from '../cli/git/constants' -import { - Flag, - ConfigKey, - DOT_DVC, - Args, - SubCommand -} from '../cli/dvc/constants' +import { DOT_DVC, Args, SubCommand } from '../cli/dvc/constants' import { GLOBAL_WEBVIEW_DVCROOT } from '../webview/factory' import { getValidInput } from '../vscode/inputBox' import { Title } from '../vscode/title' @@ -87,6 +81,7 @@ export class Setup private readonly config: Config private readonly status: Status private readonly internalCommands: InternalCommands + private readonly studio: Studio private readonly webviewMessages: WebviewMessages private readonly getHasData: () => boolean | undefined @@ -117,10 +112,6 @@ export class Setup private dotFolderWatcher?: Disposer - private studioAccessToken: string | undefined = undefined - private studioIsConnected = false - private shareLiveToStudio: boolean | undefined = undefined - private focusedSection: SetupSection | undefined = undefined constructor( @@ -160,6 +151,12 @@ export class Setup this.setCommandsAvailability(false) this.setProjectAvailability() + this.studio = new Studio( + internalCommands, + this.studioConnectionChanged, + () => this.getCwd() + ) + this.webviewMessages = this.createWebviewMessageHandler() void this.sendDataToWebview() @@ -311,34 +308,12 @@ export class Setup } } - public async removeStudioAccessToken() { + public removeStudioAccessToken() { if (!this.getCliCompatible()) { return } - if (this.dvcRoots.length !== 1) { - const cwd = getFirstWorkspaceFolder() - if (!cwd) { - return - } - return await this.accessConfig( - cwd, - Flag.GLOBAL, - Flag.UNSET, - ConfigKey.STUDIO_TOKEN - ) - } - - const cwd = this.dvcRoots[0] - - await this.accessConfig(cwd, Flag.LOCAL, Flag.UNSET, ConfigKey.STUDIO_TOKEN) - - return await this.accessConfig( - cwd, - Flag.GLOBAL, - Flag.UNSET, - ConfigKey.STUDIO_TOKEN - ) + return this.studio.removeStudioAccessToken(this.dvcRoots) } public async saveStudioAccessToken() { @@ -357,12 +332,12 @@ export class Setup return } - await this.accessConfig(cwd, Flag.GLOBAL, ConfigKey.STUDIO_TOKEN, token) + await this.studio.saveStudioAccessTokenInConfig(cwd, token) return this.updateStudioAndSend() } public getStudioAccessToken() { - return this.studioAccessToken + return this.studio.getStudioAccessToken() } public sendInitialWebviewData() { @@ -438,14 +413,14 @@ export class Setup isPythonEnvironmentGlobal, isPythonExtensionInstalled: this.config.isPythonExtensionInstalled(), isPythonExtensionUsed, - isStudioConnected: this.studioIsConnected, + isStudioConnected: this.studio.getStudioIsConnected(), needsGitCommit, needsGitInitialized, projectInitialized, pythonBinPath: getBinDisplayText(pythonBinPath), remoteList, sectionCollapsed: collectSectionCollapsed(this.focusedSection), - shareLiveToStudio: !!this.shareLiveToStudio + shareLiveToStudio: !!this.studio.getShareLiveToStudio() }) this.focusedSection = undefined } @@ -454,7 +429,7 @@ export class Setup const webviewMessages = new WebviewMessages( () => this.getWebview(), () => this.initializeGit(), - (offline: boolean) => this.updateStudioOffline(offline), + (offline: boolean) => this.studio.updateStudioOffline(offline), () => this.isPythonExtensionUsed(), () => this.updatePythonEnvironment() ) @@ -707,18 +682,10 @@ export class Setup } private async updateStudioAndSend() { - await this.updateIsStudioConnected() + await this.studio.updateIsStudioConnected() return this.sendDataToWebview() } - private async updateIsStudioConnected() { - await this.setStudioValues() - const storedToken = this.getStudioAccessToken() - const isConnected = isStudioAccessToken(storedToken) - this.studioIsConnected = isConnected - return setContextValue(ContextKey.STUDIO_CONNECTED, isConnected) - } - private watchDvcConfigs() { const createWatcher = (watchedPath: string) => createFileSystemWatcher( @@ -760,51 +727,6 @@ export class Setup ]) } - private async setStudioValues() { - const cwd = this.getCwd() - - const previousStudioAccessToken = this.studioAccessToken - - if (!cwd) { - this.studioAccessToken = undefined - this.shareLiveToStudio = undefined - - if (previousStudioAccessToken) { - this.studioConnectionChanged.fire() - } - return - } - - const [studioAccessToken, shareLiveToStudio] = await Promise.all([ - this.accessConfig(cwd, ConfigKey.STUDIO_TOKEN), - (await this.accessConfig(cwd, ConfigKey.STUDIO_OFFLINE)) !== 'true' - ]) - - this.studioAccessToken = studioAccessToken - this.shareLiveToStudio = shareLiveToStudio - - if (previousStudioAccessToken !== this.studioAccessToken) { - this.studioConnectionChanged.fire() - } - } - - private async updateStudioOffline(shareLive: boolean) { - const offline = !shareLive - - const cwd = this.getCwd() - - if (!cwd) { - return - } - - await this.accessConfig( - cwd, - Flag.GLOBAL, - ConfigKey.STUDIO_OFFLINE, - String(offline) - ) - } - private getCwd() { if (!this.getCliCompatible()) { return @@ -814,14 +736,6 @@ export class Setup : getFirstWorkspaceFolder() } - private accessConfig(cwd: string, ...args: Args) { - return this.internalCommands.executeCommand( - AvailableCommands.CONFIG, - cwd, - ...args - ) - } - private accessRemote(cwd: string, ...args: Args) { return this.internalCommands.executeCommand( AvailableCommands.REMOTE, diff --git a/extension/src/setup/studio.ts b/extension/src/setup/studio.ts new file mode 100644 index 0000000000..ae29947238 --- /dev/null +++ b/extension/src/setup/studio.ts @@ -0,0 +1,129 @@ +import { EventEmitter } from 'vscode' +import { isStudioAccessToken } from './token' +import { AvailableCommands, InternalCommands } from '../commands/internal' +import { getFirstWorkspaceFolder } from '../vscode/workspaceFolders' +import { Args, ConfigKey, Flag } from '../cli/dvc/constants' +import { ContextKey, setContextValue } from '../vscode/context' + +export class Studio { + protected studioConnectionChanged: EventEmitter + private studioAccessToken: string | undefined = undefined + private studioIsConnected = false + private shareLiveToStudio: boolean | undefined = undefined + private readonly getCwd: () => string | undefined + private readonly internalCommands: InternalCommands + + constructor( + internalCommands: InternalCommands, + studioConnectionChanged: EventEmitter, + getCwd: () => string | undefined + ) { + this.internalCommands = internalCommands + this.studioConnectionChanged = studioConnectionChanged + this.getCwd = getCwd + } + + public getStudioAccessToken() { + return this.studioAccessToken + } + + public getStudioIsConnected() { + return this.studioIsConnected + } + + public getShareLiveToStudio() { + return this.shareLiveToStudio + } + + public async removeStudioAccessToken(dvcRoots: string[]) { + if (dvcRoots.length !== 1) { + const cwd = getFirstWorkspaceFolder() + if (!cwd) { + return + } + + return await this.accessConfig( + cwd, + Flag.GLOBAL, + Flag.UNSET, + ConfigKey.STUDIO_TOKEN + ) + } + + const cwd = dvcRoots[0] + + await this.accessConfig(cwd, Flag.LOCAL, Flag.UNSET, ConfigKey.STUDIO_TOKEN) + + return await this.accessConfig( + cwd, + Flag.GLOBAL, + Flag.UNSET, + ConfigKey.STUDIO_TOKEN + ) + } + + public saveStudioAccessTokenInConfig(cwd: string, token: string) { + return this.accessConfig(cwd, Flag.GLOBAL, ConfigKey.STUDIO_TOKEN, token) + } + + public async updateIsStudioConnected() { + await this.setStudioValues() + const storedToken = this.getStudioAccessToken() + const isConnected = isStudioAccessToken(storedToken) + this.studioIsConnected = isConnected + return setContextValue(ContextKey.STUDIO_CONNECTED, isConnected) + } + + public async updateStudioOffline(shareLive: boolean) { + const offline = !shareLive + + const cwd = this.getCwd() + + if (!cwd) { + return + } + + await this.accessConfig( + cwd, + Flag.GLOBAL, + ConfigKey.STUDIO_OFFLINE, + String(offline) + ) + } + + private async setStudioValues() { + const cwd = this.getCwd() + + const previousStudioAccessToken = this.studioAccessToken + + if (!cwd) { + this.studioAccessToken = undefined + this.shareLiveToStudio = undefined + + if (previousStudioAccessToken) { + this.studioConnectionChanged.fire() + } + return + } + + const [studioAccessToken, shareLiveToStudio] = await Promise.all([ + this.accessConfig(cwd, ConfigKey.STUDIO_TOKEN), + (await this.accessConfig(cwd, ConfigKey.STUDIO_OFFLINE)) !== 'true' + ]) + + this.studioAccessToken = studioAccessToken + this.shareLiveToStudio = shareLiveToStudio + + if (previousStudioAccessToken !== this.studioAccessToken) { + this.studioConnectionChanged.fire() + } + } + + private accessConfig(cwd: string, ...args: Args) { + return this.internalCommands.executeCommand( + AvailableCommands.CONFIG, + cwd, + ...args + ) + } +} From c81c90e1667dacabd629b4d851ec33aec9d0c312 Mon Sep 17 00:00:00 2001 From: julieg18 Date: Tue, 7 Nov 2023 08:14:48 -0600 Subject: [PATCH 2/2] Apply review comments --- extension/src/setup/index.ts | 11 ++--------- extension/src/setup/inputBox.ts | 2 +- extension/src/setup/studio.ts | 27 +++++++++++++++++++-------- extension/src/setup/token.ts | 6 ------ 4 files changed, 22 insertions(+), 24 deletions(-) delete mode 100644 extension/src/setup/token.ts diff --git a/extension/src/setup/index.ts b/extension/src/setup/index.ts index 142626bfb6..c2b3ab2534 100644 --- a/extension/src/setup/index.ts +++ b/extension/src/setup/index.ts @@ -98,9 +98,6 @@ export class Setup new EventEmitter() ) - private readonly studioConnectionChanged: EventEmitter = - this.dispose.track(new EventEmitter()) - private readonly onDidChangeWorkspace: Event = this.workspaceChanged.event @@ -146,16 +143,12 @@ export class Setup } this.collectWorkspaceScale = collectWorkspaceScale - this.onDidChangeStudioConnection = this.studioConnectionChanged.event this.setCommandsAvailability(false) this.setProjectAvailability() - this.studio = new Studio( - internalCommands, - this.studioConnectionChanged, - () => this.getCwd() - ) + this.studio = new Studio(internalCommands, () => this.getCwd()) + this.onDidChangeStudioConnection = this.studio.onDidChangeStudioConnection this.webviewMessages = this.createWebviewMessageHandler() diff --git a/extension/src/setup/inputBox.ts b/extension/src/setup/inputBox.ts index c3c12893ca..54dca8dcce 100644 --- a/extension/src/setup/inputBox.ts +++ b/extension/src/setup/inputBox.ts @@ -1,4 +1,4 @@ -import { isStudioAccessToken } from './token' +import { isStudioAccessToken } from './studio' export const validateTokenInput = (input: string | undefined) => { if (!isStudioAccessToken(input)) { diff --git a/extension/src/setup/studio.ts b/extension/src/setup/studio.ts index ae29947238..8e35625cc8 100644 --- a/extension/src/setup/studio.ts +++ b/extension/src/setup/studio.ts @@ -1,26 +1,37 @@ -import { EventEmitter } from 'vscode' -import { isStudioAccessToken } from './token' +import { Event, EventEmitter } from 'vscode' import { AvailableCommands, InternalCommands } from '../commands/internal' import { getFirstWorkspaceFolder } from '../vscode/workspaceFolders' import { Args, ConfigKey, Flag } from '../cli/dvc/constants' import { ContextKey, setContextValue } from '../vscode/context' +import { Disposable } from '../class/dispose' -export class Studio { - protected studioConnectionChanged: EventEmitter +export const isStudioAccessToken = (text?: string): boolean => { + if (!text) { + return false + } + return text.startsWith('isat_') && text.length >= 53 +} + +export class Studio extends Disposable { + public readonly onDidChangeStudioConnection: Event + private readonly studioConnectionChanged: EventEmitter = + this.dispose.track(new EventEmitter()) + + private readonly getCwd: () => string | undefined + private readonly internalCommands: InternalCommands private studioAccessToken: string | undefined = undefined private studioIsConnected = false private shareLiveToStudio: boolean | undefined = undefined - private readonly getCwd: () => string | undefined - private readonly internalCommands: InternalCommands constructor( internalCommands: InternalCommands, - studioConnectionChanged: EventEmitter, getCwd: () => string | undefined ) { + super() + this.internalCommands = internalCommands - this.studioConnectionChanged = studioConnectionChanged this.getCwd = getCwd + this.onDidChangeStudioConnection = this.studioConnectionChanged.event } public getStudioAccessToken() { diff --git a/extension/src/setup/token.ts b/extension/src/setup/token.ts deleted file mode 100644 index d41d13800f..0000000000 --- a/extension/src/setup/token.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const isStudioAccessToken = (text?: string): boolean => { - if (!text) { - return false - } - return text.startsWith('isat_') && text.length >= 53 -}