The previous solution would result in a crash because the passed in
viewTreeObserver that would trigger onPreDraw would be invalid.
The proposed solution is simpler and ensures we'll always use the right
viewTreeObserver.
`FragmentPreDrawManager` is general enough that can be used by other Fragments
also, so I've added it to the `utils` package.
This cleans up how we're displaying account state in the main preference UI.
Before when it worked, it worked mostly accidentally.
'launch' wrapper around "update ui" methods would trigger a race condition
between binding the account pref view holder and actually updating that view
with values. Sometimes the "update view with values" would happen after view
was bound, and the UI will be correct. Most of the time it would happen before,
and so there will be nothing to update and we'd get into an inconsistent state.
This also splits up the "accountpreference" into two: account is good,
and account needs re-auth. This greatly simplifies their management.
This patch fixes a few issues:
- it was an extension on a CoroutineScope, but that was quite misleading
since the Main dispatcher would be always used regardless of what dispatcher
the owning CoroutineScope was configured with.
- timing was reliant on exact value of the undocumented Snackbar.LENGTH_LONG duration
- coroutine cancellation relied on cooperation of the 'operation' suspend function,
which we can't depend on
New 'allowUndo' fully controls its timing, doesn't imply a dispatcher to its consumers,
and doesn't rely on cooperation of passed-in suspend blocks for cancellation to work.