From 5c748e0fb964a943466e239aea544c75dd3604ec Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Sun, 6 Feb 2022 14:08:17 -0500 Subject: [PATCH] Moves all storage access into new class --- src/avatars.ts | 8 +-- src/commands/closeView.ts | 5 +- src/commands/gitCommands.ts | 8 +-- src/commands/showView.ts | 5 +- src/constants.ts | 113 +++-------------------------- src/container.ts | 8 +++ src/env/node/git/localGitProvider.ts | 7 +- src/extension.ts | 19 ++--- src/git/gitProviderService.ts | 7 +- src/git/models/branch.ts | 4 +- src/git/models/remote.ts | 6 +- src/git/models/repository.ts | 9 +-- src/git/remotes/provider.ts | 16 ++--- src/storage.ts | 129 ++++++++++++++++++++++++++++++++++ src/views/nodes/compareBranchNode.ts | 17 +++-- src/views/nodes/comparePickerNode.ts | 3 +- src/views/nodes/compareResultsNode.ts | 2 +- src/views/repositoriesView.ts | 9 +-- src/views/searchAndCompareView.ts | 27 +++---- 19 files changed, 224 insertions(+), 178 deletions(-) create mode 100644 src/storage.ts diff --git a/src/avatars.ts b/src/avatars.ts index 7b9c864..f76859f 100644 --- a/src/avatars.ts +++ b/src/avatars.ts @@ -1,8 +1,8 @@ import { EventEmitter, Uri } from 'vscode'; import { GravatarDefaultStyle } from './config'; -import { GlobalState } from './constants'; import { Container } from './container'; import { GitRevisionReference } from './git/models'; +import { GlobalState } from './storage'; import { debounce } from './system/function'; import { filterMap } from './system/iterable'; import { base64, equalsIgnoreCase, md5 } from './system/string'; @@ -27,7 +27,7 @@ _onDidFetchAvatar.event( ), ] : undefined; - void Container.instance.context.globalState.update(GlobalState.Avatars, avatars); + void Container.instance.storage.store(GlobalState.Avatars, avatars); }, 1000), ); @@ -137,7 +137,7 @@ function createOrUpdateAvatar( function ensureAvatarCache(cache: Map | undefined): asserts cache is Map { if (cache == null) { - const avatars: [string, Avatar][] | undefined = Container.instance.context.globalState + const avatars: [string, Avatar][] | undefined = Container.instance.storage .get<[string, SerializedAvatar][]>(GlobalState.Avatars) ?.map<[string, Avatar]>(([key, avatar]) => [ key, @@ -246,7 +246,7 @@ export function getPresenceDataUri(status: ContactPresenceStatus) { export function resetAvatarCache(reset: 'all' | 'failed' | 'fallback') { switch (reset) { case 'all': - void Container.instance.context.globalState.update(GlobalState.Avatars, undefined); + void Container.instance.storage.delete(GlobalState.Avatars); avatarCache?.clear(); avatarQueue.clear(); break; diff --git a/src/commands/closeView.ts b/src/commands/closeView.ts index 093b2e8..fa71ebf 100644 --- a/src/commands/closeView.ts +++ b/src/commands/closeView.ts @@ -1,5 +1,6 @@ -import { ContextKeys, setContext, SyncedState } from '../constants'; +import { ContextKeys, setContext } from '../constants'; import type { Container } from '../container'; +import { SyncedState } from '../storage'; import { command, Command, CommandContext, Commands } from './common'; @command() @@ -15,7 +16,7 @@ export class CloseViewCommand extends Command { async execute(command: Commands) { switch (command) { case Commands.CloseWelcomeView: - await this.container.context.globalState.update(SyncedState.WelcomeViewVisible, false); + await this.container.storage.store(SyncedState.WelcomeViewVisible, false); await setContext(ContextKeys.ViewsWelcomeVisible, false); break; } diff --git a/src/commands/gitCommands.ts b/src/commands/gitCommands.ts index 30849a2..f71fa53 100644 --- a/src/commands/gitCommands.ts +++ b/src/commands/gitCommands.ts @@ -1,9 +1,9 @@ import { Disposable, InputBox, QuickInputButton, QuickInputButtons, QuickPick, QuickPickItem, window } from 'vscode'; import { configuration, GitCommandSorting } from '../configuration'; -import { Usage, WorkspaceState } from '../constants'; import type { Container } from '../container'; import { KeyMapping } from '../keyboard'; import { Directive, DirectiveQuickPickItem } from '../quickpicks'; +import { Usage, WorkspaceState } from '../storage'; import { log } from '../system/decorators/log'; import { isPromise } from '../system/promise'; import { command, Command, CommandContext, Commands } from './common'; @@ -772,7 +772,7 @@ class PickCommandStep implements QuickPickStep { ]; if (this.container.config.gitCommands.sortBy === GitCommandSorting.Usage) { - const usage = this.container.context.workspaceState.get(WorkspaceState.GitCommandPaletteUsage); + const usage = this.container.storage.getWorkspace(WorkspaceState.GitCommandPaletteUsage); if (usage != null) { this.items.sort((a, b) => (usage[b.key] ?? 0) - (usage[a.key] ?? 0)); } @@ -812,12 +812,12 @@ class PickCommandStep implements QuickPickStep { } private async updateCommandUsage(id: string, timestamp: number) { - let usage = this.container.context.workspaceState.get(WorkspaceState.GitCommandPaletteUsage); + let usage = this.container.storage.getWorkspace(WorkspaceState.GitCommandPaletteUsage); if (usage === undefined) { usage = Object.create(null) as Usage; } usage[id] = timestamp; - await this.container.context.workspaceState.update(WorkspaceState.GitCommandPaletteUsage, usage); + await this.container.storage.storeWorkspace(WorkspaceState.GitCommandPaletteUsage, usage); } } diff --git a/src/commands/showView.ts b/src/commands/showView.ts index 314cfb4..c8d46a5 100644 --- a/src/commands/showView.ts +++ b/src/commands/showView.ts @@ -1,6 +1,7 @@ import { commands } from 'vscode'; -import { ContextKeys, setContext, SyncedState } from '../constants'; +import { ContextKeys, setContext } from '../constants'; import type { Container } from '../container'; +import { SyncedState } from '../storage'; import { command, Command, CommandContext, Commands } from './common'; @command() @@ -49,7 +50,7 @@ export class ShowViewCommand extends Command { return this.container.tagsView.show(); case Commands.ShowWelcomeView: await setContext(ContextKeys.ViewsWelcomeVisible, true); - void this.container.context.globalState.update(SyncedState.WelcomeViewVisible, true); + void this.container.storage.store(SyncedState.WelcomeViewVisible, true); void (await commands.executeCommand('gitlens.views.welcome.focus')); } diff --git a/src/constants.ts b/src/constants.ts index 0598f70..bc5c5b9 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,8 +1,17 @@ import { commands, TextDocument, TextEditor, window } from 'vscode'; -import { ViewShowBranchComparison } from './config'; -import { SearchPattern } from './git/search'; export const quickPickTitleMaxChars = 80; +export const ImageMimetypes: Record = { + '.png': 'image/png', + '.gif': 'image/gif', + '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', + '.jpe': 'image/jpeg', + '.webp': 'image/webp', + '.tif': 'image/tiff', + '.tiff': 'image/tiff', + '.bmp': 'image/bmp', +}; export const enum BuiltInCommands { CloseActiveEditor = 'workbench.action.closeActiveEditor', @@ -174,103 +183,3 @@ export const enum GlyphChars { Warning = '\u26a0', ZeroWidthSpace = '\u200b', } - -export const enum SyncedState { - Version = 'gitlens:synced:version', - WelcomeViewVisible = 'gitlens:views:welcome:visible', - - Deprecated_DisallowConnectionPrefix = 'gitlens:disallow:connection:', -} - -export const enum GlobalState { - Avatars = 'gitlens:avatars', - PendingWelcomeOnFocus = 'gitlens:pendingWelcomeOnFocus', - PendingWhatsNewOnFocus = 'gitlens:pendingWhatsNewOnFocus', - Version = 'gitlens:version', - - Deprecated_Version = 'gitlensVersion', -} - -export const ImageMimetypes: Record = { - '.png': 'image/png', - '.gif': 'image/gif', - '.jpg': 'image/jpeg', - '.jpeg': 'image/jpeg', - '.jpe': 'image/jpeg', - '.webp': 'image/webp', - '.tif': 'image/tiff', - '.tiff': 'image/tiff', - '.bmp': 'image/bmp', -}; - -export interface BranchComparison { - ref: string; - notation: '..' | '...' | undefined; - type: Exclude | undefined; -} - -export interface BranchComparisons { - [id: string]: string | BranchComparison; -} - -export interface NamedRef { - label?: string; - ref: string; -} - -export interface PinnedComparison { - type: 'comparison'; - timestamp: number; - path: string; - ref1: NamedRef; - ref2: NamedRef; - notation?: '..' | '...'; -} - -export interface PinnedSearch { - type: 'search'; - timestamp: number; - path: string; - labels: { - label: string; - queryLabel: - | string - | { - label: string; - resultsType?: { singular: string; plural: string }; - }; - }; - search: SearchPattern; -} - -export type PinnedItem = PinnedComparison | PinnedSearch; - -export interface PinnedItems { - [id: string]: PinnedItem; -} - -export interface Starred { - [id: string]: boolean; -} - -export interface Usage { - [id: string]: number; -} - -export const enum WorkspaceState { - AssumeRepositoriesOnStartup = 'gitlens:assumeRepositoriesOnStartup', - GitPath = 'gitlens:gitPath', - - BranchComparisons = 'gitlens:branch:comparisons', - ConnectedPrefix = 'gitlens:connected:', - DefaultRemote = 'gitlens:remote:default', - GitCommandPaletteUsage = 'gitlens:gitComandPalette:usage', - StarredBranches = 'gitlens:starred:branches', - StarredRepositories = 'gitlens:starred:repositories', - ViewsRepositoriesAutoRefresh = 'gitlens:views:repositories:autoRefresh', - ViewsSearchAndCompareKeepResults = 'gitlens:views:searchAndCompare:keepResults', - ViewsSearchAndComparePinnedItems = 'gitlens:views:searchAndCompare:pinned', - - Deprecated_DisallowConnectionPrefix = 'gitlens:disallow:connection:', - Deprecated_PinnedComparisons = 'gitlens:pinned:comparisons', -} diff --git a/src/container.ts b/src/container.ts index 8e602e8..8fa93a7 100644 --- a/src/container.ts +++ b/src/container.ts @@ -22,6 +22,7 @@ import { LineHoverController } from './hovers/lineHoverController'; import { Keyboard } from './keyboard'; import { Logger } from './logger'; import { StatusBarController } from './statusbar/statusBarController'; +import { Storage } from './storage'; import { log } from './system/decorators/log'; import { memoize } from './system/decorators/memoize'; import { GitTerminalLinkProvider } from './terminal/linkProvider'; @@ -136,6 +137,8 @@ export class Container { private constructor(context: ExtensionContext, config: Config) { this._context = context; this._config = this.applyMode(config); + this._storage = new Storage(this._context); + context.subscriptions.push(configuration.onWillChange(this.onConfigurationChanging, this)); context.subscriptions.push((this._git = new GitProviderService(this))); @@ -413,6 +416,11 @@ export class Container { return this._statusBarController; } + private readonly _storage: Storage; + get storage(): Storage { + return this._storage; + } + private _tagsView: TagsView | undefined; get tagsView() { if (this._tagsView == null) { diff --git a/src/env/node/git/localGitProvider.ts b/src/env/node/git/localGitProvider.ts index 96e0611..17a7de2 100644 --- a/src/env/node/git/localGitProvider.ts +++ b/src/env/node/git/localGitProvider.ts @@ -23,7 +23,7 @@ import type { GitExtension, } from '../../../@types/vscode.git'; import { configuration } from '../../../configuration'; -import { BuiltInGitConfiguration, GlyphChars, Schemes, WorkspaceState } from '../../../constants'; +import { BuiltInGitConfiguration, GlyphChars, Schemes } from '../../../constants'; import type { Container } from '../../../container'; import { StashApplyError, StashApplyErrorReason } from '../../../git/errors'; import { @@ -95,6 +95,7 @@ import { RemoteProvider, RichRemoteProvider } from '../../../git/remotes/provide import { SearchPattern } from '../../../git/search'; import { LogCorrelationContext, Logger } from '../../../logger'; import { Messages } from '../../../messages'; +import { WorkspaceState } from '../../../storage'; import { countStringLength, filterMap } from '../../../system/array'; import { gate } from '../../../system/decorators/gate'; import { debug, log } from '../../../system/decorators/log'; @@ -265,7 +266,7 @@ export class LocalGitProvider implements GitProvider, Disposable { const potentialGitPaths = configuration.getAny('git.path') ?? - this.container.context.workspaceState.get(WorkspaceState.GitPath, undefined); + this.container.storage.getWorkspace(WorkspaceState.GitPath, undefined); const start = hrtime(); @@ -289,7 +290,7 @@ export class LocalGitProvider implements GitProvider, Disposable { const location = await any(findGitPromise, findGitFromSCMPromise); // Save the found git path, but let things settle first to not impact startup performance setTimeout(() => { - void this.container.context.workspaceState.update(WorkspaceState.GitPath, location.path); + void this.container.storage.storeWorkspace(WorkspaceState.GitPath, location.path); }, 1000); if (cc != null) { diff --git a/src/extension.ts b/src/extension.ts index d046c20..e848935 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -5,13 +5,14 @@ import type { CreatePullRequestActionContext, GitLensApi, OpenPullRequestActionC import { Commands, executeCommand, OpenPullRequestOnRemoteCommandArgs, registerCommands } from './commands'; import { CreatePullRequestOnRemoteCommandArgs } from './commands/createPullRequestOnRemote'; import { configuration, Configuration, OutputLevel } from './configuration'; -import { ContextKeys, GlobalState, setContext, SyncedState } from './constants'; +import { ContextKeys, setContext } from './constants'; import { Container } from './container'; import { GitUri } from './git/gitUri'; import { GitBranch, GitCommit } from './git/models'; import { Logger, LogLevel } from './logger'; import { Messages } from './messages'; import { registerPartnerActionRunners } from './partners'; +import { GlobalState, SyncedState } from './storage'; import { once } from './system/event'; import { Stopwatch } from './system/stopwatch'; import { compare } from './system/version'; @@ -199,19 +200,19 @@ async function showWelcomeOrWhatsNew(container: Container, version: string, prev if (container.config.showWelcomeOnInstall === false) return; if (window.state.focused) { - await container.context.globalState.update(GlobalState.PendingWelcomeOnFocus, undefined); + await container.storage.delete(GlobalState.PendingWelcomeOnFocus); await commands.executeCommand(Commands.ShowWelcomePage); } else { // Save pending on window getting focus - await container.context.globalState.update(GlobalState.PendingWelcomeOnFocus, true); + await container.storage.store(GlobalState.PendingWelcomeOnFocus, true); const disposable = window.onDidChangeWindowState(e => { if (!e.focused) return; disposable.dispose(); // If the window is now focused and we are pending the welcome, clear the pending state and show the welcome - if (container.context.globalState.get(GlobalState.PendingWelcomeOnFocus) === true) { - void container.context.globalState.update(GlobalState.PendingWelcomeOnFocus, undefined); + if (container.storage.get(GlobalState.PendingWelcomeOnFocus) === true) { + void container.storage.delete(GlobalState.PendingWelcomeOnFocus); if (container.config.showWelcomeOnInstall) { void commands.executeCommand(Commands.ShowWelcomePage); } @@ -240,19 +241,19 @@ async function showWelcomeOrWhatsNew(container: Container, version: string, prev if (major !== prevMajor && container.config.showWhatsNewAfterUpgrades) { if (window.state.focused) { - await container.context.globalState.update(GlobalState.PendingWhatsNewOnFocus, undefined); + await container.storage.delete(GlobalState.PendingWhatsNewOnFocus); await Messages.showWhatsNewMessage(version); } else { // Save pending on window getting focus - await container.context.globalState.update(GlobalState.PendingWhatsNewOnFocus, true); + await container.storage.store(GlobalState.PendingWhatsNewOnFocus, true); const disposable = window.onDidChangeWindowState(e => { if (!e.focused) return; disposable.dispose(); // If the window is now focused and we are pending the what's new, clear the pending state and show the what's new - if (container.context.globalState.get(GlobalState.PendingWhatsNewOnFocus) === true) { - void container.context.globalState.update(GlobalState.PendingWhatsNewOnFocus, undefined); + if (container.storage.get(GlobalState.PendingWhatsNewOnFocus) === true) { + void container.storage.delete(GlobalState.PendingWhatsNewOnFocus); if (container.config.showWhatsNewAfterUpgrades) { void Messages.showWhatsNewMessage(version); } diff --git a/src/git/gitProviderService.ts b/src/git/gitProviderService.ts index 9c1be5c..3de7283 100644 --- a/src/git/gitProviderService.ts +++ b/src/git/gitProviderService.ts @@ -17,11 +17,12 @@ import { } from 'vscode'; import { resetAvatarCache } from '../avatars'; import { configuration } from '../configuration'; -import { BuiltInGitConfiguration, ContextKeys, GlyphChars, Schemes, setContext, WorkspaceState } from '../constants'; +import { BuiltInGitConfiguration, ContextKeys, GlyphChars, Schemes, setContext } from '../constants'; import type { Container } from '../container'; import { ProviderNotFoundError } from '../errors'; import { Logger } from '../logger'; import { asRepoComparisonKey, RepoComparisionKey, Repositories } from '../repositories'; +import { WorkspaceState } from '../storage'; import { groupByFilterMap, groupByMap } from '../system/array'; import { gate } from '../system/decorators/gate'; import { debug, log } from '../system/decorators/log'; @@ -493,7 +494,7 @@ export class GitProviderService implements Disposable { // If we think we should be disabled during startup, check if we have a saved value from the last time this repo was loaded if (!enabled && this._initializing) { disabled = !( - this.container.context.workspaceState.get(WorkspaceState.AssumeRepositoriesOnStartup) ?? true + this.container.storage.getWorkspace(WorkspaceState.AssumeRepositoriesOnStartup) ?? true ); } @@ -514,7 +515,7 @@ export class GitProviderService implements Disposable { await Promise.all(promises); if (!this._initializing) { - void this.container.context.workspaceState.update(WorkspaceState.AssumeRepositoriesOnStartup, enabled); + void this.container.storage.storeWorkspace(WorkspaceState.AssumeRepositoriesOnStartup, enabled); } } diff --git a/src/git/models/branch.ts b/src/git/models/branch.ts index 0ae84b8..4fa5562 100644 --- a/src/git/models/branch.ts +++ b/src/git/models/branch.ts @@ -1,6 +1,6 @@ import { BranchSorting, configuration, DateStyle } from '../../configuration'; -import { Starred, WorkspaceState } from '../../constants'; import { Container } from '../../container'; +import { Starred, WorkspaceState } from '../../storage'; import { formatDate, fromNow } from '../../system/date'; import { debug } from '../../system/decorators/log'; import { memoize } from '../../system/decorators/memoize'; @@ -234,7 +234,7 @@ export class GitBranch implements GitBranchReference { } get starred() { - const starred = Container.instance.context.workspaceState.get(WorkspaceState.StarredBranches); + const starred = Container.instance.storage.getWorkspace(WorkspaceState.StarredBranches); return starred !== undefined && starred[this.id] === true; } diff --git a/src/git/models/remote.ts b/src/git/models/remote.ts index ec5f653..7b13cac 100644 --- a/src/git/models/remote.ts +++ b/src/git/models/remote.ts @@ -1,5 +1,5 @@ -import { WorkspaceState } from '../../constants'; import { Container } from '../../container'; +import { WorkspaceState } from '../../storage'; import { sortCompare } from '../../system/string'; import { RemoteProvider, RichRemoteProvider } from '../remotes/provider'; @@ -59,7 +59,7 @@ export class GitRemote(WorkspaceState.DefaultRemote); + const defaultRemote = Container.instance.storage.getWorkspace(WorkspaceState.DefaultRemote); return this.id === defaultRemote; } @@ -83,7 +83,7 @@ export class GitRemote(WorkspaceState.StarredRepositories); + const starred = this.container.storage.getWorkspace(WorkspaceState.StarredRepositories); return starred != null && starred[this.id] === true; } @@ -900,7 +901,7 @@ export class Repository implements Disposable { } private async updateStarredCore(key: WorkspaceState, id: string, star: boolean) { - let starred = this.container.context.workspaceState.get(key); + let starred = this.container.storage.getWorkspace(key); if (starred === undefined) { starred = Object.create(null) as Starred; } @@ -911,7 +912,7 @@ export class Repository implements Disposable { const { [id]: _, ...rest } = starred; starred = rest; } - await this.container.context.workspaceState.update(key, starred); + await this.container.storage.storeWorkspace(key, starred); this.fireChange(RepositoryChange.Starred); } diff --git a/src/git/remotes/provider.ts b/src/git/remotes/provider.ts index c65e68f..de4f4c4 100644 --- a/src/git/remotes/provider.ts +++ b/src/git/remotes/provider.ts @@ -10,10 +10,10 @@ import { } from 'vscode'; import { DynamicAutolinkReference } from '../../annotations/autolinks'; import { AutolinkReference } from '../../config'; -import { WorkspaceState } from '../../constants'; import { Container } from '../../container'; import { AuthenticationError, ProviderRequestClientError } from '../../errors'; import { Logger } from '../../logger'; +import { WorkspaceState } from '../../storage'; import { gate } from '../../system/decorators/gate'; import { debug, log } from '../../system/decorators/log'; import { encodeUrl } from '../../system/encoding'; @@ -303,7 +303,7 @@ export abstract class RichRemoteProvider extends RemoteProvider { return this.custom ? `${this.name}:${this.domain}` : this.name; } - private get connectedKey() { + private get connectedKey(): `${WorkspaceState.ConnectedPrefix}${string}` { return `${WorkspaceState.ConnectedPrefix}${this.key}`; } @@ -346,7 +346,7 @@ export abstract class RichRemoteProvider extends RemoteProvider { this._session = null; if (connected) { - void Container.instance.context.workspaceState.update(this.connectedKey, false); + void Container.instance.storage.storeWorkspace(this.connectedKey, false); this._onDidChange.fire(); if (!silent) { @@ -573,8 +573,8 @@ export abstract class RichRemoteProvider extends RemoteProvider { if (!Container.instance.config.integrations.enabled) return undefined; if (createIfNeeded) { - await Container.instance.context.workspaceState.update(this.connectedKey, undefined); - } else if (Container.instance.context.workspaceState.get(this.connectedKey) === false) { + await Container.instance.storage.deleteWorkspace(this.connectedKey); + } else if (Container.instance.storage.getWorkspace(this.connectedKey) === false) { return undefined; } @@ -585,7 +585,7 @@ export abstract class RichRemoteProvider extends RemoteProvider { silent: !createIfNeeded, }); } catch (ex) { - await Container.instance.context.workspaceState.update(this.connectedKey, undefined); + await Container.instance.storage.deleteWorkspace(this.connectedKey); if (ex instanceof Error && ex.message.includes('User did not consent')) { return undefined; @@ -595,14 +595,14 @@ export abstract class RichRemoteProvider extends RemoteProvider { } if (session === undefined && !createIfNeeded) { - await Container.instance.context.workspaceState.update(this.connectedKey, undefined); + await Container.instance.storage.deleteWorkspace(this.connectedKey); } this._session = session ?? null; this.invalidClientExceptionCount = 0; if (session != null) { - await Container.instance.context.workspaceState.update(this.connectedKey, true); + await Container.instance.storage.storeWorkspace(this.connectedKey, true); queueMicrotask(() => { this._onDidChange.fire(); diff --git a/src/storage.ts b/src/storage.ts new file mode 100644 index 0000000..524df65 --- /dev/null +++ b/src/storage.ts @@ -0,0 +1,129 @@ +import { ExtensionContext } from 'vscode'; +import { ViewShowBranchComparison } from './config'; +import { SearchPattern } from './git/search'; + +export class Storage { + constructor(private readonly context: ExtensionContext) {} + + get(key: GlobalState | SyncedState): T | undefined; + get(key: GlobalState | SyncedState, defaultValue: T): T; + get(key: GlobalState | SyncedState, defaultValue?: T): T | undefined { + return this.context.globalState.get(key, defaultValue); + } + + async delete(key: GlobalState | SyncedState): Promise { + return this.context.globalState.update(key, undefined); + } + + async store(key: GlobalState | SyncedState, value: unknown): Promise { + return this.context.globalState.update(key, value); + } + + getWorkspace(key: WorkspaceState | `${WorkspaceState.ConnectedPrefix}${string}`): T | undefined; + getWorkspace(key: WorkspaceState | `${WorkspaceState.ConnectedPrefix}${string}`, defaultValue: T): T; + getWorkspace( + key: WorkspaceState | `${WorkspaceState.ConnectedPrefix}${string}`, + defaultValue?: T, + ): T | undefined { + return this.context.workspaceState.get(key, defaultValue); + } + + async deleteWorkspace(key: WorkspaceState | `${WorkspaceState.ConnectedPrefix}${string}`): Promise { + return this.context.workspaceState.update(key, undefined); + } + + async storeWorkspace( + key: WorkspaceState | `${WorkspaceState.ConnectedPrefix}${string}`, + value: unknown, + ): Promise { + return this.context.workspaceState.update(key, value); + } +} + +export const enum GlobalState { + Avatars = 'gitlens:avatars', + PendingWelcomeOnFocus = 'gitlens:pendingWelcomeOnFocus', + PendingWhatsNewOnFocus = 'gitlens:pendingWhatsNewOnFocus', + Version = 'gitlens:version', + + Deprecated_Version = 'gitlensVersion', +} + +export const enum SyncedState { + Version = 'gitlens:synced:version', + WelcomeViewVisible = 'gitlens:views:welcome:visible', + + Deprecated_DisallowConnectionPrefix = 'gitlens:disallow:connection:', +} + +export const enum WorkspaceState { + AssumeRepositoriesOnStartup = 'gitlens:assumeRepositoriesOnStartup', + GitPath = 'gitlens:gitPath', + + BranchComparisons = 'gitlens:branch:comparisons', + ConnectedPrefix = 'gitlens:connected:', + DefaultRemote = 'gitlens:remote:default', + GitCommandPaletteUsage = 'gitlens:gitComandPalette:usage', + StarredBranches = 'gitlens:starred:branches', + StarredRepositories = 'gitlens:starred:repositories', + ViewsRepositoriesAutoRefresh = 'gitlens:views:repositories:autoRefresh', + ViewsSearchAndCompareKeepResults = 'gitlens:views:searchAndCompare:keepResults', + ViewsSearchAndComparePinnedItems = 'gitlens:views:searchAndCompare:pinned', + + Deprecated_DisallowConnectionPrefix = 'gitlens:disallow:connection:', + Deprecated_PinnedComparisons = 'gitlens:pinned:comparisons', +} + +export interface BranchComparison { + ref: string; + notation: '..' | '...' | undefined; + type: Exclude | undefined; +} + +export interface BranchComparisons { + [id: string]: string | BranchComparison; +} + +export interface NamedRef { + label?: string; + ref: string; +} + +export interface PinnedComparison { + type: 'comparison'; + timestamp: number; + path: string; + ref1: NamedRef; + ref2: NamedRef; + notation?: '..' | '...'; +} + +export interface PinnedSearch { + type: 'search'; + timestamp: number; + path: string; + labels: { + label: string; + queryLabel: + | string + | { + label: string; + resultsType?: { singular: string; plural: string }; + }; + }; + search: SearchPattern; +} + +export type PinnedItem = PinnedComparison | PinnedSearch; + +export interface PinnedItems { + [id: string]: PinnedItem; +} + +export interface Starred { + [id: string]: boolean; +} + +export interface Usage { + [id: string]: number; +} diff --git a/src/views/nodes/compareBranchNode.ts b/src/views/nodes/compareBranchNode.ts index 324ab38..ecff5bf 100644 --- a/src/views/nodes/compareBranchNode.ts +++ b/src/views/nodes/compareBranchNode.ts @@ -1,9 +1,10 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; import { ViewShowBranchComparison } from '../../configuration'; -import { BranchComparison, BranchComparisons, GlyphChars, WorkspaceState } from '../../constants'; +import { GlyphChars } from '../../constants'; import { GitUri } from '../../git/gitUri'; import { GitBranch, GitRevision } from '../../git/models'; import { CommandQuickPickItem, ReferencePicker } from '../../quickpicks'; +import { BranchComparison, BranchComparisons, WorkspaceState } from '../../storage'; import { debug, gate, log, Strings } from '../../system'; import { BranchesView } from '../branchesView'; import { CommitsView } from '../commitsView'; @@ -310,12 +311,12 @@ export class CompareBranchNode extends ViewNode { let comparison; - if (this._compareWith!.ref === '') { + if (!this._compareWith?.ref) { comparison = this.branch.ref; } else if (this.compareWithWorkingTree) { - comparison = this._compareWith!.ref; + comparison = this._compareWith.ref; } else { - comparison = `${this._compareWith!.ref}..${this.branch.ref}`; + comparison = `${this._compareWith.ref}..${this.branch.ref}`; } const files = await this.view.container.git.getDiffStatus(this.uri.repoPath!, comparison); @@ -327,7 +328,7 @@ export class CompareBranchNode extends ViewNode( + const comparisons = this.view.container.storage.getWorkspace( WorkspaceState.BranchComparisons, ); @@ -347,9 +348,7 @@ export class CompareBranchNode extends ViewNode( - WorkspaceState.BranchComparisons, - ); + let comparisons = this.view.container.storage.getWorkspace(WorkspaceState.BranchComparisons); if (comparisons == null) { if (compareWith == null) return; @@ -366,6 +365,6 @@ export class CompareBranchNode extends ViewNode(WorkspaceState.ViewsRepositoriesAutoRefresh, true) + this.container.storage.getWorkspace(WorkspaceState.ViewsRepositoriesAutoRefresh, true) ); } @@ -770,12 +771,12 @@ export class RepositoriesView extends ViewBase( + workspaceEnabled = this.container.storage.getWorkspace( WorkspaceState.ViewsRepositoriesAutoRefresh, true, ); } else { - await this.container.context.workspaceState.update( + await this.container.storage.storeWorkspace( WorkspaceState.ViewsRepositoriesAutoRefresh, workspaceEnabled, ); diff --git a/src/views/searchAndCompareView.ts b/src/views/searchAndCompareView.ts index d30b815..e085d62 100644 --- a/src/views/searchAndCompareView.ts +++ b/src/views/searchAndCompareView.ts @@ -1,12 +1,13 @@ import { commands, ConfigurationChangeEvent, Disposable, TreeItem, TreeItemCollapsibleState } from 'vscode'; import { getRepoPathOrPrompt } from '../commands'; import { configuration, SearchAndCompareViewConfig, ViewFilesLayout } from '../configuration'; -import { ContextKeys, NamedRef, PinnedItem, PinnedItems, setContext, WorkspaceState } from '../constants'; +import { ContextKeys, setContext } from '../constants'; import { Container } from '../container'; import { GitUri } from '../git/gitUri'; import { GitLog, GitRevision } from '../git/models'; import { SearchPattern } from '../git/search'; import { ReferencePicker, ReferencesQuickPickIncludes } from '../quickpicks'; +import { NamedRef, PinnedItem, PinnedItems, WorkspaceState } from '../storage'; import { filterMap } from '../system/array'; import { gate } from '../system/decorators/gate'; import { debug, log } from '../system/decorators/log'; @@ -355,10 +356,7 @@ export class SearchAndCompareView extends ViewBase( - WorkspaceState.ViewsSearchAndCompareKeepResults, - true, - ); + return this.container.storage.getWorkspace(WorkspaceState.ViewsSearchAndCompareKeepResults, true); } clear() { @@ -436,12 +434,12 @@ export class SearchAndCompareView extends ViewBase( + let savedPins = this.container.storage.getWorkspace( WorkspaceState.ViewsSearchAndComparePinnedItems, ); if (savedPins == null) { // Migrate any deprecated pinned items - const deprecatedPins = this.container.context.workspaceState.get( + const deprecatedPins = this.container.storage.getWorkspace( WorkspaceState.Deprecated_PinnedComparisons, ); if (deprecatedPins == null) return []; @@ -457,11 +455,8 @@ export class SearchAndCompareView extends ViewBase( - WorkspaceState.ViewsSearchAndComparePinnedItems, - ); + let pinned = this.container.storage.getWorkspace(WorkspaceState.ViewsSearchAndComparePinnedItems); if (pinned == null) { pinned = Object.create(null) as PinnedItems; } @@ -496,7 +489,7 @@ export class SearchAndCompareView extends ViewBase