You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
8.5 KiB

  1. 'use strict';
  2. import { commands, ConfigurationTarget, MessageItem, Uri, window } from 'vscode';
  3. import { Commands } from './commands';
  4. import { configuration } from './configuration';
  5. import { BuiltInCommands, CommandContext, setCommandContext } from './constants';
  6. import { GitCommit } from './git/gitService';
  7. import { Logger } from './logger';
  8. export enum SuppressedMessages {
  9. CommitHasNoPreviousCommitWarning = 'suppressCommitHasNoPreviousCommitWarning',
  10. CommitNotFoundWarning = 'suppressCommitNotFoundWarning',
  11. FileNotUnderSourceControlWarning = 'suppressFileNotUnderSourceControlWarning',
  12. GitDisabledWarning = 'suppressGitDisabledWarning',
  13. GitVersionWarning = 'suppressGitVersionWarning',
  14. LineUncommittedWarning = 'suppressLineUncommittedWarning',
  15. NoRepositoryWarning = 'suppressNoRepositoryWarning',
  16. SupportGitLensNotification = 'suppressSupportGitLensNotification'
  17. }
  18. export class Messages {
  19. static showCommitHasNoPreviousCommitWarningMessage(commit?: GitCommit): Promise<MessageItem | undefined> {
  20. if (commit === undefined) {
  21. return Messages.showMessage(
  22. 'info',
  23. 'Commit has no previous commit.',
  24. SuppressedMessages.CommitHasNoPreviousCommitWarning
  25. );
  26. }
  27. return Messages.showMessage(
  28. 'info',
  29. `Commit ${commit.shortSha} (${commit.author}, ${commit.formattedDate}) has no previous commit.`,
  30. SuppressedMessages.CommitHasNoPreviousCommitWarning
  31. );
  32. }
  33. static showCommitNotFoundWarningMessage(message: string): Promise<MessageItem | undefined> {
  34. return Messages.showMessage(
  35. 'warn',
  36. `${message}. The commit could not be found.`,
  37. SuppressedMessages.CommitNotFoundWarning
  38. );
  39. }
  40. static async showGenericErrorMessage(message: string): Promise<MessageItem | undefined> {
  41. const actions: MessageItem[] = [{ title: 'Open Output Channel' }];
  42. const result = await Messages.showMessage(
  43. 'error',
  44. `${message}. See output channel for more details`,
  45. undefined,
  46. null,
  47. ...actions
  48. );
  49. if (result !== undefined) {
  50. Logger.showOutputChannel();
  51. }
  52. return result;
  53. }
  54. static showFileNotUnderSourceControlWarningMessage(message: string): Promise<MessageItem | undefined> {
  55. return Messages.showMessage(
  56. 'warn',
  57. `${message}. The file is probably not under source control.`,
  58. SuppressedMessages.FileNotUnderSourceControlWarning
  59. );
  60. }
  61. static showGitDisabledErrorMessage() {
  62. return Messages.showMessage(
  63. 'error',
  64. 'GitLens requires Git to be enabled. Please re-enable Git \u2014 set `git.enabled` to true and reload',
  65. SuppressedMessages.GitDisabledWarning
  66. );
  67. }
  68. static showGitVersionUnsupportedErrorMessage(version: string): Promise<MessageItem | undefined> {
  69. return Messages.showMessage(
  70. 'error',
  71. `GitLens requires a newer version of Git (>= 2.2.0) than is currently installed (${version}). Please install a more recent version of Git.`,
  72. SuppressedMessages.GitVersionWarning
  73. );
  74. }
  75. static showLineUncommittedWarningMessage(message: string): Promise<MessageItem | undefined> {
  76. return Messages.showMessage(
  77. 'warn',
  78. `${message}. The line has uncommitted changes.`,
  79. SuppressedMessages.LineUncommittedWarning
  80. );
  81. }
  82. static showNoRepositoryWarningMessage(message: string): Promise<MessageItem | undefined> {
  83. return Messages.showMessage(
  84. 'warn',
  85. `${message}. No repository could be found.`,
  86. SuppressedMessages.NoRepositoryWarning
  87. );
  88. }
  89. static async showSupportGitLensMessage() {
  90. const actions: MessageItem[] = [
  91. { title: 'Become a Sponsor' },
  92. { title: 'Donate via PayPal' },
  93. { title: 'Donate via Cash App' }
  94. ];
  95. const result = await Messages.showMessage(
  96. 'info',
  97. '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! ❤',
  98. undefined,
  99. null,
  100. ...actions
  101. );
  102. if (result != null) {
  103. let uri;
  104. if (result === actions[0]) {
  105. uri = Uri.parse('https://www.patreon.com/eamodio');
  106. }
  107. else if (result === actions[1]) {
  108. uri = Uri.parse('https://www.paypal.me/eamodio');
  109. }
  110. else if (result === actions[2]) {
  111. uri = Uri.parse('https://cash.me/$eamodio');
  112. }
  113. if (uri !== undefined) {
  114. await setCommandContext(CommandContext.ViewsHideSupportGitLens, true);
  115. await this.suppressedMessage(SuppressedMessages.SupportGitLensNotification!);
  116. await commands.executeCommand(BuiltInCommands.Open, uri);
  117. }
  118. }
  119. }
  120. static async showWhatsNewMessage(version: string) {
  121. const actions: MessageItem[] = [{ title: "What's New" }, { title: 'Release Notes' }, { title: '❤' }];
  122. const result = await Messages.showMessage(
  123. 'info',
  124. `GitLens has been updated to v${version} — check out what's new!`,
  125. undefined,
  126. null,
  127. ...actions
  128. );
  129. if (result != null) {
  130. if (result === actions[0]) {
  131. await commands.executeCommand(Commands.ShowWelcomePage);
  132. }
  133. else if (result === actions[1]) {
  134. await commands.executeCommand(
  135. BuiltInCommands.Open,
  136. Uri.parse('https://github.com/eamodio/vscode-gitlens/blob/master/CHANGELOG.md')
  137. );
  138. }
  139. else if (result === actions[2]) {
  140. await commands.executeCommand(
  141. BuiltInCommands.Open,
  142. Uri.parse('https://gitlens.amod.io/#support-gitlens')
  143. );
  144. }
  145. }
  146. }
  147. private static async showMessage(
  148. type: 'info' | 'warn' | 'error',
  149. message: string,
  150. suppressionKey?: SuppressedMessages,
  151. dontShowAgain: MessageItem | null = { title: "Don't Show Again" },
  152. ...actions: MessageItem[]
  153. ): Promise<MessageItem | undefined> {
  154. Logger.log(`ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain})`);
  155. if (
  156. suppressionKey !== undefined &&
  157. configuration.get<boolean>(configuration.name('advanced')('messages')(suppressionKey).value)
  158. ) {
  159. Logger.log(`ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain}) skipped`);
  160. return undefined;
  161. }
  162. if (suppressionKey !== undefined && dontShowAgain !== null) {
  163. actions.push(dontShowAgain);
  164. }
  165. let result: MessageItem | undefined = undefined;
  166. switch (type) {
  167. case 'info':
  168. result = await window.showInformationMessage(message, ...actions);
  169. break;
  170. case 'warn':
  171. result = await window.showWarningMessage(message, ...actions);
  172. break;
  173. case 'error':
  174. result = await window.showErrorMessage(message, ...actions);
  175. break;
  176. }
  177. if ((suppressionKey !== undefined && dontShowAgain === null) || result === dontShowAgain) {
  178. Logger.log(
  179. `ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain}) don't show again requested`
  180. );
  181. await this.suppressedMessage(suppressionKey!);
  182. if (result === dontShowAgain) return undefined;
  183. }
  184. Logger.log(
  185. `ShowMessage(${type}, '${message}', ${suppressionKey}, ${dontShowAgain}) returned ${
  186. result ? result.title : result
  187. }`
  188. );
  189. return result;
  190. }
  191. private static suppressedMessage(suppressionKey: SuppressedMessages) {
  192. const section = configuration.name('advanced')('messages').value;
  193. const messages: { [key: string]: boolean | undefined } = configuration.get<{}>(section);
  194. messages[suppressionKey] = true;
  195. for (const [key, value] of Object.entries(messages)) {
  196. if (value !== true) {
  197. messages[key] = undefined;
  198. }
  199. }
  200. return configuration.update(section, messages, ConfigurationTarget.Global);
  201. }
  202. }