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 = () => (
-
+
{
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 (
-
- );
- };
-
- 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
- )
- }
-
-
-
-
- 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 && (