From 9d35d80bcff31ba5c612ff755896fe3112d3017d Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Date: Sat, 5 Jul 2025 22:05:57 -0400 Subject: [PATCH] feat(nostr): Created prototype for Social Media Content Creators --- src/components/app-body/index.js | 2 + .../nostr/content-creators/content-card.js | 194 ++++++++++++++++++ .../content-creators/content-creators-list.js | 65 ++++++ .../app-body/nostr/content-creators/index.js | 15 ++ src/components/nav-menu/index.js | 7 + 5 files changed, 283 insertions(+) create mode 100644 src/components/app-body/nostr/content-creators/content-card.js create mode 100644 src/components/app-body/nostr/content-creators/content-creators-list.js create mode 100644 src/components/app-body/nostr/content-creators/index.js diff --git a/src/components/app-body/index.js b/src/components/app-body/index.js index 2f14413..21c34bf 100644 --- a/src/components/app-body/index.js +++ b/src/components/app-body/index.js @@ -26,6 +26,7 @@ import ServerSelectView from './configuration/select-server-view' import NostrPost from './nostr/nostr-post/index.js' import NostrRead from './nostr/nostr-read/index.js' import GlobalFeed from './nostr/global-feed/index.js' +import ContentCreators from './nostr/content-creators/index.js' import UserDataReview from './user-data-review' import Offers from './offers' function AppBody (props) { @@ -50,6 +51,7 @@ function AppBody (props) { } /> } /> } /> + } /> } /> } /> diff --git a/src/components/app-body/nostr/content-creators/content-card.js b/src/components/app-body/nostr/content-creators/content-card.js new file mode 100644 index 0000000..496e0dc --- /dev/null +++ b/src/components/app-body/nostr/content-creators/content-card.js @@ -0,0 +1,194 @@ +/** + * Content creators card + */ + +import React, { useState, useEffect } from 'react' +import { Card } from 'react-bootstrap' +import Jdenticon from '@chris.troutner/react-jdenticon' +import CopyOnClick from '../../bch-wallet/copy-on-click.js' +import { RelayPool } from 'nostr' + +function ContentCard (props) { + const [profile, setProfile] = useState([]) + const [loaded, setLoaded] = useState(false) + const { creator } = props + + useEffect(() => { + const loadProfile = async () => { + const psf = 'wss://nostr-relay.psfoundation.info' + + const pool = RelayPool([psf]) + pool.on('open', relay => { + relay.subscribe('subid', { limit: 5, kinds: [0], authors: [creator.pubkey] }) + }) + + pool.on('eose', relay => { + console.log('Closing Relay') + relay.close() + }) + + pool.on('event', (relay, subId, ev) => { + try { + const profile = JSON.parse(ev.content) + console.log('profile', profile) + setProfile(profile) + } catch (error) { + console.log('Error parsing profile', error) + } + }) + setLoaded(true) + } + + if (!loaded && creator.npub) { + loadProfile() + } + }, [loaded, creator]) + + return ( + + <> + + + {/* Desktop Layout - Horizontal */} +
+ + {new Date(creator.createdAt).toLocaleString()} + +
+
+ {/* Profile Picture */} +
+ +
+ + {/* Creator Info */} +
+
{profile.name}
+

{profile.about}

+ + {/* Nostr Public Key */} +
+
+ Nostr Public Key: +
+
+
+ {creator.npub} +
+ +
+
+ + {/* BCH Address */} +
+
+ BCH Address: +
+
+
+ {creator.bchAddr} +
+ +
+
+
+ + {/* Action Buttons */} +
+ + +
+
+ + {/* Mobile Layout - Vertical */} +
+ {/* Profile Picture */} +
+ +
+ + {/* Creator Info */} +
+
{profile.name}
+

{profile.about}

+ + {/* Nostr Public Key */} +
+
+ Nostr Public Key: +
+
+
+ {creator.npub} +
+ +
+
+ + {/* BCH Address */} +
+
+ BCH Address: +
+
+
+ {creator.bchAddr} +
+ +
+
+
+ + {/* Action Buttons */} +
+ + +
+
+
+
+ + ) +} + +export default ContentCard diff --git a/src/components/app-body/nostr/content-creators/content-creators-list.js b/src/components/app-body/nostr/content-creators/content-creators-list.js new file mode 100644 index 0000000..0c3643c --- /dev/null +++ b/src/components/app-body/nostr/content-creators/content-creators-list.js @@ -0,0 +1,65 @@ +import React, { useState, useEffect } from 'react' +import { Container, Spinner } from 'react-bootstrap' + +import axios from 'axios' +// Local libraries +import config from '../../../../config' +import ContentCard from './content-card' +// Global variables and constants +const SERVER = config.dexServer +function ContentCreators (props) { + const [creators, setCreators] = useState([]) + const [loaded, setLoaded] = useState(false) + + useEffect(() => { + const loadCreators = async () => { + try { + const creators = await axios.get(`${SERVER}/sm/list/all/0`) + console.log(creators.data) + setCreators(creators.data) + setLoaded(true) + } catch (error) { + setLoaded(true) + } + } + + if (!loaded) { + loadCreators() + } + }, [loaded]) + + return ( + +
+

Content Creators

+

+ Discover amazing content creators in the Bitcoin Cash ecosystem +

+
+ + {!loaded && ( +
+ +
Loading content creators...
+
+ )} + + {loaded && ( +
+ {creators.map((creator, i) => ( + + ))} +
+ )} + + {loaded && creators.length === 0 && ( +
+ +
No content creators found
+
+ )} +
+ ) +} + +export default ContentCreators diff --git a/src/components/app-body/nostr/content-creators/index.js b/src/components/app-body/nostr/content-creators/index.js new file mode 100644 index 0000000..bcfb651 --- /dev/null +++ b/src/components/app-body/nostr/content-creators/index.js @@ -0,0 +1,15 @@ +import React from 'react' +import { Container } from 'react-bootstrap' +import ContentCreatorsList from './content-creators-list.js' + +function ContentCreators (props) { + return ( + <> + + + + + ) +} + +export default ContentCreators diff --git a/src/components/nav-menu/index.js b/src/components/nav-menu/index.js index b67241e..a957ba3 100644 --- a/src/components/nav-menu/index.js +++ b/src/components/nav-menu/index.js @@ -77,6 +77,13 @@ function NavMenu (props) { > Nostr Profile + + Content Creators +