e7d349bc30
Task 8: codemod repointed 150 namespace-type files to #/lexicons (AppBskyFeedDefs.PostView -> app.bsky.feed.defs.PostView, .Record -> .Main) plus ~105 hand-fixed consumers (composer/video state, DebugMod, Profile, onboarding, dialogs). DM_SERVICE_HEADERS deleted; last chat call sites on the chat client. RichText.tsx flipped to SDK-only. Remaining @atproto/api importers: the three session bridge files, the deliberate dual-world matcher in lib/xrpc-error.ts, and test fixtures. toLex boundary casts are TODO(phase4)-tagged for bridge removal. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
105 lines
2.9 KiB
TypeScript
105 lines
2.9 KiB
TypeScript
import {useEffect, useId, useState} from 'react'
|
|
import {AtUri} from '@atproto/syntax'
|
|
|
|
import {Logger} from '#/logger'
|
|
import {type FeedSourceInfo} from '#/state/queries/feed'
|
|
import {type app} from '#/lexicons'
|
|
|
|
/**
|
|
* Separate logger for better debugging
|
|
*/
|
|
const logger = Logger.create(Logger.Context.PostSource)
|
|
|
|
export type PostSource = {
|
|
post: app.bsky.feed.defs.FeedViewPost
|
|
feedSourceInfo?: FeedSourceInfo
|
|
}
|
|
|
|
/**
|
|
* 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>()
|
|
|
|
/**
|
|
* 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>()
|
|
|
|
/**
|
|
* 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) {
|
|
assertValidDevOnly(
|
|
key,
|
|
`setUnstablePostSource key should be a URI containing a handle, received ${key} — use buildPostSourceKey`,
|
|
)
|
|
logger.debug('set', {key, source})
|
|
transientSources.set(key, source)
|
|
}
|
|
|
|
/**
|
|
* 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(() => {
|
|
assertValidDevOnly(
|
|
key,
|
|
`consumeUnstablePostSource key should be a URI containing a handle, received ${key} — be sure to use buildPostSourceKey when setting the source`,
|
|
true,
|
|
)
|
|
const source = consumedSources.get(id) || transientSources.get(key)
|
|
if (source) {
|
|
logger.debug('consume', {id, key, source})
|
|
transientSources.delete(key)
|
|
consumedSources.set(id, source)
|
|
}
|
|
return source
|
|
})
|
|
|
|
useEffect(() => {
|
|
return () => {
|
|
consumedSources.delete(id)
|
|
logger.debug('cleanup', {id})
|
|
}
|
|
}, [id])
|
|
|
|
return source
|
|
}
|
|
|
|
/**
|
|
* Builds a post source key. This (atm) is a URI where the `host` is the post
|
|
* author's handle, not DID.
|
|
*/
|
|
export function buildPostSourceKey(key: string, handle: string) {
|
|
const urip = new AtUri(key)
|
|
// @ts-expect-error TODO new-sdk-migration
|
|
urip.host = handle
|
|
return urip.toString()
|
|
}
|
|
|
|
/**
|
|
* Just a lil dev helper
|
|
*/
|
|
function assertValidDevOnly(key: string, message: string, beChill = false) {
|
|
if (__DEV__) {
|
|
const urip = new AtUri(key)
|
|
if (urip.host.startsWith('did:')) {
|
|
if (beChill) {
|
|
logger.warn(message)
|
|
} else {
|
|
throw new Error(message)
|
|
}
|
|
}
|
|
}
|
|
}
|