mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
- Add docs/capacitor-native-app-plan.md to hex-lint ignore list (code examples naturally reference hex colors in Capacitor config) - Replace direct console.error/console.log calls with logger utility in historyView.js, profileCache.js, EventDetailsModal.js, ZapInterface.js, and notificationController.js - Update CI workflow from Node 20 to Node 22 to match package.json engines https://claude.ai/code/session_01LzErpH9FNw4hAPsjoYb1v9
120 lines
4.2 KiB
JavaScript
120 lines
4.2 KiB
JavaScript
import { ZapReceiptList } from "./ZapReceiptList.js";
|
|
import { createAndPublishZapRequest, resolveZapRecipient } from "../../payments/zapRequests.js";
|
|
import { userLogger } from "../../utils/logger.js";
|
|
|
|
function createElement(doc, tag, className, text) {
|
|
const element = doc.createElement(tag);
|
|
if (className) {
|
|
element.className = className;
|
|
}
|
|
if (typeof text === "string") {
|
|
element.textContent = text;
|
|
}
|
|
return element;
|
|
}
|
|
|
|
export function createZapInterface(doc, { contact, zapReceipts, onSendZap, zapConfig }) {
|
|
const container = createElement(doc, "div", "dm-zap-interface card p-4 absolute bottom-16 right-4 z-20 w-80 shadow-xl border border-border bg-surface");
|
|
|
|
const closeBtn = createElement(doc, "button", "absolute top-2 right-2 btn-ghost btn-xs", "✕");
|
|
closeBtn.addEventListener("click", () => container.remove());
|
|
container.appendChild(closeBtn);
|
|
|
|
const title = createElement(doc, "h4", "text-sm font-bold mb-2", "Send Zap");
|
|
container.appendChild(title);
|
|
|
|
// Zap Form
|
|
const form = createElement(doc, "form", "space-y-2 mb-4");
|
|
const amountInput = createElement(doc, "input", "input input-sm w-full");
|
|
amountInput.type = "number";
|
|
amountInput.placeholder = "Amount (sats)";
|
|
amountInput.min = "1";
|
|
|
|
const noteInput = createElement(doc, "input", "input input-sm w-full");
|
|
noteInput.type = "text";
|
|
noteInput.placeholder = "Comment (optional)";
|
|
|
|
const sendBtn = createElement(doc, "button", "btn btn-sm btn-primary w-full", "Zap ⚡");
|
|
const statusDiv = createElement(doc, "div", "text-xs text-center mt-1");
|
|
|
|
sendBtn.addEventListener("click", async (e) => {
|
|
e.preventDefault();
|
|
const amount = parseInt(amountInput.value);
|
|
const comment = noteInput.value;
|
|
if (!amount || amount <= 0) {
|
|
statusDiv.textContent = "Invalid amount";
|
|
statusDiv.className = "text-error text-xs text-center mt-1";
|
|
return;
|
|
}
|
|
|
|
statusDiv.textContent = "Sending...";
|
|
statusDiv.className = "text-muted text-xs text-center mt-1";
|
|
sendBtn.disabled = true;
|
|
|
|
try {
|
|
if (typeof onSendZap === "function") {
|
|
// Use provided callback if available (e.g. from controller)
|
|
if (!contact.lightningAddress) {
|
|
throw new Error("No lightning address for this contact");
|
|
}
|
|
|
|
const resolver = zapConfig?.resolveRecipient || resolveZapRecipient;
|
|
const resolved = await resolver(contact.lightningAddress, { fetcher: zapConfig?.fetcher });
|
|
if (!resolved) throw new Error("Could not resolve lightning address");
|
|
|
|
const payload = {
|
|
amountSats: amount,
|
|
comment,
|
|
recipient: contact,
|
|
resolved
|
|
};
|
|
await onSendZap(payload);
|
|
statusDiv.textContent = "Zap sent!";
|
|
statusDiv.className = "text-success text-xs text-center mt-1";
|
|
amountInput.value = "";
|
|
noteInput.value = "";
|
|
} else if (zapConfig?.signer) {
|
|
await createAndPublishZapRequest({
|
|
address: contact.lightningAddress,
|
|
recipientPubkey: contact.pubkey,
|
|
relays: contact.relayHints || zapConfig?.relays,
|
|
amountSats: amount,
|
|
comment,
|
|
signer: zapConfig.signer,
|
|
pool: zapConfig.pool,
|
|
fetcher: zapConfig.fetcher,
|
|
});
|
|
statusDiv.textContent = "Zap sent!";
|
|
statusDiv.className = "text-success text-xs text-center mt-1";
|
|
amountInput.value = "";
|
|
noteInput.value = "";
|
|
} else {
|
|
throw new Error("No signer available");
|
|
}
|
|
} catch (err) {
|
|
userLogger.error("[ZapInterface] Failed to send zap:", err);
|
|
statusDiv.textContent = "Failed to send zap";
|
|
statusDiv.className = "text-error text-xs text-center mt-1";
|
|
} finally {
|
|
sendBtn.disabled = false;
|
|
}
|
|
});
|
|
|
|
form.appendChild(amountInput);
|
|
form.appendChild(noteInput);
|
|
form.appendChild(sendBtn);
|
|
form.appendChild(statusDiv);
|
|
container.appendChild(form);
|
|
|
|
// Receipts List
|
|
container.appendChild(
|
|
ZapReceiptList({
|
|
document: doc,
|
|
receipts: zapReceipts,
|
|
emptyLabel: "No recent zaps.",
|
|
}),
|
|
);
|
|
|
|
return container;
|
|
}
|