UI: Added the ability to change the font size (#1703)

This commit is contained in:
G4mingJon4s 2024-11-10 01:50:18 +01:00 committed by GitHub
parent 90cb8a9551
commit d6874d68aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 99 additions and 45 deletions

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [IStyleSettings](./bitburner.istylesettings.md) &gt; [fontSize](./bitburner.istylesettings.fontsize.md)
## IStyleSettings.fontSize property
**Signature:**
```typescript
fontSize: number;
```

@ -17,5 +17,7 @@ interface IStyleSettings
| Property | Modifiers | Type | Description | | Property | Modifiers | Type | Description |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| [fontFamily](./bitburner.istylesettings.fontfamily.md) | | string | | | [fontFamily](./bitburner.istylesettings.fontfamily.md) | | string | |
| [fontSize](./bitburner.istylesettings.fontsize.md) | | number | |
| [lineHeight](./bitburner.istylesettings.lineheight.md) | | number | | | [lineHeight](./bitburner.istylesettings.lineheight.md) | | number | |
| [tailFontSize](./bitburner.istylesettings.tailfontsize.md) | | number | |

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [IStyleSettings](./bitburner.istylesettings.md) &gt; [tailFontSize](./bitburner.istylesettings.tailfontsize.md)
## IStyleSettings.tailFontSize property
**Signature:**
```typescript
tailFontSize: number;
```

@ -9562,6 +9562,8 @@ interface UserInterfaceTheme {
*/ */
interface IStyleSettings { interface IStyleSettings {
fontFamily: string; fontFamily: string;
fontSize: number;
tailFontSize: number;
lineHeight: number; lineHeight: number;
} }

@ -2,5 +2,7 @@ import { IStyleSettings } from "@nsdefs";
export const defaultStyles: IStyleSettings = { export const defaultStyles: IStyleSettings = {
lineHeight: 1.5, lineHeight: 1.5,
fontSize: 14,
tailFontSize: 16,
fontFamily: `JetBrainsMono, "Courier New", monospace`, fontFamily: `JetBrainsMono, "Courier New", monospace`,
}; };

@ -20,18 +20,29 @@ interface IProps {
onClose: () => void; onClose: () => void;
} }
interface FontFamilyProps { interface StyleFieldProps<T extends keyof React.CSSProperties> {
value: React.CSSProperties["fontFamily"]; name: string;
onChange: (newValue: React.CSSProperties["fontFamily"], error?: string) => void; type: "string" | "number";
value: React.CSSProperties[T];
onChange: (newValue: React.CSSProperties[T], error?: string) => void;
} }
function FontFamilyField({ value, onChange }: FontFamilyProps): React.ReactElement { function StyleField<T extends keyof React.CSSProperties>({
value,
onChange,
name,
type,
}: StyleFieldProps<T>): React.ReactElement {
const [errorText, setErrorText] = useState<string | undefined>(); const [errorText, setErrorText] = useState<string | undefined>();
const [fontFamily, setFontFamily] = useState<React.CSSProperties["fontFamily"]>(value); const [fieldValue, setFieldValue] = useState<React.CSSProperties[T]>(value);
const update = (newValue: React.CSSProperties["fontFamily"]) => { const update = (newValue: React.CSSProperties[T]) => {
const errorText = newValue ? "" : "Must have a value"; const errorText = !newValue
setFontFamily(newValue); ? "Must have a value"
: type === "number" && Number.isNaN(Number(newValue))
? "Must be a number"
: "";
setFieldValue(newValue);
setErrorText(errorText); setErrorText(errorText);
onChange(newValue, errorText); onChange(newValue, errorText);
}; };
@ -39,45 +50,16 @@ function FontFamilyField({ value, onChange }: FontFamilyProps): React.ReactEleme
return ( return (
<TextField <TextField
sx={{ my: 1 }} sx={{ my: 1 }}
label={"Font-Family"} label={name}
error={!!errorText} error={!!errorText}
value={fontFamily} value={fieldValue}
helperText={errorText} helperText={errorText}
onChange={(event) => update(event.target.value)} onChange={(event) => update(event.target.value as React.CSSProperties[T])}
fullWidth fullWidth
/> />
); );
} }
interface LineHeightProps {
value: React.CSSProperties["lineHeight"];
onChange: (newValue: React.CSSProperties["lineHeight"], error?: string) => void;
}
function LineHeightField({ value, onChange }: LineHeightProps): React.ReactElement {
const [errorText, setErrorText] = useState<string | undefined>();
const [lineHeight, setLineHeight] = useState<React.CSSProperties["lineHeight"]>(value);
const update = (newValue: React.CSSProperties["lineHeight"]) => {
const errorText = !newValue ? "Must have a value" : isNaN(Number(newValue)) ? "Must be a number" : "";
setLineHeight(newValue);
setErrorText(errorText);
onChange(newValue, errorText);
};
return (
<TextField
sx={{ my: 1 }}
label={"Line Height"}
error={!!errorText}
value={lineHeight}
helperText={errorText}
onChange={(event) => update(event.target.value)}
/>
);
}
export function StyleEditorModal(props: IProps): React.ReactElement { export function StyleEditorModal(props: IProps): React.ReactElement {
const [error, setError] = useState<string | undefined>(); const [error, setError] = useState<string | undefined>();
const [customStyle, setCustomStyle] = useState<IStyleSettings>({ const [customStyle, setCustomStyle] = useState<IStyleSettings>({
@ -114,12 +96,37 @@ export function StyleEditorModal(props: IProps): React.ReactElement {
<strong>NOT recommended</strong>. <strong>NOT recommended</strong>.
</Typography> </Typography>
<Paper sx={{ p: 2, my: 2 }}> <Paper sx={{ p: 2, my: 2 }}>
<FontFamilyField <StyleField<"fontFamily">
name="Font Family"
type="string"
value={customStyle.fontFamily} value={customStyle.fontFamily}
onChange={(value, error) => update({ ...customStyle, fontFamily: value ?? "" }, error)} onChange={(value, error) => update({ ...customStyle, fontFamily: value ?? "" }, error)}
/> />
<br /> <br />
<LineHeightField <StyleField<"fontSize">
name="Font Size"
type="number"
value={customStyle.fontSize * (16 / 14)}
onChange={(value, error) =>
// MUI has an internal font size of 14, which then gets translated to 16px inside the typography.
// The font size that "overwrites" the tail font size is directly added by the styling. This value is in pixels.
// The inputs need to match, as two differently scaling inputs are hard to work with.
// To the user, both inputs are in pixels. The value MUI uses to set the font size needs to have this weird
// scaling of 16 to 14, so it will correctly scale back to 16px.
update({ ...customStyle, fontSize: Math.max(5, (Number(value) ?? 8) * (14 / 16)) }, error)
}
/>
<br />
<StyleField<"fontSize">
name="Tail Font Size"
type="number"
value={customStyle.tailFontSize}
onChange={(value, error) => update({ ...customStyle, tailFontSize: Number(value) ?? 0 }, error)}
/>
<br />
<StyleField<"lineHeight">
name="Line Height"
type="number"
value={customStyle.lineHeight} value={customStyle.lineHeight}
onChange={(value, error) => update({ ...customStyle, lineHeight: Number(value) ?? 0 }, error)} onChange={(value, error) => update({ ...customStyle, lineHeight: Number(value) ?? 0 }, error)}
/> />

@ -114,6 +114,7 @@ export function refreshTheme(): void {
}, },
typography: { typography: {
fontFamily: Settings.styles.fontFamily, fontFamily: Settings.styles.fontFamily,
fontSize: Settings.styles.fontSize,
button: { button: {
textTransform: "none", textTransform: "none",
}, },

@ -60,6 +60,7 @@ const lineClass = (classes: Record<string, string>, s: string): string => {
type ANSIITypographyProps = { type ANSIITypographyProps = {
text: unknown; text: unknown;
color: "primary" | "error" | "success" | "info" | "warn"; color: "primary" | "error" | "success" | "info" | "warn";
styles?: React.CSSProperties;
}; };
export const ANSIITypography = React.memo(function ANSIITypography(props: ANSIITypographyProps): React.ReactElement { export const ANSIITypography = React.memo(function ANSIITypography(props: ANSIITypographyProps): React.ReactElement {
@ -94,9 +95,14 @@ export const ANSIITypography = React.memo(function ANSIITypography(props: ANSIIT
parts.push({ code: null, text: text }); parts.push({ code: null, text: text });
} }
return ( return (
<Typography component={"div"} classes={{ root: lineClass(classes, props.color) }} paragraph={false}> <Typography
component={"div"}
classes={{ root: lineClass(classes, props.color) }}
paragraph={false}
sx={{ ...(props.styles ?? {}) }}
>
{parts.map((part, i) => ( {parts.map((part, i) => (
<span key={i} style={ansiCodeStyle(part.code)}> <span key={i} style={{ ...ansiCodeStyle(part.code), ...(props.styles ?? {}) }}>
{part.text} {part.text}
</span> </span>
))} ))}

@ -407,7 +407,19 @@ function LogWindow({ hidden, script, onClose }: LogWindowProps): React.ReactElem
<div style={{ display: "flex", flexDirection: "column" }}> <div style={{ display: "flex", flexDirection: "column" }}>
{script.logs.map( {script.logs.map(
(line: React.ReactNode, i: number): React.ReactNode => (line: React.ReactNode, i: number): React.ReactNode =>
typeof line !== "string" ? line : <ANSIITypography key={i} text={line} color={lineColor(line)} />, typeof line !== "string" ? (
line
) : (
<ANSIITypography
key={i}
text={line}
color={lineColor(line)}
styles={{
display: "inline-block",
fontSize: Settings.styles.tailFontSize,
}}
/>
),
)} )}
</div> </div>
</Paper> </Paper>