@lobehub/chat 0.140.1 → 0.141.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/locales/ar/common.json +34 -6
- package/locales/ar/setting.json +36 -0
- package/locales/de-DE/common.json +34 -6
- package/locales/de-DE/setting.json +36 -0
- package/locales/en-US/common.json +34 -6
- package/locales/en-US/setting.json +36 -0
- package/locales/es-ES/common.json +34 -6
- package/locales/es-ES/setting.json +36 -0
- package/locales/fr-FR/common.json +34 -6
- package/locales/fr-FR/setting.json +36 -0
- package/locales/it-IT/common.json +34 -6
- package/locales/it-IT/setting.json +38 -0
- package/locales/ja-JP/common.json +34 -6
- package/locales/ja-JP/setting.json +38 -0
- package/locales/ko-KR/common.json +34 -6
- package/locales/ko-KR/setting.json +36 -0
- package/locales/nl-NL/common.json +34 -6
- package/locales/nl-NL/setting.json +38 -0
- package/locales/pl-PL/common.json +34 -6
- package/locales/pl-PL/setting.json +36 -0
- package/locales/pt-BR/common.json +34 -6
- package/locales/pt-BR/setting.json +36 -0
- package/locales/ru-RU/common.json +34 -6
- package/locales/ru-RU/setting.json +36 -0
- package/locales/tr-TR/common.json +34 -6
- package/locales/tr-TR/setting.json +36 -0
- package/locales/vi-VN/common.json +34 -6
- package/locales/vi-VN/setting.json +36 -0
- package/locales/zh-CN/common.json +34 -6
- package/locales/zh-CN/setting.json +36 -0
- package/locales/zh-TW/common.json +34 -6
- package/locales/zh-TW/setting.json +36 -0
- package/package.json +10 -5
- package/src/app/chat/(desktop)/features/SessionHeader.tsx +5 -1
- package/src/app/chat/(mobile)/features/SessionHeader.tsx +9 -4
- package/src/app/chat/features/SessionListContent/List/SkeletonList.tsx +0 -1
- package/src/app/settings/(desktop)/features/Header.tsx +11 -1
- package/src/app/settings/(mobile)/features/Header/index.tsx +12 -1
- package/src/app/settings/features/SettingList/index.tsx +2 -1
- package/src/app/settings/sync/Alert.tsx +39 -0
- package/src/app/settings/sync/DeviceInfo/Card.tsx +41 -0
- package/src/app/settings/sync/DeviceInfo/DeviceName.tsx +66 -0
- package/src/app/settings/sync/DeviceInfo/index.tsx +117 -0
- package/src/app/settings/sync/PageTitle.tsx +11 -0
- package/src/app/settings/sync/WebRTC/ChannelNameInput.tsx +46 -0
- package/src/app/settings/sync/WebRTC/index.tsx +97 -0
- package/src/app/settings/sync/components/SyncSwitch/index.css +237 -0
- package/src/app/settings/sync/components/SyncSwitch/index.tsx +79 -0
- package/src/app/settings/sync/components/SystemIcon.tsx +16 -0
- package/src/app/settings/sync/layout.tsx +9 -0
- package/src/app/settings/sync/page.tsx +23 -0
- package/src/app/settings/sync/util.ts +4 -0
- package/src/components/BrowserIcon/components/Brave.tsx +56 -0
- package/src/components/BrowserIcon/components/Chrome.tsx +14 -0
- package/src/components/BrowserIcon/components/Chromium.tsx +14 -0
- package/src/components/BrowserIcon/components/Edge.tsx +36 -0
- package/src/components/BrowserIcon/components/Firefox.tsx +38 -0
- package/src/components/BrowserIcon/components/Opera.tsx +19 -0
- package/src/components/BrowserIcon/components/Safari.tsx +23 -0
- package/src/components/BrowserIcon/components/Samsung.tsx +21 -0
- package/src/components/BrowserIcon/index.tsx +50 -0
- package/src/components/BrowserIcon/types.ts +8 -0
- package/src/const/settings.ts +6 -0
- package/src/database/core/__tests__/model.test.ts +2 -2
- package/src/database/core/db.ts +1 -1
- package/src/database/core/index.ts +1 -0
- package/src/database/core/model.ts +83 -5
- package/src/database/core/sync.ts +328 -0
- package/src/database/models/__tests__/message.test.ts +0 -1
- package/src/database/models/__tests__/plugin.test.ts +5 -2
- package/src/database/models/file.ts +1 -1
- package/src/database/models/message.ts +49 -30
- package/src/database/models/plugin.ts +6 -5
- package/src/database/models/session.ts +15 -16
- package/src/database/models/sessionGroup.ts +14 -8
- package/src/database/models/topic.ts +14 -21
- package/src/features/SyncStatusInspector/DisableSync.tsx +79 -0
- package/src/features/SyncStatusInspector/EnableSync.tsx +136 -0
- package/src/features/SyncStatusInspector/EnableTag.tsx +66 -0
- package/src/features/SyncStatusInspector/index.tsx +27 -0
- package/src/hooks/useSyncData.ts +48 -0
- package/src/layout/GlobalLayout/StoreHydration.tsx +5 -0
- package/src/locales/default/common.ts +27 -5
- package/src/locales/default/setting.ts +37 -1
- package/src/services/chat.ts +6 -2
- package/src/services/config.ts +1 -1
- package/src/services/global.ts +15 -0
- package/src/store/chat/slices/topic/action.test.ts +1 -1
- package/src/store/chat/slices/topic/action.ts +21 -10
- package/src/store/global/slices/common/action.ts +71 -1
- package/src/store/global/slices/common/initialState.ts +9 -0
- package/src/store/global/slices/common/selectors.ts +1 -0
- package/src/store/global/slices/preference/initialState.ts +2 -1
- package/src/store/global/slices/preference/selectors.ts +3 -0
- package/src/store/global/slices/settings/selectors/index.ts +1 -0
- package/src/store/global/slices/settings/selectors/sync.ts +14 -0
- package/src/types/settings/index.ts +3 -0
- package/src/types/settings/sync.ts +10 -0
- package/src/types/sync.ts +41 -0
- package/src/utils/platform.ts +9 -3
- package/src/utils/responsive.ts +21 -0
|
@@ -9,6 +9,7 @@ import { StateCreator } from 'zustand/vanilla';
|
|
|
9
9
|
import { chainSummaryTitle } from '@/chains/summaryTitle';
|
|
10
10
|
import { LOADING_FLAT } from '@/const/message';
|
|
11
11
|
import { TraceNameMap } from '@/const/trace';
|
|
12
|
+
import { useClientDataSWR } from '@/libs/swr';
|
|
12
13
|
import { chatService } from '@/services/chat';
|
|
13
14
|
import { messageService } from '@/services/message';
|
|
14
15
|
import { topicService } from '@/services/topic';
|
|
@@ -22,6 +23,9 @@ import { topicSelectors } from './selectors';
|
|
|
22
23
|
|
|
23
24
|
const n = setNamespace('topic');
|
|
24
25
|
|
|
26
|
+
const SWR_USE_FETCH_TOPIC = 'SWR_USE_FETCH_TOPIC';
|
|
27
|
+
const SWR_USE_SEARCH_TOPIC = 'SWR_USE_SEARCH_TOPIC';
|
|
28
|
+
|
|
25
29
|
export interface ChatTopicAction {
|
|
26
30
|
favoriteTopic: (id: string, favState: boolean) => Promise<void>;
|
|
27
31
|
openNewTopicOrSaveTopic: () => Promise<void>;
|
|
@@ -141,18 +145,25 @@ export const chatTopic: StateCreator<
|
|
|
141
145
|
},
|
|
142
146
|
// query
|
|
143
147
|
useFetchTopics: (sessionId) =>
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
148
|
+
useClientDataSWR<ChatTopic[]>(
|
|
149
|
+
[SWR_USE_FETCH_TOPIC, sessionId],
|
|
150
|
+
async ([, sessionId]: [string, string]) => topicService.getTopics({ sessionId }),
|
|
151
|
+
{
|
|
152
|
+
onSuccess: (topics) => {
|
|
153
|
+
set({ topics, topicsInit: true }, false, n('useFetchTopics(success)', { sessionId }));
|
|
154
|
+
},
|
|
147
155
|
},
|
|
148
|
-
|
|
149
|
-
}),
|
|
156
|
+
),
|
|
150
157
|
useSearchTopics: (keywords) =>
|
|
151
|
-
useSWR<ChatTopic[]>(
|
|
152
|
-
|
|
153
|
-
|
|
158
|
+
useSWR<ChatTopic[]>(
|
|
159
|
+
[SWR_USE_SEARCH_TOPIC, keywords],
|
|
160
|
+
([, keywords]: [string, string]) => topicService.searchTopics(keywords),
|
|
161
|
+
{
|
|
162
|
+
onSuccess: (data) => {
|
|
163
|
+
set({ searchTopics: data }, false, n('useSearchTopics(success)', { keywords }));
|
|
164
|
+
},
|
|
154
165
|
},
|
|
155
|
-
|
|
166
|
+
),
|
|
156
167
|
switchTopic: async (id) => {
|
|
157
168
|
set({ activeTopicId: id }, false, n('toggleTopic'));
|
|
158
169
|
|
|
@@ -213,6 +224,6 @@ export const chatTopic: StateCreator<
|
|
|
213
224
|
set({ topicLoadingId: id }, false, n('updateTopicLoading'));
|
|
214
225
|
},
|
|
215
226
|
refreshTopic: async () => {
|
|
216
|
-
await mutate(get().activeId);
|
|
227
|
+
await mutate([SWR_USE_FETCH_TOPIC, get().activeId]);
|
|
217
228
|
},
|
|
218
229
|
});
|
|
@@ -11,12 +11,15 @@ import { messageService } from '@/services/message';
|
|
|
11
11
|
import { UserConfig, userService } from '@/services/user';
|
|
12
12
|
import type { GlobalStore } from '@/store/global';
|
|
13
13
|
import type { GlobalServerConfig, GlobalSettings } from '@/types/settings';
|
|
14
|
+
import { OnSyncEvent, PeerSyncStatus } from '@/types/sync';
|
|
14
15
|
import { merge } from '@/utils/merge';
|
|
16
|
+
import { browserInfo } from '@/utils/platform';
|
|
15
17
|
import { setNamespace } from '@/utils/storeDebug';
|
|
16
18
|
import { switchLang } from '@/utils/switchLang';
|
|
17
19
|
|
|
18
20
|
import { preferenceSelectors } from '../preference/selectors';
|
|
19
|
-
import { settingsSelectors } from '../settings/selectors';
|
|
21
|
+
import { settingsSelectors, syncSettingsSelectors } from '../settings/selectors';
|
|
22
|
+
import { commonSelectors } from './selectors';
|
|
20
23
|
|
|
21
24
|
const n = setNamespace('common');
|
|
22
25
|
|
|
@@ -24,11 +27,18 @@ const n = setNamespace('common');
|
|
|
24
27
|
* 设置操作
|
|
25
28
|
*/
|
|
26
29
|
export interface CommonAction {
|
|
30
|
+
refreshConnection: (onEvent: OnSyncEvent) => Promise<void>;
|
|
27
31
|
refreshUserConfig: () => Promise<void>;
|
|
28
32
|
switchBackToChat: (sessionId?: string) => void;
|
|
33
|
+
triggerEnableSync: (userId: string, onEvent: OnSyncEvent) => Promise<boolean>;
|
|
29
34
|
updateAvatar: (avatar: string) => Promise<void>;
|
|
30
35
|
useCheckLatestVersion: () => SWRResponse<string>;
|
|
31
36
|
useCheckTrace: (shouldFetch: boolean) => SWRResponse;
|
|
37
|
+
useEnabledSync: (
|
|
38
|
+
userEnableSync: boolean,
|
|
39
|
+
userId: string | undefined,
|
|
40
|
+
onEvent: OnSyncEvent,
|
|
41
|
+
) => SWRResponse;
|
|
32
42
|
useFetchServerConfig: () => SWRResponse;
|
|
33
43
|
useFetchUserConfig: (initServer: boolean) => SWRResponse<UserConfig | undefined>;
|
|
34
44
|
}
|
|
@@ -41,13 +51,53 @@ export const createCommonSlice: StateCreator<
|
|
|
41
51
|
[],
|
|
42
52
|
CommonAction
|
|
43
53
|
> = (set, get) => ({
|
|
54
|
+
refreshConnection: async (onEvent) => {
|
|
55
|
+
const userId = commonSelectors.userId(get());
|
|
56
|
+
|
|
57
|
+
if (!userId) return;
|
|
58
|
+
|
|
59
|
+
await get().triggerEnableSync(userId, onEvent);
|
|
60
|
+
},
|
|
61
|
+
|
|
44
62
|
refreshUserConfig: async () => {
|
|
45
63
|
await mutate([USER_CONFIG_FETCH_KEY, true]);
|
|
46
64
|
},
|
|
65
|
+
|
|
47
66
|
switchBackToChat: (sessionId) => {
|
|
48
67
|
get().router?.push(SESSION_CHAT_URL(sessionId || INBOX_SESSION_ID, get().isMobile));
|
|
49
68
|
},
|
|
69
|
+
triggerEnableSync: async (userId: string, onEvent: OnSyncEvent) => {
|
|
70
|
+
// double-check the sync ability
|
|
71
|
+
// if there is no channelName, don't start sync
|
|
72
|
+
const sync = syncSettingsSelectors.webrtcConfig(get());
|
|
73
|
+
if (!sync.channelName) return false;
|
|
74
|
+
|
|
75
|
+
const name = syncSettingsSelectors.deviceName(get());
|
|
50
76
|
|
|
77
|
+
const defaultUserName = `My ${browserInfo.browser} (${browserInfo.os})`;
|
|
78
|
+
|
|
79
|
+
set({ syncStatus: PeerSyncStatus.Connecting });
|
|
80
|
+
return globalService.enabledSync({
|
|
81
|
+
channel: {
|
|
82
|
+
name: sync.channelName,
|
|
83
|
+
password: sync.channelPassword,
|
|
84
|
+
},
|
|
85
|
+
onAwarenessChange(state) {
|
|
86
|
+
set({ syncAwareness: state });
|
|
87
|
+
},
|
|
88
|
+
onSyncEvent: onEvent,
|
|
89
|
+
onSyncStatusChange: (status) => {
|
|
90
|
+
set({ syncStatus: status });
|
|
91
|
+
},
|
|
92
|
+
signaling: sync.signaling,
|
|
93
|
+
user: {
|
|
94
|
+
id: userId,
|
|
95
|
+
// if user don't set the name, use default name
|
|
96
|
+
name: name || defaultUserName,
|
|
97
|
+
...browserInfo,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
},
|
|
51
101
|
updateAvatar: async (avatar) => {
|
|
52
102
|
await userService.updateAvatar(avatar);
|
|
53
103
|
await get().refreshUserConfig();
|
|
@@ -78,6 +128,26 @@ export const createCommonSlice: StateCreator<
|
|
|
78
128
|
revalidateOnFocus: false,
|
|
79
129
|
},
|
|
80
130
|
),
|
|
131
|
+
|
|
132
|
+
useEnabledSync: (userEnableSync, userId, onEvent) =>
|
|
133
|
+
useSWR<boolean>(
|
|
134
|
+
['enableSync', userEnableSync, userId],
|
|
135
|
+
async () => {
|
|
136
|
+
// if user don't enable sync or no userId ,don't start sync
|
|
137
|
+
if (!userId) return false;
|
|
138
|
+
|
|
139
|
+
// if user don't enable sync, stop sync
|
|
140
|
+
if (!userEnableSync) return globalService.disableSync();
|
|
141
|
+
|
|
142
|
+
return get().triggerEnableSync(userId, onEvent);
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
onSuccess: (syncEnabled) => {
|
|
146
|
+
set({ syncEnabled });
|
|
147
|
+
},
|
|
148
|
+
revalidateOnFocus: false,
|
|
149
|
+
},
|
|
150
|
+
),
|
|
81
151
|
useFetchServerConfig: () =>
|
|
82
152
|
useSWR<GlobalServerConfig>('fetchGlobalConfig', globalService.getGlobalConfig, {
|
|
83
153
|
onSuccess: (data) => {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { AppRouterInstance } from 'next/dist/shared/lib/app-router-context.shared-runtime';
|
|
2
2
|
|
|
3
|
+
import { PeerSyncStatus, SyncAwarenessState } from '@/types/sync';
|
|
4
|
+
|
|
3
5
|
export enum SidebarTabKey {
|
|
4
6
|
Chat = 'chat',
|
|
5
7
|
Market = 'market',
|
|
@@ -11,6 +13,7 @@ export enum SettingsTabs {
|
|
|
11
13
|
Agent = 'agent',
|
|
12
14
|
Common = 'common',
|
|
13
15
|
LLM = 'llm',
|
|
16
|
+
Sync = 'sync',
|
|
14
17
|
TTS = 'tts',
|
|
15
18
|
}
|
|
16
19
|
|
|
@@ -25,9 +28,15 @@ export interface GlobalCommonState {
|
|
|
25
28
|
latestVersion?: string;
|
|
26
29
|
router?: AppRouterInstance;
|
|
27
30
|
sidebarKey: SidebarTabKey;
|
|
31
|
+
syncAwareness: SyncAwarenessState[];
|
|
32
|
+
syncEnabled: boolean;
|
|
33
|
+
syncStatus: PeerSyncStatus;
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
export const initialCommonState: GlobalCommonState = {
|
|
31
37
|
isMobile: false,
|
|
32
38
|
sidebarKey: SidebarTabKey.Chat,
|
|
39
|
+
syncAwareness: [],
|
|
40
|
+
syncEnabled: false,
|
|
41
|
+
syncStatus: PeerSyncStatus.Disabled,
|
|
33
42
|
};
|
|
@@ -4,4 +4,5 @@ export const commonSelectors = {
|
|
|
4
4
|
enabledOAuthSSO: (s: GlobalStore) => s.serverConfig.enabledOAuthSSO,
|
|
5
5
|
enabledTelemetryChat: (s: GlobalStore) => s.serverConfig.telemetry.langfuse || false,
|
|
6
6
|
userAvatar: (s: GlobalStore) => s.avatar || '',
|
|
7
|
+
userId: (s: GlobalStore) => s.userId,
|
|
7
8
|
};
|
|
@@ -9,10 +9,11 @@ export interface GlobalPreference {
|
|
|
9
9
|
// which sessionGroup should expand
|
|
10
10
|
expandSessionGroupKeys: SessionGroupId[];
|
|
11
11
|
guide?: Guide;
|
|
12
|
+
hideSyncAlert?: boolean;
|
|
12
13
|
inputHeight: number;
|
|
13
14
|
mobileShowTopic?: boolean;
|
|
14
|
-
sessionsWidth: number;
|
|
15
15
|
|
|
16
|
+
sessionsWidth: number;
|
|
16
17
|
showChatSideBar?: boolean;
|
|
17
18
|
showSessionPanel?: boolean;
|
|
18
19
|
showSystemRole?: boolean;
|
|
@@ -6,7 +6,10 @@ const useCmdEnterToSend = (s: GlobalStore): boolean => s.preference.useCmdEnterT
|
|
|
6
6
|
|
|
7
7
|
const userAllowTrace = (s: GlobalStore) => s.preference.telemetry;
|
|
8
8
|
|
|
9
|
+
const hideSyncAlert = (s: GlobalStore) => s.preference.hideSyncAlert;
|
|
10
|
+
|
|
9
11
|
export const preferenceSelectors = {
|
|
12
|
+
hideSyncAlert,
|
|
10
13
|
sessionGroupKeys,
|
|
11
14
|
useCmdEnterToSend,
|
|
12
15
|
userAllowTrace,
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { GlobalStore } from '../../../store';
|
|
2
|
+
import { currentSettings } from './settings';
|
|
3
|
+
|
|
4
|
+
const webrtcConfig = (s: GlobalStore) => currentSettings(s).sync.webrtc;
|
|
5
|
+
const webrtcChannelName = (s: GlobalStore) => webrtcConfig(s).channelName;
|
|
6
|
+
const enableWebRTC = (s: GlobalStore) => webrtcConfig(s).enabled;
|
|
7
|
+
const deviceName = (s: GlobalStore) => currentSettings(s).sync.deviceName;
|
|
8
|
+
|
|
9
|
+
export const syncSettingsSelectors = {
|
|
10
|
+
deviceName,
|
|
11
|
+
enableWebRTC,
|
|
12
|
+
webrtcChannelName,
|
|
13
|
+
webrtcConfig,
|
|
14
|
+
};
|
|
@@ -4,12 +4,14 @@ import type { LobeAgentSession } from '@/types/session';
|
|
|
4
4
|
|
|
5
5
|
import { GlobalBaseSettings } from './base';
|
|
6
6
|
import { GlobalLLMConfig } from './modelProvider';
|
|
7
|
+
import { GlobalSyncSettings } from './sync';
|
|
7
8
|
import { GlobalTTSConfig } from './tts';
|
|
8
9
|
|
|
9
10
|
export type GlobalDefaultAgent = Pick<LobeAgentSession, 'config' | 'meta'>;
|
|
10
11
|
|
|
11
12
|
export * from './base';
|
|
12
13
|
export * from './modelProvider';
|
|
14
|
+
export * from './sync';
|
|
13
15
|
export * from './tts';
|
|
14
16
|
|
|
15
17
|
export interface GlobalTool {
|
|
@@ -34,6 +36,7 @@ export interface GlobalServerConfig {
|
|
|
34
36
|
export interface GlobalSettings extends GlobalBaseSettings {
|
|
35
37
|
defaultAgent: GlobalDefaultAgent;
|
|
36
38
|
languageModel: GlobalLLMConfig;
|
|
39
|
+
sync: GlobalSyncSettings;
|
|
37
40
|
tool: GlobalTool;
|
|
38
41
|
tts: GlobalTTSConfig;
|
|
39
42
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { LobeDBSchemaMap } from '@/database/core/db';
|
|
2
|
+
|
|
3
|
+
export type OnSyncEvent = (tableKey: keyof LobeDBSchemaMap) => void;
|
|
4
|
+
export type OnSyncStatusChange = (status: PeerSyncStatus) => void;
|
|
5
|
+
export type OnAwarenessChange = (state: SyncAwarenessState[]) => void;
|
|
6
|
+
|
|
7
|
+
// export type PeerSyncStatus = 'syncing' | 'synced' | 'ready' | 'unconnected';
|
|
8
|
+
|
|
9
|
+
export enum PeerSyncStatus {
|
|
10
|
+
Connecting = 'connecting',
|
|
11
|
+
Disabled = 'disabled',
|
|
12
|
+
Ready = 'ready',
|
|
13
|
+
Synced = 'synced',
|
|
14
|
+
Syncing = 'syncing',
|
|
15
|
+
Unconnected = 'unconnected',
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface StartDataSyncParams {
|
|
19
|
+
channel: {
|
|
20
|
+
name: string;
|
|
21
|
+
password?: string;
|
|
22
|
+
};
|
|
23
|
+
onAwarenessChange: OnAwarenessChange;
|
|
24
|
+
onSyncEvent: OnSyncEvent;
|
|
25
|
+
onSyncStatusChange: OnSyncStatusChange;
|
|
26
|
+
signaling?: string;
|
|
27
|
+
user: SyncUserInfo;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface SyncUserInfo {
|
|
31
|
+
browser?: string;
|
|
32
|
+
id: string;
|
|
33
|
+
isMobile: boolean;
|
|
34
|
+
name?: string;
|
|
35
|
+
os?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface SyncAwarenessState extends SyncUserInfo {
|
|
39
|
+
clientID: number;
|
|
40
|
+
current: boolean;
|
|
41
|
+
}
|
package/src/utils/platform.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import UAParser from 'ua-parser-js';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const getParser = () => {
|
|
4
4
|
if (typeof window === 'undefined') return new UAParser('Node');
|
|
5
5
|
|
|
6
6
|
let ua = navigator.userAgent;
|
|
@@ -8,11 +8,17 @@ const getPaser = () => {
|
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
export const getPlatform = () => {
|
|
11
|
-
return
|
|
11
|
+
return getParser().getOS().name;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
export const getBrowser = () => {
|
|
15
|
-
return
|
|
15
|
+
return getParser().getResult().browser.name;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const browserInfo = {
|
|
19
|
+
browser: getBrowser(),
|
|
20
|
+
isMobile: getParser().getDevice().type === 'mobile',
|
|
21
|
+
os: getParser().getOS().name,
|
|
16
22
|
};
|
|
17
23
|
|
|
18
24
|
export const isMacOS = () => getPlatform() === 'Mac OS';
|
package/src/utils/responsive.ts
CHANGED
|
@@ -17,3 +17,24 @@ export const isMobileDevice = () => {
|
|
|
17
17
|
|
|
18
18
|
return device.type === 'mobile';
|
|
19
19
|
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* check mobile device in server
|
|
23
|
+
*/
|
|
24
|
+
export const gerServerDeviceInfo = () => {
|
|
25
|
+
if (typeof process === 'undefined') {
|
|
26
|
+
throw new Error('[Server method] you are importing a server-only module outside of server');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const { get } = headers();
|
|
30
|
+
const ua = get('user-agent');
|
|
31
|
+
|
|
32
|
+
// console.debug(ua);
|
|
33
|
+
const parser = new UAParser(ua || '');
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
browser: parser.getBrowser().name,
|
|
37
|
+
isMobile: isMobileDevice(),
|
|
38
|
+
os: parser.getOS().name,
|
|
39
|
+
};
|
|
40
|
+
};
|