diff options
author | Paul Frazee <pfrazee@gmail.com> | 2022-12-18 18:54:05 -0600 |
---|---|---|
committer | Paul Frazee <pfrazee@gmail.com> | 2022-12-18 18:54:05 -0600 |
commit | ae3099dfca13f6651762f6ea9a3d2a14ebc99df4 (patch) | |
tree | c78136d8fb2f15da0c1be3bef8d0e732287d050f /src/state/models | |
parent | 69b86255c6c2275b3403ce6654b17e0a2c56ced6 (diff) | |
download | voidsky-ae3099dfca13f6651762f6ea9a3d2a14ebc99df4.tar.zst |
Improve thread rendering
Diffstat (limited to 'src/state/models')
-rw-r--r-- | src/state/models/feed-view.ts | 117 | ||||
-rw-r--r-- | src/state/models/post-thread-view.ts | 1 |
2 files changed, 77 insertions, 41 deletions
diff --git a/src/state/models/feed-view.ts b/src/state/models/feed-view.ts index f2832887a..f8080d4b5 100644 --- a/src/state/models/feed-view.ts +++ b/src/state/models/feed-view.ts @@ -17,6 +17,7 @@ let _idCounter = 0 type FeedItem = GetTimeline.FeedItem | GetAuthorFeed.FeedItem type FeedItemWithThreadMeta = FeedItem & { _isThreadParent?: boolean + _isThreadChildElided?: boolean _isThreadChild?: boolean } @@ -34,6 +35,7 @@ export class FeedItemModel implements GetTimeline.FeedItem { // ui state _reactKey: string = '' _isThreadParent: boolean = false + _isThreadChildElided: boolean = false _isThreadChild: boolean = false // data @@ -70,6 +72,7 @@ export class FeedItemModel implements GetTimeline.FeedItem { this.copy(v) this._isThreadParent = v._isThreadParent || false this._isThreadChild = v._isThreadChild || false + this._isThreadChildElided = v._isThreadChildElided || false } copy(v: GetTimeline.FeedItem | GetAuthorFeed.FeedItem) { @@ -469,15 +472,7 @@ export class FeedModel { this.loadMoreCursor = res.data.cursor this.hasMore = !!this.loadMoreCursor - // HACK 1 - // rearrange the posts to represent threads - // (should be done on the server) - // -prf - // HACK 2 - // deduplicate posts on the home feed - // (should be done on the server) - // -prf - const reorgedFeed = preprocessFeed(res.data.feed, this.feedType === 'home') + const reorgedFeed = preprocessFeed(res.data.feed) const promises = [] const toAppend: FeedItemModel[] = [] @@ -569,38 +564,78 @@ export class FeedModel { } } -function preprocessFeed( - feed: FeedItem[], - dedup: boolean, -): FeedItemWithThreadMeta[] { - // DEBUG - // this has been temporarily disabled to see if it's the cause of some bugs - // if the issues go away, we know this was the cause - // -prf - return feed - // const reorg: FeedItemWithThreadMeta[] = [] - // for (let i = feed.length - 1; i >= 0; i--) { - // const item = feed[i] as FeedItemWithThreadMeta - - // if (dedup) { - // if (reorg.find(item2 => item2.uri === item.uri)) { - // continue - // } - // } - - // const selfReplyUri = getSelfReplyUri(item) - // if (selfReplyUri) { - // const parentIndex = reorg.findIndex(item2 => item2.uri === selfReplyUri) - // if (parentIndex !== -1 && !reorg[parentIndex]._isThreadParent) { - // reorg[parentIndex]._isThreadParent = true - // item._isThreadChild = true - // reorg.splice(parentIndex + 1, 0, item) - // continue - // } - // } - // reorg.unshift(item) - // } - // return reorg +interface Slice { + index: number + length: number +} +function preprocessFeed(feed: FeedItem[]): FeedItemWithThreadMeta[] { + const reorg: FeedItemWithThreadMeta[] = [] + + // phase one: identify threads and reorganize them into the feed so + // that they are in order and marked as part of a thread + for (let i = feed.length - 1; i >= 0; i--) { + const item = feed[i] as FeedItemWithThreadMeta + + const selfReplyUri = getSelfReplyUri(item) + if (selfReplyUri) { + const parentIndex = reorg.findIndex(item2 => item2.uri === selfReplyUri) + if (parentIndex !== -1 && !reorg[parentIndex]._isThreadParent) { + reorg[parentIndex]._isThreadParent = true + item._isThreadChild = true + reorg.splice(parentIndex + 1, 0, item) + continue + } + } + reorg.unshift(item) + } + + // phase two: identify the positions of the threads + let activeSlice = -1 + let threadSlices: Slice[] = [] + for (let i = 0; i < reorg.length; i++) { + const item = reorg[i] as FeedItemWithThreadMeta + if (activeSlice === -1) { + if (item._isThreadParent) { + activeSlice = i + } + } else { + if (!item._isThreadChild) { + threadSlices.push({index: activeSlice, length: i - activeSlice}) + activeSlice = -1 + } + } + } + if (activeSlice !== -1) { + threadSlices.push({index: activeSlice, length: reorg.length - activeSlice}) + } + + // phase three: reorder the feed so that the timestamp of the + // last post in a thread establishes its ordering + for (const slice of threadSlices) { + const removed: FeedItemWithThreadMeta[] = reorg.splice( + slice.index, + slice.length, + ) + const targetDate = new Date(removed[removed.length - 1].indexedAt) + const newIndex = reorg.findIndex( + item => new Date(item.indexedAt) < targetDate, + ) + reorg.splice(newIndex, 0, ...removed) + slice.index = newIndex + } + + // phase four: compress any threads that are longer than 3 posts + let removedCount = 0 + for (const slice of threadSlices) { + if (slice.length > 3) { + reorg.splice(slice.index - removedCount + 1, slice.length - 3) + reorg[slice.index - removedCount]._isThreadChildElided = true + console.log(reorg[slice.index - removedCount]) + removedCount += slice.length - 3 + } + } + + return reorg } function getSelfReplyUri( diff --git a/src/state/models/post-thread-view.ts b/src/state/models/post-thread-view.ts index ebe5b730d..64de7d260 100644 --- a/src/state/models/post-thread-view.ts +++ b/src/state/models/post-thread-view.ts @@ -48,6 +48,7 @@ export class PostThreadViewPostModel implements GetPostThread.Post { _reactKey: string = '' _depth = 0 _isHighlightedPost = false + _hasMore = false // data $type: string = '' |