'use strict'; import { commands, ConfigurationTarget, MessageItem, Uri, window } from 'vscode'; import { Commands } from './commands'; import { configuration } from './configuration'; import { BuiltInCommands, CommandContext, setCommandContext } from './constants'; import { GitCommit } from './git/gitService'; import { Logger } from './logger'; export enum SuppressedMessages { CommitHasNoPreviousCommitWarning = 'suppressCommitHasNoPreviousCommitWarning', CommitNotFoundWarning = 'suppressCommitNotFoundWarning', FileNotUnderSourceControlWarning = 'suppressFileNotUnderSourceControlWarning', GitDisabledWarning = 'suppressGitDisabledWarning', GitVersionWarning = 'suppressGitVersionWarning', LineUncommittedWarning = 'suppressLineUncommittedWarning', NoRepositoryWarning = 'suppressNoRepositoryWarning', SupportGitLensNotification = 'suppressSupportGitLensNotification' } 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 showCommitNotFoundWarningMessage(message: string): Promise { return Messages.showMessage( 'warn', `${message}. The commit could not be found.`, SuppressedMessages.CommitNotFoundWarning ); } static async showGenericErrorMessage(message: string): Promise { const actions: MessageItem[] = [{ title: 'Open Output Channel' }]; const result = await Messages.showMessage( 'error', `${message}. See output channel for more details`, undefined, null, ...actions ); if (result !== undefined) { Logger.showOutputChannel(); } return result; } static showFileNotUnderSourceControlWarningMessage(message: string): Promise { return Messages.showMessage( 'warn', `${message}. The file is probably not under source control.`, SuppressedMessages.FileNotUnderSourceControlWarning ); } static showGitDisabledErrorMessage() { return Messages.showMessage( 'error', 'GitLens requires Git to be enabled. Please re-enable Git \u2014 set `git.enabled` to true and reload', SuppressedMessages.GitDisabledWarning ); } static showGitVersionUnsupportedErrorMessage(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 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 async showSupportGitLensMessage() { const actions: MessageItem[] = [ { title: 'Become a Sponsor' }, { title: 'Donate via PayPal' }, { title: 'Donate via Cash App' } ]; const result = await Messages.showMessage( 'info', 'While GitLens is offered to everyone for free, if you find it useful, please consider [supporting](https://gitlens.amod.io/#support-gitlens) it. Thank you! ❤', undefined, null, ...actions ); if (result != null) { let uri; if (result === actions[0]) { uri = Uri.parse('https://www.patreon.com/eamodio'); } else if (result === actions[1]) { uri = Uri.parse('https://www.paypal.me/eamodio'); } else if (result === actions[2]) { uri = Uri.parse('https://cash.me/$eamodio'); } if (uri !== undefined) { await setCommandContext(CommandContext.ViewsHideSupportGitLens, true); await this.suppressedMessage(SuppressedMessages.SupportGitLensNotification!); await commands.executeCommand(BuiltInCommands.Open, uri); } } } static async showWhatsNewMessage(version: string) { const actions: MessageItem[] = [{ title: "What's New" }, { title: 'Release Notes' }, { title: '❤' }]; const result = await Messages.showMessage( 'info', `GitLens has been updated to v${version} — check out what's new!`, undefined, null, ...actions ); if (result != null) { if (result === actions[0]) { await commands.executeCommand(Commands.ShowWelcomePage); } else if (result === actions[1]) { await commands.executeCommand( BuiltInCommands.Open, Uri.parse('https://github.com/eamodio/vscode-gitlens/blob/master/CHANGELOG.md') ); } else if (result === actions[2]) { await commands.executeCommand( BuiltInCommands.Open, Uri.parse('https://gitlens.amod.io/#support-gitlens') ); } } } private static async showMessage( type: 'info' | 'warn' | 'error', message: string, suppressionKey?: SuppressedMessages, dontShowAgain: MessageItem | null = { title: "Don't Show Again" }, ...actions: MessageItem[] ): Promise { Logger.log(`ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain})`); if ( suppressionKey !== undefined && configuration.get(configuration.name('advanced')('messages')(suppressionKey).value) ) { Logger.log(`ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain}) skipped`); return undefined; } if (suppressionKey !== undefined && dontShowAgain !== null) { actions.push(dontShowAgain); } let result: MessageItem | undefined = undefined; switch (type) { case 'info': result = await window.showInformationMessage(message, ...actions); break; case 'warn': result = await window.showWarningMessage(message, ...actions); break; case 'error': result = await window.showErrorMessage(message, ...actions); break; } if ((suppressionKey !== undefined && dontShowAgain === null) || result === dontShowAgain) { Logger.log( `ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain}) don't show again requested` ); await this.suppressedMessage(suppressionKey!); if (result === dontShowAgain) return undefined; } Logger.log( `ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain}) returned ${ result ? result.title : result }` ); return result; } private static suppressedMessage(suppressionKey: SuppressedMessages) { const section = configuration.name('advanced')('messages').value; const messages: { [key: string]: boolean | undefined } = configuration.get<{}>(section); messages[suppressionKey] = true; for (const [key, value] of Object.entries(messages)) { if (value !== true) { messages[key] = undefined; } } return configuration.update(section, messages, ConfigurationTarget.Global); } }