Deep link: add prompt (#1669)
Example: open "dyad://add-prompt?data=eyJ0aXRsZSI6IlRlc3QgUHJvbXB0IiwiZGVzY3JpcHRpb24iOiJBIHRlc3QgcHJvbXB0IGZyb20gZGVlcCBsaW5rIiwiY29udGVudCI6IlRoaXMgaXMgdGhlIGNvbnRlbnQgb2YgdGhlIHByb21wdC4ifQ%3D%3D" <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds dyad://add-prompt deep link that navigates to Library and opens a prefilled Create Prompt dialog from base64 JSON. > > - **Deep Link Handling** > - Parse `dyad://add-prompt?data=<base64-json>` in `src/main.ts`; validate with `AddPromptDataSchema` and send `deep-link-received` with payload. > - Extend `DeepLinkContext` to navigate to `/library` on `add-prompt`. > - **Library/Dialogs** > - Add controlled open state and `prefillData` support to `CreateOrEditPromptDialog` and `CreatePromptDialog` (`src/components/CreatePromptDialog.tsx`). > - In `src/pages/library.tsx`, listen for `add-prompt` deep link, prefill form, open dialog, and clear deep-link state. > - **Schemas** > - Define `AddPromptDataSchema`, `AddPromptPayload`, and `AddPromptDeepLinkData` in `src/ipc/deep_link_data.ts` and include in `DeepLinkData` union. > - **E2E Tests** > - Add Playwright test `e2e-tests/add_prompt_deep_link.spec.ts` and ARIA snapshot to verify deep link opens prefilled dialog and saves prompt. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 1ddb12306cfca195682c8a1b719f60093b858d54. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
This commit is contained in:
@@ -38,6 +38,13 @@ interface CreateOrEditPromptDialogProps {
|
||||
content: string;
|
||||
}) => Promise<any>;
|
||||
trigger?: React.ReactNode;
|
||||
prefillData?: {
|
||||
title: string;
|
||||
description: string;
|
||||
content: string;
|
||||
};
|
||||
isOpen?: boolean;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
}
|
||||
|
||||
export function CreateOrEditPromptDialog({
|
||||
@@ -46,8 +53,14 @@ export function CreateOrEditPromptDialog({
|
||||
onCreatePrompt,
|
||||
onUpdatePrompt,
|
||||
trigger,
|
||||
prefillData,
|
||||
isOpen,
|
||||
onOpenChange,
|
||||
}: CreateOrEditPromptDialogProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [internalOpen, setInternalOpen] = useState(false);
|
||||
const open = isOpen !== undefined ? isOpen : internalOpen;
|
||||
const setOpen = onOpenChange || setInternalOpen;
|
||||
|
||||
const [draft, setDraft] = useState({
|
||||
title: "",
|
||||
description: "",
|
||||
@@ -74,7 +87,7 @@ export function CreateOrEditPromptDialog({
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize draft with prompt data when editing
|
||||
// Initialize draft with prompt data when editing or prefill data
|
||||
useEffect(() => {
|
||||
if (mode === "edit" && prompt) {
|
||||
setDraft({
|
||||
@@ -82,10 +95,16 @@ export function CreateOrEditPromptDialog({
|
||||
description: prompt.description || "",
|
||||
content: prompt.content,
|
||||
});
|
||||
} else if (prefillData) {
|
||||
setDraft({
|
||||
title: prefillData.title,
|
||||
description: prefillData.description,
|
||||
content: prefillData.content,
|
||||
});
|
||||
} else {
|
||||
setDraft({ title: "", description: "", content: "" });
|
||||
}
|
||||
}, [mode, prompt, open]);
|
||||
}, [mode, prompt, prefillData, open]);
|
||||
|
||||
// Auto-resize textarea when content changes
|
||||
useEffect(() => {
|
||||
@@ -107,6 +126,12 @@ export function CreateOrEditPromptDialog({
|
||||
description: prompt.description || "",
|
||||
content: prompt.content,
|
||||
});
|
||||
} else if (prefillData) {
|
||||
setDraft({
|
||||
title: prefillData.title,
|
||||
description: prefillData.description,
|
||||
content: prefillData.content,
|
||||
});
|
||||
} else {
|
||||
setDraft({ title: "", description: "", content: "" });
|
||||
}
|
||||
@@ -222,14 +247,30 @@ export function CreateOrEditPromptDialog({
|
||||
// Backward compatibility wrapper for create mode
|
||||
export function CreatePromptDialog({
|
||||
onCreatePrompt,
|
||||
prefillData,
|
||||
isOpen,
|
||||
onOpenChange,
|
||||
}: {
|
||||
onCreatePrompt: (prompt: {
|
||||
title: string;
|
||||
description?: string;
|
||||
content: string;
|
||||
}) => Promise<any>;
|
||||
prefillData?: {
|
||||
title: string;
|
||||
description: string;
|
||||
content: string;
|
||||
};
|
||||
isOpen?: boolean;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
}) {
|
||||
return (
|
||||
<CreateOrEditPromptDialog mode="create" onCreatePrompt={onCreatePrompt} />
|
||||
<CreateOrEditPromptDialog
|
||||
mode="create"
|
||||
onCreatePrompt={onCreatePrompt}
|
||||
prefillData={prefillData}
|
||||
isOpen={isOpen}
|
||||
onOpenChange={onOpenChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user