From 26a30c4d176ae048c7b45f817a99dc0c16802fcf Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Mon, 26 Mar 2018 12:41:52 -0400 Subject: [PATCH] Adds notification for conflicting shortcuts --- CHANGELOG.md | 1 + package.json | 7 +++- src/extension.ts | 3 +- src/messages.ts | 85 ++++++++++++++++++++++++++++++++++------------ src/ui/config.ts | 1 + src/ui/settings/index.html | 6 ++-- 6 files changed, 76 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d97c52..7c43337 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ### Added - Adds rich tooltip details to most nodes in the **GitLens** explorer and **GitLens Results** view - Adds an indicator to the *GitLens* explorer branch history to mark the synchronization point between the local and remote branch (if available) +- Adds a one-time notification on startup if the `alternate` set of keyboard shortcuts is in use, with options to easily switch to another set - Adds `${agoOrDate}` and `${authorAgoOrDate}` tokens to `gitlens.blame.format`, `gitlens.currentLine.format`, `gitlens.explorers.commitFormat`, `gitlens.explorers.stashFormat`, and `gitlens.statusBar.format` settings which will honor the `gitlens.defaultDateStyle` setting — closes [#312](https://github.com/eamodio/vscode-gitlens/issues/312) - Adds `gitlens.currentLine.scrollable` setting to specify whether the current line blame annotation can be scrolled into view when it is outside the viewport — closes [#149](https://github.com/eamodio/vscode-gitlens/issues/149), [#290](https://github.com/eamodio/vscode-gitlens/issues/290), [#265](https://github.com/eamodio/vscode-gitlens/issues/265) - Adds *Copy Commit ID to Clipboard* (`gitlens.copyShaToClipboard`) command to changed file nodes in the **GitLens** explorer and **GitLens Results** view diff --git a/package.json b/package.json index 91b3ccb..c06bd97 100644 --- a/package.json +++ b/package.json @@ -1001,7 +1001,8 @@ "suppressGitVersionWarning": false, "suppressLineUncommittedWarning": false, "suppressNoRepositoryWarning": false, - "suppressResultsExplorerNotice": false + "suppressResultsExplorerNotice": false, + "suppressShowKeyBindingsNotice": false }, "properties": { "suppressCommitHasNoPreviousCommitWarning": { @@ -1031,6 +1032,10 @@ "suppressResultsExplorerNotice": { "type": "boolean", "default": false + }, + "suppressShowKeyBindingsNotice": { + "type": "boolean", + "default": false } }, "description": "Specifies which messages should be suppressed", diff --git a/src/extension.ts b/src/extension.ts index 6be7440..7752ba9 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -61,6 +61,7 @@ export async function activate(context: ExtensionContext) { notifyOnUnsupportedGitVersion(gitVersion); showWelcomePage(gitlensVersion, previousVersion); + Messages.showKeyBindingsInfoMessage(); context.globalState.update(GlobalState.GitLensVersion, gitlensVersion); @@ -138,7 +139,7 @@ async function migrateSettings(context: ExtensionContext, previousVersion: strin if (Versions.compare(previous, Versions.from(8, 0, 0, 'beta2')) !== 1) { await configuration.migrate( 'debug', configuration.name('outputLevel').value, - { migrationFn: v => v ? OutputLevel.Debug : configuration.get(configuration.name('outputLevel').value) }); + { migrationFn: v => v ? OutputLevel.Debug : configuration.get(configuration.name('outputLevel').value) }); await configuration.migrate('debug', configuration.name('debug').value, { migrationFn: v => undefined }); } diff --git a/src/messages.ts b/src/messages.ts index 7a9fd0b..398c7a1 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -1,8 +1,9 @@ 'use strict'; -import { ConfigurationTarget, window } from 'vscode'; +import { ConfigurationTarget, MessageItem, window } from 'vscode'; +import { configuration, KeyMap } from './configuration'; +import { Container } from './container'; import { GitCommit } from './gitService'; import { Logger } from './logger'; -import { configuration } from './configuration'; export enum SuppressedMessages { CommitHasNoPreviousCommitWarning = 'suppressCommitHasNoPreviousCommitWarning', @@ -11,41 +12,81 @@ export enum SuppressedMessages { GitVersionWarning = 'suppressGitVersionWarning', LineUncommittedWarning = 'suppressLineUncommittedWarning', NoRepositoryWarning = 'suppressNoRepositoryWarning', - ResultsExplorerNotice = 'suppressResultsExplorerNotice' + ResultsExplorerNotice = 'suppressResultsExplorerNotice', + ShowKeyBindingsNotice = 'suppressShowKeyBindingsNotice' } export class Messages { - static showCommitHasNoPreviousCommitWarningMessage(commit?: GitCommit): Promise { - if (commit === undefined) return Messages.showMessage('info', `Commit has no previous commit`, SuppressedMessages.CommitHasNoPreviousCommitWarning); - return Messages.showMessage('info', `Commit ${commit.shortSha} (${commit.author}, ${commit.formattedDate}) has no previous commit`, SuppressedMessages.CommitHasNoPreviousCommitWarning); + static showCommitHasNoPreviousCommitWarningMessage(commit?: GitCommit): Promise { + if (commit === undefined) return Messages.showMessage('info', `Commit has no previous commit.`, SuppressedMessages.CommitHasNoPreviousCommitWarning); + return Messages.showMessage('info', `Commit ${commit.shortSha} (${commit.author}, ${commit.formattedDate}) has no previous commit.`, SuppressedMessages.CommitHasNoPreviousCommitWarning); } - static showCommitNotFoundWarningMessage(message: string): Promise { - return Messages.showMessage('warn', `${message}. The commit could not be found`, SuppressedMessages.CommitNotFoundWarning); + static showCommitNotFoundWarningMessage(message: string): Promise { + return Messages.showMessage('warn', `${message}. The commit could not be found.`, SuppressedMessages.CommitNotFoundWarning); } - static showFileNotUnderSourceControlWarningMessage(message: string): Promise { - return Messages.showMessage('warn', `${message}. The file is probably not under source control`, SuppressedMessages.FileNotUnderSourceControlWarning); + static showFileNotUnderSourceControlWarningMessage(message: string): Promise { + return Messages.showMessage('warn', `${message}. The file is probably not under source control.`, SuppressedMessages.FileNotUnderSourceControlWarning); } - static showLineUncommittedWarningMessage(message: string): Promise { - return Messages.showMessage('warn', `${message}. The line has uncommitted changes`, SuppressedMessages.LineUncommittedWarning); + static async showKeyBindingsInfoMessage(): Promise { + const section = configuration.name('advanced')('messages').value; + const messages: { [key: string]: boolean } = configuration.get<{}>(section); + + if (messages[SuppressedMessages.ShowKeyBindingsNotice]) return undefined; + + if (Container.config.keymap !== KeyMap.Alternate) { + messages[SuppressedMessages.ShowKeyBindingsNotice] = true; + await configuration.update(section, messages, ConfigurationTarget.Global); + + return undefined; + } + + const actions: MessageItem[] = [ + { title: 'Keep Shortcuts', isCloseAffordance: true }, + { title: 'Switch Shortcuts' }, + { title: 'No Shortcuts' } + ]; + const result = await Messages.showMessage( + 'info', + `GitLens is using keyboard shortcuts which can conflict with menu mnemonics and different keyboard layouts. To avoid such conflicts, it is recommended to switch to the new default keyboard shortcuts.`, + SuppressedMessages.ShowKeyBindingsNotice, + null, + ...actions + ); + + switch (result) { + case actions[1]: + await configuration.update(configuration.name('keymap').value, KeyMap.Chorded, ConfigurationTarget.Global); + break; + + case actions[2]: + await configuration.update(configuration.name('keymap').value, KeyMap.None, ConfigurationTarget.Global); + break; + } + + return result; + } + + static showLineUncommittedWarningMessage(message: string): Promise { + return Messages.showMessage('warn', `${message}. The line has uncommitted changes.`, SuppressedMessages.LineUncommittedWarning); } - static showNoRepositoryWarningMessage(message: string): Promise { - return Messages.showMessage('warn', `${message}. No repository could be found`, SuppressedMessages.NoRepositoryWarning); + static showNoRepositoryWarningMessage(message: string): Promise { + return Messages.showMessage('warn', `${message}. No repository could be found.`, SuppressedMessages.NoRepositoryWarning); } - static showResultExplorerInfoMessage(): Promise { - return Messages.showMessage('info', `If you can't find your results, click on "GITLENS RESULTS" at the bottom of the Explorer view`, SuppressedMessages.ResultsExplorerNotice, null); + static showResultExplorerInfoMessage(): Promise { + return Messages.showMessage('info', `If you can't find your results, click on "GITLENS RESULTS" at the bottom of the Explorer view.`, SuppressedMessages.ResultsExplorerNotice, null); } - static showUnsupportedGitVersionErrorMessage(version: string): Promise { - return Messages.showMessage('error', `GitLens requires a newer version of Git (>= 2.2.0) than is currently installed (${version}). Please install a more recent version of Git`, SuppressedMessages.GitVersionWarning); + static showUnsupportedGitVersionErrorMessage(version: string): Promise { + return Messages.showMessage('error', `GitLens requires a newer version of Git (>= 2.2.0) than is currently installed (${version}). Please install a more recent version of Git.`, SuppressedMessages.GitVersionWarning); } - private static async showMessage(type: 'info' | 'warn' | 'error', message: string, suppressionKey: SuppressedMessages, dontShowAgain: string | null = 'Don\'t Show Again', ...actions: any[]): Promise { + private static async showMessage(type: 'info' | 'warn' | 'error', message: string, suppressionKey: SuppressedMessages, dontShowAgain: T | null = { title: 'Don\'t Show Again' } as T, ...actions: T[]): Promise { Logger.log(`ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain})`); if (configuration.get(configuration.name('advanced')('messages')(suppressionKey).value)) { @@ -57,7 +98,7 @@ export class Messages { actions.push(dontShowAgain); } - let result: string | undefined = undefined; + let result: T | undefined = undefined; switch (type) { case 'info': result = await window.showInformationMessage(message, ...actions); @@ -76,14 +117,14 @@ export class Messages { Logger.log(`ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain}) don't show again requested`); const section = configuration.name('advanced')('messages').value; - const messages: { [key: string]: boolean } = configuration.get(section); + const messages: { [key: string]: boolean } = configuration.get<{}>(section); messages[suppressionKey] = true; await configuration.update(section, messages, ConfigurationTarget.Global); if (result === dontShowAgain) return undefined; } - Logger.log(`ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain}) returned ${result}`); + Logger.log(`ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain}) returned ${result ? result.title : result}`); return result; } } \ No newline at end of file diff --git a/src/ui/config.ts b/src/ui/config.ts index f4551d2..743816e 100644 --- a/src/ui/config.ts +++ b/src/ui/config.ts @@ -152,6 +152,7 @@ export interface IAdvancedConfig { suppressLineUncommittedWarning: boolean; suppressNoRepositoryWarning: boolean; suppressResultsExplorerNotice: boolean; + suppressShowKeyBindingsNotice: boolean; }; quickPick: { diff --git a/src/ui/settings/index.html b/src/ui/settings/index.html index 8debfdb..c54192a 100644 --- a/src/ui/settings/index.html +++ b/src/ui/settings/index.html @@ -631,9 +631,9 @@