refactor: remove parameterization UI from SpellDialog

Removes the parameterized spell creation functionality from SpellDialog
since we now have CreateParameterizedSpellDialog that provides
context-aware spell creation from ProfileViewer, EventDetailViewer, and
RelayViewer.

Changes:
- Remove detectParameterSuggestion() function
- Remove parameter-related state (parameterEnabled, parameterType, parameterDefault)
- Remove parameter configuration UI section
- Remove unused imports (Checkbox, Sparkles, pubkey from useAccount)
- Simplify save/publish functions to not handle parameter options
- Update dialog description for clarity

SpellDialog is now focused solely on creating regular (non-parameterized)
spells. Users should use the per-screen "Create spell" buttons for
parameterized spells that work with profiles, events, or relays.
This commit is contained in:
Claude
2026-01-23 22:03:23 +00:00
parent 1224835813
commit 88f7bc4d10

View File

@@ -10,12 +10,11 @@ import {
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { toast } from "sonner";
import { parseReqCommand } from "@/lib/req-parser";
import { reconstructCommand, detectCommandType } from "@/lib/spell-conversion";
import type { ParsedSpell, SpellEvent } from "@/types/spell";
import { Loader2, Sparkles } from "lucide-react";
import { Loader2 } from "lucide-react";
import { saveSpell } from "@/services/spell-storage";
import { LocalSpell } from "@/services/db";
import { PublishSpellAction } from "@/actions/publish-spell";
@@ -54,36 +53,6 @@ function filterSpellCommand(command: string): string {
}
}
/**
* Detect if command contains values that suggest parameterization
* Returns suggested parameter type if detected
*/
function detectParameterSuggestion(
command: string,
): "$pubkey" | "$event" | "$relay" | null {
if (!command) return null;
// Check for $me or $contacts (suggests $pubkey parameter)
if (command.includes("$me") || command.includes("$contacts")) {
return "$pubkey";
}
// Check for single author hex that's not $me/$contacts
// (user might want to make it reusable)
const authorMatch = command.match(/-a\s+([a-f0-9]{64})/);
if (authorMatch) {
return "$pubkey";
}
// Check for event ID or naddr (suggests $event parameter)
const eventMatch = command.match(/-e\s+([a-f0-9]{64}|naddr1[a-z0-9]+)/);
if (eventMatch) {
return "$event";
}
return null;
}
interface SpellDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
@@ -109,20 +78,13 @@ export function SpellDialog({
existingSpell,
onSuccess,
}: SpellDialogProps) {
const { canSign, pubkey } = useAccount();
const { canSign } = useAccount();
// Form state
const [alias, setAlias] = useState("");
const [name, setName] = useState("");
const [description, setDescription] = useState("");
// Parameter configuration
const [parameterEnabled, setParameterEnabled] = useState(false);
const [parameterType, setParameterType] = useState<
"$pubkey" | "$event" | "$relay"
>("$pubkey");
const [parameterDefault, setParameterDefault] = useState<string>("$me");
// Publishing/saving state
const [publishingState, setPublishingState] =
useState<PublishingState>("idle");
@@ -134,33 +96,11 @@ export function SpellDialog({
setAlias("alias" in existingSpell ? existingSpell.alias || "" : "");
setName(existingSpell.name || "");
setDescription(existingSpell.description || "");
// Load parameter configuration from existing spell
if ("parameterType" in existingSpell && existingSpell.parameterType) {
setParameterEnabled(true);
setParameterType(existingSpell.parameterType);
setParameterDefault(existingSpell.parameterDefault?.[0] || "$me");
} else if ("parameter" in existingSpell && existingSpell.parameter) {
setParameterEnabled(true);
setParameterType(existingSpell.parameter.type);
setParameterDefault(existingSpell.parameter.default?.[0] || "$me");
} else {
setParameterEnabled(false);
}
} else if (mode === "create") {
// Reset form for create mode
setAlias("");
setName("");
setDescription("");
// Auto-detect parameter suggestion
const command = initialCommand || "";
const suggestion = detectParameterSuggestion(command);
if (suggestion) {
setParameterType(suggestion);
// Don't auto-enable, let user decide
setParameterEnabled(false);
}
}
}, [mode, existingSpell, open, initialCommand]);
@@ -208,8 +148,6 @@ export function SpellDialog({
command,
description: description.trim() || undefined,
isPublished: false,
parameterType: parameterEnabled ? parameterType : undefined,
parameterDefault: parameterEnabled ? [parameterDefault] : undefined,
});
// Success!
@@ -278,8 +216,6 @@ export function SpellDialog({
command,
description: description.trim() || undefined,
isPublished: false,
parameterType: parameterEnabled ? parameterType : undefined,
parameterDefault: parameterEnabled ? [parameterDefault] : undefined,
});
// 2. Use PublishSpellAction to handle signing and publishing
@@ -343,7 +279,7 @@ export function SpellDialog({
</DialogTitle>
<DialogDescription>
{mode === "create"
? "Save this command as a spell. You can save it locally or publish it to Nostr relays."
? "Save this command as a reusable spell. You can save it locally or publish it to Nostr."
: "Edit your spell and republish it to relays."}
</DialogDescription>
</DialogHeader>
@@ -405,136 +341,6 @@ export function SpellDialog({
/>
</div>
{/* Parameter configuration */}
<div className="rounded-lg border border-border/50 p-4 space-y-3">
<div className="flex items-center space-x-2">
<Checkbox
id="parameter-enabled"
checked={parameterEnabled}
onCheckedChange={(checked) =>
setParameterEnabled(checked as boolean)
}
disabled={isBusy}
/>
<label
htmlFor="parameter-enabled"
className="text-sm font-medium flex items-center gap-2 cursor-pointer"
>
<Sparkles className="h-4 w-4 text-purple-500" />
Cast on any{" "}
{parameterType === "$pubkey"
? "profile"
: parameterType === "$event"
? "event"
: "relay"}
</label>
</div>
{parameterEnabled && (
<div className="grid gap-3 pl-6">
<div className="grid gap-2">
<label
htmlFor="parameter-type"
className="text-sm font-medium"
>
Target type
</label>
<div className="flex gap-4">
{(
[
["$pubkey", "Profile"],
["$event", "Event"],
["$relay", "Relay"],
] as const
).map(([value, label]) => (
<label
key={value}
className="flex items-center gap-2 cursor-pointer"
>
<input
type="radio"
name="parameter-type"
value={value}
checked={parameterType === value}
onChange={(e) =>
setParameterType(
e.target.value as "$pubkey" | "$event" | "$relay",
)
}
disabled={isBusy}
className="cursor-pointer"
/>
<span className="text-sm">{label}</span>
</label>
))}
</div>
<p className="text-muted-foreground text-xs">
{parameterType === "$pubkey" &&
"Apply this spell to any user's profile"}
{parameterType === "$event" &&
"Apply this spell to any event"}
{parameterType === "$relay" &&
"Apply this spell to any relay"}
</p>
</div>
{parameterType === "$pubkey" && (
<div className="grid gap-2">
<label
htmlFor="parameter-default"
className="text-sm font-medium"
>
Default value{" "}
<span className="text-muted-foreground text-xs">
(optional)
</span>
</label>
<select
id="parameter-default"
value={parameterDefault}
onChange={(e) => setParameterDefault(e.target.value)}
disabled={isBusy}
className="rounded-md border border-input bg-background px-3 py-2 text-sm"
>
<option value="$me">Current user ($me)</option>
{pubkey && (
<option value={pubkey}>
My pubkey ({pubkey.slice(0, 8)}...)
</option>
)}
</select>
<p className="text-muted-foreground text-xs">
Value used when no argument provided
</p>
</div>
)}
</div>
)}
{!parameterEnabled &&
detectParameterSuggestion(
mode === "edit" && existingSpell
? existingSpell.command
: initialCommand || "",
) && (
<p className="text-muted-foreground text-xs pl-6">
💡 This command uses{" "}
{parameterType === "$pubkey"
? "a user"
: parameterType === "$event"
? "an event"
: "a relay"}
. Enable this to make it work with any{" "}
{parameterType === "$pubkey"
? "profile"
: parameterType === "$event"
? "event"
: "relay"}
.
</p>
)}
</div>
{/* Command display (read-only, filtered to show only spell parts) */}
<div className="grid gap-2">
<label htmlFor="command" className="text-sm font-medium">