1 /* 2 * Copyright (C) 2023 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.viewmodel 18 19 import android.content.res.Resources 20 import android.content.res.Resources.Theme 21 import android.service.quicksettings.Tile 22 import android.view.View 23 import android.widget.Switch 24 import com.android.systemui.common.shared.model.Icon 25 import kotlin.reflect.KClass 26 27 /** 28 * Represents current a state of the tile to be displayed in on the view. Consider using 29 * [QSTileState.build] for better state creation experience and preset default values for certain 30 * fields. 31 * 32 * @param iconRes For when we want to have Loaded icon, but still keep a reference to the resource 33 * id. A use case would be for tests that have to compare animated drawables. 34 * 35 * // TODO(b/http://b/299909989): Clean up legacy mappings after the transition 36 */ 37 data class QSTileState( 38 val icon: () -> Icon?, 39 val iconRes: Int?, 40 val label: CharSequence, 41 val activationState: ActivationState, 42 val secondaryLabel: CharSequence?, 43 val supportedActions: Set<UserAction>, 44 val contentDescription: CharSequence?, 45 val stateDescription: CharSequence?, 46 val sideViewIcon: SideViewIcon, 47 val enabledState: EnabledState, 48 val expandedAccessibilityClassName: String?, 49 ) { 50 51 companion object { 52 buildnull53 fun build( 54 resources: Resources, 55 theme: Theme, 56 config: QSTileUIConfig, 57 build: Builder.() -> Unit 58 ): QSTileState { 59 val iconDrawable = resources.getDrawable(config.iconRes, theme) 60 return build( 61 { Icon.Loaded(iconDrawable, null) }, 62 resources.getString(config.labelRes), 63 build, 64 ) 65 } 66 buildnull67 fun build(icon: () -> Icon?, label: CharSequence, build: Builder.() -> Unit): QSTileState = 68 Builder(icon, label).apply(build).build() 69 } 70 71 enum class ActivationState(val legacyState: Int) { 72 // An unavailable state indicates that for some reason this tile is not currently available 73 // to the user, and will have no click action. The tile's icon will be tinted differently to 74 // reflect this state. 75 UNAVAILABLE(Tile.STATE_UNAVAILABLE), 76 // This represents a tile that is currently active. (e.g. wifi is connected, bluetooth is 77 // on, cast is casting). This is the default state. 78 ACTIVE(Tile.STATE_ACTIVE), 79 // This represents a tile that is currently in a disabled state but is still interactable. A 80 // disabled state indicates that the tile is not currently active (e.g. wifi disconnected or 81 // bluetooth disabled), but is still interactable by the user to modify this state. 82 INACTIVE(Tile.STATE_INACTIVE); 83 84 companion object { 85 fun valueOf(legacyState: Int): ActivationState = 86 when (legacyState) { 87 Tile.STATE_ACTIVE -> ACTIVE 88 Tile.STATE_INACTIVE -> INACTIVE 89 else -> UNAVAILABLE 90 } 91 } 92 } 93 94 /** 95 * Enabled tile behaves as usual where is disabled one is frozen and inactive in its current 96 * [ActivationState]. 97 */ 98 enum class EnabledState { 99 ENABLED, 100 DISABLED, 101 } 102 103 enum class UserAction { 104 CLICK, 105 LONG_CLICK, 106 } 107 108 sealed interface SideViewIcon { 109 data class Custom(val icon: Icon) : SideViewIcon 110 data object Chevron : SideViewIcon 111 data object None : SideViewIcon 112 } 113 114 class Builder( 115 var icon: () -> Icon?, 116 var label: CharSequence, 117 ) { 118 var iconRes: Int? = null 119 var activationState: ActivationState = ActivationState.INACTIVE 120 var secondaryLabel: CharSequence? = null 121 var supportedActions: Set<UserAction> = setOf(UserAction.CLICK) 122 var contentDescription: CharSequence? = null 123 var stateDescription: CharSequence? = null 124 var sideViewIcon: SideViewIcon = SideViewIcon.None 125 var enabledState: EnabledState = EnabledState.ENABLED 126 var expandedAccessibilityClass: KClass<out View>? = Switch::class 127 buildnull128 fun build(): QSTileState = 129 QSTileState( 130 icon, 131 iconRes, 132 label, 133 activationState, 134 secondaryLabel, 135 supportedActions, 136 contentDescription, 137 stateDescription, 138 sideViewIcon, 139 enabledState, 140 expandedAccessibilityClass?.qualifiedName, 141 ) 142 } 143 } 144