store the filter state in route state

This commit is contained in:
hzrd149 2023-12-17 10:06:22 -06:00
parent 0396b8d2ad
commit 66f351e944
3 changed files with 67 additions and 8 deletions

View File

@ -0,0 +1,60 @@
import { useCallback, useRef } from "react";
import { useLocation, useNavigate } from "react-router-dom";
type Actions<T> = {
setValue: (v: T | ((v: T | undefined) => T)) => void;
clearValue: () => void;
};
export default function useRouteStateValue<T extends unknown>(key: string, fallback: T): { value: T } & Actions<T>;
export default function useRouteStateValue<T extends unknown>(
key: string,
fallback?: T,
): { value: T | undefined } & Actions<T>;
export default function useRouteStateValue<T extends unknown>(key: string, fallback?: T) {
const navigate = useNavigate();
const location = useLocation();
const stateRef = useRef<Record<string, any>>(location.state ?? {});
stateRef.current = location.state ?? {};
const valueRef = useRef<T>(stateRef.current[key] ?? fallback);
valueRef.current = stateRef.current[key] ?? fallback;
const setValue = useCallback(
(valueOrSetter: T | ((v: T) => T)) => {
const newState = { ...stateRef.current };
if (typeof valueOrSetter === "function") {
// @ts-ignore
newState[key] = valueOrSetter(valueRef.current);
} else newState[key] = valueOrSetter;
if (stateRef.current[key] !== newState[key]) {
navigate(".", { state: newState, replace: true });
}
},
[key],
);
const clearValue = useCallback(() => {
const newState = { ...stateRef.current };
delete newState[key];
navigate(".", newState);
}, [key]);
return { value: valueRef.current, setValue, clearValue };
}
export function useRouteStateBoolean(key: string, fallback?: boolean) {
const stateValue = useRouteStateValue<boolean>(key, fallback ?? false);
const onOpen = useCallback(() => {
stateValue.setValue(true);
}, [stateValue.setValue]);
const onClose = useCallback(() => {
stateValue.setValue(false);
}, [stateValue.setValue]);
const onToggle = useCallback(() => {
stateValue.setValue((v) => !v);
}, [stateValue.setValue]);
return { isOpen: stateValue.value, onOpen, onClose, onToggle };
}

View File

@ -5,12 +5,9 @@ import {
EditableInput,
EditablePreview,
Flex,
FormControl,
FormLabel,
IconButton,
Input,
Spacer,
useDisclosure,
useEditableControls,
} from "@chakra-ui/react";
import { CloseIcon } from "@chakra-ui/icons";
@ -30,6 +27,7 @@ import useClientSideMuteFilter from "../../hooks/use-client-side-mute-filter";
import PeopleListProvider, { usePeopleListContext } from "../../providers/people-list-provider";
import PeopleListSelection from "../../components/people-list-selection/people-list-selection";
import NoteFilterTypeButtons from "../../components/note-filter-type-buttons";
import { useRouteStateBoolean } from "../../hooks/use-route-state-value";
function EditableControls() {
const { isEditing, getSubmitButtonProps, getCancelButtonProps, getEditButtonProps } = useEditableControls();
@ -53,8 +51,8 @@ function HashTagPage() {
useAppTitle("#" + hashtag);
const showReplies = useDisclosure({ defaultIsOpen: true });
const showReposts = useDisclosure({ defaultIsOpen: true });
const showReplies = useRouteStateBoolean("show-replies", true);
const showReposts = useRouteStateBoolean("show-reposts", true);
const readRelays = useRelaySelectionRelays();

View File

@ -1,5 +1,5 @@
import { useCallback } from "react";
import { Flex, Spacer, useDisclosure } from "@chakra-ui/react";
import { Flex, Spacer } from "@chakra-ui/react";
import { useOutletContext } from "react-router-dom";
import { Kind } from "nostr-tools";
@ -12,13 +12,14 @@ import { STREAM_KIND } from "../../helpers/nostr/stream";
import TimelineViewType from "../../components/timeline-page/timeline-view-type";
import TimelinePage, { useTimelinePageEventFilter } from "../../components/timeline-page";
import NoteFilterTypeButtons from "../../components/note-filter-type-buttons";
import { useRouteStateBoolean } from "../../hooks/use-route-state-value";
export default function UserNotesTab() {
const { pubkey } = useOutletContext() as { pubkey: string };
const readRelays = useAdditionalRelayContext();
const showReplies = useDisclosure();
const showReposts = useDisclosure({ defaultIsOpen: true });
const showReplies = useRouteStateBoolean("show-replies", false);
const showReposts = useRouteStateBoolean("show-reposts", true);
const timelineEventFilter = useTimelinePageEventFilter();
const eventFilter = useCallback(