feat: auto zap

This commit is contained in:
Kieran 2023-03-10 23:52:39 +00:00
parent ef48f553b0
commit 335905449f
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
5 changed files with 96 additions and 14 deletions

View File

@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { useIntl, FormattedMessage } from "react-intl";
import { Menu, MenuItem } from "@szhsin/react-menu";
@ -26,6 +26,39 @@ import { useWallet } from "Wallet";
import messages from "./messages";
// a dumb cache to remember which notes we zapped
class DumbZapCache {
#set: Set<u256> = new Set();
constructor() {
this.#load();
}
add(id: u256) {
this.#set.add(this.#truncId(id));
this.#save();
}
has(id: u256) {
return this.#set.has(this.#truncId(id));
}
#truncId(id: u256) {
return id.slice(0, 12);
}
#save() {
window.localStorage.setItem("zap-cache", JSON.stringify([...this.#set]));
}
#load() {
const data = window.localStorage.getItem("zap-cache");
if (data) {
this.#set = new Set<u256>(JSON.parse(data) as Array<u256>);
}
}
}
const ZapCache = new DumbZapCache();
export interface Translation {
text: string;
fromLanguage: string;
@ -65,7 +98,7 @@ export default function NoteFooter(props: NoteFooterProps) {
type: "language",
});
const zapTotal = zaps.reduce((acc, z) => acc + z.amount, 0);
const didZap = zaps.some(a => a.sender === login);
const didZap = ZapCache.has(ev.Id) || zaps.some(a => a.sender === login);
const longPress = useLongPress(
e => {
e.stopPropagation();
@ -114,16 +147,6 @@ export default function NoteFooter(props: NoteFooterProps) {
if (wallet?.isReady() && lnurl) {
setZapping(true);
try {
if (prefs.fastZapDonate > 0) {
// spin off donate
const donateAmount = Math.floor(prefs.defaultZapAmount * prefs.fastZapDonate);
if (donateAmount > 0) {
console.debug(`Donating ${donateAmount} sats to ${DonateLNURL}`);
fastZapInner(DonateLNURL, donateAmount, bech32ToHex(SnortPubKey))
.then(() => console.debug("Donation sent! Thank You!"))
.catch(() => console.debug("Failed to donate"));
}
}
await fastZapInner(lnurl, prefs.defaultZapAmount, ev.PubKey, ev.Id);
} catch (e) {
console.warn("Fast zap failed", e);
@ -145,9 +168,37 @@ export default function NoteFooter(props: NoteFooterProps) {
const zap = handler.canZap ? await publisher.zap(amount * 1000, key, id) : undefined;
const invoice = await handler.getInvoice(amount, undefined, zap);
await wallet.payInvoice(unwrap(invoice.pr));
if (prefs.fastZapDonate > 0) {
// spin off donate
const donateAmount = Math.floor(prefs.defaultZapAmount * prefs.fastZapDonate);
if (donateAmount > 0) {
console.debug(`Donating ${donateAmount} sats to ${DonateLNURL}`);
fastZapInner(DonateLNURL, donateAmount, bech32ToHex(SnortPubKey))
.then(() => console.debug("Donation sent! Thank You!"))
.catch(() => console.debug("Failed to donate"));
}
}
}
}
useEffect(() => {
if (prefs.autoZap) {
const lnurl = author?.lud16 || author?.lud06;
if (wallet?.isReady() && lnurl && !ZapCache.has(ev.Id)) {
queueMicrotask(async () => {
setZapping(true);
try {
await fastZapInner(lnurl, prefs.defaultZapAmount, ev.PubKey, ev.Id);
ZapCache.add(ev.Id);
} finally {
setZapping(false);
}
});
}
}
}, [prefs.autoZap]);
function tipButton() {
const service = author?.lud16 || author?.lud06;
if (service) {

View File

@ -191,6 +191,23 @@ const PreferencesPage = () => {
/>
</div>
</div>
<div className="card flex">
<div className="flex f-col f-grow">
<div>
<FormattedMessage defaultMessage="Auto Zap" />
</div>
<small>
<FormattedMessage defaultMessage="Automatically zap every note when loaded" />
</small>
</div>
<div>
<input
type="checkbox"
checked={perf.autoZap}
onChange={e => dispatch(setPreferences({ ...perf, autoZap: e.target.checked }))}
/>
</div>
</div>
<div className="card flex f-col">
<div className="flex w-max">
<div className="flex f-col f-grow">

View File

@ -85,6 +85,11 @@ export interface UserPreferences {
* For each fast zap an additional X% will be sent to Snort donate address
*/
fastZapDonate: number;
/**
* Auto-zap every post
*/
autoZap: boolean;
}
export interface LoginStore {
@ -243,8 +248,9 @@ export const InitState = {
fileUploader: "void.cat",
imgProxyConfig: DefaultImgProxy,
defaultRootTab: "posts",
defaultZapAmount: 500,
defaultZapAmount: 50,
fastZapDonate: 0.0,
autoZap: false,
},
} as LoginStore;

View File

@ -218,6 +218,9 @@
"Cu/K85": {
"defaultMessage": "Translated from {lang}"
},
"D+KzKd": {
"defaultMessage": "Automatically zap every note when loaded"
},
"D3idYv": {
"defaultMessage": "Settings"
},
@ -227,6 +230,9 @@
"DZzCem": {
"defaultMessage": "Show latest {n} notes"
},
"Dh3hbq": {
"defaultMessage": "Auto Zap"
},
"Dt/Zd5": {
"defaultMessage": "Media in posts will automatically be shown for selected people, otherwise only the link will show"
},

View File

@ -70,9 +70,11 @@
"CHTbO3": "Failed to load invoice",
"CmZ9ls": "{n} Muted",
"Cu/K85": "Translated from {lang}",
"D+KzKd": "Automatically zap every note when loaded",
"D3idYv": "Settings",
"DKnriN": "Send sats",
"DZzCem": "Show latest {n} notes",
"Dh3hbq": "Auto Zap",
"Dt/Zd5": "Media in posts will automatically be shown for selected people, otherwise only the link will show",
"E8a4yq": "Follow some popular accounts",
"EPYwm7": "Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.",
@ -299,4 +301,4 @@
"zjJZBd": "You're ready!",
"zonsdq": "Failed to load LNURL service",
"zvCDao": "Automatically show latest notes"
}
}