mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-12 16:37:06 +02:00
feat: add copy button for NIP markdown
- Add copy button to WindowToolbar for regular NIPs (appId: "nip") - Button appears in window toolbar next to edit button - Uses Copy/CopyCheck icons from lucide-react - Fetches NIP content via useNip hook - Shows toast notification on successful copy - Add copy button to CommunityNIPDetailRenderer for community NIPs (kind 30817) - Button appears in header next to title - Copies event.content (markdown) to clipboard - Uses same Copy/CopyCheck icon pattern - Shows toast notification on successful copy Both implementations use the existing useCopy hook for state management and maintain consistent styling with other toolbar buttons.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { X, Pencil, MoreVertical, WandSparkles } from "lucide-react";
|
||||
import { X, Pencil, MoreVertical, WandSparkles, Copy, CopyCheck } from "lucide-react";
|
||||
import { useSetAtom } from "jotai";
|
||||
import { useState } from "react";
|
||||
import { WindowInstance } from "@/types/app";
|
||||
@@ -13,6 +13,8 @@ import {
|
||||
import { SpellDialog } from "@/components/nostr/SpellDialog";
|
||||
import { reconstructCommand as reconstructReqCommand } from "@/lib/spell-conversion";
|
||||
import { toast } from "sonner";
|
||||
import { useCopy } from "@/hooks/useCopy";
|
||||
import { useNip } from "@/hooks/useNip";
|
||||
|
||||
interface WindowToolbarProps {
|
||||
window?: WindowInstance;
|
||||
@@ -58,6 +60,22 @@ export function WindowToolbar({
|
||||
setShowSpellDialog(true);
|
||||
};
|
||||
|
||||
// Copy functionality for NIPs
|
||||
const { copy, copied } = useCopy();
|
||||
const isNipWindow = window?.appId === "nip";
|
||||
|
||||
// Fetch NIP content for regular NIPs
|
||||
const { content: nipContent } = useNip(
|
||||
isNipWindow && window?.props?.number ? window.props.number : ""
|
||||
);
|
||||
|
||||
const handleCopyNip = () => {
|
||||
if (!window || !nipContent) return;
|
||||
|
||||
copy(nipContent);
|
||||
toast.success("NIP markdown copied to clipboard");
|
||||
};
|
||||
|
||||
// Check if this is a REQ window for spell creation
|
||||
const isReqWindow = window?.appId === "req";
|
||||
|
||||
@@ -88,6 +106,23 @@ export function WindowToolbar({
|
||||
<Pencil className="size-4" />
|
||||
</button>
|
||||
|
||||
{/* Copy button for NIPs */}
|
||||
{isNipWindow && (
|
||||
<button
|
||||
className="p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted/50 transition-colors"
|
||||
onClick={handleCopyNip}
|
||||
title="Copy NIP markdown"
|
||||
aria-label="Copy NIP markdown"
|
||||
disabled={!nipContent}
|
||||
>
|
||||
{copied ? (
|
||||
<CopyCheck className="size-4" />
|
||||
) : (
|
||||
<Copy className="size-4" />
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* More actions menu - only for REQ windows for now */}
|
||||
{isReqWindow && (
|
||||
<DropdownMenu>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { useMemo } from "react";
|
||||
import { Copy, CopyCheck } from "lucide-react";
|
||||
import { getTagValue } from "applesauce-core/helpers";
|
||||
import { UserName } from "../UserName";
|
||||
import { MarkdownContent } from "../MarkdownContent";
|
||||
import { useCopy } from "@/hooks/useCopy";
|
||||
import { toast } from "sonner";
|
||||
import type { NostrEvent } from "@/types/nostr";
|
||||
|
||||
/**
|
||||
@@ -29,12 +32,33 @@ export function CommunityNIPDetailRenderer({ event }: { event: NostrEvent }) {
|
||||
},
|
||||
);
|
||||
|
||||
// Copy functionality
|
||||
const { copy, copied } = useCopy();
|
||||
const handleCopy = () => {
|
||||
copy(event.content);
|
||||
toast.success("Community NIP markdown copied to clipboard");
|
||||
};
|
||||
|
||||
return (
|
||||
<div dir="auto" className="flex flex-col gap-6 p-6 max-w-3xl mx-auto">
|
||||
{/* NIP Header */}
|
||||
<header className="flex flex-col gap-4 border-b border-border pb-6">
|
||||
{/* Title */}
|
||||
<h1 className="text-3xl font-bold">{title}</h1>
|
||||
{/* Title with Copy Button */}
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<h1 className="text-3xl font-bold">{title}</h1>
|
||||
<button
|
||||
onClick={handleCopy}
|
||||
className="p-2 rounded text-muted-foreground hover:text-foreground hover:bg-muted/50 transition-colors shrink-0"
|
||||
title="Copy NIP markdown"
|
||||
aria-label="Copy NIP markdown"
|
||||
>
|
||||
{copied ? (
|
||||
<CopyCheck className="size-5" />
|
||||
) : (
|
||||
<Copy className="size-5" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Metadata */}
|
||||
<div className="flex items-center gap-4 text-sm text-muted-foreground">
|
||||
|
||||
Reference in New Issue
Block a user