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.content.Context
20 import android.graphics.drawable.Drawable
21 import android.view.LayoutInflater
22 import android.view.View.GONE
23 import android.view.View.VISIBLE
24 import android.view.ViewGroup
25 import android.widget.ImageView
26 import android.widget.RadioButton
27 import android.widget.RadioGroup
28 import android.widget.TextView
29 import com.android.healthconnect.controller.R
30 import com.android.healthconnect.controller.exportimport.api.DocumentProvider
31 import com.android.healthconnect.controller.exportimport.api.DocumentProviderRoot
32 import com.android.healthconnect.controller.shared.dialog.AlertDialogBuilder
33 import com.android.healthconnect.controller.utils.logging.ErrorPageElement
34 
35 /** Adds the views for the documents provider list when setting up export and import. */
36 class DocumentProvidersViewBinder {
37     fun bindDocumentProvidersView(
38         documentProviders: List<DocumentProvider>,
39         documentProvidersView: ViewGroup,
40         inflater: LayoutInflater,
41         onSelectionChanged: (root: DocumentProviderRoot) -> Unit
42     ) {
43         for (documentProvider in documentProviders) {
44             val documentProviderView =
45                 inflater.inflate(R.layout.item_document_provider, documentProvidersView, false)
46 
47             val radioButtonView =
48                 documentProviderView.findViewById<RadioButton>(
49                     R.id.item_document_provider_radio_button)
50             val iconView =
51                 documentProviderView.findViewById<ImageView>(R.id.item_document_provider_icon)
52             val titleView =
53                 documentProviderView.findViewById<TextView>(R.id.item_document_provider_title)
54             val summaryView =
55                 documentProviderView.findViewById<TextView>(R.id.item_document_provider_summary)
56 
57             iconView.setImageDrawable(
58                 loadPackageIcon(
59                     documentProvidersView.context,
60                     documentProvider.info.authority,
61                     documentProvider.info.iconResource))
62             titleView.setText(documentProvider.info.title)
63 
64             if (documentProvider.roots.size == 1) {
65                 val root = documentProvider.roots[0]
66 
67                 summaryView.setText(root.summary)
68                 summaryView.setVisibility(VISIBLE)
69 
70                 if (documentProviders.size == 1) {
71                     radioButtonView.setVisibility(GONE)
72 
73                     onSelectionChanged(root)
74                 } else {
75                     documentProviderView.setOnClickListener {
76                         uncheckRadioButtons(documentProvidersView)
77                         radioButtonView.setChecked(true)
78 
79                         onSelectionChanged(root)
80                     }
81                 }
82             } else {
83                 if (documentProviders.size == 1) {
84                     radioButtonView.setVisibility(GONE)
85 
86                     summaryView.setText(R.string.export_import_tap_to_choose_account)
87                 } else {
88                     summaryView.setText("")
89                     summaryView.setVisibility(GONE)
90                 }
91 
92                 documentProviderView.setOnClickListener {
93                     showChooseAccountDialog(inflater, documentProvider.roots) { root ->
94                         uncheckRadioButtons(documentProvidersView)
95                         radioButtonView.setChecked(true)
96 
97                         summaryView.setText(root.summary)
98                         summaryView.setVisibility(VISIBLE)
99 
100                         onSelectionChanged(root)
101                     }
102                 }
103             }
104 
105             documentProvidersView.addView(documentProviderView)
106         }
107     }
108 
109     private fun showChooseAccountDialog(
110         inflater: LayoutInflater,
111         roots: List<DocumentProviderRoot>,
112         onSelectionChanged: (root: DocumentProviderRoot) -> Unit
113     ) {
114         val view = inflater.inflate(R.layout.dialog_export_import_account, null)
115 
116         val radioGroup = view.findViewById<RadioGroup>(R.id.radio_group_account)
117 
118         for (i in roots.indices) {
119             val radioButton =
120                 inflater.inflate(R.layout.item_document_provider_account, radioGroup, false)
121                     as RadioButton
122             radioButton.text = roots[i].summary
123             radioButton.id = i
124             if (i == 0) {
125                 radioButton.isChecked = true
126             }
127             radioGroup.addView(radioButton)
128         }
129 
130         // TODO: b/339189778 - Add proper logging for the account picker dialog.
131         AlertDialogBuilder(inflater.context, ErrorPageElement.UNKNOWN_ELEMENT)
132             .setView(view)
133             .setNegativeButton(
134                 R.string.export_import_choose_account_cancel_button,
135                 ErrorPageElement.UNKNOWN_ELEMENT)
136             .setPositiveButton(
137                 R.string.export_import_choose_account_done_button,
138                 ErrorPageElement.UNKNOWN_ELEMENT) { _, _ ->
139                     onSelectionChanged(roots[radioGroup.checkedRadioButtonId])
140                 }
141             .create()
142             .show()
143     }
144 
145     private fun loadPackageIcon(context: Context, authority: String, icon: Int): Drawable? {
146         val info = context.packageManager.resolveContentProvider(authority, 0)
147         if (info != null) {
148             return context.packageManager.getDrawable(info.packageName, icon, info.applicationInfo)
149         }
150 
151         return null
152     }
153 
154     private fun uncheckRadioButtons(view: ViewGroup) {
155         for (i in 0 until view.childCount) {
156             val child = view.getChildAt(i)
157             val childRadioButton =
158                 child.findViewById<RadioButton>(R.id.item_document_provider_radio_button)
159             childRadioButton?.setChecked(false)
160         }
161     }
162 }
163