@jetcrab/pi-desk 1.1.22-dev → 1.1.24-dev
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/docs/commands.md +4 -2
- package/docs/plugins.md +2 -0
- package/package.json +1 -1
- package/src/client/l2_biz/project-preview/l2-project-preview-dialog.tsx +1 -1
- package/src/client/l2_biz/project-preview/l2-project-preview-page.tsx +1 -1
- package/src/client/l2_biz/project-preview/l2-project-preview.tsx +28 -34
- package/src/client/l3_modules/project-files/l3-project-document-view.tsx +162 -151
- package/src/client/l3_modules/project-files/l3-project-file-browser.module.css +30 -0
- package/src/client/l3_modules/project-files/l3-project-file-browser.tsx +137 -111
- package/src/client/l3_modules/project-files/l3-project-file-tabs.tsx +26 -6
- package/src/client/l3_modules/project-files/views/l3-project-search-controls.tsx +118 -123
- package/src/client/l3_modules/project-files/views/l3-project-search-results.tsx +29 -25
- package/src/server/l1_entry/api/l1-plugin-management-route.ts +0 -4
- package/src/server/l2_biz/plugin-management/l2-plugin-management.ts +4 -37
- package/src/server/l2_biz/plugin-management/l2-plugin-updates.ts +1 -4
- package/src/server/l2_biz/work-session/l2-work-session-chat-runtime.ts +4 -2
- package/src/server/l4_foundation/pi/l4-pi-chat-worker.ts +16 -1
- package/src/server/l4_foundation/pi/l4-pi-package-root-consistency.ts +3 -6
- package/src/server/l4_foundation/pi/l4-pi-package-root-gate.ts +1 -1
- package/src/server/l4_foundation/pi/l4-pi-plugin-owner-runtime.ts +4 -0
- package/src/server/l4_foundation/pi/l4-pi-plugin-sources.ts +5 -1
- package/src/server/l4_foundation/pi/l4-pi-session-initialization.ts +30 -34
- package/src/server/l4_foundation/pi/l4-pi-session-resources.ts +15 -14
- package/src/server/l4_foundation/pi/l4-pi-work-session-runtime.ts +1 -1
- package/src/server/l4_foundation/skills/runtime/l4-skill-catalog.ts +159 -166
- package/temp/build/pi-desk/release/.next/BUILD_ID +1 -1
- package/temp/build/pi-desk/release/.next/build-manifest.json +3 -3
- package/temp/build/pi-desk/release/.next/required-server-files.js +2 -2
- package/temp/build/pi-desk/release/.next/required-server-files.json +2 -2
- package/temp/build/pi-desk/release/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.html +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/health/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/add/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/apply/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/batch/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/del/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/enabled-set/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/list/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/reload/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/plugins/update/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/page.js +2 -2
- package/temp/build/pi-desk/release/.next/server/app/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/project-preview/page.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/project-preview/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/16438.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/18748.js +1 -0
- package/temp/build/pi-desk/release/.next/server/chunks/20460.js +2 -2
- package/temp/build/pi-desk/release/.next/server/chunks/24557.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/25406.js +13 -14
- package/temp/build/pi-desk/release/.next/server/chunks/36361.js +2 -2
- package/temp/build/pi-desk/release/.next/server/chunks/50520.js +2 -2
- package/temp/build/pi-desk/release/.next/server/chunks/6917.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/80290.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/92386.js +15 -16
- package/temp/build/pi-desk/release/.next/server/instrumentation.js +1 -1
- package/temp/build/pi-desk/release/.next/server/middleware-build-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/pages/500.html +1 -1
- package/temp/build/pi-desk/release/.next/static/chunks/9038-05fd2688407b39c1.js +15 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/{page-e8a5274c115f528d.js → page-ff44dcf27c2ba1c2.js} +2 -2
- package/temp/build/pi-desk/release/.next/static/chunks/app/project-preview/{page-d70ee4e9409b970a.js → page-bc18765121950e65.js} +1 -1
- package/temp/build/pi-desk/release/.next/static/chunks/{webpack-b60891a214e0925d.js → webpack-48eecbb66781c006.js} +1 -1
- package/temp/build/pi-desk/release/.next/static/css/10e063cfb3cda7bd.css +1 -0
- package/temp/build/pi-desk/release/.next/static/css/2c3b0c0ff1f49c68.css +1 -0
- package/temp/build/pi-desk/release/.next/trace-build +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/93049.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/9038-03144ed96d613f75.js +0 -15
- package/temp/build/pi-desk/release/.next/static/css/6dbae2922f88ca31.css +0 -1
- package/temp/build/pi-desk/release/.next/static/css/f646ca6c07245c4c.css +0 -1
- /package/temp/build/pi-desk/release/.next/static/{MV6_lBt7Mzmi1rBNI-3dx → w3CeIboVupqJdq890TlcG}/_buildManifest.js +0 -0
- /package/temp/build/pi-desk/release/.next/static/{MV6_lBt7Mzmi1rBNI-3dx → w3CeIboVupqJdq890TlcG}/_ssgManifest.js +0 -0
package/docs/commands.md
CHANGED
|
@@ -71,6 +71,8 @@
|
|
|
71
71
|
|
|
72
72
|
接纳后结束当前轮;宿主等本会话完全空闲后重载,再通知并唤醒本会话。重载可能重建插件内存状态、使缓存失效,配置和工具声明变化也可能影响提示词缓存。
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
插件管理最多等待目标来源的在途调用 15 秒;超过时仅该项维护失败,可稍后手动重试,不冻结常规聊天或阻止后续其他来源维护。完成通知表示包和宿主能力已应用;新建会话使用最新工具配置,已有原生 Pi 会话不自动重载。Node/Browser 替换会重新挂载目标插件界面,旧调用可能失效;结果未知的副作用请求不自动重发。
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
维护期间或失败后允许目标包暂时缺失。会话跳过缺失或版本不符的包,明确的单插件加载/启动错误在插件管理中保留诊断,不因此让其他正常插件一起降级。聊天订阅、刷新和重连不等待包维护或插件初始化;未就绪的模型与插件状态稍后同步。修复包后按需重载目标会话,不自动重载已有会话。
|
|
77
|
+
|
|
78
|
+
需要重启时按插件管理界面的维护流程处理,只延后受影响来源,以最终结果为准。
|
package/docs/plugins.md
CHANGED
|
@@ -339,4 +339,6 @@ try {
|
|
|
339
339
|
|
|
340
340
|
## 更新生效
|
|
341
341
|
|
|
342
|
+
包维护不阻塞聊天订阅、刷新或其他会话。缺失或版本不符的包会被跳过,导入/工厂失败的入口不加载;Pi 生命周期回调和插件 Provider 注册的明确错误保留在插件管理诊断中,不升级为整会话失败。正常扩展继续加载。此隔离不终止同步死循环,也不回滚插件已发生的外部副作用;整体初始化超时仍可能使当前会话回退基础聊天,不阻塞其他会话的历史同步。
|
|
343
|
+
|
|
342
344
|
`plugins install/reload` 应用 Node/Browser 能力;目标插件活动视图重挂,旧 Browser Owner 失效。现有 Native 会话不自动重载,新 UI 可能连接旧会话方法,需兼容既有消息和方法数据;需要现有会话加载当前原生代码时使用 `session reload`。热加载无法处理的资源按宿主已有重启流程处理,不把重新挂载界面当作后端任务已停止。
|
package/package.json
CHANGED
|
@@ -45,7 +45,7 @@ export function L2ProjectPreviewPage({
|
|
|
45
45
|
refreshOnFocus={false}
|
|
46
46
|
onUnauthorized={onUnauthorized}
|
|
47
47
|
actions={
|
|
48
|
-
<Button size="sm" variant="
|
|
48
|
+
<Button size="sm" variant="ghost" onClick={() => onSelect(null)}>
|
|
49
49
|
<FolderOpenIcon className="size-4" />
|
|
50
50
|
<span>{t('switchProject')}</span>
|
|
51
51
|
</Button>
|
|
@@ -78,6 +78,7 @@ export function L2ProjectPreview({
|
|
|
78
78
|
<L3ProjectFileBrowser
|
|
79
79
|
cwd={cwd}
|
|
80
80
|
projectName={projectName}
|
|
81
|
+
showRootTitle={false}
|
|
81
82
|
runtime={files}
|
|
82
83
|
gitRuntime={git}
|
|
83
84
|
onOpenGitBranches={openGit}
|
|
@@ -85,25 +86,26 @@ export function L2ProjectPreview({
|
|
|
85
86
|
/>
|
|
86
87
|
)
|
|
87
88
|
const code = (
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
89
|
+
<L3ProjectDocumentView
|
|
90
|
+
runtime={files}
|
|
91
|
+
gitRuntime={git}
|
|
92
|
+
compact={width < 1100}
|
|
93
|
+
refreshOnFocus={refreshOnFocus}
|
|
94
|
+
onEscape={onEscape}
|
|
95
|
+
renderHeader={(actions) => (
|
|
96
|
+
<L3ProjectFileTabs
|
|
97
|
+
cwd={cwd}
|
|
98
|
+
gitRuntime={git}
|
|
99
|
+
paths={state.tabs}
|
|
100
|
+
activePath={state.activePath}
|
|
101
|
+
diffPath={diffPath}
|
|
102
|
+
mobile={narrow}
|
|
103
|
+
actions={actions}
|
|
104
|
+
onActivate={(path) => files.openFile(path)}
|
|
105
|
+
onClose={(path, scope) => files.closeTabs(path, scope)}
|
|
106
|
+
/>
|
|
107
|
+
)}
|
|
108
|
+
/>
|
|
107
109
|
)
|
|
108
110
|
const gitView = (
|
|
109
111
|
<div className="flex size-full min-h-0 min-w-0 flex-col">
|
|
@@ -226,7 +228,7 @@ export function L2ProjectPreview({
|
|
|
226
228
|
className="flex size-full min-h-0 min-w-0 flex-col overflow-hidden"
|
|
227
229
|
data-testid="project-preview"
|
|
228
230
|
>
|
|
229
|
-
<header className="flex min-h-
|
|
231
|
+
<header className="flex min-h-9 shrink-0 items-center gap-1 bg-muted px-2 py-1 pt-[max(4px,env(safe-area-inset-top))]">
|
|
230
232
|
{!stacked ? (
|
|
231
233
|
<Button
|
|
232
234
|
size="icon-sm"
|
|
@@ -241,15 +243,11 @@ export function L2ProjectPreview({
|
|
|
241
243
|
)}
|
|
242
244
|
</Button>
|
|
243
245
|
) : null}
|
|
244
|
-
<div className="min-w-0 flex-1">
|
|
245
|
-
|
|
246
|
-
<h1 className="truncate text-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
)}
|
|
250
|
-
<p className="truncate text-xs text-muted-foreground" title={cwd}>
|
|
251
|
-
{cwd}
|
|
252
|
-
</p>
|
|
246
|
+
<div className="flex min-w-0 flex-1 items-baseline gap-3" title={cwd}>
|
|
247
|
+
<div className="min-w-0 shrink-0 max-w-[50%] max-sm:max-w-full max-sm:shrink">
|
|
248
|
+
{title ?? <h1 className="truncate text-sm font-semibold">{projectName}</h1>}
|
|
249
|
+
</div>
|
|
250
|
+
<p className="min-w-0 truncate text-xs text-muted-foreground max-sm:hidden">{cwd}</p>
|
|
253
251
|
</div>
|
|
254
252
|
<Button
|
|
255
253
|
size="sm"
|
|
@@ -272,11 +270,7 @@ export function L2ProjectPreview({
|
|
|
272
270
|
) : null}
|
|
273
271
|
{stacked ? (
|
|
274
272
|
<>
|
|
275
|
-
<div
|
|
276
|
-
className="flex shrink-0 gap-1 border-b px-2 py-1"
|
|
277
|
-
role="group"
|
|
278
|
-
aria-label={t('previewArea')}
|
|
279
|
-
>
|
|
273
|
+
<div className="flex shrink-0 gap-1 px-2 py-1" role="group" aria-label={t('previewArea')}>
|
|
280
274
|
<Button
|
|
281
275
|
size="sm"
|
|
282
276
|
variant={page === 'files' ? 'secondary' : 'ghost'}
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
useRef,
|
|
20
20
|
useState,
|
|
21
21
|
useSyncExternalStore,
|
|
22
|
+
type ReactNode,
|
|
22
23
|
type Ref
|
|
23
24
|
} from 'react'
|
|
24
25
|
import { useTranslation } from 'react-i18next'
|
|
@@ -55,7 +56,8 @@ export function L3ProjectDocumentView({
|
|
|
55
56
|
visible = true,
|
|
56
57
|
refreshOnFocus = true,
|
|
57
58
|
onEscape,
|
|
58
|
-
onSwitchPane
|
|
59
|
+
onSwitchPane,
|
|
60
|
+
renderHeader
|
|
59
61
|
}: {
|
|
60
62
|
ref?: Ref<L3ProjectDocumentHandle>
|
|
61
63
|
runtime: L3ProjectFileRuntime
|
|
@@ -65,6 +67,7 @@ export function L3ProjectDocumentView({
|
|
|
65
67
|
refreshOnFocus?: boolean
|
|
66
68
|
onEscape: () => void
|
|
67
69
|
onSwitchPane?: () => void
|
|
70
|
+
renderHeader?: (actions: ReactNode) => ReactNode
|
|
68
71
|
}): React.JSX.Element {
|
|
69
72
|
const { t } = useTranslation('projectFiles')
|
|
70
73
|
const { wrapLines, diffViewMode, collapseUnchanged } = useL4CodePreferences()
|
|
@@ -149,6 +152,160 @@ export function L3ProjectDocumentView({
|
|
|
149
152
|
else toast.error(t('copyContentFailed'))
|
|
150
153
|
})
|
|
151
154
|
}
|
|
155
|
+
const actions =
|
|
156
|
+
activeDiff || activePath ? (
|
|
157
|
+
<>
|
|
158
|
+
{activeDiff ? (
|
|
159
|
+
<>
|
|
160
|
+
<span className="mr-auto shrink-0 px-1 text-xs text-muted-foreground">
|
|
161
|
+
{activeDiff.label ?? t('headToWorking')}
|
|
162
|
+
{activeDiff.status === 'text' &&
|
|
163
|
+
activeDiff.original.content === activeDiff.modified.content
|
|
164
|
+
? t('noDiffChanges')
|
|
165
|
+
: ''}
|
|
166
|
+
</span>
|
|
167
|
+
<L3CodeSurfaceToolbarButton
|
|
168
|
+
label={t('previousChange')}
|
|
169
|
+
onClick={() => diffRef.current?.previousChange()}
|
|
170
|
+
>
|
|
171
|
+
<ArrowUpIcon className="size-4" />
|
|
172
|
+
</L3CodeSurfaceToolbarButton>
|
|
173
|
+
<L3CodeSurfaceToolbarButton
|
|
174
|
+
label={t('nextChange')}
|
|
175
|
+
onClick={() => diffRef.current?.nextChange()}
|
|
176
|
+
>
|
|
177
|
+
<ArrowDownIcon className="size-4" />
|
|
178
|
+
</L3CodeSurfaceToolbarButton>
|
|
179
|
+
{!compact ? (
|
|
180
|
+
<L3CodeSurfaceToolbarButton
|
|
181
|
+
label={diffViewMode === 'side-by-side' ? t('inlineDiff') : t('sideBySideDiff')}
|
|
182
|
+
active={diffViewMode === 'inline'}
|
|
183
|
+
onClick={() =>
|
|
184
|
+
runtime.setDiffViewMode(
|
|
185
|
+
diffViewMode === 'side-by-side' ? 'inline' : 'side-by-side'
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
>
|
|
189
|
+
<Columns2Icon className="size-4" />
|
|
190
|
+
</L3CodeSurfaceToolbarButton>
|
|
191
|
+
) : null}
|
|
192
|
+
<L3CodeSurfaceToolbarButton
|
|
193
|
+
label={t(wrapLines ? 'wrapOff' : 'wrapOn')}
|
|
194
|
+
active={wrapLines}
|
|
195
|
+
onClick={() => runtime.setDiffWrapLines(!wrapLines)}
|
|
196
|
+
>
|
|
197
|
+
<WrapTextIcon className="size-4" />
|
|
198
|
+
</L3CodeSurfaceToolbarButton>
|
|
199
|
+
<L3CodeSurfaceToolbarButton
|
|
200
|
+
label={t(collapseUnchanged ? 'expandUnchanged' : 'collapseUnchanged')}
|
|
201
|
+
active={collapseUnchanged}
|
|
202
|
+
onClick={() => runtime.setDiffCollapseUnchanged(!collapseUnchanged)}
|
|
203
|
+
>
|
|
204
|
+
<FoldVerticalIcon className="size-4" />
|
|
205
|
+
</L3CodeSurfaceToolbarButton>
|
|
206
|
+
<L3CodeSurfaceToolbarButton
|
|
207
|
+
label={t('reloadDiff')}
|
|
208
|
+
onClick={() => runtime.reloadDiff()}
|
|
209
|
+
>
|
|
210
|
+
<RefreshCwIcon className="size-4" />
|
|
211
|
+
</L3CodeSurfaceToolbarButton>
|
|
212
|
+
</>
|
|
213
|
+
) : (
|
|
214
|
+
<>
|
|
215
|
+
{previewKind && document?.status === 'text' && activePath ? (
|
|
216
|
+
<div
|
|
217
|
+
className="mr-auto flex shrink-0"
|
|
218
|
+
role="group"
|
|
219
|
+
aria-label={t(previewKind === 'markdown' ? 'markdownMode' : 'htmlMode')}
|
|
220
|
+
>
|
|
221
|
+
{(['preview', 'source'] as const).map((mode) => (
|
|
222
|
+
<Button
|
|
223
|
+
key={mode}
|
|
224
|
+
variant={document.viewMode === mode ? 'secondary' : 'ghost'}
|
|
225
|
+
size="sm"
|
|
226
|
+
aria-pressed={document.viewMode === mode}
|
|
227
|
+
onClick={() => {
|
|
228
|
+
savePosition()
|
|
229
|
+
runtime.setTextViewMode(activePath, mode)
|
|
230
|
+
}}
|
|
231
|
+
>
|
|
232
|
+
{t(mode === 'preview' ? 'previewMode' : 'sourceMode')}
|
|
233
|
+
</Button>
|
|
234
|
+
))}
|
|
235
|
+
</div>
|
|
236
|
+
) : null}
|
|
237
|
+
{showSource && gitStatus ? (
|
|
238
|
+
<span
|
|
239
|
+
data-testid="file-git-status"
|
|
240
|
+
role="status"
|
|
241
|
+
className="mr-auto min-w-0 truncate text-xs text-muted-foreground"
|
|
242
|
+
title={comparison?.status === 'error' ? comparison.error : gitStatus}
|
|
243
|
+
>
|
|
244
|
+
{compact && comparison?.status === 'ready' && typeof count === 'number'
|
|
245
|
+
? t('gitChangesCompact', { count })
|
|
246
|
+
: gitStatus}
|
|
247
|
+
</span>
|
|
248
|
+
) : null}
|
|
249
|
+
{showSource && comparison?.status === 'ready' ? (
|
|
250
|
+
<>
|
|
251
|
+
{typeof count === 'number' && count > 0 ? (
|
|
252
|
+
<>
|
|
253
|
+
<L3CodeSurfaceToolbarButton
|
|
254
|
+
label={t('previousChange')}
|
|
255
|
+
onClick={() => previewRef.current?.previousChange()}
|
|
256
|
+
>
|
|
257
|
+
<ArrowUpIcon className="size-4" />
|
|
258
|
+
</L3CodeSurfaceToolbarButton>
|
|
259
|
+
<L3CodeSurfaceToolbarButton
|
|
260
|
+
label={t('nextChange')}
|
|
261
|
+
onClick={() => previewRef.current?.nextChange()}
|
|
262
|
+
>
|
|
263
|
+
<ArrowDownIcon className="size-4" />
|
|
264
|
+
</L3CodeSurfaceToolbarButton>
|
|
265
|
+
</>
|
|
266
|
+
) : null}
|
|
267
|
+
<L3CodeSurfaceToolbarButton label={t('viewDiff')} onClick={() => openDiff()}>
|
|
268
|
+
<GitCompareArrowsIcon className="size-4" />
|
|
269
|
+
</L3CodeSurfaceToolbarButton>
|
|
270
|
+
</>
|
|
271
|
+
) : null}
|
|
272
|
+
{showSource && activePath ? (
|
|
273
|
+
<>
|
|
274
|
+
<L3CodeSurfaceToolbarButton
|
|
275
|
+
label={t('findInFile')}
|
|
276
|
+
onClick={() => previewRef.current?.openSearch()}
|
|
277
|
+
>
|
|
278
|
+
<SearchIcon className="size-4" />
|
|
279
|
+
</L3CodeSurfaceToolbarButton>
|
|
280
|
+
{!compact ? (
|
|
281
|
+
<L3CodeSurfaceToolbarButton
|
|
282
|
+
label={t('goToLine')}
|
|
283
|
+
onClick={() => previewRef.current?.gotoLine()}
|
|
284
|
+
>
|
|
285
|
+
<ListOrderedIcon className="size-4" />
|
|
286
|
+
</L3CodeSurfaceToolbarButton>
|
|
287
|
+
) : null}
|
|
288
|
+
<L3CodeSurfaceToolbarButton
|
|
289
|
+
label={t(wrapLines ? 'wrapOff' : 'wrapOn')}
|
|
290
|
+
active={wrapLines}
|
|
291
|
+
onClick={() => runtime.setWrapLines(activePath, !wrapLines)}
|
|
292
|
+
>
|
|
293
|
+
<WrapTextIcon className="size-4" />
|
|
294
|
+
</L3CodeSurfaceToolbarButton>
|
|
295
|
+
<L3CodeSurfaceToolbarButton label={t('copySelectionOrAll')} onClick={copyText}>
|
|
296
|
+
<CopyIcon className="size-4" />
|
|
297
|
+
</L3CodeSurfaceToolbarButton>
|
|
298
|
+
</>
|
|
299
|
+
) : null}
|
|
300
|
+
{activePath ? (
|
|
301
|
+
<L3CodeSurfaceToolbarButton label={t('reloadCurrentFile')} onClick={refresh}>
|
|
302
|
+
<RefreshCwIcon className="size-4" />
|
|
303
|
+
</L3CodeSurfaceToolbarButton>
|
|
304
|
+
) : null}
|
|
305
|
+
</>
|
|
306
|
+
)}
|
|
307
|
+
</>
|
|
308
|
+
) : null
|
|
152
309
|
return (
|
|
153
310
|
<div
|
|
154
311
|
ref={hostRef}
|
|
@@ -162,160 +319,14 @@ export function L3ProjectDocumentView({
|
|
|
162
319
|
hostRef.current?.querySelector<HTMLElement>('[data-testid="markdown-preview"]')?.focus()
|
|
163
320
|
}}
|
|
164
321
|
>
|
|
165
|
-
{
|
|
322
|
+
{renderHeader ? (
|
|
323
|
+
renderHeader(actions)
|
|
324
|
+
) : actions ? (
|
|
166
325
|
<div
|
|
167
326
|
className="flex min-h-9 shrink-0 flex-wrap items-center justify-end gap-2 border-b px-3 py-1"
|
|
168
327
|
aria-label={t('fileActions')}
|
|
169
328
|
>
|
|
170
|
-
{
|
|
171
|
-
<>
|
|
172
|
-
<span className="mr-auto shrink-0 px-1 text-xs text-muted-foreground">
|
|
173
|
-
{activeDiff.label ?? t('headToWorking')}
|
|
174
|
-
{activeDiff.status === 'text' &&
|
|
175
|
-
activeDiff.original.content === activeDiff.modified.content
|
|
176
|
-
? t('noDiffChanges')
|
|
177
|
-
: ''}
|
|
178
|
-
</span>
|
|
179
|
-
<L3CodeSurfaceToolbarButton
|
|
180
|
-
label={t('previousChange')}
|
|
181
|
-
onClick={() => diffRef.current?.previousChange()}
|
|
182
|
-
>
|
|
183
|
-
<ArrowUpIcon className="size-4" />
|
|
184
|
-
</L3CodeSurfaceToolbarButton>
|
|
185
|
-
<L3CodeSurfaceToolbarButton
|
|
186
|
-
label={t('nextChange')}
|
|
187
|
-
onClick={() => diffRef.current?.nextChange()}
|
|
188
|
-
>
|
|
189
|
-
<ArrowDownIcon className="size-4" />
|
|
190
|
-
</L3CodeSurfaceToolbarButton>
|
|
191
|
-
{!compact ? (
|
|
192
|
-
<L3CodeSurfaceToolbarButton
|
|
193
|
-
label={diffViewMode === 'side-by-side' ? t('inlineDiff') : t('sideBySideDiff')}
|
|
194
|
-
active={diffViewMode === 'inline'}
|
|
195
|
-
onClick={() =>
|
|
196
|
-
runtime.setDiffViewMode(
|
|
197
|
-
diffViewMode === 'side-by-side' ? 'inline' : 'side-by-side'
|
|
198
|
-
)
|
|
199
|
-
}
|
|
200
|
-
>
|
|
201
|
-
<Columns2Icon className="size-4" />
|
|
202
|
-
</L3CodeSurfaceToolbarButton>
|
|
203
|
-
) : null}
|
|
204
|
-
<L3CodeSurfaceToolbarButton
|
|
205
|
-
label={t(wrapLines ? 'wrapOff' : 'wrapOn')}
|
|
206
|
-
active={wrapLines}
|
|
207
|
-
onClick={() => runtime.setDiffWrapLines(!wrapLines)}
|
|
208
|
-
>
|
|
209
|
-
<WrapTextIcon className="size-4" />
|
|
210
|
-
</L3CodeSurfaceToolbarButton>
|
|
211
|
-
<L3CodeSurfaceToolbarButton
|
|
212
|
-
label={t(collapseUnchanged ? 'expandUnchanged' : 'collapseUnchanged')}
|
|
213
|
-
active={collapseUnchanged}
|
|
214
|
-
onClick={() => runtime.setDiffCollapseUnchanged(!collapseUnchanged)}
|
|
215
|
-
>
|
|
216
|
-
<FoldVerticalIcon className="size-4" />
|
|
217
|
-
</L3CodeSurfaceToolbarButton>
|
|
218
|
-
<L3CodeSurfaceToolbarButton
|
|
219
|
-
label={t('reloadDiff')}
|
|
220
|
-
onClick={() => runtime.reloadDiff()}
|
|
221
|
-
>
|
|
222
|
-
<RefreshCwIcon className="size-4" />
|
|
223
|
-
</L3CodeSurfaceToolbarButton>
|
|
224
|
-
</>
|
|
225
|
-
) : (
|
|
226
|
-
<>
|
|
227
|
-
{previewKind && document?.status === 'text' && activePath ? (
|
|
228
|
-
<div
|
|
229
|
-
className="mr-auto flex shrink-0"
|
|
230
|
-
role="group"
|
|
231
|
-
aria-label={t(previewKind === 'markdown' ? 'markdownMode' : 'htmlMode')}
|
|
232
|
-
>
|
|
233
|
-
{(['preview', 'source'] as const).map((mode) => (
|
|
234
|
-
<Button
|
|
235
|
-
key={mode}
|
|
236
|
-
variant={document.viewMode === mode ? 'secondary' : 'ghost'}
|
|
237
|
-
size="sm"
|
|
238
|
-
aria-pressed={document.viewMode === mode}
|
|
239
|
-
onClick={() => {
|
|
240
|
-
savePosition()
|
|
241
|
-
runtime.setTextViewMode(activePath, mode)
|
|
242
|
-
}}
|
|
243
|
-
>
|
|
244
|
-
{t(mode === 'preview' ? 'previewMode' : 'sourceMode')}
|
|
245
|
-
</Button>
|
|
246
|
-
))}
|
|
247
|
-
</div>
|
|
248
|
-
) : null}
|
|
249
|
-
{showSource && gitStatus ? (
|
|
250
|
-
<span
|
|
251
|
-
data-testid="file-git-status"
|
|
252
|
-
role="status"
|
|
253
|
-
className="mr-auto min-w-0 truncate text-xs text-muted-foreground"
|
|
254
|
-
title={comparison?.status === 'error' ? comparison.error : gitStatus}
|
|
255
|
-
>
|
|
256
|
-
{compact && comparison?.status === 'ready' && typeof count === 'number'
|
|
257
|
-
? t('gitChangesCompact', { count })
|
|
258
|
-
: gitStatus}
|
|
259
|
-
</span>
|
|
260
|
-
) : null}
|
|
261
|
-
{showSource && comparison?.status === 'ready' ? (
|
|
262
|
-
<>
|
|
263
|
-
{typeof count === 'number' && count > 0 ? (
|
|
264
|
-
<>
|
|
265
|
-
<L3CodeSurfaceToolbarButton
|
|
266
|
-
label={t('previousChange')}
|
|
267
|
-
onClick={() => previewRef.current?.previousChange()}
|
|
268
|
-
>
|
|
269
|
-
<ArrowUpIcon className="size-4" />
|
|
270
|
-
</L3CodeSurfaceToolbarButton>
|
|
271
|
-
<L3CodeSurfaceToolbarButton
|
|
272
|
-
label={t('nextChange')}
|
|
273
|
-
onClick={() => previewRef.current?.nextChange()}
|
|
274
|
-
>
|
|
275
|
-
<ArrowDownIcon className="size-4" />
|
|
276
|
-
</L3CodeSurfaceToolbarButton>
|
|
277
|
-
</>
|
|
278
|
-
) : null}
|
|
279
|
-
<L3CodeSurfaceToolbarButton label={t('viewDiff')} onClick={() => openDiff()}>
|
|
280
|
-
<GitCompareArrowsIcon className="size-4" />
|
|
281
|
-
</L3CodeSurfaceToolbarButton>
|
|
282
|
-
</>
|
|
283
|
-
) : null}
|
|
284
|
-
{showSource && activePath ? (
|
|
285
|
-
<>
|
|
286
|
-
<L3CodeSurfaceToolbarButton
|
|
287
|
-
label={t('findInFile')}
|
|
288
|
-
onClick={() => previewRef.current?.openSearch()}
|
|
289
|
-
>
|
|
290
|
-
<SearchIcon className="size-4" />
|
|
291
|
-
</L3CodeSurfaceToolbarButton>
|
|
292
|
-
{!compact ? (
|
|
293
|
-
<L3CodeSurfaceToolbarButton
|
|
294
|
-
label={t('goToLine')}
|
|
295
|
-
onClick={() => previewRef.current?.gotoLine()}
|
|
296
|
-
>
|
|
297
|
-
<ListOrderedIcon className="size-4" />
|
|
298
|
-
</L3CodeSurfaceToolbarButton>
|
|
299
|
-
) : null}
|
|
300
|
-
<L3CodeSurfaceToolbarButton
|
|
301
|
-
label={t(wrapLines ? 'wrapOff' : 'wrapOn')}
|
|
302
|
-
active={wrapLines}
|
|
303
|
-
onClick={() => runtime.setWrapLines(activePath, !wrapLines)}
|
|
304
|
-
>
|
|
305
|
-
<WrapTextIcon className="size-4" />
|
|
306
|
-
</L3CodeSurfaceToolbarButton>
|
|
307
|
-
<L3CodeSurfaceToolbarButton label={t('copySelectionOrAll')} onClick={copyText}>
|
|
308
|
-
<CopyIcon className="size-4" />
|
|
309
|
-
</L3CodeSurfaceToolbarButton>
|
|
310
|
-
</>
|
|
311
|
-
) : null}
|
|
312
|
-
{activePath ? (
|
|
313
|
-
<L3CodeSurfaceToolbarButton label={t('reloadCurrentFile')} onClick={refresh}>
|
|
314
|
-
<RefreshCwIcon className="size-4" />
|
|
315
|
-
</L3CodeSurfaceToolbarButton>
|
|
316
|
-
) : null}
|
|
317
|
-
</>
|
|
318
|
-
)}
|
|
329
|
+
{actions}
|
|
319
330
|
</div>
|
|
320
331
|
) : null}
|
|
321
332
|
<div className="min-h-0 flex-1 overflow-hidden pb-[env(safe-area-inset-bottom)]">
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
.tree [role='tree'] {
|
|
2
|
+
padding: 0;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.tree [role='tree'] > div {
|
|
6
|
+
padding: 0 4px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.tree [data-slot='collapsible-content'] > div {
|
|
10
|
+
border-left-color: color-mix(in oklab, var(--border) 50%, transparent);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@media (pointer: fine) {
|
|
14
|
+
.tree [role='treeitem']:not([aria-expanded]),
|
|
15
|
+
.tree [role='treeitem'][aria-expanded] > div:first-child {
|
|
16
|
+
min-height: 24px;
|
|
17
|
+
gap: 4px;
|
|
18
|
+
padding: 0 4px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.tree [role='treeitem'][aria-expanded] > div:first-child > button {
|
|
22
|
+
min-height: 24px;
|
|
23
|
+
gap: 4px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.tree [data-slot='collapsible-content'] > div {
|
|
27
|
+
margin-left: 8px;
|
|
28
|
+
padding-left: 3px;
|
|
29
|
+
}
|
|
30
|
+
}
|