Skip to content

Commit 0c1c168

Browse files
authored
Check if there are updates before refreshing (#6943)
Fixes #6935
1 parent af712b9 commit 0c1c168

5 files changed

Lines changed: 484 additions & 7 deletions

File tree

src/github/graphql.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,48 @@ export interface TimelineEventsResponse {
250250
rateLimit: RateLimit;
251251
}
252252

253+
export interface LatestCommit {
254+
commit: {
255+
authoredDate: string;
256+
}
257+
}
258+
259+
export interface LatestReviewThread {
260+
comments: {
261+
nodes: {
262+
createdAt: string;
263+
}[];
264+
}
265+
}
266+
267+
export interface LatestUpdatesResponse {
268+
repository: {
269+
pullRequest: {
270+
reactions: {
271+
nodes: {
272+
createdAt: string;
273+
}[];
274+
}
275+
updatedAt: string;
276+
comments: {
277+
nodes: {
278+
updatedAt: string;
279+
reactions: {
280+
nodes: {
281+
createdAt: string;
282+
}[];
283+
}
284+
}[];
285+
}
286+
timelineItems: {
287+
nodes: ({
288+
createdAt: string;
289+
} | LatestCommit | LatestReviewThread)[];
290+
}
291+
}
292+
}
293+
}
294+
253295
export interface LatestReviewCommitResponse {
254296
repository: {
255297
pullRequest: {

src/github/issueModel.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import {
1414
AddIssueCommentResponse,
1515
AddPullRequestToProjectResponse,
1616
EditIssueCommentResponse,
17+
LatestCommit,
18+
LatestReviewThread,
19+
LatestUpdatesResponse,
1720
TimelineEventsResponse,
1821
UpdateIssueResponse,
1922
} from './graphql';
@@ -351,6 +354,52 @@ export class IssueModel<TItem extends Issue = Issue> {
351354
}
352355
}
353356

357+
protected getUpdatesQuery(schema: any): any {
358+
return schema.LatestIssueUpdates;
359+
}
360+
361+
async getLastUpdateTime(time: Date): Promise<Date> {
362+
Logger.debug(`Fetch timeline events of issue #${this.number} - enter`, IssueModel.ID);
363+
const githubRepository = this.githubRepository;
364+
const { query, remote, schema } = await githubRepository.ensure();
365+
try {
366+
const { data } = await query<LatestUpdatesResponse>({
367+
query: this.getUpdatesQuery(schema),
368+
variables: {
369+
owner: remote.owner,
370+
name: remote.repositoryName,
371+
number: this.number,
372+
since: new Date(time),
373+
}
374+
});
375+
376+
const times = [
377+
time,
378+
new Date(data.repository.pullRequest.updatedAt),
379+
...(data.repository.pullRequest.reactions.nodes.map(node => new Date(node.createdAt))),
380+
...(data.repository.pullRequest.comments.nodes.map(node => new Date(node.updatedAt))),
381+
...(data.repository.pullRequest.comments.nodes.flatMap(node => node.reactions.nodes.map(reaction => new Date(reaction.createdAt)))),
382+
...(data.repository.pullRequest.timelineItems.nodes.map(node => {
383+
const latestCommit = node as Partial<LatestCommit>;
384+
if (latestCommit.commit?.authoredDate) {
385+
return new Date(latestCommit.commit.authoredDate);
386+
}
387+
const latestReviewThread = node as Partial<LatestReviewThread>;
388+
if ((latestReviewThread.comments?.nodes.length ?? 0) > 0) {
389+
return new Date(latestReviewThread.comments!.nodes[0].createdAt);
390+
}
391+
return new Date((node as { createdAt: string }).createdAt);
392+
}))
393+
];
394+
395+
// Sort times and return the most recent one
396+
return new Date(Math.max(...times.map(t => t.getTime())));
397+
} catch (e) {
398+
Logger.error(`Error fetching timeline events of issue #${this.number} - ${formatError(e)}`, IssueModel.ID);
399+
return time; // Return the original time in case of an error
400+
}
401+
}
402+
354403
async updateMilestone(id: string): Promise<void> {
355404
const { mutate, schema } = await this.githubRepository.ensure();
356405
const finalId = id === 'null' ? null : id;

src/github/issueOverview.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,11 @@ export class IssueOverviewPanel<TItem extends IssueModel = IssueModel> extends W
137137
}));
138138

139139
this._register(this._panel.onDidChangeViewState(e => this.onDidChangeViewState(e)));
140-
this.pollForUpdates();
140+
this.lastRefreshTime = new Date();
141+
this.pollForUpdates(true);
141142
this._register(vscode.workspace.onDidChangeConfiguration(e => {
142143
if (e.affectsConfiguration(`${PR_SETTINGS_NAMESPACE}.${WEBVIEW_REFRESH_INTERVAL}`)) {
143-
this.pollForUpdates();
144+
this.pollForUpdates(this._panel.visible, true);
144145
}
145146
}));
146147

@@ -157,16 +158,25 @@ export class IssueOverviewPanel<TItem extends IssueModel = IssueModel> extends W
157158
}
158159

159160
private timeout: NodeJS.Timeout | undefined = undefined;
160-
private pollForUpdates(refreshImmediately: boolean = false): void {
161+
private lastRefreshTime: Date;
162+
private pollForUpdates(isVisible: boolean, refreshImmediately: boolean = false): void {
161163
clearTimeout(this.timeout);
164+
const refresh = async () => {
165+
const previousRefreshTime = this.lastRefreshTime;
166+
this.lastRefreshTime = await this._item.getLastUpdateTime(previousRefreshTime);
167+
if (this.lastRefreshTime.getTime() > previousRefreshTime.getTime()) {
168+
return this.refreshPanel();
169+
}
170+
};
171+
162172
if (refreshImmediately) {
163-
this.refreshPanel();
173+
refresh();
164174
}
165-
const webview = vscode.window.tabGroups.all.find(group => group.activeTab?.input instanceof vscode.TabInputWebview && group.activeTab.input.viewType.endsWith(this.type));
175+
const webview = isVisible || vscode.window.tabGroups.all.find(group => group.activeTab?.input instanceof vscode.TabInputWebview && group.activeTab.input.viewType.endsWith(this.type));
166176
const timeoutDuration = 1000 * (webview ? this.getRefreshInterval() : (5 * 60));
167177
this.timeout = setTimeout(async () => {
168-
await this.refreshPanel();
169-
this.pollForUpdates();
178+
await refresh();
179+
this.pollForUpdates(this._panel.visible);
170180
}, timeoutDuration);
171181
}
172182

src/github/pullRequestModel.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,10 @@ export class PullRequestModel extends IssueModel<PullRequest> implements IPullRe
11981198
}
11991199
}
12001200

1201+
protected override getUpdatesQuery(schema: any): any {
1202+
return schema.LatestUpdates;
1203+
}
1204+
12011205
private addReviewTimelineEventComments(events: TimelineEvent[], reviewThreads: IReviewThread[]): void {
12021206
interface CommentNode extends IComment {
12031207
childComments?: CommentNode[];

0 commit comments

Comments
 (0)