Improvate Dialog handling on browser back button.

This commit is contained in:
Robin Davies
2021-08-25 19:16:13 -04:00
parent 8782f15cd1
commit dce115d6c3
11 changed files with 79 additions and 270 deletions
+3 -3
View File
@@ -5,7 +5,6 @@ import Typography from '@material-ui/core/Typography';
import { PiPedalModel, PiPedalModelFactory, State } from './PiPedalModel';
import { TransitionProps } from '@material-ui/core/transitions/transition';
import Slide from '@material-ui/core/Slide';
import Dialog from '@material-ui/core/Dialog';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import { Theme, withStyles, WithStyles, createStyles } from '@material-ui/core/styles';
@@ -13,6 +12,7 @@ import ArrowBackIcon from '@material-ui/icons/ArrowBack';
import Divider from '@material-ui/core/Divider';
import JackHostStatus from './JackHostStatus';
import {PiPedalError} from './PiPedalError';
import DialogEx from './DialogEx';
interface AboutDialogProps extends WithStyles<typeof styles> {
@@ -187,7 +187,7 @@ const AboutDialog = withStyles(styles, { withTheme: true })(
let classes = this.props.classes;
return (
<Dialog fullScreen open={this.props.open}
<DialogEx tag="AboutDlg" fullScreen open={this.props.open}
onClose={() => { this.props.onClose() }} TransitionComponent={Transition}>
<div style={{ display: "flex", flexDirection: "column", flexWrap: "nowrap", width: "100%", height: "100%", overflow: "hidden" }}>
@@ -238,7 +238,7 @@ const AboutDialog = withStyles(styles, { withTheme: true })(
</div>
</div>
</div>
</Dialog >
</DialogEx >
);
+2 -49
View File
@@ -26,7 +26,6 @@ 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 Dialog from '@material-ui/core/Dialog';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import { Theme, withStyles, WithStyles, createStyles } from '@material-ui/core/styles';
@@ -152,7 +151,6 @@ const BankDialog = withStyles(styles, { withTheme: true })(
showDeletePrompt: false
};
this.handleBanksChanged = this.handleBanksChanged.bind(this);
this.handlePopState = this.handlePopState.bind(this);
}
onMoreClick(e: React.SyntheticEvent): void {
@@ -229,63 +227,18 @@ const BankDialog = withStyles(styles, { withTheme: true })(
hasHooks: boolean = false;
stateWasPopped: boolean = false;
handlePopState(e: any): any {
let state: any = e.state;
if (!state || !state.bankDialog) {
this.stateWasPopped = true;
this.props.onDialogClose();
}
}
updateBackButtonHooks(): void {
let wantHooks = this.mounted && this.props.show;
if (wantHooks !== this.hasHooks) {
this.hasHooks = wantHooks;
if (this.hasHooks) {
this.stateWasPopped = false;
window.addEventListener("popstate", this.handlePopState);
// eslint-disable-next-line no-restricted-globals
let newState: any = history.state;
if (!newState) {
newState = {};
}
newState.bankDialog = true;
// eslint-disable-next-line no-restricted-globals
history.pushState(
newState,
"PiPedal - Banks",
"#Banks"
);
} else {
window.removeEventListener("popstate", this.handlePopState);
if (!this.stateWasPopped) {
// eslint-disable-next-line no-restricted-globals
history.back();
}
// eslint-disable-next-line no-restricted-globals
history.replaceState({}, "PiPedal", "#");
}
}
}
componentDidUpdate() {
this.updateBackButtonHooks();
}
componentDidMount() {
this.model.banks.addOnChangedHandler(this.handleBanksChanged);
this.handleBanksChanged();
// scroll selected item into view.
this.mounted = true;
this.updateBackButtonHooks();
}
componentWillUnmount() {
this.model.banks.removeOnChangedHandler(this.handleBanksChanged);
this.mounted = false;
this.updateBackButtonHooks();
}
getSelectedIndex() {
@@ -453,7 +406,7 @@ const BankDialog = withStyles(styles, { withTheme: true })(
let defaultSelectedIndex = this.getSelectedIndex();
return (
<Dialog fullScreen open={this.props.show}
<DialogEx tag="BankDialog" fullScreen open={this.props.show}
onClose={() => { this.handleDialogClose() }} TransitionComponent={Transition}>
<div style={{ display: "flex", flexDirection: "column", flexWrap: "nowrap", width: "100%", height: "100%", overflow: "hidden" }}>
<div style={{ flex: "0 0 auto" }}>
@@ -601,7 +554,7 @@ const BankDialog = withStyles(styles, { withTheme: true })(
</DialogActions>
</DialogEx>
</Dialog >
</DialogEx >
);
+52 -12
View File
@@ -30,6 +30,38 @@ interface DialogExState {
}
class DialogStackEntry {
constructor(tag: string)
{
this.tag = tag;
}
tag: string;
};
let dialogStack: DialogStackEntry[] = [];
function peekDialogStack(): string {
if (dialogStack.length !== 0) {
return dialogStack[dialogStack.length-1].tag;
}
return "";
}
let ignoreNextPop = false;
function popDialogStack(ignoreNextPop_: boolean): void {
if (dialogStack.length !== 0)
{
ignoreNextPop = ignoreNextPop_;
dialogStack.splice(dialogStack.length-1,1);
}
}
function pushDialogStack(tag: string): void {
dialogStack.push(new DialogStackEntry(tag));
}
class DialogEx extends React.Component<DialogExProps,DialogExState> {
constructor(props: DialogExProps)
{
@@ -47,14 +79,25 @@ class DialogEx extends React.Component<DialogExProps,DialogExState> {
stateWasPopped: boolean = false;
handlePopState(e: any): any {
this.stateWasPopped = true;
let shouldClose = (!e.state || !e.state[this.props.tag]);
let shouldClose = (peekDialogStack() === this.props.tag);
if (shouldClose)
{
if (this.props.onClose)
if (ignoreNextPop)
{
this.props.onClose(e,"backdropClick");
ignoreNextPop = false;
} else {
if (!this.stateWasPopped)
{
this.stateWasPopped = true;
if (this.props.onClose)
{
popDialogStack(false);
this.props.onClose(e,"backdropClick");
}
}
}
e.stopPropagation();
}
}
@@ -76,28 +119,25 @@ class DialogEx extends React.Component<DialogExProps,DialogExState> {
}
state[this.props.tag] = true;
pushDialogStack(this.props.tag);
// eslint-disable-next-line no-restricted-globals
history.pushState(
state,
"",
"#" + this.props.tag
"" //"#" + this.props.tag
);
} else {
window.removeEventListener("popstate",this.handlePopState);
if (!this.stateWasPopped)
{
this.stateWasPopped = true;
popDialogStack(true);
// eslint-disable-next-line no-restricted-globals
history.back();
}
window.removeEventListener("popstate",this.handlePopState);
}
}
}
onWindowSizeChanged(width: number, height: number): void
{
this.setState({fullScreen: height < 200})
}
componentDidMount()
{
+3 -48
View File
@@ -18,7 +18,7 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import React, { SyntheticEvent } from 'react';
import Dialog from '@material-ui/core/Dialog';
import DialogEx from './DialogEx';
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
import { PiPedalModel, PiPedalModelFactory, ListenHandle } from './PiPedalModel';
import Typography from '@material-ui/core/Typography';
@@ -86,21 +86,12 @@ export const MidiBindingDialog =
listenSnackbarOpen: false
};
this.model = PiPedalModelFactory.getInstance();
this.handlePopState = this.handlePopState.bind(this);
this.handleClose = this.handleClose.bind(this);
}
mounted: boolean = false;
hasHooks: boolean = false;
stateWasPopped: boolean = false;
handlePopState(e: any): any {
this.stateWasPopped = true;
let shouldClose = (!e.state);
if (shouldClose) {
this.props.onClose();
}
}
handleClose() {
this.props.onClose();
}
@@ -163,39 +154,6 @@ export const MidiBindingDialog =
}
updateHooks(): void {
let wantHooks = this.mounted && this.props.open;
if (wantHooks !== this.hasHooks) {
this.hasHooks = wantHooks;
if (this.hasHooks) {
this.stateWasPopped = false;
window.addEventListener("popstate", this.handlePopState);
// eslint-disable-next-line no-restricted-globals
let state = history.state;
if (!state) {
state = {};
}
state.midiBindingDialog = true;
// eslint-disable-next-line no-restricted-globals
history.pushState(
state,
"Preset MIDI Bindings",
"#MidiBindingDialog"
);
} else {
window.removeEventListener("popstate", this.handlePopState);
if (!this.stateWasPopped) {
// eslint-disable-next-line no-restricted-globals
history.back();
}
this.cancelListenForControl();
}
}
}
onWindowSizeChanged(width: number, height: number): void {
}
@@ -203,18 +161,15 @@ export const MidiBindingDialog =
componentDidMount() {
super.componentDidMount();
this.mounted = true;
this.updateHooks();
}
componentWillUnmount() {
super.componentWillUnmount();
this.mounted = false;
this.updateHooks();
}
componentDidUpdate() {
this.updateHooks();
}
handleItemChanged(instanceId: number, newBinding: MidiBinding) {
this.model.setMidiBinding(instanceId, newBinding);
@@ -311,7 +266,7 @@ export const MidiBindingDialog =
}
return (
<Dialog open={open} fullWidth onClose={this.handleClose} aria-labelledby="Rename-dialog-title"
<DialogEx tag="MidiBindingsDialog" open={open} fullWidth onClose={this.handleClose} aria-labelledby="Rename-dialog-title"
fullScreen={true}
style={{userSelect: "none"}}
>
@@ -353,7 +308,7 @@ export const MidiBindingDialog =
onClose={() => this.setState({ listenSnackbarOpen: false })}
message="Listening for MIDI input"
/>
</Dialog >
</DialogEx >
);
}
});
+4 -4
View File
@@ -24,8 +24,8 @@ import { PiPedalModel, PiPedalModelFactory, PresetIndexEntry, PresetIndex } from
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 Dialog from '@material-ui/core/Dialog';
import Slide from '@material-ui/core/Slide' ;
import DialogEx from './DialogEx';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import { Theme, withStyles, WithStyles, createStyles } from '@material-ui/core/styles';
@@ -334,7 +334,7 @@ const PresetDialog = withStyles(styles, { withTheme: true })(
let defaultSelectedIndex = this.getSelectedIndex();
return (
<Dialog fullScreen open={this.props.show}
<DialogEx tag="PresetDialog" fullScreen open={this.props.show}
onClose={() => { this.handleDialogClose() }} TransitionComponent={Transition}>
<div style={{ display: "flex", flexDirection: "column", flexWrap: "nowrap", width: "100%", height: "100%", overflow: "hidden" }}>
<div style={{ flex: "0 0 auto" }}>
@@ -456,7 +456,7 @@ const PresetDialog = withStyles(styles, { withTheme: true })(
open={this.state.openUploadDialog}
onClose={() => { this.setState({ openUploadDialog: false }) }} />
</Dialog >
</DialogEx>
);
+3 -52
View File
@@ -20,7 +20,7 @@
import React from 'react';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import Dialog from '@material-ui/core/Dialog';
import DialogEx from './DialogEx';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import { nullCast } from './Utility';
@@ -49,57 +49,11 @@ export default class RenameDialog extends ResizeResponsiveComponent<RenameDialog
fullScreen: false
};
this.refText = React.createRef<HTMLInputElement>();
this.handlePopState = this.handlePopState.bind(this);
}
mounted: boolean = false;
hasHooks: boolean = false;
stateWasPopped: boolean = false;
handlePopState(e: any): any {
this.stateWasPopped = true;
let shouldClose = (!e.state || !e.state.renameDialog);
if (shouldClose)
{
this.props.onClose();
}
}
updateHooks() : void {
let wantHooks = this.mounted && this.props.open;
if (wantHooks !== this.hasHooks)
{
this.hasHooks = wantHooks;
if (this.hasHooks)
{
this.stateWasPopped = false;
window.addEventListener("popstate",this.handlePopState);
// eslint-disable-next-line no-restricted-globals
let state = history.state;
if (!state)
{
state = {};
}
state.renameDialog = true;
// eslint-disable-next-line no-restricted-globals
history.pushState(
state,
this.props.acceptActionName,
"#RenameDialog"
);
} else {
window.removeEventListener("popstate",this.handlePopState);
if (!this.stateWasPopped)
{
// eslint-disable-next-line no-restricted-globals
history.back();
}
}
}
}
onWindowSizeChanged(width: number, height: number): void
{
this.setState({fullScreen: height < 200})
@@ -110,18 +64,15 @@ export default class RenameDialog extends ResizeResponsiveComponent<RenameDialog
{
super.componentDidMount();
this.mounted = true;
this.updateHooks();
}
componentWillUnmount()
{
super.componentWillUnmount();
this.mounted = false;
this.updateHooks();
}
componentDidUpdate()
{
this.updateHooks();
}
render() {
@@ -145,7 +96,7 @@ export default class RenameDialog extends ResizeResponsiveComponent<RenameDialog
}
};
return (
<Dialog open={open} fullWidth onClose={handleClose} aria-labelledby="Rename-dialog-title" style={{}}
<DialogEx tag="RenameDialog" open={open} fullWidth onClose={handleClose} aria-labelledby="Rename-dialog-title" style={{}}
fullScreen={this.state.fullScreen}
>
<DialogContent>
@@ -169,7 +120,7 @@ export default class RenameDialog extends ResizeResponsiveComponent<RenameDialog
{acceptActionName}
</Button>
</DialogActions>
</Dialog>
</DialogEx>
);
}
}
+6 -47
View File
@@ -21,7 +21,7 @@ import React from 'react';
import Button from '@material-ui/core/Button';
import {PiPedalModel,PiPedalModelFactory} from './PiPedalModel';
import Dialog from '@material-ui/core/Dialog';
import DialogEx from './DialogEx';
import DialogTitle from '@material-ui/core/DialogTitle';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
@@ -55,52 +55,11 @@ export default class UploadDialog extends ResizeResponsiveComponent<UploadDialog
};
this.model = PiPedalModelFactory.getInstance();
this.handlePopState = this.handlePopState.bind(this);
}
mounted: boolean = false;
hasHooks: boolean = false;
stateWasPopped: boolean = false;
handlePopState(e: any): any {
this.stateWasPopped = true;
let shouldClose = (!e.state || !e.state.UploadDialog);
if (shouldClose) {
this.props.onClose();
}
}
updateHooks(): void {
let wantHooks = this.mounted && this.props.open;
if (wantHooks !== this.hasHooks) {
this.hasHooks = wantHooks;
if (this.hasHooks) {
this.stateWasPopped = false;
window.addEventListener("popstate", this.handlePopState);
// eslint-disable-next-line no-restricted-globals
let state = history.state;
if (!state) {
state = {};
}
state.UploadDialog = true;
// eslint-disable-next-line no-restricted-globals
history.pushState(
state,
"Upload",
"#UploadDialog"
);
} else {
window.removeEventListener("popstate", this.handlePopState);
if (!this.stateWasPopped) {
// eslint-disable-next-line no-restricted-globals
history.back();
}
}
}
}
onWindowSizeChanged(width: number, height: number): void {
this.setState({ fullScreen: height < 200 })
}
@@ -109,16 +68,16 @@ export default class UploadDialog extends ResizeResponsiveComponent<UploadDialog
componentDidMount() {
super.componentDidMount();
this.mounted = true;
this.updateHooks();
}
componentWillUnmount() {
super.componentWillUnmount();
this.mounted = false;
this.updateHooks();
}
componentDidUpdate() {
this.updateHooks();
}
handleClose(): void {
@@ -194,7 +153,7 @@ export default class UploadDialog extends ResizeResponsiveComponent<UploadDialog
return (
<Dialog open={this.props.open} fullWidth onClose={() => this.handleClose()} style={{}}
<DialogEx tag="UploadDialog" open={this.props.open} fullWidth onClose={() => this.handleClose()} style={{}}
fullScreen={this.state.fullScreen}
>
<DialogTitle>Upload preset</DialogTitle>
@@ -234,7 +193,7 @@ export default class UploadDialog extends ResizeResponsiveComponent<UploadDialog
/>
</Button>
</DialogActions>
</Dialog>
</DialogEx>
);
}
}
+3 -53
View File
@@ -20,7 +20,7 @@
import React from 'react';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import Dialog from '@material-ui/core/Dialog';
import DialogEx from './DialogEx';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogTitle from '@material-ui/core/DialogTitle';
@@ -29,7 +29,6 @@ import FormControlLabel from '@material-ui/core/FormControlLabel';
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
import WifiConfigSettings from './WifiConfigSettings';
import NoChangePassword from './NoChangePassword';
import DialogEx from './DialogEx'
import Typography from '@material-ui/core/Typography';
import { Theme, withStyles, WithStyles,createStyles } from '@material-ui/core/styles';
import Select from '@material-ui/core/Select';
@@ -104,60 +103,14 @@ const WifiConfigDialog = withStyles(styles, { withTheme: true })(
this.refName = React.createRef<HTMLInputElement>();
this.refPassword = React.createRef<HTMLInputElement>();
this.handlePopState = this.handlePopState.bind(this);
}
mounted: boolean = false;
hasHooks: boolean = false;
stateWasPopped: boolean = false;
handleEnableChanged(e: any) {
this.setState({ enabled: e.target.checked });
}
handlePopState(e: any): any {
this.stateWasPopped = true;
let shouldClose = (!e.state || !e.state.WifiConfig);
if (shouldClose) {
this.preventPasswordPrompt();
setTimeout(()=> {
this.props.onClose();
});
}
}
updateHooks(): void {
let wantHooks = this.mounted && this.props.open;
if (wantHooks !== this.hasHooks) {
this.hasHooks = wantHooks;
if (this.hasHooks) {
this.stateWasPopped = false;
window.addEventListener("popstate", this.handlePopState);
// eslint-disable-next-line no-restricted-globals
let state = history.state;
if (!state) {
state = {};
}
state.WifiConfig = true;
// eslint-disable-next-line no-restricted-globals
history.pushState(
state,
"Wi-Fi Configuration",
"#WifiConfig"
);
} else {
window.removeEventListener("popstate", this.handlePopState);
if (!this.stateWasPopped) {
// eslint-disable-next-line no-restricted-globals
history.back();
}
}
}
}
onWindowSizeChanged(width: number, height: number): void {
this.setState({ fullScreen: height < 200 })
}
@@ -166,16 +119,13 @@ const WifiConfigDialog = withStyles(styles, { withTheme: true })(
componentDidMount() {
super.componentDidMount();
this.mounted = true;
this.updateHooks();
}
componentWillUnmount() {
super.componentWillUnmount();
this.mounted = false;
this.updateHooks();
}
componentDidUpdate(prevProps: WifiConfigProps) {
this.updateHooks();
if (this.props.open && !prevProps.open)
{
@@ -300,7 +250,7 @@ const WifiConfigDialog = withStyles(styles, { withTheme: true })(
};
return (
<Dialog open={open} fullWidth onClose={handleClose} style={{}}
<DialogEx tag="WifiConfigDialog" open={open} fullWidth onClose={handleClose} style={{}}
fullScreen={this.state.fullScreen}
>
{ this.state.fullScreen && (
@@ -407,7 +357,7 @@ const WifiConfigDialog = withStyles(styles, { withTheme: true })(
</Button>
</DialogActions>
</DialogEx>
</Dialog>
</DialogEx>
);
}
});