diff --git a/react/CMakeLists.txt b/react/CMakeLists.txt index a8a69a3..2569431 100644 --- a/react/CMakeLists.txt +++ b/react/CMakeLists.txt @@ -34,7 +34,6 @@ add_custom_command( src/WifiChannel.tsx src/PluginControlView.tsx src/TemporaryDrawer.tsx - src/LoadPluginDialogBackup.tsx src/logo.svg src/AlsaDeviceInfo.tsx src/JackServerSettingsDialog.tsx @@ -42,6 +41,7 @@ add_custom_command( src/PedalBoardView.tsx src/MainPage.tsx src/App.tsx + src/AppThemed.tsx src/PresetDialog.tsx src/PluginPreset.tsx src/react-app-env.d.ts @@ -89,7 +89,7 @@ add_custom_command( src/DialogEx.tsx src/ToobWaveShapeView.tsx src/FullScreenIME.tsx - src/App.css + src/AppThemed.css src/PluginPresetSelector.tsx src/Utility.tsx src/SelectMidiChannelsDialog.tsx diff --git a/react/src/AboutDialog.tsx b/react/src/AboutDialog.tsx index 5b14644..929926e 100644 --- a/react/src/AboutDialog.tsx +++ b/react/src/AboutDialog.tsx @@ -1,19 +1,20 @@ import React, { SyntheticEvent, Component } from 'react'; -import IconButton from '@material-ui/core/IconButton'; -import Typography from '@material-ui/core/Typography'; +import IconButton from '@mui/material/IconButton'; +import Typography from '@mui/material/Typography'; import { PiPedalModel, PiPedalModelFactory, State } from './PiPedalModel'; -import { TransitionProps } from '@material-ui/core/transitions/transition'; -import Slide from '@material-ui/core/Slide'; -import AppBar from '@material-ui/core/AppBar'; -import Toolbar from '@material-ui/core/Toolbar'; -import { Theme, withStyles, WithStyles, createStyles } from '@material-ui/core/styles'; -import ArrowBackIcon from '@material-ui/icons/ArrowBack'; -import Divider from '@material-ui/core/Divider'; +import AppBar from '@mui/material/AppBar'; +import Toolbar from '@mui/material/Toolbar'; +import ArrowBackIcon from '@mui/icons-material//ArrowBack'; +import Divider from '@mui/material/Divider'; import JackHostStatus from './JackHostStatus'; import {PiPedalError} from './PiPedalError'; import DialogEx from './DialogEx'; +import { Theme, createStyles } from '@mui/material/styles'; +import { withStyles, WithStyles} from '@mui/styles'; +import Slide, {SlideProps} from '@mui/material/Slide'; + interface AboutDialogProps extends WithStyles { open: boolean; @@ -81,10 +82,9 @@ const styles = (theme: Theme) => createStyles({ const Transition = React.forwardRef(function Transition( - props: TransitionProps & { children?: React.ReactElement }, - ref: React.Ref, + props: SlideProps, ref: React.Ref ) { - return ; + return (); }); diff --git a/react/src/App.tsx b/react/src/App.tsx index 538bd5c..51b896f 100644 --- a/react/src/App.tsx +++ b/react/src/App.tsx @@ -17,48 +17,10 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -import { SyntheticEvent } from 'react'; -import { ThemeProvider, WithStyles } from '@mui/styles'; -import { createTheme, StyledEngineProvider, adaptV4Theme, Theme } from '@mui/material/styles'; +import React from 'react'; +import { ThemeProvider, createTheme, StyledEngineProvider, Theme } from '@mui/material/styles'; -import './App.css'; -import AppBar from '@mui/material/AppBar'; -import Toolbar from '@mui/material/Toolbar'; -import CssBaseline from '@mui/material/CssBaseline'; -import Typography from '@mui/material/Typography'; -import createStyles from '@mui/styles/createStyles'; -import withStyles from '@mui/styles/withStyles'; -import IconButton from '@mui/material/IconButton'; -import MenuButton from '@mui/icons-material/Menu'; -import { TemporaryDrawer } from './TemporaryDrawer'; -import FullscreenIcon from '@mui/icons-material/Fullscreen'; -import FullscreenExitIcon from '@mui/icons-material/FullscreenExit'; -import List from '@mui/material/List'; -import Divider from '@mui/material/Divider'; -import ListItem from '@mui/material/ListItem'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import ListItemText from '@mui/material/ListItemText'; -import CircularProgress from '@mui/material/CircularProgress'; -import { OnChangedHandler } from './ObservableProperty'; -import ErrorOutlineIcon from '@mui/icons-material/Error'; -import ResizeResponsiveComponent from './ResizeResponsiveComponent'; -import Button from '@mui/material/Button'; -import PresetSelector from './PresetSelector'; -import SettingsDialog from './SettingsDialog'; -import AboutDialog from './AboutDialog'; -import BankDialog from './BankDialog'; - -import { PiPedalModelFactory, PiPedalModel, State, ZoomedControlInfo } from './PiPedalModel'; -import ZoomedUiControl from './ZoomedUiControl' -import MainPage from './MainPage'; -import DialogContent from '@mui/material/DialogContent'; -import DialogContentText from '@mui/material/DialogContentText'; -import Dialog from '@mui/material/Dialog'; -import DialogActions from '@mui/material/DialogActions'; -import ListSubheader from '@mui/material/ListSubheader'; -import { BankIndex, BankIndexEntry } from './Banks'; -import RenameDialog from './RenameDialog'; -import JackStatusView from './JackStatusView'; +import AppThemed from "./AppThemed"; @@ -71,7 +33,7 @@ declare module '@mui/styles/defaultTheme' { -const theme = createTheme(adaptV4Theme({ +const theme = createTheme({ palette: { primary: { main: "#324c6c" @@ -80,809 +42,27 @@ const theme = createTheme(adaptV4Theme({ main: "#FF6060" } } -})); - -const appStyles = ({ palette, spacing, mixins }: Theme) => createStyles({ - loadingContent: { - display: "block", - position: "absolute", - minHeight: "10em", - left: "0px", - top: "0px", - width: "100%", - height: "100%", - background: "#DDD", - opacity: "0.95", - justifyContent: "center", - textAlign: "center", - zIndex: 2010 - }, - errorContent: { - - display: "flex", - flexDirection: "column", - justifyContent: "center", - flexWrap: "nowrap", - alignItems: "center", - position: "fixed", - minHeight: "10em", - left: "0px", - top: "0px", - width: "100%", - height: "100%", - color: "#444", - zIndex: 2000 - }, - errorContentMask: { - position: "absolute", left: 0, top: 0, - width: "100%", height: "100%", - background: "#BBB", - opacity: 0.95, - zIndex: 1999 - }, - errorText: { - marginTop: 0, - padding: 0, - marginBottom: 12, - fontWeight: 500, - fontSize: "13pt", - maxWidth: 250, - opacity: 1, - zIndex: 2010, - }, - progressText: { - marginTop: 0, - fontWeight: 500, - fontSize: "13pt", - maxWidth: 250, - opacity: 1, - zIndex: 2010, - paddingTop: 12, - }, - - errorMessageBox: { - flex: "0 0 auto", - width: 300, - marginLeft: "auto", - marginRight: "auto", - zIndex: 2010 - - - }, - errorMessage: { - color: '#000', - textAlign: "left", - zIndex: 2010 - - }, - loadingBox: { - position: "relative", - top: "20%", - width: "120px", - color: "#888", - marginLeft: "auto", - marginRight: "auto", - // border: "3px solid #888", - borderRadius: "12px", - padding: "12px", - justifyContent: "center", - textAlign: "center", - opacity: 0.8, - zIndex: 2010 - - }, - loadingBoxItem: { - justifyContent: "center", - textAlign: "center", - zIndex: 2010 - - }, - - - toolBarContent: - { - position: "absolute", top: 0, width: "100%" - }, - - toolBarSpacer: - { - position: "relative", flex: "0 0 auto" - }, - - - mainFrame: { - overflow: "hidden", - display: "flex", - flexFlow: "column", - flex: "1 1 100%" - }, - - toolbarSizingPosition: { - flexGrow: 0, - flexShrink: 1, - width: "100%", - flexBasis: "auto" - }, - mainSizingPosition: { - overflow: "hidden", - flex: "1 1 auto" - }, - - heroContent: { - backgroundColor: palette.background.paper, - position: "relative", - height: "100%", - width: "100%" - }, - - drawerItem: { - width: 350, - background: "#FF8080" - }, - drawerItemFullWidth: { - width: 'auto', - }, - - icon: { - marginRight: spacing(2), - }, - - heroButtons: { - marginTop: spacing(4), - }, - cardGrid: { - paddingTop: spacing(8), - paddingBottom: spacing(8), - }, - card: { - height: '100%', - display: 'flex', - flexDirection: 'column', - }, - cardMedia: { - paddingTop: '56.25%', // 16:9 - }, - cardContent: { - flexGrow: 1, - }, - footer: { - backgroundColor: palette.background.paper, - padding: spacing(6), - }, }); -function supportsFullScreen(): boolean { - let doc: any = window.document; - let docEl: any = doc.documentElement; - var requestFullScreen = docEl.requestFullscreen || docEl.mozRequestFullScreen || docEl.webkitRequestFullScreen || docEl.msRequestFullscreen; - return (!!requestFullScreen); -} +type AppThemeProps = { -function setFullScreen(value: boolean) { - let doc: any = window.document; - let docEl: any = doc.documentElement; - - var requestFullScreen = docEl.requestFullscreen || docEl.mozRequestFullScreen || docEl.webkitRequestFullScreen || docEl.msRequestFullscreen; - var cancelFullScreen = doc.exitFullscreen || doc.mozCancelFullScreen || doc.webkitExitFullscreen || doc.msExitFullscreen; - - if (!doc.fullscreenElement && !doc.mozFullScreenElement && !doc.webkitFullscreenElement && !doc.msFullscreenElement) { - requestFullScreen.call(docEl); - } - else { - cancelFullScreen.call(doc); - } -} - - -function preventDefault(e: SyntheticEvent): void { - e.stopPropagation(); - e.preventDefault(); -} - -type AppState = { - zoomedControlInfo: ZoomedControlInfo | undefined; - - isDrawerOpen: boolean; - errorMessage: string; - displayState: State; - - canFullScreen: boolean; - isFullScreen: boolean; - tinyToolBar: boolean; - alertDialogOpen: boolean; - alertDialogMessage: string; - isSettingsDialogOpen: boolean; - isDebug: boolean; - - renameBankDialogOpen: boolean; - saveBankAsDialogOpen: boolean; - - aboutDialogOpen: boolean; - bankDialogOpen: boolean; - editBankDialogOpen: boolean; - zoomedControlOpen: boolean; - - - presetName: string; - presetChanged: boolean; - banks: BankIndex; - bankDisplayItems: number; }; -interface AppProps extends WithStyles { -} - -const App = withStyles(appStyles)(class extends ResizeResponsiveComponent { +const App = (class extends React.Component { // Before the component mounts, we initialise our state - model_: PiPedalModel; - errorChangeHandler_: OnChangedHandler; - stateChangeHandler_: OnChangedHandler; - - constructor(props: AppProps) { + constructor(props: AppThemeProps) { super(props); - this.model_ = PiPedalModelFactory.getInstance(); - - this.model_.zoomedUiControl.addOnChangedHandler( - () => { - this.setState({ - zoomedControlOpen: this.model_.zoomedUiControl.get() !== undefined, - zoomedControlInfo: this.model_.zoomedUiControl.get() - }); - } - ); - this.state = { - zoomedControlInfo: this.model_.zoomedUiControl.get(), - isDrawerOpen: false, - errorMessage: this.model_.errorMessage.get(), - displayState: this.model_.state.get(), - canFullScreen: supportsFullScreen(), - isFullScreen: !!document.fullscreenElement, - tinyToolBar: false, - alertDialogOpen: false, - alertDialogMessage: "", - presetName: this.model_.presets.get().getSelectedText(), - isSettingsDialogOpen: false, - isDebug: true, - presetChanged: this.model_.presets.get().presetChanged, - banks: this.model_.banks.get(), - renameBankDialogOpen: false, - saveBankAsDialogOpen: false, - aboutDialogOpen: false, - bankDialogOpen: false, - editBankDialogOpen: false, - zoomedControlOpen: false, - bankDisplayItems: 5 - }; - - this.errorChangeHandler_ = this.setErrorMessage.bind(this); - this.stateChangeHandler_ = this.setDisplayState.bind(this); - this.presetChangedHandler = this.presetChangedHandler.bind(this); - this.alertMessageChangedHandler = this.alertMessageChangedHandler.bind(this); - this.handleCloseAlert = this.handleCloseAlert.bind(this); - this.banksChangedHandler = this.banksChangedHandler.bind(this); - } - - onOpenBank(bankId: number) { - this.model_.openBank(bankId) - .catch((error) => this.model_.showAlert(error)); - - } - - handleSaveBankAsOk(newName: string) { - let currentName = this.model_.banks.get().getSelectedEntryName(); - if (currentName === newName) { - this.setState({ - renameBankDialogOpen: false, - saveBankAsDialogOpen: false - }); - return; - - } - - if (this.model_.banks.get().nameExists(newName)) { - this.model_.showAlert("A bank by that name already exists."); - return; - } - this.setState({ - renameBankDialogOpen: false, - saveBankAsDialogOpen: false - }); - this.model_.saveBankAs(this.model_.banks.get().selectedBank, newName) - .catch((error) => { - this.model_.showAlert(error); - }); - - } - handleBankRenameOk(newName: string) { - let currentName = this.model_.banks.get().getSelectedEntryName(); - if (currentName === newName) { - this.setState({ - renameBankDialogOpen: false, - saveBankAsDialogOpen: false - }); - return; - - } - - if (this.model_.banks.get().nameExists(newName)) { - this.model_.showAlert("A bank by that name already exists."); - return; - } - this.setState({ - renameBankDialogOpen: false - }); - this.model_.renameBank(this.model_.banks.get().selectedBank, newName) - .catch((error) => { - this.model_.showAlert(error); - }); - - } - handleSettingsDialogClose() { - this.setState({ - isSettingsDialogOpen: false - }); - } - handleDrawerSettingsClick() { - this.setState({ - isDrawerOpen: false, - isSettingsDialogOpen: true - }); - - } - - handleDrawerManageBanks() { - this.setState({ - isDrawerOpen: false, - bankDialogOpen: true, - editBankDialogOpen: true - }); - - } - handleDrawerSelectBank() { - this.setState({ - isDrawerOpen: false, - bankDialogOpen: true, - editBankDialogOpen: false - }); - - } - - handleDrawerAboutClick() { - this.setState({ - aboutDialogOpen: true - }); - - } - handleDrawerRenameBank() { - this.setState({ - isDrawerOpen: false, - renameBankDialogOpen: true, - saveBankAsDialogOpen: false - }); - - } - handleDrawerSaveBankAs() { - this.setState({ - isDrawerOpen: false, - renameBankDialogOpen: false, - saveBankAsDialogOpen: true - }); - } - - - handleCloseAlert(e?: any, reason?: any) { - this.model_.alertMessage.set(""); - } - banksChangedHandler() { - this.setState({ - banks: this.model_.banks.get() - }); - } - presetChangedHandler() { - let presets = this.model_.presets.get(); - - this.setState({ - presetName: presets.getSelectedText(), - presetChanged: presets.presetChanged - }); - } - toggleFullScreen(): void { - setFullScreen(this.state.isFullScreen); - this.setState({ isFullScreen: !this.state.isFullScreen }); - } - componentDidMount() { - - super.componentDidMount(); - - window.addEventListener("beforeunload", (e) => { - e.preventDefault(); - if (this.model_.state.get() === State.Ready) { - e.returnValue = "Are you sure you want to leave this page?"; - return "Are you sure you want to leave this page?"; - } - }); - - this.model_.errorMessage.addOnChangedHandler(this.errorChangeHandler_); - this.model_.state.addOnChangedHandler(this.stateChangeHandler_); - this.model_.pedalBoard.addOnChangedHandler(this.presetChangedHandler); - this.model_.alertMessage.addOnChangedHandler(this.alertMessageChangedHandler); - this.model_.banks.addOnChangedHandler(this.banksChangedHandler); - this.alertMessageChangedHandler(); - } - - - updateOverscroll(): void { - if (this.model_.serverVersion) { - // no pull-down refresh on android devices once we're ready (unless we're debug) - let preventOverscroll = - this.model_.state.get() === State.Ready - && !this.model_.serverVersion.debug; - - let overscrollBehavior = preventOverscroll ? "none" : "auto"; - document.body.style.overscrollBehavior = overscrollBehavior; - } - } - - componentDidUpdate() { - } - - componentWillUnmount() { - super.componentWillUnmount(); - this.model_.errorMessage.removeOnChangedHandler(this.errorChangeHandler_); - this.model_.state.removeOnChangedHandler(this.stateChangeHandler_); - this.model_.pedalBoard.removeOnChangedHandler(this.presetChangedHandler); - this.model_.banks.addOnChangedHandler(this.banksChangedHandler); - - } - - alertMessageChangedHandler() { - let message = this.model_.alertMessage.get(); - if (message === "") { - this.setState({ alertDialogOpen: false }); - // leave the message intact so the dialog can fade. - } else { - this.setState({ - alertDialogOpen: true, - alertDialogMessage: message - }); - } - - } - updateResponsive() { - // functional, but disabled. - // let tinyToolBar_ = this.windowSize.height < 600; - // this.setState({ tinyToolBar: tinyToolBar_ }); - - let height = this.windowSize.height; - - const ENTRY_HEIGHT = 48; - // ENTRY_HEIGHT*6 +K = 727 from observation. - const K = 450; - - let bankEntries = Math.floor((height - K) / ENTRY_HEIGHT); - if (bankEntries < 1) bankEntries = 1; - if (bankEntries > 7) bankEntries = 7; - this.setState({ bankDisplayItems: bankEntries }); - - } - onWindowSizeChanged(width: number, height: number): void { - super.onWindowSizeChanged(width, height); - this.updateResponsive(); - } - - - setErrorMessage(message: string): void { - this.setState({ errorMessage: message }); - } - setDisplayState(newState: State): void { - this.updateOverscroll(); - - this.setState({ displayState: newState }); - } - - showDrawer() { - this.setState({ isDrawerOpen: true }) - } - hideDrawer() { - this.setState({ isDrawerOpen: false }) - } - shortBankList(banks: BankIndex): BankIndexEntry[] { - let n = this.state.bankDisplayItems; - let entries = banks.entries; - if (entries.length < n + 1) { // +1 for the .... entry. - return entries; - } - let result: BankIndexEntry[] = []; - let selectedIndex = -1; - for (let i = 0; i < entries.length; ++i) { - if (entries[i].instanceId === banks.selectedBank) { - selectedIndex = i; - break; - } - } - if (n > entries.length) n = entries.length; - if (selectedIndex > n) { - for (let i = 0; i < n - 1; ++i) { - result.push(entries[i]); - } - result.push(entries[selectedIndex]); - } else { - for (let i = 0; i < n; ++i) { - result.push(entries[i]); - } - } - return result; - } render() { - - const { classes } = this.props; - - let shortBankList = this.shortBankList(this.state.banks); - let showBankSelectDialog = shortBankList.length !== this.state.banks.entries.length; - - return ( -
{ - if (!this.model_.serverVersion?.debug ?? false) { - e.preventDefault(); e.stopPropagation(); - } - }} - > - - {(!this.state.tinyToolBar) ? - ( - - - { this.showDrawer() }} - size="large"> - - -
-
- -
-
- {this.state.canFullScreen && - { this.toggleFullScreen(); }} - size="large"> - {this.state.isFullScreen ? ( - - ) : ( - - - )} - - - } - - - ) : ( -
- { this.showDrawer() }} - size="large"> - - - {this.state.canFullScreen && ( - { this.toggleFullScreen(); }} - size="large"> - {this.state.isFullScreen ? ( - - ) : ( - - - )} - - - )} -
- )} - { this.hideDrawer(); }} > - Banks - }> - { - shortBankList.map((bank) => { - return ( - this.onOpenBank(bank.instanceId)} - > - - - - - ); - }) - } - { - showBankSelectDialog && ( - this.handleDrawerSelectBank()} - > - - - - - - ) - } - - - - { this.handleDrawerRenameBank() }}> - - - - { this.handleDrawerSaveBankAs() }} > - - - - - - { this.handleDrawerManageBanks(); }}> - - - - - - - - - { this.handleDrawerSettingsClick() }}> - - - - - - { this.handleDrawerAboutClick() }}> - - - - - - - - - {!this.state.tinyToolBar && ( - - )} -
-
-
- {(this.state.displayState !== State.Loading) && ( - - )} -
- -
-
- this.setState({ bankDialogOpen: false })} /> - this.setState({ aboutDialogOpen: false })} /> - this.handleSettingsDialogClose()} /> - { - this.setState({ - renameBankDialogOpen: false, - saveBankAsDialogOpen: false - }) - }} - onOk={(text: string) => { - if (this.state.renameBankDialogOpen) { - this.handleBankRenameOk(text); - } else if (this.state.saveBankAsDialogOpen) { - this.handleSaveBankAsOk(text); - } - } - } - /> - - { this.setState({ zoomedControlOpen: false }); }} - onDialogClosed={() => { this.model_.zoomedUiControl.set(undefined); } - } - /> - - - - { - this.model_.alertMessage.get() - } - - - - - - - -
-
- -
-
- -
- - Reconnecting... - -
-
-
-
-
 
-
-
- -
-
-

- Error: {this.state.errorMessage} -

-
-
- - -
- -
- -
 
- -
-
-
-
-
- -
- - Loading... - -
-
- -
+ ); diff --git a/react/src/App.css b/react/src/AppThemed.css similarity index 100% rename from react/src/App.css rename to react/src/AppThemed.css diff --git a/react/src/AppThemed.tsx b/react/src/AppThemed.tsx new file mode 100644 index 0000000..a1c69bd --- /dev/null +++ b/react/src/AppThemed.tsx @@ -0,0 +1,843 @@ +// Copyright (c) 2021 Robin Davies +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import { SyntheticEvent } from 'react'; +import { WithStyles } from '@mui/styles'; + +import './AppThemed.css'; +import AppBar from '@mui/material/AppBar'; +import Toolbar from '@mui/material/Toolbar'; +import CssBaseline from '@mui/material/CssBaseline'; +import Typography from '@mui/material/Typography'; +import createStyles from '@mui/styles/createStyles'; +import withStyles from '@mui/styles/withStyles'; +import IconButton from '@mui/material/IconButton'; +import MenuButton from '@mui/icons-material/Menu'; +import { TemporaryDrawer } from './TemporaryDrawer'; +import FullscreenIcon from '@mui/icons-material/Fullscreen'; +import FullscreenExitIcon from '@mui/icons-material/FullscreenExit'; +import List from '@mui/material/List'; +import Divider from '@mui/material/Divider'; +import ListItem from '@mui/material/ListItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import CircularProgress from '@mui/material/CircularProgress'; +import { OnChangedHandler } from './ObservableProperty'; +import ErrorOutlineIcon from '@mui/icons-material/Error'; +import ResizeResponsiveComponent from './ResizeResponsiveComponent'; +import Button from '@mui/material/Button'; +import PresetSelector from './PresetSelector'; +import SettingsDialog from './SettingsDialog'; +import AboutDialog from './AboutDialog'; +import BankDialog from './BankDialog'; + +import { PiPedalModelFactory, PiPedalModel, State, ZoomedControlInfo } from './PiPedalModel'; +import ZoomedUiControl from './ZoomedUiControl' +import MainPage from './MainPage'; +import DialogContent from '@mui/material/DialogContent'; +import DialogContentText from '@mui/material/DialogContentText'; +import Dialog from '@mui/material/Dialog'; +import DialogActions from '@mui/material/DialogActions'; +import ListSubheader from '@mui/material/ListSubheader'; +import { BankIndex, BankIndexEntry } from './Banks'; +import RenameDialog from './RenameDialog'; +import JackStatusView from './JackStatusView'; +import { Theme } from '@mui/material/styles'; + + + +const appStyles = (theme: Theme) => createStyles({ + loadingContent: { + display: "block", + position: "absolute", + minHeight: "10em", + left: "0px", + top: "0px", + width: "100%", + height: "100%", + background: "#DDD", + opacity: "0.95", + justifyContent: "center", + textAlign: "center", + zIndex: 2010 + }, + errorContent: { + + display: "flex", + flexDirection: "column", + justifyContent: "center", + flexWrap: "nowrap", + alignItems: "center", + position: "fixed", + minHeight: "10em", + left: "0px", + top: "0px", + width: "100%", + height: "100%", + color: "#444", + zIndex: 2000 + }, + errorContentMask: { + position: "absolute", left: 0, top: 0, + width: "100%", height: "100%", + background: "#BBB", + opacity: 0.95, + zIndex: 1999 + }, + errorText: { + marginTop: 0, + padding: 0, + marginBottom: 12, + fontWeight: 500, + fontSize: "13pt", + maxWidth: 250, + opacity: 1, + zIndex: 2010, + }, + progressText: { + marginTop: 0, + fontWeight: 500, + fontSize: "13pt", + maxWidth: 250, + opacity: 1, + zIndex: 2010, + paddingTop: 12, + }, + + errorMessageBox: { + flex: "0 0 auto", + width: 300, + marginLeft: "auto", + marginRight: "auto", + zIndex: 2010 + + + }, + errorMessage: { + color: '#000', + textAlign: "left", + zIndex: 2010 + + }, + loadingBox: { + position: "relative", + top: "20%", + width: "120px", + color: "#888", + marginLeft: "auto", + marginRight: "auto", + // border: "3px solid #888", + borderRadius: "12px", + padding: "12px", + justifyContent: "center", + textAlign: "center", + opacity: 0.8, + zIndex: 2010 + + }, + loadingBoxItem: { + justifyContent: "center", + textAlign: "center", + zIndex: 2010 + + }, + + + toolBarContent: + { + position: "absolute", top: 0, width: "100%" + }, + + toolBarSpacer: + { + position: "relative", flex: "0 0 auto" + }, + + + mainFrame: { + overflow: "hidden", + display: "flex", + flexFlow: "column", + flex: "1 1 100%" + }, + + toolbarSizingPosition: { + flexGrow: 0, + flexShrink: 1, + width: "100%", + flexBasis: "auto" + }, + mainSizingPosition: { + overflow: "hidden", + flex: "1 1 auto" + }, + + heroContent: { + backgroundColor: "#FFFFFF", + position: "relative", + height: "100%", + width: "100%" + }, + + drawerItem: { + width: 350, + background: "#FF8080" + }, + drawerItemFullWidth: { + width: 'auto', + }, + +}); + + +function supportsFullScreen(): boolean { + let doc: any = window.document; + let docEl: any = doc.documentElement; + var requestFullScreen = docEl.requestFullscreen || docEl.mozRequestFullScreen || docEl.webkitRequestFullScreen || docEl.msRequestFullscreen; + return (!!requestFullScreen); + +} + +function setFullScreen(value: boolean) { + let doc: any = window.document; + let docEl: any = doc.documentElement; + + var requestFullScreen = docEl.requestFullscreen || docEl.mozRequestFullScreen || docEl.webkitRequestFullScreen || docEl.msRequestFullscreen; + var cancelFullScreen = doc.exitFullscreen || doc.mozCancelFullScreen || doc.webkitExitFullscreen || doc.msExitFullscreen; + + if (!doc.fullscreenElement && !doc.mozFullScreenElement && !doc.webkitFullscreenElement && !doc.msFullscreenElement) { + requestFullScreen.call(docEl); + } + else { + cancelFullScreen.call(doc); + } +} + + +function preventDefault(e: SyntheticEvent): void { + e.stopPropagation(); + e.preventDefault(); +} + +type AppState = { + zoomedControlInfo: ZoomedControlInfo | undefined; + + isDrawerOpen: boolean; + errorMessage: string; + displayState: State; + + canFullScreen: boolean; + isFullScreen: boolean; + tinyToolBar: boolean; + alertDialogOpen: boolean; + alertDialogMessage: string; + isSettingsDialogOpen: boolean; + isDebug: boolean; + + renameBankDialogOpen: boolean; + saveBankAsDialogOpen: boolean; + + aboutDialogOpen: boolean; + bankDialogOpen: boolean; + editBankDialogOpen: boolean; + zoomedControlOpen: boolean; + + + presetName: string; + presetChanged: boolean; + banks: BankIndex; + bankDisplayItems: number; +}; +interface AppProps extends WithStyles { +} + +const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent { + // Before the component mounts, we initialise our state + + model_: PiPedalModel; + errorChangeHandler_: OnChangedHandler; + stateChangeHandler_: OnChangedHandler; + + constructor(props: AppProps) { + super(props); + this.model_ = PiPedalModelFactory.getInstance(); + + this.model_.zoomedUiControl.addOnChangedHandler( + () => { + this.setState({ + zoomedControlOpen: this.model_.zoomedUiControl.get() !== undefined, + zoomedControlInfo: this.model_.zoomedUiControl.get() + }); + } + ); + + this.state = { + zoomedControlInfo: this.model_.zoomedUiControl.get(), + isDrawerOpen: false, + errorMessage: this.model_.errorMessage.get(), + displayState: this.model_.state.get(), + canFullScreen: supportsFullScreen(), + isFullScreen: !!document.fullscreenElement, + tinyToolBar: false, + alertDialogOpen: false, + alertDialogMessage: "", + presetName: this.model_.presets.get().getSelectedText(), + isSettingsDialogOpen: false, + isDebug: true, + presetChanged: this.model_.presets.get().presetChanged, + banks: this.model_.banks.get(), + renameBankDialogOpen: false, + saveBankAsDialogOpen: false, + aboutDialogOpen: false, + bankDialogOpen: false, + editBankDialogOpen: false, + zoomedControlOpen: false, + bankDisplayItems: 5 + + }; + + this.errorChangeHandler_ = this.setErrorMessage.bind(this); + this.stateChangeHandler_ = this.setDisplayState.bind(this); + this.presetChangedHandler = this.presetChangedHandler.bind(this); + this.alertMessageChangedHandler = this.alertMessageChangedHandler.bind(this); + this.handleCloseAlert = this.handleCloseAlert.bind(this); + this.banksChangedHandler = this.banksChangedHandler.bind(this); + + } + + + onOpenBank(bankId: number) { + this.model_.openBank(bankId) + .catch((error) => this.model_.showAlert(error)); + + } + + handleSaveBankAsOk(newName: string) { + let currentName = this.model_.banks.get().getSelectedEntryName(); + if (currentName === newName) { + this.setState({ + renameBankDialogOpen: false, + saveBankAsDialogOpen: false + }); + return; + + } + + if (this.model_.banks.get().nameExists(newName)) { + this.model_.showAlert("A bank by that name already exists."); + return; + } + this.setState({ + renameBankDialogOpen: false, + saveBankAsDialogOpen: false + }); + this.model_.saveBankAs(this.model_.banks.get().selectedBank, newName) + .catch((error) => { + this.model_.showAlert(error); + }); + + } + handleBankRenameOk(newName: string) { + let currentName = this.model_.banks.get().getSelectedEntryName(); + if (currentName === newName) { + this.setState({ + renameBankDialogOpen: false, + saveBankAsDialogOpen: false + }); + return; + + } + + if (this.model_.banks.get().nameExists(newName)) { + this.model_.showAlert("A bank by that name already exists."); + return; + } + this.setState({ + renameBankDialogOpen: false + }); + this.model_.renameBank(this.model_.banks.get().selectedBank, newName) + .catch((error) => { + this.model_.showAlert(error); + }); + + } + handleSettingsDialogClose() { + this.setState({ + isSettingsDialogOpen: false + }); + } + handleDrawerSettingsClick() { + this.setState({ + isDrawerOpen: false, + isSettingsDialogOpen: true + }); + + } + + handleDrawerManageBanks() { + this.setState({ + isDrawerOpen: false, + bankDialogOpen: true, + editBankDialogOpen: true + }); + + } + handleDrawerSelectBank() { + this.setState({ + isDrawerOpen: false, + bankDialogOpen: true, + editBankDialogOpen: false + }); + + } + + handleDrawerAboutClick() { + this.setState({ + aboutDialogOpen: true + }); + + } + handleDrawerRenameBank() { + this.setState({ + isDrawerOpen: false, + renameBankDialogOpen: true, + saveBankAsDialogOpen: false + }); + + } + handleDrawerSaveBankAs() { + this.setState({ + isDrawerOpen: false, + renameBankDialogOpen: false, + saveBankAsDialogOpen: true + }); + } + + + handleCloseAlert(e?: any, reason?: any) { + this.model_.alertMessage.set(""); + } + banksChangedHandler() { + this.setState({ + banks: this.model_.banks.get() + }); + } + presetChangedHandler() { + let presets = this.model_.presets.get(); + + this.setState({ + presetName: presets.getSelectedText(), + presetChanged: presets.presetChanged + }); + } + toggleFullScreen(): void { + setFullScreen(this.state.isFullScreen); + this.setState({ isFullScreen: !this.state.isFullScreen }); + } + componentDidMount() { + + super.componentDidMount(); + + window.addEventListener("beforeunload", (e) => { + e.preventDefault(); + if (this.model_.state.get() === State.Ready) { + e.returnValue = "Are you sure you want to leave this page?"; + return "Are you sure you want to leave this page?"; + } + }); + + this.model_.errorMessage.addOnChangedHandler(this.errorChangeHandler_); + this.model_.state.addOnChangedHandler(this.stateChangeHandler_); + this.model_.pedalBoard.addOnChangedHandler(this.presetChangedHandler); + this.model_.alertMessage.addOnChangedHandler(this.alertMessageChangedHandler); + this.model_.banks.addOnChangedHandler(this.banksChangedHandler); + this.alertMessageChangedHandler(); + } + + + updateOverscroll(): void { + if (this.model_.serverVersion) { + // no pull-down refresh on android devices once we're ready (unless we're debug) + let preventOverscroll = + this.model_.state.get() === State.Ready + && !this.model_.serverVersion.debug; + + let overscrollBehavior = preventOverscroll ? "none" : "auto"; + document.body.style.overscrollBehavior = overscrollBehavior; + } + } + + componentDidUpdate() { + } + + componentWillUnmount() { + super.componentWillUnmount(); + this.model_.errorMessage.removeOnChangedHandler(this.errorChangeHandler_); + this.model_.state.removeOnChangedHandler(this.stateChangeHandler_); + this.model_.pedalBoard.removeOnChangedHandler(this.presetChangedHandler); + this.model_.banks.addOnChangedHandler(this.banksChangedHandler); + + } + + alertMessageChangedHandler() { + let message = this.model_.alertMessage.get(); + if (message === "") { + this.setState({ alertDialogOpen: false }); + // leave the message intact so the dialog can fade. + } else { + this.setState({ + alertDialogOpen: true, + alertDialogMessage: message + }); + } + + } + updateResponsive() { + // functional, but disabled. + // let tinyToolBar_ = this.windowSize.height < 600; + // this.setState({ tinyToolBar: tinyToolBar_ }); + + let height = this.windowSize.height; + + const ENTRY_HEIGHT = 48; + // ENTRY_HEIGHT*6 +K = 727 from observation. + const K = 450; + + let bankEntries = Math.floor((height - K) / ENTRY_HEIGHT); + if (bankEntries < 1) bankEntries = 1; + if (bankEntries > 7) bankEntries = 7; + this.setState({ bankDisplayItems: bankEntries }); + + } + onWindowSizeChanged(width: number, height: number): void { + super.onWindowSizeChanged(width, height); + this.updateResponsive(); + } + + + setErrorMessage(message: string): void { + this.setState({ errorMessage: message }); + } + setDisplayState(newState: State): void { + this.updateOverscroll(); + + this.setState({ displayState: newState }); + } + + showDrawer() { + this.setState({ isDrawerOpen: true }) + } + hideDrawer() { + this.setState({ isDrawerOpen: false }) + } + shortBankList(banks: BankIndex): BankIndexEntry[] { + let n = this.state.bankDisplayItems; + let entries = banks.entries; + if (entries.length < n + 1) { // +1 for the .... entry. + return entries; + } + let result: BankIndexEntry[] = []; + let selectedIndex = -1; + for (let i = 0; i < entries.length; ++i) { + if (entries[i].instanceId === banks.selectedBank) { + selectedIndex = i; + break; + } + } + if (n > entries.length) n = entries.length; + if (selectedIndex > n) { + for (let i = 0; i < n - 1; ++i) { + result.push(entries[i]); + } + result.push(entries[selectedIndex]); + } else { + for (let i = 0; i < n; ++i) { + result.push(entries[i]); + } + } + return result; + } + render() { + + const { classes } = this.props; + + let shortBankList = this.shortBankList(this.state.banks); + let showBankSelectDialog = shortBankList.length !== this.state.banks.entries.length; + + + return ( +
{ + if (!this.model_.serverVersion?.debug ?? false) { + e.preventDefault(); e.stopPropagation(); + } + }} + > + + {(!this.state.tinyToolBar) ? + ( + + + { this.showDrawer() }} + size="large"> + + +
+
+ +
+
+ {this.state.canFullScreen && + { this.toggleFullScreen(); }} + size="large"> + {this.state.isFullScreen ? ( + + ) : ( + + + )} + + + } + + + ) : ( +
+ { this.showDrawer() }} + size="large"> + + + {this.state.canFullScreen && ( + { this.toggleFullScreen(); }} + size="large"> + {this.state.isFullScreen ? ( + + ) : ( + + + )} + + + )} +
+ )} + { this.hideDrawer(); }} > + Banks + }> + { + shortBankList.map((bank) => { + return ( + this.onOpenBank(bank.instanceId)} + > + + + + + ); + }) + } + { + showBankSelectDialog && ( + this.handleDrawerSelectBank()} + > + + + + + + ) + } + + + + { this.handleDrawerRenameBank() }}> + + + + { this.handleDrawerSaveBankAs() }} > + + + + + + { this.handleDrawerManageBanks(); }}> + + + + + + + + + { this.handleDrawerSettingsClick() }}> + + + + + + { this.handleDrawerAboutClick() }}> + + + + + + + + + {!this.state.tinyToolBar && ( + + )} +
+
+
+ {(this.state.displayState !== State.Loading) && ( + + )} +
+ +
+
+ this.setState({ bankDialogOpen: false })} /> + this.setState({ aboutDialogOpen: false })} /> + this.handleSettingsDialogClose()} /> + { + this.setState({ + renameBankDialogOpen: false, + saveBankAsDialogOpen: false + }) + }} + onOk={(text: string) => { + if (this.state.renameBankDialogOpen) { + this.handleBankRenameOk(text); + } else if (this.state.saveBankAsDialogOpen) { + this.handleSaveBankAsOk(text); + } + } + } + /> + + { this.setState({ zoomedControlOpen: false }); }} + onDialogClosed={() => { this.model_.zoomedUiControl.set(undefined); } + } + /> + + + + { + this.model_.alertMessage.get() + } + + + + + + + +
+
+ +
+
+ +
+ + Reconnecting... + +
+
+
+
+
 
+
+
+ +
+
+

+ Error: {this.state.errorMessage} +

+
+
+ + +
+ +
+ +
 
+ +
+
+
+
+
+ +
+ + Loading... + +
+
+ +
+ ); + } +} +); + +export default AppThemed; diff --git a/react/src/BankDialog.tsx b/react/src/BankDialog.tsx index 7b2b154..57fca7e 100644 --- a/react/src/BankDialog.tsx +++ b/react/src/BankDialog.tsx @@ -18,34 +18,34 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import React, { Component } from 'react'; -import IconButton from '@material-ui/core/IconButton'; -import Typography from '@material-ui/core/Typography'; +import IconButton from '@mui/material/IconButton'; +import Typography from '@mui/material/Typography'; import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel'; import { BankIndexEntry, BankIndex } from './Banks'; -import Button from "@material-ui/core/Button"; -import ButtonBase from "@material-ui/core/ButtonBase"; -import { TransitionProps } from '@material-ui/core/transitions/transition'; -import Slide from '@material-ui/core/Slide'; -import AppBar from '@material-ui/core/AppBar'; -import Toolbar from '@material-ui/core/Toolbar'; -import { Theme, withStyles, WithStyles, createStyles } from '@material-ui/core/styles'; +import Button from "@mui/material/Button"; +import ButtonBase from "@mui/material/ButtonBase"; +import Slide, {SlideProps} from '@mui/material/Slide'; +import AppBar from '@mui/material/AppBar'; +import Toolbar from '@mui/material/Toolbar'; +import { Theme, createStyles } from '@mui/material/styles'; +import { WithStyles,withStyles } from "@mui/styles"; import DraggableGrid, { ScrollDirection } from './DraggableGrid'; -import Fade from '@material-ui/core/Fade'; +import Fade from '@mui/material/Fade'; import SelectHoverBackground from './SelectHoverBackground'; -import CloseIcon from '@material-ui/icons/Close'; -import ArrowBackIcon from '@material-ui/icons/ArrowBack'; -import EditIcon from '@material-ui/icons/Edit'; +import CloseIcon from '@mui/icons-material/Close'; +import ArrowBackIcon from '@mui/icons-material/ArrowBack'; +import EditIcon from '@mui/icons-material/Edit'; import RenameDialog from './RenameDialog'; -import MoreVertIcon from '@material-ui/icons/MoreVert'; -import ListItemIcon from '@material-ui/core/ListItemIcon'; -import ListItemText from '@material-ui/core/ListItemText'; -import Menu from '@material-ui/core/Menu'; -import MenuItem from '@material-ui/core/MenuItem'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import Menu from '@mui/material/Menu'; +import MenuItem from '@mui/material/MenuItem'; import DialogEx from './DialogEx'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@mui/material/DialogContent'; +import DialogActions from '@mui/material/DialogActions'; interface BankDialogProps extends WithStyles { show: boolean; @@ -110,18 +110,9 @@ const styles = (theme: Theme) => createStyles({ const Transition = React.forwardRef(function Transition( - props: TransitionProps & { children?: React.ReactElement }, - ref: React.Ref, + props: SlideProps, ref: React.Ref ) { - return ; -}); - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const ActionBarTransition = React.forwardRef(function Transition( - props: TransitionProps & { children?: React.ReactElement }, - ref: React.Ref, -) { - return ; + return (); }); diff --git a/react/src/JackServerSettingsDialog.tsx b/react/src/JackServerSettingsDialog.tsx index e909cb2..91672f6 100644 --- a/react/src/JackServerSettingsDialog.tsx +++ b/react/src/JackServerSettingsDialog.tsx @@ -276,7 +276,7 @@ const JackServerSettingsDialog = withStyles(styles)(
Device - this.handleDeviceChanged(e)} value={this.state.jackServerSettings.alsaDevice} style={{width: 220}} inputProps={{ @@ -302,7 +302,7 @@ const JackServerSettingsDialog = withStyles(styles)(
Sample rate - this.handleSizeChanged(e)} value={this.state.jackServerSettings.bufferSize} inputProps={{ @@ -340,7 +340,7 @@ const JackServerSettingsDialog = withStyles(styles)( Buffers - { this.onFilterChange(e); }} style={{ flex: "0 0 160px" }} - variant="standard"> + > {this.createFilterOptions()}
diff --git a/react/src/LoadPluginDialogBackup.tsx b/react/src/LoadPluginDialogBackup.tsx deleted file mode 100644 index 5d61b4d..0000000 --- a/react/src/LoadPluginDialogBackup.tsx +++ /dev/null @@ -1,462 +0,0 @@ -// Copyright (c) 2021 Robin Davies -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -import React, { ReactNode, SyntheticEvent } from 'react'; -import Grid from '@material-ui/core/Grid'; -import { createStyles, withStyles, WithStyles, Theme } from '@material-ui/core/styles'; -import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel'; -import { UiPlugin, PluginType } from './Lv2Plugin'; -import Paper from '@material-ui/core/Paper'; -import ButtonBase from '@material-ui/core/ButtonBase'; -import Button from '@material-ui/core/Button'; -import MenuItem from '@material-ui/core/MenuItem'; -import Typography from '@material-ui/core/Typography'; -import PluginInfoDialog from './PluginInfoDialog' -import PluginIcon from './PluginIcon' -import Dialog from '@material-ui/core/Dialog'; -import DialogActions from '@material-ui/core/DialogActions'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogTitle from '@material-ui/core/DialogTitle'; -import SelectHoverBackground from './SelectHoverBackground'; -import ArrowBackIcon from '@material-ui/icons/ArrowBack'; -import IconButton from '@material-ui/core/IconButton'; -import Select from '@material-ui/core/Select'; -import PluginClass from './PluginClass' -import ClearIcon from '@material-ui/icons/Clear'; -import ResizeResponsiveComponent from './ResizeResponsiveComponent'; -import { TransitionProps } from '@material-ui/core/transitions/transition'; -import Slide from '@material-ui/core/Slide'; - - -export type CloseEventHandler = () => void; -export type OkEventHandler = (pluginUri: string) => void; - -const NARROW_DISPLAY_THRESHOLD = 600; -const FILTER_STORAGE_KEY = "com.twoplay.pipedal.load_dlg.filter"; - -const Transition = React.forwardRef(function Transition( - props: TransitionProps & { children?: React.ReactElement }, - ref: React.Ref, -) { - return ; -}); - - - -const pluginGridStyles = (theme: Theme) => createStyles({ - frame: { - - position: "relative", - width: "100%", - height: "100%" - }, - - top: { - top: "0px", - right: "0px", - left: "0px", - bottom: "64px", - position: "relative", - flexGrow: 1, - background: "#eee", - overflowX: "hidden", - overflowY: "visible" - }, - bottom: { - position: "relative", - bottom: "0px", - height: "64px", - width: "100%", - display: "flex", - flexDirection: "row", - flexWrap: "nowrap", - justifyContent: "space-between", - paddingLeft: "24px", - paddingRight: "48px", - background: theme.palette.background.paper, - }, - paper: { - position: "relative", - overflow: "hidden", - height: "56px", - width: "100%", - background: theme.palette.background.paper - }, - buttonBase: { - - width: "100%", - height: "100%'" - }, - content: { - marginTop: "8px", - marginBottom: "8px", - marginLeft: "12px", - marginRight: "12px", - width: "100%", - overflow: "hidden" - }, - table: { - borderCollapse: "collapse", - }, - icon: { - width: "24px", - height: "24px", - margin: "0px", - opacity: "0.6" - }, - label: { - marginLeft: "8px", - - }, - control: { - padding: theme.spacing(1), - }, - tdText: { - padding: "0px" - - } -}) - ; - -interface PluginGridProps extends WithStyles { - onOk: OkEventHandler; - onCancel: CloseEventHandler; - uri?: string; - minimumItemWidth?: number; - theme: Theme; - open: boolean -}; - -type PluginGridState = { - selected_uri?: string, - hover_uri?: string, - filterType: PluginType, - client_width: number, - client_height: number, - minimumItemWidth: number, - -} - - -export const LoadPluginDialog = - withStyles(pluginGridStyles, { withTheme: true })( - class extends ResizeResponsiveComponent - { - model: PiPedalModel; - - constructor(props: PluginGridProps) { - super(props); - this.model = PiPedalModelFactory.getInstance(); - - let filterType_ = PluginType.Plugin; // i.e. "Any". - let persistedFilter = window.localStorage.getItem(FILTER_STORAGE_KEY); - if (persistedFilter) { - filterType_ = persistedFilter as PluginType; - } - - this.state = { - selected_uri: this.props.uri, - hover_uri: "", - filterType: filterType_, - client_width: window.innerWidth, - client_height: window.innerHeight, - minimumItemWidth: props.minimumItemWidth ? props.minimumItemWidth : 220 - }; - - this.updateWindowSize = this.updateWindowSize.bind(this); - this.handleCancel = this.handleCancel.bind(this); - this.handleOk = this.handleOk.bind(this); - } - - updateWindowSize() { - this.setState({ - client_width: window.innerWidth, - client_height: window.innerHeight - }); - } - componentDidMount() { - super.componentDidMount(); - this.updateWindowSize(); - window.addEventListener('resize', this.updateWindowSize); - } - componentWillUnmount() { - super.componentWillUnmount(); - window.removeEventListener('resize', this.updateWindowSize); - } - - onWindowSizeChanged(width: number,height: number): void { - super.onWindowSizeChanged(width,height); - - } - - onFilterChange(e: any) { - let value = e.target.value as PluginType; - - window.localStorage.setItem(FILTER_STORAGE_KEY, value as string); - - this.setState({ filterType: value }); - } - onClearFilter(): void { - let value = PluginType.Plugin; - window.localStorage.setItem(FILTER_STORAGE_KEY, value as string); - - this.setState({ filterType: value }); - } - - selectItem(item: number): void { - let uri: string = ""; - let plugins = this.model.ui_plugins.get(); - if (item >= 0 && item < plugins.length) { - uri = plugins[item].uri; - } - if (uri !== this.state.selected_uri) { - this.setState({ selected_uri: uri }); - } - }; - - - handleCancel(e: SyntheticEvent): void { - e.preventDefault(); - this.cancel(); - } - handleOk(e: SyntheticEvent): void { - e.preventDefault(); - if (this.state.selected_uri) { - this.props.onOk(this.state.selected_uri); - } - } - - onDoubleClick(e: SyntheticEvent, uri: string): void { - this.props.onOk(uri); - } - - - cancel(): void { - this.props.onCancel(); - } - - fireSelected(item?: UiPlugin) { - if (item) { - this.setState({ selected_uri: item.uri }); - } - } - setHoverUri(uri: string) { - this.setState({ hover_uri: uri }); - } - - onClick(e: SyntheticEvent, uri: string): void { - this.setState({ selected_uri: uri }); - } - handleMouseEnter(e: SyntheticEvent, uri: string): void { - this.setHoverUri(uri); - - } - handleMouseLeave(e: SyntheticEvent, uri: string): void { - this.setHoverUri(""); - - } - onInfoClicked(): void { - // let selectedUri = this.state.selected_uri; - } - - stereo_indicator(uiPlugin?: UiPlugin): string { - if (!uiPlugin) return ""; - if (uiPlugin.audio_inputs === 2 || uiPlugin.audio_outputs === 2) { - return " (Stereo)"; - } - return ""; - } - info_string(uiPlugin?: UiPlugin): string { - if (uiPlugin === undefined) return ""; - let result = uiPlugin.name; - if (uiPlugin.author_name !== "") { - result += ", " + uiPlugin.author_name; - } - result += this.stereo_indicator(uiPlugin); - return result; - } - createFilterChildren(result: ReactNode[], classNode: PluginClass, level: number): void { - for (let i = 0; i < classNode.children.length; ++i) { - let child = classNode.children[i]; - let name = "\u00A0".repeat(level * 3+1) + child.display_name; - result.push(({name})); - if (child.children.length !== 0) { - this.createFilterChildren(result, child, level + 1); - } - } - } - createFilterOptions(): ReactNode[] { - let classes = this.model.plugin_classes.get(); - let result: ReactNode[] = []; - - result.push(( All)); - this.createFilterChildren(result, classes, 1); - return result; - - } - filterPlugins(plugins: UiPlugin[]): ReactNode[] { - let result: ReactNode[] = []; - let filterType = this.state.filterType; - let classes = this.props.classes; - let rootClass = this.model.plugin_classes.get(); - - for (let i = 0; i < plugins.length; ++i) { - let value = plugins[i]; - if (filterType === PluginType.Plugin || rootClass.is_type_of(filterType, value.plugin_type)) { - result.push( - ( - { this.onDoubleClick(e, value.uri) }} - onClick={(e) => { this.onClick(e, value.uri) }} - onMouseEnter={(e) => { this.handleMouseEnter(e, value.uri) }} - onMouseLeave={(e) => { this.handleMouseLeave(e, value.uri) }} - > - - - -
-
-
- -
-
- {value.name} - - - {value.plugin_display_type} {this.stereo_indicator(value)} - -
-
-
-
-
-
- ) - ); - - } - } - return result; - } - render() { - const { classes } = this.props; - - - let model = this.model; - let plugins = model.ui_plugins.get(); - - let selectedPlugin: UiPlugin | undefined = undefined; - if (this.state.selected_uri) { - let t = this.model.getUiPlugin(this.state.selected_uri); - if (t) selectedPlugin = t; - } - - return ( - - - -
- { this.cancel(); }} style={{ flex: "0 0 auto" }} > - - - - - { this.state.client_width > 520 ? "Select Plugin" : "" } - -
- -
- { this.onClearFilter(); }}> - - -
-
- - - - { - this.filterPlugins(plugins) - } - - - - - { (this.state.client_width >= NARROW_DISPLAY_THRESHOLD)? ( - -
-
- - - {this.info_string(selectedPlugin)} - -
-
- - -
-
-
- ) :( - -
- -
- - {this.info_string(selectedPlugin)} - -
-
-
-
- - -
-
- - - )} -
-
- ); - } - } - ); -export default LoadPluginDialog; - diff --git a/react/src/MainPage.tsx b/react/src/MainPage.tsx index 4fba174..4e946fd 100644 --- a/react/src/MainPage.tsx +++ b/react/src/MainPage.tsx @@ -385,7 +385,7 @@ export const MainPage = }} >
- +
{ diff --git a/react/src/MidiBindingView.tsx b/react/src/MidiBindingView.tsx index 04d77a8..5003e0f 100644 --- a/react/src/MidiBindingView.tsx +++ b/react/src/MidiBindingView.tsx @@ -168,7 +168,7 @@ const MidiBindingView = return (
- this.handleNoteChange(e, extra)} value={midiBinding.note} @@ -218,7 +218,7 @@ const MidiBindingView = (
- this.handleLatchControlTypeChange(e, extra)} value={midiBinding.switchControlType} @@ -276,7 +276,7 @@ const MidiBindingView = (showLinearControlTypeSelect) && (
- { show: boolean; isEditDialog: boolean; @@ -108,18 +111,9 @@ const styles = (theme: Theme) => createStyles({ const Transition = React.forwardRef(function Transition( - props: TransitionProps & { children?: React.ReactElement }, - ref: React.Ref, + props: SlideProps, ref: React.Ref ) { - return ; -}); - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const ActionBarTransition = React.forwardRef(function Transition( - props: TransitionProps & { children?: React.ReactElement }, - ref: React.Ref, -) { - return ; + return (); }); diff --git a/react/src/PresetSelector.tsx b/react/src/PresetSelector.tsx index 98d1f3e..96d9949 100644 --- a/react/src/PresetSelector.tsx +++ b/react/src/PresetSelector.tsx @@ -286,7 +286,7 @@ const PresetSelector = justifyContent: "left", flexWrap: "nowrap", alignItems: "center", height: "100%", position: "relative" }}>
{true ? ( - this.handleCountryChanged(event)} > {Object.entries(this.model.countryCodes).map(([key,value])=> { return ( @@ -316,7 +316,7 @@ const WifiConfigDialog = withStyles(styles, { withTheme: true })(
Channel - { this.handleChannelChange(e); }}> {this.state.wifiChannels.map((channel)=> { diff --git a/react/src/ZoomedUiControl.tsx b/react/src/ZoomedUiControl.tsx index 5e38862..327be8f 100644 --- a/react/src/ZoomedUiControl.tsx +++ b/react/src/ZoomedUiControl.tsx @@ -19,8 +19,7 @@ import React, {SyntheticEvent} from 'react'; import { Theme } from '@mui/material/styles'; -import { WithStyles } from '@mui/styles'; -import withStyles from '@mui/styles/withStyles'; +import { WithStyles,withStyles } from '@mui/styles'; import createStyles from '@mui/styles/createStyles'; import { ZoomedControlInfo } from './PiPedalModel'; import DialogEx from './DialogEx';