@lijian-ui/dsh-file-manager 0.2.3 → 0.2.4
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/LICENSE +38 -38
- package/README.i18n.yaml +6 -6
- package/README.md +66 -66
- package/README.zh.md +66 -66
- package/cordis.patch.yml +13 -13
- package/lib/client.js +27305 -270
- package/lib/client.js.map +1 -1
- package/lib/index.js +474 -42
- package/lib/tsconfig.client.tsbuildinfo +1 -1
- package/lib/tsconfig.host.tsbuildinfo +1 -1
- package/lib/types/client/file-source.d.ts +10 -0
- package/lib/types/client/file-source.d.ts.map +1 -1
- package/lib/types/client/fileType.d.ts +19 -4
- package/lib/types/client/fileType.d.ts.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/locales.d.ts +3 -0
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/mount.d.ts +1 -1
- package/lib/types/client/mount.d.ts.map +1 -1
- package/lib/types/client/preview/PreviewPanel.d.ts +2 -1
- package/lib/types/client/preview/PreviewPanel.d.ts.map +1 -1
- package/lib/types/client/preview/PreviewToolbar.d.ts +3 -1
- package/lib/types/client/preview/PreviewToolbar.d.ts.map +1 -1
- package/lib/types/client/preview/content.d.ts +3 -1
- package/lib/types/client/preview/content.d.ts.map +1 -1
- package/lib/types/client/preview/office.d.ts +23 -0
- package/lib/types/client/preview/office.d.ts.map +1 -0
- package/lib/types/client/reference.d.ts +17 -0
- package/lib/types/client/reference.d.ts.map +1 -1
- package/lib/types/client/store.d.ts.map +1 -1
- package/lib/types/host/fs-service.d.ts.map +1 -1
- package/lib/types/host/office-preview.d.ts +13 -0
- package/lib/types/host/office-preview.d.ts.map +1 -0
- package/lib/types/host/routes.d.ts.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +19 -4
- package/src/client/FileManagerSettingsCard.tsx +117 -117
- package/src/client/PluginSettingsCard.tsx +337 -337
- package/src/client/chat/file-ref.ts +144 -144
- package/src/client/chat/mermaid-chat.tsx +102 -102
- package/src/client/chat/placeholder-hint.tsx +46 -46
- package/src/client/components/ExplorerPanel.tsx +534 -534
- package/src/client/components/FileIcon.tsx +46 -46
- package/src/client/components/ScmPanel.tsx +480 -480
- package/src/client/components/a11y.ts +20 -20
- package/src/client/components/icons.tsx +274 -274
- package/src/client/components/overlay.tsx +225 -225
- package/src/client/drag/DragFileInlay.tsx +89 -89
- package/src/client/drag/file-drag.ts +67 -67
- package/src/client/drag.ts +154 -154
- package/src/client/file-source.ts +34 -0
- package/src/client/fileType.ts +32 -5
- package/src/client/hooks/useResizableSplit.ts +91 -91
- package/src/client/hooks/useStore.ts +15 -15
- package/src/client/index.ts +42 -3
- package/src/client/layout.ts +523 -523
- package/src/client/locales.ts +6 -0
- package/src/client/maximize.ts +34 -34
- package/src/client/mount.tsx +2 -1
- package/src/client/persist.ts +194 -194
- package/src/client/picker/FilePickerModal.tsx +526 -526
- package/src/client/picker/file-picker.ts +86 -86
- package/src/client/preview/PreviewPanel.tsx +7 -1
- package/src/client/preview/PreviewTabs.tsx +159 -159
- package/src/client/preview/PreviewToolbar.tsx +3 -2
- package/src/client/preview/content.tsx +7 -2
- package/src/client/preview/markdown.ts +351 -351
- package/src/client/preview/mermaid.ts +274 -274
- package/src/client/preview/office.tsx +321 -0
- package/src/client/reference.ts +49 -0
- package/src/client/settings-card.module.css +316 -316
- package/src/client/settings-form.ts +451 -451
- package/src/client/store.ts +17 -12
- package/src/client/styles/drag.module.css +30 -30
- package/src/client/styles/explorer.module.css +371 -371
- package/src/client/styles/picker.module.css +344 -344
- package/src/client/styles/preview.module.css +3 -1
- package/src/client/styles/scm.module.css +380 -380
- package/src/client/styles/tokens.module.css +376 -371
- package/src/core/types.ts +162 -162
- package/src/host/fs-service.ts +7 -1
- package/src/host/gate.ts +73 -73
- package/src/host/git-runner.ts +116 -116
- package/src/host/git-service.ts +395 -395
- package/src/host/loopback.ts +63 -63
- package/src/host/office-preview.ts +399 -0
- package/src/host/poll-guard.ts +109 -109
- package/src/host/routes.ts +72 -1
- package/src/index.ts +3 -1
- package/src/mount-once.ts +48 -48
- package/lib/types/client/chat/AttachedFilesDock.d.ts +0 -51
- package/lib/types/client/chat/AttachedFilesDock.d.ts.map +0 -1
- package/lib/types/client/floating.d.ts +0 -27
- package/lib/types/client/floating.d.ts.map +0 -1
- package/lib/types/client/mention.d.ts +0 -44
- package/lib/types/client/mention.d.ts.map +0 -1
|
@@ -1,91 +1,91 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The panel system's single drag engine hook — a thin React wrapper over the
|
|
3
|
-
* framework-free machinery in drag.ts (FileManager's useResizableSplit
|
|
4
|
-
* architecture, re-implemented): px or ratio units, range-validated
|
|
5
|
-
* localStorage persistence, double-click reset to the default width.
|
|
6
|
-
* @module dsh-filemgr/client/hooks/useResizableSplit
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
10
|
-
import type { PointerEvent as ReactPointerEvent } from 'react'
|
|
11
|
-
import { handlePointerDragStart } from '../drag.ts'
|
|
12
|
-
import { readStoredNumber, writeStoredNumber } from '../persist.ts'
|
|
13
|
-
|
|
14
|
-
export interface UseResizableSplitOptions {
|
|
15
|
-
/** Default width (px or percent). */
|
|
16
|
-
defaultWidth?: number
|
|
17
|
-
/** Minimum (same unit). */
|
|
18
|
-
minWidth?: number
|
|
19
|
-
/** Maximum (same unit). */
|
|
20
|
-
maxWidth?: number
|
|
21
|
-
/** localStorage key (preference persistence). */
|
|
22
|
-
storageKey?: string
|
|
23
|
-
/** 'px' for fixed pixel widths, 'ratio' for percents (default 'ratio'). */
|
|
24
|
-
unit?: 'px' | 'ratio'
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface DragHandleProps {
|
|
28
|
-
onPointerDown: (event: ReactPointerEvent<HTMLDivElement>) => void
|
|
29
|
-
onDoubleClick: () => void
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Resizable-split engine.
|
|
34
|
-
* @param options - width contract + persistence key.
|
|
35
|
-
* @returns current width, the committed setter, handle props, and the clamp.
|
|
36
|
-
*/
|
|
37
|
-
export function useResizableSplit(options: UseResizableSplitOptions = {}) {
|
|
38
|
-
const {
|
|
39
|
-
defaultWidth = 50,
|
|
40
|
-
minWidth = 20,
|
|
41
|
-
maxWidth = 80,
|
|
42
|
-
storageKey,
|
|
43
|
-
unit = 'ratio',
|
|
44
|
-
} = options
|
|
45
|
-
const isPx = unit === 'px'
|
|
46
|
-
|
|
47
|
-
const [width, setWidthState] = useState(() =>
|
|
48
|
-
storageKey === undefined
|
|
49
|
-
? defaultWidth
|
|
50
|
-
: readStoredNumber(storageKey, minWidth, maxWidth, defaultWidth))
|
|
51
|
-
|
|
52
|
-
// The pointer-down closure reads the width at drag START without rebinding.
|
|
53
|
-
const widthRef = useRef(width)
|
|
54
|
-
useEffect(() => {
|
|
55
|
-
widthRef.current = width
|
|
56
|
-
}, [width])
|
|
57
|
-
|
|
58
|
-
/** The committed setter: state + storage (validated) + resize event. */
|
|
59
|
-
const setWidth = useCallback((value: number) => {
|
|
60
|
-
setWidthState(value)
|
|
61
|
-
if (storageKey !== undefined) writeStoredNumber(storageKey, value)
|
|
62
|
-
try {
|
|
63
|
-
window.dispatchEvent(new CustomEvent('preview-panel-resize', { detail: { width: value } }))
|
|
64
|
-
} catch {
|
|
65
|
-
// event dispatch is best-effort
|
|
66
|
-
}
|
|
67
|
-
}, [storageKey])
|
|
68
|
-
|
|
69
|
-
const clamp = useCallback((value: number): number => {
|
|
70
|
-
return Math.min(maxWidth, Math.max(minWidth, value))
|
|
71
|
-
}, [minWidth, maxWidth])
|
|
72
|
-
|
|
73
|
-
const handlePointerDown = useCallback((event: ReactPointerEvent<HTMLDivElement>) => {
|
|
74
|
-
const el = event.currentTarget as HTMLDivElement
|
|
75
|
-
handlePointerDragStart(event.nativeEvent, el, {
|
|
76
|
-
reverse: el.dataset.reverse === 'true',
|
|
77
|
-
getStartWidth: () => widthRef.current,
|
|
78
|
-
compute: (startWidth, deltaX) => clamp(startWidth + deltaX),
|
|
79
|
-
onFrame: (value) => setWidthState(value),
|
|
80
|
-
onEnd: (value) => setWidth(value),
|
|
81
|
-
})
|
|
82
|
-
}, [clamp, setWidth])
|
|
83
|
-
|
|
84
|
-
const handleDoubleClick = useCallback(() => {
|
|
85
|
-
setWidth(defaultWidth)
|
|
86
|
-
}, [defaultWidth, setWidth])
|
|
87
|
-
|
|
88
|
-
const handleProps: DragHandleProps = { onPointerDown: handlePointerDown, onDoubleClick: handleDoubleClick }
|
|
89
|
-
|
|
90
|
-
return { width, setWidth, handleProps, clamp, isPx }
|
|
91
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* The panel system's single drag engine hook — a thin React wrapper over the
|
|
3
|
+
* framework-free machinery in drag.ts (FileManager's useResizableSplit
|
|
4
|
+
* architecture, re-implemented): px or ratio units, range-validated
|
|
5
|
+
* localStorage persistence, double-click reset to the default width.
|
|
6
|
+
* @module dsh-filemgr/client/hooks/useResizableSplit
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
10
|
+
import type { PointerEvent as ReactPointerEvent } from 'react'
|
|
11
|
+
import { handlePointerDragStart } from '../drag.ts'
|
|
12
|
+
import { readStoredNumber, writeStoredNumber } from '../persist.ts'
|
|
13
|
+
|
|
14
|
+
export interface UseResizableSplitOptions {
|
|
15
|
+
/** Default width (px or percent). */
|
|
16
|
+
defaultWidth?: number
|
|
17
|
+
/** Minimum (same unit). */
|
|
18
|
+
minWidth?: number
|
|
19
|
+
/** Maximum (same unit). */
|
|
20
|
+
maxWidth?: number
|
|
21
|
+
/** localStorage key (preference persistence). */
|
|
22
|
+
storageKey?: string
|
|
23
|
+
/** 'px' for fixed pixel widths, 'ratio' for percents (default 'ratio'). */
|
|
24
|
+
unit?: 'px' | 'ratio'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface DragHandleProps {
|
|
28
|
+
onPointerDown: (event: ReactPointerEvent<HTMLDivElement>) => void
|
|
29
|
+
onDoubleClick: () => void
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Resizable-split engine.
|
|
34
|
+
* @param options - width contract + persistence key.
|
|
35
|
+
* @returns current width, the committed setter, handle props, and the clamp.
|
|
36
|
+
*/
|
|
37
|
+
export function useResizableSplit(options: UseResizableSplitOptions = {}) {
|
|
38
|
+
const {
|
|
39
|
+
defaultWidth = 50,
|
|
40
|
+
minWidth = 20,
|
|
41
|
+
maxWidth = 80,
|
|
42
|
+
storageKey,
|
|
43
|
+
unit = 'ratio',
|
|
44
|
+
} = options
|
|
45
|
+
const isPx = unit === 'px'
|
|
46
|
+
|
|
47
|
+
const [width, setWidthState] = useState(() =>
|
|
48
|
+
storageKey === undefined
|
|
49
|
+
? defaultWidth
|
|
50
|
+
: readStoredNumber(storageKey, minWidth, maxWidth, defaultWidth))
|
|
51
|
+
|
|
52
|
+
// The pointer-down closure reads the width at drag START without rebinding.
|
|
53
|
+
const widthRef = useRef(width)
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
widthRef.current = width
|
|
56
|
+
}, [width])
|
|
57
|
+
|
|
58
|
+
/** The committed setter: state + storage (validated) + resize event. */
|
|
59
|
+
const setWidth = useCallback((value: number) => {
|
|
60
|
+
setWidthState(value)
|
|
61
|
+
if (storageKey !== undefined) writeStoredNumber(storageKey, value)
|
|
62
|
+
try {
|
|
63
|
+
window.dispatchEvent(new CustomEvent('preview-panel-resize', { detail: { width: value } }))
|
|
64
|
+
} catch {
|
|
65
|
+
// event dispatch is best-effort
|
|
66
|
+
}
|
|
67
|
+
}, [storageKey])
|
|
68
|
+
|
|
69
|
+
const clamp = useCallback((value: number): number => {
|
|
70
|
+
return Math.min(maxWidth, Math.max(minWidth, value))
|
|
71
|
+
}, [minWidth, maxWidth])
|
|
72
|
+
|
|
73
|
+
const handlePointerDown = useCallback((event: ReactPointerEvent<HTMLDivElement>) => {
|
|
74
|
+
const el = event.currentTarget as HTMLDivElement
|
|
75
|
+
handlePointerDragStart(event.nativeEvent, el, {
|
|
76
|
+
reverse: el.dataset.reverse === 'true',
|
|
77
|
+
getStartWidth: () => widthRef.current,
|
|
78
|
+
compute: (startWidth, deltaX) => clamp(startWidth + deltaX),
|
|
79
|
+
onFrame: (value) => setWidthState(value),
|
|
80
|
+
onEnd: (value) => setWidth(value),
|
|
81
|
+
})
|
|
82
|
+
}, [clamp, setWidth])
|
|
83
|
+
|
|
84
|
+
const handleDoubleClick = useCallback(() => {
|
|
85
|
+
setWidth(defaultWidth)
|
|
86
|
+
}, [defaultWidth, setWidth])
|
|
87
|
+
|
|
88
|
+
const handleProps: DragHandleProps = { onPointerDown: handlePointerDown, onDoubleClick: handleDoubleClick }
|
|
89
|
+
|
|
90
|
+
return { width, setWidth, handleProps, clamp, isPx }
|
|
91
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* React bindings for the framework-free stores: useSyncExternalStore with a
|
|
3
|
-
* stable snapshot (the stores return immutable snapshots, so selector-free
|
|
4
|
-
* subscription is safe), plus a stable-callback helper for event handlers.
|
|
5
|
-
* @module dsh-filemgr/client/hooks/useStore
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useSyncExternalStore } from 'react'
|
|
9
|
-
import type { StateHandle } from '../store.ts'
|
|
10
|
-
|
|
11
|
-
/** Subscribe a component to one store (full snapshot). */
|
|
12
|
-
export function useStore<S>(store: StateHandle<S>): S {
|
|
13
|
-
return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot)
|
|
14
|
-
}
|
|
15
|
-
|
|
1
|
+
/**
|
|
2
|
+
* React bindings for the framework-free stores: useSyncExternalStore with a
|
|
3
|
+
* stable snapshot (the stores return immutable snapshots, so selector-free
|
|
4
|
+
* subscription is safe), plus a stable-callback helper for event handlers.
|
|
5
|
+
* @module dsh-filemgr/client/hooks/useStore
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useSyncExternalStore } from 'react'
|
|
9
|
+
import type { StateHandle } from '../store.ts'
|
|
10
|
+
|
|
11
|
+
/** Subscribe a component to one store (full snapshot). */
|
|
12
|
+
export function useStore<S>(store: StateHandle<S>): S {
|
|
13
|
+
return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot)
|
|
14
|
+
}
|
|
15
|
+
|
package/src/client/index.ts
CHANGED
|
@@ -34,8 +34,8 @@ import { MermaidChatEnhancer } from './chat/mermaid-chat.tsx'
|
|
|
34
34
|
import { PlaceholderHint } from './chat/placeholder-hint.tsx'
|
|
35
35
|
import { FilePickerHost } from './picker/FilePickerModal.tsx'
|
|
36
36
|
import { handleFileRefClick } from './chat/file-ref.ts'
|
|
37
|
-
import { appendToDraft, appendFileReferenceChip } from './reference.ts'
|
|
38
|
-
import { registerFileReferenceSource } from './file-source.ts'
|
|
37
|
+
import { appendToDraft, appendFileReferenceChip, appendSheetChip } from './reference.ts'
|
|
38
|
+
import { registerFileReferenceSource, registerSheetReferenceSource } from './file-source.ts'
|
|
39
39
|
import type { FileReferenceSelection } from './preview/selection.ts'
|
|
40
40
|
import { FilePanelDockItem } from './FilePanelDockItem.tsx'
|
|
41
41
|
|
|
@@ -107,6 +107,7 @@ export function apply(ctx: ClientContext): void {
|
|
|
107
107
|
// `slash/input-insert-reference` chip can send. Inert as a menu
|
|
108
108
|
// participant — the '@' tree modal is our own picker, not the shell menu.
|
|
109
109
|
ctx.effect(() => registerFileReferenceSource(ctx), 'dsh-filemgr: file reference source')
|
|
110
|
+
ctx.effect(() => registerSheetReferenceSource(ctx), 'dsh-filemgr: sheet reference source')
|
|
110
111
|
|
|
111
112
|
// The '@' picker is our own tree modal (pi-desktop style), NOT the shell's
|
|
112
113
|
// flat trigger menu: a bare `@` in the composer opens FilePickerHost
|
|
@@ -218,6 +219,7 @@ export function apply(ctx: ClientContext): void {
|
|
|
218
219
|
const layout = new PanelLayoutController(stores.layout)
|
|
219
220
|
const disposers: Array<() => void> = []
|
|
220
221
|
let disposeGitEvents: (() => void) | undefined
|
|
222
|
+
let disposeFsEvents: (() => void) | undefined
|
|
221
223
|
let currentRoot = ''
|
|
222
224
|
let lastPreviewOpen = false
|
|
223
225
|
|
|
@@ -244,6 +246,14 @@ export function apply(ctx: ClientContext): void {
|
|
|
244
246
|
return appendFileReferenceChip(ctx, sessionId, selection)
|
|
245
247
|
}
|
|
246
248
|
|
|
249
|
+
// The preview Excel "引用到对话" action: mint a `sheet` chip (appearance
|
|
250
|
+
// only) appended at the draft end, serializing the
|
|
251
|
+
// `相对路径!Sheet名!Range` token on submit.
|
|
252
|
+
const onInsertSheetReference = (path: string, sheetName: string, range: string): boolean => {
|
|
253
|
+
const sessionId = ctx.sessions.list.getSnapshot().current as SessionId | undefined
|
|
254
|
+
return appendSheetChip(ctx, sessionId, path, { sheetName, range })
|
|
255
|
+
}
|
|
256
|
+
|
|
247
257
|
// The project root follows the active session's cwd; switching sessions
|
|
248
258
|
// re-binds every store (widths, collapse, tree, tabs persist per root).
|
|
249
259
|
const bindRoot = (): void => {
|
|
@@ -260,6 +270,8 @@ export function apply(ctx: ClientContext): void {
|
|
|
260
270
|
// switches; syncGitSubscription re-evaluates it below.
|
|
261
271
|
disposeGitEvents?.()
|
|
262
272
|
disposeGitEvents = undefined
|
|
273
|
+
disposeFsEvents?.()
|
|
274
|
+
disposeFsEvents = undefined
|
|
263
275
|
const previewOpen = stores.preview.getSnapshot().open
|
|
264
276
|
lastPreviewOpen = previewOpen
|
|
265
277
|
layoutSetRoot(stores.layout, root, previewOpen)
|
|
@@ -268,6 +280,7 @@ export function apply(ctx: ClientContext): void {
|
|
|
268
280
|
stores.preview.setRoot(root)
|
|
269
281
|
|
|
270
282
|
syncGitSubscription()
|
|
283
|
+
syncFsSubscription()
|
|
271
284
|
}
|
|
272
285
|
|
|
273
286
|
/**
|
|
@@ -301,8 +314,33 @@ export function apply(ctx: ClientContext): void {
|
|
|
301
314
|
disposeGitEvents = undefined
|
|
302
315
|
}
|
|
303
316
|
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Live-filesystem notifications: the host watches the workspace root
|
|
320
|
+
* while any SSE stream is open (recursive fs.watch + debounce) and emits
|
|
321
|
+
* `{kind:'fs'}` on out-of-band writes — chiefly an agent/LLM subprocess
|
|
322
|
+
* creating or editing a work product directly on disk (which never
|
|
323
|
+
* touches the /filemgr/* write APIs). Refresh the explorer so the new
|
|
324
|
+
* file shows up without a manual UI action. The subscription mirrors the
|
|
325
|
+
* panel lifecycle: only while a session root exists AND the explorer
|
|
326
|
+
* panel is visible (CollapsiblePanel/折叠 keeps the dock icon hot).
|
|
327
|
+
*/
|
|
328
|
+
const syncFsSubscription = (): void => {
|
|
329
|
+
const root = currentRoot
|
|
330
|
+
const visible = !stores.layout.getSnapshot().explorerCollapsed
|
|
331
|
+
const want = root !== '' && visible
|
|
332
|
+
if (want && disposeFsEvents === undefined) {
|
|
333
|
+
disposeFsEvents = subscribePanelEvents(root, (event) => {
|
|
334
|
+
if (event.kind === 'fs') void stores.explorer.handleFsChange()
|
|
335
|
+
})
|
|
336
|
+
} else if (!want && disposeFsEvents !== undefined) {
|
|
337
|
+
disposeFsEvents()
|
|
338
|
+
disposeFsEvents = undefined
|
|
339
|
+
}
|
|
340
|
+
}
|
|
304
341
|
disposers.push(ctx.sessions.list.subscribe(bindRoot))
|
|
305
342
|
disposers.push(stores.explorer.subscribe(syncGitSubscription))
|
|
343
|
+
disposers.push(stores.layout.subscribe(syncFsSubscription))
|
|
306
344
|
bindRoot()
|
|
307
345
|
|
|
308
346
|
// Header tool-dock bridge (dsh-term's AnimatedDock): the "file panel"
|
|
@@ -347,7 +385,7 @@ export function apply(ctx: ClientContext): void {
|
|
|
347
385
|
// Mount everything. DOM failures degrade the panels, never the GUI.
|
|
348
386
|
try {
|
|
349
387
|
layout.mount()
|
|
350
|
-
mountPanels(stores, () => layout.toggleExplorer(), onReference, onAddFileReference, ctx.locale)
|
|
388
|
+
mountPanels(stores, () => layout.toggleExplorer(), onReference, onAddFileReference, onInsertSheetReference, ctx.locale)
|
|
351
389
|
} catch (error) {
|
|
352
390
|
console.error('[dsh-filemgr] mount failed:', error)
|
|
353
391
|
}
|
|
@@ -388,6 +426,7 @@ export function apply(ctx: ClientContext): void {
|
|
|
388
426
|
document.removeEventListener('visibilitychange', onVisibilityChange)
|
|
389
427
|
document.removeEventListener('click', onFileRefClick)
|
|
390
428
|
disposeGitEvents?.()
|
|
429
|
+
disposeFsEvents?.()
|
|
391
430
|
langObserver?.disconnect()
|
|
392
431
|
pickerRoot.unmount()
|
|
393
432
|
pickerHostEl.remove()
|