Skip to content

Commit

Permalink
Merge pull request #202 from Cycling74/fde/patcher_view
Browse files Browse the repository at this point in the history
move patcher management to dedicated top level nav item and page
  • Loading branch information
fde31 authored Mar 5, 2025
2 parents 3ad67b2 + 5cfd935 commit 27b3590
Show file tree
Hide file tree
Showing 9 changed files with 351 additions and 172 deletions.
10 changes: 10 additions & 0 deletions src/components/editor/addNodeMenu.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.patcherMenuSection {
display: flex;
flex-direction: column;
max-height: inherit;
}

.patcherMenuSectionList {
flex: 1;
overflow: auto;
}
96 changes: 96 additions & 0 deletions src/components/editor/addNodeMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { FC, memo, useCallback, useRef, useState } from "react";
import { PatcherExportRecord } from "../../models/patcher";
import { Seq } from "immutable";
import { ActionIcon, Alert, Anchor, Menu, Text, Tooltip, useMantineTheme } from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { mdiPlusBox } from "@mdi/js";
import { IconElement } from "../elements/icon";
import classes from "./addNodeMenu.module.css";

type PatcherMenuEntryProps = {
onLoad: (p: PatcherExportRecord) => void;
patcher: PatcherExportRecord;
};

const PatcherMenuEntry: FC<PatcherMenuEntryProps> = ({ patcher, onLoad }) => {
return (
<Menu.Item onClick={ () => onLoad(patcher) } >
{ patcher.name }
</Menu.Item>
);
};

type AddPatcherInstanceMenuSectionProps = {
onLoadPatcherInstance: (p: PatcherExportRecord) => void;
patchers: Seq.Indexed<PatcherExportRecord>;
};

const AddPatcherInstanceMenuSection: FC<AddPatcherInstanceMenuSectionProps> = memo(function WrappedAddPatcherSection({
onLoadPatcherInstance,
patchers
}) {
return (
<div className={ classes.patcherMenuSection } >
<Menu.Label>Patchers</Menu.Label>
{
!patchers.size ? (
<Alert title="No Patcher available" variant="light" color="yellow">
<Text size="xs">
Please <Anchor inherit target="_blank" href="https://rnbo.cycling74.com/learn/export-targets-overview">export a RNBO patcher</Anchor> to load on the runner.
</Text>
</Alert>
) : null
}
<div className={ classes.patcherMenuSectionList } >
{
patchers.map(p => <PatcherMenuEntry key={ p.id } patcher={ p } onLoad={ onLoadPatcherInstance } />)
}
</div>
</div>
);
});

export type AddNodeMenuProps = {
onAddPatcherInstance: (patcher: PatcherExportRecord) => void;
patchers: Seq.Indexed<PatcherExportRecord>;
};

export const AddNodeMenu: FC<AddNodeMenuProps> = memo(function WrappedAddNodeMenu({
onAddPatcherInstance,
patchers
}) {

const dropdownRef = useRef<HTMLDivElement>();
const theme = useMantineTheme();
const [maxDropdownMenuHeight, setMaxDropdownMenuHeight] = useState<string>("0px");
const [addNodeMenuIsOpen, { close: closeMenu, open: openMenu }] = useDisclosure();

const onTriggerOpen = useCallback(() => {
if (!dropdownRef.current) return;

const { bottom } = dropdownRef.current.getBoundingClientRect();
setMaxDropdownMenuHeight(`calc(${window.innerHeight}px - ${bottom}px - 2 * ${theme.spacing.md}`);
openMenu();

}, [setMaxDropdownMenuHeight, openMenu, dropdownRef, theme.spacing.md]);

return (
<Menu position="bottom-start" opened={ addNodeMenuIsOpen } onOpen={ onTriggerOpen } onClose={ closeMenu } >
<Menu.Target ref={ dropdownRef } >
<Tooltip label="Add Node">
<ActionIcon variant="default" size="lg">
<IconElement path={ mdiPlusBox } />
</ActionIcon>
</Tooltip>
</Menu.Target>
<Menu.Dropdown>
<div style={{ maxHeight: maxDropdownMenuHeight }}>
<AddPatcherInstanceMenuSection
onLoadPatcherInstance={ onAddPatcherInstance }
patchers={ patchers }
/>
</div>
</Menu.Dropdown>
</Menu>
);
});
8 changes: 7 additions & 1 deletion src/components/nav/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getShowSettingsModal } from "../../selectors/settings";
import { ExternalNavLink, NavLink } from "./link";
import { useRouter } from "next/router";
import { getFirstPatcherNodeId } from "../../selectors/graph";
import { mdiChartSankeyVariant, mdiCog, mdiFileMusic, mdiHelpCircle, mdiMidiPort, mdiVectorSquare, mdiTableEye } from "@mdi/js";
import { mdiChartSankeyVariant, mdiCog, mdiFileMusic, mdiHelpCircle, mdiMidiPort, mdiVectorSquare, mdiTableEye, mdiFileExport } from "@mdi/js";

const AppNav: FunctionComponent = memo(function WrappedNav() {

Expand Down Expand Up @@ -45,6 +45,12 @@ const AppNav: FunctionComponent = memo(function WrappedNav() {
href={{ pathname: "/instances/[id]", query: { ...restQuery, id: instanceId } }}
isActive={ pathname === "/instances/[id]" }
/>
<NavLink
icon={ mdiFileExport }
label="Patchers"
href={{ pathname: "/patchers", query: restQuery }}
isActive={ pathname === "/patchers" }
/>
<NavLink
icon={ mdiFileMusic }
label="Audio Files"
Expand Down
54 changes: 54 additions & 0 deletions src/components/patchers/addMenuSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Alert, Menu, Text } from "@mantine/core";
import { FC, memo } from "react";
import { PatcherExportRecord } from "../../models/patcher";
import { Seq } from "immutable";
import classes from "./patchers.module.css";

type PatcherMenuEntryProps = {
onLoad: (p: PatcherExportRecord) => void;
patcher: PatcherExportRecord;
};

const PatcherMenuEntry: FC<PatcherMenuEntryProps> = ({ patcher, onLoad }) => {
return (
<Menu.Item onClick={ () => onLoad(patcher) } >
{ patcher.name }
</Menu.Item>
);
};

export type AddPatcherInstanceMenuSectionProps = {
onLoadPatcherInstance: (p: PatcherExportRecord) => void;
patchers: Seq.Indexed<PatcherExportRecord>;
};

export const AddPatcherInstanceMenuSection: FC<AddPatcherInstanceMenuSectionProps> = memo(function WrappedAddPatcherSection({
onLoadPatcherInstance,
patchers
}) {
return (
<div className={ classes.patcherMenuSection } >
<Menu.Label className={ classes.patcherMenuSectionTitle } >Add Patcher Instance</Menu.Label>
{
!patchers.size ? (
<Alert title="No Patcher available" variant="light" color="yellow">
<Text size="xs">
Please export a RNBO patcher to load on the runner.
</Text>
</Alert>
) : null
}
<div className={ classes.patcherMenuSectionList } >
{
patchers.map(p => <PatcherMenuEntry key={ p.id } patcher={ p } onLoad={ onLoadPatcherInstance } />)
}
{
patchers.map(p => <PatcherMenuEntry key={ p.id + "1" } patcher={ p } onLoad={ onLoadPatcherInstance } />)
}
{
patchers.map(p => <PatcherMenuEntry key={ p.id + "2" } patcher={ p } onLoad={ onLoadPatcherInstance } />)
}
</div>
</div>
);
});
71 changes: 0 additions & 71 deletions src/components/patchers/index.tsx

This file was deleted.

Loading

0 comments on commit 27b3590

Please sign in to comment.