Migrate SnackStore to mobx
This commit is contained in:
parent
8947dbb9bd
commit
9fe00bf004
|
|
@ -2,44 +2,37 @@ import IconButton from '@material-ui/core/IconButton';
|
||||||
import Snackbar from '@material-ui/core/Snackbar';
|
import Snackbar from '@material-ui/core/Snackbar';
|
||||||
import Close from '@material-ui/icons/Close';
|
import Close from '@material-ui/icons/Close';
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import SnackBarStore from '../stores/SnackBarStore';
|
import {observable, reaction} from 'mobx';
|
||||||
|
import {observer} from 'mobx-react';
|
||||||
|
import SnackManager from '../stores/SnackManager';
|
||||||
|
|
||||||
interface IState {
|
@observer
|
||||||
current: string;
|
class SnackBarHandler extends Component {
|
||||||
hasNext: boolean;
|
|
||||||
open: boolean;
|
|
||||||
openWhen: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SnackBarHandler extends Component<{}, IState> {
|
|
||||||
private static MAX_VISIBLE_SNACK_TIME_IN_MS = 6000;
|
private static MAX_VISIBLE_SNACK_TIME_IN_MS = 6000;
|
||||||
private static MIN_VISIBLE_SNACK_TIME_IN_MS = 1000;
|
private static MIN_VISIBLE_SNACK_TIME_IN_MS = 1000;
|
||||||
|
|
||||||
public state = {
|
@observable
|
||||||
current: '',
|
private open = false;
|
||||||
hasNext: false,
|
@observable
|
||||||
open: false,
|
private openWhen = 0;
|
||||||
openWhen: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
public componentWillMount() {
|
private dispose: () => void = () => {};
|
||||||
SnackBarStore.on('change', this.onNewSnack);
|
|
||||||
}
|
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentDidMount = () =>
|
||||||
SnackBarStore.removeListener('change', this.onNewSnack);
|
(this.dispose = reaction(() => SnackManager.counter, this.onNewSnack));
|
||||||
}
|
|
||||||
|
public componentWillUnmount = () => this.dispose();
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const {open, current, hasNext} = this.state;
|
const {message: current, hasNext} = SnackManager;
|
||||||
const duration = hasNext
|
const duration = hasNext()
|
||||||
? SnackBarHandler.MIN_VISIBLE_SNACK_TIME_IN_MS
|
? SnackBarHandler.MIN_VISIBLE_SNACK_TIME_IN_MS
|
||||||
: SnackBarHandler.MAX_VISIBLE_SNACK_TIME_IN_MS;
|
: SnackBarHandler.MAX_VISIBLE_SNACK_TIME_IN_MS;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Snackbar
|
<Snackbar
|
||||||
anchorOrigin={{vertical: 'bottom', horizontal: 'left'}}
|
anchorOrigin={{vertical: 'bottom', horizontal: 'left'}}
|
||||||
open={open}
|
open={this.open}
|
||||||
autoHideDuration={duration}
|
autoHideDuration={duration}
|
||||||
onClose={this.closeCurrentSnack}
|
onClose={this.closeCurrentSnack}
|
||||||
onExited={this.openNextSnack}
|
onExited={this.openNextSnack}
|
||||||
|
|
@ -58,7 +51,7 @@ class SnackBarHandler extends Component<{}, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private onNewSnack = () => {
|
private onNewSnack = () => {
|
||||||
const {open, openWhen} = this.state;
|
const {open, openWhen} = this;
|
||||||
|
|
||||||
if (!open) {
|
if (!open) {
|
||||||
this.openNextSnack();
|
this.openNextSnack();
|
||||||
|
|
@ -77,18 +70,14 @@ class SnackBarHandler extends Component<{}, IState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
private openNextSnack = () => {
|
private openNextSnack = () => {
|
||||||
if (SnackBarStore.hasNext()) {
|
if (SnackManager.hasNext()) {
|
||||||
this.setState({
|
this.open = true;
|
||||||
...this.state,
|
this.openWhen = Date.now();
|
||||||
open: true,
|
SnackManager.next();
|
||||||
openWhen: Date.now(),
|
|
||||||
current: SnackBarStore.next(),
|
|
||||||
hasNext: SnackBarStore.hasNext(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private closeCurrentSnack = () => this.setState({...this.state, open: false});
|
private closeCurrentSnack = () => (this.open = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SnackBarHandler;
|
export default SnackBarHandler;
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
import {EventEmitter} from 'events';
|
|
||||||
import dispatcher, {IEvent} from './dispatcher';
|
|
||||||
|
|
||||||
class SnackBarStore extends EventEmitter {
|
|
||||||
public messages: string[] = [];
|
|
||||||
|
|
||||||
public next(): string {
|
|
||||||
if (!this.hasNext()) {
|
|
||||||
throw new Error('no such element');
|
|
||||||
}
|
|
||||||
return this.messages.shift() as string;
|
|
||||||
}
|
|
||||||
|
|
||||||
public hasNext(): boolean {
|
|
||||||
return this.messages.length !== 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public handle(data: IEvent): void {
|
|
||||||
if (data.type === 'SNACK') {
|
|
||||||
this.messages.push(data.payload);
|
|
||||||
this.emit('change');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const store = new SnackBarStore();
|
|
||||||
dispatcher.register(store.handle.bind(store));
|
|
||||||
export default store;
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
import {action, observable} from 'mobx';
|
||||||
|
|
||||||
|
export interface SnackReporter {
|
||||||
|
(message: string): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SnackManager {
|
||||||
|
@observable
|
||||||
|
private messages: string[] = [];
|
||||||
|
@observable
|
||||||
|
public message: string | null;
|
||||||
|
@observable
|
||||||
|
public counter = 0;
|
||||||
|
|
||||||
|
@action
|
||||||
|
public next = (): void => {
|
||||||
|
if (!this.hasNext()) {
|
||||||
|
throw new Error('There is nothing here :(');
|
||||||
|
}
|
||||||
|
this.message = this.messages.shift() as string;
|
||||||
|
};
|
||||||
|
|
||||||
|
public hasNext = () => this.messages.length > 0;
|
||||||
|
|
||||||
|
@action
|
||||||
|
public snack: SnackReporter = (message: string): void => {
|
||||||
|
this.messages.push(message);
|
||||||
|
this.counter++;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new SnackManager();
|
||||||
Loading…
Reference in New Issue