@lobehub/lobehub 2.0.0-next.294 → 2.0.0-next.296

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.
Files changed (249) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/apps/desktop/src/main/__mocks__/node-mac-permissions.ts +0 -1
  3. package/apps/desktop/src/main/__mocks__/setup.ts +0 -1
  4. package/apps/desktop/src/main/controllers/__tests__/SystemCtr.test.ts +1 -4
  5. package/apps/desktop/tsconfig.json +4 -10
  6. package/changelog/v1.json +18 -0
  7. package/e2e/scripts/setup.ts +45 -32
  8. package/locales/en-US/plugin.json +4 -0
  9. package/locales/zh-CN/plugin.json +4 -0
  10. package/package.json +1 -1
  11. package/packages/agent-runtime/src/core/__tests__/runtime.test.ts +5 -5
  12. package/packages/agent-runtime/src/utils/stepContextComputer.test.ts +5 -5
  13. package/packages/builtin-tool-gtd/src/client/Inspector/index.ts +0 -4
  14. package/packages/builtin-tool-gtd/src/client/Intervention/AddTodo.tsx +1 -1
  15. package/packages/builtin-tool-gtd/src/client/Render/TodoList/index.tsx +39 -10
  16. package/packages/builtin-tool-gtd/src/client/Render/index.ts +0 -2
  17. package/packages/builtin-tool-gtd/src/client/components/SortableTodoList/TodoItemRow.tsx +26 -12
  18. package/packages/builtin-tool-gtd/src/client/components/SortableTodoList/store/actions.ts +5 -5
  19. package/packages/builtin-tool-gtd/src/client/components/SortableTodoList/store/store.test.ts +14 -8
  20. package/packages/builtin-tool-gtd/src/executor/index.test.ts +48 -227
  21. package/packages/builtin-tool-gtd/src/executor/index.ts +15 -158
  22. package/packages/builtin-tool-gtd/src/manifest.ts +12 -42
  23. package/packages/builtin-tool-gtd/src/systemRole.ts +14 -8
  24. package/packages/builtin-tool-gtd/src/types.ts +47 -41
  25. package/packages/builtin-tool-memory/package.json +8 -0
  26. package/packages/builtin-tool-memory/src/client/Inspector/AddContextMemory/index.tsx +60 -0
  27. package/packages/builtin-tool-memory/src/client/Inspector/AddExperienceMemory/index.tsx +60 -0
  28. package/packages/builtin-tool-memory/src/client/Inspector/AddIdentityMemory/index.tsx +60 -0
  29. package/packages/builtin-tool-memory/src/client/Inspector/AddPreferenceMemory/index.tsx +60 -0
  30. package/packages/builtin-tool-memory/src/client/Inspector/RemoveIdentityMemory/index.tsx +60 -0
  31. package/packages/builtin-tool-memory/src/client/Inspector/SearchUserMemory/index.tsx +67 -0
  32. package/packages/builtin-tool-memory/src/client/Inspector/UpdateIdentityMemory/index.tsx +60 -0
  33. package/packages/builtin-tool-memory/src/client/Inspector/index.ts +35 -0
  34. package/packages/builtin-tool-memory/src/client/Intervention/AddExperienceMemory/index.tsx +17 -0
  35. package/packages/builtin-tool-memory/src/client/Intervention/index.ts +13 -0
  36. package/packages/builtin-tool-memory/src/client/Render/AddExperienceMemory/index.tsx +17 -0
  37. package/packages/builtin-tool-memory/src/client/Render/SearchUserMemory/index.tsx +217 -0
  38. package/packages/builtin-tool-memory/src/client/Render/index.ts +15 -0
  39. package/packages/builtin-tool-memory/src/client/Streaming/AddExperienceMemory/index.tsx +17 -0
  40. package/packages/builtin-tool-memory/src/client/Streaming/index.ts +18 -0
  41. package/packages/builtin-tool-memory/src/client/components/ExperienceMemoryCard.tsx +231 -0
  42. package/packages/builtin-tool-memory/src/client/components/index.ts +1 -0
  43. package/packages/builtin-tool-memory/src/client/index.ts +27 -0
  44. package/packages/builtin-tool-memory/src/executor/index.ts +9 -1
  45. package/packages/builtin-tool-memory/src/types.ts +61 -0
  46. package/packages/context-engine/src/providers/GTDTodoInjector.ts +15 -7
  47. package/packages/conversation-flow/src/__tests__/fixtures/outputs/assistantGroup/tools-with-branches.json +4 -0
  48. package/packages/conversation-flow/src/transformation/FlatListBuilder.ts +1 -0
  49. package/packages/database/src/models/__tests__/knowledgeBase.test.ts +1 -1
  50. package/packages/database/src/repositories/knowledge/index.ts +1 -4
  51. package/packages/prompts/src/prompts/gtd/index.test.ts +32 -16
  52. package/packages/prompts/src/prompts/gtd/index.ts +9 -5
  53. package/packages/types/src/discover/assistants.ts +2 -2
  54. package/packages/types/src/stepContext.ts +4 -1
  55. package/scripts/migrate-spa-navigation.ts +129 -0
  56. package/src/app/(backend)/api/workflows/memory-user-memory/pipelines/chat-topic/process-topics/route.ts +112 -109
  57. package/src/app/(backend)/api/workflows/memory-user-memory/pipelines/chat-topic/process-user-topics/route.ts +125 -113
  58. package/src/app/(backend)/api/workflows/memory-user-memory/pipelines/chat-topic/process-users/route.ts +74 -65
  59. package/src/app/[variants]/(auth)/auth-error/page.tsx +1 -1
  60. package/src/app/[variants]/(auth)/login/[[...login]]/page.tsx +1 -1
  61. package/src/app/[variants]/(auth)/next-auth/error/AuthErrorPage.tsx +1 -1
  62. package/src/app/[variants]/(auth)/next-auth/signin/AuthSignInBox.tsx +1 -1
  63. package/src/app/[variants]/(auth)/oauth/callback/error/page.tsx +1 -1
  64. package/src/app/[variants]/(auth)/oauth/callback/success/page.tsx +1 -1
  65. package/src/app/[variants]/(auth)/oauth/consent/[uid]/page.tsx +1 -1
  66. package/src/app/[variants]/(auth)/reset-password/layout.tsx +1 -1
  67. package/src/app/[variants]/(auth)/reset-password/page.tsx +2 -2
  68. package/src/app/[variants]/(auth)/signin/layout.tsx +1 -1
  69. package/src/app/[variants]/(auth)/signin/useSignIn.ts +1 -1
  70. package/src/app/[variants]/(auth)/signup/[[...signup]]/BetterAuthSignUpForm.tsx +2 -2
  71. package/src/app/[variants]/(auth)/signup/[[...signup]]/page.tsx +1 -1
  72. package/src/app/[variants]/(auth)/signup/[[...signup]]/useSignUp.tsx +1 -1
  73. package/src/app/[variants]/(auth)/verify-email/layout.tsx +1 -1
  74. package/src/app/[variants]/(auth)/verify-email/page.tsx +2 -2
  75. package/src/app/[variants]/(main)/_layout/index.tsx +1 -1
  76. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/CronTopicGroup.tsx +1 -1
  77. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Header/AddTopicButon.tsx +1 -1
  78. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Header/Nav.tsx +1 -1
  79. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/AllTopicsDrawer/index.tsx +1 -1
  80. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/hooks/useThreadNavigation.ts +1 -1
  81. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/hooks/useTopicNavigation.ts +1 -1
  82. package/src/app/[variants]/(main)/agent/features/TelemetryNotification.tsx +2 -3
  83. package/src/app/[variants]/(main)/community/(detail)/assistant/features/Details/Nav.tsx +9 -9
  84. package/src/app/[variants]/(main)/community/(detail)/assistant/features/Details/Versions/index.tsx +2 -3
  85. package/src/app/[variants]/(main)/community/(detail)/features/MakedownRender.tsx +1 -2
  86. package/src/app/[variants]/(main)/community/(detail)/features/ShareButton.tsx +2 -3
  87. package/src/app/[variants]/(main)/community/(detail)/features/Toc/Heading.tsx +2 -3
  88. package/src/app/[variants]/(main)/community/(detail)/mcp/features/Details/Versions/index.tsx +2 -2
  89. package/src/app/[variants]/(main)/community/(detail)/model/features/Details/Nav.tsx +12 -11
  90. package/src/app/[variants]/(main)/community/(detail)/model/features/Details/Parameter/ParameterItem.tsx +2 -3
  91. package/src/app/[variants]/(main)/community/(detail)/provider/features/Details/Nav.tsx +11 -10
  92. package/src/app/[variants]/(main)/community/(detail)/provider/features/Header.tsx +10 -9
  93. package/src/app/[variants]/(main)/community/(list)/(home)/index.tsx +1 -1
  94. package/src/app/[variants]/(main)/community/(list)/assistant/features/Category/useCategory.tsx +1 -1
  95. package/src/app/[variants]/(main)/community/(list)/features/SortButton/index.tsx +2 -3
  96. package/src/app/[variants]/(main)/community/_layout/Sidebar/Header/Nav.tsx +1 -1
  97. package/src/app/[variants]/(main)/community/features/CreateButton/Inner.tsx +1 -1
  98. package/src/app/[variants]/(main)/community/features/CreateButton/index.tsx +1 -1
  99. package/src/app/[variants]/(main)/community/features/Search.tsx +1 -2
  100. package/src/app/[variants]/(main)/community/features/Title.tsx +5 -5
  101. package/src/app/[variants]/(main)/group/_layout/Sidebar/Header/Nav.tsx +1 -1
  102. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/AllTopicsDrawer/index.tsx +1 -1
  103. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/hooks/useThreadNavigation.ts +1 -1
  104. package/src/app/[variants]/(main)/group/features/Conversation/Header/ShareButton/index.tsx +1 -1
  105. package/src/app/[variants]/(main)/group/features/TelemetryNotification.tsx +2 -3
  106. package/src/app/[variants]/(main)/home/_layout/Body/Agent/AllAgentsDrawer/index.tsx +1 -1
  107. package/src/app/[variants]/(main)/hooks/useActiveTabKey.ts +6 -11
  108. package/src/app/[variants]/(main)/image/NotSupportClient.tsx +4 -3
  109. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/ImageUpload.tsx +1 -1
  110. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/MultiImagesUpload/ImageManageModal.tsx +1 -1
  111. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/MultiImagesUpload/index.tsx +1 -1
  112. package/src/app/[variants]/(main)/memory/(home)/features/RoleTagCloud/index.tsx +1 -1
  113. package/src/app/[variants]/(main)/memory/_layout/Sidebar/Header/Nav.tsx +1 -1
  114. package/src/app/[variants]/(main)/memory/features/SourceLink.tsx +1 -1
  115. package/src/app/[variants]/(main)/page/_layout/Body/AllPagesDrawer/index.tsx +1 -1
  116. package/src/app/[variants]/(main)/resource/features/DndContextWrapper.tsx +4 -2
  117. package/src/app/[variants]/(main)/resource/library/_layout/Header/LibraryHead.tsx +30 -35
  118. package/src/app/[variants]/(main)/resource/library/_layout/Header/index.tsx +9 -11
  119. package/src/app/[variants]/(main)/settings/about/features/ItemCard.tsx +2 -3
  120. package/src/app/[variants]/(main)/settings/about/features/ItemLink.tsx +2 -3
  121. package/src/app/[variants]/(main)/settings/about/features/Version.tsx +6 -7
  122. package/src/app/[variants]/(main)/settings/features/SettingsContent.tsx +1 -1
  123. package/src/app/[variants]/(main)/settings/features/UpgradeAlert.tsx +4 -4
  124. package/src/app/[variants]/(main)/settings/provider/(list)/Footer.tsx +2 -2
  125. package/src/app/[variants]/(main)/settings/provider/detail/index.tsx +1 -1
  126. package/src/app/[variants]/(main)/settings/provider/detail/ollama/CheckError.tsx +1 -1
  127. package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/index.tsx +12 -6
  128. package/src/app/[variants]/(main)/settings/security/index.tsx +1 -1
  129. package/src/app/[variants]/(main)/settings/stats/features/overview/ShareButton/ShareModal.tsx +1 -1
  130. package/src/app/[variants]/(main)/settings/stats/features/rankings/AssistantsRank.tsx +1 -1
  131. package/src/app/[variants]/(main)/settings/stats/features/rankings/TopicsRank.tsx +1 -1
  132. package/src/app/[variants]/(mobile)/_layout/index.tsx +1 -1
  133. package/src/app/[variants]/(mobile)/chat/settings/features/AgentInfoDescription/index.tsx +1 -1
  134. package/src/app/[variants]/(mobile)/chat/settings/features/SettingButton.tsx +1 -1
  135. package/src/app/[variants]/(mobile)/router/index.tsx +1 -1
  136. package/src/app/[variants]/page.tsx +1 -1
  137. package/src/app/[variants]/router/index.tsx +1 -1
  138. package/src/components/404/index.tsx +4 -4
  139. package/src/components/Analytics/index.tsx +1 -1
  140. package/src/components/BrandWatermark/index.tsx +4 -4
  141. package/src/components/Branding/ProductLogo/Custom.tsx +1 -1
  142. package/src/components/Error/index.tsx +3 -4
  143. package/src/components/GoBack/index.tsx +2 -2
  144. package/src/components/LabsModal/LabCard.tsx +1 -1
  145. package/src/components/Link.tsx +25 -5
  146. package/src/components/OllamaSetupGuide/index.tsx +5 -4
  147. package/src/components/WebFavicon/index.tsx +1 -1
  148. package/src/components/client/ClientResponsiveContent/index.tsx +1 -1
  149. package/src/components/client/ClientResponsiveLayout.tsx +1 -1
  150. package/src/components/mdx/Image.tsx +1 -1
  151. package/src/components/mdx/Link.tsx +26 -9
  152. package/src/features/AlertBanner/CloudBanner.tsx +2 -3
  153. package/src/features/ChatInput/ActionBar/Model/ControlsForm.tsx +8 -7
  154. package/src/features/ChatInput/ActionBar/Params/Controls.tsx +1 -3
  155. package/src/features/ChatInput/ActionBar/Token/index.tsx +1 -1
  156. package/src/features/ChatInput/Mobile/index.tsx +1 -1
  157. package/src/features/Conversation/ChatItem/components/MessageContent/index.tsx +1 -1
  158. package/src/features/Conversation/Error/OllamaBizError/index.tsx +1 -1
  159. package/src/features/Conversation/Error/OllamaSetupGuide/Desktop.tsx +1 -2
  160. package/src/features/Conversation/Error/index.tsx +1 -1
  161. package/src/features/Conversation/Messages/AssistantGroup/Tool/Actions/Settings.tsx +1 -1
  162. package/src/features/Conversation/Messages/AssistantGroup/Tool/Actions/index.tsx +11 -17
  163. package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/LoadingPlaceholder/index.tsx +13 -3
  164. package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Render/CustomRender.tsx +43 -0
  165. package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Render/FallbacktArgumentRender.tsx +59 -0
  166. package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Render/index.tsx +46 -0
  167. package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/index.tsx +13 -19
  168. package/src/features/Conversation/Messages/AssistantGroup/Tool/index.tsx +18 -18
  169. package/src/features/Conversation/Messages/AssistantGroup/index.tsx +1 -1
  170. package/src/features/Conversation/Messages/Tool/Tool/index.tsx +11 -10
  171. package/src/features/Conversation/Messages/components/SearchGrounding.tsx +1 -1
  172. package/src/features/Conversation/TodoProgress/index.tsx +56 -23
  173. package/src/features/DataImporter/Error.tsx +3 -3
  174. package/src/features/DevPanel/CacheViewer/cacheProvider.tsx +2 -1
  175. package/src/features/DevPanel/MetadataViewer/Og.tsx +1 -1
  176. package/src/features/DevPanel/features/FloatPanel.tsx +1 -1
  177. package/src/features/DevPanel/features/Table/TooltipContent.tsx +3 -4
  178. package/src/features/DevPanel/index.tsx +1 -1
  179. package/src/features/EditorCanvas/InlineToolbar.tsx +1 -6
  180. package/src/features/FileViewer/NotSupport/index.tsx +2 -3
  181. package/src/features/Follow/index.tsx +8 -9
  182. package/src/features/LibraryModal/AddFilesToKnowledgeBase/SelectForm.tsx +2 -2
  183. package/src/features/MCP/Scores.tsx +1 -1
  184. package/src/features/MCPPluginDetail/Nav.tsx +8 -8
  185. package/src/features/MCPPluginDetail/Overview/TagList.tsx +1 -1
  186. package/src/features/MobileTabBar/index.tsx +2 -1
  187. package/src/features/OllamaSetupGuide/Desktop.tsx +1 -2
  188. package/src/features/PWAInstall/Install.tsx +1 -1
  189. package/src/features/PWAInstall/index.tsx +1 -1
  190. package/src/features/PluginStore/McpList/index.tsx +1 -1
  191. package/src/features/PluginStore/PluginList/Detail/Header.tsx +6 -6
  192. package/src/features/PluginsUI/Render/DefaultType/index.tsx +1 -1
  193. package/src/features/PluginsUI/Render/MCPType/index.tsx +1 -1
  194. package/src/features/Portal/Artifacts/Body/Renderer/index.tsx +1 -1
  195. package/src/features/ResourceManager/components/ChunkDrawer/index.tsx +1 -1
  196. package/src/features/ResourceManager/components/Explorer/Header/index.tsx +57 -4
  197. package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +6 -4
  198. package/src/features/ResourceManager/components/Explorer/ListView/Skeleton.tsx +26 -26
  199. package/src/features/ResourceManager/components/Explorer/ListView/index.tsx +16 -5
  200. package/src/features/ResourceManager/components/Explorer/ToolBar/BatchActionsDropdown.tsx +147 -149
  201. package/src/features/ResourceManager/components/LibraryHierarchy/styles.ts +5 -4
  202. package/src/features/ResourceManager/index.tsx +1 -1
  203. package/src/features/Setting/Footer.tsx +4 -5
  204. package/src/features/User/UserPanel/PanelContent.tsx +1 -1
  205. package/src/hooks/useActiveTabKey.ts +6 -4
  206. package/src/hooks/useIsSingleMode.test.ts +10 -24
  207. package/src/hooks/useIsSingleMode.ts +4 -2
  208. package/src/hooks/useIsSubSlug.ts +2 -1
  209. package/src/hooks/useQuery.ts +5 -5
  210. package/src/layout/GlobalProvider/AppTheme.tsx +2 -2
  211. package/src/layout/GlobalProvider/StyleRegistry.tsx +1 -1
  212. package/src/layout/GlobalProvider/useUserStateRedirect.ts +13 -25
  213. package/src/libs/next/Image.tsx +13 -0
  214. package/src/libs/next/Link.tsx +13 -0
  215. package/src/libs/next/dynamic.tsx +13 -0
  216. package/src/libs/next/index.ts +22 -0
  217. package/src/libs/next/navigation.ts +22 -0
  218. package/src/libs/router/Link.tsx +30 -0
  219. package/src/libs/router/index.ts +18 -0
  220. package/src/libs/router/navigation.ts +72 -0
  221. package/src/locales/default/plugin.ts +1 -0
  222. package/src/server/modules/AgentRuntime/AgentStateManager.ts +5 -1
  223. package/src/store/chat/slices/message/selectors/dbMessage.test.ts +11 -11
  224. package/src/store/chat/slices/portal/selectors.test.ts +5 -15
  225. package/src/store/file/slices/resource/action.ts +4 -2
  226. package/src/store/page/index.ts +1 -1
  227. package/src/store/page/slices/crud/index.ts +1 -1
  228. package/src/tools/inspectors.ts +2 -0
  229. package/src/tools/interventions.ts +2 -0
  230. package/src/tools/renders.ts +3 -1
  231. package/src/tools/streamings.ts +2 -0
  232. package/packages/builtin-tool-gtd/src/client/Inspector/CompleteTodos/index.tsx +0 -52
  233. package/packages/builtin-tool-gtd/src/client/Inspector/RemoveTodos/index.tsx +0 -52
  234. package/src/app/[variants]/(main)/hooks/usePathname.ts +0 -10
  235. package/src/app/[variants]/(main)/hooks/useQuery.ts +0 -12
  236. package/src/app/[variants]/(main)/hooks/useRouter.ts +0 -22
  237. package/src/app/[variants]/(main)/hooks/useSearchParams.ts +0 -11
  238. package/src/features/Conversation/Messages/AssistantGroup/Tool/Render/CustomRender.tsx +0 -113
  239. package/src/features/Conversation/Messages/Tool/Tool/Render.tsx +0 -47
  240. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/AbortResponse.tsx +0 -0
  241. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Arguments/index.tsx +0 -0
  242. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/ErrorResponse.tsx +0 -0
  243. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/ApprovalActions.tsx +0 -0
  244. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/Fallback.tsx +0 -0
  245. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/KeyValueEditor.tsx +0 -0
  246. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/ModeSelector.tsx +0 -0
  247. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/index.tsx +0 -0
  248. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/PluginSettings.tsx +0 -0
  249. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/RejectedResponse.tsx +0 -0
@@ -34,33 +34,33 @@ const ListViewSkeleton = ({
34
34
  opacity: getOpacity(index),
35
35
  }}
36
36
  >
37
- <Center height={40} style={{ paddingInline: 4 }}>
38
- <Checkbox disabled />
39
- </Center>
40
- <Flexbox
41
- align={'center'}
42
- horizontal
43
- style={{
44
- flexShrink: 0,
45
- maxWidth: columnWidths.name,
46
- minWidth: columnWidths.name,
47
- paddingInline: 8,
48
- width: columnWidths.name,
49
- }}
50
- >
51
- <Skeleton.Avatar active shape={'square'} size={24} style={{ marginInline: 8 }} />
52
- <Skeleton.Button active style={{ height: 16, width: '60%' }} />
53
- </Flexbox>
54
- <Flexbox style={{ flexShrink: 0, paddingInline: '0 24px' }} width={columnWidths.date}>
55
- <Skeleton.Button active style={{ height: 16, width: '80%' }} />
56
- </Flexbox>
57
- <Flexbox style={{ flexShrink: 0, paddingInline: '0 24px' }} width={columnWidths.size}>
58
- <Skeleton.Button active style={{ height: 16, width: '60%' }} />
37
+ <Center height={40} style={{ paddingInline: 4 }}>
38
+ <Checkbox disabled />
39
+ </Center>
40
+ <Flexbox
41
+ align={'center'}
42
+ horizontal
43
+ style={{
44
+ flexShrink: 0,
45
+ maxWidth: columnWidths.name,
46
+ minWidth: columnWidths.name,
47
+ paddingInline: 8,
48
+ width: columnWidths.name,
49
+ }}
50
+ >
51
+ <Skeleton.Avatar active shape={'square'} size={24} style={{ marginInline: 8 }} />
52
+ <Skeleton.Button active style={{ height: 16, width: '60%' }} />
53
+ </Flexbox>
54
+ <Flexbox style={{ flexShrink: 0, paddingInline: '0 24px' }} width={columnWidths.date}>
55
+ <Skeleton.Button active style={{ height: 16, width: '80%' }} />
56
+ </Flexbox>
57
+ <Flexbox style={{ flexShrink: 0, paddingInline: '0 24px' }} width={columnWidths.size}>
58
+ <Skeleton.Button active style={{ height: 16, width: '60%' }} />
59
+ </Flexbox>
59
60
  </Flexbox>
60
- </Flexbox>
61
- ))}
62
- </Flexbox>
63
- );
61
+ ))}
62
+ </Flexbox>
63
+ );
64
64
  };
65
65
 
66
66
  export default ListViewSkeleton;
@@ -34,7 +34,7 @@ const styles = createStaticStyles(({ css }) => ({
34
34
  `,
35
35
  dropZoneActive: css`
36
36
  background: ${cssVar.colorPrimaryBg};
37
- outline: 2px dashed ${cssVar.colorPrimary};
37
+ outline: 1px dashed ${cssVar.colorPrimaryBorder};
38
38
  outline-offset: -4px;
39
39
  `,
40
40
  header: css`
@@ -330,9 +330,15 @@ const ListView = memo(function ListView() {
330
330
 
331
331
  // Memoize footer component to show skeleton loaders when loading more
332
332
  const Footer = useCallback(() => {
333
- if (!isLoadingMore || !fileListHasMore) return null;
334
- return <ListViewSkeleton columnWidths={columnWidths} />;
335
- }, [isLoadingMore, fileListHasMore, columnWidths]);
333
+ if (isLoadingMore && fileListHasMore) return <ListViewSkeleton columnWidths={columnWidths} />;
334
+
335
+ // Leave some padding at the end when there are no more pages,
336
+ // so users can clearly feel they've reached the end of the list.
337
+ if (fileListHasMore === false && dataLength > 0)
338
+ return <div aria-hidden style={{ height: 96 }} />;
339
+
340
+ return null;
341
+ }, [columnWidths, dataLength, fileListHasMore, isLoadingMore]);
336
342
 
337
343
  if (showSkeleton) return <ListViewSkeleton columnWidths={columnWidths} />;
338
344
 
@@ -369,7 +375,12 @@ const ListView = memo(function ListView() {
369
375
  width: columnWidths.name,
370
376
  }}
371
377
  >
372
- {t('FileManager.title.title')}
378
+ {selectFileIds.length > 0
379
+ ? t('FileManager.total.selectedCount', {
380
+ count: selectFileIds.length,
381
+ ns: 'components',
382
+ })
383
+ : t('FileManager.title.title')}
373
384
  <ColumnResizeHandle
374
385
  column="name"
375
386
  currentWidth={columnWidths.name}
@@ -29,168 +29,166 @@ interface BatchActionsDropdownProps {
29
29
  selectCount: number;
30
30
  }
31
31
 
32
- const BatchActionsDropdown = memo<BatchActionsDropdownProps>(
33
- ({ selectCount, onActionClick }) => {
34
- const { t } = useTranslation(['components', 'common', 'file', 'knowledgeBase']);
35
- const { modal, message } = App.useApp();
36
-
37
- const [libraryId, selectedFileIds] = useResourceManagerStore((s) => [
38
- s.libraryId,
39
- s.selectedFileIds,
40
- ]);
41
- const [useFetchKnowledgeBaseList, addFilesToKnowledgeBase] = useKnowledgeBaseStore((s) => [
42
- s.useFetchKnowledgeBaseList,
43
- s.addFilesToKnowledgeBase,
44
- ]);
45
- const { data: knowledgeBases } = useFetchKnowledgeBaseList();
46
-
47
- const menuItems = useMemo<DropdownItem[]>(() => {
48
- const items: DropdownItem[] = [];
49
-
50
- // Show delete library option only when in a knowledge base and no files selected
51
- if (libraryId && selectCount === 0) {
52
- items.push({
53
- danger: true,
54
- icon: <Icon icon={Trash2Icon} />,
55
- key: 'deleteLibrary',
56
- label: t('header.actions.deleteLibrary', { ns: 'file' }),
57
- onClick: async () => {
58
- modal.confirm({
59
- okButtonProps: {
60
- danger: true,
61
- },
62
- onOk: async () => {
63
- await onActionClick('deleteLibrary');
64
- },
65
- title: t('library.list.confirmRemoveLibrary', { ns: 'file' }),
66
- });
67
- },
68
- });
69
- return items;
70
- }
71
-
72
- // Filter out current knowledge base and create submenu items
73
- const availableKnowledgeBases = (knowledgeBases || []).filter((kb) => kb.id !== libraryId);
74
-
75
- const addToKnowledgeBaseSubmenu: DropdownItem[] = availableKnowledgeBases.map((kb) => ({
76
- disabled: selectCount === 0,
77
- icon: <RepoIcon />,
78
- key: `add-to-kb-${kb.id}`,
79
- label: <span style={{ marginLeft: 8 }}>{kb.name}</span>,
32
+ const BatchActionsDropdown = memo<BatchActionsDropdownProps>(({ selectCount, onActionClick }) => {
33
+ const { t } = useTranslation(['components', 'common', 'file', 'knowledgeBase']);
34
+ const { modal, message } = App.useApp();
35
+
36
+ const [libraryId, selectedFileIds] = useResourceManagerStore((s) => [
37
+ s.libraryId,
38
+ s.selectedFileIds,
39
+ ]);
40
+ const [useFetchKnowledgeBaseList, addFilesToKnowledgeBase] = useKnowledgeBaseStore((s) => [
41
+ s.useFetchKnowledgeBaseList,
42
+ s.addFilesToKnowledgeBase,
43
+ ]);
44
+ const { data: knowledgeBases } = useFetchKnowledgeBaseList();
45
+
46
+ const menuItems = useMemo<DropdownItem[]>(() => {
47
+ const items: DropdownItem[] = [];
48
+
49
+ // Show delete library option only when in a knowledge base and no files selected
50
+ if (libraryId && selectCount === 0) {
51
+ items.push({
52
+ danger: true,
53
+ icon: <Icon icon={Trash2Icon} />,
54
+ key: 'deleteLibrary',
55
+ label: t('header.actions.deleteLibrary', { ns: 'file' }),
80
56
  onClick: async () => {
81
- try {
82
- await addFilesToKnowledgeBase(kb.id, selectedFileIds);
83
- message.success(
84
- t('addToKnowledgeBase.addSuccess', {
85
- count: selectCount,
86
- ns: 'knowledgeBase',
87
- }),
88
- );
89
- } catch (e) {
90
- console.error(e);
91
- message.error(t('addToKnowledgeBase.error', { ns: 'knowledgeBase' }));
92
- }
57
+ modal.confirm({
58
+ okButtonProps: {
59
+ danger: true,
60
+ },
61
+ onOk: async () => {
62
+ await onActionClick('deleteLibrary');
63
+ },
64
+ title: t('library.list.confirmRemoveLibrary', { ns: 'file' }),
65
+ });
93
66
  },
94
- }));
95
-
96
- if (libraryId) {
97
- items.push({
98
- disabled: selectCount === 0,
99
- icon: <Icon icon={BookMinusIcon} />,
100
- key: 'removeFromKnowledgeBase',
101
- label: t('FileManager.actions.removeFromKnowledgeBase'),
102
- onClick: () => {
103
- modal.confirm({
104
- okButtonProps: {
105
- danger: true,
106
- },
107
- onOk: async () => {
108
- await onActionClick('removeFromKnowledgeBase');
109
- message.success(t('FileManager.actions.removeFromKnowledgeBaseSuccess'));
110
- },
111
- title: t('FileManager.actions.confirmRemoveFromKnowledgeBase', {
112
- count: selectCount,
113
- }),
114
- });
115
- },
116
- });
67
+ });
68
+ return items;
69
+ }
70
+
71
+ // Filter out current knowledge base and create submenu items
72
+ const availableKnowledgeBases = (knowledgeBases || []).filter((kb) => kb.id !== libraryId);
73
+
74
+ const addToKnowledgeBaseSubmenu: DropdownItem[] = availableKnowledgeBases.map((kb) => ({
75
+ disabled: selectCount === 0,
76
+ icon: <RepoIcon />,
77
+ key: `add-to-kb-${kb.id}`,
78
+ label: <span style={{ marginLeft: 8 }}>{kb.name}</span>,
79
+ onClick: async () => {
80
+ try {
81
+ await addFilesToKnowledgeBase(kb.id, selectedFileIds);
82
+ message.success(
83
+ t('addToKnowledgeBase.addSuccess', {
84
+ count: selectCount,
85
+ ns: 'knowledgeBase',
86
+ }),
87
+ );
88
+ } catch (e) {
89
+ console.error(e);
90
+ message.error(t('addToKnowledgeBase.error', { ns: 'knowledgeBase' }));
91
+ }
92
+ },
93
+ }));
117
94
 
118
- if (availableKnowledgeBases.length > 0) {
119
- items.push({
120
- children: addToKnowledgeBaseSubmenu as any,
121
- disabled: selectCount === 0,
122
- icon: <Icon icon={BookPlusIcon} />,
123
- key: 'addToOtherKnowledgeBase',
124
- label: t('FileManager.actions.addToOtherKnowledgeBase'),
95
+ if (libraryId) {
96
+ items.push({
97
+ disabled: selectCount === 0,
98
+ icon: <Icon icon={BookMinusIcon} />,
99
+ key: 'removeFromKnowledgeBase',
100
+ label: t('FileManager.actions.removeFromKnowledgeBase'),
101
+ onClick: () => {
102
+ modal.confirm({
103
+ okButtonProps: {
104
+ danger: true,
105
+ },
106
+ onOk: async () => {
107
+ await onActionClick('removeFromKnowledgeBase');
108
+ message.success(t('FileManager.actions.removeFromKnowledgeBaseSuccess'));
109
+ },
110
+ title: t('FileManager.actions.confirmRemoveFromKnowledgeBase', {
111
+ count: selectCount,
112
+ }),
125
113
  });
126
- }
127
- } else if (availableKnowledgeBases.length > 0) {
114
+ },
115
+ });
116
+
117
+ if (availableKnowledgeBases.length > 0) {
128
118
  items.push({
129
119
  children: addToKnowledgeBaseSubmenu as any,
130
120
  disabled: selectCount === 0,
131
121
  icon: <Icon icon={BookPlusIcon} />,
132
- key: 'addToKnowledgeBase',
133
- label: t('FileManager.actions.addToKnowledgeBase'),
122
+ key: 'addToOtherKnowledgeBase',
123
+ label: t('FileManager.actions.addToOtherKnowledgeBase'),
134
124
  });
135
125
  }
136
-
137
- items.push(
138
- {
139
- disabled: selectCount === 0,
140
- icon: <Icon icon={FileBoxIcon} />,
141
- key: 'batchChunking',
142
- label: t('FileManager.actions.batchChunking'),
143
- onClick: async () => {
144
- await onActionClick('batchChunking');
145
- },
146
- },
147
- {
148
- type: 'divider',
126
+ } else if (availableKnowledgeBases.length > 0) {
127
+ items.push({
128
+ children: addToKnowledgeBaseSubmenu as any,
129
+ disabled: selectCount === 0,
130
+ icon: <Icon icon={BookPlusIcon} />,
131
+ key: 'addToKnowledgeBase',
132
+ label: t('FileManager.actions.addToKnowledgeBase'),
133
+ });
134
+ }
135
+
136
+ items.push(
137
+ {
138
+ disabled: selectCount === 0,
139
+ icon: <Icon icon={FileBoxIcon} />,
140
+ key: 'batchChunking',
141
+ label: t('FileManager.actions.batchChunking'),
142
+ onClick: async () => {
143
+ await onActionClick('batchChunking');
149
144
  },
150
- {
151
- danger: true,
152
- disabled: selectCount === 0,
153
- icon: <Icon icon={Trash2Icon} />,
154
- key: 'delete',
155
- label: t('delete', { ns: 'common' }),
156
- onClick: async () => {
157
- modal.confirm({
158
- okButtonProps: {
159
- danger: true,
160
- },
161
- onOk: async () => {
162
- await onActionClick('delete');
163
- message.success(t('FileManager.actions.deleteSuccess'));
164
- },
165
- title: t('FileManager.actions.confirmDeleteMultiFiles', { count: selectCount }),
166
- });
167
- },
145
+ },
146
+ {
147
+ type: 'divider',
148
+ },
149
+ {
150
+ danger: true,
151
+ disabled: selectCount === 0,
152
+ icon: <Icon icon={Trash2Icon} />,
153
+ key: 'delete',
154
+ label: t('delete', { ns: 'common' }),
155
+ onClick: async () => {
156
+ modal.confirm({
157
+ okButtonProps: {
158
+ danger: true,
159
+ },
160
+ onOk: async () => {
161
+ await onActionClick('delete');
162
+ message.success(t('FileManager.actions.deleteSuccess'));
163
+ },
164
+ title: t('FileManager.actions.confirmDeleteMultiFiles', { count: selectCount }),
165
+ });
168
166
  },
169
- );
170
-
171
- return items;
172
- }, [
173
- libraryId,
174
- selectCount,
175
- selectedFileIds,
176
- onActionClick,
177
- addFilesToKnowledgeBase,
178
- t,
179
- modal,
180
- message,
181
- knowledgeBases,
182
- ]);
183
-
184
- return (
185
- <DropdownMenu items={menuItems} placement="bottomLeft">
186
- <ActionIconWithChevron
187
- icon={CircleEllipsisIcon}
188
- title={t('FileManager.actions.batchActions', 'Batch actions')}
189
- />
190
- </DropdownMenu>
167
+ },
191
168
  );
192
- },
193
- );
169
+
170
+ return items;
171
+ }, [
172
+ libraryId,
173
+ selectCount,
174
+ selectedFileIds,
175
+ onActionClick,
176
+ addFilesToKnowledgeBase,
177
+ t,
178
+ modal,
179
+ message,
180
+ knowledgeBases,
181
+ ]);
182
+
183
+ return (
184
+ <DropdownMenu items={menuItems} placement="bottomLeft">
185
+ <ActionIconWithChevron
186
+ icon={CircleEllipsisIcon}
187
+ title={t('FileManager.actions.batchActions', 'Batch actions')}
188
+ />
189
+ </DropdownMenu>
190
+ );
191
+ });
194
192
 
195
193
  BatchActionsDropdown.displayName = 'BatchActionsDropdown';
196
194
 
@@ -6,11 +6,12 @@ export const styles = createStaticStyles(({ css, cssVar }) => ({
6
6
  opacity: 0.5;
7
7
  `,
8
8
  fileItemDragOver: css`
9
- color: ${cssVar.colorBgElevated} !important;
10
- background-color: ${cssVar.colorText} !important;
9
+ outline: 1px dashed ${cssVar.colorPrimaryBorder};
10
+ outline-offset: -2px;
11
11
 
12
- * {
13
- color: ${cssVar.colorBgElevated} !important;
12
+ &,
13
+ &:hover {
14
+ background: ${cssVar.colorPrimaryBg};
14
15
  }
15
16
  `,
16
17
  treeItem: css`
@@ -3,12 +3,12 @@
3
3
  import { BRANDING_NAME } from '@lobechat/business-const';
4
4
  import { Flexbox } from '@lobehub/ui';
5
5
  import { createStyles, cssVar } from 'antd-style';
6
- import dynamic from 'next/dynamic';
7
6
  import { memo, useEffect } from 'react';
8
7
  import { useSearchParams } from 'react-router-dom';
9
8
 
10
9
  import { useResourceManagerStore } from '@/app/[variants]/(main)/resource/features/store';
11
10
  import { PageEditor } from '@/features/PageEditor';
11
+ import dynamic from '@/libs/next/dynamic';
12
12
  import { documentService } from '@/services/document';
13
13
  import { useFileStore } from '@/store/file';
14
14
  import { documentSelectors } from '@/store/file/slices/document/selectors';
@@ -4,7 +4,6 @@ import { BRANDING_NAME } from '@lobechat/business-const';
4
4
  import { Center, Flexbox, Icon } from '@lobehub/ui';
5
5
  import { createStaticStyles } from 'antd-style';
6
6
  import { MessageSquareHeart } from 'lucide-react';
7
- import Link from 'next/link';
8
7
  import { type PropsWithChildren, memo, useState } from 'react';
9
8
  import { useTranslation } from 'react-i18next';
10
9
 
@@ -43,7 +42,7 @@ const Footer = memo<PropsWithChildren>(() => {
43
42
  >
44
43
  <div style={{ textAlign: 'center' }}>
45
44
  <Icon icon={MessageSquareHeart} /> {`${t('footer.title')} `}
46
- <Link
45
+ <a
47
46
  aria-label={'star'}
48
47
  href={GITHUB}
49
48
  onClick={(e) => {
@@ -52,9 +51,9 @@ const Footer = memo<PropsWithChildren>(() => {
52
51
  }}
53
52
  >
54
53
  {t('footer.action.star')}
55
- </Link>
54
+ </a>
56
55
  {` ${t('footer.and')} `}
57
- <Link
56
+ <a
58
57
  aria-label={'feedback'}
59
58
  href={GITHUB_ISSUES}
60
59
  onClick={(e) => {
@@ -63,7 +62,7 @@ const Footer = memo<PropsWithChildren>(() => {
63
62
  }}
64
63
  >
65
64
  {t('footer.action.feedback')}
66
- </Link>
65
+ </a>
67
66
  {' !'}
68
67
  </div>
69
68
  </Center>
@@ -1,6 +1,6 @@
1
1
  import { ENABLE_BUSINESS_FEATURES } from '@lobechat/business-const';
2
2
  import { Flexbox } from '@lobehub/ui';
3
- import { useRouter } from 'next/navigation';
3
+ import { useRouter } from '@/libs/next/navigation';
4
4
  import { memo } from 'react';
5
5
  import { Link, useNavigate } from 'react-router-dom';
6
6
 
@@ -1,9 +1,9 @@
1
- import { usePathname, useSearchParams } from 'next/navigation';
2
-
1
+ import { usePathname, useSearchParams } from '@/libs/router/navigation';
3
2
  import { ProfileTabs, SettingsTabs, SidebarTabKey } from '@/store/global/initialState';
4
3
 
5
4
  /**
6
5
  * Returns the active tab key (chat/market/settings/...)
6
+ * React Router version for SPA
7
7
  */
8
8
  export const useActiveTabKey = () => {
9
9
  const pathname = usePathname();
@@ -12,16 +12,18 @@ export const useActiveTabKey = () => {
12
12
 
13
13
  /**
14
14
  * Returns the active setting page key (?active=common/sync/agent/...)
15
+ * React Router version for SPA
15
16
  */
16
17
  export const useActiveSettingsKey = () => {
17
- const search = useSearchParams();
18
- const tabs = search.get('active');
18
+ const [searchParams] = useSearchParams();
19
+ const tabs = searchParams.get('active');
19
20
  if (!tabs) return SettingsTabs.Common;
20
21
  return tabs as SettingsTabs;
21
22
  };
22
23
 
23
24
  /**
24
25
  * Returns the active profile page key (profile/security/stats/...)
26
+ * React Router version for SPA
25
27
  */
26
28
  export const useActiveProfileKey = () => {
27
29
  const pathname = usePathname();
@@ -1,23 +1,18 @@
1
1
  import { renderHook } from '@testing-library/react';
2
- import { ReadonlyURLSearchParams } from 'next/navigation';
3
2
  import { describe, expect, it, vi } from 'vitest';
4
3
 
5
4
  import { useIsSingleMode } from './useIsSingleMode';
6
5
 
7
- // Mock next/navigation
6
+ // Mock react-router-dom useSearchParams (via the wrapper hook)
8
7
  const mockUseSearchParams = vi.hoisted(() => vi.fn());
9
- vi.mock('next/navigation', () => ({
8
+ vi.mock('@/libs/router/navigation', () => ({
10
9
  useSearchParams: mockUseSearchParams,
11
10
  }));
12
11
 
13
12
  describe('useIsSingleMode', () => {
14
-
15
13
  it('should return false initially (during SSR)', () => {
16
- const mockSearchParams = {
17
- get: vi.fn(() => 'single'),
18
- } as unknown as ReadonlyURLSearchParams;
19
-
20
- mockUseSearchParams.mockReturnValue(mockSearchParams);
14
+ const mockSearchParams = new URLSearchParams('mode=single');
15
+ mockUseSearchParams.mockReturnValue([mockSearchParams, vi.fn()]);
21
16
 
22
17
  const { result } = renderHook(() => useIsSingleMode());
23
18
 
@@ -26,11 +21,8 @@ describe('useIsSingleMode', () => {
26
21
  });
27
22
 
28
23
  it('should return true when mode=single', () => {
29
- const mockSearchParams = {
30
- get: vi.fn((key: string) => (key === 'mode' ? 'single' : null)),
31
- } as unknown as ReadonlyURLSearchParams;
32
-
33
- mockUseSearchParams.mockReturnValue(mockSearchParams);
24
+ const mockSearchParams = new URLSearchParams('mode=single');
25
+ mockUseSearchParams.mockReturnValue([mockSearchParams, vi.fn()]);
34
26
 
35
27
  const { result } = renderHook(() => useIsSingleMode());
36
28
 
@@ -39,11 +31,8 @@ describe('useIsSingleMode', () => {
39
31
  });
40
32
 
41
33
  it('should return false when mode is not single', () => {
42
- const mockSearchParams = {
43
- get: vi.fn((key: string) => (key === 'mode' ? 'normal' : null)),
44
- } as unknown as ReadonlyURLSearchParams;
45
-
46
- mockUseSearchParams.mockReturnValue(mockSearchParams);
34
+ const mockSearchParams = new URLSearchParams('mode=normal');
35
+ mockUseSearchParams.mockReturnValue([mockSearchParams, vi.fn()]);
47
36
 
48
37
  const { result } = renderHook(() => useIsSingleMode());
49
38
 
@@ -52,11 +41,8 @@ describe('useIsSingleMode', () => {
52
41
  });
53
42
 
54
43
  it('should return false when no mode parameter exists', () => {
55
- const mockSearchParams = {
56
- get: vi.fn(() => null),
57
- } as unknown as ReadonlyURLSearchParams;
58
-
59
- mockUseSearchParams.mockReturnValue(mockSearchParams);
44
+ const mockSearchParams = new URLSearchParams();
45
+ mockUseSearchParams.mockReturnValue([mockSearchParams, vi.fn()]);
60
46
 
61
47
  const { result } = renderHook(() => useIsSingleMode());
62
48
 
@@ -1,11 +1,13 @@
1
1
  'use client';
2
2
 
3
- import { useSearchParams } from 'next/navigation';
4
3
  import { useEffect, useState } from 'react';
5
4
 
5
+ import { useSearchParams } from '@/libs/router/navigation';
6
+
6
7
  /**
7
8
  * Hook to check if the current page is in single mode
8
9
  * Single mode is used for standalone windows in desktop app
10
+ * React Router version for SPA
9
11
  * @returns boolean indicating if the current page is in single mode
10
12
  */
11
13
  export const useIsSingleMode = (): boolean => {
@@ -16,7 +18,7 @@ export const useIsSingleMode = (): boolean => {
16
18
  setMounted(true);
17
19
  }, []);
18
20
 
19
- const searchParams = useSearchParams();
21
+ const [searchParams] = useSearchParams();
20
22
 
21
23
  useEffect(() => {
22
24
  if (mounted) {
@@ -1,7 +1,8 @@
1
- import { usePathname } from 'next/navigation';
1
+ import { usePathname } from '@/libs/router/navigation';
2
2
 
3
3
  /**
4
4
  * Returns true if the current path has a sub slug (`/chat/mobile` or `/chat/settings`)
5
+ * React Router version for SPA
5
6
  */
6
7
  export const useIsSubSlug = () => {
7
8
  const pathname = usePathname();
@@ -1,13 +1,13 @@
1
- import { useSearchParams } from 'next/navigation';
2
1
  import qs from 'query-string';
3
2
  import { useMemo } from 'react';
4
3
 
4
+ import { useSearchParams } from '@/libs/router/navigation';
5
+
5
6
  /**
6
7
  * Hook to get query parameters
7
- * This is the Next.js version
8
- * For React Router version, use useQuery from @/app/[variants]/(main)/hooks/useQuery
8
+ * React Router version for SPA
9
9
  */
10
10
  export const useQuery = () => {
11
- const rawQuery = useSearchParams();
12
- return useMemo(() => qs.parse(rawQuery.toString()), [rawQuery]);
11
+ const [searchParams] = useSearchParams();
12
+ return useMemo(() => qs.parse(searchParams.toString()), [searchParams]);
13
13
  };