Files
jrshikoku/lib/preloadStartupIconFonts.ts
harukin-expo-dev-env 19b280a467 feat: implement startup icon font preloading and improve loading checks in AppContainer
refactor: simplify CarouselTypeChanger by removing redundant onPressIn handlers
fix: enhance MenuLED memoization for better performance
refactor: optimize EachData component with useMemo for derived values
fix: improve error handling in TrainPosition data fetching
refactor: streamline AddressText component's API call with abort controller
refactor: update Menu component to manage selected station state more effectively
2026-09-13 15:09:37 +09:00

67 lines
2.0 KiB
TypeScript

import {
AntDesign,
FontAwesome,
FontAwesome5,
Foundation,
Ionicons,
MaterialCommunityIcons,
} from "@expo/vector-icons";
import LegacyIonicons from "react-native-vector-icons/Ionicons";
import { telemetry } from "./observability/telemetry";
const startupIconFontTelemetry = telemetry.scope("startup.iconFonts");
type IconFontLoader = {
name: string;
load: () => Promise<void>;
};
const startupIconFontLoaders: IconFontLoader[] = [
{ name: "expo.ant-design", load: AntDesign.loadFont },
{ name: "expo.font-awesome", load: FontAwesome.loadFont },
{ name: "expo.font-awesome-5", load: FontAwesome5.loadFont },
{ name: "expo.foundation", load: Foundation.loadFont },
{ name: "expo.ionicons", load: Ionicons.loadFont },
{
name: "expo.material-community-icons",
load: MaterialCommunityIcons.loadFont,
},
{ name: "rnvi.ionicons", load: LegacyIonicons.loadFont },
];
let startupIconFontsPromise: Promise<void> | null = null;
/**
* Loads the icon families used by the first visible menu before navigation is
* mounted. Each family has its own lazy loader, so relying on the first icon
* render makes icons appear one family at a time during startup.
*/
export function preloadStartupIconFonts(): Promise<void> {
if (startupIconFontsPromise) return startupIconFontsPromise;
const startedAt = Date.now();
startupIconFontsPromise = Promise.all(
startupIconFontLoaders.map(({ name, load }) =>
Promise.resolve()
.then(() => load())
.catch(() => {
// A missing optional icon font must not prevent the app from
// starting. The icon component keeps its existing fallback path.
startupIconFontTelemetry.warning("icon font preload failed", {
font: name,
});
}),
),
).then(() => {
startupIconFontTelemetry.breadcrumb({
message: "startup icon font preload completed",
data: {
durationMs: Date.now() - startedAt,
fontCount: startupIconFontLoaders.length,
},
});
});
return startupIconFontsPromise;
}