Files
bsky-social-app/src/state/unstable-post-source.tsx
T
Eric Bailey c4aef9f668 Age Assurance V2 (#9479)
* Age Assurance V2

* Tighten up test

* Add todos for sdk migration

* Align RQ versions

* Use useEffect for side effect

* Improve effects, memoize

* Standarize on birthdate

* Copy feedback

* Copilot

* Add support link

* Reove double ..

* Cleanup

* Remove redirect dialog

* Cleanup todos, add comments

* Update splash in main template too

* Mock some stuff

* Exhaustive checks

Co-authored-by: Samuel Newman <mozzius@protonmail.com>

* Exhaustive checks

Co-authored-by: Samuel Newman <mozzius@protonmail.com>

* Small fix to bday handling

* Add comment

* onboarding style tweak

sneaking this in sorry!

* rm unreachable breaks

* Put useIntentHandler back on web

* Remove misleading success set

* Align on birthdate

---------

Co-authored-by: Samuel Newman <mozzius@protonmail.com>
2025-12-04 15:20:00 -06:00

104 lines
2.9 KiB
TypeScript

import {useEffect, useId, useState} from 'react'
import {type AppBskyFeedDefs, AtUri} from '@atproto/api'
import {Logger} from '#/logger'
import {type FeedSourceInfo} from '#/state/queries/feed'
/**
* Separate logger for better debugging
*/
const logger = Logger.create(Logger.Context.PostSource)
export type PostSource = {
post: AppBskyFeedDefs.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)
}
}
}
}