blob: 8f6600cddb0e241d23c7c443719c51b19d13ac41 [file] [log] [blame]
package com.android.systemui.statusbar.phone
import android.view.WindowInsets
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.plugins.qs.QS
import com.android.systemui.plugins.qs.QSContainerController
import com.android.systemui.recents.OverviewProxyService
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener
import com.android.systemui.shared.system.QuickStepContract
import com.android.systemui.util.ViewController
import java.util.function.Consumer
import javax.inject.Inject
class NotificationsQSContainerController @Inject constructor(
view: NotificationsQuickSettingsContainer,
private val navigationModeController: NavigationModeController,
private val overviewProxyService: OverviewProxyService,
private val featureFlags: FeatureFlags
) : ViewController<NotificationsQuickSettingsContainer>(view), QSContainerController {
var qsExpanded = false
set(value) {
if (field != value) {
field = value
mView.invalidate()
}
}
var splitShadeEnabled = false
set(value) {
if (field != value) {
field = value
// in case device configuration changed while showing QS details/customizer
updateBottomSpacing()
}
}
private var isQSDetailShowing = false
private var isQSCustomizing = false
private var isQSCustomizerAnimating = false
private var notificationsBottomMargin = 0
private var bottomStableInsets = 0
private var bottomCutoutInsets = 0
private var isGestureNavigation = true
private var taskbarVisible = false
private val taskbarVisibilityListener: OverviewProxyListener = object : OverviewProxyListener {
override fun onTaskbarStatusUpdated(visible: Boolean, stashed: Boolean) {
taskbarVisible = visible
}
}
private val windowInsetsListener: Consumer<WindowInsets> = Consumer { insets ->
// when taskbar is visible, stableInsetBottom will include its height
bottomStableInsets = insets.stableInsetBottom
bottomCutoutInsets = insets.displayCutout?.safeInsetBottom ?: 0
updateBottomSpacing()
}
override fun onInit() {
val currentMode: Int = navigationModeController.addListener { mode: Int ->
isGestureNavigation = QuickStepContract.isGesturalMode(mode)
}
isGestureNavigation = QuickStepContract.isGesturalMode(currentMode)
}
public override fun onViewAttached() {
notificationsBottomMargin = mView.defaultNotificationsMarginBottom
overviewProxyService.addCallback(taskbarVisibilityListener)
mView.setInsetsChangedListener(windowInsetsListener)
mView.setQSFragmentAttachedListener { qs: QS -> qs.setContainerController(this) }
}
override fun onViewDetached() {
overviewProxyService.removeCallback(taskbarVisibilityListener)
mView.removeOnInsetsChangedListener()
mView.removeQSFragmentAttachedListener()
}
override fun setCustomizerAnimating(animating: Boolean) {
if (isQSCustomizerAnimating != animating) {
isQSCustomizerAnimating = animating
mView.invalidate()
}
}
override fun setCustomizerShowing(showing: Boolean) {
isQSCustomizing = showing
updateBottomSpacing()
}
override fun setDetailShowing(showing: Boolean) {
isQSDetailShowing = showing
updateBottomSpacing()
}
private fun updateBottomSpacing() {
val (containerPadding, notificationsMargin) = calculateBottomSpacing()
var qsScrollPaddingBottom = 0
if (!(splitShadeEnabled || isQSCustomizing || isQSDetailShowing || isGestureNavigation ||
taskbarVisible)) {
// no taskbar, portrait, navigation buttons enabled:
// padding is needed so QS can scroll up over bottom insets - to reach the point when
// the whole QS is above bottom insets
qsScrollPaddingBottom = bottomStableInsets
}
mView.setPadding(0, 0, 0, containerPadding)
mView.setNotificationsMarginBottom(notificationsMargin)
if (featureFlags.isEnabled(Flags.NEW_FOOTER)) {
mView.setQSContainerPaddingBottom(notificationsMargin)
} else {
mView.setQSScrollPaddingBottom(qsScrollPaddingBottom)
}
}
private fun calculateBottomSpacing(): Pair<Int, Int> {
val containerPadding: Int
var stackScrollMargin = notificationsBottomMargin
if (splitShadeEnabled) {
if (isGestureNavigation) {
// only default cutout padding, taskbar always hides
containerPadding = bottomCutoutInsets
} else if (taskbarVisible) {
// navigation buttons + visible taskbar means we're NOT on homescreen
containerPadding = bottomStableInsets
} else {
// navigation buttons + hidden taskbar means we're on homescreen
containerPadding = 0
// we need extra margin for notifications as navigation buttons are below them
stackScrollMargin = bottomStableInsets + notificationsBottomMargin
}
} else {
if (isQSCustomizing || isQSDetailShowing) {
// Clear out bottom paddings/margins so the qs customization can be full height.
containerPadding = 0
stackScrollMargin = 0
} else if (isGestureNavigation) {
containerPadding = bottomCutoutInsets
} else if (taskbarVisible) {
containerPadding = bottomStableInsets
} else {
containerPadding = 0
}
}
return containerPadding to stackScrollMargin
}
}