@vibe-forge/client 0.11.3 → 1.0.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.
Files changed (200) hide show
  1. package/cli.cjs +6 -11
  2. package/dist/assets/{arc-h39NrT24.js → arc-CbOXL0l9.js} +1 -1
  3. package/dist/assets/{blockDiagram-c4efeb88-CaDg46I6.js → blockDiagram-c4efeb88-CqxINvsS.js} +1 -1
  4. package/dist/assets/{c4Diagram-c83219d4-CDqjcF9U.js → c4Diagram-c83219d4-BKazU0hb.js} +1 -1
  5. package/dist/assets/channel-Dnopc5A6.js +1 -0
  6. package/dist/assets/{classDiagram-beda092f-BDnZm8nO.js → classDiagram-beda092f-fAFX5BpB.js} +1 -1
  7. package/dist/assets/{classDiagram-v2-2358418a-BUi85KJW.js → classDiagram-v2-2358418a-w1VkNGJj.js} +1 -1
  8. package/dist/assets/clone-sQthahUA.js +1 -0
  9. package/dist/assets/{createText-1719965b-Ca5dEwfo.js → createText-1719965b-CEinakVP.js} +1 -1
  10. package/dist/assets/{cssMode-Ysz7NfYo.js → cssMode-DPqRki4y.js} +1 -1
  11. package/dist/assets/{edges-96097737-CdSKqxZt.js → edges-96097737-Cb0F1_3K.js} +1 -1
  12. package/dist/assets/{erDiagram-0228fc6a-B-veAUv_.js → erDiagram-0228fc6a-C-N2fx-J.js} +1 -1
  13. package/dist/assets/{flowDb-c6c81e3f-DD8Cx7_9.js → flowDb-c6c81e3f-D1Xz_8Gf.js} +1 -1
  14. package/dist/assets/{flowDiagram-50d868cf-9f-_x1ET.js → flowDiagram-50d868cf-DyPSZyAj.js} +1 -1
  15. package/dist/assets/flowDiagram-v2-4f6560a1-OazrdWQO.js +1 -0
  16. package/dist/assets/{flowchart-elk-definition-6af322e1-5RhpQM4M.js → flowchart-elk-definition-6af322e1-Dr1DDXwE.js} +1 -1
  17. package/dist/assets/{freemarker2-SgMdIXw4.js → freemarker2-C3DvPFaK.js} +1 -1
  18. package/dist/assets/{ganttDiagram-a2739b55-DnxNghZA.js → ganttDiagram-a2739b55-DmvY1GRj.js} +1 -1
  19. package/dist/assets/{gitGraphDiagram-82fe8481-CBvS3Tf9.js → gitGraphDiagram-82fe8481-CoXfPYYi.js} +1 -1
  20. package/dist/assets/{graph-CkHF299-.js → graph-BkDQy7Qt.js} +1 -1
  21. package/dist/assets/{handlebars-C57IyLUe.js → handlebars-BcTFdqjl.js} +1 -1
  22. package/dist/assets/{html-YsDy5wvW.js → html-Dg-O6XFr.js} +1 -1
  23. package/dist/assets/{htmlMode-7o_VDODD.js → htmlMode-B_wqYWvn.js} +1 -1
  24. package/dist/assets/{index-5325376f-BzOVQPu-.js → index-5325376f-kxPTR3_e.js} +1 -1
  25. package/dist/assets/index-o93dlo92.css +32 -0
  26. package/dist/assets/{index-BHFpctk6.js → index-wkhI4dr6.js} +357 -337
  27. package/dist/assets/{infoDiagram-8eee0895-DJ-UI1h4.js → infoDiagram-8eee0895-BEvqkwPI.js} +1 -1
  28. package/dist/assets/{javascript-BHQ9NEZr.js → javascript-DhlOH8_z.js} +1 -1
  29. package/dist/assets/{journeyDiagram-c64418c1-DwfykcG9.js → journeyDiagram-c64418c1-gKtLYmmp.js} +1 -1
  30. package/dist/assets/{jsonMode-3QjftkMM.js → jsonMode-DxTbF9OD.js} +1 -1
  31. package/dist/assets/{layout-CbViRb_b.js → layout-CDaZEk6E.js} +1 -1
  32. package/dist/assets/{line-DBdBvv9D.js → line-DNRQu8iq.js} +1 -1
  33. package/dist/assets/{linear-BDAfhcjn.js → linear-Cph9Z6_j.js} +1 -1
  34. package/dist/assets/{liquid-B0cPPzIR.js → liquid-ByZ6JgRG.js} +1 -1
  35. package/dist/assets/{lspLanguageFeatures-IOxbobOz.js → lspLanguageFeatures-DzvhkgnM.js} +1 -1
  36. package/dist/assets/{mdx-Dma_RA8P.js → mdx-D8RGHTl6.js} +1 -1
  37. package/dist/assets/{mermaid.core-Cvn8Go4x.js → mermaid.core-BgcryF__.js} +4 -4
  38. package/dist/assets/{mindmap-definition-8da855dc-DEnYq0Lc.js → mindmap-definition-8da855dc-WrxK0FcB.js} +1 -1
  39. package/dist/assets/{pieDiagram-a8764435-ZC4j8sHU.js → pieDiagram-a8764435-VsZBsiQy.js} +1 -1
  40. package/dist/assets/{python-Be0WX4q5.js → python-CXVtk_cg.js} +1 -1
  41. package/dist/assets/{quadrantDiagram-1e28029f-DUaqHlIB.js → quadrantDiagram-1e28029f-BVlgwOvU.js} +1 -1
  42. package/dist/assets/{razor-Tjhny-uT.js → razor-0tind7h2.js} +1 -1
  43. package/dist/assets/{requirementDiagram-08caed73-DjSal3es.js → requirementDiagram-08caed73-CpPMPoYp.js} +1 -1
  44. package/dist/assets/{sankeyDiagram-a04cb91d-BMDXMrMz.js → sankeyDiagram-a04cb91d-Cm5nnRmc.js} +1 -1
  45. package/dist/assets/{sequenceDiagram-c5b8d532-CQl9YUlH.js → sequenceDiagram-c5b8d532-DpMlJvJB.js} +1 -1
  46. package/dist/assets/{stateDiagram-1ecb1508-DG7mU9jD.js → stateDiagram-1ecb1508-DU1zc7vq.js} +1 -1
  47. package/dist/assets/{stateDiagram-v2-c2b004d7-DTbR_azy.js → stateDiagram-v2-c2b004d7-D-0RgmAp.js} +1 -1
  48. package/dist/assets/{styles-b4e223ce-C9aS3zb8.js → styles-b4e223ce-BSO-yNWV.js} +1 -1
  49. package/dist/assets/{styles-ca3715f6-Bh3keVTZ.js → styles-ca3715f6-CHnsn2Ro.js} +1 -1
  50. package/dist/assets/{styles-d45a18b0-BDcLLa65.js → styles-d45a18b0-B-rVGjEq.js} +1 -1
  51. package/dist/assets/{svgDrawCommon-b86b1483-B9H5ZS_9.js → svgDrawCommon-b86b1483-CA3Pl89f.js} +1 -1
  52. package/dist/assets/{timeline-definition-faaaa080-DCMYCBhK.js → timeline-definition-faaaa080-BcihLR6s.js} +1 -1
  53. package/dist/assets/{tsMode-DVqLsn98.js → tsMode-D9GGa5Ur.js} +1 -1
  54. package/dist/assets/{typescript-wMVyXw7G.js → typescript-BT9CK_EL.js} +1 -1
  55. package/dist/assets/{xml-w0gzmn0c.js → xml-DNO75J-T.js} +1 -1
  56. package/dist/assets/{xychartDiagram-f5964ef8-CdxyD3K5.js → xychartDiagram-f5964ef8-DJTwe32X.js} +1 -1
  57. package/dist/assets/{yaml-C29TL1ed.js → yaml-7CVzhiP2.js} +1 -1
  58. package/dist/index.html +2 -2
  59. package/package.json +13 -10
  60. package/src/api/git.ts +12 -0
  61. package/src/api/sessions.ts +61 -3
  62. package/src/api.ts +8 -0
  63. package/src/components/ArchiveView.scss +143 -54
  64. package/src/components/ArchiveView.tsx +181 -167
  65. package/src/components/CodeBlock.scss +5 -0
  66. package/src/components/ConfigView.scss +142 -31
  67. package/src/components/ConfigView.tsx +161 -86
  68. package/src/components/MarkdownContent.tsx +7 -0
  69. package/src/components/NavRail.scss +248 -0
  70. package/src/components/NavRail.tsx +80 -107
  71. package/src/components/NavRailCompact.tsx +107 -0
  72. package/src/components/NavRailCompactMoreSheet.tsx +141 -0
  73. package/src/components/ShortcutTooltip.tsx +4 -2
  74. package/src/components/Sidebar.scss +51 -0
  75. package/src/components/Sidebar.tsx +43 -16
  76. package/src/components/automation-view/RuleFormPanel.scss +40 -13
  77. package/src/components/automation-view/RuleSidebar.scss +73 -47
  78. package/src/components/automation-view/RuleSidebar.tsx +9 -13
  79. package/src/components/automation-view/RunHistoryPanel.scss +141 -13
  80. package/src/components/automation-view/RunHistoryPanel.tsx +203 -161
  81. package/src/components/automation-view/TaskList.scss +44 -13
  82. package/src/components/automation-view/TriggerList.scss +46 -14
  83. package/src/components/automation-view/index.scss +82 -10
  84. package/src/components/automation-view/index.tsx +108 -55
  85. package/src/components/benchmark-view/BenchmarkCasePanel.scss +36 -16
  86. package/src/components/benchmark-view/BenchmarkSidebar.scss +44 -22
  87. package/src/components/benchmark-view/BenchmarkSidebar.tsx +0 -6
  88. package/src/components/benchmark-view/BenchmarkView.scss +63 -20
  89. package/src/components/benchmark-view/index.tsx +71 -34
  90. package/src/components/chat/ChatComposerCard.scss +4 -0
  91. package/src/components/chat/ChatHeader.scss +187 -0
  92. package/src/components/chat/ChatHeader.tsx +206 -56
  93. package/src/components/chat/ChatHistoryView.tsx +63 -2
  94. package/src/components/chat/ChatTimelineView.scss +94 -1
  95. package/src/components/chat/ChatTimelineView.tsx +42 -0
  96. package/src/components/chat/NewSessionGuide.scss +139 -1
  97. package/src/components/chat/NewSessionGuide.tsx +57 -100
  98. package/src/components/chat/NewSessionGuideCompactPanel.tsx +130 -0
  99. package/src/components/chat/NewSessionGuideGrid.tsx +141 -0
  100. package/src/components/chat/git-controls/BranchSwitcherDropdown.tsx +61 -56
  101. package/src/components/chat/git-controls/BranchSwitcherResults.tsx +167 -0
  102. package/src/components/chat/git-controls/BranchTreeEntries.tsx +99 -0
  103. package/src/components/chat/git-controls/ChatGitControls.scss +437 -5
  104. package/src/components/chat/git-controls/ChatGitControls.tsx +136 -109
  105. package/src/components/chat/git-controls/DraftGitControls.tsx +91 -0
  106. package/src/components/chat/git-controls/GitOperationsDropdown.tsx +10 -2
  107. package/src/components/chat/git-controls/GitWorktreeDropdown.tsx +301 -28
  108. package/src/components/chat/git-controls/git-branch-tree.ts +148 -0
  109. package/src/components/chat/git-controls/use-chat-draft-git-controls.ts +168 -0
  110. package/src/components/chat/git-controls/use-chat-git-controls.ts +76 -3
  111. package/src/components/chat/messages/MessageContextMenu.tsx +3 -1
  112. package/src/components/chat/messages/MessageItem.scss +78 -4
  113. package/src/components/chat/messages/MessageItem.tsx +47 -3
  114. package/src/components/chat/sender/@components/adapter-select/AdapterSelectControl.scss +15 -0
  115. package/src/components/chat/sender/@components/reference-actions/ReferenceActionsControl.scss +17 -0
  116. package/src/components/chat/sender/@components/reference-actions/ReferencePermissionActionsPopover.tsx +4 -1
  117. package/src/components/chat/sender/@components/sender-attachments/SenderAttachments.scss +15 -2
  118. package/src/components/chat/sender/@components/sender-body/SenderBody.tsx +3 -0
  119. package/src/components/chat/sender/@components/sender-monaco-editor/use-sender-monaco-theme.ts +52 -3
  120. package/src/components/chat/sender/@components/sender-submit-action/SenderSubmitAction.scss +12 -0
  121. package/src/components/chat/sender/@components/sender-toolbar/SenderSelectBase.scss +21 -0
  122. package/src/components/chat/sender/@components/sender-toolbar/SenderSelectShared.scss +21 -0
  123. package/src/components/chat/sender/@components/sender-toolbar/SenderToolbar.scss +63 -0
  124. package/src/components/chat/sender/@core/get-sender-runtime-state.ts +1 -1
  125. package/src/components/chat/sender/@hooks/use-model-select-browser.tsx +4 -2
  126. package/src/components/chat/sender/@types/sender-props.ts +1 -0
  127. package/src/components/chat/sender/Sender.scss +1 -1
  128. package/src/components/chat/sender/Sender.tsx +1 -0
  129. package/src/components/chat/session-timeline-panel/EventList.scss +88 -0
  130. package/src/components/chat/session-timeline-panel/EventList.tsx +99 -47
  131. package/src/components/chat/session-timeline-panel/gantt.ts +23 -7
  132. package/src/components/chat/session-timeline-panel/git-graph.ts +6 -1
  133. package/src/components/chat/session-timeline-panel/index.scss +14 -1
  134. package/src/components/chat/session-timeline-panel/index.tsx +86 -10
  135. package/src/components/chat/session-timeline-panel/types.ts +4 -0
  136. package/src/components/chat/status-bar/ChatStatusBar.scss +27 -0
  137. package/src/components/chat/status-bar/ChatStatusBar.tsx +39 -0
  138. package/src/components/chat/terminal/ChatTerminalView.tsx +6 -0
  139. package/src/components/chat/tools/core/ToolCallBox.scss +19 -0
  140. package/src/components/chat/tools/core/ToolGroup.scss +32 -0
  141. package/src/components/chat/tools/task/components/TaskToolCard.scss +59 -1
  142. package/src/components/config/ConfigEditors.scss +20 -6
  143. package/src/components/config/ConfigFieldRow.scss +57 -17
  144. package/src/components/config/ConfigSectionForm.scss +10 -4
  145. package/src/components/config/ConfigSectionPanel.tsx +18 -11
  146. package/src/components/config/configSchema.ts +1 -0
  147. package/src/components/config/record-editors/RecordEditors.scss +42 -9
  148. package/src/components/dock-panel/DockPanel.scss +6 -2
  149. package/src/components/dock-panel/DockPanel.tsx +12 -16
  150. package/src/components/knowledge-base/KnowledgeBaseView.scss +180 -6
  151. package/src/components/knowledge-base/KnowledgeBaseView.tsx +98 -26
  152. package/src/components/knowledge-base/components/ActionButton.scss +4 -0
  153. package/src/components/knowledge-base/components/EmptyState.scss +5 -8
  154. package/src/components/knowledge-base/components/EntitiesTab.tsx +8 -2
  155. package/src/components/knowledge-base/components/EntityItem.scss +10 -3
  156. package/src/components/knowledge-base/components/FilterBar.scss +13 -2
  157. package/src/components/knowledge-base/components/FlowsTab.tsx +8 -2
  158. package/src/components/knowledge-base/components/KnowledgeBaseHeader.scss +2 -23
  159. package/src/components/knowledge-base/components/KnowledgeBaseHeader.tsx +0 -5
  160. package/src/components/knowledge-base/components/KnowledgeList.scss +15 -6
  161. package/src/components/knowledge-base/components/LoadingState.scss +4 -0
  162. package/src/components/knowledge-base/components/RuleItem.scss +86 -0
  163. package/src/components/knowledge-base/components/RuleItem.tsx +2 -0
  164. package/src/components/knowledge-base/components/RulesTab.tsx +8 -2
  165. package/src/components/knowledge-base/components/SectionHeader.scss +3 -18
  166. package/src/components/knowledge-base/components/SectionHeader.tsx +3 -7
  167. package/src/components/knowledge-base/components/SkillsTab.tsx +8 -3
  168. package/src/components/knowledge-base/components/SpecItem.scss +16 -7
  169. package/src/components/layout/@hooks/use-mobile-sidebar-modal.ts +190 -0
  170. package/src/components/layout/AppShell.scss +106 -6
  171. package/src/components/layout/AppShell.tsx +118 -10
  172. package/src/components/layout/PageShell.scss +41 -0
  173. package/src/components/layout/PageShell.tsx +32 -0
  174. package/src/components/layout/mobile-sidebar-constants.ts +1 -0
  175. package/src/components/nav-rail-compact-config.ts +114 -0
  176. package/src/components/nav-rail-items.tsx +181 -0
  177. package/src/components/sidebar/SessionContextMenu.tsx +3 -1
  178. package/src/components/sidebar/SessionItem.scss +62 -0
  179. package/src/components/sidebar/SessionItem.tsx +97 -52
  180. package/src/components/sidebar/SessionList.tsx +6 -0
  181. package/src/components/sidebar/SidebarHeader.scss +49 -0
  182. package/src/components/sidebar/SidebarHeader.tsx +27 -5
  183. package/src/components/sidebar/SidebarHeaderBatchActions.tsx +8 -4
  184. package/src/components/sidebar/SidebarHeaderSearchActions.tsx +6 -3
  185. package/src/components/sidebar/SidebarUtilityFooter.tsx +69 -0
  186. package/src/components/workspace/ContextFilePicker.tsx +12 -4
  187. package/src/hooks/chat/chat-session-workspace-draft.ts +25 -0
  188. package/src/hooks/chat/use-chat-scroll.ts +24 -7
  189. package/src/hooks/chat/use-chat-session-actions.ts +19 -2
  190. package/src/hooks/use-responsive-layout.ts +115 -0
  191. package/src/resources/adapters.ts +15 -0
  192. package/src/resources/locales/en.json +52 -0
  193. package/src/resources/locales/zh.json +52 -0
  194. package/src/routes/ChatRoute.scss +113 -14
  195. package/src/routes/ChatRoute.tsx +29 -35
  196. package/src/store/index.ts +2 -0
  197. package/dist/assets/channel-CBULQbJz.js +0 -1
  198. package/dist/assets/clone-dkS7LczW.js +0 -1
  199. package/dist/assets/flowDiagram-v2-4f6560a1-1miffU4x.js +0 -1
  200. package/dist/assets/index-D_XqxIvp.css +0 -32
@@ -6,16 +6,22 @@ import dayjs from 'dayjs'
6
6
  import React, { useMemo, useState } from 'react'
7
7
  import { useTranslation } from 'react-i18next'
8
8
  import useSWR from 'swr'
9
+
10
+ import { PageShell } from '#~/components/layout/PageShell'
11
+ import { useResponsiveLayout } from '#~/hooks/use-responsive-layout'
12
+
9
13
  import { deleteSession, getApiErrorMessage, listSessions, updateSession } from '../api'
10
14
 
11
15
  export function ArchiveView() {
12
16
  const { t } = useTranslation()
13
17
  const { message } = App.useApp()
18
+ const { isCompactLayout, isTouchInteraction } = useResponsiveLayout()
14
19
  const { data: sessionsRes, mutate } = useSWR<{ sessions: Session[] }>(
15
20
  '/api/sessions/archived',
16
21
  async () => listSessions('archived')
17
22
  )
18
23
  const sessions: Session[] = sessionsRes?.sessions ?? []
24
+ const isCompactView = isCompactLayout || isTouchInteraction
19
25
 
20
26
  const [searchQuery, setSearchQuery] = useState('')
21
27
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set())
@@ -99,109 +105,105 @@ export function ArchiveView() {
99
105
  const isAllSelected = filteredSessions.length > 0 && selectedIds.size === filteredSessions.length
100
106
 
101
107
  return (
102
- <div className='archive-view'>
103
- <div className='archive-view__header'>
104
- <Space size={8} className='archive-view__title'>
105
- <h2 className='archive-view__title-text'>{t('common.archivedSessions')}</h2>
106
- </Space>
107
-
108
- <Space>
109
- {isBatchMode
110
- ? (
111
- <>
112
- <span className='archive-view__batch-info'>
113
- {t('common.selectedCount', { count: selectedIds.size })}
114
- </span>
115
- <Tooltip title={t('common.cancel')}>
116
- <Button
117
- icon={
118
- <span className='material-symbols-rounded archive-view__action-icon'>
119
- close
120
- </span>
121
- }
122
- onClick={() => {
123
- setIsBatchMode(false)
124
- setSelectedIds(new Set())
125
- }}
126
- className='archive-view__icon-button'
127
- />
128
- </Tooltip>
129
- <Tooltip title={t('common.batchRestore')}>
130
- <Button
131
- type='primary'
132
- icon={
133
- <span className='material-symbols-rounded archive-view__action-icon'>
134
- unarchive
135
- </span>
136
- }
137
- onClick={() => {
138
- void handleBatchRestore()
139
- }}
140
- disabled={selectedIds.size === 0}
141
- className='archive-view__icon-button'
142
- />
143
- </Tooltip>
144
- <Popconfirm
145
- title={t('common.deleteConfirm', { count: selectedIds.size })}
146
- onConfirm={() => {
147
- void handleBatchDelete()
148
- }}
149
- disabled={selectedIds.size === 0}
150
- >
151
- <Tooltip title={t('common.batchDelete')}>
108
+ <PageShell
109
+ className={`archive-view ${isCompactView ? 'archive-view--compact' : ''}`}
110
+ header={
111
+ <div className='archive-view__toolbar'>
112
+ {isBatchMode && (
113
+ <div className='archive-view__select-all'>
114
+ <Tooltip title={isAllSelected ? t('common.deselectAll') : t('common.selectAll')}>
115
+ <Checkbox
116
+ checked={isAllSelected}
117
+ indeterminate={selectedIds.size > 0 && selectedIds.size < filteredSessions.length}
118
+ onChange={(e) => handleSelectAll(e.target.checked)}
119
+ />
120
+ </Tooltip>
121
+ </div>
122
+ )}
123
+ <Input
124
+ prefix={<span className='material-symbols-rounded archive-view__search-icon'>search</span>}
125
+ placeholder={t('common.search')}
126
+ value={searchQuery}
127
+ onChange={e => setSearchQuery(e.target.value)}
128
+ allowClear
129
+ className='archive-view__search-input'
130
+ />
131
+ <Space size={6} className='archive-view__toolbar-actions'>
132
+ {isBatchMode
133
+ ? (
134
+ <>
135
+ <span className='archive-view__batch-info'>
136
+ {t('common.selectedCount', { count: selectedIds.size })}
137
+ </span>
138
+ <Tooltip title={t('common.cancel')}>
139
+ <Button
140
+ icon={
141
+ <span className='material-symbols-rounded archive-view__action-icon'>
142
+ close
143
+ </span>
144
+ }
145
+ onClick={() => {
146
+ setIsBatchMode(false)
147
+ setSelectedIds(new Set())
148
+ }}
149
+ className='archive-view__icon-button'
150
+ />
151
+ </Tooltip>
152
+ <Tooltip title={t('common.batchRestore')}>
152
153
  <Button
153
- danger
154
+ type='primary'
154
155
  icon={
155
156
  <span className='material-symbols-rounded archive-view__action-icon'>
156
- delete_sweep
157
+ unarchive
157
158
  </span>
158
159
  }
160
+ onClick={() => {
161
+ void handleBatchRestore()
162
+ }}
159
163
  disabled={selectedIds.size === 0}
160
164
  className='archive-view__icon-button'
161
165
  />
162
166
  </Tooltip>
163
- </Popconfirm>
164
- </>
165
- )
166
- : (
167
- <Tooltip title={t('common.batchMode')}>
168
- <Button
169
- icon={
170
- <span className='material-symbols-rounded archive-view__action-icon'>
171
- checklist
172
- </span>
173
- }
174
- onClick={() => setIsBatchMode(true)}
175
- disabled={sessions.length === 0}
176
- className='archive-view__icon-button'
177
- />
178
- </Tooltip>
179
- )}
180
- </Space>
181
- </div>
182
-
183
- <div className='archive-view__filter-bar'>
184
- {isBatchMode && (
185
- <div className='archive-view__select-all'>
186
- <Tooltip title={isAllSelected ? t('common.deselectAll') : t('common.selectAll')}>
187
- <Checkbox
188
- checked={isAllSelected}
189
- indeterminate={selectedIds.size > 0 && selectedIds.size < filteredSessions.length}
190
- onChange={(e) => handleSelectAll(e.target.checked)}
191
- />
192
- </Tooltip>
193
- </div>
194
- )}
195
- <Input
196
- prefix={<span className='material-symbols-rounded archive-view__search-icon'>search</span>}
197
- placeholder={t('common.search')}
198
- value={searchQuery}
199
- onChange={e => setSearchQuery(e.target.value)}
200
- allowClear
201
- className='archive-view__search-input'
202
- />
203
- </div>
204
-
167
+ <Popconfirm
168
+ title={t('common.deleteConfirm', { count: selectedIds.size })}
169
+ onConfirm={() => {
170
+ void handleBatchDelete()
171
+ }}
172
+ disabled={selectedIds.size === 0}
173
+ >
174
+ <Tooltip title={t('common.batchDelete')}>
175
+ <Button
176
+ danger
177
+ icon={
178
+ <span className='material-symbols-rounded archive-view__action-icon'>
179
+ delete_sweep
180
+ </span>
181
+ }
182
+ disabled={selectedIds.size === 0}
183
+ className='archive-view__icon-button'
184
+ />
185
+ </Tooltip>
186
+ </Popconfirm>
187
+ </>
188
+ )
189
+ : (
190
+ <Tooltip title={t('common.batchMode')}>
191
+ <Button
192
+ icon={
193
+ <span className='material-symbols-rounded archive-view__action-icon'>
194
+ checklist
195
+ </span>
196
+ }
197
+ onClick={() => setIsBatchMode(true)}
198
+ disabled={sessions.length === 0}
199
+ className='archive-view__icon-button'
200
+ />
201
+ </Tooltip>
202
+ )}
203
+ </Space>
204
+ </div>
205
+ }
206
+ >
205
207
  <div className='archive-view__list'>
206
208
  {filteredSessions.length === 0
207
209
  ? (
@@ -214,86 +216,98 @@ export function ArchiveView() {
214
216
  <List
215
217
  itemLayout='horizontal'
216
218
  dataSource={filteredSessions}
217
- renderItem={(session) => (
218
- <List.Item
219
- className={[
220
- 'archive-view__item',
221
- selectedIds.has(session.id) ? 'archive-view__item--selected' : '',
222
- isBatchMode ? 'archive-view__item--batch' : ''
223
- ].filter(Boolean).join(' ')}
224
- onClick={() => isBatchMode && handleToggleSelect(session.id)}
225
- >
226
- <div className='archive-view__item-row'>
227
- {isBatchMode && (
228
- <div className='archive-view__item-select'>
229
- <Checkbox
230
- checked={selectedIds.has(session.id)}
231
- onChange={() => handleToggleSelect(session.id)}
232
- onClick={(e) => e.stopPropagation()}
233
- />
234
- </div>
235
- )}
236
- <span className='material-symbols-rounded archive-view__item-icon'>
237
- chat_bubble
238
- </span>
239
- <div className='archive-view__item-main'>
240
- <span className='archive-view__item-title'>
241
- {(session.title != null && session.title !== '')
242
- ? session.title
243
- : (session.lastMessage != null && session.lastMessage !== '')
244
- ? session.lastMessage
245
- : t('common.newChat')}
246
- </span>
247
- {session.tags && session.tags.length > 0 && (
248
- <div className='archive-view__item-tags'>
249
- {session.tags.map((tag: string) => (
250
- <Tag key={tag} className='archive-view__item-tag'>{tag}</Tag>
251
- ))}
219
+ renderItem={(session) => {
220
+ const displayTitle = (session.title != null && session.title !== '')
221
+ ? session.title
222
+ : (session.lastMessage != null && session.lastMessage !== '')
223
+ ? session.lastMessage
224
+ : t('common.newChat')
225
+ const sessionTags = session.tags ?? []
226
+ const visibleTags = isCompactView ? sessionTags.slice(0, 1) : sessionTags
227
+ const hiddenTagCount = Math.max(sessionTags.length - visibleTags.length, 0)
228
+
229
+ return (
230
+ <List.Item
231
+ className={[
232
+ 'archive-view__item',
233
+ selectedIds.has(session.id) ? 'archive-view__item--selected' : '',
234
+ isBatchMode ? 'archive-view__item--batch' : ''
235
+ ].filter(Boolean).join(' ')}
236
+ onClick={() => isBatchMode && handleToggleSelect(session.id)}
237
+ >
238
+ <div className='archive-view__item-row'>
239
+ {isBatchMode && (
240
+ <div className='archive-view__item-select'>
241
+ <Checkbox
242
+ checked={selectedIds.has(session.id)}
243
+ onChange={() => handleToggleSelect(session.id)}
244
+ onClick={(e) => e.stopPropagation()}
245
+ />
252
246
  </div>
253
247
  )}
254
- <span className='archive-view__item-time'>
255
- {dayjs(session.createdAt).format('YYYY-MM-DD HH:mm')}
248
+ <span className='material-symbols-rounded archive-view__item-icon'>
249
+ chat_bubble
256
250
  </span>
257
- </div>
251
+ <div className='archive-view__item-main'>
252
+ <span className='archive-view__item-title'>{displayTitle}</span>
253
+ <div className='archive-view__item-meta'>
254
+ {visibleTags.length > 0 && (
255
+ <div className='archive-view__item-tags'>
256
+ {visibleTags.map((tag: string) => (
257
+ <Tag key={tag} className='archive-view__item-tag'>{tag}</Tag>
258
+ ))}
259
+ {hiddenTagCount > 0 && (
260
+ <span className='archive-view__item-tag-count'>+{hiddenTagCount}</span>
261
+ )}
262
+ </div>
263
+ )}
264
+ <span className='archive-view__item-time'>
265
+ {dayjs(session.createdAt).format('YYYY-MM-DD HH:mm')}
266
+ </span>
267
+ </div>
268
+ </div>
258
269
 
259
- {!isBatchMode && (
260
- <div className='archive-view__item-actions'>
261
- <Tooltip title={t('common.restore')}>
262
- <Button
263
- type='text'
264
- size='small'
265
- className='archive-view__item-action-button'
266
- icon={<span className='material-symbols-rounded archive-view__action-icon'>unarchive</span>}
267
- onClick={(e) => {
268
- e.stopPropagation()
269
- void handleRestore(session.id)
270
+ {!isBatchMode && (
271
+ <div className='archive-view__item-actions'>
272
+ <Tooltip title={t('common.restore')}>
273
+ <Button
274
+ type='text'
275
+ size='small'
276
+ className='archive-view__item-action-button'
277
+ icon={
278
+ <span className='material-symbols-rounded archive-view__action-icon'>unarchive</span>
279
+ }
280
+ onClick={(e) => {
281
+ e.stopPropagation()
282
+ void handleRestore(session.id)
283
+ }}
284
+ />
285
+ </Tooltip>
286
+ <Popconfirm
287
+ title={t('common.deleteSessionConfirm')}
288
+ onConfirm={(e) => {
289
+ e?.stopPropagation()
290
+ void handleDelete(session.id)
270
291
  }}
271
- />
272
- </Tooltip>
273
- <Popconfirm
274
- title={t('common.deleteSessionConfirm')}
275
- onConfirm={(e) => {
276
- e?.stopPropagation()
277
- void handleDelete(session.id)
278
- }}
279
- >
280
- <Button
281
- type='text'
282
- size='small'
283
- danger
284
- className='archive-view__item-action-button'
285
- icon={<span className='material-symbols-rounded archive-view__action-icon'>delete</span>}
286
- onClick={(e) => e.stopPropagation()}
287
- />
288
- </Popconfirm>
289
- </div>
290
- )}
291
- </div>
292
- </List.Item>
293
- )}
292
+ >
293
+ <Button
294
+ type='text'
295
+ size='small'
296
+ danger
297
+ className='archive-view__item-action-button'
298
+ icon={<span className='material-symbols-rounded archive-view__action-icon'>delete</span>}
299
+ onClick={(e) => e.stopPropagation()}
300
+ />
301
+ </Popconfirm>
302
+ </div>
303
+ )}
304
+ </div>
305
+ </List.Item>
306
+ )
307
+ }}
294
308
  />
295
309
  )}
296
310
  </div>
297
- </div>
311
+ </PageShell>
298
312
  )
299
313
  }
@@ -44,6 +44,9 @@
44
44
  display: flex;
45
45
  align-items: center;
46
46
  justify-content: center;
47
+ width: 24px;
48
+ min-width: 24px;
49
+ height: 24px;
47
50
  padding: 4px;
48
51
  border: none;
49
52
  background: transparent;
@@ -59,6 +62,8 @@
59
62
 
60
63
  .material-symbols-rounded {
61
64
  font-size: 16px;
65
+ font-family: 'Material Symbols Rounded';
66
+ line-height: 1;
62
67
  }
63
68
  }
64
69
  }