diff --git a/src/components/ChatViewer.tsx b/src/components/ChatViewer.tsx index babb434..a2ab769 100644 --- a/src/components/ChatViewer.tsx +++ b/src/components/ChatViewer.tsx @@ -18,6 +18,7 @@ import { Nip29Adapter } from "@/lib/chat/adapters/nip-29-adapter"; import { Nip53Adapter } from "@/lib/chat/adapters/nip-53-adapter"; import type { ChatProtocolAdapter } from "@/lib/chat/adapters/base-adapter"; import type { Message } from "@/types/chat"; +import type { ChatAction } from "@/types/chat-actions"; import { parseSlashCommand } from "@/lib/chat/slash-command-parser"; import { UserName } from "./nostr/UserName"; import { RichText } from "./nostr/RichText"; @@ -497,6 +498,36 @@ export function ChatViewer({ } }; + // Handle command execution from autocomplete + const handleCommandExecute = useCallback( + async (action: ChatAction) => { + if (!conversation || !hasActiveAccount || isSending) return; + + setIsSending(true); + try { + const result = await adapter.executeAction(action.name, { + activePubkey: activeAccount.pubkey, + activeSigner: activeAccount.signer, + conversation, + }); + + if (result.success) { + toast.success(result.message || "Action completed"); + } else { + toast.error(result.message || "Action failed"); + } + } catch (error) { + console.error("[Chat] Failed to execute action:", error); + const errorMessage = + error instanceof Error ? error.message : "Action failed"; + toast.error(errorMessage); + } finally { + setIsSending(false); + } + }, + [conversation, hasActiveAccount, isSending, adapter, activeAccount], + ); + // Handle reply button click const handleReply = useCallback((messageId: string) => { setReplyTo(messageId); @@ -813,6 +844,7 @@ export function ChatViewer({ searchProfiles={searchProfiles} searchEmojis={searchEmojis} searchCommands={searchCommands} + onCommandExecute={handleCommandExecute} onSubmit={(content, emojiTags) => { if (content.trim()) { handleSend(content, replyTo, emojiTags); diff --git a/src/components/editor/MentionEditor.tsx b/src/components/editor/MentionEditor.tsx index a4b31cf..dfb5cee 100644 --- a/src/components/editor/MentionEditor.tsx +++ b/src/components/editor/MentionEditor.tsx @@ -56,6 +56,7 @@ export interface MentionEditorProps { searchProfiles: (query: string) => Promise; searchEmojis?: (query: string) => Promise; searchCommands?: (query: string) => Promise; + onCommandExecute?: (action: ChatAction) => Promise; autoFocus?: boolean; className?: string; } @@ -159,6 +160,7 @@ export const MentionEditor = forwardRef< searchProfiles, searchEmojis, searchCommands, + onCommandExecute, autoFocus = false, className = "", }, @@ -620,15 +622,17 @@ export const MentionEditor = forwardRef< ...slashCommandSuggestion, command: ({ editor, props }: any) => { // props is the ChatAction - // Replace the entire content with just the command - editor - .chain() - .focus() - .deleteRange({ from: 0, to: editor.state.doc.content.size }) - .insertContentAt(0, [ - { type: "text", text: `/${props.name}` }, - ]) - .run(); + // Execute the command immediately and clear the editor + editor.commands.clearContent(); + if (onCommandExecute) { + // Execute action asynchronously + onCommandExecute(props).catch((error) => { + console.error( + "[MentionEditor] Command execution failed:", + error, + ); + }); + } }, }, renderLabel({ node }) { @@ -643,6 +647,7 @@ export const MentionEditor = forwardRef< mentionSuggestion, emojiSuggestion, slashCommandSuggestion, + onCommandExecute, placeholder, ]);