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

Commit da3d8e9d authored by William Xiao's avatar William Xiao Committed by Android (Google) Code Review
Browse files

Merge "Show the UMO in the hub mode UI" into main

parents ec4f1ac9 6a48efee
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.GridItemSpan
@@ -48,6 +49,8 @@ import androidx.compose.ui.viewinterop.AndroidView
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.communal.shared.model.CommunalContentSize
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.media.controls.ui.MediaHierarchyManager
import com.android.systemui.media.controls.ui.MediaHostState
import com.android.systemui.res.R

@Composable
@@ -73,6 +76,7 @@ fun CommunalHub(
                CommunalContent(
                    modifier = Modifier.fillMaxHeight().width(Dimensions.CardWidth),
                    model = communalContent[index],
                    viewModel = viewModel,
                    deleteOnClick = viewModel::onDeleteWidget,
                    size =
                        SizeF(
@@ -94,6 +98,7 @@ fun CommunalHub(
@Composable
private fun CommunalContent(
    model: CommunalContentModel,
    viewModel: CommunalViewModel,
    size: SizeF,
    deleteOnClick: (id: Int) -> Unit,
    modifier: Modifier = Modifier,
@@ -102,6 +107,7 @@ private fun CommunalContent(
        is CommunalContentModel.Widget -> WidgetContent(model, size, deleteOnClick, modifier)
        is CommunalContentModel.Smartspace -> SmartspaceContent(model, modifier)
        is CommunalContentModel.Tutorial -> TutorialContent(modifier)
        is CommunalContentModel.Umo -> Umo(viewModel, modifier)
    }
}

@@ -155,6 +161,31 @@ private fun TutorialContent(modifier: Modifier = Modifier) {
    Card(modifier = modifier, content = {})
}

@Composable
private fun Umo(viewModel: CommunalViewModel, modifier: Modifier = Modifier) {
    AndroidView(
        modifier =
            modifier
                .width(Dimensions.CardWidth)
                .height(Dimensions.CardHeightThird)
                .padding(Dimensions.Spacing),
        factory = {
            viewModel.mediaHost.expansion = MediaHostState.EXPANDED
            viewModel.mediaHost.showsOnlyActiveMedia = false
            viewModel.mediaHost.falsingProtectionNeeded = false
            viewModel.mediaHost.init(MediaHierarchyManager.LOCATION_COMMUNAL_HUB)
            viewModel.mediaHost.hostView.layoutParams =
                FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.MATCH_PARENT,
                    FrameLayout.LayoutParams.MATCH_PARENT
                )
            viewModel.mediaHost.hostView
        },
        // For reusing composition in lazy lists.
        onReset = {},
    )
}

private fun CommunalContentSize.dp(): Dp {
    return when (this) {
        CommunalContentSize.FULL -> Dimensions.CardHeightFull
+2 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.communal.dagger

import com.android.systemui.communal.data.db.CommunalDatabaseModule
import com.android.systemui.communal.data.repository.CommunalMediaRepositoryModule
import com.android.systemui.communal.data.repository.CommunalRepositoryModule
import com.android.systemui.communal.data.repository.CommunalTutorialRepositoryModule
import com.android.systemui.communal.data.repository.CommunalWidgetRepositoryModule
@@ -26,6 +27,7 @@ import dagger.Module
    includes =
        [
            CommunalRepositoryModule::class,
            CommunalMediaRepositoryModule::class,
            CommunalTutorialRepositoryModule::class,
            CommunalWidgetRepositoryModule::class,
            CommunalDatabaseModule::class,
+73 −0
Original line number Diff line number Diff line
/*
 * 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.communal.data.repository

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.media.controls.models.player.MediaData
import com.android.systemui.media.controls.pipeline.MediaDataManager
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onStart

/** Encapsulates the state of smartspace in communal. */
interface CommunalMediaRepository {
    val mediaPlaying: Flow<Boolean>
}

@SysUISingleton
class CommunalMediaRepositoryImpl
@Inject
constructor(
    private val mediaDataManager: MediaDataManager,
) : CommunalMediaRepository {

    private val mediaDataListener =
        object : MediaDataManager.Listener {
            override fun onMediaDataLoaded(
                key: String,
                oldKey: String?,
                data: MediaData,
                immediately: Boolean,
                receivedSmartspaceCardLatency: Int,
                isSsReactivated: Boolean
            ) {
                if (!mediaDataManager.hasAnyMediaOrRecommendation()) {
                    return
                }
                _mediaPlaying.value = true
            }

            override fun onMediaDataRemoved(key: String) {
                if (mediaDataManager.hasAnyMediaOrRecommendation()) {
                    return
                }
                _mediaPlaying.value = false
            }
        }

    private val _mediaPlaying: MutableStateFlow<Boolean> = MutableStateFlow(false)

    override val mediaPlaying: Flow<Boolean> =
        _mediaPlaying
            .onStart {
                mediaDataManager.addListener(mediaDataListener)
                _mediaPlaying.value = mediaDataManager.hasAnyMediaOrRecommendation()
            }
            .onCompletion { mediaDataManager.removeListener(mediaDataListener) }
}
+25 −0
Original line number Diff line number Diff line
/*
 * 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.communal.data.repository

import dagger.Binds
import dagger.Module

@Module
interface CommunalMediaRepositoryModule {
    @Binds fun communalMediaRepository(impl: CommunalMediaRepositoryImpl): CommunalMediaRepository
}
+14 −2
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.communal.domain.interactor
import android.app.smartspace.SmartspaceTarget
import android.appwidget.AppWidgetHost
import android.content.ComponentName
import com.android.systemui.communal.data.repository.CommunalMediaRepository
import com.android.systemui.communal.data.repository.CommunalRepository
import com.android.systemui.communal.data.repository.CommunalWidgetRepository
import com.android.systemui.communal.domain.model.CommunalContentModel
@@ -37,12 +38,14 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map

/** Encapsulates business-logic related to communal mode. */
@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalInteractor
@Inject
constructor(
    private val communalRepository: CommunalRepository,
    private val widgetRepository: CommunalWidgetRepository,
    mediaRepository: CommunalMediaRepository,
    smartspaceRepository: SmartspaceRepository,
    tutorialInteractor: CommunalTutorialInteractor,
    private val appWidgetHost: AppWidgetHost,
@@ -87,8 +90,8 @@ constructor(
            if (isTutorialMode) {
                return@flatMapLatest flowOf(tutorialContent)
            }
            combine(smartspaceContent, widgetContent) { smartspace, widgets ->
                smartspace + widgets
            combine(smartspaceContent, umoContent, widgetContent) { smartspace, umo, widgets ->
                smartspace + umo + widgets
            }
        }

@@ -138,4 +141,13 @@ constructor(
            CommunalContentModel.Tutorial(id = 6, CommunalContentSize.HALF),
            CommunalContentModel.Tutorial(id = 7, CommunalContentSize.HALF),
        )

    private val umoContent: Flow<List<CommunalContentModel.Umo>> =
        mediaRepository.mediaPlaying.flatMapLatest { mediaPlaying ->
            if (mediaPlaying) {
                flowOf(listOf(CommunalContentModel.Umo(CommunalContentSize.THIRD)))
            } else {
                flowOf(emptyList())
            }
        }
}
Loading