From f1469624cecb9a6bcfef3af5c9c5ab62aeba7092 Mon Sep 17 00:00:00 2001 From: appdevelopsk Date: Sat, 7 Nov 2026 08:43:59 +0900 Subject: [PATCH 1/2] fix(catalog): keep selected category deep link in sync with UI --- apps.html | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps.html b/apps.html index ecc4486..7b2b775 100644 --- a/apps.html +++ b/apps.html @@ -1437,6 +1437,13 @@

Chaos - Stranger Missions

const src = card.querySelector('img')?.getAttribute('src') || ''; return src.split('/').pop()?.replace(/\.png$/, '') || ''; }; + // Keep the selected purpose shareable across reloads without exposing search text. + const syncGoalUrl = () => { + const url = new URL(window.location.href); + if (goal === 'all') url.searchParams.delete('goal'); + else url.searchParams.set('goal', goal); + window.history.replaceState(window.history.state, '', url.pathname + url.search + url.hash); + }; const fire = (event, data) => { if (typeof window.gtag === 'function') window.gtag('event', event, data); }; @@ -1476,6 +1483,7 @@

Chaos - Stranger Missions

goal = 'all'; lastReportedSearch = ''; buttons.forEach(button => button.setAttribute('aria-pressed', String(button.dataset.goal === 'all'))); + syncGoalUrl(); render(); input.focus(); fire('catalog_search_reset', {source: 'empty_state'}); @@ -1483,6 +1491,7 @@

Chaos - Stranger Missions

buttons.forEach(button => button.addEventListener('click', () => { goal = button.dataset.goal; buttons.forEach(b => b.setAttribute('aria-pressed', String(b === button))); + syncGoalUrl(); fire('catalog_filter_used', {goal, results: render()}); })); document.querySelectorAll('[data-detail-app]').forEach(link => { From dfaa5776e6fbeb151f5a4b7bb0b1773eee1fff7e Mon Sep 17 00:00:00 2001 From: appdevelopsk Date: Sat, 7 Nov 2026 08:44:25 +0900 Subject: [PATCH 2/2] test(catalog): guard deep-link sync and privacy of manual filters --- scripts/test_guide_catalog_links.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/scripts/test_guide_catalog_links.py b/scripts/test_guide_catalog_links.py index b013a70..a8c9281 100644 --- a/scripts/test_guide_catalog_links.py +++ b/scripts/test_guide_catalog_links.py @@ -55,6 +55,23 @@ def test_missing_baseline_app_is_rejected(self): cards = '' * (MIN_CATALOG_CARDS - 1) self.assertFalse(catalog_card_count_ok(cards)) + def test_manual_filter_syncs_shareable_goal_url(self): + catalog = (ROOT / "apps.html").read_text(encoding="utf-8") + self.assertIn("const syncGoalUrl = () =>", catalog) + self.assertIn("url.searchParams.set('goal', goal)", catalog) + self.assertIn("url.searchParams.delete('goal')", catalog) + self.assertIn("window.history.replaceState(", catalog) + self.assertIn("url.pathname + url.search + url.hash", catalog) + self.assertEqual(catalog.count(" syncGoalUrl();"), 2) + + def test_filter_url_does_not_capture_private_search_text(self): + catalog = (ROOT / "apps.html").read_text(encoding="utf-8") + start = catalog.index("const syncGoalUrl = () =>") + end = catalog.index(" const fire =", start) + sync_code = catalog[start:end] + self.assertNotIn("input.value", sync_code) + self.assertNotIn("find-app", sync_code) + def test_catalog_cards_and_details_preserved(self): catalog = (ROOT / "apps.html").read_text(encoding="utf-8") self.assertTrue(catalog_card_count_ok(catalog), "app catalog fell below the 92-card baseline")