From d5a50d0c6faf8c8a638cb7be1e58af810e987475 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 19 Sep 2023 07:23:05 -0500 Subject: [PATCH 1/4] Fix follow and mute button not updating when switching accounts --- .changeset/wet-plants-joke.md | 5 +++++ src/components/user-follow-button.tsx | 5 ++--- src/hooks/use-async-error-handler.ts | 2 +- src/hooks/use-user-mute-functions.ts | 4 ++-- src/views/hashtag/index.tsx | 5 ++++- src/views/lists/components/user-card.tsx | 2 +- 6 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 .changeset/wet-plants-joke.md diff --git a/.changeset/wet-plants-joke.md b/.changeset/wet-plants-joke.md new file mode 100644 index 000000000..37808e35f --- /dev/null +++ b/.changeset/wet-plants-joke.md @@ -0,0 +1,5 @@ +--- +"nostrudel": patch +--- + +Fix follow and mute button not updating when switching accounts diff --git a/src/components/user-follow-button.tsx b/src/components/user-follow-button.tsx index 4dfab7934..c55d94f40 100644 --- a/src/components/user-follow-button.tsx +++ b/src/components/user-follow-button.tsx @@ -34,7 +34,6 @@ import useUserContactList from "../hooks/use-user-contact-list"; import replaceableEventLoaderService from "../services/replaceable-event-requester"; import useAsyncErrorHandler from "../hooks/use-async-error-handler"; import NewListModal from "../views/lists/components/new-list-modal"; -import useUserMuteList from "../hooks/use-user-mute-list"; import useUserMuteFunctions from "../hooks/use-user-mute-functions"; function UsersLists({ pubkey }: { pubkey: string }) { @@ -129,13 +128,13 @@ export const UserFollowButton = ({ pubkey, showLists, ...props }: UserFollowButt const signed = await requestSignature(draft); const pub = new NostrPublishAction("Follow", clientRelaysService.getWriteUrls(), signed); replaceableEventLoaderService.handleEvent(signed); - }); + }, [contacts, requestSignature]); const handleUnfollow = useAsyncErrorHandler(async () => { const draft = draftRemovePerson(contacts || createEmptyContactList(), pubkey); const signed = await requestSignature(draft); const pub = new NostrPublishAction("Unfollow", clientRelaysService.getWriteUrls(), signed); replaceableEventLoaderService.handleEvent(signed); - }); + }, [contacts, requestSignature]); if (showLists) { return ( diff --git a/src/hooks/use-async-error-handler.ts b/src/hooks/use-async-error-handler.ts index 10b9709cf..c074d6cc1 100644 --- a/src/hooks/use-async-error-handler.ts +++ b/src/hooks/use-async-error-handler.ts @@ -3,7 +3,7 @@ import { DependencyList, useCallback } from "react"; export default function useAsyncErrorHandler( fn: () => Promise, - deps: DependencyList = [], + deps: DependencyList, ): () => Promise { const toast = useToast(); diff --git a/src/hooks/use-user-mute-functions.ts b/src/hooks/use-user-mute-functions.ts index 73bf96caa..8ae2a9271 100644 --- a/src/hooks/use-user-mute-functions.ts +++ b/src/hooks/use-user-mute-functions.ts @@ -19,13 +19,13 @@ export default function useUserMuteFunctions(pubkey: string) { const signed = await requestSignature(draft); new NostrPublishAction("Mute", clientRelaysService.getWriteUrls(), signed); replaceableEventLoaderService.handleEvent(signed); - }); + }, [requestSignature, muteList]); const unmute = useAsyncErrorHandler(async () => { const draft = draftRemovePerson(muteList || createEmptyMuteList(), pubkey); const signed = await requestSignature(draft); new NostrPublishAction("Unmute", clientRelaysService.getWriteUrls(), signed); replaceableEventLoaderService.handleEvent(signed); - }); + }, [requestSignature, muteList]); return { isMuted, mute, unmute }; } diff --git a/src/views/hashtag/index.tsx b/src/views/hashtag/index.tsx index 83da1290d..c10c040e2 100644 --- a/src/views/hashtag/index.tsx +++ b/src/views/hashtag/index.tsx @@ -26,6 +26,7 @@ import RelaySelectionProvider, { useRelaySelectionRelays } from "../../providers import useRelaysChanged from "../../hooks/use-relays-changed"; import TimelinePage, { useTimelinePageEventFilter } from "../../components/timeline-page"; import TimelineViewTypeButtons from "../../components/timeline-page/timeline-view-type"; +import useClientSideMuteFilter from "../../hooks/use-client-side-mute-filter"; function EditableControls() { const { isEditing, getSubmitButtonProps, getCancelButtonProps, getEditButtonProps } = useEditableControls(); @@ -52,12 +53,14 @@ function HashTagPage() { const { isOpen: showReplies, onToggle } = useDisclosure(); const timelinePageEventFilter = useTimelinePageEventFilter(); + const muteFilter = useClientSideMuteFilter(); const eventFilter = useCallback( (event: NostrEvent) => { + if (muteFilter(event)) return false; if (!showReplies && isReply(event)) return false; return timelinePageEventFilter(event); }, - [showReplies], + [showReplies, muteFilter, timelinePageEventFilter], ); const timeline = useTimelineLoader( `${hashtag}-hashtag`, diff --git a/src/views/lists/components/user-card.tsx b/src/views/lists/components/user-card.tsx index 3f43d4634..4ecc9ce72 100644 --- a/src/views/lists/components/user-card.tsx +++ b/src/views/lists/components/user-card.tsx @@ -26,7 +26,7 @@ export default function UserCard({ pubkey, relay, list, ...props }: UserCardProp const draft = draftRemovePerson(list, pubkey); const signed = await requestSignature(draft); const pub = new NostrPublishAction("Remove from list", clientRelaysService.getWriteUrls(), signed); - }, [list]); + }, [list, requestSignature]); return ( From f440e816d15d7c84e86bf83eaf314d64a9268b40 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 19 Sep 2023 08:03:39 -0500 Subject: [PATCH 2/4] cleanup sidenav --- .changeset/nervous-pigs-judge.md | 5 + src/components/connected-relays.tsx | 7 +- src/components/layout/desktop-side-nav.tsx | 50 ++++--- src/components/layout/mobile-side-drawer.tsx | 24 +-- src/components/layout/nav-items.tsx | 138 ++++++++++++++---- .../{profile-link.tsx => profile-button.tsx} | 19 +-- src/views/badges/index.tsx | 14 +- src/views/lists/index.tsx | 10 +- src/views/map/index.tsx | 5 +- src/views/tools/index.tsx | 2 + 10 files changed, 181 insertions(+), 93 deletions(-) create mode 100644 .changeset/nervous-pigs-judge.md rename src/components/layout/{profile-link.tsx => profile-button.tsx} (66%) diff --git a/.changeset/nervous-pigs-judge.md b/.changeset/nervous-pigs-judge.md new file mode 100644 index 000000000..dff3f101d --- /dev/null +++ b/.changeset/nervous-pigs-judge.md @@ -0,0 +1,5 @@ +--- +"nostrudel": minor +--- + +Cleanup sidenav diff --git a/src/components/connected-relays.tsx b/src/components/connected-relays.tsx index 64e9e1493..abe114f35 100644 --- a/src/components/connected-relays.tsx +++ b/src/components/connected-relays.tsx @@ -17,6 +17,7 @@ import { Tr, Th, Flex, + ButtonProps, } from "@chakra-ui/react"; import relayPoolService from "../services/relay-pool"; import { useInterval } from "react-use"; @@ -27,7 +28,7 @@ import { RelayFavicon } from "./relay-favicon"; import relayScoreboardService from "../services/relay-scoreboard"; import { RelayScoreBreakdown } from "./relay-score-breakdown"; -export const ConnectedRelays = () => { +export const ConnectedRelays = ({ ...props }: Omit) => { const { isOpen, onOpen, onClose } = useDisclosure(); const [relays, setRelays] = useState(relayPoolService.getRelays()); const sortedRelays = useMemo(() => relayScoreboardService.getRankedRelays(relays.map((r) => r.url)), [relays]); @@ -40,8 +41,8 @@ export const ConnectedRelays = () => { return ( <> - diff --git a/src/components/layout/desktop-side-nav.tsx b/src/components/layout/desktop-side-nav.tsx index 12ce976b6..6fcca7e69 100644 --- a/src/components/layout/desktop-side-nav.tsx +++ b/src/components/layout/desktop-side-nav.tsx @@ -1,12 +1,12 @@ +import { useContext } from "react"; import { Avatar, Button, Flex, FlexProps, Heading, IconButton, LinkOverlay, Text } from "@chakra-ui/react"; import { Link as RouterLink } from "react-router-dom"; + import { useCurrentAccount } from "../../hooks/use-current-account"; import accountService from "../../services/account"; -import { ConnectedRelays } from "../connected-relays"; import { EditIcon, LogoutIcon } from "../icons"; -import ProfileLink from "./profile-link"; +import ProfileButton from "./profile-button"; import AccountSwitcher from "./account-switcher"; -import { useContext } from "react"; import { PostModalContext } from "../../providers/post-modal-provider"; import PublishLog from "../publish-log"; import NavItems from "./nav-items"; @@ -35,23 +35,38 @@ export default function DesktopSideNav(props: Omit) { noStrudel - - } - aria-label="New note" - title="New note" - w="3rem" - h="3rem" - fontSize="1.5rem" - colorScheme="brand" - onClick={() => openModal()} - flexShrink={0} - /> + {account ? ( + <> + + } + aria-label="New note" + title="New note" + w="3rem" + h="3rem" + fontSize="1.5rem" + colorScheme="brand" + onClick={() => openModal()} + flexShrink={0} + /> + + ) : ( + + )} {account && ( - )} @@ -60,9 +75,8 @@ export default function DesktopSideNav(props: Omit) { Readonly Mode )} - - + ); } diff --git a/src/components/layout/mobile-side-drawer.tsx b/src/components/layout/mobile-side-drawer.tsx index 0e72fe0a8..7e69b4e5f 100644 --- a/src/components/layout/mobile-side-drawer.tsx +++ b/src/components/layout/mobile-side-drawer.tsx @@ -13,7 +13,6 @@ import { } from "@chakra-ui/react"; import { Link as RouterLink } from "react-router-dom"; -import { ConnectedRelays } from "../connected-relays"; import { LogoutIcon } from "../icons"; import { UserAvatar } from "../user-avatar"; import { UserLink } from "../user-link"; @@ -44,19 +43,26 @@ export default function MobileSideDrawer({ ...props }: Omit - + {account && } - - {account ? ( - - ) : ( + {!account && ( )} - + + {account && ( + + )} diff --git a/src/components/layout/nav-items.tsx b/src/components/layout/nav-items.tsx index 0ec29ab1b..6780159aa 100644 --- a/src/components/layout/nav-items.tsx +++ b/src/components/layout/nav-items.tsx @@ -1,5 +1,5 @@ -import { AbsoluteCenter, Box, Button, Divider } from "@chakra-ui/react"; -import { useNavigate } from "react-router-dom"; +import { AbsoluteCenter, Box, Button, ButtonProps, Divider, Text } from "@chakra-ui/react"; +import { useLoaderData, useLocation, useNavigate } from "react-router-dom"; import { BadgeIcon, ChatIcon, @@ -14,56 +14,138 @@ import { SettingsIcon, ToolsIcon, } from "../icons"; +import { useCurrentAccount } from "../../hooks/use-current-account"; -export default function NavItems({ isInDrawer = false }: { isInDrawer?: boolean }) { +export default function NavItems() { const navigate = useNavigate(); + const location = useLocation(); + const account = useCurrentAccount(); + + const buttonProps: ButtonProps = { + py: "2", + pl: "2", + justifyContent: "flex-start", + variant: "link", + }; + + let active = "notes"; + if (location.pathname.startsWith("/notifications")) active = "notifications"; + else if (location.pathname.startsWith("/dm")) active = "dm"; + else if (location.pathname.startsWith("/streams")) active = "streams"; + else if (location.pathname.startsWith("/relays")) active = "relays"; + else if (location.pathname.startsWith("/lists")) active = "lists"; + else if (location.pathname.startsWith("/goals")) active = "goals"; + else if (location.pathname.startsWith("/badges")) active = "badges"; + else if (location.pathname.startsWith("/emojis")) active = "emojis"; + else if (location.pathname.startsWith("/settings")) active = "settings"; + else if (location.pathname.startsWith("/tools")) active = "tools"; + else if (location.pathname.startsWith("/search")) active = "search"; + else if (location.pathname.startsWith("/t/")) active = "search"; return ( <> - - - - + + + )} + - - - - - Other Stuff - - - - - - - - - diff --git a/src/components/layout/profile-link.tsx b/src/components/layout/profile-button.tsx similarity index 66% rename from src/components/layout/profile-link.tsx rename to src/components/layout/profile-button.tsx index 577b703cd..07ffaa85e 100644 --- a/src/components/layout/profile-link.tsx +++ b/src/components/layout/profile-button.tsx @@ -1,5 +1,5 @@ -import { Box, Button, ButtonProps, LinkBox, LinkOverlay } from "@chakra-ui/react"; -import { Link as RouterLink, useLocation } from "react-router-dom"; +import { LinkBox, LinkOverlay } from "@chakra-ui/react"; +import { Link as RouterLink } from "react-router-dom"; import { nip19 } from "nostr-tools"; import { UserAvatar } from "../user-avatar"; @@ -7,7 +7,7 @@ import { useCurrentAccount } from "../../hooks/use-current-account"; import { useUserMetadata } from "../../hooks/use-user-metadata"; import { getUserDisplayName } from "../../helpers/user-metadata"; -function ProfileButton() { +export default function ProfileButton() { const account = useCurrentAccount()!; const metadata = useUserMetadata(account.pubkey); @@ -37,16 +37,3 @@ function ProfileButton() { ); } - -export default function ProfileLink() { - const account = useCurrentAccount(); - const location = useLocation(); - - if (account) return ; - - return ( - - ); -} diff --git a/src/views/badges/index.tsx b/src/views/badges/index.tsx index 7a374cc64..029bfb3d6 100644 --- a/src/views/badges/index.tsx +++ b/src/views/badges/index.tsx @@ -1,11 +1,8 @@ -import { Button, Flex, Heading, Image, Link, SimpleGrid, Spacer, useDisclosure } from "@chakra-ui/react"; -import { Link as RouterLink } from "react-router-dom"; +import { Button, Flex, Image, Link, Spacer } from "@chakra-ui/react"; +import { Navigate, Link as RouterLink } from "react-router-dom"; import { useCurrentAccount } from "../../hooks/use-current-account"; import { ExternalLinkIcon } from "../../components/icons"; -import RequireCurrentAccount from "../../providers/require-current-account"; -import BadgeCard from "./components/badge-card"; -import { getEventUID } from "../../helpers/nostr/events"; import VerticalPageLayout from "../../components/vertical-page-layout"; function BadgesPage() { @@ -33,9 +30,6 @@ function BadgesPage() { } export default function BadgesView() { - return ( - - - - ); + const account = useCurrentAccount(); + return account ? : ; } diff --git a/src/views/lists/index.tsx b/src/views/lists/index.tsx index 3a7c34722..e474bae06 100644 --- a/src/views/lists/index.tsx +++ b/src/views/lists/index.tsx @@ -1,10 +1,9 @@ import { Button, Divider, Flex, Heading, Image, Link, SimpleGrid, Spacer, useDisclosure } from "@chakra-ui/react"; -import { useNavigate, Link as RouterLink } from "react-router-dom"; +import { useNavigate, Link as RouterLink, Navigate } from "react-router-dom"; import { Kind } from "nostr-tools"; import { useCurrentAccount } from "../../hooks/use-current-account"; import { ExternalLinkIcon, PlusCircleIcon } from "../../components/icons"; -import RequireCurrentAccount from "../../providers/require-current-account"; import ListCard from "./components/list-card"; import { getEventUID } from "../../helpers/nostr/events"; import useUserLists from "../../hooks/use-user-lists"; @@ -98,9 +97,6 @@ function ListsPage() { } export default function ListsView() { - return ( - - - - ); + const account = useCurrentAccount(); + return account ? : ; } diff --git a/src/views/map/index.tsx b/src/views/map/index.tsx index 76fe54a4c..baee5a7a7 100644 --- a/src/views/map/index.tsx +++ b/src/views/map/index.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect, useRef, useState } from "react"; -import { Link as RouterLink, useSearchParams } from "react-router-dom"; +import { useNavigate, useSearchParams } from "react-router-dom"; import { Box, Button, Flex } from "@chakra-ui/react"; import { Kind } from "nostr-tools"; import ngeohash from "ngeohash"; @@ -82,6 +82,7 @@ function useEventMarkers(events: NostrEvent[], map?: L.Map, onClick?: (event: No } export default function MapView() { + const navigate = useNavigate(); const ref = useRef(null); const [map, setMap] = useState(); const [searchParams, setSearchParams] = useSearchParams(); @@ -152,7 +153,7 @@ export default function MapView() { - + - + {filteredRelays.map((url) => ( @@ -61,7 +61,7 @@ export default function RelaysView() { <> Discovered Relays - + {discoveredRelays.map((url) => ( diff --git a/src/views/settings/display-settings.tsx b/src/views/settings/display-settings.tsx index 823f690b2..8a4d97f46 100644 --- a/src/views/settings/display-settings.tsx +++ b/src/views/settings/display-settings.tsx @@ -54,6 +54,20 @@ export default function DisplaySettings() { The primary color of the theme + + + Max Page width + + + + Setting this will restrict the width of app on desktop + + diff --git a/src/views/user/about.tsx b/src/views/user/about.tsx index 529810358..932a72816 100644 --- a/src/views/user/about.tsx +++ b/src/views/user/about.tsx @@ -283,7 +283,7 @@ export default function UserAboutTab() { )} - +