mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-06-05 18:21:28 +02:00
fix: improve zap/nutzap rendering in chat
- Add mb-1 margin bottom to zap messages for spacing - Show inline reply preview for zaps that target specific messages - Fix nutzap amount extraction to handle multiple proof tags - Extract replyTo from e-tag for nutzaps - Pass nutzap event to RichText for custom emoji rendering
This commit is contained in:
@@ -181,9 +181,15 @@ const MessageItem = memo(function MessageItem({
|
||||
// Zap messages have special styling with gradient border
|
||||
if (message.type === "zap") {
|
||||
const zapRequest = message.event ? getZapRequest(message.event) : null;
|
||||
// For NIP-57 zaps, reply target is in the zap request's e-tag
|
||||
// For NIP-61 nutzaps, reply target is already in message.replyTo
|
||||
const zapReplyTo =
|
||||
message.replyTo ||
|
||||
zapRequest?.tags.find((t) => t[0] === "e")?.[1] ||
|
||||
undefined;
|
||||
|
||||
return (
|
||||
<div className="pl-2">
|
||||
<div className="pl-2 mb-1">
|
||||
<div
|
||||
className="p-[1px]"
|
||||
style={{
|
||||
@@ -213,11 +219,19 @@ const MessageItem = memo(function MessageItem({
|
||||
<Timestamp timestamp={message.timestamp} />
|
||||
</span>
|
||||
</div>
|
||||
{zapReplyTo && (
|
||||
<ReplyPreview
|
||||
replyToId={zapReplyTo}
|
||||
adapter={adapter}
|
||||
conversation={conversation}
|
||||
onScrollToMessage={onScrollToMessage}
|
||||
/>
|
||||
)}
|
||||
{message.content && (
|
||||
<RichText
|
||||
content={message.content}
|
||||
event={zapRequest || undefined}
|
||||
className="mt-1 text-sm leading-tight break-words"
|
||||
event={zapRequest || message.event}
|
||||
className="text-sm leading-tight break-words"
|
||||
options={{ showMedia: false, showEventEmbeds: false }}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -676,22 +676,29 @@ export class Nip29Adapter extends ChatProtocolAdapter {
|
||||
const pTag = event.tags.find((t) => t[0] === "p");
|
||||
const recipient = pTag?.[1] || "";
|
||||
|
||||
// Amount is sum of proof amounts from the proof tag
|
||||
// proof tag format: ["proof", "<JSON proofs array>"]
|
||||
const proofTag = event.tags.find((t) => t[0] === "proof");
|
||||
// Reply target is the e-tag (the event being nutzapped)
|
||||
const eTag = event.tags.find((t) => t[0] === "e");
|
||||
const replyTo = eTag?.[1];
|
||||
|
||||
// Amount is sum of proof amounts from all proof tags
|
||||
// NIP-61 allows multiple proof tags, each containing a JSON-encoded Cashu proof
|
||||
let amount = 0;
|
||||
if (proofTag?.[1]) {
|
||||
try {
|
||||
const proofs = JSON.parse(proofTag[1]);
|
||||
if (Array.isArray(proofs)) {
|
||||
amount = proofs.reduce(
|
||||
(sum: number, proof: { amount?: number }) =>
|
||||
sum + (proof.amount || 0),
|
||||
0,
|
||||
);
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "proof" && tag[1]) {
|
||||
try {
|
||||
const proof = JSON.parse(tag[1]);
|
||||
// Proof can be a single object or an array of proofs
|
||||
if (Array.isArray(proof)) {
|
||||
amount += proof.reduce(
|
||||
(sum: number, p: { amount?: number }) => sum + (p.amount || 0),
|
||||
0,
|
||||
);
|
||||
} else if (typeof proof === "object" && proof.amount) {
|
||||
amount += proof.amount;
|
||||
}
|
||||
} catch {
|
||||
// Invalid proof JSON, skip this tag
|
||||
}
|
||||
} catch {
|
||||
// Invalid proof JSON, amount stays 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,6 +716,7 @@ export class Nip29Adapter extends ChatProtocolAdapter {
|
||||
content: comment,
|
||||
timestamp: event.created_at,
|
||||
type: "zap", // Render the same as zaps
|
||||
replyTo,
|
||||
protocol: "nip-29",
|
||||
metadata: {
|
||||
encrypted: false,
|
||||
|
||||
Reference in New Issue
Block a user