From 75500fa298418d0b4eb655274ce5bff11c87f01c Mon Sep 17 00:00:00 2001 From: Alejandro Date: Mon, 22 Dec 2025 22:41:10 +0100 Subject: [PATCH] feat: add clickable example commands to welcome screen (#23) * feat: add clickable example commands to welcome screen Add 4 example commands to the welcome splash screen to make the client more friendly on cold start and to new users: - nip 29: View relay-based groups spec - profile verbiricha@habla.news: Explore a Nostr profile - req -k 1 -l 20: Query recent notes - nips: Browse all NIPs Commands are clickable and execute directly, opening the appropriate window without requiring users to type or use the command palette. Changes: - Update GrimoireWelcome component with EXAMPLE_COMMANDS constant - Add onExecuteCommand prop to handle direct command execution - Update WorkspaceView to pass handleExecuteCommand callback - Use parseAndExecuteCommand from command-parser for execution * fix: lint --------- Co-authored-by: Claude --- src/components/GrimoireWelcome.tsx | 37 +++++++++++++++++++++++++++++- src/components/WorkspaceView.tsx | 27 ++++++++++++++++++++-- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/components/GrimoireWelcome.tsx b/src/components/GrimoireWelcome.tsx index 059e640..e4c89af 100644 --- a/src/components/GrimoireWelcome.tsx +++ b/src/components/GrimoireWelcome.tsx @@ -4,9 +4,23 @@ import { Kbd, KbdGroup } from "./ui/kbd"; interface GrimoireWelcomeProps { onLaunchCommand: () => void; + onExecuteCommand: (command: string) => void; } -export function GrimoireWelcome({ onLaunchCommand }: GrimoireWelcomeProps) { +const EXAMPLE_COMMANDS = [ + { command: "nip 29", description: "View relay-based groups spec" }, + { + command: "profile verbiricha@habla.news", + description: "Explore a Nostr profile", + }, + { command: "req -k 1 -l 20", description: "Query recent notes" }, + { command: "nips", description: "Browse all NIPs" }, +]; + +export function GrimoireWelcome({ + onLaunchCommand, + onExecuteCommand, +}: GrimoireWelcomeProps) { return (
@@ -65,6 +79,27 @@ export function GrimoireWelcome({ onLaunchCommand }: GrimoireWelcomeProps) { Launch Command
+ + {/* Example commands */} +
+

+ Try these commands: +

+ {EXAMPLE_COMMANDS.map(({ command, description }) => ( + + ))} +
); diff --git a/src/components/WorkspaceView.tsx b/src/components/WorkspaceView.tsx index b3692bd..ecffaa3 100644 --- a/src/components/WorkspaceView.tsx +++ b/src/components/WorkspaceView.tsx @@ -4,15 +4,35 @@ import { WindowToolbar } from "./WindowToolbar"; import { WindowTile } from "./WindowTitle"; import { GrimoireWelcome } from "./GrimoireWelcome"; import { useAppShell } from "./layouts/AppShellContext"; +import { parseAndExecuteCommand } from "@/lib/command-parser"; export function WorkspaceView() { - const { state, updateLayout, removeWindow } = useGrimoire(); + const { state, updateLayout, removeWindow, addWindow } = useGrimoire(); const { openCommandLauncher } = useAppShell(); const handleRemoveWindow = (id: string) => { removeWindow(id); }; + const handleExecuteCommand = async (commandString: string) => { + const result = await parseAndExecuteCommand( + commandString, + state.activeAccount?.pubkey, + ); + + if (result.error || !result.props || !result.command) { + console.error("Failed to execute command:", result.error); + return; + } + + addWindow( + result.command.appId, + result.props, + commandString, + result.globalFlags?.windowProps?.title, + ); + }; + const renderTile = (id: string, path: MosaicBranch[]) => { const window = state.windows[id]; @@ -48,7 +68,10 @@ export function WorkspaceView() { return ( <> {activeWorkspace.layout === null ? ( - + ) : (