Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4ec8c40 authored by Danny Burakov's avatar Danny Burakov Committed by Android (Google) Code Review
Browse files

Merge "[flexiglass] Remove NotificationsShadeSceneContentViewModel." into main

parents f7234748 1eb52471
Loading
Loading
Loading
Loading
+0 −10
Original line number Original line Diff line number Diff line
@@ -20,19 +20,15 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.SceneScope
import com.android.compose.animation.scene.SceneScope
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.ui.composable.LockscreenContent
import com.android.systemui.keyguard.ui.composable.LockscreenContent
import com.android.systemui.lifecycle.rememberViewModel
import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeSceneActionsViewModel
import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeSceneActionsViewModel
import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeSceneContentViewModel
import com.android.systemui.scene.session.ui.composable.SaveableSession
import com.android.systemui.scene.session.ui.composable.SaveableSession
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.ComposableScene
import com.android.systemui.scene.ui.composable.ComposableScene
@@ -54,7 +50,6 @@ import kotlinx.coroutines.flow.Flow
class NotificationsShadeScene
class NotificationsShadeScene
@Inject
@Inject
constructor(
constructor(
    private val contentViewModelFactory: NotificationsShadeSceneContentViewModel.Factory,
    private val actionsViewModelFactory: NotificationsShadeSceneActionsViewModel.Factory,
    private val actionsViewModelFactory: NotificationsShadeSceneActionsViewModel.Factory,
    private val overlayShadeViewModelFactory: OverlayShadeViewModel.Factory,
    private val overlayShadeViewModelFactory: OverlayShadeViewModel.Factory,
    private val shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory,
    private val shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory,
@@ -84,9 +79,6 @@ constructor(
    override fun SceneScope.Content(
    override fun SceneScope.Content(
        modifier: Modifier,
        modifier: Modifier,
    ) {
    ) {
        val viewModel = rememberViewModel { contentViewModelFactory.create() }
        val isEmptySpaceClickable by viewModel.isEmptySpaceClickable.collectAsStateWithLifecycle()

        OverlayShade(
        OverlayShade(
            modifier = modifier,
            modifier = modifier,
            viewModelFactory = overlayShadeViewModelFactory,
            viewModelFactory = overlayShadeViewModelFactory,
@@ -110,8 +102,6 @@ constructor(
                    shouldFillMaxSize = false,
                    shouldFillMaxSize = false,
                    shouldReserveSpaceForNavBar = false,
                    shouldReserveSpaceForNavBar = false,
                    shadeMode = ShadeMode.Dual,
                    shadeMode = ShadeMode.Dual,
                    onEmptySpaceClick =
                        viewModel::onEmptySpaceClicked.takeIf { isEmptySpaceClickable },
                    modifier = Modifier.fillMaxWidth(),
                    modifier = Modifier.fillMaxWidth(),
                )
                )


+0 −3
Original line number Original line Diff line number Diff line
@@ -29,9 +29,6 @@ import dagger.assisted.AssistedInject


/**
/**
 * Models the UI state for the user actions that the user can perform to navigate to other scenes.
 * Models the UI state for the user actions that the user can perform to navigate to other scenes.
 *
 * Different from the [NotificationsShadeSceneContentViewModel] which models the _content_ of the
 * scene.
 */
 */
class NotificationsShadeSceneActionsViewModel
class NotificationsShadeSceneActionsViewModel
@AssistedInject
@AssistedInject
+0 −49
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 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.
 */

@file:OptIn(ExperimentalCoroutinesApi::class)

package com.android.systemui.notifications.ui.viewmodel

import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.shade.ui.viewmodel.BaseShadeSceneViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.ExperimentalCoroutinesApi

/**
 * Models UI state used to render the content of the notifications shade scene.
 *
 * Different from [NotificationsShadeSceneActionsViewModel], which only models user actions that can
 * be performed to navigate to other scenes.
 */
class NotificationsShadeSceneContentViewModel
@AssistedInject
constructor(
    deviceEntryInteractor: DeviceEntryInteractor,
    sceneInteractor: SceneInteractor,
) :
    BaseShadeSceneViewModel(
        deviceEntryInteractor,
        sceneInteractor,
    ) {

    @AssistedFactory
    interface Factory {
        fun create(): NotificationsShadeSceneContentViewModel
    }
}
+0 −56
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 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.
 */

@file:OptIn(ExperimentalCoroutinesApi::class)

package com.android.systemui.shade.ui.viewmodel

import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.lifecycle.SysUiViewModel
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest

/** Base class for classes that model UI state of the content of shade scenes. */
abstract class BaseShadeSceneViewModel(
    private val deviceEntryInteractor: DeviceEntryInteractor,
    private val sceneInteractor: SceneInteractor,
) : SysUiViewModel() {

    private val _isEmptySpaceClickable =
        MutableStateFlow(!deviceEntryInteractor.isDeviceEntered.value)
    /** Whether clicking on the empty area of the shade does something */
    val isEmptySpaceClickable: StateFlow<Boolean> = _isEmptySpaceClickable.asStateFlow()

    override suspend fun onActivated() {
        deviceEntryInteractor.isDeviceEntered.collectLatest { isDeviceEntered ->
            _isEmptySpaceClickable.value = !isDeviceEntered
        }
    }

    /** Notifies that the empty space in the shade has been clicked. */
    fun onEmptySpaceClicked() {
        if (!isEmptySpaceClickable.value) {
            return
        }

        sceneInteractor.changeScene(Scenes.Lockscreen, "Shade empty space clicked.")
    }
}
+28 −7
Original line number Original line Diff line number Diff line
@@ -20,11 +20,13 @@ package com.android.systemui.shade.ui.viewmodel


import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleOwner
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.lifecycle.SysUiViewModel
import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
import com.android.systemui.qs.FooterActionsController
import com.android.systemui.qs.FooterActionsController
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.qs.ui.adapter.QSSceneAdapter
import com.android.systemui.qs.ui.adapter.QSSceneAdapter
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel
import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.shade.shared.model.ShadeMode
@@ -34,7 +36,10 @@ import dagger.assisted.AssistedInject
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicBoolean
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest


/**
/**
 * Models UI state used to render the content of the shade scene.
 * Models UI state used to render the content of the shade scene.
@@ -53,20 +58,27 @@ constructor(
    private val footerActionsViewModelFactory: FooterActionsViewModel.Factory,
    private val footerActionsViewModelFactory: FooterActionsViewModel.Factory,
    private val footerActionsController: FooterActionsController,
    private val footerActionsController: FooterActionsController,
    private val unfoldTransitionInteractor: UnfoldTransitionInteractor,
    private val unfoldTransitionInteractor: UnfoldTransitionInteractor,
    deviceEntryInteractor: DeviceEntryInteractor,
    private val deviceEntryInteractor: DeviceEntryInteractor,
    sceneInteractor: SceneInteractor,
    private val sceneInteractor: SceneInteractor,
) :
) : SysUiViewModel() {
    BaseShadeSceneViewModel(
        deviceEntryInteractor,
        sceneInteractor,
    ) {


    val shadeMode: StateFlow<ShadeMode> = shadeInteractor.shadeMode
    val shadeMode: StateFlow<ShadeMode> = shadeInteractor.shadeMode


    private val _isEmptySpaceClickable =
        MutableStateFlow(!deviceEntryInteractor.isDeviceEntered.value)
    /** Whether clicking on the empty area of the shade does something */
    val isEmptySpaceClickable: StateFlow<Boolean> = _isEmptySpaceClickable.asStateFlow()

    val isMediaVisible: StateFlow<Boolean> = mediaCarouselInteractor.hasActiveMediaOrRecommendation
    val isMediaVisible: StateFlow<Boolean> = mediaCarouselInteractor.hasActiveMediaOrRecommendation


    private val footerActionsControllerInitialized = AtomicBoolean(false)
    private val footerActionsControllerInitialized = AtomicBoolean(false)


    override suspend fun onActivated() {
        deviceEntryInteractor.isDeviceEntered.collectLatest { isDeviceEntered ->
            _isEmptySpaceClickable.value = !isDeviceEntered
        }
    }

    /**
    /**
     * Amount of X-axis translation to apply to various elements as the unfolded foldable is folded
     * Amount of X-axis translation to apply to various elements as the unfolded foldable is folded
     * slightly, in pixels.
     * slightly, in pixels.
@@ -82,6 +94,15 @@ constructor(
        return footerActionsViewModelFactory.create(lifecycleOwner)
        return footerActionsViewModelFactory.create(lifecycleOwner)
    }
    }


    /** Notifies that the empty space in the shade has been clicked. */
    fun onEmptySpaceClicked() {
        if (!isEmptySpaceClickable.value) {
            return
        }

        sceneInteractor.changeScene(Scenes.Lockscreen, "Shade empty space clicked.")
    }

    @AssistedFactory
    @AssistedFactory
    interface Factory {
    interface Factory {
        fun create(): ShadeSceneContentViewModel
        fun create(): ShadeSceneContentViewModel
Loading