Skip to content

Commit 599d9e5

Browse files
committed
fix: debounce preview updates to prevent message flooding
- Add 150ms debounce to document change handler - Skip non-critical messages when panel not visible - Add webview ready check with 100ms initialization delay - Clear pending timeouts on panel disposal - Reduces conflicts with slow CodeLens providers
1 parent 632e74e commit 599d9e5

File tree

1 file changed

+44
-19
lines changed

1 file changed

+44
-19
lines changed

src/extension.ts

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,13 @@ function openCheckboxPreview(
175175

176176
Logger.info(`Created preview panel for ${document.uri.toString()} in column two`);
177177

178+
let isWebviewReady = false;
178179
const sendMessage = (message: { type: string; [key: string]: unknown }) => {
180+
if (!panel.visible && message.type !== 'rerender') {
181+
Logger.debug(`Skipping message type ${message.type}; panel not visible`);
182+
return;
183+
}
184+
179185
panel.webview.postMessage(message).then(sent => {
180186
if (!sent) {
181187
Logger.warn(`Webview message of type ${message.type} was not delivered`);
@@ -188,35 +194,51 @@ function openCheckboxPreview(
188194
// Set the initial HTML content
189195
panel.webview.html = getWebviewContent(panel.webview, context, document.getText());
190196
Logger.debug(`Initial preview content rendered for ${document.uri.toString()}`);
197+
198+
// Mark webview as ready after short delay to ensure initialization
199+
setTimeout(() => {
200+
isWebviewReady = true;
201+
Logger.debug(`Webview ready for ${document.uri.toString()}`);
202+
}, 100);
191203

192204
// Register panel with auto-preview manager to prevent duplicates
193205
if (autoPreviewManager) {
194206
autoPreviewManager.registerPanel(panel, document.uri);
195207
}
196208

197-
// Handle document changes
209+
// Handle document changes with debouncing to avoid flooding webview
210+
let updateTimeout: NodeJS.Timeout | undefined;
198211
const changeDisposable = vscode.workspace.onDidChangeTextDocument(event => {
199212
if (event.document.uri.toString() === document.uri.toString()) {
200213
Logger.debug(`Document change detected for ${document.uri.toString()} (${event.contentChanges.length} change(s))`);
201-
const newContent = event.document.getText();
202-
const html = renderMarkdown(newContent);
203-
const stats = getTaskListCount(newContent);
204-
205-
sendMessage({
206-
type: 'rerender',
207-
html: html
208-
});
209-
210-
sendMessage({
211-
type: 'updateProgress',
212-
completed: stats.completed,
213-
total: stats.total
214-
});
215-
216-
// Refresh tree view if available
217-
if (treeDataProvider) {
218-
treeDataProvider.refresh();
214+
215+
// Clear existing timeout
216+
if (updateTimeout) {
217+
clearTimeout(updateTimeout);
219218
}
219+
220+
// Debounce updates by 150ms to batch rapid changes
221+
updateTimeout = setTimeout(() => {
222+
const newContent = event.document.getText();
223+
const html = renderMarkdown(newContent);
224+
const stats = getTaskListCount(newContent);
225+
226+
sendMessage({
227+
type: 'rerender',
228+
html: html
229+
});
230+
231+
sendMessage({
232+
type: 'updateProgress',
233+
completed: stats.completed,
234+
total: stats.total
235+
});
236+
237+
// Refresh tree view if available
238+
if (treeDataProvider) {
239+
treeDataProvider.refresh();
240+
}
241+
}, 150);
220242
}
221243
});
222244

@@ -237,6 +259,9 @@ function openCheckboxPreview(
237259

238260
// Clean up when panel is disposed
239261
panel.onDidDispose(() => {
262+
if (updateTimeout) {
263+
clearTimeout(updateTimeout);
264+
}
240265
changeDisposable.dispose();
241266
Logger.debug(`Disposed preview panel for ${document.uri.toString()}`);
242267
// Auto-preview manager automatically unregisters via its own onDidDispose handler

0 commit comments

Comments
 (0)