Use external open API in Files plugin

This commit is contained in:
2026-06-27 13:34:16 +08:00
parent bf21df14f1
commit 084580d3fd
4 changed files with 46 additions and 19 deletions
+8 -9
View File
@@ -9,7 +9,7 @@
| # | Feature | Приоритет | Зависит от |
|---|---------|-----------|------------|
| 1 | Контекстное меню (правый клик) | 🔥 High | — |
| 2 | Open External / Show in Explorer fallback | ✅ Done | |
| 2 | Open External / Show in Explorer | ✅ Done | `files.openExternal` |
| 3 | Кастомный ConfirmModal | 🔥 High | — |
| 4 | Duplicate | 🔥 High | — |
| 5 | Cut/Copy/Paste | 🔥 High | — |
@@ -38,16 +38,15 @@
---
### Feature 2: Open External / Show in Explorer fallback
### Feature 2: Open External / Show in Explorer
**Описание:** Пункты меню для будущего открытия файла во внешнем приложении и
показа папки в системном файловом менеджере.
**Описание:** Пункты меню для открытия файла во внешнем приложении и показа
файла/папки в системном файловом менеджере.
**Текущий v2 статус:** core/runtime API для внешнего открытия пока нет, поэтому
пункты меню показывают fallback modal с vault-relative path и кнопкой `Copy Path`.
Никаких v1 Wails мостов или прямых backend calls.
Полное внешнее открытие остается deferred до отдельного публичного v2 API.
**Текущий v2 статус:** плагин использует публичные методы
`api.files.openExternal(relativePath)` и `api.files.showInFolder(relativePath)`,
guarded by `files.openExternal`. Fallback modal с vault-relative path и кнопкой
`Copy Path` показывается только если API недоступен или вернул ошибку.
**Файлы:** `plugins/files/frontend/src/index.js`
+17 -4
View File
@@ -271,14 +271,14 @@
return Promise.reject(new Error('clipboard unavailable'));
}
function showExternalFallback(entry, mode) {
function showExternalFallback(entry, mode, reason) {
if (!entry) return;
var pathToShow = entry.relativePath;
if (mode === 'explorer' && entry.type !== 'folder') {
pathToShow = parentPath(entry.relativePath) || entry.relativePath;
}
var title = mode === 'explorer' ? 'Show in Explorer' : 'Open External';
var message = title + ' is not available in the current v2 runtime yet.\nVault-relative path:\n' + pathToShow;
var message = title + ' failed.\n' + (reason ? String(reason) + '\n' : '') + 'Vault-relative path:\n' + pathToShow;
confirmModal(message, { confirmText: 'Copy Path', cancelText: 'Close' }).then(function (copy) {
if (!copy) return;
copyTextToClipboard(pathToShow).catch(function (err) {
@@ -796,6 +796,19 @@
return el('div', { className: 'files-ctx-menu-sep' });
}
function openExternalEntry(entry, mode) {
if (!entry) return;
var filesApi = api && api.files;
var action = mode === 'explorer' ? filesApi && filesApi.showInFolder : filesApi && filesApi.openExternal;
if (typeof action !== 'function') {
showExternalFallback(entry, mode, 'files external-open API is unavailable.');
return;
}
action(entry.relativePath).catch(function (err) {
showExternalFallback(entry, mode, err && err.message ? err.message : err);
});
}
function showCtxMenu(x, y, entry) {
ctxTarget = entry;
ctxMenu.innerHTML = '';
@@ -808,8 +821,8 @@
}
var isFolder = entry.type === 'folder';
ctxMenu.appendChild(ctxItem(isFolder ? 'Open Folder' : 'Open', '', function () { openEntry(entry); }, 'open', 'open'));
ctxMenu.appendChild(ctxItem('Open External', '', function () { showExternalFallback(entry, 'external'); }, 'open-external', 'external'));
ctxMenu.appendChild(ctxItem('Show in Explorer', '', function () { showExternalFallback(entry, 'explorer'); }, 'show-in-explorer', 'explorer'));
ctxMenu.appendChild(ctxItem('Open External', '', function () { openExternalEntry(entry, 'external'); }, 'open-external', 'external'));
ctxMenu.appendChild(ctxItem('Show in Explorer', '', function () { openExternalEntry(entry, 'explorer'); }, 'show-in-explorer', 'explorer'));
ctxMenu.appendChild(ctxSep());
ctxMenu.appendChild(ctxItem('Rename', '', function () { beginRename(entry); }, 'rename', 'rename'));
if (entry.type !== 'folder') {
+1
View File
@@ -18,6 +18,7 @@
"files.read",
"files.write",
"files.delete",
"files.openExternal",
"workbench.open",
"ui.register"
],