modified: src/app/component/Bus.tsx
modified: src/app/component/BusesList.tsx modified: src/app/component/Strip.tsx modified: src/app/page.tsx modified: src/utils/DetectMobile.ts
This commit is contained in:
parent
7a65c76757
commit
42ccd675b8
|
@ -1,18 +1,31 @@
|
|||
"use client";
|
||||
import { Button, ButtonGroup, Grid, Input, Slider, Stack } from "@mui/material";
|
||||
import {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Grid,
|
||||
Input,
|
||||
Slider,
|
||||
Stack,
|
||||
TextField,
|
||||
} from "@mui/material";
|
||||
import React from "react";
|
||||
import { StripBusOutput, StripBusOutputEvent } from "./StripBusOutput";
|
||||
import { EventCounter } from "@/utils/EventCounter";
|
||||
|
||||
export interface BusProps {
|
||||
values?: Partial<BusState>;
|
||||
values?: Partial<Omit<BusState, StateDefaultValueException>>;
|
||||
showInputdB?: boolean;
|
||||
name: string;
|
||||
onChange: (event: BusEvent) => any;
|
||||
}
|
||||
|
||||
type StateDefaultValueException = "showInputdB";
|
||||
|
||||
export interface BusState {
|
||||
gain: number;
|
||||
muted: boolean;
|
||||
selected: boolean;
|
||||
showInputdB: boolean;
|
||||
}
|
||||
|
||||
export type BusEvent = BusMuted | BusGainChanged | BusSelectToggle;
|
||||
|
@ -32,26 +45,29 @@ export interface BusSelectToggle {
|
|||
|
||||
export class Bus extends React.Component<BusProps, BusState> {
|
||||
private eventCounter = new EventCounter<"onSliderResetDefaults">();
|
||||
private defaultValues: BusState = {
|
||||
private defaultValues: Omit<BusState, StateDefaultValueException> = {
|
||||
gain: 0,
|
||||
selected: false,
|
||||
muted: false,
|
||||
};
|
||||
constructor(props: BusProps) {
|
||||
super(props);
|
||||
const { values: initialValues } = props;
|
||||
let { values: initialValues } = props;
|
||||
const getValue = (name: keyof typeof this.defaultValues) => {
|
||||
if (initialValues === undefined) return this.defaultValues[name];
|
||||
return initialValues[name] !== undefined
|
||||
? this.defaultValues[name]
|
||||
: initialValues[name];
|
||||
};
|
||||
this.state = Object.fromEntries(
|
||||
Object.entries(this.defaultValues).map(([name]) => [
|
||||
name,
|
||||
getValue(name as keyof typeof this.defaultValues) as any,
|
||||
])
|
||||
) as BusState;
|
||||
this.state = {
|
||||
...Object.fromEntries(
|
||||
Object.entries(this.defaultValues).map(([name]) => [
|
||||
name,
|
||||
getValue(name as keyof typeof this.defaultValues) as any,
|
||||
])
|
||||
),
|
||||
showInputdB: props.showInputdB !== undefined ? props.showInputdB : true,
|
||||
} as BusState;
|
||||
this.eventCounter.on({
|
||||
callback: this.onResetDefaults.bind(this),
|
||||
count: 2,
|
||||
|
@ -69,11 +85,9 @@ export class Bus extends React.Component<BusProps, BusState> {
|
|||
}
|
||||
}
|
||||
onGainChange(event: Event | React.ChangeEvent<HTMLInputElement>) {
|
||||
|
||||
let changedGain =
|
||||
parseFloat((event.target as HTMLInputElement).value);
|
||||
if(changedGain > 12) changedGain = 12
|
||||
else if(changedGain < -60) changedGain = -60;
|
||||
let changedGain = parseFloat((event.target as HTMLInputElement).value);
|
||||
if (changedGain > 12) changedGain = 12;
|
||||
else if (changedGain < -60) changedGain = -60;
|
||||
this.setState({
|
||||
gain: changedGain,
|
||||
});
|
||||
|
@ -117,20 +131,30 @@ export class Bus extends React.Component<BusProps, BusState> {
|
|||
render() {
|
||||
return (
|
||||
<>
|
||||
<Stack alignItems={"center"} direction={"row"} spacing={0}>
|
||||
<Input
|
||||
inputProps={{
|
||||
"aria-labelledby": "input-slider",
|
||||
itemType: "number",
|
||||
style:{padding: 0}
|
||||
}}
|
||||
value={this.state.gain}
|
||||
onWheel={(e) => this.onStripWheel(e)}
|
||||
onClick={(e) => this.stopPropagation(e)}
|
||||
onChange={(e) => this.onGainChange(e as unknown as Event)}
|
||||
size="small"
|
||||
sx={{ width: "50px" }}
|
||||
/>
|
||||
<Stack
|
||||
alignItems={"center"}
|
||||
direction={"row"}
|
||||
spacing={0}
|
||||
sx={{ width: "inherit" }}
|
||||
>
|
||||
{this.state.showInputdB && (
|
||||
<TextField
|
||||
// inputProps={{
|
||||
// "aria-labelledby": "input-slider",
|
||||
// itemType: "number",
|
||||
// style:{padding: 0}
|
||||
// }}
|
||||
value={this.state.gain}
|
||||
onWheel={(e) => this.onStripWheel(e)}
|
||||
onClick={(e) => this.stopPropagation(e)}
|
||||
onChange={(e) => this.onGainChange(e as unknown as Event)}
|
||||
size="small"
|
||||
label={this.props.name}
|
||||
type="number"
|
||||
variant="outlined"
|
||||
sx={{ minWidth: "100px", maxWidth: "100px" }}
|
||||
/>
|
||||
)}
|
||||
<Slider
|
||||
sx={{
|
||||
margin: "5px",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Stack, Theme, Typography, useTheme, withTheme } from "@mui/material";
|
||||
import { Chip, Stack, Theme, Typography, useTheme, withTheme } from "@mui/material";
|
||||
import React from "react";
|
||||
import { Bus } from "./Bus";
|
||||
import { range } from "@/utils/Range";
|
||||
|
@ -22,17 +22,16 @@ export class BusesList extends React.Component<BusesListProps, BusesListState> {
|
|||
) {
|
||||
const [busId] = args;
|
||||
const isPhysical = busId < this.props.physical;
|
||||
const name = `${isPhysical ? "A" : "B"}${
|
||||
isPhysical ? busId + 1 : busId - this.props.physical + 1
|
||||
}`;
|
||||
return (
|
||||
<React.Fragment
|
||||
key={`${isPhysical ? "A" : "B"}${
|
||||
isPhysical ? busId + 1 : busId - this.props.physical + 1
|
||||
}`}
|
||||
<Stack direction={"row"} sx={{width:"100%"}} alignItems={"center"}
|
||||
key={name}
|
||||
>
|
||||
<Typography variant="caption">{`${isPhysical ? "A" : "B"}${
|
||||
isPhysical ? busId + 1 : busId - this.props.physical + 1
|
||||
}`}</Typography>
|
||||
<Bus onChange={console.log} />
|
||||
</React.Fragment>
|
||||
{/* <Chip variant="outlined" sx={{marginInlineEnd: "15px"}} label={name}/> */}
|
||||
<Bus name={name} onChange={console.log} />
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
render(): React.ReactNode {
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
Input,
|
||||
Slider,
|
||||
Stack,
|
||||
TextField,
|
||||
} from "@mui/material";
|
||||
import React from "react";
|
||||
import { StripBusOutput, StripBusOutputEvent } from "./StripBusOutput";
|
||||
|
@ -16,13 +17,17 @@ export interface StripProps {
|
|||
physicalBuses: number;
|
||||
virtualBuses: number;
|
||||
values?: Partial<StripState>;
|
||||
showOutputdB?: boolean;
|
||||
name: string;
|
||||
onChange: (event: StripEvent) => any;
|
||||
}
|
||||
type StateDefaultValueException = "showOutputdB";
|
||||
|
||||
export interface StripState {
|
||||
gain: number;
|
||||
outputBuses: boolean[];
|
||||
muted: boolean;
|
||||
showOutputdB: boolean;
|
||||
}
|
||||
|
||||
export type StripEvent = StripBusOutputChanged | StripMuted | StripGainChanged;
|
||||
|
@ -41,7 +46,7 @@ export interface StripMuted {
|
|||
}
|
||||
|
||||
export class Strip extends React.Component<StripProps, StripState> {
|
||||
private defaultValues: StripState;
|
||||
private defaultValues: Omit<StripState, StateDefaultValueException>;
|
||||
private eventCounter = new EventCounter<"onSliderResetDefaults">();
|
||||
constructor(props: StripProps) {
|
||||
super(props);
|
||||
|
@ -59,12 +64,16 @@ export class Strip extends React.Component<StripProps, StripState> {
|
|||
? this.defaultValues[name]
|
||||
: initialValues[name];
|
||||
};
|
||||
this.state = Object.fromEntries(
|
||||
Object.entries(this.defaultValues).map(([name]) => [
|
||||
name,
|
||||
getValue(name as keyof typeof this.defaultValues) as any,
|
||||
])
|
||||
) as StripState;
|
||||
this.state = {
|
||||
...(Object.fromEntries(
|
||||
Object.entries(this.defaultValues).map(([name]) => [
|
||||
name,
|
||||
getValue(name as keyof typeof this.defaultValues) as any,
|
||||
])
|
||||
) as Omit<StripState, StateDefaultValueException>),
|
||||
showOutputdB:
|
||||
props.showOutputdB !== undefined ? props.showOutputdB : true,
|
||||
};
|
||||
this.eventCounter.on({
|
||||
callback: this.onResetDefaults.bind(this),
|
||||
count: 2,
|
||||
|
@ -135,18 +144,21 @@ export class Strip extends React.Component<StripProps, StripState> {
|
|||
return (
|
||||
<>
|
||||
<Stack direction={"row"}>
|
||||
<Stack alignItems={"center"} style={{ maxWidth: "min-content" }}>
|
||||
<Input
|
||||
inputProps={{
|
||||
"aria-labelledby": "input-slider",
|
||||
itemType: "number",
|
||||
style: { padding: 0 },
|
||||
}}
|
||||
<Stack alignItems={"center"} style={{ maxWidth: "70px" }}>
|
||||
<TextField
|
||||
// inputProps={{
|
||||
// "aria-labelledby": "input-slider",
|
||||
// itemType: "number",
|
||||
// style: { padding: 0 },
|
||||
// }}
|
||||
value={this.state.gain}
|
||||
onWheel={(e) => this.onStripWheel(e)}
|
||||
onClick={(e) => this.stopPropagation(e)}
|
||||
size="small"
|
||||
sx={{ marginInline: "5px" }}
|
||||
type="number"
|
||||
label={this.props.name}
|
||||
// sx={{minWidth: "4em", maxWidth: "5em"}}
|
||||
// fullWidth
|
||||
/>
|
||||
<Slider
|
||||
sx={{
|
||||
|
@ -171,7 +183,7 @@ export class Strip extends React.Component<StripProps, StripState> {
|
|||
/>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<ButtonGroup orientation="vertical" sx={{paddingInlineStart:"5px"}}>
|
||||
<ButtonGroup orientation="vertical">
|
||||
{[
|
||||
...Array(this.props.physicalBuses + this.props.virtualBuses),
|
||||
].map((_v, i) => (
|
||||
|
|
|
@ -26,7 +26,13 @@ function random(min: number, max: number, floor: boolean = true) {
|
|||
}
|
||||
|
||||
export default function Home() {
|
||||
const theme = useMemo(() => createTheme({ palette: { mode: "dark",background:{default: "black"} } }), []);
|
||||
const theme = useMemo(
|
||||
() =>
|
||||
createTheme({
|
||||
palette: { mode: "dark", background: { default: "#000" } },
|
||||
}),
|
||||
[]
|
||||
);
|
||||
function onStripEvent(event: StripEvent) {
|
||||
console.log(event);
|
||||
}
|
||||
|
@ -36,9 +42,7 @@ export default function Home() {
|
|||
}, []);
|
||||
const [snackBarVisible, setSnackBarVisibility] = useState(false);
|
||||
const breakPoints = useMemo(() => theme.breakpoints.values, []);
|
||||
const [width, setWidth] = useState(
|
||||
1000
|
||||
);
|
||||
const [width, setWidth] = useState(1000);
|
||||
const eventCounter = useMemo(() => {
|
||||
const eventCounter = new EventCounter<"emptySpaceClick">();
|
||||
eventCounter.on({
|
||||
|
@ -93,6 +97,7 @@ export default function Home() {
|
|||
const buses = { virtual: 3, physical: 5 };
|
||||
const amountOfStrips = strips.physical + strips.virtual;
|
||||
const amountOfBuses = buses.physical + buses.virtual;
|
||||
const virtualInputNames = useMemo(() => ["VAIO", "AUX", "VAIO3"], []);
|
||||
if (typeof document !== "undefined") {
|
||||
document.onclick = () => eventCounter.emit("emptySpaceClick");
|
||||
window.onresize = () => {
|
||||
|
@ -115,8 +120,8 @@ export default function Home() {
|
|||
);
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<Container
|
||||
id="container"
|
||||
<Container
|
||||
id="container"
|
||||
maxWidth={"xl"}
|
||||
style={{ height: "100%", paddingInline: "10px" }}
|
||||
>
|
||||
|
@ -129,35 +134,44 @@ export default function Home() {
|
|||
display={"flex"}
|
||||
alignItems={"center"}
|
||||
justifyContent={"space-evenly"}
|
||||
columns={{ xs: 8, sm: 12, md: 16, lg: 12 }}
|
||||
columns={{ xs: 8, sm: 12, md: 16, lg: 14 }}
|
||||
>
|
||||
{[...Array(amountOfStrips)].map((_v, stripId) => (
|
||||
<React.Fragment
|
||||
key={`${stripId < amountOfStrips ? "a" : "b"}${
|
||||
stripId < amountOfStrips
|
||||
? stripId + 1
|
||||
: stripId + 1 - amountOfStrips
|
||||
}`}
|
||||
>
|
||||
<Grid
|
||||
lgOffset={stripId === strips.physical ? 2 : 0}
|
||||
mdOffset={stripId === strips.physical ? 0.5 : 0}
|
||||
sx={{ minWidth: "fit-content" }}
|
||||
>
|
||||
<Typography variant="overline">{`Strip #${
|
||||
stripId + 1
|
||||
}`}</Typography>
|
||||
<Strip
|
||||
onChange={(ev) => onStripEvent(ev)}
|
||||
physicalBuses={buses.physical}
|
||||
virtualBuses={buses.virtual}
|
||||
/>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
))}
|
||||
{[...Array(amountOfStrips)].map((_v, stripId) => {
|
||||
const isPhysical = stripId < strips.physical;
|
||||
const name = `${isPhysical ? "A" : "B"}${
|
||||
isPhysical ? stripId + 1 : stripId + 1 - strips.physical
|
||||
}`;
|
||||
return (
|
||||
<React.Fragment key={name}>
|
||||
<Grid
|
||||
lgOffset={stripId === strips.physical ? 2 : 0}
|
||||
mdOffset={stripId === strips.physical ? 0.8 : 0}
|
||||
sx={{ minWidth: "fit-content" }}
|
||||
>
|
||||
{/* <Typography variant="overline">{`Strip #${
|
||||
stripId + 1
|
||||
}`}</Typography> */}
|
||||
<Strip
|
||||
onChange={(ev) => onStripEvent(ev)}
|
||||
physicalBuses={buses.physical}
|
||||
virtualBuses={buses.virtual}
|
||||
name={
|
||||
isPhysical
|
||||
? `#${stripId + 1}`
|
||||
: virtualInputNames[stripId - strips.physical]
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
<Typography variant="h5">Outputs</Typography>
|
||||
<BusesList width={width} physical={buses.physical} virtual={buses.virtual} />
|
||||
<BusesList
|
||||
width={width}
|
||||
physical={buses.physical}
|
||||
virtual={buses.virtual}
|
||||
/>
|
||||
</div>
|
||||
</Container>
|
||||
<Snackbar
|
||||
|
@ -168,15 +182,16 @@ export default function Home() {
|
|||
message={
|
||||
<>
|
||||
<Typography fontWeight={600}>Tips:</Typography>
|
||||
<Typography component={"span"}>
|
||||
<Typography component={"span"}>
|
||||
<Typography variant={"button"} fontWeight={500}>
|
||||
Double {isItMobileDevice? "tap": "click"}
|
||||
Double {isItMobileDevice ? "tap" : "click"}
|
||||
</Typography>{" "}
|
||||
on any gain slider to reset it's value to 0 dB<br/>
|
||||
on any gain slider to reset it's value to 0 dB
|
||||
<br />
|
||||
</Typography>
|
||||
<Typography component={"span"}>
|
||||
<Typography variant={"button"} fontWeight={500}>
|
||||
Triple {isItMobileDevice? "tap": "click"}
|
||||
Triple {isItMobileDevice ? "tap" : "click"}
|
||||
</Typography>{" "}
|
||||
on empty space for toggle fullscreen
|
||||
</Typography>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export function isItMobile(userAgent: string) {
|
||||
return (
|
||||
userAgent.includes("Android") ||
|
||||
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
|
||||
userAgent
|
||||
) ||
|
||||
|
|
Loading…
Reference in New Issue
Block a user