- Detail About tab: EV yield, base EXP, catch rate + ~%, base friendship, growth rate + total EXP, held items; Breeding block with a gender-ratio bar, egg groups, egg cycles/steps - Stats tab: 'STAB coverage (attacking)' — types the Pokemon's STAB hits hard / is walled by (data/type-chart.js offensiveSummary) - Feed: Type and Generation filter dropdowns + a Random button; cards now resolve typings for the selected game's generation via snapshot pastTypes - Recently-viewed strip on the feed (ui.recent, capped at 12) - Play-cry button on the detail hero; service worker caches PokeAPI cries Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
54 lines
1.6 KiB
JavaScript
54 lines
1.6 KiB
JavaScript
/**
|
|
* Service worker (Workbox, injectManifest mode).
|
|
*
|
|
* - App shell + the PokéAPI snapshot are precached (offline launch, instant
|
|
* list / search / game switching).
|
|
* - Lazy detail JSON from pokeapi.co: stale-while-revalidate, 30-day TTL.
|
|
* - Sprites from the PokeAPI sprites repo: cache-first, capped LRU.
|
|
*/
|
|
import { precacheAndRoute } from 'workbox-precaching';
|
|
import { registerRoute } from 'workbox-routing';
|
|
import { StaleWhileRevalidate, CacheFirst } from 'workbox-strategies';
|
|
import { ExpirationPlugin } from 'workbox-expiration';
|
|
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
|
|
|
|
precacheAndRoute(self.__WB_MANIFEST || []);
|
|
|
|
const MONTH = 30 * 24 * 60 * 60;
|
|
|
|
registerRoute(
|
|
({ url }) => url.origin === 'https://pokeapi.co',
|
|
new StaleWhileRevalidate({
|
|
cacheName: 'pokeapi-json',
|
|
plugins: [
|
|
new CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
new ExpirationPlugin({
|
|
maxEntries: 1500,
|
|
maxAgeSeconds: MONTH,
|
|
purgeOnQuotaError: true,
|
|
}),
|
|
],
|
|
}),
|
|
);
|
|
|
|
registerRoute(
|
|
({ url }) =>
|
|
url.origin === 'https://raw.githubusercontent.com' &&
|
|
(url.pathname.includes('/PokeAPI/sprites/') || url.pathname.includes('/PokeAPI/cries/')),
|
|
new CacheFirst({
|
|
cacheName: 'pokeapi-img',
|
|
plugins: [
|
|
new CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
new ExpirationPlugin({
|
|
maxEntries: 600,
|
|
maxAgeSeconds: MONTH,
|
|
purgeOnQuotaError: true,
|
|
}),
|
|
],
|
|
}),
|
|
);
|
|
|
|
self.addEventListener('message', (event) => {
|
|
if (event.data && event.data.type === 'SKIP_WAITING') self.skipWaiting();
|
|
});
|