mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-06-06 02:31:13 +02:00
Add copy chat ID button to header (#103)
* feat: add copy chat ID button to chat header Add a button next to the chat title that copies the chat identifier to clipboard. The identifier can be used with the `chat` command to reopen the same conversation. - For NIP-29 groups: copies relay'group-id format - For NIP-53 live activities: copies naddr encoding The button shows a check icon for feedback when copied. * refactor: simplify copy chat ID button styling - Use CopyCheck icon instead of Check for consistency with CodeCopyButton - Remove tooltip to reduce UI noise - Keep hover state styling (muted to foreground) --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,10 @@ import {
|
||||
AlertTriangle,
|
||||
RefreshCw,
|
||||
Paperclip,
|
||||
Copy,
|
||||
CopyCheck,
|
||||
} from "lucide-react";
|
||||
import { nip19 } from "nostr-tools";
|
||||
import { getZapRequest } from "applesauce-common/helpers/zap";
|
||||
import { toast } from "sonner";
|
||||
import accountManager from "@/services/accounts";
|
||||
@@ -45,6 +48,7 @@ import {
|
||||
} from "./editor/MentionEditor";
|
||||
import { useProfileSearch } from "@/hooks/useProfileSearch";
|
||||
import { useEmojiSearch } from "@/hooks/useEmojiSearch";
|
||||
import { useCopy } from "@/hooks/useCopy";
|
||||
import { Label } from "./ui/label";
|
||||
import {
|
||||
Tooltip,
|
||||
@@ -129,6 +133,43 @@ function isLiveActivityMetadata(value: unknown): value is LiveActivityMetadata {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the chat command identifier for a conversation
|
||||
* Returns a string that can be passed to the `chat` command to open this conversation
|
||||
*
|
||||
* For NIP-29 groups: relay'group-id (without wss:// prefix)
|
||||
* For NIP-53 live activities: naddr1... encoding
|
||||
*/
|
||||
function getChatIdentifier(conversation: Conversation): string | null {
|
||||
if (conversation.protocol === "nip-29") {
|
||||
const groupId = conversation.metadata?.groupId;
|
||||
const relayUrl = conversation.metadata?.relayUrl;
|
||||
if (!groupId || !relayUrl) return null;
|
||||
|
||||
// Strip wss:// or ws:// prefix for cleaner identifier
|
||||
const cleanRelay = relayUrl.replace(/^wss?:\/\//, "");
|
||||
return `${cleanRelay}'${groupId}`;
|
||||
}
|
||||
|
||||
if (conversation.protocol === "nip-53") {
|
||||
const activityAddress = conversation.metadata?.activityAddress;
|
||||
if (!activityAddress) return null;
|
||||
|
||||
// Get relay hints from live activity metadata
|
||||
const liveActivity = conversation.metadata?.liveActivity;
|
||||
const relays = liveActivity?.relays || [];
|
||||
|
||||
return nip19.naddrEncode({
|
||||
kind: activityAddress.kind,
|
||||
pubkey: activityAddress.pubkey,
|
||||
identifier: activityAddress.identifier,
|
||||
relays: relays.slice(0, 3), // Limit relay hints to keep naddr short
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversation resolution result - either success with conversation or error
|
||||
*/
|
||||
@@ -360,6 +401,9 @@ export function ChatViewer({
|
||||
// Emoji search for custom emoji autocomplete
|
||||
const { searchEmojis } = useEmojiSearch();
|
||||
|
||||
// Copy chat identifier to clipboard
|
||||
const { copy: copyChatId, copied: chatIdCopied } = useCopy();
|
||||
|
||||
// Ref to MentionEditor for programmatic submission
|
||||
const editorRef = useRef<MentionEditorHandle>(null);
|
||||
|
||||
@@ -811,6 +855,23 @@ export function ChatViewer({
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
{/* Copy Chat ID button */}
|
||||
{getChatIdentifier(conversation) && (
|
||||
<button
|
||||
onClick={() => {
|
||||
const chatId = getChatIdentifier(conversation);
|
||||
if (chatId) copyChatId(chatId);
|
||||
}}
|
||||
className="text-muted-foreground hover:text-foreground transition-colors flex-shrink-0"
|
||||
aria-label="Copy chat ID"
|
||||
>
|
||||
{chatIdCopied ? (
|
||||
<CopyCheck className="size-3.5" />
|
||||
) : (
|
||||
<Copy className="size-3.5" />
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-xs text-muted-foreground p-1">
|
||||
<MembersDropdown participants={derivedParticipants} />
|
||||
|
||||
Reference in New Issue
Block a user