mirror of
https://github.com/BlowaterNostr/blowater.git
synced 2024-10-18 15:43:20 +00:00
parent
0bfa86e55d
commit
ea4199d05b
11
UI/app.tsx
11
UI/app.tsx
@ -26,10 +26,9 @@ import { About } from "./about.tsx";
|
||||
import { ProfileSyncer } from "../features/profile.ts";
|
||||
import { Popover, PopOverInputChannel } from "./components/popover.tsx";
|
||||
import { Channel } from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
|
||||
import { GroupChatController } from "../group-chat.ts";
|
||||
import { GroupChatController, GroupChatSyncer } from "../group-chat.ts";
|
||||
import { OtherConfig } from "./config-other.ts";
|
||||
import { ProfileGetter } from "./search.tsx";
|
||||
import { ZodError } from "https://esm.sh/zod@3.22.4";
|
||||
import { fromEvents } from "../time.ts";
|
||||
|
||||
export async function Start(database: DexieDatabase) {
|
||||
@ -138,7 +137,13 @@ export class App {
|
||||
const conversationLists = new ConversationLists(args.ctx, profileSyncer);
|
||||
conversationLists.addEvents(args.database.events);
|
||||
|
||||
const groupChatController = new GroupChatController(args.ctx, conversationLists);
|
||||
const groupSyncer = new GroupChatSyncer(args.database, args.pool);
|
||||
const groupChatController = new GroupChatController(
|
||||
args.ctx,
|
||||
conversationLists,
|
||||
groupSyncer,
|
||||
profileSyncer,
|
||||
);
|
||||
for (const e of args.database.events) {
|
||||
if (e.kind == NostrKind.Group_Message) {
|
||||
const err = await groupChatController.addEvent({
|
||||
|
@ -11,15 +11,15 @@ import { convertEventsToChatMessages } from "./dm.ts";
|
||||
|
||||
import { sendDMandImages } from "../features/dm.ts";
|
||||
import { notify } from "./notification.ts";
|
||||
import { emitFunc, EventBus } from "../event-bus.ts";
|
||||
import { EventBus } from "../event-bus.ts";
|
||||
import { ContactUpdate } from "./conversation-list.tsx";
|
||||
import { MyProfileUpdate } from "./edit-profile.tsx";
|
||||
import { EditorEvent, EditorModel, new_DM_EditorModel, SendMessage } from "./editor.tsx";
|
||||
import { DirectMessagePanelUpdate } from "./message-panel.tsx";
|
||||
import { NavigationUpdate } from "./nav.tsx";
|
||||
import { Model } from "./app_model.ts";
|
||||
import { SearchUpdate, SelectConversation } from "./search_model.ts";
|
||||
import { fromEvents, LamportTime } from "../time.ts";
|
||||
import { SearchUpdate } from "./search_model.ts";
|
||||
import { LamportTime } from "../time.ts";
|
||||
import { SignInEvent, signInWithExtension, signInWithPrivateKey } from "./signIn.tsx";
|
||||
import {
|
||||
DirectedMessage_Event,
|
||||
@ -39,11 +39,11 @@ import { EventDetail, EventDetailItem } from "./event-detail.tsx";
|
||||
import { CreateGroup, CreateGroupChat, StartCreateGroupChat } from "./create-group.tsx";
|
||||
import { prepareEncryptedNostrEvent, prepareNormalNostrEvent } from "../lib/nostr-ts/event.ts";
|
||||
import { PublicKey } from "../lib/nostr-ts/key.ts";
|
||||
import { InMemoryAccountContext, NostrAccountContext, NostrEvent, NostrKind } from "../lib/nostr-ts/nostr.ts";
|
||||
import { NostrAccountContext, NostrEvent, NostrKind } from "../lib/nostr-ts/nostr.ts";
|
||||
import { ConnectionPool } from "../lib/nostr-ts/relay.ts";
|
||||
import { OtherConfig } from "./config-other.ts";
|
||||
import { EditGroup, EditGroupChatProfile, StartEditGroupChatProfile } from "./edit-group.tsx";
|
||||
import { GroupChatController, GroupMessage } from "../group-chat.ts";
|
||||
import { GroupChatController } from "../group-chat.ts";
|
||||
import { ChatMessage } from "./message.ts";
|
||||
|
||||
export type UI_Interaction_Event =
|
||||
@ -692,19 +692,19 @@ export async function handle_SendMessage(
|
||||
}
|
||||
} else {
|
||||
// todo: hack, change later
|
||||
const invitation = isInvitation(event.text);
|
||||
if (invitation) {
|
||||
const invitationEvent = await groupControl.createInvitation(invitation, event.pubkey);
|
||||
if (invitationEvent instanceof Error) {
|
||||
return invitationEvent;
|
||||
}
|
||||
console.log(invitationEvent);
|
||||
const err = await pool.sendEvent(invitationEvent);
|
||||
if (err instanceof Error) {
|
||||
return err;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// const invitation = isInvitation(event.text);
|
||||
// if (invitation) {
|
||||
// const invitationEvent = await groupControl.createInvitation(invitation, event.pubkey);
|
||||
// if (invitationEvent instanceof Error) {
|
||||
// return invitationEvent;
|
||||
// }
|
||||
// console.log(invitationEvent);
|
||||
// const err = await pool.sendEvent(invitationEvent);
|
||||
// if (err instanceof Error) {
|
||||
// return err;
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
const events = await sendDMandImages({
|
||||
sender: ctx,
|
||||
receiverPublicKey: event.pubkey,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { z } from "https://esm.sh/zod@3.22.4";
|
||||
import { ConversationLists, ConversationSummary } from "./UI/conversation-list.ts";
|
||||
import { parseJSON } from "./features/profile.ts";
|
||||
import { parseJSON, ProfileSyncer } from "./features/profile.ts";
|
||||
import { prepareEncryptedNostrEvent } from "./lib/nostr-ts/event.ts";
|
||||
import { PrivateKey, PublicKey } from "./lib/nostr-ts/key.ts";
|
||||
import { InMemoryAccountContext, NostrAccountContext, NostrEvent, NostrKind } from "./lib/nostr-ts/nostr.ts";
|
||||
@ -8,6 +8,9 @@ import { GroupMessageGetter } from "./UI/app_update.tsx";
|
||||
import { getTags } from "./nostr.ts";
|
||||
import { ChatMessage } from "./UI/message.ts";
|
||||
import { GroupChatListGetter } from "./UI/conversation-list.tsx";
|
||||
import { Channel, semaphore } from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
|
||||
import { ConnectionPool } from "./lib/nostr-ts/relay.ts";
|
||||
import { Database_Contextual_View } from "./database.ts";
|
||||
|
||||
export type GM_Types = "gm_creation" | "gm_message" | "gm_invitation";
|
||||
|
||||
@ -29,10 +32,13 @@ export class GroupChatController implements GroupMessageGetter, GroupChatListGet
|
||||
created_groups = new Map<string, GroupChatCreation>();
|
||||
invitations = new Map<string, GroupChatInvitation>();
|
||||
messages = new Map<string, ChatMessage[]>();
|
||||
resync_chan = new Channel<null>();
|
||||
|
||||
constructor(
|
||||
private readonly ctx: NostrAccountContext,
|
||||
private readonly conversationLists: ConversationLists,
|
||||
private readonly groupSyncer: GroupChatSyncer,
|
||||
private readonly profileSyncer: ProfileSyncer,
|
||||
) {}
|
||||
|
||||
getGroupChat() {
|
||||
@ -79,6 +85,8 @@ export class GroupChatController implements GroupMessageGetter, GroupChatListGet
|
||||
groupKey: InMemoryAccountContext.New(PrivateKey.Generate()),
|
||||
};
|
||||
this.created_groups.set(groupChatCreation.groupKey.publicKey.bech32(), groupChatCreation);
|
||||
this.groupSyncer.add(groupChatCreation.groupKey.publicKey.hex);
|
||||
this.profileSyncer.add(groupChatCreation.groupKey.publicKey.hex);
|
||||
return groupChatCreation;
|
||||
}
|
||||
|
||||
@ -153,6 +161,8 @@ export class GroupChatController implements GroupMessageGetter, GroupChatListGet
|
||||
groupAddr,
|
||||
};
|
||||
this.invitations.set(groupAddr.bech32(), invitation);
|
||||
this.groupSyncer.add(groupAddr.hex);
|
||||
this.profileSyncer.add(groupAddr.hex);
|
||||
}
|
||||
|
||||
async handleMessage(event: NostrEvent<NostrKind.Group_Message>) {
|
||||
@ -249,6 +259,8 @@ export class GroupChatController implements GroupMessageGetter, GroupChatListGet
|
||||
cipherKey: InMemoryAccountContext.New(cipherKey),
|
||||
};
|
||||
this.created_groups.set(groupKey.toPublicKey().bech32(), groupChatCreation);
|
||||
this.groupSyncer.add(groupKey.toPublicKey().hex);
|
||||
this.profileSyncer.add(groupKey.toPublicKey().hex);
|
||||
|
||||
this.conversationLists.addGroupCreation(groupChatCreation);
|
||||
} else if (content.type == "gm_message") {
|
||||
@ -321,3 +333,41 @@ async function eventType(
|
||||
}
|
||||
return "gm_message";
|
||||
}
|
||||
|
||||
export class GroupChatSyncer {
|
||||
readonly groupAddrSet = new Set<string>();
|
||||
private readonly lock = semaphore(1);
|
||||
|
||||
constructor(
|
||||
private readonly database: Database_Contextual_View,
|
||||
private readonly pool: ConnectionPool,
|
||||
) {
|
||||
}
|
||||
|
||||
async add(...groupAddresses: string[]) {
|
||||
const size = this.groupAddrSet.size;
|
||||
for (const groupAddr of groupAddresses) {
|
||||
this.groupAddrSet.add(groupAddr);
|
||||
}
|
||||
if (this.groupAddrSet.size == size) {
|
||||
return;
|
||||
}
|
||||
const resp = await this.lock(async () => {
|
||||
await this.pool.closeSub(GroupChatSyncer.name);
|
||||
const resp = await this.pool.newSub(GroupChatSyncer.name, {
|
||||
"#p": Array.from(this.groupAddrSet),
|
||||
kinds: [NostrKind.Group_Message],
|
||||
});
|
||||
return resp;
|
||||
});
|
||||
if (resp instanceof Error) {
|
||||
console.log(resp);
|
||||
return;
|
||||
}
|
||||
for await (let { res: nostrMessage, url: relayUrl } of resp.chan) {
|
||||
if (nostrMessage.type === "EVENT" && nostrMessage.event.content) {
|
||||
this.database.addEvent(nostrMessage.event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user