74 lines
1.9 KiB
TypeScript
74 lines
1.9 KiB
TypeScript
"use client";
|
|
|
|
/**
|
|
* Auth → Chat 同步器
|
|
*
|
|
* Chat machine 不直接感知 Auth machine;这里作为根级桥接器,持续监听
|
|
* loginStatus 变化并派发 chat 鉴权生命周期事件。这样页面组件只负责 UI,
|
|
* 不再承担全局状态同步职责。
|
|
*/
|
|
import { useEffect, useRef } from "react";
|
|
import { shallowEqual } from "@xstate/react";
|
|
|
|
import { AuthStorage } from "@/data/storage/auth";
|
|
import {
|
|
selectAuthIsLoading,
|
|
useAuthSelector,
|
|
} from "@/stores/auth/auth-context";
|
|
import { useChatDispatch } from "@/stores/chat/chat-context";
|
|
|
|
export function ChatAuthSync() {
|
|
const authState = useAuthSelector(
|
|
(state) => ({
|
|
hasInitialized: state.context.hasInitialized,
|
|
isLoading: selectAuthIsLoading(state),
|
|
loginStatus: state.context.loginStatus,
|
|
}),
|
|
shallowEqual,
|
|
);
|
|
const chatDispatch = useChatDispatch();
|
|
const prevSessionKeyRef = useRef<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (!authState.hasInitialized || authState.isLoading) return;
|
|
|
|
const sessionKey = authState.loginStatus;
|
|
if (prevSessionKeyRef.current === sessionKey) return;
|
|
|
|
if (authState.loginStatus === "notLoggedIn") {
|
|
prevSessionKeyRef.current = sessionKey;
|
|
chatDispatch({ type: "ChatLogout" });
|
|
return;
|
|
}
|
|
|
|
if (authState.loginStatus === "guest") {
|
|
prevSessionKeyRef.current = sessionKey;
|
|
chatDispatch({ type: "ChatGuestLogin" });
|
|
return;
|
|
}
|
|
|
|
let cancelled = false;
|
|
void (async () => {
|
|
const tokenR = await AuthStorage.getInstance().getLoginToken();
|
|
if (!cancelled && tokenR.success && tokenR.data) {
|
|
prevSessionKeyRef.current = sessionKey;
|
|
chatDispatch({
|
|
type: "ChatUserLogin",
|
|
token: tokenR.data,
|
|
});
|
|
}
|
|
})();
|
|
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, [
|
|
authState.hasInitialized,
|
|
authState.isLoading,
|
|
authState.loginStatus,
|
|
chatDispatch,
|
|
]);
|
|
|
|
return null;
|
|
}
|