Loading packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt +8 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ import com.android.systemui.controls.management.ControlsProviderSelectorActivity import com.android.systemui.controls.management.ControlsRequestDialog import com.android.systemui.controls.ui.ControlsUiController import com.android.systemui.controls.ui.ControlsUiControllerImpl import com.android.systemui.controls.ui.ControlActionCoordinator import com.android.systemui.controls.ui.ControlActionCoordinatorImpl import dagger.Binds import dagger.BindsOptionalOf import dagger.Module Loading @@ -55,6 +57,11 @@ abstract class ControlsModule { @Binds abstract fun provideUiController(controller: ControlsUiControllerImpl): ControlsUiController @Binds abstract fun provideControlActionCoordinator( coordinator: ControlActionCoordinatorImpl ): ControlActionCoordinator @BindsOptionalOf abstract fun optionalPersistenceWrapper(): ControlsFavoritePersistenceWrapper Loading packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt +34 −71 Original line number Diff line number Diff line Loading @@ -16,89 +16,52 @@ package com.android.systemui.controls.ui import android.app.Dialog import android.content.Intent import android.os.Vibrator import android.os.VibrationEffect import android.service.controls.Control import android.service.controls.actions.BooleanAction import android.service.controls.actions.CommandAction import android.view.HapticFeedbackConstants import com.android.systemui.controls.controller.ControlsController import com.android.systemui.util.concurrency.DelayableExecutor object ControlActionCoordinator { const val MIN_LEVEL = 0 const val MAX_LEVEL = 10000 private var dialog: Dialog? = null private var vibrator: Vibrator? = null lateinit var bgExecutor: DelayableExecutor fun closeDialog() { dialog?.dismiss() dialog = null } /** * All control interactions should be routed through this coordinator. It handles dispatching of * actions, haptic support, and all detail panels */ interface ControlActionCoordinator { /** * Create custom vibrations, all intended to create very subtle feedback while interacting * with the controls. * Close any dialogs which may have been open */ fun initialize(vibrator: Vibrator, bgExecutor: DelayableExecutor) { this.vibrator = vibrator this.bgExecutor = bgExecutor } fun closeDialogs() fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) { val effect = if (isChecked) Vibrations.toggleOnEffect else Vibrations.toggleOffEffect vibrate(effect) cvh.action(BooleanAction(templateId, !isChecked)) } /** * Create a [BooleanAction], and inform the service of a request to change the device state * * @param cvh [ControlViewHolder] for the control * @param templateId id of the control's template, as given by the service * @param isChecked new requested state of the control */ fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) fun touch(cvh: ControlViewHolder, templateId: String, control: Control) { vibrate(Vibrations.toggleOnEffect) if (cvh.usePanel()) { showDialog(cvh, control.getAppIntent().getIntent()) } else { cvh.action(CommandAction(templateId)) } } /** * For non-toggle controls, touching may create a dialog or invoke a [CommandAction]. * * @param cvh [ControlViewHolder] for the control * @param templateId id of the control's template, as given by the service * @param control the control as sent by the service */ fun touch(cvh: ControlViewHolder, templateId: String, control: Control) fun drag(isEdge: Boolean) { if (isEdge) { vibrate(Vibrations.rangeEdgeEffect) } else { vibrate(Vibrations.rangeMiddleEffect) } } /** * When a ToggleRange control is interacting with, a drag event is sent. * * @param isEdge did the drag event reach a control edge */ fun drag(isEdge: Boolean) /** * All long presses will be shown in a 3/4 height bottomsheet panel, in order for the user to * retain context with their favorited controls in the power menu. */ fun longPress(cvh: ControlViewHolder) { // Long press snould only be called when there is valid control state, otherwise ignore cvh.cws.control?.let { cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) showDialog(cvh, it.getAppIntent().getIntent()) } } private fun vibrate(effect: VibrationEffect) { vibrator?.let { bgExecutor.execute { it.vibrate(effect) } } } private fun showDialog(cvh: ControlViewHolder, intent: Intent) { dialog = DetailDialog(cvh, intent).also { it.setOnDismissListener { _ -> dialog = null } it.show() } } fun longPress(cvh: ControlViewHolder) fun setFocusedElement(cvh: ControlViewHolder?, controlsController: ControlsController) { controlsController.onFocusChanged(cvh?.cws) } /** * Event to inform the UI that the user has has focused on a single control. */ fun setFocusedElement(cvh: ControlViewHolder?) } packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt 0 → 100644 +126 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.controls.ui import android.app.Dialog import android.content.Context import android.content.Intent import android.os.Vibrator import android.os.VibrationEffect import android.service.controls.Control import android.service.controls.actions.BooleanAction import android.service.controls.actions.CommandAction import android.util.Log import android.view.HapticFeedbackConstants import com.android.systemui.controls.controller.ControlsController import com.android.systemui.globalactions.GlobalActionsComponent import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.concurrency.DelayableExecutor import dagger.Lazy import javax.inject.Inject import javax.inject.Singleton @Singleton class ControlActionCoordinatorImpl @Inject constructor( private val context: Context, private val bgExecutor: DelayableExecutor, private val controlsController: Lazy<ControlsController>, private val activityStarter: ActivityStarter, private val keyguardStateController: KeyguardStateController, private val globalActionsComponent: GlobalActionsComponent ) : ControlActionCoordinator { private var dialog: Dialog? = null private val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator private var lastAction: (() -> Unit)? = null override fun closeDialogs() { dialog?.dismiss() dialog = null } override fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) { bouncerOrRun { val effect = if (isChecked) Vibrations.toggleOnEffect else Vibrations.toggleOffEffect vibrate(effect) cvh.action(BooleanAction(templateId, !isChecked)) } } override fun touch(cvh: ControlViewHolder, templateId: String, control: Control) { vibrate(Vibrations.toggleOnEffect) bouncerOrRun { if (cvh.usePanel()) { showDialog(cvh, control.getAppIntent().getIntent()) } else { cvh.action(CommandAction(templateId)) } } } override fun drag(isEdge: Boolean) { bouncerOrRun { if (isEdge) { vibrate(Vibrations.rangeEdgeEffect) } else { vibrate(Vibrations.rangeMiddleEffect) } } } override fun longPress(cvh: ControlViewHolder) { bouncerOrRun { // Long press snould only be called when there is valid control state, otherwise ignore cvh.cws.control?.let { cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) showDialog(cvh, it.getAppIntent().getIntent()) } } } override fun setFocusedElement(cvh: ControlViewHolder?) { controlsController.get().onFocusChanged(cvh?.cws) } private fun bouncerOrRun(f: () -> Unit) { if (!keyguardStateController.isUnlocked()) { context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) activityStarter.dismissKeyguardThenExecute({ Log.d(ControlsUiController.TAG, "Device unlocked, invoking controls action") globalActionsComponent.handleShowGlobalActionsMenu() f() true }, null, true) } else { f() } } private fun vibrate(effect: VibrationEffect) { bgExecutor.execute { vibrator.vibrate(effect) } } private fun showDialog(cvh: ControlViewHolder, intent: Intent) { dialog = DetailDialog(cvh, intent).also { it.setOnDismissListener { _ -> dialog = null } it.show() } } } packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt +6 −2 Original line number Diff line number Diff line Loading @@ -53,7 +53,8 @@ class ControlViewHolder( val layout: ViewGroup, val controlsController: ControlsController, val uiExecutor: DelayableExecutor, val bgExecutor: DelayableExecutor val bgExecutor: DelayableExecutor, val controlActionCoordinator: ControlActionCoordinator ) { companion object { Loading @@ -65,6 +66,9 @@ class ControlViewHolder( DeviceTypes.TYPE_THERMOSTAT, DeviceTypes.TYPE_CAMERA ) const val MIN_LEVEL = 0 const val MAX_LEVEL = 10000 } private val toggleBackgroundIntensity: Float = layout.context.resources Loading Loading @@ -121,7 +125,7 @@ class ControlViewHolder( cws.control?.let { layout.setClickable(true) layout.setOnLongClickListener(View.OnLongClickListener() { ControlActionCoordinator.longPress(this@ControlViewHolder) controlActionCoordinator.longPress(this@ControlViewHolder) true }) } Loading packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +18 −12 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import android.content.res.Configuration import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable import android.os.Process import android.os.Vibrator import android.service.controls.Control import android.util.Log import android.util.TypedValue Loading Loading @@ -59,6 +58,8 @@ import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.management.ControlsProviderSelectorActivity import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.concurrency.DelayableExecutor import dagger.Lazy import java.text.Collator Loading @@ -75,7 +76,10 @@ class ControlsUiControllerImpl @Inject constructor ( @Main val uiExecutor: DelayableExecutor, @Background val bgExecutor: DelayableExecutor, val controlsListingController: Lazy<ControlsListingController>, @Main val sharedPreferences: SharedPreferences @Main val sharedPreferences: SharedPreferences, val controlActionCoordinator: ControlActionCoordinator, private val activityStarter: ActivityStarter, private val keyguardStateController: KeyguardStateController ) : ControlsUiController { companion object { Loading Loading @@ -107,11 +111,6 @@ class ControlsUiControllerImpl @Inject constructor ( private lateinit var listingCallback: ControlsListingController.ControlsListingCallback init { val vibratorService = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator ControlActionCoordinator.initialize(vibratorService, bgExecutor) } private fun createCallback( onResult: (List<SelectionItem>) -> Unit ): ControlsListingController.ControlsListingCallback { Loading Loading @@ -267,8 +266,16 @@ class ControlsUiControllerImpl @Inject constructor ( private fun startActivity(context: Context, intent: Intent) { // Force animations when transitioning from a dialog to an activity intent.putExtra(ControlsUiController.EXTRA_ANIMATE, true) context.startActivity(intent) dismissGlobalActions.run() if (!keyguardStateController.isUnlocked()) { activityStarter.dismissKeyguardThenExecute({ context.startActivity(intent) true }, null, true) } else { context.startActivity(intent) } } private fun showControlsView(items: List<SelectionItem>) { Loading Loading @@ -463,7 +470,8 @@ class ControlsUiControllerImpl @Inject constructor ( baseLayout, controlsController.get(), uiExecutor, bgExecutor bgExecutor, controlActionCoordinator ) cvh.bindData(it) controlViewsById.put(key, cvh) Loading Loading @@ -545,9 +553,7 @@ class ControlsUiControllerImpl @Inject constructor ( controlViewsById.forEach { it.value.dismiss() } ControlActionCoordinator.closeDialog() controlActionCoordinator.closeDialogs() controlsController.get().unsubscribe() parent.removeAllViews() Loading Loading
packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt +8 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ import com.android.systemui.controls.management.ControlsProviderSelectorActivity import com.android.systemui.controls.management.ControlsRequestDialog import com.android.systemui.controls.ui.ControlsUiController import com.android.systemui.controls.ui.ControlsUiControllerImpl import com.android.systemui.controls.ui.ControlActionCoordinator import com.android.systemui.controls.ui.ControlActionCoordinatorImpl import dagger.Binds import dagger.BindsOptionalOf import dagger.Module Loading @@ -55,6 +57,11 @@ abstract class ControlsModule { @Binds abstract fun provideUiController(controller: ControlsUiControllerImpl): ControlsUiController @Binds abstract fun provideControlActionCoordinator( coordinator: ControlActionCoordinatorImpl ): ControlActionCoordinator @BindsOptionalOf abstract fun optionalPersistenceWrapper(): ControlsFavoritePersistenceWrapper Loading
packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt +34 −71 Original line number Diff line number Diff line Loading @@ -16,89 +16,52 @@ package com.android.systemui.controls.ui import android.app.Dialog import android.content.Intent import android.os.Vibrator import android.os.VibrationEffect import android.service.controls.Control import android.service.controls.actions.BooleanAction import android.service.controls.actions.CommandAction import android.view.HapticFeedbackConstants import com.android.systemui.controls.controller.ControlsController import com.android.systemui.util.concurrency.DelayableExecutor object ControlActionCoordinator { const val MIN_LEVEL = 0 const val MAX_LEVEL = 10000 private var dialog: Dialog? = null private var vibrator: Vibrator? = null lateinit var bgExecutor: DelayableExecutor fun closeDialog() { dialog?.dismiss() dialog = null } /** * All control interactions should be routed through this coordinator. It handles dispatching of * actions, haptic support, and all detail panels */ interface ControlActionCoordinator { /** * Create custom vibrations, all intended to create very subtle feedback while interacting * with the controls. * Close any dialogs which may have been open */ fun initialize(vibrator: Vibrator, bgExecutor: DelayableExecutor) { this.vibrator = vibrator this.bgExecutor = bgExecutor } fun closeDialogs() fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) { val effect = if (isChecked) Vibrations.toggleOnEffect else Vibrations.toggleOffEffect vibrate(effect) cvh.action(BooleanAction(templateId, !isChecked)) } /** * Create a [BooleanAction], and inform the service of a request to change the device state * * @param cvh [ControlViewHolder] for the control * @param templateId id of the control's template, as given by the service * @param isChecked new requested state of the control */ fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) fun touch(cvh: ControlViewHolder, templateId: String, control: Control) { vibrate(Vibrations.toggleOnEffect) if (cvh.usePanel()) { showDialog(cvh, control.getAppIntent().getIntent()) } else { cvh.action(CommandAction(templateId)) } } /** * For non-toggle controls, touching may create a dialog or invoke a [CommandAction]. * * @param cvh [ControlViewHolder] for the control * @param templateId id of the control's template, as given by the service * @param control the control as sent by the service */ fun touch(cvh: ControlViewHolder, templateId: String, control: Control) fun drag(isEdge: Boolean) { if (isEdge) { vibrate(Vibrations.rangeEdgeEffect) } else { vibrate(Vibrations.rangeMiddleEffect) } } /** * When a ToggleRange control is interacting with, a drag event is sent. * * @param isEdge did the drag event reach a control edge */ fun drag(isEdge: Boolean) /** * All long presses will be shown in a 3/4 height bottomsheet panel, in order for the user to * retain context with their favorited controls in the power menu. */ fun longPress(cvh: ControlViewHolder) { // Long press snould only be called when there is valid control state, otherwise ignore cvh.cws.control?.let { cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) showDialog(cvh, it.getAppIntent().getIntent()) } } private fun vibrate(effect: VibrationEffect) { vibrator?.let { bgExecutor.execute { it.vibrate(effect) } } } private fun showDialog(cvh: ControlViewHolder, intent: Intent) { dialog = DetailDialog(cvh, intent).also { it.setOnDismissListener { _ -> dialog = null } it.show() } } fun longPress(cvh: ControlViewHolder) fun setFocusedElement(cvh: ControlViewHolder?, controlsController: ControlsController) { controlsController.onFocusChanged(cvh?.cws) } /** * Event to inform the UI that the user has has focused on a single control. */ fun setFocusedElement(cvh: ControlViewHolder?) }
packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt 0 → 100644 +126 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.controls.ui import android.app.Dialog import android.content.Context import android.content.Intent import android.os.Vibrator import android.os.VibrationEffect import android.service.controls.Control import android.service.controls.actions.BooleanAction import android.service.controls.actions.CommandAction import android.util.Log import android.view.HapticFeedbackConstants import com.android.systemui.controls.controller.ControlsController import com.android.systemui.globalactions.GlobalActionsComponent import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.concurrency.DelayableExecutor import dagger.Lazy import javax.inject.Inject import javax.inject.Singleton @Singleton class ControlActionCoordinatorImpl @Inject constructor( private val context: Context, private val bgExecutor: DelayableExecutor, private val controlsController: Lazy<ControlsController>, private val activityStarter: ActivityStarter, private val keyguardStateController: KeyguardStateController, private val globalActionsComponent: GlobalActionsComponent ) : ControlActionCoordinator { private var dialog: Dialog? = null private val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator private var lastAction: (() -> Unit)? = null override fun closeDialogs() { dialog?.dismiss() dialog = null } override fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) { bouncerOrRun { val effect = if (isChecked) Vibrations.toggleOnEffect else Vibrations.toggleOffEffect vibrate(effect) cvh.action(BooleanAction(templateId, !isChecked)) } } override fun touch(cvh: ControlViewHolder, templateId: String, control: Control) { vibrate(Vibrations.toggleOnEffect) bouncerOrRun { if (cvh.usePanel()) { showDialog(cvh, control.getAppIntent().getIntent()) } else { cvh.action(CommandAction(templateId)) } } } override fun drag(isEdge: Boolean) { bouncerOrRun { if (isEdge) { vibrate(Vibrations.rangeEdgeEffect) } else { vibrate(Vibrations.rangeMiddleEffect) } } } override fun longPress(cvh: ControlViewHolder) { bouncerOrRun { // Long press snould only be called when there is valid control state, otherwise ignore cvh.cws.control?.let { cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) showDialog(cvh, it.getAppIntent().getIntent()) } } } override fun setFocusedElement(cvh: ControlViewHolder?) { controlsController.get().onFocusChanged(cvh?.cws) } private fun bouncerOrRun(f: () -> Unit) { if (!keyguardStateController.isUnlocked()) { context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) activityStarter.dismissKeyguardThenExecute({ Log.d(ControlsUiController.TAG, "Device unlocked, invoking controls action") globalActionsComponent.handleShowGlobalActionsMenu() f() true }, null, true) } else { f() } } private fun vibrate(effect: VibrationEffect) { bgExecutor.execute { vibrator.vibrate(effect) } } private fun showDialog(cvh: ControlViewHolder, intent: Intent) { dialog = DetailDialog(cvh, intent).also { it.setOnDismissListener { _ -> dialog = null } it.show() } } }
packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt +6 −2 Original line number Diff line number Diff line Loading @@ -53,7 +53,8 @@ class ControlViewHolder( val layout: ViewGroup, val controlsController: ControlsController, val uiExecutor: DelayableExecutor, val bgExecutor: DelayableExecutor val bgExecutor: DelayableExecutor, val controlActionCoordinator: ControlActionCoordinator ) { companion object { Loading @@ -65,6 +66,9 @@ class ControlViewHolder( DeviceTypes.TYPE_THERMOSTAT, DeviceTypes.TYPE_CAMERA ) const val MIN_LEVEL = 0 const val MAX_LEVEL = 10000 } private val toggleBackgroundIntensity: Float = layout.context.resources Loading Loading @@ -121,7 +125,7 @@ class ControlViewHolder( cws.control?.let { layout.setClickable(true) layout.setOnLongClickListener(View.OnLongClickListener() { ControlActionCoordinator.longPress(this@ControlViewHolder) controlActionCoordinator.longPress(this@ControlViewHolder) true }) } Loading
packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +18 −12 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import android.content.res.Configuration import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable import android.os.Process import android.os.Vibrator import android.service.controls.Control import android.util.Log import android.util.TypedValue Loading Loading @@ -59,6 +58,8 @@ import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.management.ControlsProviderSelectorActivity import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.concurrency.DelayableExecutor import dagger.Lazy import java.text.Collator Loading @@ -75,7 +76,10 @@ class ControlsUiControllerImpl @Inject constructor ( @Main val uiExecutor: DelayableExecutor, @Background val bgExecutor: DelayableExecutor, val controlsListingController: Lazy<ControlsListingController>, @Main val sharedPreferences: SharedPreferences @Main val sharedPreferences: SharedPreferences, val controlActionCoordinator: ControlActionCoordinator, private val activityStarter: ActivityStarter, private val keyguardStateController: KeyguardStateController ) : ControlsUiController { companion object { Loading Loading @@ -107,11 +111,6 @@ class ControlsUiControllerImpl @Inject constructor ( private lateinit var listingCallback: ControlsListingController.ControlsListingCallback init { val vibratorService = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator ControlActionCoordinator.initialize(vibratorService, bgExecutor) } private fun createCallback( onResult: (List<SelectionItem>) -> Unit ): ControlsListingController.ControlsListingCallback { Loading Loading @@ -267,8 +266,16 @@ class ControlsUiControllerImpl @Inject constructor ( private fun startActivity(context: Context, intent: Intent) { // Force animations when transitioning from a dialog to an activity intent.putExtra(ControlsUiController.EXTRA_ANIMATE, true) context.startActivity(intent) dismissGlobalActions.run() if (!keyguardStateController.isUnlocked()) { activityStarter.dismissKeyguardThenExecute({ context.startActivity(intent) true }, null, true) } else { context.startActivity(intent) } } private fun showControlsView(items: List<SelectionItem>) { Loading Loading @@ -463,7 +470,8 @@ class ControlsUiControllerImpl @Inject constructor ( baseLayout, controlsController.get(), uiExecutor, bgExecutor bgExecutor, controlActionCoordinator ) cvh.bindData(it) controlViewsById.put(key, cvh) Loading Loading @@ -545,9 +553,7 @@ class ControlsUiControllerImpl @Inject constructor ( controlViewsById.forEach { it.value.dismiss() } ControlActionCoordinator.closeDialog() controlActionCoordinator.closeDialogs() controlsController.get().unsubscribe() parent.removeAllViews() Loading