2025-07-10 11:33:35 +08:00
|
|
|
import { getSingletonAnalyticsOptional } from '@lobehub/analytics';
|
2024-05-23 22:33:07 +08:00
|
|
|
import useSWR, { SWRResponse, mutate } from 'swr';
|
2025-07-10 17:50:01 +08:00
|
|
|
import type { PartialDeep } from 'type-fest';
|
2023-07-16 23:22:26 +08:00
|
|
|
import type { StateCreator } from 'zustand/vanilla';
|
|
|
|
|
|
2024-05-23 22:33:07 +08:00
|
|
|
import { DEFAULT_PREFERENCE } from '@/const/user';
|
2024-05-28 23:57:14 +08:00
|
|
|
import { useOnlyFetchOnceSWR } from '@/libs/swr';
|
2024-05-03 09:52:15 +08:00
|
|
|
import { userService } from '@/services/user';
|
2024-04-28 23:28:17 +08:00
|
|
|
import type { UserStore } from '@/store/user';
|
2024-04-10 00:02:22 +08:00
|
|
|
import type { GlobalServerConfig } from '@/types/serverConfig';
|
2025-04-16 23:21:55 +08:00
|
|
|
import { LobeUser, UserInitializationState } from '@/types/user';
|
2024-05-26 23:33:01 +08:00
|
|
|
import type { UserSettings } from '@/types/user/settings';
|
2023-10-06 15:15:14 +08:00
|
|
|
import { merge } from '@/utils/merge';
|
2023-07-31 22:18:04 +08:00
|
|
|
import { setNamespace } from '@/utils/storeDebug';
|
2024-02-15 09:42:58 +08:00
|
|
|
|
2024-03-05 14:15:49 +08:00
|
|
|
import { preferenceSelectors } from '../preference/selectors';
|
2023-07-16 23:22:26 +08:00
|
|
|
|
2024-01-30 22:38:25 +08:00
|
|
|
const n = setNamespace('common');
|
2023-07-31 22:18:04 +08:00
|
|
|
|
2024-05-23 22:33:07 +08:00
|
|
|
const GET_USER_STATE_KEY = 'initUserState';
|
2023-07-22 17:19:44 +08:00
|
|
|
/**
|
|
|
|
|
* 设置操作
|
|
|
|
|
*/
|
2023-08-10 23:20:15 +08:00
|
|
|
export interface CommonAction {
|
2024-05-23 22:33:07 +08:00
|
|
|
refreshUserState: () => Promise<void>;
|
2024-01-30 22:38:25 +08:00
|
|
|
updateAvatar: (avatar: string) => Promise<void>;
|
2025-11-27 20:10:40 +08:00
|
|
|
updateFullName: (fullName: string) => Promise<void>;
|
2025-11-03 13:14:35 +08:00
|
|
|
updateKeyVaultConfig: (provider: string, config: any) => Promise<void>;
|
2025-12-05 01:35:20 +08:00
|
|
|
updateUsername: (username: string) => Promise<void>;
|
2024-03-05 14:15:49 +08:00
|
|
|
useCheckTrace: (shouldFetch: boolean) => SWRResponse;
|
2024-05-23 22:33:07 +08:00
|
|
|
useInitUserState: (
|
|
|
|
|
isLogin: boolean | undefined,
|
|
|
|
|
serverConfig: GlobalServerConfig,
|
|
|
|
|
options?: {
|
2025-11-17 20:54:37 +08:00
|
|
|
onError?: (error: any) => void;
|
2024-05-23 22:33:07 +08:00
|
|
|
onSuccess: (data: UserInitializationState) => void;
|
|
|
|
|
},
|
|
|
|
|
) => SWRResponse;
|
2023-07-16 23:22:26 +08:00
|
|
|
}
|
|
|
|
|
|
2023-08-10 23:20:15 +08:00
|
|
|
export const createCommonSlice: StateCreator<
|
2024-04-28 23:28:17 +08:00
|
|
|
UserStore,
|
2023-07-16 23:22:26 +08:00
|
|
|
[['zustand/devtools', never]],
|
|
|
|
|
[],
|
2023-08-10 23:20:15 +08:00
|
|
|
CommonAction
|
2023-07-16 23:22:26 +08:00
|
|
|
> = (set, get) => ({
|
2024-05-23 22:33:07 +08:00
|
|
|
refreshUserState: async () => {
|
|
|
|
|
await mutate(GET_USER_STATE_KEY);
|
|
|
|
|
},
|
2024-01-30 22:38:25 +08:00
|
|
|
updateAvatar: async (avatar) => {
|
2025-04-24 23:45:01 +08:00
|
|
|
await userService.updateAvatar(avatar);
|
2025-11-27 20:10:40 +08:00
|
|
|
await get().refreshUserState();
|
|
|
|
|
},
|
2024-11-08 12:53:57 +08:00
|
|
|
|
2025-11-27 20:10:40 +08:00
|
|
|
updateFullName: async (fullName) => {
|
|
|
|
|
await userService.updateFullName(fullName);
|
2024-05-23 22:33:07 +08:00
|
|
|
await get().refreshUserState();
|
2023-07-31 18:36:55 +08:00
|
|
|
},
|
2024-05-03 09:52:15 +08:00
|
|
|
|
2025-11-03 13:14:35 +08:00
|
|
|
updateKeyVaultConfig: async (provider, config) => {
|
|
|
|
|
await get().setSettings({ keyVaults: { [provider]: config } });
|
|
|
|
|
},
|
|
|
|
|
|
2025-12-05 01:35:20 +08:00
|
|
|
updateUsername: async (username) => {
|
|
|
|
|
await userService.updateUsername(username);
|
|
|
|
|
await get().refreshUserState();
|
|
|
|
|
},
|
|
|
|
|
|
2024-03-05 14:15:49 +08:00
|
|
|
useCheckTrace: (shouldFetch) =>
|
|
|
|
|
useSWR<boolean>(
|
2024-05-23 22:33:07 +08:00
|
|
|
shouldFetch ? 'checkTrace' : null,
|
2024-03-05 14:15:49 +08:00
|
|
|
() => {
|
|
|
|
|
const userAllowTrace = preferenceSelectors.userAllowTrace(get());
|
|
|
|
|
|
|
|
|
|
// if user have set the trace, return false
|
|
|
|
|
if (typeof userAllowTrace === 'boolean') return Promise.resolve(false);
|
|
|
|
|
|
2024-05-23 22:33:07 +08:00
|
|
|
return Promise.resolve(get().isUserCanEnableTrace);
|
2024-03-05 14:15:49 +08:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
revalidateOnFocus: false,
|
|
|
|
|
},
|
|
|
|
|
),
|
2024-05-23 22:33:07 +08:00
|
|
|
useInitUserState: (isLogin, serverConfig, options) =>
|
2024-05-28 23:57:14 +08:00
|
|
|
useOnlyFetchOnceSWR<UserInitializationState>(
|
2024-05-23 22:33:07 +08:00
|
|
|
!!isLogin ? GET_USER_STATE_KEY : null,
|
|
|
|
|
() => userService.getUserState(),
|
2024-05-18 22:30:48 +08:00
|
|
|
{
|
2025-11-17 20:54:37 +08:00
|
|
|
onError: (error) => {
|
|
|
|
|
options?.onError?.(error);
|
|
|
|
|
},
|
2024-05-18 22:30:48 +08:00
|
|
|
onSuccess: (data) => {
|
2024-05-23 22:33:07 +08:00
|
|
|
options?.onSuccess?.(data);
|
|
|
|
|
|
2024-05-18 22:30:48 +08:00
|
|
|
if (data) {
|
2024-05-23 22:33:07 +08:00
|
|
|
// merge settings
|
2025-07-10 17:50:01 +08:00
|
|
|
const serverSettings: PartialDeep<UserSettings> = {
|
2024-05-23 22:33:07 +08:00
|
|
|
defaultAgent: serverConfig.defaultAgent,
|
2025-10-12 23:56:17 +08:00
|
|
|
image: serverConfig.image,
|
2024-05-28 19:20:36 +08:00
|
|
|
systemAgent: serverConfig.systemAgent,
|
2024-05-18 22:30:48 +08:00
|
|
|
};
|
2024-05-28 19:20:36 +08:00
|
|
|
|
2024-05-18 22:30:48 +08:00
|
|
|
const defaultSettings = merge(get().defaultSettings, serverSettings);
|
2024-04-13 11:21:21 +08:00
|
|
|
|
2024-05-23 22:33:07 +08:00
|
|
|
// merge preference
|
|
|
|
|
const isEmpty = Object.keys(data.preference || {}).length === 0;
|
|
|
|
|
const preference = isEmpty ? DEFAULT_PREFERENCE : data.preference;
|
|
|
|
|
|
2024-05-24 23:51:19 +08:00
|
|
|
// if there is avatar or userId (from client DB), update it into user
|
|
|
|
|
const user =
|
|
|
|
|
data.avatar || data.userId
|
2025-04-16 23:21:55 +08:00
|
|
|
? merge(get().user, {
|
|
|
|
|
avatar: data.avatar,
|
2025-05-23 14:20:45 +08:00
|
|
|
email: data.email,
|
2025-04-16 23:21:55 +08:00
|
|
|
firstName: data.firstName,
|
|
|
|
|
fullName: data.fullName,
|
|
|
|
|
id: data.userId,
|
|
|
|
|
latestName: data.lastName,
|
|
|
|
|
username: data.username,
|
|
|
|
|
} as LobeUser)
|
2024-05-24 23:51:19 +08:00
|
|
|
: get().user;
|
|
|
|
|
|
2024-05-23 22:33:07 +08:00
|
|
|
set(
|
|
|
|
|
{
|
|
|
|
|
defaultSettings,
|
2024-05-24 01:05:39 +08:00
|
|
|
isOnboard: data.isOnboard,
|
|
|
|
|
isShowPWAGuide: data.canEnablePWAGuide,
|
2024-05-23 22:33:07 +08:00
|
|
|
isUserCanEnableTrace: data.canEnableTrace,
|
2024-05-24 01:05:39 +08:00
|
|
|
isUserHasConversation: data.hasConversation,
|
2024-05-23 22:33:07 +08:00
|
|
|
isUserStateInit: true,
|
|
|
|
|
preference,
|
|
|
|
|
settings: data.settings || {},
|
2025-07-29 17:41:42 +08:00
|
|
|
subscriptionPlan: data.subscriptionPlan,
|
2024-05-24 23:51:19 +08:00
|
|
|
user,
|
2024-05-23 22:33:07 +08:00
|
|
|
},
|
|
|
|
|
false,
|
|
|
|
|
n('initUserState'),
|
|
|
|
|
);
|
2025-07-10 11:33:35 +08:00
|
|
|
//analytics
|
|
|
|
|
const analytics = getSingletonAnalyticsOptional();
|
|
|
|
|
analytics?.identify(data.userId || '', {
|
|
|
|
|
email: data.email,
|
|
|
|
|
firstName: data.firstName,
|
|
|
|
|
lastName: data.lastName,
|
|
|
|
|
username: data.username,
|
|
|
|
|
});
|
2024-05-18 22:30:48 +08:00
|
|
|
}
|
|
|
|
|
},
|
2023-12-23 16:11:17 +08:00
|
|
|
},
|
2024-05-18 22:30:48 +08:00
|
|
|
),
|
2023-07-16 23:22:26 +08:00
|
|
|
});
|