From 5add2819a9e9aea8b13dc115cb81c269b9e0109d Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Fri, 16 Aug 2024 11:41:24 -0500 Subject: [PATCH] add blindspots feed --- .changeset/nasty-scissors-mate.md | 5 + src/app.tsx | 25 +++- src/classes/accounts/account.ts | 9 +- src/classes/accounts/extension-account.ts | 12 +- src/classes/accounts/nsec-account.ts | 9 +- src/classes/pubkey-graph.ts | 14 +- src/components/layout/nav-items.tsx | 6 +- src/services/account.ts | 6 +- src/views/discovery/blindspot/feed.tsx | 107 ++++++++++++++++ src/views/discovery/blindspot/index.tsx | 121 ++++++++++++++++++ .../dvm-feed/components/debug-chains.tsx | 10 +- .../dvm-feed/components/dvm-avatar.tsx | 4 +- .../dvm-feed/components/dvm-card.tsx | 10 +- .../dvm-feed/components/dvm-name.tsx | 6 +- .../dvm-feed/components/dvm-params.tsx | 2 +- .../dvm-feed/components/feed-status.tsx | 12 +- .../dvm-feed/components/feed.tsx | 6 +- src/views/{ => discovery}/dvm-feed/feed.tsx | 28 ++-- src/views/{dvm-feed => discovery}/index.tsx | 40 ++++-- src/views/home/index.tsx | 9 +- .../user/components/user-profile-menu.tsx | 8 ++ 21 files changed, 375 insertions(+), 74 deletions(-) create mode 100644 .changeset/nasty-scissors-mate.md create mode 100644 src/views/discovery/blindspot/feed.tsx create mode 100644 src/views/discovery/blindspot/index.tsx rename src/views/{ => discovery}/dvm-feed/components/debug-chains.tsx (93%) rename src/views/{ => discovery}/dvm-feed/components/dvm-avatar.tsx (89%) rename src/views/{ => discovery}/dvm-feed/components/dvm-card.tsx (76%) rename src/views/{ => discovery}/dvm-feed/components/dvm-name.tsx (80%) rename src/views/{ => discovery}/dvm-feed/components/dvm-params.tsx (93%) rename src/views/{ => discovery}/dvm-feed/components/feed-status.tsx (90%) rename src/views/{ => discovery}/dvm-feed/components/feed.tsx (70%) rename src/views/{ => discovery}/dvm-feed/feed.tsx (78%) rename src/views/{dvm-feed => discovery}/index.tsx (59%) diff --git a/.changeset/nasty-scissors-mate.md b/.changeset/nasty-scissors-mate.md new file mode 100644 index 000000000..c83077f77 --- /dev/null +++ b/.changeset/nasty-scissors-mate.md @@ -0,0 +1,5 @@ +--- +"nostrudel": minor +--- + +Add blindspots discovery feed diff --git a/src/app.tsx b/src/app.tsx index cc032fd17..c8b3b01b2 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -7,11 +7,14 @@ import Layout from "./components/layout"; import DrawerSubViewProvider from "./providers/drawer-sub-view-provider"; import useSetColorMode from "./hooks/use-set-color-mode"; import { RouteProviders } from "./providers/route"; +import RequireCurrentAccount from "./providers/route/require-current-account"; import GlobalStyles from "./styles"; import HomeView from "./views/home/index"; -const DVMFeedHomeView = lazy(() => import("./views/dvm-feed/index")); -const DVMFeedView = lazy(() => import("./views/dvm-feed/feed")); +const DiscoveryHomeView = lazy(() => import("./views/discovery/index")); +const DVMFeedView = lazy(() => import("./views/discovery/dvm-feed/feed")); +const BlindspotHomeView = lazy(() => import("./views/discovery/blindspot")); +const BlindspotFeedView = lazy(() => import("./views/discovery/blindspot/feed")); import SettingsView from "./views/settings"; import NostrLinkView from "./views/link"; import ProfileView from "./views/profile"; @@ -316,10 +319,22 @@ const router = createHashRouter([ ], }, { - path: "dvm", + path: "discovery", children: [ - { path: ":addr", element: }, - { path: "", element: }, + { path: "", element: }, + { path: "dvm/:addr", element: }, + { + path: "blindspot", + element: ( + + + + ), + children: [ + { path: "", element: }, + { path: ":pubkey", element: }, + ], + }, ], }, { path: "search", element: }, diff --git a/src/classes/accounts/account.ts b/src/classes/accounts/account.ts index bf0c561e2..aecebdf00 100644 --- a/src/classes/accounts/account.ts +++ b/src/classes/accounts/account.ts @@ -4,9 +4,16 @@ import { Nip07Signer } from "../../types/nostr-extensions"; export class Account { readonly type: string = "unknown"; pubkey: string; - signer?: Nip07Signer; localSettings?: AppSettings; + protected _signer?: Nip07Signer | undefined; + public get signer(): Nip07Signer | undefined { + return this._signer; + } + public set signer(value: Nip07Signer | undefined) { + this._signer = value; + } + get readonly() { return !this.signer; } diff --git a/src/classes/accounts/extension-account.ts b/src/classes/accounts/extension-account.ts index 8c9691c98..ce0787414 100644 --- a/src/classes/accounts/extension-account.ts +++ b/src/classes/accounts/extension-account.ts @@ -3,16 +3,16 @@ import { Account } from "./account"; export default class ExtensionAccount extends Account { readonly type = "extension"; - signer?: Nip07Signer; - constructor(pubkey: string) { - super(pubkey); - this.signer = window.nostr; + override get signer() { + if (!window.nostr) throw new Error("Missing NIP-07 signer extension"); + return window.nostr; + } + set signer(signer: Nip07Signer) { + throw new Error("Cant update signer"); } fromJSON(data: any): this { - if (!window.nostr) throw new Error("Missing NIP-07 signer extension"); - this.signer = window.nostr; return super.fromJSON(data); } } diff --git a/src/classes/accounts/nsec-account.ts b/src/classes/accounts/nsec-account.ts index 43b6395d6..6641107cb 100644 --- a/src/classes/accounts/nsec-account.ts +++ b/src/classes/accounts/nsec-account.ts @@ -4,7 +4,14 @@ import { Account } from "./account"; export default class NsecAccount extends Account { readonly type = "nsec"; - declare signer?: SimpleSigner; + + protected declare _signer?: SimpleSigner | undefined; + public get signer(): SimpleSigner | undefined { + return this._signer; + } + public set signer(value: SimpleSigner | undefined) { + this._signer = value; + } constructor(pubkey: string) { super(pubkey); diff --git a/src/classes/pubkey-graph.ts b/src/classes/pubkey-graph.ts index a85161702..c5c4a5744 100644 --- a/src/classes/pubkey-graph.ts +++ b/src/classes/pubkey-graph.ts @@ -1,12 +1,19 @@ import { NostrEvent } from "nostr-tools"; import _throttle from "lodash.throttle"; -import { logger } from "../helpers/debug"; -export class PubkeyGraph { +import { logger } from "../helpers/debug"; +import EventEmitter from "eventemitter3"; + +type EventMap = { + computed: []; +}; + +export class PubkeyGraph extends EventEmitter { /** the pubkey at the center of it all */ root: string; log = logger.extend("PubkeyGraph"); + /** a map of what pubkeys follow other pubkeys */ connections = new Map(); distance = new Map(); @@ -14,6 +21,7 @@ export class PubkeyGraph { connectionCount = new Map(); constructor(root: string) { + super(); this.root = root; } @@ -128,6 +136,8 @@ export class PubkeyGraph { next.add(this.root); walkLevel(0); console.timeEnd("walk"); + + this.emit("computed"); } getPaths(pubkey: string, maxLength = 2) { diff --git a/src/components/layout/nav-items.tsx b/src/components/layout/nav-items.tsx index ff080384b..f891e1aad 100644 --- a/src/components/layout/nav-items.tsx +++ b/src/components/layout/nav-items.tsx @@ -48,7 +48,7 @@ export default function NavItems() { else if (location.pathname === "/") active = "notes"; else if (location.pathname.startsWith("/notifications")) active = "notifications"; else if (location.pathname.startsWith("/launchpad")) active = "launchpad"; - else if (location.pathname.startsWith("/dvm")) active = "dvm"; + else if (location.pathname.startsWith("/discovery")) active = "discovery"; else if (location.pathname.startsWith("/dm")) active = "dm"; else if (location.pathname.startsWith("/streams")) active = "streams"; else if (location.pathname.startsWith("/relays")) active = "relays"; @@ -120,9 +120,9 @@ export default function NavItems() { diff --git a/src/views/dvm-feed/index.tsx b/src/views/discovery/index.tsx similarity index 59% rename from src/views/dvm-feed/index.tsx rename to src/views/discovery/index.tsx index da3ff4412..4f3215279 100644 --- a/src/views/dvm-feed/index.tsx +++ b/src/views/discovery/index.tsx @@ -1,7 +1,8 @@ -import { Heading, Link, SimpleGrid, Text } from "@chakra-ui/react"; +import { Card, Flex, Heading, Link, LinkBox, SimpleGrid, Text } from "@chakra-ui/react"; +import { Link as RouterLink } from "react-router-dom"; import VerticalPageLayout from "../../components/vertical-page-layout"; -import DVMCard from "./components/dvm-card"; +import DVMCard from "./dvm-feed/components/dvm-card"; import { DVM_CONTENT_DISCOVERY_JOB_KIND } from "../../helpers/nostr/dvm"; import useTimelineLoader from "../../hooks/use-timeline-loader"; import { useReadRelays } from "../../hooks/use-client-relays"; @@ -10,8 +11,10 @@ import RequireCurrentAccount from "../../providers/route/require-current-account import { getEventCoordinate } from "../../helpers/nostr/event"; import { useTimelineCurserIntersectionCallback } from "../../hooks/use-timeline-cursor-intersection-callback"; import IntersectionObserverProvider from "../../providers/local/intersection-observer"; +import Telescope from "../../components/icons/telescope"; +import HoverLinkOverlay from "../../components/hover-link-overlay"; -function DVMFeedHomePage() { +function DVMFeeds() { const readRelays = useReadRelays(); const timeline = useTimelineLoader("content-discovery-dvms", readRelays, { kinds: [31990], @@ -23,8 +26,10 @@ function DVMFeedHomePage() { const callback = useTimelineCurserIntersectionCallback(timeline); return ( - - DVM Feeds + <> + + DVM Feeds + Learn more about data vending machines here:{" "} @@ -34,18 +39,37 @@ function DVMFeedHomePage() { {DMVs.map((appData) => ( - + ))} + + ); +} + +function DiscoveryHomePage() { + return ( + + + + + + + Blind spots + + + What are other users seeing that you are not? + + + ); } -export default function DVMFeedHomeView() { +export default function DiscoveryHomeView() { return ( - + ); } diff --git a/src/views/home/index.tsx b/src/views/home/index.tsx index a92a9733f..1acb8ee02 100644 --- a/src/views/home/index.tsx +++ b/src/views/home/index.tsx @@ -14,14 +14,7 @@ import NoteFilterTypeButtons from "../../components/note-filter-type-buttons"; import KindSelectionProvider, { useKindSelectionContext } from "../../providers/local/kind-selection-provider"; import { useReadRelays } from "../../hooks/use-client-relays"; -const defaultKinds = [ - kinds.ShortTextNote, - kinds.Repost, - kinds.GenericRepost, - kinds.LongFormArticle, - kinds.RecommendRelay, - kinds.BadgeAward, -]; +const defaultKinds = [kinds.ShortTextNote, kinds.Repost, kinds.GenericRepost, kinds.LongFormArticle]; function HomePage() { const showReplies = useDisclosure({ defaultIsOpen: localStorage.getItem("show-replies") === "true" }); diff --git a/src/views/user/components/user-profile-menu.tsx b/src/views/user/components/user-profile-menu.tsx index 0f8780826..764affa8f 100644 --- a/src/views/user/components/user-profile-menu.tsx +++ b/src/views/user/components/user-profile-menu.tsx @@ -24,6 +24,7 @@ import userMailboxesService from "../../../services/user-mailboxes"; import { useContext } from "react"; import { AppHandlerContext } from "../../../providers/route/app-handler-provider"; import PubkeyAccount from "../../../classes/accounts/pubkey-account"; +import Telescope from "../../../components/icons/telescope"; export const UserProfileMenu = ({ pubkey, @@ -60,6 +61,13 @@ export const UserProfileMenu = ({ } as={RouterLink} to={`/dm/${nip19.npubEncode(pubkey)}`}> Direct messages + } + as={RouterLink} + to={`/discovery/blindspot/${nip19.npubEncode(pubkey)}`} + > + Blind spot + } onClick={() => loginAsUser()}> Login as user