91 lines
2.2 KiB
TypeScript
91 lines
2.2 KiB
TypeScript
import { useSyncExternalStore } from "react";
|
|
import { Nip4ChatSystem } from "./nip4";
|
|
import { EventKind, EventPublisher, NostrEvent, RequestBuilder, SystemInterface, UserMetadata } from "@snort/system";
|
|
import { unwrap } from "@snort/shared";
|
|
import { Chats } from "cache";
|
|
import { findTag, unixNow } from "SnortUtils";
|
|
import { Nip29ChatSystem } from "./nip29";
|
|
|
|
export enum ChatType {
|
|
DirectMessage = 1,
|
|
PublicGroupChat = 2,
|
|
PrivateGroupChat = 3,
|
|
}
|
|
|
|
export interface Chat {
|
|
type: ChatType;
|
|
id: string;
|
|
unread: number;
|
|
lastMessage: number;
|
|
messages: Array<NostrEvent>;
|
|
profile?: UserMetadata;
|
|
createMessage(msg: string, pub: EventPublisher): Promise<NostrEvent>;
|
|
sendMessage(ev: NostrEvent, system: SystemInterface): void | Promise<void>;
|
|
}
|
|
|
|
export interface ChatSystem {
|
|
/**
|
|
* Create a request for this system to get updates
|
|
*/
|
|
subscription(id: string): RequestBuilder | undefined;
|
|
onEvent(evs: Array<NostrEvent>): Promise<void> | void;
|
|
|
|
listChats(): Array<Chat>;
|
|
}
|
|
|
|
export const Nip4Chats = new Nip4ChatSystem(Chats);
|
|
export const Nip29Chats = new Nip29ChatSystem(Chats);
|
|
|
|
/**
|
|
* Extract the P tag of the event
|
|
*/
|
|
export function chatTo(e: NostrEvent) {
|
|
if (e.kind === EventKind.DirectMessage) {
|
|
return unwrap(findTag(e, "p"));
|
|
} else if (e.kind === EventKind.SimpleChatMessage) {
|
|
const gt = unwrap(e.tags.find(a => a[0] === "g"));
|
|
return `${gt[2]}${gt[1]}`;
|
|
}
|
|
throw new Error("Not a chat message");
|
|
}
|
|
|
|
export function inChatWith(e: NostrEvent, myPk: string) {
|
|
if (e.pubkey === myPk) {
|
|
return chatTo(e);
|
|
} else {
|
|
return e.pubkey;
|
|
}
|
|
}
|
|
|
|
export function lastReadInChat(id: string) {
|
|
const k = `dm:seen:${id}`;
|
|
return parseInt(window.localStorage.getItem(k) ?? "0");
|
|
}
|
|
|
|
export function setLastReadIn(id: string) {
|
|
const now = unixNow();
|
|
const k = `dm:seen:${id}`;
|
|
window.localStorage.setItem(k, now.toString());
|
|
}
|
|
|
|
export function useNip4Chat() {
|
|
return useSyncExternalStore(
|
|
c => Nip4Chats.hook(c),
|
|
() => Nip4Chats.snapshot()
|
|
);
|
|
}
|
|
|
|
export function useNip29Chat() {
|
|
return useSyncExternalStore(
|
|
c => Nip29Chats.hook(c),
|
|
() => Nip29Chats.snapshot()
|
|
);
|
|
}
|
|
|
|
export function useChatSystem() {
|
|
const nip4 = useNip4Chat();
|
|
const nip29 = useNip29Chat();
|
|
|
|
return [...nip4, ...nip29];
|
|
}
|