Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +77 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.FlagsParameterization import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.systemui.Flags.FLAG_GESTURE_BETWEEN_HUB_AND_LOCKSCREEN_MOTION import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2 import com.android.systemui.Flags.FLAG_LOCKSCREEN_SHADE_TO_DREAM_TRANSITION_FIX import com.android.systemui.Flags.FLAG_STATUS_BAR_FOR_DESKTOP Loading @@ -27,6 +29,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.communal.data.repository.communalSceneRepository import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.desktop.domain.interactor.enableUsingDesktopStatusBar Loading Loading @@ -79,6 +82,7 @@ import com.android.systemui.shade.shadeTestUtil import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel.Companion.PUSHBACK_SCALE import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel.HorizontalPosition import com.android.systemui.testKosmos import com.android.systemui.window.ui.viewmodel.fakeBouncerTransitions Loading Loading @@ -1618,6 +1622,79 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S assertThat(blurRadius).isEqualTo(40.0f) } @Test @DisableSceneContainer @EnableFlags(FLAG_GESTURE_BETWEEN_HUB_AND_LOCKSCREEN_MOTION) fun glanceableHubViewScale_transitionFromLockscreenToHubAndBack() = kosmos.runTest { val scale by collectLastValue(underTest.viewScale) showLockscreen() assertThat(scale).isEqualTo(1.0f) val transitionState: MutableStateFlow<ObservableTransitionState> = MutableStateFlow( ObservableTransitionState.Transition( fromScene = CommunalScenes.Blank, toScene = CommunalScenes.Communal, currentScene = flowOf(CommunalScenes.Blank), progress = flowOf(0f), isInitiatedByUserInput = true, isUserInputOngoing = flowOf(false), ) ) // Start transition to communal. communalSceneRepository.setTransitionState(transitionState) // Transition to the glanceable hub and back. keyguardTransitionRepository.sendTransitionSteps( from = LOCKSCREEN, to = GLANCEABLE_HUB, testScope, ) transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal) assertThat(scale).isEqualTo(1 - PUSHBACK_SCALE) // Start transitioning back. keyguardTransitionRepository.sendTransitionSteps( from = GLANCEABLE_HUB, to = LOCKSCREEN, testScope, ) transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Blank) assertThat(scale).isEqualTo(1f) } @Test @DisableSceneContainer @EnableFlags(FLAG_GESTURE_BETWEEN_HUB_AND_LOCKSCREEN_MOTION) fun glanceableHubViewScale_reset_transitionedAwayFromHub() = kosmos.runTest { val scale by collectLastValue(underTest.viewScale) val transitionState: MutableStateFlow<ObservableTransitionState> = MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Blank)) // Transition to the glanceable hub and then to bouncer. keyguardTransitionRepository.sendTransitionSteps( from = LOCKSCREEN, to = GLANCEABLE_HUB, testScope, ) transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal) keyguardTransitionRepository.sendTransitionSteps( from = GLANCEABLE_HUB, to = PRIMARY_BOUNCER, testScope, ) transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Blank) assertThat(scale).isEqualTo(1f) } private suspend fun Kosmos.showLockscreen() { shadeTestUtil.setQsExpansion(0f) shadeTestUtil.setLockscreenShadeExpansion(0f) Loading packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt +21 −17 Original line number Diff line number Diff line Loading @@ -59,9 +59,11 @@ import com.android.systemui.util.ui.AnimatableEvent import com.android.systemui.util.ui.AnimatedValue import com.android.systemui.util.ui.toAnimatedValueFlow import com.android.systemui.util.ui.zip import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated import java.util.Optional import javax.inject.Inject import kotlin.math.max import kotlin.math.round import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted Loading Loading @@ -236,26 +238,28 @@ constructor( if (!Flags.gestureBetweenHubAndLockscreenMotion()) { emptyFlow() } else { combine( communalInteractor.isCommunalVisible, // Use flatMapLatestConflated so the animation flows aren't collected at all when // communal is not visible. communalInteractor.isCommunalVisible.flatMapLatestConflated { isCommunalVisible -> if (!isCommunalVisible) { // reset zoom out once we've exited the communal scene flowOf(0f) } else { merge( lockscreenToGlanceableHubTransitionViewModel.zoomOut, glanceableHubToLockscreenTransitionViewModel.zoomOut, aodToGlanceableHubTransitionViewModel.zoomOut, glanceableHubToAodTransitionViewModel.zoomOut, ), ) { isCommunalVisible, zoomOut -> if (!isCommunalVisible) { // reset zoom out once we've exited the communal scene 0f } else { ) .map { // rate limit the zoom out by 5% step to avoid jank ((zoomOut * 20).toInt() / 20f).coerceIn(0f, 1f) (round(it * 20) / 20f).coerceIn(0f, 1f) } } } } .distinctUntilChanged() .dumpWhileCollecting("zoomOutFromGlanceableHub") } private fun dozingToLockscreenAlpha(viewState: ViewStateAccessor) = alphaOnShadeExpansion Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt +10 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.notification.stack.ui.viewbinder import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.app.tracing.coroutines.launchTraced as launch import com.android.systemui.Flags import com.android.systemui.common.ui.view.onLayoutChanged import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor Loading @@ -39,6 +38,7 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch /** Binds the shared notification container to its view-model. */ @SysUISingleton Loading Loading @@ -195,6 +195,15 @@ constructor( controller.setMaxAlphaForGlanceableHub(it) } } if (Flags.gestureBetweenHubAndLockscreenMotion()) { launch { viewModel.viewScale.collect { view.scaleX = it view.scaleY = it } } } } } } Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt +34 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.systemui.biometrics.Utils.getInsetsOf import com.android.systemui.bouncer.domain.interactor.BouncerInteractor import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application Loading Loading @@ -106,8 +107,10 @@ import com.android.systemui.util.kotlin.FlowDumperImpl import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine import com.android.systemui.util.kotlin.sample import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated import dagger.Lazy import javax.inject.Inject import kotlin.math.round import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.awaitClose Loading Loading @@ -143,6 +146,7 @@ constructor( @Application applicationScope: CoroutineScope, @ShadeDisplayAware private val context: Context, @ShadeDisplayAware configurationInteractor: ConfigurationInteractor, communalInteractor: CommunalInteractor, private val keyguardInteractor: KeyguardInteractor, private val keyguardTransitionInteractor: KeyguardTransitionInteractor, private val shadeInteractor: ShadeInteractor, Loading Loading @@ -762,6 +766,32 @@ constructor( .merge() .dumpWhileCollecting("blurRadius") /** * Flow of view scale values for the zoom animation between the lockscreen and glanceable hub. * 1.0f means no visual change to the view. */ val viewScale: Flow<Float> = // Use flatMapLatestConflated so the animation flows aren't collected at all when communal // is not visible. communalInteractor.isCommunalVisible .flatMapLatestConflated { isCommunalVisible -> if (!isCommunalVisible) { flowOf(1f) } else { merge( lockscreenToGlanceableHubTransitionViewModel.zoomOut, glanceableHubToLockscreenTransitionViewModel.zoomOut, ) .map { // Rate limit the zoom out by 5% step to avoid jank. val limited = (round(it * 20) / 20f).coerceIn(0f, 1f) 1 - limited * PUSHBACK_SCALE } } } .distinctUntilChanged() .dumpWhileCollecting("viewScale") /** * Returns a flow of the expected alpha while running a LOCKSCREEN<->GLANCEABLE_HUB or * DREAMING<->GLANCEABLE_HUB transition or idle on the hub. Loading Loading @@ -1009,4 +1039,8 @@ constructor( */ data class MiddleToEdge(val maxWidth: Int = Int.MAX_VALUE) : HorizontalPosition } companion object { @VisibleForTesting const val PUSHBACK_SCALE = 0.05f } } packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt +2 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import android.content.applicationContext import com.android.systemui.bouncer.domain.interactor.bouncerInteractor import com.android.systemui.common.ui.domain.interactor.configurationInteractor import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.dump.dumpManager import com.android.systemui.keyguard.domain.interactor.keyguardInteractor Loading Loading @@ -75,6 +76,7 @@ val Kosmos.sharedNotificationContainerViewModel by Fixture { applicationScope = applicationCoroutineScope, context = applicationContext, configurationInteractor = configurationInteractor, communalInteractor = communalInteractor, keyguardInteractor = keyguardInteractor, keyguardTransitionInteractor = keyguardTransitionInteractor, shadeInteractor = shadeInteractor, Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +77 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.FlagsParameterization import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.systemui.Flags.FLAG_GESTURE_BETWEEN_HUB_AND_LOCKSCREEN_MOTION import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2 import com.android.systemui.Flags.FLAG_LOCKSCREEN_SHADE_TO_DREAM_TRANSITION_FIX import com.android.systemui.Flags.FLAG_STATUS_BAR_FOR_DESKTOP Loading @@ -27,6 +29,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.communal.data.repository.communalSceneRepository import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.desktop.domain.interactor.enableUsingDesktopStatusBar Loading Loading @@ -79,6 +82,7 @@ import com.android.systemui.shade.shadeTestUtil import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel.Companion.PUSHBACK_SCALE import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel.HorizontalPosition import com.android.systemui.testKosmos import com.android.systemui.window.ui.viewmodel.fakeBouncerTransitions Loading Loading @@ -1618,6 +1622,79 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S assertThat(blurRadius).isEqualTo(40.0f) } @Test @DisableSceneContainer @EnableFlags(FLAG_GESTURE_BETWEEN_HUB_AND_LOCKSCREEN_MOTION) fun glanceableHubViewScale_transitionFromLockscreenToHubAndBack() = kosmos.runTest { val scale by collectLastValue(underTest.viewScale) showLockscreen() assertThat(scale).isEqualTo(1.0f) val transitionState: MutableStateFlow<ObservableTransitionState> = MutableStateFlow( ObservableTransitionState.Transition( fromScene = CommunalScenes.Blank, toScene = CommunalScenes.Communal, currentScene = flowOf(CommunalScenes.Blank), progress = flowOf(0f), isInitiatedByUserInput = true, isUserInputOngoing = flowOf(false), ) ) // Start transition to communal. communalSceneRepository.setTransitionState(transitionState) // Transition to the glanceable hub and back. keyguardTransitionRepository.sendTransitionSteps( from = LOCKSCREEN, to = GLANCEABLE_HUB, testScope, ) transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal) assertThat(scale).isEqualTo(1 - PUSHBACK_SCALE) // Start transitioning back. keyguardTransitionRepository.sendTransitionSteps( from = GLANCEABLE_HUB, to = LOCKSCREEN, testScope, ) transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Blank) assertThat(scale).isEqualTo(1f) } @Test @DisableSceneContainer @EnableFlags(FLAG_GESTURE_BETWEEN_HUB_AND_LOCKSCREEN_MOTION) fun glanceableHubViewScale_reset_transitionedAwayFromHub() = kosmos.runTest { val scale by collectLastValue(underTest.viewScale) val transitionState: MutableStateFlow<ObservableTransitionState> = MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Blank)) // Transition to the glanceable hub and then to bouncer. keyguardTransitionRepository.sendTransitionSteps( from = LOCKSCREEN, to = GLANCEABLE_HUB, testScope, ) transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal) keyguardTransitionRepository.sendTransitionSteps( from = GLANCEABLE_HUB, to = PRIMARY_BOUNCER, testScope, ) transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Blank) assertThat(scale).isEqualTo(1f) } private suspend fun Kosmos.showLockscreen() { shadeTestUtil.setQsExpansion(0f) shadeTestUtil.setLockscreenShadeExpansion(0f) Loading
packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt +21 −17 Original line number Diff line number Diff line Loading @@ -59,9 +59,11 @@ import com.android.systemui.util.ui.AnimatableEvent import com.android.systemui.util.ui.AnimatedValue import com.android.systemui.util.ui.toAnimatedValueFlow import com.android.systemui.util.ui.zip import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated import java.util.Optional import javax.inject.Inject import kotlin.math.max import kotlin.math.round import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted Loading Loading @@ -236,26 +238,28 @@ constructor( if (!Flags.gestureBetweenHubAndLockscreenMotion()) { emptyFlow() } else { combine( communalInteractor.isCommunalVisible, // Use flatMapLatestConflated so the animation flows aren't collected at all when // communal is not visible. communalInteractor.isCommunalVisible.flatMapLatestConflated { isCommunalVisible -> if (!isCommunalVisible) { // reset zoom out once we've exited the communal scene flowOf(0f) } else { merge( lockscreenToGlanceableHubTransitionViewModel.zoomOut, glanceableHubToLockscreenTransitionViewModel.zoomOut, aodToGlanceableHubTransitionViewModel.zoomOut, glanceableHubToAodTransitionViewModel.zoomOut, ), ) { isCommunalVisible, zoomOut -> if (!isCommunalVisible) { // reset zoom out once we've exited the communal scene 0f } else { ) .map { // rate limit the zoom out by 5% step to avoid jank ((zoomOut * 20).toInt() / 20f).coerceIn(0f, 1f) (round(it * 20) / 20f).coerceIn(0f, 1f) } } } } .distinctUntilChanged() .dumpWhileCollecting("zoomOutFromGlanceableHub") } private fun dozingToLockscreenAlpha(viewState: ViewStateAccessor) = alphaOnShadeExpansion Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt +10 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.notification.stack.ui.viewbinder import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.app.tracing.coroutines.launchTraced as launch import com.android.systemui.Flags import com.android.systemui.common.ui.view.onLayoutChanged import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor Loading @@ -39,6 +38,7 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch /** Binds the shared notification container to its view-model. */ @SysUISingleton Loading Loading @@ -195,6 +195,15 @@ constructor( controller.setMaxAlphaForGlanceableHub(it) } } if (Flags.gestureBetweenHubAndLockscreenMotion()) { launch { viewModel.viewScale.collect { view.scaleX = it view.scaleY = it } } } } } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt +34 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.systemui.biometrics.Utils.getInsetsOf import com.android.systemui.bouncer.domain.interactor.BouncerInteractor import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application Loading Loading @@ -106,8 +107,10 @@ import com.android.systemui.util.kotlin.FlowDumperImpl import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine import com.android.systemui.util.kotlin.sample import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated import dagger.Lazy import javax.inject.Inject import kotlin.math.round import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.awaitClose Loading Loading @@ -143,6 +146,7 @@ constructor( @Application applicationScope: CoroutineScope, @ShadeDisplayAware private val context: Context, @ShadeDisplayAware configurationInteractor: ConfigurationInteractor, communalInteractor: CommunalInteractor, private val keyguardInteractor: KeyguardInteractor, private val keyguardTransitionInteractor: KeyguardTransitionInteractor, private val shadeInteractor: ShadeInteractor, Loading Loading @@ -762,6 +766,32 @@ constructor( .merge() .dumpWhileCollecting("blurRadius") /** * Flow of view scale values for the zoom animation between the lockscreen and glanceable hub. * 1.0f means no visual change to the view. */ val viewScale: Flow<Float> = // Use flatMapLatestConflated so the animation flows aren't collected at all when communal // is not visible. communalInteractor.isCommunalVisible .flatMapLatestConflated { isCommunalVisible -> if (!isCommunalVisible) { flowOf(1f) } else { merge( lockscreenToGlanceableHubTransitionViewModel.zoomOut, glanceableHubToLockscreenTransitionViewModel.zoomOut, ) .map { // Rate limit the zoom out by 5% step to avoid jank. val limited = (round(it * 20) / 20f).coerceIn(0f, 1f) 1 - limited * PUSHBACK_SCALE } } } .distinctUntilChanged() .dumpWhileCollecting("viewScale") /** * Returns a flow of the expected alpha while running a LOCKSCREEN<->GLANCEABLE_HUB or * DREAMING<->GLANCEABLE_HUB transition or idle on the hub. Loading Loading @@ -1009,4 +1039,8 @@ constructor( */ data class MiddleToEdge(val maxWidth: Int = Int.MAX_VALUE) : HorizontalPosition } companion object { @VisibleForTesting const val PUSHBACK_SCALE = 0.05f } }
packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt +2 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import android.content.applicationContext import com.android.systemui.bouncer.domain.interactor.bouncerInteractor import com.android.systemui.common.ui.domain.interactor.configurationInteractor import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.dump.dumpManager import com.android.systemui.keyguard.domain.interactor.keyguardInteractor Loading Loading @@ -75,6 +76,7 @@ val Kosmos.sharedNotificationContainerViewModel by Fixture { applicationScope = applicationCoroutineScope, context = applicationContext, configurationInteractor = configurationInteractor, communalInteractor = communalInteractor, keyguardInteractor = keyguardInteractor, keyguardTransitionInteractor = keyguardTransitionInteractor, shadeInteractor = shadeInteractor, Loading