|
|
|
@@ -32,7 +32,7 @@ const toAuthErrorMessage = (error: unknown): string =>
|
|
|
|
|
//
|
|
|
|
|
// 设计:所有登录/同步流跑完都回 `idle`(带正确 `loginStatus`)。
|
|
|
|
|
//
|
|
|
|
|
// 未找到任何登录态时,初始化流程会自动进入 guest login,补齐游客会话。
|
|
|
|
|
// 初始化只恢复已有登录态;游客登录必须由用户明确操作触发。
|
|
|
|
|
// ============================================================
|
|
|
|
|
export const authMachine = setup({
|
|
|
|
|
types: {
|
|
|
|
@@ -49,6 +49,13 @@ export const authMachine = setup({
|
|
|
|
|
checkAuthStatus: checkAuthStatusActor,
|
|
|
|
|
logout: logoutActor,
|
|
|
|
|
},
|
|
|
|
|
guards: {
|
|
|
|
|
canSubmitGuestLogin: ({ context }) =>
|
|
|
|
|
context.loginStatus === "notLoggedIn",
|
|
|
|
|
canLogoutToGuest: ({ context }) =>
|
|
|
|
|
context.loginStatus !== "notLoggedIn" &&
|
|
|
|
|
context.loginStatus !== "guest",
|
|
|
|
|
},
|
|
|
|
|
}).createMachine({
|
|
|
|
|
/** @xstate-layout N4IgpgJg5mDOIC5QEMCuAXAFgOgJYQBswBiAQQ0wAVkA7MAgWQHsIwBhTWmCAbQAYAuolAAHJrFzpcTGsJAAPRABYA7NgAc6gEzqAjCvUBOLbvUqlWgDQgAnohWnsAZgCsSpXyeHdTgGy6lXwBfIOs0LDxCEnIsZlYOLkh+ISQQMQkpGTlFBF81Y1MzX3UvdT5NaztcrS1sD10tQ1dvPi0+YNCQcJx8IjIKADEmACcAWzYiZGGkwTl0yWlZVJzzbHMarSUvNpctYsrEXd86pT0SvfULXyUQsIpIvpjMACU4MHRkufEFrOXEXT4fGwvkMLicmxUTT4qj4hgOCC2QKUoL4KkaShc5ycty69160QoAEkaJJPql5pklqAcl4nGtDCCtGDdqotCp4YY9MC0Xw3CpfH5Gi4cd0HgSsABxVBwdAAGSYUFwNAAyqgAEajSToGYpUTfSnZRC0+mM5kQtnwlzlDQuQynEpOJz6BoqEV4qL9LAAUVGyFwBHlipV6s16G1vFm5P1i0NCGNkNNrnN7Ns9gx2D2LhUDjcl0BN06ovxnswPr9BFeitg2uGqo1Wp1XwyMb+caaJuMZtZKaquhBQKMsOhHiafY6dwixaeEqYCqIgaVddD4bJeubv2pRvbCc7Se78P0SjqYLaewuTtObsnHqeA2QAGMwGrZwBrBfB+thxtR9dUhRbukdyZPc0R7RAaiPUEnRKREjH0dQrx6G8KFIEQRHnBVFxDBsI11NJow3f8EVqVRfCzJ14L4Qp4UdI83F0Bkz3BJxtEQsUSxnOcwGVGwaHvJccNXfDf1jeMGV3FlQIPDEj1OQITAYjwijYqdBgfJ9Xx4viBK-XCmx+P8aW3cTgMki1UwQBpHFRB1IQMdRMXHXFr0eCgJjAKZKDAGgICVKBXl86Z7w+SM1wM2MLGwQFopimKAnhLQWOwTFNF2JxAWuDwtBUkkpGQAhcAALz84gIBkMA8BoAA3JgXwqotctwfKir8hAlRq+9kEpZIhIpFtNwRAVkt8JkdCaXxWhMeFNHUNZTEMTwXExaEXF0HKFma4qaCgYgwGGYYRmwdCuoAMxGUZsAajaCq2qA2uqphOu6wReoIwzlGubAFoFUw3BMEpQXhSEXDWMiVDSlkJtdQt7gIJhkF87apRld9SvKyqarqy7YfhxGoGR6t33ujqusWHrQuE8LWytIFwT0fxAW0F14SUXQQe+x0HDZRy7TYuGEb8gm5Uwmhdv2w7jvQM6xmxiJ+bxoWifax7SZkcm8L6wicitXRuQYq1-C2cwXBomovrBX7jDaVonNFeW-LLf1UbKugMdq+qcYF7bHYDEXiZV56BFekTqdaPXxs5PJdGj+EyNqJ0z08Cx6b53GHd9J2RbFg7hiOghTvO2WcHt72M99oN-aesmXopzX3oQK0jyolxrkS05JuzS1bWcW1Am8Jw0SdW3Pbxn3K1was9rR13laxu209L8tx8n4ZK9Vmh1f0g1WwsXWLacEcjAPxuD1tfIB-B8FPBUcFsphuWF6gMewCrGts4l-OpcL+evafsvl5rGvQOwcqYDQsLUMwjcBQGxbmBSyjcvqXAmgxTkAQDCp1-gAeSeNPCqs8PYPywU8IB1cg61zehFUEyUDCmD8M6TQ-IErg2PEPCwB9QQmAwXjbBFB3650ltLC6P9uHEOVlXNWNcNYUJ3gyL6-1NCGAMDTPw0097RVWrvCEAQ2KwF4veQWs4oBEAAEIPjqj5XBbs573F0XxAxXFTH3nMRAEhEiyFSJDmArYUU2Y-VMCCTQugDx0OSheEEnIHKeDvhOHAtj9FI0MSYsx3kIB8LzgXGWoo4n2KMWARxzjXEb0kVvfqRF3BHmaBYVEo4TYWQaMUahJRTAGEaIUHRei-J3kfM+Wq+SUmWPwUXbA2TtpdI0r05JPlCmbx-KAspexnANHIiYTkqIBQHiWdgJZ-jszgnWO0uxoz1I9JfH0ixe0c7pK-pkmxHSjndNfGclxYj14zLCtvMBbJgQtzZA5PQ0cmgHiiVsnkrhYHFE5CEToNAWBwDkN0EpWtEAAFp2aGHRRizF6L1C+HhMi4eLkwCIvrpsowlxsxgjRAEUwqjDDOFRBoxKI1ygIXvj0Rqm0-LEtjAEnudo-DjQ8CNVRQJo43zWQKR0pguGC2lITEW3LWy8sqQKvwQqrAWU5vS1QrNEo6BvgS4uj8fbvkVQNZVvdVXXHaBqqo5E5oAl8GDXkvyZWL39AAvaZqiIWv5SCNVNrT4MWcHQ8iQ5mluqgDwrA3qci+q2P661wq6lh30E68pmh3CbGxGy4Zdz8aJLyZMiAsbEDxqteqg8OhajGE5OYWEA8jDQxiXmw5UAxknKeaW3InI+UJsFYGlNgRkqJVtOUJRE1WUhCAA */
|
|
|
|
|
id: "auth",
|
|
|
|
@@ -78,10 +85,17 @@ export const authMachine = setup({
|
|
|
|
|
errorMessage: null,
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
AuthLogoutSubmitted: "loggingOut",
|
|
|
|
|
AuthLogoutSubmitted: {
|
|
|
|
|
guard: "canLogoutToGuest",
|
|
|
|
|
target: "loggingOut",
|
|
|
|
|
},
|
|
|
|
|
// 启动一次性 init:从 storage 同步 loginStatus 到状态机 —— 由 <AuthStatusChecker /> 派发
|
|
|
|
|
AuthInit: "initializing",
|
|
|
|
|
|
|
|
|
|
AuthGuestLoginSubmitted: {
|
|
|
|
|
guard: "canSubmitGuestLogin",
|
|
|
|
|
target: "loadingGuestLogin",
|
|
|
|
|
},
|
|
|
|
|
AuthEmailLoginSubmitted: "loadingEmailLogin",
|
|
|
|
|
AuthEmailRegisterSubmitted: "loadingEmailRegister",
|
|
|
|
|
AuthGoogleLoginSubmitted: "loadingOAuth",
|
|
|
|
@@ -102,26 +116,14 @@ export const authMachine = setup({
|
|
|
|
|
entry: assign({ errorMessage: null }),
|
|
|
|
|
invoke: {
|
|
|
|
|
src: "checkAuthStatus",
|
|
|
|
|
onDone: [
|
|
|
|
|
{
|
|
|
|
|
guard: ({ event }) => event.output === "notLoggedIn",
|
|
|
|
|
target: "loadingGuestLogin",
|
|
|
|
|
actions: assign({
|
|
|
|
|
loginStatus: "notLoggedIn",
|
|
|
|
|
// 自动游客登录仍属于初始化流程,完成前不标记 initialized。
|
|
|
|
|
hasInitialized: false,
|
|
|
|
|
errorMessage: null,
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
target: "idle", // ← init 完回 idle(从 storage 拿到 loginStatus 后落地)
|
|
|
|
|
actions: assign({
|
|
|
|
|
loginStatus: ({ event }) => event.output,
|
|
|
|
|
hasInitialized: true,
|
|
|
|
|
errorMessage: null,
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
onDone: {
|
|
|
|
|
target: "idle", // ← init 完回 idle(从 storage 拿到 loginStatus 后落地)
|
|
|
|
|
actions: assign({
|
|
|
|
|
loginStatus: ({ event }) => event.output,
|
|
|
|
|
hasInitialized: true,
|
|
|
|
|
errorMessage: null,
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
onError: {
|
|
|
|
|
target: "idle",
|
|
|
|
|
actions: assign({
|
|
|
|
|