added zapping functionality on event cards and sidebar
This commit is contained in:
parent
b0017440a0
commit
c6ee922391
@ -1,7 +1,10 @@
|
||||
import { Search } from "./components/Search";
|
||||
import AuthActions from "./components/AuthActions";
|
||||
import Logo from "@/assets/Logo";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
const Search = dynamic(() => import("./components/Search"), {
|
||||
ssr: false,
|
||||
});
|
||||
export default function Header() {
|
||||
return (
|
||||
<header className="flex h-[var(--header-height)] shrink-0 grow-0 ">
|
||||
|
@ -43,6 +43,19 @@ type NavigationElement = {
|
||||
current: boolean;
|
||||
active: boolean;
|
||||
} & (NavigationLink | NavigationButton);
|
||||
const flockstrEvent = {
|
||||
created_at: 1697736945,
|
||||
content:
|
||||
"Officially announcing Flockstr. Check it out at https://flockstr.com",
|
||||
tags: [
|
||||
["r", "https://flockstr.com"],
|
||||
["client", "flockstr"],
|
||||
],
|
||||
kind: 1,
|
||||
pubkey: "17717ad4d20e2a425cda0a2195624a0a4a73c4f6975f16b1593fc87fa46f2d58",
|
||||
id: "a867ff28711eeab4767fb6bacbb33dfe17b2b5bbbff98f8e57f90a85ea684b0a",
|
||||
sig: "37d8918e6da88d989467021a1f5809a3fbcab941ca1044d109ce261f29270d2d545aaa84297b7f224ae1ad7760263e50c317c24abc809034bcdb5c3260faf4b0",
|
||||
};
|
||||
|
||||
export default function Sidebar() {
|
||||
const modal = useModal();
|
||||
@ -76,7 +89,7 @@ export default function Sidebar() {
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
onClick: () => modal?.show(<ZapPickerModal />),
|
||||
onClick: () => modal?.show(<ZapPickerModal event={flockstrEvent} />),
|
||||
name: "zap",
|
||||
label: "Zap Flockstr",
|
||||
icon: HiOutlineLightningBolt,
|
||||
|
70
app/(app)/_layout/components/CommandDialog.tsx
Normal file
70
app/(app)/_layout/components/CommandDialog.tsx
Normal file
@ -0,0 +1,70 @@
|
||||
"use client";
|
||||
|
||||
import { useKeyboardShortcut } from "@/lib/hooks/useKeyboardShortcut";
|
||||
import {
|
||||
CalendarIcon,
|
||||
EnvelopeClosedIcon,
|
||||
FaceIcon,
|
||||
GearIcon,
|
||||
PersonIcon,
|
||||
RocketIcon,
|
||||
} from "@radix-ui/react-icons";
|
||||
import {
|
||||
CommandDialog,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
CommandSeparator,
|
||||
CommandShortcut,
|
||||
} from "@/components/ui/command";
|
||||
import { atom, useAtom } from "jotai";
|
||||
|
||||
export const commandDialogAtom = atom(false);
|
||||
|
||||
export default function CommandDialogComponent() {
|
||||
const [open, setOpen] = useAtom(commandDialogAtom);
|
||||
useKeyboardShortcut(["ctrl", "k"], () => setOpen((open) => !open));
|
||||
|
||||
return (
|
||||
<CommandDialog open={open} onOpenChange={setOpen}>
|
||||
<CommandInput placeholder="Type a command or search..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>No results found.</CommandEmpty>
|
||||
<CommandGroup heading="Suggestions">
|
||||
<CommandItem>
|
||||
<CalendarIcon className="mr-2 h-4 w-4" />
|
||||
<span>Calendar</span>
|
||||
</CommandItem>
|
||||
<CommandItem>
|
||||
<FaceIcon className="mr-2 h-4 w-4" />
|
||||
<span>Search Emoji</span>
|
||||
</CommandItem>
|
||||
<CommandItem>
|
||||
<RocketIcon className="mr-2 h-4 w-4" />
|
||||
<span>Launch</span>
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
<CommandSeparator />
|
||||
<CommandGroup heading="Settings">
|
||||
<CommandItem>
|
||||
<PersonIcon className="mr-2 h-4 w-4" />
|
||||
<span>Profile</span>
|
||||
<CommandShortcut>⌘P</CommandShortcut>
|
||||
</CommandItem>
|
||||
<CommandItem>
|
||||
<EnvelopeClosedIcon className="mr-2 h-4 w-4" />
|
||||
<span>Mail</span>
|
||||
<CommandShortcut>⌘B</CommandShortcut>
|
||||
</CommandItem>
|
||||
<CommandItem>
|
||||
<GearIcon className="mr-2 h-4 w-4" />
|
||||
<span>Settings</span>
|
||||
<CommandShortcut>⌘S</CommandShortcut>
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</CommandDialog>
|
||||
);
|
||||
}
|
@ -1,12 +1,17 @@
|
||||
import { Input } from "@/components/ui/input";
|
||||
"use client";
|
||||
|
||||
export function Search() {
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { commandDialogAtom } from "./CommandDialog";
|
||||
import { useAtom } from "jotai";
|
||||
export default function Search() {
|
||||
const [open, setOpen] = useAtom(commandDialogAtom);
|
||||
return (
|
||||
<div>
|
||||
<Input
|
||||
type="search"
|
||||
placeholder="Search..."
|
||||
className="sm:w-[200px] lg:w-[300px]"
|
||||
onFocus={() => setOpen(true)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -3,7 +3,11 @@ import Header from "./Header";
|
||||
import Keystone from "./Keystone";
|
||||
import MobileBanner from "./MobileBanner";
|
||||
import Sidebar from "./Sidebar";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
const CommandDialog = dynamic(() => import("./components/CommandDialog"), {
|
||||
ssr: false,
|
||||
});
|
||||
export default function AppLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<main className="app-layout w-screen sm:absolute sm:inset-0">
|
||||
@ -23,6 +27,7 @@ export default function AppLayout({ children }: { children: React.ReactNode }) {
|
||||
|
||||
{/* BottomNav */}
|
||||
<BottomNav />
|
||||
<CommandDialog />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
@ -15,8 +15,6 @@ export default function Kind1(props: Event) {
|
||||
|
||||
return (
|
||||
<Container
|
||||
pubkey={pubkey}
|
||||
createdAt={createdAt}
|
||||
actionOptions={[
|
||||
{
|
||||
label: "View profile",
|
||||
|
@ -19,9 +19,7 @@ export default function Kind30023(props: Event) {
|
||||
|
||||
return (
|
||||
<Container
|
||||
pubkey={pubkey}
|
||||
contentTags={contentTags}
|
||||
createdAt={createdAt}
|
||||
event={props}
|
||||
actionOptions={[
|
||||
{
|
||||
label: "View profile",
|
||||
|
@ -10,19 +10,16 @@ import { getTagValues, getTagsValues } from "@/lib/nostr/utils";
|
||||
import ReactPlayer from "react-player";
|
||||
|
||||
export default function Kind30311(props: Event) {
|
||||
const { pubkey, created_at: createdAt, tags } = props;
|
||||
const { pubkey, tags } = props;
|
||||
const streamingUrl =
|
||||
getTagValues("streaming", tags) ?? getTagValues("recording", tags);
|
||||
const title = getTagValues("title", tags);
|
||||
const summary = getTagValues("summary", tags);
|
||||
const contentTags = getTagsValues("t", tags).filter(Boolean);
|
||||
const npub = nip19.npubEncode(pubkey);
|
||||
|
||||
return (
|
||||
<Container
|
||||
pubkey={pubkey}
|
||||
createdAt={createdAt}
|
||||
contentTags={contentTags}
|
||||
event={props}
|
||||
actionOptions={[
|
||||
{
|
||||
label: "View profile",
|
||||
|
@ -65,7 +65,7 @@ export default function Kind3745(props: Event) {
|
||||
return <KindCard {...decryptedEvent} />;
|
||||
}
|
||||
return (
|
||||
<Container pubkey={pubkey}>
|
||||
<Container event={props}>
|
||||
<div className="relative ">
|
||||
<div className=" blur">
|
||||
<CardTitle className="mb-1.5 line-clamp-2 text-lg font-semibold">
|
||||
|
@ -1,11 +1,21 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
HiOutlineHandThumbUp,
|
||||
HiOutlineChatBubbleLeftEllipsis,
|
||||
} from "react-icons/hi2";
|
||||
import { HiOutlineLightningBolt } from "react-icons/hi";
|
||||
import ZapPicker from "@/components/Modals/ZapPicker";
|
||||
import { useModal } from "@/app/_providers/modal/provider";
|
||||
import { NostrEvent } from "@nostr-dev-kit/ndk";
|
||||
import { stopPropagation } from "@/lib/utils";
|
||||
|
||||
export default function Actions() {
|
||||
type ActionProps = {
|
||||
event: NostrEvent;
|
||||
};
|
||||
export default function Actions({ event }: ActionProps) {
|
||||
const modal = useModal();
|
||||
return (
|
||||
<div className="mt-3 flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
@ -17,7 +27,15 @@ export default function Actions() {
|
||||
<HiOutlineChatBubbleLeftEllipsis className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
<Button size={"sm"} className="gap-x-1.5">
|
||||
<Button
|
||||
onClick={(e) => {
|
||||
stopPropagation(e);
|
||||
console.log("captured");
|
||||
modal?.show(<ZapPicker event={event} />);
|
||||
}}
|
||||
size={"sm"}
|
||||
className="gap-x-1.5"
|
||||
>
|
||||
<HiOutlineLightningBolt className="h-4 w-4" />
|
||||
<span>zap</span>
|
||||
</Button>
|
||||
|
@ -7,10 +7,12 @@ import { formatDate } from "@/lib/utils/dates";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ReactNode } from "react";
|
||||
import ProfileHeader, { LoadingProfileHeader } from "./ProfileHeader";
|
||||
import { getTagValues, getTagsValues } from "@/lib/nostr/utils";
|
||||
import Actions from "./Actions";
|
||||
import Tags from "./Tags";
|
||||
import DropDownMenu from "@/components/DropDownMenu";
|
||||
|
||||
import { NostrEvent } from "@nostr-dev-kit/ndk";
|
||||
import { removeDuplicates } from "@/lib/utils";
|
||||
type OptionLink = {
|
||||
href: string;
|
||||
type: "link";
|
||||
@ -24,25 +26,54 @@ type Option = {
|
||||
} & (OptionLink | OptionButton);
|
||||
|
||||
type CreatorCardProps = {
|
||||
pubkey?: string;
|
||||
contentTags?: string[];
|
||||
createdAt?: number;
|
||||
children: ReactNode;
|
||||
actionOptions?: Option[];
|
||||
event?: NostrEvent;
|
||||
};
|
||||
|
||||
export default function Container({
|
||||
children,
|
||||
createdAt,
|
||||
contentTags,
|
||||
pubkey,
|
||||
actionOptions = [],
|
||||
event,
|
||||
}: CreatorCardProps) {
|
||||
if (!event) {
|
||||
return (
|
||||
<Card className="relative flex h-full w-full flex-col overflow-hidden @container">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 p-4 pb-4">
|
||||
<LoadingProfileHeader />
|
||||
<div className="-mr-1 flex items-center gap-x-1.5 text-xs text-muted-foreground">
|
||||
<DropDownMenu options={[]}>
|
||||
<Button
|
||||
size={"sm"}
|
||||
variant={"ghost"}
|
||||
className="center h-6 w-6 p-0"
|
||||
>
|
||||
<RiMoreFill className="h-4 w-4" />
|
||||
</Button>
|
||||
</DropDownMenu>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="flex grow flex-col px-4 pb-3">
|
||||
{children}
|
||||
<div className="mt-auto"></div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
const { pubkey, tags, created_at: createdAt } = event;
|
||||
const contentTags = removeDuplicates(getTagsValues("t", tags)).filter(
|
||||
Boolean,
|
||||
);
|
||||
|
||||
return (
|
||||
<Card className="relative flex h-full w-full flex-col overflow-hidden @container">
|
||||
<Card
|
||||
onClick={() => {
|
||||
console.log("CLICK IN CONTAINER");
|
||||
}}
|
||||
className="relative flex h-full w-full flex-col overflow-hidden @container"
|
||||
>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 p-4 pb-4">
|
||||
{pubkey ? <ProfileHeader pubkey={pubkey} /> : <LoadingProfileHeader />}
|
||||
|
||||
<div className="-mr-1 flex items-center gap-x-1.5 text-xs text-muted-foreground">
|
||||
{!!createdAt &&
|
||||
formatDate(new Date(createdAt * 1000), "MMM Do, h:mm a")}
|
||||
@ -68,7 +99,7 @@ export default function Container({
|
||||
<div className="h-1.5" />
|
||||
)}
|
||||
<div className="border-t">
|
||||
<Actions />
|
||||
<Actions event={event} />
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
@ -16,8 +16,7 @@ export default function KindDefault(props: Event) {
|
||||
|
||||
return (
|
||||
<Container
|
||||
pubkey={pubkey}
|
||||
createdAt={createdAt}
|
||||
event={props}
|
||||
actionOptions={[
|
||||
{
|
||||
label: "View profile",
|
||||
|
@ -3,23 +3,16 @@ import { useState, useRef, useEffect } from "react";
|
||||
import Template from "./Template";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useModal } from "@/app/_providers/modal/provider";
|
||||
import { nip19 } from "nostr-tools";
|
||||
// import { useKeys } from "@/app/_providers/keysProvider";
|
||||
import { toast } from "sonner";
|
||||
import { useNDK } from "@/app/_providers/ndk";
|
||||
import useCurrentUser from "@/lib/hooks/useCurrentUser";
|
||||
import { HiOutlineLightningBolt } from "react-icons/hi";
|
||||
import { RiSubtractFill, RiAddFill } from "react-icons/ri";
|
||||
import { formatCount } from "@/lib/utils";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { type NostrEvent } from "@nostr-dev-kit/ndk";
|
||||
import { sendZap } from "@/lib/actions/zap";
|
||||
|
||||
const intervals = [
|
||||
10, 25, 50, 75, 100, 150, 200, 250, 350, 500, 750, 1000, 1250, 1500, 2_000,
|
||||
@ -27,13 +20,18 @@ const intervals = [
|
||||
20_000, 25_000, 30_000, 40_000, 50_000, 75_000, 100_000, 150_000, 200_000,
|
||||
300_000, 500_000, 750_000, 1_000_000, 1_250_000, 1_500_000, 2_000_000,
|
||||
];
|
||||
export default function ZapPicker() {
|
||||
|
||||
type ZapPickerProps = {
|
||||
event: NostrEvent;
|
||||
};
|
||||
export default function ZapPicker({ event }: ZapPickerProps) {
|
||||
const { loginWithNip07 } = useNDK();
|
||||
const { loginWithPubkey, currentUser } = useCurrentUser();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [note, setNote] = useState("");
|
||||
const modal = useModal();
|
||||
const [sats, setSats] = useState(2000);
|
||||
const { ndk } = useNDK();
|
||||
|
||||
function onClick(type: "+" | "-") {
|
||||
setSats((prev) => {
|
||||
@ -48,6 +46,18 @@ export default function ZapPicker() {
|
||||
});
|
||||
}
|
||||
|
||||
async function handleSendZap() {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const result = await sendZap(ndk!, sats, event, note);
|
||||
toast.success("Zap Sent!");
|
||||
} catch (err) {
|
||||
console.log("error sending zap", err);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Template title="Send Zap!" className="md:max-w-[400px]">
|
||||
<div className="flex flex-col gap-y-5">
|
||||
@ -71,15 +81,7 @@ export default function ZapPicker() {
|
||||
Satoshis
|
||||
</div>
|
||||
</div>
|
||||
<div className="">
|
||||
<FormLabel>Note</FormLabel>
|
||||
<Textarea
|
||||
placeholder="Add a note..."
|
||||
onChange={(e) => setNote(e.target.value)}
|
||||
value={note}
|
||||
className="auto-sizing"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
@ -91,9 +93,22 @@ export default function ZapPicker() {
|
||||
<span className="sr-only">Increase</span>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="pt-3">
|
||||
<Label>Note</Label>
|
||||
<Textarea
|
||||
placeholder="Add a note..."
|
||||
onChange={(e) => setNote(e.target.value)}
|
||||
value={note}
|
||||
className="auto-sizing"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button className="w-full gap-x-1">
|
||||
<Button
|
||||
onClick={handleSendZap}
|
||||
loading={isLoading}
|
||||
className="w-full gap-x-1"
|
||||
>
|
||||
<span>Send Zap</span>
|
||||
<HiOutlineLightningBolt className="h-4 w-4" />
|
||||
</Button>
|
||||
|
@ -1,12 +1,12 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import { DialogProps } from "@radix-ui/react-dialog"
|
||||
import { MagnifyingGlassIcon } from "@radix-ui/react-icons"
|
||||
import { Command as CommandPrimitive } from "cmdk"
|
||||
import * as React from "react";
|
||||
import { DialogProps } from "@radix-ui/react-dialog";
|
||||
import { MagnifyingGlassIcon } from "@radix-ui/react-icons";
|
||||
import { Command as CommandPrimitive } from "cmdk";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Dialog, DialogContent } from "@/components/ui/dialog"
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
||||
|
||||
const Command = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive>,
|
||||
@ -16,12 +16,12 @@ const Command = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Command.displayName = CommandPrimitive.displayName
|
||||
));
|
||||
Command.displayName = CommandPrimitive.displayName;
|
||||
|
||||
interface CommandDialogProps extends DialogProps {}
|
||||
|
||||
@ -34,8 +34,8 @@ const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
|
||||
</Command>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const CommandInput = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive.Input>,
|
||||
@ -47,14 +47,14 @@ const CommandInput = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
));
|
||||
|
||||
CommandInput.displayName = CommandPrimitive.Input.displayName
|
||||
CommandInput.displayName = CommandPrimitive.Input.displayName;
|
||||
|
||||
const CommandList = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive.List>,
|
||||
@ -65,9 +65,9 @@ const CommandList = React.forwardRef<
|
||||
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
));
|
||||
|
||||
CommandList.displayName = CommandPrimitive.List.displayName
|
||||
CommandList.displayName = CommandPrimitive.List.displayName;
|
||||
|
||||
const CommandEmpty = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive.Empty>,
|
||||
@ -78,9 +78,9 @@ const CommandEmpty = React.forwardRef<
|
||||
className="py-6 text-center text-sm"
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
));
|
||||
|
||||
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
|
||||
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
|
||||
|
||||
const CommandGroup = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive.Group>,
|
||||
@ -90,13 +90,13 @@ const CommandGroup = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
));
|
||||
|
||||
CommandGroup.displayName = CommandPrimitive.Group.displayName
|
||||
CommandGroup.displayName = CommandPrimitive.Group.displayName;
|
||||
|
||||
const CommandSeparator = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive.Separator>,
|
||||
@ -107,8 +107,8 @@ const CommandSeparator = React.forwardRef<
|
||||
className={cn("-mx-1 h-px bg-border", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
|
||||
));
|
||||
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
|
||||
|
||||
const CommandItem = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive.Item>,
|
||||
@ -118,13 +118,13 @@ const CommandItem = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
));
|
||||
|
||||
CommandItem.displayName = CommandPrimitive.Item.displayName
|
||||
CommandItem.displayName = CommandPrimitive.Item.displayName;
|
||||
|
||||
const CommandShortcut = ({
|
||||
className,
|
||||
@ -134,13 +134,13 @@ const CommandShortcut = ({
|
||||
<span
|
||||
className={cn(
|
||||
"ml-auto text-xs tracking-widest text-muted-foreground",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
CommandShortcut.displayName = "CommandShortcut"
|
||||
);
|
||||
};
|
||||
CommandShortcut.displayName = "CommandShortcut";
|
||||
|
||||
export {
|
||||
Command,
|
||||
@ -152,4 +152,4 @@ export {
|
||||
CommandItem,
|
||||
CommandShortcut,
|
||||
CommandSeparator,
|
||||
}
|
||||
};
|
||||
|
@ -1,16 +1,16 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
||||
import { Cross2Icon } from "@radix-ui/react-icons"
|
||||
import * as React from "react";
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||
import { Cross2Icon } from "@radix-ui/react-icons";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Dialog = DialogPrimitive.Root
|
||||
const Dialog = DialogPrimitive.Root;
|
||||
|
||||
const DialogTrigger = DialogPrimitive.Trigger
|
||||
const DialogTrigger = DialogPrimitive.Trigger;
|
||||
|
||||
const DialogPortal = DialogPrimitive.Portal
|
||||
const DialogPortal = DialogPrimitive.Portal;
|
||||
|
||||
const DialogOverlay = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
||||
@ -19,13 +19,13 @@ const DialogOverlay = React.forwardRef<
|
||||
<DialogPrimitive.Overlay
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
className
|
||||
"z-overlay- fixed inset-0 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
|
||||
));
|
||||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
||||
|
||||
const DialogContent = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Content>,
|
||||
@ -36,20 +36,20 @@ const DialogContent = React.forwardRef<
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full",
|
||||
className
|
||||
"z-overlay fixed left-[50%] top-[50%] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity data-[state=open]:bg-accent data-[state=open]:text-muted-foreground hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none">
|
||||
<Cross2Icon className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
</DialogPrimitive.Content>
|
||||
</DialogPortal>
|
||||
))
|
||||
DialogContent.displayName = DialogPrimitive.Content.displayName
|
||||
));
|
||||
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
||||
|
||||
const DialogHeader = ({
|
||||
className,
|
||||
@ -58,12 +58,12 @@ const DialogHeader = ({
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col space-y-1.5 text-center sm:text-left",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
DialogHeader.displayName = "DialogHeader"
|
||||
);
|
||||
DialogHeader.displayName = "DialogHeader";
|
||||
|
||||
const DialogFooter = ({
|
||||
className,
|
||||
@ -72,12 +72,12 @@ const DialogFooter = ({
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
DialogFooter.displayName = "DialogFooter"
|
||||
);
|
||||
DialogFooter.displayName = "DialogFooter";
|
||||
|
||||
const DialogTitle = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Title>,
|
||||
@ -87,12 +87,12 @@ const DialogTitle = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"text-lg font-semibold leading-none tracking-tight",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DialogTitle.displayName = DialogPrimitive.Title.displayName
|
||||
));
|
||||
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
||||
|
||||
const DialogDescription = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Description>,
|
||||
@ -103,8 +103,8 @@ const DialogDescription = React.forwardRef<
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DialogDescription.displayName = DialogPrimitive.Description.displayName
|
||||
));
|
||||
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
||||
|
||||
export {
|
||||
Dialog,
|
||||
@ -116,4 +116,4 @@ export {
|
||||
DialogFooter,
|
||||
DialogTitle,
|
||||
DialogDescription,
|
||||
}
|
||||
};
|
||||
|
@ -28,7 +28,7 @@ export async function sendZap(
|
||||
) {
|
||||
log("func", "sendZap");
|
||||
const event = await new NDKEvent(ndk, _event);
|
||||
log("info", event.toString());
|
||||
log("info", JSON.stringify(event));
|
||||
const pr = await event.zap(amount * 1000, comment);
|
||||
if (!pr) {
|
||||
log("info", "No PR");
|
||||
|
@ -88,7 +88,7 @@ export function log(
|
||||
type: "info" | "error" | "warn" | "func",
|
||||
...args: unknown[]
|
||||
) {
|
||||
const isOn = true;
|
||||
const isOn = process.env.NODE_ENV === "development";
|
||||
if (!isOn) return;
|
||||
const consoleType = type === "func" ? "info" : type;
|
||||
const items = [...args].map((a) => `%c${a}`);
|
||||
@ -115,3 +115,8 @@ export function btcToSats(amount: number) {
|
||||
export function satsToBtc(amount: number) {
|
||||
return amount / 100_000_000;
|
||||
}
|
||||
export function stopPropagation(e: React.MouseEvent) {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
"dayjs": "^1.11.10",
|
||||
"focus-trap-react": "^10.2.3",
|
||||
"framer-motion": "^10.16.4",
|
||||
"jotai": "^2.4.3",
|
||||
"next": "13.5.4",
|
||||
"next-themes": "^0.2.1",
|
||||
"node-html-parser": "^6.1.10",
|
||||
|
Loading…
x
Reference in New Issue
Block a user