From 1af8e83d536cf6a9db128409c8e00a0b44d9a985 Mon Sep 17 00:00:00 2001
From: Paul Frazee <pfrazee@gmail.com>
Date: Tue, 19 Sep 2023 19:08:11 -0700
Subject: Tree view threads experiment (#1480)

* Add tree-view experiment to threads

* Fix typo

* Remove extra minimalshellmode call

* Fix to parent line rendering

* Fix extra border

* Some ui cleanup
---
 src/view/com/post-thread/PostThreadItem.tsx | 141 ++++++++++++++++++++--------
 1 file changed, 103 insertions(+), 38 deletions(-)

(limited to 'src/view/com/post-thread/PostThreadItem.tsx')

diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx
index 37c7ece47..1089bfabf 100644
--- a/src/view/com/post-thread/PostThreadItem.tsx
+++ b/src/view/com/post-thread/PostThreadItem.tsx
@@ -35,15 +35,18 @@ import {formatCount} from '../util/numeric/format'
 import {TimeElapsed} from 'view/com/util/TimeElapsed'
 import {makeProfileLink} from 'lib/routes/links'
 import {isDesktopWeb} from 'platform/detection'
+import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 
 export const PostThreadItem = observer(function PostThreadItem({
   item,
   onPostReply,
   hasPrecedingItem,
+  treeView,
 }: {
   item: PostThreadItemModel
   onPostReply: () => void
   hasPrecedingItem: boolean
+  treeView: boolean
 }) {
   const pal = usePalette('default')
   const store = useStores()
@@ -389,25 +392,28 @@ export const PostThreadItem = observer(function PostThreadItem({
       </>
     )
   } else {
+    const isThreadedChild = treeView && item._depth > 0
     return (
-      <>
+      <PostOuterWrapper
+        item={item}
+        hasPrecedingItem={hasPrecedingItem}
+        treeView={treeView}>
         <PostHider
           testID={`postThreadItem-by-${item.post.author.handle}`}
           href={itemHref}
-          style={[
-            styles.outer,
-            pal.border,
-            pal.view,
-            item._showParentReplyLine && hasPrecedingItem && styles.noTopBorder,
-            styles.cursor,
-          ]}
+          style={[pal.view]}
           moderation={item.moderation.content}>
           <PostSandboxWarning />
 
           <View
-            style={{flexDirection: 'row', gap: 10, paddingLeft: 8, height: 16}}>
+            style={{
+              flexDirection: 'row',
+              gap: 10,
+              paddingLeft: 8,
+              height: isThreadedChild ? 8 : 16,
+            }}>
             <View style={{width: 52}}>
-              {item._showParentReplyLine && (
+              {!isThreadedChild && item._showParentReplyLine && (
                 <View
                   style={[
                     styles.replyLine,
@@ -431,7 +437,7 @@ export const PostThreadItem = observer(function PostThreadItem({
             ]}>
             <View style={styles.layoutAvi}>
               <PreviewableUserAvatar
-                size={52}
+                size={isThreadedChild ? 24 : 52}
                 did={item.post.author.did}
                 handle={item.post.author.handle}
                 avatar={item.post.author.avatar}
@@ -444,7 +450,9 @@ export const PostThreadItem = observer(function PostThreadItem({
                     styles.replyLine,
                     {
                       flexGrow: 1,
-                      backgroundColor: pal.colors.replyLine,
+                      backgroundColor: isThreadedChild
+                        ? pal.colors.border
+                        : pal.colors.replyLine,
                       marginTop: 4,
                     },
                   ]}
@@ -464,7 +472,11 @@ export const PostThreadItem = observer(function PostThreadItem({
                 style={styles.alert}
               />
               {item.richText?.text ? (
-                <View style={styles.postTextContainer}>
+                <View
+                  style={[
+                    styles.postTextContainer,
+                    isThreadedChild && {paddingTop: 2},
+                  ]}>
                   <RichText
                     type="post-text"
                     richText={item.richText}
@@ -508,30 +520,84 @@ export const PostThreadItem = observer(function PostThreadItem({
               />
             </View>
           </View>
+          {item._hasMore ? (
+            <Link
+              style={[
+                styles.loadMore,
+                {
+                  paddingLeft: treeView ? 44 : 70,
+                  paddingTop: 0,
+                  paddingBottom: treeView ? 4 : 12,
+                },
+              ]}
+              href={itemHref}
+              title={itemTitle}
+              noFeedback>
+              <Text type="sm-medium" style={pal.textLight}>
+                More
+              </Text>
+              <FontAwesomeIcon
+                icon="angle-right"
+                color={pal.colors.textLight}
+                size={14}
+              />
+            </Link>
+          ) : undefined}
         </PostHider>
-        {item._hasMore ? (
-          <Link
-            style={[
-              styles.loadMore,
-              {borderTopColor: pal.colors.border},
-              pal.view,
-            ]}
-            href={itemHref}
-            title={itemTitle}
-            noFeedback>
-            <Text style={pal.link}>Continue thread...</Text>
-            <FontAwesomeIcon
-              icon="angle-right"
-              style={pal.link as FontAwesomeIconStyle}
-              size={18}
-            />
-          </Link>
-        ) : undefined}
-      </>
+      </PostOuterWrapper>
     )
   }
 })
 
+function PostOuterWrapper({
+  item,
+  hasPrecedingItem,
+  treeView,
+  children,
+}: React.PropsWithChildren<{
+  item: PostThreadItemModel
+  hasPrecedingItem: boolean
+  treeView: boolean
+}>) {
+  const {isMobile} = useWebMediaQueries()
+  const pal = usePalette('default')
+  if (treeView && item._depth > 0) {
+    return (
+      <View
+        style={[
+          pal.view,
+          styles.cursor,
+          {flexDirection: 'row', paddingLeft: 10},
+        ]}>
+        {Array.from(Array(item._depth - 1)).map((_, n: number) => (
+          <View
+            key={`${item.uri}-padding-${n}`}
+            style={{
+              borderLeftWidth: 2,
+              borderLeftColor: pal.colors.border,
+              marginLeft: 19,
+              paddingLeft: isMobile ? 0 : 4,
+            }}
+          />
+        ))}
+        <View style={{flex: 1}}>{children}</View>
+      </View>
+    )
+  }
+  return (
+    <View
+      style={[
+        styles.outer,
+        pal.view,
+        pal.border,
+        item._showParentReplyLine && hasPrecedingItem && styles.noTopBorder,
+        styles.cursor,
+      ]}>
+      {children}
+    </View>
+  )
+}
+
 function ExpandedPostDetails({
   post,
   needsTranslation,
@@ -600,7 +666,7 @@ const styles = StyleSheet.create({
     flexDirection: 'row',
     alignItems: 'center',
     flexWrap: 'wrap',
-    paddingBottom: 8,
+    paddingBottom: 4,
     paddingRight: 10,
   },
   postTextLargeContainer: {
@@ -629,11 +695,10 @@ const styles = StyleSheet.create({
   },
   loadMore: {
     flexDirection: 'row',
-    justifyContent: 'space-between',
-    borderTopWidth: 1,
-    paddingLeft: 80,
-    paddingRight: 20,
-    paddingVertical: 12,
+    alignItems: 'center',
+    justifyContent: 'flex-start',
+    gap: 4,
+    paddingHorizontal: 20,
   },
   replyLine: {
     width: 2,
-- 
cgit 1.4.1

