Add recipe install warning (#3537)
Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
@@ -60,6 +60,7 @@ import { type View, ViewOptions } from '../App';
|
||||
import { MainPanelLayout } from './Layout/MainPanelLayout';
|
||||
import ChatInput from './ChatInput';
|
||||
import { ScrollArea, ScrollAreaHandle } from './ui/scroll-area';
|
||||
import { RecipeWarningModal } from './ui/RecipeWarningModal';
|
||||
import { useChatEngine } from '../hooks/useChatEngine';
|
||||
import { useRecipeManager } from '../hooks/useRecipeManager';
|
||||
import { useSessionContinuation } from '../hooks/useSessionContinuation';
|
||||
@@ -195,6 +196,10 @@ function BaseChatContent({
|
||||
handleAutoExecution,
|
||||
recipeError,
|
||||
setRecipeError,
|
||||
isRecipeWarningModalOpen,
|
||||
recipeAccepted,
|
||||
handleRecipeAccept,
|
||||
handleRecipeCancel,
|
||||
} = useRecipeManager(messages, location.state);
|
||||
|
||||
// Reset recipe usage tracking when recipe changes
|
||||
@@ -356,9 +361,9 @@ function BaseChatContent({
|
||||
{
|
||||
// Check if we should show splash instead of messages
|
||||
(() => {
|
||||
// Show splash if we have a recipe and user hasn't started using it yet
|
||||
// Show splash if we have a recipe and user hasn't started using it yet, and recipe has been accepted
|
||||
const shouldShowSplash =
|
||||
recipeConfig && !hasStartedUsingRecipe && !suppressEmptyState;
|
||||
recipeConfig && recipeAccepted && !hasStartedUsingRecipe && !suppressEmptyState;
|
||||
|
||||
return shouldShowSplash;
|
||||
})() ? (
|
||||
@@ -377,7 +382,8 @@ function BaseChatContent({
|
||||
<PopularChatTopics append={(text: string) => appendWithTracking(text)} />
|
||||
) : null}
|
||||
</>
|
||||
) : filteredMessages.length > 0 || (recipeConfig && hasStartedUsingRecipe) ? (
|
||||
) : filteredMessages.length > 0 ||
|
||||
(recipeConfig && recipeAccepted && hasStartedUsingRecipe) ? (
|
||||
<>
|
||||
{disableSearch ? (
|
||||
// Render messages without SearchView wrapper when search is disabled
|
||||
@@ -523,6 +529,18 @@ function BaseChatContent({
|
||||
summaryContent={summaryContent}
|
||||
/>
|
||||
|
||||
{/* Recipe Warning Modal */}
|
||||
<RecipeWarningModal
|
||||
isOpen={isRecipeWarningModalOpen}
|
||||
onConfirm={handleRecipeAccept}
|
||||
onCancel={handleRecipeCancel}
|
||||
recipeDetails={{
|
||||
title: recipeConfig?.title,
|
||||
description: recipeConfig?.description,
|
||||
instructions: recipeConfig?.instructions,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Recipe Error Modal */}
|
||||
{recipeError && (
|
||||
<div className="fixed inset-0 z-[300] flex items-center justify-center bg-black/50">
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from './dialog';
|
||||
import { Button } from './button';
|
||||
|
||||
interface RecipeWarningModalProps {
|
||||
isOpen: boolean;
|
||||
onConfirm: () => void;
|
||||
onCancel: () => void;
|
||||
recipeDetails: {
|
||||
title?: string;
|
||||
description?: string;
|
||||
instructions?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export function RecipeWarningModal({
|
||||
isOpen,
|
||||
onConfirm,
|
||||
onCancel,
|
||||
recipeDetails,
|
||||
}: RecipeWarningModalProps) {
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={(open) => !open && onCancel()}>
|
||||
<DialogContent className="sm:max-w-[600px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>⚠️ New Recipe Warning</DialogTitle>
|
||||
<DialogDescription>
|
||||
You are about to execute a recipe that you haven't run before. Only proceed if you trust
|
||||
the source of this recipe.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="bg-background-muted p-4 rounded-lg">
|
||||
<h3 className="font-medium mb-2 text-text-standard">Recipe Details:</h3>
|
||||
<div className="space-y-2 text-sm">
|
||||
{recipeDetails.title && (
|
||||
<p className="text-text-standard">
|
||||
<strong>Title:</strong> {recipeDetails.title}
|
||||
</p>
|
||||
)}
|
||||
{recipeDetails.description && (
|
||||
<p className="text-text-standard">
|
||||
<strong>Description:</strong> {recipeDetails.description}
|
||||
</p>
|
||||
)}
|
||||
{recipeDetails.instructions && (
|
||||
<p className="text-text-standard">
|
||||
<strong>Instructions:</strong> {recipeDetails.instructions}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={onCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={onConfirm}>Trust and Execute</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user