about summary refs log tree commit diff
path: root/src/components/hooks
diff options
context:
space:
mode:
authorEric Bailey <git@esb.lol>2024-04-12 17:01:32 -0500
committerGitHub <noreply@github.com>2024-04-12 17:01:32 -0500
commit1f61109cfa8307cbbceea604b1daec7486dd3393 (patch)
treedbbad83a4367555e1586f6c2d5b0450612600d44 /src/components/hooks
parentf91aa37c6bd900bdc4eec1095c9ecd83da2f13f2 (diff)
downloadvoidsky-1f61109cfa8307cbbceea604b1daec7486dd3393.tar.zst
Profile card hover preview (#3508)
* feat: initial user card hover

* feat: flesh it out some more

* fix: initialize middlewares once

* chore: remove floating-ui react-native

* chore: clean up

* Update moderation apis, fix lint

* Refactor profile hover card to alf

* Clean up

* Debounce, fix positioning when loading

* Fix going away

* Close on all link presses

* Tweak styles

* Disable on mobile web

* cleanup some of the changes pt. 1

* cleanup some of the changes pt. 2

* cleanup some of the changes pt. 3

* cleanup some of the changes pt. 4

* Re-revert files

* Fix handle presentation

* Don't follow yourself, silly

* Collapsed notifications group

* ProfileCard

* Tree view replies

* Suggested follows

* Fix hover-back-on-card edge case

* Moar

---------

Co-authored-by: Mary <git@mary.my.id>
Co-authored-by: Hailey <me@haileyok.com>
Diffstat (limited to 'src/components/hooks')
-rw-r--r--src/components/hooks/useFollowMethods.ts60
-rw-r--r--src/components/hooks/useRichText.ts33
2 files changed, 93 insertions, 0 deletions
diff --git a/src/components/hooks/useFollowMethods.ts b/src/components/hooks/useFollowMethods.ts
new file mode 100644
index 000000000..1e91a1f38
--- /dev/null
+++ b/src/components/hooks/useFollowMethods.ts
@@ -0,0 +1,60 @@
+import React from 'react'
+import {AppBskyActorDefs} from '@atproto/api'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+import {LogEvents} from '#/lib/statsig/statsig'
+import {logger} from '#/logger'
+import {Shadow} from '#/state/cache/types'
+import {useProfileFollowMutationQueue} from '#/state/queries/profile'
+import {useRequireAuth} from '#/state/session'
+import * as Toast from '#/view/com/util/Toast'
+
+export function useFollowMethods({
+  profile,
+  logContext,
+}: {
+  profile: Shadow<AppBskyActorDefs.ProfileViewBasic>
+  logContext: LogEvents['profile:follow']['logContext'] &
+    LogEvents['profile:unfollow']['logContext']
+}) {
+  const {_} = useLingui()
+  const requireAuth = useRequireAuth()
+  const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(
+    profile,
+    logContext,
+  )
+
+  const follow = React.useCallback(() => {
+    requireAuth(async () => {
+      try {
+        await queueFollow()
+      } catch (e: any) {
+        logger.error(`useFollowMethods: failed to follow`, {message: String(e)})
+        if (e?.name !== 'AbortError') {
+          Toast.show(_(msg`An issue occurred, please try again.`))
+        }
+      }
+    })
+  }, [_, queueFollow, requireAuth])
+
+  const unfollow = React.useCallback(() => {
+    requireAuth(async () => {
+      try {
+        await queueUnfollow()
+      } catch (e: any) {
+        logger.error(`useFollowMethods: failed to unfollow`, {
+          message: String(e),
+        })
+        if (e?.name !== 'AbortError') {
+          Toast.show(_(msg`An issue occurred, please try again.`))
+        }
+      }
+    })
+  }, [_, queueUnfollow, requireAuth])
+
+  return {
+    follow,
+    unfollow,
+  }
+}
diff --git a/src/components/hooks/useRichText.ts b/src/components/hooks/useRichText.ts
new file mode 100644
index 000000000..e363ae5a9
--- /dev/null
+++ b/src/components/hooks/useRichText.ts
@@ -0,0 +1,33 @@
+import React from 'react'
+import {RichText as RichTextAPI} from '@atproto/api'
+
+import {getAgent} from '#/state/session'
+
+export function useRichText(text: string): [RichTextAPI, boolean] {
+  const [prevText, setPrevText] = React.useState(text)
+  const [rawRT, setRawRT] = React.useState(() => new RichTextAPI({text}))
+  const [resolvedRT, setResolvedRT] = React.useState<RichTextAPI | null>(null)
+  if (text !== prevText) {
+    setPrevText(text)
+    setRawRT(new RichTextAPI({text}))
+    setResolvedRT(null)
+    // This will queue an immediate re-render
+  }
+  React.useEffect(() => {
+    let ignore = false
+    async function resolveRTFacets() {
+      // new each time
+      const resolvedRT = new RichTextAPI({text})
+      await resolvedRT.detectFacets(getAgent())
+      if (!ignore) {
+        setResolvedRT(resolvedRT)
+      }
+    }
+    resolveRTFacets()
+    return () => {
+      ignore = true
+    }
+  }, [text])
+  const isResolving = resolvedRT === null
+  return [resolvedRT ?? rawRT, isResolving]
+}