diff options
| author | 2024-08-14 01:56:08 +0000 | |
|---|---|---|
| committer | 2024-08-14 01:56:08 +0000 | |
| commit | d3e206a85bba7c3cb0e15c8bac06b49829bc0dd0 (patch) | |
| tree | 2c7bfead7e6861e0a13b09eea47ce0dbbffed2cf | |
| parent | cd6cccb57223f88b63677a110daef8792fa55b5d (diff) | |
| parent | c1b875b54c6406f03fefa8ea778933736585f151 (diff) | |
Merge "[flexiglass] QS scene view-model is a SysUiViewModel" into main
| -rw-r--r-- | packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt | 21 | ||||
| -rw-r--r-- | packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt (renamed from packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt) | 98 | ||||
| -rw-r--r-- | packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModelTest.kt | 126 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt | 88 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt (renamed from packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt) | 66 |
5 files changed, 266 insertions, 133 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt index 12edd049c0e1..9db8bf14e5e0 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt @@ -92,7 +92,8 @@ import com.android.systemui.notifications.ui.composable.NotificationStackCutoffG import com.android.systemui.qs.footer.ui.compose.FooterActionsWithAnimatedVisibility import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaLandscapeTopOffset import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaOffset.InQS -import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneViewModel +import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneActionsViewModel +import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneContentViewModel import com.android.systemui.res.R import com.android.systemui.scene.session.ui.composable.SaveableSession import com.android.systemui.scene.shared.model.Scenes @@ -120,8 +121,9 @@ class QuickSettingsScene constructor( private val shadeSession: SaveableSession, private val notificationStackScrollView: Lazy<NotificationScrollView>, - private val viewModel: QuickSettingsSceneViewModel, private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory, + private val actionsViewModelFactory: QuickSettingsSceneActionsViewModel.Factory, + private val contentViewModelFactory: QuickSettingsSceneContentViewModel.Factory, private val tintedIconManagerFactory: TintedIconManager.Factory, private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory, private val statusBarIconController: StatusBarIconController, @@ -130,8 +132,16 @@ constructor( ) : ComposableScene { override val key = Scenes.QuickSettings + private val actionsViewModel: QuickSettingsSceneActionsViewModel by lazy { + actionsViewModelFactory.create() + } + override val destinationScenes: Flow<Map<UserAction, UserActionResult>> = - viewModel.destinationScenes + actionsViewModel.actions + + override suspend fun activate() { + actionsViewModel.activate() + } @Composable override fun SceneScope.Content( @@ -139,7 +149,7 @@ constructor( ) { QuickSettingsScene( notificationStackScrollView = notificationStackScrollView.get(), - viewModel = viewModel, + viewModelFactory = contentViewModelFactory, notificationsPlaceholderViewModel = rememberViewModel { notificationsPlaceholderViewModelFactory.create() }, createTintedIconManager = tintedIconManagerFactory::create, @@ -156,7 +166,7 @@ constructor( @Composable private fun SceneScope.QuickSettingsScene( notificationStackScrollView: NotificationScrollView, - viewModel: QuickSettingsSceneViewModel, + viewModelFactory: QuickSettingsSceneContentViewModel.Factory, notificationsPlaceholderViewModel: NotificationsPlaceholderViewModel, createTintedIconManager: (ViewGroup, StatusBarLocation) -> TintedIconManager, createBatteryMeterViewController: (ViewGroup, StatusBarLocation) -> BatteryMeterViewController, @@ -168,6 +178,7 @@ private fun SceneScope.QuickSettingsScene( ) { val cutoutLocation = LocalDisplayCutout.current.location + val viewModel = rememberViewModel { viewModelFactory.create() } val brightnessMirrorViewModel = rememberViewModel { viewModel.brightnessMirrorViewModelFactory.create() } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt index 036380853a71..f26a9db56450 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt @@ -36,11 +36,7 @@ import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintA import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.testScope -import com.android.systemui.media.controls.data.repository.mediaFilterRepository -import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor -import com.android.systemui.media.controls.shared.model.MediaData -import com.android.systemui.qs.FooterActionsController -import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel +import com.android.systemui.lifecycle.activateIn import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneBackInteractor @@ -49,41 +45,29 @@ import com.android.systemui.scene.domain.resolver.homeSceneFamilyResolver import com.android.systemui.scene.domain.startable.sceneContainerStartable import com.android.systemui.scene.shared.model.SceneFamilies import com.android.systemui.scene.shared.model.Scenes -import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModelFactory -import com.android.systemui.shade.ui.viewmodel.shadeHeaderViewModelFactory import com.android.systemui.testKosmos -import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock -import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mockito.times -import org.mockito.Mockito.verify @SmallTest @RunWith(AndroidJUnit4::class) @RunWithLooper @EnableSceneContainer -class QuickSettingsSceneViewModelTest : SysuiTestCase() { +class QuickSettingsSceneActionsViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope private val qsFlexiglassAdapter = FakeQSSceneAdapter({ mock() }) - private val footerActionsViewModel = mock<FooterActionsViewModel>() - private val footerActionsViewModelFactory = - mock<FooterActionsViewModel.Factory> { - whenever(create(any())).thenReturn(footerActionsViewModel) - } - private val footerActionsController = mock<FooterActionsController>() private val sceneInteractor = kosmos.sceneInteractor private val sceneBackInteractor = kosmos.sceneBackInteractor private val sceneContainerStartable = kosmos.sceneContainerStartable - private lateinit var underTest: QuickSettingsSceneViewModel + private lateinit var underTest: QuickSettingsSceneActionsViewModel @Before fun setUp() { @@ -91,22 +75,18 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { sceneContainerStartable.start() underTest = - QuickSettingsSceneViewModel( - brightnessMirrorViewModelFactory = kosmos.brightnessMirrorViewModelFactory, - shadeHeaderViewModelFactory = kosmos.shadeHeaderViewModelFactory, + QuickSettingsSceneActionsViewModel( qsSceneAdapter = qsFlexiglassAdapter, - footerActionsViewModelFactory = footerActionsViewModelFactory, - footerActionsController = footerActionsController, sceneBackInteractor = sceneBackInteractor, - mediaCarouselInteractor = kosmos.mediaCarouselInteractor, ) + underTest.activateIn(testScope) } @Test fun destinations_whenNotCustomizing_unlocked() = testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, false) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene) qsFlexiglassAdapter.setCustomizing(false) kosmos.fakeAuthenticationRepository.setAuthenticationMethod( @@ -116,7 +96,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { SuccessFingerprintAuthenticationStatus(0, true) ) - assertThat(destinations) + assertThat(actions) .isEqualTo( mapOf( Back to UserActionResult(Scenes.Shade), @@ -135,7 +115,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, false) qsFlexiglassAdapter.setCustomizing(false) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) val currentScene by collectLastValue(sceneInteractor.currentScene) val backScene by collectLastValue(sceneBackInteractor.backScene) @@ -145,7 +125,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(Scenes.QuickSettings) assertThat(backScene).isEqualTo(Scenes.Lockscreen) - assertThat(destinations) + assertThat(actions) .isEqualTo( mapOf( Back to UserActionResult(Scenes.Lockscreen), @@ -164,7 +144,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, false) qsFlexiglassAdapter.setCustomizing(false) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) val currentScene by collectLastValue(sceneInteractor.currentScene) val backScene by collectLastValue(sceneBackInteractor.backScene) @@ -176,7 +156,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(Scenes.Gone) assertThat(backScene).isNull() - assertThat(destinations) + assertThat(actions) .isEqualTo( mapOf( Back to UserActionResult(Scenes.Shade), @@ -194,7 +174,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { fun destinations_whenNotCustomizing_authMethodSwipe_lockscreenNotDismissed() = testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, false) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene) qsFlexiglassAdapter.setCustomizing(false) kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true) @@ -202,7 +182,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { AuthenticationMethodModel.None ) - assertThat(destinations) + assertThat(actions) .isEqualTo( mapOf( Back to UserActionResult(Scenes.Shade), @@ -220,17 +200,17 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { fun destinations_whenCustomizing_noDestinations() = testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, false) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) qsFlexiglassAdapter.setCustomizing(true) - assertThat(destinations).isEmpty() + assertThat(actions).isEmpty() } @Test fun destinations_whenNotCustomizing_inSplitShade_unlocked() = testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, true) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene) qsFlexiglassAdapter.setCustomizing(false) kosmos.fakeAuthenticationRepository.setAuthenticationMethod( @@ -240,7 +220,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { SuccessFingerprintAuthenticationStatus(0, true) ) - assertThat(destinations) + assertThat(actions) .isEqualTo( mapOf( Back to UserActionResult(Scenes.Shade), @@ -258,49 +238,9 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { fun destinations_whenCustomizing_inSplitShade_noDestinations() = testScope.runTest { overrideResource(R.bool.config_use_split_notification_shade, true) - val destinations by collectLastValue(underTest.destinationScenes) + val actions by collectLastValue(underTest.actions) qsFlexiglassAdapter.setCustomizing(true) - assertThat(destinations).isEmpty() - } - - @Test - fun gettingViewModelInitializesControllerOnlyOnce() { - underTest.getFooterActionsViewModel(mock()) - underTest.getFooterActionsViewModel(mock()) - - verify(footerActionsController, times(1)).init() - } - - @Test - fun addAndRemoveMedia_mediaVisibilityIsUpdated() = - testScope.runTest { - kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false) - val isMediaVisible by collectLastValue(underTest.isMediaVisible) - val userMedia = MediaData(active = true) - - assertThat(isMediaVisible).isFalse() - - kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) - - assertThat(isMediaVisible).isTrue() - - kosmos.mediaFilterRepository.removeSelectedUserMediaEntry(userMedia.instanceId) - - assertThat(isMediaVisible).isFalse() - } - - @Test - fun addInactiveMedia_mediaVisibilityIsUpdated() = - testScope.runTest { - kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false) - val isMediaVisible by collectLastValue(underTest.isMediaVisible) - val userMedia = MediaData(active = false) - - assertThat(isMediaVisible).isFalse() - - kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) - - assertThat(isMediaVisible).isTrue() + assertThat(actions).isEmpty() } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModelTest.kt new file mode 100644 index 000000000000..956353845506 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModelTest.kt @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.ui.viewmodel + +import android.testing.TestableLooper.RunWithLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.EnableSceneContainer +import com.android.systemui.flags.Flags +import com.android.systemui.flags.fakeFeatureFlagsClassic +import com.android.systemui.kosmos.testScope +import com.android.systemui.lifecycle.activateIn +import com.android.systemui.media.controls.data.repository.mediaFilterRepository +import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor +import com.android.systemui.media.controls.shared.model.MediaData +import com.android.systemui.qs.FooterActionsController +import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel +import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter +import com.android.systemui.scene.domain.startable.sceneContainerStartable +import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModelFactory +import com.android.systemui.shade.ui.viewmodel.shadeHeaderViewModelFactory +import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.whenever +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.times +import org.mockito.Mockito.verify + +@SmallTest +@RunWith(AndroidJUnit4::class) +@RunWithLooper +@EnableSceneContainer +class QuickSettingsSceneContentViewModelTest : SysuiTestCase() { + + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val qsFlexiglassAdapter = FakeQSSceneAdapter({ mock() }) + private val footerActionsViewModel = mock<FooterActionsViewModel>() + private val footerActionsViewModelFactory = + mock<FooterActionsViewModel.Factory> { + whenever(create(any())).thenReturn(footerActionsViewModel) + } + private val footerActionsController = mock<FooterActionsController>() + + private val sceneContainerStartable = kosmos.sceneContainerStartable + + private lateinit var underTest: QuickSettingsSceneContentViewModel + + @Before + fun setUp() { + kosmos.fakeFeatureFlagsClassic.set(Flags.NEW_NETWORK_SLICE_UI, false) + + sceneContainerStartable.start() + underTest = + QuickSettingsSceneContentViewModel( + brightnessMirrorViewModelFactory = kosmos.brightnessMirrorViewModelFactory, + shadeHeaderViewModelFactory = kosmos.shadeHeaderViewModelFactory, + qsSceneAdapter = qsFlexiglassAdapter, + footerActionsViewModelFactory = footerActionsViewModelFactory, + footerActionsController = footerActionsController, + mediaCarouselInteractor = kosmos.mediaCarouselInteractor, + ) + underTest.activateIn(testScope) + } + + @Test + fun gettingViewModelInitializesControllerOnlyOnce() { + underTest.getFooterActionsViewModel(mock()) + underTest.getFooterActionsViewModel(mock()) + + verify(footerActionsController, times(1)).init() + } + + @Test + fun addAndRemoveMedia_mediaVisibilityIsUpdated() = + testScope.runTest { + kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false) + val isMediaVisible by collectLastValue(underTest.isMediaVisible) + val userMedia = MediaData(active = true) + + assertThat(isMediaVisible).isFalse() + + kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + + assertThat(isMediaVisible).isTrue() + + kosmos.mediaFilterRepository.removeSelectedUserMediaEntry(userMedia.instanceId) + + assertThat(isMediaVisible).isFalse() + } + + @Test + fun addInactiveMedia_mediaVisibilityIsUpdated() = + testScope.runTest { + kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false) + val isMediaVisible by collectLastValue(underTest.isMediaVisible) + val userMedia = MediaData(active = false) + + assertThat(isMediaVisible).isFalse() + + kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + + assertThat(isMediaVisible).isTrue() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt new file mode 100644 index 000000000000..af55f5a9a968 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.ui.viewmodel + +import com.android.compose.animation.scene.Back +import com.android.compose.animation.scene.Edge +import com.android.compose.animation.scene.SceneKey +import com.android.compose.animation.scene.Swipe +import com.android.compose.animation.scene.SwipeDirection +import com.android.compose.animation.scene.UserAction +import com.android.compose.animation.scene.UserActionResult +import com.android.systemui.qs.ui.adapter.QSSceneAdapter +import com.android.systemui.scene.domain.interactor.SceneBackInteractor +import com.android.systemui.scene.shared.model.SceneFamilies +import com.android.systemui.scene.shared.model.Scenes +import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.map + +/** + * Models the UI state needed to figure out which user actions can trigger navigation from the quick + * settings scene to other scenes. + * + * Different from [QuickSettingsSceneContentViewModel] that models UI state needed for rendering the + * content of the quick settings scene. + */ +class QuickSettingsSceneActionsViewModel +@AssistedInject +constructor( + private val qsSceneAdapter: QSSceneAdapter, + sceneBackInteractor: SceneBackInteractor, +) : SceneActionsViewModel() { + + private val backScene: Flow<SceneKey> = + sceneBackInteractor.backScene + .filter { it != Scenes.QuickSettings } + .map { it ?: Scenes.Shade } + + override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) { + combine( + qsSceneAdapter.isCustomizerShowing, + backScene, + ) { isCustomizing, backScene -> + buildMap<UserAction, UserActionResult> { + if (isCustomizing) { + // TODO(b/332749288) Empty map so there are no back handlers and back can + // close + // customizer + + // TODO(b/330200163) Add an Up from Bottom to be able to collapse the shade + // while customizing + } else { + put(Back, UserActionResult(backScene)) + put(Swipe(SwipeDirection.Up), UserActionResult(backScene)) + put( + Swipe(fromSource = Edge.Bottom, direction = SwipeDirection.Up), + UserActionResult(SceneFamilies.Home), + ) + } + } + } + .collectLatest { actions -> setActions(actions) } + } + + @AssistedFactory + interface Factory { + fun create(): QuickSettingsSceneActionsViewModel + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt index 7258882e9ffa..55b8f5f0ca98 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt @@ -17,71 +17,34 @@ package com.android.systemui.qs.ui.viewmodel import androidx.lifecycle.LifecycleOwner -import com.android.compose.animation.scene.Back -import com.android.compose.animation.scene.Edge -import com.android.compose.animation.scene.SceneKey -import com.android.compose.animation.scene.Swipe -import com.android.compose.animation.scene.SwipeDirection -import com.android.compose.animation.scene.UserAction -import com.android.compose.animation.scene.UserActionResult -import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.lifecycle.SysUiViewModel import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor import com.android.systemui.qs.FooterActionsController import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel import com.android.systemui.qs.ui.adapter.QSSceneAdapter -import com.android.systemui.scene.domain.interactor.SceneBackInteractor -import com.android.systemui.scene.shared.model.SceneFamilies -import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import java.util.concurrent.atomic.AtomicBoolean -import javax.inject.Inject -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.map -/** Models UI state and handles user input for the quick settings scene. */ -@SysUISingleton -class QuickSettingsSceneViewModel -@Inject +/** + * Models UI state needed for rendering the content of the quick settings scene. + * + * Different from [QuickSettingsSceneActionsViewModel] that models the UI state needed to figure out + * which user actions can trigger navigation to other scenes. + */ +class QuickSettingsSceneContentViewModel +@AssistedInject constructor( val brightnessMirrorViewModelFactory: BrightnessMirrorViewModel.Factory, val shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory, val qsSceneAdapter: QSSceneAdapter, private val footerActionsViewModelFactory: FooterActionsViewModel.Factory, private val footerActionsController: FooterActionsController, - sceneBackInteractor: SceneBackInteractor, val mediaCarouselInteractor: MediaCarouselInteractor, -) { - private val backScene: Flow<SceneKey> = - sceneBackInteractor.backScene - .filter { it != Scenes.QuickSettings } - .map { it ?: Scenes.Shade } - - val destinationScenes: Flow<Map<UserAction, UserActionResult>> = - combine( - qsSceneAdapter.isCustomizerShowing, - backScene, - ) { isCustomizing, backScene -> - buildMap<UserAction, UserActionResult> { - if (isCustomizing) { - // TODO(b/332749288) Empty map so there are no back handlers and back can close - // customizer - - // TODO(b/330200163) Add an Up from Bottom to be able to collapse the shade - // while customizing - } else { - put(Back, UserActionResult(backScene)) - put(Swipe(SwipeDirection.Up), UserActionResult(backScene)) - put( - Swipe(fromSource = Edge.Bottom, direction = SwipeDirection.Up), - UserActionResult(SceneFamilies.Home), - ) - } - } - } +) : SysUiViewModel() { val isMediaVisible: StateFlow<Boolean> = mediaCarouselInteractor.hasAnyMediaOrRecommendation @@ -93,4 +56,9 @@ constructor( } return footerActionsViewModelFactory.create(lifecycleOwner) } + + @AssistedFactory + interface Factory { + fun create(): QuickSettingsSceneContentViewModel + } } |