When we get a new profile with a given name or
family name, it usually doesn't change. Prior to
this commit, we would reindex regardless so long
as at least one of the names was nonnil. This
commit reindexes only if the names have actually
changed.
When you open a chat if there is no inputToolbar
then applyTheme() will call ensureBannerState().
Unfortunately, ensureBannerState() is very slow
because of group name collision finding. This
commit avoids doing the search twice in this case.
I considered changing ConverationViewController so
that it will not duplicate the effort of
GroupMembershipNameCollisionFinder when nothing
has changed. I still want to do that, but it's a
much larger task.
Impact: This reduces database queries when opening
the MobileCoin group from 11,216 to 6,669—a 40%
reduction!
These tests fulfill an expectation when a write to the database causes
the desired state to be reached. However, there may still be writes to
the database in flight, and the *next* write will *also* probably be
in the desired state, resulting in the expectation being fulfilled
again. Because this happened *after* the test finished, an exception
was thrown, the test environment terminated, and the *next* test (or
possibly a later one) was being blamed for the failure.
Fix this issue in both places where it happens by allowing multiple
fulfills, and re-enable the test that was previously getting blamed
for this.
We ship with 49 stickers and the previous cache size of 32 led to
thrasing every time a chat was opened.
Since sticker packs can be as large as 200 stickers and we hold three
pages in cache while the keyboard is open, increase the cache size for
the main app to 600. For the share extension, make it 64 to minimize
memory use while avoiding threashing.
The cost of this cache is just the sticker metadata (unique ID, emoji
description, etc.) so it won't make much difference in memory
utilization.
When profile updates are applied, we diff them to
avoid redundant saves and the resulting work (like
reloading all cells of the conversation).
The diff often failed spuriously because
OWSUserProfileBadgeInfo did not implement
`isEqual:` and instead relied on `NSObject`'s
default implementation using pointer equality.
This commit makes two changes:
1. Implement `-[OWSUserProfileBadgeInfo isEqual:]`
2. Force the ProfileBadge to be loaded prior to
comparing snapshots so the comparison will be
correct.
This significantly reduces the number of database
calls when opening a large chat. It may possibly
increase the amount of DB work needed for smaller
groups by loading the profile badge earlier.
The default cache size for a SQLite connection is 2000KiB, but our
database pool has several reader connections plus a writer connection.
They can't share a cache because that changes SQLite's locking model,
so the next best thing is to limit their caches individually when
we're in a memory-constrained environment. To avoid the caches getting
*too* small, this also removes one of the available readers outside
the main app.
Every single message updates a TSThread model, but only a change in a
member's profile name or phone number, or a change to a group's model,
can update the indexing information. Turn 'shouldBeIndexedForFTS' into
a tri-state 'FTSIndexMode' with options 'never', 'manualUpdates', and
'always', and use 'manualUpdates' for TSThreads. Then explicitly
reindex on any of the changes listed above.
Previously this class used AtomicOptional for its properties, a
convenience wrapper we have for protecting a single value with a lock.
This wrapper trades extra heap allocations for simplicity (stepping
around Swift's prohibitions on non-atomically mutating struct
properties or relying on the addresses of object properties). However,
SignalServiceAddresses are created in sufficient numbers to make this
trade-off a problem.
This commit unboxes all of the properties on a SignalServiceAddress
and manually protects them with a shared dedicated UnfairLock.
(AtomicOptional and AtomicValue also use a shared lock, so this is no
less efficient and could actually lead to *less* contention.)
The UI updates (including adding a new message to conversation) were
being blocked for 1 second because of the animated dismissal of message
quote panel attached to the input field.
The fix is to block UI updates just for the duration of keyboard animations.