Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useChangesTab } from "./hooks/useChangesTab";
import type { SidebarTabDefinition } from "./types";

interface WorkspaceSidebarProps {
onSelectFile: (absolutePath: string) => void;
onSelectFile: (absolutePath: string, openInNewTab?: boolean) => void;
onSelectDiffFile?: (path: string) => void;
onSearch?: () => void;
selectedFilePath?: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import type { AppRouter } from "@superset/host-service";
import type { ExternalApp } from "@superset/local-db";
import { alert } from "@superset/ui/atoms/Alert";
import { Button } from "@superset/ui/button";
import { toast } from "@superset/ui/sonner";
import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
import { workspaceTrpc } from "@superset/workspace-client";
import { eq } from "@tanstack/db";
import { useLiveQuery } from "@tanstack/react-db";
import type { inferRouterOutputs } from "@trpc/server";
import { FilePlus, FolderPlus, FoldVertical, RefreshCw } from "lucide-react";
import { Fragment, useCallback, useEffect, useRef, useState } from "react";
Expand All @@ -16,6 +19,9 @@ import {
useGitStatusMap,
} from "renderer/hooks/host-service/useGitStatusMap";
import { useWorkspaceEvent } from "renderer/hooks/host-service/useWorkspaceEvent";
import { electronTrpcClient } from "renderer/lib/trpc-client";
import { useCollections } from "renderer/routes/_authenticated/providers/CollectionsProvider";
import { useLocalHostService } from "renderer/routes/_authenticated/providers/LocalHostServiceProvider";
import {
ROW_HEIGHT,
TREE_INDENT,
Expand All @@ -31,7 +37,7 @@ type InlineEditState =
| null;

interface FilesTabProps {
onSelectFile: (absolutePath: string) => void;
onSelectFile: (absolutePath: string, openInNewTab?: boolean) => void;
selectedFilePath?: string;
workspaceId: string;
workspaceName?: string;
Expand All @@ -55,6 +61,7 @@ function TreeNode({
folderStatusByPath,
ignoredPaths,
onSelectFile,
onOpenInEditor,
onToggleDirectory,
onInlineEditSubmit,
onInlineEditCancel,
Expand All @@ -74,7 +81,8 @@ function TreeNode({
fileStatusByPath: Map<string, FileStatus>;
folderStatusByPath: Map<string, FileStatus>;
ignoredPaths: Set<string>;
onSelectFile: (absolutePath: string) => void;
onSelectFile: (absolutePath: string, openInNewTab?: boolean) => void;
onOpenInEditor: (absolutePath: string) => void;
onToggleDirectory: (absolutePath: string) => void;
onInlineEditSubmit: (name: string) => void;
onInlineEditCancel: () => void;
Expand Down Expand Up @@ -127,6 +135,7 @@ function TreeNode({
decoration={decoration}
isMuted={isMuted}
onSelectFile={onSelectFile}
onOpenInEditor={onOpenInEditor}
onToggleDirectory={onToggleDirectory}
onNewFile={onNewFile}
onNewFolder={onNewFolder}
Expand Down Expand Up @@ -162,6 +171,7 @@ function TreeNode({
folderStatusByPath={folderStatusByPath}
ignoredPaths={ignoredPaths}
onSelectFile={onSelectFile}
onOpenInEditor={onOpenInEditor}
onToggleDirectory={onToggleDirectory}
onInlineEditSubmit={onInlineEditSubmit}
onInlineEditCancel={onInlineEditCancel}
Expand Down Expand Up @@ -210,6 +220,53 @@ export function FilesTab({
id: workspaceId,
});
const rootPath = workspaceQuery.data?.worktreePath ?? "";
const projectId = workspaceQuery.data?.projectId;

const collections = useCollections();
const { machineId } = useLocalHostService();
const { data: workspacesWithHost = [] } = useLiveQuery(
(q) =>
q
.from({ workspaces: collections.v2Workspaces })
.leftJoin({ hosts: collections.v2Hosts }, ({ workspaces, hosts }) =>
eq(workspaces.hostId, hosts.id),
)
.where(({ workspaces }) => eq(workspaces.id, workspaceId))
.select(({ hosts }) => ({
hostMachineId: hosts?.machineId ?? null,
})),
[collections, workspaceId],
);
const workspaceHost = workspacesWithHost[0];

const { data: sidebarProjectRows = [] } = useLiveQuery(
(q) =>
q
.from({ sp: collections.v2SidebarProjects })
.where(({ sp }) => eq(sp.projectId, projectId ?? ""))
.select(({ sp }) => ({ defaultOpenInApp: sp.defaultOpenInApp })),
[collections, projectId],
);
const resolvedOpenInApp: ExternalApp =
(sidebarProjectRows[0]?.defaultOpenInApp as ExternalApp | null) ?? "finder";

const handleOpenInEditor = useCallback(
(absolutePath: string) => {
if (!workspaceHost) return;
if (workspaceHost.hostMachineId !== machineId) {
toast.error("Opening in editor is only supported on local workspaces");
return;
}
electronTrpcClient.external.openInApp
.mutate({ path: absolutePath, app: resolvedOpenInApp })
.catch((err) => {
toast.error("Couldn't open file", {
description: err instanceof Error ? err.message : String(err),
});
});
},
[workspaceHost, machineId, resolvedOpenInApp],
);

const writeFile = workspaceTrpc.filesystem.writeFile.useMutation();
const createDirectory =
Expand Down Expand Up @@ -566,6 +623,7 @@ export function FilesTab({
folderStatusByPath={folderStatusByPath}
ignoredPaths={ignoredPaths}
onSelectFile={onSelectFile}
onOpenInEditor={handleOpenInEditor}
onToggleDirectory={(absolutePath) =>
void fileTree.toggle(absolutePath)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ interface WorkspaceFilesTreeItemProps {
isHovered?: boolean;
decoration?: FileStatus;
isMuted?: boolean;
onSelectFile: (absolutePath: string) => void;
onSelectFile: (absolutePath: string, openInNewTab?: boolean) => void;
onOpenInEditor: (absolutePath: string) => void;
onToggleDirectory: (absolutePath: string) => void;
onNewFile: (parentPath: string) => void;
onNewFolder: (parentPath: string) => void;
Expand All @@ -57,6 +58,7 @@ function WorkspaceFilesTreeItemComponent({
decoration,
isMuted,
onSelectFile,
onOpenInEditor,
onToggleDirectory,
onNewFile,
onNewFolder,
Expand Down Expand Up @@ -88,11 +90,17 @@ function WorkspaceFilesTreeItemComponent({
: undefined,
isSelected ? "!bg-accent" : undefined,
)}
onClick={() =>
isFolder
? onToggleDirectory(node.absolutePath)
: onSelectFile(node.absolutePath)
}
onClick={(e) => {
if (e.metaKey || e.ctrlKey) {
onOpenInEditor(node.absolutePath);
} else if (isFolder) {
onToggleDirectory(node.absolutePath);
} else if (e.shiftKey) {
onSelectFile(node.absolutePath, true);
} else {
onSelectFile(node.absolutePath);
}
}}
style={{
height: rowHeight,
paddingLeft: 8 + (depth - 1) * indent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,24 @@ function WorkspaceContent({
});

const openFilePane = useCallback(
(filePath: string) => {
(filePath: string, openInNewTab?: boolean) => {
const state = store.getState();
if (openInNewTab) {
state.addTab({
titleOverride: filePath.split(/[/\\]/).pop(),
panes: [
{
kind: "file",
data: {
filePath,
mode: "editor",
hasChanges: false,
} as FilePaneData,
},
],
});
return;
}
const active = state.getActivePane();
if (
active?.pane.kind === "file" &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ export function FileSearchResultItem({

const handleClick = (e: React.MouseEvent) => {
if (!entry.isDirectory) {
if (e.metaKey || e.ctrlKey) {
if (e.shiftKey) {
onActivate(entry, true);
} else if (e.metaKey || e.ctrlKey) {
onOpenInEditor(entry);
} else {
onActivate(entry);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,16 @@ export function FileTreeItem({

const handleClick = (e: React.MouseEvent) => {
e.stopPropagation();
if (isFolder) {
if (e.metaKey || e.ctrlKey) {
onOpenInEditor(entry);
} else if (isFolder) {
if (isExpanded) {
item.collapse();
} else {
item.expand();
}
} else if (e.metaKey || e.ctrlKey) {
onOpenInEditor(entry);
} else if (e.shiftKey) {
onActivate(entry, true);
} else {
onActivate(entry);
}
Expand Down
Loading