mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-25 10:51:57 +01:00
189 lines
6.2 KiB
TypeScript
189 lines
6.2 KiB
TypeScript
import { open } from "@tauri-apps/plugin-dialog";
|
|
import { revealItemInDir } from "@tauri-apps/plugin-opener";
|
|
import { getModel, settingsAtom, workspacesAtom } from "@yaakapp-internal/models";
|
|
import classNames from "classnames";
|
|
import { useAtomValue } from "jotai";
|
|
import { memo, useCallback, useMemo } from "react";
|
|
import { openWorkspaceFromSyncDir } from "../commands/openWorkspaceFromSyncDir";
|
|
import { openWorkspaceSettings } from "../commands/openWorkspaceSettings";
|
|
import { switchWorkspace } from "../commands/switchWorkspace";
|
|
import {
|
|
activeWorkspaceAtom,
|
|
activeWorkspaceIdAtom,
|
|
activeWorkspaceMetaAtom,
|
|
} from "../hooks/useActiveWorkspace";
|
|
import { useCreateWorkspace } from "../hooks/useCreateWorkspace";
|
|
import { useDeleteSendHistory } from "../hooks/useDeleteSendHistory";
|
|
import { useWorkspaceActions } from "../hooks/useWorkspaceActions";
|
|
import { showDialog } from "../lib/dialog";
|
|
import { jotaiStore } from "../lib/jotai";
|
|
import { revealInFinderText } from "../lib/reveal";
|
|
import { CloneGitRepositoryDialog } from "./CloneGitRepositoryDialog";
|
|
import type { ButtonProps } from "./core/Button";
|
|
import { Button } from "./core/Button";
|
|
import type { DropdownItem } from "./core/Dropdown";
|
|
import { Icon } from "@yaakapp-internal/ui";
|
|
import type { RadioDropdownItem } from "./core/RadioDropdown";
|
|
import { RadioDropdown } from "./core/RadioDropdown";
|
|
import { SwitchWorkspaceDialog } from "./SwitchWorkspaceDialog";
|
|
|
|
type Props = Pick<ButtonProps, "className" | "justify" | "forDropdown" | "leftSlot">;
|
|
|
|
export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
|
|
className,
|
|
...buttonProps
|
|
}: Props) {
|
|
const workspaces = useAtomValue(workspacesAtom);
|
|
const workspace = useAtomValue(activeWorkspaceAtom);
|
|
const createWorkspace = useCreateWorkspace();
|
|
const workspaceMeta = useAtomValue(activeWorkspaceMetaAtom);
|
|
const { mutate: deleteSendHistory } = useDeleteSendHistory();
|
|
const workspaceActions = useWorkspaceActions();
|
|
|
|
const openCloneGitRepositoryDialog = useCallback(() => {
|
|
showDialog({
|
|
id: "clone-git-repository",
|
|
size: "md",
|
|
title: "Clone Git Repository",
|
|
render: ({ hide }) => <CloneGitRepositoryDialog hide={hide} />,
|
|
});
|
|
}, []);
|
|
|
|
const { workspaceItems, itemsAfter, itemsBefore } = useMemo<{
|
|
workspaceItems: RadioDropdownItem[];
|
|
itemsAfter: DropdownItem[];
|
|
itemsBefore: DropdownItem[];
|
|
}>(() => {
|
|
const workspaceItems: RadioDropdownItem[] = workspaces.map((w) => ({
|
|
key: w.id,
|
|
label: w.name,
|
|
value: w.id,
|
|
leftSlot: w.id === workspace?.id ? <Icon icon="check" /> : <Icon icon="empty" />,
|
|
}));
|
|
|
|
const itemsBefore: DropdownItem[] = [
|
|
{
|
|
label: "New Workspace",
|
|
leftSlot: <Icon icon="plus" />,
|
|
submenu: [
|
|
{
|
|
label: "Create Empty",
|
|
leftSlot: <Icon icon="plus_circle" />,
|
|
onSelect: createWorkspace,
|
|
},
|
|
{
|
|
label: "Open Folder",
|
|
leftSlot: <Icon icon="folder_open" />,
|
|
onSelect: async () => {
|
|
const dir = await open({
|
|
title: "Select Workspace Directory",
|
|
directory: true,
|
|
multiple: false,
|
|
});
|
|
|
|
if (dir == null) return;
|
|
openWorkspaceFromSyncDir.mutate(dir);
|
|
},
|
|
},
|
|
{
|
|
label: "Clone Git Repository",
|
|
leftSlot: <Icon icon="hard_drive_download" />,
|
|
onSelect: openCloneGitRepositoryDialog,
|
|
},
|
|
],
|
|
},
|
|
];
|
|
const itemsAfter: DropdownItem[] = [
|
|
...workspaceActions.map((a) => ({
|
|
label: a.label,
|
|
leftSlot: <Icon icon={a.icon ?? "empty"} />,
|
|
onSelect: async () => {
|
|
if (workspace != null) await a.call(workspace);
|
|
},
|
|
})),
|
|
...(workspaceActions.length > 0 ? [{ type: "separator" as const }] : []),
|
|
{
|
|
label: "Workspace Settings",
|
|
leftSlot: <Icon icon="settings" />,
|
|
hotKeyAction: "workspace_settings.show",
|
|
onSelect: openWorkspaceSettings,
|
|
},
|
|
{
|
|
label: revealInFinderText,
|
|
hidden: workspaceMeta == null || workspaceMeta.settingSyncDir == null,
|
|
leftSlot: <Icon icon="folder_symlink" />,
|
|
onSelect: async () => {
|
|
if (workspaceMeta?.settingSyncDir == null) return;
|
|
await revealItemInDir(workspaceMeta.settingSyncDir);
|
|
},
|
|
},
|
|
{
|
|
label: "Clear Send History",
|
|
color: "warning",
|
|
leftSlot: <Icon icon="history" />,
|
|
onSelect: deleteSendHistory,
|
|
},
|
|
];
|
|
|
|
return { workspaceItems, itemsAfter, itemsBefore };
|
|
}, [
|
|
workspaces,
|
|
workspaceMeta,
|
|
deleteSendHistory,
|
|
createWorkspace,
|
|
openCloneGitRepositoryDialog,
|
|
workspace?.id,
|
|
workspace,
|
|
workspaceActions.map,
|
|
workspaceActions.length,
|
|
]);
|
|
|
|
const handleSwitchWorkspace = useCallback(async (workspaceId: string | null) => {
|
|
if (workspaceId == null) return;
|
|
|
|
const settings = jotaiStore.get(settingsAtom);
|
|
const activeWorkspaceId = jotaiStore.get(activeWorkspaceIdAtom);
|
|
if (workspaceId === activeWorkspaceId) {
|
|
// Always open a new window if the selected one is already active
|
|
switchWorkspace.mutate({ workspaceId, inNewWindow: true });
|
|
return;
|
|
}
|
|
if (typeof settings.openWorkspaceNewWindow === "boolean") {
|
|
switchWorkspace.mutate({ workspaceId, inNewWindow: settings.openWorkspaceNewWindow });
|
|
return;
|
|
}
|
|
|
|
const workspace = getModel("workspace", workspaceId);
|
|
if (workspace == null) return;
|
|
|
|
showDialog({
|
|
id: "switch-workspace",
|
|
size: "sm",
|
|
title: "Switch Workspace",
|
|
render: ({ hide }) => <SwitchWorkspaceDialog workspace={workspace} hide={hide} />,
|
|
});
|
|
}, []);
|
|
|
|
return (
|
|
<RadioDropdown
|
|
items={workspaceItems}
|
|
itemsAfter={itemsAfter}
|
|
itemsBefore={itemsBefore}
|
|
onChange={handleSwitchWorkspace}
|
|
value={workspace?.id ?? null}
|
|
>
|
|
<Button
|
|
size="sm"
|
|
className={classNames(
|
|
className,
|
|
"text !px-2 truncate",
|
|
workspace === null && "italic opacity-disabled",
|
|
)}
|
|
{...buttonProps}
|
|
>
|
|
{workspace?.name ?? "Workspace"}
|
|
</Button>
|
|
</RadioDropdown>
|
|
);
|
|
});
|