feat: Slightly update fonts look and remove Build Type from Settings

refactor: Improve font card UI

- Use a more modern card style - Use flexbox for better layout - Add
padding and rounded corners - Replace the preview text with a Paragraph
element - Remove Build Type from about page
This commit is contained in:
kmmiio99o 2025-11-08 15:46:28 +01:00
parent c9223d44f3
commit 771d244a4a
3 changed files with 93 additions and 134 deletions

View file

@ -77,7 +77,7 @@ const config = {
constModules: {
globals: {
"bunny-build-info": {
version: `"1.1.10-1"`,
version: `"1.1.10-2"`,
},
},
},

View file

@ -8,7 +8,13 @@ import { BundleUpdaterManager } from "@lib/api/native/modules";
import { lazyDestructure } from "@lib/utils/lazy";
import { findByProps } from "@metro";
import { NavigationNative, tokens } from "@metro/common";
import { Button, Card, IconButton, Stack, Text } from "@metro/common/components";
import {
Button,
Card,
IconButton,
Stack,
Text,
} from "@metro/common/components";
import * as Skia from "@shopify/react-native-skia";
import { TextStyleSheet } from "@ui/styles";
import { useMemo } from "react";
@ -18,101 +24,100 @@ import FontEditor from "./FontEditor";
const { useToken } = lazyDestructure(() => findByProps("useToken"));
function FontPreview({ font }: { font: FontDefinition; }) {
const TEXT_NORMAL = useToken(tokens.colors.TEXT_NORMAL);
const { fontFamily: fontFamilyList, fontSize } = TextStyleSheet["text-md/medium"];
const fontFamily = fontFamilyList!.split(/,/g)[0];
function FontPreview({ font }: { font: FontDefinition }) {
const TEXT_NORMAL = useToken(tokens.colors.TEXT_NORMAL);
const { fontFamily: fontFamilyList, fontSize } =
TextStyleSheet["text-md/medium"];
const fontFamily = fontFamilyList!.split(/,/g)[0];
const typeface = Skia.useFont(font.main[fontFamily])?.getTypeface();
const typeface = Skia.useFont(font.main[fontFamily])?.getTypeface();
const paragraph = useMemo(() => {
if (!typeface) return null;
const paragraph = useMemo(() => {
if (!typeface) return null;
const fMgr = SkiaApi.TypefaceFontProvider.Make();
fMgr.registerFont(typeface, fontFamily);
const fMgr = SkiaApi.TypefaceFontProvider.Make();
fMgr.registerFont(typeface, fontFamily);
return SkiaApi.ParagraphBuilder.Make({}, fMgr)
.pushStyle({
color: SkiaApi.Color(TEXT_NORMAL),
fontFamilies: [fontFamily],
fontSize,
})
.addText(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
)
.pop()
.build();
}, [typeface]);
return SkiaApi.ParagraphBuilder.Make({}, fMgr)
.pushStyle({
color: SkiaApi.Color(TEXT_NORMAL),
fontFamilies: [fontFamily],
fontSize,
})
.addText("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
.pop()
.build();
}, [typeface]);
return (
// This does not work, actually :woeis:
<View style={{ height: 64 }}>
{typeface
? <Skia.Canvas style={{ height: 64 }}>
<Skia.Paragraph paragraph={paragraph} x={0} y={0} width={300} />
</Skia.Canvas>
: <View style={{ justifyContent: "center", alignItems: "center" }}>
<Text color="text-muted" variant="heading-lg/semibold">
Loading...
</Text>
</View>}
return (
// This does not work, actually :woeis:
<View style={{ height: 64 }}>
{typeface ? (
<Skia.Canvas style={{ height: 64 }}>
<Skia.Paragraph paragraph={paragraph} x={0} y={0} width={300} />
</Skia.Canvas>
) : (
<View style={{ justifyContent: "center", alignItems: "center" }}>
<Text color="text-muted" variant="heading-lg/semibold">
Loading...
</Text>
</View>
);
)}
</View>
);
}
export default function FontCard({ item: font }: CardWrapper<FontDefinition>) {
useProxy(fonts);
useProxy(fonts);
const navigation = NavigationNative.useNavigation();
const selected = fonts.__selected === font.name;
const navigation = NavigationNative.useNavigation();
const selected = fonts.__selected === font.name;
return (
<Card>
<Stack spacing={16}>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<View>
<Text variant="heading-lg/semibold">
{font.name}
</Text>
{/* TODO: Text wrapping doesn't work well */}
{/* <Text color="text-muted" variant="text-sm/semibold">
{font.description}
</Text> */}
</View>
<View style={{ marginLeft: "auto" }}>
<Stack spacing={12} direction="horizontal">
<IconButton
onPress={() => {
navigation.push("BUNNY_CUSTOM_PAGE", {
title: "Edit Font",
render: () => <FontEditor name={font.name} />
});
}}
size="sm"
variant="secondary"
disabled={selected}
icon={findAssetId("WrenchIcon")}
/>
<Button
size="sm"
variant={selected ? "secondary" : "primary"}
text={selected ? "Unapply" : "Apply"}
onPress={async () => {
await selectFont(selected ? null : font.name);
showConfirmationAlert({
title: Strings.HOLD_UP,
content: "Reload Discord to apply changes?",
confirmText: Strings.RELOAD,
cancelText: Strings.CANCEL,
confirmColor: "red",
onConfirm: BundleUpdaterManager.reload
});
}}
/>
</Stack>
</View>
</View>
<FontPreview font={font} />
</Stack>
</Card>
);
return (
<Card style={{ padding: 18, borderRadius: 16, backgroundColor: "#23272a" }}>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<View style={{ flex: 1, minWidth: 0 }}>
<Text variant="heading-lg/bold" style={{ marginBottom: 2 }}>
{font.name}
</Text>
<FontPreview font={font} />
</View>
<View
style={{ marginLeft: 16, flexDirection: "row", alignItems: "center" }}
>
<Button
size="sm"
variant={selected ? "secondary" : "primary"}
text={selected ? "Unapply" : "Apply"}
style={{ minWidth: 80, marginRight: 8 }}
onPress={async () => {
await selectFont(selected ? null : font.name);
showConfirmationAlert({
title: Strings.HOLD_UP,
content: "Reload Discord to apply changes?",
confirmText: Strings.RELOAD,
cancelText: Strings.CANCEL,
confirmColor: "red",
onConfirm: BundleUpdaterManager.reload,
});
}}
/>
<IconButton
onPress={() => {
navigation.push("BUNNY_CUSTOM_PAGE", {
title: "Edit Font",
render: () => <FontEditor name={font.name} />,
});
}}
size="sm"
variant="secondary"
disabled={selected}
icon={findAssetId("WrenchIcon")}
/>
</View>
</View>
</Card>
);
}

View file

@ -13,47 +13,6 @@ export default function About() {
useProxy(settings);
useProxy(loaderConfig);
function getBuildType() {
// If running in React Native dev mode, treat as development
if (__DEV__) return "Development";
try {
// If a custom URL is enabled, inspect it
if (loaderConfig?.customLoadUrl?.enabled) {
const url = loaderConfig.customLoadUrl.url ?? "";
const u = new URL(url);
const host = u.hostname;
// Localhost / local IP -> dev server (bun run serve)
if (
host === "localhost" ||
host === "127.0.0.1" ||
host === "0.0.0.0" ||
host.startsWith("192.") ||
host.startsWith("10.") ||
host.startsWith("172.")
)
return "Development";
// If the URL points to GitHub releases/raw, treat as Release
if (
url.includes("github.com") ||
url.includes("raw.githubusercontent.com") ||
url.includes("/releases/")
)
return "Release";
// Custom remote URL (not recognized as local or GitHub)
return "Custom";
}
} catch (e) {
// If URL parsing fails, fall back below
}
// Default: when not using a custom URL the loader fetches from GitHub releases
return "Release";
}
const coreVersions = [
{
label: Strings.SHIGGYCORD,
@ -181,11 +140,6 @@ export default function About() {
}
icon={<TableRow.Icon source={findAssetId("ScreenIcon")} />}
/>
<TableRow
label="Build Type"
trailing={<TableRow.TrailingText text={getBuildType()} />}
icon={<TableRow.Icon source={findAssetId("HammerIcon")} />}
/>
</TableRowGroup>
</Stack>
</ScrollView>