mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-28 18:53:47 +01:00
add sats per minute button
This commit is contained in:
parent
8ea8c88c52
commit
343a23c945
.changeset
src
5
.changeset/kind-walls-wave.md
Normal file
5
.changeset/kind-walls-wave.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": minor
|
||||
---
|
||||
|
||||
Add sats per minute button on stream view on desktop
|
@ -349,3 +349,15 @@ export const BookmarkedIcon = createIcon({
|
||||
d: "M4 2H20C20.5523 2 21 2.44772 21 3V22.2763C21 22.5525 20.7761 22.7764 20.5 22.7764C20.4298 22.7764 20.3604 22.7615 20.2963 22.7329L12 19.0313L3.70373 22.7329C3.45155 22.8455 3.15591 22.7322 3.04339 22.4801C3.01478 22.4159 3 22.3465 3 22.2763V3C3 2.44772 3.44772 2 4 2ZM12 13.5L14.9389 15.0451L14.3776 11.7725L16.7553 9.45492L13.4695 8.97746L12 6L10.5305 8.97746L7.24472 9.45492L9.62236 11.7725L9.06107 15.0451L12 13.5Z",
|
||||
defaultProps,
|
||||
});
|
||||
|
||||
export const PlayIcon = createIcon({
|
||||
displayName: "PlayIcon",
|
||||
d: "M16.3944 11.9998L10 7.73686V16.2628L16.3944 11.9998ZM19.376 12.4158L8.77735 19.4816C8.54759 19.6348 8.23715 19.5727 8.08397 19.3429C8.02922 19.2608 8 19.1643 8 19.0656V4.93408C8 4.65794 8.22386 4.43408 8.5 4.43408C8.59871 4.43408 8.69522 4.4633 8.77735 4.51806L19.376 11.5838C19.6057 11.737 19.6678 12.0474 19.5146 12.2772C19.478 12.3321 19.4309 12.3792 19.376 12.4158Z",
|
||||
defaultProps,
|
||||
});
|
||||
|
||||
export const StopIcon = createIcon({
|
||||
displayName: "StopIcon",
|
||||
d: "M7 7V17H17V7H7ZM6 5H18C18.5523 5 19 5.44772 19 6V18C19 18.5523 18.5523 19 18 19H6C5.44772 19 5 18.5523 5 18V6C5 5.44772 5.44772 5 6 5Z",
|
||||
defaultProps,
|
||||
});
|
||||
|
@ -14,13 +14,15 @@ import {
|
||||
Text,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import { DraftNostrEvent, NostrEvent } from "../types/nostr-event";
|
||||
import dayjs from "dayjs";
|
||||
import { Kind } from "nostr-tools";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
import { DraftNostrEvent, NostrEvent } from "../types/nostr-event";
|
||||
import { UserAvatar } from "./user-avatar";
|
||||
import { UserLink } from "./user-link";
|
||||
import { parsePaymentRequest, readablizeSats } from "../helpers/bolt11";
|
||||
import { LightningIcon } from "./icons";
|
||||
import { Kind } from "nostr-tools";
|
||||
import clientRelaysService from "../services/client-relays";
|
||||
import { getEventRelays } from "../services/event-relays";
|
||||
import { useSigningContext } from "../providers/signing-provider";
|
||||
@ -30,7 +32,6 @@ import useUserLNURLMetadata from "../hooks/use-user-lnurl-metadata";
|
||||
import { requestZapInvoice } from "../helpers/zaps";
|
||||
import { ParsedStream, getATag } from "../helpers/nostr/stream";
|
||||
import EmbeddedNote from "./note/embedded-note";
|
||||
import dayjs from "dayjs";
|
||||
import { unique } from "../helpers/array";
|
||||
import { useUserRelays } from "../hooks/use-user-relays";
|
||||
import { RelayMode } from "../classes/relay";
|
||||
|
108
src/views/streams/components/stream-sats-per-minute.tsx
Normal file
108
src/views/streams/components/stream-sats-per-minute.tsx
Normal file
@ -0,0 +1,108 @@
|
||||
import { useCallback, useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
Flex,
|
||||
FlexProps,
|
||||
NumberDecrementStepper,
|
||||
NumberIncrementStepper,
|
||||
NumberInput,
|
||||
NumberInputField,
|
||||
NumberInputStepper,
|
||||
Popover,
|
||||
PopoverArrow,
|
||||
PopoverBody,
|
||||
PopoverCloseButton,
|
||||
PopoverContent,
|
||||
PopoverHeader,
|
||||
PopoverTrigger,
|
||||
Spinner,
|
||||
Text,
|
||||
} from "@chakra-ui/react";
|
||||
import { useInterval } from "react-use";
|
||||
|
||||
import useUserLNURLMetadata from "../../../hooks/use-user-lnurl-metadata";
|
||||
import { parsePaymentRequest } from "../../../helpers/bolt11";
|
||||
import { PlayIcon, StopIcon } from "../../../components/icons";
|
||||
|
||||
export default function StreamSatsPerMinute({ pubkey, ...props }: { pubkey: string } & FlexProps) {
|
||||
const [enabled, setEnabled] = useState(false);
|
||||
const [paying, setPaying] = useState(false);
|
||||
const [amountStr, setAmountStr] = useState("21");
|
||||
|
||||
const { metadata } = useUserLNURLMetadata(pubkey);
|
||||
|
||||
const isAvailable = !!window.webln;
|
||||
const isEnabled = isAvailable && enabled && !!metadata?.callback;
|
||||
|
||||
const sendSats = useCallback(async () => {
|
||||
if (isEnabled && window.webln) {
|
||||
try {
|
||||
setPaying(true);
|
||||
if (!window.webln.enabled) await window.webln.enable();
|
||||
|
||||
const amountMsats = parseInt(amountStr) * 1000;
|
||||
if (!Number.isFinite(amountMsats)) throw new Error("invalid amount");
|
||||
|
||||
const callbackUrl = new URL(metadata.callback);
|
||||
callbackUrl.searchParams.append("amount", String(amountMsats));
|
||||
|
||||
const { pr: payRequest } = await fetch(callbackUrl).then((res) => res.json());
|
||||
|
||||
if (payRequest as string) {
|
||||
const parsed = parsePaymentRequest(payRequest);
|
||||
if (parsed.amount !== amountMsats) throw new Error("incorrect amount");
|
||||
} else throw new Error("Failed to get invoice");
|
||||
|
||||
await window.webln.sendPayment(payRequest);
|
||||
} catch (e) {
|
||||
setEnabled(false);
|
||||
}
|
||||
setPaying(false);
|
||||
}
|
||||
}, [setPaying, metadata?.callback, enabled, isEnabled]);
|
||||
|
||||
useInterval(sendSats, 1000 * 60);
|
||||
|
||||
return (
|
||||
<Flex gap="2">
|
||||
<Popover>
|
||||
<PopoverTrigger>
|
||||
<Button rightIcon={isEnabled ? <Spinner size="sm" /> : undefined}>Stream sats</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent>
|
||||
<PopoverArrow />
|
||||
<PopoverCloseButton />
|
||||
<PopoverHeader>Stream {amountStr} sats per minute</PopoverHeader>
|
||||
<PopoverBody>
|
||||
{isAvailable ? (
|
||||
<Flex gap="2">
|
||||
<NumberInput
|
||||
step={1}
|
||||
min={1}
|
||||
value={amountStr}
|
||||
onChange={(v) => setAmountStr(v)}
|
||||
isDisabled={!isAvailable}
|
||||
>
|
||||
<NumberInputField />
|
||||
<NumberInputStepper>
|
||||
<NumberIncrementStepper />
|
||||
<NumberDecrementStepper />
|
||||
</NumberInputStepper>
|
||||
</NumberInput>
|
||||
<Button
|
||||
leftIcon={isEnabled ? <StopIcon /> : <PlayIcon />}
|
||||
onClick={() => setEnabled((v) => !v)}
|
||||
isDisabled={!isAvailable}
|
||||
>
|
||||
{isEnabled ? "Stop" : "Start"}
|
||||
</Button>
|
||||
</Flex>
|
||||
) : (
|
||||
<Text colorScheme="orange">Missing WebLN</Text>
|
||||
)}
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</Flex>
|
||||
);
|
||||
}
|
@ -34,6 +34,7 @@ import RelaySelectionButton from "../../../components/relay-selection/relay-sele
|
||||
import RelaySelectionProvider from "../../../providers/relay-selection-provider";
|
||||
import StreamerCards from "../components/streamer-cards";
|
||||
import { useAppTitle } from "../../../hooks/use-app-title";
|
||||
import StreamSatsPerMinute from "../components/stream-sats-per-minute";
|
||||
|
||||
function StreamPage({ stream, displayMode }: { stream: ParsedStream; displayMode?: ChatDisplayMode }) {
|
||||
useAppTitle(stream.title);
|
||||
@ -122,6 +123,7 @@ function StreamPage({ stream, displayMode }: { stream: ParsedStream; displayMode
|
||||
<Text>{stream.title}</Text>
|
||||
</Box>
|
||||
<Spacer />
|
||||
{!!window.webln && <StreamSatsPerMinute pubkey={stream.host} />}
|
||||
<StreamDebugButton stream={stream} variant="ghost" />
|
||||
<RelaySelectionButton />
|
||||
<Button onClick={() => navigate(-1)}>Back</Button>
|
||||
|
Loading…
x
Reference in New Issue
Block a user