Loading packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt +2 −10 Original line number Diff line number Diff line Loading @@ -567,16 +567,8 @@ private fun ScrollOnUpdatedLiveContentEffect( // Do nothing if there is no new live content val indexOfFirstUpdatedContent = newLiveContentKeys.indexOfFirst { !prevLiveContentKeys.contains(it) } if (indexOfFirstUpdatedContent < 0) { return@LaunchedEffect } // Scroll if the live content is not visible val lastVisibleItemIndex = gridState.layoutInfo.visibleItemsInfo.lastOrNull()?.index if (lastVisibleItemIndex != null && indexOfFirstUpdatedContent > lastVisibleItemIndex) { // Launching with a scope to prevent the job from being canceled in the case of a // recomposition during scrolling coroutineScope.launch { gridState.animateScrollToItem(indexOfFirstUpdatedContent) } if (indexOfFirstUpdatedContent in 0 until gridState.firstVisibleItemIndex) { gridState.scrollToItem(indexOfFirstUpdatedContent) } } } Loading packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt +3 −17 Original line number Diff line number Diff line Loading @@ -352,7 +352,7 @@ class CommunalInteractorTest : SysuiTestCase() { smartspaceRepository.setTimers(targets) val smartspaceContent by collectLastValue(underTest.getOngoingContent(true)) val smartspaceContent by collectLastValue(underTest.ongoingContent) assertThat(smartspaceContent?.size).isEqualTo(totalTargets) for (index in 0 until totalTargets) { assertThat(smartspaceContent?.get(index)?.size).isEqualTo(expectedSizes[index]) Loading @@ -368,27 +368,13 @@ class CommunalInteractorTest : SysuiTestCase() { // Media is playing. mediaRepository.mediaActive() val umoContent by collectLastValue(underTest.getOngoingContent(true)) val umoContent by collectLastValue(underTest.ongoingContent) assertThat(umoContent?.size).isEqualTo(1) assertThat(umoContent?.get(0)).isInstanceOf(CommunalContentModel.Umo::class.java) assertThat(umoContent?.get(0)?.key).isEqualTo(CommunalContentModel.KEY.umo()) } @Test fun umo_mediaPlaying_doNotShowUmo() = testScope.run { // Tutorial completed. tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) // Media is playing. mediaRepository.mediaActive() val umoContent by collectLastValue(underTest.getOngoingContent(false)) assertThat(umoContent?.size).isEqualTo(0) } @Test fun ongoing_shouldOrderAndSizeByTimestamp() = testScope.runTest { Loading @@ -412,7 +398,7 @@ class CommunalInteractorTest : SysuiTestCase() { val timer3 = smartspaceTimer("timer3", timestamp = 4L) smartspaceRepository.setTimers(listOf(timer1, timer2, timer3)) val ongoingContent by collectLastValue(underTest.getOngoingContent(true)) val ongoingContent by collectLastValue(underTest.ongoingContent) assertThat(ongoingContent?.size).isEqualTo(4) assertThat(ongoingContent?.get(0)?.key) .isEqualTo(CommunalContentModel.KEY.smartspace("timer3")) Loading packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt +2 −1 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import org.mockito.kotlin.atLeastOnce import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.never Loading Loading @@ -757,7 +758,7 @@ class CommunalViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { // updateViewVisibility is called when the flow is collected. assertThat(communalContent).isNotNull() verify(mediaHost).updateViewVisibility() verify(mediaHost, atLeastOnce()).updateViewVisibility() } @Test Loading packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt +2 −2 Original line number Diff line number Diff line Loading @@ -510,7 +510,7 @@ constructor( * A flow of ongoing content, including smartspace timers and umo, ordered by creation time and * sized dynamically. */ fun getOngoingContent(mediaHostVisible: Boolean): Flow<List<CommunalContentModel.Ongoing>> = val ongoingContent: Flow<List<CommunalContentModel.Ongoing>> = combine(smartspaceRepository.timers, mediaRepository.mediaModel) { timers, media -> val ongoingContent = mutableListOf<CommunalContentModel.Ongoing>() Loading @@ -526,7 +526,7 @@ constructor( ) // Add UMO if (mediaHostVisible && media.hasAnyMediaOrRecommendation) { if (media.hasAnyMediaOrRecommendation) { ongoingContent.add( CommunalContentModel.Umo( createdTimestampMillis = media.createdTimestampMillis, Loading packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt +15 −3 Original line number Diff line number Diff line Loading @@ -99,7 +99,7 @@ constructor( private val logger = Logger(logBuffer, "CommunalViewModel") private val _isMediaHostVisible = private val isMediaHostVisible = conflatedCallbackFlow { val callback = { visible: Boolean -> trySend(visible) Loading @@ -117,12 +117,26 @@ constructor( mediaHost.updateViewVisibility() emit(mediaHost.visible) } .distinctUntilChanged() .onEach { logger.d({ "_isMediaHostVisible: $bool1" }) { bool1 = it } } .flowOn(mainDispatcher) /** Communal content saved from the previous emission when the flow is active (not "frozen"). */ private var frozenCommunalContent: List<CommunalContentModel>? = null private val ongoingContent = combine( isMediaHostVisible, communalInteractor.ongoingContent.onEach { mediaHost.updateViewVisibility() } ) { mediaVisible, ongoingContent -> if (mediaVisible) { ongoingContent } else { // Media is not visible, don't show UMO ongoingContent.filterNot { it is CommunalContentModel.Umo } } } @OptIn(ExperimentalCoroutinesApi::class) private val latestCommunalContent: Flow<List<CommunalContentModel>> = tutorialInteractor.isTutorialAvailable Loading @@ -130,8 +144,6 @@ constructor( if (isTutorialMode) { return@flatMapLatest flowOf(communalInteractor.tutorialContent) } val ongoingContent = _isMediaHostVisible.flatMapLatest { communalInteractor.getOngoingContent(it) } combine( ongoingContent, communalInteractor.widgetContent, Loading Loading
packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt +2 −10 Original line number Diff line number Diff line Loading @@ -567,16 +567,8 @@ private fun ScrollOnUpdatedLiveContentEffect( // Do nothing if there is no new live content val indexOfFirstUpdatedContent = newLiveContentKeys.indexOfFirst { !prevLiveContentKeys.contains(it) } if (indexOfFirstUpdatedContent < 0) { return@LaunchedEffect } // Scroll if the live content is not visible val lastVisibleItemIndex = gridState.layoutInfo.visibleItemsInfo.lastOrNull()?.index if (lastVisibleItemIndex != null && indexOfFirstUpdatedContent > lastVisibleItemIndex) { // Launching with a scope to prevent the job from being canceled in the case of a // recomposition during scrolling coroutineScope.launch { gridState.animateScrollToItem(indexOfFirstUpdatedContent) } if (indexOfFirstUpdatedContent in 0 until gridState.firstVisibleItemIndex) { gridState.scrollToItem(indexOfFirstUpdatedContent) } } } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt +3 −17 Original line number Diff line number Diff line Loading @@ -352,7 +352,7 @@ class CommunalInteractorTest : SysuiTestCase() { smartspaceRepository.setTimers(targets) val smartspaceContent by collectLastValue(underTest.getOngoingContent(true)) val smartspaceContent by collectLastValue(underTest.ongoingContent) assertThat(smartspaceContent?.size).isEqualTo(totalTargets) for (index in 0 until totalTargets) { assertThat(smartspaceContent?.get(index)?.size).isEqualTo(expectedSizes[index]) Loading @@ -368,27 +368,13 @@ class CommunalInteractorTest : SysuiTestCase() { // Media is playing. mediaRepository.mediaActive() val umoContent by collectLastValue(underTest.getOngoingContent(true)) val umoContent by collectLastValue(underTest.ongoingContent) assertThat(umoContent?.size).isEqualTo(1) assertThat(umoContent?.get(0)).isInstanceOf(CommunalContentModel.Umo::class.java) assertThat(umoContent?.get(0)?.key).isEqualTo(CommunalContentModel.KEY.umo()) } @Test fun umo_mediaPlaying_doNotShowUmo() = testScope.run { // Tutorial completed. tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) // Media is playing. mediaRepository.mediaActive() val umoContent by collectLastValue(underTest.getOngoingContent(false)) assertThat(umoContent?.size).isEqualTo(0) } @Test fun ongoing_shouldOrderAndSizeByTimestamp() = testScope.runTest { Loading @@ -412,7 +398,7 @@ class CommunalInteractorTest : SysuiTestCase() { val timer3 = smartspaceTimer("timer3", timestamp = 4L) smartspaceRepository.setTimers(listOf(timer1, timer2, timer3)) val ongoingContent by collectLastValue(underTest.getOngoingContent(true)) val ongoingContent by collectLastValue(underTest.ongoingContent) assertThat(ongoingContent?.size).isEqualTo(4) assertThat(ongoingContent?.get(0)?.key) .isEqualTo(CommunalContentModel.KEY.smartspace("timer3")) Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt +2 −1 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import org.mockito.kotlin.atLeastOnce import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.never Loading Loading @@ -757,7 +758,7 @@ class CommunalViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { // updateViewVisibility is called when the flow is collected. assertThat(communalContent).isNotNull() verify(mediaHost).updateViewVisibility() verify(mediaHost, atLeastOnce()).updateViewVisibility() } @Test Loading
packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt +2 −2 Original line number Diff line number Diff line Loading @@ -510,7 +510,7 @@ constructor( * A flow of ongoing content, including smartspace timers and umo, ordered by creation time and * sized dynamically. */ fun getOngoingContent(mediaHostVisible: Boolean): Flow<List<CommunalContentModel.Ongoing>> = val ongoingContent: Flow<List<CommunalContentModel.Ongoing>> = combine(smartspaceRepository.timers, mediaRepository.mediaModel) { timers, media -> val ongoingContent = mutableListOf<CommunalContentModel.Ongoing>() Loading @@ -526,7 +526,7 @@ constructor( ) // Add UMO if (mediaHostVisible && media.hasAnyMediaOrRecommendation) { if (media.hasAnyMediaOrRecommendation) { ongoingContent.add( CommunalContentModel.Umo( createdTimestampMillis = media.createdTimestampMillis, Loading
packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt +15 −3 Original line number Diff line number Diff line Loading @@ -99,7 +99,7 @@ constructor( private val logger = Logger(logBuffer, "CommunalViewModel") private val _isMediaHostVisible = private val isMediaHostVisible = conflatedCallbackFlow { val callback = { visible: Boolean -> trySend(visible) Loading @@ -117,12 +117,26 @@ constructor( mediaHost.updateViewVisibility() emit(mediaHost.visible) } .distinctUntilChanged() .onEach { logger.d({ "_isMediaHostVisible: $bool1" }) { bool1 = it } } .flowOn(mainDispatcher) /** Communal content saved from the previous emission when the flow is active (not "frozen"). */ private var frozenCommunalContent: List<CommunalContentModel>? = null private val ongoingContent = combine( isMediaHostVisible, communalInteractor.ongoingContent.onEach { mediaHost.updateViewVisibility() } ) { mediaVisible, ongoingContent -> if (mediaVisible) { ongoingContent } else { // Media is not visible, don't show UMO ongoingContent.filterNot { it is CommunalContentModel.Umo } } } @OptIn(ExperimentalCoroutinesApi::class) private val latestCommunalContent: Flow<List<CommunalContentModel>> = tutorialInteractor.isTutorialAvailable Loading @@ -130,8 +144,6 @@ constructor( if (isTutorialMode) { return@flatMapLatest flowOf(communalInteractor.tutorialContent) } val ongoingContent = _isMediaHostVisible.flatMapLatest { communalInteractor.getOngoingContent(it) } combine( ongoingContent, communalInteractor.widgetContent, Loading