Update to the latest APIs

This commit is contained in:
Paul Frazee 2022-11-04 17:39:54 -05:00
parent 8ae6e67eea
commit f333a90fab
165 changed files with 2963 additions and 4747 deletions

View file

@ -11,7 +11,7 @@ import Animated, {
withTiming,
interpolate,
} from 'react-native-reanimated'
import {colors} from '../../../lib/styles'
import {colors} from '../../lib/styles'
export function Autocomplete({
active,

View file

@ -2,7 +2,7 @@ import React, {useEffect, useMemo, useState} from 'react'
import {StyleSheet, Text, TextInput, TouchableOpacity, View} from 'react-native'
import LinearGradient from 'react-native-linear-gradient'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import * as GetUserFollows from '../../../third-party/api/src/types/app/bsky/getUserFollows'
import * as GetFollows from '../../../third-party/api/src/client/types/app/bsky/graph/getFollows'
import {Autocomplete} from './Autocomplete'
import Toast from '../util/Toast'
import ProgressCircle from '../util/ProgressCircle'
@ -28,14 +28,14 @@ export function ComposePost({
const [error, setError] = useState('')
const [text, setText] = useState('')
const [followedUsers, setFollowedUsers] = useState<
undefined | GetUserFollows.OutputSchema['follows']
undefined | GetFollows.OutputSchema['follows']
>(undefined)
const [autocompleteOptions, setAutocompleteOptions] = useState<string[]>([])
useEffect(() => {
let aborted = false
store.api.app.bsky
.getUserFollows({
store.api.app.bsky.graph
.getFollows({
user: store.me.did || '',
})
.then(res => {
@ -58,8 +58,8 @@ export function ComposePost({
setAutocompleteOptions(
[prefix].concat(
followedUsers
.filter(user => user.name.startsWith(prefix))
.map(user => user.name),
.filter(user => user.handle.startsWith(prefix))
.map(user => user.handle),
),
)
} else if (autocompleteOptions) {

View file

@ -6,7 +6,7 @@ import {ErrorMessage} from '../util/ErrorMessage'
import {useStores} from '../../../state'
import {ProfileViewModel} from '../../../state/models/profile-view'
import {s, colors, gradients} from '../../lib/styles'
import * as Profile from '../../../third-party/api/src/types/app/bsky/profile'
import * as Profile from '../../../third-party/api/src/client/types/app/bsky/actor/profile'
export const snapPoints = ['80%']

View file

@ -23,7 +23,7 @@ export const FeedItem = observer(function FeedItem({
const urip = new AtUri(item.subjectUri)
return `/profile/${urip.host}/post/${urip.rkey}`
} else if (item.isFollow) {
return `/profile/${item.author.name}`
return `/profile/${item.author.handle}`
} else if (item.isReply) {
const urip = new AtUri(item.uri)
return `/profile/${urip.host}/post/${urip.rkey}`
@ -34,7 +34,7 @@ export const FeedItem = observer(function FeedItem({
if (item.isLike || item.isRepost) {
return 'Post'
} else if (item.isFollow) {
return item.author.name
return item.author.handle
} else if (item.isReply) {
return 'Post'
}
@ -76,18 +76,18 @@ export const FeedItem = observer(function FeedItem({
return <></>
}
let authors: {href: string; name: string; displayName?: string}[] = [
let authors: {href: string; handle: string; displayName?: string}[] = [
{
href: `/profile/${item.author.name}`,
name: item.author.name,
href: `/profile/${item.author.handle}`,
handle: item.author.handle,
displayName: item.author.displayName,
},
]
if (item.additional?.length) {
authors = authors.concat(
item.additional.map(item2 => ({
href: `/profile/${item2.author.name}`,
name: item2.author.name,
href: `/profile/${item2.author.handle}`,
handle: item2.author.handle,
displayName: item2.author.displayName,
})),
)
@ -113,11 +113,11 @@ export const FeedItem = observer(function FeedItem({
style={s.mr2}
key={author.href}
href={author.href}
title={`@${author.name}`}>
title={`@${author.handle}`}>
<UserAvatar
size={30}
displayName={author.displayName}
name={author.name}
handle={author.handle}
/>
</Link>
))}
@ -132,9 +132,9 @@ export const FeedItem = observer(function FeedItem({
key={authors[0].href}
style={styles.metaItem}
href={authors[0].href}
title={`@${authors[0].name}`}>
title={`@${authors[0].handle}`}>
<Text style={[s.f14, s.bold]}>
{authors[0].displayName || authors[0].name}
{authors[0].displayName || authors[0].handle}
</Text>
</Link>
{authors.length > 1 ? (

View file

@ -67,18 +67,21 @@ export const PostLikedBy = observer(function PostLikedBy({uri}: {uri: string}) {
const LikedByItem = ({item}: {item: LikedByViewItemModel}) => {
return (
<Link style={styles.outer} href={`/profile/${item.name}`} title={item.name}>
<Link
style={styles.outer}
href={`/profile/${item.handle}`}
title={item.handle}>
<View style={styles.layout}>
<View style={styles.layoutAvi}>
<UserAvatar
size={40}
displayName={item.displayName}
name={item.name}
handle={item.handle}
/>
</View>
<View style={styles.layoutContent}>
<Text style={[s.f15, s.bold]}>{item.displayName}</Text>
<Text style={[s.f14, s.gray5]}>@{item.name}</Text>
<Text style={[s.f14, s.gray5]}>@{item.handle}</Text>
</View>
</View>
</Link>

View file

@ -80,18 +80,21 @@ export const PostRepostedBy = observer(function PostRepostedBy({
const RepostedByItem = ({item}: {item: RepostedByViewItemModel}) => {
return (
<Link style={styles.outer} href={`/profile/${item.name}`} title={item.name}>
<Link
style={styles.outer}
href={`/profile/${item.handle}`}
title={item.handle}>
<View style={styles.layout}>
<View style={styles.layoutAvi}>
<UserAvatar
size={40}
displayName={item.displayName}
name={item.name}
handle={item.handle}
/>
</View>
<View style={styles.layoutContent}>
<Text style={[s.f15, s.bold]}>{item.displayName}</Text>
<Text style={[s.f14, s.gray5]}>@{item.name}</Text>
<Text style={[s.f14, s.gray5]}>@{item.handle}</Text>
</View>
</View>
</Link>

View file

@ -3,7 +3,7 @@ import {observer} from 'mobx-react-lite'
import {Image, StyleSheet, Text, TouchableOpacity, View} from 'react-native'
import Svg, {Line} from 'react-native-svg'
import {AtUri} from '../../../third-party/uri'
import * as PostType from '../../../third-party/api/src/types/app/bsky/post'
import * as PostType from '../../../third-party/api/src/client/types/app/bsky/feed/post'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {PostThreadViewPostModel} from '../../../state/models/post-thread-view'
import {Link} from '../util/Link'
@ -31,20 +31,20 @@ export const PostThreadItem = observer(function PostThreadItem({
const itemHref = useMemo(() => {
const urip = new AtUri(item.uri)
return `/profile/${item.author.name}/post/${urip.rkey}`
}, [item.uri, item.author.name])
const itemTitle = `Post by ${item.author.name}`
const authorHref = `/profile/${item.author.name}`
const authorTitle = item.author.name
return `/profile/${item.author.handle}/post/${urip.rkey}`
}, [item.uri, item.author.handle])
const itemTitle = `Post by ${item.author.handle}`
const authorHref = `/profile/${item.author.handle}`
const authorTitle = item.author.handle
const likesHref = useMemo(() => {
const urip = new AtUri(item.uri)
return `/profile/${item.author.name}/post/${urip.rkey}/liked-by`
}, [item.uri, item.author.name])
return `/profile/${item.author.handle}/post/${urip.rkey}/liked-by`
}, [item.uri, item.author.handle])
const likesTitle = 'Likes on this post'
const repostsHref = useMemo(() => {
const urip = new AtUri(item.uri)
return `/profile/${item.author.name}/post/${urip.rkey}/reposted-by`
}, [item.uri, item.author.name])
return `/profile/${item.author.handle}/post/${urip.rkey}/reposted-by`
}, [item.uri, item.author.handle])
const repostsTitle = 'Reposts of this post'
const onPressReply = () => {
@ -116,7 +116,7 @@ export const PostThreadItem = observer(function PostThreadItem({
<UserAvatar
size={50}
displayName={item.author.displayName}
name={item.author.name}
handle={item.author.handle}
/>
</Link>
<View style={styles.layoutContent}>
@ -147,7 +147,7 @@ export const PostThreadItem = observer(function PostThreadItem({
style={styles.metaItem}
href={authorHref}
title={authorTitle}>
<Text style={[s.f14, s.gray5]}>@{item.author.name}</Text>
<Text style={[s.f14, s.gray5]}>@{item.author.handle}</Text>
</Link>
</View>
</View>
@ -235,12 +235,12 @@ export const PostThreadItem = observer(function PostThreadItem({
<UserAvatar
size={50}
displayName={item.author.displayName}
name={item.author.name}
handle={item.author.handle}
/>
</Link>
<View style={styles.layoutContent}>
{item.replyingToAuthor &&
item.replyingToAuthor !== item.author.name && (
item.replyingToAuthor !== item.author.handle && (
<View style={[s.flexRow, {alignItems: 'center'}]}>
<FontAwesomeIcon
icon="reply"
@ -267,7 +267,7 @@ export const PostThreadItem = observer(function PostThreadItem({
style={styles.metaItem}
href={authorHref}
title={authorTitle}>
<Text style={[s.f14, s.gray5]}>@{item.author.name}</Text>
<Text style={[s.f14, s.gray5]}>@{item.author.handle}</Text>
</Link>
<Text style={[styles.metaItem, s.f14, s.gray5]}>
&middot; {ago(item.indexedAt)}

View file

@ -1,7 +1,7 @@
import React, {useState, useEffect, useMemo} from 'react'
import React, {useState, useEffect} from 'react'
import {observer} from 'mobx-react-lite'
import {AtUri} from '../../../third-party/uri'
import * as PostType from '../../../third-party/api/src/types/app/bsky/post'
import * as PostType from '../../../third-party/api/src/client/types/app/bsky/feed/post'
import {
ActivityIndicator,
StyleSheet,
@ -58,10 +58,10 @@ export const Post = observer(function Post({uri}: {uri: string}) {
const record = view.thread?.record as unknown as PostType.Record
const itemUrip = new AtUri(item.uri)
const itemHref = `/profile/${item.author.name}/post/${itemUrip.rkey}`
const itemTitle = `Post by ${item.author.name}`
const authorHref = `/profile/${item.author.name}`
const authorTitle = item.author.name
const itemHref = `/profile/${item.author.handle}/post/${itemUrip.rkey}`
const itemTitle = `Post by ${item.author.handle}`
const authorHref = `/profile/${item.author.handle}`
const authorTitle = item.author.handle
let replyAuthorDid = ''
let replyHref = ''
if (record.reply) {
@ -90,7 +90,7 @@ export const Post = observer(function Post({uri}: {uri: string}) {
<UserAvatar
size={50}
displayName={item.author.displayName}
name={item.author.name}
handle={item.author.handle}
/>
</Link>
<View style={styles.layoutContent}>
@ -99,7 +99,7 @@ export const Post = observer(function Post({uri}: {uri: string}) {
<Text style={[s.f15, s.bold]}>{item.author.displayName}</Text>
</Link>
<Link style={styles.metaItem} href={authorHref} title={authorTitle}>
<Text style={[s.f14, s.gray5]}>@{item.author.name}</Text>
<Text style={[s.f14, s.gray5]}>@{item.author.handle}</Text>
</Link>
<Text style={[styles.metaItem, s.f14, s.gray5]}>
&middot; {ago(item.indexedAt)}

View file

@ -2,7 +2,7 @@ import React, {useMemo} from 'react'
import {observer} from 'mobx-react-lite'
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'
import {AtUri} from '../../../third-party/uri'
import * as PostType from '../../../third-party/api/src/types/app/bsky/post'
import * as PostType from '../../../third-party/api/src/client/types/app/bsky/feed/post'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {FeedItemModel} from '../../../state/models/feed-view'
import {SharePostModel} from '../../../state/models/shell'
@ -24,10 +24,10 @@ export const FeedItem = observer(function FeedItem({
const record = item.record as unknown as PostType.Record
const itemHref = useMemo(() => {
const urip = new AtUri(item.uri)
return `/profile/${item.author.name}/post/${urip.rkey}`
}, [item.uri, item.author.name])
const itemTitle = `Post by ${item.author.name}`
const authorHref = `/profile/${item.author.name}`
return `/profile/${item.author.handle}/post/${urip.rkey}`
}, [item.uri, item.author.handle])
const itemTitle = `Post by ${item.author.handle}`
const authorHref = `/profile/${item.author.handle}`
const replyAuthorDid = useMemo(() => {
if (!record.reply) return ''
const urip = new AtUri(record.reply.parent?.uri || record.reply.root.uri)
@ -70,11 +70,11 @@ export const FeedItem = observer(function FeedItem({
<Link
style={styles.layoutAvi}
href={authorHref}
title={item.author.name}>
title={item.author.handle}>
<UserAvatar
size={50}
displayName={item.author.displayName}
name={item.author.name}
handle={item.author.handle}
/>
</Link>
<View style={styles.layoutContent}>
@ -82,14 +82,14 @@ export const FeedItem = observer(function FeedItem({
<Link
style={styles.metaItem}
href={authorHref}
title={item.author.name}>
title={item.author.handle}>
<Text style={[s.f15, s.bold]}>{item.author.displayName}</Text>
</Link>
<Link
style={styles.metaItem}
href={authorHref}
title={item.author.name}>
<Text style={[s.f14, s.gray5]}>@{item.author.name}</Text>
title={item.author.handle}>
<Text style={[s.f14, s.gray5]}>@{item.author.handle}</Text>
</Link>
<Text style={[styles.metaItem, s.f14, s.gray5]}>
&middot; {ago(item.indexedAt)}

View file

@ -1,13 +1,6 @@
import React, {useState, useEffect} from 'react'
import {observer} from 'mobx-react-lite'
import {
ActivityIndicator,
FlatList,
Image,
StyleSheet,
Text,
View,
} from 'react-native'
import {ActivityIndicator, FlatList, StyleSheet, Text, View} from 'react-native'
import {
UserFollowersViewModel,
FollowerItem,
@ -78,18 +71,21 @@ export const ProfileFollowers = observer(function ProfileFollowers({
const User = ({item}: {item: FollowerItem}) => {
return (
<Link style={styles.outer} href={`/profile/${item.name}`} title={item.name}>
<Link
style={styles.outer}
href={`/profile/${item.handle}`}
title={item.handle}>
<View style={styles.layout}>
<View style={styles.layoutAvi}>
<UserAvatar
size={40}
displayName={item.displayName}
name={item.name}
handle={item.handle}
/>
</View>
<View style={styles.layoutContent}>
<Text style={[s.f15, s.bold]}>{item.displayName}</Text>
<Text style={[s.f14, s.gray5]}>@{item.name}</Text>
<Text style={[s.f14, s.gray5]}>@{item.handle}</Text>
</View>
</View>
</Link>

View file

@ -1,13 +1,6 @@
import React, {useState, useEffect} from 'react'
import {observer} from 'mobx-react-lite'
import {
ActivityIndicator,
FlatList,
Image,
StyleSheet,
Text,
View,
} from 'react-native'
import {ActivityIndicator, FlatList, StyleSheet, Text, View} from 'react-native'
import {
UserFollowsViewModel,
FollowItem,
@ -78,18 +71,21 @@ export const ProfileFollows = observer(function ProfileFollows({
const User = ({item}: {item: FollowItem}) => {
return (
<Link style={styles.outer} href={`/profile/${item.name}`} title={item.name}>
<Link
style={styles.outer}
href={`/profile/${item.handle}`}
title={item.handle}>
<View style={styles.layout}>
<View style={styles.layoutAvi}>
<UserAvatar
size={40}
displayName={item.displayName}
name={item.name}
handle={item.handle}
/>
</View>
<View style={styles.layoutContent}>
<Text style={[s.f15, s.bold]}>{item.displayName}</Text>
<Text style={[s.f14, s.gray5]}>@{item.name}</Text>
<Text style={[s.f14, s.gray5]}>@{item.handle}</Text>
</View>
</View>
</Link>

View file

@ -35,7 +35,7 @@ export const ProfileHeader = observer(function ProfileHeader({
() => {
Toast.show(
`${view.myState.follow ? 'Following' : 'No longer following'} ${
view.displayName || view.name
view.displayName || view.handle
}`,
{
duration: Toast.durations.LONG,
@ -53,10 +53,10 @@ export const ProfileHeader = observer(function ProfileHeader({
// TODO
}
const onPressFollowers = () => {
store.nav.navigate(`/profile/${view.name}/followers`)
store.nav.navigate(`/profile/${view.handle}/followers`)
}
const onPressFollows = () => {
store.nav.navigate(`/profile/${view.name}/follows`)
store.nav.navigate(`/profile/${view.handle}/follows`)
}
// loading
@ -95,7 +95,11 @@ export const ProfileHeader = observer(function ProfileHeader({
</TouchableOpacity>
) : undefined}
<View style={styles.avi}>
<UserAvatar size={80} displayName={view.displayName} name={view.name} />
<UserAvatar
size={80}
displayName={view.displayName}
handle={view.handle}
/>
</View>
<View style={styles.content}>
<View style={[styles.displayNameLine]}>

View file

@ -12,14 +12,14 @@ const GRADIENTS = [
export function UserAvatar({
size,
displayName,
name,
handle,
}: {
size: number
displayName: string | undefined
name: string
handle: string
}) {
const initials = getInitials(displayName || name)
const gi = cyrb53(name) % GRADIENTS.length
const initials = getInitials(displayName || handle)
const gi = cyrb53(handle) % GRADIENTS.length
return (
<Svg width={size} height={size} viewBox="0 0 100 100">
<Defs>

View file

@ -1,5 +1,5 @@
import React, {useState, useEffect} from 'react'
import * as AppBskyGetProfile from '../../../third-party/api/src/types/app/bsky/getProfile'
import * as GetProfile from '../../../third-party/api/src/client/types/app/bsky/actor/getProfile'
import {StyleProp, Text, TextStyle} from 'react-native'
import {useStores} from '../../../state'
@ -12,26 +12,26 @@ export function UserInfoText({
style,
}: {
did: string
attr?: keyof AppBskyGetProfile.OutputSchema
attr?: keyof GetProfile.OutputSchema
loading?: string
failed?: string
prefix?: string
style?: StyleProp<TextStyle>
}) {
attr = attr || 'name'
attr = attr || 'handle'
loading = loading || '...'
failed = failed || 'user'
const store = useStores()
const [profile, setProfile] = useState<
undefined | AppBskyGetProfile.OutputSchema
>(undefined)
const [profile, setProfile] = useState<undefined | GetProfile.OutputSchema>(
undefined,
)
const [didFail, setFailed] = useState<boolean>(false)
useEffect(() => {
let aborted = false
// TODO use caching to reduce loads
store.api.app.bsky.getProfile({user: did}).then(
store.api.app.bsky.actor.getProfile({user: did}).then(
v => {
if (aborted) return
setProfile(v.data)