fix(clients): persist project icons across reloads and reconnects - #10138
Conversation
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This PR introduces substantial web and mobile runtime behavior for persistent favicon fetching, image processing, storage, hydration, refresh, and clearing across connection lifecycles. Its cross-cutting production impact and new persistence layers warrant human review. You can add or adjust custom eligibility rules. Learn more. |
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
Dismissing prior approval to re-evaluate 1933a14
Dismissing prior approval to re-evaluate 176ee22
SVG favicons without width/height attributes report a 300x150 (or, on older Firefox, 0x0) natural size, so the canvas thumbnail letterboxed the icon at half size or collapsed it to one pixel and then persisted that image. Fetch the icon bytes and inline them when they fit the cache limit; only bitmaps larger than that go through a platform downscaler, and large SVGs stay remote. Persist one record per icon rather than a single JSON blob so tabs cannot overwrite each other's entries. On mobile the records live in client_cache so Settings → Client storage counts and clears them, and clearing also drops the in-memory images. Remote mobile icons key expo-image's disk cache by revision again so signed-token rotation reuses cached bytes, and a changed icon starts from the loading state. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Pushed
Verified in an isolated dev environment with a viewBox-only Model: Claude Fable 5. Harness: Claude Code in T3 Code. |
…obile runtime Cap icon responses at 4 MiB while streaming so an oversized image is dropped before it is materialized. On mobile, the environment cache store hands its database to the favicon cache instead of the cache calling back into the application runtime from inside a fiber that already runs on it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
A resolve that started after the revision bump but before the clear finished could persist its result once the deletes had run. Downloads now wait for an in-flight clear before capturing the revision they compare against. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
## What's Changed * fix(server): settle threads using actual pull request terminal timestamps by @maria-rcks in pingdotgg/t3code#9934 * fix(clients): persist project icons across reloads and reconnects by @StiensWout in pingdotgg/t3code#10138 * fix(mobile): use selected theme across input forms and controls by @juliusmarminge in pingdotgg/t3code#10239 * fix(mobile): keep the new-task draft when switching environment by @juliusmarminge in pingdotgg/t3code#10247 **Full Changelog**: pingdotgg/t3code@v0.0.39-nightly.20260906.1291...v0.0.39-nightly.20260906.1292 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.39-nightly.20260906.1292

Project icons fall back to generic icons while remote environments reconnect or the page reloads. Keep the last resolved URL during reconnects, and persist the icon image so cached sidebar entries can show their icons before the next remote response arrives.
The shared cache is scoped to the environment, workspace, and selected favicon path. Icons are fetched and stored exactly as served when they fit 32 KiB, which covers SVG, ICO, and small PNG favicons; only larger bitmaps are downscaled to 96×96 (48×48 retry) through
createImageBitmapon web and expo-image on mobile, and larger SVGs stay remote. Downloads are capped at 4 MiB while streaming. Each icon is its own record: IndexedDB on web and desktop, aproject-faviconrow inclient_cacheon mobile so Settings → Client storage counts and clears it. The cache holds at most 128 entries and 1 MiB. Hydrate before restoring the cached sidebar; refresh when the image revision changes, retain the previous image during failures, and remove it on a confirmed missing-icon response or when its environment is removed. Signed URL and origin changes reuse the same saved image. Storage is best effort. No new native dependencies.Validation: 69 focused tests plus web, mobile, and client-runtime typechecks. In an isolated browser with
/api/assets/**aborted across reload, icons restore from storage for both a PNG project and a viewBox-onlyfavicon.svgproject, and stay visible after networking is disabled. Native mobile UI was not exercised.Before: reloading with remote icon requests held, using sample thread titles.
After: the same requests remain held; the sidebar and breadcrumb use saved icons.
Recording of reload with remote icon requests held
After disabling networking and closing the WebSocket:
An SVG favicon without
width/heightattributes, which browsers report at a 300×150 natural size, was thumbnailed at half size by the earlier canvas approach. Storing the bytes as served fixes it (breadcrumb after reload with asset requests aborted):Model: GPT-6. Harness: Codex in T3 Code. Follow-up fixes: Claude Fable 5, Claude Code in T3 Code.
Note
Persist project favicons across reloads and reconnects via shared cache and atom family
projectFaviconCacheinclient-runtimethat downloads, validates, and downscales favicon images into self-contained data URLs, then persists them platform-side so icons survive signed-URL rotation and reconnects.MobileDatabaseunder a newproject-faviconcache kind (projectFaviconCache.ts).projectFaviconUrlAtomatom family replaces the old asset-URL hooks in bothProjectFaviconcomponents, retaining the last successful image during connection failures and returning cached data when available.MobileDatabasegains a newlist-cacheoperation andproject-faviconClientCacheKind; any out-of-tree consumers of the mobile database schema or operation vocabulary must add support for these values.Macroscope summarized dd57844.