From d36b91fe67225a9d3c79c8eeb3c80f6a72e9f73f Mon Sep 17 00:00:00 2001
From: dan <dan.abramov@gmail.com>
Date: Fri, 9 Feb 2024 05:00:50 +0000
Subject: Fix flashes and jumps when opening profile (#2815)

* Don't reset the tree when profile loads fully

* Give avatars a background color like placeholders

* Prevent jumps due to rich text resolving

* Rm log

* Rm unused
---
 src/view/com/profile/ProfileHeader.tsx | 123 ++++++++-------------------------
 1 file changed, 27 insertions(+), 96 deletions(-)

(limited to 'src/view/com/profile/ProfileHeader.tsx')

diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx
index 2e80ca808..8fd50fad6 100644
--- a/src/view/com/profile/ProfileHeader.tsx
+++ b/src/view/com/profile/ProfileHeader.tsx
@@ -51,76 +51,47 @@ import {sanitizeDisplayName} from 'lib/strings/display-names'
 import {shareUrl} from 'lib/sharing'
 import {s, colors} from 'lib/styles'
 import {logger} from '#/logger'
-import {useSession, getAgent} from '#/state/session'
+import {useSession} from '#/state/session'
 import {Shadow} from '#/state/cache/types'
 import {useRequireAuth} from '#/state/session'
 import {LabelInfo} from '../util/moderation/LabelInfo'
 import {useProfileShadow} from 'state/cache/profile-shadow'
 
-interface Props {
-  profile: AppBskyActorDefs.ProfileView | null
-  placeholderData?: AppBskyActorDefs.ProfileView | null
-  moderationOpts: ModerationOpts | null
-  hideBackButton?: boolean
-  isProfilePreview?: boolean
-}
-
-export function ProfileHeader({
-  profile,
-  moderationOpts,
-  hideBackButton = false,
-  isProfilePreview,
-}: Props) {
+let ProfileHeaderLoading = (_props: {}): React.ReactNode => {
   const pal = usePalette('default')
-
-  // loading
-  // =
-  if (!profile || !moderationOpts) {
-    return (
-      <View style={pal.view}>
-        <LoadingPlaceholder
-          width="100%"
-          height={150}
-          style={{borderRadius: 0}}
-        />
-        <View
-          style={[pal.view, {borderColor: pal.colors.background}, styles.avi]}>
-          <LoadingPlaceholder width={80} height={80} style={styles.br40} />
-        </View>
-        <View style={styles.content}>
-          <View style={[styles.buttonsLine]}>
-            <LoadingPlaceholder width={167} height={31} style={styles.br50} />
-          </View>
+  return (
+    <View style={pal.view}>
+      <LoadingPlaceholder width="100%" height={150} style={{borderRadius: 0}} />
+      <View
+        style={[pal.view, {borderColor: pal.colors.background}, styles.avi]}>
+        <LoadingPlaceholder width={80} height={80} style={styles.br40} />
+      </View>
+      <View style={styles.content}>
+        <View style={[styles.buttonsLine]}>
+          <LoadingPlaceholder width={167} height={31} style={styles.br50} />
         </View>
       </View>
-    )
-  }
-
-  // loaded
-  // =
-  return (
-    <ProfileHeaderLoaded
-      profile={profile}
-      moderationOpts={moderationOpts}
-      hideBackButton={hideBackButton}
-      isProfilePreview={isProfilePreview}
-    />
+    </View>
   )
 }
+ProfileHeaderLoading = memo(ProfileHeaderLoading)
+export {ProfileHeaderLoading}
 
-interface LoadedProps {
+interface Props {
   profile: AppBskyActorDefs.ProfileViewDetailed
+  descriptionRT: RichTextAPI | null
   moderationOpts: ModerationOpts
   hideBackButton?: boolean
-  isProfilePreview?: boolean
+  isPlaceholderProfile?: boolean
 }
 
-let ProfileHeaderLoaded = ({
+let ProfileHeader = ({
   profile: profileUnshadowed,
+  descriptionRT,
   moderationOpts,
   hideBackButton = false,
-  isProfilePreview,
-}: LoadedProps): React.ReactNode => {
+  isPlaceholderProfile,
+}: Props): React.ReactNode => {
   const profile: Shadow<AppBskyActorDefs.ProfileViewDetailed> =
     useProfileShadow(profileUnshadowed)
   const pal = usePalette('default')
@@ -144,37 +115,6 @@ let ProfileHeaderLoaded = ({
     [profile, moderationOpts],
   )
 
-  /*
-   * BEGIN handle bio facet resolution
-   */
-  // should be undefined on first render to trigger a resolution
-  const prevProfileDescription = React.useRef<string | undefined>()
-  const [descriptionRT, setDescriptionRT] = React.useState<
-    RichTextAPI | undefined
-  >(
-    profile.description
-      ? new RichTextAPI({text: profile.description})
-      : undefined,
-  )
-  React.useEffect(() => {
-    async function resolveRTFacets() {
-      // new each time
-      const rt = new RichTextAPI({text: profile.description || ''})
-      await rt.detectFacets(getAgent())
-      // replace existing RT instance
-      setDescriptionRT(rt)
-    }
-
-    if (profile.description !== prevProfileDescription.current) {
-      // update prev immediately
-      prevProfileDescription.current = profile.description
-      resolveRTFacets()
-    }
-  }, [profile.description, setDescriptionRT])
-  /*
-   * END handle bio facet resolution
-   */
-
   const invalidateProfileQuery = React.useCallback(() => {
     queryClient.invalidateQueries({
       queryKey: profileQueryKey(profile.did),
@@ -454,14 +394,9 @@ let ProfileHeaderLoaded = ({
   const pluralizedFollowers = pluralize(profile.followersCount || 0, 'follower')
 
   return (
-    <View
-      style={[
-        pal.view,
-        isProfilePreview && isDesktop && styles.loadingBorderStyle,
-      ]}
-      pointerEvents="box-none">
+    <View style={[pal.view]} pointerEvents="box-none">
       <View pointerEvents="none">
-        {isProfilePreview ? (
+        {isPlaceholderProfile ? (
           <LoadingPlaceholder
             width="100%"
             height={150}
@@ -622,7 +557,7 @@ let ProfileHeaderLoaded = ({
             {invalidHandle ? _(msg`⚠Invalid Handle`) : `@${profile.handle}`}
           </ThemedText>
         </View>
-        {!isProfilePreview && !blockHide && (
+        {!isPlaceholderProfile && !blockHide && (
           <>
             <View style={styles.metricsLine} pointerEvents="box-none">
               <Link
@@ -737,7 +672,8 @@ let ProfileHeaderLoaded = ({
     </View>
   )
 }
-ProfileHeaderLoaded = memo(ProfileHeaderLoaded)
+ProfileHeader = memo(ProfileHeader)
+export {ProfileHeader}
 
 const styles = StyleSheet.create({
   banner: {
@@ -845,9 +781,4 @@ const styles = StyleSheet.create({
 
   br40: {borderRadius: 40},
   br50: {borderRadius: 50},
-
-  loadingBorderStyle: {
-    borderLeftWidth: 1,
-    borderRightWidth: 1,
-  },
 })
-- 
cgit 1.4.1

