(themes: CustomTheme[])
| 7444 | } |
| 7445 | |
| 7446 | function applyCustomThemes(themes: CustomTheme[]): void { |
| 7447 | useStore.setState({ customThemes: themes }) |
| 7448 | // App.tsx injects the active theme's CSS in response to the state change. |
| 7449 | // One-time canonicalization of any legacy two-id custom selection |
| 7450 | // (`custom-<slug>-<mode>`) persisted by the pre-release WIP: only rewrites |
| 7451 | // when the stored id doesn't match a loaded theme but its stripped form does, |
| 7452 | // so a real theme whose slug ends in `-light`/`-dark` is left untouched. |
| 7453 | const { themeId, themeMode } = useStore.getState() |
| 7454 | if (isCustomThemeId(themeId)) { |
| 7455 | const slug = customThemeSlugFromId(themeId) |
| 7456 | if (slug && !themes.some((t) => t.slug === slug)) { |
| 7457 | const legacy = /^custom-(.+)-(?:light|dark)$/.exec(themeId) |
| 7458 | if (legacy && themes.some((t) => t.slug === legacy[1])) { |
| 7459 | useStore |
| 7460 | .getState() |
| 7461 | .setTheme({ id: `custom-${legacy[1]}`, family: 'custom', mode: themeMode }) |
| 7462 | } |
| 7463 | } |
| 7464 | } |
| 7465 | } |
| 7466 | |
| 7467 | /** Re-scan the themes dir and apply the result. Used after an in-app change |
| 7468 | * (e.g. deleting a theme) so the UI updates without waiting on the watcher. */ |
nothing calls this directly
no test coverage detected