mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-18 12:15:44 +01:00
Allow drag on character overview
Makes the character overview (and tutorial) draggable, persisting the {x, y, opened} in the user's settings. - Remove margin & padding from html, body and ensure main content is full height - Add setting to disable progress bars - Refactor options to use new OptionSwitch - Add exclusions to prettierignore - Specify line ending in prettier & gitattributes
This commit is contained in:
parent
a53b36ed27
commit
7ee2612c17
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1 +1 @@
|
|||||||
* text=auto
|
* text=auto eol=lf
|
||||||
|
@ -2,3 +2,14 @@ node_modules
|
|||||||
package.json
|
package.json
|
||||||
dist
|
dist
|
||||||
doc/build/
|
doc/build/
|
||||||
|
doc/source
|
||||||
|
.build
|
||||||
|
.package
|
||||||
|
|
||||||
|
editor.main.js
|
||||||
|
main.bundle.js
|
||||||
|
index.html
|
||||||
|
markdown
|
||||||
|
|
||||||
|
package.json
|
||||||
|
package.lock.json
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"trailingComma": "all",
|
"trailingComma": "all",
|
||||||
|
"endOfLine": "lf",
|
||||||
"tabWidth": 2,
|
"tabWidth": 2,
|
||||||
"printWidth": 120
|
"printWidth": 120
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@ import { ISelfInitializer, ISelfLoading } from "../types";
|
|||||||
import { OwnedAugmentationsOrderSetting, PurchaseAugmentationsOrderSetting } from "./SettingEnums";
|
import { OwnedAugmentationsOrderSetting, PurchaseAugmentationsOrderSetting } from "./SettingEnums";
|
||||||
import { defaultTheme, ITheme } from "./Themes";
|
import { defaultTheme, ITheme } from "./Themes";
|
||||||
import { defaultStyles, IStyleSettings } from "./Styles";
|
import { defaultStyles, IStyleSettings } from "./Styles";
|
||||||
import { WordWrapOptions } from '../ScriptEditor/ui/Options';
|
import { WordWrapOptions } from "../ScriptEditor/ui/Options";
|
||||||
|
import { OverviewSettings } from "../ui/React/Overview";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the default settings the player could customize.
|
* Represents the default settings the player could customize.
|
||||||
@ -41,6 +42,11 @@ interface IDefaultSettings {
|
|||||||
*/
|
*/
|
||||||
DisableTextEffects: boolean;
|
DisableTextEffects: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether overview progress bars should be visible.
|
||||||
|
*/
|
||||||
|
DisableOverviewProgressBars: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable bash hotkeys
|
* Enable bash hotkeys
|
||||||
*/
|
*/
|
||||||
@ -125,6 +131,11 @@ interface IDefaultSettings {
|
|||||||
* Use GiB instead of GB
|
* Use GiB instead of GB
|
||||||
*/
|
*/
|
||||||
UseIEC60027_2: boolean;
|
UseIEC60027_2: boolean;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Character overview settings
|
||||||
|
*/
|
||||||
|
overview: OverviewSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,6 +171,7 @@ export const defaultSettings: IDefaultSettings = {
|
|||||||
DisableASCIIArt: false,
|
DisableASCIIArt: false,
|
||||||
DisableHotkeys: false,
|
DisableHotkeys: false,
|
||||||
DisableTextEffects: false,
|
DisableTextEffects: false,
|
||||||
|
DisableOverviewProgressBars: false,
|
||||||
EnableBashHotkeys: false,
|
EnableBashHotkeys: false,
|
||||||
TimestampsFormat: "",
|
TimestampsFormat: "",
|
||||||
Locale: "en",
|
Locale: "en",
|
||||||
@ -178,6 +190,7 @@ export const defaultSettings: IDefaultSettings = {
|
|||||||
|
|
||||||
theme: defaultTheme,
|
theme: defaultTheme,
|
||||||
styles: defaultStyles,
|
styles: defaultStyles,
|
||||||
|
overview: { x: 0, y: 0, opened: true },
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -192,6 +205,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
|||||||
DisableASCIIArt: defaultSettings.DisableASCIIArt,
|
DisableASCIIArt: defaultSettings.DisableASCIIArt,
|
||||||
DisableHotkeys: defaultSettings.DisableHotkeys,
|
DisableHotkeys: defaultSettings.DisableHotkeys,
|
||||||
DisableTextEffects: defaultSettings.DisableTextEffects,
|
DisableTextEffects: defaultSettings.DisableTextEffects,
|
||||||
|
DisableOverviewProgressBars: defaultSettings.DisableOverviewProgressBars,
|
||||||
EnableBashHotkeys: defaultSettings.EnableBashHotkeys,
|
EnableBashHotkeys: defaultSettings.EnableBashHotkeys,
|
||||||
TimestampsFormat: defaultSettings.TimestampsFormat,
|
TimestampsFormat: defaultSettings.TimestampsFormat,
|
||||||
Locale: "en",
|
Locale: "en",
|
||||||
@ -213,10 +227,11 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
|||||||
MonacoInsertSpaces: false,
|
MonacoInsertSpaces: false,
|
||||||
MonacoFontSize: 20,
|
MonacoFontSize: 20,
|
||||||
MonacoVim: false,
|
MonacoVim: false,
|
||||||
MonacoWordWrap: 'off',
|
MonacoWordWrap: "off",
|
||||||
|
|
||||||
theme: { ...defaultTheme },
|
theme: { ...defaultTheme },
|
||||||
styles: { ...defaultStyles },
|
styles: { ...defaultStyles },
|
||||||
|
overview: defaultSettings.overview,
|
||||||
init() {
|
init() {
|
||||||
Object.assign(Settings, defaultSettings);
|
Object.assign(Settings, defaultSettings);
|
||||||
},
|
},
|
||||||
@ -226,6 +241,8 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
|||||||
delete save.theme;
|
delete save.theme;
|
||||||
Object.assign(Settings.styles, save.styles);
|
Object.assign(Settings.styles, save.styles);
|
||||||
delete save.styles;
|
delete save.styles;
|
||||||
|
Object.assign(Settings.overview, save.overview);
|
||||||
|
delete save.overview;
|
||||||
Object.assign(Settings, save);
|
Object.assign(Settings, save);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -5,8 +5,6 @@ import { BaseServer } from "../../Server/BaseServer";
|
|||||||
import { getServerOnNetwork } from "../../Server/ServerHelpers";
|
import { getServerOnNetwork } from "../../Server/ServerHelpers";
|
||||||
import { GetServer } from "../../Server/AllServers";
|
import { GetServer } from "../../Server/AllServers";
|
||||||
import { Server } from "../../Server/Server";
|
import { Server } from "../../Server/Server";
|
||||||
import { Programs } from "src/Programs/Programs";
|
|
||||||
import { programsMetadata } from "src/Programs/data/ProgramsMetadata";
|
|
||||||
|
|
||||||
export function connect(
|
export function connect(
|
||||||
terminal: ITerminal,
|
terminal: ITerminal,
|
||||||
|
@ -52,6 +52,11 @@
|
|||||||
</script>
|
</script>
|
||||||
<% } %>
|
<% } %>
|
||||||
<style>
|
<style>
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
body {
|
body {
|
||||||
background-color: black;
|
background-color: black;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,6 @@ import { enterBitNode } from "../RedPill";
|
|||||||
import { Context } from "./Context";
|
import { Context } from "./Context";
|
||||||
import { RecoveryMode, RecoveryRoot } from "./React/RecoveryRoot";
|
import { RecoveryMode, RecoveryRoot } from "./React/RecoveryRoot";
|
||||||
import { AchievementsRoot } from "../Achievements/AchievementsRoot";
|
import { AchievementsRoot } from "../Achievements/AchievementsRoot";
|
||||||
import { Settings } from "../Settings/Settings";
|
|
||||||
|
|
||||||
const htmlLocation = location;
|
const htmlLocation = location;
|
||||||
|
|
||||||
@ -93,6 +92,10 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
"-ms-overflow-style": "none" /* for Internet Explorer, Edge */,
|
"-ms-overflow-style": "none" /* for Internet Explorer, Edge */,
|
||||||
"scrollbar-width": "none" /* for Firefox */,
|
"scrollbar-width": "none" /* for Firefox */,
|
||||||
margin: theme.spacing(0),
|
margin: theme.spacing(0),
|
||||||
|
flexGrow: 1,
|
||||||
|
display: "block",
|
||||||
|
padding: "8px",
|
||||||
|
minHeight: "100vh",
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@ -187,7 +190,7 @@ export let Router: IRouter = {
|
|||||||
},
|
},
|
||||||
toAchievements: () => {
|
toAchievements: () => {
|
||||||
throw new Error("Router called before initialization");
|
throw new Error("Router called before initialization");
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function determineStartPage(player: IPlayer): Page {
|
function determineStartPage(player: IPlayer): Page {
|
||||||
@ -198,7 +201,7 @@ function determineStartPage(player: IPlayer): Page {
|
|||||||
|
|
||||||
export function GameRoot({ player, engine, terminal }: IProps): React.ReactElement {
|
export function GameRoot({ player, engine, terminal }: IProps): React.ReactElement {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [{files, vim}, setEditorOptions] = useState({files: {}, vim: false})
|
const [{ files, vim }, setEditorOptions] = useState({ files: {}, vim: false });
|
||||||
const [page, setPage] = useState(determineStartPage(player));
|
const [page, setPage] = useState(determineStartPage(player));
|
||||||
const setRerender = useState(0)[1];
|
const setRerender = useState(0)[1];
|
||||||
const [faction, setFaction] = useState<Faction>(
|
const [faction, setFaction] = useState<Faction>(
|
||||||
@ -315,7 +318,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
mainPage = <BitverseRoot flume={flume} enter={enterBitNode} quick={quick} />;
|
mainPage = <BitverseRoot flume={flume} enter={enterBitNode} quick={quick} />;
|
||||||
withSidebar = false;
|
withSidebar = false;
|
||||||
withPopups = false;
|
withPopups = false;
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
case Page.Infiltration: {
|
case Page.Infiltration: {
|
||||||
mainPage = <InfiltrationRoot location={location} />;
|
mainPage = <InfiltrationRoot location={location} />;
|
||||||
@ -351,13 +354,15 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.ScriptEditor: {
|
case Page.ScriptEditor: {
|
||||||
mainPage = <ScriptEditorRoot
|
mainPage = (
|
||||||
|
<ScriptEditorRoot
|
||||||
files={files}
|
files={files}
|
||||||
hostname={player.getCurrentServer().hostname}
|
hostname={player.getCurrentServer().hostname}
|
||||||
player={player}
|
player={player}
|
||||||
router={Router}
|
router={Router}
|
||||||
vim={vim}
|
vim={vim}
|
||||||
/>;
|
/>
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.ActiveScripts: {
|
case Page.ActiveScripts: {
|
||||||
@ -385,13 +390,15 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.Tutorial: {
|
case Page.Tutorial: {
|
||||||
mainPage = <TutorialRoot
|
mainPage = (
|
||||||
|
<TutorialRoot
|
||||||
reactivateTutorial={() => {
|
reactivateTutorial={() => {
|
||||||
prestigeAugmentation();
|
prestigeAugmentation();
|
||||||
Router.toTerminal();
|
Router.toTerminal();
|
||||||
iTutorialStart();
|
iTutorialStart();
|
||||||
}}
|
}}
|
||||||
/>;
|
/>
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.DevMenu: {
|
case Page.DevMenu: {
|
||||||
@ -419,7 +426,8 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.StockMarket: {
|
case Page.StockMarket: {
|
||||||
mainPage = <StockMarketRoot
|
mainPage = (
|
||||||
|
<StockMarketRoot
|
||||||
buyStockLong={buyStock}
|
buyStockLong={buyStock}
|
||||||
buyStockShort={shortStock}
|
buyStockShort={shortStock}
|
||||||
cancelOrder={cancelOrder}
|
cancelOrder={cancelOrder}
|
||||||
@ -430,7 +438,8 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
sellStockLong={sellStock}
|
sellStockLong={sellStock}
|
||||||
sellStockShort={sellShort}
|
sellStockShort={sellShort}
|
||||||
stockMarket={StockMarket}
|
stockMarket={StockMarket}
|
||||||
/>;
|
/>
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.City: {
|
case Page.City: {
|
||||||
@ -443,13 +452,14 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.Options: {
|
case Page.Options: {
|
||||||
mainPage = <GameOptionsRoot
|
mainPage = (
|
||||||
|
<GameOptionsRoot
|
||||||
player={player}
|
player={player}
|
||||||
save={() => saveObject.saveGame()}
|
save={() => saveObject.saveGame()}
|
||||||
export={() => {
|
export={() => {
|
||||||
// Apply the export bonus before saving the game
|
// Apply the export bonus before saving the game
|
||||||
onExport(player);
|
onExport(player);
|
||||||
saveObject.exportGame()
|
saveObject.exportGame();
|
||||||
}}
|
}}
|
||||||
forceKill={killAllScripts}
|
forceKill={killAllScripts}
|
||||||
softReset={() => {
|
softReset={() => {
|
||||||
@ -457,11 +467,13 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
prestigeAugmentation();
|
prestigeAugmentation();
|
||||||
Router.toTerminal();
|
Router.toTerminal();
|
||||||
}}
|
}}
|
||||||
/>;
|
/>
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.Augmentations: {
|
case Page.Augmentations: {
|
||||||
mainPage = <AugmentationsRoot
|
mainPage = (
|
||||||
|
<AugmentationsRoot
|
||||||
exportGameFn={() => {
|
exportGameFn={() => {
|
||||||
// Apply the export bonus before saving the game
|
// Apply the export bonus before saving the game
|
||||||
onExport(player);
|
onExport(player);
|
||||||
@ -471,7 +483,8 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
installAugmentations();
|
installAugmentations();
|
||||||
Router.toTerminal();
|
Router.toTerminal();
|
||||||
}}
|
}}
|
||||||
/>;
|
/>
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page.Achievements: {
|
case Page.Achievements: {
|
||||||
@ -484,7 +497,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
<Context.Player.Provider value={player}>
|
<Context.Player.Provider value={player}>
|
||||||
<Context.Router.Provider value={Router}>
|
<Context.Router.Provider value={Router}>
|
||||||
<SnackbarProvider>
|
<SnackbarProvider>
|
||||||
<Overview>
|
<Overview mode={ITutorial.isRunning ? "tutorial" : "overview"}>
|
||||||
{!ITutorial.isRunning ? (
|
{!ITutorial.isRunning ? (
|
||||||
<CharacterOverview save={() => saveObject.saveGame()} killScripts={killAllScripts} />
|
<CharacterOverview save={() => saveObject.saveGame()} killScripts={killAllScripts} />
|
||||||
) : (
|
) : (
|
||||||
@ -494,11 +507,11 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
{withSidebar ? (
|
{withSidebar ? (
|
||||||
<Box display="flex" flexDirection="row" width="100%">
|
<Box display="flex" flexDirection="row" width="100%">
|
||||||
<SidebarRoot player={player} router={Router} page={page} />
|
<SidebarRoot player={player} router={Router} page={page} />
|
||||||
<Box className={classes.root} flexGrow={1} display="block" px={1} min-height="100vh">
|
<Box className={classes.root}>{mainPage}</Box>
|
||||||
{mainPage}
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
) : (
|
||||||
) : mainPage }
|
<Box className={classes.root}>{mainPage}</Box>
|
||||||
|
)}
|
||||||
<Unclickable />
|
<Unclickable />
|
||||||
{withPopups && (
|
{withPopups && (
|
||||||
<>
|
<>
|
||||||
|
@ -12,7 +12,6 @@ import { CopyableText } from "../React/CopyableText";
|
|||||||
import ListItem from "@mui/material/ListItem";
|
import ListItem from "@mui/material/ListItem";
|
||||||
import EqualizerIcon from "@mui/icons-material/Equalizer";
|
import EqualizerIcon from "@mui/icons-material/Equalizer";
|
||||||
import LastPageIcon from "@mui/icons-material/LastPage";
|
import LastPageIcon from "@mui/icons-material/LastPage";
|
||||||
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
|
|
||||||
import HelpIcon from "@mui/icons-material/Help";
|
import HelpIcon from "@mui/icons-material/Help";
|
||||||
import AccountTreeIcon from "@mui/icons-material/AccountTree";
|
import AccountTreeIcon from "@mui/icons-material/AccountTree";
|
||||||
import StorageIcon from "@mui/icons-material/Storage";
|
import StorageIcon from "@mui/icons-material/Storage";
|
||||||
@ -61,7 +60,7 @@ export function InteractiveTutorialRoot(): React.ReactElement {
|
|||||||
This tutorial will show you the basics of the game. You may skip the tutorial at any time.
|
This tutorial will show you the basics of the game. You may skip the tutorial at any time.
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
You can also click the eye symbol <VisibilityOffIcon /> to temporarily hide this tutorial.
|
You can also collapse this panel to temporarily hide this tutorial.
|
||||||
</Typography>
|
</Typography>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
|
@ -287,7 +287,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
{!Settings.DisableOverviewProgressBars && (
|
||||||
<StatsProgressOverviewCell progress={hackingProgress} color={theme.colors.hack} />
|
<StatsProgressOverviewCell progress={hackingProgress} color={theme.colors.hack} />
|
||||||
|
)}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell component="th" scope="row" classes={{ root: classes.cell }}>
|
<TableCell component="th" scope="row" classes={{ root: classes.cell }}>
|
||||||
@ -314,7 +316,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
{!Settings.DisableOverviewProgressBars && (
|
||||||
<StatsProgressOverviewCell progress={strengthProgress} color={theme.colors.combat} />
|
<StatsProgressOverviewCell progress={strengthProgress} color={theme.colors.combat} />
|
||||||
|
)}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
@ -331,7 +335,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
{!Settings.DisableOverviewProgressBars && (
|
||||||
<StatsProgressOverviewCell progress={defenseProgress} color={theme.colors.combat} />
|
<StatsProgressOverviewCell progress={defenseProgress} color={theme.colors.combat} />
|
||||||
|
)}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
@ -348,7 +354,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
{!Settings.DisableOverviewProgressBars && (
|
||||||
<StatsProgressOverviewCell progress={dexterityProgress} color={theme.colors.combat} />
|
<StatsProgressOverviewCell progress={dexterityProgress} color={theme.colors.combat} />
|
||||||
|
)}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
@ -365,7 +373,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
{!Settings.DisableOverviewProgressBars && (
|
||||||
<StatsProgressOverviewCell progress={agilityProgress} color={theme.colors.combat} />
|
<StatsProgressOverviewCell progress={agilityProgress} color={theme.colors.combat} />
|
||||||
|
)}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
@ -382,7 +392,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
{!Settings.DisableOverviewProgressBars && (
|
||||||
<StatsProgressOverviewCell progress={charismaProgress} color={theme.colors.cha} />
|
<StatsProgressOverviewCell progress={charismaProgress} color={theme.colors.cha} />
|
||||||
|
)}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
<Intelligence />
|
<Intelligence />
|
||||||
|
@ -8,8 +8,6 @@ import createStyles from "@mui/styles/createStyles";
|
|||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Slider from "@mui/material/Slider";
|
import Slider from "@mui/material/Slider";
|
||||||
import Grid from "@mui/material/Grid";
|
import Grid from "@mui/material/Grid";
|
||||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
|
||||||
import Switch from "@mui/material/Switch";
|
|
||||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||||
import MenuItem from "@mui/material/MenuItem";
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
@ -35,6 +33,7 @@ import { SnackbarEvents } from "./Snackbar";
|
|||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
import { save, deleteGame } from "../../db";
|
import { save, deleteGame } from "../../db";
|
||||||
import { formatTime } from "../../utils/helpers/formatTime";
|
import { formatTime } from "../../utils/helpers/formatTime";
|
||||||
|
import { OptionSwitch } from "./OptionSwitch";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
@ -68,27 +67,8 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
|||||||
const [logSize, setLogSize] = useState(Settings.MaxLogCapacity);
|
const [logSize, setLogSize] = useState(Settings.MaxLogCapacity);
|
||||||
const [portSize, setPortSize] = useState(Settings.MaxPortCapacity);
|
const [portSize, setPortSize] = useState(Settings.MaxPortCapacity);
|
||||||
const [terminalSize, setTerminalSize] = useState(Settings.MaxTerminalCapacity);
|
const [terminalSize, setTerminalSize] = useState(Settings.MaxTerminalCapacity);
|
||||||
|
|
||||||
const [autosaveInterval, setAutosaveInterval] = useState(Settings.AutosaveInterval);
|
const [autosaveInterval, setAutosaveInterval] = useState(Settings.AutosaveInterval);
|
||||||
|
|
||||||
const [suppressMessages, setSuppressMessages] = useState(Settings.SuppressMessages);
|
|
||||||
const [suppressFactionInvites, setSuppressFactionInvites] = useState(Settings.SuppressFactionInvites);
|
|
||||||
const [suppressTravelConfirmations, setSuppressTravelConfirmations] = useState(Settings.SuppressTravelConfirmation);
|
|
||||||
const [suppressBuyAugmentationConfirmation, setSuppressBuyAugmentationConfirmation] = useState(
|
|
||||||
Settings.SuppressBuyAugmentationConfirmation,
|
|
||||||
);
|
|
||||||
const [suppressTIXPopup, setSuppressTIXPopup] = useState(Settings.SuppressTIXPopup);
|
|
||||||
const [suppressBladeburnerPopup, setSuppressBladeburnerPopup] = useState(Settings.SuppressBladeburnerPopup);
|
|
||||||
const [suppressSavedGameToast, setSuppresSavedGameToast] = useState(Settings.SuppressSavedGameToast);
|
|
||||||
|
|
||||||
const [disableHotkeys, setDisableHotkeys] = useState(Settings.DisableHotkeys);
|
|
||||||
const [disableASCIIArt, setDisableASCIIArt] = useState(Settings.DisableASCIIArt);
|
|
||||||
const [disableTextEffects, setDisableTextEffects] = useState(Settings.DisableTextEffects);
|
|
||||||
const [enableBashHotkeys, setEnableBashHotkeys] = useState(Settings.EnableBashHotkeys);
|
|
||||||
const [timestampFormat, setTimestampFormat] = useState(Settings.TimestampsFormat);
|
const [timestampFormat, setTimestampFormat] = useState(Settings.TimestampsFormat);
|
||||||
const [saveGameOnFileSave, setSaveGameOnFileSave] = useState(Settings.SaveGameOnFileSave);
|
|
||||||
const [useIEC60027_2, setUseIEC60027_2] = useState(Settings.UseIEC60027_2);
|
|
||||||
|
|
||||||
const [locale, setLocale] = useState(Settings.Locale);
|
const [locale, setLocale] = useState(Settings.Locale);
|
||||||
const [diagnosticOpen, setDiagnosticOpen] = useState(false);
|
const [diagnosticOpen, setDiagnosticOpen] = useState(false);
|
||||||
const [deleteGameOpen, setDeleteOpen] = useState(false);
|
const [deleteGameOpen, setDeleteOpen] = useState(false);
|
||||||
@ -123,76 +103,15 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
|||||||
Settings.AutosaveInterval = newValue as number;
|
Settings.AutosaveInterval = newValue as number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSuppressMessagesChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setSuppressMessages(event.target.checked);
|
|
||||||
Settings.SuppressMessages = event.target.checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSuppressFactionInvitesChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setSuppressFactionInvites(event.target.checked);
|
|
||||||
Settings.SuppressFactionInvites = event.target.checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSuppressTravelConfirmationsChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setSuppressTravelConfirmations(event.target.checked);
|
|
||||||
Settings.SuppressTravelConfirmation = event.target.checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSuppressBuyAugmentationConfirmationChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setSuppressBuyAugmentationConfirmation(event.target.checked);
|
|
||||||
Settings.SuppressBuyAugmentationConfirmation = event.target.checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSuppressTIXPopupChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setSuppressTIXPopup(event.target.checked);
|
|
||||||
Settings.SuppressTIXPopup = event.target.checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSuppressBladeburnerPopupChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setSuppressBladeburnerPopup(event.target.checked);
|
|
||||||
Settings.SuppressBladeburnerPopup = event.target.checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSuppressSavedGameToastChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setSuppresSavedGameToast(event.target.checked);
|
|
||||||
Settings.SuppressSavedGameToast = event.target.checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDisableHotkeysChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setDisableHotkeys(event.target.checked);
|
|
||||||
Settings.DisableHotkeys = event.target.checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDisableASCIIArtChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setDisableASCIIArt(event.target.checked);
|
|
||||||
Settings.DisableASCIIArt = event.target.checked;
|
|
||||||
}
|
|
||||||
function handleUseIEC60027_2Change(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setUseIEC60027_2(event.target.checked);
|
|
||||||
Settings.UseIEC60027_2 = event.target.checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDisableTextEffectsChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setDisableTextEffects(event.target.checked);
|
|
||||||
Settings.DisableTextEffects = event.target.checked;
|
|
||||||
}
|
|
||||||
function handleLocaleChange(event: SelectChangeEvent<string>): void {
|
function handleLocaleChange(event: SelectChangeEvent<string>): void {
|
||||||
setLocale(event.target.value as string);
|
setLocale(event.target.value as string);
|
||||||
Settings.Locale = event.target.value as string;
|
Settings.Locale = event.target.value as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleEnableBashHotkeysChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setEnableBashHotkeys(event.target.checked);
|
|
||||||
Settings.EnableBashHotkeys = event.target.checked;
|
|
||||||
}
|
|
||||||
function handleTimestampFormatChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
function handleTimestampFormatChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||||
setTimestampFormat(event.target.value);
|
setTimestampFormat(event.target.value);
|
||||||
Settings.TimestampsFormat = event.target.value;
|
Settings.TimestampsFormat = event.target.value;
|
||||||
}
|
}
|
||||||
function handleSaveGameOnFile(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setSaveGameOnFileSave(event.target.checked);
|
|
||||||
Settings.SaveGameOnFileSave = event.target.checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
function startImport(): void {
|
function startImport(): void {
|
||||||
if (!window.File || !window.FileReader || !window.FileList || !window.Blob) return;
|
if (!window.File || !window.FileReader || !window.FileList || !window.Blob) return;
|
||||||
@ -392,200 +311,120 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
|||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<FormControlLabel
|
<OptionSwitch checked={Settings.SuppressMessages}
|
||||||
control={<Switch checked={suppressMessages} onChange={handleSuppressMessagesChange} />}
|
onChange={(newValue) => Settings.SuppressMessages = newValue}
|
||||||
label={
|
text="Suppress story messages"
|
||||||
<Tooltip
|
tooltip={<>
|
||||||
title={
|
|
||||||
<Typography>
|
|
||||||
If this is set, then any messages you receive will not appear as popups on the screen. They will
|
If this is set, then any messages you receive will not appear as popups on the screen. They will
|
||||||
still get sent to your home computer as '.msg' files and can be viewed with the 'cat' Terminal
|
still get sent to your home computer as '.msg' files and can be viewed with the 'cat' Terminal
|
||||||
command.
|
command.
|
||||||
</Typography>
|
</>} />
|
||||||
}
|
|
||||||
>
|
|
||||||
<Typography>Suppress story messages</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<FormControlLabel
|
<OptionSwitch checked={Settings.SuppressFactionInvites}
|
||||||
control={<Switch checked={suppressFactionInvites} onChange={handleSuppressFactionInvitesChange} />}
|
onChange={(newValue) => Settings.SuppressFactionInvites = newValue}
|
||||||
label={
|
text="Suppress faction invites"
|
||||||
<Tooltip
|
tooltip={<>
|
||||||
title={
|
|
||||||
<Typography>
|
|
||||||
If this is set, then any faction invites you receive will not appear as popups on the screen.
|
If this is set, then any faction invites you receive will not appear as popups on the screen.
|
||||||
Your outstanding faction invites can be viewed in the 'Factions' page.
|
Your outstanding faction invites can be viewed in the 'Factions' page.
|
||||||
</Typography>
|
</>} />
|
||||||
}
|
|
||||||
>
|
|
||||||
<Typography>Suppress faction invites</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<FormControlLabel
|
<OptionSwitch checked={Settings.SuppressTravelConfirmation}
|
||||||
control={
|
onChange={(newValue) => Settings.SuppressTravelConfirmation = newValue}
|
||||||
<Switch checked={suppressTravelConfirmations} onChange={handleSuppressTravelConfirmationsChange} />
|
text="Suppress travel confirmations"
|
||||||
}
|
tooltip={<>
|
||||||
label={
|
|
||||||
<Tooltip
|
|
||||||
title={
|
|
||||||
<Typography>
|
|
||||||
If this is set, the confirmation message before traveling will not show up. You will
|
If this is set, the confirmation message before traveling will not show up. You will
|
||||||
automatically be deducted the travel cost as soon as you click.
|
automatically be deducted the travel cost as soon as you click.
|
||||||
</Typography>
|
</>} />
|
||||||
}
|
|
||||||
>
|
|
||||||
<Typography>Suppress travel confirmations</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<FormControlLabel
|
<OptionSwitch checked={Settings.SuppressBuyAugmentationConfirmation}
|
||||||
control={
|
onChange={(newValue) => Settings.SuppressBuyAugmentationConfirmation = newValue}
|
||||||
<Switch
|
text="Suppress augmentations confirmation"
|
||||||
checked={suppressBuyAugmentationConfirmation}
|
tooltip={<>
|
||||||
onChange={handleSuppressBuyAugmentationConfirmationChange}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={
|
|
||||||
<Tooltip
|
|
||||||
title={
|
|
||||||
<Typography>
|
|
||||||
If this is set, the confirmation message before buying augmentation will not show up.
|
If this is set, the confirmation message before buying augmentation will not show up.
|
||||||
</Typography>
|
</>} />
|
||||||
}
|
|
||||||
>
|
|
||||||
<Typography>Suppress augmentations confirmation</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<FormControlLabel
|
<OptionSwitch checked={Settings.SuppressTIXPopup}
|
||||||
control={<Switch checked={suppressTIXPopup} onChange={handleSuppressTIXPopupChange} />}
|
onChange={(newValue) => Settings.SuppressTIXPopup = newValue}
|
||||||
label={
|
text="Suppress TIX messages"
|
||||||
<Tooltip
|
tooltip={<>
|
||||||
title={<Typography>If this is set, the stock market will never create any popup.</Typography>}
|
If this is set, the stock market will never create any popup.
|
||||||
>
|
</>} />
|
||||||
<Typography>Suppress TIX messages</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
{!!props.player.bladeburner && (
|
{!!props.player.bladeburner && (
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<FormControlLabel
|
<OptionSwitch checked={Settings.SuppressBladeburnerPopup}
|
||||||
control={
|
onChange={(newValue) => Settings.SuppressBladeburnerPopup = newValue}
|
||||||
<Switch checked={suppressBladeburnerPopup} onChange={handleSuppressBladeburnerPopupChange} />
|
text="Suppress bladeburner popup"
|
||||||
}
|
tooltip={<>
|
||||||
label={
|
|
||||||
<Tooltip
|
|
||||||
title={
|
|
||||||
<Typography>
|
|
||||||
If this is set, then having your Bladeburner actions interrupted by being busy with something
|
If this is set, then having your Bladeburner actions interrupted by being busy with something
|
||||||
else will not display a popup message.
|
else will not display a popup message.
|
||||||
</Typography>
|
</>} />
|
||||||
}
|
|
||||||
>
|
|
||||||
<Typography>Suppress bladeburner popup</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
)}
|
)}
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<FormControlLabel
|
<OptionSwitch checked={Settings.SuppressSavedGameToast}
|
||||||
control={<Switch checked={suppressSavedGameToast} onChange={handleSuppressSavedGameToastChange} />}
|
onChange={(newValue) => Settings.SuppressSavedGameToast = newValue}
|
||||||
label={
|
text="Suppress Auto-Save Game Toast"
|
||||||
<Tooltip
|
tooltip={<>
|
||||||
title={
|
If this is set, there will be no "Game Saved!" toast appearing after an auto-save.
|
||||||
<Typography>If this is set, there will be no "Game Saved!" toast appearing after an auto-save.</Typography>
|
</>} />
|
||||||
}
|
|
||||||
>
|
|
||||||
<Typography>Suppress Auto-Save Game Toast</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<FormControlLabel
|
<OptionSwitch checked={Settings.DisableHotkeys}
|
||||||
control={<Switch checked={disableHotkeys} onChange={handleDisableHotkeysChange} />}
|
onChange={(newValue) => Settings.DisableHotkeys = newValue}
|
||||||
label={
|
text="Disable hotkeys"
|
||||||
<Tooltip
|
tooltip={<>
|
||||||
title={
|
|
||||||
<Typography>
|
|
||||||
If this is set, then most hotkeys (keyboard shortcuts) in the game are disabled. This includes
|
If this is set, then most hotkeys (keyboard shortcuts) in the game are disabled. This includes
|
||||||
Terminal commands, hotkeys to navigate between different parts of the game, and the "Save and
|
Terminal commands, hotkeys to navigate between different parts of the game, and the "Save and
|
||||||
Close (Ctrl + b)" hotkey in the Text Editor.
|
Close (Ctrl + b)" hotkey in the Text Editor.
|
||||||
</Typography>
|
</>} />
|
||||||
}
|
|
||||||
>
|
|
||||||
<Typography>Disable hotkeys</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<FormControlLabel
|
<OptionSwitch checked={Settings.DisableASCIIArt}
|
||||||
control={<Switch checked={disableASCIIArt} onChange={handleDisableASCIIArtChange} />}
|
onChange={(newValue) => Settings.DisableASCIIArt = newValue}
|
||||||
label={
|
text="Disable ascii art"
|
||||||
<Tooltip title={<Typography>If this is set all ASCII art will be disabled.</Typography>}>
|
tooltip={<>
|
||||||
<Typography>Disable ascii art</Typography>
|
If this is set all ASCII art will be disabled.
|
||||||
</Tooltip>
|
</>} />
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<FormControlLabel
|
<OptionSwitch checked={Settings.DisableTextEffects}
|
||||||
control={<Switch checked={disableTextEffects} onChange={handleDisableTextEffectsChange} />}
|
onChange={(newValue) => Settings.DisableTextEffects = newValue}
|
||||||
label={
|
text="Disable text effects"
|
||||||
<Tooltip
|
tooltip={<>
|
||||||
title={
|
|
||||||
<Typography>
|
|
||||||
If this is set, text effects will not be displayed. This can help if text is difficult to read
|
If this is set, text effects will not be displayed. This can help if text is difficult to read
|
||||||
in certain areas.
|
in certain areas.
|
||||||
</Typography>
|
</>} />
|
||||||
}
|
|
||||||
>
|
|
||||||
<Typography>Disable text effects</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<FormControlLabel
|
<OptionSwitch checked={Settings.DisableOverviewProgressBars}
|
||||||
control={<Switch checked={enableBashHotkeys} onChange={handleEnableBashHotkeysChange} />}
|
onChange={(newValue) => Settings.DisableOverviewProgressBars = newValue}
|
||||||
label={
|
text="Disable Overview Progress Bars"
|
||||||
<Tooltip
|
tooltip={<>
|
||||||
title={
|
If this is set, the progress bars in the character overview will be hidden.
|
||||||
<Typography>
|
</>} />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem>
|
||||||
|
<OptionSwitch checked={Settings.EnableBashHotkeys}
|
||||||
|
onChange={(newValue) => Settings.EnableBashHotkeys = newValue}
|
||||||
|
text="Enable bash hotkeys"
|
||||||
|
tooltip={<>
|
||||||
Improved Bash emulation mode. Setting this to 1 enables several new Terminal shortcuts and
|
Improved Bash emulation mode. Setting this to 1 enables several new Terminal shortcuts and
|
||||||
features that more closely resemble a real Bash-style shell. Note that when this mode is
|
features that more closely resemble a real Bash-style shell. Note that when this mode is
|
||||||
enabled, the default browser shortcuts are overriden by the new Bash shortcuts.
|
enabled, the default browser shortcuts are overriden by the new Bash shortcuts.
|
||||||
</Typography>
|
</>} />
|
||||||
}
|
|
||||||
>
|
|
||||||
<Typography>Enable bash hotkeys</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<FormControlLabel
|
<OptionSwitch checked={Settings.UseIEC60027_2}
|
||||||
control={<Switch checked={useIEC60027_2} onChange={handleUseIEC60027_2Change} />}
|
onChange={(newValue) => Settings.UseIEC60027_2 = newValue}
|
||||||
label={
|
text="Use GiB instead of GB"
|
||||||
<Tooltip title={<Typography>If this is set all references to memory will use GiB instead of GB, in accordance with IEC 60027-2.</Typography>}>
|
tooltip={<>
|
||||||
<Typography>Use GiB instead of GB</Typography>
|
If this is set all references to memory will use GiB instead of GB, in accordance with IEC 60027-2.
|
||||||
</Tooltip>
|
</>} />
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@ -620,16 +459,12 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<FormControlLabel
|
<OptionSwitch checked={Settings.SaveGameOnFileSave}
|
||||||
control={<Switch checked={saveGameOnFileSave} onChange={handleSaveGameOnFile} />}
|
onChange={(newValue) => Settings.SaveGameOnFileSave = newValue}
|
||||||
label={
|
text="Save game on file save"
|
||||||
<Tooltip
|
tooltip={<>
|
||||||
title={<Typography>Save your game any time a file is saved in the script editor.</Typography>}
|
Save your game any time a file is saved in the script editor.
|
||||||
>
|
</>} />
|
||||||
<Typography>Save game on file save</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
|
30
src/ui/React/OptionSwitch.tsx
Normal file
30
src/ui/React/OptionSwitch.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { FormControlLabel, Switch, Tooltip, Typography } from "@mui/material";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
checked: boolean;
|
||||||
|
onChange: (newValue: boolean, error?: string) => void;
|
||||||
|
text: React.ReactNode;
|
||||||
|
tooltip: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function OptionSwitch({ checked, onChange, text, tooltip }: IProps): React.ReactElement {
|
||||||
|
const [value, setValue] = useState(checked);
|
||||||
|
|
||||||
|
function handleSwitchChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||||
|
setValue(event.target.checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => onChange(value), [value]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControlLabel
|
||||||
|
control={<Switch checked={value} onChange={handleSwitchChange} />}
|
||||||
|
label={
|
||||||
|
<Tooltip title={<Typography>{tooltip}</Typography>}>
|
||||||
|
<Typography>{text}</Typography>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -1,21 +1,19 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState, useEffect, useRef } from "react";
|
||||||
|
import Draggable, { DraggableEventHandler } from "react-draggable";
|
||||||
import makeStyles from "@mui/styles/makeStyles";
|
import makeStyles from "@mui/styles/makeStyles";
|
||||||
import Collapse from "@mui/material/Collapse";
|
import Collapse from "@mui/material/Collapse";
|
||||||
import Fab from "@mui/material/Fab";
|
|
||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
|
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
|
||||||
import VisibilityIcon from "@mui/icons-material/Visibility";
|
import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
|
||||||
|
import EqualizerIcon from "@mui/icons-material/Equalizer";
|
||||||
|
import SchoolIcon from "@mui/icons-material/School";
|
||||||
import { use } from "../Context";
|
import { use } from "../Context";
|
||||||
import { Page } from "../Router";
|
import { Page } from "../Router";
|
||||||
|
import { Settings } from "../../Settings/Settings";
|
||||||
|
import { Box, Button, Typography } from "@mui/material";
|
||||||
|
import { debounce } from "lodash";
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
visibilityToggle: {
|
|
||||||
backgroundColor: "transparent",
|
|
||||||
position: "absolute",
|
|
||||||
top: "100%",
|
|
||||||
right: 0,
|
|
||||||
},
|
|
||||||
overviewContainer: {
|
overviewContainer: {
|
||||||
position: "fixed",
|
position: "fixed",
|
||||||
top: 0,
|
top: 0,
|
||||||
@ -25,31 +23,116 @@ const useStyles = makeStyles({
|
|||||||
justifyContent: "flex-end",
|
justifyContent: "flex-end",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
header: {
|
||||||
|
cursor: "grab",
|
||||||
|
textAlign: "center",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
|
||||||
|
visibilityToggle: {
|
||||||
|
padding: "2px",
|
||||||
|
minWidth: "inherit",
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
border: "none",
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
collapse: {
|
||||||
|
borderTop: `1px solid ${Settings.theme.welllight}`,
|
||||||
|
margin: "0 auto",
|
||||||
|
},
|
||||||
|
|
||||||
|
icon: {
|
||||||
|
fontSize: "24px",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
children: JSX.Element[] | JSX.Element | React.ReactElement[] | React.ReactElement;
|
children: JSX.Element[] | JSX.Element | React.ReactElement[] | React.ReactElement;
|
||||||
|
mode: "tutorial" | "overview";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Overview({ children }: IProps): React.ReactElement {
|
export interface OverviewSettings {
|
||||||
const [open, setOpen] = useState(true);
|
opened: boolean;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Overview({ children, mode }: IProps): React.ReactElement {
|
||||||
|
const draggableRef = useRef<HTMLDivElement>(null);
|
||||||
|
const [open, setOpen] = useState(Settings.overview.opened);
|
||||||
|
const [x, setX] = useState(Settings.overview.x);
|
||||||
|
const [y, setY] = useState(Settings.overview.y);
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const router = use.Router();
|
const router = use.Router();
|
||||||
|
|
||||||
|
const CurrentIcon = open ? KeyboardArrowUpIcon : KeyboardArrowDownIcon;
|
||||||
|
const LeftIcon = mode === "tutorial" ? SchoolIcon : EqualizerIcon;
|
||||||
|
const header = mode === "tutorial" ? "Tutorial" : "Overview";
|
||||||
|
const handleStop: DraggableEventHandler = (e, data) => {
|
||||||
|
setX(data.x);
|
||||||
|
setY(data.y);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
Settings.overview = { x, y, opened: open };
|
||||||
|
}, [open, x, y]);
|
||||||
|
|
||||||
|
// Trigger fakeDrag once to make sure loaded data is not outside bounds
|
||||||
|
useEffect(() => fakeDrag(), []);
|
||||||
|
|
||||||
|
// And trigger fakeDrag when the window is resized
|
||||||
|
useEffect(() => {
|
||||||
|
window.addEventListener("resize", fakeDrag);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("resize", fakeDrag);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fakeDrag = debounce((): void => {
|
||||||
|
const node = draggableRef?.current;
|
||||||
|
if (!node) return;
|
||||||
|
|
||||||
|
// No official way to trigger an onChange to recompute the bounds
|
||||||
|
// See: https://github.com/react-grid-layout/react-draggable/issues/363#issuecomment-947751127
|
||||||
|
triggerMouseEvent(node, "mouseover");
|
||||||
|
triggerMouseEvent(node, "mousedown");
|
||||||
|
triggerMouseEvent(document, "mousemove");
|
||||||
|
triggerMouseEvent(node, "mouseup");
|
||||||
|
triggerMouseEvent(node, "click");
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
const triggerMouseEvent = (node: HTMLDivElement | Document, eventType: string): void => {
|
||||||
|
const clickEvent = document.createEvent("MouseEvents");
|
||||||
|
clickEvent.initEvent(eventType, true, true);
|
||||||
|
node.dispatchEvent(clickEvent);
|
||||||
|
};
|
||||||
|
|
||||||
if (router.page() === Page.BitVerse || router.page() === Page.Loading || router.page() === Page.Recovery)
|
if (router.page() === Page.BitVerse || router.page() === Page.Loading || router.page() === Page.Recovery)
|
||||||
return <></>;
|
return <></>;
|
||||||
let icon;
|
|
||||||
if (open) {
|
|
||||||
icon = <VisibilityOffIcon color="primary" />;
|
|
||||||
} else {
|
|
||||||
icon = <VisibilityIcon color="primary" />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper square classes={{ root: classes.overviewContainer }}>
|
<Draggable handle=".drag" bounds="body" onStop={handleStop} defaultPosition={{ x, y }}>
|
||||||
<Collapse in={open}>{children}</Collapse>
|
<Paper className={classes.overviewContainer} square>
|
||||||
<Fab size="small" classes={{ root: classes.visibilityToggle }} onClick={() => setOpen((old) => !old)}>
|
<Box className="drag" onDoubleClick={() => setOpen((old) => !old)} ref={draggableRef}>
|
||||||
{icon}
|
<Box className={classes.header}>
|
||||||
</Fab>
|
<LeftIcon color="secondary" className={classes.icon} sx={{ padding: "2px" }} />
|
||||||
|
<Typography flexGrow={1} color="secondary">
|
||||||
|
{header}
|
||||||
|
</Typography>
|
||||||
|
<Button variant="text" size="small" className={classes.visibilityToggle}>
|
||||||
|
{<CurrentIcon className={classes.icon} color="secondary" onClick={() => setOpen((old) => !old)} />}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<Collapse in={open} className={classes.collapse}>
|
||||||
|
{children}
|
||||||
|
</Collapse>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
</Draggable>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user