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

Commit a8386a6b authored by Ale Nijamkin's avatar Ale Nijamkin Committed by Automerger Merge Worker
Browse files

Merge "[flexiglass] Drive window view visibility." into udc-qpr-dev am: c9f03886

parents 2ddafe86 c9f03886
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.scene

import com.android.systemui.scene.domain.startable.SceneContainerStartableModule
import com.android.systemui.scene.shared.model.SceneContainerConfigModule
import com.android.systemui.scene.ui.composable.SceneModule
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModelModule
@@ -25,6 +26,7 @@ import dagger.Module
    includes =
        [
            SceneContainerConfigModule::class,
            SceneContainerStartableModule::class,
            SceneContainerViewModelModule::class,
            SceneModule::class,
        ],
+11 −1
Original line number Diff line number Diff line
@@ -24,7 +24,17 @@ import com.android.systemui.scene.shared.model.SceneTransitionModel
import javax.inject.Inject
import kotlinx.coroutines.flow.StateFlow

/** Business logic and app state accessors for the scene framework. */
/**
 * Generic business logic and app state accessors for the scene framework.
 *
 * Note that scene container specific business logic does not belong in this class. Instead, it
 * should be hoisted to a class that is specific to that scene container, for an example, please see
 * [SystemUiDefaultSceneContainerStartable].
 *
 * Also note that this class should not depend on state or logic of other modules or features.
 * Instead, other feature modules should depend on and call into this class when their parts of the
 * application state change.
 */
@SysUISingleton
class SceneInteractor
@Inject
+32 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.scene.domain.startable

import com.android.systemui.CoreStartable
import dagger.Binds
import dagger.Module
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap

@Module
interface SceneContainerStartableModule {

    @Binds
    @IntoMap
    @ClassKey(SystemUiDefaultSceneContainerStartable::class)
    fun bind(impl: SystemUiDefaultSceneContainerStartable): CoreStartable
}
+69 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.scene.domain.startable

import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.SceneContainerNames
import com.android.systemui.scene.shared.model.SceneKey
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

/**
 * Hooks up business logic that manipulates the state of the [SceneInteractor] for the default
 * system UI scene container (the one named [SceneContainerNames.SYSTEM_UI_DEFAULT]) based on state
 * from other systems.
 */
@SysUISingleton
class SystemUiDefaultSceneContainerStartable
@Inject
constructor(
    @Application private val applicationScope: CoroutineScope,
    private val sceneInteractor: SceneInteractor,
    private val featureFlags: FeatureFlags,
) : CoreStartable {

    override fun start() {
        if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
            keepVisibilityUpdated()
        }
    }

    /** Drives visibility of the scene container. */
    private fun keepVisibilityUpdated() {
        applicationScope.launch {
            sceneInteractor
                .currentScene(CONTAINER_NAME)
                .map { it.key }
                .distinctUntilChanged()
                .collect { sceneKey ->
                    sceneInteractor.setVisible(CONTAINER_NAME, sceneKey != SceneKey.Gone)
                }
        }
    }

    companion object {
        private const val CONTAINER_NAME = SceneContainerNames.SYSTEM_UI_DEFAULT
    }
}
+13 −48
Original line number Diff line number Diff line
@@ -2,19 +2,10 @@ package com.android.systemui.scene.ui.view

import android.content.Context
import android.util.AttributeSet
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.OnBackPressedDispatcherOwner
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.compose.ComposeFacade
import com.android.systemui.lifecycle.repeatWhenAttached
import android.view.View
import com.android.systemui.scene.shared.model.Scene
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import kotlinx.coroutines.launch

/** A root view of the main SysUI window that supports scenes. */
class SceneWindowRootView(
@@ -30,45 +21,19 @@ class SceneWindowRootView(
        containerConfig: SceneContainerConfig,
        scenes: Set<Scene>,
    ) {
        val unsortedSceneByKey: Map<SceneKey, Scene> = scenes.associateBy { scene -> scene.key }
        val sortedSceneByKey: Map<SceneKey, Scene> = buildMap {
            containerConfig.sceneKeys.forEach { sceneKey ->
                val scene =
                    checkNotNull(unsortedSceneByKey[sceneKey]) {
                        "Scene not found for key \"$sceneKey\"!"
                    }

                put(sceneKey, scene)
            }
        }

        repeatWhenAttached {
            lifecycleScope.launch {
                repeatOnLifecycle(Lifecycle.State.CREATED) {
                    setViewTreeOnBackPressedDispatcherOwner(
                        object : OnBackPressedDispatcherOwner {
                            override val onBackPressedDispatcher =
                                OnBackPressedDispatcher().apply {
                                    setOnBackInvokedDispatcher(viewRootImpl.onBackInvokedDispatcher)
                                }

                            override val lifecycle: Lifecycle =
                                this@repeatWhenAttached.lifecycle
                        }
                    )

                    addView(
                        ComposeFacade.createSceneContainerView(
                            context = context,
        SceneWindowRootViewBinder.bind(
            view = this@SceneWindowRootView,
            viewModel = viewModel,
                            sceneByKey = sortedSceneByKey,
                        )
            containerConfig = containerConfig,
            scenes = scenes,
            onVisibilityChangedInternal = { isVisible ->
                super.setVisibility(if (isVisible) View.VISIBLE else View.INVISIBLE)
            }
        )
    }

                // Here when destroyed.
                removeAllViews()
            }
        }
    override fun setVisibility(visibility: Int) {
        // Do nothing. We don't want external callers to invoke this. Instead, we drive our own
        // visibility from our view-binder.
    }
}
Loading