diff --git a/components/AIAssist.tsx b/components/AIAssist.tsx index c1137aa..f1f9d02 100644 --- a/components/AIAssist.tsx +++ b/components/AIAssist.tsx @@ -34,6 +34,37 @@ interface PreviewData { * A ultra-stable iframe wrapper that avoids hydration issues * and provides a WOW visual experience. */ + +// Error Boundary for Canvas crashes +class CanvasErrorBoundary extends React.Component<{ children: React.ReactNode }, { hasError: boolean, error: string | null }> { + constructor(props: { children: React.ReactNode }) { + super(props); + this.state = { hasError: false, error: null }; + } + + static getDerivedStateFromError(error: Error) { + return { hasError: true, error: error.message }; + } + + render() { + if (this.state.hasError) { + return ( +
+ +

Canvas Crashed

+

{this.state.error}

+ +
+ ); + } + return this.props.children; + } +} const BuildingArtifact = ({ type }: { type: string }) => { const [progress, setProgress] = useState(0); const steps = [ @@ -393,7 +424,7 @@ export default function AIAssist() { } = useStore(); const t = translations[language].aiAssist; - const activeTab = aiAssistTabs.find(t => t.id === activeTabId) || aiAssistTabs[0]; + const activeTab = aiAssistTabs?.find(t => t.id === activeTabId) || aiAssistTabs?.[0] || { id: 'default', title: 'New Chat', history: [], currentAgent: 'general' }; const aiAssistHistory = activeTab?.history || []; const [input, setInput] = useState(""); @@ -404,10 +435,10 @@ export default function AIAssist() { // Sync local state when tab changes useEffect(() => { if (activeTab) { - setCurrentAgent(activeTab.currentAgent); - setPreviewData(activeTab.previewData); + setCurrentAgent(activeTab.currentAgent || "general"); + setPreviewData(activeTab.previewData || null); } - }, [activeTabId]); + }, [activeTabId, activeTab]); const [availableModels, setAvailableModels] = useState([]); const [showCanvas, setShowCanvas] = useState(false); const [viewMode, setViewMode] = useState<"preview" | "code">("preview"); @@ -716,7 +747,10 @@ export default function AIAssist() { ].map(({ label, agent, icon }) => (