From 767f9c508be763668bc0cc5c67204372d0cde48e Mon Sep 17 00:00:00 2001 From: ergosteur <1992147+ergosteur@users.noreply.github.com> Date: Sat, 7 Mar 2026 05:07:04 -0500 Subject: [PATCH] feat: implement permalinks for archives, tabs, and posts --- src/App.tsx | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/App.tsx b/src/App.tsx index 018555d..2777000 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -651,6 +651,56 @@ export default function App() { refreshCachedArchives(); }, [refreshCachedArchives]); + // --- Permalink Synchronization --- + + // Update URL based on state + useEffect(() => { + const params = new URLSearchParams(); + if (currentArchive) params.set('a', currentArchive.name); + if (activeTab !== 'posts') params.set('t', activeTab); + if (selectedPost) params.set('p', selectedPost.id); + + const newSearch = params.toString(); + const currentSearch = window.location.search.replace(/^\?/, ''); + + if (newSearch !== currentSearch) { + const newUrl = window.location.pathname + (newSearch ? `?${newSearch}` : ''); + window.history.replaceState(null, '', newUrl); + } + }, [currentArchive?.name, activeTab, selectedPost?.id]); + + // Read state from URL on mount/initialization + const [hasInitialLoaded, setHasInitialLoaded] = useState(false); + useEffect(() => { + if (hasInitialLoaded || serverArchives.length === 0) return; + + const params = new URLSearchParams(window.location.search); + const archiveName = params.get('a'); + const tab = params.get('t'); + const postId = params.get('p'); + + if (archiveName) { + const archive = serverArchives.find(a => a.name === archiveName); + if (archive) { + loadServerArchive(archive); + if (tab && ['posts', 'reels', 'saved'].includes(tab)) { + setActiveTab(tab as any); + } + } + } + setHasInitialLoaded(true); + }, [serverArchives, hasInitialLoaded]); + + // Auto-open post if postId is in URL and posts are loaded + useEffect(() => { + const params = new URLSearchParams(window.location.search); + const postId = params.get('p'); + if (postId && allPosts.length > 0 && !selectedPost) { + const post = allPosts.find(p => p.id === postId); + if (post) setSelectedPost(post); + } + }, [allPosts, selectedPost]); + // Intercept back button and page exit useEffect(() => { const hasData = allPosts.length > 0;