Skip to content

Commit 30176bd

Browse files
lucienlmymcthesw
authored andcommitted
feat(ui): 增加文件点击时按住Ctrl打开父文件夹的功能
在SaveLocationDrawer.vue中增加了一个新的异步函数handleOpenPath,用于处理文件路径的点击事件,并根据是否按住Ctrl键来决定是打开文件本身还是打开其包含的文件夹。同时,对模板中的两个按钮添加了el-tooltip,用于显示提示信息。 在locales/en_US.json和locales/zh_SIMPLIFIED.json中添加了新的翻译项"open_ctrl_hint",分别对应英文和简体中文的提示信息,用于告知用户如何通过按住Ctrl键来打开父文件夹。
1 parent a6ac7ef commit 30176bd

4 files changed

Lines changed: 77 additions & 26 deletions

File tree

apps/rgsm-gui/src/components/PathVariableInput.vue

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -190,17 +190,18 @@ function getCursorOffset(): number {
190190
const sel = window.getSelection();
191191
if (!sel || sel.rangeCount === 0) return -1;
192192
const range = sel.getRangeAt(0);
193-
if (!editorRef.value.contains(range.startContainer)) return -1;
193+
if (!editorRef.value.contains(range.startContainer as Node)) return -1;
194194
195195
let offset = 0;
196-
const children = Array.from(editorRef.value.childNodes);
196+
const children = Array.from((editorRef.value as unknown as HTMLElement).childNodes) as Node[];
197197
198198
for (let i = 0; i < children.length; i++) {
199199
const node = children[i];
200200
if (!node) continue;
201-
if (range.startContainer === editorRef.value && i === range.startOffset) return offset;
201+
if (range.startContainer === (editorRef.value as unknown as Node) && i === range.startOffset)
202+
return offset;
202203
if (range.startContainer === node) return offset + range.startOffset;
203-
if (node.contains(range.startContainer)) return offset;
204+
if (node.contains(range.startContainer as Node)) return offset;
204205
offset += nodeRawLen(node);
205206
}
206207
@@ -213,17 +214,17 @@ function setCursorAtOffset(targetOffset: number) {
213214
if (!sel) return;
214215
215216
let offset = 0;
216-
const children = Array.from(editorRef.value.childNodes);
217+
const children = Array.from((editorRef.value as unknown as HTMLElement).childNodes) as Node[];
217218
218219
for (const node of children) {
219220
const len = nodeRawLen(node);
220221
if (offset + len >= targetOffset) {
221222
const r = document.createRange();
222223
if (node.nodeType === Node.TEXT_NODE) {
223224
const pos = Math.min(targetOffset - offset, node.textContent?.length || 0);
224-
r.setStart(node, pos);
225+
r.setStart(node as Node, pos);
225226
} else {
226-
r.setStartAfter(node);
227+
r.setStartAfter(node as Node);
227228
}
228229
r.collapse(true);
229230
sel.removeAllRanges();
@@ -234,7 +235,7 @@ function setCursorAtOffset(targetOffset: number) {
234235
}
235236
236237
const r = document.createRange();
237-
r.selectNodeContents(editorRef.value);
238+
r.selectNodeContents(editorRef.value as unknown as Node);
238239
r.collapse(false);
239240
sel.removeAllRanges();
240241
sel.addRange(r);
@@ -347,9 +348,10 @@ function onKeydown(e: KeyboardEvent) {
347348
const range = sel.getRangeAt(0);
348349
if (range.collapsed) {
349350
let nodeBefore: Node | null = null;
350-
if (range.startContainer === editorRef.value) {
351+
if (range.startContainer === (editorRef.value as unknown as Node)) {
351352
const idx = range.startOffset - 1;
352-
if (idx >= 0) nodeBefore = editorRef.value.childNodes[idx] ?? null;
353+
if (idx >= 0)
354+
nodeBefore = (editorRef.value as unknown as HTMLElement).childNodes[idx] ?? null;
353355
} else if (range.startOffset === 0) {
354356
nodeBefore = range.startContainer.previousSibling;
355357
}

apps/rgsm-gui/src/components/SaveLocationDrawer.vue

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,35 @@ function formatUnitType(unitType: SaveUnit['unit_type']) {
395395
return unitType;
396396
}
397397
}
398+
399+
async function handleOpenPath(e: MouseEvent, path: string, unit?: SaveUnit) {
400+
if (!path || !path.trim()) return;
401+
402+
const ctrl = (e && (e as MouseEvent).ctrlKey) || (e && (e as MouseEvent).metaKey);
403+
if (ctrl && unit && unit.unit_type === 'File') {
404+
const normalized = path.replace(/\\/g, '/');
405+
const idx = normalized.lastIndexOf('/');
406+
const parent = idx > -1 ? normalized.substring(0, idx) : normalized;
407+
try {
408+
const result = await commands.openFileOrFolder(parent);
409+
if (result.status === 'error') {
410+
showError({ message: $t('error.open_url_failed') });
411+
}
412+
} catch {
413+
showError({ message: $t('error.open_url_failed') });
414+
}
415+
return;
416+
}
417+
418+
try {
419+
const result = await commands.openFileOrFolder(path);
420+
if (result.status === 'error') {
421+
showError({ message: $t('error.open_url_failed') });
422+
}
423+
} catch {
424+
showError({ message: $t('error.open_url_failed') });
425+
}
426+
}
398427
</script>
399428

400429
<template>
@@ -539,14 +568,23 @@ function formatUnitType(unitType: SaveUnit['unit_type']) {
539568
}}</el-tag>
540569
</div>
541570
<div class="unit-card-actions">
542-
<el-button
543-
text
544-
size="small"
545-
:disabled="!getDevicePath(unit, selectedDeviceId)"
546-
@click="openPath(getDevicePath(unit, selectedDeviceId))"
571+
<el-tooltip
572+
:content="
573+
unit.unit_type === 'File'
574+
? $t('save_location_drawer.open_ctrl_hint')
575+
: $t('save_location_drawer.open')
576+
"
577+
placement="top"
547578
>
548-
{{ $t('save_location_drawer.open') }}
549-
</el-button>
579+
<el-button
580+
text
581+
size="small"
582+
:disabled="!getDevicePath(unit, selectedDeviceId)"
583+
@click="(e) => handleOpenPath(e, getDevicePath(unit, selectedDeviceId), unit)"
584+
>
585+
{{ $t('save_location_drawer.open') }}
586+
</el-button>
587+
</el-tooltip>
550588
<el-button text size="small" @click="chooseUnitPath(unit)">
551589
{{ $t('save_location_drawer.pick_path') }}
552590
</el-button>
@@ -624,14 +662,23 @@ function formatUnitType(unitType: SaveUnit['unit_type']) {
624662
<el-button text size="small" @click="chooseUnitPath(unit)">
625663
{{ $t('save_location_drawer.pick_path') }}
626664
</el-button>
627-
<el-button
628-
text
629-
size="small"
630-
:disabled="!getDevicePath(unit, selectedDeviceId)"
631-
@click="openPath(getDevicePath(unit, selectedDeviceId))"
665+
<el-tooltip
666+
:content="
667+
unit.unit_type === 'File'
668+
? $t('save_location_drawer.open_ctrl_hint')
669+
: $t('save_location_drawer.open')
670+
"
671+
placement="top"
632672
>
633-
{{ $t('save_location_drawer.open') }}
634-
</el-button>
673+
<el-button
674+
text
675+
size="small"
676+
:disabled="!getDevicePath(unit, selectedDeviceId)"
677+
@click="(e) => handleOpenPath(e, getDevicePath(unit, selectedDeviceId), unit)"
678+
>
679+
{{ $t('save_location_drawer.open') }}
680+
</el-button>
681+
</el-tooltip>
635682
<el-button type="primary" size="small" plain @click="setUnitEnabled(unit, true)">
636683
{{ $t('save_location_drawer.restore') }}
637684
</el-button>

locales/en_US.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,8 @@
452452
"no_active_paths": "No active save locations yet. Add a folder, file, or registry key to start backing up this game.",
453453
"type_folder": "Folder",
454454
"type_file": "File",
455-
"type_registry": "Registry"
455+
"type_registry": "Registry",
456+
"open_ctrl_hint": "Hold Ctrl and click to open the containing folder"
456457
},
457458
"sync_settings": {
458459
"title": "Sync settings",

locales/zh_SIMPLIFIED.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,8 @@
452452
"no_active_paths": "还没有启用中的存档路径。新增文件夹、文件或注册表项后即可开始备份。",
453453
"type_folder": "文件夹",
454454
"type_file": "文件",
455-
"type_registry": "注册表"
455+
"type_registry": "注册表",
456+
"open_ctrl_hint": "按住 Ctrl 并点击打开父文件夹"
456457
},
457458
"sync_settings": {
458459
"title": "同步设置",

0 commit comments

Comments
 (0)