Add DM zap composer and zap request support

This commit is contained in:
thePR0M3TH3AN committed 2026-01-19 11:29:55 -05:00
1 parent 26486ca57a
commit d082df8e41
11 files changed
+1005 -3

No files matched your search

+70 -2
View File
@@ -2,6 +2,7 @@ import { Composer } from "./Composer.js";
import { ConversationList } from "./ConversationList.js";
import { MessageThread } from "./MessageThread.js";
import { NotificationCenter } from "./NotificationCenter.js";
import { aggregateZapTotals } from "./zapHelpers.js";
function createElement(doc, tag, className, text) {
const element = doc.createElement(tag);
@@ -23,6 +24,9 @@ const DEFAULT_CONVERSATIONS = [
unreadCount: 2,
status: "Online",
avatarSrc: "",
pubkey: "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2",
lightningAddress: "[email protected]",
relayHints: ["wss://relay.damus.io", "wss://nostr.wine"],
},
{
id: "conv-2",
@@ -32,6 +36,9 @@ const DEFAULT_CONVERSATIONS = [
unreadCount: 0,
status: "Away",
avatarSrc: "",
pubkey: "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52",
lightningAddress: "[email protected]",
relayHints: ["wss://relay.primal.net"],
},
];
@@ -66,6 +73,42 @@ const DEFAULT_MESSAGES = [
},
];
const DEFAULT_ZAP_RECEIPTS = [
{
id: "zap-1",
kind: 9735,
conversationId: "conv-1",
profileId: "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2",
senderName: "You",
amountSats: 120,
note: "For the quick relay fix!",
timestamp: "09:20",
status: "confirmed",
},
{
id: "zap-2",
kind: 9735,
conversationId: "conv-1",
profileId: "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2",
senderName: "Nia Nova",
amountSats: 42,
note: "Thanks for testing the DM flow.",
timestamp: "09:22",
status: "confirmed",
},
{
id: "zap-3",
kind: 9735,
conversationId: "conv-2",
profileId: "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52",
senderName: "You",
amountSats: 250,
note: "Ops support fund.",
timestamp: "Yesterday",
status: "pending",
},
];
export class AppShell {
constructor({
document: doc,
@@ -73,14 +116,17 @@ export class AppShell {
activeConversationId = DEFAULT_CONVERSATIONS[0]?.id || "",
conversationState = "idle",
messages = DEFAULT_MESSAGES,
zapReceipts = DEFAULT_ZAP_RECEIPTS,
threadState = "idle",
threadErrorType = "",
composerState = "idle",
privacyMode = "nip04",
notifications = [],
signingAdapter = null,
zapConfig = null,
onSelectConversation,
onSendMessage,
onSendZap,
} = {}) {
if (!doc) {
throw new Error("AppShell requires a document reference.");
@@ -89,6 +135,21 @@ export class AppShell {
this.document = doc;
this.root = createElement(doc, "div", "dm-app-shell");
const { totalsByConversation, totalsByProfile } = aggregateZapTotals(zapReceipts);
const enrichedConversations = conversations.map((conversation) => ({
...conversation,
zapTotalSats: totalsByConversation.get(conversation.id) || 0,
profileZapTotalSats: totalsByProfile.get(conversation.pubkey) || 0,
}));
const activeConversation =
enrichedConversations.find((conversation) => conversation.id === activeConversationId) ||
enrichedConversations[0] ||
{};
const activeZapReceipts = zapReceipts.filter(
(receipt) => receipt.conversationId === activeConversation.id,
);
const sidebar = createElement(doc, "aside", "dm-app-shell__sidebar");
const sidebarTitle = createElement(
doc,
@@ -100,7 +161,7 @@ export class AppShell {
sidebar.appendChild(
ConversationList({
document: doc,
conversations,
conversations: enrichedConversations,
activeId: activeConversationId,
state: conversationState,
onSelect: onSelectConversation,
@@ -117,11 +178,15 @@ export class AppShell {
main.appendChild(
MessageThread({
document: doc,
contact: conversations.find((conversation) => conversation.id === activeConversationId) || {},
contact: activeConversation,
messages,
state: threadState,
errorType: threadErrorType,
privacyMode,
zapReceipts: activeZapReceipts,
conversationZapTotalSats:
totalsByConversation.get(activeConversation.id) || 0,
profileZapTotalSats: totalsByProfile.get(activeConversation.pubkey) || 0,
}),
);
main.appendChild(
@@ -130,7 +195,10 @@ export class AppShell {
state: composerState,
privacyMode,
signingAdapter,
zapRecipient: activeConversation,
zapConfig,
onSend: onSendMessage,
onSendZap,
}),
);