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 package com.android.healthconnect.controller.autodelete
17 
18 import android.content.Context
19 import android.icu.text.MessageFormat
20 import android.os.Bundle
21 import android.view.LayoutInflater
22 import android.view.View
23 import android.view.ViewGroup
24 import android.widget.LinearLayout
25 import android.widget.RadioButton
26 import android.widget.RadioGroup
27 import androidx.core.os.bundleOf
28 import androidx.core.view.children
29 import androidx.fragment.app.FragmentManager
30 import androidx.preference.Preference
31 import androidx.preference.PreferenceViewHolder
32 import com.android.healthconnect.controller.R
33 import com.android.healthconnect.controller.utils.logging.AutoDeleteElement
34 import com.android.healthconnect.controller.utils.logging.ErrorPageElement
35 import com.android.healthconnect.controller.utils.logging.HealthConnectLogger
36 
37 /**
38  * Custom preference for displaying a custom dialog where the user can confirm the auto-delete range
39  * update.
40  */
41 class AutoDeleteRangePickerPreference
42 constructor(
43     context: Context,
44     private val childFragmentManager: FragmentManager,
45     private var autoDeleteRange: AutoDeleteRange,
46     private val logger: HealthConnectLogger
47 ) : Preference(context), RadioGroup.OnCheckedChangeListener {
48 
49     companion object {
50         const val SET_TO_NEVER_EVENT = "SET_TO_NEVER_EVENT"
51         const val AUTO_DELETE_RANGE_PICKER_PREFERENCE_KEY = "auto_delete_range_picker"
52     }
53 
54     init {
55         key = AUTO_DELETE_RANGE_PICKER_PREFERENCE_KEY
56     }
57 
onBindViewHoldernull58     override fun onBindViewHolder(holder: PreferenceViewHolder) {
59         super.onBindViewHolder(holder)
60 
61         val widgetFrame: ViewGroup = holder.findViewById(android.R.id.widget_frame) as ViewGroup
62         val widgetFrameParent: LinearLayout = widgetFrame.parent as LinearLayout
63 
64         val iconFrame: LinearLayout? = holder.findViewById(android.R.id.icon_frame) as LinearLayout?
65         widgetFrameParent.removeView(iconFrame)
66 
67         var autoDeleteWidget: ViewGroup? =
68             holder.findViewById(R.id.auto_delete_range_picker_layout) as ViewGroup?
69         if (autoDeleteWidget == null) {
70             val inflater: LayoutInflater = context.getSystemService(LayoutInflater::class.java)
71             autoDeleteWidget =
72                 inflater.inflate(R.layout.widget_auto_delete_range_picker, widgetFrameParent, false)
73                     as ViewGroup?
74             widgetFrameParent.addView(autoDeleteWidget, 0)
75             widgetFrameParent.isFocusable = false
76             widgetFrameParent.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
77         }
78 
79         val radioGroup: RadioGroup = holder.findViewById(R.id.radio_group_time_range) as RadioGroup
80         setRadioButtonTexts(radioGroup)
81 
82         setRadioButtonLogging(radioGroup)
83 
84         radioGroup.setOnCheckedChangeListener(null)
85         setCheckedRadioButton(radioGroup, autoDeleteRange)
86         radioGroup.setOnCheckedChangeListener(this)
87     }
88 
setRadioButtonLoggingnull89     private fun setRadioButtonLogging(radioGroup: RadioGroup) {
90         radioGroup.children.forEach {
91             val element =
92                 when (it.id) {
93                     R.id.radio_button_3_months -> AutoDeleteElement.AUTO_DELETE_3_MONTHS_BUTTON
94                     R.id.radio_button_18_months -> AutoDeleteElement.AUTO_DELETE_18_MONTHS_BUTTON
95                     R.id.radio_button_never -> AutoDeleteElement.AUTO_DELETE_NEVER_BUTTON
96                     else -> ErrorPageElement.UNKNOWN_ELEMENT
97                 }
98 
99             it.setOnClickListener { logger.logInteraction(element) }
100 
101             logger.logImpression(element)
102         }
103     }
104 
setRadioButtonTextsnull105     private fun setRadioButtonTexts(radioGroup: RadioGroup) {
106         val radioButton3Months: RadioButton = radioGroup.findViewById(R.id.radio_button_3_months)
107         var count = AutoDeleteRange.AUTO_DELETE_RANGE_THREE_MONTHS.numberOfMonths
108         radioButton3Months.text =
109             MessageFormat.format(
110                 context.getString(R.string.range_after_x_months), mapOf("count" to count))
111 
112         val radioButton18Months: RadioButton = radioGroup.findViewById(R.id.radio_button_18_months)
113         count = AutoDeleteRange.AUTO_DELETE_RANGE_EIGHTEEN_MONTHS.numberOfMonths
114         radioButton18Months.text =
115             MessageFormat.format(
116                 context.getString(R.string.range_after_x_months), mapOf("count" to count))
117     }
118 
setCheckedRadioButtonnull119     private fun setCheckedRadioButton(radioGroup: RadioGroup, autoDeleteRange: AutoDeleteRange) {
120         when (autoDeleteRange) {
121             AutoDeleteRange.AUTO_DELETE_RANGE_NEVER -> radioGroup.check(R.id.radio_button_never)
122             AutoDeleteRange.AUTO_DELETE_RANGE_THREE_MONTHS ->
123                 radioGroup.check(R.id.radio_button_3_months)
124             AutoDeleteRange.AUTO_DELETE_RANGE_EIGHTEEN_MONTHS ->
125                 radioGroup.check(R.id.radio_button_18_months)
126         }
127     }
128 
setToNeverOrAskConfirmationnull129     private fun setToNeverOrAskConfirmation(chosenId: Int) {
130         if (chosenId == R.id.radio_button_never) {
131             childFragmentManager.setFragmentResult(SET_TO_NEVER_EVENT, Bundle())
132             return
133         }
134         val newAutoDeleteRange: AutoDeleteRange =
135             if (chosenId == R.id.radio_button_3_months)
136                 AutoDeleteRange.AUTO_DELETE_RANGE_THREE_MONTHS
137             else AutoDeleteRange.AUTO_DELETE_RANGE_EIGHTEEN_MONTHS
138         childFragmentManager.setFragmentResult(
139             AutoDeleteConfirmationDialogFragment.AUTO_DELETE_CONFIRMATION_DIALOG_EVENT,
140             bundleOf(
141                 AutoDeleteConfirmationDialogFragment.NEW_AUTO_DELETE_RANGE_BUNDLE to
142                     newAutoDeleteRange,
143                 AutoDeleteConfirmationDialogFragment.OLD_AUTO_DELETE_RANGE_BUNDLE to
144                     autoDeleteRange))
145     }
146 
onCheckedChangednull147     override fun onCheckedChanged(radioGroup: RadioGroup, checkedId: Int) {
148         setToNeverOrAskConfirmation(checkedId)
149     }
150 
updateAutoDeleteRangenull151     fun updateAutoDeleteRange(newAutoDeleteRange: AutoDeleteRange) {
152         autoDeleteRange = newAutoDeleteRange
153         notifyChanged()
154     }
155 }
156