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.flow.Flow
21 import kotlinx.coroutines.flow.combine
22 import kotlinx.coroutines.flow.filter
23 import kotlinx.coroutines.flow.map
24 
25 class Utils {
26     companion object {
27         fun <A, B, C> toTriple(a: A, bc: Pair<B, C>) = Triple(a, bc.first, bc.second)
28 
29         fun <A, B, C> toTriple(ab: Pair<A, B>, c: C) = Triple(ab.first, ab.second, c)
30 
31         fun <A, B, C, D> toQuad(a: A, b: B, c: C, d: D) = Quad(a, b, c, d)
32 
33         fun <A, B, C, D> toQuad(a: A, bcd: Triple<B, C, D>) =
34             Quad(a, bcd.first, bcd.second, bcd.third)
35         fun <A, B, C, D> toQuad(abc: Triple<A, B, C>, d: D) =
36             Quad(abc.first, abc.second, abc.third, d)
37 
38         fun <A, B, C, D, E> toQuint(a: A, b: B, c: C, d: D, e: E) = Quint(a, b, c, d, e)
39 
40         fun <A, B, C, D, E> toQuint(a: A, bcde: Quad<B, C, D, E>) =
41             Quint(a, bcde.first, bcde.second, bcde.third, bcde.fourth)
42 
43         fun <A, B, C, D, E, F> toSextuple(a: A, bcdef: Quint<B, C, D, E, F>) =
44             Sextuple(a, bcdef.first, bcdef.second, bcdef.third, bcdef.fourth, bcdef.fifth)
45 
46         fun <A, B, C, D, E, F, G> toSeptuple(a: A, bcdefg: Sextuple<B, C, D, E, F, G>) =
47             Septuple(
48                 a,
49                 bcdefg.first,
50                 bcdefg.second,
51                 bcdefg.third,
52                 bcdefg.fourth,
53                 bcdefg.fifth,
54                 bcdefg.sixth
55             )
56 
57         /**
58          * Samples the provided flow, performs a filter on the sampled value, then returns the
59          * original value.
60          */
61         fun <A, B> Flow<A>.sampleFilter(b: Flow<B>, predicate: (B) -> Boolean): Flow<A> {
62             return this.sample(b, ::Pair).filter { (_, b) -> predicate(b) }.map { (a, _) -> a }
63         }
64 
65         /**
66          * Samples the provided flows, emitting a tuple of the original flow's value as well as each
67          * of the combined flows' values.
68          *
69          * Flow<A>.sample(Flow<B>, Flow<C>) -> (A, B, C)
70          */
71         fun <A, B, C> Flow<A>.sample(b: Flow<B>, c: Flow<C>): Flow<Triple<A, B, C>> {
72             return this.sample(combine(b, c, ::Pair), ::toTriple)
73         }
74 
75         /**
76          * Samples the provided flows, emitting a tuple of the original flow's value as well as each
77          * of the combined flows' values.
78          *
79          * Flow<A>.sample(Flow<B>, Flow<C>, Flow<D>) -> (A, B, C, D)
80          */
81         fun <A, B, C, D> Flow<A>.sample(
82             b: Flow<B>,
83             c: Flow<C>,
84             d: Flow<D>
85         ): Flow<Quad<A, B, C, D>> {
86             return this.sample(combine(b, c, d, ::Triple), ::toQuad)
87         }
88 
89         /**
90          * Samples the provided flows, emitting a tuple of the original flow's value as well as each
91          * of the combined flows' values.
92          *
93          * Flow<A>.sample(Flow<B>, Flow<C>, Flow<D>, Flow<E>) -> (A, B, C, D, E)
94          */
95         fun <A, B, C, D, E> Flow<A>.sample(
96             b: Flow<B>,
97             c: Flow<C>,
98             d: Flow<D>,
99             e: Flow<E>,
100         ): Flow<Quint<A, B, C, D, E>> {
101             return this.sample(combine(b, c, d, e, ::Quad), ::toQuint)
102         }
103 
104         /**
105          * Samples the provided flows, emitting a tuple of the original flow's value as well as each
106          * of the combined flows' values.
107          *
108          * Flow<A>.sample(Flow<B>, Flow<C>, Flow<D>, Flow<E>, Flow<F>) -> (A, B, C, D, E, F)
109          */
110         fun <A, B, C, D, E, F> Flow<A>.sample(
111             b: Flow<B>,
112             c: Flow<C>,
113             d: Flow<D>,
114             e: Flow<E>,
115             f: Flow<F>,
116         ): Flow<Sextuple<A, B, C, D, E, F>> {
117             return this.sample(combine(b, c, d, e, f, ::Quint), ::toSextuple)
118         }
119 
120         /**
121          * Samples the provided flows, emitting a tuple of the original flow's value as well as each
122          * of the combined flows' values.
123          *
124          * Flow<A>.sample(Flow<B>, Flow<C>, Flow<D>, Flow<E>, Flow<F>, Flow<G>) -> (A, B, C, D, E,
125          * F, G)
126          */
127         fun <A, B, C, D, E, F, G> Flow<A>.sample(
128             b: Flow<B>,
129             c: Flow<C>,
130             d: Flow<D>,
131             e: Flow<E>,
132             f: Flow<F>,
133             g: Flow<G>,
134         ): Flow<Septuple<A, B, C, D, E, F, G>> {
135             return this.sample(combine(b, c, d, e, f, g, ::Sextuple), ::toSeptuple)
136         }
137     }
138 }
139 
140 data class Quad<A, B, C, D>(val first: A, val second: B, val third: C, val fourth: D)
141 
142 data class Quint<A, B, C, D, E>(
143     val first: A,
144     val second: B,
145     val third: C,
146     val fourth: D,
147     val fifth: E
148 )
149 
150 data class Sextuple<A, B, C, D, E, F>(
151     val first: A,
152     val second: B,
153     val third: C,
154     val fourth: D,
155     val fifth: E,
156     val sixth: F,
157 )
158 
159 data class Septuple<A, B, C, D, E, F, G>(
160     val first: A,
161     val second: B,
162     val third: C,
163     val fourth: D,
164     val fifth: E,
165     val sixth: F,
166     val seventh: G,
167 )
168 
toPxnull169 fun Int.toPx(context: Context): Int {
170     return (this * context.resources.displayMetrics.density).toInt()
171 }
172 
toDpnull173 fun Int.toDp(context: Context): Int {
174     return (this / context.resources.displayMetrics.density).toInt()
175 }
176