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.logging.RecentAccessElement 30 import java.time.Instant 31 import java.time.LocalTime 32 import java.time.ZoneId 33 import java.time.format.DateTimeFormatter 34 import java.util.Locale 35 36 /** Custom preference for displaying Recent access apps, including dash lines for timeline views. */ 37 class RecentAccessPreference 38 constructor( 39 context: Context, 40 private val recentAccessApp: RecentAccessEntry, 41 private val timeSource: TimeSource, 42 private val showCategories: Boolean 43 ) : HealthPreference(context), ComparablePreference { 44 45 private lateinit var appIcon: ImageView 46 private lateinit var appTitle: TextView 47 private lateinit var dataTypesWritten: TextView 48 private lateinit var dataTypesRead: TextView 49 private lateinit var accessTime: TextView 50 private val separator: String = context.getString(R.string.data_type_separator) 51 52 private val appName = recentAccessApp.metadata.appName 53 private val writtenText: String = 54 context.getString( 55 R.string.write_data_access_label, <lambda>null56 recentAccessApp.dataTypesWritten.sorted().joinToString(separator) { 57 context.getString(it) 58 }) 59 private val readText: String = 60 context.getString( 61 R.string.read_data_access_label, <lambda>null62 recentAccessApp.dataTypesRead.sorted().joinToString(separator) { 63 context.getString(it) 64 }) 65 private val formattedTime = formatTime(recentAccessApp.instantTime) 66 // Used to compare this preference to other RecentAccessPreferences 67 val comparableTitle = "${formattedTime}_${appName}_${writtenText}_${readText}" 68 69 init { 70 layoutResource = R.layout.widget_recent_access_timeline 71 isSelectable = true 72 this.logName = RecentAccessElement.RECENT_ACCESS_ENTRY_BUTTON 73 } 74 onBindViewHoldernull75 override fun onBindViewHolder(holder: PreferenceViewHolder) { 76 super.onBindViewHolder(holder) 77 78 appIcon = holder.findViewById(R.id.recent_access_app_icon) as ImageView 79 appIcon.setImageDrawable(recentAccessApp.metadata.icon) 80 81 appTitle = holder.findViewById(R.id.title) as TextView 82 appTitle.text = appName 83 84 dataTypesWritten = holder.findViewById(R.id.data_types_written) as TextView 85 dataTypesRead = holder.findViewById(R.id.data_types_read) as TextView 86 87 if (showCategories) { 88 if (recentAccessApp.dataTypesWritten.isNotEmpty()) { 89 dataTypesWritten.text = writtenText 90 dataTypesWritten.isVisible = true 91 } 92 93 if (recentAccessApp.dataTypesRead.isNotEmpty()) { 94 dataTypesRead.text = readText 95 dataTypesRead.isVisible = true 96 } 97 } 98 99 accessTime = holder.findViewById(R.id.time) as TextView 100 accessTime.text = formattedTime 101 accessTime.contentDescription = 102 context.getString(R.string.recent_access_time_content_descritption, formattedTime) 103 } 104 isSameItemnull105 override fun isSameItem(preference: Preference): Boolean { 106 return preference is RecentAccessPreference && this == preference 107 } 108 hasSameContentsnull109 override fun hasSameContents(preference: Preference): Boolean { 110 return preference is RecentAccessPreference && 111 this.recentAccessApp == preference.recentAccessApp 112 } 113 formatTimenull114 private fun formatTime(instant: Instant): String { 115 val localTime: LocalTime = instant.atZone(ZoneId.systemDefault()).toLocalTime() 116 return if (timeSource.is24Hour(context)) { 117 localTime.format(DateTimeFormatter.ofPattern("HH:mm")) 118 } else { 119 if (Locale.getDefault() == Locale.KOREA || Locale.getDefault() == Locale.KOREAN) { 120 localTime.format(DateTimeFormatter.ofPattern("a h:mm")) 121 } else { 122 localTime.format(DateTimeFormatter.ofPattern("h:mm a")) 123 } 124 } 125 } 126 } 127