From 5e14462a2379a3efca8c24e2d0caca90c42387e3 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Fri, 7 Jun 2024 08:11:29 -0700 Subject: [PATCH] Add error boundary and ATProto Embed --- package.json | 1 + src/components/appcom/vocabulary/Embed.tsx | 59 ++++++++++++++++++++++ src/components/appcom/vocabulary/index.tsx | 33 +++++++++--- src/view/screens/DebugAppcom.tsx | 34 ++++++++++++- yarn.lock | 7 +++ 5 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 src/components/appcom/vocabulary/Embed.tsx diff --git a/package.json b/package.json index 0ea23a2749..cf8d788cd8 100644 --- a/package.json +++ b/package.json @@ -165,6 +165,7 @@ "react-avatar-editor": "^13.0.0", "react-compiler-runtime": "file:./lib/react-compiler-runtime", "react-dom": "^18.2.0", + "react-error-boundary": "^4.0.13", "react-keyed-flatten-children": "^3.0.0", "react-native": "0.74.1", "react-native-compressor": "^1.8.24", diff --git a/src/components/appcom/vocabulary/Embed.tsx b/src/components/appcom/vocabulary/Embed.tsx new file mode 100644 index 0000000000..a32af80489 --- /dev/null +++ b/src/components/appcom/vocabulary/Embed.tsx @@ -0,0 +1,59 @@ +import React from 'react' +import {View} from 'react-native' +import {AtUri} from '@atproto/api' +import {z} from 'zod' + +import {usePostQuery} from '#/state/queries/post' +import {useProfileQuery} from '#/state/queries/profile' +import {useResolveDidQuery} from '#/state/queries/resolve-uri' +import {Post as PostInner} from '#/view/com/post/Post' +import {ProfileCardWithFollowBtn} from '#/view/com/profile/ProfileCard' +import {Text} from '#/components/Typography' + +const embedProps = z.object({ + uri: z.string(), +}) + +export type ProfileCardProps = z.infer + +export function Embed(props: React.PropsWithChildren) { + const propsParsed = embedProps.parse(props) + const urip = new AtUri(propsParsed.uri) + console.log(urip) + + if (!urip.pathname || urip.pathname === '/') { + return + } + if (urip.collection === 'app.bsky.feed.post') { + return + } + return +} + +function Actor({actor}: {actor: string}) { + const {data: did} = useResolveDidQuery(actor) + const {data: profile} = useProfileQuery({did}) + + if (profile) { + return + } + // TODO error, loading + return +} + +function Post({uri}: {uri: string}) { + const {data: post} = usePostQuery(uri) + if (post) { + return + } + // TODO error, loading + return +} + +function Unknown({urip}: {urip: AtUri}) { + return ( + + Unsupported record type: {urip.collection} + + ) +} diff --git a/src/components/appcom/vocabulary/index.tsx b/src/components/appcom/vocabulary/index.tsx index 7e44c38045..70f4cf5e1e 100644 --- a/src/components/appcom/vocabulary/index.tsx +++ b/src/components/appcom/vocabulary/index.tsx @@ -1,7 +1,12 @@ import React from 'react' +import {View} from 'react-native' +import {ErrorBoundary} from 'react-error-boundary' +import {ZodError} from 'zod' +import {Text} from '#/components/Typography' import type {AppComNode} from '../types' import {Box} from './Box' +import {Embed} from './Embed' import {Expandable} from './Expandable' import {Label} from './Label' import {Stack} from './Stack' @@ -9,6 +14,7 @@ import {Tabs} from './Tabs' export const VOCAB: Record> = { Box, + Embed, Expandable, Label, Stack, @@ -22,12 +28,25 @@ export function AppComponent({node}: {node: AppComNode}) { return <> } return ( - - {node.children?.length - ? node.children.map((child, i) => ( - - )) - : null} - + + + {node.children?.length + ? node.children.map((child, i) => ( + + )) + : null} + + + ) +} +function fallbackRender({error}: {error: Error}) { + const msg = + error instanceof ZodError + ? `${error.issues[0].path.join('.')}: ${error.issues[0].message}` + : error.toString() + return ( + + {msg} + ) } diff --git a/src/view/screens/DebugAppcom.tsx b/src/view/screens/DebugAppcom.tsx index 7276538938..cc125dafd0 100644 --- a/src/view/screens/DebugAppcom.tsx +++ b/src/view/screens/DebugAppcom.tsx @@ -74,7 +74,39 @@ const DEFAULT_AC = h('Stack', {gap: 10}, [ h('Label', {text: 'Display TODO'}), h('Label', {text: 'Inputs TODO'}), h('Label', {text: 'Forms TODO'}), - h('Label', {text: 'ATProto TODO'}), + h('Stack', {gap: 10, pad: {t: 20}}, [ + h('Box', {pad: {x: 10}}, [ + h('Label', {text: 'Embed (Actor)', size: 10, weight: 'bold'}), + ]), + h('Box', {border: 'secondary', corner: 8}, [ + h('Embed', {uri: 'bsky.app'}), + ]), + h('Box', {border: 'secondary', corner: 8}, [ + h('Embed', {uri: 'at://atproto.com/'}), + ]), + h('Box', {border: 'secondary', corner: 8}, [ + h('Embed', {uri: 'at://pfrazee.com'}), + ]), + h('Box', {pad: {x: 10}}, [ + h('Label', {text: 'Embed (Post)', size: 10, weight: 'bold'}), + ]), + h('Box', {border: 'secondary', corner: 8}, [ + h('Embed', {uri: 'at://pfrazee.com/app.bsky.feed.post/3ku7fbojcqs25'}), + ]), + h('Box', {border: 'secondary', corner: 8}, [ + h('Embed', {uri: 'at://bsky.app/app.bsky.feed.post/3ku73zs755e27'}), + ]), + h('Box', {pad: {x: 10}}, [ + h('Label', { + text: 'Embed (Unsupported record type)', + size: 10, + weight: 'bold', + }), + ]), + h('Box', {border: 'secondary', corner: 8}, [ + h('Embed', {uri: 'at://pfrazee.com/com.example.unknown/123'}), + ]), + ]), ]), ]) diff --git a/yarn.lock b/yarn.lock index a83d41dba6..60d2ae9c31 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18820,6 +18820,13 @@ react-dom@^18.2.0: loose-envify "^1.1.0" scheduler "^0.23.0" +react-error-boundary@^4.0.13: + version "4.0.13" + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-4.0.13.tgz#80386b7b27b1131c5fbb7368b8c0d983354c7947" + integrity sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ== + dependencies: + "@babel/runtime" "^7.12.5" + react-error-overlay@^6.0.11: version "6.0.11" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb"