• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 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 package com.android.systemui.util.kotlin
18 
19 import android.content.Context
20 import kotlinx.coroutines.CoroutineScope
21 import kotlinx.coroutines.flow.Flow
22 import kotlinx.coroutines.flow.SharingStarted
23 import kotlinx.coroutines.flow.StateFlow
24 import kotlinx.coroutines.flow.combine
25 import kotlinx.coroutines.flow.filter
26 import kotlinx.coroutines.flow.map
27 import kotlinx.coroutines.flow.stateIn
28 
29 class Utils {
30     companion object {
31         fun <A, B, C> toTriple(a: A, bc: Pair<B, C>) = Triple(a, bc.first, bc.second)
32 
33         fun <A, B, C> toTriple(ab: Pair<A, B>, c: C) = Triple(ab.first, ab.second, c)
34 
35         fun <A, B, C, D> toQuad(a: A, b: B, c: C, d: D) = Quad(a, b, c, d)
36 
37         fun <A, B, C, D> toQuad(a: A, bcd: Triple<B, C, D>) =
38             Quad(a, bcd.first, bcd.second, bcd.third)
39 
40         fun <A, B, C, D> toQuad(abc: Triple<A, B, C>, d: D) =
41             Quad(abc.first, abc.second, abc.third, d)
42 
43         fun <A, B, C, D, E> toQuint(a: A, b: B, c: C, d: D, e: E) = Quint(a, b, c, d, e)
44 
45         fun <A, B, C, D, E> toQuint(a: A, bcde: Quad<B, C, D, E>) =
46             Quint(a, bcde.first, bcde.second, bcde.third, bcde.fourth)
47 
48         fun <A, B, C, D, E, F> toSextuple(a: A, bcdef: Quint<B, C, D, E, F>) =
49             Sextuple(a, bcdef.first, bcdef.second, bcdef.third, bcdef.fourth, bcdef.fifth)
50 
51         fun <A, B, C, D, E, F, G> toSeptuple(a: A, bcdefg: Sextuple<B, C, D, E, F, G>) =
52             Septuple(
53                 a,
54                 bcdefg.first,
55                 bcdefg.second,
56                 bcdefg.third,
57                 bcdefg.fourth,
58                 bcdefg.fifth,
59                 bcdefg.sixth,
60             )
61 
62         /**
63          * Samples the provided flow, performs a filter on the sampled value, then returns the
64          * original value.
65          */
66         fun <A, B> Flow<A>.sampleFilter(b: Flow<B>, predicate: (B) -> Boolean): Flow<A> {
67             return this.sample(b, ::Pair).filter { (_, b) -> predicate(b) }.map { (a, _) -> a }
68         }
69 
70         /**
71          * Samples the provided flows, emitting a tuple of the original flow's value as well as each
72          * of the combined flows' values.
73          *
74          * Flow<A>.sample(Flow<B>, Flow<C>) -> (A, B, C)
75          */
76         fun <A, B, C> Flow<A>.sample(b: Flow<B>, c: Flow<C>): Flow<Triple<A, B, C>> {
77             return this.sample(combine(b, c, ::Pair), ::toTriple)
78         }
79 
80         /**
81          * Samples the provided flows, emitting a tuple of the original flow's value as well as each
82          * of the combined flows' values.
83          *
84          * Flow<A>.sample(Flow<B>, Flow<C>, Flow<D>) -> (A, B, C, D)
85          */
86         fun <A, B, C, D> Flow<A>.sample(
87             b: Flow<B>,
88             c: Flow<C>,
89             d: Flow<D>,
90         ): Flow<Quad<A, B, C, D>> {
91             return this.sample(combine(b, c, d, ::Triple), ::toQuad)
92         }
93 
94         /**
95          * Samples the provided flows, emitting a tuple of the original flow's value as well as each
96          * of the combined flows' values.
97          *
98          * Flow<A>.sample(Flow<B>, Flow<C>, Flow<D>, Flow<E>) -> (A, B, C, D, E)
99          */
100         fun <A, B, C, D, E> Flow<A>.sample(
101             b: Flow<B>,
102             c: Flow<C>,
103             d: Flow<D>,
104             e: Flow<E>,
105         ): Flow<Quint<A, B, C, D, E>> {
106             return this.sample(combine(b, c, d, e, ::Quad), ::toQuint)
107         }
108 
109         /**
110          * Samples the provided flows, emitting a tuple of the original flow's value as well as each
111          * of the combined flows' values.
112          *
113          * Flow<A>.sample(Flow<B>, Flow<C>, Flow<D>, Flow<E>, Flow<F>) -> (A, B, C, D, E, F)
114          */
115         fun <A, B, C, D, E, F> Flow<A>.sample(
116             b: Flow<B>,
117             c: Flow<C>,
118             d: Flow<D>,
119             e: Flow<E>,
120             f: Flow<F>,
121         ): Flow<Sextuple<A, B, C, D, E, F>> {
122             return this.sample(combine(b, c, d, e, f, ::Quint), ::toSextuple)
123         }
124 
125         /**
126          * Samples the provided flows, emitting a tuple of the original flow's value as well as each
127          * of the combined flows' values.
128          *
129          * Flow<A>.sample(Flow<B>, Flow<C>, Flow<D>, Flow<E>, Flow<F>, Flow<G>) -> (A, B, C, D, E,
130          * F, G)
131          */
132         fun <A, B, C, D, E, F, G> Flow<A>.sample(
133             b: Flow<B>,
134             c: Flow<C>,
135             d: Flow<D>,
136             e: Flow<E>,
137             f: Flow<F>,
138             g: Flow<G>,
139         ): Flow<Septuple<A, B, C, D, E, F, G>> {
140             return this.sample(combine(b, c, d, e, f, g, ::Sextuple), ::toSeptuple)
141         }
142 
143         /**
144          * Combines 2 state flows, applying [transform] between the initial values to set the
145          * initial value of the resulting StateFlow.
146          */
147         fun <A, B, R> combineState(
148             f1: StateFlow<A>,
149             f2: StateFlow<B>,
150             scope: CoroutineScope,
151             sharingStarted: SharingStarted,
152             transform: (A, B) -> R,
153         ): StateFlow<R> =
154             combine(f1, f2) { a, b -> transform(a, b) }
155                 .stateIn(scope, sharingStarted, transform(f1.value, f2.value))
156     }
157 }
158 
159 data class Quad<A, B, C, D>(val first: A, val second: B, val third: C, val fourth: D)
160 
161 data class Quint<A, B, C, D, E>(
162     val first: A,
163     val second: B,
164     val third: C,
165     val fourth: D,
166     val fifth: E,
167 )
168 
169 data class Sextuple<A, B, C, D, E, F>(
170     val first: A,
171     val second: B,
172     val third: C,
173     val fourth: D,
174     val fifth: E,
175     val sixth: F,
176 )
177 
178 data class Septuple<A, B, C, D, E, F, G>(
179     val first: A,
180     val second: B,
181     val third: C,
182     val fourth: D,
183     val fifth: E,
184     val sixth: F,
185     val seventh: G,
186 )
187 
toPxnull188 fun Int.toPx(context: Context): Int {
189     return (this * context.resources.displayMetrics.density).toInt()
190 }
191 
toDpnull192 fun Int.toDp(context: Context): Int {
193     return (this / context.resources.displayMetrics.density).toInt()
194 }
195