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