[Chat] Sync convo agent with shadow cache (#10827)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: DS Boyce <260543580+ds-boyce@users.noreply.github.com> Co-authored-by: Samuel Newman <mozzius@protonmail.com>
This commit is contained in:
Vendored
+53
-1
@@ -53,6 +53,21 @@ const shadows: WeakMap<
|
||||
> = new WeakMap()
|
||||
const emitter = new EventEmitter()
|
||||
|
||||
type ShadowUpdateEventPayload = {did: string; shadow: Partial<ProfileShadow>}
|
||||
|
||||
/**
|
||||
* Subscribe to all profile shadow updates, regardless of did. Useful for
|
||||
* non-React consumers like the Convo agent. Returns an unlisten function.
|
||||
*/
|
||||
export function listenProfileShadowUpdate(
|
||||
listener: (payload: ShadowUpdateEventPayload) => void,
|
||||
): () => void {
|
||||
emitter.addListener('shadow-update', listener)
|
||||
return () => {
|
||||
emitter.removeListener('shadow-update', listener)
|
||||
}
|
||||
}
|
||||
|
||||
export function useProfileShadow<
|
||||
TProfileView extends bsky.profile.AnyProfileView,
|
||||
>(profile: TProfileView): Shadow<TProfileView> {
|
||||
@@ -206,10 +221,47 @@ export function updateProfileShadow(
|
||||
}
|
||||
batchedUpdates(() => {
|
||||
emitter.emit(did, value)
|
||||
emitter.emit('shadow-update', {
|
||||
did,
|
||||
shadow: value,
|
||||
} satisfies ShadowUpdateEventPayload)
|
||||
})
|
||||
}
|
||||
|
||||
function mergeShadow<TProfileView extends bsky.profile.AnyProfileView>(
|
||||
/**
|
||||
* Returns true if merging `shadow` into `profile` would change nothing, i.e.
|
||||
* `mergeShadow` would be a no-op. Object-valued fields are compared by
|
||||
* reference, so this can return false negatives - callers may do redundant
|
||||
* merges, but never skip a real change.
|
||||
*/
|
||||
export function isProfileShadowApplied<
|
||||
TProfileView extends bsky.profile.AnyProfileView,
|
||||
>(profile: TProfileView, shadow: Partial<ProfileShadow>): boolean {
|
||||
if ('followingUri' in shadow) {
|
||||
if (profile.viewer?.following !== shadow.followingUri) return false
|
||||
}
|
||||
if ('muted' in shadow) {
|
||||
if (profile.viewer?.muted !== shadow.muted) return false
|
||||
}
|
||||
if ('blockingUri' in shadow) {
|
||||
if (profile.viewer?.blocking !== shadow.blockingUri) return false
|
||||
}
|
||||
if ('activitySubscription' in shadow) {
|
||||
if (profile.viewer?.activitySubscription !== shadow.activitySubscription) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if ('verification' in shadow) {
|
||||
if (profile.verification !== shadow.verification) return false
|
||||
}
|
||||
if ('status' in shadow) {
|
||||
const current = 'status' in profile ? profile.status : undefined
|
||||
if (current !== shadow.status) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export function mergeShadow<TProfileView extends bsky.profile.AnyProfileView>(
|
||||
profile: TProfileView,
|
||||
shadow: Partial<ProfileShadow>,
|
||||
): Shadow<TProfileView> {
|
||||
|
||||
Reference in New Issue
Block a user