This avoids repeated database accesses for ranges that are mostly
loaded already.
Also, don't rebuild items that are already loaded, since overlapping
ranges are still expected in this design.
The tile view will only reload the sections that changed. The page
view will reload its current item. This is necessary to keep the
MediaGallery model in sync with the database, but as a side benefit it
also means the All Media view gets live updates as new messages come
in.
And rewrite and simplify the rest of deletion logic appropriately.
(Thanks to Nora for the strategy.)
There is one tough case here: database updates have happened
/externally/ (say, from a disappearing message expiring), in which
case the database will be updated but the MediaGallery model will not.
In this case we've broken the invariant that we have the correct count
for each month-section, and need to put a hold on database access
until the model has been updated. The only effect of this is in the
page-based media VC, where we'll exit out of the browser rather than
advancing to the next item if the item we were looking at was deleted
/and/ the next item hasn't been loaded yet. (This can happen if you're
at the start of a message with many items and the whole message gets
deleted.)
...rather than a flat list of loaded MediaGalleryItems. This is
similar to the ad hoc approach in MediaTileViewController in the
previous commit, but is consistent across MediaPageViewController as
well.
Still not handled yet: deletions, also avoiding redundant database
access
- Measure an entire section all at once, so items don't jump around
- Load individual items lazily by section instead of by plain index
- Search for more sections by enumerating timestamps
Does not handle deletes yet. Also I haven't removed all the old APIs.
- Now a struct, meaning no need for a clone() method
- Now a RandomAccessCollection indexed by Int
- Removed the subscript setter that EarlyMessageManager was using to
make the reordering behavior more explicit
- Generalized insert(key:value:isAppend:) to insert(key:at:value:)
- Added removeSubrange(_:)