mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
perf: preload theme button and background images on app startup
This commit is contained in:
@@ -18,6 +18,15 @@ const notFoundImages = readdirSync(notFoundDir)
|
|||||||
.filter((file) => /^not-found-.*\.(jpg|jpeg|gif|png)$/i.test(file))
|
.filter((file) => /^not-found-.*\.(jpg|jpeg|gif|png)$/i.test(file))
|
||||||
.map((file) => `assets/not-found/${file}`);
|
.map((file) => `assets/not-found/${file}`);
|
||||||
|
|
||||||
|
// Scan for button images (theme-specific buttons like cross, plus, minus, help, button-fade)
|
||||||
|
const buttonsDir = join(publicDir, 'assets', 'buttons');
|
||||||
|
const buttonImages = readdirSync(buttonsDir)
|
||||||
|
.filter((file) => /\.(jpg|jpeg|gif|png)$/i.test(file))
|
||||||
|
.map((file) => `assets/buttons/${file}`);
|
||||||
|
|
||||||
|
// Theme background images
|
||||||
|
const themeBackgrounds = ['assets/background-fade.png', 'assets/background-fade-blue.png'];
|
||||||
|
|
||||||
// Generate TypeScript file with proper formatting (matches prettier config)
|
// Generate TypeScript file with proper formatting (matches prettier config)
|
||||||
const formatArray = (arr) => {
|
const formatArray = (arr) => {
|
||||||
if (arr.length === 0) return '[]';
|
if (arr.length === 0) return '[]';
|
||||||
@@ -32,6 +41,12 @@ const output = `// Auto-generated file - do not edit manually
|
|||||||
export const BANNERS = ${formatArray(banners)} as const;
|
export const BANNERS = ${formatArray(banners)} as const;
|
||||||
|
|
||||||
export const NOT_FOUND_IMAGES = ${formatArray(notFoundImages)} as const;
|
export const NOT_FOUND_IMAGES = ${formatArray(notFoundImages)} as const;
|
||||||
|
|
||||||
|
// Theme button images (cross, plus, minus, help, button-fade variants)
|
||||||
|
export const THEME_BUTTON_IMAGES = ${formatArray(buttonImages)} as const;
|
||||||
|
|
||||||
|
// Theme background pattern images
|
||||||
|
export const THEME_BACKGROUND_IMAGES = ${formatArray(themeBackgrounds)} as const;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Ensure directory exists
|
// Ensure directory exists
|
||||||
@@ -41,4 +56,6 @@ mkdirSync(generatedDir, { recursive: true });
|
|||||||
const outputPath = join(generatedDir, 'asset-manifest.ts');
|
const outputPath = join(generatedDir, 'asset-manifest.ts');
|
||||||
writeFileSync(outputPath, output, 'utf8');
|
writeFileSync(outputPath, output, 'utf8');
|
||||||
|
|
||||||
console.log(`✅ Generated asset manifest with ${banners.length} banners and ${notFoundImages.length} not-found images`);
|
console.log(
|
||||||
|
`✅ Generated asset manifest with ${banners.length} banners, ${notFoundImages.length} not-found images, ${buttonImages.length} button images, and ${themeBackgrounds.length} background images`,
|
||||||
|
);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Outlet, Route, Routes, useLocation, useParams } from 'react-router-dom'
|
|||||||
import { useAccountComment } from '@plebbit/plebbit-react-hooks';
|
import { useAccountComment } from '@plebbit/plebbit-react-hooks';
|
||||||
import { initSnow, removeSnow } from './lib/snow';
|
import { initSnow, removeSnow } from './lib/snow';
|
||||||
import { isAllView, isModView, isSubscriptionsView } from './lib/utils/view-utils';
|
import { isAllView, isModView, isSubscriptionsView } from './lib/utils/view-utils';
|
||||||
|
import { preloadThemeAssets } from './lib/utils/preload-utils';
|
||||||
import useReplyModalStore from './stores/use-reply-modal-store';
|
import useReplyModalStore from './stores/use-reply-modal-store';
|
||||||
import useCreateBoardModalStore from './stores/use-create-board-modal-store';
|
import useCreateBoardModalStore from './stores/use-create-board-modal-store';
|
||||||
import useSpecialThemeStore from './stores/use-special-theme-store';
|
import useSpecialThemeStore from './stores/use-special-theme-store';
|
||||||
@@ -31,6 +32,10 @@ import DirectoryModal from './components/directory-modal';
|
|||||||
import DisclaimerModal from './components/disclaimer-modal';
|
import DisclaimerModal from './components/disclaimer-modal';
|
||||||
import SettingsModal from './components/settings-modal';
|
import SettingsModal from './components/settings-modal';
|
||||||
|
|
||||||
|
// Preload all theme assets (buttons, backgrounds) immediately on app load
|
||||||
|
// to prevent visible loading delays when switching themes
|
||||||
|
preloadThemeAssets();
|
||||||
|
|
||||||
const BoardLayout = () => {
|
const BoardLayout = () => {
|
||||||
const { accountCommentIndex, boardIdentifier } = useParams();
|
const { accountCommentIndex, boardIdentifier } = useParams();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { THEME_BUTTON_IMAGES, THEME_BACKGROUND_IMAGES } from '../../generated/asset-manifest';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preloads an array of image URLs by creating Image objects.
|
||||||
|
* Images are loaded in the background and cached by the browser.
|
||||||
|
*/
|
||||||
|
const preloadImages = (imagePaths: readonly string[]): void => {
|
||||||
|
imagePaths.forEach((path) => {
|
||||||
|
const img = new Image();
|
||||||
|
img.src = `/${path}`;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preloads all theme-related assets (buttons, backgrounds) on app startup.
|
||||||
|
* This prevents visible loading delays when switching themes.
|
||||||
|
*/
|
||||||
|
export const preloadThemeAssets = (): void => {
|
||||||
|
preloadImages(THEME_BUTTON_IMAGES);
|
||||||
|
preloadImages(THEME_BACKGROUND_IMAGES);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user