Skip to content

Commit a669ddc

Browse files
committed
Recovers markdown preview content on tab visibility changes
Addresses issues where markdown previews may display corrupted or outdated content by detecting tab visibility changes and forcing content recovery for affected documents. Improves reliability of previews when switching tabs or reopening custom editors. (#4328, #4489)
1 parent 1f08c2d commit a669ddc

File tree

1 file changed

+68
-2
lines changed

1 file changed

+68
-2
lines changed

src/documents/markdown.ts

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import type { Disposable, Event, TextDocumentContentProvider } from 'vscode';
2-
import { EventEmitter, Uri, workspace } from 'vscode';
1+
import type { Event, TabChangeEvent, TextDocumentContentProvider } from 'vscode';
2+
import { Disposable, EventEmitter, TabInputCustom, Uri, window, workspace } from 'vscode';
33
import { Schemes } from '../constants';
44
import type { GlCommands } from '../constants.commands';
55
import type { Container } from '../container';
@@ -17,6 +17,7 @@ export interface MarkdownContentMetadata {
1717
export class MarkdownContentProvider implements TextDocumentContentProvider {
1818
private contents = new Map<string, string>();
1919
private registration: Disposable;
20+
private visibilityTracker: Disposable;
2021

2122
private _onDidChange = new EventEmitter<Uri>();
2223
get onDidChange(): Event<Uri> {
@@ -26,6 +27,18 @@ export class MarkdownContentProvider implements TextDocumentContentProvider {
2627
constructor(private container: Container) {
2728
this.registration = workspace.registerTextDocumentContentProvider(Schemes.GitLensAIMarkdown, this);
2829

30+
// Track document visibility to detect when content needs recovery
31+
this.visibilityTracker = Disposable.from(
32+
window.tabGroups.onDidChangeTabs((e: TabChangeEvent) => {
33+
this.onTabsChanged(e);
34+
}),
35+
// // Also track when tabs change which might affect preview visibility
36+
// window.onDidChangeActiveTextEditor(() => {
37+
// // Delay to allow VS Code to finish tab switching
38+
// setTimeout(() => this.forceRecoveryForAllOpenedDocuments(), 1000);
39+
// }),
40+
);
41+
2942
workspace.onDidCloseTextDocument(document => {
3043
if (document.uri.scheme === Schemes.GitLensAIMarkdown) {
3144
this.contents.delete(document.uri.toString());
@@ -71,13 +84,66 @@ export class MarkdownContentProvider implements TextDocumentContentProvider {
7184
this._onDidChange.fire(uri);
7285
}
7386

87+
/**
88+
* Forces content recovery for a document - useful when content gets corrupted
89+
*/
90+
forceContentRecovery(uri: Uri): void {
91+
const uriString = uri.toString();
92+
if (!this.contents.has(uriString)) return;
93+
94+
const storedContent = this.contents.get(uriString);
95+
if (!storedContent) return;
96+
97+
// I'm deleting the content because if I just fire the change once to make VSCode
98+
// reach our `provideTextDocumentContent` method
99+
// and `provideTextDocumentContent` returns the unchanged conent,
100+
// VSCode will not refresh the content, instead it keeps displaying the original conetnt
101+
// that the view had when it was opened initially.
102+
// That's why I need to blink the content.
103+
if (storedContent.at(storedContent.length - 1) === '\n') {
104+
this.contents.set(uriString, storedContent.substring(0, storedContent.length - 1));
105+
} else {
106+
this.contents.set(uriString, `${storedContent}\n`);
107+
}
108+
this._onDidChange.fire(uri);
109+
}
110+
74111
closeDocument(uri: Uri): void {
75112
this.contents.delete(uri.toString());
76113
}
77114

78115
dispose(): void {
79116
this.contents.clear();
80117
this.registration.dispose();
118+
this.visibilityTracker.dispose();
119+
}
120+
121+
// /**
122+
// * Checks preview visibility by examining workspace documents
123+
// */
124+
// private forceRecoveryForAllOpenedDocuments(): void {
125+
// // Check all workspace documents for our markdown scheme
126+
// for (const document of workspace.textDocuments) {
127+
// if (document.uri.scheme === Schemes.GitLensAIMarkdown) {
128+
// const uriString = document.uri.toString();
129+
// if (this.contents.has(uriString)) {
130+
// console.log(`[GitLens] Checking preview visibility for: ${document.uri.path}`);
131+
// // Trigger recovery check for this document
132+
// setTimeout(() => {
133+
// this.forceContentRecovery(document.uri);
134+
// }, 1000);
135+
// }
136+
// }
137+
// }
138+
// }
139+
140+
private onTabsChanged(e: TabChangeEvent) {
141+
for (const tab of e.changed) {
142+
if (tab.input instanceof TabInputCustom && tab.input.uri.scheme === Schemes.GitLensAIMarkdown) {
143+
const uri = tab.input.uri;
144+
this.forceContentRecovery(uri);
145+
}
146+
}
81147
}
82148
}
83149

0 commit comments

Comments
 (0)