diff options
author | Eric Bailey <git@esb.lol> | 2025-06-11 13:22:02 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-11 13:22:02 -0500 |
commit | 143d5f3b814f1ce707fdfc87dabff7af5349bd06 (patch) | |
tree | 86cd639d45da0c994f8bf1d9160b1a8497f53e0c /src/state | |
parent | 7341294df6156afdf24ab43e1e27ebba94f265ad (diff) | |
download | voidsky-143d5f3b814f1ce707fdfc87dabff7af5349bd06.tar.zst |
Post source handling updates (#8472)
* Add debugs * Key post-source using URI with handle * Enhance * EnHANCE * ENHANCE * ENHANCEEEECEE * ᵉⁿʰᵃⁿᶜᵉ * enhance
Diffstat (limited to 'src/state')
-rw-r--r-- | src/state/feed-feedback.tsx | 8 | ||||
-rw-r--r-- | src/state/unstable-post-source.tsx | 115 |
2 files changed, 82 insertions, 41 deletions
diff --git a/src/state/feed-feedback.tsx b/src/state/feed-feedback.tsx index 225b495d3..a718a761d 100644 --- a/src/state/feed-feedback.tsx +++ b/src/state/feed-feedback.tsx @@ -12,7 +12,7 @@ import throttle from 'lodash.throttle' import {FEEDBACK_FEEDS, STAGING_FEEDS} from '#/lib/constants' import {logEvent} from '#/lib/statsig/statsig' -import {logger} from '#/logger' +import {Logger} from '#/logger' import { type FeedDescriptor, type FeedPostSliceItem, @@ -20,6 +20,8 @@ import { import {getItemsForFeedback} from '#/view/com/posts/PostFeed' import {useAgent} from './session' +const logger = Logger.create(Logger.Context.FeedFeedback) + export type StateContext = { enabled: boolean onItemSeen: (item: any) => void @@ -89,6 +91,7 @@ export function useFeedFeedback( } sendOrAggregateInteractionsForStats(aggregatedStats.current, interactions) throttledFlushAggregatedStats() + logger.debug('flushed') }, [agent, throttledFlushAggregatedStats, feed]) const sendToFeed = useMemo( @@ -141,6 +144,9 @@ export function useFeedFeedback( if (!enabled) { return } + logger.debug('sendInteraction', { + ...interaction, + }) if (!history.current.has(interaction)) { history.current.add(interaction) queue.current.add(toString(interaction)) diff --git a/src/state/unstable-post-source.tsx b/src/state/unstable-post-source.tsx index 43aac6f4d..ac126d79c 100644 --- a/src/state/unstable-post-source.tsx +++ b/src/state/unstable-post-source.tsx @@ -1,62 +1,97 @@ -import {createContext, useCallback, useContext, useRef, useState} from 'react' -import {type AppBskyFeedDefs} from '@atproto/api' +import {useEffect, useId, useState} from 'react' +import {type AppBskyFeedDefs, AtUri} from '@atproto/api' -import {type FeedDescriptor} from './queries/post-feed' +import {Logger} from '#/logger' +import {type FeedDescriptor} from '#/state/queries/post-feed' /** - * For passing the source of the post (i.e. the original post, from the feed) to the threadview, - * without using query params. Deliberately unstable to avoid using query params, use for FeedFeedback - * and other ephemeral non-critical systems. + * Separate logger for better debugging */ +const logger = Logger.create(Logger.Context.PostSource) -type Source = { +export type PostSource = { post: AppBskyFeedDefs.FeedViewPost feed?: FeedDescriptor } -const SetUnstablePostSourceContext = createContext< - (key: string, source: Source) => void ->(() => {}) -const ConsumeUnstablePostSourceContext = createContext< - (uri: string) => Source | undefined ->(() => undefined) +/** + * A cache of sources that will be consumed by the post thread view. This is + * cleaned up any time a source is consumed. + */ +const transientSources = new Map<string, PostSource>() -export function Provider({children}: {children: React.ReactNode}) { - const sourcesRef = useRef<Map<string, Source>>(new Map()) +/** + * A cache of sources that have been consumed by the post thread view. This is + * not cleaned up, but because we use a new ID for each post thread view that + * consumes a source, this is never reused unless a user navigates back to a + * post thread view that has not been dropped from memory. + */ +const consumedSources = new Map<string, PostSource>() - const setUnstablePostSource = useCallback((key: string, source: Source) => { - sourcesRef.current.set(key, source) - }, []) +/** + * For stashing the feed that the user was browsing when they clicked on a post. + * + * Used for FeedFeedback and other ephemeral non-critical systems. + */ +export function setUnstablePostSource(key: string, source: PostSource) { + assertValid( + key, + `setUnstablePostSource key should be a URI containing a handle, received ${key} — use buildPostSourceKey`, + ) + logger.debug('set', {key, source}) + transientSources.set(key, source) +} - const consumeUnstablePostSource = useCallback((uri: string) => { - const source = sourcesRef.current.get(uri) +/** + * This hook is unstable and should only be used for FeedFeedback and other + * ephemeral non-critical systems. Views that use this hook will continue to + * return a reference to the same source until those views are dropped from + * memory. + */ +export function useUnstablePostSource(key: string) { + const id = useId() + const [source] = useState(() => { + assertValid( + key, + `consumeUnstablePostSource key should be a URI containing a handle, received ${key} — use buildPostSourceKey`, + ) + const source = consumedSources.get(id) || transientSources.get(key) if (source) { - sourcesRef.current.delete(uri) + logger.debug('consume', {id, key, source}) + transientSources.delete(key) + consumedSources.set(id, source) } return source - }, []) - - return ( - <SetUnstablePostSourceContext.Provider value={setUnstablePostSource}> - <ConsumeUnstablePostSourceContext.Provider - value={consumeUnstablePostSource}> - {children} - </ConsumeUnstablePostSourceContext.Provider> - </SetUnstablePostSourceContext.Provider> - ) -} + }) -export function useSetUnstablePostSource() { - return useContext(SetUnstablePostSourceContext) + useEffect(() => { + return () => { + consumedSources.delete(id) + logger.debug('cleanup', {id}) + } + }, [id]) + + return source } /** - * DANGER - This hook is unstable and should only be used for FeedFeedback - * and other ephemeral non-critical systems. Does not change when the URI changes. + * Builds a post source key. This (atm) is a URI where the `host` is the post + * author's handle, not DID. */ -export function useUnstablePostSource(uri: string) { - const consume = useContext(ConsumeUnstablePostSourceContext) +export function buildPostSourceKey(key: string, handle: string) { + const urip = new AtUri(key) + urip.host = handle + return urip.toString() +} - const [source] = useState(() => consume(uri)) - return source +/** + * Just a lil dev helper + */ +function assertValid(key: string, message: string) { + if (__DEV__) { + const urip = new AtUri(key) + if (urip.host.startsWith('did:')) { + throw new Error(message) + } + } } |