diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt index 7baebf4ef600e..729fdfeb2ffba 100644 --- a/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt +++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt @@ -74,10 +74,19 @@ data class WithPrev(val previousValue: T, val newValue: T) /** * Returns a new [Flow] that combines the [Set] changes between each emission from [this] using * [transform]. + * + * If [emitFirstEvent] is `true`, then the first [Set] emitted from the upstream [Flow] will cause + * a change event to be emitted that contains no removals, and all elements from that first [Set] + * as additions. + * + * If [emitFirstEvent] is `false`, then the first emission is ignored and no changes are emitted + * until a second [Set] has been emitted from the upstream [Flow]. */ fun Flow>.setChangesBy( transform: suspend (removed: Set, added: Set) -> R, -): Flow = onStart { emit(emptySet()) }.distinctUntilChanged() + emitFirstEvent: Boolean = true, +): Flow = (if (emitFirstEvent) onStart { emit(emptySet()) } else this) + .distinctUntilChanged() .pairwiseBy { old: Set, new: Set -> // If an element was present in the old set, but not the new one, then it was removed val removed = old - new @@ -86,8 +95,18 @@ fun Flow>.setChangesBy( transform(removed, added) } -/** Returns a new [Flow] that produces the [Set] changes between each emission from [this]. */ -fun Flow>.setChanges(): Flow> = setChangesBy(::SetChanges) +/** + * Returns a new [Flow] that produces the [Set] changes between each emission from [this]. + * + * If [emitFirstEvent] is `true`, then the first [Set] emitted from the upstream [Flow] will cause + * a change event to be emitted that contains no removals, and all elements from that first [Set] + * as additions. + * + * If [emitFirstEvent] is `false`, then the first emission is ignored and no changes are emitted + * until a second [Set] has been emitted from the upstream [Flow]. + */ +fun Flow>.setChanges(emitFirstEvent: Boolean = true): Flow> = + setChangesBy(::SetChanges, emitFirstEvent) /** Contains the difference in elements between two [Set]s. */ data class SetChanges( diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt index 092e82c526e3c..460b71febc247 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt @@ -127,6 +127,17 @@ class SetChangesFlowTest : SysuiTestCase() { ) ) } + + @Test + fun dontEmitFirstEvent() = runBlocking { + assertThatFlow(flowOf(setOf(1, 2), setOf(2, 3)).setChanges(emitFirstEvent = false)) + .emitsExactly( + SetChanges( + removed = setOf(1), + added = setOf(3), + ) + ) + } } private fun assertThatFlow(flow: Flow) = object {