1 /**
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 package com.android.healthconnect.controller.datasources.appsources
15 
16 import android.content.Context
17 import androidx.preference.Preference
18 import androidx.preference.PreferenceViewHolder
19 import androidx.recyclerview.widget.ItemTouchHelper
20 import androidx.recyclerview.widget.RecyclerView
21 import com.android.healthconnect.controller.R
22 import com.android.healthconnect.controller.datasources.DataSourcesFragment
23 import com.android.healthconnect.controller.datasources.DataSourcesViewModel
24 import com.android.healthconnect.controller.permissions.connectedapps.ComparablePreference
25 import com.android.healthconnect.controller.shared.HealthDataCategoryInt
26 import com.android.healthconnect.controller.shared.app.AppMetadata
27 import com.android.healthconnect.controller.shared.app.AppUtils
28 
29 class AppSourcesPreference
30 constructor(
31     context: Context,
32     private val appUtils: AppUtils,
33     private val dataSourcesViewModel: DataSourcesViewModel,
34     val category: @HealthDataCategoryInt Int,
35     private val fragment: DataSourcesFragment
36 ) : Preference(context), ComparablePreference, AppSourcesAdapter.ItemMoveAttachCallbackListener {
37 
38     private var priorityList: List<AppMetadata> = listOf()
39     private var potentialAppSourcesList: List<AppMetadata> = listOf()
40     private lateinit var priorityListView: RecyclerView
41     private lateinit var adapter: AppSourcesAdapter
42     private var isEditMode = false
43 
44     init {
45         layoutResource = R.layout.widget_linear_layout_preference
46     }
47 
onBindViewHoldernull48     override fun onBindViewHolder(holder: PreferenceViewHolder) {
49         super.onBindViewHolder(holder)
50 
51         priorityList = dataSourcesViewModel.getEditedPriorityList()
52         potentialAppSourcesList = dataSourcesViewModel.getEditedPotentialAppSources()
53         priorityListView = holder.findViewById(R.id.linear_layout_recycle_view) as RecyclerView
54         priorityListView.isNestedScrollingEnabled = false
55 
56         adapter =
57             AppSourcesAdapter(
58                 context,
59                 appUtils,
60                 priorityList,
61                 potentialAppSourcesList,
62                 dataSourcesViewModel,
63                 category,
64                 fragment,
65                 this)
66         priorityListView.adapter = adapter
67         priorityListView.layoutManager = AppSourcesLinearLayoutManager(context, adapter)
68         createAndAttachItemMoveCallback()
69 
70         adapter.toggleEditMode(isEditMode)
71     }
72 
attachCallbacknull73     override fun attachCallback() {
74         createAndAttachItemMoveCallback()
75     }
76 
createAndAttachItemMoveCallbacknull77     private fun createAndAttachItemMoveCallback() {
78         val callback = AppSourcesItemMoveCallback(adapter)
79         val priorityListMover = ItemTouchHelper(callback)
80         adapter.setOnItemDragStartedListener(priorityListMover)
81         priorityListMover.attachToRecyclerView(priorityListView)
82     }
83 
84     /** Toggles the edit mode on/off after the preference has been created */
toggleEditModenull85     fun toggleEditMode(isEditMode: Boolean) {
86         setEditMode(isEditMode)
87         adapter.toggleEditMode(isEditMode)
88     }
89 
90     /**
91      * Sets the edit mode on/off before the preference is fully created and the onBindViewHolder
92      * method is called.
93      */
setEditModenull94     fun setEditMode(isEditMode: Boolean) {
95         this.isEditMode = isEditMode
96     }
97 
isSameItemnull98     override fun isSameItem(preference: Preference): Boolean {
99         return preference is AppSourcesPreference && this == preference
100     }
101 
hasSameContentsnull102     override fun hasSameContents(preference: Preference): Boolean {
103         return preference is AppSourcesPreference &&
104             preference.priorityList == this.priorityList &&
105             preference.category == this.category
106     }
107 }
108