import { memo, useCallback, useMemo, useState, type ReactElement } from "react"; import { Text, View } from "react-native"; import { FileText, Layers, MessageSquare, Undo2 } from "lucide-react-native"; import { StyleSheet, useUnistyles } from "react-native-unistyles"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { type RewindMode, useRewindCapabilities } from "./use-rewind-capabilities"; import type { AgentCapabilityFlags } from "@getpaseo/protocol/agent-types"; export type { RewindMode }; interface RewindMenuProps { capabilities: AgentCapabilityFlags; rewoundText: string; onRewind: (input: { mode: RewindMode; rewoundText: string }) => Promise | void; isPending?: boolean; testID?: string; } function getIcon(mode: RewindMode, color: string): ReactElement { switch (mode) { case "conversation": return ; case "files": return ; case "both": return ; } } export const RewindMenu = memo(function RewindMenu({ capabilities, rewoundText, onRewind, isPending: isPendingProp = false, testID = "rewind-menu", }: RewindMenuProps) { const { theme } = useUnistyles(); const items = useRewindCapabilities(capabilities); const [isOpen, setIsOpen] = useState(false); const [pendingMode, setPendingMode] = useState(null); const isLocked = isPendingProp || pendingMode !== null; const handleOpenChange = useCallback( (next: boolean) => { if (!next && pendingMode !== null) return; setIsOpen(next); }, [pendingMode], ); const handleSelect = useCallback( (mode: RewindMode) => async () => { if (isLocked) return; setPendingMode(mode); try { await onRewind({ mode, rewoundText }); } catch { // useRewindAgentMutation owns the toast; the menu only owns flow state. } finally { setPendingMode(null); setIsOpen(false); } }, [isLocked, onRewind, rewoundText], ); const triggerStyle = useCallback( () => [styles.trigger, isLocked ? styles.triggerDisabled : null], [isLocked], ); const tooltipContent = useMemo( () => ( Rewind to this message ), [], ); if (items.length === 0) { return null; } return ( {({ hovered, open }) => ( )} {tooltipContent} This action cannot be undone {items.map((item) => ( {item.label} ))} ); }); const styles = StyleSheet.create((theme) => ({ trigger: { padding: theme.spacing[1], paddingTop: theme.spacing[1], alignItems: "center", justifyContent: "center", backgroundColor: "transparent", }, triggerDisabled: { opacity: theme.opacity[50], }, triggerSlot: { alignSelf: "center", }, tooltipText: { color: theme.colors.foreground, fontSize: theme.fontSize.xs, }, warningHeader: { paddingHorizontal: theme.spacing[3], paddingTop: theme.spacing[2], paddingBottom: theme.spacing[2], }, warningText: { color: theme.colors.foregroundMuted, fontSize: theme.fontSize.xs, }, }));