1
1
package com.squareup.workflow1.ui.navigation
2
2
3
+ import com.squareup.workflow1.ui.Compatible
3
4
import com.squareup.workflow1.ui.ViewEnvironment
4
5
import com.squareup.workflow1.ui.ViewEnvironmentKey
5
6
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
6
7
import com.squareup.workflow1.ui.navigation.DialogCollator.IdAndSessions
8
+ import com.squareup.workflow1.ui.navigation.DialogSession.KeyAndBundle
7
9
import java.util.UUID
8
10
9
11
/* *
@@ -38,7 +40,11 @@ internal class DialogSessionUpdate(
38
40
oldSessionFinder: OldSessionFinder ,
39
41
covered: Boolean
40
42
) -> DialogSession
41
- )
43
+ ) {
44
+ override fun toString (): String {
45
+ return " DialogSessionUpdate(overlay=${Compatible .keyFor(overlay)} )"
46
+ }
47
+ }
42
48
43
49
/* *
44
50
* Init method called at the start of [LayeredDialogSessions.update].
@@ -113,8 +119,7 @@ internal fun ViewEnvironment.establishDialogCollator(
113
119
* updates that were enqueued with the shared [DialogCollator] are executed in a single
114
120
* pass. Because this [DialogCollator] has complete knowledge of the existing stack
115
121
* of `Dialog` windows and all updates, it is able to decide if any existing instances need to be
116
- * [dismissed][android.app.Dialog.dismiss] and [re-shown][android.app.Dialog.show]
117
- * to keep them in the correct order.
122
+ * [destroyed][DialogSession.destroyDialog] and rebuilt to keep them in the correct order.
118
123
*/
119
124
@WorkflowUiExperimentalApi
120
125
internal class DialogCollator {
@@ -149,7 +154,11 @@ internal class DialogCollator {
149
154
val id : UUID ,
150
155
val updates : List <DialogSessionUpdate >,
151
156
val onSessionsUpdated : (List <DialogSession >) -> Unit
152
- )
157
+ ) {
158
+ override fun toString (): String {
159
+ return " IdAndUpdates(id=$id , updates=$updates )"
160
+ }
161
+ }
153
162
154
163
/* *
155
164
* The [IdAndUpdates] instances accumulated by all calls to [scheduleUpdates].
@@ -199,10 +208,6 @@ internal class DialogCollator {
199
208
.flatMap { it.sessions.map { session -> Pair (it.id, session) } }
200
209
.iterator()
201
210
202
- // Collects members of establishedSessions that are dismissed because they
203
- // are out of order, so that we can try to show them again.
204
- val hiddenSessions = mutableListOf<Pair <UUID , DialogSession >>()
205
-
206
211
// Z index of the uppermost ModalOverlay.
207
212
val topModalIndex = allUpdates.asSequence()
208
213
.flatMap { it.updates.asSequence().map { update -> update.overlay } }
@@ -212,14 +217,13 @@ internal class DialogCollator {
212
217
var updatingSessionIndex = 0
213
218
214
219
val allNewSessions = mutableListOf<DialogSession >()
220
+ val viewStates = mutableMapOf<String , KeyAndBundle >()
215
221
allUpdates.forEach { idAndUpdates ->
216
222
val updatedSessions = mutableListOf<DialogSession >()
217
223
218
224
// We're building an object that the next LayeredDialogSessions can use to
219
225
// find an existing dialog that matches a given Overlay. Any
220
- // incompatible dialog that we skip on the way to find a match is dismissed.
221
- // If we later find a match for one of the dismissed dialogs, it is re-shown --
222
- // which moves it to the front, ensuring the correct Z order.
226
+ // incompatible dialog that we skip on the way to find a match is destroyed.
223
227
val oldSessionFinder = OldSessionFinder { overlay ->
224
228
225
229
// First we iterate through the existing windows to find one that belongs
@@ -228,26 +232,23 @@ internal class DialogCollator {
228
232
val (id, session) = establishedSessionsIterator.next()
229
233
if (idAndUpdates.id == id && session.canShow(overlay)) return @OldSessionFinder session
230
234
231
- // Can't update this session from this Overlay. Dismiss it (via Dialog.dismiss
232
- // under the hood), but hold on to it in case it can except a later Overlay .
233
- session.setVisible( false )
234
- hiddenSessions.add( Pair (id, session) )
235
+ // Can't update this session from this Overlay, save its view state and destroy it.
236
+ // If it was just out of z order, a new one with matching id will be made and restored .
237
+ session.save()?. let { viewStates[id.toString() + session.savedStateKey] = it }
238
+ session.destroyDialog(saveViewState = true )
235
239
continue
236
240
}
237
241
238
- // There are no established windows left. See if any of the ones that were
239
- // dismissed because they were out of order can be shown again.
240
- return @OldSessionFinder hiddenSessions.indexOfFirst { (hiddenId, dialogSession) ->
241
- idAndUpdates.id == hiddenId && dialogSession.canShow(overlay)
242
- }.takeUnless { it == - 1 }?.let { compatibleIndex ->
243
- val restoredSession = hiddenSessions.removeAt(compatibleIndex).second
244
- restoredSession.apply { setVisible(true ) }
245
- }
242
+ // There are no established windows left.
243
+ return @OldSessionFinder null
246
244
}
247
245
248
246
idAndUpdates.updates.forEach { update ->
249
247
val covered = updatingSessionIndex < topModalIndex
250
- updatedSessions + = update.doUpdate(oldSessionFinder, covered)
248
+ updatedSessions + = update.doUpdate(oldSessionFinder, covered).also { session ->
249
+ viewStates.remove(idAndUpdates.id.toString() + session.savedStateKey)
250
+ ?.let { session.restore(it) }
251
+ }
251
252
updatingSessionIndex++
252
253
}
253
254
idAndUpdates.onSessionsUpdated(updatedSessions)
0 commit comments