1import 'typeface-roboto';
 2
 3import { createMuiTheme, CssBaseline, IconButton, responsiveFontSizes, ThemeProvider } from '@material-ui/core';
 4import { Brightness4, Brightness7 } from '@material-ui/icons';
 5import { useLocalStorage } from '@rehooks/local-storage';
 6import * as React from 'react';
 7import * as ReactDOM from 'react-dom';
 8
 9import { App } from './app';
10import { AboutButton } from './components/about';
11import * as serviceWorker from './serviceWorker';
12
13function useTheme() {
14    const [themeName, setThemeName] = useLocalStorage<'light' | 'dark'>('themeName', 'dark');
15
16    // Workaround for https://github.com/mui-org/material-ui/issues/20708.
17    //
18    // When in strict mode (development only), this is required to properly allow
19    // the theme to be changed, as unused styles are not cleaned up. Create a new theme
20    // each time, so that they're forced to be injected again at the end of the existing
21    // block of stylesheets (as the styling library will see them as "new" styles, rather than
22    // assuming they can just be reused).
23    //
24    // This is gross, as it means every time the button is clicked it's a slew of extra
25    // stylesheets (each overriding the previous), but in production the cleanup works
26    // so this extra work is "only" a performance hit. If the bug is ever fixed, we can
27    // simply store two global themes and swap between them.
28    const theme = responsiveFontSizes(
29        createMuiTheme({
30            palette: {
31                type: themeName,
32            },
33        })
34    );
35
36    const toggleTheme = () => {
37        if (themeName === 'light') {
38            setThemeName('dark');
39        } else {
40            setThemeName('light');
41        }
42    };
43
44    return { theme, toggleTheme, isDark: themeName === 'dark' };
45}
46
47const Root = (_props: {}) => {
48    const { theme, toggleTheme, isDark } = useTheme();
49
50    return (
51        <React.StrictMode>
52            <ThemeProvider theme={theme}>
53                <CssBaseline />
54                <div
55                    style={{
56                        position: 'absolute',
57                        top: 0,
58                        right: 0,
59                        margin: '0.5rem',
60                    }}
61                >
62                    <AboutButton style={{ marginRight: '0.5rem' }} />
63                    <IconButton size="small" onClick={toggleTheme}>
64                        {isDark ? <Brightness7 /> : <Brightness4 />}
65                    </IconButton>
66                </div>
67                <App />
68            </ThemeProvider>
69        </React.StrictMode>
70    );
71};
72
73ReactDOM.render(<Root />, document.getElementById('root'));
74
75// If you want your app to work offline and load faster, you can change
76// unregister() to register() below. Note this comes with some pitfalls.
77// Learn more about service workers: https://bit.ly/CRA-PWA
78serviceWorker.unregister();
79
80// TODO: Try using a service worker to aid in reloading when needed.
81// let refreshing = false;
82// serviceWorker.register({
83//     onUpdate: () => {
84//         if (!refreshing) {
85//             refreshing = true;
86//             window.location.reload();
87//         }
88//     }
89// });