Merge changes Id61f2c0d,Ib5f2151d,I8b7c50f9 into main
* changes:
[flexiglass] Make SharedNotificationContainerBinder an injectable instance
[flexiglass] Make NotificationStackViewBinder an injectable instance
[flexiglass] Fix notification scrim rounding in split shade
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt
index 5c9b271..525ad16 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt
@@ -16,45 +16,33 @@
package com.android.systemui.keyguard.ui.composable.section
-import android.content.Context
import android.view.ViewGroup
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.android.compose.animation.scene.SceneScope
import com.android.systemui.Flags.migrateClocksToBlueprint
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.notifications.ui.composable.NotificationStack
import com.android.systemui.scene.shared.flag.SceneContainerFlags
-import com.android.systemui.statusbar.notification.stack.AmbientState
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
-import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationStackAppearanceViewBinder
+import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationStackViewBinder
import com.android.systemui.statusbar.notification.stack.ui.viewbinder.SharedNotificationContainerBinder
-import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationStackAppearanceViewModel
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel
import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
@SysUISingleton
class NotificationSection
@Inject
constructor(
- @Application private val context: Context,
private val viewModel: NotificationsPlaceholderViewModel,
- controller: NotificationStackScrollLayoutController,
sceneContainerFlags: SceneContainerFlags,
sharedNotificationContainer: SharedNotificationContainer,
sharedNotificationContainerViewModel: SharedNotificationContainerViewModel,
stackScrollLayout: NotificationStackScrollLayout,
- notificationStackAppearanceViewModel: NotificationStackAppearanceViewModel,
- ambientState: AmbientState,
- notificationStackSizeCalculator: NotificationStackSizeCalculator,
- @Main private val mainImmediateDispatcher: CoroutineDispatcher,
+ sharedNotificationContainerBinder: SharedNotificationContainerBinder,
+ notificationStackViewBinder: NotificationStackViewBinder,
) {
init {
@@ -73,24 +61,13 @@
sharedNotificationContainer.addNotificationStackScrollLayout(stackScrollLayout)
}
- SharedNotificationContainerBinder.bind(
+ sharedNotificationContainerBinder.bind(
sharedNotificationContainer,
sharedNotificationContainerViewModel,
- sceneContainerFlags,
- controller,
- notificationStackSizeCalculator,
- mainImmediateDispatcher = mainImmediateDispatcher,
)
if (sceneContainerFlags.isEnabled()) {
- NotificationStackAppearanceViewBinder.bind(
- context,
- sharedNotificationContainer,
- notificationStackAppearanceViewModel,
- ambientState,
- controller,
- mainImmediateDispatcher = mainImmediateDispatcher,
- )
+ notificationStackViewBinder.bindWhileAttached()
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
index 8ad2bb7..9ba5e3b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
@@ -57,6 +57,7 @@
import androidx.compose.ui.layout.positionInWindow
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
@@ -70,10 +71,10 @@
import com.android.systemui.notifications.ui.composable.Notifications.Form
import com.android.systemui.notifications.ui.composable.Notifications.TransitionThresholds.EXPANSION_FOR_MAX_CORNER_RADIUS
import com.android.systemui.notifications.ui.composable.Notifications.TransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA
+import com.android.systemui.res.R
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.ui.composable.ShadeHeader
import com.android.systemui.statusbar.notification.stack.shared.model.StackRounding
-import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationStackAppearanceViewBinder.SCRIM_CORNER_RADIUS
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
import kotlin.math.roundToInt
@@ -140,6 +141,7 @@
) {
val density = LocalDensity.current
val screenCornerRadius = LocalScreenCornerRadius.current
+ val scrimCornerRadius = dimensionResource(R.dimen.notification_scrim_corner_radius)
val scrollState = rememberScrollState()
val syntheticScroll = viewModel.syntheticScroll.collectAsState(0f)
val expansionFraction by viewModel.expandFraction.collectAsState(0f)
@@ -157,7 +159,7 @@
val contentHeight = viewModel.intrinsicContentHeight.collectAsState()
- val stackRounding = viewModel.stackRounding.collectAsState()
+ val stackRounding = viewModel.stackRounding.collectAsState(StackRounding())
// the offset for the notifications scrim. Its upper bound is 0, and its lower bound is
// calculated in minScrimOffset. The scrim is the same height as the screen minus the
@@ -225,6 +227,7 @@
.graphicsLayer {
shape =
calculateCornerRadius(
+ scrimCornerRadius,
screenCornerRadius,
{ expansionFraction },
layoutState.isTransitioningBetween(Scenes.Gone, Scenes.Shade)
@@ -357,6 +360,7 @@
}
private fun calculateCornerRadius(
+ scrimCornerRadius: Dp,
screenCornerRadius: Dp,
expansionFraction: () -> Float,
transitioning: Boolean,
@@ -364,12 +368,12 @@
return if (transitioning) {
lerp(
start = screenCornerRadius.value,
- stop = SCRIM_CORNER_RADIUS,
+ stop = scrimCornerRadius.value,
fraction = (expansionFraction() / EXPANSION_FOR_MAX_CORNER_RADIUS).coerceIn(0f, 1f),
)
.dp
} else {
- SCRIM_CORNER_RADIUS.dp
+ scrimCornerRadius
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 2c31f9b..85798ac 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -370,7 +370,8 @@
NotificationScrollingStack(
viewModel = viewModel.notifications,
maxScrimTop = { 0f },
- modifier = Modifier.weight(1f).fillMaxHeight(),
+ modifier =
+ Modifier.weight(1f).fillMaxHeight().padding(bottom = navBarBottomHeight),
)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt
index 6dd425c..e3fa89c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt
@@ -20,9 +20,12 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
+import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.stack.shared.model.StackBounds
+import com.android.systemui.statusbar.notification.stack.shared.model.StackRounding
+import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
import org.junit.Test
@@ -30,10 +33,9 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
-@android.platform.test.annotations.EnabledOnRavenwood
class NotificationStackAppearanceInteractorTest : SysuiTestCase() {
- private val kosmos = Kosmos()
+ private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val underTest = kosmos.notificationStackAppearanceInteractor
@@ -59,6 +61,18 @@
assertThat(stackBounds).isEqualTo(bounds2)
}
+ @Test
+ fun stackRounding() =
+ testScope.runTest {
+ val stackRounding by collectLastValue(underTest.stackRounding)
+
+ kosmos.shadeRepository.setShadeMode(ShadeMode.Single)
+ assertThat(stackRounding).isEqualTo(StackRounding(roundTop = true, roundBottom = false))
+
+ kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+ assertThat(stackRounding).isEqualTo(StackRounding(roundTop = true, roundBottom = true))
+ }
+
@Test(expected = IllegalStateException::class)
fun setStackBounds_withImproperBounds_throwsException() =
testScope.runTest {
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
index 964eb6f..578389b 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
@@ -54,6 +54,18 @@
}
/**
+ * Returns a [Flow] that emits a dimension pixel size that is kept in sync with the device
+ * configuration.
+ *
+ * @see android.content.res.Resources.getDimensionPixelSize
+ */
+ fun getDimensionPixelOffset(@DimenRes id: Int): Flow<Int> {
+ return configurationController.onDensityOrFontScaleChanged.emitOnStart().map {
+ context.resources.getDimensionPixelOffset(id)
+ }
+ }
+
+ /**
* Returns a [Flow] that emits a color that is kept in sync with the device theme.
*
* @see Utils.getColorAttrDefaultColor
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
index 6a3b920..c1b0cc6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
@@ -26,20 +26,16 @@
import androidx.constraintlayout.widget.ConstraintSet.TOP
import com.android.systemui.Flags.centralizedStatusBarHeightFix
import com.android.systemui.Flags.migrateClocksToBlueprint
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.shade.LargeScreenHeaderHelper
import com.android.systemui.shade.NotificationPanelView
-import com.android.systemui.statusbar.notification.stack.AmbientState
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
-import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationStackAppearanceViewModel
+import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationStackViewBinder
+import com.android.systemui.statusbar.notification.stack.ui.viewbinder.SharedNotificationContainerBinder
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel
import dagger.Lazy
import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
/** Single column format for notifications (default for phones) */
class DefaultNotificationStackScrollLayoutSection
@@ -50,12 +46,9 @@
notificationPanelView: NotificationPanelView,
sharedNotificationContainer: SharedNotificationContainer,
sharedNotificationContainerViewModel: SharedNotificationContainerViewModel,
- notificationStackAppearanceViewModel: NotificationStackAppearanceViewModel,
- ambientState: AmbientState,
- controller: NotificationStackScrollLayoutController,
- notificationStackSizeCalculator: NotificationStackSizeCalculator,
+ sharedNotificationContainerBinder: SharedNotificationContainerBinder,
+ notificationStackViewBinder: NotificationStackViewBinder,
private val largeScreenHeaderHelperLazy: Lazy<LargeScreenHeaderHelper>,
- @Main mainDispatcher: CoroutineDispatcher,
) :
NotificationStackScrollLayoutSection(
context,
@@ -63,11 +56,8 @@
notificationPanelView,
sharedNotificationContainer,
sharedNotificationContainerViewModel,
- notificationStackAppearanceViewModel,
- ambientState,
- controller,
- notificationStackSizeCalculator,
- mainDispatcher,
+ sharedNotificationContainerBinder,
+ notificationStackViewBinder,
) {
override fun applyConstraints(constraintSet: ConstraintSet) {
if (!migrateClocksToBlueprint()) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt
index 5dea7cb..e73fa72 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt
@@ -31,15 +31,10 @@
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.shade.NotificationPanelView
-import com.android.systemui.statusbar.notification.stack.AmbientState
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
-import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationStackAppearanceViewBinder
+import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationStackViewBinder
import com.android.systemui.statusbar.notification.stack.ui.viewbinder.SharedNotificationContainerBinder
-import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationStackAppearanceViewModel
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel
-import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.DisposableHandle
abstract class NotificationStackScrollLayoutSection
@@ -49,11 +44,8 @@
private val notificationPanelView: NotificationPanelView,
private val sharedNotificationContainer: SharedNotificationContainer,
private val sharedNotificationContainerViewModel: SharedNotificationContainerViewModel,
- private val notificationStackAppearanceViewModel: NotificationStackAppearanceViewModel,
- private val ambientState: AmbientState,
- private val controller: NotificationStackScrollLayoutController,
- private val notificationStackSizeCalculator: NotificationStackSizeCalculator,
- private val mainDispatcher: CoroutineDispatcher,
+ private val sharedNotificationContainerBinder: SharedNotificationContainerBinder,
+ private val notificationStackViewBinder: NotificationStackViewBinder,
) : KeyguardSection() {
private val placeHolderId = R.id.nssl_placeholder
private val disposableHandles: MutableList<DisposableHandle> = mutableListOf()
@@ -104,27 +96,14 @@
disposeHandles()
disposableHandles.add(
- SharedNotificationContainerBinder.bind(
+ sharedNotificationContainerBinder.bind(
sharedNotificationContainer,
sharedNotificationContainerViewModel,
- sceneContainerFlags,
- controller,
- notificationStackSizeCalculator,
- mainImmediateDispatcher = mainDispatcher,
)
)
if (sceneContainerFlags.isEnabled()) {
- disposableHandles.add(
- NotificationStackAppearanceViewBinder.bind(
- context,
- sharedNotificationContainer,
- notificationStackAppearanceViewModel,
- ambientState,
- controller,
- mainImmediateDispatcher = mainDispatcher,
- )
- )
+ disposableHandles.add(notificationStackViewBinder.bindWhileAttached())
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeNotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeNotificationStackScrollLayoutSection.kt
index 2545302..4a705a7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeNotificationStackScrollLayoutSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeNotificationStackScrollLayoutSection.kt
@@ -24,19 +24,14 @@
import androidx.constraintlayout.widget.ConstraintSet.START
import androidx.constraintlayout.widget.ConstraintSet.TOP
import com.android.systemui.Flags.migrateClocksToBlueprint
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.shade.NotificationPanelView
-import com.android.systemui.statusbar.notification.stack.AmbientState
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
-import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationStackAppearanceViewModel
+import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationStackViewBinder
+import com.android.systemui.statusbar.notification.stack.ui.viewbinder.SharedNotificationContainerBinder
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel
import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
/** Large-screen format for notifications, shown as two columns on the device */
class SplitShadeNotificationStackScrollLayoutSection
@@ -47,12 +42,8 @@
notificationPanelView: NotificationPanelView,
sharedNotificationContainer: SharedNotificationContainer,
sharedNotificationContainerViewModel: SharedNotificationContainerViewModel,
- notificationStackAppearanceViewModel: NotificationStackAppearanceViewModel,
- ambientState: AmbientState,
- controller: NotificationStackScrollLayoutController,
- notificationStackSizeCalculator: NotificationStackSizeCalculator,
- private val smartspaceViewModel: KeyguardSmartspaceViewModel,
- @Main mainDispatcher: CoroutineDispatcher,
+ sharedNotificationContainerBinder: SharedNotificationContainerBinder,
+ notificationStackViewBinder: NotificationStackViewBinder,
) :
NotificationStackScrollLayoutSection(
context,
@@ -60,11 +51,8 @@
notificationPanelView,
sharedNotificationContainer,
sharedNotificationContainerViewModel,
- notificationStackAppearanceViewModel,
- ambientState,
- controller,
- notificationStackSizeCalculator,
- mainDispatcher,
+ sharedNotificationContainerBinder,
+ notificationStackViewBinder,
) {
override fun applyConstraints(constraintSet: ConstraintSet) {
if (!migrateClocksToBlueprint()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationStackAppearanceRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationStackAppearanceRepository.kt
index 9fffb66..79ba25e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationStackAppearanceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationStackAppearanceRepository.kt
@@ -19,7 +19,6 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.notification.stack.shared.model.StackBounds
-import com.android.systemui.statusbar.notification.stack.shared.model.StackRounding
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
@@ -29,10 +28,6 @@
/** The bounds of the notification stack in the current scene. */
val stackBounds = MutableStateFlow(StackBounds())
- /** The whether the corners of the notification stack should be rounded */
- // TODO: replace with the logic from QSController
- val stackRounding = MutableStateFlow(StackRounding(roundTop = true, roundBottom = false))
-
/**
* The height in px of the contents of notification stack. Depending on the number of
* notifications, this can exceed the space available on screen to show notifications, at which
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
index 5a56ca1..f05d017 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
@@ -18,6 +18,8 @@
package com.android.systemui.statusbar.notification.stack.domain.interactor
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.stack.data.repository.NotificationStackAppearanceRepository
import com.android.systemui.statusbar.notification.stack.shared.model.StackBounds
import com.android.systemui.statusbar.notification.stack.shared.model.StackRounding
@@ -25,6 +27,9 @@
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOf
/** An interactor which controls the appearance of the NSSL */
@SysUISingleton
@@ -32,12 +37,30 @@
@Inject
constructor(
private val repository: NotificationStackAppearanceRepository,
+ shadeInteractor: ShadeInteractor,
) {
/** The bounds of the notification stack in the current scene. */
val stackBounds: StateFlow<StackBounds> = repository.stackBounds.asStateFlow()
+ /**
+ * Whether the stack is expanding from GONE-with-HUN to SHADE
+ *
+ * TODO(b/296118689): implement this to match legacy QSController logic
+ */
+ private val isExpandingFromHeadsUp: Flow<Boolean> = flowOf(false)
+
/** The rounding of the notification stack. */
- val stackRounding: StateFlow<StackRounding> = repository.stackRounding.asStateFlow()
+ val stackRounding: Flow<StackRounding> =
+ combine(
+ shadeInteractor.shadeMode,
+ isExpandingFromHeadsUp,
+ ) { shadeMode, isExpandingFromHeadsUp ->
+ StackRounding(
+ roundTop = !(shadeMode == ShadeMode.Split && isExpandingFromHeadsUp),
+ roundBottom = shadeMode != ShadeMode.Single,
+ )
+ }
+ .distinctUntilChanged()
/**
* The height in px of the contents of notification stack. Depending on the number of
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt
deleted file mode 100644
index 189c5e0..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.statusbar.notification.stack.ui.viewbinder
-
-import android.content.Context
-import android.util.TypedValue
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.repeatOnLifecycle
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.statusbar.notification.stack.AmbientState
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
-import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationStackAppearanceViewModel
-import kotlin.math.roundToInt
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.launch
-
-/** Binds the shared notification container to its view-model. */
-object NotificationStackAppearanceViewBinder {
- const val SCRIM_CORNER_RADIUS = 32f
-
- @JvmStatic
- fun bind(
- context: Context,
- view: SharedNotificationContainer,
- viewModel: NotificationStackAppearanceViewModel,
- ambientState: AmbientState,
- controller: NotificationStackScrollLayoutController,
- @Main mainImmediateDispatcher: CoroutineDispatcher,
- ): DisposableHandle {
- return view.repeatWhenAttached(mainImmediateDispatcher) {
- repeatOnLifecycle(Lifecycle.State.CREATED) {
- launch {
- viewModel.stackClipping.collect { (bounds, rounding) ->
- val viewLeft = controller.view.left
- val viewTop = controller.view.top
- val roundRadius = SCRIM_CORNER_RADIUS.dpToPx(context)
- controller.setRoundedClippingBounds(
- bounds.left.roundToInt() - viewLeft,
- bounds.top.roundToInt() - viewTop,
- bounds.right.roundToInt() - viewLeft,
- bounds.bottom.roundToInt() - viewTop,
- if (rounding.roundTop) roundRadius else 0,
- if (rounding.roundBottom) roundRadius else 0,
- )
- }
- }
-
- launch {
- viewModel.contentTop.collect {
- controller.updateTopPadding(it, controller.isAddOrRemoveAnimationPending)
- }
- }
-
- launch {
- var wasExpanding = false
- viewModel.expandFraction.collect { expandFraction ->
- val nowExpanding = expandFraction != 0f && expandFraction != 1f
- if (nowExpanding && !wasExpanding) {
- controller.onExpansionStarted()
- }
- ambientState.expansionFraction = expandFraction
- controller.expandedHeight = expandFraction * controller.view.height
- if (!nowExpanding && wasExpanding) {
- controller.onExpansionStopped()
- }
- wasExpanding = nowExpanding
- }
- }
-
- launch { viewModel.isScrollable.collect { controller.setScrollingEnabled(it) } }
- }
- }
- }
-
- private fun Float.dpToPx(context: Context): Int {
- return TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_DIP,
- this,
- context.resources.displayMetrics
- )
- .roundToInt()
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackViewBinder.kt
new file mode 100644
index 0000000..1a34bb4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackViewBinder.kt
@@ -0,0 +1,102 @@
+/*
+ * 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.statusbar.notification.stack.ui.viewbinder
+
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.common.ui.ConfigurationState
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.notification.stack.AmbientState
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationStackAppearanceViewModel
+import javax.inject.Inject
+import kotlin.math.roundToInt
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.launch
+
+/** Binds the NSSL/Controller/AmbientState to their ViewModel. */
+@SysUISingleton
+class NotificationStackViewBinder
+@Inject
+constructor(
+ @Main private val mainImmediateDispatcher: CoroutineDispatcher,
+ private val ambientState: AmbientState,
+ private val view: NotificationStackScrollLayout,
+ private val controller: NotificationStackScrollLayoutController,
+ private val viewModel: NotificationStackAppearanceViewModel,
+ private val configuration: ConfigurationState,
+) {
+
+ fun bindWhileAttached(): DisposableHandle {
+ return view.repeatWhenAttached(mainImmediateDispatcher) {
+ repeatOnLifecycle(Lifecycle.State.CREATED) { bind() }
+ }
+ }
+
+ suspend fun bind() = coroutineScope {
+ launch {
+ combine(viewModel.stackClipping, clipRadius, ::Pair).collect { (clipping, clipRadius) ->
+ val (bounds, rounding) = clipping
+ val viewLeft = controller.view.left
+ val viewTop = controller.view.top
+ controller.setRoundedClippingBounds(
+ bounds.left.roundToInt() - viewLeft,
+ bounds.top.roundToInt() - viewTop,
+ bounds.right.roundToInt() - viewLeft,
+ bounds.bottom.roundToInt() - viewTop,
+ if (rounding.roundTop) clipRadius else 0,
+ if (rounding.roundBottom) clipRadius else 0,
+ )
+ }
+ }
+
+ launch {
+ viewModel.contentTop.collect {
+ controller.updateTopPadding(it, controller.isAddOrRemoveAnimationPending)
+ }
+ }
+
+ launch {
+ var wasExpanding = false
+ viewModel.expandFraction.collect { expandFraction ->
+ val nowExpanding = expandFraction != 0f && expandFraction != 1f
+ if (nowExpanding && !wasExpanding) {
+ controller.onExpansionStarted()
+ }
+ ambientState.expansionFraction = expandFraction
+ controller.expandedHeight = expandFraction * controller.view.height
+ if (!nowExpanding && wasExpanding) {
+ controller.onExpansionStopped()
+ }
+ wasExpanding = nowExpanding
+ }
+ }
+
+ launch { viewModel.isScrollable.collect { controller.setScrollingEnabled(it) } }
+ }
+
+ private val clipRadius: Flow<Int>
+ get() = configuration.getDimensionPixelOffset(R.dimen.notification_scrim_corner_radius)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
index 7c76ddb..3352079 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
@@ -20,6 +20,7 @@
import android.view.WindowInsets
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters
import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor
@@ -30,6 +31,7 @@
import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel
+import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.flow.MutableStateFlow
@@ -38,16 +40,19 @@
import kotlinx.coroutines.launch
/** Binds the shared notification container to its view-model. */
-object SharedNotificationContainerBinder {
+@SysUISingleton
+class SharedNotificationContainerBinder
+@Inject
+constructor(
+ private val sceneContainerFlags: SceneContainerFlags,
+ private val controller: NotificationStackScrollLayoutController,
+ private val notificationStackSizeCalculator: NotificationStackSizeCalculator,
+ @Main private val mainImmediateDispatcher: CoroutineDispatcher,
+) {
- @JvmStatic
fun bind(
view: SharedNotificationContainer,
viewModel: SharedNotificationContainerViewModel,
- sceneContainerFlags: SceneContainerFlags,
- controller: NotificationStackScrollLayoutController,
- notificationStackSizeCalculator: NotificationStackSizeCalculator,
- @Main mainImmediateDispatcher: CoroutineDispatcher,
): DisposableHandle {
val disposableHandle =
view.repeatWhenAttached {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
index ed44f20..bd83121 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
@@ -28,7 +28,6 @@
import com.android.systemui.statusbar.notification.stack.shared.model.StackRounding
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.StateFlow
/**
* ViewModel used by the Notification placeholders inside the scene container to update the
@@ -73,7 +72,7 @@
}
/** Corner rounding of the stack */
- val stackRounding: StateFlow<StackRounding> = interactor.stackRounding
+ val stackRounding: Flow<StackRounding> = interactor.stackRounding
/**
* The height in px of the contents of notification stack. Depending on the number of
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorKosmos.kt
index 546a1e0..5605d10 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorKosmos.kt
@@ -18,10 +18,12 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.statusbar.notification.stack.data.repository.notificationStackAppearanceRepository
val Kosmos.notificationStackAppearanceInteractor by Fixture {
NotificationStackAppearanceInteractor(
repository = notificationStackAppearanceRepository,
+ shadeInteractor = shadeInteractor,
)
}