refactor: uiStore.ts
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import { useEffect } from "react";
|
||||
|
||||
import {
|
||||
bindScriptWorkspaceApi,
|
||||
editSessionHandle,
|
||||
useScriptWorkspaceStore,
|
||||
} from "../state/scriptWorkspaceStore";
|
||||
|
||||
type ActivePage = "home" | "scripts" | "schedules" | "system";
|
||||
|
||||
/**
|
||||
* 必须在 layout 层挂载,不能放在 ScriptsPage。
|
||||
* 原因:心跳 / cleanup / beforeunload 需要在用户切到 /schedules 时仍运行,
|
||||
* 否则其他 tab 中的编辑会话锁会过期。
|
||||
*/
|
||||
export function useEditSessionLifecycle({
|
||||
activePage,
|
||||
}: {
|
||||
activePage: ActivePage;
|
||||
}) {
|
||||
// 1) 切到非 scripts 页时,如果当前有 active session,结束编辑
|
||||
useEffect(() => {
|
||||
if (activePage === "scripts") return;
|
||||
const editBusy = useScriptWorkspaceStore.getState().editBusy;
|
||||
if (editBusy) return;
|
||||
if (!editSessionHandle.current) return;
|
||||
void useScriptWorkspaceStore.getState().endEditing(true, false);
|
||||
}, [activePage]);
|
||||
|
||||
// 2) 心跳 + cleanup 定时器(15s 心跳,60s 检查 cleanup)
|
||||
useEffect(() => {
|
||||
let heartbeatRunning = false;
|
||||
let cleanupRunning = false;
|
||||
const heartbeatTimer = window.setInterval(() => {
|
||||
if (heartbeatRunning) return;
|
||||
heartbeatRunning = true;
|
||||
void useScriptWorkspaceStore.getState().tickHeartbeats().finally(() => {
|
||||
heartbeatRunning = false;
|
||||
});
|
||||
}, 15 * 1000);
|
||||
const cleanupTimer = window.setInterval(() => {
|
||||
if (cleanupRunning) return;
|
||||
cleanupRunning = true;
|
||||
try {
|
||||
useScriptWorkspaceStore.getState().tickCleanup();
|
||||
} finally {
|
||||
cleanupRunning = false;
|
||||
}
|
||||
}, 60 * 1000);
|
||||
return () => {
|
||||
window.clearInterval(heartbeatTimer);
|
||||
window.clearInterval(cleanupTimer);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 3) 卸载前释放编辑锁
|
||||
useEffect(() => {
|
||||
const handleUnload = () => {
|
||||
useScriptWorkspaceStore.getState().releaseActiveOnUnload();
|
||||
};
|
||||
window.addEventListener("beforeunload", handleUnload);
|
||||
return () => window.removeEventListener("beforeunload", handleUnload);
|
||||
}, []);
|
||||
|
||||
// 4) layout 卸载时解绑 api
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
bindScriptWorkspaceApi(null);
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
Reference in New Issue
Block a user