We still need the AxolotlKit model classes to migrate old sessions,
but we don't need any of the actual protocol support. This also
means we can drop HKDFKit.
Additionally, we do still use some utilities from AxolotlKit:
- AxolotlExceptions.h: NSException names, should eventually be
replaced by NSErrors everywhere
- NSData+keyVersionByte.h: prepend/remove public key type byte,
should eventually be replaced by strong types (ECPublicKey)
- SPKProtocolContext.h: defines the SPKProtocol{Read,Write}Context
marker protocols, should be replaced by direct use of
SDSAny{Read,Write}Transaction
- Fixes up content alignment issues from parallel changes to table view
styling.
- Re-adds view controller presentation within a nav controller (stemming
from parallel changes to table view styling)
- Fixes a bug around overzealous collision detection
Also fixes an unrelated issue. Setting up cv banners performs layout, which
can cause the conversation view controller's trait collection to change.
This can lead to us reenterantly setting up banners and updating trait
collection.
The workaround is to just call -ensureBannerState asynchronously from
-traitCollectionDidChange to break the synchronous chain.
If you're scrolled to the end, you probably want to stay scrolled to
the end rather than keep the same top position. This applies both when
the footer bar shows up (in multi-select mode) and when the scroll
view is initially loaded, fixing a bug where the bottom row is cut
off. Unfortunately, the latter fix does not seem to work on older
iOSs, but it doesn't make things worse either.
...unless you clicked on an individual message to get into the
gallery. In the All Media case, we don't need to fetch later sections
because we started at the end.
The collection view loads earlier sections if you're scrolled near the
top and later sections if you're scrolled near the bottom. However, if
there's only a page of loaded content, you can be near the top /and/
the bottom. Therefore, we need to potentially load later sections even
if you're at the top, because you might be at the beginning.
Some calendars have year numbers change in the middle of months; some
calendars occasionally reset the year number. Switch to a
DateInterval-based representation in GalleryDate to avoid these
pitfalls.
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(_:)