diff --git a/desktop/index.html b/desktop/index.html index 5309a15..bffc3a7 100644 --- a/desktop/index.html +++ b/desktop/index.html @@ -9,6 +9,13 @@ dev vs. production rules cleanly. --> DChain diff --git a/desktop/src/sections/messages/Conversation.tsx b/desktop/src/sections/messages/Conversation.tsx index a354191..bf1c8c5 100644 --- a/desktop/src/sections/messages/Conversation.tsx +++ b/desktop/src/sections/messages/Conversation.tsx @@ -98,12 +98,13 @@ export function Conversation({ address }: { address: string }): React.ReactEleme } }; - const name = contact?.username ? `@${contact.username}` + const name = (contact?.username ? `@${contact.username}` : contact?.alias ? contact.alias : isSelf ? 'Saved Messages' - : shortAddr(address, 8); + : shortAddr(address || '', 8)) || shortAddr(address || '', 8); + const firstLetter = (name || '?').replace(/^@/, '').charAt(0).toUpperCase() || '?'; return (
@@ -118,12 +119,18 @@ export function Conversation({ address }: { address: string }): React.ReactEleme color: '#fff', fontWeight: 700, fontSize: 14, display: 'flex', alignItems: 'center', justifyContent: 'center', }}> - {isSelf ? '★' : name.replace(/^@/, '').charAt(0).toUpperCase()} + {isSelf ? '★' : firstLetter}
-
{name}
-
- {shortAddr(address, 6)} +
{name}
+
+ {shortAddr(address || '', 6)}
diff --git a/desktop/src/shell/PaneBoundary.tsx b/desktop/src/shell/PaneBoundary.tsx new file mode 100644 index 0000000..a83c237 --- /dev/null +++ b/desktop/src/shell/PaneBoundary.tsx @@ -0,0 +1,62 @@ +// PaneBoundary — ErrorBoundary scoped to one Shell pane. A crash in +// the Conversation component shouldn't black-out the whole window; it +// should leave NavBar + List + StatusBar usable so the operator can +// switch sections and report the bug. Resets when the keyed section +// changes. + +import React from 'react'; + +interface Props { + /** Used as React key at the callsite; also shown in the panic copy. */ + sectionName: string; + children: React.ReactNode; +} + +interface State { + error: Error | null; +} + +export class PaneBoundary extends React.Component { + state: State = { error: null }; + + static getDerivedStateFromError(error: Error): State { + return { error }; + } + + componentDidCatch(error: Error, info: React.ErrorInfo): void { + console.error(`[PaneBoundary:${this.props.sectionName}]`, error, info); + } + + render(): React.ReactNode { + if (!this.state.error) return this.props.children; + return ( +
+
+ {this.props.sectionName} crashed +
+
+ {this.state.error.message} +
+
+          {this.state.error.stack}
+        
+ +
+ ); + } +} diff --git a/desktop/src/shell/Shell.tsx b/desktop/src/shell/Shell.tsx index 4d22e0f..29a161e 100644 --- a/desktop/src/shell/Shell.tsx +++ b/desktop/src/shell/Shell.tsx @@ -24,6 +24,7 @@ import { TitleBar } from './TitleBar'; import { NavBar } from './NavBar'; import { StatusBar } from './StatusBar'; import { UpdateBanner } from './UpdateBanner'; +import { PaneBoundary } from './PaneBoundary'; import { MessagesList, MessagesDetail } from '@/sections/messages'; import { FeedList, FeedDetail } from '@/sections/feed'; import { WalletList, WalletDetail } from '@/sections/wallet'; @@ -51,10 +52,14 @@ export function Shell(): React.ReactElement { borderRight: '1px solid #1f1f1f', overflowY: 'auto', }}> - + + +
- + + +