diff --git a/src/app/component/Bus.tsx b/src/app/component/Bus.tsx index 59a96a8..79736ac 100644 --- a/src/app/component/Bus.tsx +++ b/src/app/component/Bus.tsx @@ -3,52 +3,55 @@ import { Button, ButtonGroup, Grid, Input, Slider, Stack } from "@mui/material"; import React from "react"; import { StripBusOutput, StripBusOutputEvent } from "./StripBusOutput"; -export interface StripProps { - physicalBuses: number; - virtualBuses: number; - default?: Partial; +export interface BusProps { + values?: Partial; onChange: (event: BusEvent) => any; } -export interface StripState { +export interface BusState { gain: number; - buses: boolean[]; muted: boolean; + selected: boolean; } -export type BusEvent = StripBusOutputChanged | StripMuted | StripGainChanged; +export type BusEvent = BusMuted | BusGainChanged | BusSelectToggle; -export interface StripBusOutputChanged extends StripBusOutputEvent { - type: "StripBusOutputChanged"; -} - -export interface StripGainChanged { +export interface BusGainChanged { type: "StripGainChanged"; gain: number; } -export interface StripMuted { +export interface BusMuted { type: "StripMuted"; muted: boolean; } +export interface BusSelectToggle { + type: "BusSelectToggle"; + selected: boolean; +} -export class Bus extends React.Component { - constructor(props: StripProps) { +export class Bus extends React.Component { + constructor(props: BusProps) { super(props); - const buses = (props.default && props.default.buses) || []; - this.state = { - gain: - props.default && props.default.gain !== undefined - ? props.default.gain - : 0, - buses: [...Array(props.physicalBuses + props.virtualBuses)].map((_v, k) => - buses[k] === undefined ? false : buses[k] - ), - muted: - props.default && props.default.muted !== undefined - ? props.default.muted - : false, + const { values: initialValues } = props; + const defaultValues: BusState = { + gain: 0, + selected: false, + muted: false, }; + const getValue = (name: keyof typeof defaultValues) => { + if (initialValues === undefined) return defaultValues[name]; + return initialValues[name] !== undefined + ? defaultValues[name] + : initialValues[name]; + }; + this.state = Object.fromEntries( + Object.entries(defaultValues).map(([name]) => [ + name, + getValue(name as keyof typeof defaultValues) as any, + ]) + ) as BusState; } + onResetDefaults(e: React.MouseEvent) {} onKeyDown(event: React.KeyboardEvent) { console.log(event); @@ -70,21 +73,6 @@ export class Bus extends React.Component { gain: changedGain, }); } - onBusChange(event: StripBusOutputEvent) { - const buses = this.state.buses; - buses[ - event.isVirtual ? this.props.physicalBuses + event.busId : event.busId - ] = event.enabled; - this.setState({ - buses, - }); - this.props.onChange({ - type: "StripBusOutputChanged", - busId: event.busId, - isVirtual: event.isVirtual, - enabled: event.enabled, - }); - } onStripWheel(event: React.WheelEvent) { console.log(event); } @@ -96,58 +84,69 @@ export class Bus extends React.Component { } ); } + onSelectToggle() { + this.setState( + (state) => ({ selected: !state.selected }), + () => { + this.props.onChange({ + type: "BusSelectToggle", + selected: this.state.selected, + }); + } + ); + } render() { return ( <> - - - this.onStripWheel(ev)} - size="small" - sx={{ width: "50px" }} - /> - - this.onChange( - ev as unknown as React.ChangeEvent - ) - } - onKeyDown={(ev) => this.onKeyDown(ev)} - /> + + this.onStripWheel(ev)} + size="small" + sx={{ width: "50px" }} + /> + + this.onChange( + ev as unknown as React.ChangeEvent + ) + } + onKeyDown={(ev) => this.onKeyDown(ev)} + /> - - - - - - {/* + + + + + + {/* {[ ...Array(this.props.physicalBuses + this.props.virtualBuses), @@ -170,7 +169,6 @@ export class Bus extends React.Component { ))} */} - ); } diff --git a/src/app/component/Strip.tsx b/src/app/component/Strip.tsx index b8c061b..7843135 100644 --- a/src/app/component/Strip.tsx +++ b/src/app/component/Strip.tsx @@ -1,18 +1,26 @@ "use client"; -import { Button, ButtonGroup, Grid, Input, Slider, Stack } from "@mui/material"; +import { + Box, + Button, + ButtonGroup, + Grid, + Input, + Slider, + Stack, +} from "@mui/material"; import React from "react"; import { StripBusOutput, StripBusOutputEvent } from "./StripBusOutput"; export interface StripProps { physicalBuses: number; virtualBuses: number; - default?: Partial; + values?: Partial; onChange: (event: StripEvent) => any; } export interface StripState { gain: number; - buses: boolean[]; + outputBuses: boolean[]; muted: boolean; } @@ -34,24 +42,34 @@ export interface StripMuted { export class Strip extends React.Component { constructor(props: StripProps) { super(props); - const buses = (props.default && props.default.buses) || []; - this.state = { - gain: - props.default && props.default.gain !== undefined - ? props.default.gain - : 0, - buses: [...Array(props.physicalBuses + props.virtualBuses)].map((_v, k) => - buses[k] === undefined ? false : buses[k] + const { values: initialValues } = props; + const defaultValues: StripState = { + gain: 0, + outputBuses: [...Array(props.physicalBuses + props.virtualBuses)].map( + (_v, k) => false ), - muted: - props.default && props.default.muted !== undefined - ? props.default.muted - : false, + muted: false, }; + const getValue = (name: keyof typeof defaultValues) => { + if (initialValues === undefined) return defaultValues[name]; + return initialValues[name] !== undefined + ? defaultValues[name] + : initialValues[name]; + }; + this.state = Object.fromEntries( + Object.entries(defaultValues).map(([name]) => [ + name, + getValue(name as keyof typeof defaultValues) as any, + ]) + ) as StripState; + } + onResetDefaults(e: React.MouseEvent) { + e.stopPropagation(); + this.setState({ gain: 0 }); } onKeyDown(event: React.KeyboardEvent) { console.log(event); - + if (event.key === "ArrowLeft" || event.key === "ArrowRight") { event.preventDefault(); } @@ -71,12 +89,12 @@ export class Strip extends React.Component { }); } onBusChange(event: StripBusOutputEvent) { - const buses = this.state.buses; + const buses = this.state.outputBuses; buses[ event.isVirtual ? this.props.physicalBuses + event.busId : event.busId ] = event.enabled; this.setState({ - buses, + outputBuses: buses, }); this.props.onChange({ type: "StripBusOutputChanged", @@ -87,7 +105,6 @@ export class Strip extends React.Component { } onStripWheel(event: React.WheelEvent) { console.log(event); - } onMuteToggle() { this.setState( @@ -100,8 +117,8 @@ export class Strip extends React.Component { render() { return ( <> - - + + { value={this.state.gain} onWheel={(ev) => this.onStripWheel(ev)} size="small" - sx={{ width: "50px" }} + sx={{ marginInline: "5px" }} /> { onClick={() => this.onMuteToggle()} variant={this.state.muted ? "contained" : "outlined"} color={"error"} + style={{ paddingInline: "0px", maxWidth: "5px" }} + size="large" > Mute @@ -157,12 +177,12 @@ export class Strip extends React.Component { } isVirtual={i < this.props.physicalBuses ? false : true} onChange={(ev) => this.onBusChange(ev)} - default={{ enabled: this.state.buses[i] }} + default={{ enabled: this.state.outputBuses[i] }} /> ))} - + ); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 782eaad..00a1e30 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -16,6 +16,7 @@ export default function RootLayout({ + {children} ); diff --git a/src/app/page.tsx b/src/app/page.tsx index 23109da..dbd77b4 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,5 +1,5 @@ "use client"; -import React from "react"; +import React, { useEffect, useMemo, useState } from "react"; import { Strip, StripEvent } from "./component/Strip"; import { Button, @@ -7,11 +7,15 @@ import { createTheme, CssBaseline, Divider, + Slide, + Snackbar, Stack, ThemeProvider, Typography, + useMediaQuery, } from "@mui/material"; import { Bus } from "./component/Bus"; +import Grid from "@mui/material/Unstable_Grid2"; function random(min: number, max: number, floor: boolean = true) { const value = Math.random() * (max - min + 1) + min; @@ -19,92 +23,175 @@ function random(min: number, max: number, floor: boolean = true) { } export default function Home() { + const theme = useMemo(() => createTheme({ palette: { mode: "dark" } }), []); function onStripEvent(event: StripEvent) { console.log(event); } - const physicalBuses = 5; - const virtualBuses = 3; - const strips = physicalBuses + virtualBuses; + const isSnackBarHidden = useMemo(() => { + if (typeof localStorage === "undefined") return false; + return localStorage.getItem("snackBarHidden") === "true"; + }, []); + const [snackBarVisible, setSnackBarVisibility] = useState(false); + const breakPoints = useMemo(() => theme.breakpoints.values, []); + const [width, setWidth] = useState( + typeof document !== "undefined" ? window.innerWidth : 0 + ); + useEffect(() => { + setSnackBarVisibility(!isSnackBarHidden); + }, []); + useEffect(() => { + const values = {} as Record; + type valuesKey = keyof typeof breakPoints; + for (const key in breakPoints) { + if (Object.prototype.hasOwnProperty.call(breakPoints, key)) { + const breakPointWidth = breakPoints[key as keyof typeof breakPoints]; + values[key as valuesKey] = + [breakPointWidth, breakPointWidth === width + ? "equal" + : breakPointWidth > width + ? "bigger" + : "smaller"]; + } + } + console.clear() + console.log( + width, + `Closest: ${ + Object.entries(breakPoints).reduce((acc, i) => { + const equation = Math.abs(i[1] - width) <= Math.abs(acc[1] - width) ? i : acc; + return equation; + })[0] + }`, + ); + console.table(values); + }, [width]); + const strips = { virtual: 3, physical: 5 }; + const buses = { virtual: 3, physical: 5 }; + const amountOfStrips = strips.physical + strips.virtual; + const amountOfBuses = buses.physical + buses.virtual; let clicks = 0; let timeout: NodeJS.Timeout | undefined; - document.body.onclick = (e) => { - clicks++; - if (timeout !== undefined) { + if (typeof document !== "undefined") { + document.onclick = (e) => { + clicks++; + if (timeout !== undefined) { + clearTimeout(timeout); + timeout = undefined; + } + timeout = setTimeout(() => (clicks = 0), 250); + console.log(e); + if (clicks < 2) return; clearTimeout(timeout); - timeout = undefined; - } - timeout = setTimeout(() => (clicks = 0), 500); - if (clicks < 2) return; - clearTimeout(timeout); - clicks = 0; - console.log(e.target); - - e.stopPropagation(); - e.preventDefault(); - if (document.fullscreenElement !== null) document.exitFullscreen(); - else document.body.requestFullscreen({ navigationUI: "hide" }); - - }; + clicks = 0; + // e.stopPropagation(); + + // if (document.fullscreenElement !== null) document.exitFullscreen(); + // else document.body.requestFullscreen({ navigationUI: "hide" }); + }; + window.onresize = () => { + setWidth(window.innerWidth); + }; + } + + const snackBarActionButton = ( + <> + + + ); return ( - - + +
Inputs - - {[...Array(strips)].map((_v, i) => ( + + {[...Array(amountOfStrips)].map((_v, stripId) => ( - {i === physicalBuses ? ( - - ) : ( - "" + {stripId === amountOfStrips && width > breakPoints.lg && ( + + + Virtual Inputs + + )} - onStripEvent(ev)} - physicalBuses={physicalBuses} - virtualBuses={virtualBuses} - /> + + {`Strip #${ + stripId + 1 + }`} + onStripEvent(ev)} + physicalBuses={buses.physical} + virtualBuses={buses.virtual} + /> + ))} - - Outputs - - {[...Array(strips)].map((_v, i) => ( - - {i === physicalBuses ? ( - - ) : ( - "" - )} - onStripEvent(ev)} - physicalBuses={physicalBuses} - virtualBuses={virtualBuses} - /> - - ))} - + - + Outputs + + {[...Array(amountOfBuses)].map((_v, busId) => ( + + {`Bus ${ + busId < buses.physical ? "a" : "b" + }${ + busId < buses.physical + ? busId + 1 + : busId + 1 - buses.physical + }`} + + + ))} +
+
); } diff --git a/src/utils/EventCounter.ts b/src/utils/EventCounter.ts new file mode 100644 index 0000000..cc1b042 --- /dev/null +++ b/src/utils/EventCounter.ts @@ -0,0 +1,29 @@ +interface EventListener { + name: keyof EventCounter["events"]; + callback: Function | Promise; + count: number; +} +type EventName = string; +type EventInfo = number[]; + +export class EventCounter { + events: Record = {}; + + listeners: Record = {}; + + private checkListeners(eventName: EventListener["name"]) { + this.events[eventName]; + } + private countEmits(eventName: EventListener["name"], periodOfTime: number) {} + emit(eventName: EventListener["name"]) { + + this.events[eventName].length >= 100 && this.events[eventName].shift(); +} + on(args: EventListener) { + const { name: eventName, callback, count } = args; + if (eventName in this.events === undefined) this.events[eventName] = []; + if (!Object.prototype.hasOwnProperty.call(this.listeners, eventName)) + this.listeners[eventName] = []; + this.listeners[eventName].push({ callback, count, name: eventName }); + } +}