@lobehub/chat 1.119.1 → 1.120.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/.vscode/settings.json +2 -3
- package/CHANGELOG.md +58 -0
- package/changelog/v1.json +17 -0
- package/package.json +5 -6
- package/packages/const/src/auth.ts +0 -36
- package/packages/const/src/index.ts +3 -1
- package/packages/database/src/models/__tests__/aiModel.test.ts +1 -2
- package/packages/database/src/models/__tests__/generationBatch.test.ts +47 -1
- package/packages/database/src/models/aiModel.ts +2 -3
- package/packages/database/src/models/generationBatch.ts +8 -1
- package/packages/database/src/repositories/aiInfra/index.test.ts +1 -1
- package/packages/database/src/repositories/aiInfra/index.ts +4 -4
- package/packages/model-bank/src/aiModels/ai21.ts +1 -1
- package/packages/model-bank/src/aiModels/ai302.ts +1 -1
- package/packages/model-bank/src/aiModels/ai360.ts +1 -1
- package/packages/model-bank/src/aiModels/aihubmix.ts +3 -3
- package/packages/model-bank/src/aiModels/akashchat.ts +1 -1
- package/packages/model-bank/src/aiModels/anthropic.ts +1 -1
- package/packages/model-bank/src/aiModels/azure.ts +1 -1
- package/packages/model-bank/src/aiModels/azureai.ts +1 -1
- package/packages/model-bank/src/aiModels/baichuan.ts +1 -1
- package/packages/model-bank/src/aiModels/bedrock.ts +1 -1
- package/packages/model-bank/src/aiModels/bfl.ts +2 -3
- package/packages/model-bank/src/aiModels/cloudflare.ts +1 -1
- package/packages/model-bank/src/aiModels/cohere.ts +1 -1
- package/packages/model-bank/src/aiModels/deepseek.ts +1 -1
- package/packages/model-bank/src/aiModels/fal.ts +1 -1
- package/packages/model-bank/src/aiModels/fireworksai.ts +1 -1
- package/packages/model-bank/src/aiModels/giteeai.ts +1 -1
- package/packages/model-bank/src/aiModels/github.ts +1 -1
- package/packages/model-bank/src/aiModels/google.ts +6 -7
- package/packages/model-bank/src/aiModels/groq.ts +1 -1
- package/packages/model-bank/src/aiModels/higress.ts +1 -1
- package/packages/model-bank/src/aiModels/huggingface.ts +1 -1
- package/packages/model-bank/src/aiModels/hunyuan.ts +1 -1
- package/packages/model-bank/src/aiModels/index.ts +1 -1
- package/packages/model-bank/src/aiModels/infiniai.ts +1 -1
- package/packages/model-bank/src/aiModels/internlm.ts +1 -1
- package/packages/model-bank/src/aiModels/jina.ts +1 -1
- package/packages/model-bank/src/aiModels/lmstudio.ts +1 -1
- package/packages/model-bank/src/aiModels/lobehub.ts +1 -1
- package/packages/model-bank/src/aiModels/minimax.ts +1 -1
- package/packages/model-bank/src/aiModels/mistral.ts +1 -1
- package/packages/model-bank/src/aiModels/modelscope.ts +1 -1
- package/packages/model-bank/src/aiModels/moonshot.ts +1 -1
- package/packages/model-bank/src/aiModels/novita.ts +1 -1
- package/packages/model-bank/src/aiModels/nvidia.ts +1 -1
- package/packages/model-bank/src/aiModels/ollama.ts +1 -1
- package/packages/model-bank/src/aiModels/openai.ts +1 -1
- package/packages/model-bank/src/aiModels/openrouter.ts +3 -3
- package/packages/model-bank/src/aiModels/perplexity.ts +1 -1
- package/packages/model-bank/src/aiModels/ppio.ts +1 -1
- package/packages/model-bank/src/aiModels/qiniu.ts +1 -1
- package/packages/model-bank/src/aiModels/qwen.ts +4 -2
- package/packages/model-bank/src/aiModels/sambanova.ts +1 -1
- package/packages/model-bank/src/aiModels/search1api.ts +1 -1
- package/packages/model-bank/src/aiModels/sensenova.ts +1 -1
- package/packages/model-bank/src/aiModels/siliconcloud.ts +7 -1
- package/packages/model-bank/src/aiModels/spark.ts +1 -1
- package/packages/model-bank/src/aiModels/stepfun.ts +1 -1
- package/packages/model-bank/src/aiModels/taichu.ts +1 -1
- package/packages/model-bank/src/aiModels/tencentcloud.ts +1 -1
- package/packages/model-bank/src/aiModels/togetherai.ts +1 -1
- package/packages/model-bank/src/aiModels/upstage.ts +1 -1
- package/packages/model-bank/src/aiModels/v0.ts +1 -1
- package/packages/model-bank/src/aiModels/vertexai.ts +3 -3
- package/packages/model-bank/src/aiModels/vllm.ts +1 -1
- package/packages/model-bank/src/aiModels/volcengine.ts +1 -1
- package/packages/model-bank/src/aiModels/wenxin.ts +1 -1
- package/packages/model-bank/src/aiModels/xai.ts +1 -1
- package/packages/model-bank/src/aiModels/xinference.ts +1 -1
- package/packages/model-bank/src/aiModels/zeroone.ts +1 -1
- package/packages/model-bank/src/aiModels/zhipu.ts +1 -1
- package/packages/model-bank/src/index.ts +1 -0
- package/packages/model-bank/src/standard-parameters/index.ts +48 -0
- package/packages/{types/src → model-bank/src/types}/aiModel.ts +12 -1
- package/packages/model-bank/src/types/index.ts +1 -0
- package/packages/model-runtime/package.json +4 -1
- package/packages/model-runtime/src/BaseAI.ts +2 -2
- package/packages/model-runtime/src/ModelRuntime.test.ts +4 -4
- package/packages/model-runtime/src/RouterRuntime/createRuntime.ts +3 -7
- package/packages/model-runtime/src/ai302/index.ts +1 -1
- package/packages/model-runtime/src/aihubmix/index.ts +1 -2
- package/packages/model-runtime/src/anthropic/index.ts +1 -1
- package/packages/model-runtime/src/azureOpenai/index.ts +2 -3
- package/packages/model-runtime/src/azureai/index.ts +2 -3
- package/packages/model-runtime/src/bedrock/index.ts +1 -1
- package/packages/model-runtime/src/bfl/createImage.test.ts +4 -4
- package/packages/model-runtime/src/bfl/createImage.ts +2 -2
- package/packages/model-runtime/src/bfl/index.ts +1 -1
- package/packages/model-runtime/src/cloudflare/index.ts +1 -1
- package/packages/model-runtime/src/const/models.ts +64 -0
- package/packages/model-runtime/src/fal/index.test.ts +2 -3
- package/packages/model-runtime/src/fal/index.ts +1 -1
- package/packages/model-runtime/src/github/index.ts +1 -1
- package/packages/model-runtime/src/google/createImage.test.ts +1 -1
- package/packages/model-runtime/src/google/createImage.ts +53 -25
- package/packages/model-runtime/src/google/index.test.ts +1 -1
- package/packages/model-runtime/src/google/index.ts +4 -3
- package/packages/model-runtime/src/groq/index.ts +1 -1
- package/packages/model-runtime/src/helpers/parseToolCalls.ts +1 -2
- package/packages/model-runtime/src/huggingface/index.ts +1 -1
- package/packages/model-runtime/src/index.ts +3 -1
- package/packages/model-runtime/src/infiniai/index.ts +1 -1
- package/packages/model-runtime/src/ollama/index.test.ts +1 -1
- package/packages/model-runtime/src/ollama/index.ts +2 -3
- package/packages/model-runtime/src/openai/index.ts +16 -8
- package/packages/model-runtime/src/providerTestUtils.ts +1 -2
- package/packages/model-runtime/src/qiniu/index.test.ts +2 -3
- package/packages/model-runtime/src/qwen/index.ts +1 -1
- package/packages/model-runtime/src/siliconcloud/index.ts +2 -2
- package/packages/model-runtime/src/types/chat.ts +2 -22
- package/packages/model-runtime/src/{error.ts → types/error.ts} +29 -0
- package/packages/model-runtime/src/types/index.ts +4 -0
- package/packages/model-runtime/src/types/toolsCalling.ts +48 -0
- package/packages/model-runtime/src/types/type.ts +1 -1
- package/packages/model-runtime/src/types/usage.ts +27 -0
- package/packages/model-runtime/src/utils/anthropicHelpers.test.ts +2 -2
- package/packages/model-runtime/src/utils/anthropicHelpers.ts +1 -1
- package/packages/model-runtime/src/utils/createError.ts +1 -1
- package/packages/model-runtime/src/utils/errorResponse.test.ts +110 -0
- package/packages/model-runtime/src/utils/errorResponse.ts +64 -0
- package/packages/{utils/src → model-runtime/src/utils}/getFallbackModelProperty.ts +1 -1
- package/packages/model-runtime/src/utils/googleErrorParser.test.ts +1 -1
- package/packages/model-runtime/src/utils/googleErrorParser.ts +1 -1
- package/packages/model-runtime/src/utils/handleOpenAIError.ts +1 -1
- package/packages/model-runtime/src/utils/imageToBase64.test.ts +91 -0
- package/packages/model-runtime/src/utils/imageToBase64.ts +62 -0
- package/packages/model-runtime/src/utils/modelParse.test.ts +2 -2
- package/packages/model-runtime/src/utils/modelParse.ts +16 -10
- package/packages/model-runtime/src/utils/openaiCompatibleFactory/createImage.ts +1 -1
- package/packages/model-runtime/src/utils/openaiCompatibleFactory/index.ts +3 -3
- package/packages/model-runtime/src/utils/openaiHelpers.test.ts +2 -2
- package/packages/model-runtime/src/utils/openaiHelpers.ts +3 -4
- package/packages/model-runtime/src/utils/postProcessModelList.ts +2 -2
- package/packages/model-runtime/src/utils/safeParseJSON.test.ts +71 -0
- package/packages/model-runtime/src/utils/safeParseJSON.ts +12 -0
- package/packages/model-runtime/src/utils/streams/bedrock/claude.ts +1 -1
- package/packages/model-runtime/src/utils/streams/bedrock/llama.test.ts +1 -2
- package/packages/model-runtime/src/utils/streams/bedrock/llama.ts +1 -1
- package/packages/model-runtime/src/utils/streams/google-ai.test.ts +1 -1
- package/packages/model-runtime/src/utils/streams/google-ai.ts +1 -1
- package/packages/model-runtime/src/utils/streams/ollama.test.ts +1 -1
- package/packages/model-runtime/src/utils/streams/ollama.ts +2 -3
- package/packages/model-runtime/src/utils/streams/openai/openai.test.ts +1 -2
- package/packages/model-runtime/src/utils/streams/openai/openai.ts +1 -1
- package/packages/model-runtime/src/utils/streams/openai/responsesStream.ts +1 -1
- package/packages/model-runtime/src/utils/streams/protocol.ts +3 -3
- package/packages/model-runtime/src/utils/streams/vertex-ai.test.ts +1 -1
- package/packages/model-runtime/src/utils/streams/vertex-ai.ts +2 -2
- package/packages/model-runtime/src/utils/uuid.ts +7 -0
- package/packages/model-runtime/src/vertexai/index.ts +1 -1
- package/packages/types/src/agent/index.ts +2 -1
- package/packages/types/src/aiProvider.ts +10 -2
- package/packages/types/src/auth.ts +35 -0
- package/packages/types/src/discover/models.ts +1 -1
- package/packages/types/src/discover/providers.ts +1 -1
- package/packages/types/src/index.ts +4 -0
- package/packages/types/src/llm.ts +2 -47
- package/packages/types/src/session/agentSession.ts +3 -3
- package/packages/types/src/session/index.ts +2 -2
- package/packages/types/src/session/sessionGroup.ts +0 -2
- package/packages/types/src/user/settings/general.ts +1 -1
- package/packages/types/src/user/settings/modelProvider.ts +1 -1
- package/packages/utils/src/fetch/fetchSSE.ts +1 -1
- package/packages/utils/src/format.ts +2 -3
- package/packages/utils/src/index.ts +3 -1
- package/packages/utils/src/number.test.ts +1 -2
- package/packages/utils/src/number.ts +1 -2
- package/packages/utils/src/parseModels.test.ts +1 -2
- package/packages/utils/src/parseModels.ts +2 -3
- package/packages/utils/src/pricing.test.ts +1 -2
- package/packages/utils/src/pricing.ts +1 -1
- package/packages/utils/src/server/xor.ts +3 -1
- package/src/app/(backend)/middleware/auth/index.ts +1 -2
- package/src/app/(backend)/webapi/chat/vertexai/route.ts +1 -1
- package/src/app/(backend)/webapi/text-to-image/[provider]/route.ts +1 -2
- package/src/app/[variants]/(main)/(mobile)/me/settings/features/useCategory.tsx +2 -16
- package/src/app/[variants]/(main)/chat/@session/_layout/Desktop/SessionHeader.tsx +1 -3
- package/src/app/[variants]/(main)/chat/@session/_layout/Mobile/SessionHeader.tsx +1 -3
- package/src/app/[variants]/(main)/discover/(list)/model/features/List/ModelTypeIcon.tsx +1 -2
- package/src/app/[variants]/(main)/image/@menu/components/SeedNumberInput/index.tsx +1 -1
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/hooks/useAutoDimensions.ts +4 -3
- package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +3 -21
- package/src/app/[variants]/(main)/settings/provider/features/ModelList/CreateNewModelModal/Form.tsx +1 -1
- package/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelItem.tsx +1 -1
- package/src/app/[variants]/(main)/settings/provider/features/ModelList/SortModelModal/ListItem.tsx +1 -1
- package/src/app/[variants]/(main)/settings/provider/features/ModelList/SortModelModal/index.tsx +1 -1
- package/src/components/ModelSelect/index.tsx +1 -1
- package/src/config/featureFlags/schema.test.ts +1 -2
- package/src/config/featureFlags/schema.ts +0 -6
- package/src/config/featureFlags/utils/parser.test.ts +7 -7
- package/src/database/_deprecated/core/index.ts +0 -1
- package/src/database/_deprecated/core/migrations/migrateSettingsToUser/type.ts +2 -5
- package/src/database/_deprecated/core/model.ts +4 -38
- package/src/database/_deprecated/models/message.ts +1 -1
- package/src/features/Conversation/Extras/Usage/UsageDetail/ModelCard.tsx +1 -1
- package/src/features/Conversation/Extras/Usage/UsageDetail/pricing.ts +3 -4
- package/src/features/Conversation/Extras/Usage/UsageDetail/tokens.test.ts +1 -1
- package/src/features/Conversation/Extras/Usage/UsageDetail/tokens.ts +3 -2
- package/src/layout/GlobalProvider/StoreInitialization.tsx +0 -3
- package/src/libs/trpc/async/context.ts +2 -1
- package/src/libs/trpc/edge/context.ts +2 -6
- package/src/libs/trpc/lambda/context.ts +1 -1
- package/src/migrations/FromV5ToV6/types/v5.ts +2 -2
- package/src/migrations/FromV5ToV6/types/v6.ts +2 -1
- package/src/server/globalConfig/genServerAiProviderConfig.ts +3 -3
- package/src/server/modules/ModelRuntime/index.test.ts +1 -1
- package/src/server/modules/ModelRuntime/index.ts +1 -1
- package/src/server/routers/async/caller.ts +2 -1
- package/src/server/routers/async/image.ts +2 -2
- package/src/server/routers/lambda/aiModel.ts +1 -1
- package/src/server/services/chunk/index.ts +2 -1
- package/src/server/services/generation/index.ts +2 -2
- package/src/services/_auth.ts +2 -1
- package/src/services/aiModel/server.test.ts +1 -1
- package/src/services/aiModel/type.ts +1 -1
- package/src/services/chat.ts +1 -1
- package/src/services/upload.ts +3 -3
- package/src/store/agent/slices/chat/action.ts +1 -1
- package/src/store/aiInfra/slices/aiModel/action.ts +6 -6
- package/src/store/aiInfra/slices/aiModel/initialState.ts +1 -1
- package/src/store/aiInfra/slices/aiModel/selectors.test.ts +1 -1
- package/src/store/aiInfra/slices/aiModel/selectors.ts +2 -1
- package/src/store/aiInfra/slices/aiProvider/__tests__/action.test.ts +7 -7
- package/src/store/aiInfra/slices/aiProvider/action.ts +8 -8
- package/src/store/aiInfra/slices/aiProvider/initialState.ts +2 -1
- package/src/store/electron/actions/app.ts +1 -1
- package/src/store/image/slices/generationConfig/action.test.ts +1 -1
- package/src/store/image/slices/generationConfig/action.ts +1 -1
- package/src/store/image/slices/generationConfig/hooks.test.ts +1 -1
- package/src/store/image/slices/generationConfig/hooks.ts +6 -3
- package/src/store/image/slices/generationConfig/selectors.test.ts +1 -1
- package/src/store/serverConfig/selectors.test.ts +0 -1
- package/src/store/user/initialState.ts +1 -4
- package/src/store/user/selectors.ts +0 -1
- package/src/store/user/slices/auth/action.ts +1 -1
- package/src/store/user/slices/auth/selectors.ts +3 -4
- package/src/store/user/slices/modelList/action.ts +8 -7
- package/src/store/user/slices/modelList/selectors/modelProvider.ts +8 -5
- package/src/store/user/slices/preference/selectors.ts +3 -2
- package/src/store/user/slices/settings/selectors/settings.ts +1 -2
- package/src/store/user/store.ts +1 -4
- package/docs/self-hosting/advanced/webrtc.mdx +0 -86
- package/docs/self-hosting/advanced/webrtc.zh-CN.mdx +0 -80
- package/packages/const/src/image.ts +0 -51
- package/src/app/[variants]/(main)/settings/sync/features/Alert.tsx +0 -53
- package/src/app/[variants]/(main)/settings/sync/features/DeviceInfo/Card.tsx +0 -42
- package/src/app/[variants]/(main)/settings/sync/features/DeviceInfo/DeviceName.tsx +0 -62
- package/src/app/[variants]/(main)/settings/sync/features/DeviceInfo/SystemIcon.tsx +0 -31
- package/src/app/[variants]/(main)/settings/sync/features/DeviceInfo/index.tsx +0 -103
- package/src/app/[variants]/(main)/settings/sync/features/WebRTC/ChannelNameInput.tsx +0 -45
- package/src/app/[variants]/(main)/settings/sync/features/WebRTC/SyncSwitch/index.css +0 -238
- package/src/app/[variants]/(main)/settings/sync/features/WebRTC/SyncSwitch/index.tsx +0 -79
- package/src/app/[variants]/(main)/settings/sync/features/WebRTC/generateRandomRoomName.ts +0 -4
- package/src/app/[variants]/(main)/settings/sync/features/WebRTC/index.tsx +0 -103
- package/src/app/[variants]/(main)/settings/sync/index.tsx +0 -17
- package/src/app/[variants]/(main)/settings/sync/page.tsx +0 -29
- package/src/database/_deprecated/core/sync.ts +0 -321
- package/src/features/SyncStatusInspector/DisableSync.tsx +0 -79
- package/src/features/SyncStatusInspector/EnableSync.tsx +0 -132
- package/src/features/SyncStatusInspector/EnableTag.tsx +0 -66
- package/src/features/SyncStatusInspector/index.tsx +0 -27
- package/src/hooks/useSyncData.ts +0 -50
- package/src/services/__tests__/sync.test.ts +0 -56
- package/src/services/sync.ts +0 -19
- package/src/store/user/slices/sync/action.test.ts +0 -164
- package/src/store/user/slices/sync/action.ts +0 -101
- package/src/store/user/slices/sync/initialState.ts +0 -13
- package/src/store/user/slices/sync/selectors.ts +0 -20
- /package/packages/{utils/src → model-runtime/src/utils}/getFallbackModelProperty.test.ts +0 -0
@@ -1,66 +0,0 @@
|
|
1
|
-
import { Icon, Tag, Tooltip } from '@lobehub/ui';
|
2
|
-
import { Badge } from 'antd';
|
3
|
-
import { LucideCloudy, LucideRefreshCw, LucideRouter, LucideWifiOff } from 'lucide-react';
|
4
|
-
import { memo } from 'react';
|
5
|
-
import { useTranslation } from 'react-i18next';
|
6
|
-
|
7
|
-
import { PeerSyncStatus } from '@/types/sync';
|
8
|
-
|
9
|
-
const EnableTag = memo<{ isSyncing: boolean; status: PeerSyncStatus }>(({ status, isSyncing }) => {
|
10
|
-
const { t } = useTranslation('common');
|
11
|
-
|
12
|
-
switch (status) {
|
13
|
-
case PeerSyncStatus.Connecting: {
|
14
|
-
return (
|
15
|
-
<Tag
|
16
|
-
bordered={false}
|
17
|
-
color={'blue'}
|
18
|
-
icon={<Badge color={'blue'} status="processing" />}
|
19
|
-
style={{ display: 'flex', gap: 4 }}
|
20
|
-
>
|
21
|
-
{t('sync.status.connecting')}
|
22
|
-
</Tag>
|
23
|
-
);
|
24
|
-
}
|
25
|
-
|
26
|
-
case PeerSyncStatus.Synced: {
|
27
|
-
return (
|
28
|
-
<Tag bordered={false} color={'green'} icon={<Icon icon={LucideCloudy} />}>
|
29
|
-
{t('sync.status.synced')}
|
30
|
-
</Tag>
|
31
|
-
);
|
32
|
-
}
|
33
|
-
|
34
|
-
case PeerSyncStatus.Ready: {
|
35
|
-
return (
|
36
|
-
<Tag bordered={false} color={'blue'} icon={<Icon icon={LucideRouter} />}>
|
37
|
-
{t('sync.status.ready')}
|
38
|
-
</Tag>
|
39
|
-
);
|
40
|
-
}
|
41
|
-
|
42
|
-
case PeerSyncStatus.Syncing: {
|
43
|
-
return (
|
44
|
-
<Tag
|
45
|
-
bordered={false}
|
46
|
-
color={'blue'}
|
47
|
-
icon={<Icon icon={LucideRefreshCw} spin={isSyncing} />}
|
48
|
-
>
|
49
|
-
{t('sync.status.syncing')}
|
50
|
-
</Tag>
|
51
|
-
);
|
52
|
-
}
|
53
|
-
|
54
|
-
case PeerSyncStatus.Unconnected: {
|
55
|
-
return (
|
56
|
-
<Tooltip title={t('sync.unconnected.tip')}>
|
57
|
-
<Tag bordered={false} color={'red'} icon={<Icon icon={LucideWifiOff} />}>
|
58
|
-
{t('sync.status.unconnected')}
|
59
|
-
</Tag>
|
60
|
-
</Tooltip>
|
61
|
-
);
|
62
|
-
}
|
63
|
-
}
|
64
|
-
});
|
65
|
-
|
66
|
-
export default EnableTag;
|
@@ -1,27 +0,0 @@
|
|
1
|
-
import { TooltipPlacement } from 'antd/es/tooltip';
|
2
|
-
import { memo } from 'react';
|
3
|
-
|
4
|
-
import { useUserStore } from '@/store/user';
|
5
|
-
|
6
|
-
import DisableSync from './DisableSync';
|
7
|
-
import EnableSync from './EnableSync';
|
8
|
-
|
9
|
-
interface SyncStatusTagProps {
|
10
|
-
hiddenActions?: boolean;
|
11
|
-
hiddenEnableGuide?: boolean;
|
12
|
-
placement?: TooltipPlacement;
|
13
|
-
}
|
14
|
-
|
15
|
-
const SyncStatusTag = memo<SyncStatusTagProps>(
|
16
|
-
({ hiddenActions, placement, hiddenEnableGuide }) => {
|
17
|
-
const [enableSync] = useUserStore((s) => [s.syncEnabled]);
|
18
|
-
|
19
|
-
return enableSync ? (
|
20
|
-
<EnableSync hiddenActions={hiddenActions} placement={placement} />
|
21
|
-
) : (
|
22
|
-
<DisableSync noPopover={hiddenEnableGuide} placement={placement} />
|
23
|
-
);
|
24
|
-
},
|
25
|
-
);
|
26
|
-
|
27
|
-
export default SyncStatusTag;
|
package/src/hooks/useSyncData.ts
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
import { useCallback } from 'react';
|
2
|
-
|
3
|
-
import { useChatStore } from '@/store/chat';
|
4
|
-
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
5
|
-
import { useSessionStore } from '@/store/session';
|
6
|
-
import { useUserStore } from '@/store/user';
|
7
|
-
import { syncSettingsSelectors, userProfileSelectors } from '@/store/user/selectors';
|
8
|
-
|
9
|
-
export const useSyncEvent = () => {
|
10
|
-
const [refreshMessages, refreshTopic] = useChatStore((s) => [s.refreshMessages, s.refreshTopic]);
|
11
|
-
const [refreshSessions] = useSessionStore((s) => [s.refreshSessions]);
|
12
|
-
|
13
|
-
return useCallback((tableKey: string) => {
|
14
|
-
// console.log('triggerSync Event:', tableKey);
|
15
|
-
|
16
|
-
switch (tableKey) {
|
17
|
-
case 'messages': {
|
18
|
-
refreshMessages();
|
19
|
-
break;
|
20
|
-
}
|
21
|
-
|
22
|
-
case 'topics': {
|
23
|
-
refreshTopic();
|
24
|
-
break;
|
25
|
-
}
|
26
|
-
|
27
|
-
case 'sessions': {
|
28
|
-
refreshSessions();
|
29
|
-
break;
|
30
|
-
}
|
31
|
-
|
32
|
-
default: {
|
33
|
-
break;
|
34
|
-
}
|
35
|
-
}
|
36
|
-
}, []);
|
37
|
-
};
|
38
|
-
|
39
|
-
export const useEnabledDataSync = () => {
|
40
|
-
const [userId, userEnableSync, useEnabledSync] = useUserStore((s) => [
|
41
|
-
userProfileSelectors.userId(s),
|
42
|
-
syncSettingsSelectors.enableWebRTC(s),
|
43
|
-
s.useEnabledSync,
|
44
|
-
]);
|
45
|
-
|
46
|
-
const { enableWebrtc } = useServerConfigStore(featureFlagsSelectors);
|
47
|
-
const syncEvent = useSyncEvent();
|
48
|
-
|
49
|
-
useEnabledSync(enableWebrtc, { onEvent: syncEvent, userEnableSync, userId });
|
50
|
-
};
|
@@ -1,56 +0,0 @@
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
2
|
-
|
3
|
-
import { dataSync } from '@/database/_deprecated/core';
|
4
|
-
import { StartDataSyncParams } from '@/types/sync';
|
5
|
-
|
6
|
-
import { syncService } from '../sync';
|
7
|
-
|
8
|
-
vi.mock('@/database/_deprecated/core', () => ({
|
9
|
-
dataSync: {
|
10
|
-
startDataSync: vi.fn(),
|
11
|
-
disconnect: vi.fn(),
|
12
|
-
},
|
13
|
-
}));
|
14
|
-
|
15
|
-
describe('SyncService', () => {
|
16
|
-
afterEach(() => {
|
17
|
-
vi.resetAllMocks();
|
18
|
-
});
|
19
|
-
|
20
|
-
describe('enabledSync', () => {
|
21
|
-
it('should return false when running on server side', async () => {
|
22
|
-
const params = { user: { id: '123' }, authToken: 'abc' } as unknown as StartDataSyncParams;
|
23
|
-
|
24
|
-
const origin = global.window;
|
25
|
-
|
26
|
-
// @ts-ignore
|
27
|
-
global.window = undefined;
|
28
|
-
|
29
|
-
const result = await syncService.enabledSync(params);
|
30
|
-
|
31
|
-
expect(result).toBe(false);
|
32
|
-
expect(dataSync.startDataSync).not.toHaveBeenCalled();
|
33
|
-
|
34
|
-
// reset
|
35
|
-
global.window = origin;
|
36
|
-
});
|
37
|
-
|
38
|
-
it('should start data sync and return true when running on client side', async () => {
|
39
|
-
const params = { user: { id: '123' }, authToken: 'abc' } as unknown as StartDataSyncParams;
|
40
|
-
|
41
|
-
const result = await syncService.enabledSync(params);
|
42
|
-
|
43
|
-
expect(result).toBe(true);
|
44
|
-
expect(dataSync.startDataSync).toHaveBeenCalledWith(params);
|
45
|
-
});
|
46
|
-
});
|
47
|
-
|
48
|
-
describe('disableSync', () => {
|
49
|
-
it('should disconnect data sync and return false', async () => {
|
50
|
-
const result = await syncService.disableSync();
|
51
|
-
|
52
|
-
expect(result).toBe(false);
|
53
|
-
expect(dataSync.disconnect).toHaveBeenCalled();
|
54
|
-
});
|
55
|
-
});
|
56
|
-
});
|
package/src/services/sync.ts
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
import { dataSync } from '@/database/_deprecated/core';
|
2
|
-
import { StartDataSyncParams } from '@/types/sync';
|
3
|
-
|
4
|
-
class SyncService {
|
5
|
-
enabledSync = async (params: StartDataSyncParams) => {
|
6
|
-
if (typeof window === 'undefined') return false;
|
7
|
-
|
8
|
-
await dataSync.startDataSync(params);
|
9
|
-
return true;
|
10
|
-
};
|
11
|
-
|
12
|
-
disableSync = async () => {
|
13
|
-
await dataSync.disconnect();
|
14
|
-
|
15
|
-
return false;
|
16
|
-
};
|
17
|
-
}
|
18
|
-
|
19
|
-
export const syncService = new SyncService();
|
@@ -1,164 +0,0 @@
|
|
1
|
-
import { act, renderHook, waitFor } from '@testing-library/react';
|
2
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
3
|
-
import { withSWR } from '~test-utils';
|
4
|
-
|
5
|
-
import { syncService } from '@/services/sync';
|
6
|
-
import { useUserStore } from '@/store/user';
|
7
|
-
import { userProfileSelectors } from '@/store/user/selectors';
|
8
|
-
import { syncSettingsSelectors } from '@/store/user/selectors';
|
9
|
-
|
10
|
-
vi.mock('zustand/traditional');
|
11
|
-
|
12
|
-
vi.mock('swr', async (importOriginal) => {
|
13
|
-
const modules = await importOriginal();
|
14
|
-
return {
|
15
|
-
...(modules as any),
|
16
|
-
mutate: vi.fn(),
|
17
|
-
};
|
18
|
-
});
|
19
|
-
|
20
|
-
afterEach(() => {
|
21
|
-
vi.restoreAllMocks();
|
22
|
-
});
|
23
|
-
|
24
|
-
describe('createSyncSlice', () => {
|
25
|
-
describe('refreshConnection', () => {
|
26
|
-
it('should not call triggerEnableSync when userId is empty', async () => {
|
27
|
-
const { result } = renderHook(() => useUserStore());
|
28
|
-
const onEvent = vi.fn();
|
29
|
-
|
30
|
-
vi.spyOn(userProfileSelectors, 'userId').mockReturnValueOnce(undefined as any);
|
31
|
-
const triggerEnableSyncSpy = vi.spyOn(result.current, 'triggerEnableSync');
|
32
|
-
|
33
|
-
await act(async () => {
|
34
|
-
await result.current.refreshConnection(onEvent);
|
35
|
-
});
|
36
|
-
|
37
|
-
expect(triggerEnableSyncSpy).not.toHaveBeenCalled();
|
38
|
-
});
|
39
|
-
|
40
|
-
it('should call triggerEnableSync when userId exists', async () => {
|
41
|
-
const { result } = renderHook(() => useUserStore());
|
42
|
-
const onEvent = vi.fn();
|
43
|
-
const userId = 'user-id';
|
44
|
-
|
45
|
-
vi.spyOn(userProfileSelectors, 'userId').mockReturnValueOnce(userId);
|
46
|
-
const triggerEnableSyncSpy = vi.spyOn(result.current, 'triggerEnableSync');
|
47
|
-
|
48
|
-
await act(async () => {
|
49
|
-
await result.current.refreshConnection(onEvent);
|
50
|
-
});
|
51
|
-
|
52
|
-
expect(triggerEnableSyncSpy).toHaveBeenCalledWith(userId, onEvent);
|
53
|
-
});
|
54
|
-
});
|
55
|
-
|
56
|
-
describe('triggerEnableSync', () => {
|
57
|
-
it('should return false when sync.channelName is empty', async () => {
|
58
|
-
const { result } = renderHook(() => useUserStore());
|
59
|
-
const userId = 'user-id';
|
60
|
-
const onEvent = vi.fn();
|
61
|
-
|
62
|
-
vi.spyOn(syncSettingsSelectors, 'webrtcConfig').mockReturnValueOnce({
|
63
|
-
channelName: '',
|
64
|
-
enabled: true,
|
65
|
-
});
|
66
|
-
|
67
|
-
const data = await act(async () => {
|
68
|
-
return result.current.triggerEnableSync(userId, onEvent);
|
69
|
-
});
|
70
|
-
|
71
|
-
expect(data).toBe(false);
|
72
|
-
});
|
73
|
-
|
74
|
-
it('should call globalService.enabledSync when sync.channelName exists', async () => {
|
75
|
-
const userId = 'user-id';
|
76
|
-
const onEvent = vi.fn();
|
77
|
-
const channelName = 'channel-name';
|
78
|
-
const channelPassword = 'channel-password';
|
79
|
-
const deviceName = 'device-name';
|
80
|
-
const signaling = 'signaling';
|
81
|
-
|
82
|
-
vi.spyOn(syncSettingsSelectors, 'webrtcConfig').mockReturnValueOnce({
|
83
|
-
channelName,
|
84
|
-
channelPassword,
|
85
|
-
signaling,
|
86
|
-
enabled: true,
|
87
|
-
});
|
88
|
-
vi.spyOn(syncSettingsSelectors, 'deviceName').mockReturnValueOnce(deviceName);
|
89
|
-
const enabledSyncSpy = vi.spyOn(syncService, 'enabledSync').mockResolvedValueOnce(true);
|
90
|
-
const { result } = renderHook(() => useUserStore());
|
91
|
-
|
92
|
-
const data = await act(async () => {
|
93
|
-
return result.current.triggerEnableSync(userId, onEvent);
|
94
|
-
});
|
95
|
-
|
96
|
-
expect(enabledSyncSpy).toHaveBeenCalledWith({
|
97
|
-
channel: { name: channelName, password: channelPassword },
|
98
|
-
onAwarenessChange: expect.any(Function),
|
99
|
-
onSyncEvent: onEvent,
|
100
|
-
onSyncStatusChange: expect.any(Function),
|
101
|
-
signaling,
|
102
|
-
user: expect.objectContaining({ id: userId, name: deviceName }),
|
103
|
-
});
|
104
|
-
expect(data).toBe(true);
|
105
|
-
});
|
106
|
-
});
|
107
|
-
|
108
|
-
describe('useEnabledSync', () => {
|
109
|
-
it('should return false when userId is empty', async () => {
|
110
|
-
const { result } = renderHook(
|
111
|
-
() =>
|
112
|
-
useUserStore().useEnabledSync(true, {
|
113
|
-
userEnableSync: true,
|
114
|
-
userId: undefined,
|
115
|
-
onEvent: vi.fn(),
|
116
|
-
}),
|
117
|
-
{
|
118
|
-
wrapper: withSWR,
|
119
|
-
},
|
120
|
-
);
|
121
|
-
|
122
|
-
await waitFor(() => expect(result.current.data).toBe(false));
|
123
|
-
});
|
124
|
-
|
125
|
-
it('should call syncService.disableSync when userEnableSync is false', async () => {
|
126
|
-
const disableSyncSpy = vi.spyOn(syncService, 'disableSync').mockResolvedValueOnce(false);
|
127
|
-
|
128
|
-
const { result } = renderHook(
|
129
|
-
() =>
|
130
|
-
useUserStore().useEnabledSync(true, {
|
131
|
-
userEnableSync: false,
|
132
|
-
userId: 'user-id',
|
133
|
-
onEvent: vi.fn(),
|
134
|
-
}),
|
135
|
-
|
136
|
-
{ wrapper: withSWR },
|
137
|
-
);
|
138
|
-
|
139
|
-
await waitFor(() => expect(result.current.data).toBeUndefined());
|
140
|
-
expect(disableSyncSpy).toHaveBeenCalled();
|
141
|
-
});
|
142
|
-
|
143
|
-
it('should call triggerEnableSync when userEnableSync and userId exist', async () => {
|
144
|
-
const userId = 'user-id';
|
145
|
-
const onEvent = vi.fn();
|
146
|
-
const triggerEnableSyncSpy = vi.fn().mockResolvedValueOnce(true);
|
147
|
-
|
148
|
-
const { result } = renderHook(() => useUserStore());
|
149
|
-
|
150
|
-
// replace triggerEnableSync as a mock
|
151
|
-
result.current.triggerEnableSync = triggerEnableSyncSpy;
|
152
|
-
|
153
|
-
const { result: swrResult } = renderHook(
|
154
|
-
() => result.current.useEnabledSync(true, { userEnableSync: true, userId, onEvent }),
|
155
|
-
{
|
156
|
-
wrapper: withSWR,
|
157
|
-
},
|
158
|
-
);
|
159
|
-
|
160
|
-
await waitFor(() => expect(swrResult.current.data).toBe(true));
|
161
|
-
expect(triggerEnableSyncSpy).toHaveBeenCalledWith(userId, onEvent);
|
162
|
-
});
|
163
|
-
});
|
164
|
-
});
|
@@ -1,101 +0,0 @@
|
|
1
|
-
import useSWR, { SWRResponse } from 'swr';
|
2
|
-
import type { StateCreator } from 'zustand/vanilla';
|
3
|
-
|
4
|
-
import type { UserStore } from '@/store/user';
|
5
|
-
import { OnSyncEvent, PeerSyncStatus } from '@/types/sync';
|
6
|
-
import { browserInfo } from '@/utils/platform';
|
7
|
-
import { setNamespace } from '@/utils/storeDebug';
|
8
|
-
|
9
|
-
import { userProfileSelectors } from '../auth/selectors';
|
10
|
-
import { syncSettingsSelectors } from './selectors';
|
11
|
-
|
12
|
-
const n = setNamespace('sync');
|
13
|
-
|
14
|
-
/**
|
15
|
-
* 设置操作
|
16
|
-
*/
|
17
|
-
export interface SyncAction {
|
18
|
-
refreshConnection: (onEvent: OnSyncEvent) => Promise<void>;
|
19
|
-
triggerEnableSync: (userId: string, onEvent: OnSyncEvent) => Promise<boolean>;
|
20
|
-
useEnabledSync: (
|
21
|
-
systemEnable: boolean | undefined,
|
22
|
-
params: {
|
23
|
-
onEvent: OnSyncEvent;
|
24
|
-
userEnableSync: boolean;
|
25
|
-
userId: string | undefined;
|
26
|
-
},
|
27
|
-
) => SWRResponse;
|
28
|
-
}
|
29
|
-
|
30
|
-
export const createSyncSlice: StateCreator<
|
31
|
-
UserStore,
|
32
|
-
[['zustand/devtools', never]],
|
33
|
-
[],
|
34
|
-
SyncAction
|
35
|
-
> = (set, get) => ({
|
36
|
-
refreshConnection: async (onEvent) => {
|
37
|
-
const userId = userProfileSelectors.userId(get());
|
38
|
-
|
39
|
-
if (!userId) return;
|
40
|
-
|
41
|
-
await get().triggerEnableSync(userId, onEvent);
|
42
|
-
},
|
43
|
-
|
44
|
-
triggerEnableSync: async (userId: string, onEvent: OnSyncEvent) => {
|
45
|
-
// double-check the sync ability
|
46
|
-
// if there is no channelName, don't start sync
|
47
|
-
const sync = syncSettingsSelectors.webrtcConfig(get());
|
48
|
-
if (!sync.channelName || !sync.signaling) return false;
|
49
|
-
|
50
|
-
const name = syncSettingsSelectors.deviceName(get());
|
51
|
-
|
52
|
-
const defaultUserName = `My ${browserInfo.browser} (${browserInfo.os})`;
|
53
|
-
|
54
|
-
set({ syncStatus: PeerSyncStatus.Connecting });
|
55
|
-
const { syncService } = await import('@/services/sync');
|
56
|
-
|
57
|
-
return syncService.enabledSync({
|
58
|
-
channel: {
|
59
|
-
name: sync.channelName,
|
60
|
-
password: sync.channelPassword,
|
61
|
-
},
|
62
|
-
onAwarenessChange(state) {
|
63
|
-
set({ syncAwareness: state });
|
64
|
-
},
|
65
|
-
onSyncEvent: onEvent,
|
66
|
-
onSyncStatusChange: (status) => {
|
67
|
-
set({ syncStatus: status });
|
68
|
-
},
|
69
|
-
signaling: sync.signaling,
|
70
|
-
user: {
|
71
|
-
id: userId,
|
72
|
-
// if user don't set the name, use default name
|
73
|
-
name: name || defaultUserName,
|
74
|
-
...browserInfo,
|
75
|
-
},
|
76
|
-
});
|
77
|
-
},
|
78
|
-
|
79
|
-
useEnabledSync: (systemEnable, { userEnableSync, userId, onEvent }) =>
|
80
|
-
useSWR<boolean>(
|
81
|
-
systemEnable ? ['enableSync', userEnableSync, userId] : null,
|
82
|
-
async () => {
|
83
|
-
// if user don't enable sync or no userId ,don't start sync
|
84
|
-
if (!userId) return false;
|
85
|
-
|
86
|
-
// if user don't enable sync, stop sync
|
87
|
-
if (!userEnableSync) {
|
88
|
-
const { syncService } = await import('@/services/sync');
|
89
|
-
return syncService.disableSync();
|
90
|
-
}
|
91
|
-
|
92
|
-
return get().triggerEnableSync(userId, onEvent);
|
93
|
-
},
|
94
|
-
{
|
95
|
-
onSuccess: (syncEnabled) => {
|
96
|
-
set({ syncEnabled }, false, n('useEnabledSync'));
|
97
|
-
},
|
98
|
-
revalidateOnFocus: false,
|
99
|
-
},
|
100
|
-
),
|
101
|
-
});
|
@@ -1,13 +0,0 @@
|
|
1
|
-
import { PeerSyncStatus, SyncAwarenessState } from '@/types/sync';
|
2
|
-
|
3
|
-
export interface UserSyncState {
|
4
|
-
syncAwareness: SyncAwarenessState[];
|
5
|
-
syncEnabled: boolean;
|
6
|
-
syncStatus: PeerSyncStatus;
|
7
|
-
}
|
8
|
-
|
9
|
-
export const initialSyncState: UserSyncState = {
|
10
|
-
syncAwareness: [],
|
11
|
-
syncEnabled: false,
|
12
|
-
syncStatus: PeerSyncStatus.Disabled,
|
13
|
-
};
|
@@ -1,20 +0,0 @@
|
|
1
|
-
import { DEFAULT_SYNC_CONFIG } from '@/const/settings/sync';
|
2
|
-
import { UserSyncSettings } from '@/types/user/settings';
|
3
|
-
|
4
|
-
import { UserStore } from '../../store';
|
5
|
-
import { currentSettings } from '../settings/selectors/settings';
|
6
|
-
|
7
|
-
const syncConfig = (s: UserStore): UserSyncSettings =>
|
8
|
-
currentSettings(s).sync || DEFAULT_SYNC_CONFIG;
|
9
|
-
|
10
|
-
const webrtcConfig = (s: UserStore) => syncConfig(s).webrtc;
|
11
|
-
const webrtcChannelName = (s: UserStore) => webrtcConfig(s).channelName;
|
12
|
-
const enableWebRTC = (s: UserStore) => webrtcConfig(s).enabled;
|
13
|
-
const deviceName = (s: UserStore) => syncConfig(s).deviceName;
|
14
|
-
|
15
|
-
export const syncSettingsSelectors = {
|
16
|
-
deviceName,
|
17
|
-
enableWebRTC,
|
18
|
-
webrtcChannelName,
|
19
|
-
webrtcConfig,
|
20
|
-
};
|
File without changes
|