Simplify useRichText hook to use synchronous facet detection
Replace async detectFacets with synchronous detectFacetsWithoutResolution, eliminating the need for loading states, agent dependency, and complex effect-based resolution. This simplifies the hook from ~30 lines to ~6 lines and removes the duplicate local implementation from Profile.tsx.
This commit is contained in:
@@ -430,7 +430,7 @@ function Inner({
|
||||
() => moderateProfile(profile, moderationOpts),
|
||||
[profile, moderationOpts],
|
||||
)
|
||||
const [descriptionRT] = useRichText(profile.description ?? '')
|
||||
const descriptionRT = useRichText(profile.description ?? '')
|
||||
const profileShadow = useProfileShadow(profile)
|
||||
const {follow, unfollow} = useFollowMethods({
|
||||
profile: profileShadow,
|
||||
|
||||
@@ -1,34 +1,10 @@
|
||||
import React from 'react'
|
||||
import {useMemo} from 'react'
|
||||
import {RichText as RichTextAPI} from '@atproto/api'
|
||||
|
||||
import {useAgent} 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)
|
||||
const agent = useAgent()
|
||||
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(agent)
|
||||
if (!ignore) {
|
||||
setResolvedRT(resolvedRT)
|
||||
}
|
||||
}
|
||||
resolveRTFacets()
|
||||
return () => {
|
||||
ignore = true
|
||||
}
|
||||
}, [text, agent])
|
||||
const isResolving = resolvedRT === null
|
||||
return [resolvedRT ?? rawRT, isResolving]
|
||||
export function useRichText(text: string): RichTextAPI {
|
||||
return useMemo(() => {
|
||||
const rt = new RichTextAPI({text})
|
||||
rt.detectFacetsWithoutResolution()
|
||||
return rt
|
||||
}, [text])
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ function DialogInner({
|
||||
const playHaptic = useHaptics()
|
||||
const control = Dialog.useDialogContext()
|
||||
const reportDialogControl = useReportDialogControl()
|
||||
const [rt] = useRichText(info.description.text)
|
||||
const rt = useRichText(info.description.text)
|
||||
const {mutateAsync: likeFeed, isPending: isLikePending} = useLikeMutation()
|
||||
const {mutateAsync: unlikeFeed, isPending: isUnlikePending} =
|
||||
useUnlikeMutation()
|
||||
|
||||
@@ -125,7 +125,7 @@ function LandingScreenLoaded({
|
||||
const setActiveStarterPack = useSetActiveStarterPack()
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
const androidDialogControl = useDialogControl()
|
||||
const [descriptionRt] = useRichText(record.description || '')
|
||||
const descriptionRt = useRichText(record.description || '')
|
||||
|
||||
const [appClipOverlayVisible, setAppClipOverlayVisible] =
|
||||
React.useState(false)
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
type AppBskyActorDefs,
|
||||
moderateProfile,
|
||||
type ModerationOpts,
|
||||
RichText as RichTextAPI,
|
||||
} from '@atproto/api'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
@@ -32,7 +31,7 @@ import {useLabelerInfoQuery} from '#/state/queries/labeler'
|
||||
import {resetProfilePostsQueries} from '#/state/queries/post-feed'
|
||||
import {useProfileQuery} from '#/state/queries/profile'
|
||||
import {useResolveDidQuery} from '#/state/queries/resolve-uri'
|
||||
import {useAgent, useSession} from '#/state/session'
|
||||
import {useSession} from '#/state/session'
|
||||
import {useSetMinimalShellMode} from '#/state/shell'
|
||||
import {ProfileFeedgens} from '#/view/com/feeds/ProfileFeedgens'
|
||||
import {ProfileLists} from '#/view/com/lists/ProfileLists'
|
||||
@@ -44,6 +43,7 @@ import {ProfileHeader, ProfileHeaderLoading} from '#/screens/Profile/Header'
|
||||
import {ProfileFeedSection} from '#/screens/Profile/Sections/Feed'
|
||||
import {ProfileLabelsSection} from '#/screens/Profile/Sections/Labels'
|
||||
import {atoms as a} from '#/alf'
|
||||
import {useRichText} from '#/components/hooks/useRichText'
|
||||
import {Circle_And_Square_Stroke1_Corner0_Rounded_Filled as CircleAndSquareIcon} from '#/components/icons/CircleAndSquare'
|
||||
import {Heart2_Stroke1_Corner0_Rounded as HeartIcon} from '#/components/icons/Heart2'
|
||||
import {Image_Stroke1_Corner0_Rounded as ImageIcon} from '#/components/icons/Image'
|
||||
@@ -205,8 +205,8 @@ function ProfileScreenLoaded({
|
||||
|
||||
const description = profile.description ?? ''
|
||||
const hasDescription = description !== ''
|
||||
const [descriptionRT, isResolvingDescriptionRT] = useRichText(description)
|
||||
const showPlaceholder = isPlaceholderProfile || isResolvingDescriptionRT
|
||||
const descriptionRT = useRichText(description)
|
||||
const showPlaceholder = isPlaceholderProfile
|
||||
const moderation = useMemo(
|
||||
() => moderateProfile(profile, moderationOpts),
|
||||
[profile, moderationOpts],
|
||||
@@ -599,36 +599,6 @@ function ProfileScreenLoaded({
|
||||
)
|
||||
}
|
||||
|
||||
function useRichText(text: string): [RichTextAPI, boolean] {
|
||||
const agent = useAgent()
|
||||
const [prevText, setPrevText] = useState(text)
|
||||
const [rawRT, setRawRT] = useState(() => new RichTextAPI({text}))
|
||||
const [resolvedRT, setResolvedRT] = useState<RichTextAPI | null>(null)
|
||||
if (text !== prevText) {
|
||||
setPrevText(text)
|
||||
setRawRT(new RichTextAPI({text}))
|
||||
setResolvedRT(null)
|
||||
// This will queue an immediate re-render
|
||||
}
|
||||
useEffect(() => {
|
||||
let ignore = false
|
||||
async function resolveRTFacets() {
|
||||
// new each time
|
||||
const resolvedRT = new RichTextAPI({text})
|
||||
await resolvedRT.detectFacets(agent)
|
||||
if (!ignore) {
|
||||
setResolvedRT(resolvedRT)
|
||||
}
|
||||
}
|
||||
void resolveRTFacets()
|
||||
return () => {
|
||||
ignore = true
|
||||
}
|
||||
}, [text, agent])
|
||||
const isResolving = resolvedRT === null
|
||||
return [resolvedRT ?? rawRT, isResolving]
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flexDirection: 'column',
|
||||
|
||||
Reference in New Issue
Block a user