-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generic Multi-Trackers, Inbox Middleware #726
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
EricBAndrews
force-pushed
the
eric/inbox-middleware
branch
2 times, most recently
from
October 28, 2023 02:50
d0336d8
to
2a8f58e
Compare
EricBAndrews
requested review from
WestonHanners and
ShadowJonathan
and removed request for
a team
October 28, 2023 02:50
EricBAndrews
force-pushed
the
eric/inbox-middleware
branch
from
October 28, 2023 16:53
2a8f58e
to
32f29b2
Compare
Sjmarf
reviewed
Oct 28, 2023
EricBAndrews
force-pushed
the
eric/inbox-middleware
branch
from
October 29, 2023 18:09
ffecd07
to
ab9d232
Compare
EricBAndrews
force-pushed
the
eric/inbox-middleware
branch
from
October 30, 2023 23:54
7f2636f
to
417e2df
Compare
I'll do a proper review of this today 👍 |
Sjmarf
requested changes
Oct 31, 2023
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears that tapping on a reply in the inbox feed no longer opens the post
Sjmarf
requested changes
Oct 31, 2023
Mlem/Views/Tabs/Inbox/Feed/InteractionSwipeAndMenuHelpers.swift
Outdated
Show resolved
Hide resolved
Sjmarf
approved these changes
Nov 1, 2023
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
EricBAndrews
force-pushed
the
eric/inbox-middleware
branch
from
November 1, 2023 15:07
e5739f0
to
e0e974c
Compare
4 tasks
This was referenced Mar 20, 2024
Closed
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Checklist
- progress on 2.0: Rewrite API and Middleware #73 and Profile Tab Middleware #569
Pull Request Information
About this Pull Request
This PR replaces the existing inbox backend with a new, middleware-model based implementation. To support this, it adds a set of new generic multi-feed trackers. In short, here's how those work:
All of the loading and filtering operations are performed by the child trackers. These look more or less identical to the existing trackers; they extend
BasicTracker
, which is much likeFeedTracking
but built with generic trackers in mind. Child trackers augment this normal tracker functionality with the ability to treat their arrays as streams via two new methods:nextItemSortVal
, which returns the sorting value of the next item in the stream, andconsumeNextItem
, which returns the next item in the stream and increments the cursor.To the consumer, the streams abstract loading operations; the consumer simply awaits the next item and it appears, regardless of whether data needed to be fetched. To avoid the case where multiple threads invoke loading at the same time,
loadNextPage
has been reworked: it now requires the caller to specify a page, and using a semaphore it ensures that only one thread accesses the function at a time. If the page is not the expected next page, the call is ignored. This has the consequence that threads can effectively await aloadNextPage
called by a different thread.ParentTracker
then uses stream system this to efficiently aggregate child trackers: provided all child trackers are sorted on the same criterion, the parent tracker can "fetch a new page" by effectively just merge sorting the streams of its child trackers. This ensures that loading behavior is only invoked when needed, and handles cases where one child tracker has many more items than the others. Since the child trackers are themselves just trackers, they can be used as normal trackers in single-stream views while at the same time feeding a multi-feed.This implementation is pushing the limits of what Swift really wants to do with generics--the
Item
associated with the parent and the child must be related, such that items of the child type are convertable to items of the parent type and all can be sorted on the same criteria. This latter condition unfortunately proved impossible (at least for me) to pull off in a fully compiler-safe way; there is therefore only a singleTrackerSortType
, which must enumerate all possible sorts for a tracker. If a givenTrackerItem
does not implement a givenTrackerSortType
, that should be expressed in assertions.To use the generic trackers, implement:
ParentTrackerItem
conformance for the parent type, which should probably be an enum of child typesChildTrackerItem
conformance for all child typesChildTracker
and using the appropriateChildTrackerItem
. These should be very quick and easy, since onlyfetchPage
needs to be overridden and everything else is handled by genericsParentTracker
with theParentTrackerType
This PR also changes the structure of how the inbox is organized. The trackers are all held in
InboxView
; they are passed to the per-item views asObservedObject
s. The per-stream views are now their own views rather than functions on the main view, and some of the structure of the individual items has been lightly refactored. None of the changes here are major.A note to reviewers
The line count on this is simply obscene. It's not as bad as it looks, though, since a ton of those changes are just moving logic around, notably splitting
Inbox View Logic
into the models and moving some things between repositories.The core new code is limited to
BasicTracker
,ChildTracker
, andParentTracker
; almost everything else is refactoring or very thin (protocols, extending classes, etc.)Behavior Changes
Blocking a user no longer removes them from the feed. The code is there, but not used. Since those users just show up again when the inbox is refreshed, I disabled that behavior in order to present a more consistent experience; long-term, we should look into filtering blocked users more robustly, but that's out of scope here.
There is one issue I am aware of: refreshing the inbox does not refresh the read status of replies or mentions, though it does refresh messages. I'm losing sanity trying to debug that one, and it's so minor that I'm willing to call it acceptable for the sake of getting this PR in, but if anybody has any insight into why I'd love to hear it.