1 /* 2 * Copyright (C) 2022 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.healthconnect.controller.recentaccess 18 19 import android.content.Context 20 import android.widget.ImageView 21 import android.widget.TextView 22 import androidx.core.view.isVisible 23 import androidx.preference.Preference 24 import androidx.preference.PreferenceViewHolder 25 import com.android.healthconnect.controller.R 26 import com.android.healthconnect.controller.permissions.connectedapps.ComparablePreference 27 import com.android.healthconnect.controller.shared.preference.HealthPreference 28 import com.android.healthconnect.controller.utils.TimeSource 29 import com.android.healthconnect.controller.utils.formatRecentAccessTime 30 import com.android.healthconnect.controller.utils.logging.RecentAccessElement 31 32 /** Custom preference for displaying Recent access apps, including dash lines for timeline views. */ 33 class RecentAccessPreference( 34 context: Context, 35 private val recentAccessEntry: RecentAccessEntry, 36 private val timeSource: TimeSource, 37 private val showCategories: Boolean, 38 ) : HealthPreference(context), ComparablePreference { 39 <lambda>null40 private val separator: String by lazy { context.getString(R.string.separator) } 41 42 init { 43 layoutResource = R.layout.widget_recent_access_timeline 44 isSelectable = true 45 this.logName = RecentAccessElement.RECENT_ACCESS_ENTRY_BUTTON 46 } 47 onBindViewHoldernull48 override fun onBindViewHolder(holder: PreferenceViewHolder) { 49 super.onBindViewHolder(holder) 50 51 val appIcon = holder.findViewById(R.id.recent_access_app_icon) as ImageView 52 appIcon.setImageDrawable(recentAccessEntry.metadata.icon) 53 54 val appTitle = holder.findViewById(R.id.title) as TextView 55 appTitle.text = recentAccessEntry.metadata.appName 56 57 val dataTypesWritten = holder.findViewById(R.id.data_types_written) as TextView 58 if (showCategories && recentAccessEntry.dataTypesWritten.isNotEmpty()) { 59 dataTypesWritten.text = getWrittenText() 60 dataTypesWritten.isVisible = true 61 } else { 62 dataTypesWritten.isVisible = false 63 } 64 65 val dataTypesRead = holder.findViewById(R.id.data_types_read) as TextView 66 if (showCategories && recentAccessEntry.dataTypesRead.isNotEmpty()) { 67 dataTypesRead.text = getReadText() 68 dataTypesRead.isVisible = true 69 } else { 70 dataTypesRead.isVisible = false 71 } 72 73 val accessTime = holder.findViewById(R.id.time) as TextView 74 val formattedTime = 75 formatRecentAccessTime(recentAccessEntry.instantTime, timeSource, context) 76 accessTime.text = formattedTime 77 accessTime.contentDescription = 78 context.getString(R.string.recent_access_time_content_descritption, formattedTime) 79 } 80 isSameItemnull81 override fun isSameItem(preference: Preference): Boolean { 82 return preference is RecentAccessPreference && this == preference 83 } 84 hasSameContentsnull85 override fun hasSameContents(preference: Preference): Boolean { 86 return preference is RecentAccessPreference && 87 this.recentAccessEntry == preference.recentAccessEntry 88 } 89 getWrittenTextnull90 private fun getWrittenText(): String { 91 val sortedDataTypes = sortWithHealthRecordsFirst(recentAccessEntry.dataTypesWritten) 92 return context.getString( 93 R.string.write_data_access_label, 94 sortedDataTypes.joinToString(separator), 95 ) 96 } 97 getReadTextnull98 private fun getReadText(): String { 99 val sortedDataTypes = sortWithHealthRecordsFirst(recentAccessEntry.dataTypesRead) 100 return context.getString( 101 R.string.read_data_access_label, 102 sortedDataTypes.joinToString(separator), 103 ) 104 } 105 sortWithHealthRecordsFirstnull106 private fun sortWithHealthRecordsFirst(dataTypes: MutableSet<Int>): List<String> { 107 val sortedList = dataTypes.map { context.getString(it) }.sorted().toMutableList() 108 109 val healthRecordsString = context.getString(R.string.medical_permissions) 110 if (sortedList.contains(healthRecordsString)) { 111 sortedList.remove(healthRecordsString) 112 sortedList.add(0, healthRecordsString) 113 } 114 115 return sortedList 116 } 117 } 118