From 8ac3dd27dd5fe7ecd5a0ce2dc7b86d305b46b8d0 Mon Sep 17 00:00:00 2001 From: Chuck Dries Date: Sun, 10 Jul 2022 16:11:07 -0700 Subject: [PATCH] manually manage filter and sort storage --- TODO.md | 2 +- package.json | 1 - src/components/MasonryGallery.js | 20 -------- src/pages/photogallery/[...].js | 84 ++++++++++++++++++++++++++------ yarn.lock | 17 ------- 5 files changed, 69 insertions(+), 55 deletions(-) diff --git a/TODO.md b/TODO.md index 8db093d..3e11d04 100644 --- a/TODO.md +++ b/TODO.md @@ -3,5 +3,5 @@ - [ ] tags - [ ] photo stories/collection pages - [ ] typescript (w/ graphql codegen) -- [ ] gallery sort and filter preserved in url (use-query or whatever?) +- [x] gallery sort and filter preserved in url (use-query or whatever?) - [ ] nav next/prev buttons use saved gallery sort and filter diff --git a/package.json b/package.json index 8fc9c6b..d2554ab 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "react-div-100vh": "^0.7.0", "react-dom": "^17.0.1", "react-helmet": "^6.1.0", - "react-use-query-param-string": "^2.0.3", "sass": "^1.34.0", "tailwindcss": "^2.1.2", "use-breakpoint": "^2.0.1" diff --git a/src/components/MasonryGallery.js b/src/components/MasonryGallery.js index f459911..d0e2cbc 100644 --- a/src/components/MasonryGallery.js +++ b/src/components/MasonryGallery.js @@ -21,26 +21,6 @@ const MasonryGallery = ({ const { breakpoint } = useBreakpoint(breakpoints, "sm"); - const scrollIntoView = React.useCallback(() => { - if (!window.location.hash) { - return; - } - const el = document.getElementById(window.location.hash.split("#")[1]); - if (!el) { - return; - } - el.scrollIntoView({ - block: "center", - }); - }, []); - - React.useEffect(() => { - // hacky but it works for now - setTimeout(() => { - scrollIntoView(); - }, 100); - }, [scrollIntoView]); - const aspectRatios = React.useMemo( () => R.map(getAspectRatio, images), [images] diff --git a/src/pages/photogallery/[...].js b/src/pages/photogallery/[...].js index 5fe6b8e..2cfd54a 100644 --- a/src/pages/photogallery/[...].js +++ b/src/pages/photogallery/[...].js @@ -7,8 +7,6 @@ import { Picker, Item } from "@adobe/react-spectrum"; import MasonryGallery from "../../components/MasonryGallery"; import KeywordsPicker from "../../components/KeywordsPicker"; -import { useQueryParamString } from "react-use-query-param-string"; -import { useState } from "react"; const SORT_KEYS = { hue: ["fields", "imageMeta", "vibrantHue"], @@ -17,46 +15,100 @@ const SORT_KEYS = { date: [], }; +const getUrl = ({ keyword, sortKey }) => { + const url = new URL(window.location.toString()); + if (keyword !== undefined) { + if (keyword === null) { + url.searchParams.delete("filter"); + } else { + url.searchParams.set("filter", keyword); + } + } + if (sortKey !== undefined) { + if (sortKey === "rating") { + url.searchParams.delete("sort"); + } else { + url.searchParams.set("sort", sortKey); + } + } + return url.toString(); +}; + const GalleryPage = ({ data }) => { - const [keyword, _setKeyword] = useQueryParamString("filter", null); - const [showDebug, _setShowDebug] = useQueryParamString("debug", false); - const [sortKey, _setSortKey] = useState("rating"); + const [keyword, _setKeyword] = React.useState(null); + const [sortKey, _setSortKey] = React.useState("rating"); + const showDebug = + typeof window !== "undefined" && + window.location.search.includes("debug=true"); const setKeyword = React.useCallback( - (keyword) => { + (newKeyword) => { try { window.plausible("Filter Keyword", { - props: { keyword }, + props: { keyword: newKeyword }, }); } catch (e) { // do nothing } - _setKeyword(keyword); + _setKeyword(newKeyword); + localStorage?.setItem("photogallery.keyword", newKeyword); + window.history.replaceState(null, "", getUrl({ keyword: newKeyword })); }, [_setKeyword] ); const setSortKey = React.useCallback( - (key) => { + (newSortKey) => { try { window.plausible("Sort Gallery", { - props: { key }, + props: { key: newSortKey }, }); } catch (e) { // do nothing } - localStorage?.setItem("photogallery.sortkey2", key); - _setSortKey(key); + _setSortKey(newSortKey); + localStorage?.setItem("photogallery.sortkey2", newSortKey); + window.history.replaceState(null, "", getUrl({ sortKey: newSortKey })); }, [_setSortKey] ); React.useEffect(() => { - const _sortKey = localStorage.getItem("photogallery.sortkey2"); - if (_sortKey) { - setSortKey(_sortKey); + const url = new URL(window.location.toString()); + + const sortKeyFromUrl = url.searchParams.get("sort"); + const sortKeyFromStorage = localStorage.getItem("photogallery.sortkey2"); + if (sortKeyFromUrl || sortKeyFromStorage) { + setSortKey(sortKeyFromUrl || sortKeyFromStorage); } - }, [setSortKey]); + + const filterKeyFromUrl = url.searchParams.get("filter"); + const filterKeyFromStorage = localStorage.getItem("photogallery.keyword"); + if (filterKeyFromUrl || filterKeyFromStorage !== "null") { + setKeyword(filterKeyFromUrl || filterKeyFromStorage); + } + }, [setSortKey, setKeyword]); + + const scrollIntoView = React.useCallback(() => { + if (!window.location.hash) { + return; + } + const el = document.getElementById(window.location.hash.split("#")[1]); + if (!el) { + return; + } + el.scrollIntoView({ + block: "center", + }); + }, []); + + React.useEffect(() => { + // hacky but it works for now + setTimeout(() => { + // don't scroll into view if user got here with back button + scrollIntoView(); + }, 100); + }, [scrollIntoView]); const images = React.useMemo( () => diff --git a/yarn.lock b/yarn.lock index a1195e2..8b18698 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12282,16 +12282,6 @@ query-string@^6.13.8, query-string@^6.14.1: split-on-first "^1.0.0" strict-uri-encode "^2.0.0" -query-string@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.1.tgz#754620669db978625a90f635f12617c271a088e1" - integrity sha512-MplouLRDHBZSG9z7fpuAAcI7aAYjDLhtsiVZsevsfaHWDS2IDdORKbSd1kWUA+V4zyva/HZoSfpwnYMMQDhb0w== - dependencies: - decode-uri-component "^0.2.0" - filter-obj "^1.1.0" - split-on-first "^1.0.0" - strict-uri-encode "^2.0.0" - querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" @@ -12481,13 +12471,6 @@ react-transition-group@^4.4.2: loose-envify "^1.4.0" prop-types "^15.6.2" -react-use-query-param-string@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/react-use-query-param-string/-/react-use-query-param-string-2.0.3.tgz#e1b986f9c49c5b9caad7a6a1c3c5a8f0bb841483" - integrity sha512-6rAimAH+IL0Ghq9EDs0Ywg0E51eeT1Uo6wY+JbwUEQvLiKfMKY8lsHlEqLtEj6udnVFUA4kEspGf2LBxpiknVw== - dependencies: - query-string "^7.1.1" - react@^17.0.1: version "17.0.2" resolved "https://registry.npmjs.org/react/-/react-17.0.2.tgz"