feat(quick-pane): promote active runtime
This commit is contained in:
@@ -28,6 +28,9 @@ export function useWorkspace() {
|
||||
const legacyMigrationPending = useRef(false);
|
||||
const disposed = useRef(true);
|
||||
const refreshGeneration = useRef(0);
|
||||
const workspaceReady = useRef(false);
|
||||
const pendingPromotedRuntime = useRef<string | undefined>(undefined);
|
||||
const consumingPromotion = useRef(false);
|
||||
|
||||
const loadSnapshot = useCallback(
|
||||
async (runtimeId: string, options: { throwOnError?: boolean } = {}) => {
|
||||
@@ -150,10 +153,44 @@ export function useWorkspace() {
|
||||
[loadSnapshot],
|
||||
);
|
||||
|
||||
const consumePromotedRuntime = useCallback(() => {
|
||||
if (!workspaceReady.current || consumingPromotion.current) return;
|
||||
consumingPromotion.current = true;
|
||||
void (async () => {
|
||||
while (pendingPromotedRuntime.current && !disposed.current) {
|
||||
const runtimeId = pendingPromotedRuntime.current;
|
||||
pendingPromotedRuntime.current = undefined;
|
||||
await refresh();
|
||||
if (disposed.current) return;
|
||||
dispatch({ type: "selectRuntime", runtimeId });
|
||||
await loadSnapshot(runtimeId);
|
||||
if (disposed.current) return;
|
||||
await invoke("consume_pending_promoted_runtime", { runtimeId });
|
||||
}
|
||||
})()
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
consumingPromotion.current = false;
|
||||
if (pendingPromotedRuntime.current) consumePromotedRuntime();
|
||||
});
|
||||
}, [loadSnapshot, refresh]);
|
||||
|
||||
useEffect(() => {
|
||||
disposed.current = false;
|
||||
workspaceReady.current = false;
|
||||
let stop: (() => void) | undefined;
|
||||
let stopNewRuntime: (() => void) | undefined;
|
||||
let stopPromotedRuntime: (() => void) | undefined;
|
||||
const promotedListenerReady = listen<{ runtimeId: string }>(
|
||||
"workspace-promoted-runtime",
|
||||
(message) => {
|
||||
pendingPromotedRuntime.current = message.payload.runtimeId;
|
||||
consumePromotedRuntime();
|
||||
},
|
||||
).then((unlisten) => {
|
||||
if (disposed.current) unlisten();
|
||||
else stopPromotedRuntime = unlisten;
|
||||
});
|
||||
void listen<{
|
||||
phase: "starting" | "ready" | "error";
|
||||
runtimeId?: string;
|
||||
@@ -197,6 +234,7 @@ export function useWorkspace() {
|
||||
"runtime_recovered",
|
||||
"runtime_renewed",
|
||||
"runtime_restore_failed",
|
||||
"runtime_promoted",
|
||||
].includes(eventType ?? "")
|
||||
) {
|
||||
void refresh();
|
||||
@@ -215,10 +253,17 @@ export function useWorkspace() {
|
||||
});
|
||||
void (async () => {
|
||||
try {
|
||||
await promotedListenerReady;
|
||||
const loaded = await loadPresentation();
|
||||
if (disposed.current) return;
|
||||
await refresh(loaded);
|
||||
if (disposed.current) return;
|
||||
workspaceReady.current = true;
|
||||
const runtimeId = await invoke<string | null>(
|
||||
"get_pending_promoted_runtime",
|
||||
).catch(() => null);
|
||||
if (runtimeId) pendingPromotedRuntime.current = runtimeId;
|
||||
consumePromotedRuntime();
|
||||
initialized.current = true;
|
||||
} catch (error) {
|
||||
if (!disposed.current)
|
||||
@@ -243,9 +288,11 @@ export function useWorkspace() {
|
||||
document.addEventListener("visibilitychange", visibility);
|
||||
return () => {
|
||||
disposed.current = true;
|
||||
workspaceReady.current = false;
|
||||
refreshGeneration.current += 1;
|
||||
stop?.();
|
||||
stopNewRuntime?.();
|
||||
stopPromotedRuntime?.();
|
||||
void invoke("unsubscribe_workspace").catch(() => {});
|
||||
window.removeEventListener("focus", visibility);
|
||||
window.removeEventListener("blur", visibility);
|
||||
@@ -253,7 +300,7 @@ export function useWorkspace() {
|
||||
Object.values(timers.current).forEach(clearTimeout);
|
||||
void appWindow;
|
||||
};
|
||||
}, [refresh, scheduleSnapshot]);
|
||||
}, [consumePromotedRuntime, refresh, scheduleSnapshot]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialized.current) return;
|
||||
|
||||
Reference in New Issue
Block a user