-
Notifications
You must be signed in to change notification settings - Fork 0
/
App.tsx
executable file
·106 lines (91 loc) · 3.12 KB
/
App.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/* SPDX-FileCopyrightText: 2014-present Kriasoft <hello@kriasoft.com> */
/* SPDX-License-Identifier: MIT */
import { CssBaseline, PaletteMode, Toolbar } from "@material-ui/core";
import { ThemeProvider } from "@material-ui/core/styles";
import { Action, Update } from "history";
import * as React from "react";
import { Environment, RelayEnvironmentProvider } from "react-relay";
import { History, HistoryContext, LocationContext } from "../core/history";
import type { RouteResponse } from "../core/router";
import { resolveRoute } from "../core/router";
import { LoginDialog } from "../dialogs";
import theme from "../theme";
import { ErrorPage } from "./ErrorPage";
type AppProps = {
history: History;
relay: Environment;
};
export class App extends React.Component<AppProps> {
state = {
route: undefined as RouteResponse | undefined,
location: this.props.history.location,
error: undefined as Error | undefined,
theme: (window?.localStorage?.getItem("theme") === "dark"
? "dark"
: "light") as PaletteMode,
};
static getDerivedStateFromError(error: Error): { error: Error } {
return { error };
}
dispose?: () => void;
componentDidMount(): void {
const { history } = this.props;
this.dispose = history.listen(this.renderPath);
this.renderPath({ location: history.location, action: Action.Pop });
}
componentDidUpdate(): void {
if (this.state.route?.title) {
self.document.title = this.state.route.title;
}
}
componentWillUnmount(): void {
if (this.dispose) this.dispose();
}
componentDidCatch(error: Error, errorInfo: unknown): void {
// You can also log the error to an error reporting service
console.error(error, errorInfo);
}
renderPath = async (ctx: Update): Promise<void> => {
resolveRoute({
path: ctx.location.pathname,
relay: this.props.relay,
}).then((route) => {
if (route.error) console.error(route.error);
this.setState({ route, location: ctx.location, error: route.error });
});
};
handleChangeTheme = (): void => {
this.setState((x: { theme: PaletteMode }) => {
const theme = x.theme === "light" ? "dark" : "light";
window.localStorage?.setItem("theme", theme);
return { ...x, theme };
});
};
render(): JSX.Element {
const { history } = this.props;
const { route, location, error } = this.state;
if (error) {
return (
<ThemeProvider theme={theme[this.state.theme]}>
<ErrorPage error={error} history={history} />;
</ThemeProvider>
);
}
return (
<ThemeProvider theme={theme[this.state.theme]}>
<RelayEnvironmentProvider environment={this.props.relay}>
<HistoryContext.Provider value={history}>
<LocationContext.Provider value={location}>
<CssBaseline />
<Toolbar />
{route?.component
? React.createElement(route.component, route.props)
: null}
<LoginDialog />
</LocationContext.Provider>
</HistoryContext.Provider>
</RelayEnvironmentProvider>
</ThemeProvider>
);
}
}