From 5af2b90fd6e0eff6f00a92c414f3242675778b6c Mon Sep 17 00:00:00 2001 From: Sam Samskies Date: Wed, 2 Aug 2023 17:50:53 -0500 Subject: [PATCH 1/3] playlist feed poc --- components/PlaylistFeed/PlaylistFeed.tsx | 81 ++++++++++++++++++++++++ package.json | 2 +- pages/playlist/[naddr].tsx | 57 +++++++++++++++++ yarn.lock | 68 ++++++++------------ 4 files changed, 166 insertions(+), 42 deletions(-) create mode 100644 components/PlaylistFeed/PlaylistFeed.tsx create mode 100644 pages/playlist/[naddr].tsx diff --git a/components/PlaylistFeed/PlaylistFeed.tsx b/components/PlaylistFeed/PlaylistFeed.tsx new file mode 100644 index 0000000..5f0ce1a --- /dev/null +++ b/components/PlaylistFeed/PlaylistFeed.tsx @@ -0,0 +1,81 @@ +import { useEffect, useState } from "react"; +import { type NDKEvent } from "@nostr-dev-kit/ndk"; +import { useNDK } from "../../ndk/NDKProvider"; +import { EventProvider } from "../../ndk/NDKEventProvider"; +import { FeedNote } from "../Note/Note"; +import { Stack } from "@mantine/core"; +import useFooterHeight from "../../ndk/hooks/useFooterHeight"; + +export default function PlaylistFeed({ + d, + playlistCreatorPubkey, +}: { + d: string; + playlistCreatorPubkey: string; +}) { + const { ndk, stemstrRelaySet } = useNDK(); + const [events, setEvents] = useState([]); + const footerHeight = useFooterHeight(); + + useEffect(() => { + if (!ndk) { + return; + } + + // for some reason, the query works more consistently providing the author pubkey even though it shouldn't + // be necessary + ndk + .fetchEvent( + { + kinds: [30001], + authors: [playlistCreatorPubkey], + "#d": [d], + }, + {} + ) + .then((event) => { + if (event) { + return event.getMatchingTags("e").map((tag) => tag[1]); + } + }) + .then(async (eventIds) => { + if (eventIds) { + return { + sortedEventIds: eventIds, + events: await ndk.fetchEvents( + { ids: eventIds }, + {}, + stemstrRelaySet + ), + }; + } + + return { sortedEventIds: [], events: [] }; + }) + .then(({ sortedEventIds, events }) => { + if (!events) { + return; + } + + const eventsMap: Record = {}; + + events.forEach((event) => { + eventsMap[event.id] = event; + }); + + setEvents(sortedEventIds.map((id) => eventsMap[id])); + }) + .catch(console.error); + }, [d, ndk, stemstrRelaySet, playlistCreatorPubkey]); + + // Not using the Feed component because it causes an infinite loop for some reason + return ( + + {events.map((event) => ( + + + + ))} + + ); +} diff --git a/package.json b/package.json index e52d445..32cc703 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "next": "13.1.6", "next-pwa": "^5.6.0", "next-redux-wrapper": "^8.1.0", - "nostr-tools": "^1.6.0", + "nostr-tools": "^1.14.0", "qrcode.react": "^3.1.0", "react": "18.2.0", "react-device-detect": "^2.2.3", diff --git a/pages/playlist/[naddr].tsx b/pages/playlist/[naddr].tsx new file mode 100644 index 0000000..46db21c --- /dev/null +++ b/pages/playlist/[naddr].tsx @@ -0,0 +1,57 @@ +import { Flex, Stack, Text } from "@mantine/core"; +import Head from "next/head"; +import FeedHeader from "components/FeedHeader/FeedHeader"; +import { useRouter } from "next/router"; +import { nip19 } from "nostr-tools"; +import { Route } from "../../enums"; +import { ChevronLeftIcon } from "../../icons/StemstrIcon"; +import BackButton from "../../components/BackButton/BackButton"; +import PlaylistFeed from "../../components/PlaylistFeed/PlaylistFeed"; + +const useNip19Address = () => { + const router = useRouter(); + const { naddr } = router.query; + + try { + const { type, data } = nip19.decode(naddr as string); + + if (type === "naddr") { + return data as nip19.AddressPointer; + } + } catch (error) { + console.error(error); + } +}; + +export default function Playlist() { + // the address id should be a slug, but listr.lol uses the title as the id so just going with using the id as the + // title for now + const { identifier: playlistTitle, pubkey } = useNip19Address() ?? {}; + + if (!playlistTitle) { + return null; + } + + return ( + <> + + Stemstr - {playlistTitle} + + + + + + + + {playlistTitle} + + + + + + ); +} diff --git a/yarn.lock b/yarn.lock index 95cd695..0eb7d8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3868,31 +3868,23 @@ dependencies: "@noble/hashes" "1.3.0" -"@noble/hashes@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.0.0.tgz#d5e38bfbdaba174805a4e649f13be9a9ed3351ae" - integrity sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg== +"@noble/curves@1.1.0", "@noble/curves@~1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" + integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA== + dependencies: + "@noble/hashes" "1.3.1" "@noble/hashes@1.3.0", "@noble/hashes@~1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== -"@noble/hashes@^1.3.1": +"@noble/hashes@1.3.1", "@noble/hashes@^1.3.1", "@noble/hashes@~1.3.1": version "1.3.1" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== -"@noble/hashes@~1.2.0": - version "1.2.0" - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz" - integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== - -"@noble/secp256k1@^1.7.1", "@noble/secp256k1@~1.7.0": - version "1.7.1" - resolved "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz" - integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== - "@noble/secp256k1@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-2.0.0.tgz#c214269d45e0233ad6a8ae5104655453636e253d" @@ -4172,13 +4164,13 @@ "@noble/hashes" "~1.3.0" "@scure/base" "~1.1.0" -"@scure/bip32@^1.1.5": - version "1.1.5" - resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz" - integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== +"@scure/bip32@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10" + integrity sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A== dependencies: - "@noble/hashes" "~1.2.0" - "@noble/secp256k1" "~1.7.0" + "@noble/curves" "~1.1.0" + "@noble/hashes" "~1.3.1" "@scure/base" "~1.1.0" "@scure/bip39@1.2.0": @@ -4189,12 +4181,12 @@ "@noble/hashes" "~1.3.0" "@scure/base" "~1.1.0" -"@scure/bip39@^1.1.1": - version "1.1.1" - resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz" - integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== +"@scure/bip39@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" + integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== dependencies: - "@noble/hashes" "~1.2.0" + "@noble/hashes" "~1.3.0" "@scure/base" "~1.1.0" "@sinclair/typebox@^0.25.16": @@ -12937,17 +12929,16 @@ nostr-tools@^1.11.2: "@scure/bip32" "1.3.0" "@scure/bip39" "1.2.0" -nostr-tools@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-1.6.0.tgz#4052fe717a378982c8ce56d39986089abacfc6d3" - integrity sha512-qjjJQ7YxJUMzgS24eVlxkZ87PKJtU6dlH04OzVuK6w+GSPL+VdUZkMe2lfSpnb7OkCrDIzmbFbtx+Q4LXdU2xw== +nostr-tools@^1.14.0: + version "1.14.0" + resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-1.14.0.tgz#5cb21cd9f7b1a471b9010e3feed6c74d126ab106" + integrity sha512-hwq2i1z5/DneXRE5Zu/TzQuKzVLcB+gOdfT9CeoiScvNw/2dWRGJvyTXIdF92d7NQ7nMcEwqVJPDytLpEpiiKw== dependencies: - "@noble/hashes" "1.0.0" - "@noble/secp256k1" "^1.7.1" - "@scure/base" "^1.1.1" - "@scure/bip32" "^1.1.5" - "@scure/bip39" "^1.1.1" - prettier "^2.8.4" + "@noble/curves" "1.1.0" + "@noble/hashes" "1.3.1" + "@scure/base" "1.1.1" + "@scure/bip32" "1.3.1" + "@scure/bip39" "1.2.1" npm-run-all@^4.1.5: version "4.1.5" @@ -13774,11 +13765,6 @@ prettier@^2.7.1: resolved "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz" integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== -prettier@^2.8.4: - version "2.8.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.4.tgz#34dd2595629bfbb79d344ac4a91ff948694463c3" - integrity sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw== - pretty-bytes@^5.3.0, pretty-bytes@^5.4.1: version "5.6.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" From d575892b8bf9a4988276939c0bd1f7383231a2d2 Mon Sep 17 00:00:00 2001 From: Sam Samskies Date: Wed, 2 Aug 2023 18:22:56 -0500 Subject: [PATCH 2/3] fix build --- package.json | 2 +- pages/playlist/[naddr].tsx | 2 +- yarn.lock | 67 ++++++++++++++++++++------------------ 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index 32cc703..479615e 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "next": "13.1.6", "next-pwa": "^5.6.0", "next-redux-wrapper": "^8.1.0", - "nostr-tools": "^1.14.0", + "nostr-tools": "1.10.1", "qrcode.react": "^3.1.0", "react": "18.2.0", "react-device-detect": "^2.2.3", diff --git a/pages/playlist/[naddr].tsx b/pages/playlist/[naddr].tsx index 46db21c..1b9c04a 100644 --- a/pages/playlist/[naddr].tsx +++ b/pages/playlist/[naddr].tsx @@ -28,7 +28,7 @@ export default function Playlist() { // title for now const { identifier: playlistTitle, pubkey } = useNip19Address() ?? {}; - if (!playlistTitle) { + if (!playlistTitle || !pubkey) { return null; } diff --git a/yarn.lock b/yarn.lock index 0eb7d8b..cdba9d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3868,23 +3868,26 @@ dependencies: "@noble/hashes" "1.3.0" -"@noble/curves@1.1.0", "@noble/curves@~1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" - integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA== - dependencies: - "@noble/hashes" "1.3.1" +"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" + integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== "@noble/hashes@1.3.0", "@noble/hashes@~1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== -"@noble/hashes@1.3.1", "@noble/hashes@^1.3.1", "@noble/hashes@~1.3.1": +"@noble/hashes@^1.3.1": version "1.3.1" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== +"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== + "@noble/secp256k1@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-2.0.0.tgz#c214269d45e0233ad6a8ae5104655453636e253d" @@ -4155,6 +4158,15 @@ resolved "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz" integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== +"@scure/bip32@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.4.tgz#2c91a7be0156b15f26dd0c843a06a1917f129efd" + integrity sha512-m925ACYK0wPELsF7Z/VdLGmKj1StIeHraPMYB9xiAFiq/PnvqWd/99I0TQ2OZhjjlMDsDJeZlyXMWi0beaA7NA== + dependencies: + "@noble/hashes" "~1.2.0" + "@noble/secp256k1" "~1.7.0" + "@scure/base" "~1.1.0" + "@scure/bip32@1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.0.tgz#6c8d980ef3f290987736acd0ee2e0f0d50068d87" @@ -4164,13 +4176,12 @@ "@noble/hashes" "~1.3.0" "@scure/base" "~1.1.0" -"@scure/bip32@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10" - integrity sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A== +"@scure/bip39@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" + integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== dependencies: - "@noble/curves" "~1.1.0" - "@noble/hashes" "~1.3.1" + "@noble/hashes" "~1.2.0" "@scure/base" "~1.1.0" "@scure/bip39@1.2.0": @@ -4181,14 +4192,6 @@ "@noble/hashes" "~1.3.0" "@scure/base" "~1.1.0" -"@scure/bip39@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" - integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== - dependencies: - "@noble/hashes" "~1.3.0" - "@scure/base" "~1.1.0" - "@sinclair/typebox@^0.25.16": version "0.25.24" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718" @@ -12918,6 +12921,17 @@ normalize-range@^0.1.2: resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= +nostr-tools@1.10.1: + version "1.10.1" + resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-1.10.1.tgz#b52043b3031f4314478d0a3bfaa8ffb9cc4f98a0" + integrity sha512-zgTYJeuZQ3CDASsmBEcB5i6V6l0IaA6cjnll6OVik3FoZcvbCaL7yP8I40hYnOIi3KlJykV7jEF9fn8h1NzMnA== + dependencies: + "@noble/hashes" "1.2.0" + "@noble/secp256k1" "1.7.1" + "@scure/base" "1.1.1" + "@scure/bip32" "1.1.4" + "@scure/bip39" "1.1.1" + nostr-tools@^1.11.2: version "1.12.1" resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-1.12.1.tgz#4ac9c0d1cff8c7107b0d3ef647571137c2250557" @@ -12929,17 +12943,6 @@ nostr-tools@^1.11.2: "@scure/bip32" "1.3.0" "@scure/bip39" "1.2.0" -nostr-tools@^1.14.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-1.14.0.tgz#5cb21cd9f7b1a471b9010e3feed6c74d126ab106" - integrity sha512-hwq2i1z5/DneXRE5Zu/TzQuKzVLcB+gOdfT9CeoiScvNw/2dWRGJvyTXIdF92d7NQ7nMcEwqVJPDytLpEpiiKw== - dependencies: - "@noble/curves" "1.1.0" - "@noble/hashes" "1.3.1" - "@scure/base" "1.1.1" - "@scure/bip32" "1.3.1" - "@scure/bip39" "1.2.1" - npm-run-all@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" From 212fc7ec08f3248bc9b6d473873aaf18488c76c7 Mon Sep 17 00:00:00 2001 From: Sam Samskies Date: Wed, 2 Aug 2023 18:36:06 -0500 Subject: [PATCH 3/3] remove unnecessary comment --- components/PlaylistFeed/PlaylistFeed.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/PlaylistFeed/PlaylistFeed.tsx b/components/PlaylistFeed/PlaylistFeed.tsx index 5f0ce1a..f9364a4 100644 --- a/components/PlaylistFeed/PlaylistFeed.tsx +++ b/components/PlaylistFeed/PlaylistFeed.tsx @@ -22,8 +22,6 @@ export default function PlaylistFeed({ return; } - // for some reason, the query works more consistently providing the author pubkey even though it shouldn't - // be necessary ndk .fetchEvent( {