diff --git a/src/components/profile/DataTables/UserRelaysTable.js b/src/components/profile/DataTables/UserRelaysTable.js new file mode 100644 index 0000000..802b266 --- /dev/null +++ b/src/components/profile/DataTables/UserRelaysTable.js @@ -0,0 +1,139 @@ +import React, { useState, useEffect, useCallback } from "react"; +import { DataTable } from "primereact/datatable"; +import { Column } from "primereact/column"; +import { InputText } from "primereact/inputtext"; +import GenericButton from "@/components/buttons/GenericButton"; +import { useToast } from "@/hooks/useToast"; +import appConfig from "@/config/appConfig"; + +const UserRelaysTable = ({ ndk, userRelays, setUserRelays, reInitializeNDK }) => { + const [collapsed, setCollapsed] = useState(true); + const [newRelayUrl, setNewRelayUrl] = useState(""); + const { showToast } = useToast(); + const [relayStatuses, setRelayStatuses] = useState({}); + const [updateTrigger, setUpdateTrigger] = useState(0); + + const updateRelayStatuses = useCallback(() => { + if (ndk) { + const statuses = {}; + ndk.pool.relays.forEach((relay, url) => { + statuses[url] = relay.connectivity.status === 5; + }); + setRelayStatuses(statuses); + } + }, [ndk]); + + // Effect for periodic polling + useEffect(() => { + const intervalId = setInterval(() => { + setUpdateTrigger(prev => prev + 1); + }, 7000); + return () => clearInterval(intervalId); + }, []); + + useEffect(() => { + updateRelayStatuses(); + }, [updateRelayStatuses, updateTrigger]); + + const addRelay = () => { + if (newRelayUrl && !userRelays.includes(newRelayUrl)) { + setUserRelays([...userRelays, newRelayUrl]); + setNewRelayUrl(""); + reInitializeNDK(); + setCollapsed(true); + showToast("success", "Relay added", "Relay successfully added to your list of relays."); + } + }; + + const removeRelay = (url) => { + if (!appConfig.defaultRelayUrls.includes(url)) { + setUserRelays(userRelays.filter(relay => relay !== url)); + reInitializeNDK(); + setCollapsed(true); + showToast("success", "Relay removed", "Relay successfully removed from your list of relays."); + } + }; + + const header = ( +
+
+
+

Relays

+

Manage your connected relays

+
+ setCollapsed(!collapsed)} + /> +
+ + {!collapsed && ( +
+ setNewRelayUrl(e.target.value)} + className="flex-1" + /> + +
+ )} +
+ ); + + const relayStatusBody = (url) => { + const isConnected = relayStatuses[url]; + return ( + + ); + }; + + const relayActionsBody = (rowData) => { + return ( +
+ {!appConfig.defaultRelayUrls.includes(rowData) ? ( + removeRelay(rowData)} + /> + ) : ( + removeRelay(rowData)} + tooltip="Cannot remove default relays at this time (soon ™)" + tooltipOptions={{ position: 'top' }} + style={{ + pointerEvents: 'none', + cursor: 'not-allowed' + }} + /> + )} +
+ ); + }; + + return ( +
+ + url} header="Relay URL"> + + + +
+ ); +}; + +export default UserRelaysTable; \ No newline at end of file diff --git a/src/components/profile/UserProfile.js b/src/components/profile/UserProfile.js index 2df31b6..cd10e04 100644 --- a/src/components/profile/UserProfile.js +++ b/src/components/profile/UserProfile.js @@ -38,8 +38,11 @@ const UserProfile = () => { ) }
- -
+
+ {user && } +
+ +
{account && account?.provider === "github" ? ( ) : ( diff --git a/src/components/profile/UserProfileCard.js b/src/components/profile/UserProfileCard.js index 961df81..e7186e2 100644 --- a/src/components/profile/UserProfileCard.js +++ b/src/components/profile/UserProfileCard.js @@ -46,7 +46,7 @@ const UserProfileCard = ({ user }) => { ]; const MobileProfileCard = () => ( -
+
{ src={returnImageProxy(user.avatar, user?.pubkey || "")} width={100} height={100} - className="rounded-full mt-2 mx-auto" + className="rounded-full m-2 mt-0" />

{user.username || user?.name || user?.email || "Anon"} @@ -84,7 +84,7 @@ const UserProfileCard = ({ user }) => { ) } {user?.createdAt && ( -

+

Joined: {new Date(user.createdAt).toLocaleDateString()}

)} @@ -119,21 +119,21 @@ const UserProfileCard = ({ user }) => {

)} -
+
); const DesktopProfileCard = () => ( -
+
user's avatar { const [user, setUser] = useState(null); - const [collapsed, setCollapsed] = useState(true); const { ndk, userRelays, setUserRelays, reInitializeNDK } = useNDKContext(); const { data: session } = useSession(); - const { returnImageProxy } = useImageProxy(); - const menu = useRef(null); const windowWidth = useWindowWidth(); - const [newRelayUrl, setNewRelayUrl] = useState(""); - const { showToast } = useToast(); - const [relayStatuses, setRelayStatuses] = useState({}); - const [updateTrigger, setUpdateTrigger] = useState(0); useEffect(() => { if (session?.user) { @@ -39,256 +25,40 @@ const UserSettings = () => { } }, [session]); - useEffect(() => { - if (ndk) { - updateRelayStatuses(); - } - }, [ndk]); - - const copyToClipboard = (text) => { - navigator.clipboard.writeText(text); - showToast("success", "Copied", "Copied to clipboard"); - }; - - - const updateRelayStatuses = useCallback(() => { - // export enum NDKRelayStatus { - // DISCONNECTING, // 0 - // DISCONNECTED, // 1 - // RECONNECTING, // 2 - // FLAPPING, // 3 - // CONNECTING, // 4 - - // // connected states - // CONNECTED, // 5 - // AUTH_REQUESTED, // 6 - // AUTHENTICATING, // 7 - // AUTHENTICATED, // 8 - // } - if (ndk) { - const statuses = {}; - ndk.pool.relays.forEach((relay, url) => { - statuses[url] = relay.connectivity.status === 5; - }); - setRelayStatuses(statuses); - } - }, [ndk]); - - // Effect for periodic polling - useEffect(() => { - const intervalId = setInterval(() => { - setUpdateTrigger(prev => prev + 1); - }, 7000); // Poll every 7 seconds - - return () => clearInterval(intervalId); // Cleanup on unmount - }, []); - - // Effect to update on every render and when updateTrigger changes - useEffect(() => { - updateRelayStatuses(); - }, [updateRelayStatuses, updateTrigger]); - - const relayStatusBody = (url) => { - const isConnected = relayStatuses[url]; - return ( - - ); - }; - - const addRelay = () => { - if (newRelayUrl && !userRelays.includes(newRelayUrl)) { - setUserRelays([...userRelays, newRelayUrl]); - setNewRelayUrl(""); - reInitializeNDK(); - setCollapsed(true); - showToast("success", "Relay added", "Relay successfully added to your list of relays."); - } - }; - - const removeRelay = (url) => { - if (!appConfig.defaultRelayUrls.includes(url)) { - setUserRelays(userRelays.filter(relay => relay !== url)); - reInitializeNDK(); - setCollapsed(true); - showToast("success", "Relay removed", "Relay successfully removed from your list of relays."); - } - }; - - const relayActionsBody = (rowData) => { - return ( -
- {!appConfig.defaultRelayUrls.includes(rowData) ? ( - removeRelay(rowData)} - /> - ) : ( - <> - removeRelay(rowData)} - tooltip="Cannot remove default relays at this time (soon ™)" - tooltipOptions={{ position: 'top' }} - style={{ - pointerEvents: 'none', - cursor: 'not-allowed' - }} - /> - - )} -
- ); - }; - - const PanelHeader = (options) => { - return ( -
-

Relays

- -
- ); - }; - - const header = ( -
- Purchases -
- ); - - const menuItems = [ - ...(user?.privkey ? [{ - label: 'Copy nsec', - icon: 'pi pi-key', - command: () => { - const privkeyBuffer = Buffer.from(user.privkey, 'hex'); - copyToClipboard(nip19.nsecEncode(privkeyBuffer)); - } - }] : []), - { - label: 'Copy npub', - icon: 'pi pi-user', - command: () => { - copyToClipboard(nip19.npubEncode(user?.pubkey)); - } - }, - { - label: 'Open Nostr Profile', - icon: 'pi pi-external-link', - command: () => window.open(`https://nostr.com/${nip19.npubEncode(user?.pubkey)}`, '_blank') - } - ]; - return ( user && (
- { - windowWidth < 768 && ( -

Settings

- ) - } -
-
- user's avatar -
- menu.current.toggle(e)} - /> - -
-
+ {windowWidth < 768 && ( +

Settings

+ )} +
+
+ -

- {user.username || user?.name || user?.email || "Anon"} -

- {user.pubkey && ( -

- - {nip19.npubEncode(user.pubkey)} -

- )} - {user?.lightningAddress && ( -

- Lightning Address: {user.lightningAddress.name}@plebdevs.com copyToClipboard(user.lightningAddress.name + "@plebdevs.com")} /> -

- )} - {user?.nip05 && ( -

- NIP-05: {user.nip05.name}@plebdevs.com copyToClipboard(user.nip05.name + "@plebdevs.com")} /> -

- )} -
-
-
+ {/* Lightning Info Card */} +
+
-

- Lightning Wallet Connection -

+

Lightning Wallet Connection

-

+

Connect your Lightning wallet for easier payments across the platform

+ + {/* Subscription Modal */} + {user && } +
+ +
+
- {user && ( - - )} -
-
- setCollapsed(e.value)} - > -
- setNewRelayUrl(e.target.value)} - /> - -
-
- setUpdateTrigger(prev => prev + 1)} // Trigger update when table value changes - > - url} header="Relay URL"> - - -
) diff --git a/src/components/profile/subscription/SubscribeModal.js b/src/components/profile/subscription/SubscribeModal.js index 6b951a1..a7d0b26 100644 --- a/src/components/profile/subscription/SubscribeModal.js +++ b/src/components/profile/subscription/SubscribeModal.js @@ -148,7 +148,7 @@ const SubscribeModal = ({ user }) => { return ( <> - + {subscribed && !user?.role?.nwc && (