diff --git a/.reasonix/desktop-topic-auto-title-meta.json b/.reasonix/desktop-topic-auto-title-meta.json index 1af7c51..8a878b7 100644 --- a/.reasonix/desktop-topic-auto-title-meta.json +++ b/.reasonix/desktop-topic-auto-title-meta.json @@ -58,5 +58,11 @@ "userTurns": 4, "basisHash": "aaae120b1f33c2f2", "updatedAt": 1783674217586 + }, + "topic_20260710-090003_60717bd90da5ec68": { + "stage": 1, + "userTurns": 1, + "basisHash": "cd60850543a6985b", + "updatedAt": 1783700550206 } } \ No newline at end of file diff --git a/.reasonix/desktop-topic-created-at.json b/.reasonix/desktop-topic-created-at.json index 5b59f18..d081832 100644 --- a/.reasonix/desktop-topic-created-at.json +++ b/.reasonix/desktop-topic-created-at.json @@ -1,14 +1,3 @@ { - "topic_20260630-144952_fd0584fe8f266d6a": 1782830992641, - "topic_20260703-022850_50330b4eb93f116d": 1783045730616, - "topic_20260706-145507_076a32df5f4276b5": 1783349707873, - "topic_20260706-153317_238f65a7a470703c": 1783351997029, - "topic_20260710-024855_5c4b1833149d66bb": 1783651735446, - "topic_20260710-030936_cedad2907c3954fe": 1783652976310, - "topic_20260710-032907_600adc6b00791607": 1783654147796, - "topic_20260710-034033_6432ee6566f7b432": 1783654833341, - "topic_20260710-034724_3c6fb29d8d0a4119": 1783655244536, - "topic_20260710-054543_5e7c427932aecd7b": 1783662343716, - "topic_20260710-063053_353d579222d3b70b": 1783665053391, - "topic_20260710-090003_60717bd90da5ec68": 1783674003004 + "topic_20260707-131941_481a70d2be9881dd": 1783430381000 } \ No newline at end of file diff --git a/.reasonix/desktop-topic-title-sources.json b/.reasonix/desktop-topic-title-sources.json index b4ef565..13143e2 100644 --- a/.reasonix/desktop-topic-title-sources.json +++ b/.reasonix/desktop-topic-title-sources.json @@ -38,6 +38,7 @@ "topic_20260707-093602_5c75f77654cab0c3": "manual", "topic_20260707-094645_05255aaa45d5f673": "manual", "topic_20260707-095503_bf879b65e4666516": "auto", + "topic_20260707-131941_481a70d2be9881dd": "manual", "topic_20260708-020616_9ab54d98daf65053": "auto", "topic_20260708-093419_71d1fea2e4b5a40f": "auto", "topic_20260708-095428_990617acd4168b40": "auto", diff --git a/.reasonix/desktop-topic-titles.json b/.reasonix/desktop-topic-titles.json index 1414c6c..8ac077d 100644 --- a/.reasonix/desktop-topic-titles.json +++ b/.reasonix/desktop-topic-titles.json @@ -38,6 +38,8 @@ "topic_20260707-093602_5c75f77654cab0c3": "隐藏单栏和双栏的切换功能,把mark…", "topic_20260707-094645_05255aaa45d5f673": "帮我移除markdownEditor…", "topic_20260707-095503_bf879b65e4666516": "帮我移除markdownEditor…", + "topic_20260707-131941_481a70d2be9881dd": "新的会话", + "topic_20260707-132824_49b096d569ffa3d3": "现在帮我把这个markdownEdi…", "topic_20260708-020616_9ab54d98daf65053": "帮我分析一下现在的markdownE…", "topic_20260708-093419_71d1fea2e4b5a40f": "src/components/Dir…", "topic_20260708-095428_990617acd4168b40": "帮我检查一下这个应用在进行放大缩小的…", @@ -48,5 +50,5 @@ "topic_20260710-034724_3c6fb29d8d0a4119": "目录树中鼠标悬浮弹框dropmenu…", "topic_20260710-054543_5e7c427932aecd7b": "现在在markdown的编辑区域中…", "topic_20260710-063053_353d579222d3b70b": "这个应用里有一个全局搜索的功能,帮我…", - "topic_20260710-090003_60717bd90da5ec68": "新的会话" + "topic_20260710-090003_60717bd90da5ec68": "当用户在markdownEditor…" } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index bed5ac1..9228d5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@codemirror/search": "^6.7.1", "@codemirror/state": "^6.7.1", "@codemirror/view": "^6.43.6", + "@fancyapps/ui": "^6.1.14", "@lezer/highlight": "^1.2.3", "@lucide/vue": "^1.23.0", "@tauri-apps/api": "^2", @@ -1460,6 +1461,12 @@ "node": "^20.19.0 || ^22.13.0 || >=24" } }, + "node_modules/@fancyapps/ui": { + "version": "6.1.14", + "resolved": "https://registry.npmjs.org/@fancyapps/ui/-/ui-6.1.14.tgz", + "integrity": "sha512-cBV73XXHrc0qMca+PJJ6qay3xweIgsoYse13rGRstgUs0xA5WAv1tgbSzPCIOOjiLs2S2jiVFJxyszgvgyfxMg==", + "license": "SEE LICENSE IN LICENSE.md" + }, "node_modules/@floating-ui/core": { "version": "1.8.0", "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.8.0.tgz", @@ -2031,9 +2038,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2048,9 +2052,6 @@ "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2065,9 +2066,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2082,9 +2080,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2099,9 +2094,6 @@ "loong64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2116,9 +2108,6 @@ "loong64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2133,9 +2122,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2150,9 +2136,6 @@ "ppc64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2167,9 +2150,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2184,9 +2164,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2201,9 +2178,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2218,9 +2192,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2235,9 +2206,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2570,9 +2538,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2590,9 +2555,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2610,9 +2572,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2630,9 +2589,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2672,6 +2628,72 @@ "node": ">=14.0.0" } }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.11.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.1", + "dev": true, + "inBundle": true, + "license": "0BSD", + "optional": true + }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { "version": "4.3.2", "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.2.tgz", @@ -2846,9 +2868,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0 OR MIT", "optional": true, "os": [ @@ -2866,9 +2885,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "Apache-2.0 OR MIT", "optional": true, "os": [ @@ -2886,9 +2902,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0 OR MIT", "optional": true, "os": [ @@ -2906,9 +2919,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0 OR MIT", "optional": true, "os": [ @@ -2926,9 +2936,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "Apache-2.0 OR MIT", "optional": true, "os": [ @@ -5963,9 +5970,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -5987,9 +5991,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -6011,9 +6012,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -6035,9 +6033,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -6350,7 +6345,7 @@ }, "node_modules/mdast-util-newline-to-break": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/mdast-util-newline-to-break/-/mdast-util-newline-to-break-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/mdast-util-newline-to-break/-/mdast-util-newline-to-break-2.0.0.tgz", "integrity": "sha512-MbgeFca0hLYIEx/2zGsszCSEJJ1JSCdiY5xQxRcLDDGa8EPvlLPupJ4DSajbMPAnC0je8jfb9TiUATnxxrHUog==", "license": "MIT", "dependencies": { @@ -7940,7 +7935,7 @@ }, "node_modules/remark-breaks": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/remark-breaks/-/remark-breaks-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/remark-breaks/-/remark-breaks-4.0.0.tgz", "integrity": "sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ==", "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 22dd901..860b525 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@codemirror/search": "^6.7.1", "@codemirror/state": "^6.7.1", "@codemirror/view": "^6.43.6", + "@fancyapps/ui": "^6.1.14", "@lezer/highlight": "^1.2.3", "@lucide/vue": "^1.23.0", "@tauri-apps/api": "^2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fc21bfc..1d55382 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: '@codemirror/view': specifier: ^6.43.6 version: 6.43.6 + '@fancyapps/ui': + specifier: ^6.1.14 + version: 6.1.14 '@lezer/highlight': specifier: ^1.2.3 version: 1.2.3 @@ -543,6 +546,9 @@ packages: resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@fancyapps/ui@6.1.14': + resolution: {integrity: sha512-cBV73XXHrc0qMca+PJJ6qay3xweIgsoYse13rGRstgUs0xA5WAv1tgbSzPCIOOjiLs2S2jiVFJxyszgvgyfxMg==} + '@floating-ui/core@1.7.5': resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} @@ -1841,6 +1847,7 @@ packages: glob@11.0.0: resolution: {integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==} engines: {node: 20 || >=22} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@7.2.0: @@ -2813,10 +2820,6 @@ packages: resolution: {integrity: sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A==} engines: {node: '>=18'} - string-width@4.2.0: - resolution: {integrity: sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==} - engines: {node: '>=8'} - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -3698,6 +3701,8 @@ snapshots: '@eslint/core': 1.2.1 levn: 0.4.1 + '@fancyapps/ui@6.1.14': {} + '@floating-ui/core@1.7.5': dependencies: '@floating-ui/utils': 0.2.11 @@ -3749,7 +3754,7 @@ snapshots: '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 - string-width-cjs: string-width@4.2.0 + string-width-cjs: string-width@4.2.3 strip-ansi: 7.2.0 strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 @@ -6186,12 +6191,6 @@ snapshots: stdin-discarder@0.3.2: {} - string-width@4.2.0: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -6470,7 +6469,7 @@ snapshots: wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 - string-width: 4.2.0 + string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi@8.1.0: diff --git a/src/components/DirectorySidebar.vue b/src/components/DirectorySidebar.vue index e8bbef6..b404aba 100644 --- a/src/components/DirectorySidebar.vue +++ b/src/components/DirectorySidebar.vue @@ -21,6 +21,11 @@ interface WorkspaceEntry { path: string; } +interface TreeExpansionCommand { + id: number; + expanded: boolean; +} + const props = withDefaults( defineProps<{ @@ -458,6 +463,7 @@ watch(showWorkspaceMenu, (open) => { watch(() => props.folderPath, () => { closeWorkspaceMenu(); + treeExpansionCommand.value = null; }); onBeforeUnmount(() => { @@ -535,6 +541,16 @@ function handleCreateRootFile() { }); } +const treeExpansionCommand = ref(null); +let treeExpansionCommandId = 0; + +function setAllFoldersExpanded(expanded: boolean) { + treeExpansionCommand.value = { + id: ++treeExpansionCommandId, + expanded, + }; +} + @@ -600,6 +616,25 @@ function handleCreateRootFile() { > + + +
{ restoreScrollAfterModeChange(scrollSnapshot); }); +onMounted(() => { + Fancybox.bind(scrollRef.value ?? null, previewImageSelector, { + groupAll: true, + placeFocusBack: true, + theme: "auto", + }); +}); + onBeforeUnmount(() => { + Fancybox.unbind(scrollRef.value ?? null, previewImageSelector); + if (modeScrollRestoreFrame !== null) { cancelAnimationFrame(modeScrollRestoreFrame); } @@ -1189,6 +1203,10 @@ defineExpose({ margin: 0.5em 0; } +.markdown-preview:not(.markdown-mixed) img { + cursor: zoom-in; +} + /* ── Mixed mode block editing ────────────────────────────────────── */ .markdown-block { diff --git a/src/components/SettingsModal.vue b/src/components/SettingsModal.vue index 8cbeaff..a4d764f 100644 --- a/src/components/SettingsModal.vue +++ b/src/components/SettingsModal.vue @@ -142,11 +142,9 @@ const syncTargetDescription = computed(() => { }); const syncFileDetails = computed(() => { const files = syncFeedback.value?.result?.files || []; - return [...files].sort((left, right) => { - if (left.action === "skip" && right.action !== "skip") return 1; - if (left.action !== "skip" && right.action === "skip") return -1; - return left.path.localeCompare(right.path); - }); + return files + .filter((file) => file.action !== "skip") + .sort((left, right) => left.path.localeCompare(right.path)); }); const menuItems: Array<{ @@ -875,7 +873,7 @@ onBeforeUnmount(() => {
- 文件明细 + 变更文件 {{ syncFileDetails.length }} 个文件
@@ -887,7 +885,7 @@ onBeforeUnmount(() => { {{ formatFileSize(file.size) }}
-

工作目录与远端都没有文件。

+

本次同步没有文件变更。

diff --git a/src/components/TreeEntry.vue b/src/components/TreeEntry.vue index e149969..25b0a95 100644 --- a/src/components/TreeEntry.vue +++ b/src/components/TreeEntry.vue @@ -15,12 +15,18 @@ interface DirEntry { children?: DirEntry[]; } +interface TreeExpansionCommand { + id: number; + expanded: boolean; +} + const TREE_CONTEXT_MENU_CLOSE_EVENT = "yurou-tree-context-menu-close"; const props = defineProps<{ entry: DirEntry; depth: number; currentFilePath?: string | null; + expansionCommand?: TreeExpansionCommand | null; }>(); const emit = defineEmits<{ @@ -33,6 +39,7 @@ const emit = defineEmits<{ }>(); const expanded = ref(true); +const handledExpansionCommandId = ref(0); const contextMenuOpen = ref(false); const contextMenuPoint = ref<{ x: number; y: number } | null>(null); const contextMenuStyle = computed(() => { @@ -76,12 +83,35 @@ function onContextMenuKeydown(event: KeyboardEvent) { watch( () => props.entry.children, (children, oldChildren) => { - if (children !== undefined && oldChildren === undefined) { + if ( + children !== undefined && + oldChildren === undefined && + props.expansionCommand?.expanded !== false + ) { expanded.value = true; } }, ); +watch( + () => props.expansionCommand, + (command) => { + if ( + !command || + !props.entry.is_dir || + command.id <= handledExpansionCommandId.value + ) return; + + handledExpansionCommandId.value = command.id; + expanded.value = command.expanded; + + if (command.expanded && props.entry.children === undefined) { + emit("toggleFolder", props.entry.path); + } + }, + { immediate: true }, +); + const isActive = computed(() => { return props.currentFilePath != null && props.currentFilePath === props.entry.path; }); @@ -307,6 +337,7 @@ function onContextMenu(event: MouseEvent) { :entry="child" :depth="depth + 1" :currentFilePath="currentFilePath" + :expansion-command="expansionCommand" @toggle-folder="(path: string) => emit('toggleFolder', path)" @open-file="(path: string) => emit('openFile', path)" @create-folder="(path: string) => emit('createFolder', path)"