From 2a34b370cd81f188190e65d0af2fc7a6f0640b1e Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 7 Feb 2023 17:04:18 -0600 Subject: [PATCH] add following and discover tabs to home view --- src/components/post-modal.tsx | 2 +- src/components/post/index.tsx | 4 +- src/components/post/post-cc.tsx | 2 +- src/components/{ => post}/post-contents.tsx | 4 +- src/index.tsx | 5 ++ src/views/global/index.tsx | 4 +- src/views/home.tsx | 28 -------- src/views/home/discover-tab.tsx | 77 +++++++++++++++++++++ src/views/home/following-tab.tsx | 43 ++++++++++++ src/views/home/index.tsx | 28 ++++++++ src/views/user/index.tsx | 4 +- 11 files changed, 163 insertions(+), 38 deletions(-) rename src/components/{ => post}/post-contents.tsx (96%) delete mode 100644 src/views/home.tsx create mode 100644 src/views/home/discover-tab.tsx create mode 100644 src/views/home/following-tab.tsx create mode 100644 src/views/home/index.tsx diff --git a/src/components/post-modal.tsx b/src/components/post-modal.tsx index c401a3e03..aa7f2e16d 100644 --- a/src/components/post-modal.tsx +++ b/src/components/post-modal.tsx @@ -10,7 +10,7 @@ import { ModalOverlay, } from "@chakra-ui/react"; import { NostrEvent } from "../types/nostr-event"; -import { PostContents } from "./post-contents"; +import { PostContents } from "./post/post-contents"; export type PostModalProps = { event: NostrEvent; diff --git a/src/components/post/index.tsx b/src/components/post/index.tsx index 49c7d8c43..1b001ffd4 100644 --- a/src/components/post/index.tsx +++ b/src/components/post/index.tsx @@ -20,7 +20,7 @@ import { UserAvatarLink } from "../user-avatar-link"; import { getUserDisplayName } from "../../helpers/user-metadata"; import { Bech32Prefix, normalizeToBech32 } from "../../helpers/nip-19"; -import { PostContents } from "../post-contents"; +import { PostContents } from "./post-contents"; import { PostMenu } from "./post-menu"; import { PostCC } from "./post-cc"; @@ -35,7 +35,7 @@ export const Post = React.memo(({ event }: PostProps) => { - + diff --git a/src/components/post/post-cc.tsx b/src/components/post/post-cc.tsx index 6f1f7bf44..bef447e7e 100644 --- a/src/components/post/post-cc.tsx +++ b/src/components/post/post-cc.tsx @@ -23,7 +23,7 @@ export const PostCC = ({ event }: { event: NostrEvent }) => { if (!hasCC) return null; return ( - + Replying to: {event.tags .filter((t) => t[0] === "p") diff --git a/src/components/post-contents.tsx b/src/components/post/post-contents.tsx similarity index 96% rename from src/components/post-contents.tsx rename to src/components/post/post-contents.tsx index 529fd4ba5..a13d091a7 100644 --- a/src/components/post-contents.tsx +++ b/src/components/post/post-contents.tsx @@ -13,8 +13,8 @@ import remarkUnwrapImages from "remark-unwrap-images"; import rehypeExternalLinks from "rehype-external-links"; // @ts-ignore import linkifyRegex from "remark-linkify-regex"; -import { InlineInvoiceCard } from "./inline-invoice-card"; -import { TweetEmbed } from "./tweet-embed"; +import { InlineInvoiceCard } from "../inline-invoice-card"; +import { TweetEmbed } from "../tweet-embed"; const lightningInvoiceRegExp = /(lightning:)?LNBC[A-Za-z0-9]+/i; diff --git a/src/index.tsx b/src/index.tsx index 1dbe96983..b12f6baff 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,3 +1,4 @@ +import moment from "moment"; import { createRoot } from "react-dom/client"; import { App } from "./app"; import { Providers } from "./providers"; @@ -11,3 +12,7 @@ root.render( ); + +if (import.meta.env.DEV) { + window.moment = moment; +} diff --git a/src/views/global/index.tsx b/src/views/global/index.tsx index b977917e2..26934492b 100644 --- a/src/views/global/index.tsx +++ b/src/views/global/index.tsx @@ -75,10 +75,10 @@ export const GlobalView = () => { flexDirection="column" flexGrow="1" overflow="hidden" - isManual + isLazy > - Posts + Notes Replies diff --git a/src/views/home.tsx b/src/views/home.tsx deleted file mode 100644 index a86c3ffe1..000000000 --- a/src/views/home.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { HStack } from "@chakra-ui/react"; -import { UserAvatarLink } from "../components/user-avatar-link"; -import { normalizeToHex } from "../helpers/nip-19"; - -export const HomeView = () => { - return ( - - - - - - - - - - - - - - - ); -}; diff --git a/src/views/home/discover-tab.tsx b/src/views/home/discover-tab.tsx new file mode 100644 index 000000000..ea50ada94 --- /dev/null +++ b/src/views/home/discover-tab.tsx @@ -0,0 +1,77 @@ +import { useEffect, useState } from "react"; +import { Flex, Text } from "@chakra-ui/react"; +import moment from "moment"; +import { mergeAll, from } from "rxjs"; +import { Post } from "../../components/post"; +import { useEventDir } from "../../hooks/use-event-dir"; +import useSubject from "../../hooks/use-subject"; +import { useSubscription } from "../../hooks/use-subscription"; +import { useUserContacts } from "../../hooks/use-user-contacts"; +import identity from "../../services/identity"; +import settings from "../../services/settings"; +import userContacts from "../../services/user-contacts"; + +function useExtendedContacts(pubkey: string) { + const relays = useSubject(settings.relays); + const [extendedContacts, setExtendedContacts] = useState([]); + const { contacts } = useUserContacts(pubkey); + + useEffect(() => { + if (contacts) { + const following = contacts.contacts.map((c) => c.pubkey); + const subscriptions = contacts.contacts.map((contact) => + userContacts.requestUserContacts(contact.pubkey, relays) + ); + + const rxSub = from(subscriptions) + .pipe(mergeAll()) + .subscribe((contacts) => { + if (contacts) { + setExtendedContacts((value) => { + const more = contacts.contacts + .map((c) => c.pubkey) + .filter((key) => !following.includes(key)); + return Array.from(new Set([...value, ...more])); + }); + } + }); + + return () => rxSub.unsubscribe(); + } + }, [contacts, setExtendedContacts]); + + return extendedContacts; +} + +export const DiscoverTab = () => { + const relays = useSubject(settings.relays); + const pubkey = useSubject(identity.pubkey); + + const contactsOfContacts = useExtendedContacts(pubkey); + + const [since, setSince] = useState(moment().subtract(1, "hour")); + const [after, setAfter] = useState(moment()); + + const sub = useSubscription( + relays, + { + authors: contactsOfContacts, + kinds: [1], + since: since.unix(), + }, + "home-discover" + ); + + const { events } = useEventDir(sub); + const timeline = Object.values(events).sort( + (a, b) => b.created_at - a.created_at + ); + + return ( + + {timeline.map((event) => ( + + ))} + + ); +}; diff --git a/src/views/home/following-tab.tsx b/src/views/home/following-tab.tsx new file mode 100644 index 000000000..8a1bc19e9 --- /dev/null +++ b/src/views/home/following-tab.tsx @@ -0,0 +1,43 @@ +import { Flex } from "@chakra-ui/react"; +import moment from "moment"; +import { useState } from "react"; +import { Post } from "../../components/post"; +import { useEventDir } from "../../hooks/use-event-dir"; +import useSubject from "../../hooks/use-subject"; +import { useSubscription } from "../../hooks/use-subscription"; +import { useUserContacts } from "../../hooks/use-user-contacts"; +import identity from "../../services/identity"; +import settings from "../../services/settings"; + +export const FollowingTab = () => { + const relays = useSubject(settings.relays); + const pubkey = useSubject(identity.pubkey); + const { contacts } = useUserContacts(pubkey); + + const [since, setSince] = useState(moment().subtract(1, "hour")); + const [after, setAfter] = useState(moment()); + + const following = contacts?.contacts.map((contact) => contact.pubkey) || []; + const sub = useSubscription( + relays, + { + authors: following, + kinds: [1], + since: since.unix(), + }, + "home-following" + ); + + const { events } = useEventDir(sub); + const timeline = Object.values(events).sort( + (a, b) => b.created_at - a.created_at + ); + + return ( + + {timeline.map((event) => ( + + ))} + + ); +}; diff --git a/src/views/home/index.tsx b/src/views/home/index.tsx new file mode 100644 index 000000000..c68e7fb97 --- /dev/null +++ b/src/views/home/index.tsx @@ -0,0 +1,28 @@ +import { Tab, TabList, TabPanel, TabPanels, Tabs } from "@chakra-ui/react"; +import { DiscoverTab } from "./discover-tab"; +import { FollowingTab } from "./following-tab"; + +export const HomeView = () => { + return ( + + + Following + Discover + + + + + + + + + + + ); +}; diff --git a/src/views/user/index.tsx b/src/views/user/index.tsx index 5103f4dad..f18192b95 100644 --- a/src/views/user/index.tsx +++ b/src/views/user/index.tsx @@ -85,10 +85,10 @@ export const UserView = ({ pubkey }: UserViewProps) => { flexDirection="column" flexGrow="1" overflow="hidden" - isManual + isLazy > - Posts + Notes {/* Replies */} Following Relays