When you compose reply to a message but do not
send it, we would persist the text you entered but
would lose the quoted message to which you were
replying.
This commit adds support for persisting that
information.
ThreadReplyInfo is a new class that uses the
key-value store to associate a single optional
reference to a message with each thread.
The following behaviors are nw:
* When you enter the CVC the input toolbar is
updated to have the quoted message.
* When you exit the CVC the quoted message is
saved.
* When a thread is deleted, the quoted message is
deleted.
* Start muted, unmute when pressing volume buttons
* move ringer switch observation into its own class
* observe ringer switch in stories
* add foreground time to AppContext; use to drive mute foregrounding behavior
* dont double observe
* mix story volume with others, show volume controls
Previously this used UIDevice.ows_setOrientation, an undocumented hack
to basically lie to the device about which way is up. This sounds
sketchy, but it's the result of a lot of testing various solutions for
something that could reliably force the app into portrait orientation.
However, every UIWindow has its own "supported orientations", provided
by the root view controller. And calls are implemented in their own
UIWindow (so that they don't disrupt whatever you were doing). So for
*calls specifically*, we can use supportedInterfaceOrientations to
force the app into portrait mode.
All other callers of UIDevice.ows_setOrientation work in the shared
main window, so they'll be left alone. This only changes things for
the call window.
* allow playback of audio messages from the message detail view
* Update UI when an audio message pauses because another one started playing
* pr feedback
* Add audio playback rate button UI
* update animation values and remove feature flags since its now ready to go to prod
* address PR feedback
* PR nits
Commit 04737ff044
attempted to fix an assertion in
StoriesViewController due to UITableView
complaining about inconsistent state. The issue
continues to happen. This diff fixes it once and
for all (I hope!).
The scenario that caused a crash prior to
04737ff044 was:
Initially:
models = [a,b,c]
Database changes to [a,b]
reloadStories (loading queue)
newModels = [a,b]
schedule block to run on main queue
Database changes to [x, b]
updateStories (loading queue)
captures self.models, value is [a,b,c] // cue ominous music
load from database
newModels = [x,b]
schedule block to run on main queue; will delete c and change a to x
reloadStories.block runs on main queue
self.models=newModels, value is [a,b]
tableView.reloadData() // UITableView thinks c is deleted
updateStories.block runs on main queue
self.models=newModels, value is [x,b]
tableView.beginUpdates()
tableView.delete(index: 2) // crashes because c was already deleted
Post-04737ff the following scenario causes a
crash:
Initially:
models = [a,b,c]
Database changes to [a,b]
updateStories (loading queue)
load from database
models.set([a,b])
schedule block to run on main queue which will delete c
iOS gets a wild hair and decides to call some
UITableViewDataSource methods.
tableView(_, numberOfRowsInSection:)
return [a,b].count // Now UIKit thinks c is gone
updateStories.block runs on main queue
tableView.beginUpdates()
tableView.delete(index: 2) // crashes because 2 is out of bounds vs number of rows
This commit fixes the problem by ensuring the
read-modify-write that happens in updateStories
never reads older data than what UITableView
has been told about and also that updates to the
model are properly synchronized with
beginUpdates()...endUpdates().
Here's how to think about it: the database goes
through a series of changes. Call them v1, v2,
..., vN.
The loading queue will see each in turn. For each,
it will enqueue a corresponding block on the main
queue to update `model` and tell UITableView about
it.
From the POV of the main queue, each update occurs
in the scope of a UITableView update.
From the POV of the loading queue, each update
reads from exactly the preceding version (from
`trueModels`) and writes to exactly the next
version of `trueModels`.
Therefore, there are no data races.
This change should have no direct user impact.
`OWSOutgoingReactionMessage` was untested. This adds a basic test for
its `shouldBeSaved` method.
I think this is a useful change on its own, but may make future changes
easier, too.
SignalServiceKit is currently a separate pod. This makes merges tedious
and error-prone. Ultimately, it slows us down. It might've made sense as
a standalone library before, but it's so tightly integrated now that it
isn't useful to have it be separate.
This changes that, and makes SignalServiceKit a "normal" target.
IMO, most of this change isn't that exciting—just a bunch of changes to
scaffolding. There's one slightly spicier change: our generated
`Acknowledgements.plist` is now a little more clever.
Co-authored-by: Max Radermacher <max@signal.org>