mirror of
https://github.com/microsoft/vscode.git
synced 2026-02-15 07:28:05 +00:00
SCM - graph hover provided by extension (#271519)
* Git - 💄 consolidate git blame and timeline hover code * Git - Delete code that was commented out * SCM - graph hover provided by extension * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * More fixes * More fixes --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -12,7 +12,7 @@ import { AvatarQuery, AvatarQueryCommit, Branch, LogOptions, Ref, RefType } from
|
||||
import { emojify, ensureEmojis } from './emoji';
|
||||
import { Commit, CommitShortStat } from './git';
|
||||
import { OperationKind, OperationResult } from './operation';
|
||||
import { ISourceControlHistoryItemDetailsProviderRegistry, provideSourceControlHistoryItemAvatar, provideSourceControlHistoryItemMessageLinks } from './historyItemDetailsProvider';
|
||||
import { ISourceControlHistoryItemDetailsProviderRegistry, provideSourceControlHistoryItemAvatar, provideSourceControlHistoryItemHoverCommands, provideSourceControlHistoryItemMessageLinks } from './historyItemDetailsProvider';
|
||||
import { throttle } from './decorators';
|
||||
|
||||
function compareSourceControlHistoryItemRef(ref1: SourceControlHistoryItemRef, ref2: SourceControlHistoryItemRef): number {
|
||||
@@ -282,6 +282,8 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec
|
||||
const commitAvatars = await provideSourceControlHistoryItemAvatar(
|
||||
this.historyItemDetailProviderRegistry, this.repository, avatarQuery);
|
||||
|
||||
const remoteHoverCommands = await provideSourceControlHistoryItemHoverCommands(this.historyItemDetailProviderRegistry, this.repository) ?? [];
|
||||
|
||||
await ensureEmojis();
|
||||
|
||||
const historyItems: SourceControlHistoryItem[] = [];
|
||||
@@ -293,6 +295,13 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec
|
||||
const avatarUrl = commitAvatars?.get(commit.hash);
|
||||
const references = this._resolveHistoryItemRefs(commit);
|
||||
|
||||
const commands: Command[][] = [
|
||||
getHistoryItemHoverCommitHashCommands(Uri.file(this.repository.root), commit.hash),
|
||||
processHistoryItemRemoteHoverCommands(remoteHoverCommands, commit.hash)
|
||||
];
|
||||
|
||||
const tooltip = getHistoryItemHover(avatarUrl, commit.authorName, commit.authorEmail, commit.authorDate ?? commit.commitDate, messageWithLinks, commit.shortStat, commands);
|
||||
|
||||
historyItems.push({
|
||||
id: commit.hash,
|
||||
parentIds: commit.parents,
|
||||
@@ -304,7 +313,8 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec
|
||||
displayId: truncate(commit.hash, this.commitShortHashLength, false),
|
||||
timestamp: commit.authorDate?.getTime(),
|
||||
statistics: commit.shortStat ?? { files: 0, insertions: 0, deletions: 0 },
|
||||
references: references.length !== 0 ? references : undefined
|
||||
references: references.length !== 0 ? references : undefined,
|
||||
tooltip
|
||||
} satisfies SourceControlHistoryItem);
|
||||
}
|
||||
|
||||
@@ -663,6 +673,17 @@ export function getHistoryItemHover(authorAvatar: string | undefined, authorName
|
||||
markdownString.appendMarkdown(`\n\n---\n\n`);
|
||||
}
|
||||
|
||||
// References
|
||||
// TODO@lszomoru - move these to core
|
||||
// if (references && references.length > 0) {
|
||||
// markdownString.appendMarkdown((references ?? []).map(ref => {
|
||||
// console.log(ref);
|
||||
// const labelIconId = ref.icon instanceof ThemeIcon ? ref.icon.id : '';
|
||||
// return `<span style="color:var(--vscode-scmGraph-historyItemHoverDefaultLabelForeground);background-color:var(--vscode-scmGraph-historyItemHoverDefaultLabelBackground);border-radius:10px;"> $(${labelIconId}) ${ref.name} </span>`;
|
||||
// }).join(' '));
|
||||
// markdownString.appendMarkdown(`\n\n---\n\n`);
|
||||
// }
|
||||
|
||||
// Commands
|
||||
if (commands && commands.length > 0) {
|
||||
for (let index = 0; index < commands.length; index++) {
|
||||
@@ -676,21 +697,5 @@ export function getHistoryItemHover(authorAvatar: string | undefined, authorName
|
||||
}
|
||||
}
|
||||
|
||||
// markdownString.appendMarkdown(`[\`$(git-commit) ${getCommitShortHash(documentUri, hash)} \`](command:git.viewCommit?${encodeURIComponent(JSON.stringify([documentUri, hash, documentUri]))} "${l10n.t('Open Commit')}")`);
|
||||
// markdownString.appendMarkdown(' ');
|
||||
// markdownString.appendMarkdown(`[$(copy)](command:git.copyContentToClipboard?${encodeURIComponent(JSON.stringify(hash))} "${l10n.t('Copy Commit Hash')}")`);
|
||||
|
||||
// // Remote hover commands
|
||||
// if (commands && commands.length > 0) {
|
||||
// markdownString.appendMarkdown(' | ');
|
||||
|
||||
// const remoteCommandsMarkdown = commands
|
||||
// .map(command => `[${command.title}](command:${command.command}?${encodeURIComponent(JSON.stringify([...command.arguments ?? [], hash]))} "${command.tooltip}")`);
|
||||
// markdownString.appendMarkdown(remoteCommandsMarkdown.join(' '));
|
||||
// }
|
||||
|
||||
// markdownString.appendMarkdown(' | ');
|
||||
// markdownString.appendMarkdown(`[$(gear)](command:workbench.action.openSettings?%5B%22git.blame%22%5D "${l10n.t('Open Settings')}")`);
|
||||
|
||||
return markdownString;
|
||||
}
|
||||
|
||||
@@ -157,13 +157,6 @@
|
||||
"group": "0_view@2"
|
||||
}
|
||||
],
|
||||
"scm/historyItem/hover": [
|
||||
{
|
||||
"command": "github.graph.openOnGitHub",
|
||||
"when": "github.hasGitHubRepo",
|
||||
"group": "1_open@1"
|
||||
}
|
||||
],
|
||||
"timeline/item/context": [
|
||||
{
|
||||
"command": "github.timeline.openOnGitHub",
|
||||
|
||||
@@ -145,7 +145,6 @@ export class MenuId {
|
||||
static readonly SCMHistoryTitle = new MenuId('SCMHistoryTitle');
|
||||
static readonly SCMHistoryItemContext = new MenuId('SCMHistoryItemContext');
|
||||
static readonly SCMHistoryItemChangeContext = new MenuId('SCMHistoryItemChangeContext');
|
||||
static readonly SCMHistoryItemHover = new MenuId('SCMHistoryItemHover');
|
||||
static readonly SCMHistoryItemRefContext = new MenuId('SCMHistoryItemRefContext');
|
||||
static readonly SCMQuickDiffDecorations = new MenuId('SCMQuickDiffDecorations');
|
||||
static readonly SCMTitle = new MenuId('SCMTitle');
|
||||
|
||||
@@ -1661,6 +1661,7 @@ export interface SCMHistoryItemDto {
|
||||
readonly deletions: number;
|
||||
};
|
||||
readonly references?: SCMHistoryItemRefDto[];
|
||||
readonly tooltip?: string | IMarkdownString | undefined;
|
||||
}
|
||||
|
||||
export interface SCMHistoryItemChangeDto {
|
||||
|
||||
@@ -75,11 +75,13 @@ function getHistoryItemIconDto(icon: vscode.Uri | { light: vscode.Uri; dark: vsc
|
||||
|
||||
function toSCMHistoryItemDto(historyItem: vscode.SourceControlHistoryItem): SCMHistoryItemDto {
|
||||
const authorIcon = getHistoryItemIconDto(historyItem.authorIcon);
|
||||
const tooltip = MarkdownString.fromStrict(historyItem.tooltip);
|
||||
|
||||
const references = historyItem.references?.map(r => ({
|
||||
...r, icon: getHistoryItemIconDto(r.icon)
|
||||
}));
|
||||
|
||||
return { ...historyItem, authorIcon, references };
|
||||
return { ...historyItem, authorIcon, references, tooltip };
|
||||
}
|
||||
|
||||
function toSCMHistoryItemRefDto(historyItemRef?: vscode.SourceControlHistoryItemRef): SCMHistoryItemRefDto | undefined {
|
||||
|
||||
@@ -49,7 +49,7 @@ import { IPreferencesService } from '../../../services/preferences/common/prefer
|
||||
import { revealInSideBarCommand } from '../../files/browser/fileActions.contribution.js';
|
||||
import { CellUri } from '../../notebook/common/notebookCommon.js';
|
||||
import { INotebookService } from '../../notebook/common/notebookService.js';
|
||||
import { getHistoryItemEditorTitle, getHistoryItemHoverContent } from '../../scm/browser/util.js';
|
||||
import { getHistoryItemEditorTitle } from '../../scm/browser/util.js';
|
||||
import { IChatContentReference } from '../common/chatService.js';
|
||||
import { IChatRequestPasteVariableEntry, IChatRequestVariableEntry, IElementVariableEntry, INotebookOutputVariableEntry, IPromptFileVariableEntry, IPromptTextVariableEntry, ISCMHistoryItemVariableEntry, OmittedState, PromptFileVariableKind, ChatRequestToolReferenceEntry, ISCMHistoryItemChangeVariableEntry, ISCMHistoryItemChangeRangeVariableEntry } from '../common/chatVariableEntries.js';
|
||||
import { ILanguageModelChatMetadataAndIdentifier, ILanguageModelsService } from '../common/languageModels.js';
|
||||
@@ -790,7 +790,12 @@ export class SCMHistoryItemAttachmentWidget extends AbstractChatAttachmentWidget
|
||||
this.element.style.cursor = 'pointer';
|
||||
this.element.ariaLabel = localize('chat.attachment', "Attached context, {0}", attachment.name);
|
||||
|
||||
this._store.add(hoverService.setupManagedHover(hoverDelegate, this.element, () => getHistoryItemHoverContent(themeService, attachment.historyItem), { trapFocus: true }));
|
||||
const historyItem = attachment.historyItem;
|
||||
const hoverContent = {
|
||||
markdown: historyItem.tooltip ?? historyItem.message,
|
||||
markdownNotSupportedFallback: historyItem.message
|
||||
} satisfies IManagedHoverTooltipMarkdownString;
|
||||
this._store.add(hoverService.setupManagedHover(hoverDelegate, this.element, hoverContent, { trapFocus: true }));
|
||||
|
||||
this._store.add(dom.addDisposableListener(this.element, dom.EventType.CLICK, (e: MouseEvent) => {
|
||||
dom.EventHelper.stop(e, true);
|
||||
@@ -835,7 +840,13 @@ export class SCMHistoryItemChangeAttachmentWidget extends AbstractChatAttachment
|
||||
this.label.setFile(attachment.value, { fileKind: FileKind.FILE, hidePath: true, nameSuffix });
|
||||
|
||||
this.element.ariaLabel = localize('chat.attachment', "Attached context, {0}", attachment.name);
|
||||
this._store.add(hoverService.setupManagedHover(hoverDelegate, this.element, () => getHistoryItemHoverContent(themeService, attachment.historyItem), { trapFocus: true }));
|
||||
|
||||
const historyItem = attachment.historyItem;
|
||||
const hoverContent = {
|
||||
markdown: historyItem.tooltip ?? historyItem.message,
|
||||
markdownNotSupportedFallback: historyItem.message
|
||||
} satisfies IManagedHoverTooltipMarkdownString;
|
||||
this._store.add(hoverService.setupManagedHover(hoverDelegate, this.element, hoverContent, { trapFocus: true }));
|
||||
|
||||
this.addResourceOpenHandlers(attachment.value, undefined);
|
||||
this.attachClearButton();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import './media/scm.css';
|
||||
import { $, append, h, reset } from '../../../../base/browser/dom.js';
|
||||
import { IHoverAction, IHoverOptions } from '../../../../base/browser/ui/hover/hover.js';
|
||||
import { IHoverOptions, IManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js';
|
||||
import { IHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegate.js';
|
||||
import { IconLabel } from '../../../../base/browser/ui/iconLabel/iconLabel.js';
|
||||
import { IIdentityProvider, IListVirtualDelegate } from '../../../../base/browser/ui/list/list.js';
|
||||
@@ -29,7 +29,7 @@ import { IFileIconTheme, IThemeService } from '../../../../platform/theme/common
|
||||
import { IViewPaneOptions, ViewAction, ViewPane, ViewPaneShowActions } from '../../../browser/parts/views/viewPane.js';
|
||||
import { IViewDescriptorService, ViewContainerLocation } from '../../../common/views.js';
|
||||
import { renderSCMHistoryItemGraph, toISCMHistoryItemViewModelArray, SWIMLANE_WIDTH, renderSCMHistoryGraphPlaceholder, historyItemHoverLabelForeground, historyItemHoverDefaultLabelBackground, getHistoryItemIndex } from './scmHistory.js';
|
||||
import { getHistoryItemEditorTitle, getHistoryItemHoverContent, getProviderKey, isSCMHistoryItemChangeNode, isSCMHistoryItemChangeViewModelTreeElement, isSCMHistoryItemLoadMoreTreeElement, isSCMHistoryItemViewModelTreeElement, isSCMRepository } from './util.js';
|
||||
import { getHistoryItemEditorTitle, getProviderKey, isSCMHistoryItemChangeNode, isSCMHistoryItemChangeViewModelTreeElement, isSCMHistoryItemLoadMoreTreeElement, isSCMHistoryItemViewModelTreeElement, isSCMRepository } from './util.js';
|
||||
import { ISCMHistoryItem, ISCMHistoryItemChange, ISCMHistoryItemGraphNode, ISCMHistoryItemRef, ISCMHistoryItemViewModel, ISCMHistoryProvider, SCMHistoryItemChangeViewModelTreeElement, SCMHistoryItemLoadMoreTreeElement, SCMHistoryItemViewModelTreeElement } from '../common/history.js';
|
||||
import { HISTORY_VIEW_PANE_ID, ISCMProvider, ISCMRepository, ISCMService, ISCMViewService, ViewMode } from '../common/scm.js';
|
||||
import { IListAccessibilityProvider } from '../../../../base/browser/ui/list/listWidget.js';
|
||||
@@ -53,7 +53,6 @@ import { Iterable } from '../../../../base/common/iterator.js';
|
||||
import { clamp } from '../../../../base/common/numbers.js';
|
||||
import { observableConfigValue } from '../../../../platform/observable/common/platformObservableUtils.js';
|
||||
import { compare } from '../../../../base/common/strings.js';
|
||||
import { IClipboardService } from '../../../../platform/clipboard/common/clipboardService.js';
|
||||
import { getDefaultHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegateFactory.js';
|
||||
import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
|
||||
import { IExtensionService } from '../../../services/extensions/common/extensions.js';
|
||||
@@ -408,7 +407,6 @@ class HistoryItemRenderer implements ICompressibleTreeRenderer<SCMHistoryItemVie
|
||||
|
||||
constructor(
|
||||
private readonly hoverDelegate: IHoverDelegate,
|
||||
@IClipboardService private readonly _clipboardService: IClipboardService,
|
||||
@ICommandService private readonly _commandService: ICommandService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
|
||||
@@ -416,8 +414,7 @@ class HistoryItemRenderer implements ICompressibleTreeRenderer<SCMHistoryItemVie
|
||||
@IHoverService private readonly _hoverService: IHoverService,
|
||||
@IKeybindingService private readonly _keybindingService: IKeybindingService,
|
||||
@IMenuService private readonly _menuService: IMenuService,
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService,
|
||||
@IThemeService private readonly _themeService: IThemeService
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService
|
||||
) {
|
||||
this._badgesConfig = observableConfigValue<'all' | 'filter'>('scm.graph.badges', 'filter', this._configurationService);
|
||||
}
|
||||
@@ -445,9 +442,11 @@ class HistoryItemRenderer implements ICompressibleTreeRenderer<SCMHistoryItemVie
|
||||
const historyItemViewModel = node.element.historyItemViewModel;
|
||||
const historyItem = historyItemViewModel.historyItem;
|
||||
|
||||
const historyItemHover = this._hoverService.setupManagedHover(this.hoverDelegate, templateData.element, getHistoryItemHoverContent(this._themeService, historyItem), {
|
||||
actions: this._getHoverActions(provider, historyItem),
|
||||
});
|
||||
const hoverContent = {
|
||||
markdown: historyItem.tooltip ?? historyItem.message,
|
||||
markdownNotSupportedFallback: historyItem.message
|
||||
} satisfies IManagedHoverTooltipMarkdownString;
|
||||
const historyItemHover = this._hoverService.setupManagedHover(this.hoverDelegate, templateData.element, hoverContent);
|
||||
templateData.elementDisposables.add(historyItemHover);
|
||||
|
||||
templateData.graphContainer.textContent = '';
|
||||
@@ -546,34 +545,6 @@ class HistoryItemRenderer implements ICompressibleTreeRenderer<SCMHistoryItemVie
|
||||
append(templateData.labelContainer, elements.root);
|
||||
}
|
||||
|
||||
private _getHoverActions(provider: ISCMProvider, historyItem: ISCMHistoryItem): IHoverAction[] {
|
||||
const actions = this._menuService.getMenuActions(MenuId.SCMHistoryItemHover, this._contextKeyService, {
|
||||
arg: provider,
|
||||
shouldForwardArgs: true
|
||||
}).flatMap(item => item[1]);
|
||||
|
||||
return [
|
||||
{
|
||||
commandId: 'workbench.scm.action.graph.copyHistoryItemId',
|
||||
iconClass: 'codicon.codicon-copy',
|
||||
label: historyItem.displayId ?? historyItem.id,
|
||||
run: () => this._clipboardService.writeText(historyItem.id)
|
||||
},
|
||||
...actions.map(action => {
|
||||
const iconClass = ThemeIcon.isThemeIcon(action.item.icon)
|
||||
? ThemeIcon.asClassNameArray(action.item.icon).join('.')
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
commandId: action.id,
|
||||
label: action.label,
|
||||
iconClass,
|
||||
run: () => action.run(historyItem)
|
||||
};
|
||||
}) satisfies IHoverAction[]
|
||||
];
|
||||
}
|
||||
|
||||
private _processMatches(historyItemViewModel: ISCMHistoryItemViewModel, filterData: LabelFuzzyScore | undefined): [IMatch[] | undefined, IMatch[] | undefined] {
|
||||
if (!filterData) {
|
||||
return [undefined, undefined];
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from '../../../../nls.js';
|
||||
import * as platform from '../../../../base/common/platform.js';
|
||||
import { ISCMHistoryItem, SCMHistoryItemChangeViewModelTreeElement, SCMHistoryItemLoadMoreTreeElement, SCMHistoryItemViewModelTreeElement } from '../common/history.js';
|
||||
import { ISCMResource, ISCMRepository, ISCMResourceGroup, ISCMInput, ISCMActionButton, ISCMViewService, ISCMProvider } from '../common/scm.js';
|
||||
import { IMenu, MenuItemAction } from '../../../../platform/actions/common/actions.js';
|
||||
@@ -20,14 +18,6 @@ import { Command } from '../../../../editor/common/languages.js';
|
||||
import { reset } from '../../../../base/browser/dom.js';
|
||||
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
|
||||
import { IResourceNode, ResourceTree } from '../../../../base/common/resourceTree.js';
|
||||
import { IThemeService } from '../../../../platform/theme/common/themeService.js';
|
||||
import { IManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js';
|
||||
import { MarkdownString } from '../../../../base/common/htmlContent.js';
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
import { ThemeIcon } from '../../../../base/common/themables.js';
|
||||
import { fromNow, safeIntl } from '../../../../base/common/date.js';
|
||||
import { historyItemHoverAdditionsForeground, historyItemHoverDefaultLabelBackground, historyItemHoverDefaultLabelForeground, historyItemHoverDeletionsForeground, historyItemHoverLabelForeground } from './scmHistory.js';
|
||||
import { asCssVariable } from '../../../../platform/theme/common/colorUtils.js';
|
||||
|
||||
export function isSCMViewService(element: any): element is ISCMViewService {
|
||||
return Array.isArray((element as ISCMViewService).repositories) && Array.isArray((element as ISCMViewService).visibleRepositories);
|
||||
@@ -156,68 +146,3 @@ export function getRepositoryResourceCount(provider: ISCMProvider): number {
|
||||
export function getHistoryItemEditorTitle(historyItem: ISCMHistoryItem): string {
|
||||
return `${historyItem.displayId ?? historyItem.id} - ${historyItem.subject}`;
|
||||
}
|
||||
|
||||
export function getHistoryItemHoverContent(themeService: IThemeService, historyItem: ISCMHistoryItem): IManagedHoverTooltipMarkdownString {
|
||||
const colorTheme = themeService.getColorTheme();
|
||||
const markdown = new MarkdownString('', { isTrusted: true, supportThemeIcons: true });
|
||||
|
||||
if (historyItem.author) {
|
||||
const icon = URI.isUri(historyItem.authorIcon)
|
||||
? `}|width=20,height=20)`
|
||||
: ThemeIcon.isThemeIcon(historyItem.authorIcon)
|
||||
? `$(${historyItem.authorIcon.id})`
|
||||
: '$(account)';
|
||||
|
||||
if (historyItem.authorEmail) {
|
||||
const emailTitle = localize('emailLinkTitle', "Email");
|
||||
markdown.appendMarkdown(`${icon} [**${historyItem.author}**](mailto:${historyItem.authorEmail} "${emailTitle} ${historyItem.author}")`);
|
||||
} else {
|
||||
markdown.appendMarkdown(`${icon} **${historyItem.author}**`);
|
||||
}
|
||||
|
||||
if (historyItem.timestamp) {
|
||||
const dateFormatter = safeIntl.DateTimeFormat(platform.language, { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' }).value;
|
||||
markdown.appendMarkdown(`, $(history) ${fromNow(historyItem.timestamp, true, true)} (${dateFormatter.format(historyItem.timestamp)})`);
|
||||
}
|
||||
|
||||
markdown.appendMarkdown('\n\n');
|
||||
}
|
||||
|
||||
markdown.appendMarkdown(`${historyItem.message.replace(/\r\n|\r|\n/g, '\n\n')}\n\n`);
|
||||
|
||||
if (historyItem.statistics) {
|
||||
markdown.appendMarkdown(`---\n\n`);
|
||||
|
||||
markdown.appendMarkdown(`<span>${historyItem.statistics.files === 1 ?
|
||||
localize('fileChanged', "{0} file changed", historyItem.statistics.files) :
|
||||
localize('filesChanged', "{0} files changed", historyItem.statistics.files)}</span>`);
|
||||
|
||||
if (historyItem.statistics.insertions) {
|
||||
const additionsForegroundColor = colorTheme.getColor(historyItemHoverAdditionsForeground);
|
||||
markdown.appendMarkdown(`, <span style="color:${additionsForegroundColor};">${historyItem.statistics.insertions === 1 ?
|
||||
localize('insertion', "{0} insertion{1}", historyItem.statistics.insertions, '(+)') :
|
||||
localize('insertions', "{0} insertions{1}", historyItem.statistics.insertions, '(+)')}</span>`);
|
||||
}
|
||||
|
||||
if (historyItem.statistics.deletions) {
|
||||
const deletionsForegroundColor = colorTheme.getColor(historyItemHoverDeletionsForeground);
|
||||
markdown.appendMarkdown(`, <span style="color:${deletionsForegroundColor};">${historyItem.statistics.deletions === 1 ?
|
||||
localize('deletion', "{0} deletion{1}", historyItem.statistics.deletions, '(-)') :
|
||||
localize('deletions', "{0} deletions{1}", historyItem.statistics.deletions, '(-)')}</span>`);
|
||||
}
|
||||
}
|
||||
|
||||
if ((historyItem.references ?? []).length > 0) {
|
||||
markdown.appendMarkdown(`\n\n---\n\n`);
|
||||
markdown.appendMarkdown((historyItem.references ?? []).map(ref => {
|
||||
const labelIconId = ThemeIcon.isThemeIcon(ref.icon) ? ref.icon.id : '';
|
||||
|
||||
const labelBackgroundColor = ref.color ? asCssVariable(ref.color) : asCssVariable(historyItemHoverDefaultLabelBackground);
|
||||
const labelForegroundColor = ref.color ? asCssVariable(historyItemHoverLabelForeground) : asCssVariable(historyItemHoverDefaultLabelForeground);
|
||||
|
||||
return `<span style="color:${labelForegroundColor};background-color:${labelBackgroundColor};border-radius:10px;"> $(${labelIconId}) ${ref.name} </span>`;
|
||||
}).join(' '));
|
||||
}
|
||||
|
||||
return { markdown, markdownNotSupportedFallback: historyItem.message };
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CancellationToken } from '../../../../base/common/cancellation.js';
|
||||
import { IMarkdownString } from '../../../../base/common/htmlContent.js';
|
||||
import { IObservable } from '../../../../base/common/observable.js';
|
||||
import { ThemeIcon } from '../../../../base/common/themables.js';
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
@@ -73,6 +74,7 @@ export interface ISCMHistoryItem {
|
||||
readonly timestamp?: number;
|
||||
readonly statistics?: ISCMHistoryItemStatistics;
|
||||
readonly references?: ISCMHistoryItemRef[];
|
||||
readonly tooltip?: string | IMarkdownString | undefined;
|
||||
}
|
||||
|
||||
export interface ISCMHistoryItemGraphNode {
|
||||
|
||||
@@ -192,12 +192,6 @@ const apiMenus: IAPIMenu[] = [
|
||||
description: localize('menus.historyItemContext', "The Source Control history item context menu"),
|
||||
proposed: 'contribSourceControlHistoryItemMenu'
|
||||
},
|
||||
{
|
||||
key: 'scm/historyItem/hover',
|
||||
id: MenuId.SCMHistoryItemHover,
|
||||
description: localize('menus.historyItemHover', "The Source Control history item hover menu"),
|
||||
proposed: 'contribSourceControlHistoryItemMenu'
|
||||
},
|
||||
{
|
||||
key: 'scm/historyItemRef/context',
|
||||
id: MenuId.SCMHistoryItemRefContext,
|
||||
|
||||
@@ -61,6 +61,7 @@ declare module 'vscode' {
|
||||
readonly timestamp?: number;
|
||||
readonly statistics?: SourceControlHistoryItemStatistics;
|
||||
readonly references?: SourceControlHistoryItemRef[];
|
||||
readonly tooltip?: string | MarkdownString | undefined;
|
||||
}
|
||||
|
||||
export interface SourceControlHistoryItemRef {
|
||||
|
||||
Reference in New Issue
Block a user