notification-rendering error boundary

since a lot is going on there now

Changed files
+49 -2
atproto-notifications
+25
atproto-notifications/package-lock.json
··· 15 15 "psl": "^1.15.0", 16 16 "react": "^19.1.0", 17 17 "react-dom": "^19.1.0", 18 + "react-error-boundary": "^6.0.0", 18 19 "react-router": "^7.6.3", 19 20 "react-time-ago": "^7.3.3", 20 21 "reactjs-popup": "^2.0.6" ··· 36 37 "../lexicons": { 37 38 "version": "0.0.1", 38 39 "dependencies": { 40 + "@atcute/client": "^4.0.3", 41 + "@atcute/identity-resolver": "^1.1.3", 42 + "jsonpath-plus": "^10.3.0", 39 43 "psl": "^1.15.0" 40 44 } 41 45 }, ··· 327 331 }, 328 332 "peerDependencies": { 329 333 "@babel/core": "^7.0.0-0" 334 + } 335 + }, 336 + "node_modules/@babel/runtime": { 337 + "version": "7.27.6", 338 + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", 339 + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", 340 + "license": "MIT", 341 + "engines": { 342 + "node": ">=6.9.0" 330 343 } 331 344 }, 332 345 "node_modules/@babel/template": { ··· 3075 3088 }, 3076 3089 "peerDependencies": { 3077 3090 "react": "^19.1.0" 3091 + } 3092 + }, 3093 + "node_modules/react-error-boundary": { 3094 + "version": "6.0.0", 3095 + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-6.0.0.tgz", 3096 + "integrity": "sha512-gdlJjD7NWr0IfkPlaREN2d9uUZUlksrfOx7SX62VRerwXbMY6ftGCIZua1VG1aXFNOimhISsTq+Owp725b9SiA==", 3097 + "license": "MIT", 3098 + "dependencies": { 3099 + "@babel/runtime": "^7.12.5" 3100 + }, 3101 + "peerDependencies": { 3102 + "react": ">=16.13.1" 3078 3103 } 3079 3104 }, 3080 3105 "node_modules/react-is": {
+1
atproto-notifications/package.json
··· 18 18 "psl": "^1.15.0", 19 19 "react": "^19.1.0", 20 20 "react-dom": "^19.1.0", 21 + "react-error-boundary": "^6.0.0", 21 22 "react-router": "^7.6.3", 22 23 "react-time-ago": "^7.3.3", 23 24 "reactjs-popup": "^2.0.6"
+8
atproto-notifications/src/components/Notification.css
··· 22 22 border-bottom-color: hsla(0, 0%, 0%, 0.3); 23 23 } 24 24 25 + .notification.error { 26 + background: hsla(347, 72%, 20%, 0.333); 27 + align-items: center; 28 + } 29 + .notification.error p { 30 + margin: 0; 31 + } 32 + 25 33 .handle { 26 34 color: skyblue; 27 35 }
+10
atproto-notifications/src/components/Notification.tsx
··· 7 7 8 8 import './Notification.css'; 9 9 10 + export function fallbackRender({ error, resetErrorBoundary }) { 11 + console.error('rendering fallback for error', error); 12 + return ( 13 + <div className="notification error"> 14 + <p>sorry, something went wrong trying to show this notification</p> 15 + <p><button onClick={resetErrorBoundary}>retry</button></p> 16 + </div> 17 + ); 18 + } 19 + 10 20 export function Notification({ app, group, source, source_record, source_did, subject, timestamp }) { 11 21 const [resolvedLink, setResolvedLink] = useState(null); 12 22
+5 -2
atproto-notifications/src/pages/Feed.tsx
··· 1 1 import { useCallback, useEffect, useState } from 'react'; 2 + import { ErrorBoundary } from 'react-error-boundary'; 2 3 import Popup from 'reactjs-popup'; 3 4 import { getNotifications, getSecondary } from '../db'; 4 5 import { ButtonGroup } from '../components/Buttons'; 5 6 import { NotificationSettings } from '../components/NotificationSettings'; 6 - import { Notification } from '../components/Notification'; 7 + import { Notification, fallbackRender } from '../components/Notification'; 7 8 import { GetJson, PostJson } from '../components/Fetch'; 8 9 import psl from 'psl'; 9 10 import lexicons from 'lexicons'; ··· 232 233 233 234 <div className="feed-notifications"> 234 235 {feed.map(([k, n]) => ( 235 - <Notification key={k} {...n} /> 236 + <ErrorBoundary key={k} fallbackRender={fallbackRender}> 237 + <Notification {...n} /> 238 + </ErrorBoundary> 236 239 ))} 237 240 </div> 238 241 </div>