1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.qs.tiles.impl.modes.domain.interactor 18 19 import android.content.Intent 20 import android.provider.Settings 21 import android.util.Log 22 import com.android.systemui.animation.Expandable 23 import com.android.systemui.dagger.SysUISingleton 24 import com.android.systemui.dagger.qualifiers.Main 25 import com.android.systemui.qs.flags.QSComposeFragment 26 import com.android.systemui.qs.tiles.base.domain.actions.QSTileIntentUserInputHandler 27 import com.android.systemui.qs.tiles.base.domain.interactor.QSTileUserActionInteractor 28 import com.android.systemui.qs.tiles.base.domain.model.QSTileInput 29 import com.android.systemui.qs.tiles.base.shared.model.QSTileUserAction 30 import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel 31 import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor 32 import com.android.systemui.statusbar.policy.ui.dialog.ModesDialogDelegate 33 import com.android.systemui.statusbar.policy.ui.dialog.ModesDialogEventLogger 34 import javax.inject.Inject 35 import kotlin.coroutines.CoroutineContext 36 import kotlinx.coroutines.withContext 37 38 @SysUISingleton 39 class ModesTileUserActionInteractor 40 @Inject 41 constructor( 42 @Main private val mainContext: CoroutineContext, 43 private val qsTileIntentUserInputHandler: QSTileIntentUserInputHandler, 44 // TODO(b/353896370): The domain layer should not have to depend on the UI layer. 45 private val dialogDelegate: ModesDialogDelegate, 46 private val zenModeInteractor: ZenModeInteractor, 47 private val dialogEventLogger: ModesDialogEventLogger, 48 ) : QSTileUserActionInteractor<ModesTileModel> { 49 val longClickIntent = Intent(Settings.ACTION_ZEN_MODE_SETTINGS) 50 handleInputnull51 override suspend fun handleInput(input: QSTileInput<ModesTileModel>) { 52 with(input) { 53 when (action) { 54 is QSTileUserAction.Click -> { 55 handleClick(action.expandable) 56 } 57 is QSTileUserAction.ToggleClick -> { 58 handleToggleClick(input.data) 59 } 60 is QSTileUserAction.LongClick -> { 61 handleLongClick(action.expandable) 62 } 63 } 64 } 65 } 66 handleClicknull67 suspend fun handleClick(expandable: Expandable?) { 68 // Show a dialog with the list of modes to configure. 69 dialogDelegate.showDialog(expandable) 70 } 71 handleToggleClicknull72 suspend fun handleToggleClick(modesTileModel: ModesTileModel) { 73 if (QSComposeFragment.isUnexpectedlyInLegacyMode()) { 74 return 75 } 76 77 // If no modes are on, turn on DND since it's the highest-priority mode. Otherwise, turn 78 // them all off. 79 // We want this toggle to work as a shortcut to DND in most cases, but it should still 80 // correctly toggle the tile state to "off" as the user would expect when more modes are on. 81 if (modesTileModel.activeModes.isEmpty()) { 82 val dnd = zenModeInteractor.dndMode.value 83 if (dnd == null) { 84 Log.wtf(TAG, "Triggered DND but it's null!?") 85 return 86 } 87 88 if (zenModeInteractor.shouldAskForZenDuration(dnd)) { 89 dialogEventLogger.logOpenDurationDialog(dnd) 90 withContext(mainContext) { 91 // NOTE: The dialog handles turning on the mode itself. 92 val dialog = dialogDelegate.makeDndDurationDialog() 93 dialog.show() 94 } 95 } else { 96 dialogEventLogger.logModeOn(dnd) 97 zenModeInteractor.activateMode(dnd) 98 } 99 } else { 100 zenModeInteractor.deactivateAllModes() 101 } 102 } 103 handleLongClicknull104 fun handleLongClick(expandable: Expandable?) { 105 qsTileIntentUserInputHandler.handle(expandable, longClickIntent) 106 } 107 108 companion object { 109 const val TAG = "ModesTileUserActionInteractor" 110 } 111 } 112