@lobehub/lobehub 2.0.0-next.273 → 2.0.0-next.275
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 +59 -0
- package/changelog/v1.json +18 -0
- package/locales/ar/chat.json +7 -0
- package/locales/ar/models.json +2 -3
- package/locales/ar/plugin.json +22 -1
- package/locales/bg-BG/chat.json +7 -0
- package/locales/bg-BG/models.json +3 -3
- package/locales/bg-BG/plugin.json +22 -1
- package/locales/de-DE/chat.json +7 -0
- package/locales/de-DE/models.json +3 -4
- package/locales/de-DE/plugin.json +22 -1
- package/locales/en-US/chat.json +7 -0
- package/locales/en-US/models.json +5 -5
- package/locales/en-US/plugin.json +22 -1
- package/locales/es-ES/chat.json +7 -0
- package/locales/es-ES/models.json +3 -4
- package/locales/es-ES/plugin.json +22 -1
- package/locales/fa-IR/chat.json +7 -0
- package/locales/fa-IR/models.json +3 -4
- package/locales/fa-IR/plugin.json +22 -1
- package/locales/fr-FR/chat.json +7 -0
- package/locales/fr-FR/models.json +50 -3
- package/locales/fr-FR/plugin.json +22 -1
- package/locales/it-IT/chat.json +7 -0
- package/locales/it-IT/models.json +3 -3
- package/locales/it-IT/plugin.json +22 -1
- package/locales/ja-JP/chat.json +7 -0
- package/locales/ja-JP/models.json +43 -4
- package/locales/ja-JP/plugin.json +22 -1
- package/locales/ko-KR/chat.json +7 -0
- package/locales/ko-KR/models.json +3 -4
- package/locales/ko-KR/plugin.json +22 -1
- package/locales/nl-NL/chat.json +7 -0
- package/locales/nl-NL/models.json +51 -3
- package/locales/nl-NL/plugin.json +22 -1
- package/locales/pl-PL/chat.json +7 -0
- package/locales/pl-PL/models.json +3 -3
- package/locales/pl-PL/plugin.json +22 -1
- package/locales/pt-BR/chat.json +7 -0
- package/locales/pt-BR/models.json +3 -4
- package/locales/pt-BR/plugin.json +22 -1
- package/locales/ru-RU/chat.json +7 -0
- package/locales/ru-RU/models.json +3 -4
- package/locales/ru-RU/plugin.json +22 -1
- package/locales/tr-TR/chat.json +7 -0
- package/locales/tr-TR/models.json +3 -4
- package/locales/tr-TR/plugin.json +22 -1
- package/locales/vi-VN/chat.json +7 -0
- package/locales/vi-VN/models.json +3 -3
- package/locales/vi-VN/plugin.json +22 -1
- package/locales/zh-CN/chat.json +7 -0
- package/locales/zh-CN/models.json +54 -4
- package/locales/zh-CN/plugin.json +22 -1
- package/locales/zh-TW/chat.json +7 -0
- package/locales/zh-TW/models.json +43 -4
- package/locales/zh-TW/plugin.json +22 -1
- package/package.json +2 -2
- package/packages/builtin-tool-agent-builder/package.json +1 -0
- package/packages/builtin-tool-agent-builder/src/client/Inspector/GetAvailableModels/index.tsx +66 -0
- package/packages/builtin-tool-agent-builder/src/client/Inspector/InstallPlugin/index.tsx +63 -0
- package/packages/builtin-tool-agent-builder/src/client/Inspector/SearchMarketTools/index.tsx +64 -0
- package/packages/builtin-tool-agent-builder/src/client/Inspector/UpdateConfig/index.tsx +94 -0
- package/packages/builtin-tool-agent-builder/src/client/Inspector/UpdatePrompt/index.tsx +96 -0
- package/packages/builtin-tool-agent-builder/src/client/Inspector/index.ts +29 -0
- package/packages/builtin-tool-agent-builder/src/client/index.ts +13 -0
- package/packages/builtin-tool-agent-builder/src/executor.ts +132 -0
- package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/ExecuteCode/index.tsx +5 -14
- package/packages/builtin-tool-cloud-sandbox/src/client/Inspector/RunCommand/index.tsx +5 -13
- package/packages/builtin-tool-group-agent-builder/package.json +7 -1
- package/packages/builtin-tool-group-agent-builder/src/ExecutionRuntime/index.ts +331 -87
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/BatchCreateAgents/index.tsx +110 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/CreateAgent/index.tsx +72 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/InviteAgent/index.tsx +57 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/RemoveAgent/index.tsx +57 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/SearchAgent/index.tsx +66 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/UpdateAgentPrompt/index.tsx +120 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/UpdateGroup/index.tsx +87 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/UpdateGroupPrompt/index.tsx +99 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/index.ts +52 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Render/BatchCreateAgents.tsx +103 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Render/UpdateAgentPrompt/index.tsx +36 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Render/UpdateGroupPrompt/index.tsx +36 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Render/index.ts +16 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Streaming/BatchCreateAgents/index.tsx +88 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Streaming/UpdateAgentPrompt/index.tsx +37 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Streaming/UpdateGroupPrompt/index.tsx +35 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Streaming/index.ts +22 -0
- package/packages/builtin-tool-group-agent-builder/src/client/index.ts +26 -0
- package/packages/builtin-tool-group-agent-builder/src/executor.ts +284 -0
- package/packages/builtin-tool-group-agent-builder/src/index.ts +1 -14
- package/packages/builtin-tool-group-agent-builder/src/manifest.ts +160 -15
- package/packages/builtin-tool-group-agent-builder/src/systemRole.ts +232 -46
- package/packages/builtin-tool-group-agent-builder/src/types.ts +191 -41
- package/packages/builtin-tool-group-management/src/client/Inspector/Broadcast/index.tsx +2 -2
- package/packages/builtin-tool-group-management/src/manifest.ts +1 -1
- package/packages/builtin-tool-gtd/src/client/Inspector/ClearTodos/index.tsx +5 -11
- package/packages/builtin-tool-gtd/src/client/Inspector/CompleteTodos/index.tsx +3 -9
- package/packages/builtin-tool-gtd/src/client/Inspector/CreatePlan/index.tsx +6 -15
- package/packages/builtin-tool-gtd/src/client/Inspector/CreateTodos/index.tsx +3 -9
- package/packages/builtin-tool-gtd/src/client/Inspector/ExecTask/index.tsx +6 -17
- package/packages/builtin-tool-gtd/src/client/Inspector/RemoveTodos/index.tsx +3 -9
- package/packages/builtin-tool-gtd/src/client/Inspector/UpdatePlan/index.tsx +3 -9
- package/packages/builtin-tool-gtd/src/client/Inspector/UpdateTodos/index.tsx +3 -9
- package/packages/builtin-tool-knowledge-base/src/client/Inspector/ReadKnowledge/index.tsx +4 -16
- package/packages/builtin-tool-knowledge-base/src/client/Inspector/SearchKnowledgeBase/index.tsx +5 -16
- package/packages/builtin-tool-local-system/src/client/Inspector/EditLocalFile/index.tsx +4 -12
- package/packages/builtin-tool-local-system/src/client/Inspector/GlobLocalFiles/index.tsx +5 -13
- package/packages/builtin-tool-local-system/src/client/Inspector/GrepContent/index.tsx +5 -16
- package/packages/builtin-tool-local-system/src/client/Inspector/ListLocalFiles/index.tsx +5 -16
- package/packages/builtin-tool-local-system/src/client/Inspector/ReadLocalFile/index.tsx +5 -16
- package/packages/builtin-tool-local-system/src/client/Inspector/RenameLocalFile/index.tsx +5 -11
- package/packages/builtin-tool-local-system/src/client/Inspector/RunCommand/index.tsx +5 -13
- package/packages/builtin-tool-local-system/src/client/Inspector/SearchLocalFiles/index.tsx +5 -16
- package/packages/builtin-tool-local-system/src/client/Inspector/WriteLocalFile/index.tsx +6 -15
- package/packages/builtin-tool-notebook/src/client/Inspector/CreateDocument/index.tsx +7 -15
- package/packages/builtin-tool-page-agent/src/client/Inspector/EditTitle/index.tsx +5 -14
- package/packages/builtin-tool-page-agent/src/client/Inspector/GetPageContent/index.tsx +7 -8
- package/packages/builtin-tool-page-agent/src/client/Inspector/InitPage/index.tsx +4 -10
- package/packages/builtin-tool-page-agent/src/client/Inspector/ModifyNodes/index.tsx +3 -9
- package/packages/builtin-tool-page-agent/src/client/Inspector/ReplaceText/index.tsx +5 -11
- package/packages/builtin-tool-web-browsing/src/client/Inspector/CrawlMultiPages/index.tsx +6 -15
- package/packages/builtin-tool-web-browsing/src/client/Inspector/CrawlSinglePage/index.tsx +6 -15
- package/packages/builtin-tool-web-browsing/src/client/Inspector/Search/index.tsx +4 -15
- package/packages/database/src/models/chatGroup.ts +1 -1
- package/packages/model-bank/src/aiModels/aihubmix.ts +2 -1
- package/packages/model-bank/src/aiModels/google.ts +2 -1
- package/packages/model-bank/src/aiModels/infiniai.ts +9 -6
- package/packages/model-bank/src/aiModels/minimax.ts +9 -5
- package/packages/model-bank/src/aiModels/ollamacloud.ts +4 -2
- package/packages/model-bank/src/aiModels/vertexai.ts +2 -1
- package/packages/types/src/agentGroup/index.ts +8 -0
- package/patches/@upstash__qstash.patch +13 -1
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Header/Nav.tsx +1 -1
- package/src/app/[variants]/(main)/agent/cron/[cronId]/index.tsx +4 -3
- package/src/app/[variants]/(main)/agent/profile/features/ProfileEditor/index.tsx +1 -1
- package/src/app/[variants]/(main)/agent/profile/features/store/action.ts +18 -21
- package/src/app/[variants]/(main)/community/(detail)/features/MakedownRender.tsx +8 -6
- package/src/app/[variants]/(main)/group/_layout/GroupIdSync.tsx +6 -1
- package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/AgentProfilePopup.tsx +29 -21
- package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/GroupMember.tsx +1 -0
- package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/GroupMemberItem.tsx +35 -18
- package/src/app/[variants]/(main)/group/_layout/Sidebar/Header/AddTopicButon.tsx +2 -10
- package/src/app/[variants]/(main)/group/_layout/Sidebar/Header/Nav.tsx +10 -2
- package/src/app/[variants]/(main)/group/_layout/Sidebar/Header/index.tsx +1 -2
- package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/AgentBuilderProvider.tsx +1 -0
- package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/TopicSelector.tsx +15 -9
- package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/index.tsx +12 -6
- package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor/AgentHeader.tsx → GroupProfile/GroupHeader.tsx} +22 -29
- package/src/app/[variants]/(main)/group/profile/features/GroupProfile/index.tsx +96 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/AgentBuilderToggle.tsx +3 -4
- package/src/app/[variants]/(main)/group/profile/features/Header/AutoSaveHint.tsx +11 -7
- package/src/app/[variants]/(main)/group/profile/features/Header/ChromeTabs/index.tsx +147 -0
- package/src/app/[variants]/(main)/group/profile/features/Header/index.tsx +104 -13
- package/src/app/[variants]/(main)/group/profile/features/MemberProfile/AgentHeader.tsx +222 -0
- package/src/app/[variants]/(main)/group/profile/features/MemberProfile/index.tsx +155 -0
- package/src/app/[variants]/(main)/group/profile/features/ProfileHydration.tsx +63 -5
- package/src/app/[variants]/(main)/group/profile/index.tsx +34 -37
- package/src/app/[variants]/(main)/settings/proxy/features/ProxyForm.tsx +156 -253
- package/src/app/[variants]/(main)/settings/proxy/index.tsx +1 -3
- package/src/app/[variants]/(mobile)/(home)/_layout/SessionHydration.tsx +1 -1
- package/src/app/[variants]/(mobile)/(home)/features/SessionListContent/List/Item/index.tsx +1 -1
- package/src/features/AgentBuilder/index.tsx +16 -1
- package/src/features/Conversation/Messages/AssistantGroup/Tool/Inspector/StatusIndicator.tsx +3 -2
- package/src/features/Conversation/Messages/User/useMarkdown.tsx +1 -0
- package/src/features/EditorCanvas/EditorCanvas.test.tsx +206 -0
- package/src/features/EditorCanvas/EditorDataMode.tsx +53 -19
- package/src/features/EditorModal/index.tsx +2 -2
- package/src/features/NavPanel/components/SessionHydration.tsx +1 -1
- package/src/features/PageEditor/EditorCanvas/useAskCopilotItem.tsx +10 -6
- package/src/features/PageEditor/Header/index.tsx +12 -10
- package/src/features/PageEditor/Header/useMenu.tsx +45 -48
- package/src/features/RightPanel/ToggleRightPanelButton.tsx +3 -1
- package/src/features/ShareModal/ShareImage/ChatList/index.tsx +1 -1
- package/src/features/ShareModal/SharePdf/index.tsx +1 -1
- package/src/hooks/useBidirectionalQuerySync.ts +112 -0
- package/src/locales/default/chat.ts +10 -0
- package/src/locales/default/plugin.ts +22 -1
- package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +45 -45
- package/src/server/modules/KeyVaultsEncrypt/index.ts +6 -6
- package/src/server/modules/S3/index.ts +1 -1
- package/src/server/routers/lambda/agent.ts +24 -0
- package/src/server/routers/lambda/agentGroup.ts +39 -0
- package/src/services/agent.ts +22 -0
- package/src/services/chatGroup/index.ts +14 -0
- package/src/store/agent/selectors/selectors.ts +3 -0
- package/src/store/agentGroup/initialState.ts +6 -0
- package/src/store/agentGroup/selectors/byId.ts +3 -1
- package/src/store/agentGroup/selectors/current.ts +2 -2
- package/src/store/agentGroup/slices/lifecycle.ts +18 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/fixtures/mockStore.ts +1 -1
- package/src/store/chat/slices/aiAgent/actions/__tests__/agentGroup.test.ts +4 -1
- package/src/store/chat/slices/aiAgent/actions/agentGroup.ts +1 -1
- package/src/store/chat/slices/aiChat/actions/__tests__/conversationLifecycle.test.ts +65 -0
- package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +2 -1
- package/src/store/chat/slices/builtinTool/actions/__tests__/search.test.ts +1 -1
- package/src/store/chat/slices/builtinTool/actions/index.ts +1 -6
- package/src/store/chat/slices/message/action.test.ts +5 -5
- package/src/store/chat/slices/message/actions/publicApi.ts +5 -5
- package/src/store/chat/slices/message/initialState.ts +0 -5
- package/src/store/chat/slices/message/selectors/displayMessage.test.ts +4 -4
- package/src/store/chat/slices/plugin/action.test.ts +54 -19
- package/src/store/chat/slices/plugin/actions/pluginTypes.ts +15 -21
- package/src/store/chat/slices/topic/action.test.ts +74 -24
- package/src/store/chat/slices/topic/action.ts +21 -13
- package/src/store/chat/slices/topic/selectors.test.ts +1 -1
- package/src/store/global/initialState.ts +10 -0
- package/src/store/global/selectors/systemStatus.ts +5 -0
- package/src/store/groupProfile/action.ts +168 -0
- package/src/store/groupProfile/index.ts +16 -0
- package/src/{app/[variants]/(main)/group/profile/features/store → store/groupProfile}/initialState.ts +17 -0
- package/src/store/groupProfile/selectors.ts +13 -0
- package/src/store/tool/slices/builtin/executors/index.ts +4 -0
- package/src/styles/text.ts +16 -0
- package/src/tools/inspectors.ts +13 -0
- package/src/tools/renders.ts +3 -0
- package/src/tools/streamings.ts +8 -0
- package/tests/mocks/lru_map.ts +40 -0
- package/vitest.config.mts +9 -1
- package/src/app/[variants]/(main)/group/profile/features/EditorCanvas/TypoBar.tsx +0 -129
- package/src/app/[variants]/(main)/group/profile/features/EditorCanvas/index.tsx +0 -138
- package/src/app/[variants]/(main)/group/profile/features/EditorCanvas/useSlashItems.tsx +0 -139
- package/src/app/[variants]/(main)/group/profile/features/ProfileEditor/index.tsx +0 -82
- package/src/app/[variants]/(main)/group/profile/features/ProfileProvider.tsx +0 -20
- package/src/app/[variants]/(main)/group/profile/features/StoreUpdater.tsx +0 -24
- package/src/app/[variants]/(main)/group/profile/features/store/action.ts +0 -163
- package/src/app/[variants]/(main)/group/profile/features/store/index.ts +0 -23
- package/src/app/[variants]/(main)/group/profile/features/store/selectors.ts +0 -7
- package/src/features/EditorModal/EditorCanvas.tsx +0 -84
- package/src/features/EditorModal/Typobar.tsx +0 -139
- package/src/store/chat/slices/builtinTool/actions/agentBuilder.ts +0 -192
- package/src/store/chat/slices/builtinTool/actions/groupAgentBuilder.ts +0 -242
- package/src/tools/executionRuntimes.ts +0 -14
- /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/AgentTool.tsx +0 -0
- /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/MentionList/MentionDropdown.tsx +0 -0
- /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/MentionList/index.tsx +0 -0
- /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/MentionList/types.ts +0 -0
- /package/src/app/[variants]/(main)/group/profile/features/{ProfileEditor → MemberProfile}/MentionList/useMentionItems.tsx +0 -0
|
@@ -1,15 +1,73 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useEditor, useEditorState } from '@lobehub/editor/react';
|
|
4
|
+
import { useUnmount } from 'ahooks';
|
|
5
|
+
import { memo, useEffect, useRef } from 'react';
|
|
6
|
+
import { createStoreUpdater } from 'zustand-utils';
|
|
4
7
|
|
|
5
|
-
import {
|
|
8
|
+
import { useRegisterFilesHotkeys, useSaveDocumentHotkey } from '@/hooks/useHotkeys';
|
|
9
|
+
import { parseAsString, useQueryState } from '@/hooks/useQueryParam';
|
|
10
|
+
import { useChatStore } from '@/store/chat';
|
|
11
|
+
import { useGroupProfileStore } from '@/store/groupProfile';
|
|
6
12
|
|
|
7
13
|
const ProfileHydration = memo(() => {
|
|
8
|
-
|
|
9
|
-
const
|
|
14
|
+
const editor = useEditor();
|
|
15
|
+
const editorState = useEditorState(editor);
|
|
16
|
+
const flushSave = useGroupProfileStore((s) => s.flushSave);
|
|
17
|
+
|
|
18
|
+
const storeUpdater = createStoreUpdater(useGroupProfileStore);
|
|
19
|
+
|
|
20
|
+
// Sync editor to store
|
|
21
|
+
storeUpdater('editor', editor);
|
|
22
|
+
// Sync editorState to store
|
|
23
|
+
storeUpdater('editorState', editorState);
|
|
24
|
+
// Sync tab query param to store
|
|
25
|
+
const [activeTabId] = useQueryState('tab', parseAsString.withDefault('group'));
|
|
26
|
+
storeUpdater('activeTabId', activeTabId);
|
|
27
|
+
|
|
28
|
+
// Bidirectional sync between URL query 'bt' and chatStore.activeTopicId
|
|
29
|
+
const [builderTopicId, setBuilderTopicId] = useQueryState('bt');
|
|
30
|
+
const activeTopicId = useChatStore((s) => s.activeTopicId);
|
|
31
|
+
|
|
32
|
+
// Track if the change came from URL to prevent sync loops
|
|
33
|
+
const isUrlChangeRef = useRef(false);
|
|
34
|
+
|
|
35
|
+
// Sync URL → Store (when URL changes)
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const urlTopicId = builderTopicId ?? undefined;
|
|
38
|
+
if (urlTopicId !== activeTopicId) {
|
|
39
|
+
isUrlChangeRef.current = true;
|
|
40
|
+
useChatStore.setState({ activeTopicId: urlTopicId });
|
|
41
|
+
}
|
|
42
|
+
}, [builderTopicId]);
|
|
43
|
+
|
|
44
|
+
// Sync Store → URL (when store changes, but not from URL)
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (isUrlChangeRef.current) {
|
|
47
|
+
isUrlChangeRef.current = false;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const urlTopicId = builderTopicId ?? undefined;
|
|
51
|
+
if (activeTopicId !== urlTopicId) {
|
|
52
|
+
setBuilderTopicId(activeTopicId ?? null);
|
|
53
|
+
}
|
|
54
|
+
}, [activeTopicId]);
|
|
55
|
+
|
|
56
|
+
// Register hotkeys
|
|
10
57
|
useRegisterFilesHotkeys();
|
|
11
58
|
useSaveDocumentHotkey(flushSave);
|
|
12
59
|
|
|
60
|
+
// Clear state when unmounting
|
|
61
|
+
useUnmount(() => {
|
|
62
|
+
useGroupProfileStore.setState({
|
|
63
|
+
activeTabId: 'group',
|
|
64
|
+
editor: undefined,
|
|
65
|
+
editorState: undefined,
|
|
66
|
+
saveStateMap: {},
|
|
67
|
+
});
|
|
68
|
+
useChatStore.setState({ activeTopicId: undefined });
|
|
69
|
+
});
|
|
70
|
+
|
|
13
71
|
return null;
|
|
14
72
|
});
|
|
15
73
|
|
|
@@ -7,58 +7,55 @@ import Loading from '@/components/Loading/BrandTextLoading';
|
|
|
7
7
|
import WideScreenContainer from '@/features/WideScreenContainer';
|
|
8
8
|
import { useAgentGroupStore } from '@/store/agentGroup';
|
|
9
9
|
import { agentGroupSelectors } from '@/store/agentGroup/selectors';
|
|
10
|
+
import { useGroupProfileStore } from '@/store/groupProfile';
|
|
10
11
|
|
|
11
12
|
import AgentBuilder from './features/AgentBuilder';
|
|
13
|
+
import GroupProfileSettings from './features/GroupProfile';
|
|
12
14
|
import Header from './features/Header';
|
|
13
|
-
import
|
|
15
|
+
import MemberProfile from './features/MemberProfile';
|
|
14
16
|
import ProfileHydration from './features/ProfileHydration';
|
|
15
|
-
import ProfileProvider from './features/ProfileProvider';
|
|
16
|
-
import { useProfileStore } from './features/store';
|
|
17
17
|
|
|
18
18
|
const ProfileArea = memo(() => {
|
|
19
|
-
const editor =
|
|
19
|
+
const editor = useGroupProfileStore((s) => s.editor);
|
|
20
|
+
const activeTabId = useGroupProfileStore((s) => s.activeTabId);
|
|
20
21
|
const isGroupsLoading = useAgentGroupStore(agentGroupSelectors.isGroupsInit);
|
|
21
22
|
|
|
23
|
+
const isGroupTab = activeTabId === 'group';
|
|
24
|
+
|
|
22
25
|
return (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
>
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
</Flexbox>
|
|
46
|
-
<Suspense fallback={null}>
|
|
47
|
-
<ProfileHydration />
|
|
48
|
-
</Suspense>
|
|
49
|
-
</>
|
|
26
|
+
<Flexbox flex={1} height={'100%'} style={{ minWidth: 0, overflow: 'hidden' }}>
|
|
27
|
+
{isGroupsLoading ? (
|
|
28
|
+
<Loading debugId="ProfileArea" />
|
|
29
|
+
) : (
|
|
30
|
+
<>
|
|
31
|
+
<Header />
|
|
32
|
+
<Flexbox
|
|
33
|
+
height={'100%'}
|
|
34
|
+
horizontal
|
|
35
|
+
onClick={() => {
|
|
36
|
+
editor?.focus();
|
|
37
|
+
}}
|
|
38
|
+
style={{ cursor: 'text', display: 'flex', overflowY: 'auto', position: 'relative' }}
|
|
39
|
+
width={'100%'}
|
|
40
|
+
>
|
|
41
|
+
<WideScreenContainer>
|
|
42
|
+
{isGroupTab ? <GroupProfileSettings /> : <MemberProfile />}
|
|
43
|
+
</WideScreenContainer>
|
|
44
|
+
</Flexbox>
|
|
45
|
+
</>
|
|
46
|
+
)}
|
|
47
|
+
</Flexbox>
|
|
50
48
|
);
|
|
51
49
|
});
|
|
52
50
|
|
|
53
51
|
const GroupProfile: FC = () => {
|
|
54
52
|
return (
|
|
55
53
|
<Suspense fallback={<Loading debugId="GroupProfile" />}>
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
</ProfileProvider>
|
|
54
|
+
<ProfileHydration />
|
|
55
|
+
<Flexbox height={'100%'} horizontal width={'100%'}>
|
|
56
|
+
<ProfileArea />
|
|
57
|
+
<AgentBuilder />
|
|
58
|
+
</Flexbox>
|
|
62
59
|
</Suspense>
|
|
63
60
|
);
|
|
64
61
|
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { type NetworkProxySettings } from '@lobechat/electron-client-ipc';
|
|
4
|
-
import { Alert,
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
4
|
+
import { Alert, Flexbox, Form, type FormGroupItemType, Icon, Skeleton } from '@lobehub/ui';
|
|
5
|
+
import { Form as AntdForm, Button, Input, Radio, Space, Switch } from 'antd';
|
|
6
|
+
import { Loader2Icon } from 'lucide-react';
|
|
7
7
|
import { useCallback, useEffect, useState } from 'react';
|
|
8
8
|
import { useTranslation } from 'react-i18next';
|
|
9
9
|
|
|
10
|
+
import { FORM_STYLE } from '@/const/layoutTokens';
|
|
10
11
|
import { desktopSettingsService } from '@/services/electron/settings';
|
|
11
12
|
import { useElectronStore } from '@/store/electron';
|
|
12
13
|
|
|
@@ -19,15 +20,15 @@ interface ProxyTestResult {
|
|
|
19
20
|
const ProxyForm = () => {
|
|
20
21
|
const { t } = useTranslation('electron');
|
|
21
22
|
const [form] = Form.useForm();
|
|
22
|
-
const { message } = App.useApp();
|
|
23
23
|
const [testUrl, setTestUrl] = useState('https://www.google.com');
|
|
24
24
|
const [isTesting, setIsTesting] = useState(false);
|
|
25
25
|
const [isSaving, setIsSaving] = useState(false);
|
|
26
26
|
const [testResult, setTestResult] = useState<ProxyTestResult | null>(null);
|
|
27
27
|
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
|
|
28
|
+
const [loading, setLoading] = useState(false);
|
|
28
29
|
|
|
29
|
-
const isEnableProxy =
|
|
30
|
-
const proxyRequireAuth =
|
|
30
|
+
const isEnableProxy = AntdForm.useWatch('enableProxy', form);
|
|
31
|
+
const proxyRequireAuth = AntdForm.useWatch('proxyRequireAuth', form);
|
|
31
32
|
|
|
32
33
|
const [setProxySettings, useGetProxySettings] = useElectronStore((s) => [
|
|
33
34
|
s.setProxySettings,
|
|
@@ -44,19 +45,12 @@ const ProxyForm = () => {
|
|
|
44
45
|
|
|
45
46
|
// 监听表单变化
|
|
46
47
|
const handleValuesChange = useCallback(() => {
|
|
48
|
+
setLoading(true);
|
|
47
49
|
setHasUnsavedChanges(true);
|
|
48
50
|
setTestResult(null); // 清除之前的测试结果
|
|
51
|
+
setLoading(false);
|
|
49
52
|
}, []);
|
|
50
53
|
|
|
51
|
-
const updateFormValue = (value: any) => {
|
|
52
|
-
const preValues = form.getFieldsValue();
|
|
53
|
-
form.setFieldsValue(value);
|
|
54
|
-
const newValues = form.getFieldsValue();
|
|
55
|
-
if (isEqual(newValues, preValues)) return;
|
|
56
|
-
|
|
57
|
-
handleValuesChange();
|
|
58
|
-
};
|
|
59
|
-
|
|
60
54
|
// 保存配置
|
|
61
55
|
const handleSave = useCallback(async () => {
|
|
62
56
|
try {
|
|
@@ -64,15 +58,12 @@ const ProxyForm = () => {
|
|
|
64
58
|
const values = await form.validateFields();
|
|
65
59
|
await setProxySettings(values);
|
|
66
60
|
setHasUnsavedChanges(false);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (error instanceof Error) {
|
|
70
|
-
message.error(t('proxy.saveFailed', { error: error.message }));
|
|
71
|
-
}
|
|
61
|
+
} catch {
|
|
62
|
+
// validation error
|
|
72
63
|
} finally {
|
|
73
64
|
setIsSaving(false);
|
|
74
65
|
}
|
|
75
|
-
}, [form,
|
|
66
|
+
}, [form, setProxySettings]);
|
|
76
67
|
|
|
77
68
|
// 重置配置
|
|
78
69
|
const handleReset = useCallback(() => {
|
|
@@ -107,240 +98,159 @@ const ProxyForm = () => {
|
|
|
107
98
|
success: false,
|
|
108
99
|
};
|
|
109
100
|
setTestResult(result);
|
|
110
|
-
message.error(t('proxy.testFailed'));
|
|
111
101
|
} finally {
|
|
112
102
|
setIsTesting(false);
|
|
113
103
|
}
|
|
114
|
-
}, [proxySettings, testUrl]);
|
|
104
|
+
}, [proxySettings, testUrl, form]);
|
|
115
105
|
|
|
116
|
-
if (isLoading) return <Skeleton />;
|
|
106
|
+
if (isLoading) return <Skeleton active paragraph={{ rows: 5 }} title={false} />;
|
|
117
107
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
>
|
|
134
|
-
<Form.Item name="enableProxy" noStyle valuePropName="checked">
|
|
135
|
-
<Flexbox align={'center'} horizontal justify={'space-between'}>
|
|
136
|
-
<Flexbox>
|
|
137
|
-
<Text as={'h4'}>{t('proxy.enable')}</Text>
|
|
138
|
-
<Text type={'secondary'}>{t('proxy.enableDesc')}</Text>
|
|
139
|
-
</Flexbox>
|
|
140
|
-
<Switch
|
|
141
|
-
checked={isEnableProxy}
|
|
142
|
-
onChange={(checked) => {
|
|
143
|
-
updateFormValue({ enableProxy: checked });
|
|
144
|
-
}}
|
|
145
|
-
/>
|
|
146
|
-
</Flexbox>
|
|
147
|
-
</Form.Item>
|
|
148
|
-
</Block>
|
|
108
|
+
const enableProxyGroup: FormGroupItemType = {
|
|
109
|
+
children: [
|
|
110
|
+
{
|
|
111
|
+
children: <Switch />,
|
|
112
|
+
desc: t('proxy.enableDesc'),
|
|
113
|
+
label: t('proxy.enable'),
|
|
114
|
+
layout: 'horizontal',
|
|
115
|
+
minWidth: undefined,
|
|
116
|
+
name: 'enableProxy',
|
|
117
|
+
valuePropName: 'checked',
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
extra: loading && <Icon icon={Loader2Icon} size={16} spin style={{ opacity: 0.5 }} />,
|
|
121
|
+
title: t('proxy.enable'),
|
|
122
|
+
};
|
|
149
123
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
124
|
+
const basicSettingsGroup: FormGroupItemType = {
|
|
125
|
+
children: [
|
|
126
|
+
{
|
|
127
|
+
children: (
|
|
128
|
+
<Radio.Group disabled={!isEnableProxy}>
|
|
129
|
+
<Radio value="http">HTTP</Radio>
|
|
130
|
+
<Radio value="https">HTTPS</Radio>
|
|
131
|
+
<Radio value="socks5">SOCKS5</Radio>
|
|
132
|
+
</Radio.Group>
|
|
133
|
+
),
|
|
134
|
+
label: t('proxy.type'),
|
|
135
|
+
minWidth: undefined,
|
|
136
|
+
name: 'proxyType',
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
children: <Input disabled={!isEnableProxy} placeholder="127.0.0.1" />,
|
|
140
|
+
desc: t('proxy.validation.serverRequired'),
|
|
141
|
+
label: t('proxy.server'),
|
|
142
|
+
name: 'proxyServer',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
children: <Input disabled={!isEnableProxy} placeholder="7890" style={{ width: 120 }} />,
|
|
146
|
+
desc: t('proxy.validation.portRequired'),
|
|
147
|
+
label: t('proxy.port'),
|
|
148
|
+
name: 'proxyPort',
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
extra: loading && <Icon icon={Loader2Icon} size={16} spin style={{ opacity: 0.5 }} />,
|
|
152
|
+
title: t('proxy.basicSettings'),
|
|
153
|
+
};
|
|
180
154
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
155
|
+
const authGroup: FormGroupItemType = {
|
|
156
|
+
children: [
|
|
157
|
+
{
|
|
158
|
+
children: <Switch disabled={!isEnableProxy} />,
|
|
159
|
+
desc: t('proxy.authDesc'),
|
|
160
|
+
label: t('proxy.auth'),
|
|
161
|
+
layout: 'horizontal',
|
|
162
|
+
minWidth: undefined,
|
|
163
|
+
name: 'proxyRequireAuth',
|
|
164
|
+
valuePropName: 'checked',
|
|
165
|
+
},
|
|
166
|
+
...(proxyRequireAuth && isEnableProxy
|
|
167
|
+
? [
|
|
168
|
+
{
|
|
169
|
+
children: <Input placeholder={t('proxy.username_placeholder')} />,
|
|
170
|
+
label: t('proxy.username'),
|
|
171
|
+
name: 'proxyUsername',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
children: <Input.Password placeholder={t('proxy.password_placeholder')} />,
|
|
175
|
+
label: t('proxy.password'),
|
|
176
|
+
name: 'proxyPassword',
|
|
177
|
+
},
|
|
178
|
+
]
|
|
179
|
+
: []),
|
|
180
|
+
],
|
|
181
|
+
extra: loading && <Icon icon={Loader2Icon} size={16} spin style={{ opacity: 0.5 }} />,
|
|
182
|
+
title: t('proxy.authSettings'),
|
|
183
|
+
};
|
|
201
184
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
<Form.Item
|
|
226
|
-
dependencies={['enableProxy']}
|
|
227
|
-
name="proxyRequireAuth"
|
|
228
|
-
noStyle
|
|
229
|
-
valuePropName="checked"
|
|
230
|
-
>
|
|
231
|
-
<Flexbox align={'center'} horizontal justify={'space-between'}>
|
|
232
|
-
<Flexbox>
|
|
233
|
-
<Text as={'h5'}>{t('proxy.auth')}</Text>
|
|
234
|
-
<Text type={'secondary'}>{t('proxy.authDesc')}</Text>
|
|
185
|
+
const testGroup: FormGroupItemType = {
|
|
186
|
+
children: [
|
|
187
|
+
{
|
|
188
|
+
children: (
|
|
189
|
+
<Flexbox gap={8}>
|
|
190
|
+
<Space.Compact style={{ width: '100%' }}>
|
|
191
|
+
<Input
|
|
192
|
+
onChange={(e) => setTestUrl(e.target.value)}
|
|
193
|
+
placeholder={t('proxy.testUrlPlaceholder')}
|
|
194
|
+
style={{ flex: 1 }}
|
|
195
|
+
value={testUrl}
|
|
196
|
+
/>
|
|
197
|
+
<Button loading={isTesting} onClick={handleTest} type="default">
|
|
198
|
+
{t('proxy.testButton')}
|
|
199
|
+
</Button>
|
|
200
|
+
</Space.Compact>
|
|
201
|
+
{/* 测试结果显示 */}
|
|
202
|
+
{!testResult ? null : testResult.success ? (
|
|
203
|
+
<Alert
|
|
204
|
+
closable
|
|
205
|
+
title={
|
|
206
|
+
<Flexbox align="center" gap={8} horizontal>
|
|
207
|
+
{t('proxy.testSuccessWithTime', { time: testResult.responseTime })}
|
|
235
208
|
</Flexbox>
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
({ getFieldValue }) => ({
|
|
252
|
-
message: t('proxy.validation.usernameRequired'),
|
|
253
|
-
required: getFieldValue('proxyRequireAuth') && getFieldValue('enableProxy'),
|
|
254
|
-
}),
|
|
255
|
-
]}
|
|
256
|
-
style={{
|
|
257
|
-
display:
|
|
258
|
-
form.getFieldValue('proxyRequireAuth') && form.getFieldValue('enableProxy')
|
|
259
|
-
? 'block'
|
|
260
|
-
: 'none',
|
|
261
|
-
}}
|
|
262
|
-
>
|
|
263
|
-
<Input placeholder={t('proxy.username_placeholder')} />
|
|
264
|
-
</Form.Item>
|
|
265
|
-
|
|
266
|
-
<Form.Item
|
|
267
|
-
dependencies={['proxyRequireAuth', 'enableProxy']}
|
|
268
|
-
label={t('proxy.password')}
|
|
269
|
-
name="proxyPassword"
|
|
270
|
-
rules={[
|
|
271
|
-
({ getFieldValue }) => ({
|
|
272
|
-
message: t('proxy.validation.passwordRequired'),
|
|
273
|
-
required: getFieldValue('proxyRequireAuth') && getFieldValue('enableProxy'),
|
|
274
|
-
}),
|
|
275
|
-
]}
|
|
276
|
-
style={{
|
|
277
|
-
display:
|
|
278
|
-
form.getFieldValue('proxyRequireAuth') && form.getFieldValue('enableProxy')
|
|
279
|
-
? 'block'
|
|
280
|
-
: 'none',
|
|
281
|
-
}}
|
|
282
|
-
>
|
|
283
|
-
<Input.Password placeholder={t('proxy.password_placeholder')} />
|
|
284
|
-
</Form.Item>
|
|
285
|
-
</Flexbox>
|
|
209
|
+
}
|
|
210
|
+
type={'success'}
|
|
211
|
+
/>
|
|
212
|
+
) : (
|
|
213
|
+
<Alert
|
|
214
|
+
closable
|
|
215
|
+
title={
|
|
216
|
+
<Flexbox align="center" gap={8} horizontal>
|
|
217
|
+
{t('proxy.testFailed')}: {testResult.message}
|
|
218
|
+
</Flexbox>
|
|
219
|
+
}
|
|
220
|
+
type={'error'}
|
|
221
|
+
variant={'outlined'}
|
|
222
|
+
/>
|
|
223
|
+
)}
|
|
286
224
|
</Flexbox>
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
225
|
+
),
|
|
226
|
+
desc: t('proxy.testDescription'),
|
|
227
|
+
label: t('proxy.testUrl'),
|
|
228
|
+
minWidth: undefined,
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
extra: loading && <Icon icon={Loader2Icon} size={16} spin style={{ opacity: 0.5 }} />,
|
|
232
|
+
title: t('proxy.connectionTest'),
|
|
233
|
+
};
|
|
290
234
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
/>
|
|
311
|
-
<Button loading={isTesting} onClick={handleTest} type="default">
|
|
312
|
-
{t('proxy.testButton')}
|
|
313
|
-
</Button>
|
|
314
|
-
</Space.Compact>
|
|
315
|
-
{/* 测试结果显示 */}
|
|
316
|
-
{!testResult ? null : testResult.success ? (
|
|
317
|
-
<Alert
|
|
318
|
-
closable
|
|
319
|
-
title={
|
|
320
|
-
<Flexbox align="center" gap={8} horizontal>
|
|
321
|
-
{t('proxy.testSuccessWithTime', { time: testResult.responseTime })}
|
|
322
|
-
</Flexbox>
|
|
323
|
-
}
|
|
324
|
-
type={'success'}
|
|
325
|
-
/>
|
|
326
|
-
) : (
|
|
327
|
-
<Alert
|
|
328
|
-
closable
|
|
329
|
-
title={
|
|
330
|
-
<Flexbox align="center" gap={8} horizontal>
|
|
331
|
-
{t('proxy.testFailed')}: {testResult.message}
|
|
332
|
-
</Flexbox>
|
|
333
|
-
}
|
|
334
|
-
type={'error'}
|
|
335
|
-
variant={'outlined'}
|
|
336
|
-
/>
|
|
337
|
-
)}
|
|
338
|
-
</Flexbox>
|
|
339
|
-
</Form.Item>
|
|
340
|
-
</Flexbox>
|
|
341
|
-
</Block>
|
|
342
|
-
{/* 操作按钮 */}
|
|
343
|
-
<Space>
|
|
235
|
+
return (
|
|
236
|
+
<Flexbox gap={24}>
|
|
237
|
+
<Form
|
|
238
|
+
collapsible={false}
|
|
239
|
+
form={form}
|
|
240
|
+
initialValues={proxySettings}
|
|
241
|
+
items={[enableProxyGroup, basicSettingsGroup, authGroup, testGroup]}
|
|
242
|
+
itemsType={'group'}
|
|
243
|
+
onValuesChange={handleValuesChange}
|
|
244
|
+
variant={'filled'}
|
|
245
|
+
{...FORM_STYLE}
|
|
246
|
+
/>
|
|
247
|
+
<Flexbox align="end" justify="flex-end">
|
|
248
|
+
{hasUnsavedChanges && (
|
|
249
|
+
<span style={{ color: 'var(--ant-color-warning)', marginBottom: 8 }}>
|
|
250
|
+
{t('proxy.unsavedChanges')}
|
|
251
|
+
</span>
|
|
252
|
+
)}
|
|
253
|
+
<Flexbox gap={8} horizontal>
|
|
344
254
|
<Button
|
|
345
255
|
disabled={!hasUnsavedChanges}
|
|
346
256
|
loading={isSaving}
|
|
@@ -349,19 +259,12 @@ const ProxyForm = () => {
|
|
|
349
259
|
>
|
|
350
260
|
{t('proxy.saveButton')}
|
|
351
261
|
</Button>
|
|
352
|
-
|
|
353
262
|
<Button disabled={!hasUnsavedChanges || isSaving} onClick={handleReset}>
|
|
354
263
|
{t('proxy.resetButton')}
|
|
355
264
|
</Button>
|
|
356
|
-
|
|
357
|
-
{hasUnsavedChanges && (
|
|
358
|
-
<Text style={{ marginLeft: 8 }} type="warning">
|
|
359
|
-
{t('proxy.unsavedChanges')}
|
|
360
|
-
</Text>
|
|
361
|
-
)}
|
|
362
|
-
</Space>
|
|
265
|
+
</Flexbox>
|
|
363
266
|
</Flexbox>
|
|
364
|
-
</
|
|
267
|
+
</Flexbox>
|
|
365
268
|
);
|
|
366
269
|
};
|
|
367
270
|
|