1 /* <lambda>null2 * Copyright (C) 2019 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.statusbar.notification.row 18 19 import android.app.NotificationChannel 20 import android.app.NotificationManager.IMPORTANCE_DEFAULT 21 import android.app.NotificationManager.IMPORTANCE_NONE 22 import android.app.NotificationManager.IMPORTANCE_UNSPECIFIED 23 import android.content.Context 24 import android.graphics.drawable.Drawable 25 import android.text.TextUtils 26 import android.transition.AutoTransition 27 import android.transition.Transition 28 import android.transition.TransitionManager 29 import android.util.AttributeSet 30 import android.view.LayoutInflater 31 import android.view.View 32 import android.widget.ImageView 33 import android.widget.LinearLayout 34 import android.widget.Switch 35 import android.widget.TextView 36 37 import com.android.systemui.R 38 39 /** 40 * Half-shelf for notification channel controls 41 */ 42 class ChannelEditorListView(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) { 43 lateinit var controller: ChannelEditorDialogController 44 var appIcon: Drawable? = null 45 var appName: String? = null 46 var channels = mutableListOf<NotificationChannel>() 47 set(newValue) { 48 field = newValue 49 updateRows() 50 } 51 52 // The first row is for the entire app 53 private lateinit var appControlRow: AppControlView 54 55 override fun onFinishInflate() { 56 super.onFinishInflate() 57 58 appControlRow = findViewById(R.id.app_control) 59 } 60 61 private fun updateRows() { 62 val enabled = controller.appNotificationsEnabled 63 64 val transition = AutoTransition() 65 transition.duration = 200 66 transition.addListener(object : Transition.TransitionListener { 67 override fun onTransitionEnd(p0: Transition?) { 68 notifySubtreeAccessibilityStateChangedIfNeeded() 69 } 70 71 override fun onTransitionResume(p0: Transition?) { 72 } 73 74 override fun onTransitionPause(p0: Transition?) { 75 } 76 77 override fun onTransitionCancel(p0: Transition?) { 78 } 79 80 override fun onTransitionStart(p0: Transition?) { 81 } 82 }) 83 TransitionManager.beginDelayedTransition(this, transition) 84 85 // Remove any rows 86 val n = childCount 87 for (i in n.downTo(0)) { 88 val child = getChildAt(i) 89 if (child is ChannelRow) { 90 removeView(child) 91 } 92 } 93 94 updateAppControlRow(enabled) 95 96 if (enabled) { 97 val inflater = LayoutInflater.from(context) 98 for (channel in channels) { 99 addChannelRow(channel, inflater) 100 } 101 } 102 } 103 104 private fun addChannelRow(channel: NotificationChannel, inflater: LayoutInflater) { 105 val row = inflater.inflate(R.layout.notif_half_shelf_row, null) as ChannelRow 106 row.controller = controller 107 row.channel = channel 108 addView(row) 109 } 110 111 private fun updateAppControlRow(enabled: Boolean) { 112 appControlRow.iconView.setImageDrawable(appIcon) 113 appControlRow.channelName.text = context.resources 114 .getString(R.string.notification_channel_dialog_title, appName) 115 appControlRow.switch.isChecked = enabled 116 appControlRow.switch.setOnCheckedChangeListener { _, b -> 117 controller.appNotificationsEnabled = b 118 updateRows() 119 } 120 } 121 } 122 123 class AppControlView(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) { 124 lateinit var iconView: ImageView 125 lateinit var channelName: TextView 126 lateinit var switch: Switch 127 onFinishInflatenull128 override fun onFinishInflate() { 129 iconView = findViewById(R.id.icon) 130 channelName = findViewById(R.id.app_name) 131 switch = findViewById(R.id.toggle) 132 } 133 } 134 135 class ChannelRow(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) { 136 137 lateinit var controller: ChannelEditorDialogController 138 private lateinit var channelName: TextView 139 private lateinit var channelDescription: TextView 140 private lateinit var switch: Switch 141 var gentle = false 142 143 var channel: NotificationChannel? = null 144 set(newValue) { 145 field = newValue 146 updateImportance() 147 updateViews() 148 } 149 onFinishInflatenull150 override fun onFinishInflate() { 151 channelName = findViewById(R.id.channel_name) 152 channelDescription = findViewById(R.id.channel_description) 153 switch = findViewById(R.id.toggle) 154 switch.setOnCheckedChangeListener { _, b -> 155 channel?.let { 156 controller.proposeEditForChannel(it, if (b) it.importance else IMPORTANCE_NONE) 157 } 158 } 159 } 160 updateViewsnull161 private fun updateViews() { 162 val nc = channel ?: return 163 164 channelName.text = nc.name ?: "" 165 166 nc.group?.let { groupId -> 167 channelDescription.text = controller.groupNameForId(groupId) 168 } 169 170 if (nc.group == null || TextUtils.isEmpty(channelDescription.text)) { 171 channelDescription.visibility = View.GONE 172 } else { 173 channelDescription.visibility = View.VISIBLE 174 } 175 176 switch.isChecked = nc.importance != IMPORTANCE_NONE 177 } 178 updateImportancenull179 private fun updateImportance() { 180 val importance = channel?.importance ?: 0 181 gentle = importance != IMPORTANCE_UNSPECIFIED && importance < IMPORTANCE_DEFAULT 182 } 183 } 184