import { Component, ReactNode, Suspense, lazy } from "react"; import { AlertCircle, Loader2 } from "lucide-react"; import { Button } from "@/components/ui/button"; import { WindowInstance } from "@/types/app"; // Lazy load all viewer components for better code splitting const NipRenderer = lazy(() => import("./NipRenderer").then((m) => ({ default: m.NipRenderer })), ); const ManPage = lazy(() => import("./ManPage")); const ReqViewer = lazy(() => import("./ReqViewer")); const EventDetailViewer = lazy(() => import("./EventDetailViewer").then((m) => ({ default: m.EventDetailViewer })), ); const ProfileViewer = lazy(() => import("./ProfileViewer").then((m) => ({ default: m.ProfileViewer })), ); const EncodeViewer = lazy(() => import("./EncodeViewer")); const DecodeViewer = lazy(() => import("./DecodeViewer")); const RelayViewer = lazy(() => import("./RelayViewer").then((m) => ({ default: m.RelayViewer })), ); const KindRenderer = lazy(() => import("./KindRenderer")); const KindsViewer = lazy(() => import("./KindsViewer")); const NipsViewer = lazy(() => import("./NipsViewer")); const DebugViewer = lazy(() => import("./DebugViewer").then((m) => ({ default: m.DebugViewer })), ); const ConnViewer = lazy(() => import("./ConnViewer")); const ChatViewer = lazy(() => import("./ChatViewer").then((m) => ({ default: m.ChatViewer })), ); const GroupListViewer = lazy(() => import("./GroupListViewer").then((m) => ({ default: m.GroupListViewer })), ); const SpellsViewer = lazy(() => import("./SpellsViewer").then((m) => ({ default: m.SpellsViewer })), ); const SpellbooksViewer = lazy(() => import("./SpellbooksViewer").then((m) => ({ default: m.SpellbooksViewer })), ); // Loading fallback component function ViewerLoading() { return (

Loading...

); } interface WindowRendererProps { window: WindowInstance; onClose: () => void; } interface WindowErrorBoundaryState { hasError: boolean; error?: Error; } class WindowErrorBoundary extends Component< { children: ReactNode; windowTitle: string; onClose: () => void }, WindowErrorBoundaryState > { constructor(props: { children: ReactNode; windowTitle: string; onClose: () => void; }) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error: Error): WindowErrorBoundaryState { return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { console.error( `Window "${this.props.windowTitle}" crashed:`, error, errorInfo, ); } render() { if (this.state.hasError) { return (

Window Crashed

{this.state.error?.message || "An unexpected error occurred in this window."}

); } return this.props.children; } } export function WindowRenderer({ window, onClose }: WindowRendererProps) { let content: ReactNode; try { switch (window.appId) { case "nip": content = ; break; case "kind": content = ; break; case "kinds": content = ; break; case "nips": content = ; break; case "man": content = ; break; case "req": content = ( ); break; case "open": content = ; break; case "profile": content = ; break; case "encode": content = ; break; case "decode": content = ; break; case "relay": content = ; break; case "debug": content = ; break; case "conn": content = ; break; case "chat": // Check if this is a group list (kind 10009) - render multi-room interface if (window.props.identifier?.type === "group-list") { content = ; } else { content = ( ); } break; case "spells": content = ; break; case "spellbooks": content = ; break; default: content = (
Unknown app: {window.appId}
); } } catch (error) { content = (

Failed to render window

{error instanceof Error ? error.message : "An unexpected error occurred"}

); } return ( }>
{content}
); }