toast
This commit is contained in:
parent
3a8125f0bb
commit
154098b5dc
@ -25,6 +25,7 @@ import Avatar from "Element/Avatar";
|
|||||||
import { useUserProfile } from "Hooks/useUserProfile";
|
import { useUserProfile } from "Hooks/useUserProfile";
|
||||||
import { profileLink } from "Util";
|
import { profileLink } from "Util";
|
||||||
import { getCurrentSubscription } from "Subscription";
|
import { getCurrentSubscription } from "Subscription";
|
||||||
|
import Toaster from "Toaster";
|
||||||
|
|
||||||
export default function Layout() {
|
export default function Layout() {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
@ -170,6 +171,7 @@ export default function Layout() {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{window.localStorage.getItem("debug") && <SubDebug />}
|
{window.localStorage.getItem("debug") && <SubDebug />}
|
||||||
|
<Toaster />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ export default function ZapPoolPage() {
|
|||||||
|
|
||||||
const sumPending = zapPool.reduce((acc, v) => acc + v.sum, 0);
|
const sumPending = zapPool.reduce((acc, v) => acc + v.sum, 0);
|
||||||
return (
|
return (
|
||||||
<div className="zap-pool">
|
<div className="zap-pool main-content">
|
||||||
<h1>
|
<h1>
|
||||||
<FormattedMessage defaultMessage="Zap Pool" />
|
<FormattedMessage defaultMessage="Zap Pool" />
|
||||||
</h1>
|
</h1>
|
||||||
|
12
packages/app/src/Toaster.css
Normal file
12
packages/app/src/Toaster.css
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.toaster {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toaster > .card {
|
||||||
|
border: 1px solid var(--gray);
|
||||||
|
}
|
53
packages/app/src/Toaster.tsx
Normal file
53
packages/app/src/Toaster.tsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import ExternalStore from "ExternalStore";
|
||||||
|
import Icon from "Icons/Icon";
|
||||||
|
import { ReactNode, useSyncExternalStore } from "react";
|
||||||
|
import { unixNow } from "Util";
|
||||||
|
|
||||||
|
import "./Toaster.css";
|
||||||
|
|
||||||
|
interface ToastNotification {
|
||||||
|
element: ReactNode;
|
||||||
|
expire?: number;
|
||||||
|
icon?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ToasterSlots extends ExternalStore<Array<ToastNotification>> {
|
||||||
|
#stack: Array<ToastNotification> = [];
|
||||||
|
#cleanup = setInterval(() => this.#eatToast(), 1000);
|
||||||
|
|
||||||
|
push(n: ToastNotification) {
|
||||||
|
n.expire ??= unixNow() + 3;
|
||||||
|
this.#stack.push(n);
|
||||||
|
this.notifyChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
takeSnapshot(): ToastNotification[] {
|
||||||
|
return [...this.#stack];
|
||||||
|
}
|
||||||
|
|
||||||
|
#eatToast() {
|
||||||
|
const now = unixNow();
|
||||||
|
this.#stack = this.#stack.filter(a => (a.expire ?? 0) > now);
|
||||||
|
this.notifyChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Toastore = new ToasterSlots();
|
||||||
|
|
||||||
|
export default function Toaster() {
|
||||||
|
const toast = useSyncExternalStore(
|
||||||
|
c => Toastore.hook(c),
|
||||||
|
() => Toastore.snapshot()
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="toaster">
|
||||||
|
{toast.map(a => (
|
||||||
|
<div className="card flex">
|
||||||
|
<Icon name={a.icon ?? "bell"} className="mr5" />
|
||||||
|
{a.element}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -1,6 +1,9 @@
|
|||||||
import { UserCache } from "Cache";
|
import { UserCache } from "Cache";
|
||||||
|
import { getDisplayName } from "Element/ProfileImage";
|
||||||
import ExternalStore from "ExternalStore";
|
import ExternalStore from "ExternalStore";
|
||||||
import { LNURL } from "LNURL";
|
import { LNURL } from "LNURL";
|
||||||
|
import { Toastore } from "Toaster";
|
||||||
|
import { unixNow } from "Util";
|
||||||
import { LNWallet, WalletInvoiceState } from "Wallet";
|
import { LNWallet, WalletInvoiceState } from "Wallet";
|
||||||
|
|
||||||
export enum ZapPoolRecipientType {
|
export enum ZapPoolRecipientType {
|
||||||
@ -46,6 +49,14 @@ class ZapPool extends ExternalStore<Array<ZapPoolRecipient>> {
|
|||||||
const result = await wallet.payInvoice(invoice.pr);
|
const result = await wallet.payInvoice(invoice.pr);
|
||||||
if (result.state === WalletInvoiceState.Paid) {
|
if (result.state === WalletInvoiceState.Paid) {
|
||||||
x.sum -= amtSend;
|
x.sum -= amtSend;
|
||||||
|
Toastore.push({
|
||||||
|
element: `Sent ${amtSend.toLocaleString()} sats to ${getDisplayName(
|
||||||
|
profile,
|
||||||
|
x.pubkey
|
||||||
|
)} from your zap pool`,
|
||||||
|
expire: unixNow() + 10,
|
||||||
|
icon: "zap",
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Payment failed");
|
throw new Error("Payment failed");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user