mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-08 16:53:54 +01:00
Sidebar tweaks
This commit is contained in:
parent
a46d34bd60
commit
2489ec43fe
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,3 +22,4 @@ Netburner.txt
|
|||||||
.idea/
|
.idea/
|
||||||
*.bundle.*
|
*.bundle.*
|
||||||
index.html
|
index.html
|
||||||
|
tsdoc-metadata.json
|
||||||
|
@ -17,7 +17,7 @@ interface IProps {
|
|||||||
clickPage: (page: Page) => void;
|
clickPage: (page: Page) => void;
|
||||||
flash: Page | null;
|
flash: Page | null;
|
||||||
items: (IItemProps | boolean)[];
|
items: (IItemProps | boolean)[];
|
||||||
icon: React.ReactElement;
|
icon: React.ReactElement["type"];
|
||||||
sidebarOpen: boolean;
|
sidebarOpen: boolean;
|
||||||
classes: any;
|
classes: any;
|
||||||
}
|
}
|
||||||
@ -44,10 +44,7 @@ function getClickFn(toWrap: (page: Page) => void, page: Page) {
|
|||||||
// This can't be usefully memoized, because props.items is a new array every time.
|
// This can't be usefully memoized, because props.items is a new array every time.
|
||||||
export function SidebarAccordion(props: IProps): React.ReactElement {
|
export function SidebarAccordion(props: IProps): React.ReactElement {
|
||||||
const [open, setOpen] = useState(true);
|
const [open, setOpen] = useState(true);
|
||||||
// Obnoxious, because we can't modify props at all.
|
|
||||||
const li_classes = useMemo(() => ({ root: props.classes.listitem }), [props.classes.listitem]);
|
const li_classes = useMemo(() => ({ root: props.classes.listitem }), [props.classes.listitem]);
|
||||||
const icon = Object.assign({}, props.icon);
|
|
||||||
icon.props = Object.assign({ color: "primary" }, icon.props);
|
|
||||||
|
|
||||||
// Explicitily useMemo() to save rerendering deep chunks of this tree.
|
// Explicitily useMemo() to save rerendering deep chunks of this tree.
|
||||||
// memo() can't be (easily) used on components like <List>, because the
|
// memo() can't be (easily) used on components like <List>, because the
|
||||||
@ -58,13 +55,15 @@ export function SidebarAccordion(props: IProps): React.ReactElement {
|
|||||||
() => (
|
() => (
|
||||||
<ListItem classes={li_classes} button onClick={() => setOpen((open) => !open)}>
|
<ListItem classes={li_classes} button onClick={() => setOpen((open) => !open)}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<Tooltip title={!props.sidebarOpen ? props.key_ : ""} children={icon} />
|
<Tooltip title={!props.sidebarOpen ? props.key_ : ""}>
|
||||||
|
<props.icon color={"primary"} />
|
||||||
|
</Tooltip>
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary={<Typography>{props.key_}</Typography>} />
|
<ListItemText primary={<Typography>{props.key_}</Typography>} />
|
||||||
{open ? <ExpandLessIcon color="primary" /> : <ExpandMoreIcon color="primary" />}
|
{open ? <ExpandLessIcon color="primary" /> : <ExpandMoreIcon color="primary" />}
|
||||||
</ListItem>
|
</ListItem>
|
||||||
),
|
),
|
||||||
[li_classes, props.sidebarOpen, props.key_, open, props.icon.type],
|
[li_classes, props.sidebarOpen, props.key_, open, props.icon],
|
||||||
)}
|
)}
|
||||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||||
{props.items.map((x) => {
|
{props.items.map((x) => {
|
||||||
|
@ -10,7 +10,7 @@ import type { Page } from "../../ui/Router";
|
|||||||
|
|
||||||
export interface ICreateProps {
|
export interface ICreateProps {
|
||||||
key_: Page;
|
key_: Page;
|
||||||
icon: React.ReactElement;
|
icon: React.ReactElement["type"];
|
||||||
count?: number;
|
count?: number;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
}
|
}
|
||||||
@ -23,15 +23,7 @@ export interface IProps extends ICreateProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const SidebarItem = memo(function (props: IProps): React.ReactElement {
|
export const SidebarItem = memo(function (props: IProps): React.ReactElement {
|
||||||
// Use icon as a template. (We can't modify props)
|
const color = props.flash ? "error" : props.active ? "primary" : "secondary";
|
||||||
const icon: React.ReactElement = {
|
|
||||||
type: props.icon.type,
|
|
||||||
key: props.icon.key,
|
|
||||||
props: {
|
|
||||||
color: props.flash ? "error" : !props.active ? "secondary" : "primary",
|
|
||||||
...props.icon.props,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<ListItem
|
<ListItem
|
||||||
classes={{ root: props.classes.listitem }}
|
classes={{ root: props.classes.listitem }}
|
||||||
@ -42,11 +34,13 @@ export const SidebarItem = memo(function (props: IProps): React.ReactElement {
|
|||||||
>
|
>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<Badge badgeContent={(props.count ?? 0) > 0 ? props.count : undefined} color="error">
|
<Badge badgeContent={(props.count ?? 0) > 0 ? props.count : undefined} color="error">
|
||||||
<Tooltip title={!props.sidebarOpen ? props.key_ : ""} children={icon} />
|
<Tooltip title={!props.sidebarOpen ? props.key_ : ""}>
|
||||||
|
<props.icon color={color} />
|
||||||
|
</Tooltip>
|
||||||
</Badge>
|
</Badge>
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText>
|
<ListItemText>
|
||||||
<Typography color={props.flash ? "error" : !props.active ? "secondary" : "primary"} children={props.key_} />
|
<Typography color={color} children={props.key_} />
|
||||||
</ListItemText>
|
</ListItemText>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
);
|
);
|
||||||
|
@ -55,38 +55,9 @@ import { InvitationsSeen } from "../../Faction/ui/FactionsRoot";
|
|||||||
import { hash } from "../../hash/hash";
|
import { hash } from "../../hash/hash";
|
||||||
import { Locations } from "../../Locations/Locations";
|
import { Locations } from "../../Locations/Locations";
|
||||||
|
|
||||||
// All icon instances need to be constant, so they have stable object identity.
|
const RotatedDoubleArrowIcon = (props: { color: "primary" | "secondary" | "error" }) => (
|
||||||
// Otherwise, the memoization of all the higher-level components doesn't work.
|
<DoubleArrowIcon color={props.color} style={{ transform: "rotate(-90deg)" }} />
|
||||||
const computerIcon = <ComputerIcon />;
|
);
|
||||||
const lastPageIcon = <LastPageIcon />;
|
|
||||||
const createIcon = <CreateIcon />;
|
|
||||||
const storageIcon = <StorageIcon />;
|
|
||||||
const bugReportIcon = <BugReportIcon />;
|
|
||||||
const equalizerIcon = <EqualizerIcon />;
|
|
||||||
const contactsIcon = <ContactsIcon />;
|
|
||||||
const doubleArrowIcon = <DoubleArrowIcon style={{ transform: "rotate(-90deg)" }} />;
|
|
||||||
const accountTreeIcon = <AccountTreeIcon />;
|
|
||||||
const peopleAltIcon = <PeopleAltIcon />;
|
|
||||||
const locationCityIcon = <LocationCityIcon />;
|
|
||||||
const airplanemodeActiveIcon = <AirplanemodeActiveIcon />;
|
|
||||||
const workIcon = <WorkIcon />;
|
|
||||||
const trendingUpIcon = <TrendingUpIcon />;
|
|
||||||
const formatBoldIcon = <FormatBoldIcon />;
|
|
||||||
const businessIcon = <BusinessIcon />;
|
|
||||||
const sportsMmaIcon = <SportsMmaIcon />;
|
|
||||||
const checkIcon = <CheckIcon />;
|
|
||||||
const helpIcon = <HelpIcon />;
|
|
||||||
const settingsIcon = <SettingsIcon />;
|
|
||||||
const developerBoardIcon = <DeveloperBoardIcon />;
|
|
||||||
const emojiEventsIcon = <EmojiEventsIcon />;
|
|
||||||
const accountBoxIcon = <AccountBoxIcon />;
|
|
||||||
const publicIcon = <PublicIcon />;
|
|
||||||
const liveHelpIcon = <LiveHelpIcon />;
|
|
||||||
const chevronLeftIcon = <ChevronLeftIcon color="primary" />;
|
|
||||||
const chevronRightIcon = <ChevronRightIcon color="primary" />;
|
|
||||||
|
|
||||||
// Use constant Dividers just for performance
|
|
||||||
const divider = <Divider />;
|
|
||||||
|
|
||||||
const openedMixin = (theme: Theme): CSSObject => ({
|
const openedMixin = (theme: Theme): CSSObject => ({
|
||||||
width: theme.spacing(31),
|
width: theme.spacing(31),
|
||||||
@ -295,6 +266,7 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
return !old;
|
return !old;
|
||||||
});
|
});
|
||||||
const li_classes = useMemo(() => ({ root: classes.listitem }), [classes.listitem]);
|
const li_classes = useMemo(() => ({ root: classes.listitem }), [classes.listitem]);
|
||||||
|
const ChevronOpenClose = open ? ChevronLeftIcon : ChevronRightIcon;
|
||||||
|
|
||||||
// Explicitily useMemo() to save rerendering deep chunks of this tree.
|
// Explicitily useMemo() to save rerendering deep chunks of this tree.
|
||||||
// memo() can't be (easily) used on components like <List>, because the
|
// memo() can't be (easily) used on components like <List>, because the
|
||||||
@ -304,7 +276,9 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
{useMemo(
|
{useMemo(
|
||||||
() => (
|
() => (
|
||||||
<ListItem classes={li_classes} button onClick={toggleDrawer}>
|
<ListItem classes={li_classes} button onClick={toggleDrawer}>
|
||||||
<ListItemIcon>{!open ? chevronRightIcon : chevronLeftIcon}</ListItemIcon>
|
<ListItemIcon>
|
||||||
|
<ChevronOpenClose color={"primary"} />
|
||||||
|
</ListItemIcon>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={
|
primary={
|
||||||
<Tooltip title={hash()}>
|
<Tooltip title={hash()}>
|
||||||
@ -316,88 +290,88 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
|||||||
),
|
),
|
||||||
[li_classes, open],
|
[li_classes, open],
|
||||||
)}
|
)}
|
||||||
{divider}
|
<Divider />
|
||||||
<List>
|
<List>
|
||||||
<SidebarAccordion
|
<SidebarAccordion
|
||||||
key_="Hacking"
|
key_="Hacking"
|
||||||
page={props.page}
|
page={props.page}
|
||||||
clickPage={clickPage}
|
clickPage={clickPage}
|
||||||
flash={flash}
|
flash={flash}
|
||||||
icon={computerIcon}
|
icon={ComputerIcon}
|
||||||
sidebarOpen={open}
|
sidebarOpen={open}
|
||||||
classes={classes}
|
classes={classes}
|
||||||
items={[
|
items={[
|
||||||
{ key_: Page.Terminal, icon: lastPageIcon },
|
{ key_: Page.Terminal, icon: LastPageIcon },
|
||||||
{ key_: Page.ScriptEditor, icon: createIcon },
|
{ key_: Page.ScriptEditor, icon: CreateIcon },
|
||||||
{ key_: Page.ActiveScripts, icon: storageIcon },
|
{ key_: Page.ActiveScripts, icon: StorageIcon },
|
||||||
{ key_: Page.CreateProgram, icon: bugReportIcon, count: programCount },
|
{ key_: Page.CreateProgram, icon: BugReportIcon, count: programCount },
|
||||||
canStaneksGift && { key_: Page.StaneksGift, icon: developerBoardIcon },
|
canStaneksGift && { key_: Page.StaneksGift, icon: DeveloperBoardIcon },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
{divider}
|
<Divider />
|
||||||
<SidebarAccordion
|
<SidebarAccordion
|
||||||
key_="Character"
|
key_="Character"
|
||||||
page={props.page}
|
page={props.page}
|
||||||
clickPage={clickPage}
|
clickPage={clickPage}
|
||||||
flash={flash}
|
flash={flash}
|
||||||
icon={accountBoxIcon}
|
icon={AccountBoxIcon}
|
||||||
sidebarOpen={open}
|
sidebarOpen={open}
|
||||||
classes={classes}
|
classes={classes}
|
||||||
items={[
|
items={[
|
||||||
{ key_: Page.Stats, icon: equalizerIcon },
|
{ key_: Page.Stats, icon: EqualizerIcon },
|
||||||
canOpenFactions && {
|
canOpenFactions && {
|
||||||
key_: Page.Factions,
|
key_: Page.Factions,
|
||||||
icon: contactsIcon,
|
icon: ContactsIcon,
|
||||||
active: [Page.Factions as Page, Page.Faction].includes(props.page),
|
active: [Page.Factions as Page, Page.Faction].includes(props.page),
|
||||||
count: invitationsCount,
|
count: invitationsCount,
|
||||||
},
|
},
|
||||||
canOpenAugmentations && {
|
canOpenAugmentations && {
|
||||||
key_: Page.Augmentations,
|
key_: Page.Augmentations,
|
||||||
icon: doubleArrowIcon,
|
icon: RotatedDoubleArrowIcon,
|
||||||
count: augmentationCount,
|
count: augmentationCount,
|
||||||
},
|
},
|
||||||
{ key_: Page.Hacknet, icon: accountTreeIcon },
|
{ key_: Page.Hacknet, icon: AccountTreeIcon },
|
||||||
canOpenSleeves && { key_: Page.Sleeves, icon: peopleAltIcon },
|
canOpenSleeves && { key_: Page.Sleeves, icon: PeopleAltIcon },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
{divider}
|
<Divider />
|
||||||
<SidebarAccordion
|
<SidebarAccordion
|
||||||
key_="World"
|
key_="World"
|
||||||
page={props.page}
|
page={props.page}
|
||||||
clickPage={clickPage}
|
clickPage={clickPage}
|
||||||
flash={flash}
|
flash={flash}
|
||||||
icon={publicIcon}
|
icon={PublicIcon}
|
||||||
sidebarOpen={open}
|
sidebarOpen={open}
|
||||||
classes={classes}
|
classes={classes}
|
||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
key_: Page.City,
|
key_: Page.City,
|
||||||
icon: locationCityIcon,
|
icon: LocationCityIcon,
|
||||||
active: [Page.City as Page, Page.Grafting, Page.Location].includes(props.page),
|
active: [Page.City as Page, Page.Grafting, Page.Location].includes(props.page),
|
||||||
},
|
},
|
||||||
{ key_: Page.Travel, icon: airplanemodeActiveIcon },
|
{ key_: Page.Travel, icon: AirplanemodeActiveIcon },
|
||||||
canJob && { key_: Page.Job, icon: workIcon },
|
canJob && { key_: Page.Job, icon: WorkIcon },
|
||||||
canStockMarket && { key_: Page.StockMarket, icon: trendingUpIcon },
|
canStockMarket && { key_: Page.StockMarket, icon: TrendingUpIcon },
|
||||||
canBladeburner && { key_: Page.Bladeburner, icon: formatBoldIcon },
|
canBladeburner && { key_: Page.Bladeburner, icon: FormatBoldIcon },
|
||||||
canCorporation && { key_: Page.Corporation, icon: businessIcon },
|
canCorporation && { key_: Page.Corporation, icon: BusinessIcon },
|
||||||
canGang && { key_: Page.Gang, icon: sportsMmaIcon },
|
canGang && { key_: Page.Gang, icon: SportsMmaIcon },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
{divider}
|
<Divider />
|
||||||
<SidebarAccordion
|
<SidebarAccordion
|
||||||
key_="Help"
|
key_="Help"
|
||||||
page={props.page}
|
page={props.page}
|
||||||
clickPage={clickPage}
|
clickPage={clickPage}
|
||||||
flash={flash}
|
flash={flash}
|
||||||
icon={liveHelpIcon}
|
icon={LiveHelpIcon}
|
||||||
sidebarOpen={open}
|
sidebarOpen={open}
|
||||||
classes={classes}
|
classes={classes}
|
||||||
items={[
|
items={[
|
||||||
{ key_: Page.Milestones, icon: checkIcon },
|
{ key_: Page.Milestones, icon: CheckIcon },
|
||||||
{ key_: Page.Tutorial, icon: helpIcon },
|
{ key_: Page.Tutorial, icon: HelpIcon },
|
||||||
{ key_: Page.Achievements, icon: emojiEventsIcon },
|
{ key_: Page.Achievements, icon: EmojiEventsIcon },
|
||||||
{ key_: Page.Options, icon: settingsIcon },
|
{ key_: Page.Options, icon: SettingsIcon },
|
||||||
process.env.NODE_ENV === "development" && { key_: Page.DevMenu, icon: developerBoardIcon },
|
process.env.NODE_ENV === "development" && { key_: Page.DevMenu, icon: DeveloperBoardIcon },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</List>
|
</List>
|
||||||
|
Loading…
Reference in New Issue
Block a user