// Copyright 2024, Command Line // SPDX-License-Identifier: Apache-2.0 import { ExpandableMenu, ExpandableMenuItem, ExpandableMenuItemGroup, ExpandableMenuItemGroupTitle, ExpandableMenuItemLeftElement, ExpandableMenuItemRightElement, } from "@/element/expandablemenu"; import { Popover, PopoverButton, PopoverContent } from "@/element/popover"; import { fireAndForget, makeIconClass, useAtomValueSafe } from "@/util/util"; import clsx from "clsx"; import { atom, PrimitiveAtom, useAtom, useAtomValue, useSetAtom } from "jotai"; import { splitAtom } from "jotai/utils"; import { OverlayScrollbarsComponent } from "overlayscrollbars-react"; import { CSSProperties, forwardRef, useCallback, useEffect } from "react"; import WorkspaceSVG from "../asset/workspace.svg"; import { IconButton } from "../element/iconbutton"; import { atoms, getApi } from "../store/global"; import { WorkspaceService } from "../store/services"; import { getObjectValue, makeORef } from "../store/wos"; import { waveEventSubscribe } from "../store/wps"; import { WorkspaceEditor } from "./workspaceeditor"; import "./workspaceswitcher.scss"; type WorkspaceListEntry = { windowId: string; workspace: Workspace; }; type WorkspaceList = WorkspaceListEntry[]; const workspaceMapAtom = atom([]); const workspaceSplitAtom = splitAtom(workspaceMapAtom); const editingWorkspaceAtom = atom(); const WorkspaceSwitcher = forwardRef((_, ref) => { const setWorkspaceList = useSetAtom(workspaceMapAtom); const activeWorkspace = useAtomValueSafe(atoms.workspace); const workspaceList = useAtomValue(workspaceSplitAtom); const setEditingWorkspace = useSetAtom(editingWorkspaceAtom); const updateWorkspaceList = useCallback(async () => { const workspaceList = await WorkspaceService.ListWorkspaces(); if (!workspaceList) { return; } const newList: WorkspaceList = []; for (const entry of workspaceList) { // This just ensures that the atom exists for easier setting of the object getObjectValue(makeORef("workspace", entry.workspaceid)); newList.push({ windowId: entry.windowid, workspace: await WorkspaceService.GetWorkspace(entry.workspaceid), }); } setWorkspaceList(newList); }, []); useEffect( () => waveEventSubscribe({ eventType: "workspace:update", handler: () => fireAndForget(updateWorkspaceList), }), [] ); useEffect(() => { fireAndForget(updateWorkspaceList); }, []); const onDeleteWorkspace = useCallback((workspaceId: string) => { getApi().deleteWorkspace(workspaceId); }, []); const isActiveWorkspaceSaved = !!(activeWorkspace.name && activeWorkspace.icon); const workspaceIcon = isActiveWorkspaceSaved ? ( ) : ( ); const saveWorkspace = () => { fireAndForget(async () => { await WorkspaceService.UpdateWorkspace(activeWorkspace.oid, "", "", "", true); await updateWorkspaceList(); setEditingWorkspace(activeWorkspace.oid); }); }; return ( setEditingWorkspace(null)} ref={ref} > { fireAndForget(updateWorkspaceList); }} > {workspaceIcon}
{isActiveWorkspaceSaved ? "Switch workspace" : "Open workspace"}
{workspaceList.map((entry, i) => ( ))}
{isActiveWorkspaceSaved ? ( getApi().createWorkspace()}>
Create new workspace
) : ( saveWorkspace()}>
Save workspace
)}
); }); const WorkspaceSwitcherItem = ({ entryAtom, onDeleteWorkspace, }: { entryAtom: PrimitiveAtom; onDeleteWorkspace: (workspaceId: string) => void; }) => { const activeWorkspace = useAtomValueSafe(atoms.workspace); const [workspaceEntry, setWorkspaceEntry] = useAtom(entryAtom); const [editingWorkspace, setEditingWorkspace] = useAtom(editingWorkspaceAtom); const workspace = workspaceEntry.workspace; const isCurrentWorkspace = activeWorkspace.oid === workspace.oid; const setWorkspace = useCallback((newWorkspace: Workspace) => { if (newWorkspace.name != "") { fireAndForget(() => WorkspaceService.UpdateWorkspace( workspace.oid, newWorkspace.name, newWorkspace.icon, newWorkspace.color, false ) ); } }, []); const isActive = !!workspaceEntry.windowId; const editIconDecl: IconButtonDecl = { elemtype: "iconbutton", className: "edit", icon: "pencil", title: "Edit workspace", click: (e) => { e.stopPropagation(); if (editingWorkspace === workspace.oid) { setEditingWorkspace(null); } else { setEditingWorkspace(workspace.oid); } }, }; const windowIconDecl: IconButtonDecl = { elemtype: "iconbutton", className: "window", noAction: true, icon: isCurrentWorkspace ? "check" : "window", title: isCurrentWorkspace ? "This is your current workspace" : "This workspace is open", }; const isEditing = editingWorkspace === workspace.oid; return ( { getApi().switchWorkspace(workspace.oid); // Create a fake escape key event to close the popover document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape" })); }} >
{workspace.name}
{isActive && }
setWorkspace({ ...workspace, name: title })} onColorChange={(color) => setWorkspace({ ...workspace, color })} onIconChange={(icon) => setWorkspace({ ...workspace, icon })} onDeleteWorkspace={() => onDeleteWorkspace(workspace.oid)} />
); }; export { WorkspaceSwitcher };