1 /* 2 * 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 package com.android.systemui.unfold.data.repository 17 18 import androidx.annotation.FloatRange 19 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow 20 import com.android.systemui.unfold.UnfoldTransitionProgressProvider 21 import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionFinished 22 import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionInProgress 23 import com.android.systemui.unfold.data.repository.UnfoldTransitionStatus.TransitionStarted 24 import com.android.systemui.util.kotlin.getOrNull 25 import java.util.Optional 26 import javax.inject.Inject 27 import kotlinx.coroutines.channels.awaitClose 28 import kotlinx.coroutines.flow.Flow 29 import kotlinx.coroutines.flow.emptyFlow 30 31 /** Repository for fold/unfold transitions */ 32 interface UnfoldTransitionRepository { 33 /** Returns false if fold/unfold transitions are not available on this device */ 34 val isAvailable: Boolean 35 36 /** 37 * Emits current transition state on each transition change such as transition start or finish 38 * [UnfoldTransitionStatus] 39 */ 40 val transitionStatus: Flow<UnfoldTransitionStatus> 41 } 42 43 /** Transition event of fold/unfold transition */ 44 sealed class UnfoldTransitionStatus { 45 /** Status that is sent when fold or unfold transition is in started state */ 46 data object TransitionStarted : UnfoldTransitionStatus() 47 /** Status that is sent while fold or unfold transition is in progress */ 48 data class TransitionInProgress( 49 @FloatRange(from = 0.0, to = 1.0) val progress: Float, 50 ) : UnfoldTransitionStatus() 51 /** Status that is sent when fold or unfold transition is finished */ 52 data object TransitionFinished : UnfoldTransitionStatus() 53 } 54 55 class UnfoldTransitionRepositoryImpl 56 @Inject 57 constructor( 58 private val unfoldProgressProvider: Optional<UnfoldTransitionProgressProvider>, 59 ) : UnfoldTransitionRepository { 60 61 override val isAvailable: Boolean 62 get() = unfoldProgressProvider.isPresent 63 64 override val transitionStatus: Flow<UnfoldTransitionStatus> 65 get() { 66 val provider = unfoldProgressProvider.getOrNull() ?: return emptyFlow() 67 <lambda>null68 return conflatedCallbackFlow { 69 val callback = 70 object : UnfoldTransitionProgressProvider.TransitionProgressListener { 71 override fun onTransitionStarted() { 72 trySend(TransitionStarted) 73 } 74 75 override fun onTransitionProgress(progress: Float) { 76 trySend(TransitionInProgress(progress)) 77 } 78 79 override fun onTransitionFinished() { 80 trySend(TransitionFinished) 81 } 82 } 83 provider.addCallback(callback) 84 awaitClose { provider.removeCallback(callback) } 85 } 86 } 87 } 88