Skip to content

Commit 561de4d

Browse files
committed
Improves graph hover stability
1 parent cb23bb8 commit 561de4d

File tree

3 files changed

+31
-17
lines changed

3 files changed

+31
-17
lines changed

src/plus/webviews/graph/graphWebview.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
917917
private async onHoverRowRequest<T extends typeof GetRowHoverRequest>(requestType: T, msg: IpcCallMessageType<T>) {
918918
const hover: DidGetRowHoverParams = {
919919
id: msg.params.id,
920-
markdown: undefined,
920+
cancelled: true,
921921
};
922922

923923
if (this._hoverCancellation != null) {
@@ -965,9 +965,9 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
965965
});
966966
}
967967

968-
markdown = this.getCommitTooltip(commit, cancellation.token).catch(() => {
968+
markdown = this.getCommitTooltip(commit, cancellation.token).catch((ex: unknown) => {
969969
this._hoverCache.delete(id);
970-
return undefined;
970+
throw ex;
971971
});
972972
if (cache) {
973973
this._hoverCache.set(id, markdown);
@@ -976,7 +976,10 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
976976
}
977977

978978
if (markdown != null) {
979-
hover.markdown = await markdown;
979+
try {
980+
hover.markdown = await markdown;
981+
hover.cancelled = false;
982+
} catch {}
980983
}
981984
}
982985

src/plus/webviews/graph/protocol.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,13 @@ export type GetRowHoverParams = {
314314
type: GitGraphRowType;
315315
id: string;
316316
};
317+
317318
export interface DidGetRowHoverParams {
318319
id: string;
319320
markdown?: string;
321+
cancelled: boolean;
320322
}
323+
321324
export const GetRowHoverRequest = new IpcRequest<GetRowHoverParams, DidGetRowHoverParams>(scope, 'row/hover/get');
322325

323326
export interface SearchParams {

src/webviews/apps/plus/graph/hover/graphHover.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,15 @@ export class GlGraphHover extends GlElement {
7878
this.hoverMarkdownCache.clear();
7979
}
8080

81-
onRowHovered(row: GraphRow, anchor: Anchor) {
82-
console.log('onRowHovered', row.sha);
81+
onParentMouseLeave = () => {
82+
this.hide();
83+
};
8384

85+
onRowHovered(row: GraphRow, anchor: Anchor) {
86+
clearTimeout(this.unhoverTimer);
8487
if (this.requestMarkdown == null) return;
88+
// Break if we are already showing the hover for thesame row
89+
if (this.hoveredSha === row.sha && this.open) return;
8590

8691
this.hoveredSha = row.sha;
8792

@@ -98,19 +103,20 @@ export class GlGraphHover extends GlElement {
98103
}
99104

100105
this.hoverMarkdownCache.delete(row.sha);
106+
if (params?.cancelled) throw new Error('Cancelled');
107+
101108
return '';
102109
});
103110

104111
if (cache) {
105112
this.hoverMarkdownCache.set(row.sha, markdown);
106113
}
107114
}
115+
108116
this.showCore(anchor, markdown);
109117
}
110118

111119
onRowUnhovered(row: GraphRow, relatedTarget: EventTarget | null) {
112-
console.log('onRowUnhovered', row.sha);
113-
114120
clearTimeout(this.unhoverTimer);
115121

116122
if (
@@ -121,35 +127,37 @@ export class GlGraphHover extends GlElement {
121127
return;
122128
}
123129

124-
this.hoveredSha = undefined;
125-
126-
this.unhoverTimer = setTimeout(() => {
127-
console.log('onRowUnhovered timeout', this.hoveredSha);
128-
if (this.hoveredSha == null) {
129-
this.hide();
130-
}
131-
}, 100);
130+
this.unhoverTimer = setTimeout(() => this.hide(), 250);
132131
}
133132

134133
private showCore(
135134
anchor: string | HTMLElement | { getBoundingClientRect: () => Omit<DOMRect, 'toJSON'> },
136135
markdown: Promise<string | undefined> | string | undefined,
137136
) {
138137
if (isPromise(markdown)) {
138+
const previousSha = this.hoveredSha;
139139
void markdown.then(markdown => {
140+
if (previousSha !== this.hoveredSha) return;
141+
140142
this.markdown = markdown;
141143
if (!markdown) {
142-
this.open = false;
144+
this.hide();
143145
}
144146
});
145147
}
146148

147149
this.anchor = anchor;
148150
this.markdown = markdown;
149151
this.open = true;
152+
this.parentElement?.addEventListener('mouseleave', this.onParentMouseLeave);
150153
}
151154

152155
hide() {
156+
clearTimeout(this.unhoverTimer);
157+
this.parentElement?.removeEventListener('mouseleave', this.onParentMouseLeave);
158+
159+
this.hoveredSha = undefined;
160+
this.markdown = undefined;
153161
this.open = false;
154162
}
155163
}

0 commit comments

Comments
 (0)