Preserve thread numbering in placeholders (#11616)
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import {type app} from '#/lexicons'
|
||||
import {createFeedViewPostsSlices} from './feed-manip'
|
||||
|
||||
jest.mock('./feed/home', () => ({
|
||||
FALLBACK_MARKER_POST: {post: {uri: 'at://did:plc:test/app.bsky.feed.post/1'}},
|
||||
}))
|
||||
|
||||
const author = {
|
||||
$type: 'app.bsky.actor.defs#profileViewBasic',
|
||||
did: 'did:plc:alice',
|
||||
handle: 'alice.test',
|
||||
} as app.bsky.actor.defs.ProfileViewBasic
|
||||
|
||||
function post(id: string) {
|
||||
return {
|
||||
$type: 'app.bsky.feed.defs#postView',
|
||||
uri: `at://did:plc:alice/app.bsky.feed.post/${id}`,
|
||||
cid: id,
|
||||
author,
|
||||
record: {
|
||||
$type: 'app.bsky.feed.post',
|
||||
text: id,
|
||||
createdAt: '2026-08-31T00:00:00.000Z',
|
||||
},
|
||||
indexedAt: '2026-08-31T00:00:00.000Z',
|
||||
} as app.bsky.feed.defs.PostView
|
||||
}
|
||||
|
||||
describe('createFeedViewPostsSlices', () => {
|
||||
it('preserves selected numbering and infers hydrated parent and root numbering', () => {
|
||||
const root = post('root')
|
||||
const parent = post('parent')
|
||||
const selected = post('selected')
|
||||
const feedPost = {
|
||||
post: selected,
|
||||
reply: {root, parent},
|
||||
opThreadPostIndex: 3,
|
||||
opThreadPostCount: 4,
|
||||
} as app.bsky.feed.defs.FeedViewPost & {
|
||||
opThreadPostIndex: number
|
||||
opThreadPostCount: number
|
||||
}
|
||||
|
||||
const [slice] = createFeedViewPostsSlices([feedPost])
|
||||
|
||||
expect(
|
||||
slice.items.map(item => [item.post.uri, item.postNumbering]),
|
||||
).toEqual([
|
||||
[root.uri, {opThreadPostIndex: 1, opThreadPostCount: 4}],
|
||||
[parent.uri, {opThreadPostIndex: 2, opThreadPostCount: 4}],
|
||||
[selected.uri, {opThreadPostIndex: 3, opThreadPostCount: 4}],
|
||||
])
|
||||
})
|
||||
})
|
||||
+20
-14
@@ -9,7 +9,7 @@ export type FeedPostNumbering = Pick<
|
||||
'opThreadPostIndex' | 'opThreadPostCount'
|
||||
>
|
||||
|
||||
type ValidFeedPostNumbering = Required<FeedPostNumbering>
|
||||
export type ValidFeedPostNumbering = Required<FeedPostNumbering>
|
||||
|
||||
// AppView adds these fields to feed responses ahead of their feed lexicon.
|
||||
type FeedViewPost = app.bsky.feed.defs.FeedViewPost & FeedPostNumbering
|
||||
@@ -62,7 +62,7 @@ export type FeedTunerFn = (
|
||||
type FeedSliceItem = {
|
||||
post: app.bsky.feed.defs.PostView
|
||||
record: app.bsky.feed.post.Main
|
||||
postNumbering: FeedPostNumbering | undefined
|
||||
postNumbering: ValidFeedPostNumbering | undefined
|
||||
parentAuthor: app.bsky.actor.defs.ProfileViewBasic | undefined
|
||||
isParentBlocked: boolean
|
||||
isParentNotFound: boolean
|
||||
@@ -88,7 +88,7 @@ export class FeedViewPostsSlice {
|
||||
|
||||
constructor(
|
||||
feedPost: FeedViewPost,
|
||||
postNumberingByUri: Map<string, FeedPostNumbering>,
|
||||
postNumberingByUri: Map<string, ValidFeedPostNumbering>,
|
||||
) {
|
||||
const {post, reply, reason} = feedPost
|
||||
this.items = []
|
||||
@@ -286,6 +286,22 @@ export class FeedViewPostsSlice {
|
||||
}
|
||||
}
|
||||
|
||||
export function createFeedViewPostsSlices(
|
||||
feed: FeedViewPost[],
|
||||
): FeedViewPostsSlice[] {
|
||||
const postNumberingByUri = new Map<string, ValidFeedPostNumbering>()
|
||||
for (const item of feed) {
|
||||
const postNumbering = getPostNumbering(item)
|
||||
if (postNumbering) {
|
||||
postNumberingByUri.set(item.post.uri, postNumbering)
|
||||
}
|
||||
}
|
||||
|
||||
return feed
|
||||
.map(item => new FeedViewPostsSlice(item, postNumberingByUri))
|
||||
.filter(slice => slice.items.length > 0 || slice.isFallbackMarker)
|
||||
}
|
||||
|
||||
export class FeedTuner {
|
||||
seenKeys: Set<string> = new Set()
|
||||
seenUris: Set<string> = new Set()
|
||||
@@ -299,17 +315,7 @@ export class FeedTuner {
|
||||
dryRun: false,
|
||||
},
|
||||
): FeedViewPostsSlice[] {
|
||||
const postNumberingByUri = new Map<string, FeedPostNumbering>()
|
||||
for (const item of feed) {
|
||||
const postNumbering = getPostNumbering(item)
|
||||
if (postNumbering) {
|
||||
postNumberingByUri.set(item.post.uri, postNumbering)
|
||||
}
|
||||
}
|
||||
|
||||
let slices: FeedViewPostsSlice[] = feed
|
||||
.map(item => new FeedViewPostsSlice(item, postNumberingByUri))
|
||||
.filter(s => s.items.length > 0 || s.isFallbackMarker)
|
||||
let slices = createFeedViewPostsSlices(feed)
|
||||
|
||||
// run the custom tuners
|
||||
for (const tunerFn of this.tunerFns) {
|
||||
|
||||
Reference in New Issue
Block a user