From ef84f3a25e9ff69000a2bc4f9f8caa7966dc3910 Mon Sep 17 00:00:00 2001
From: dan <dan.abramov@gmail.com>
Date: Thu, 25 Jan 2024 21:32:17 +0000
Subject: Dejank navigation between thread posts (#2625)

* Dejank parent thread spinner

* Fix bottom border/spinner jank

* Revert unnecessary change
---
 src/view/com/post-thread/PostThread.tsx | 61 +++++++++++++--------------------
 1 file changed, 23 insertions(+), 38 deletions(-)

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

diff --git a/src/view/com/post-thread/PostThread.tsx b/src/view/com/post-thread/PostThread.tsx
index 4d0aee494..cace5c38b 100644
--- a/src/view/com/post-thread/PostThread.tsx
+++ b/src/view/com/post-thread/PostThread.tsx
@@ -45,10 +45,9 @@ import {isAndroid, isNative} from '#/platform/detection'
 import {logger} from '#/logger'
 import {moderatePost_wrapped as moderatePost} from '#/lib/moderatePost_wrapped'
 
-const MAINTAIN_VISIBLE_CONTENT_POSITION = {minIndexForVisible: 2}
+const MAINTAIN_VISIBLE_CONTENT_POSITION = {minIndexForVisible: 1}
 
 const TOP_COMPONENT = {_reactKey: '__top_component__'}
-const PARENT_SPINNER = {_reactKey: '__parent_spinner__'}
 const REPLY_PROMPT = {_reactKey: '__reply__'}
 const DELETED = {_reactKey: '__deleted__'}
 const BLOCKED = {_reactKey: '__blocked__'}
@@ -59,11 +58,9 @@ const BOTTOM_COMPONENT = {_reactKey: '__bottom_component__'}
 type YieldedItem =
   | ThreadPost
   | typeof TOP_COMPONENT
-  | typeof PARENT_SPINNER
   | typeof REPLY_PROMPT
   | typeof DELETED
   | typeof BLOCKED
-  | typeof PARENT_SPINNER
 
 export function PostThread({
   uri,
@@ -152,7 +149,7 @@ function PostThreadLoaded({
   const {hasSession} = useSession()
   const {_} = useLingui()
   const pal = usePalette('default')
-  const {isTablet, isMobile, isDesktop, isTabletOrMobile} = useWebMediaQueries()
+  const {isMobile, isTabletOrMobile} = useWebMediaQueries()
   const ref = useRef<ListMethods>(null)
   const highlightedPostRef = useRef<View | null>(null)
   const needsScrollAdjustment = useRef<boolean>(
@@ -168,13 +165,11 @@ function PostThreadLoaded({
 
   // construct content
   const posts = React.useMemo(() => {
-    let arr = [TOP_COMPONENT].concat(
-      Array.from(
-        flattenThreadSkeleton(
-          sortThread(thread, threadViewPrefs),
-          hasSession,
-          treeView,
-        ),
+    let arr = Array.from(
+      flattenThreadSkeleton(
+        sortThread(thread, threadViewPrefs),
+        hasSession,
+        treeView,
       ),
     )
     if (arr.length > maxVisible) {
@@ -215,15 +210,9 @@ function PostThreadLoaded({
     // wait for loading to finish
     if (thread.type === 'post' && !!thread.parent) {
       function onMeasure(pageY: number) {
-        let spinnerHeight = 0
-        if (isDesktop) {
-          spinnerHeight = 40
-        } else if (isTabletOrMobile) {
-          spinnerHeight = 82
-        }
         ref.current?.scrollToOffset({
           animated: false,
-          offset: pageY - spinnerHeight,
+          offset: pageY,
         })
       }
       if (isNative) {
@@ -242,7 +231,7 @@ function PostThreadLoaded({
       }
       needsScrollAdjustment.current = false
     }
-  }, [thread, isDesktop, isTabletOrMobile])
+  }, [thread])
 
   const onPTR = React.useCallback(async () => {
     setIsPTRing(true)
@@ -257,17 +246,11 @@ function PostThreadLoaded({
   const renderItem = React.useCallback(
     ({item, index}: {item: YieldedItem; index: number}) => {
       if (item === TOP_COMPONENT) {
-        return isTablet ? (
+        return isTabletOrMobile ? (
           <ViewHeader
             title={_(msg({message: `Post`, context: 'description'}))}
           />
         ) : null
-      } else if (item === PARENT_SPINNER) {
-        return (
-          <View style={styles.parentSpinner}>
-            <ActivityIndicator />
-          </View>
-        )
       } else if (item === REPLY_PROMPT && hasSession) {
         return (
           <View>
@@ -318,7 +301,7 @@ function PostThreadLoaded({
             // @ts-ignore web-only
             style={{
               // Leave enough space below that the scroll doesn't jump
-              height: isNative ? 400 : '100vh',
+              height: isNative ? 600 : '100vh',
               borderTopWidth: 1,
               borderColor: pal.colors.border,
             }}
@@ -326,7 +309,7 @@ function PostThreadLoaded({
         )
       } else if (item === CHILD_SPINNER) {
         return (
-          <View style={styles.childSpinner}>
+          <View style={[pal.border, styles.childSpinner]}>
             <ActivityIndicator />
           </View>
         )
@@ -361,7 +344,7 @@ function PostThreadLoaded({
     },
     [
       hasSession,
-      isTablet,
+      isTabletOrMobile,
       isMobile,
       onPressReply,
       pal.border,
@@ -507,12 +490,15 @@ function* flattenThreadSkeleton(
   node: ThreadNode,
   hasSession: boolean,
   treeView: boolean,
+  isTraversingReplies: boolean = false,
 ): Generator<YieldedItem, void> {
   if (node.type === 'post') {
-    if (node.parent) {
-      yield* flattenThreadSkeleton(node.parent, hasSession, treeView)
-    } else if (node.ctx.isParentLoading) {
-      yield PARENT_SPINNER
+    if (!node.ctx.isParentLoading) {
+      if (node.parent) {
+        yield* flattenThreadSkeleton(node.parent, hasSession, treeView, false)
+      } else if (!isTraversingReplies) {
+        yield TOP_COMPONENT
+      }
     }
     if (!hasSession && node.ctx.depth > 0 && hasPwiOptOut(node)) {
       return
@@ -523,7 +509,7 @@ function* flattenThreadSkeleton(
     }
     if (node.replies?.length) {
       for (const reply of node.replies) {
-        yield* flattenThreadSkeleton(reply, hasSession, treeView)
+        yield* flattenThreadSkeleton(reply, hasSession, treeView, true)
         if (!treeView && !node.ctx.isHighlightedPost) {
           break
         }
@@ -567,10 +553,9 @@ const styles = StyleSheet.create({
     paddingHorizontal: 18,
     paddingVertical: 18,
   },
-  parentSpinner: {
-    paddingVertical: 10,
-  },
   childSpinner: {
+    borderTopWidth: 1,
+    paddingTop: 40,
     paddingBottom: 200,
   },
 })
-- 
cgit 1.4.1

