feat(chat): add support action cards and live entitlements

This commit is contained in:
Codex
2026-07-24 17:59:57 +08:00
parent d746d04503
commit ff2759cf0f
52 changed files with 1151 additions and 40 deletions
+10 -3
View File
@@ -1,7 +1,10 @@
import { fromPromise } from "xstate";
import { getUserRepository } from "@/data/repositories/user_repository";
import type { UserEntitlementSnapshotData } from "@/data/schemas/user";
import type {
UserEntitlementsData,
UserEntitlementSnapshotData,
} from "@/data/schemas/user";
import { UserStorage } from "@/data/storage/user/user_storage";
import type { UserView } from "@/stores/user/user-view";
import { Result } from "@/utils/result";
@@ -15,6 +18,7 @@ import {
export interface UserFetchData {
user: UserView | null;
snapshot: UserEntitlementSnapshotData | null;
entitlements?: UserEntitlementsData | null;
}
export const userFetchActor = fromPromise<UserFetchData>(async () => {
@@ -31,14 +35,17 @@ export const userFetchActor = fromPromise<UserFetchData>(async () => {
creditBalance: entitlementsResult.data.creditBalance,
})
: null;
const entitlements = Result.isOk(entitlementsResult)
? entitlementsResult.data
: null;
if (snapshot) await userStorage.setEntitlementSnapshot(snapshot);
if (Result.isErr(userResult)) return { user: null, snapshot };
if (Result.isErr(userResult)) return { user: null, snapshot, entitlements };
const view = applyEntitlementSnapshotToView(
toView(userResult.data),
snapshot,
);
await userStorage.setUser(userResult.data);
return { user: view, snapshot };
return { user: view, snapshot, entitlements };
});
+1
View File
@@ -49,6 +49,7 @@ const applyFetchedUserAction = userFetchDoneSetup.assign(
context.currentUser,
isVip: snapshot?.isVip ?? context.isVip,
creditBalance: snapshot?.creditBalance ?? context.creditBalance,
entitlements: event.output.entitlements ?? context.entitlements,
isLoading: false,
};
},
+1
View File
@@ -10,6 +10,7 @@ const clearUserAction = profileMachineSetup.assign(() => ({
avatarUrl: null,
isVip: false,
creditBalance: 0,
entitlements: null,
}));
export const userMachineSetup = profileMachineSetup.extend({
+2
View File
@@ -18,6 +18,7 @@ interface UserState {
avatarUrl: string | null;
isVip: boolean;
creditBalance: number;
entitlements: MachineContext["entitlements"];
}
type UserSnapshot = SnapshotFrom<typeof userMachine>;
@@ -59,5 +60,6 @@ function selectUserState(state: UserSnapshot): UserState {
avatarUrl: state.context.avatarUrl,
isVip: state.context.isVip,
creditBalance: state.context.creditBalance,
entitlements: state.context.entitlements,
};
}
+3
View File
@@ -2,6 +2,7 @@
* User 状态机:State 形状 + 初始值
*/
import type { UserView } from "@/stores/user/user-view";
import type { UserEntitlementsData } from "@/data/schemas/user";
export interface UserState {
currentUser: UserView | null;
@@ -9,6 +10,7 @@ export interface UserState {
avatarUrl: string | null;
isVip: boolean;
creditBalance: number;
entitlements: UserEntitlementsData | null;
}
export const initialState: UserState = {
@@ -17,4 +19,5 @@ export const initialState: UserState = {
avatarUrl: null,
isVip: false,
creditBalance: 0,
entitlements: null,
};