From cc43a1fb4ef69b79abc342a93aee24b106da2485 Mon Sep 17 00:00:00 2001 From: AUDO Date: Wed, 12 Aug 2026 23:27:31 +0800 Subject: [PATCH 1/2] perf(environments): still posters for the built-in picker thumbs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The picker pointed at the same asset as the stage, so opening Appearance handed the compositor three animated GIFs — ~32MB and ~480 frames between them — to play inside 40px boxes. All three loaded whether or not one was selected, and stayed resident for the rest of the session. Built-ins now carry a committed 192x112 poster that the picker uses instead. The stage is untouched, which makes it the only thing that ever loads a GIF, and only for the environment actually in use. The posters are generated by the existing `npm run thumbs` path rather than a new dependency: no GIF decoder ships with the project and the renderer already has one, the same argument generateBundledThumbnails.js makes for avatar portraits. That also puts the image-thumbnail helper in place for the custom environment folder, which needs the same thing at runtime. Posters are globbed rather than imported by name, following config/avatars.js. A named import would deadlock the generator, which imports this module: adding an environment would fail to resolve the poster that the run was supposed to create. `loading="lazy"` comes along on the built-in row for parity with the Custom grid, though it does nothing for elements already in the viewport. The custom/ embargo test asserted that no `import.meta.glob` survived a production build, which was a proxy for "the custom glob is gone" that only held while environments.js had exactly one glob. It now asserts on the custom/ path itself, and that the thumbs glob is kept. Refs #22 Co-Authored-By: Claude Opus 5 --- CONTRIBUTING.md | 10 +- avatar/electron/main.cjs | 31 +++++- avatar/electron/preload.cjs | 4 +- avatar/scripts/custom-envs.test.mjs | 7 +- .../src/assets/environments/thumbs/bloom.png | Bin 0 -> 42730 bytes .../src/assets/environments/thumbs/code.png | Bin 0 -> 56325 bytes .../src/assets/environments/thumbs/stars.png | Bin 0 -> 42593 bytes avatar/src/components/panels/PalettePanel.jsx | 3 +- avatar/src/config/environments.js | 25 ++++- avatar/src/lib/environmentThumbnails.js | 104 ++++++++++++++++++ avatar/src/lib/generateBundledThumbnails.js | 64 +++++++++-- avatar/vite.config.js | 10 +- docs/avatars.md | 2 +- docs/development/project-layout.md | 4 +- docs/environments.md | 2 + 15 files changed, 232 insertions(+), 34 deletions(-) create mode 100644 avatar/src/assets/environments/thumbs/bloom.png create mode 100644 avatar/src/assets/environments/thumbs/code.png create mode 100644 avatar/src/assets/environments/thumbs/stars.png create mode 100644 avatar/src/lib/environmentThumbnails.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e226182..1063c41 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -54,13 +54,15 @@ A `src/` module is only testable if nothing in its import graph reaches a Vite-r Anything needing React, the DOM, or `URL.createObjectURL` has **no** automated coverage today and is verified by hand (`npm run dev:desktop`) — say so in the PR rather than leaving it implied. -### Bundled avatar thumbnails +### Bundled picker thumbnails -The Appearance picker draws avatars as static images, not live VRM previews. Portraits for the bundled avatars are **committed** under `avatar/src/assets/avatars/thumbs/` (`avatar1.png` … `avatar3.png`). +The Appearance picker draws avatars as static images, not live VRM previews, and environments as still posters, not the animated stage GIFs. Both are **committed**: portraits under `avatar/src/assets/avatars/thumbs/` (`avatar1.png` … `avatar3.png`), environment posters under `avatar/src/assets/environments/thumbs/` (one PNG per id in `src/config/environments.js`). -If you change a bundled `.vrm`, or add or remove an entry in `src/config/avatars.js`, run `npm run thumbs` and commit the result — the picker will otherwise show a stale or missing portrait. The command opens Electron briefly, renders each avatar with the same renderer the app uses at runtime, writes the PNGs into the source tree, and exits. It is dev-only: the write channel is registered only for that run, so a packaged app cannot write into the source tree. +Run `npm run thumbs` and commit the result if you change a bundled `.vrm` or `.gif`, or add or remove an entry in `src/config/avatars.js` or `src/config/environments.js` — the picker will otherwise show a stale or missing thumbnail. The command opens Electron briefly, renders both sets with the same code the app uses at runtime, writes the PNGs into the source tree, and exits. It is dev-only: the write channel is registered only for that run, so a packaged app cannot write into the source tree. -Thumbnails for a user's own custom folder are **not** committed — they are rendered on demand and cached under Electron `userData/thumbnails/`. +Both sets are globbed rather than imported by name, so a missing file degrades (the avatar picker renders one on the spot; the environment picker falls back to the GIF) instead of breaking the build. That matters because the generator itself imports those config modules — a named import for a poster that does not exist yet would stop the run that was meant to create it. + +Thumbnails for a user's own custom folders are **not** committed — they are generated on demand and cached under Electron `userData/thumbnails/`. --- diff --git a/avatar/electron/main.cjs b/avatar/electron/main.cjs index dc62087..cb715c8 100644 --- a/avatar/electron/main.cjs +++ b/avatar/electron/main.cjs @@ -615,16 +615,35 @@ ipcMain.handle('thumbnail:get', (event, id) => { // Dev-only asset generation (npm run thumbs). Registered only for that run, so // a packaged app has no channel that can write into the source tree at all. if (!app.isPackaged && process.env.AVATAR_GEN_THUMBS) { - ipcMain.handle('thumbnail:dev-write', (event, fileName, png) => { + // Both the directory and the shape of the name are fixed here rather than + // taken from the renderer, so this channel can only ever write generated + // artwork into the two directories that hold it. + const DEV_THUMB_TARGETS = { + avatars: { dir: '../src/assets/avatars/thumbs', pattern: /^avatar\d+\.png$/ }, + environments: { + dir: '../src/assets/environments/thumbs', + // Environment ids are author-defined, so this bounds the shape instead of + // listing them: no separators and no dots means no path to escape into. + pattern: /^[a-z][a-z0-9-]{0,31}\.png$/, + }, + }; + + ipcMain.handle('thumbnail:dev-write', (event, kind, fileName, png) => { assertTrustedLibrarySender(event); - if (!/^avatar\d+\.png$/.test(String(fileName))) { + // hasOwn, not a bare lookup: `__proto__` and friends would otherwise sail + // past this guard with something truthy off Object.prototype. + if (!Object.hasOwn(DEV_THUMB_TARGETS, String(kind))) { + throw new Error(`Refusing to write thumbnails for unknown kind: ${kind}`); + } + const target = DEV_THUMB_TARGETS[String(kind)]; + if (!target.pattern.test(String(fileName))) { throw new Error(`Refusing to write unexpected thumbnail name: ${fileName}`); } - const dir = path.join(__dirname, '../src/assets/avatars/thumbs'); + const dir = path.join(__dirname, target.dir); fs.mkdirSync(dir, { recursive: true }); - const target = path.join(dir, fileName); - fs.writeFileSync(target, Buffer.from(png)); - return target; + const filePath = path.join(dir, fileName); + fs.writeFileSync(filePath, Buffer.from(png)); + return filePath; }); } diff --git a/avatar/electron/preload.cjs b/avatar/electron/preload.cjs index c2ba67d..ff82efe 100644 --- a/avatar/electron/preload.cjs +++ b/avatar/electron/preload.cjs @@ -37,8 +37,8 @@ contextBridge.exposeInMainWorld('voxDesktop', { getThumbnail: (id) => ipcRenderer.invoke('thumbnail:get', id), putThumbnail: (id, png) => ipcRenderer.invoke('thumbnail:put', id, png), // Only answered during `npm run thumbs`; rejects in any normal run. - devWriteThumbnail: (fileName, png) => - ipcRenderer.invoke('thumbnail:dev-write', fileName, png), + devWriteThumbnail: (kind, fileName, png) => + ipcRenderer.invoke('thumbnail:dev-write', kind, fileName, png), }); contextBridge.exposeInMainWorld('voxVroidHub', { diff --git a/avatar/scripts/custom-envs.test.mjs b/avatar/scripts/custom-envs.test.mjs index 536b818..1d54a88 100644 --- a/avatar/scripts/custom-envs.test.mjs +++ b/avatar/scripts/custom-envs.test.mjs @@ -51,7 +51,12 @@ test('a production build strips the custom/ glob', (context) => { assert.ok(result, 'expected the plugin to rewrite environments.js'); assert.match(result.code, /const customModules = \{\};/); - assert.doesNotMatch(result.code, /import\.meta\.glob/); + // What must not survive is any glob that can reach into custom/. Asserting + // on the path rather than on `import.meta.glob` in general: environments.js + // also globs the committed thumbs/ posters, which are build assets that are + // meant to ship, and that glob has to stay. + assert.doesNotMatch(result.code, /assets\/environments\/custom/); + assert.match(result.code, /import\.meta\.glob\('\.\.\/assets\/environments\/thumbs/); }); test('the dev server keeps the custom/ glob', (context) => { diff --git a/avatar/src/assets/environments/thumbs/bloom.png b/avatar/src/assets/environments/thumbs/bloom.png new file mode 100644 index 0000000000000000000000000000000000000000..dedb4b8c1877f4509ca861c6db967828d197ba7c GIT binary patch literal 42730 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

%r?YMrsbS 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 Z{~sk(kaV;+D^36a002ovPDHLkV1hI`g2ey; literal 0 HcmV?d00001 diff --git a/avatar/src/components/panels/PalettePanel.jsx b/avatar/src/components/panels/PalettePanel.jsx index 7fd3885..fbcf432 100644 --- a/avatar/src/components/panels/PalettePanel.jsx +++ b/avatar/src/components/panels/PalettePanel.jsx @@ -136,7 +136,8 @@ export function PalettePanel({ onClick={() => setSelectedBg({ type: 'env', id: env.id })} title={env.label} > - {env.label} + {/* Poster, not the GIF: the stage owns the animation. */} + {env.label} {env.label} ))} diff --git a/avatar/src/config/environments.js b/avatar/src/config/environments.js index 25325ef..a05f9a5 100644 --- a/avatar/src/config/environments.js +++ b/avatar/src/config/environments.js @@ -2,6 +2,25 @@ import starsGif from '../assets/environments/stars.gif'; import codeGif from '../assets/environments/code.gif'; import bloomGif from '../assets/environments/bloom.gif'; +// Still posters generated ahead of time (see npm run thumbs), so the picker +// never plays a full stage GIF inside a 40px box. Globbed rather than imported +// by name because the generator imports this module: a named import for a +// poster that does not exist yet would fail to resolve, and the run that would +// have produced it could never start. A missing file is not an error — the +// picker falls back to the animated source. +const thumbnailModules = import.meta.glob('../assets/environments/thumbs/*.png', { + eager: true, + import: 'default', +}); + +/** @param {string} id */ +function bundledEnvThumb(id) { + const match = Object.entries(thumbnailModules).find(([modulePath]) => + modulePath.endsWith(`/${id}.png`), + ); + return match ? /** @type {string} */ (match[1]) : null; +} + /** @typedef {{ strong: string, soft: string, highlight: string }} HoloGlow */ /** Default lavender fade used for Color mode. */ @@ -23,7 +42,8 @@ const customGlow = { * @typedef {Object} EnvironmentEntry * @property {string} id * @property {string} label - * @property {string} src Bundled GIF URL (Vite-resolved) + * @property {string} src Bundled GIF URL (Vite-resolved), used by the stage + * @property {string | null} [thumb] Still poster for the picker; falls back to `src` * @property {HoloGlow} glow * @property {boolean} [custom] */ @@ -34,6 +54,7 @@ export const environments = [ id: 'stars', label: 'Stars', src: starsGif, + thumb: bundledEnvThumb('stars'), glow: { strong: 'rgba(130, 150, 230, 0.58)', soft: 'rgba(85, 105, 190, 0.26)', @@ -44,6 +65,7 @@ export const environments = [ id: 'code', label: 'Code', src: codeGif, + thumb: bundledEnvThumb('code'), glow: { strong: 'rgba(100, 220, 160, 0.45)', soft: 'rgba(40, 120, 80, 0.22)', @@ -54,6 +76,7 @@ export const environments = [ id: 'bloom', label: 'Bloom', src: bloomGif, + thumb: bundledEnvThumb('bloom'), glow: { strong: 'rgba(255, 190, 230, 0.58)', soft: 'rgba(210, 160, 245, 0.28)', diff --git a/avatar/src/lib/environmentThumbnails.js b/avatar/src/lib/environmentThumbnails.js new file mode 100644 index 0000000..00c57a2 --- /dev/null +++ b/avatar/src/lib/environmentThumbnails.js @@ -0,0 +1,104 @@ +/** + * Still posters for environment pickers. + * + * The picker used to point at the same asset as the stage, so opening + * Appearance handed the compositor three full animated GIFs — ~32MB and ~480 + * frames between them — to play inside 40px boxes. A poster is what the picker + * actually needs; the stage keeps the animation. + * + * Nothing here touches three.js: unlike an avatar portrait, an environment + * thumbnail is a decode and a downscale, both of which run off the main thread. + */ + +// Wider than tall because the picker lays these out in a 3-up grid at 40px +// high, and 2x covers HiDPI. `object-fit: cover` still does the final crop, so +// this only has to be big enough, not exactly the displayed shape. +const THUMB_W = 192; +const THUMB_H = 112; + +/** + * GIFs commonly fade in, and frame 0 of a fade is a black rectangle that tells + * the user nothing about the environment. Sampling a little way in costs one + * extra decoded frame and avoids that. + */ +const PREFERRED_FRAME = 8; + +/** + * @param {Blob} source + * @returns {Promise<{ frame: ImageBitmap | VideoFrame, close: () => void }>} + */ +async function decodeStill(source, frameIndex) { + // ImageDecoder is the only way to ask a GIF for a specific frame; + // createImageBitmap always hands back frame 0. + if (source.type === 'image/gif' && typeof ImageDecoder === 'function') { + const decoder = new ImageDecoder({ data: await source.arrayBuffer(), type: source.type }); + try { + await decoder.tracks.ready; + // frameCount climbs as the track is parsed and reads 0 before it starts, + // so clamping against it too early would silently ask for frame 0 — the + // fade-in frame this is here to skip. The whole file is already in hand, + // so waiting for the true count costs nothing. + await decoder.completed; + const available = decoder.tracks.selectedTrack?.frameCount ?? 0; + const wanted = available > 0 ? Math.min(frameIndex, available - 1) : frameIndex; + const { image } = await decoder.decode({ frameIndex: wanted }); + return { frame: image, close: () => image.close() }; + } finally { + decoder.close(); + } + } + + // Stills, and the fallback if ImageDecoder is unavailable. Resizing at decode + // time is what keeps a 6000x4000 photo dropped into a custom folder from ever + // materialising at full size. + let bitmap = await createImageBitmap(source, { + resizeHeight: THUMB_H, + resizeQuality: 'high', + }); + + // Height alone leaves anything narrower than the box short on width, and the + // cover scale below would then stretch a source that had pixels to spare. + // Which axis needs constraining is only knowable once one decode has run. + if (bitmap.width < THUMB_W) { + const byWidth = await createImageBitmap(source, { + resizeWidth: THUMB_W, + resizeQuality: 'high', + }); + bitmap.close(); + bitmap = byWidth; + } + + return { frame: bitmap, close: () => bitmap.close() }; +} + +/** + * Render a still poster for an environment image. + * + * @param {Blob} source A `.gif` / `.png` / `.jpg` blob. + * @param {{ frameIndex?: number }} [options] + * @returns {Promise} A PNG sized {@link THUMB_W}x{@link THUMB_H}. + */ +export async function renderEnvironmentThumbnailBlob(source, options = {}) { + const { frame, close } = await decodeStill(source, options.frameIndex ?? PREFERRED_FRAME); + + try { + const width = frame.displayWidth ?? frame.width; + const height = frame.displayHeight ?? frame.height; + if (!width || !height) throw new Error('Environment image has no dimensions.'); + + const canvas = new OffscreenCanvas(THUMB_W, THUMB_H); + const ctx = canvas.getContext('2d'); + if (!ctx) throw new Error('Could not get a 2d context for the thumbnail.'); + + // `cover`: fill the box on both axes and centre the overflow, matching how + // the picker's CSS crops these. + const scale = Math.max(THUMB_W / width, THUMB_H / height); + const drawW = width * scale; + const drawH = height * scale; + ctx.drawImage(frame, (THUMB_W - drawW) / 2, (THUMB_H - drawH) / 2, drawW, drawH); + + return await canvas.convertToBlob({ type: 'image/png' }); + } finally { + close(); + } +} diff --git a/avatar/src/lib/generateBundledThumbnails.js b/avatar/src/lib/generateBundledThumbnails.js index ad4ddcc..03a24e4 100644 --- a/avatar/src/lib/generateBundledThumbnails.js +++ b/avatar/src/lib/generateBundledThumbnails.js @@ -1,11 +1,12 @@ /** - * Dev-only: renders a portrait for each bundled avatar and writes it into - * `src/assets/avatars/thumbs/`, to be committed. + * Dev-only: renders the picker artwork for each bundled avatar and environment + * and writes it into `src/assets/avatars/thumbs/` and + * `src/assets/environments/thumbs/`, to be committed. * - * This deliberately reuses the same renderer the app uses at runtime rather + * This deliberately reuses the same renderers the app uses at runtime rather * than standing up a headless-GL or Puppeteer pipeline just for build assets — * one code path means the committed thumbnails cannot drift from the ones - * generated for a user's own .vrm files. + * generated for a user's own .vrm files or custom environment folder. * * Run with: npm run thumbs * @@ -13,28 +14,69 @@ * guard at its only call site. */ import { avatars } from '../config/avatars'; +import { environments } from '../config/environments'; import { getDesktopApi } from './desktopMode'; import { renderThumbnailBlob } from './thumbnails'; +import { renderEnvironmentThumbnailBlob } from './environmentThumbnails'; -export async function generateBundledThumbnails() { - const api = getDesktopApi(); - if (!api?.devWriteThumbnail) { - console.error('[thumbs] dev write channel unavailable — run via npm run thumbs'); - return; - } +/** + * Frame to sample per bundled environment, where the default lands on a fade-in + * or an otherwise unrepresentative frame. Keyed by environment id. + * @type {Record} + */ +const ENVIRONMENT_FRAME_OVERRIDES = {}; +async function generateAvatarThumbnails(api) { for (const entry of avatars) { const modelPath = entry.skins.find((skin) => skin.id === 'default')?.path ?? entry.skins[0]?.path; if (!modelPath) continue; try { const blob = await renderThumbnailBlob(modelPath); - const written = await api.devWriteThumbnail(`${entry.id}.png`, await blob.arrayBuffer()); + const written = await api.devWriteThumbnail( + 'avatars', + `${entry.id}.png`, + await blob.arrayBuffer(), + ); console.log(`[thumbs] ${entry.id} -> ${written}`); } catch (error) { console.error(`[thumbs] ${entry.id} failed`, error); } } +} + +async function generateEnvironmentThumbnails(api) { + for (const entry of environments) { + try { + // The bundled GIFs are Vite-resolved urls, so this is the same fetch the + // stage does — no filesystem access from the renderer. + const response = await fetch(entry.src); + if (!response.ok) throw new Error(`fetch ${entry.src} -> ${response.status}`); + + const blob = await renderEnvironmentThumbnailBlob(await response.blob(), { + frameIndex: ENVIRONMENT_FRAME_OVERRIDES[entry.id], + }); + const written = await api.devWriteThumbnail( + 'environments', + `${entry.id}.png`, + await blob.arrayBuffer(), + ); + console.log(`[thumbs] env ${entry.id} -> ${written}`); + } catch (error) { + console.error(`[thumbs] env ${entry.id} failed`, error); + } + } +} + +export async function generateBundledThumbnails() { + const api = getDesktopApi(); + if (!api?.devWriteThumbnail) { + console.error('[thumbs] dev write channel unavailable — run via npm run thumbs'); + return; + } + + await generateAvatarThumbnails(api); + await generateEnvironmentThumbnails(api); console.log('[thumbs] done'); api.closeWindow?.(); diff --git a/avatar/vite.config.js b/avatar/vite.config.js index b568260..e6f6155 100644 --- a/avatar/vite.config.js +++ b/avatar/vite.config.js @@ -42,12 +42,12 @@ export default defineConfig(({ command }) => { plugins: [react(), stripCustomEnvs(includeCustom)], server: { watch: { - // `npm run thumbs` writes generated portraits into this directory while - // the dev server is running. Watching it means each write invalidates the - // module graph, reloads the generator, and starts the whole run again — - // an endless loop that also interrupts in-flight VRM loads. These are + // `npm run thumbs` writes generated artwork into these directories while + // the dev server is running. Watching them means each write invalidates + // the module graph, reloads the generator, and starts the whole run again + // — an endless loop that also interrupts in-flight VRM loads. These are // build assets; they never need hot reload. - ignored: ['**/src/assets/avatars/thumbs/**'], + ignored: ['**/src/assets/avatars/thumbs/**', '**/src/assets/environments/thumbs/**'], }, }, }; diff --git a/docs/avatars.md b/docs/avatars.md index 19eaad8..e04d239 100644 --- a/docs/avatars.md +++ b/docs/avatars.md @@ -12,7 +12,7 @@ Path: `avatar/src/assets/avatars/`. Gear → **Appearance** → **Avatars**. Selection persists as `avatarId` in [config.yaml](user-settings.md). -Picker cards use **static thumbnails** (not live 3D previews), so Appearance opens quickly. Bundled portraits live under `src/assets/avatars/thumbs/` (regenerate with `npm run thumbs` when a bundled `.vrm` or the catalog changes — see [Contributing](../CONTRIBUTING.md#bundled-avatar-thumbnails)). Custom-folder portraits are rendered once and cached under Electron `userData/thumbnails/` (keyed by path, mtime, and size). +Picker cards use **static thumbnails** (not live 3D previews), so Appearance opens quickly. Bundled portraits live under `src/assets/avatars/thumbs/` (regenerate with `npm run thumbs` when a bundled `.vrm` or the catalog changes — see [Contributing](../CONTRIBUTING.md#bundled-picker-thumbnails)). Custom-folder portraits are rendered once and cached under Electron `userData/thumbnails/` (keyed by path, mtime, and size).

Avatar 1, 2, 3, and 4 diff --git a/docs/development/project-layout.md b/docs/development/project-layout.md index 64a721d..7173df8 100644 --- a/docs/development/project-layout.md +++ b/docs/development/project-layout.md @@ -44,7 +44,7 @@ End users personalize via **Settings → Directories** and **VRoid Hub** (see [U | `npm run build` | CI / web | Production Vite bundle | | `npm run lint` | Contributors / CI | ESLint (`src/`, `electron/**/*.cjs`, scripts; `--max-warnings=0`) | | `npm test` | Contributors / CI | Electron unit tests (`electron/*.test.cjs`), renderer unit tests (`src/**/*.test.mjs`), and build-tooling tests (`scripts/*.test.mjs`, which run three real `vite build`s, so the suite takes ~15s) | -| `npm run thumbs` | Contributors | Re-render committed avatar portraits into `src/assets/avatars/thumbs/` | +| `npm run thumbs` | Contributors | Re-render committed picker thumbnails into `src/assets/avatars/thumbs/` and `src/assets/environments/thumbs/` | ### Continuous integration @@ -52,4 +52,4 @@ Pull requests and pushes to `main` run [`.github/workflows/ci.yml`](../../.githu Maintainer version bumps and GitHub Releases: [Release checklist](release-checklist.md). -Run `npm run thumbs` whenever a bundled `.vrm` or the `config/avatars.js` catalog changes, and commit the PNGs — the Appearance picker reads those files rather than rendering a live preview. Custom-folder avatars are cached at runtime under Electron `userData/thumbnails/` instead. See [Contributing](../../CONTRIBUTING.md#bundled-avatar-thumbnails). +Run `npm run thumbs` whenever a bundled `.vrm` or `.gif`, or the `config/avatars.js` / `config/environments.js` catalog, changes, and commit the PNGs — the Appearance picker reads those files rather than rendering a live preview or playing the stage GIF. Custom-folder assets are cached at runtime under Electron `userData/thumbnails/` instead. See [Contributing](../../CONTRIBUTING.md#bundled-picker-thumbnails). diff --git a/docs/environments.md b/docs/environments.md index b181ee4..841c679 100644 --- a/docs/environments.md +++ b/docs/environments.md @@ -23,6 +23,8 @@ Open Gear → **Appearance** → **Environments**. Credits for the three GIFs (GIPHY): see [Assets & credits](assets-and-credits.md#built-in-environment-gifs). +The picker shows a **still poster** for each of these (committed under `src/assets/environments/thumbs/`), not the GIF — only the environment you actually select animates, and only on the stage. Regenerate the posters with `npm run thumbs` if you change a bundled GIF or the catalog; see [Contributing](../CONTRIBUTING.md#bundled-picker-thumbnails). +

Stars Code From 7db7a55d2a76da61223bc6fbdb77752e234303d1 Mon Sep 17 00:00:00 2001 From: AUDO Date: Thu, 13 Aug 2026 00:04:45 +0800 Subject: [PATCH 2/2] perf(environments): read a custom folder one image at a time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit loadLibraryEnvironments pulled every file in a configured folder fully into the renderer as a blob url — no cap, no laziness, and it ran when the folder was configured rather than when the Custom expander was opened. Blob urls pin their bytes, so unlike ordinary images Chromium could not discard and refetch them: a folder of large gifs held hundreds of MB resident for the session, and the picker animated all of it inside 40px boxes. Entries now carry no image data. The picker draws a poster generated once per file and cached under userData/thumbnails/, reusing the cache and the IPC channel avatar portraits already use — keying on the absolute path means the two kinds share it without colliding. Only the environment actually selected has its bytes read. Posters are generated with ImageDecoder rather than three.js, and run three at a time rather than strictly serially: unlike a VRM parse this is decode work Chromium runs off-thread, so the cap is there to bound resident source files, not to protect the frame rate. Reading at selection time costs a delay a resident folder did not, so two things soften it. The read moved off the Electron main process, which a synchronous read of a 20MB gif blocked — window and all. And the stage holds the background it is already showing, glow included, until the new one is ready: `pending` distinguishes an image still being read from a selection that has no image, so None and Color fade still take effect at once. Bridging with the low-resolution poster was tried first and read as a fault rather than as a load. Refs #22 Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 2 + avatar/electron/main.cjs | 6 +- avatar/electron/thumbnails.cjs | 12 +- avatar/electron/user-library.cjs | 25 +++- avatar/electron/user-library.test.cjs | 16 +++ avatar/src/components/AvatarStage.jsx | 74 +++++++++++ .../components/avatar/AvatarStageShell.jsx | 30 ++++- .../src/components/panels/MiniEnvironment.jsx | 49 ++++++++ avatar/src/components/panels/PalettePanel.jsx | 44 ++++--- avatar/src/config/environments.js | 19 ++- avatar/src/lib/environmentThumbnails.js | 118 ++++++++++++++++++ avatar/src/lib/holoField.js | 26 ++++ avatar/src/lib/userLibrary.js | 60 +++++++-- avatar/src/styles/app.css | 15 ++- docs/environments.md | 4 + 15 files changed, 451 insertions(+), 49 deletions(-) create mode 100644 avatar/src/components/panels/MiniEnvironment.jsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bd13da..5f419c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Changed +- **Environment pickers draw still posters, not the stage assets.** Opening Gear → **Appearance** → **Environments** used to hand the compositor the three bundled GIFs — ~32MB and ~480 frames between them — to play inside 40px boxes, and it loaded all three whether or not one was selected. Built-ins now ship a committed 192×112 poster (`src/assets/environments/thumbs/`, regenerate with `npm run thumbs`), so a GIF is loaded only for the environment actually on stage. Custom-folder tiles get the same treatment at runtime: a poster is generated once per file and cached under Electron `userData/thumbnails/`, alongside avatar portraits. Only the picker changes — the stage still animates. (#22) +- **A custom environments folder is no longer read into memory up front.** Configuring the folder used to pull every file in it fully into the renderer as a blob URL, before the Custom expander had even been opened; blob URLs pin their bytes, so a folder of large GIFs stayed resident for the session. Files are now read one at a time, only for the environment being selected. The stage holds the current background until the new one is ready rather than blanking, and the read moved off the Electron main process so a large image no longer stalls the window. (#22) - `npm test` now also runs renderer unit tests (`src/**/*.test.mjs`), starting with the animation catalog lookups. To make them loadable by plain Node, `src/config/animations.js` is split into `vrmaAssets.js` (Vite-resolved `.vrma` imports), `animationLookup.js` (pure lookups), and a composing entry point that re-exports both — the public API is unchanged. See [Contributing → Where tests go](CONTRIBUTING.md#where-tests-go). (#23) - Remove the README CI status badge; workflow status stays on the Actions tab. - README badge: replace misleading **BOOTH VRM** (linked to vrm.dev) with **VRM Docs** → https://vrm.dev/en/. diff --git a/avatar/electron/main.cjs b/avatar/electron/main.cjs index cb715c8..0c50c2f 100644 --- a/avatar/electron/main.cjs +++ b/avatar/electron/main.cjs @@ -31,7 +31,7 @@ const { } = require('./vroid-oauth-server.cjs'); const { pathExists, - readLibraryFile, + readLibraryFileAsync, resolveLibraryPath, scanAnimations, scanAvatars, @@ -597,9 +597,9 @@ ipcMain.handle('library:scan-environments', (event, dirPath) => { return scanEnvironments(dirPath); }); -ipcMain.handle('library:read-file', (event, id) => { +ipcMain.handle('library:read-file', async (event, id) => { assertTrustedLibrarySender(event); - const buffer = readLibraryFile(id); + const buffer = await readLibraryFileAsync(id); return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength); }); diff --git a/avatar/electron/thumbnails.cjs b/avatar/electron/thumbnails.cjs index cc9323c..23e3e7c 100644 --- a/avatar/electron/thumbnails.cjs +++ b/avatar/electron/thumbnails.cjs @@ -5,8 +5,9 @@ const path = require('node:path'); const crypto = require('node:crypto'); const CACHE_DIR_NAME = 'thumbnails'; -// A 112x112 RGBA PNG of a character portrait; anything far past this is not a -// thumbnail we wrote, so refuse to serve or store it. +// A 112x112 character portrait or a 192x112 environment poster, both RGBA PNG; +// anything far past this is not a thumbnail we wrote, so refuse to serve or +// store it. const MAX_THUMBNAIL_BYTES = 512 * 1024; /** @type {string | null} */ @@ -29,8 +30,11 @@ function configureThumbnailCache(userDataPath) { /** * Two files can share a name across folders, and the same file can be replaced * in place, so the identity of a thumbnail is the path *and* what the file - * looked like when we rendered it. Swapping in a new .vrm under the same name - * changes mtime and size, which misses the cache and regenerates. + * looked like when we rendered it. Swapping in a new .vrm or .gif under the + * same name changes mtime and size, which misses the cache and regenerates. + * + * Nothing here is specific to avatars: keying on the absolute path is what lets + * avatar portraits and environment posters share one cache without colliding. * * @param {string} absolutePath * @returns {string | null} diff --git a/avatar/electron/user-library.cjs b/avatar/electron/user-library.cjs index 23e7750..d8eeb27 100644 --- a/avatar/electron/user-library.cjs +++ b/avatar/electron/user-library.cjs @@ -108,7 +108,7 @@ function scanEnvironments(dirPath) { * @param {unknown} id * @returns {Buffer} */ -function readLibraryFile(id) { +function resolveReadablePath(id) { if (typeof id !== 'string' || id.trim() === '') { throw new Error('Missing library file id.'); } @@ -116,6 +116,11 @@ function readLibraryFile(id) { if (!absolutePath) { throw new Error('Unknown library file. Refresh the directory and try again.'); } + return absolutePath; +} + +function readLibraryFile(id) { + const absolutePath = resolveReadablePath(id); // Ensure the indexed path still exists and is a regular file. const stat = fs.statSync(absolutePath); if (!stat.isFile()) { @@ -124,6 +129,23 @@ function readLibraryFile(id) { return fs.readFileSync(absolutePath); } +/** + * The same read off the main thread. Environment images are fetched while the + * user is watching — a synchronous read of a 20MB gif blocks the main process, + * and with it the window, for as long as the disk takes. + * + * @param {unknown} id + * @returns {Promise} + */ +async function readLibraryFileAsync(id) { + const absolutePath = resolveReadablePath(id); + const stat = await fs.promises.stat(absolutePath); + if (!stat.isFile()) { + throw new Error('Library path is not a file.'); + } + return fs.promises.readFile(absolutePath); +} + /** * @param {unknown} dirPath */ @@ -147,6 +169,7 @@ module.exports = { scanAnimations, scanEnvironments, readLibraryFile, + readLibraryFileAsync, resolveLibraryPath, pathExists, normalizeDir, diff --git a/avatar/electron/user-library.test.cjs b/avatar/electron/user-library.test.cjs index 49e12ba..4d54ccc 100644 --- a/avatar/electron/user-library.test.cjs +++ b/avatar/electron/user-library.test.cjs @@ -7,6 +7,7 @@ const path = require("node:path"); const test = require("node:test"); const { readLibraryFile, + readLibraryFileAsync, scanAnimations, scanAvatars, scanEnvironments, @@ -111,3 +112,18 @@ test("reading a clip that vanished after the scan throws", (context) => { assert.throws(() => readLibraryFile(entry.id)); assert.throws(() => readLibraryFile("lib-anim-never-scanned-000000000000")); }); + +// The IPC channel reads asynchronously so a large environment image cannot +// block the main process, and with it the window. Same contract as the sync +// read, or the renderer's error handling would only hold for one of them. +test("the async read matches the sync one, including its failures", async (context) => { + const root = fixture(context, { "clip.vrma": "animation-bytes" }); + const [entry] = scanAnimations(root); + + assert.equal((await readLibraryFileAsync(entry.id)).toString(), "animation-bytes"); + + fs.rmSync(path.join(root, "clip.vrma")); + + await assert.rejects(() => readLibraryFileAsync(entry.id)); + await assert.rejects(() => readLibraryFileAsync("lib-anim-never-scanned-000000000000")); +}); diff --git a/avatar/src/components/AvatarStage.jsx b/avatar/src/components/AvatarStage.jsx index ba24d70..8a0bddb 100644 --- a/avatar/src/components/AvatarStage.jsx +++ b/avatar/src/components/AvatarStage.jsx @@ -28,6 +28,7 @@ import { import { useAudioSource } from '../hooks/useAudioSource'; import { getDesktopApi, getLibraryApi, isDesktopMode } from '../lib/desktopMode'; import { + loadEnvironmentSource, loadLibraryAnimations, loadLibraryAvatars, loadLibraryEnvironments, @@ -37,6 +38,7 @@ import { } from '../lib/userLibrary'; import { loadUserSettings, resetUserSettings, saveUserSettings } from '../lib/userSettingsStore'; import { revokeThumbnailUrls } from '../lib/thumbnails'; +import { revokeEnvironmentThumbnailUrls } from '../lib/environmentThumbnails'; import { VrmAvatar } from './avatar/VrmAvatar'; import { AvatarStageShell } from './avatar/AvatarStageShell'; import { CameraController } from './ui/CameraController'; @@ -93,6 +95,8 @@ export function AvatarStage() { const libraryAvatarsRef = useRef([]); const libraryAnimationsRef = useRef([]); const libraryEnvironmentsRef = useRef([]); + /** Id of the environment whose full-size image is currently being read. */ + const environmentSourceLoadRef = useRef(null); const panelRef = useRef(null); const drawerRef = useRef(null); const commandMenuRef = useRef(null); @@ -440,6 +444,10 @@ export function AvatarStage() { // screen — but a remount in that window loaded nothing. Hold the old list // and drop it only once its replacement is in state (#39). const previous = libraryEnvironmentsRef.current; + // Posters are keyed by path, so a rescan has to drop them or an image + // replaced in place keeps serving its old one: the disk cache would catch + // the new mtime, but this session's url cache answers first. + revokeEnvironmentThumbnailUrls(); const useLibrary = desktopMode && directories.environments.mode === 'custom' && @@ -510,12 +518,78 @@ export function AvatarStage() { }; }, [directories.environments.mode, directories.environments.path]); + useEffect(() => { + // Bytes are held for the environment on stage and, while one is being read, + // for the outgoing one the stage is still showing — never for the whole + // folder, which is what loadLibraryEnvironments used to do the moment the + // folder was configured. The picker draws posters instead. + const selectedId = selectedBg.type === 'env' ? selectedBg.id : null; + + // The registry backs getEnvironmentById, which the holo field and the + // chrome tone both read during render, so it has to move with the state + // rather than trail it by an effect. + const publish = (next) => { + setLibraryCustomEnvironments(next); + setLibraryEnvironments(next); + }; + + const target = selectedId + ? libraryEnvironments.find((entry) => entry.id === selectedId) + : null; + + // The stage holds the previous background until the incoming one is ready, + // so its url is still on screen and cannot be released yet. + if (!target || target.src) { + const stale = libraryEnvironments.filter((entry) => entry.src && entry.id !== selectedId); + if (stale.length > 0) { + revokeEnvironmentBlobUrls(stale); + publish( + libraryEnvironments.map((entry) => + entry.src && entry.id !== selectedId ? { ...entry, src: null } : entry, + ), + ); + } + return undefined; + } + + // Publishing below re-runs this effect, and rapid switching can re-enter it + // for an id already being read. One marker cannot cover every interleaving, + // so the read itself checks again before it publishes. + if (environmentSourceLoadRef.current === target.id) return undefined; + environmentSourceLoadRef.current = target.id; + + void (async () => { + try { + const url = await loadEnvironmentSource(target); + if (!url) return; + const current = libraryEnvironmentsRef.current; + const entry = current.find((candidate) => candidate.id === target.id); + // Gone in a rescan, or another read of the same file got there first. + if (!entry || entry.src) { + URL.revokeObjectURL(url); + return; + } + // Published even if the selection has moved on: the pass above releases + // it on the next run, which is cheaper than losing the read and having + // to redo it if the user comes back. + publish(current.map((item) => (item.id === target.id ? { ...item, src: url } : item))); + } finally { + if (environmentSourceLoadRef.current === target.id) { + environmentSourceLoadRef.current = null; + } + } + })(); + + return undefined; + }, [selectedBg, libraryEnvironments]); + useEffect(() => { return () => { revokeAvatarBlobUrls(libraryAvatarsRef.current); revokeThumbnailUrls(); revokeAnimationBlobUrls(libraryAnimationsRef.current); revokeEnvironmentBlobUrls(libraryEnvironmentsRef.current); + revokeEnvironmentThumbnailUrls(); setLibraryCustomEnvironments([]); }; }, []); diff --git a/avatar/src/components/avatar/AvatarStageShell.jsx b/avatar/src/components/avatar/AvatarStageShell.jsx index 8399b58..360361f 100644 --- a/avatar/src/components/avatar/AvatarStageShell.jsx +++ b/avatar/src/components/avatar/AvatarStageShell.jsx @@ -1,8 +1,13 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { Cog } from 'lucide-react'; import { STAGE } from '../../config/defaults'; import { resolveChromeTone, resolveChromeToneSync, toneFromLuma } from '../../lib/chromeTone'; -import { getHoloFieldStyle, isHoloFieldHidden } from '../../lib/holoField'; +import { + getHoloFieldStyle, + getHoloImageUrl, + isHoloFieldHidden, + isHoloFieldPending, +} from '../../lib/holoField'; import { getDesktopApi, isDesktopMode } from '../../lib/desktopMode'; import { BarCommandMenu } from '../ui/BarCommandMenu'; import { WindowScaleMenu } from '../ui/WindowScaleMenu'; @@ -30,7 +35,19 @@ export function AvatarStageShell({ }) { const { barHeight, canvasOverflowTop, canvasOverflowSide } = STAGE; const desktopMode = isDesktopMode(); - const holoStyle = getHoloFieldStyle(environmentSelection); + // A custom-folder environment is read from disk only once selected, so its + // image arrives a moment after the selection does. Rather than blank the + // stage for that moment, hold the last background that was ready — glow + // included, so the whole field changes at once instead of in two steps. + const holoPending = isHoloFieldPending(environmentSelection); + const lastReadyHoloStyle = useRef(null); + const resolvedHoloStyle = getHoloFieldStyle(environmentSelection); + if (!holoPending) lastReadyHoloStyle.current = resolvedHoloStyle; + const holoStyle = holoPending ? (lastReadyHoloStyle.current ?? resolvedHoloStyle) : resolvedHoloStyle; + + // Tone is sampled from the image, which resolves after the selection for the + // same reason — so the selection alone is not enough to know when to sample. + const holoImageUrl = getHoloImageUrl(environmentSelection); const [chromeTone, setChromeTone] = useState(() => resolveChromeToneSync(environmentSelection)); useEffect(() => { @@ -59,7 +76,10 @@ export function AvatarStageShell({ } if (!useDesktopSample) { - void applyEnvironmentTone(); + // Hold the current tone while the image is still being read: there is + // nothing to sample yet, and resolving now would flip the bar to its + // default and back a moment later. + if (!holoPending) void applyEnvironmentTone(); return () => { cancelled = true; }; @@ -83,7 +103,7 @@ export function AvatarStageShell({ unsubSettled?.(); window.removeEventListener('focus', onFocus); }; - }, [environmentSelection, desktopMode, overlayMode]); + }, [environmentSelection, holoImageUrl, holoPending, desktopMode, overlayMode]); function toggleMenu(event) { event.stopPropagation(); diff --git a/avatar/src/components/panels/MiniEnvironment.jsx b/avatar/src/components/panels/MiniEnvironment.jsx new file mode 100644 index 0000000..438342e --- /dev/null +++ b/avatar/src/components/panels/MiniEnvironment.jsx @@ -0,0 +1,49 @@ +import { useEffect, useState } from 'react'; +import { getEnvironmentThumbnail } from '../../lib/environmentThumbnails'; + +/** + * A custom-folder environment tile. + * + * The picker used to point straight at the full-size image, which for a folder + * of gifs meant decoding and animating every one of them inside a 40px box. + * Each tile now draws a poster that is generated once and cached to disk, the + * same arrangement MiniAvatar uses for portraits. Only the environment actually + * selected loads its real bytes, and only on the stage. + */ +export function MiniEnvironment({ entry, selected, onClick }) { + const [src, setSrc] = useState(null); + const { id, fileName } = entry; + + useEffect(() => { + let cancelled = false; + setSrc(null); + + // Deliberately not keyed on `entry`: selecting an environment replaces that + // object to carry its loaded source, and re-running here would drop the + // tile back to its placeholder — a flicker in the picker, of all places. + void getEnvironmentThumbnail({ id, fileName }).then((url) => { + if (!cancelled) setSrc(url); + }); + + return () => { + cancelled = true; + }; + }, [id, fileName]); + + return ( + + ); +} diff --git a/avatar/src/components/panels/PalettePanel.jsx b/avatar/src/components/panels/PalettePanel.jsx index fbcf432..06995e3 100644 --- a/avatar/src/components/panels/PalettePanel.jsx +++ b/avatar/src/components/panels/PalettePanel.jsx @@ -2,6 +2,7 @@ import { useLayoutEffect, useRef, useState } from 'react'; import { ChevronDown } from 'lucide-react'; import { environments, defaultColor } from '../../config/environments'; import { MiniAvatar } from '../avatar/MiniAvatar'; +import { MiniEnvironment } from './MiniEnvironment'; import { AccordionSection, Divider } from '../ui/PanelPrimitives'; import { VroidHubPanel } from './VroidHubPanel'; @@ -178,22 +179,33 @@ export function PalettePanel({ Close Custom to show Stars / Code / Bloom / None again.

- {customEnvironmentList.map((env) => ( - - ))} + {customEnvironmentList.map((env) => + // A user's folder resolves a cached poster; contributor + // custom/ media is a build asset and already has a url. + env.library ? ( + setSelectedBg({ type: 'env', id: env.id })} + /> + ) : ( + + ), + )}
)} diff --git a/avatar/src/config/environments.js b/avatar/src/config/environments.js index a05f9a5..5cbc031 100644 --- a/avatar/src/config/environments.js +++ b/avatar/src/config/environments.js @@ -46,6 +46,8 @@ const customGlow = { * @property {string | null} [thumb] Still poster for the picker; falls back to `src` * @property {HoloGlow} glow * @property {boolean} [custom] + * @property {boolean} [library] From a user-picked folder, so `src` is read on + * demand rather than resolved by Vite — see lib/userLibrary.js */ /** @type {EnvironmentEntry[]} */ @@ -145,20 +147,29 @@ export function getEnvironmentById(id) { /** * @param {EnvironmentSelection} selection - * @returns {{ glow: HoloGlow | null, imageUrl: string | null, hidden: boolean }} + * @returns {{ glow: HoloGlow | null, imageUrl: string | null, hidden: boolean, pending: boolean }} */ export function resolveHoloTheme(selection) { if (selection.type === 'none') { - return { glow: null, imageUrl: null, hidden: true }; + return { glow: null, imageUrl: null, hidden: true, pending: false }; } if (selection.type === 'env') { const env = getEnvironmentById(selection.id); - return { glow: env.glow, imageUrl: env.src, hidden: false }; + // A custom-folder environment reads its bytes only once selected, which + // takes as long as the file is big. `pending` separates that from the cases + // that legitimately have no image, so the stage can hold what it is already + // showing instead of blanking — see AvatarStageShell. + return { + glow: env.glow, + imageUrl: env.src ?? null, + hidden: false, + pending: Boolean(env.library) && !env.src, + }; } const hex = selection.value.length === 4 ? defaultColor : selection.value; - return { glow: glowFromHex(hex), imageUrl: null, hidden: false }; + return { glow: glowFromHex(hex), imageUrl: null, hidden: false, pending: false }; } /** @param {string} hex */ diff --git a/avatar/src/lib/environmentThumbnails.js b/avatar/src/lib/environmentThumbnails.js index 00c57a2..6ea7802 100644 --- a/avatar/src/lib/environmentThumbnails.js +++ b/avatar/src/lib/environmentThumbnails.js @@ -6,9 +6,15 @@ * frames between them — to play inside 40px boxes. A poster is what the picker * actually needs; the stage keeps the animation. * + * Bundled environments carry a committed poster (npm run thumbs). A user's own + * folder cannot, so those are generated here on demand and cached to disk, the + * same arrangement avatar portraits use — see lib/thumbnails.js. + * * Nothing here touches three.js: unlike an avatar portrait, an environment * thumbnail is a decode and a downscale, both of which run off the main thread. */ +import { getLibraryApi } from './desktopMode'; +import { imageMime } from './userLibrary'; // Wider than tall because the picker lays these out in a 3-up grid at 40px // high, and 2x covers HiDPI. `object-fit: cover` still does the final crop, so @@ -102,3 +108,115 @@ export async function renderEnvironmentThumbnailBlob(source, options = {}) { close(); } } + +/** @type {Map} library entry id → object URL, for this session. */ +const urlCache = new Map(); +/** @type {Map>} in-flight work, so two mounts share one decode. */ +const pending = new Map(); + +/** + * Unlike a VRM portrait, which blocks the main thread for a second and so has + * to be generated strictly one at a time, this is decode work that Chromium + * runs off-thread. The cap is here to bound how many source files are held in + * memory at once, not to protect the frame rate. + */ +const MAX_CONCURRENT = 3; +let active = 0; +/** @type {(() => void)[]} */ +const waiting = []; + +/** + * @template T + * @param {() => Promise} job + * @returns {Promise} + */ +async function runBounded(job) { + if (active >= MAX_CONCURRENT) { + await new Promise((resolve) => waiting.push(resolve)); + } + active += 1; + try { + return await job(); + } finally { + active -= 1; + waiting.shift()?.(); + } +} + +/** + * @param {{ id: string, fileName: string }} entry + * @returns {Promise} + */ +async function generateThumbnail(entry) { + const api = getLibraryApi(); + if (!api) throw new Error('Library API unavailable.'); + + const buffer = await api.readFile(entry.id); + // Deliberately not a blob url: those pin their bytes until revoked, and the + // whole point of this path is that the full-size file does not stay resident + // once the poster exists. A Blob is collectable as soon as this returns. + const source = new Blob([buffer], { type: imageMime(entry.fileName) }); + return renderEnvironmentThumbnailBlob(source); +} + +/** + * A cached poster for a user-library environment, generating and storing one if + * this is the first time we have seen the file. + * + * @param {{ id: string, fileName: string }} entry + * @returns {Promise} object URL, or null if unavailable + */ +export function getEnvironmentThumbnail(entry) { + const cached = urlCache.get(entry.id); + if (cached) return Promise.resolve(cached); + + const inFlight = pending.get(entry.id); + if (inFlight) return inFlight; + + const work = (async () => { + const api = getLibraryApi(); + if (!api) return null; + + try { + const stored = await api.getThumbnail(entry.id); + if (stored) { + const url = URL.createObjectURL(new Blob([stored], { type: 'image/png' })); + urlCache.set(entry.id, url); + return url; + } + + const blob = await runBounded(() => generateThumbnail(entry)); + + // Best-effort, and it has to actually behave that way: a cache that + // refuses the write must not cost us the poster we just generated. + try { + await api.putThumbnail(entry.id, await blob.arrayBuffer()); + } catch { + // Falls back to regenerating next launch. + } + + const url = URL.createObjectURL(blob); + urlCache.set(entry.id, url); + return url; + } catch { + return null; + } finally { + pending.delete(entry.id); + } + })(); + + pending.set(entry.id, work); + return work; +} + +/** + * Drop this session's poster urls. Must be called whenever the environment + * library is rescanned: ids are derived from the file path alone, so without + * this an image replaced in place keeps serving its old poster for the rest of + * the session — urlCache would answer before the disk cache's mtime/size check + * ever got a chance to miss. + */ +export function revokeEnvironmentThumbnailUrls() { + for (const url of urlCache.values()) URL.revokeObjectURL(url); + urlCache.clear(); +} diff --git a/avatar/src/lib/holoField.js b/avatar/src/lib/holoField.js index 960f120..540f7f9 100644 --- a/avatar/src/lib/holoField.js +++ b/avatar/src/lib/holoField.js @@ -22,3 +22,29 @@ export function getHoloFieldStyle(selection) { export function isHoloFieldHidden(selection) { return selection.type === 'none'; } + +/** + * The image url a selection currently resolves to, or null. + * + * A custom-folder environment loads its bytes only once it is the one on stage, + * so the same selection resolves to null and then to a url. Anything deriving + * from the image rather than from the selection has to watch this instead. + * + * @param {import('../config/environments').EnvironmentSelection} selection + * @returns {string | null} + */ +export function getHoloImageUrl(selection) { + return resolveHoloTheme(selection).imageUrl; +} + +/** + * Whether this selection is waiting on an image that is still being read, as + * opposed to one that has no image at all. Callers hold what they are already + * showing while this is true: swapping to a blank stage and back reads as a + * fault, and bridging with the low-resolution poster reads as one too. + * + * @param {import('../config/environments').EnvironmentSelection} selection + */ +export function isHoloFieldPending(selection) { + return resolveHoloTheme(selection).pending; +} diff --git a/avatar/src/lib/userLibrary.js b/avatar/src/lib/userLibrary.js index 80f4e93..9683c96 100644 --- a/avatar/src/lib/userLibrary.js +++ b/avatar/src/lib/userLibrary.js @@ -17,7 +17,7 @@ function toBlobUrl(mime, buffer) { /** * @param {string} fileName */ -function imageMime(fileName) { +export function imageMime(fileName) { const lower = fileName.toLowerCase(); if (lower.endsWith('.png')) return 'image/png'; if (lower.endsWith('.jpg') || lower.endsWith('.jpeg')) return 'image/jpeg'; @@ -147,6 +147,16 @@ export async function loadLibraryAnimations(dirPath) { /** * Load image entries from a user folder into EnvironmentEntry-shaped objects. + * + * This reads no image data. It used to pull every file in the folder fully into + * renderer memory as a blob url the moment the folder was configured — before + * the Custom expander had even been opened — and blob urls pin their bytes, + * so Chromium could not discard and refetch them the way it can an ordinary + * image. A folder of large gifs therefore held hundreds of MB resident for the + * session. Entries now start with `src: null`; the picker draws a cached poster + * (lib/environmentThumbnails.js) and only the environment actually selected + * gets its bytes read, via loadEnvironmentSource. + * * @param {string} dirPath * @returns {Promise<{ environments: object[], error: string | null }>} */ @@ -163,18 +173,20 @@ export async function loadLibraryEnvironments(dirPath) { }; } const scanned = await api.scanEnvironments(dirPath); - const environments = []; - for (const entry of scanned) { - const buffer = await api.readFile(entry.id); - const blobUrl = toBlobUrl(imageMime(entry.fileName), buffer); - environments.push({ - id: entry.id, - label: entry.label, - src: blobUrl, - glow: customEnvGlow, - custom: true, - }); - } + const environments = scanned.map((entry) => ({ + id: entry.id, + label: entry.label, + // Kept so the poster and the on-demand source can both work out the mime + // type without going back to the scan. + fileName: entry.fileName, + src: null, + glow: customEnvGlow, + custom: true, + // Distinguishes these from bundled custom/ media, which carries a url from + // the start. `src` cannot do that job: it fills in once this entry is the + // one on stage, and the picker must not start showing the full image then. + library: true, + })); return { environments, error: null }; } catch (error) { return { @@ -184,6 +196,28 @@ export async function loadLibraryEnvironments(dirPath) { } } +/** + * Read one environment image and mint a blob url for it. Only ever called for + * the environment currently on the stage: the picker uses posters instead, so + * at most one full-size image is resident at a time. + * + * @param {{ id: string, fileName: string }} entry + * @returns {Promise} + */ +export async function loadEnvironmentSource(entry) { + const api = getLibraryApi(); + if (!api) return null; + + try { + const buffer = await api.readFile(entry.id); + return toBlobUrl(imageMime(entry.fileName), buffer); + } catch { + // The file went away between the scan and here; the stage keeps its glow + // and simply shows no image. + return null; + } +} + /** * @param {object[]} avatars */ diff --git a/avatar/src/styles/app.css b/avatar/src/styles/app.css index cac829b..0ffd775 100644 --- a/avatar/src/styles/app.css +++ b/avatar/src/styles/app.css @@ -1072,7 +1072,8 @@ min-height: 58px; } -.environment-custom__grid .background-thumb img { +.environment-custom__grid .background-thumb img, +.environment-custom__grid .background-thumb__pending { height: 40px; } @@ -1195,7 +1196,8 @@ } @media (prefers-reduced-motion: reduce) { - .mini-avatar__pending { + .mini-avatar__pending, + .background-thumb__pending { animation: none; } } @@ -1236,13 +1238,20 @@ } .background-thumb img, -.background-thumb__default { +.background-thumb__default, +.background-thumb__pending { width: 100%; height: 52px; object-fit: cover; display: block; } +/* Shown while a custom environment's poster is being generated. */ +.background-thumb__pending { + background: linear-gradient(135deg, #efeaf8, #dcd3f0); + animation: mini-avatar-pulse 1.4s ease-in-out infinite; +} + .background-thumb__label { display: block; font-size: 10px; diff --git a/docs/environments.md b/docs/environments.md index 841c679..3ca3c7b 100644 --- a/docs/environments.md +++ b/docs/environments.md @@ -56,6 +56,10 @@ The Color fade row stays pinned under the environment list (**Use color** + **Re Built-ins are **never** replaced by a custom env directory (unlike avatars). +Tiles in the Custom grid are **posters**, generated once per file and cached under Electron `userData/thumbnails/` (keyed by path, mtime, and size — the same cache avatar portraits use). A tile pulses while its poster is being made, and an animated file only ever animates on the stage. Nothing in the folder is read into memory until you select it, so folder size costs you disk, not RAM. + +Because the file is read at selection time, a large image takes a moment to appear. The stage keeps showing the current background until the new one is ready, then changes over in one step — so a slow read looks like a delay, never a blank stage. +

Browsing a custom environments folder in Appearance