-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduces DialogCollator
#981
Conversation
6fc1a62
to
87819fc
Compare
87819fc
to
1b90f84
Compare
1b90f84
to
bc40918
Compare
Lol @square/ui-systems-android was literally just talking about how painful dialogs can be and if it would be less painful to draw them manually 🙊 |
Last time we tried that it was just painful in a different way — enough so
that we went back to dialogs.
But that was a long time ago. And the decoupling provided by the Overlay
interface means it will be much easier to try again.
…On Thu, Mar 30, 2023, 7:04 AM Victoria Gonda ***@***.***> wrote:
Lol @square/ui-systems-android
<https://github.com/orgs/square/teams/ui-systems-android> was literally
just talking about how painful dialogs can be and if it would be less
painful to draw them manually 🙊
—
Reply to this email directly, view it on GitHub
<#981 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAOMCHOUCKMUSWQRVTYX4PTW6WHH5ANCNFSM6AAAAAAWMEII2I>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
f024178
to
6b4cc6c
Compare
One vacation and one sick bed later, this has passed our internal test suite with flying colors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of kdoc/understandability questions.
I'm going to have to trust the tests for this to a certain extent as, as you noted, its very complex!
Would be great to have a class diagram and a mock up of how that maps to your main example app used for tests.
But ... maybe there is not need for that as this code will hopefully not be often maintained?
...ose/src/androidTest/java/com/squareup/workflow1/ui/compose/ComposeViewTreeIntegrationTest.kt
Show resolved
Hide resolved
...re-android/src/androidTest/java/com/squareup/workflow1/ui/container/DialogIntegrationTest.kt
Show resolved
Hide resolved
...ore-android/src/main/java/com/squareup/workflow1/ui/androidx/KeyedSavedStateRegistryOwner.kt
Show resolved
Hide resolved
workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/DialogCollator.kt
Outdated
Show resolved
Hide resolved
workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/DialogCollator.kt
Outdated
Show resolved
Hide resolved
workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/DialogCollator.kt
Show resolved
Hide resolved
workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/DialogCollator.kt
Outdated
Show resolved
Hide resolved
workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/DialogCollator.kt
Outdated
Show resolved
Hide resolved
workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/DialogCollator.kt
Outdated
Show resolved
Hide resolved
workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/DialogCollator.kt
Outdated
Show resolved
Hide resolved
Great feedback, thanks @steve-the-edwards. |
49b2883
to
41be190
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. I understand better now I think! Can you contribute this back to Android 🙏🏻 😆
...w-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/LayeredDialogSessions.kt
Outdated
Show resolved
Hide resolved
|
||
oldSessionOrNull | ||
?.also { session -> session.show(overlay, dialogEnv) } | ||
?: overlay.toDialogFactory(dialogEnv) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: The work here to set up a new session is still a bit hidden after the elvis operator.
I think its fine but a comment might help, "If we don't have an old session to update, create a new session and initialize it to show the dialog in this environment."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oldSessionOrNull
// If there is already a matching session, it may have been hidden b/c out of order.
?.also { session -> session.show(overlay, dialogEnv) }
// This is a new Overlay, create and show its Dialog.
workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/DialogSession.kt
Outdated
Show resolved
Hide resolved
workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/DialogCollator.kt
Outdated
Show resolved
Hide resolved
workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/DialogCollator.kt
Outdated
Show resolved
Hide resolved
workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/DialogCollator.kt
Outdated
Show resolved
Hide resolved
workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/DialogCollator.kt
Outdated
Show resolved
Hide resolved
workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/container/DialogCollator.kt
Show resolved
Hide resolved
Android notoriously give us no control over the z order of Dialog windows other than taking care to `show()` them in the right order, so keeping a pile of windows in sync with a list of `Overlay` rendering models is hard. We've already solved that for individual instances of `LayeredDialogSessions` (the delegate that does all of the work for `BodyAndOverlaysContainer`), but it was still a problem when you nested them, e.g. in the style of the recently introduced Nested Overlays sample. Also, the solution was kind of nasty because we would replace any out of order Dialogs with brand new ones, rather than preserving them by calling `dismiss()` and `show()`. To fix all that we introduce `internal class DialogCollator`. On each view update pass, a new `DialogCollator` instance is created by the outermost `LayeredDialogSessions` and made available to any nested instances via the `ViewEnvironment`. The shared collator collects a list of all existing `DialogSession` instances, and a set of `DialogSessionUpdate` functions to be asynchronously used to update existing instances or create new ones. Because a `DialogCollator` has complete knowledge of all the windows managed by the set of nested `LayerDialogSessions` instances it supports, it is able to ensure that inserts are supported by calling `dismiss()` / `show()` on existing windows in the sequence needed to reorder them. One important change to note: our `SavedStateRegistry` code requires that each window in a set has a unique name, which we derive by applying `Compatible.keyFor` to its defining `Overlay`. We used to append to that key an `Overlay`'s position in its `LayeredDialogSessions` list, as a poorly considered hack to simplify showing several of the same type at once. That approach conflicts with reordering. With this commit we no longer include the index value in `SavedStateRegistry` keys, meaning that each `Overlay` shown by a `LayeredDialogSession` must have a unique key -- `BackStackScreen` has long had a similar requirement. `NamedScreen` exists to simplify that kind of thing, and in particular can be used to wrap `ScreenOverlay.content` to meet the new requirement. Fixes #966
41be190
to
e081c2e
Compare
Android notoriously doesn't give us any control over the z order of Dialog windows
other than taking care to
show()
them in the right order, so keeping a pileof windows in sync with a list of
Overlay
rendering models is hard.We've already solved that for individual instances of
LayeredDialogSessions
(the delegate that does all of the work for
BodyAndOverlaysContainer
), butit was still a problem when you nested them, e.g. in the style of the
recently introduced Nested Overlays sample. Also, the solution was kind of
nasty because we would replace any out of order Dialogs with brand new ones,
rather than preserving them by calling
dismiss()
andshow()
.To fix all that we introduce
internal class DialogCollator
. On each viewupdate pass, a new
DialogCollator
instance is created by the outermostLayeredDialogSession
and made available to any nested instances via theViewEnvironment
. The shared collator collects a list of all existingDialogSession
instances, and a set ofDialogSessionUpdate
objects to beasynchronously used to update existing instances or create new ones.
Because a
DialogCollator
has complete knowledge of all the windows managedby the set of nested
LayerDialogSession
instances it supports, it is able toensure that inserts are supported by calling
dismiss()
/show()
on existingwindows in the sequence needed to reorder them.
One important change to note: our
SavedStateRegistry
code requires that eachwindow in a set has a unique name, which we derive by applying
Compatible.keyFor
toits defining
Overlay
. We used to append to that key anOverlay
's position in itsLayeredDialogSessions
list, as a poorly considered hack to simplify showingseveral of the same type at once. That approach conflicts with reordering.
With this commit we no longer include the index value in
SavedStateRegistry
keys,meaning that each
Overlay
shown by aLayeredDialogSession
must have a uniquekey --
BackStackScreen
has long had a similar requirement.NamedScreen
exists to simplify that kind of thing, and in particular can be used to wrap
ScreenOverlay.content
to meet the new requirement.Fixes #966