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