import React, { useState, useRef, useEffect } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { ArrowLeft, ArrowRight, RefreshCw, X, Minimize2, Maximize2, Loader2, AlertCircle, Globe, Home, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; // TODO: These imports will be used when implementing actual Tauri webview // import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"; // import { WebviewWindow } from "@tauri-apps/api/webviewWindow"; interface WebviewPreviewProps { /** * Initial URL to load */ initialUrl: string; /** * Callback when close is clicked */ onClose: () => void; /** * Whether the webview is maximized */ isMaximized?: boolean; /** * Callback when maximize/minimize is clicked */ onToggleMaximize?: () => void; /** * Callback when URL changes */ onUrlChange?: (url: string) => void; /** * Optional className for styling */ className?: string; } /** * WebviewPreview component - Browser-like webview with navigation controls * * @example * setShowPreview(false)} * /> */ const WebviewPreviewComponent: React.FC = ({ initialUrl, onClose, isMaximized = false, onToggleMaximize, onUrlChange, className, }) => { const [currentUrl, setCurrentUrl] = useState(initialUrl); const [inputUrl, setInputUrl] = useState(initialUrl); const [isLoading, setIsLoading] = useState(false); const [hasError, setHasError] = useState(false); const [errorMessage, setErrorMessage] = useState(""); // TODO: These will be implemented with actual webview navigation // const [canGoBack, setCanGoBack] = useState(false); // const [canGoForward, setCanGoForward] = useState(false); // TODO: These will be used for actual Tauri webview implementation // const webviewRef = useRef(null); const iframeRef = useRef(null); const containerRef = useRef(null); const contentRef = useRef(null); // const previewId = useRef(`preview-${Date.now()}`); // Handle ESC key to exit full screen useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape' && isMaximized && onToggleMaximize) { onToggleMaximize(); } }; document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); }, [isMaximized, onToggleMaximize]); // Debug: Log initial URL on mount useEffect(() => { console.log('[WebviewPreview] Component mounted with initialUrl:', initialUrl, 'isMaximized:', isMaximized); }, []); // Focus management for full screen mode useEffect(() => { if (isMaximized && containerRef.current) { containerRef.current.focus(); } }, [isMaximized]); // For now, we'll use an iframe as a placeholder // In the full implementation, this would create a Tauri webview window useEffect(() => { if (currentUrl) { // This is where we'd create the actual webview // For now, using iframe for demonstration setIsLoading(true); setHasError(false); // Simulate loading const timer = setTimeout(() => { setIsLoading(false); }, 1000); return () => clearTimeout(timer); } }, [currentUrl]); const navigate = (url: string) => { try { // Validate URL const urlObj = new URL(url.startsWith('http') ? url : `https://${url}`); const finalUrl = urlObj.href; console.log('[WebviewPreview] Navigating to:', finalUrl); setCurrentUrl(finalUrl); setInputUrl(finalUrl); setHasError(false); onUrlChange?.(finalUrl); } catch (err) { setHasError(true); setErrorMessage("Invalid URL"); } }; const handleNavigate = () => { if (inputUrl.trim()) { navigate(inputUrl); } }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { handleNavigate(); } }; const handleGoBack = () => { // In real implementation, this would call webview.goBack() console.log("Go back"); }; const handleGoForward = () => { // In real implementation, this would call webview.goForward() console.log("Go forward"); }; const handleRefresh = () => { setIsLoading(true); // In real implementation, this would call webview.reload() setTimeout(() => setIsLoading(false), 1000); }; const handleGoHome = () => { navigate(initialUrl); }; return (
{/* Browser Top Bar */}
{/* Title Bar */}
Preview {isLoading && ( )}
{onToggleMaximize && ( {isMaximized ? "Exit full screen (ESC)" : "Enter full screen"} )}
{/* Navigation Bar */}
{/* Navigation Buttons */}
{/* URL Bar */}
setInputUrl(e.target.value)} onKeyDown={handleKeyDown} placeholder="Enter URL..." className="pr-10 h-8 text-sm font-mono" /> {inputUrl !== currentUrl && ( )}
{/* Webview Content */}
{/* Loading Overlay */} {isLoading && (

Loading preview...

)}
{/* Error State */} {hasError ? (

Failed to load preview

{errorMessage || "The page could not be loaded. Please check the URL and try again."}

) : currentUrl ? ( // Placeholder iframe - in real implementation, this would be a Tauri webview