mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-13 11:13:50 +01:00
a26b9c8dcf
Removed the themes buttons that were in the ThemeEditorModal and only left a "Revert to Default" button along with a link to the ThemeBrowser page. Split off the buttons into reusable components since they are now used in two pages. Display the themes in big cards with a zoomable screenshot. Applying the theme now shows a toast with an option to undo the action. The snackbar now allows ReactNode instead of only strings. - Add link with details on how to create a new theme in the game. - Add link to the theme-sharing discord channel. - Add icons to the theme & style buttons in GameOptions - Add "Theme Editor" button to ThemeBrowser - Add "Style Editor" button to ThemeBrowser - Move Styles related files into Themes folder - Includes a modal that shows a bigger version of the screenshot. - Change Snackbar to allow for ReactNode as the message
94 lines
2.9 KiB
TypeScript
94 lines
2.9 KiB
TypeScript
import React, { useEffect, useState } from "react";
|
|
import Typography from "@mui/material/Typography";
|
|
import Paper from "@mui/material/Paper";
|
|
import { ThemeEvents } from "./Theme";
|
|
import { Settings } from "../../Settings/Settings";
|
|
import { getPredefinedThemes, IPredefinedTheme } from "../Themes";
|
|
import { Box, ButtonGroup, Button } from "@mui/material";
|
|
import { IRouter } from "../../ui/Router";
|
|
import { ThemeEditorButton } from "./ThemeEditorButton";
|
|
import { StyleEditorButton } from "./StyleEditorButton";
|
|
import { ThemeEntry } from "./ThemeEntry";
|
|
import { ThemeCollaborate } from "./ThemeCollaborate";
|
|
import { Modal } from "../../ui/React/Modal";
|
|
import { SnackbarEvents } from "../../ui/React/Snackbar";
|
|
|
|
interface IProps {
|
|
router: IRouter;
|
|
}
|
|
|
|
// Everything dies when the theme gets reloaded, so we'll keep the current scroll to not jump around.
|
|
let previousScrollY = 0;
|
|
|
|
export function ThemeBrowser({ router }: IProps): React.ReactElement {
|
|
const [modalOpen, setModalOpen] = useState(false);
|
|
const [modalImageSrc, setModalImageSrc] = useState<string | undefined>();
|
|
const predefinedThemes = getPredefinedThemes();
|
|
const themes = (predefinedThemes &&
|
|
Object.entries(predefinedThemes).map(([key, templateTheme]) => (
|
|
<ThemeEntry
|
|
key={key}
|
|
theme={templateTheme}
|
|
onActivated={() => setTheme(templateTheme)}
|
|
onImageClick={handleZoom}
|
|
/>
|
|
))) || <></>;
|
|
|
|
function setTheme(theme: IPredefinedTheme): void {
|
|
previousScrollY = window.scrollY;
|
|
const previousColors = { ...Settings.theme };
|
|
Object.assign(Settings.theme, theme.colors);
|
|
ThemeEvents.emit();
|
|
SnackbarEvents.emit(
|
|
<>
|
|
Updated theme to "<strong>{theme.name}</strong>"
|
|
<Button
|
|
sx={{ ml: 1 }}
|
|
color="secondary"
|
|
size="small"
|
|
onClick={() => {
|
|
Object.assign(Settings.theme, previousColors);
|
|
ThemeEvents.emit();
|
|
}}
|
|
>
|
|
UNDO
|
|
</Button>
|
|
</>,
|
|
"info",
|
|
30000,
|
|
);
|
|
}
|
|
|
|
function handleZoom(src: string): void {
|
|
previousScrollY = window.scrollY;
|
|
setModalImageSrc(src);
|
|
setModalOpen(true);
|
|
}
|
|
|
|
function handleCloseZoom(): void {
|
|
previousScrollY = window.scrollY;
|
|
setModalOpen(false);
|
|
}
|
|
|
|
useEffect(() => {
|
|
requestAnimationFrame(() => window.scrollTo(0, previousScrollY));
|
|
});
|
|
|
|
return (
|
|
<Box sx={{ mx: 2 }}>
|
|
<Typography variant="h4">Theme Browser</Typography>
|
|
<Paper sx={{ px: 2, py: 1, my: 1 }}>
|
|
<ThemeCollaborate />
|
|
<ButtonGroup sx={{ mb: 2, display: "block" }}>
|
|
<ThemeEditorButton router={router} />
|
|
<StyleEditorButton />
|
|
</ButtonGroup>
|
|
<Box sx={{ display: "flex", flexWrap: "wrap" }}>{themes}</Box>
|
|
<Modal open={modalOpen} onClose={handleCloseZoom}>
|
|
<img src={modalImageSrc} style={{ width: "100%" }} />
|
|
</Modal>
|
|
</Paper>
|
|
</Box>
|
|
);
|
|
}
|