1 /*
<lambda>null2  * Copyright (C) 2023 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 
18 package com.android.customization.picker.grid.ui.viewmodel
19 
20 import android.annotation.SuppressLint
21 import android.content.Context
22 import android.content.res.Resources
23 import androidx.lifecycle.ViewModel
24 import androidx.lifecycle.ViewModelProvider
25 import androidx.lifecycle.viewModelScope
26 import com.android.customization.model.ResourceConstants
27 import com.android.customization.picker.grid.domain.interactor.GridInteractor
28 import com.android.customization.picker.grid.shared.model.GridOptionItemsModel
29 import com.android.wallpaper.picker.common.text.ui.viewmodel.Text
30 import com.android.wallpaper.picker.option.ui.viewmodel.OptionItemViewModel
31 import kotlinx.coroutines.flow.Flow
32 import kotlinx.coroutines.flow.MutableStateFlow
33 import kotlinx.coroutines.flow.StateFlow
34 import kotlinx.coroutines.flow.map
35 import kotlinx.coroutines.launch
36 
37 class GridScreenViewModel(
38     context: Context,
39     private val interactor: GridInteractor,
40 ) : ViewModel() {
41 
42     @SuppressLint("StaticFieldLeak") // We're not leaking this context as it is the app context.
43     private val applicationContext = context.applicationContext
44 
45     val optionItems: Flow<List<OptionItemViewModel<GridIconViewModel>>> =
46         interactor.options.map { model -> toViewModel(model) }
47 
48     private fun toViewModel(
49         model: GridOptionItemsModel,
50     ): List<OptionItemViewModel<GridIconViewModel>> {
51         val iconShapePath =
52             applicationContext.resources.getString(
53                 Resources.getSystem()
54                     .getIdentifier(
55                         ResourceConstants.CONFIG_ICON_MASK,
56                         "string",
57                         ResourceConstants.ANDROID_PACKAGE,
58                     )
59             )
60 
61         return when (model) {
62             is GridOptionItemsModel.Loaded ->
63                 model.options.map { option ->
64                     val text = Text.Loaded(option.name)
65                     OptionItemViewModel<GridIconViewModel>(
66                         key =
67                             MutableStateFlow("${option.cols}x${option.rows}") as StateFlow<String>,
68                         payload =
69                             GridIconViewModel(
70                                 columns = option.cols,
71                                 rows = option.rows,
72                                 path = iconShapePath,
73                             ),
74                         text = text,
75                         isSelected = option.isSelected,
76                         onClicked =
77                             option.isSelected.map { isSelected ->
78                                 if (!isSelected) {
79                                     { viewModelScope.launch { option.onSelected() } }
80                                 } else {
81                                     null
82                                 }
83                             },
84                     )
85                 }
86             is GridOptionItemsModel.Error -> emptyList()
87         }
88     }
89 
90     class Factory(
91         context: Context,
92         private val interactor: GridInteractor,
93     ) : ViewModelProvider.Factory {
94 
95         private val applicationContext = context.applicationContext
96 
97         @Suppress("UNCHECKED_CAST")
98         override fun <T : ViewModel> create(modelClass: Class<T>): T {
99             return GridScreenViewModel(
100                 context = applicationContext,
101                 interactor = interactor,
102             )
103                 as T
104         }
105     }
106 }
107