feat(folder): add Add to session actions in changes menus

Add the Add to session context action for tracked and untracked nodes in the Changes panel, including root, directory, and file entries.

Reorder Changes context actions so Add to session is placed below View diff, and Rollback is placed below Add to VCS.

Update attachToCurrentSession translations to the Add to session wording across all supported locales.
This commit is contained in:
xintaofei
2026-04-15 09:54:07 +08:00
parent 11b6a4f051
commit 66549ce2f7
11 changed files with 105 additions and 30 deletions

View File

@@ -35,6 +35,7 @@ import {
} from "@/components/ui/context-menu"
import { Skeleton } from "@/components/ui/skeleton"
import { useFolderContext } from "@/contexts/folder-context"
import { useTabContext } from "@/contexts/tab-context"
import { useWorkspaceContext } from "@/contexts/workspace-context"
import { useWorkspaceStateStore } from "@/hooks/use-workspace-state-store"
import {
@@ -44,6 +45,8 @@ import {
gitStatus,
openCommitWindow,
} from "@/lib/api"
import { joinFsPath } from "@/lib/path-utils"
import { emitAttachFileToSession } from "@/lib/session-attachment-events"
import type { GitStatusEntry } from "@/lib/types"
import {
AlertDialog,
@@ -373,7 +376,9 @@ function canOpenFile(status: string): boolean {
export function GitChangesTab() {
const t = useTranslations("Folder.gitChangesTab")
const tCommon = useTranslations("Folder.common")
const tFileTree = useTranslations("Folder.fileTreeTab")
const { folder } = useFolderContext()
const { tabs, activeTabId } = useTabContext()
const { openFilePreview, openWorkingTreeDiff } = useWorkspaceContext()
const workspaceState = useWorkspaceStateStore(folder?.path ?? null)
@@ -413,6 +418,12 @@ export function GitChangesTab() {
const parts = path.split(/[\\/]/).filter(Boolean)
return (parts[parts.length - 1] ?? path) || t("workspace")
}, [folder?.path, t])
const activeSessionTabId = useMemo(() => {
const activeTab = tabs.find((tab) => tab.id === activeTabId)
if (!activeTab || activeTab.kind !== "conversation") return null
return activeTab.id
}, [activeTabId, tabs])
const canAttachToSession = Boolean(activeSessionTabId && folder?.path)
const changes = useMemo<WorkingTreeChange[]>(() => {
return [...workspaceState.git]
@@ -557,6 +568,16 @@ export function GitChangesTab() {
})
})
}, [folder, t])
const handleAttachToSession = useCallback(
(relativePath: string) => {
if (!activeSessionTabId || !folder?.path) return
emitAttachFileToSession({
tabId: activeSessionTabId,
path: joinFsPath(folder.path, relativePath),
})
},
[activeSessionTabId, folder?.path]
)
const resetDirectoryGitActionDialog = useCallback(() => {
setDirectoryGitActionType(null)
@@ -836,6 +857,17 @@ export function GitChangesTab() {
>
{tCommon("viewDiff")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleAttachToSession(node.path)
}}
disabled={!canAttachToSession}
>
{tFileTree("attachToCurrentSession")}
</ContextMenuItem>
<ContextMenuItem disabled>
{t("actions.addToVcs")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestRollback(target)
@@ -844,9 +876,6 @@ export function GitChangesTab() {
>
{t("actions.rollback")}
</ContextMenuItem>
<ContextMenuItem disabled>
{t("actions.addToVcs")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestDelete(target, "tracked")
@@ -920,6 +949,15 @@ export function GitChangesTab() {
>
{tCommon("viewDiff")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleAttachToSession(file.path)
}}
disabled={!canAttachToSession}
>
{tFileTree("attachToCurrentSession")}
</ContextMenuItem>
<ContextMenuItem disabled>{t("actions.addToVcs")}</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestRollback(target)
@@ -928,7 +966,6 @@ export function GitChangesTab() {
>
{t("actions.rollback")}
</ContextMenuItem>
<ContextMenuItem disabled>{t("actions.addToVcs")}</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestDelete(target, "tracked")
@@ -942,6 +979,8 @@ export function GitChangesTab() {
)
},
[
canAttachToSession,
handleAttachToSession,
handleOpenCommitWindow,
handleRequestDelete,
handleRequestRollback,
@@ -949,6 +988,7 @@ export function GitChangesTab() {
openWorkingTreeDiff,
t,
tCommon,
tFileTree,
]
)
@@ -991,11 +1031,11 @@ export function GitChangesTab() {
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestRollback(target)
handleAttachToSession(node.path)
}}
variant="destructive"
disabled={!canAttachToSession}
>
{t("actions.rollback")}
{tFileTree("attachToCurrentSession")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
@@ -1004,6 +1044,14 @@ export function GitChangesTab() {
>
{t("actions.addToVcs")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestRollback(target)
}}
variant="destructive"
>
{t("actions.rollback")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestDelete(target, "untracked")
@@ -1069,11 +1117,11 @@ export function GitChangesTab() {
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestRollback(target)
handleAttachToSession(file.path)
}}
variant="destructive"
disabled={!canAttachToSession}
>
{t("actions.rollback")}
{tFileTree("attachToCurrentSession")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
@@ -1082,6 +1130,14 @@ export function GitChangesTab() {
>
{t("actions.addToVcs")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestRollback(target)
}}
variant="destructive"
>
{t("actions.rollback")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestDelete(target, "untracked")
@@ -1095,6 +1151,8 @@ export function GitChangesTab() {
)
},
[
canAttachToSession,
handleAttachToSession,
handleOpenCommitWindow,
handleAddToVcs,
handleRequestDelete,
@@ -1103,6 +1161,7 @@ export function GitChangesTab() {
openWorkingTreeDiff,
t,
tCommon,
tFileTree,
]
)
@@ -1200,6 +1259,17 @@ export function GitChangesTab() {
>
{tCommon("viewDiff")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleAttachToSession("")
}}
disabled={!canAttachToSession}
>
{tFileTree("attachToCurrentSession")}
</ContextMenuItem>
<ContextMenuItem disabled>
{t("actions.addToVcs")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestRollback({
@@ -1212,9 +1282,6 @@ export function GitChangesTab() {
>
{t("actions.rollback")}
</ContextMenuItem>
<ContextMenuItem disabled>
{t("actions.addToVcs")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
@@ -1303,15 +1370,11 @@ export function GitChangesTab() {
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestRollback({
kind: "dir",
path: "",
name: folderName,
})
handleAttachToSession("")
}}
variant="destructive"
disabled={!canAttachToSession}
>
{t("actions.rollback")}
{tFileTree("attachToCurrentSession")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
@@ -1324,6 +1387,18 @@ export function GitChangesTab() {
>
{t("actions.addToVcs")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestRollback({
kind: "dir",
path: "",
name: folderName,
})
}}
variant="destructive"
>
{t("actions.rollback")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
handleRequestDelete(

View File

@@ -1282,7 +1282,7 @@
"openInFileManager": "فتح في مدير الملفات",
"openInFinder": "فتح في Finder",
"openInExplorer": "فتح في Explorer",
"attachToCurrentSession": رفاق بالجلسة الحالية",
"attachToCurrentSession": ضافة إلى الجلسة",
"compareWithBranch": "المقارنة مع الفرع...",
"reloadFromDisk": "إعادة التحميل من القرص",
"new": "جديد",

View File

@@ -1282,7 +1282,7 @@
"openInFileManager": "Im Dateimanager öffnen",
"openInFinder": "In Finder öffnen",
"openInExplorer": "In Explorer öffnen",
"attachToCurrentSession": "An aktuelle Sitzung anhängen",
"attachToCurrentSession": "Zur Sitzung hinzufügen",
"compareWithBranch": "Mit Branch vergleichen...",
"reloadFromDisk": "Von Datenträger neu laden",
"new": "Neu",

View File

@@ -1282,7 +1282,7 @@
"openInFileManager": "Open in file manager",
"openInFinder": "Open in Finder",
"openInExplorer": "Open in Explorer",
"attachToCurrentSession": "Attach to current session",
"attachToCurrentSession": "Add to session",
"compareWithBranch": "Compare with branch...",
"reloadFromDisk": "Reload from disk",
"new": "New",

View File

@@ -1282,7 +1282,7 @@
"openInFileManager": "Abrir en el gestor de archivos",
"openInFinder": "Abrir en Finder",
"openInExplorer": "Abrir en Explorer",
"attachToCurrentSession": "Adjuntar a la sesión actual",
"attachToCurrentSession": "Agregar a la sesión",
"compareWithBranch": "Comparar con rama...",
"reloadFromDisk": "Recargar desde disco",
"new": "Nuevo",

View File

@@ -1282,7 +1282,7 @@
"openInFileManager": "Ouvrir dans le gestionnaire de fichiers",
"openInFinder": "Ouvrir dans Finder",
"openInExplorer": "Ouvrir dans Explorer",
"attachToCurrentSession": "Attacher à la session actuelle",
"attachToCurrentSession": "Ajouter à la session",
"compareWithBranch": "Comparer avec la branche...",
"reloadFromDisk": "Recharger depuis le disque",
"new": "Nouveau",

View File

@@ -1282,7 +1282,7 @@
"openInFileManager": "ファイルマネージャーで開く",
"openInFinder": "Finderで開く",
"openInExplorer": "エクスプローラーで開く",
"attachToCurrentSession": "現在のセッションに添付",
"attachToCurrentSession": "セッションに追加",
"compareWithBranch": "ブランチと比較...",
"reloadFromDisk": "ディスクから再読み込み",
"new": "新規作成",

View File

@@ -1282,7 +1282,7 @@
"openInFileManager": "파일 관리자에서 열기",
"openInFinder": "Finder에서 열기",
"openInExplorer": "Explorer에서 열기",
"attachToCurrentSession": "현재 세션에 연결",
"attachToCurrentSession": "세션에 추가",
"compareWithBranch": "브랜치와 비교...",
"reloadFromDisk": "디스크에서 다시 불러오기",
"new": "새로 만들기",

View File

@@ -1282,7 +1282,7 @@
"openInFileManager": "Abrir no gerenciador de arquivos",
"openInFinder": "Abrir no Finder",
"openInExplorer": "Abrir no Explorer",
"attachToCurrentSession": "Anexar à sessão atual",
"attachToCurrentSession": "Adicionar à sessão",
"compareWithBranch": "Comparar com branch...",
"reloadFromDisk": "Recarregar do disco",
"new": "Novo",

View File

@@ -1282,7 +1282,7 @@
"openInFileManager": "在文件管理器打开",
"openInFinder": "在访达打开",
"openInExplorer": "在资源管理器打开",
"attachToCurrentSession": "加到当前会话",
"attachToCurrentSession": "加到会话",
"compareWithBranch": "与分支比较...",
"reloadFromDisk": "从磁盘重新加载",
"new": "新建",

View File

@@ -1282,7 +1282,7 @@
"openInFileManager": "在檔案管理器開啟",
"openInFinder": "在 Finder 開啟",
"openInExplorer": "在檔案總管開啟",
"attachToCurrentSession": "加到目前會話",
"attachToCurrentSession": "加到會話",
"compareWithBranch": "與分支比較...",
"reloadFromDisk": "從磁碟重新載入",
"new": "新建",