1 /*
<lambda>null2  * 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 package com.google.jetpackcamera.feature.preview.ui
17 
18 import android.content.Context
19 import android.view.OrientationEventListener
20 import android.view.OrientationEventListener.ORIENTATION_UNKNOWN
21 import com.google.jetpackcamera.settings.model.DeviceRotation
22 import kotlin.math.abs
23 import kotlin.math.min
24 import kotlinx.coroutines.channels.Channel.Factory.CONFLATED
25 import kotlinx.coroutines.channels.awaitClose
26 import kotlinx.coroutines.flow.buffer
27 import kotlinx.coroutines.flow.callbackFlow
28 import kotlinx.coroutines.flow.distinctUntilChanged
29 import kotlinx.coroutines.flow.runningFold
30 
31 /** Orientation hysteresis amount used in rounding, in degrees. */
32 private const val ORIENTATION_HYSTERESIS = 5
33 
34 fun debouncedOrientationFlow(context: Context) = callbackFlow {
35     val orientationListener = object : OrientationEventListener(context) {
36         override fun onOrientationChanged(orientation: Int) {
37             trySend(orientation)
38         }
39     }
40 
41     orientationListener.enable()
42 
43     awaitClose {
44         orientationListener.disable()
45     }
46 }.buffer(capacity = CONFLATED)
prevSnapnull47     .runningFold(initial = DeviceRotation.Natural) { prevSnap, newDegrees ->
48         if (
49             newDegrees != ORIENTATION_UNKNOWN &&
50             abs(prevSnap.toClockwiseRotationDegrees() - newDegrees).let { min(it, 360 - it) } >=
51             45 + ORIENTATION_HYSTERESIS
52         ) {
53             DeviceRotation.snapFrom(newDegrees)
54         } else {
55             prevSnap
56         }
57     }.distinctUntilChanged()
58