mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-10-09 12:23:37 +02:00
add reply and repost toggles to hashtag view
This commit is contained in:
29
src/components/note-filter-type-buttons.tsx
Normal file
29
src/components/note-filter-type-buttons.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { ButtonGroup, ButtonGroupProps, IconButton } from "@chakra-ui/react";
|
||||||
|
import { ReplyIcon, RepostIcon } from "./icons";
|
||||||
|
|
||||||
|
type Disclosure = { isOpen: boolean; onToggle: () => void };
|
||||||
|
|
||||||
|
export default function NoteFilterTypeButtons({
|
||||||
|
showReplies,
|
||||||
|
showReposts,
|
||||||
|
...props
|
||||||
|
}: Omit<ButtonGroupProps, "children"> & { showReplies: Disclosure; showReposts: Disclosure }) {
|
||||||
|
return (
|
||||||
|
<ButtonGroup variant="outline" {...props}>
|
||||||
|
<IconButton
|
||||||
|
icon={<ReplyIcon boxSize={5} />}
|
||||||
|
colorScheme={showReplies.isOpen ? "primary" : undefined}
|
||||||
|
aria-label="Toggle replies"
|
||||||
|
title="Toggle replies"
|
||||||
|
onClick={showReplies.onToggle}
|
||||||
|
/>
|
||||||
|
<IconButton
|
||||||
|
icon={<RepostIcon boxSize={5} />}
|
||||||
|
colorScheme={showReposts.isOpen ? "primary" : undefined}
|
||||||
|
aria-label="Toggle reposts"
|
||||||
|
title="Toggle reposts"
|
||||||
|
onClick={showReposts.onToggle}
|
||||||
|
/>
|
||||||
|
</ButtonGroup>
|
||||||
|
);
|
||||||
|
}
|
@@ -10,15 +10,15 @@ import {
|
|||||||
IconButton,
|
IconButton,
|
||||||
Input,
|
Input,
|
||||||
Spacer,
|
Spacer,
|
||||||
Switch,
|
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
useEditableControls,
|
useEditableControls,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { CloseIcon } from "@chakra-ui/icons";
|
import { CloseIcon } from "@chakra-ui/icons";
|
||||||
|
|
||||||
import { useLocation, useNavigate, useParams } from "react-router-dom";
|
import { useLocation, useNavigate, useParams } from "react-router-dom";
|
||||||
import { useAppTitle } from "../../hooks/use-app-title";
|
import { useAppTitle } from "../../hooks/use-app-title";
|
||||||
import useTimelineLoader from "../../hooks/use-timeline-loader";
|
import useTimelineLoader from "../../hooks/use-timeline-loader";
|
||||||
import { isReply } from "../../helpers/nostr/events";
|
import { isReply, isRepost } from "../../helpers/nostr/events";
|
||||||
import { CheckIcon, EditIcon } from "../../components/icons";
|
import { CheckIcon, EditIcon } from "../../components/icons";
|
||||||
import { NostrEvent } from "../../types/nostr-event";
|
import { NostrEvent } from "../../types/nostr-event";
|
||||||
import RelaySelectionButton from "../../components/relay-selection/relay-selection-button";
|
import RelaySelectionButton from "../../components/relay-selection/relay-selection-button";
|
||||||
@@ -29,6 +29,7 @@ import TimelineViewTypeButtons from "../../components/timeline-page/timeline-vie
|
|||||||
import useClientSideMuteFilter from "../../hooks/use-client-side-mute-filter";
|
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";
|
||||||
|
|
||||||
function EditableControls() {
|
function EditableControls() {
|
||||||
const { isEditing, getSubmitButtonProps, getCancelButtonProps, getEditButtonProps } = useEditableControls();
|
const { isEditing, getSubmitButtonProps, getCancelButtonProps, getEditButtonProps } = useEditableControls();
|
||||||
@@ -52,8 +53,10 @@ function HashTagPage() {
|
|||||||
|
|
||||||
useAppTitle("#" + hashtag);
|
useAppTitle("#" + hashtag);
|
||||||
|
|
||||||
|
const showReplies = useDisclosure({ defaultIsOpen: true });
|
||||||
|
const showReposts = useDisclosure({ defaultIsOpen: true });
|
||||||
|
|
||||||
const readRelays = useRelaySelectionRelays();
|
const readRelays = useRelaySelectionRelays();
|
||||||
const { isOpen: showReplies, onToggle } = useDisclosure();
|
|
||||||
|
|
||||||
const { listId, filter } = usePeopleListContext();
|
const { listId, filter } = usePeopleListContext();
|
||||||
const timelinePageEventFilter = useTimelinePageEventFilter();
|
const timelinePageEventFilter = useTimelinePageEventFilter();
|
||||||
@@ -61,10 +64,11 @@ function HashTagPage() {
|
|||||||
const eventFilter = useCallback(
|
const eventFilter = useCallback(
|
||||||
(event: NostrEvent) => {
|
(event: NostrEvent) => {
|
||||||
if (muteFilter(event)) return false;
|
if (muteFilter(event)) return false;
|
||||||
if (!showReplies && isReply(event)) return false;
|
if (!showReplies.isOpen && isReply(event)) return false;
|
||||||
|
if (!showReposts.isOpen && isRepost(event)) return false;
|
||||||
return timelinePageEventFilter(event);
|
return timelinePageEventFilter(event);
|
||||||
},
|
},
|
||||||
[showReplies, muteFilter, timelinePageEventFilter],
|
[showReplies.isOpen, showReposts.isOpen, muteFilter, timelinePageEventFilter],
|
||||||
);
|
);
|
||||||
const timeline = useTimelineLoader(
|
const timeline = useTimelineLoader(
|
||||||
`${listId ?? "global"}-${hashtag}-hashtag`,
|
`${listId ?? "global"}-${hashtag}-hashtag`,
|
||||||
@@ -97,12 +101,7 @@ function HashTagPage() {
|
|||||||
</Editable>
|
</Editable>
|
||||||
<PeopleListSelection />
|
<PeopleListSelection />
|
||||||
<RelaySelectionButton />
|
<RelaySelectionButton />
|
||||||
<FormControl display="flex" alignItems="center" w="auto">
|
<NoteFilterTypeButtons showReplies={showReplies} showReposts={showReposts} />
|
||||||
<Switch id="show-replies" isChecked={showReplies} onChange={onToggle} mr="2" />
|
|
||||||
<FormLabel htmlFor="show-replies" mb="0">
|
|
||||||
Show Replies
|
|
||||||
</FormLabel>
|
|
||||||
</FormControl>
|
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<TimelineViewTypeButtons />
|
<TimelineViewTypeButtons />
|
||||||
</Flex>
|
</Flex>
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { useCallback, useEffect, useMemo } from "react";
|
import { useCallback, useEffect, useMemo } from "react";
|
||||||
import { ButtonGroup, Flex, IconButton, useDisclosure } from "@chakra-ui/react";
|
import { Flex, useDisclosure } from "@chakra-ui/react";
|
||||||
import { Kind } from "nostr-tools";
|
import { Kind } from "nostr-tools";
|
||||||
|
|
||||||
import { isReply, isRepost } from "../../helpers/nostr/events";
|
import { isReply, isRepost } from "../../helpers/nostr/events";
|
||||||
@@ -13,7 +13,7 @@ import PeopleListProvider, { usePeopleListContext } from "../../providers/people
|
|||||||
import RelaySelectionProvider, { useRelaySelectionContext } from "../../providers/relay-selection-provider";
|
import RelaySelectionProvider, { useRelaySelectionContext } from "../../providers/relay-selection-provider";
|
||||||
import { NostrRequestFilter } from "../../types/nostr-query";
|
import { NostrRequestFilter } from "../../types/nostr-query";
|
||||||
import useClientSideMuteFilter from "../../hooks/use-client-side-mute-filter";
|
import useClientSideMuteFilter from "../../hooks/use-client-side-mute-filter";
|
||||||
import { ReplyIcon, RepostIcon } from "../../components/icons";
|
import NoteFilterTypeButtons from "../../components/note-filter-type-buttons";
|
||||||
|
|
||||||
function HomePage() {
|
function HomePage() {
|
||||||
const showReplies = useDisclosure({ defaultIsOpen: localStorage.getItem("show-replies") === "true" });
|
const showReplies = useDisclosure({ defaultIsOpen: localStorage.getItem("show-replies") === "true" });
|
||||||
@@ -54,22 +54,7 @@ function HomePage() {
|
|||||||
const header = (
|
const header = (
|
||||||
<Flex gap="2" wrap="wrap" px={["2", 0]} alignItems="center">
|
<Flex gap="2" wrap="wrap" px={["2", 0]} alignItems="center">
|
||||||
<PeopleListSelection />
|
<PeopleListSelection />
|
||||||
<ButtonGroup variant="outline">
|
<NoteFilterTypeButtons showReplies={showReplies} showReposts={showReposts} />
|
||||||
<IconButton
|
|
||||||
icon={<ReplyIcon boxSize={5} />}
|
|
||||||
colorScheme={showReplies.isOpen ? "primary" : undefined}
|
|
||||||
aria-label="Toggle replies"
|
|
||||||
title="Toggle replies"
|
|
||||||
onClick={showReplies.onToggle}
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
icon={<RepostIcon boxSize={5} />}
|
|
||||||
colorScheme={showReposts.isOpen ? "primary" : undefined}
|
|
||||||
aria-label="Toggle reposts"
|
|
||||||
title="Toggle reposts"
|
|
||||||
onClick={showReposts.onToggle}
|
|
||||||
/>
|
|
||||||
</ButtonGroup>
|
|
||||||
<RelaySelectionButton ml="auto" />
|
<RelaySelectionButton ml="auto" />
|
||||||
<TimelineViewTypeButtons />
|
<TimelineViewTypeButtons />
|
||||||
</Flex>
|
</Flex>
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
import { ButtonGroup, Flex, IconButton, Spacer, useDisclosure } from "@chakra-ui/react";
|
import { Flex, Spacer, useDisclosure } 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";
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ import useTimelineLoader from "../../hooks/use-timeline-loader";
|
|||||||
import { STREAM_KIND } from "../../helpers/nostr/stream";
|
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 { ReplyIcon, RepostIcon } from "../../components/icons";
|
import NoteFilterTypeButtons from "../../components/note-filter-type-buttons";
|
||||||
|
|
||||||
export default function UserNotesTab() {
|
export default function UserNotesTab() {
|
||||||
const { pubkey } = useOutletContext() as { pubkey: string };
|
const { pubkey } = useOutletContext() as { pubkey: string };
|
||||||
@@ -41,22 +41,7 @@ export default function UserNotesTab() {
|
|||||||
|
|
||||||
const header = (
|
const header = (
|
||||||
<Flex gap="2" alignItems="center">
|
<Flex gap="2" alignItems="center">
|
||||||
<ButtonGroup variant="outline">
|
<NoteFilterTypeButtons showReplies={showReplies} showReposts={showReposts} />
|
||||||
<IconButton
|
|
||||||
icon={<ReplyIcon boxSize={5} />}
|
|
||||||
colorScheme={showReplies.isOpen ? "primary" : undefined}
|
|
||||||
aria-label="Toggle replies"
|
|
||||||
title="Toggle replies"
|
|
||||||
onClick={showReplies.onToggle}
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
icon={<RepostIcon boxSize={5} />}
|
|
||||||
colorScheme={showReposts.isOpen ? "primary" : undefined}
|
|
||||||
aria-label="Toggle reposts"
|
|
||||||
title="Toggle reposts"
|
|
||||||
onClick={showReposts.onToggle}
|
|
||||||
/>
|
|
||||||
</ButtonGroup>
|
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<RelayIconStack relays={readRelays} direction="row-reverse" maxRelays={4} />
|
<RelayIconStack relays={readRelays} direction="row-reverse" maxRelays={4} />
|
||||||
<TimelineViewType />
|
<TimelineViewType />
|
||||||
|
Reference in New Issue
Block a user