1 /*
<lambda>null2  * Copyright (C) 2024 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.exportimport
18 
19 import android.os.Bundle
20 import android.view.View
21 import android.widget.Toast
22 import androidx.fragment.app.viewModels
23 import androidx.preference.Preference
24 import androidx.preference.PreferenceGroup
25 import com.android.healthconnect.controller.R
26 import com.android.healthconnect.controller.exportimport.ExportFrequencyRadioGroupPreference.Companion.EXPORT_FREQUENCY_RADIO_GROUP_PREFERENCE
27 import com.android.healthconnect.controller.exportimport.api.ExportFrequency
28 import com.android.healthconnect.controller.exportimport.api.ExportSettings
29 import com.android.healthconnect.controller.exportimport.api.ExportSettingsViewModel
30 import com.android.healthconnect.controller.exportimport.api.ExportStatusViewModel
31 import com.android.healthconnect.controller.exportimport.api.ScheduledExportUiState
32 import com.android.healthconnect.controller.exportimport.api.ScheduledExportUiStatus
33 import com.android.healthconnect.controller.shared.preference.HealthMainSwitchPreference
34 import com.android.healthconnect.controller.shared.preference.HealthPreferenceFragment
35 import com.android.healthconnect.controller.utils.LocalDateTimeFormatter
36 import dagger.hilt.android.AndroidEntryPoint
37 import java.time.temporal.ChronoUnit
38 
39 /** Fragment showing the status of configured automatic fragment. */
40 @AndroidEntryPoint(HealthPreferenceFragment::class)
41 @kotlinx.coroutines.ExperimentalCoroutinesApi
42 class ScheduledExportFragment : Hilt_ScheduledExportFragment() {
43 
44     // TODO: b/325917283 - Add proper logging for the automatic export fragment.
45     companion object {
46         const val SCHEDULED_EXPORT_CONTROL_PREFERENCE_KEY = "scheduled_export_control_preference"
47         const val CHOOSE_FREQUENCY_PREFERENCE_KEY = "choose_frequency"
48         const val EXPORT_STATUS_PREFERENCE_ORDER = 1
49     }
50 
51     private val exportSettingsViewModel: ExportSettingsViewModel by viewModels()
52     private val exportStatusViewModel: ExportStatusViewModel by viewModels()
53 
54     private val scheduledExportControlPreference: HealthMainSwitchPreference? by lazy {
55         preferenceScreen.findPreference(SCHEDULED_EXPORT_CONTROL_PREFERENCE_KEY)
56     }
57 
58     private val chooseFrequencyPreferenceGroup: PreferenceGroup? by lazy {
59         preferenceScreen.findPreference(CHOOSE_FREQUENCY_PREFERENCE_KEY)
60     }
61 
62     private val dateFormatter: LocalDateTimeFormatter by lazy {
63         LocalDateTimeFormatter(requireContext())
64     }
65 
66     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
67         super.onCreatePreferences(savedInstanceState, rootKey)
68         setPreferencesFromResource(R.xml.scheduled_export_screen, rootKey)
69     }
70 
71     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
72         super.onViewCreated(view, savedInstanceState)
73 
74         exportStatusViewModel.storedScheduledExportStatus.observe(viewLifecycleOwner) {
75             scheduledExportUiStatus ->
76             when (scheduledExportUiStatus) {
77                 is ScheduledExportUiStatus.WithData -> {
78                     maybeShowNextExportStatus(scheduledExportUiStatus.scheduledExportUiState)
79                 }
80                 else -> {
81                     // do nothing
82                 }
83             }
84         }
85 
86         exportSettingsViewModel.storedExportSettings.observe(viewLifecycleOwner) { exportSettings ->
87             when (exportSettings) {
88                 is ExportSettings.WithData -> {
89                     if (exportSettings.frequency != ExportFrequency.EXPORT_FREQUENCY_NEVER) {
90                         scheduledExportControlPreference?.isChecked = true
91                         scheduledExportControlPreference?.title =
92                             getString(R.string.automatic_export_on)
93                         chooseFrequencyPreferenceGroup?.setVisible(true)
94                     } else {
95                         scheduledExportControlPreference?.isChecked = false
96                         scheduledExportControlPreference?.title =
97                             getString(R.string.automatic_export_off)
98                         chooseFrequencyPreferenceGroup?.setVisible(false)
99                     }
100                     exportSettingsViewModel.updatePreviousExportFrequency(exportSettings.frequency)
101                     if (chooseFrequencyPreferenceGroup?.findPreference<Preference>(
102                         EXPORT_FREQUENCY_RADIO_GROUP_PREFERENCE) == null) {
103                         val exportFrequencyPreference =
104                             ExportFrequencyRadioGroupPreference(
105                                 requireContext(),
106                                 exportSettings.frequency,
107                                 exportSettingsViewModel::updateExportFrequency)
108                         chooseFrequencyPreferenceGroup?.addPreference(exportFrequencyPreference)
109                     }
110                 }
111                 is ExportSettings.LoadingFailed ->
112                     Toast.makeText(requireActivity(), R.string.default_error, Toast.LENGTH_LONG)
113                         .show()
114                 is ExportSettings.Loading -> {
115                     // Do nothing.
116                 }
117             }
118         }
119 
120         scheduledExportControlPreference?.addOnSwitchChangeListener { _, isChecked ->
121             if (isChecked) {
122                 exportSettingsViewModel.previousExportFrequency.value?.let { previousExportFrequency
123                     ->
124                     exportSettingsViewModel.updateExportFrequency(previousExportFrequency)
125                 }
126             } else {
127                 exportSettingsViewModel.updateExportFrequency(
128                     ExportFrequency.EXPORT_FREQUENCY_NEVER)
129             }
130         }
131     }
132 
133     private fun maybeShowNextExportStatus(scheduledExportUiState: ScheduledExportUiState) {
134         val lastSuccessfulExportTime = scheduledExportUiState.lastSuccessfulExportTime
135         val periodInDays = scheduledExportUiState.periodInDays
136         if (lastSuccessfulExportTime != null) {
137             val nextExportTime =
138                 getString(
139                     R.string.next_export_time,
140                     dateFormatter.formatLongDate(
141                         lastSuccessfulExportTime.plus(periodInDays.toLong(), ChronoUnit.DAYS)))
142             preferenceScreen.addPreference(
143                 ExportStatusPreference(requireContext(), nextExportTime).also {
144                     it.order = EXPORT_STATUS_PREFERENCE_ORDER
145                 })
146         }
147     }
148 }
149