diff --git a/src/views/SearchView.js b/src/views/SearchView.js index 962ea47..d9d86b7 100644 --- a/src/views/SearchView.js +++ b/src/views/SearchView.js @@ -111,38 +111,59 @@ export async function SearchView() { function buildFilters() { clear(filters); if (tab === 'moves') { + const vg = settings.get().versionGroup; + const gameHasKind = (kind) => + snap.moves.some((m) => + m.machines.some( + (x) => (vg === 'all' || x.vg === vg) && (x.tm || '').startsWith(kind), + ), + ); + const hasTm = gameHasKind('TM'); + const hasHm = gameHasKind('HM'); // false for Gen 8+ games, which dropped HMs + + // A machine filter left on for a game that has no such machines would + // silently zero the list with no visible checkbox to switch it off. + if ((!hasTm && ui.get().mvTm) || (!hasHm && ui.get().mvHm)) { + ui.set({ mvTm: hasTm && ui.get().mvTm, mvHm: hasHm && ui.get().mvHm }); + if (!ui.get().mvTm && !ui.get().mvHm && ui.get().mvSort === 'tm') { + ui.set({ mvSort: 'name' }); + } + } + filters.append( - pill('mvType', [['', 'Any type'], ...TYPES.map((t) => [t, prettify(t)])], ui.get().mvType, (v) => { - ui.set({ mvType: v }); - run(); - }), - pill( - 'mvClass', - [['', 'Any category'], ['physical', 'Physical'], ['special', 'Special'], ['status', 'Status']], - ui.get().mvClass, - (v) => { - ui.set({ mvClass: v }); + ...[ + pill('mvType', [['', 'Any type'], ...TYPES.map((t) => [t, prettify(t)])], ui.get().mvType, (v) => { + ui.set({ mvType: v }); run(); - }, - ), - pill( - 'mvSort', - [ - ['name', 'A–Z'], - ['power', 'Power'], - ['accuracy', 'Accuracy'], - ['gen', 'Newest'], - // "By number" only makes sense with a TM/HM filter on. - ...(ui.get().mvTm || ui.get().mvHm ? [['tm', 'TM / HM number']] : []), - ], - ui.get().mvSort, - (v) => { - ui.set({ mvSort: v }); - run(); - }, - ), - machineToggle('mvTm', 'TMs only'), - machineToggle('mvHm', 'HMs only'), + }), + pill( + 'mvClass', + [['', 'Any category'], ['physical', 'Physical'], ['special', 'Special'], ['status', 'Status']], + ui.get().mvClass, + (v) => { + ui.set({ mvClass: v }); + run(); + }, + ), + pill( + 'mvSort', + [ + ['name', 'A–Z'], + ['power', 'Power'], + ['accuracy', 'Accuracy'], + ['gen', 'Newest'], + // "By number" only makes sense with a TM/HM filter on. + ...(ui.get().mvTm || ui.get().mvHm ? [['tm', 'TM / HM number']] : []), + ], + ui.get().mvSort, + (v) => { + ui.set({ mvSort: v }); + run(); + }, + ), + hasTm ? machineToggle('mvTm', 'TMs only') : null, + hasHm ? machineToggle('mvHm', 'HMs only') : null, + ].filter(Boolean), ); } else if (tab === 'items') { filters.append( @@ -379,7 +400,19 @@ export async function SearchView() { run(); requestAnimationFrame(() => window.scrollTo(0, ui.get().searchScroll || 0)); + + // Switching games (from the Games sheet) changes which TM/HM filters + // apply and the numbers shown — refresh the filter row and results. + let lastVg = settings.get().versionGroup; + const offSettings = settings.subscribe((s) => { + if (s.versionGroup === lastVg) return; + lastVg = s.versionGroup; + syncUI(); + run(); + }); + onTeardown(view, () => { + offSettings(); ui.set({ searchScroll: window.scrollY }); });