parent
7c1d5273fc
commit
379bce6f9e
@ -8,11 +8,12 @@ import NoteToSelf from "Element/NoteToSelf";
|
||||
import useLogin from "Hooks/useLogin";
|
||||
import WriteMessage from "Element/WriteMessage";
|
||||
import { Chat, ChatType, useChatSystem } from "chat";
|
||||
import { Nip4ChatSystem } from "chat/nip4";
|
||||
|
||||
export default function DmWindow({ id }: { id: string }) {
|
||||
const pubKey = useLogin().publicKey;
|
||||
const dms = useChatSystem();
|
||||
const chat = dms.find(a => a.id === id);
|
||||
const chat = dms.find(a => a.id === id) ?? Nip4ChatSystem.createChatObj(id, []);
|
||||
|
||||
function sender() {
|
||||
if (id === pubKey) {
|
||||
@ -24,7 +25,7 @@ export default function DmWindow({ id }: { id: string }) {
|
||||
if (chat?.profile) {
|
||||
return <ProfileImage pubkey={id} className="f-grow mb10" profile={chat.profile} />;
|
||||
}
|
||||
return <ProfileImage pubkey={""} className="f-grow mb10" overrideUsername={chat?.id} />;
|
||||
return <ProfileImage pubkey={id ?? ""} className="f-grow mb10" overrideUsername={chat?.id} />;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -34,7 +35,7 @@ export default function DmWindow({ id }: { id: string }) {
|
||||
<div className="flex f-col">{chat && <DmChatSelected chat={chat} />}</div>
|
||||
</div>
|
||||
<div>
|
||||
<WriteMessage chatId={id} />
|
||||
<WriteMessage chat={chat} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -7,9 +7,9 @@ import useFileUpload from "Upload";
|
||||
import { openFile } from "SnortUtils";
|
||||
import Textarea from "./Textarea";
|
||||
import { System } from "index";
|
||||
import { useChatSystem } from "chat";
|
||||
import { Chat } from "chat";
|
||||
|
||||
export default function WriteMessage({ chatId }: { chatId: string }) {
|
||||
export default function WriteMessage({ chat }: { chat: Chat }) {
|
||||
const [msg, setMsg] = useState("");
|
||||
const [sending, setSending] = useState(false);
|
||||
const [uploading, setUploading] = useState(false);
|
||||
@ -17,7 +17,6 @@ export default function WriteMessage({ chatId }: { chatId: string }) {
|
||||
const [error, setError] = useState("");
|
||||
const publisher = useEventPublisher();
|
||||
const uploader = useFileUpload();
|
||||
const chat = useChatSystem().find(a => a.id === chatId);
|
||||
|
||||
async function attachFile() {
|
||||
try {
|
||||
|
@ -1,3 +0,0 @@
|
||||
.chat-page {
|
||||
height: calc(100vh - 57px);
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import DmWindow from "Element/DmWindow";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { bech32ToHex } from "SnortUtils";
|
||||
|
||||
import "./ChatPage.css";
|
||||
|
||||
export default function ChatPage() {
|
||||
const { id } = useParams();
|
||||
|
||||
return (
|
||||
<div className="chat-page">
|
||||
<DmWindow id={bech32ToHex(id ?? "")} />
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { NostrPrefix } from "@snort/system";
|
||||
import { useUserProfile } from "@snort/system-react";
|
||||
|
||||
import UnreadCount from "Element/UnreadCount";
|
||||
import ProfileImage, { getDisplayName } from "Element/ProfileImage";
|
||||
import { hexToBech32 } from "SnortUtils";
|
||||
import { hexToBech32, parseId } from "SnortUtils";
|
||||
import NoteToSelf from "Element/NoteToSelf";
|
||||
import useModeration from "Hooks/useModeration";
|
||||
import useLogin from "Hooks/useLogin";
|
||||
@ -29,7 +29,9 @@ export default function MessagesPage() {
|
||||
const login = useLogin();
|
||||
const { formatMessage } = useIntl();
|
||||
const navigate = useNavigate();
|
||||
const [chat, setChat] = useState<string>();
|
||||
const { id } = useParams();
|
||||
const parsedId = parseId(id ?? "");
|
||||
const [chat, setChat] = useState(id ? parsedId : undefined);
|
||||
const pageWidth = usePageWidth();
|
||||
|
||||
const chats = useChatSystem();
|
||||
|
@ -107,7 +107,7 @@ export function profileLink(hex: HexKey, relays?: Array<string> | string) {
|
||||
* Convert hex to bech32
|
||||
*/
|
||||
export function hexToBech32(hrp: string, hex?: string) {
|
||||
if (typeof hex !== "string" || hex.length === 0 || hex.length % 2 !== 0) {
|
||||
if (typeof hex !== "string" || hex.length === 0 || hex.length % 2 !== 0 || !isHex(hex)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -173,6 +173,14 @@ export function deepClone<T>(obj: T) {
|
||||
}
|
||||
}
|
||||
|
||||
export function isHex(s: string) {
|
||||
// 48-57 = 0-9
|
||||
// 65-90 = A-Z
|
||||
// 97-122 = a-z
|
||||
return [...s]
|
||||
.map(v => v.charCodeAt(0))
|
||||
.every(v => (v >= 48 && v <= 57) || (v >= 65 && v <= 90) || v >= 97 || v <= 122);
|
||||
}
|
||||
/**
|
||||
* Simple debounce
|
||||
*/
|
||||
|
@ -40,25 +40,29 @@ export class Nip4ChatSystem extends ExternalStore<Array<Chat>> implements ChatSy
|
||||
|
||||
listChats(): Chat[] {
|
||||
const myDms = this.#nip4Events();
|
||||
return dedupe(myDms.map(a => a.pubkey)).map(a => {
|
||||
return dedupe(myDms.map(a => chatTo(a))).map(a => {
|
||||
const messages = myDms.filter(b => chatTo(b) === a || b.pubkey === a);
|
||||
const last = lastReadInChat(a);
|
||||
return {
|
||||
type: ChatType.DirectMessage,
|
||||
id: a,
|
||||
unread: messages.reduce((acc, v) => (v.created_at > last ? acc++ : acc), 0),
|
||||
lastMessage: messages.reduce((acc, v) => (v.created_at > acc ? v.created_at : acc), 0),
|
||||
messages,
|
||||
createMessage: (msg, pub) => {
|
||||
return pub.sendDm(msg, a);
|
||||
},
|
||||
sendMessage: (ev: NostrEvent, system: SystemInterface) => {
|
||||
system.BroadcastEvent(ev);
|
||||
},
|
||||
} as Chat;
|
||||
return Nip4ChatSystem.createChatObj(a, messages);
|
||||
});
|
||||
}
|
||||
|
||||
static createChatObj(id: string, messages: Array<NostrEvent>) {
|
||||
const last = lastReadInChat(id);
|
||||
return {
|
||||
type: ChatType.DirectMessage,
|
||||
id,
|
||||
unread: messages.reduce((acc, v) => (v.created_at > last ? acc++ : acc), 0),
|
||||
lastMessage: messages.reduce((acc, v) => (v.created_at > acc ? v.created_at : acc), 0),
|
||||
messages,
|
||||
createMessage: (msg, pub) => {
|
||||
return pub.sendDm(msg, id);
|
||||
},
|
||||
sendMessage: (ev: NostrEvent, system: SystemInterface) => {
|
||||
system.BroadcastEvent(ev);
|
||||
},
|
||||
} as Chat;
|
||||
}
|
||||
|
||||
#nip4Events() {
|
||||
return this.#cache.snapshot().filter(a => a.kind === EventKind.DirectMessage);
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import SettingsPage, { SettingsRoutes } from "Pages/SettingsPage";
|
||||
import ErrorPage from "Pages/ErrorPage";
|
||||
import VerificationPage from "Pages/Verification";
|
||||
import MessagesPage from "Pages/MessagesPage";
|
||||
import ChatPage from "Pages/ChatPage";
|
||||
import DonatePage from "Pages/DonatePage";
|
||||
import HashTagsPage from "Pages/HashTagsPage";
|
||||
import SearchPage from "Pages/SearchPage";
|
||||
@ -123,13 +122,9 @@ export const router = createBrowserRouter([
|
||||
element: <VerificationPage />,
|
||||
},
|
||||
{
|
||||
path: "/messages",
|
||||
path: "/messages/:id?",
|
||||
element: <MessagesPage />,
|
||||
},
|
||||
{
|
||||
path: "/messages/:id",
|
||||
element: <ChatPage />,
|
||||
},
|
||||
{
|
||||
path: "/donate",
|
||||
element: <DonatePage />,
|
||||
|
@ -244,7 +244,9 @@ export class NostrSystem extends ExternalStore<SystemSnapshot> implements System
|
||||
*/
|
||||
BroadcastEvent(ev: NostrEvent) {
|
||||
for (const [, s] of this.#sockets) {
|
||||
s.SendEvent(ev);
|
||||
if (!s.Ephemeral) {
|
||||
s.SendEvent(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user