mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-09-19 12:00:32 +02:00
store the filter state in route state
This commit is contained in:
60
src/hooks/use-route-state-value.ts
Normal file
60
src/hooks/use-route-state-value.ts
Normal 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 };
|
||||||
|
}
|
@@ -5,12 +5,9 @@ import {
|
|||||||
EditableInput,
|
EditableInput,
|
||||||
EditablePreview,
|
EditablePreview,
|
||||||
Flex,
|
Flex,
|
||||||
FormControl,
|
|
||||||
FormLabel,
|
|
||||||
IconButton,
|
IconButton,
|
||||||
Input,
|
Input,
|
||||||
Spacer,
|
Spacer,
|
||||||
useDisclosure,
|
|
||||||
useEditableControls,
|
useEditableControls,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { CloseIcon } from "@chakra-ui/icons";
|
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 PeopleListProvider, { usePeopleListContext } from "../../providers/people-list-provider";
|
||||||
import PeopleListSelection from "../../components/people-list-selection/people-list-selection";
|
import PeopleListSelection from "../../components/people-list-selection/people-list-selection";
|
||||||
import NoteFilterTypeButtons from "../../components/note-filter-type-buttons";
|
import NoteFilterTypeButtons from "../../components/note-filter-type-buttons";
|
||||||
|
import { useRouteStateBoolean } from "../../hooks/use-route-state-value";
|
||||||
|
|
||||||
function EditableControls() {
|
function EditableControls() {
|
||||||
const { isEditing, getSubmitButtonProps, getCancelButtonProps, getEditButtonProps } = useEditableControls();
|
const { isEditing, getSubmitButtonProps, getCancelButtonProps, getEditButtonProps } = useEditableControls();
|
||||||
@@ -53,8 +51,8 @@ function HashTagPage() {
|
|||||||
|
|
||||||
useAppTitle("#" + hashtag);
|
useAppTitle("#" + hashtag);
|
||||||
|
|
||||||
const showReplies = useDisclosure({ defaultIsOpen: true });
|
const showReplies = useRouteStateBoolean("show-replies", true);
|
||||||
const showReposts = useDisclosure({ defaultIsOpen: true });
|
const showReposts = useRouteStateBoolean("show-reposts", true);
|
||||||
|
|
||||||
const readRelays = useRelaySelectionRelays();
|
const readRelays = useRelaySelectionRelays();
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { useCallback } from "react";
|
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 { useOutletContext } from "react-router-dom";
|
||||||
import { Kind } from "nostr-tools";
|
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 TimelineViewType from "../../components/timeline-page/timeline-view-type";
|
||||||
import TimelinePage, { useTimelinePageEventFilter } from "../../components/timeline-page";
|
import TimelinePage, { useTimelinePageEventFilter } from "../../components/timeline-page";
|
||||||
import NoteFilterTypeButtons from "../../components/note-filter-type-buttons";
|
import NoteFilterTypeButtons from "../../components/note-filter-type-buttons";
|
||||||
|
import { useRouteStateBoolean } from "../../hooks/use-route-state-value";
|
||||||
|
|
||||||
export default function UserNotesTab() {
|
export default function UserNotesTab() {
|
||||||
const { pubkey } = useOutletContext() as { pubkey: string };
|
const { pubkey } = useOutletContext() as { pubkey: string };
|
||||||
const readRelays = useAdditionalRelayContext();
|
const readRelays = useAdditionalRelayContext();
|
||||||
|
|
||||||
const showReplies = useDisclosure();
|
const showReplies = useRouteStateBoolean("show-replies", false);
|
||||||
const showReposts = useDisclosure({ defaultIsOpen: true });
|
const showReposts = useRouteStateBoolean("show-reposts", true);
|
||||||
|
|
||||||
const timelineEventFilter = useTimelinePageEventFilter();
|
const timelineEventFilter = useTimelinePageEventFilter();
|
||||||
const eventFilter = useCallback(
|
const eventFilter = useCallback(
|
||||||
|
Reference in New Issue
Block a user