diff --git a/images/dark/icon-tag-selected.svg b/images/dark/icon-tag-selected.svg new file mode 100644 index 0000000..4f9ad30 --- /dev/null +++ b/images/dark/icon-tag-selected.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/images/dark/icon-tag.svg b/images/dark/icon-tag.svg index f686736..45a06d7 100644 --- a/images/dark/icon-tag.svg +++ b/images/dark/icon-tag.svg @@ -1,4 +1,4 @@ - + diff --git a/images/light/icon-tag-selected.svg b/images/light/icon-tag-selected.svg new file mode 100644 index 0000000..6ec52a4 --- /dev/null +++ b/images/light/icon-tag-selected.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/images/light/icon-tag.svg b/images/light/icon-tag.svg index 1e4bd97..5a2361f 100644 --- a/images/light/icon-tag.svg +++ b/images/light/icon-tag.svg @@ -1,4 +1,4 @@ - + diff --git a/src/commands/git/pull.ts b/src/commands/git/pull.ts index d292ae1..8fb0951 100644 --- a/src/commands/git/pull.ts +++ b/src/commands/git/pull.ts @@ -1,5 +1,5 @@ 'use strict'; -import { QuickInputButton } from 'vscode'; +import { QuickInputButton, Uri } from 'vscode'; import { Container } from '../../container'; import { Repository } from '../../git/gitService'; import { QuickCommandBase, QuickPickStep, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand'; @@ -26,8 +26,8 @@ export class PullGitCommand extends QuickCommandBase { private readonly Buttons = class { static readonly Fetch: QuickInputButton = { iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-sync.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-sync.svg') as any + dark: Uri.file(Container.context.asAbsolutePath('images/dark/icon-sync.svg')), + light: Uri.file(Container.context.asAbsolutePath('images/light/icon-sync.svg')) }, tooltip: 'Fetch' }; @@ -198,7 +198,7 @@ export class PullGitCommand extends QuickCommandBase { await repo.fetch({ progress: true }); const step = await this.getSingleRepoConfirmStep(state); quickpick.title = step.title; - quickpick.items = step.items as any; + quickpick.items = step.items as FlagsQuickPickItem[]; } finally { quickpick.busy = false; quickpick.enabled = true; diff --git a/src/commands/git/rebase.ts b/src/commands/git/rebase.ts index 980303a..ed756ad 100644 --- a/src/commands/git/rebase.ts +++ b/src/commands/git/rebase.ts @@ -1,5 +1,4 @@ 'use strict'; -import { QuickInputButton } from 'vscode'; import { Container } from '../../container'; import { GitReference, Repository } from '../../git/gitService'; import { GlyphChars } from '../../constants'; @@ -10,7 +9,8 @@ import { QuickPickStep, StepAsyncGenerator, StepSelection, - StepState + StepState, + ToggleQuickInputButton } from '../quickCommand'; import { CommitQuickPickItem, @@ -21,7 +21,7 @@ import { RefQuickPickItem, RepositoryQuickPickItem } from '../../quickpicks'; -import { Iterables, Mutable, Strings } from '../../system'; +import { Iterables, Strings } from '../../system'; import { runGitCommandInTerminal } from '../../terminal'; import { Logger } from '../../logger'; @@ -40,20 +40,14 @@ export interface RebaseGitCommandArgs { export class RebaseGitCommand extends QuickCommandBase { private readonly Buttons = class { - static readonly PickBranch: QuickInputButton = { - iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-branch.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-branch.svg') as any - }, - tooltip: 'Use the selected Branch or Tag' - }; - - static readonly PickCommit: QuickInputButton = { - iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-commit.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-commit.svg') as any - }, - tooltip: 'Choose a commit from the selected Branch or Tag' + static readonly PickBranchOrCommit = class extends ToggleQuickInputButton { + constructor(on = false) { + super( + { tooltip: 'Use the selected Branch or Tag', icon: 'branch' }, + { tooltip: 'Choose a commit from the selected Branch or Tag', icon: 'commit' }, + on + ); + } }; }; @@ -139,9 +133,9 @@ export class RebaseGitCommand extends QuickCommandBase { if (destination === undefined) break; if (state.reference === undefined || state.counter < 2) { - const pickBranchOrCommitButton: Mutable = { - ...(pickCommit ? this.Buttons.PickCommit : this.Buttons.PickBranch) - }; + const pickBranchOrCommitButton: ToggleQuickInputButton = new this.Buttons.PickBranchOrCommit( + pickCommit + ); const step = this.createPickStep({ title: `${this.title} ${destination.name}${Strings.pad(GlyphChars.Dot, 2, 2)}${ @@ -159,13 +153,7 @@ export class RebaseGitCommand extends QuickCommandBase { // eslint-disable-next-line no-loop-func onDidClickButton: (quickpick, button) => { pickCommit = !pickCommit; - - pickBranchOrCommitButton.iconPath = pickCommit - ? this.Buttons.PickCommit.iconPath - : this.Buttons.PickBranch.iconPath; - pickBranchOrCommitButton.tooltip = pickCommit - ? this.Buttons.PickCommit.tooltip - : this.Buttons.PickBranch.tooltip; + pickBranchOrCommitButton.on = pickCommit; }, onValidateValue: getValidateGitReferenceFn(state.repo) }); diff --git a/src/commands/git/search.ts b/src/commands/git/search.ts index 4d6c4ba..7d234ec 100644 --- a/src/commands/git/search.ts +++ b/src/commands/git/search.ts @@ -1,6 +1,6 @@ 'use strict'; /* eslint-disable no-loop-func */ -import { QuickInputButton } from 'vscode'; +import { QuickInputButton, Uri } from 'vscode'; import { Container } from '../../container'; import { GitLog, @@ -12,9 +12,15 @@ import { SearchPattern } from '../../git/gitService'; import { GlyphChars } from '../../constants'; -import { QuickCommandBase, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand'; +import { + QuickCommandBase, + SelectableQuickInputButton, + StepAsyncGenerator, + StepSelection, + StepState +} from '../quickCommand'; import { CommandQuickPickItem, CommitQuickPick, RepositoryQuickPickItem } from '../../quickpicks'; -import { Iterables, Mutable, Strings } from '../../system'; +import { Iterables, Strings } from '../../system'; import { Logger } from '../../logger'; import { CommitQuickPickItem, @@ -52,84 +58,44 @@ const searchOperatorToTitleMap = new Map([ export class SearchGitCommand extends QuickCommandBase { private readonly Buttons = class { - static readonly MatchCase: QuickInputButton = { - iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-match-case.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-match-case.svg') as any - }, - tooltip: 'Match Case' - }; - - static readonly MatchCaseSelected: QuickInputButton = { - iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-match-case-selected.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-match-case-selected.svg') as any - }, - tooltip: 'Match Case' - }; - - static readonly MatchAll: QuickInputButton = { - iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-match-all.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-match-all.svg') as any - }, - tooltip: 'Match All' - }; - - static readonly MatchAllSelected: QuickInputButton = { - iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-match-all-selected.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-match-all-selected.svg') as any - }, - tooltip: 'Match All' + static readonly MatchCase = class extends SelectableQuickInputButton { + constructor(on = false) { + super('Match Case', 'match-case', on); + } }; - static readonly MatchRegex: QuickInputButton = { - iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-match-regex.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-match-regex.svg') as any - }, - tooltip: 'Match using Regular Expressions' + static readonly MatchAll = class extends SelectableQuickInputButton { + constructor(on = false) { + super('Match All', 'match-all', on); + } }; - static readonly MatchRegexSelected: QuickInputButton = { - iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-match-regex-selected.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-match-regex-selected.svg') as any - }, - tooltip: 'Match using Regular Expressions' + static readonly MatchRegex = class extends SelectableQuickInputButton { + constructor(on = false) { + super('Match using Regular Expressions', 'match-regex', on); + } }; static readonly RevealInView: QuickInputButton = { iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-eye.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-eye.svg') as any + dark: Uri.file(Container.context.asAbsolutePath('images/dark/icon-eye.svg')), + light: Uri.file(Container.context.asAbsolutePath('images/light/icon-eye.svg')) }, tooltip: 'Reveal Commit in Repositories View' }; static readonly ShowInView: QuickInputButton = { iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-open.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-open.svg') as any + dark: Uri.file(Container.context.asAbsolutePath('images/dark/icon-open.svg')), + light: Uri.file(Container.context.asAbsolutePath('images/light/icon-open.svg')) }, tooltip: 'Show Commit in Search Commits View' }; - static readonly ShowResultsInView: QuickInputButton = { - iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-eye.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-eye.svg') as any - }, - tooltip: 'Show Results in Search Commits View' - }; - - static readonly ShowResultsInViewSelected: QuickInputButton = { - iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-eye-selected.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-eye-selected.svg') as any - }, - tooltip: 'Show Results in Search Commits View' + static readonly ShowResultsInView = class extends SelectableQuickInputButton { + constructor(on = false) { + super('Show Results in Search Commits View', 'eye', on); + } }; }; @@ -251,20 +217,12 @@ export class SearchGitCommand extends QuickCommandBase { ]; const titleSuffix = `${Strings.pad(GlyphChars.Dot, 2, 2)}${state.repo.formattedName}`; - const matchCaseButton: Mutable = { - ...(state.matchCase ? this.Buttons.MatchCaseSelected : this.Buttons.MatchCase) - }; - const matchAllButton: Mutable = { - ...(state.matchAll ? this.Buttons.MatchAllSelected : this.Buttons.MatchAll) - }; - const matchRegexButton: Mutable = { - ...(state.matchRegex ? this.Buttons.MatchRegexSelected : this.Buttons.MatchRegex) - }; - const showResultsInViewButton: Mutable = { - ...(state.showResultsInView - ? this.Buttons.ShowResultsInViewSelected - : this.Buttons.ShowResultsInView) - }; + const matchCaseButton: SelectableQuickInputButton = new this.Buttons.MatchCase(state.matchCase); + const matchAllButton: SelectableQuickInputButton = new this.Buttons.MatchAll(state.matchAll); + const matchRegexButton: SelectableQuickInputButton = new this.Buttons.MatchRegex(state.matchRegex); + const showResultsInViewButton: SelectableQuickInputButton = new this.Buttons.ShowResultsInView( + state.showResultsInView + ); const step = this.createPickStep>({ title: `${this.title}${titleSuffix}`, @@ -292,36 +250,28 @@ export class SearchGitCommand extends QuickCommandBase { onDidClickButton: (quickpick, button) => { if (button === matchCaseButton) { state.matchCase = !state.matchCase; - matchCaseButton.iconPath = state.matchCase - ? this.Buttons.MatchCaseSelected.iconPath - : this.Buttons.MatchCase.iconPath; + matchCaseButton.on = state.matchCase; return; } if (button === matchAllButton) { state.matchAll = !state.matchAll; - matchAllButton.iconPath = state.matchAll - ? this.Buttons.MatchAllSelected.iconPath - : this.Buttons.MatchAll.iconPath; + matchAllButton.on = state.matchAll; return; } if (button === matchRegexButton) { state.matchRegex = !state.matchRegex; - matchRegexButton.iconPath = state.matchRegex - ? this.Buttons.MatchRegexSelected.iconPath - : this.Buttons.MatchRegex.iconPath; + matchRegexButton.on = state.matchRegex; return; } if (button === showResultsInViewButton) { state.showResultsInView = !state.showResultsInView; - showResultsInViewButton.iconPath = state.showResultsInView - ? this.Buttons.ShowResultsInViewSelected.iconPath - : this.Buttons.ShowResultsInView.iconPath; + showResultsInViewButton.on = state.showResultsInView; } }, onDidChangeValue: (quickpick): boolean => { diff --git a/src/commands/git/stash.ts b/src/commands/git/stash.ts index cc3d294..fb3da66 100644 --- a/src/commands/git/stash.ts +++ b/src/commands/git/stash.ts @@ -84,8 +84,8 @@ export class StashGitCommand extends QuickCommandBase { private readonly Buttons = class { static readonly RevealInView: QuickInputButton = { iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-eye.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-eye.svg') as any + dark: Uri.file(Container.context.asAbsolutePath('images/dark/icon-eye.svg')), + light: Uri.file(Container.context.asAbsolutePath('images/light/icon-eye.svg')) }, tooltip: 'Reveal Stash in Repositories View' }; diff --git a/src/commands/git/switch.ts b/src/commands/git/switch.ts index 01c3d49..70c5a5c 100644 --- a/src/commands/git/switch.ts +++ b/src/commands/git/switch.ts @@ -1,6 +1,6 @@ 'use strict'; /* eslint-disable no-loop-func */ -import { ProgressLocation, QuickInputButton, window } from 'vscode'; +import { ProgressLocation, window } from 'vscode'; import { Container } from '../../container'; import { GitBranch, GitReference, Repository } from '../../git/gitService'; import { GlyphChars } from '../../constants'; @@ -8,12 +8,13 @@ import { getBranchesAndOrTags, getValidateGitReferenceFn, QuickCommandBase, + SelectableQuickInputButton, StepAsyncGenerator, StepSelection, StepState } from '../quickCommand'; import { ReferencesQuickPickItem, RepositoryQuickPickItem } from '../../quickpicks'; -import { Mutable, Strings } from '../../system'; +import { Strings } from '../../system'; import { Logger } from '../../logger'; interface State { @@ -31,20 +32,10 @@ export interface SwitchGitCommandArgs { export class SwitchGitCommand extends QuickCommandBase { private readonly Buttons = class { - static readonly HideTags: QuickInputButton = { - iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-tag.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-tag.svg') as any - }, - tooltip: 'Hide Tags' - }; - - static readonly ShowTags: QuickInputButton = { - iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-tag.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-tag.svg') as any - }, - tooltip: 'Show Tags' + static readonly ShowTags = class extends SelectableQuickInputButton { + constructor(on = false) { + super('Show Tags', 'tag', on); + } }; }; @@ -143,9 +134,7 @@ export class SwitchGitCommand extends QuickCommandBase { if (state.reference === undefined || state.counter < 2) { showTags = state.repos.length === 1; - const toggleTagsButton: Mutable = { - ...(showTags ? this.Buttons.HideTags : this.Buttons.ShowTags) - }; + const showTagsButton: SelectableQuickInputButton = new this.Buttons.ShowTags(showTags); const items = await getBranchesAndOrTags( state.repos, @@ -168,15 +157,13 @@ export class SwitchGitCommand extends QuickCommandBase { selectedItems: state.reference ? items.filter(ref => ref.label === state.reference!.ref) : undefined, - additionalButtons: [toggleTagsButton], + additionalButtons: [showTagsButton], onDidClickButton: async (quickpick, button) => { quickpick.busy = true; quickpick.enabled = false; showTags = !showTags; - toggleTagsButton.tooltip = showTags - ? this.Buttons.HideTags.tooltip - : this.Buttons.ShowTags.tooltip; + showTagsButton.on = showTags; quickpick.placeholder = `Choose a branch${ showTags ? ' or tag' : '' diff --git a/src/commands/gitCommands.ts b/src/commands/gitCommands.ts index 41e53e1..8df2088 100644 --- a/src/commands/gitCommands.ts +++ b/src/commands/gitCommands.ts @@ -1,5 +1,5 @@ 'use strict'; -import { Disposable, InputBox, QuickInputButton, QuickInputButtons, QuickPick, QuickPickItem, window } from 'vscode'; +import { Disposable, InputBox, QuickInputButton, QuickInputButtons, QuickPick, QuickPickItem, Uri, window } from 'vscode'; import { command, Command, Commands } from './common'; import { log } from '../system'; import { @@ -46,40 +46,40 @@ export class GitCommandsCommand extends Command { private readonly Buttons = class { static readonly CloseOnFocusOut: QuickInputButton = { iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-pin-small.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-pin-small.svg') as any + dark: Uri.file(Container.context.asAbsolutePath('images/dark/icon-pin-small.svg')), + light: Uri.file(Container.context.asAbsolutePath('images/light/icon-pin-small.svg')) }, tooltip: 'Keep Open' }; static readonly KeepOpen: QuickInputButton = { iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-pin-small-selected.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-pin-small-selected.svg') as any + dark: Uri.file(Container.context.asAbsolutePath('images/dark/icon-pin-small-selected.svg')), + light: Uri.file(Container.context.asAbsolutePath('images/light/icon-pin-small-selected.svg')) }, tooltip: 'Keep Open' }; static readonly WillConfirm: QuickInputButton = { iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-check.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-check.svg') as any + dark: Uri.file(Container.context.asAbsolutePath('images/dark/icon-check.svg')), + light: Uri.file(Container.context.asAbsolutePath('images/light/icon-check.svg')) }, tooltip: 'Will confirm' }; static readonly WillConfirmForced: QuickInputButton = { iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-check.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-check.svg') as any + dark: Uri.file(Container.context.asAbsolutePath('images/dark/icon-check.svg')), + light: Uri.file(Container.context.asAbsolutePath('images/light/icon-check.svg')) }, tooltip: 'Will always confirm' }; static readonly WillSkipConfirm: QuickInputButton = { iconPath: { - dark: Container.context.asAbsolutePath('images/dark/icon-no-check.svg') as any, - light: Container.context.asAbsolutePath('images/light/icon-no-check.svg') as any + dark: Uri.file(Container.context.asAbsolutePath('images/dark/icon-no-check.svg')), + light: Uri.file(Container.context.asAbsolutePath('images/light/icon-no-check.svg')) }, tooltip: 'Skips confirm' }; diff --git a/src/commands/quickCommand.ts b/src/commands/quickCommand.ts index d1717b2..0bca8c2 100644 --- a/src/commands/quickCommand.ts +++ b/src/commands/quickCommand.ts @@ -1,11 +1,55 @@ 'use strict'; -import { InputBox, QuickInputButton, QuickPick, QuickPickItem } from 'vscode'; +import { InputBox, QuickInputButton, QuickPick, QuickPickItem, Uri } from 'vscode'; import { Directive, DirectiveQuickPickItem } from '../quickpicks'; import { Container } from '../container'; import { Keys } from '../keyboard'; export * from './quickCommand.helpers'; +export class ToggleQuickInputButton implements QuickInputButton { + constructor( + private _off: { icon: string; tooltip: string }, + private _on: { icon: string; tooltip: string }, + private _toggled = false + ) { + this._iconPath = this.getIconPath(); + } + + private _iconPath: { light: Uri; dark: Uri }; + get iconPath(): { light: Uri; dark: Uri } { + return this._iconPath; + } + + get tooltip(): string { + return this._toggled ? this._on.tooltip : this._off.tooltip; + } + + get on() { + return this._toggled; + } + set on(value: boolean) { + this._toggled = value; + this._iconPath = this.getIconPath(); + } + + private getIconPath() { + return { + dark: Uri.file( + Container.context.asAbsolutePath(`images/dark/icon-${this.on ? this._on.icon : this._off.icon}.svg`) + ), + light: Uri.file( + Container.context.asAbsolutePath(`images/light/icon-${this.on ? this._on.icon : this._off.icon}.svg`) + ) + }; + } +} + +export class SelectableQuickInputButton extends ToggleQuickInputButton { + constructor(tooltip: string, icon: string, selected: boolean = false) { + super({ tooltip: tooltip, icon: icon }, { tooltip: tooltip, icon: `${icon}-selected` }, selected); + } +} + export class BreakQuickCommand extends Error { constructor() { super('break');