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.wallpaper.picker.category.data.repository
18 
19 import android.content.Context
20 import android.util.Log
21 import com.android.wallpaper.config.BaseFlags
22 import com.android.wallpaper.model.Category
23 import com.android.wallpaper.picker.category.client.DefaultWallpaperCategoryClient
24 import com.android.wallpaper.picker.data.category.CategoryModel
25 import com.android.wallpaper.picker.di.modules.BackgroundDispatcher
26 import com.android.wallpaper.util.converter.category.CategoryFactory
27 import dagger.hilt.android.qualifiers.ApplicationContext
28 import javax.inject.Inject
29 import javax.inject.Singleton
30 import kotlinx.coroutines.CoroutineScope
31 import kotlinx.coroutines.flow.MutableStateFlow
32 import kotlinx.coroutines.flow.StateFlow
33 import kotlinx.coroutines.flow.asStateFlow
34 import kotlinx.coroutines.launch
35 
36 @Singleton
37 open class DefaultWallpaperCategoryRepository
38 @Inject
39 constructor(
40     @ApplicationContext val context: Context,
41     private val defaultWallpaperClient: DefaultWallpaperCategoryClient,
42     private val categoryFactory: CategoryFactory,
43     @BackgroundDispatcher private val backgroundScope: CoroutineScope,
44 ) : WallpaperCategoryRepository {
45 
46     private var myPhotosFetchedCategory: Category? = null
47     private var onDeviceFetchedCategory: Category? = null
48     private var thirdPartyFetchedCategory: List<Category> = emptyList()
49     private var systemFetchedCategories: List<Category> = emptyList()
50     private var thirdPartyLiveWallpaperFetchedCategories: List<Category> = emptyList()
51 
52     override fun getMyPhotosFetchedCategory(): Category? {
53         return myPhotosFetchedCategory
54     }
55 
56     override fun getOnDeviceFetchedCategories(): Category? {
57         return onDeviceFetchedCategory
58     }
59 
60     override fun getThirdPartyFetchedCategories(): List<Category> {
61         return thirdPartyFetchedCategory
62     }
63 
64     override fun getSystemFetchedCategories(): List<Category> {
65         return systemFetchedCategories
66     }
67 
68     override fun getThirdPartyLiveWallpaperFetchedCategories(): List<Category> {
69         return thirdPartyLiveWallpaperFetchedCategories
70     }
71 
72     private val _systemCategories = MutableStateFlow<List<CategoryModel>>(emptyList())
73     override val systemCategories: StateFlow<List<CategoryModel>> = _systemCategories.asStateFlow()
74 
75     private val _myPhotosCategory = MutableStateFlow<CategoryModel?>(null)
76     override val myPhotosCategory: StateFlow<CategoryModel?> = _myPhotosCategory.asStateFlow()
77 
78     private val _onDeviceCategory = MutableStateFlow<CategoryModel?>(null)
79     override val onDeviceCategory: StateFlow<CategoryModel?> = _onDeviceCategory.asStateFlow()
80 
81     private val _thirdPartyAppCategory = MutableStateFlow<List<CategoryModel>>(emptyList())
82     override val thirdPartyAppCategory: StateFlow<List<CategoryModel>> =
83         _thirdPartyAppCategory.asStateFlow()
84 
85     private val _thirdPartyLiveWallpaperCategory =
86         MutableStateFlow<List<CategoryModel>>(emptyList())
87     override val thirdPartyLiveWallpaperCategory: StateFlow<List<CategoryModel>> =
88         _thirdPartyLiveWallpaperCategory.asStateFlow()
89 
90     private val _isDefaultCategoriesFetched = MutableStateFlow(false)
91     override val isDefaultCategoriesFetched: StateFlow<Boolean> =
92         _isDefaultCategoriesFetched.asStateFlow()
93 
94     init {
95         if (BaseFlags.get().isWallpaperCategoryRefactoringEnabled()) {
96             backgroundScope.launch { fetchAllCategories() }
97         }
98     }
99 
100     private suspend fun fetchAllCategories() {
101         try {
102             fetchSystemCategories()
103             fetchMyPhotosCategory()
104             fetchOnDeviceCategory()
105             fetchThirdPartyAppCategory()
106             fetchThirdPartyLiveWallpaperCategory()
107         } catch (e: Exception) {
108             Log.e(TAG, "Error fetching default categories", e)
109         } finally {
110             _isDefaultCategoriesFetched.value = true
111         }
112     }
113 
114     private suspend fun fetchThirdPartyLiveWallpaperCategory() {
115         try {
116             val excludedPackageNames = defaultWallpaperClient.getExcludedLiveWallpaperPackageNames()
117             thirdPartyLiveWallpaperFetchedCategories =
118                 defaultWallpaperClient.getThirdPartyLiveWallpaperCategory(excludedPackageNames)
119             val processedCategories =
120                 thirdPartyLiveWallpaperFetchedCategories.map {
121                     categoryFactory.getCategoryModel(it)
122                 }
123             _thirdPartyLiveWallpaperCategory.value = processedCategories
124         } catch (e: Exception) {
125             Log.e(TAG, "Error fetching third party live wallpaper categories", e)
126         }
127     }
128 
129     private suspend fun fetchSystemCategories() {
130         try {
131             systemFetchedCategories = defaultWallpaperClient.getSystemCategories()
132             val processedCategories =
133                 systemFetchedCategories.map { categoryFactory.getCategoryModel(it) }
134             _systemCategories.value = processedCategories
135         } catch (e: Exception) {
136             Log.e(TAG, "Error fetching system categories", e)
137         }
138     }
139 
140     override suspend fun fetchMyPhotosCategory() {
141         try {
142             myPhotosFetchedCategory = defaultWallpaperClient.getMyPhotosCategory()
143             myPhotosFetchedCategory.let { category ->
144                 _myPhotosCategory.value = category?.let { categoryFactory.getCategoryModel(it) }
145             }
146         } catch (e: Exception) {
147             Log.e(TAG, "Error fetching My Photos category", e)
148         }
149     }
150 
151     override suspend fun refreshNetworkCategories() {}
152 
153     override suspend fun refreshThirdPartyAppCategories() {
154         _isDefaultCategoriesFetched.value = false
155         fetchThirdPartyAppCategory()
156         _isDefaultCategoriesFetched.value = true
157     }
158 
159     override suspend fun refreshThirdPartyLiveWallpaperCategories() {
160         _isDefaultCategoriesFetched.value = false
161         fetchThirdPartyLiveWallpaperCategory()
162         _isDefaultCategoriesFetched.value = true
163     }
164 
165     private suspend fun fetchOnDeviceCategory() {
166         try {
167             onDeviceFetchedCategory =
168                 (defaultWallpaperClient as? DefaultWallpaperCategoryClient)?.getOnDeviceCategory()
169             _onDeviceCategory.value =
170                 onDeviceFetchedCategory?.let { categoryFactory.getCategoryModel(it) }
171         } catch (e: Exception) {
172             Log.e(TAG, "Error fetching On Device category", e)
173         }
174     }
175 
176     private suspend fun fetchThirdPartyAppCategory() {
177         try {
178             val excludedPackageNames = defaultWallpaperClient.getExcludedThirdPartyPackageNames()
179             thirdPartyFetchedCategory =
180                 defaultWallpaperClient.getThirdPartyCategory(excludedPackageNames)
181             val processedCategories =
182                 thirdPartyFetchedCategory.map { category ->
183                     categoryFactory.getCategoryModel(category)
184                 }
185             _thirdPartyAppCategory.value = processedCategories
186         } catch (e: Exception) {
187             Log.e(TAG, "Error fetching third party app categories", e)
188         }
189     }
190 
191     companion object {
192         private const val TAG = "DefaultWallpaperCategoryRepository"
193     }
194 }
195