2017-09-27 02:33:08 +08:00
|
|
|
import React from 'react';
|
2018-01-23 14:18:46 +08:00
|
|
|
import { CSSTransitionGroup } from 'react-transition-group';
|
2017-09-27 02:42:18 +08:00
|
|
|
import { WorkspaceStore } from 'mailspring-exports';
|
2017-08-01 13:21:00 +08:00
|
|
|
|
2017-09-27 02:33:08 +08:00
|
|
|
import Sheet from './sheet';
|
|
|
|
import Toolbar from './sheet-toolbar';
|
2019-03-05 03:03:12 +08:00
|
|
|
import { Flexbox } from './components/flexbox';
|
|
|
|
import { InjectedComponentSet } from './components/injected-component-set';
|
|
|
|
import { SheetDeclaration } from './flux/stores/workspace-store';
|
|
|
|
|
|
|
|
interface SheetContainerState {
|
|
|
|
stack: SheetDeclaration[];
|
|
|
|
mode: string;
|
|
|
|
error?: string;
|
|
|
|
}
|
2017-08-01 13:21:00 +08:00
|
|
|
|
2019-03-05 03:03:12 +08:00
|
|
|
export default class SheetContainer extends React.Component<{}, SheetContainerState> {
|
2017-08-01 13:21:00 +08:00
|
|
|
static displayName = 'SheetContainer';
|
|
|
|
|
2019-03-05 03:03:12 +08:00
|
|
|
_toolbarComponents = {};
|
|
|
|
unsubscribe?: () => void;
|
|
|
|
|
2017-08-01 13:21:00 +08:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2017-09-27 02:33:08 +08:00
|
|
|
this.state = this._getStateFromStores();
|
2017-08-01 13:21:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
this.unsubscribe = WorkspaceStore.listen(this._onStoreChange);
|
|
|
|
}
|
|
|
|
|
2018-01-23 14:18:46 +08:00
|
|
|
componentDidCatch(error, info) {
|
2018-01-29 01:04:52 +08:00
|
|
|
// We don't currently display the error, but we need to call setState within
|
|
|
|
// this function or the component does not re-render after being reset.
|
|
|
|
this.setState({ error: error.stack });
|
2018-01-23 14:18:46 +08:00
|
|
|
AppEnv.reportError(error);
|
|
|
|
}
|
|
|
|
|
2017-08-01 13:21:00 +08:00
|
|
|
componentWillUnmount() {
|
|
|
|
if (this.unsubscribe) {
|
|
|
|
this.unsubscribe();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_getStateFromStores() {
|
|
|
|
return {
|
|
|
|
stack: WorkspaceStore.sheetStack(),
|
|
|
|
mode: WorkspaceStore.layoutMode(),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-09-27 02:33:08 +08:00
|
|
|
_onColumnSizeChanged = sheet => {
|
2017-08-01 13:21:00 +08:00
|
|
|
const toolbar = this._toolbarComponents[sheet.props.depth];
|
|
|
|
if (toolbar) {
|
|
|
|
toolbar.recomputeLayout();
|
|
|
|
}
|
|
|
|
window.dispatchEvent(new Event('resize'));
|
2017-09-27 02:33:08 +08:00
|
|
|
};
|
2017-08-01 13:21:00 +08:00
|
|
|
|
|
|
|
_onStoreChange = () => {
|
|
|
|
this.setState(this._getStateFromStores());
|
2017-09-27 02:33:08 +08:00
|
|
|
};
|
2017-08-01 13:21:00 +08:00
|
|
|
|
|
|
|
_toolbarContainerElement() {
|
2017-09-27 02:36:58 +08:00
|
|
|
const { toolbar } = AppEnv.getLoadSettings();
|
2017-08-01 13:21:00 +08:00
|
|
|
if (!toolbar) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
2017-09-27 02:33:08 +08:00
|
|
|
const components = this.state.stack.map((sheet, index) => (
|
2017-08-01 13:21:00 +08:00
|
|
|
<Toolbar
|
|
|
|
data={sheet}
|
2017-09-27 02:33:08 +08:00
|
|
|
ref={cm => {
|
|
|
|
this._toolbarComponents[index] = cm;
|
|
|
|
}}
|
2017-08-01 13:21:00 +08:00
|
|
|
key={`${index}:${sheet.id}:toolbar`}
|
|
|
|
depth={index}
|
|
|
|
/>
|
2017-09-27 02:33:08 +08:00
|
|
|
));
|
2017-08-01 13:21:00 +08:00
|
|
|
return (
|
2019-03-05 03:03:12 +08:00
|
|
|
<div style={{ order: 0, zIndex: 3 }} className="sheet-toolbar">
|
2017-08-01 13:21:00 +08:00
|
|
|
{components[0]}
|
2018-01-23 14:18:46 +08:00
|
|
|
<CSSTransitionGroup
|
2017-08-01 13:21:00 +08:00
|
|
|
transitionLeaveTimeout={125}
|
|
|
|
transitionEnterTimeout={125}
|
|
|
|
transitionName="opacity-125ms"
|
|
|
|
>
|
|
|
|
{components.slice(1)}
|
2018-01-23 14:18:46 +08:00
|
|
|
</CSSTransitionGroup>
|
2017-08-01 13:21:00 +08:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const totalSheets = this.state.stack.length;
|
|
|
|
const topSheet = this.state.stack[totalSheets - 1];
|
|
|
|
|
|
|
|
if (!topSheet) {
|
2017-09-27 02:33:08 +08:00
|
|
|
return <div />;
|
2017-08-01 13:21:00 +08:00
|
|
|
}
|
|
|
|
|
2017-09-27 02:33:08 +08:00
|
|
|
const sheetComponents = this.state.stack.map((sheet, index) => (
|
2017-08-01 13:21:00 +08:00
|
|
|
<Sheet
|
|
|
|
data={sheet}
|
|
|
|
depth={index}
|
2019-03-05 03:03:12 +08:00
|
|
|
key={index > 0 ? `${index}:${sheet.id}` : `root`}
|
2017-08-01 13:21:00 +08:00
|
|
|
onColumnSizeChanged={this._onColumnSizeChanged}
|
|
|
|
/>
|
2017-09-27 02:33:08 +08:00
|
|
|
));
|
2017-08-01 13:21:00 +08:00
|
|
|
|
|
|
|
return (
|
|
|
|
<Flexbox
|
|
|
|
direction="column"
|
|
|
|
className={`layout-mode-${this.state.mode}`}
|
2017-09-27 02:33:08 +08:00
|
|
|
style={{ overflow: 'hidden' }}
|
2017-08-01 13:21:00 +08:00
|
|
|
>
|
|
|
|
{this._toolbarContainerElement()}
|
|
|
|
|
2019-03-05 03:03:12 +08:00
|
|
|
<div style={{ order: 1, zIndex: 2 }}>
|
2017-08-01 13:21:00 +08:00
|
|
|
<InjectedComponentSet
|
2017-09-27 02:33:08 +08:00
|
|
|
matching={{ locations: [topSheet.Header, WorkspaceStore.Sheet.Global.Header] }}
|
2017-08-01 13:21:00 +08:00
|
|
|
direction="column"
|
|
|
|
id={topSheet.id}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
2019-03-05 03:03:12 +08:00
|
|
|
<div style={{ order: 2, flex: 1, position: 'relative', zIndex: 1 }}>
|
2017-08-01 13:21:00 +08:00
|
|
|
{sheetComponents[0]}
|
2018-01-23 14:18:46 +08:00
|
|
|
<CSSTransitionGroup
|
2017-08-01 13:21:00 +08:00
|
|
|
transitionLeaveTimeout={125}
|
|
|
|
transitionEnterTimeout={125}
|
|
|
|
transitionName="sheet-stack"
|
|
|
|
>
|
|
|
|
{sheetComponents.slice(1)}
|
2018-01-23 14:18:46 +08:00
|
|
|
</CSSTransitionGroup>
|
2017-08-01 13:21:00 +08:00
|
|
|
</div>
|
|
|
|
|
2019-03-05 03:03:12 +08:00
|
|
|
<div style={{ order: 3, zIndex: 4 }}>
|
2017-08-01 13:21:00 +08:00
|
|
|
<InjectedComponentSet
|
2017-09-27 02:33:08 +08:00
|
|
|
matching={{ locations: [topSheet.Footer, WorkspaceStore.Sheet.Global.Footer] }}
|
2017-08-01 13:21:00 +08:00
|
|
|
direction="column"
|
|
|
|
id={topSheet.id}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</Flexbox>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|