Add the ability to navigate to posts within a thread
parent
139c9deb75
commit
28dbc5f5e6
|
@ -15,7 +15,7 @@
|
|||
"dependencies": {
|
||||
"@adxp/auth": "*",
|
||||
"@adxp/common": "*",
|
||||
"@adxp/mock-api": "git+ssh://git@github.com:bluesky-social/adx-mock-api.git#3714722a09503caad6e3aba7f9e9027994d07bdb",
|
||||
"@adxp/mock-api": "git+ssh://git@github.com:bluesky-social/adx-mock-api.git#464712517e8f42b307622aa625bf2b2e11ad763e",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.1.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.1.1",
|
||||
|
|
|
@ -24,6 +24,7 @@ export class PostThreadViewPostModel implements bsky.PostThreadView.Post {
|
|||
| bsky.PostThreadView.RecordEmbed
|
||||
| bsky.PostThreadView.ExternalEmbed
|
||||
| bsky.PostThreadView.UnknownEmbed
|
||||
parent?: PostThreadViewPostModel
|
||||
replyCount: number = 0
|
||||
replies?: PostThreadViewPostModel[]
|
||||
repostCount: number = 0
|
||||
|
@ -34,11 +35,25 @@ export class PostThreadViewPostModel implements bsky.PostThreadView.Post {
|
|||
makeAutoObservable(this)
|
||||
this._reactKey = reactKey
|
||||
if (v) {
|
||||
Object.assign(this, _omit(v, 'replies')) // copy everything but the replies
|
||||
Object.assign(this, _omit(v, 'parent', 'replies')) // copy everything but the replies and the parent
|
||||
}
|
||||
}
|
||||
|
||||
setReplies(keyGen: Generator<string>, v: bsky.PostThreadView.Post) {
|
||||
assignTreeModels(keyGen: Generator<string>, v: bsky.PostThreadView.Post) {
|
||||
// parents
|
||||
if (v.parent) {
|
||||
// TODO: validate .record
|
||||
const parentModel = new PostThreadViewPostModel(
|
||||
keyGen.next().value,
|
||||
v.parent,
|
||||
)
|
||||
parentModel._depth = this._depth - 1
|
||||
if (v.parent.parent) {
|
||||
parentModel.assignTreeModels(keyGen, v.parent)
|
||||
}
|
||||
this.parent = parentModel
|
||||
}
|
||||
// replies
|
||||
if (v.replies) {
|
||||
const replies = []
|
||||
for (const item of v.replies) {
|
||||
|
@ -46,7 +61,7 @@ export class PostThreadViewPostModel implements bsky.PostThreadView.Post {
|
|||
const itemModel = new PostThreadViewPostModel(keyGen.next().value, item)
|
||||
itemModel._depth = this._depth + 1
|
||||
if (item.replies) {
|
||||
itemModel.setReplies(keyGen, item)
|
||||
itemModel.assignTreeModels(keyGen, item)
|
||||
}
|
||||
replies.push(itemModel)
|
||||
}
|
||||
|
@ -161,7 +176,7 @@ export class PostThreadViewModel implements bsky.PostThreadView.Response {
|
|||
const keyGen = reactKeyGenerator()
|
||||
const thread = new PostThreadViewPostModel(keyGen.next().value, res.thread)
|
||||
thread._isHighlightedPost = true
|
||||
thread.setReplies(keyGen, res.thread)
|
||||
thread.assignTreeModels(keyGen, res.thread)
|
||||
this.thread = thread
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,9 @@ export const PostThread = observer(function PostThread({
|
|||
function* flattenThread(
|
||||
post: PostThreadViewPostModel,
|
||||
): Generator<PostThreadViewPostModel, void> {
|
||||
if (post.parent) {
|
||||
yield* flattenThread(post.parent)
|
||||
}
|
||||
yield post
|
||||
if (post.replies?.length) {
|
||||
for (const reply of post.replies) {
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {bsky} from '@adxp/mock-api'
|
||||
import {bsky, AdxUri} from '@adxp/mock-api'
|
||||
import moment from 'moment'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import {OnNavigateContent} from '../../routes/types'
|
||||
|
@ -31,7 +31,8 @@ function iter<T>(n: number, fn: (i: number) => T): Array<T> {
|
|||
}
|
||||
|
||||
export const PostThreadItem = observer(function PostThreadItem({
|
||||
item, // onNavigateContent,
|
||||
item,
|
||||
onNavigateContent,
|
||||
}: {
|
||||
item: PostThreadViewPostModel
|
||||
onNavigateContent: OnNavigateContent
|
||||
|
@ -39,12 +40,16 @@ export const PostThreadItem = observer(function PostThreadItem({
|
|||
const record = item.record as unknown as bsky.Post.Record
|
||||
const hasEngagement = item.likeCount || item.repostCount
|
||||
const onPressOuter = () => {
|
||||
// TODO onNavigateContent
|
||||
const urip = new AdxUri(item.uri)
|
||||
onNavigateContent('PostThread', {
|
||||
name: item.author.name,
|
||||
recordKey: urip.recordKey,
|
||||
})
|
||||
}
|
||||
return (
|
||||
<TouchableOpacity style={styles.outer} onPress={onPressOuter}>
|
||||
<View style={styles.layout}>
|
||||
{iter(item._depth, () => (
|
||||
{iter(Math.abs(item._depth), () => (
|
||||
<View style={styles.replyBar} />
|
||||
))}
|
||||
<View style={styles.layoutAvi}>
|
||||
|
@ -143,7 +148,7 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
replyBar: {
|
||||
width: 5,
|
||||
backgroundColor: '#d4f0ff',
|
||||
backgroundColor: 'gray',
|
||||
marginRight: 2,
|
||||
},
|
||||
layoutAvi: {
|
||||
|
|
|
@ -54,20 +54,24 @@ const tabBarScreenOptions = ({
|
|||
route: RouteProp<ParamListBase, string>
|
||||
}) => ({
|
||||
headerShown: false,
|
||||
tabBarIcon: (_state: {focused: boolean; color: string; size: number}) => {
|
||||
tabBarIcon: (state: {focused: boolean; color: string; size: number}) => {
|
||||
switch (route.name) {
|
||||
case 'Home':
|
||||
return <FontAwesomeIcon icon="house" />
|
||||
return <FontAwesomeIcon icon="house" style={{color: state.color}} />
|
||||
case 'Search':
|
||||
return <FontAwesomeIcon icon="magnifying-glass" />
|
||||
return (
|
||||
<FontAwesomeIcon
|
||||
icon="magnifying-glass"
|
||||
style={{color: state.color}}
|
||||
/>
|
||||
)
|
||||
case 'Notifications':
|
||||
return <FontAwesomeIcon icon="bell" />
|
||||
return <FontAwesomeIcon icon="bell" style={{color: state.color}} />
|
||||
case 'Menu':
|
||||
return <FontAwesomeIcon icon="bars" />
|
||||
return <FontAwesomeIcon icon="bars" style={{color: state.color}} />
|
||||
default:
|
||||
return <FontAwesomeIcon icon="bars" />
|
||||
return <FontAwesomeIcon icon="bars" style={{color: state.color}} />
|
||||
}
|
||||
// return <Text>{route.name?.[0] || ''}</Text>
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ Paul's todo list
|
|||
- Thread view
|
||||
- Mock API support fetch on thread that's not root
|
||||
- Header (back btn, highlight)
|
||||
- Navigate on post press
|
||||
- View likes list
|
||||
- View reposts list
|
||||
- Reply control
|
||||
|
|
|
@ -55,9 +55,9 @@
|
|||
ucans "0.9.0-alpha3"
|
||||
uint8arrays "^3.0.0"
|
||||
|
||||
"@adxp/mock-api@git+ssh://git@github.com:bluesky-social/adx-mock-api.git#3714722a09503caad6e3aba7f9e9027994d07bdb":
|
||||
"@adxp/mock-api@git+ssh://git@github.com:bluesky-social/adx-mock-api.git#464712517e8f42b307622aa625bf2b2e11ad763e":
|
||||
version "0.0.1"
|
||||
resolved "git+ssh://git@github.com:bluesky-social/adx-mock-api.git#3714722a09503caad6e3aba7f9e9027994d07bdb"
|
||||
resolved "git+ssh://git@github.com:bluesky-social/adx-mock-api.git#464712517e8f42b307622aa625bf2b2e11ad763e"
|
||||
dependencies:
|
||||
ajv "^8.11.0"
|
||||
ajv-formats "^2.1.1"
|
||||
|
|
Loading…
Reference in New Issue