• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.healthconnect.controller.selectabledeletion
17 
18 import android.app.Dialog
19 import android.os.Bundle
20 import android.view.View
21 import android.widget.CheckBox
22 import android.widget.ImageView
23 import android.widget.TextView
24 import androidx.fragment.app.DialogFragment
25 import androidx.fragment.app.activityViewModels
26 import androidx.fragment.app.setFragmentResult
27 import com.android.healthconnect.controller.R
28 import com.android.healthconnect.controller.data.entries.datenavigation.DateNavigationPeriod
29 import com.android.healthconnect.controller.selectabledeletion.DeletionConstants.CONFIRMATION_KEY
30 import com.android.healthconnect.controller.shared.dialog.AlertDialogBuilder
31 import com.android.healthconnect.controller.utils.AttributeResolver
32 import com.android.healthconnect.controller.utils.LocalDateTimeFormatter
33 import com.android.healthconnect.controller.utils.TimeSource
34 import com.android.healthconnect.controller.utils.formatDateTimeForTimePeriod
35 import com.android.healthconnect.controller.utils.logging.DeletionDialogConfirmationElement
36 import com.android.settingslib.widget.SettingsThemeHelper
37 import dagger.hilt.android.AndroidEntryPoint
38 import javax.inject.Inject
39 
40 @AndroidEntryPoint(DialogFragment::class)
41 class DeletionConfirmationDialogFragment : Hilt_DeletionConfirmationDialogFragment() {
42     @Inject lateinit var timeSource: TimeSource
43     private val viewModel: DeletionViewModel by activityViewModels()
44     // TODO (b/384028690) replace after pagination implementation
45     private val PAGE_SIZE = 1000
46 
47     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
48         val view: View =
49             layoutInflater.inflate(
50                 if (SettingsThemeHelper.isExpressiveTheme(requireContext()))
51                     R.layout.dialog_layout_expressive
52                 else R.layout.dialog_layout_legacy,
53                 null,
54             )
55         val title: TextView = view.findViewById(R.id.dialog_title)
56         val message: TextView = view.findViewById(R.id.dialog_custom_message)
57         val icon: ImageView = view.findViewById(R.id.dialog_icon)
58         val checkbox: CheckBox = view.findViewById(R.id.dialog_checkbox)
59         val iconDrawable = AttributeResolver.getNullableDrawable(view.context, R.attr.deleteIcon)
60 
61         title.text = buildTitle()
62         message.setText(R.string.deletion_confirmation_dialog_body)
63         iconDrawable?.let {
64             icon.setImageDrawable(it)
65             icon.visibility = View.VISIBLE
66         }
67 
68         setupCheckbox(checkbox)
69 
70         val alertDialogBuilder =
71             AlertDialogBuilder(
72                     this,
73                     DeletionDialogConfirmationElement.DELETION_DIALOG_CONFIRMATION_CONTAINER,
74                 )
75                 .setView(view)
76                 .setPositiveButton(
77                     R.string.confirming_question_delete_button,
78                     DeletionDialogConfirmationElement.DELETION_DIALOG_CONFIRMATION_DELETE_BUTTON,
79                 ) { _, _ ->
80                     viewModel.removePermissions = checkbox.isChecked
81                     setFragmentResult(CONFIRMATION_KEY, Bundle())
82                 }
83                 .setNeutralButton(
84                     android.R.string.cancel,
85                     DeletionDialogConfirmationElement.DELETION_DIALOG_CONFIRMATION_CANCEL_BUTTON,
86                 )
87 
88         return alertDialogBuilder.create()
89     }
90 
91     private fun setupCheckbox(checkBox: CheckBox) {
92         val deletionType = viewModel.getDeletionType()
93         if (deletionType is DeletionType.DeleteHealthPermissionTypesFromApp) {
94             if (deletionType.healthPermissionTypes.size == deletionType.totalPermissionTypes) {
95                 checkBox.visibility = View.VISIBLE
96             } else {
97                 checkBox.visibility = View.GONE
98             }
99             val appName = deletionType.appName
100             checkBox.text =
101                 getString(R.string.confirming_question_app_remove_all_permissions, appName)
102         } else {
103             checkBox.visibility = View.GONE
104         }
105     }
106 
107     private fun buildTitle(): String {
108         return when (val deletionType = viewModel.getDeletionType()) {
109             is DeletionType.DeleteHealthPermissionTypes ->
110                 if (deletionType.healthPermissionTypes.size < deletionType.totalPermissionTypes) {
111                     getString(R.string.some_data_selected_deletion_confirmation_dialog)
112                 } else {
113                     getString(R.string.all_data_selected_deletion_confirmation_dialog)
114                 }
115             is DeletionType.DeleteHealthPermissionTypesFromApp -> {
116                 val appName = deletionType.appName
117                 if (deletionType.healthPermissionTypes.size < deletionType.totalPermissionTypes) {
118                     getString(R.string.some_app_data_selected_deletion_confirmation_dialog, appName)
119                 } else {
120                     getString(R.string.all_app_data_selected_deletion_confirmation_dialog, appName)
121                 }
122             }
123             is DeletionType.DeleteEntries -> {
124                 val deletionMapSize = deletionType.idsToDataTypes.size
125                 if (deletionMapSize == 1) {
126                     return getString(R.string.one_entry_selected_deletion_confirmation_dialog)
127                 }
128                 val selectedPeriod = deletionType.period
129                 val startTime = deletionType.startTime
130                 val displayString =
131                     formatDateTimeForTimePeriod(
132                         startTime,
133                         selectedPeriod,
134                         LocalDateTimeFormatter(requireContext()),
135                         timeSource,
136                         false,
137                     )
138                 if (selectedPeriod == DateNavigationPeriod.PERIOD_DAY) {
139                     if (
140                         deletionMapSize < deletionType.totalEntries || deletionMapSize == PAGE_SIZE
141                     ) {
142                         getString(
143                             R.string.some_entries_selected_day_deletion_confirmation_dialog,
144                             displayString,
145                         )
146                     } else {
147                         getString(
148                             R.string.all_entries_selected_day_deletion_confirmation_dialog,
149                             displayString,
150                         )
151                     }
152                 } else if (selectedPeriod == DateNavigationPeriod.PERIOD_WEEK) {
153                     if (
154                         deletionMapSize < deletionType.totalEntries || deletionMapSize == PAGE_SIZE
155                     ) {
156                         getString(
157                             R.string.some_entries_selected_week_deletion_confirmation_dialog,
158                             displayString,
159                         )
160                     } else {
161                         getString(
162                             R.string.all_entries_selected_week_deletion_confirmation_dialog,
163                             displayString,
164                         )
165                     }
166                 } else {
167                     if (
168                         deletionMapSize < deletionType.totalEntries || deletionMapSize == PAGE_SIZE
169                     ) {
170                         getString(
171                             R.string.some_entries_selected_month_deletion_confirmation_dialog,
172                             displayString,
173                         )
174                     } else {
175                         getString(
176                             R.string.all_entries_selected_month_deletion_confirmation_dialog,
177                             displayString,
178                         )
179                     }
180                 }
181             }
182             is DeletionType.DeleteEntriesFromApp -> {
183                 val deletionMapSize = deletionType.idsToDataTypes.size
184                 val appName = deletionType.appName
185                 if (deletionMapSize == 1) {
186                     return getString(
187                         R.string.one_app_entry_selected_deletion_confirmation_dialog,
188                         appName,
189                     )
190                 }
191                 val selectedPeriod = deletionType.period
192                 val startTime = deletionType.startTime
193                 val displayString =
194                     formatDateTimeForTimePeriod(
195                         startTime,
196                         selectedPeriod,
197                         LocalDateTimeFormatter(requireContext()),
198                         timeSource,
199                         false,
200                     )
201 
202                 if (selectedPeriod == DateNavigationPeriod.PERIOD_DAY) {
203                     if (
204                         deletionMapSize < deletionType.totalEntries || deletionMapSize == PAGE_SIZE
205                     ) {
206                         getString(
207                             R.string.some_app_entries_selected_day_deletion_confirmation_dialog,
208                             appName,
209                             displayString,
210                         )
211                     } else {
212                         getString(
213                             R.string.all_app_entries_selected_day_deletion_confirmation_dialog,
214                             appName,
215                             displayString,
216                         )
217                     }
218                 } else if (selectedPeriod == DateNavigationPeriod.PERIOD_WEEK) {
219                     if (
220                         deletionMapSize < deletionType.totalEntries || deletionMapSize == PAGE_SIZE
221                     ) {
222                         getString(
223                             R.string.some_app_entries_selected_week_deletion_confirmation_dialog,
224                             appName,
225                             displayString,
226                         )
227                     } else {
228                         getString(
229                             R.string.all_app_entries_selected_week_deletion_confirmation_dialog,
230                             appName,
231                             displayString,
232                         )
233                     }
234                 } else {
235                     if (
236                         deletionMapSize < deletionType.totalEntries || deletionMapSize == PAGE_SIZE
237                     ) {
238                         getString(
239                             R.string.some_app_entries_selected_month_deletion_confirmation_dialog,
240                             appName,
241                             displayString,
242                         )
243                     } else {
244                         getString(
245                             R.string.all_app_entries_selected_month_deletion_confirmation_dialog,
246                             appName,
247                             displayString,
248                         )
249                     }
250                 }
251             }
252             is DeletionType.DeleteAppData -> {
253                 val appName = deletionType.appName
254                 getString(R.string.all_app_data_selected_deletion_confirmation_dialog, appName)
255             }
256             is DeletionType.DeleteInactiveAppData -> {
257                 val appName = deletionType.appName
258                 val healthPermissionType =
259                     getString(deletionType.healthPermissionType.lowerCaseLabel())
260                 getString(
261                     R.string.inactive_app_data_selected_deletion_confirmation_dialog,
262                     healthPermissionType,
263                     appName,
264                 )
265             }
266         }
267     }
268 
269     companion object {
270         const val TAG = "NewDeletionConfirmationDialog"
271     }
272 }
273