mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Open project and workspace folders from the sidebar (#2491)
* feat(app): open project folder from project context menu (#2487) * refactor(app): give file manager action a home --------- Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
This commit is contained in:
@@ -131,6 +131,7 @@ import {
|
||||
getIsElectron,
|
||||
} from "@/constants/platform";
|
||||
import { getDesktopHost } from "@/desktop/host";
|
||||
import { OpenInFileManagerMenuItem } from "@/workspace/open-in-file-manager/menu-item";
|
||||
|
||||
const workspaceKeyExtractor = (workspace: SidebarWorkspacePlacement) => workspace.workspaceKey;
|
||||
|
||||
@@ -609,6 +610,10 @@ function ProjectKebabMenu({
|
||||
{t("sidebar.project.actions.openNewWindow")}
|
||||
</DropdownMenuItem>
|
||||
) : null}
|
||||
<OpenInFileManagerMenuItem
|
||||
path={projectPath}
|
||||
testID={`sidebar-project-menu-open-folder-${projectKey}`}
|
||||
/>
|
||||
<DropdownMenuItem
|
||||
testID={`sidebar-project-menu-remove-${projectKey}`}
|
||||
leading={trash2LeadingIcon}
|
||||
@@ -660,6 +665,7 @@ function WorkspaceRowRightGroup({
|
||||
isPinned?: boolean;
|
||||
onTogglePin?: () => void;
|
||||
}) {
|
||||
const workspacePath = workspace.workspaceDirectory ?? workspace.projectRootPath;
|
||||
const { t } = useTranslation();
|
||||
const showShortcut = showShortcutBadge && shortcutNumber !== null;
|
||||
const showKebab = Boolean(onArchive && (isHovered || isTouchPlatform));
|
||||
@@ -698,6 +704,7 @@ function WorkspaceRowRightGroup({
|
||||
archiveShortcutKeys={archiveShortcutKeys}
|
||||
isPinned={isPinned}
|
||||
onTogglePin={onTogglePin}
|
||||
openInFileManagerPath={workspacePath}
|
||||
/>
|
||||
) : null}
|
||||
</SidebarWorkspaceTrailingActionOverlay>
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Shortcut } from "@/components/ui/shortcut";
|
||||
import { OpenInFileManagerMenuItem } from "@/workspace/open-in-file-manager/menu-item";
|
||||
|
||||
const foregroundColorMapping = (theme: Theme) => ({ color: theme.colors.foreground });
|
||||
const foregroundMutedColorMapping = (theme: Theme) => ({
|
||||
@@ -58,6 +59,7 @@ interface SidebarWorkspaceMenuProps {
|
||||
archiveShortcutKeys?: ShortcutKey[][] | null;
|
||||
isPinned?: boolean;
|
||||
onTogglePin?: () => void;
|
||||
openInFileManagerPath?: string | null;
|
||||
}
|
||||
|
||||
export function SidebarWorkspaceMenu({
|
||||
@@ -73,6 +75,7 @@ export function SidebarWorkspaceMenu({
|
||||
archiveShortcutKeys,
|
||||
isPinned,
|
||||
onTogglePin,
|
||||
openInFileManagerPath,
|
||||
}: SidebarWorkspaceMenuProps) {
|
||||
const { t } = useTranslation();
|
||||
const archiveTrailing = useMemo(
|
||||
@@ -137,6 +140,10 @@ export function SidebarWorkspaceMenu({
|
||||
{isPinned ? t("sidebar.workspace.actions.unpin") : t("sidebar.workspace.actions.pin")}
|
||||
</DropdownMenuItem>
|
||||
) : null}
|
||||
<OpenInFileManagerMenuItem
|
||||
path={openInFileManagerPath}
|
||||
testID={`sidebar-workspace-menu-open-folder-${workspaceKey}`}
|
||||
/>
|
||||
<DropdownMenuItem
|
||||
testID={`sidebar-workspace-menu-archive-${workspaceKey}`}
|
||||
leading={archiveLeadingIcon}
|
||||
|
||||
@@ -908,6 +908,8 @@ export const ar: TranslationResources = {
|
||||
openSettings: "افتح إعدادات المشروع",
|
||||
openNewWindow: "Open in new window",
|
||||
openNewWindowFailed: "Couldn't open a new window",
|
||||
openFolder: "Open in file manager",
|
||||
openFolderFailed: "Couldn't open folder",
|
||||
remove: "إزالة المشروع",
|
||||
removing: "جارٍ الإزالة...",
|
||||
},
|
||||
|
||||
@@ -918,6 +918,8 @@ export const en = {
|
||||
openSettings: "Open project settings",
|
||||
openNewWindow: "Open in new window",
|
||||
openNewWindowFailed: "Couldn't open a new window",
|
||||
openFolder: "Open in file manager",
|
||||
openFolderFailed: "Couldn't open folder",
|
||||
remove: "Remove project",
|
||||
removing: "Removing...",
|
||||
},
|
||||
|
||||
@@ -939,6 +939,8 @@ export const es: TranslationResources = {
|
||||
openSettings: "Abrir la configuración del proyecto",
|
||||
openNewWindow: "Open in new window",
|
||||
openNewWindowFailed: "Couldn't open a new window",
|
||||
openFolder: "Open in file manager",
|
||||
openFolderFailed: "Couldn't open folder",
|
||||
remove: "Eliminar proyecto",
|
||||
removing: "Eliminando...",
|
||||
},
|
||||
|
||||
@@ -938,6 +938,8 @@ export const fr: TranslationResources = {
|
||||
openSettings: "Ouvrir les paramètres du projet",
|
||||
openNewWindow: "Open in new window",
|
||||
openNewWindowFailed: "Couldn't open a new window",
|
||||
openFolder: "Open in file manager",
|
||||
openFolderFailed: "Couldn't open folder",
|
||||
remove: "Supprimer le projet",
|
||||
removing: "Suppression...",
|
||||
},
|
||||
|
||||
@@ -919,6 +919,8 @@ export const ja: TranslationResources = {
|
||||
openSettings: "プロジェクト設定を開く",
|
||||
openNewWindow: "新しいウィンドウで開く",
|
||||
openNewWindowFailed: "新しいウィンドウを開けませんでした",
|
||||
openFolder: "Open in file manager",
|
||||
openFolderFailed: "Couldn't open folder",
|
||||
remove: "プロジェクトを削除",
|
||||
removing: "削除中...",
|
||||
},
|
||||
|
||||
@@ -930,6 +930,8 @@ export const ptBR: TranslationResources = {
|
||||
openSettings: "Abrir configurações do projeto",
|
||||
openNewWindow: "Abrir em nova janela",
|
||||
openNewWindowFailed: "Não foi possível abrir uma nova janela",
|
||||
openFolder: "Open in file manager",
|
||||
openFolderFailed: "Couldn't open folder",
|
||||
remove: "Remover projeto",
|
||||
removing: "Removendo...",
|
||||
},
|
||||
|
||||
@@ -930,6 +930,8 @@ export const ru: TranslationResources = {
|
||||
openSettings: "Открыть настройки проекта",
|
||||
openNewWindow: "Open in new window",
|
||||
openNewWindowFailed: "Couldn't open a new window",
|
||||
openFolder: "Open in file manager",
|
||||
openFolderFailed: "Couldn't open folder",
|
||||
remove: "Удалить проект",
|
||||
removing: "Удаление...",
|
||||
},
|
||||
|
||||
@@ -899,6 +899,8 @@ export const zhCN: TranslationResources = {
|
||||
openSettings: "打开 project 设置",
|
||||
openNewWindow: "在新窗口中打开",
|
||||
openNewWindowFailed: "无法打开新窗口",
|
||||
openFolder: "Open in file manager",
|
||||
openFolderFailed: "Couldn't open folder",
|
||||
remove: "移除 project",
|
||||
removing: "正在移除...",
|
||||
},
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { useCallback } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FolderOpen } from "lucide-react-native";
|
||||
import { withUnistyles } from "react-native-unistyles";
|
||||
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||
import { getIsElectron } from "@/constants/platform";
|
||||
import { useToast } from "@/contexts/toast-context";
|
||||
import type { Theme } from "@/styles/theme";
|
||||
import { openDesktopTarget, useDesktopOpenTargets } from "@/workspace/desktop-open-targets";
|
||||
|
||||
interface OpenInFileManagerMenuItemProps {
|
||||
path?: string | null;
|
||||
testID: string;
|
||||
}
|
||||
|
||||
const ThemedFolderOpen = withUnistyles(FolderOpen);
|
||||
|
||||
const foregroundMutedColorMapping = (theme: Theme) => ({
|
||||
color: theme.colors.foregroundMuted,
|
||||
});
|
||||
|
||||
const leadingIcon = <ThemedFolderOpen size={14} uniProps={foregroundMutedColorMapping} />;
|
||||
|
||||
export function OpenInFileManagerMenuItem({ path, testID }: OpenInFileManagerMenuItemProps) {
|
||||
const { t } = useTranslation();
|
||||
const toast = useToast();
|
||||
const isElectron = getIsElectron();
|
||||
const workspacePath = path?.trim() ?? "";
|
||||
const { targets } = useDesktopOpenTargets({
|
||||
isLocalExecution: isElectron && workspacePath.length > 0,
|
||||
});
|
||||
const fileManagerTarget = targets.find((target) => target.kind === "file-manager");
|
||||
|
||||
const openInFileManager = useCallback(() => {
|
||||
if (!fileManagerTarget || workspacePath.length === 0) return;
|
||||
void openDesktopTarget({
|
||||
editorId: fileManagerTarget.id,
|
||||
workspacePath,
|
||||
}).catch((error) => {
|
||||
console.warn("[open-in-file-manager] open failed", error);
|
||||
toast.error(t("sidebar.project.actions.openFolderFailed"));
|
||||
});
|
||||
}, [fileManagerTarget, t, toast, workspacePath]);
|
||||
|
||||
if (!isElectron || !fileManagerTarget || workspacePath.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<DropdownMenuItem testID={testID} leading={leadingIcon} onSelect={openInFileManager}>
|
||||
{t("sidebar.project.actions.openFolder")}
|
||||
</DropdownMenuItem>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user