From ba4288dda2f9c1f886173a9e13711088c9b03dab Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Tue, 2 Jul 2019 18:54:37 +0000 Subject: [PATCH 1/6] Initial Live Share support --- package.json | 12 +++++- src/commands.ts | 1 + src/constants.ts | 4 ++ src/extension.ts | 95 +++++++++++++++++++++++++++++------------- src/services/config.ts | 36 +++++++++++++++- 5 files changed, 118 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index 5aff379..74d07a2 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,10 @@ "command": "extension.selectProfile", "title": "Profile Switcher: Select Profile" }, + { + "command": "extension.selectLiveShareProfile", + "title": "Profile Switcher: Select Live Share Profile" + }, { "command": "extension.saveProfile", "title": "Profile Switcher: Save Profile" @@ -74,6 +78,11 @@ } } }, + "profileSwitcher.liveShareProfile": { + "type": "string", + "description": "Specifies the profile you'd like to use when you start a Live Share session. Defaults to using the current profile", + "default": null + }, "profileSwitcher.extensions": { "type": "object", "description": "These are the extensions for each profile that has been saved. Probably don't hand-edit this", @@ -124,6 +133,7 @@ "vscode": "^1.1.28" }, "dependencies": { - "fs-extra": "^8.0.1" + "fs-extra": "^8.0.1", + "vsls": "^0.3.1291" } } diff --git a/src/commands.ts b/src/commands.ts index fe18f11..7d16c29 100755 --- a/src/commands.ts +++ b/src/commands.ts @@ -1,4 +1,5 @@ enum ContributedCommands { + SelectLiveShareProfile = "extension.selectLiveShareProfile", SelectProfile = "extension.selectProfile", SaveProfile = "extension.saveProfile", DeleteProfile = "extension.deleteProfile" diff --git a/src/constants.ts b/src/constants.ts index a6cb74d..525895b 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -2,6 +2,10 @@ export const ExtensionName = "vscode-profile-switcher"; export const ExtensionPublisher = "aaronpowell"; export const ExtensionId = `${ExtensionPublisher}.${ExtensionName}`; +export const ContextSettingCurrentProfile = "currentProfile"; +export const ContextSettingPreviousProfile = "previousProfile"; + +export const ConfigLiveShareProfileKey = "liveShareProfile"; export const ConfigKey = "profileSwitcher"; export const ConfigProfilesKey = "profiles"; export const ConfigStorageKey = "storage"; diff --git a/src/extension.ts b/src/extension.ts index eac8181..59da08a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -3,49 +3,77 @@ import SettingsHelper from "./settingsHelper"; import ContributedCommands from "./commands"; import Config from "./services/config"; import ExtensionHelper from "./services/extensions"; +import * as liveShare from "./services/liveShare"; -function selectProfile( +async function activateProfile( + profile: string, config: Config, settingsHelper: SettingsHelper, extensionsHelper: ExtensionHelper ) { - return async () => { - let profiles = config.getProfiles(); + let msg = vscode.window.setStatusBarMessage("Switching profiles."); - if (!profiles.length) { - await vscode.window.showInformationMessage( - "There are no profiles saved to switch to. First save a profile and then you can pick it" - ); - return; - } + config.setCurrentProfile(profile); - let profile = await vscode.window.showQuickPick(profiles, { - placeHolder: "Select a profile" - }); + let profileSettings = config.getProfileSettings(profile); + await settingsHelper.updateUserSettings(profileSettings); - if (!profile) { - return; - } + let extensions = config.getProfileExtensions(profile); + await extensionsHelper.installExtensions(extensions); + await extensionsHelper.removeExtensions(extensions); - let msg = vscode.window.setStatusBarMessage("Switching profiles."); + msg.dispose(); - let profileSettings = config.getProfileSettings(profile); - await settingsHelper.updateUserSettings(profileSettings); + const message = await vscode.window.showInformationMessage( + "Do you want to reload and activate the extensions?", + "Yes" + ); - let extensions = config.getProfileExtensions(profile); - await extensionsHelper.installExtensions(extensions); - await extensionsHelper.removeExtensions(extensions); + if (message === "Yes") { + vscode.commands.executeCommand("workbench.action.reloadWindow"); + } +} - msg.dispose(); +async function promptProfile(config: Config): Promise { + let profiles = config.getProfiles(); - const message = await vscode.window.showInformationMessage( - "Do you want to reload and activate the extensions?", - "Yes" + if (!profiles.length) { + await vscode.window.showInformationMessage( + "There are no profiles saved to switch to. First save a profile and then you can pick it" ); + return; + } - if (message === "Yes") { - vscode.commands.executeCommand("workbench.action.reloadWindow"); + let profile = await vscode.window.showQuickPick(profiles, { + placeHolder: "Select a profile" + }); + + return profile; +} + +function selectProfile( + config: Config, + settingsHelper: SettingsHelper, + extensionsHelper: ExtensionHelper +) { + return async () => { + const profile = await promptProfile(config); + if (!profile) { + return; } + + activateProfile(profile, config, settingsHelper, extensionsHelper); + }; +} + +function selectLiveShareProfile(config: Config) { + return async () => { + const profile = await promptProfile(config); + if (!profile) { + return; + } + + await config.setLiveShareProfile(profile); }; } @@ -117,10 +145,17 @@ function deleteProfile(config: Config) { } export async function activate(context: vscode.ExtensionContext) { - let config = new Config(); + let config = new Config(context); let settingsHelper = new SettingsHelper(context); let extensionsHelper = new ExtensionHelper(context, settingsHelper, config); + context.subscriptions.push( + vscode.commands.registerCommand( + ContributedCommands.SelectLiveShareProfile, + selectLiveShareProfile(config) + ) + ); + context.subscriptions.push( vscode.commands.registerCommand( ContributedCommands.SelectProfile, @@ -141,4 +176,8 @@ export async function activate(context: vscode.ExtensionContext) { deleteProfile(config) ) ); + + liveShare.initialize(context, config, (profile: string) => { + activateProfile(profile, config, settingsHelper, extensionsHelper); + }); } diff --git a/src/services/config.ts b/src/services/config.ts index c535974..4680c7b 100755 --- a/src/services/config.ts +++ b/src/services/config.ts @@ -4,7 +4,10 @@ import { ConfigProfilesKey, ConfigStorageKey, ConfigExtensionsKey, - ConfigExtensionsIgnoreKey + ConfigExtensionsIgnoreKey, + ConfigLiveShareProfileKey, + ContextSettingCurrentProfile, + ContextSettingPreviousProfile } from "../constants"; import { ExtensionInfo } from "./extensions"; @@ -21,10 +24,41 @@ interface ExtensionStorage { } class Config { + constructor(private context?: vscode.ExtensionContext) {} + private getConfig() { return vscode.workspace.getConfiguration(ConfigKey); } + public getLiveShareProfile() { + let config = this.getConfig(); + + return config.get(ConfigLiveShareProfileKey, null); + } + + public setLiveShareProfile(profile: string) { + let config = this.getConfig(); + + return config.update(ConfigLiveShareProfileKey, profile, vscode.ConfigurationTarget.Global); + } + + public setCurrentProfile(profile: string) { + if (this.context) { + const previousProfile = this.context.globalState.get(ContextSettingCurrentProfile); + this.setPreviousProfile(previousProfile); + + this.context.globalState.update(ContextSettingCurrentProfile, profile); + } + } + + public getPreviousProfile(): string | undefined { + return this.context && this.context.globalState.get(ContextSettingPreviousProfile); + } + + public setPreviousProfile(profile: string | undefined) { + this.context && this.context.globalState.update(ContextSettingPreviousProfile, profile); + } + public getProfiles() { let config = this.getConfig(); From a7b1c1d0d5c24662795321ff4dc31db129f77ac0 Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Tue, 2 Jul 2019 18:54:58 +0000 Subject: [PATCH 2/6] Initial Live Share support --- src/services/liveShare.ts | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/services/liveShare.ts diff --git a/src/services/liveShare.ts b/src/services/liveShare.ts new file mode 100644 index 0000000..bcbaa78 --- /dev/null +++ b/src/services/liveShare.ts @@ -0,0 +1,45 @@ +import * as vscode from "vscode"; +import * as vsls from "vsls"; +import Config from "./config"; + +export async function initialize( + context: vscode.ExtensionContext, + config: Config, + activateProfileHandler: (profile: string) => void +) { + const liveShare = await vsls.getApi(); + if (!liveShare) { + return; + } + + const liveShareProfile = config.getLiveShareProfile(); + if (!liveShareProfile) { + return; + } + + // Check to see whether there was a lingering profile set + // (e.g. because the user closed VS Code while in a Live Share + // session), and if so, restore the right profile. + restorePreviousProfile(config, activateProfileHandler); + + liveShare.onDidChangeSession(e => { + if (e.session.id) { + activateProfileHandler(liveShareProfile); + } else { + restorePreviousProfile(config, activateProfileHandler); + } + }) +} + +function restorePreviousProfile( + config: Config, + activateProfileHandler: (profile: string) => void +) { + const previousProfile = config.getPreviousProfile(); + if (!previousProfile) { + return; + } + + config.setPreviousProfile(undefined); + activateProfileHandler(previousProfile); +} \ No newline at end of file From 2cab0a760429db076b5a327eb29da1765739cfc0 Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Tue, 2 Jul 2019 12:40:45 -0700 Subject: [PATCH 3/6] Misc. cleanup --- src/extension.ts | 2 +- src/services/config.ts | 4 ++-- src/services/liveShare.ts | 15 +++++---------- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 59da08a..25209ec 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -13,7 +13,7 @@ async function activateProfile( ) { let msg = vscode.window.setStatusBarMessage("Switching profiles."); - config.setCurrentProfile(profile); + await config.setCurrentProfile(profile); let profileSettings = config.getProfileSettings(profile); await settingsHelper.updateUserSettings(profileSettings); diff --git a/src/services/config.ts b/src/services/config.ts index 4680c7b..d297e41 100755 --- a/src/services/config.ts +++ b/src/services/config.ts @@ -42,12 +42,12 @@ class Config { return config.update(ConfigLiveShareProfileKey, profile, vscode.ConfigurationTarget.Global); } - public setCurrentProfile(profile: string) { + public async setCurrentProfile(profile: string) { if (this.context) { const previousProfile = this.context.globalState.get(ContextSettingCurrentProfile); this.setPreviousProfile(previousProfile); - this.context.globalState.update(ContextSettingCurrentProfile, profile); + await this.context.globalState.update(ContextSettingCurrentProfile, profile); } } diff --git a/src/services/liveShare.ts b/src/services/liveShare.ts index bcbaa78..19397b7 100644 --- a/src/services/liveShare.ts +++ b/src/services/liveShare.ts @@ -12,17 +12,12 @@ export async function initialize( return; } - const liveShareProfile = config.getLiveShareProfile(); - if (!liveShareProfile) { - return; - } - - // Check to see whether there was a lingering profile set - // (e.g. because the user closed VS Code while in a Live Share - // session), and if so, restore the right profile. - restorePreviousProfile(config, activateProfileHandler); - liveShare.onDidChangeSession(e => { + const liveShareProfile = config.getLiveShareProfile(); + if (!liveShareProfile) { + return; + } + if (e.session.id) { activateProfileHandler(liveShareProfile); } else { From eb72f38c2e8a9afe43422a129f45816cd8c7aa37 Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Tue, 2 Jul 2019 12:57:19 -0700 Subject: [PATCH 4/6] Simplifying LS code --- package-lock.json | 7 ++++++- src/services/liveShare.ts | 31 ++++++++++++------------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3f560ea..55300e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vscode-profile-switcher", - "version": "0.2.0", + "version": "0.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1783,6 +1783,11 @@ "https-proxy-agent": "^2.2.1" } }, + "vsls": { + "version": "0.3.1291", + "resolved": "https://registry.npmjs.org/vsls/-/vsls-0.3.1291.tgz", + "integrity": "sha512-8yJPN9p7k+XYyczOVtQmpun4K1CRDsw/hdnIzT/c40r5bIkpptfsBlHmmLemoIV+CAHvrTLdWKEf5OtRvdcn9A==" + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/src/services/liveShare.ts b/src/services/liveShare.ts index 19397b7..6fee8d9 100644 --- a/src/services/liveShare.ts +++ b/src/services/liveShare.ts @@ -13,28 +13,21 @@ export async function initialize( } liveShare.onDidChangeSession(e => { - const liveShareProfile = config.getLiveShareProfile(); - if (!liveShareProfile) { - return; - } - if (e.session.id) { + const liveShareProfile = config.getLiveShareProfile(); + if (!liveShareProfile) { + return; + } + activateProfileHandler(liveShareProfile); } else { - restorePreviousProfile(config, activateProfileHandler); + const previousProfile = config.getPreviousProfile(); + if (!previousProfile) { + return; + } + + config.setPreviousProfile(undefined); + activateProfileHandler(previousProfile); } }) -} - -function restorePreviousProfile( - config: Config, - activateProfileHandler: (profile: string) => void -) { - const previousProfile = config.getPreviousProfile(); - if (!previousProfile) { - return; - } - - config.setPreviousProfile(undefined); - activateProfileHandler(previousProfile); } \ No newline at end of file From 96f090607e0596b7c68100f2969e780b070dedca Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Tue, 2 Jul 2019 13:07:55 -0700 Subject: [PATCH 5/6] Add documentation --- src/services/liveShare.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/services/liveShare.ts b/src/services/liveShare.ts index 6fee8d9..3768a9c 100644 --- a/src/services/liveShare.ts +++ b/src/services/liveShare.ts @@ -7,18 +7,27 @@ export async function initialize( config: Config, activateProfileHandler: (profile: string) => void ) { + // Check to see if the end-user has the Live Share + // extension installed, and if not, exit early. const liveShare = await vsls.getApi(); if (!liveShare) { return; } + // Begin listening for the beginning and end of Live + // Share sessions, in case we need to switch profiles. liveShare.onDidChangeSession(e => { - if (e.session.id) { - const liveShareProfile = config.getLiveShareProfile(); - if (!liveShareProfile) { - return; - } + // If the end-user never set a Live Share profile, then + // there's nothing we need to do. Note that we're calling + // this here, instead of as part of the activation flow, + // so that the end-user can set their profile any time + // and have it take effect immediately. + const liveShareProfile = config.getLiveShareProfile(); + if (!liveShareProfile) { + return; + } + if (e.session.id) { activateProfileHandler(liveShareProfile); } else { const previousProfile = config.getPreviousProfile(); From 8ab0c2f45295510bb27d3897d9499ce35a2d5455 Mon Sep 17 00:00:00 2001 From: Jonathan Carter Date: Tue, 2 Jul 2019 13:11:24 -0700 Subject: [PATCH 6/6] Fixing ESLint error --- src/services/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/config.ts b/src/services/config.ts index d297e41..1d68a2b 100755 --- a/src/services/config.ts +++ b/src/services/config.ts @@ -24,7 +24,7 @@ interface ExtensionStorage { } class Config { - constructor(private context?: vscode.ExtensionContext) {} + public constructor(private context?: vscode.ExtensionContext) {} private getConfig() { return vscode.workspace.getConfiguration(ConfigKey);