- {Object.values(workspaces).map((ws) => (
+ {sortedWorkspaces.map((ws) => (
))}
diff --git a/src/components/WinViewer.tsx b/src/components/WinViewer.tsx
index a7f2359..a3f6fb4 100644
--- a/src/components/WinViewer.tsx
+++ b/src/components/WinViewer.tsx
@@ -69,8 +69,9 @@ export function WinViewer() {
const continuer = isLast ? " " : "│ ";
// Workspace header
+ const wsDisplay = ws.label ? `${ws.number} "${ws.label}"` : `${ws.number}`;
lines.push(
- `${prefix} ${isActive ? "●" : "○"} workspace: "${ws.label}" (${wsId})`,
+ `${prefix} ${isActive ? "●" : "○"} workspace: ${wsDisplay} (${wsId})`,
);
// Window IDs
diff --git a/src/components/WindowRenderer.tsx b/src/components/WindowRenderer.tsx
index 8827168..440f3d9 100644
--- a/src/components/WindowRenderer.tsx
+++ b/src/components/WindowRenderer.tsx
@@ -1,20 +1,44 @@
-import { Component, ReactNode } from "react";
-import { AlertCircle } from "lucide-react";
+import { Component, ReactNode, Suspense, lazy } from "react";
+import { AlertCircle, Loader2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { WindowInstance } from "@/types/app";
-import { NipRenderer } from "./NipRenderer";
-import ManPage from "./ManPage";
-import ReqViewer from "./ReqViewer";
-import { EventDetailViewer } from "./EventDetailViewer";
-import { ProfileViewer } from "./ProfileViewer";
-import EncodeViewer from "./EncodeViewer";
-import DecodeViewer from "./DecodeViewer";
-import { RelayViewer } from "./RelayViewer";
-import KindRenderer from "./KindRenderer";
-import KindsViewer from "./KindsViewer";
-import NipsViewer from "./NipsViewer";
-import { DebugViewer } from "./DebugViewer";
-import ConnViewer from "./ConnViewer";
+
+// 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"));
+
+// Loading fallback component
+function ViewerLoading() {
+ return (
+
+ );
+}
interface WindowRendererProps {
window: WindowInstance;
@@ -168,7 +192,9 @@ export function WindowRenderer({ window, onClose }: WindowRendererProps) {
return (
- {content}
+ }>
+ {content}
+
);
}
diff --git a/src/components/WindowTitle.tsx b/src/components/WindowTitle.tsx
index 5373201..246a6d6 100644
--- a/src/components/WindowTitle.tsx
+++ b/src/components/WindowTitle.tsx
@@ -3,6 +3,7 @@ import { WindowInstance } from "@/types/app";
import { WindowToolbar } from "./WindowToolbar";
import { WindowRenderer } from "./WindowRenderer";
import { useDynamicWindowTitle } from "./DynamicWindowTitle";
+import { ErrorBoundary } from "./ErrorBoundary";
interface WindowTileProps {
id: string;
@@ -47,7 +48,9 @@ export function WindowTile({
return (
- onClose(id)} />
+
+ onClose(id)} />
+
);
}
diff --git a/src/components/WindowToolbar.tsx b/src/components/WindowToolbar.tsx
index 0a43699..438f078 100644
--- a/src/components/WindowToolbar.tsx
+++ b/src/components/WindowToolbar.tsx
@@ -21,8 +21,7 @@ export function WindowToolbar({
if (!window) return;
// Get command string (existing or reconstructed)
- const commandString =
- window.commandString || reconstructCommand(window);
+ const commandString = window.commandString || reconstructCommand(window);
// Set edit mode state
setEditMode({
@@ -43,6 +42,7 @@ export function WindowToolbar({
className="p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted/50 transition-colors"
onClick={handleEdit}
title="Edit command"
+ aria-label="Edit command"
>
@@ -52,6 +52,7 @@ export function WindowToolbar({
className="p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted/50 transition-colors"
onClick={onClose}
title="Close window"
+ aria-label="Close window"
>
diff --git a/src/components/nostr/RichText/Mention.tsx b/src/components/nostr/RichText/Mention.tsx
index 428a85c..02f0732 100644
--- a/src/components/nostr/RichText/Mention.tsx
+++ b/src/components/nostr/RichText/Mention.tsx
@@ -79,7 +79,8 @@ export function Mention({ node }: MentionNodeProps) {
if (!options.showEventEmbeds) {
return (
- {node.encoded || `naddr:${pointer.identifier || pointer.pubkey.slice(0, 8)}...`}
+ {node.encoded ||
+ `naddr:${pointer.identifier || pointer.pubkey.slice(0, 8)}...`}
);
}
diff --git a/src/components/nostr/user-menu.tsx b/src/components/nostr/user-menu.tsx
index 7c90917..15fbfc9 100644
--- a/src/components/nostr/user-menu.tsx
+++ b/src/components/nostr/user-menu.tsx
@@ -83,7 +83,7 @@ export default function UserMenu() {
return (
-