about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2022-09-28 15:03:16 -0500
committerPaul Frazee <pfrazee@gmail.com>2022-09-28 15:03:16 -0500
commita21a0d29884dfa5a21f15a8a3684c48ecdf90b40 (patch)
tree696fa2ca1fe8a68728540a71e4956b980e2d64a8
parent9f91edc1d1dce322c87eac20b6dd060bc9ccbcfb (diff)
downloadvoidsky-a21a0d29884dfa5a21f15a8a3684c48ecdf90b40.tar.zst
Improve thread rendering (show reply lines)
-rw-r--r--src/state/models/post-thread-view.ts21
-rw-r--r--src/state/models/session.ts1
-rw-r--r--src/view/com/post-thread/PostThreadItem.tsx59
-rw-r--r--src/view/index.ts2
4 files changed, 77 insertions, 6 deletions
diff --git a/src/state/models/post-thread-view.ts b/src/state/models/post-thread-view.ts
index fab0eb895..923562c5a 100644
--- a/src/state/models/post-thread-view.ts
+++ b/src/state/models/post-thread-view.ts
@@ -43,6 +43,9 @@ export class PostThreadViewPostModel implements GetPostThread.Post {
   indexedAt: string = ''
   myState = new PostThreadViewPostMyStateModel()
 
+  // added data
+  replyingToAuthor?: string
+
   constructor(
     public rootStore: RootStoreModel,
     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
-    if (v.parent) {
+    if (includeParent && v.parent) {
       // TODO: validate .record
       const parentModel = new PostThreadViewPostModel(
         this.rootStore,
@@ -69,12 +77,15 @@ export class PostThreadViewPostModel implements GetPostThread.Post {
       )
       parentModel._depth = this._depth - 1
       if (v.parent.parent) {
-        parentModel.assignTreeModels(keyGen, v.parent)
+        parentModel.assignTreeModels(keyGen, v.parent, true, false)
       }
       this.parent = parentModel
     }
+    if (v.parent?.author.name) {
+      this.replyingToAuthor = v.parent.author.name
+    }
     // replies
-    if (v.replies) {
+    if (includeChildren && v.replies) {
       const replies = []
       for (const item of v.replies) {
         // TODO: validate .record
@@ -85,7 +96,7 @@ export class PostThreadViewPostModel implements GetPostThread.Post {
         )
         itemModel._depth = this._depth + 1
         if (item.replies) {
-          itemModel.assignTreeModels(keyGen, item)
+          itemModel.assignTreeModels(keyGen, item, false, true)
         }
         replies.push(itemModel)
       }
diff --git a/src/state/models/session.ts b/src/state/models/session.ts
index 494aed5d4..ec3a7fc03 100644
--- a/src/state/models/session.ts
+++ b/src/state/models/session.ts
@@ -88,7 +88,6 @@ export class SessionModel {
   }
 
   clear() {
-    console.log('clear()')
     this.data = null
   }
 
diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx
index 8a2034cc6..daba54b5a 100644
--- a/src/view/com/post-thread/PostThreadItem.tsx
+++ b/src/view/com/post-thread/PostThreadItem.tsx
@@ -1,6 +1,7 @@
 import React, {useMemo} from 'react'
 import {observer} from 'mobx-react-lite'
 import {Image, StyleSheet, Text, TouchableOpacity, View} from 'react-native'
+import Svg, {Line, Circle} from 'react-native-svg'
 import {AdxUri} from '../../../third-party/uri'
 import * as PostType from '../../../third-party/api/src/types/todo/social/post'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
@@ -13,6 +14,8 @@ import {ago, pluralize} from '../../lib/strings'
 import {DEF_AVATER} from '../../lib/assets'
 import {useStores} from '../../../state'
 
+const PARENT_REPLY_LINE_LENGTH = 8
+
 export const PostThreadItem = observer(function PostThreadItem({
   item,
   onPressShare,
@@ -185,11 +188,56 @@ export const PostThreadItem = observer(function PostThreadItem({
   } else {
     return (
       <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}>
           <Link style={styles.layoutAvi} href={authorHref} title={authorTitle}>
             <Image style={styles.avi} source={DEF_AVATER} />
           </Link>
           <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}>
               <Link
                 style={styles.metaItem}
@@ -236,6 +284,17 @@ const styles = StyleSheet.create({
     margin: 2,
     marginBottom: 0,
   },
+  parentReplyLine: {
+    position: 'absolute',
+    left: 30,
+    top: -1 * PARENT_REPLY_LINE_LENGTH + 6,
+  },
+  childReplyLine: {
+    position: 'absolute',
+    left: 30,
+    top: 65,
+    bottom: 0,
+  },
   layout: {
     flexDirection: 'row',
   },
diff --git a/src/view/index.ts b/src/view/index.ts
index c7577436f..ee4ab8bc9 100644
--- a/src/view/index.ts
+++ b/src/view/index.ts
@@ -34,6 +34,7 @@ import {faPlus} from '@fortawesome/free-solid-svg-icons/faPlus'
 import {faShare} from '@fortawesome/free-solid-svg-icons/faShare'
 import {faShareFromSquare} from '@fortawesome/free-solid-svg-icons/faShareFromSquare'
 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 {faUser} from '@fortawesome/free-regular-svg-icons/faUser'
 import {faUsers} from '@fortawesome/free-solid-svg-icons/faUsers'
@@ -73,6 +74,7 @@ export function setup() {
     faMessage,
     faPenNib,
     faPlus,
+    faReply,
     faRetweet,
     faShare,
     faShareFromSquare,