diff options
| author | 2024-10-25 13:29:41 +0100 | |
|---|---|---|
| committer | 2024-10-29 15:32:27 +0000 | |
| commit | a4fda58f29f8f1651a1cdb56019b3e4b456218ab (patch) | |
| tree | 89a9037932a6df4b88db1dad2c19bb281568e276 | |
| parent | 70e721f99793376dcb39e78064622c53960cff7b (diff) | |
Add Volume Dialog window title based on the currently active slider.
Flag: com.android.systemui.volume_redesign
Bug: 369994090
Test: manual on the foldable
Change-Id: If80334326b0ec37b8ff850196dd710dcb97aa02d
5 files changed, 89 insertions, 98 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt index 7476c6a279f3..097a60fdc440 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt @@ -25,20 +25,20 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.res.R import com.android.systemui.volume.Events import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogVisibilityInteractor -import com.android.systemui.volume.dialog.ui.binder.VolumeDialogBinder +import com.android.systemui.volume.dialog.ui.binder.VolumeDialogViewBinder import javax.inject.Inject class VolumeDialog @Inject constructor( @Application context: Context, - private val dialogBinder: VolumeDialogBinder, + private val viewBinder: VolumeDialogViewBinder, private val visibilityInteractor: VolumeDialogVisibilityInteractor, ) : Dialog(ContextThemeWrapper(context, R.style.volume_dialog_theme)) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - dialogBinder.bind(this) + viewBinder.bind(this) } /** diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/shared/model/VolumeDialogStreamModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/shared/model/VolumeDialogStreamModel.kt index be3cd97edf10..cec58c347111 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/shared/model/VolumeDialogStreamModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/shared/model/VolumeDialogStreamModel.kt @@ -16,6 +16,7 @@ package com.android.systemui.volume.dialog.shared.model +import android.content.Context import androidx.annotation.StringRes import com.android.systemui.plugins.VolumeDialogController @@ -29,7 +30,9 @@ data class VolumeDialogStreamModel( val levelMax: Int = 0, val muted: Boolean = false, val muteSupported: Boolean = false, + /** You likely need to use [streamLabel] instead. */ @StringRes val name: Int = 0, + /** You likely need to use [streamLabel] instead. */ val remoteLabel: String? = null, val routedToBluetooth: Boolean = false, ) { @@ -51,3 +54,10 @@ data class VolumeDialogStreamModel( routedToBluetooth = legacyState.routedToBluetooth, ) } + +fun VolumeDialogStreamModel.streamLabel(context: Context): String { + if (remoteLabel != null) { + return remoteLabel + } + return context.resources.getString(name) +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogBinder.kt deleted file mode 100644 index cd535e420e18..000000000000 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogBinder.kt +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2024 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.volume.dialog.ui.binder - -import android.app.Dialog -import android.graphics.Color -import android.graphics.PixelFormat -import android.graphics.drawable.ColorDrawable -import android.view.View -import android.view.ViewGroup -import android.view.Window -import android.view.WindowManager -import com.android.systemui.res.R -import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog -import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope -import com.android.systemui.volume.dialog.ringer.ui.binder.VolumeDialogRingerViewBinder -import com.android.systemui.volume.dialog.settings.ui.binder.VolumeDialogSettingsButtonViewBinder -import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogSlidersViewBinder -import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogGravityViewModel -import javax.inject.Inject -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach - -/** Binds the Volume Dialog itself. */ -@VolumeDialogScope -class VolumeDialogBinder -@Inject -constructor( - @VolumeDialog private val coroutineScope: CoroutineScope, - private val volumeDialogViewBinder: VolumeDialogViewBinder, - private val slidersViewBinder: VolumeDialogSlidersViewBinder, - private val volumeDialogRingerViewBinder: VolumeDialogRingerViewBinder, - private val settingsButtonViewBinder: VolumeDialogSettingsButtonViewBinder, - private val gravityViewModel: VolumeDialogGravityViewModel, -) { - - fun bind(dialog: Dialog) { - with(dialog) { - setupWindow(window!!) - dialog.setContentView(R.layout.volume_dialog) - dialog.setCanceledOnTouchOutside(true) - - with(dialog.requireViewById<View>(R.id.volume_dialog_container)) { - volumeDialogRingerViewBinder.bind(this) - slidersViewBinder.bind(this) - settingsButtonViewBinder.bind(this) - volumeDialogViewBinder.bind(dialog, this) - } - } - } - - /** Configures [Window] for the [Dialog]. */ - private fun setupWindow(window: Window) = - with(window) { - clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) - addFlags( - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or - WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or - WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or - WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED - ) - addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY) - - requestFeature(Window.FEATURE_NO_TITLE) - setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY) - setWindowAnimations(-1) - setFormat(PixelFormat.TRANSLUCENT) - - attributes = - attributes.apply { - title = "VolumeDialog" // Not the same as Window#setTitle - } - setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) - - gravityViewModel.dialogGravity.onEach { window.setGravity(it) }.launchIn(coroutineScope) - } -} diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt index 23e6eac05ea8..f9c7bc06672f 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt @@ -17,15 +17,26 @@ package com.android.systemui.volume.dialog.ui.binder import android.app.Dialog +import android.graphics.Color +import android.graphics.PixelFormat +import android.graphics.drawable.ColorDrawable import android.view.Gravity import android.view.View +import android.view.ViewGroup +import android.view.Window +import android.view.WindowManager import com.android.internal.view.RotationPolicy import com.android.systemui.lifecycle.WindowLifecycleState import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.lifecycle.viewModel +import com.android.systemui.res.R import com.android.systemui.volume.SystemUIInterpolators +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope +import com.android.systemui.volume.dialog.ringer.ui.binder.VolumeDialogRingerViewBinder +import com.android.systemui.volume.dialog.settings.ui.binder.VolumeDialogSettingsButtonViewBinder import com.android.systemui.volume.dialog.shared.model.VolumeDialogVisibilityModel +import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogSlidersViewBinder import com.android.systemui.volume.dialog.ui.utils.JankListenerFactory import com.android.systemui.volume.dialog.ui.utils.suspendAnimate import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogGravityViewModel @@ -40,6 +51,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.mapLatest +import kotlinx.coroutines.flow.onEach /** Binds the root view of the Volume Dialog. */ @OptIn(ExperimentalCoroutinesApi::class) @@ -52,9 +64,15 @@ constructor( private val viewModelFactory: VolumeDialogViewModel.Factory, private val jankListenerFactory: JankListenerFactory, private val tracer: VolumeTracer, + @VolumeDialog private val coroutineScope: CoroutineScope, + private val volumeDialogRingerViewBinder: VolumeDialogRingerViewBinder, + private val slidersViewBinder: VolumeDialogSlidersViewBinder, + private val settingsButtonViewBinder: VolumeDialogSettingsButtonViewBinder, ) { - fun bind(dialog: Dialog, view: View) { + fun bind(dialog: Dialog) { + setupDialog(dialog) + val view: View = dialog.requireViewById(R.id.volume_dialog_container) view.alpha = 0f view.repeatWhenAttached { view.viewModel( @@ -62,11 +80,46 @@ constructor( minWindowLifecycleState = WindowLifecycleState.ATTACHED, factory = { viewModelFactory.create() }, ) { viewModel -> + viewModel.dialogTitle.onEach { dialog.window?.setTitle(it) }.launchIn(this) + animateVisibility(view, dialog, viewModel.dialogVisibilityModel) awaitCancellation() } } + volumeDialogRingerViewBinder.bind(view) + slidersViewBinder.bind(view) + settingsButtonViewBinder.bind(view) + } + + /** Configures [Window] for the [Dialog]. */ + private fun setupDialog(dialog: Dialog) { + with(dialog.window!!) { + clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) + addFlags( + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or + WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or + WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or + WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED + ) + addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY) + + requestFeature(Window.FEATURE_NO_TITLE) + setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY) + setWindowAnimations(-1) + setFormat(PixelFormat.TRANSLUCENT) + + attributes = + attributes.apply { + title = "VolumeDialog" // Not the same as Window#setTitle + } + setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + + gravityViewModel.dialogGravity.onEach { setGravity(it) }.launchIn(coroutineScope) + } + dialog.setContentView(R.layout.volume_dialog) + dialog.setCanceledOnTouchOutside(true) } private fun CoroutineScope.animateVisibility( diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt index 84c837c9033d..e9786d0b53a3 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt @@ -16,21 +16,42 @@ package com.android.systemui.volume.dialog.ui.viewmodel +import android.content.Context import com.android.systemui.lifecycle.ExclusiveActivatable +import com.android.systemui.res.R import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogVisibilityInteractor import com.android.systemui.volume.dialog.shared.model.VolumeDialogVisibilityModel +import com.android.systemui.volume.dialog.shared.model.streamLabel +import com.android.systemui.volume.dialog.sliders.domain.interactor.VolumeDialogSliderInteractor +import com.android.systemui.volume.dialog.sliders.domain.interactor.VolumeDialogSlidersInteractor import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.map /** Provides a state for the Volume Dialog. */ +@OptIn(ExperimentalCoroutinesApi::class) class VolumeDialogViewModel @AssistedInject -constructor(dialogVisibilityInteractor: VolumeDialogVisibilityInteractor) : ExclusiveActivatable() { +constructor( + private val context: Context, + dialogVisibilityInteractor: VolumeDialogVisibilityInteractor, + volumeDialogSlidersInteractor: VolumeDialogSlidersInteractor, + private val volumeDialogSliderInteractorFactory: VolumeDialogSliderInteractor.Factory, +) : ExclusiveActivatable() { val dialogVisibilityModel: Flow<VolumeDialogVisibilityModel> = dialogVisibilityInteractor.dialogVisibility + val dialogTitle: Flow<String> = + volumeDialogSlidersInteractor.sliders.flatMapLatest { slidersModel -> + val interactor = volumeDialogSliderInteractorFactory.create(slidersModel.slider) + interactor.slider.map { sliderModel -> + context.getString(R.string.volume_dialog_title, sliderModel.streamLabel(context)) + } + } override suspend fun onActivated(): Nothing { awaitCancellation() |