1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 @file:OptIn(ExperimentalCoroutinesApi::class, ExperimentalTypeInference::class)
18 
19 package com.android.systemui.utils.coroutines.flow
20 
21 import kotlin.experimental.ExperimentalTypeInference
22 import kotlinx.coroutines.ExperimentalCoroutinesApi
23 import kotlinx.coroutines.flow.Flow
24 import kotlinx.coroutines.flow.FlowCollector
25 import kotlinx.coroutines.flow.conflate
26 import kotlinx.coroutines.flow.flatMapLatest
27 import kotlinx.coroutines.flow.mapLatest
28 import kotlinx.coroutines.flow.transformLatest
29 
30 /**
31  * Returns a flow that emits elements from the original flow transformed by [transform] function.
32  * When the original flow emits a new value, computation of the [transform] block for previous value
33  * is cancelled.
34  *
35  * For example, the following flow:
36  * ```
37  * flow {
38  *     emit("a")
39  *     delay(100)
40  *     emit("b")
41  * }.mapLatest { value ->
42  *     println("Started computing $value")
43  *     delay(200)
44  *     "Computed $value"
45  * }
46  * ```
47  *
48  * will print "Started computing a" and "Started computing b", but the resulting flow will contain
49  * only "Computed b" value.
50  *
51  * This operator is [conflated][conflate] by default, and as such should be preferred over usage of
52  * [mapLatest], due to the latter's default configuration of using an internal buffer, negatively
53  * impacting system health.
54  *
55  * @see mapLatest
56  */
mapLatestConflatednull57 fun <T, R> Flow<T>.mapLatestConflated(@BuilderInference transform: suspend (T) -> R): Flow<R> =
58     mapLatest(transform).conflate()
59 
60 /**
61  * Returns a flow that switches to a new flow produced by [transform] function every time the
62  * original flow emits a value. When the original flow emits a new value, the previous flow produced
63  * by `transform` block is cancelled.
64  *
65  * For example, the following flow:
66  * ```
67  * flow {
68  *     emit("a")
69  *     delay(100)
70  *     emit("b")
71  * }.flatMapLatest { value ->
72  *     flow {
73  *         emit(value)
74  *         delay(200)
75  *         emit(value + "_last")
76  *     }
77  * }
78  * ```
79  *
80  * produces `a b b_last`
81  *
82  * This operator is [conflated][conflate] by default, and as such should be preferred over usage of
83  * [flatMapLatest], due to the latter's default configuration of using an internal buffer,
84  * negatively impacting system health.
85  *
86  * @see flatMapLatest
87  */
88 fun <T, R> Flow<T>.flatMapLatestConflated(
89     @BuilderInference transform: suspend (T) -> Flow<R>,
90 ): Flow<R> = flatMapLatest(transform).conflate()
91 
92 /**
93  * Returns a flow that produces element by [transform] function every time the original flow emits a
94  * value. When the original flow emits a new value, the previous `transform` block is cancelled,
95  * thus the name `transformLatest`.
96  *
97  * For example, the following flow:
98  * ```
99  * flow {
100  *     emit("a")
101  *     delay(100)
102  *     emit("b")
103  * }.transformLatest { value ->
104  *     emit(value)
105  *     delay(200)
106  *     emit(value + "_last")
107  * }
108  * ```
109  *
110  * produces `a b b_last`.
111  *
112  * This operator is [conflated][conflate] by default, and as such should be preferred over usage of
113  * [transformLatest], due to the latter's default configuration of using an internal buffer,
114  * negatively impacting system health.
115  *
116  * @see transformLatest
117  */
118 fun <T, R> Flow<T>.transformLatestConflated(
119     @BuilderInference transform: suspend FlowCollector<R>.(T) -> Unit,
120 ): Flow<R> = transformLatest(transform).conflate()
121