mirror of
https://github.com/DustinBrett/daedalOS.git
synced 2025-12-06 00:20:05 +01:00
Nostr Messenger PT4
This commit is contained in:
parent
682cc7ebbd
commit
9c6b381dc1
|
|
@ -95,6 +95,7 @@
|
|||
}
|
||||
}
|
||||
],
|
||||
"jsx-a11y/no-autofocus": "off",
|
||||
"no-console": ["error", { "allow": ["info", "error"] }],
|
||||
"no-constant-binary-expression": "error",
|
||||
"no-implicit-coercion": "error",
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, useMemo } from "react";
|
||||
import {
|
||||
decryptMessage,
|
||||
shortTimeStamp,
|
||||
} from "components/apps/Messenger/functions";
|
||||
import { MILLISECONDS_IN_MINUTE } from "utils/constants";
|
||||
import { type Event } from "nostr-tools";
|
||||
import { nip19, type Event } from "nostr-tools";
|
||||
import { useNostrProfile } from "components/apps/Messenger/hooks";
|
||||
import { Avatar } from "components/apps/Messenger/Icons";
|
||||
import Button from "styles/common/Button";
|
||||
import { useMenu } from "contexts/menu";
|
||||
|
||||
type ContactProps = {
|
||||
lastEvent: Event;
|
||||
|
|
@ -34,6 +35,18 @@ const Contact: FC<ContactProps> = ({
|
|||
const [timeStamp, setTimeStamp] = useState("");
|
||||
const { picture, userName } = useNostrProfile(pubkey);
|
||||
const unreadClass = unreadEvent ? "unread" : undefined;
|
||||
const { contextMenu } = useMenu();
|
||||
const { onContextMenuCapture } = useMemo(
|
||||
() =>
|
||||
contextMenu?.(() => [
|
||||
{
|
||||
action: () =>
|
||||
navigator.clipboard?.writeText(nip19.npubEncode(pubkey)),
|
||||
label: "Copy npub address",
|
||||
},
|
||||
]),
|
||||
[contextMenu, pubkey]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (content) {
|
||||
|
|
@ -57,7 +70,7 @@ const Contact: FC<ContactProps> = ({
|
|||
}, [created_at, lastEvent]);
|
||||
|
||||
return (
|
||||
<li className={unreadClass}>
|
||||
<li className={unreadClass} onContextMenuCapture={onContextMenuCapture}>
|
||||
<Button onClick={onClick}>
|
||||
<figure>
|
||||
{picture ? <img alt={userName} src={picture} /> : <Avatar />}
|
||||
|
|
|
|||
|
|
@ -26,3 +26,18 @@ export const Send = memo(() => (
|
|||
<path d="m16.692 12.474-13.186.786c-.314 0-.47.157-.47.314l-1.884 6.441c-.314.786-.162 1.875.627 2.505.631.47 1.727.58 2.355.323l17.58-8.798c.942-.47 1.413-1.413 1.256-2.356a2.496 2.496 0 0 0-1.255-1.571L4.134 1.163c-.785-.263-1.727-.157-2.355.315-.784.628-.941 1.57-.627 2.513l1.883 6.441c0 .157.314.314.471.314l13.186.786s.47 0 .47.471-.47.471-.47.471Z" />
|
||||
</svg>
|
||||
));
|
||||
|
||||
export const Back = memo(() => (
|
||||
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M244 400 100 256l144-144M120 256h292"
|
||||
style={{
|
||||
fill: "none",
|
||||
stroke: "currentColor",
|
||||
strokeLinecap: "round",
|
||||
strokeLinejoin: "round",
|
||||
strokeWidth: "50px",
|
||||
}}
|
||||
/>
|
||||
</svg>
|
||||
));
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { useNostrProfile } from "components/apps/Messenger/hooks";
|
||||
import { useMemo } from "react";
|
||||
import Button from "styles/common/Button";
|
||||
import { Back } from "components/apps/FileExplorer/NavigationIcons";
|
||||
import StyledProfileBanner from "components/apps/Messenger/StyledProfileBanner";
|
||||
import { Avatar, Write } from "components/apps/Messenger/Icons";
|
||||
import { Avatar, Back, Write } from "components/apps/Messenger/Icons";
|
||||
import { UNKNOWN_PUBLIC_KEY } from "components/apps/Messenger/constants";
|
||||
import { haltEvent } from "utils/functions";
|
||||
|
||||
const GRADIENT = "linear-gradient(rgba(0, 0, 0, 0.10), rgba(0, 0, 0, 0.5))";
|
||||
const STYLING =
|
||||
|
|
@ -22,8 +23,14 @@ const ProfileBanner: FC<ProfileBannerProps> = ({
|
|||
selectedRecipientKey,
|
||||
publicKey,
|
||||
}) => {
|
||||
const { banner, picture, userName } = useNostrProfile(
|
||||
selectedRecipientKey || publicKey
|
||||
const {
|
||||
banner,
|
||||
picture,
|
||||
userName = "...",
|
||||
} = useNostrProfile(
|
||||
selectedRecipientKey === UNKNOWN_PUBLIC_KEY
|
||||
? ""
|
||||
: selectedRecipientKey || publicKey
|
||||
);
|
||||
const style = useMemo(
|
||||
() =>
|
||||
|
|
@ -32,16 +39,10 @@ const ProfileBanner: FC<ProfileBannerProps> = ({
|
|||
);
|
||||
|
||||
return (
|
||||
<StyledProfileBanner style={style}>
|
||||
{selectedRecipientKey ? (
|
||||
<Button onClick={goHome}>
|
||||
<Back />
|
||||
</Button>
|
||||
) : (
|
||||
<Button className="write" onClick={newChat}>
|
||||
<Write />
|
||||
</Button>
|
||||
)}
|
||||
<StyledProfileBanner onContextMenuCapture={haltEvent} style={style}>
|
||||
<Button onClick={selectedRecipientKey ? goHome : newChat}>
|
||||
{selectedRecipientKey ? <Back /> : <Write />}
|
||||
</Button>
|
||||
<figure>
|
||||
{picture ? <img alt={userName} src={picture} /> : <Avatar />}
|
||||
<figcaption>{userName}</figcaption>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import Button from "styles/common/Button";
|
|||
import { useNostr } from "nostr-react";
|
||||
import { createMessageEvent } from "components/apps/Messenger/functions";
|
||||
import { Send } from "components/apps/Messenger/Icons";
|
||||
import { haltEvent } from "utils/functions";
|
||||
import { UNKNOWN_PUBLIC_KEY } from "./constants";
|
||||
|
||||
type SendMessageProps = { publicKey: string; recipientPublicKey: string };
|
||||
|
||||
|
|
@ -13,6 +15,7 @@ const SendMessage: FC<SendMessageProps> = ({
|
|||
}) => {
|
||||
const { publish } = useNostr();
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const isUnknownKey = recipientPublicKey === UNKNOWN_PUBLIC_KEY;
|
||||
const sendMessage = useCallback(async () => {
|
||||
const message = inputRef.current?.value;
|
||||
|
||||
|
|
@ -27,13 +30,19 @@ const SendMessage: FC<SendMessageProps> = ({
|
|||
<StyledSendMessage>
|
||||
<input
|
||||
ref={inputRef}
|
||||
disabled={isUnknownKey}
|
||||
onKeyDown={({ key }) => {
|
||||
if (key === "Enter") sendMessage();
|
||||
}}
|
||||
placeholder="Type a message..."
|
||||
type="text"
|
||||
autoFocus
|
||||
/>
|
||||
<Button onClick={sendMessage}>
|
||||
<Button
|
||||
disabled={isUnknownKey}
|
||||
onClick={sendMessage}
|
||||
onContextMenuCapture={haltEvent}
|
||||
>
|
||||
<Send />
|
||||
</Button>
|
||||
</StyledSendMessage>
|
||||
|
|
|
|||
|
|
@ -11,10 +11,15 @@ const StyledContacts = styled.ol`
|
|||
li {
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
margin: 8px;
|
||||
padding: 8px;
|
||||
position: relative;
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #3a3b3c;
|
||||
}
|
||||
|
|
@ -25,6 +30,7 @@ const StyledContacts = styled.ol`
|
|||
}
|
||||
|
||||
figure {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
width: calc(100% - 15px);
|
||||
|
|
@ -38,10 +44,12 @@ const StyledContacts = styled.ol`
|
|||
max-width: 56px;
|
||||
min-height: 56px;
|
||||
min-width: 56px;
|
||||
pointer-events: none;
|
||||
width: 56px;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
|
|
@ -51,18 +59,21 @@ const StyledContacts = styled.ol`
|
|||
|
||||
> span {
|
||||
color: #e4e6eb;
|
||||
cursor: pointer;
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
> div {
|
||||
color: #b0b3b8;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
gap: 3px;
|
||||
width: 100%;
|
||||
|
||||
div:first-child {
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
|
@ -75,6 +86,7 @@ const StyledContacts = styled.ol`
|
|||
|
||||
div:last-child {
|
||||
color: #8b8d92;
|
||||
cursor: pointer;
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import styled from "styled-components";
|
||||
|
||||
const StyledProfileBanner = styled.div`
|
||||
background: linear-gradient(rgba(255, 255, 255, 10%), rgba(0, 0, 0, 50%));
|
||||
border-bottom: 1px solid rgb(57, 58, 59);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
|
|
@ -31,27 +32,28 @@ const StyledProfileBanner = styled.div`
|
|||
min-width: 38px;
|
||||
width: 38px;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
padding-top: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
cursor: pointer;
|
||||
height: 30px;
|
||||
padding-top: 3px;
|
||||
width: 30px;
|
||||
|
||||
svg:first-child {
|
||||
background-color: rgb(0, 0, 0, 50%);
|
||||
border-radius: 5px;
|
||||
color: #fff;
|
||||
fill: #fff;
|
||||
height: 24px;
|
||||
outline: 4px solid rgb(0, 0, 0, 50%);
|
||||
pointer-events: none;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
&.write {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
|
||||
svg {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
|
|||
13
components/apps/Messenger/StyledTo.ts
Normal file
13
components/apps/Messenger/StyledTo.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import styled from "styled-components";
|
||||
|
||||
const StyledTo = styled.div`
|
||||
input {
|
||||
background-color: #242526;
|
||||
border-bottom: 1px solid rgb(57, 58, 59);
|
||||
color: #fff;
|
||||
padding: 15px;
|
||||
width: 100%;
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledTo;
|
||||
25
components/apps/Messenger/To.tsx
Normal file
25
components/apps/Messenger/To.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import StyledTo from "components/apps/Messenger/StyledTo";
|
||||
|
||||
type ToProps = { setRecipientKey: (key: string) => boolean };
|
||||
|
||||
const To: FC<ToProps> = ({ setRecipientKey }) => (
|
||||
<StyledTo>
|
||||
<input
|
||||
onKeyDown={(event) => {
|
||||
if (
|
||||
event.key === "Enter" &&
|
||||
!setRecipientKey(event.currentTarget.value)
|
||||
) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
event.currentTarget.value = "";
|
||||
}
|
||||
}}
|
||||
placeholder="Type a Nostr address (npub/nprofile/hex)"
|
||||
spellCheck={false}
|
||||
type="text"
|
||||
autoFocus
|
||||
/>
|
||||
</StyledTo>
|
||||
);
|
||||
|
||||
export default To;
|
||||
|
|
@ -1,4 +1,10 @@
|
|||
export const BASE_RW_RELAYS = ["wss://nos.lol/"];
|
||||
export const BASE_RW_RELAYS = [
|
||||
"wss://relayable.org",
|
||||
"wss://ca.relayable.org",
|
||||
"wss://la.relayable.org",
|
||||
"wss://au.relayable.org",
|
||||
"wss://he.relayable.org",
|
||||
];
|
||||
|
||||
export const DM_KIND = 4;
|
||||
|
||||
|
|
@ -6,3 +12,5 @@ export const PRIVATE_KEY_IDB_NAME = "nostr_private_key";
|
|||
export const PUBLIC_KEY_IDB_NAME = "nostr_public_key";
|
||||
|
||||
export const NOTIFICATION_SOUND = "/Program Files/Messenger/notification.mp3";
|
||||
|
||||
export const UNKNOWN_PUBLIC_KEY = "?";
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import {
|
|||
} from "components/apps/Messenger/constants";
|
||||
import { MILLISECONDS_IN_SECOND } from "utils/constants";
|
||||
import { dateToUnix } from "nostr-react";
|
||||
import type { ProfilePointer } from "nostr-tools/lib/nip19";
|
||||
|
||||
export const getRelayUrls = async (
|
||||
publicKey: string,
|
||||
|
|
@ -41,9 +42,13 @@ export const getRelayUrls = async (
|
|||
|
||||
export const toHexKey = (key: string): string => {
|
||||
if (key.startsWith("npub") || key.startsWith("nsec")) {
|
||||
const { data } = nip19.decode(key);
|
||||
try {
|
||||
const { data } = nip19.decode(key);
|
||||
|
||||
if (typeof data === "string") return data;
|
||||
if (typeof data === "string") return data;
|
||||
} catch {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
|
|
@ -202,7 +207,34 @@ export const dataToProfile = (
|
|||
display_name ||
|
||||
name ||
|
||||
username ||
|
||||
(npub || nip19.npubEncode(publicKey)).slice(0, 12),
|
||||
(
|
||||
npub ||
|
||||
(publicKey.startsWith("npub") ? publicKey : nip19.npubEncode(publicKey))
|
||||
).slice(0, 12),
|
||||
website,
|
||||
};
|
||||
};
|
||||
|
||||
export const getPublicHexFromNostrAddress = (key: string): string => {
|
||||
const nprofile = key.startsWith("nprofile");
|
||||
const nsec = key.startsWith("nsec");
|
||||
|
||||
if (nprofile || nsec || key.startsWith("npub")) {
|
||||
try {
|
||||
const { data } = nip19.decode(key) || {};
|
||||
const hex = nprofile
|
||||
? (data as ProfilePointer)?.pubkey
|
||||
: (data as string);
|
||||
|
||||
return nsec ? getPublicKey(hex) : hex;
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return toHexKey(nip19.npubEncode(key));
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,17 +31,16 @@ export const useNostrProfile = (publicKey: string): NostrProfile => {
|
|||
);
|
||||
const [profile, setProfile] = useState<NostrProfile>({} as NostrProfile);
|
||||
const { onEvent } = useNostrEvents({
|
||||
enabled: !cachedProfile,
|
||||
enabled: !cachedProfile && !!publicKey,
|
||||
filter: {
|
||||
authors: [publicKey],
|
||||
kinds: [0],
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(
|
||||
() => setProfile(cachedProfile || dataToProfile(publicKey)),
|
||||
[cachedProfile, publicKey]
|
||||
);
|
||||
useEffect(() => {
|
||||
setProfile(publicKey ? cachedProfile || dataToProfile(publicKey) : {});
|
||||
}, [cachedProfile, publicKey]);
|
||||
|
||||
onEvent(({ content }) => {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import type { ComponentProcessProps } from "components/system/Apps/RenderComponent";
|
||||
import { NostrProvider } from "nostr-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { getRelayUrls } from "components/apps/Messenger/functions";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
getRelayUrls,
|
||||
getPublicHexFromNostrAddress,
|
||||
} from "components/apps/Messenger/functions";
|
||||
import StyledMessenger from "components/apps/Messenger/StyledMessenger";
|
||||
import Contact from "components/apps/Messenger/Contact";
|
||||
import SendMessage from "components/apps/Messenger/SendMessage";
|
||||
|
|
@ -14,35 +17,92 @@ import {
|
|||
import StyledContacts from "components/apps/Messenger/StyledContacts";
|
||||
import ProfileBanner from "components/apps/Messenger/ProfileBanner";
|
||||
import ChatLog from "components/apps/Messenger/ChatLog";
|
||||
import To from "components/apps/Messenger/To";
|
||||
import { UNKNOWN_PUBLIC_KEY } from "components/apps/Messenger/constants";
|
||||
import type { Event } from "nostr-tools";
|
||||
import { haltEvent } from "utils/functions";
|
||||
|
||||
const NostrChat: FC<{
|
||||
id: string;
|
||||
type NostrChatProps = {
|
||||
loginTime: number;
|
||||
processId: string;
|
||||
publicKey: string;
|
||||
wellKnownNames: Record<string, string>;
|
||||
}> = ({ id, loginTime, publicKey, wellKnownNames }) => {
|
||||
};
|
||||
|
||||
const NostrChat: FC<NostrChatProps> = ({
|
||||
processId,
|
||||
loginTime,
|
||||
publicKey,
|
||||
wellKnownNames,
|
||||
}) => {
|
||||
const [seenEventIds, setSeenEventIds] = useState<string[]>([]);
|
||||
const [selectedRecipientKey, setSelectedRecipientKey] = useState<string>("");
|
||||
const changeRecipient = useCallback(
|
||||
(recipientKey: string, currentEvents?: Event[]) =>
|
||||
setSelectedRecipientKey((currenRecipientKey: string) => {
|
||||
if ((currenRecipientKey || recipientKey) && currentEvents) {
|
||||
setSeenEventIds((currentSeenEventIds) => [
|
||||
...new Set([
|
||||
...currentEvents
|
||||
.filter(
|
||||
({ created_at, pubkey }) =>
|
||||
[recipientKey, currenRecipientKey].includes(pubkey) &&
|
||||
created_at > loginTime
|
||||
)
|
||||
.map(({ id }) => id),
|
||||
...currentSeenEventIds,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
return recipientKey;
|
||||
}),
|
||||
[loginTime]
|
||||
);
|
||||
const { contactKeys, events, lastEvents, unreadEvents } = useNostrContacts(
|
||||
publicKey,
|
||||
wellKnownNames,
|
||||
loginTime,
|
||||
seenEventIds
|
||||
);
|
||||
const setRecipientKey = useCallback(
|
||||
(recipientKey: string): boolean => {
|
||||
const hexKey = getPublicHexFromNostrAddress(recipientKey);
|
||||
|
||||
useUnreadStatus(id, unreadEvents.length);
|
||||
if (hexKey) changeRecipient(hexKey);
|
||||
|
||||
return Boolean(hexKey);
|
||||
},
|
||||
[changeRecipient]
|
||||
);
|
||||
|
||||
useUnreadStatus(processId, unreadEvents.length);
|
||||
|
||||
useEffect(() => {
|
||||
if (unreadEvents && selectedRecipientKey) {
|
||||
unreadEvents
|
||||
.filter(({ pubkey }) => pubkey === selectedRecipientKey)
|
||||
.forEach(({ id }) =>
|
||||
setSeenEventIds((currentSeenEventIds) => [
|
||||
...new Set([id, ...currentSeenEventIds]),
|
||||
])
|
||||
);
|
||||
}
|
||||
}, [selectedRecipientKey, unreadEvents]);
|
||||
|
||||
return (
|
||||
<StyledMessenger>
|
||||
<ProfileBanner
|
||||
goHome={() => setSelectedRecipientKey("")}
|
||||
// TODO: Show chat with "To: ..."
|
||||
newChat={() => setSelectedRecipientKey("")}
|
||||
goHome={() => changeRecipient("", events)}
|
||||
newChat={() => changeRecipient(UNKNOWN_PUBLIC_KEY)}
|
||||
publicKey={publicKey}
|
||||
selectedRecipientKey={selectedRecipientKey}
|
||||
/>
|
||||
{selectedRecipientKey ? (
|
||||
<>
|
||||
{selectedRecipientKey === UNKNOWN_PUBLIC_KEY && (
|
||||
<To setRecipientKey={setRecipientKey} />
|
||||
)}
|
||||
<ChatLog
|
||||
events={events}
|
||||
publicKey={publicKey}
|
||||
|
|
@ -54,20 +114,15 @@ const NostrChat: FC<{
|
|||
/>
|
||||
</>
|
||||
) : (
|
||||
<StyledContacts>
|
||||
{contactKeys.map((pubkey) => (
|
||||
<StyledContacts onContextMenu={haltEvent}>
|
||||
{contactKeys.map((contactKey) => (
|
||||
<Contact
|
||||
key={pubkey}
|
||||
lastEvent={lastEvents[pubkey]}
|
||||
onClick={() => {
|
||||
setSeenEventIds((currentSeenEventIds) => [
|
||||
...new Set([lastEvents[pubkey]?.id, ...currentSeenEventIds]),
|
||||
]);
|
||||
setSelectedRecipientKey(pubkey);
|
||||
}}
|
||||
pubkey={pubkey}
|
||||
key={contactKey}
|
||||
lastEvent={lastEvents[contactKey]}
|
||||
onClick={() => changeRecipient(contactKey, events)}
|
||||
pubkey={contactKey}
|
||||
publicKey={publicKey}
|
||||
unreadEvent={unreadEvents.includes(lastEvents[pubkey])}
|
||||
unreadEvent={unreadEvents.includes(lastEvents[contactKey])}
|
||||
/>
|
||||
))}
|
||||
</StyledContacts>
|
||||
|
|
@ -79,11 +134,14 @@ const NostrChat: FC<{
|
|||
const Messenger: FC<ComponentProcessProps> = ({ id }) => {
|
||||
const [loginTime, setLoginTime] = useState<number>(0);
|
||||
const [relayUrls, setRelayUrls] = useState<string[] | undefined>();
|
||||
const initStarted = useRef(false);
|
||||
const { names, relays } = useNip05();
|
||||
const publicKey = usePublicKey();
|
||||
|
||||
useEffect(() => {
|
||||
if (!publicKey || !relays) return;
|
||||
if (initStarted.current || !publicKey || !relays) return;
|
||||
|
||||
initStarted.current = true;
|
||||
|
||||
getRelayUrls(publicKey, relays).then((foundRelays) => {
|
||||
setRelayUrls(foundRelays);
|
||||
|
|
@ -94,8 +152,8 @@ const Messenger: FC<ComponentProcessProps> = ({ id }) => {
|
|||
return publicKey && relayUrls ? (
|
||||
<NostrProvider relayUrls={relayUrls}>
|
||||
<NostrChat
|
||||
id={id}
|
||||
loginTime={loginTime}
|
||||
processId={id}
|
||||
publicKey={publicKey}
|
||||
wellKnownNames={names}
|
||||
/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user