1 /**
<lambda>null2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * ```
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * ```
10  *
11  * Unless required by applicable law or agreed to in writing, software distributed under the License
12  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13  * or implied. See the License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 package com.android.healthconnect.controller.dataentries.units
17 
18 import android.os.Bundle
19 import androidx.annotation.StringRes
20 import androidx.preference.ListPreference
21 import com.android.healthconnect.controller.R
22 import com.android.healthconnect.controller.dataentries.units.DistanceUnit.*
23 import com.android.healthconnect.controller.dataentries.units.EnergyUnit.*
24 import com.android.healthconnect.controller.dataentries.units.HeightUnit.*
25 import com.android.healthconnect.controller.dataentries.units.TemperatureUnit.CELSIUS
26 import com.android.healthconnect.controller.dataentries.units.TemperatureUnit.FAHRENHEIT
27 import com.android.healthconnect.controller.dataentries.units.TemperatureUnit.KELVIN
28 import com.android.healthconnect.controller.dataentries.units.UnitPreferences.Companion.DISTANCE_UNIT_PREF_KEY
29 import com.android.healthconnect.controller.dataentries.units.UnitPreferences.Companion.ENERGY_UNIT_PREF_KEY
30 import com.android.healthconnect.controller.dataentries.units.UnitPreferences.Companion.HEIGHT_UNIT_PREF_KEY
31 import com.android.healthconnect.controller.dataentries.units.UnitPreferences.Companion.TEMPERATURE_UNIT_PREF_KEY
32 import com.android.healthconnect.controller.dataentries.units.UnitPreferences.Companion.WEIGHT_UNIT_PREF_KEY
33 import com.android.healthconnect.controller.dataentries.units.UnitPreferencesStrings.getUnitLabel
34 import com.android.healthconnect.controller.dataentries.units.WeightUnit.KILOGRAM
35 import com.android.healthconnect.controller.dataentries.units.WeightUnit.POUND
36 import com.android.healthconnect.controller.dataentries.units.WeightUnit.STONE
37 import com.android.healthconnect.controller.shared.preference.HealthPreferenceFragment
38 import com.android.healthconnect.controller.utils.logging.ElementName
39 import com.android.healthconnect.controller.utils.logging.HealthConnectLogger
40 import com.android.healthconnect.controller.utils.logging.PageName
41 import com.android.healthconnect.controller.utils.logging.UnitsElement
42 import dagger.hilt.android.AndroidEntryPoint
43 import javax.inject.Inject
44 
45 @AndroidEntryPoint(HealthPreferenceFragment::class)
46 class UnitsFragment : Hilt_UnitsFragment() {
47 
48     @Inject lateinit var logger: HealthConnectLogger
49     @Inject lateinit var unitsPreferences: UnitPreferences
50     init {
51         this.setPageName(PageName.UNITS_PAGE)
52     }
53 
54     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
55         setPreferencesFromResource(R.xml.units_screen, rootKey)
56 
57         val height =
58             createUnitPreference(
59                 HEIGHT_UNIT_PREF_KEY,
60                 UnitsElement.CHANGE_UNITS_HEIGHT_BUTTON,
61                 R.string.height_unit_title,
62                 unitsPreferences.getHeightUnit().toString()) { newUnit ->
63                     val newHeightUnit = HeightUnit.valueOf(newUnit)
64                     val logName =
65                         when (newHeightUnit) {
66                             CENTIMETERS -> UnitsElement.CENTIMETERS_BUTTON
67                             FEET -> UnitsElement.FEET_AND_INCHES_BUTTON
68                         }
69                     logger.logInteraction(logName)
70                     unitsPreferences.setHeightUnit(newHeightUnit)
71                 }
72         val weight =
73             createUnitPreference(
74                 WEIGHT_UNIT_PREF_KEY,
75                 UnitsElement.CHANGE_UNITS_WEIGHT_BUTTON,
76                 R.string.weight_unit_title,
77                 unitsPreferences.getWeightUnit().toString()) { newUnit ->
78                     val newWeightUnit = WeightUnit.valueOf(newUnit)
79                     val logName =
80                         when (newWeightUnit) {
81                             POUND -> UnitsElement.POUNDS_BUTTON
82                             KILOGRAM -> UnitsElement.KILOGRAMS_BUTTON
83                             STONE -> UnitsElement.STONES_BUTTON
84                         }
85                     logger.logInteraction(logName)
86                     unitsPreferences.setWeightUnit(newWeightUnit)
87                 }
88         val distance =
89             createUnitPreference(
90                 DISTANCE_UNIT_PREF_KEY,
91                 UnitsElement.CHANGE_UNITS_DISTANCE_BUTTON,
92                 R.string.distance_unit_title,
93                 unitsPreferences.getDistanceUnit().toString()) { newUnit ->
94                     val newDistanceUnit = DistanceUnit.valueOf(newUnit)
95                     val logName =
96                         when (newDistanceUnit) {
97                             KILOMETERS -> UnitsElement.KILOMETERS_BUTTON
98                             MILES -> UnitsElement.MILES_BUTTON
99                         }
100                     logger.logInteraction(logName)
101                     unitsPreferences.setDistanceUnit(newDistanceUnit)
102                 }
103         val energy =
104             createUnitPreference(
105                 ENERGY_UNIT_PREF_KEY,
106                 UnitsElement.CHANGE_UNITS_ENERGY_BUTTON,
107                 R.string.energy_unit_title,
108                 unitsPreferences.getEnergyUnit().toString()) { newUnit ->
109                     val newEnergyUnit = EnergyUnit.valueOf(newUnit)
110                     val logName =
111                         when (newEnergyUnit) {
112                             CALORIE -> UnitsElement.CALORIES_BUTTON
113                             KILOJOULE -> UnitsElement.KILOJOULES_BUTTON
114                         }
115                     logger.logInteraction(logName)
116                     unitsPreferences.setEnergyUnit(newEnergyUnit)
117                 }
118         val temperature =
119             createUnitPreference(
120                 TEMPERATURE_UNIT_PREF_KEY,
121                 UnitsElement.CHANGE_UNITS_TEMPERATURE_BUTTON,
122                 R.string.temperature_unit_title,
123                 unitsPreferences.getTemperatureUnit().toString()) { newUnit ->
124                     val newTemperatureUnit = TemperatureUnit.valueOf(newUnit)
125                     val logName =
126                         when (newTemperatureUnit) {
127                             CELSIUS -> UnitsElement.CELSIUS_BUTTON
128                             FAHRENHEIT -> UnitsElement.FAHRENHEIT_BUTTON
129                             KELVIN -> UnitsElement.KELVIN_BUTTON
130                         }
131                     logger.logInteraction(logName)
132                     unitsPreferences.setTemperatureUnit(newTemperatureUnit)
133                 }
134         preferenceScreen.addPreference(height)
135         preferenceScreen.addPreference(weight)
136         preferenceScreen.addPreference(distance)
137         preferenceScreen.addPreference(energy)
138         preferenceScreen.addPreference(temperature)
139     }
140 
141     private fun createUnitPreference(
142         key: String,
143         logName: ElementName,
144         @StringRes title: Int,
145         unitValue: String,
146         onNewValue: (String) -> Unit
147     ): ListPreference {
148         val listPreference = ListPreference(requireContext())
149         logger.logImpression(logName)
150 
151         with(listPreference) {
152             isPersistent = false
153             isIconSpaceReserved = false
154             value = unitValue
155             setKey(key)
156             setTitle(title)
157             setDialogTitle(title)
158             setEntries(getEntries(key))
159             setEntryValues(getEntriesValues(key))
160             setSummary("%s")
161             setNegativeButtonText(R.string.units_cancel)
162         }
163         listPreference.setOnPreferenceChangeListener { _, newValue ->
164             onNewValue(newValue.toString())
165             true
166         }
167 
168         return listPreference
169     }
170 
171     private fun getEntries(key: String): Array<String> {
172         val entries = getUnits(key)
173         return entries.map { getString(getUnitLabel(it)) }.toTypedArray()
174     }
175 
176     private fun getEntriesValues(key: String): Array<String> {
177         val entries = getUnits(key)
178         return entries.map { it.toString() }.toTypedArray()
179     }
180 
181     private fun getUnits(key: String): Array<UnitPreference> {
182         return when (key) {
183             DISTANCE_UNIT_PREF_KEY -> arrayOf(KILOMETERS, MILES)
184             HEIGHT_UNIT_PREF_KEY -> arrayOf(CENTIMETERS, FEET)
185             WEIGHT_UNIT_PREF_KEY -> arrayOf(POUND, KILOGRAM, STONE)
186             ENERGY_UNIT_PREF_KEY -> arrayOf(CALORIE, KILOJOULE)
187             TEMPERATURE_UNIT_PREF_KEY -> arrayOf(CELSIUS, FAHRENHEIT, KELVIN)
188             else -> emptyArray()
189         }
190     }
191 }
192