Add ATProto Avatar
This commit is contained in:
@@ -0,0 +1,24 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {AtUri} from '@atproto/api'
|
||||||
|
import {z} from 'zod'
|
||||||
|
|
||||||
|
import {useProfileQuery} from '#/state/queries/profile'
|
||||||
|
import {useResolveDidQuery} from '#/state/queries/resolve-uri'
|
||||||
|
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||||
|
|
||||||
|
const avatarProps = z.object({
|
||||||
|
uri: z.string(),
|
||||||
|
size: z.number().default(50),
|
||||||
|
})
|
||||||
|
|
||||||
|
export type AvatarProps = z.infer<typeof avatarProps>
|
||||||
|
|
||||||
|
export function Avatar(props: React.PropsWithChildren<AvatarProps>) {
|
||||||
|
const propsParsed = avatarProps.parse(props)
|
||||||
|
const urip = new AtUri(propsParsed.uri)
|
||||||
|
|
||||||
|
const {data: did} = useResolveDidQuery(urip.host)
|
||||||
|
const {data: profile} = useProfileQuery({did})
|
||||||
|
|
||||||
|
return <UserAvatar avatar={profile?.avatar} size={propsParsed.size} />
|
||||||
|
}
|
||||||
@@ -14,12 +14,11 @@ const embedProps = z.object({
|
|||||||
uri: z.string(),
|
uri: z.string(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type ProfileCardProps = z.infer<typeof embedProps>
|
export type EmbedProps = z.infer<typeof embedProps>
|
||||||
|
|
||||||
export function Embed(props: React.PropsWithChildren<ProfileCardProps>) {
|
export function Embed(props: React.PropsWithChildren<EmbedProps>) {
|
||||||
const propsParsed = embedProps.parse(props)
|
const propsParsed = embedProps.parse(props)
|
||||||
const urip = new AtUri(propsParsed.uri)
|
const urip = new AtUri(propsParsed.uri)
|
||||||
console.log(urip)
|
|
||||||
|
|
||||||
if (!urip.pathname || urip.pathname === '/') {
|
if (!urip.pathname || urip.pathname === '/') {
|
||||||
return <Actor actor={urip.host} />
|
return <Actor actor={urip.host} />
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {ZodError} from 'zod'
|
|||||||
|
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import type {AppComNode} from '../types'
|
import type {AppComNode} from '../types'
|
||||||
|
import {Avatar} from './Avatar'
|
||||||
import {Box} from './Box'
|
import {Box} from './Box'
|
||||||
import {Embed} from './Embed'
|
import {Embed} from './Embed'
|
||||||
import {Expandable} from './Expandable'
|
import {Expandable} from './Expandable'
|
||||||
@@ -13,6 +14,7 @@ import {Stack} from './Stack'
|
|||||||
import {Tabs} from './Tabs'
|
import {Tabs} from './Tabs'
|
||||||
|
|
||||||
export const VOCAB: Record<string, React.ComponentType<any>> = {
|
export const VOCAB: Record<string, React.ComponentType<any>> = {
|
||||||
|
Avatar,
|
||||||
Box,
|
Box,
|
||||||
Embed,
|
Embed,
|
||||||
Expandable,
|
Expandable,
|
||||||
|
|||||||
@@ -75,6 +75,16 @@ const DEFAULT_AC = h('Stack', {gap: 10}, [
|
|||||||
h('Label', {text: 'Inputs TODO'}),
|
h('Label', {text: 'Inputs TODO'}),
|
||||||
h('Label', {text: 'Forms TODO'}),
|
h('Label', {text: 'Forms TODO'}),
|
||||||
h('Stack', {gap: 10, pad: {t: 20}}, [
|
h('Stack', {gap: 10, pad: {t: 20}}, [
|
||||||
|
h('Box', {pad: {x: 10}}, [
|
||||||
|
h('Label', {text: 'Avatar', size: 10, weight: 'bold'}),
|
||||||
|
]),
|
||||||
|
h('Box', {border: 'secondary', corner: 8, pad: {x: 16, y: 12}}, [
|
||||||
|
h('Stack', {direction: 'row', gap: 10}, [
|
||||||
|
h('Avatar', {uri: 'bsky.app'}),
|
||||||
|
h('Avatar', {uri: 'at://atproto.com'}),
|
||||||
|
h('Avatar', {uri: 'at://pfrazee.com/'}),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
h('Box', {pad: {x: 10}}, [
|
h('Box', {pad: {x: 10}}, [
|
||||||
h('Label', {text: 'Embed (Actor)', size: 10, weight: 'bold'}),
|
h('Label', {text: 'Embed (Actor)', size: 10, weight: 'bold'}),
|
||||||
]),
|
]),
|
||||||
|
|||||||
Reference in New Issue
Block a user