Skip to content

Commit 1fd277a

Browse files
authored
fix: Open active file in external app instead of repo directory (#1470)
## Problem Clicking "Open in [app]" always opened the repo root directory, even when a specific file was active in the editor. <!-- Who is this for and what problem does it solve? --> <!-- Closes #ISSUE_ID --> ## Changes 1. Derive active file path from panel layout store in TaskDetail 2. Join relative path with repo path as the external app target, fall back to repo directory 3. Add fixed overlay to prevent drag-through when dropdown menu is open 4. Fix dead diff type check and normalize path joining <!-- What did you change and why? --> <!-- If there are frontend changes, include screenshots. --> ## How did you test this? Manually <!-- Describe what you tested -- manual steps, automated tests, or both. --> <!-- If you're an agent, only list tests you actually ran. -->
1 parent 613748b commit 1fd277a

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

apps/code/src/renderer/features/task-detail/components/ExternalAppsOpener.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ChevronDownIcon } from "@radix-ui/react-icons";
44
import { Button, DropdownMenu, Flex, Text } from "@radix-ui/themes";
55
import { SHORTCUTS } from "@renderer/constants/keyboard-shortcuts";
66
import { handleExternalAppAction } from "@utils/handleExternalAppAction";
7-
import { useCallback } from "react";
7+
import { useCallback, useState } from "react";
88
import { useHotkeys } from "react-hotkeys-hook";
99

1010
const THUMBNAIL_ICON_SIZE = 20;
@@ -20,6 +20,7 @@ export function ExternalAppsOpener({
2020
label = "Open",
2121
}: ExternalAppsOpenerProps) {
2222
const { detectedApps, defaultApp, isLoading } = useExternalApps();
23+
const [dropdownOpen, setDropdownOpen] = useState(false);
2324

2425
const handleOpenDefault = useCallback(async () => {
2526
if (!defaultApp || !targetPath) return;
@@ -81,7 +82,17 @@ export function ExternalAppsOpener({
8182
const isReady = !isLoading && detectedApps.length > 0;
8283

8384
return (
84-
<DropdownMenu.Root>
85+
<DropdownMenu.Root open={dropdownOpen} onOpenChange={setDropdownOpen}>
86+
{dropdownOpen && (
87+
<div
88+
className="no-drag"
89+
style={{
90+
position: "fixed",
91+
inset: 0,
92+
zIndex: 1,
93+
}}
94+
/>
95+
)}
8596
<Flex className="no-drag">
8697
<Button
8798
size="1"

apps/code/src/renderer/features/task-detail/components/TaskDetail.tsx

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { FilePicker } from "@features/command/components/FilePicker";
22
import { PanelLayout } from "@features/panels";
3+
import { usePanelLayoutStore } from "@features/panels/store/panelLayoutStore";
4+
import {
5+
getLeafPanel,
6+
parseTabId,
7+
} from "@features/panels/store/panelStoreHelpers";
38
import { useCwd } from "@features/sidebar/hooks/useCwd";
49
import { useTaskData } from "@features/task-detail/hooks/useTaskData";
510
import { useTaskStore } from "@features/tasks/stores/taskStore";
@@ -30,6 +35,28 @@ export function TaskDetail({ task: initialTask }: TaskDetailProps) {
3035

3136
const effectiveRepoPath = useCwd(taskId);
3237

38+
const activeRelativePath = usePanelLayoutStore((state) => {
39+
const layout = state.getLayout(taskId);
40+
if (!layout) return null;
41+
42+
const panelId = layout.focusedPanelId;
43+
if (!panelId) return null;
44+
45+
const panel = getLeafPanel(layout.panelTree, panelId);
46+
if (!panel) return null;
47+
48+
const parsed = parseTabId(panel.content.activeTabId);
49+
if (parsed.type === "file") {
50+
return parsed.value;
51+
}
52+
return null;
53+
});
54+
55+
const openTargetPath =
56+
activeRelativePath && effectiveRepoPath
57+
? [effectiveRepoPath, activeRelativePath].join("/").replace(/\/+/g, "/")
58+
: effectiveRepoPath;
59+
3360
const [filePickerOpen, setFilePickerOpen] = useState(false);
3461

3562
const { enableScope, disableScope } = useHotkeysContext();
@@ -60,12 +87,10 @@ export function TaskDetail({ task: initialTask }: TaskDetailProps) {
6087
{task.title}
6188
</Text>
6289
</Flex>
63-
{effectiveRepoPath && (
64-
<ExternalAppsOpener targetPath={effectiveRepoPath} />
65-
)}
90+
{openTargetPath && <ExternalAppsOpener targetPath={openTargetPath} />}
6691
</Flex>
6792
),
68-
[task.title, effectiveRepoPath],
93+
[task.title, openTargetPath],
6994
);
7095

7196
useSetHeaderContent(headerContent);

0 commit comments

Comments
 (0)