Files
grimoire/src/components/WorkspaceView.tsx
Alejandro 75500fa298 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 <noreply@anthropic.com>
2025-12-22 22:41:10 +01:00

91 lines
2.3 KiB
TypeScript

import { useGrimoire } from "@/core/state";
import { Mosaic, MosaicWindow, MosaicBranch } from "react-mosaic-component";
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, 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];
if (!window) {
return (
<MosaicWindow
path={path}
title="Unknown Window"
toolbarControls={<WindowToolbar />}
>
<div className="p-4 text-muted-foreground">
Window not found: {id}
</div>
</MosaicWindow>
);
}
return (
<WindowTile
id={id}
window={window}
path={path}
onClose={handleRemoveWindow}
onEditCommand={openCommandLauncher}
/>
);
};
const activeWorkspace = state.workspaces[state.activeWorkspaceId];
if (!activeWorkspace) return null;
return (
<>
{activeWorkspace.layout === null ? (
<GrimoireWelcome
onLaunchCommand={openCommandLauncher}
onExecuteCommand={handleExecuteCommand}
/>
) : (
<Mosaic
renderTile={renderTile}
value={activeWorkspace.layout}
onChange={updateLayout}
onRelease={(node) => {
if (typeof node === "string") {
handleRemoveWindow(node);
}
}}
className="mosaic-blueprint-theme"
/>
)}
</>
);
}