about summary refs log tree commit diff
path: root/src/view/com/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/util')
-rw-r--r--src/view/com/util/Link.tsx7
-rw-r--r--src/view/com/util/PostMeta.tsx17
-rw-r--r--src/view/com/util/TimeElapsed.tsx5
-rw-r--r--src/view/com/util/UserAvatar.tsx32
-rw-r--r--src/view/com/util/post-embeds/QuoteEmbed.tsx6
5 files changed, 46 insertions, 21 deletions
diff --git a/src/view/com/util/Link.tsx b/src/view/com/util/Link.tsx
index d35d0fcc6..78d995ee8 100644
--- a/src/view/com/util/Link.tsx
+++ b/src/view/com/util/Link.tsx
@@ -148,6 +148,7 @@ export const TextLink = memo(function TextLink({
   dataSet,
   title,
   onPress,
+  onBeforePress,
   disableMismatchWarning,
   navigationAction,
   anchorNoUnderline,
@@ -165,6 +166,7 @@ export const TextLink = memo(function TextLink({
   disableMismatchWarning?: boolean
   navigationAction?: 'push' | 'replace' | 'navigate'
   anchorNoUnderline?: boolean
+  onBeforePress?: () => void
 } & TextProps) {
   const {...props} = useLinkProps({to: sanitizeUrl(href)})
   const navigation = useNavigationDeduped()
@@ -202,6 +204,7 @@ export const TextLink = memo(function TextLink({
         // Let the browser handle opening in new tab etc.
         return
       }
+      onBeforePress?.()
       if (onPress) {
         e?.preventDefault?.()
         // @ts-ignore function signature differs by platform -prf
@@ -226,6 +229,7 @@ export const TextLink = memo(function TextLink({
       disableMismatchWarning,
       navigationAction,
       openLink,
+      onBeforePress,
     ],
   )
   const hrefAttrs = useMemo(() => {
@@ -274,6 +278,7 @@ interface TextLinkOnWebOnlyProps extends TextProps {
   title?: string
   navigationAction?: 'push' | 'replace' | 'navigate'
   disableMismatchWarning?: boolean
+  onBeforePress?: () => void
   onPointerEnter?: () => void
   anchorNoUnderline?: boolean
 }
@@ -287,6 +292,7 @@ export const TextLinkOnWebOnly = memo(function DesktopWebTextLink({
   lineHeight,
   navigationAction,
   disableMismatchWarning,
+  onBeforePress,
   ...props
 }: TextLinkOnWebOnlyProps) {
   if (isWeb) {
@@ -302,6 +308,7 @@ export const TextLinkOnWebOnly = memo(function DesktopWebTextLink({
         title={props.title}
         navigationAction={navigationAction}
         disableMismatchWarning={disableMismatchWarning}
+        onBeforePress={onBeforePress}
         {...props}
       />
     )
diff --git a/src/view/com/util/PostMeta.tsx b/src/view/com/util/PostMeta.tsx
index ed3d3e5b0..db16ff066 100644
--- a/src/view/com/util/PostMeta.tsx
+++ b/src/view/com/util/PostMeta.tsx
@@ -1,8 +1,9 @@
-import React, {memo} from 'react'
+import React, {memo, useCallback} from 'react'
 import {StyleProp, StyleSheet, TextStyle, View, ViewStyle} from 'react-native'
 import {AppBskyActorDefs, ModerationDecision, ModerationUI} from '@atproto/api'
+import {useQueryClient} from '@tanstack/react-query'
 
-import {usePrefetchProfileQuery} from '#/state/queries/profile'
+import {precacheProfile, usePrefetchProfileQuery} from '#/state/queries/profile'
 import {usePalette} from 'lib/hooks/usePalette'
 import {makeProfileLink} from 'lib/routes/links'
 import {sanitizeDisplayName} from 'lib/strings/display-names'
@@ -40,15 +41,18 @@ let PostMeta = (opts: PostMetaOpts): React.ReactNode => {
     ? () => prefetchProfileQuery(opts.author.did)
     : undefined
 
+  const queryClient = useQueryClient()
+  const onBeforePress = useCallback(() => {
+    precacheProfile(queryClient, opts.author)
+  }, [queryClient, opts.author])
+
   return (
     <View style={[styles.container, opts.style]}>
       {opts.showAvatar && (
         <View style={styles.avatar}>
           <PreviewableUserAvatar
             size={opts.avatarSize || 16}
-            did={opts.author.did}
-            handle={opts.author.handle}
-            avatar={opts.author.avatar}
+            profile={opts.author}
             moderation={opts.avatarModeration}
             type={opts.author.associated?.labeler ? 'labeler' : 'user'}
           />
@@ -71,6 +75,7 @@ let PostMeta = (opts: PostMetaOpts): React.ReactNode => {
             </>
           }
           href={profileLink}
+          onBeforePress={onBeforePress}
           onPointerEnter={onPointerEnter}
         />
         <TextLinkOnWebOnly
@@ -79,6 +84,7 @@ let PostMeta = (opts: PostMetaOpts): React.ReactNode => {
           style={[pal.textLight, {flexShrink: 4}]}
           text={'\xa0' + sanitizeHandle(handle, '@')}
           href={profileLink}
+          onBeforePress={onBeforePress}
           onPointerEnter={onPointerEnter}
           anchorNoUnderline
         />
@@ -103,6 +109,7 @@ let PostMeta = (opts: PostMetaOpts): React.ReactNode => {
             title={niceDate(opts.timestamp)}
             accessibilityHint=""
             href={opts.postHref}
+            onBeforePress={onBeforePress}
           />
         )}
       </TimeElapsed>
diff --git a/src/view/com/util/TimeElapsed.tsx b/src/view/com/util/TimeElapsed.tsx
index aa3a09223..6ea41b82b 100644
--- a/src/view/com/util/TimeElapsed.tsx
+++ b/src/view/com/util/TimeElapsed.tsx
@@ -1,6 +1,7 @@
 import React from 'react'
-import {ago} from 'lib/strings/time'
+
 import {useTickEveryMinute} from '#/state/shell'
+import {ago} from 'lib/strings/time'
 
 // FIXME(dan): Figure out why the false positives
 
@@ -12,7 +13,7 @@ export function TimeElapsed({
   children: ({timeElapsed}: {timeElapsed: string}) => JSX.Element
 }) {
   const tick = useTickEveryMinute()
-  const [timeElapsed, setTimeAgo] = React.useState(ago(timestamp))
+  const [timeElapsed, setTimeAgo] = React.useState(() => ago(timestamp))
 
   React.useEffect(() => {
     setTimeAgo(ago(timestamp))
diff --git a/src/view/com/util/UserAvatar.tsx b/src/view/com/util/UserAvatar.tsx
index 89aa56b73..118e2ce2b 100644
--- a/src/view/com/util/UserAvatar.tsx
+++ b/src/view/com/util/UserAvatar.tsx
@@ -2,10 +2,11 @@ import React, {memo, useMemo} from 'react'
 import {Image, StyleSheet, TouchableOpacity, View} from 'react-native'
 import {Image as RNImage} from 'react-native-image-crop-picker'
 import Svg, {Circle, Path, Rect} from 'react-native-svg'
-import {ModerationUI} from '@atproto/api'
+import {AppBskyActorDefs, ModerationUI} from '@atproto/api'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {msg, Trans} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
+import {useQueryClient} from '@tanstack/react-query'
 
 import {usePalette} from 'lib/hooks/usePalette'
 import {
@@ -15,6 +16,7 @@ import {
 import {makeProfileLink} from 'lib/routes/links'
 import {colors} from 'lib/styles'
 import {isAndroid, isNative, isWeb} from 'platform/detection'
+import {precacheProfile} from 'state/queries/profile'
 import {HighPriorityImage} from 'view/com/util/images/Image'
 import {tokens, useTheme} from '#/alf'
 import {
@@ -47,8 +49,7 @@ interface EditableUserAvatarProps extends BaseUserAvatarProps {
 
 interface PreviewableUserAvatarProps extends BaseUserAvatarProps {
   moderation?: ModerationUI
-  did: string
-  handle: string
+  profile: AppBskyActorDefs.ProfileViewBasic
 }
 
 const BLUR_AMOUNT = isWeb ? 5 : 100
@@ -371,19 +372,28 @@ let EditableUserAvatar = ({
 EditableUserAvatar = memo(EditableUserAvatar)
 export {EditableUserAvatar}
 
-let PreviewableUserAvatar = (
-  props: PreviewableUserAvatarProps,
-): React.ReactNode => {
+let PreviewableUserAvatar = ({
+  moderation,
+  profile,
+  ...rest
+}: PreviewableUserAvatarProps): React.ReactNode => {
   const {_} = useLingui()
+  const queryClient = useQueryClient()
+
+  const onPress = React.useCallback(() => {
+    precacheProfile(queryClient, profile)
+  }, [profile, queryClient])
+
   return (
-    <ProfileHoverCard did={props.did}>
+    <ProfileHoverCard did={profile.did}>
       <Link
         label={_(msg`See profile`)}
         to={makeProfileLink({
-          did: props.did,
-          handle: props.handle,
-        })}>
-        <UserAvatar {...props} />
+          did: profile.did,
+          handle: profile.handle,
+        })}
+        onPress={onPress}>
+        <UserAvatar avatar={profile.avatar} moderation={moderation} {...rest} />
       </Link>
     </ProfileHoverCard>
   )
diff --git a/src/view/com/util/post-embeds/QuoteEmbed.tsx b/src/view/com/util/post-embeds/QuoteEmbed.tsx
index 935696ab7..e0178f34b 100644
--- a/src/view/com/util/post-embeds/QuoteEmbed.tsx
+++ b/src/view/com/util/post-embeds/QuoteEmbed.tsx
@@ -26,10 +26,10 @@ import {useQueryClient} from '@tanstack/react-query'
 import {HITSLOP_20} from '#/lib/constants'
 import {s} from '#/lib/styles'
 import {useModerationOpts} from '#/state/queries/preferences'
-import {RQKEY as RQKEY_URI} from '#/state/queries/resolve-uri'
 import {usePalette} from 'lib/hooks/usePalette'
 import {InfoCircleIcon} from 'lib/icons'
 import {makeProfileLink} from 'lib/routes/links'
+import {precacheProfile} from 'state/queries/profile'
 import {ComposerOptsQuote} from 'state/shell/composer'
 import {atoms as a} from '#/alf'
 import {RichText} from '#/components/RichText'
@@ -149,8 +149,8 @@ export function QuoteEmbed({
   }, [quote.embeds])
 
   const onBeforePress = React.useCallback(() => {
-    queryClient.setQueryData(RQKEY_URI(quote.author.handle), quote.author.did)
-  }, [queryClient, quote.author.did, quote.author.handle])
+    precacheProfile(queryClient, quote.author)
+  }, [queryClient, quote.author])
 
   return (
     <ContentHider modui={moderation?.ui('contentList')}>