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.

91 lines
2.7 KiB

  1. import type { CancellationTokenSource, Extension, ExtensionContext, Uri } from 'vscode';
  2. import { extensions } from 'vscode';
  3. import type { ActionContext, HoverCommandsActionContext } from './api/gitlens';
  4. import type { InviteToLiveShareCommandArgs } from './commands';
  5. import { Commands, CoreCommands } from './constants';
  6. import { Container } from './container';
  7. import { executeCommand, executeCoreCommand } from './system/command';
  8. import type { ContactPresence } from './vsls/vsls';
  9. export async function installExtension<T>(
  10. extensionId: string,
  11. tokenSource: CancellationTokenSource,
  12. timeout: number,
  13. vsix?: Uri,
  14. ): Promise<Extension<T> | undefined> {
  15. try {
  16. let timer: ReturnType<typeof setTimeout> | undefined = undefined;
  17. const extension = new Promise<Extension<any> | undefined>(resolve => {
  18. const disposable = extensions.onDidChange(() => {
  19. const extension = extensions.getExtension(extensionId);
  20. if (extension != null) {
  21. if (timer != null) {
  22. clearTimeout(timer);
  23. timer = undefined;
  24. }
  25. disposable.dispose();
  26. resolve(extension);
  27. }
  28. });
  29. tokenSource.token.onCancellationRequested(() => {
  30. disposable.dispose();
  31. resolve(undefined);
  32. });
  33. });
  34. await executeCoreCommand(CoreCommands.InstallExtension, vsix ?? extensionId);
  35. // Wait for extension activation until timeout expires
  36. timer = setTimeout(() => {
  37. timer = undefined;
  38. tokenSource.cancel();
  39. }, timeout);
  40. return extension;
  41. } catch {
  42. tokenSource.cancel();
  43. return undefined;
  44. }
  45. }
  46. export function registerPartnerActionRunners(context: ExtensionContext): void {
  47. registerLiveShare(context);
  48. }
  49. function registerLiveShare(context: ExtensionContext) {
  50. context.subscriptions.push(
  51. Container.instance.actionRunners.registerBuiltInPartner<HoverCommandsActionContext>(
  52. 'liveshare',
  53. 'hover.commands',
  54. {
  55. name: 'Live Share',
  56. label: (context: ActionContext) => {
  57. if (context.type === 'hover.commands') {
  58. if (context.commit.author.name !== 'You') {
  59. return `$(live-share) Invite ${context.commit.author.name}${
  60. (context.commit.author.presence as ContactPresence)?.statusText
  61. ? ` (${(context.commit.author.presence as ContactPresence)?.statusText})`
  62. : ''
  63. } to a Live Share Session`;
  64. }
  65. }
  66. return '$(live-share) Start a Live Share Session';
  67. },
  68. run: async (context: ActionContext) => {
  69. if (context.type !== 'hover.commands' || context.commit.author.name === 'You') {
  70. await executeCommand<InviteToLiveShareCommandArgs>(Commands.InviteToLiveShare, {});
  71. return;
  72. }
  73. await executeCommand<InviteToLiveShareCommandArgs>(Commands.InviteToLiveShare, {
  74. email: context.commit.author.email,
  75. });
  76. },
  77. },
  78. ),
  79. );
  80. }