Phase 16E.2 - Runtime Update Reliability and Responsiveness

This commit is contained in:
Nick Beckley 2026-06-27 22:34:35 +01:00
parent 18f204460f
commit 0fc21041fc
2 changed files with 51 additions and 10 deletions

View File

@ -198,7 +198,8 @@
let selectionRefreshTimer = null;
let runtimeSelectionDirty = false;
let runtimeLastActivityAt = 0;
const runtimeIdleDelayMs = 1800;
let runtimeUpdatePending = false;
const runtimeIdleDelayMs = 1200;
let selectionHandlerRegistered = false;
let isAutoRefreshingScene = false;
let sceneWordCountSyncTimer = null;
@ -4063,18 +4064,27 @@
const refreshCurrentSceneFromSelection = async () => {
selectionRefreshTimer = null;
if (isAutoRefreshingScene || !isAuthenticated || !selectedBook()) {
if (isAutoRefreshingScene) {
runtimeUpdatePending = true;
runtimeDebug("Runtime update deferred; update already running.");
return;
}
if (!isAuthenticated || !selectedBook()) {
runtimeSelectionDirty = false;
runtimeDebug("Runtime update skipped.");
return;
}
if (!officeReady || !wordHostAvailable || !window.Word || typeof window.Word.run !== "function") {
runtimeSelectionDirty = false;
setSceneTrackingState("Manual");
setDocumentMessage("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.");
return;
}
if (!documentStructureCache) {
runtimeSelectionDirty = false;
setSceneTrackingState("Manual");
setDocumentMessage("Document structure is not cached yet. Use Refresh Current Scene.");
return;
@ -4089,17 +4099,19 @@
isAutoRefreshingScene = true;
runtimeSelectionDirty = false;
setSceneTrackingState("Live");
runtimeUpdatePending = false;
setSceneTrackingState("Updating...");
runtimeDebug("Runtime update executed.");
try {
const selectionParagraphs = await window.Word.run(async (context) => await readSelectionParagraphs(context));
const selectedIndex = findSelectedParagraphIndex(documentStructureCache, selectionParagraphs);
const changed = applyRuntimeSelection(selectedIndex);
await recountCachedCurrentScene();
if (!changed) {
setSceneContextStale(false);
setSceneTrackingState("Live");
setSceneTrackingState("Current scene updated");
scheduleSceneWordCountSync();
return;
}
@ -4110,8 +4122,8 @@
await refreshPlotDirectorScene();
}
setSceneContextStale(false);
setSceneTrackingState("Live");
setDocumentMessage("");
setSceneTrackingState("Current scene updated");
setDocumentMessage("Current scene updated.");
scheduleSceneWordCountSync();
} catch (error) {
console.error("Unable to refresh current scene from Word selection.", error);
@ -4119,6 +4131,10 @@
setSceneContextStale(true, "The Word cursor is now in a different scene. Refresh Current Scene before saving.");
} finally {
isAutoRefreshingScene = false;
if (runtimeUpdatePending || runtimeSelectionDirty) {
runtimeUpdatePending = false;
scheduleSelectionRefresh(runtimeIdleDelayMs);
}
}
};
@ -4127,15 +4143,36 @@
window.clearTimeout(selectionRefreshTimer);
}
selectionRefreshTimer = window.setTimeout(refreshCurrentSceneFromSelection, Math.max(0, delayMs));
setSceneTrackingState("Waiting for typing to pause");
runtimeDebug("Runtime update scheduled.");
};
const handleDocumentSelectionChanged = () => {
const markRuntimeDirty = (reason = "selection", delayMs = runtimeIdleDelayMs) => {
runtimeSelectionDirty = true;
runtimeLastActivityAt = Date.now();
clearPendingSceneWordCountSync();
runtimeDebug("Selection changed.");
scheduleSelectionRefresh();
runtimeDebug(`${reason} changed.`);
if (isAutoRefreshingScene) {
runtimeUpdatePending = true;
setSceneTrackingState("Waiting for typing to pause");
return;
}
scheduleSelectionRefresh(delayMs);
};
const cancelPendingRuntimeUpdate = () => {
if (selectionRefreshTimer) {
window.clearTimeout(selectionRefreshTimer);
selectionRefreshTimer = null;
}
runtimeSelectionDirty = false;
runtimeUpdatePending = false;
};
const handleDocumentSelectionChanged = () => {
markRuntimeDirty("Selection");
};
const removeSelectionTracking = () => {
@ -4199,7 +4236,9 @@
return;
}
cancelPendingRuntimeUpdate();
setRefreshCurrentSceneBusy(true);
setSceneTrackingState("Updating...");
try {
const scanned = await refreshDocumentStructure();
if (!scanned) {
@ -4209,10 +4248,12 @@
if (!detectedSceneTitle) {
await refreshPlotDirectorChapter();
setSceneTrackingState("Current scene updated");
return;
}
await refreshPlotDirectorScene();
setSceneTrackingState("Current scene updated");
} finally {
setRefreshCurrentSceneBusy(false);
}

File diff suppressed because one or more lines are too long