Improve thread rendering (show reply lines)

zio/stable
Paul Frazee 2022-09-28 15:03:16 -05:00
parent 9f91edc1d1
commit a21a0d2988
4 changed files with 77 additions and 6 deletions

View File

@ -43,6 +43,9 @@ export class PostThreadViewPostModel implements GetPostThread.Post {
indexedAt: string = '' indexedAt: string = ''
myState = new PostThreadViewPostMyStateModel() myState = new PostThreadViewPostMyStateModel()
// added data
replyingToAuthor?: string
constructor( constructor(
public rootStore: RootStoreModel, public rootStore: RootStoreModel,
reactKey: string, reactKey: string,
@ -58,9 +61,14 @@ export class PostThreadViewPostModel implements GetPostThread.Post {
} }
} }
assignTreeModels(keyGen: Generator<string>, v: GetPostThread.Post) { assignTreeModels(
keyGen: Generator<string>,
v: GetPostThread.Post,
includeParent = true,
includeChildren = true,
) {
// parents // parents
if (v.parent) { if (includeParent && v.parent) {
// TODO: validate .record // TODO: validate .record
const parentModel = new PostThreadViewPostModel( const parentModel = new PostThreadViewPostModel(
this.rootStore, this.rootStore,
@ -69,12 +77,15 @@ export class PostThreadViewPostModel implements GetPostThread.Post {
) )
parentModel._depth = this._depth - 1 parentModel._depth = this._depth - 1
if (v.parent.parent) { if (v.parent.parent) {
parentModel.assignTreeModels(keyGen, v.parent) parentModel.assignTreeModels(keyGen, v.parent, true, false)
} }
this.parent = parentModel this.parent = parentModel
} }
if (v.parent?.author.name) {
this.replyingToAuthor = v.parent.author.name
}
// replies // replies
if (v.replies) { if (includeChildren && v.replies) {
const replies = [] const replies = []
for (const item of v.replies) { for (const item of v.replies) {
// TODO: validate .record // TODO: validate .record
@ -85,7 +96,7 @@ export class PostThreadViewPostModel implements GetPostThread.Post {
) )
itemModel._depth = this._depth + 1 itemModel._depth = this._depth + 1
if (item.replies) { if (item.replies) {
itemModel.assignTreeModels(keyGen, item) itemModel.assignTreeModels(keyGen, item, false, true)
} }
replies.push(itemModel) replies.push(itemModel)
} }

View File

@ -88,7 +88,6 @@ export class SessionModel {
} }
clear() { clear() {
console.log('clear()')
this.data = null this.data = null
} }

View File

@ -1,6 +1,7 @@
import React, {useMemo} from 'react' import React, {useMemo} from 'react'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import {Image, StyleSheet, Text, TouchableOpacity, View} from 'react-native' import {Image, StyleSheet, Text, TouchableOpacity, View} from 'react-native'
import Svg, {Line, Circle} from 'react-native-svg'
import {AdxUri} from '../../../third-party/uri' import {AdxUri} from '../../../third-party/uri'
import * as PostType from '../../../third-party/api/src/types/todo/social/post' import * as PostType from '../../../third-party/api/src/types/todo/social/post'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
@ -13,6 +14,8 @@ import {ago, pluralize} from '../../lib/strings'
import {DEF_AVATER} from '../../lib/assets' import {DEF_AVATER} from '../../lib/assets'
import {useStores} from '../../../state' import {useStores} from '../../../state'
const PARENT_REPLY_LINE_LENGTH = 8
export const PostThreadItem = observer(function PostThreadItem({ export const PostThreadItem = observer(function PostThreadItem({
item, item,
onPressShare, onPressShare,
@ -185,11 +188,56 @@ export const PostThreadItem = observer(function PostThreadItem({
} else { } else {
return ( return (
<Link style={styles.outer} href={itemHref} title={itemTitle}> <Link style={styles.outer} href={itemHref} title={itemTitle}>
{!!item.replyingToAuthor && (
<View style={styles.parentReplyLine}>
<Svg width="10" height={PARENT_REPLY_LINE_LENGTH}>
<Line
x1="5"
x2="5"
y1="0"
y2={PARENT_REPLY_LINE_LENGTH}
stroke={colors.gray2}
strokeWidth={2}
/>
</Svg>
</View>
)}
{item.replies?.length !== 0 && (
<View style={styles.childReplyLine}>
<Svg width="10" height={100}>
<Line
x1="5"
x2="5"
y1="0"
y2={100}
stroke={colors.gray2}
strokeWidth={2}
/>
</Svg>
</View>
)}
<View style={styles.layout}> <View style={styles.layout}>
<Link style={styles.layoutAvi} href={authorHref} title={authorTitle}> <Link style={styles.layoutAvi} href={authorHref} title={authorTitle}>
<Image style={styles.avi} source={DEF_AVATER} /> <Image style={styles.avi} source={DEF_AVATER} />
</Link> </Link>
<View style={styles.layoutContent}> <View style={styles.layoutContent}>
{item.replyingToAuthor &&
item.replyingToAuthor !== item.author.name && (
<View style={[s.flexRow, {alignItems: 'center'}]}>
<FontAwesomeIcon
icon="reply"
size={9}
style={[s.gray4, s.mr5]}
/>
<Link
href={`/profile/${item.replyingToAuthor}`}
title={`@${item.replyingToAuthor}`}>
<Text style={[s.f12, s.gray5]}>
@{item.replyingToAuthor}
</Text>
</Link>
</View>
)}
<View style={styles.meta}> <View style={styles.meta}>
<Link <Link
style={styles.metaItem} style={styles.metaItem}
@ -236,6 +284,17 @@ const styles = StyleSheet.create({
margin: 2, margin: 2,
marginBottom: 0, marginBottom: 0,
}, },
parentReplyLine: {
position: 'absolute',
left: 30,
top: -1 * PARENT_REPLY_LINE_LENGTH + 6,
},
childReplyLine: {
position: 'absolute',
left: 30,
top: 65,
bottom: 0,
},
layout: { layout: {
flexDirection: 'row', flexDirection: 'row',
}, },

View File

@ -34,6 +34,7 @@ import {faPlus} from '@fortawesome/free-solid-svg-icons/faPlus'
import {faShare} from '@fortawesome/free-solid-svg-icons/faShare' import {faShare} from '@fortawesome/free-solid-svg-icons/faShare'
import {faShareFromSquare} from '@fortawesome/free-solid-svg-icons/faShareFromSquare' import {faShareFromSquare} from '@fortawesome/free-solid-svg-icons/faShareFromSquare'
import {faShield} from '@fortawesome/free-solid-svg-icons/faShield' import {faShield} from '@fortawesome/free-solid-svg-icons/faShield'
import {faReply} from '@fortawesome/free-solid-svg-icons/faReply'
import {faRetweet} from '@fortawesome/free-solid-svg-icons/faRetweet' import {faRetweet} from '@fortawesome/free-solid-svg-icons/faRetweet'
import {faUser} from '@fortawesome/free-regular-svg-icons/faUser' import {faUser} from '@fortawesome/free-regular-svg-icons/faUser'
import {faUsers} from '@fortawesome/free-solid-svg-icons/faUsers' import {faUsers} from '@fortawesome/free-solid-svg-icons/faUsers'
@ -73,6 +74,7 @@ export function setup() {
faMessage, faMessage,
faPenNib, faPenNib,
faPlus, faPlus,
faReply,
faRetweet, faRetweet,
faShare, faShare,
faShareFromSquare, faShareFromSquare,