From 5b9c3592458cff407cf8d050b7d3595de6ee0309 Mon Sep 17 00:00:00 2001 From: cpkt9762 Date: Tue, 10 Feb 2026 20:08:05 +0800 Subject: [PATCH] feat(app): add context menu to copy file paths in file tree Add right-click context menu to file nodes in the sidebar file tree with options to: - Copy Relative Path - Copy Absolute Path This addresses feature requests in #11820 and #11620. Includes i18n translations for all 16 supported languages. --- packages/app/src/components/file-tree.tsx | 37 +++++++++++++++++++---- packages/app/src/i18n/ar.ts | 3 ++ packages/app/src/i18n/br.ts | 3 ++ packages/app/src/i18n/bs.ts | 3 ++ packages/app/src/i18n/da.ts | 3 ++ packages/app/src/i18n/de.ts | 3 ++ packages/app/src/i18n/en.ts | 3 ++ packages/app/src/i18n/es.ts | 3 ++ packages/app/src/i18n/fr.ts | 3 ++ packages/app/src/i18n/ja.ts | 3 ++ packages/app/src/i18n/ko.ts | 3 ++ packages/app/src/i18n/no.ts | 3 ++ packages/app/src/i18n/pl.ts | 3 ++ packages/app/src/i18n/ru.ts | 3 ++ packages/app/src/i18n/th.ts | 3 ++ packages/app/src/i18n/zh.ts | 3 ++ packages/app/src/i18n/zht.ts | 3 ++ 17 files changed, 79 insertions(+), 6 deletions(-) diff --git a/packages/app/src/components/file-tree.tsx b/packages/app/src/components/file-tree.tsx index d7b7299731c..99dbed9218f 100644 --- a/packages/app/src/components/file-tree.tsx +++ b/packages/app/src/components/file-tree.tsx @@ -1,6 +1,8 @@ import { useFile } from "@/context/file" import { encodeFilePath } from "@/context/file/path" +import { useLanguage } from "@/context/language" import { Collapsible } from "@opencode-ai/ui/collapsible" +import { ContextMenu } from "@opencode-ai/ui/context-menu" import { FileIcon } from "@opencode-ai/ui/file-icon" import { Icon } from "@opencode-ai/ui/icon" import { Tooltip } from "@opencode-ai/ui/tooltip" @@ -78,6 +80,7 @@ export default function FileTree(props: { _kinds?: ReadonlyMap }) { const file = useFile() + const language = useLanguage() const level = props.level ?? 0 const draggable = () => props.draggable ?? true const tooltip = () => props.tooltip ?? true @@ -451,12 +454,34 @@ export default function FileTree(props: { - - props.onFileClick?.(node)}> -
- - - + + + + props.onFileClick?.(node)}> +
+ + + + + + + { + void navigator.clipboard.writeText(node.path) + }} + > + {language.t("filetree.copyRelativePath")} + + { + void navigator.clipboard.writeText(node.absolute) + }} + > + {language.t("filetree.copyAbsolutePath")} + + + + ) diff --git a/packages/app/src/i18n/ar.ts b/packages/app/src/i18n/ar.ts index 201d63660a3..80348a31029 100644 --- a/packages/app/src/i18n/ar.ts +++ b/packages/app/src/i18n/ar.ts @@ -503,6 +503,9 @@ export const dict = { "sidebar.project.recentSessions": "الجلسات الحديثة", "sidebar.project.viewAllSessions": "عرض جميع الجلسات", + "filetree.copyRelativePath": "نسخ المسار النسبي", + "filetree.copyAbsolutePath": "نسخ المسار المطلق", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "سطح المكتب", "settings.section.server": "الخادم", diff --git a/packages/app/src/i18n/br.ts b/packages/app/src/i18n/br.ts index b7f2d74857f..86c664dcb47 100644 --- a/packages/app/src/i18n/br.ts +++ b/packages/app/src/i18n/br.ts @@ -507,6 +507,9 @@ export const dict = { "sidebar.project.recentSessions": "Sessões recentes", "sidebar.project.viewAllSessions": "Ver todas as sessões", + "filetree.copyRelativePath": "Copiar caminho relativo", + "filetree.copyAbsolutePath": "Copiar caminho absoluto", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Desktop", "settings.section.server": "Servidor", diff --git a/packages/app/src/i18n/bs.ts b/packages/app/src/i18n/bs.ts index 05eca1628e5..39b6bb240e5 100644 --- a/packages/app/src/i18n/bs.ts +++ b/packages/app/src/i18n/bs.ts @@ -533,6 +533,9 @@ export const dict = { "sidebar.project.recentSessions": "Nedavne sesije", "sidebar.project.viewAllSessions": "Prikaži sve sesije", + "filetree.copyRelativePath": "Kopiraj relativnu putanju", + "filetree.copyAbsolutePath": "Kopiraj apsolutnu putanju", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Desktop", diff --git a/packages/app/src/i18n/da.ts b/packages/app/src/i18n/da.ts index 8ea4907c1b6..c57762067c6 100644 --- a/packages/app/src/i18n/da.ts +++ b/packages/app/src/i18n/da.ts @@ -507,6 +507,9 @@ export const dict = { "sidebar.project.recentSessions": "Seneste sessioner", "sidebar.project.viewAllSessions": "Vis alle sessioner", + "filetree.copyRelativePath": "Kopier relativ sti", + "filetree.copyAbsolutePath": "Kopier absolut sti", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Desktop", "settings.section.server": "Server", diff --git a/packages/app/src/i18n/de.ts b/packages/app/src/i18n/de.ts index a4884a1033d..249337314d8 100644 --- a/packages/app/src/i18n/de.ts +++ b/packages/app/src/i18n/de.ts @@ -551,6 +551,9 @@ export const dict = { "sidebar.project.recentSessions": "Letzte Sitzungen", "sidebar.project.viewAllSessions": "Alle Sitzungen anzeigen", + "filetree.copyRelativePath": "Relativen Pfad kopieren", + "filetree.copyAbsolutePath": "Absoluten Pfad kopieren", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Desktop", "settings.section.server": "Server", diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index b0ffa70f84d..74c89c13d28 100644 --- a/packages/app/src/i18n/en.ts +++ b/packages/app/src/i18n/en.ts @@ -577,6 +577,9 @@ export const dict = { "sidebar.project.recentSessions": "Recent sessions", "sidebar.project.viewAllSessions": "View all sessions", + "filetree.copyRelativePath": "Copy Relative Path", + "filetree.copyAbsolutePath": "Copy Absolute Path", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Desktop", diff --git a/packages/app/src/i18n/es.ts b/packages/app/src/i18n/es.ts index 50d9060703e..0e37d053ffd 100644 --- a/packages/app/src/i18n/es.ts +++ b/packages/app/src/i18n/es.ts @@ -510,6 +510,9 @@ export const dict = { "sidebar.project.recentSessions": "Sesiones recientes", "sidebar.project.viewAllSessions": "Ver todas las sesiones", + "filetree.copyRelativePath": "Copiar ruta relativa", + "filetree.copyAbsolutePath": "Copiar ruta absoluta", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Escritorio", "settings.section.server": "Servidor", diff --git a/packages/app/src/i18n/fr.ts b/packages/app/src/i18n/fr.ts index 7ad39f34063..9f0fe7fee18 100644 --- a/packages/app/src/i18n/fr.ts +++ b/packages/app/src/i18n/fr.ts @@ -517,6 +517,9 @@ export const dict = { "sidebar.project.recentSessions": "Sessions récentes", "sidebar.project.viewAllSessions": "Voir toutes les sessions", + "filetree.copyRelativePath": "Copier le chemin relatif", + "filetree.copyAbsolutePath": "Copier le chemin absolu", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Bureau", "settings.section.server": "Serveur", diff --git a/packages/app/src/i18n/ja.ts b/packages/app/src/i18n/ja.ts index a39bfbaf331..85d83ce06b9 100644 --- a/packages/app/src/i18n/ja.ts +++ b/packages/app/src/i18n/ja.ts @@ -502,6 +502,9 @@ export const dict = { "sidebar.project.recentSessions": "最近のセッション", "sidebar.project.viewAllSessions": "すべてのセッションを表示", + "filetree.copyRelativePath": "相対パスをコピー", + "filetree.copyAbsolutePath": "絶対パスをコピー", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "デスクトップ", "settings.section.server": "サーバー", diff --git a/packages/app/src/i18n/ko.ts b/packages/app/src/i18n/ko.ts index b5927b21076..b7beea7c5ab 100644 --- a/packages/app/src/i18n/ko.ts +++ b/packages/app/src/i18n/ko.ts @@ -508,6 +508,9 @@ export const dict = { "sidebar.project.recentSessions": "최근 세션", "sidebar.project.viewAllSessions": "모든 세션 보기", + "filetree.copyRelativePath": "상대 경로 복사", + "filetree.copyAbsolutePath": "절대 경로 복사", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "데스크톱", "settings.section.server": "서버", diff --git a/packages/app/src/i18n/no.ts b/packages/app/src/i18n/no.ts index 7d8cdd27f3d..b9ab7c85ff8 100644 --- a/packages/app/src/i18n/no.ts +++ b/packages/app/src/i18n/no.ts @@ -510,6 +510,9 @@ export const dict = { "sidebar.project.recentSessions": "Nylige sesjoner", "sidebar.project.viewAllSessions": "Vis alle sesjoner", + "filetree.copyRelativePath": "Kopier relativ sti", + "filetree.copyAbsolutePath": "Kopier absolutt sti", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Skrivebord", "settings.section.server": "Server", diff --git a/packages/app/src/i18n/pl.ts b/packages/app/src/i18n/pl.ts index 76a47ea26f8..c17e675f52c 100644 --- a/packages/app/src/i18n/pl.ts +++ b/packages/app/src/i18n/pl.ts @@ -509,6 +509,9 @@ export const dict = { "sidebar.project.recentSessions": "Ostatnie sesje", "sidebar.project.viewAllSessions": "Zobacz wszystkie sesje", + "filetree.copyRelativePath": "Kopiuj ścieżkę względną", + "filetree.copyAbsolutePath": "Kopiuj ścieżkę bezwzględną", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Pulpit", "settings.section.server": "Serwer", diff --git a/packages/app/src/i18n/ru.ts b/packages/app/src/i18n/ru.ts index e83ce37618c..b027dcefd4a 100644 --- a/packages/app/src/i18n/ru.ts +++ b/packages/app/src/i18n/ru.ts @@ -512,6 +512,9 @@ export const dict = { "sidebar.project.recentSessions": "Недавние сессии", "sidebar.project.viewAllSessions": "Посмотреть все сессии", + "filetree.copyRelativePath": "Копировать относительный путь", + "filetree.copyAbsolutePath": "Копировать абсолютный путь", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Приложение", "settings.section.server": "Сервер", diff --git a/packages/app/src/i18n/th.ts b/packages/app/src/i18n/th.ts index 2be19d15b17..476170f3004 100644 --- a/packages/app/src/i18n/th.ts +++ b/packages/app/src/i18n/th.ts @@ -510,6 +510,9 @@ export const dict = { "sidebar.project.recentSessions": "เซสชันล่าสุด", "sidebar.project.viewAllSessions": "ดูเซสชันทั้งหมด", + "filetree.copyRelativePath": "คัดลอกเส้นทางสัมพัทธ์", + "filetree.copyAbsolutePath": "คัดลอกเส้นทางสมบูรณ์", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "เดสก์ท็อป", diff --git a/packages/app/src/i18n/zh.ts b/packages/app/src/i18n/zh.ts index a48f9e54941..2f948916d9f 100644 --- a/packages/app/src/i18n/zh.ts +++ b/packages/app/src/i18n/zh.ts @@ -543,6 +543,9 @@ export const dict = { "sidebar.project.recentSessions": "最近会话", "sidebar.project.viewAllSessions": "查看全部会话", + "filetree.copyRelativePath": "复制相对路径", + "filetree.copyAbsolutePath": "复制绝对路径", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "桌面", "settings.section.server": "服务器", diff --git a/packages/app/src/i18n/zht.ts b/packages/app/src/i18n/zht.ts index 60363fc99ef..3222d4301fc 100644 --- a/packages/app/src/i18n/zht.ts +++ b/packages/app/src/i18n/zht.ts @@ -540,6 +540,9 @@ export const dict = { "sidebar.project.recentSessions": "最近工作階段", "sidebar.project.viewAllSessions": "查看全部工作階段", + "filetree.copyRelativePath": "複製相對路徑", + "filetree.copyAbsolutePath": "複製絕對路徑", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "桌面", "settings.section.server": "伺服器",