1 /*
<lambda>null2  * Copyright (C) 2022 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.wallpaper.picker.customization.ui.viewmodel
19 
20 import android.os.Bundle
21 import androidx.annotation.VisibleForTesting
22 import androidx.lifecycle.AbstractSavedStateViewModelFactory
23 import androidx.lifecycle.SavedStateHandle
24 import androidx.lifecycle.ViewModel
25 import androidx.lifecycle.viewModelScope
26 import androidx.savedstate.SavedStateRegistryOwner
27 import com.android.wallpaper.model.Screen
28 import com.android.wallpaper.module.logging.UserEventLogger
29 import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor
30 import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination
31 import com.android.wallpaper.picker.undo.domain.interactor.UndoInteractor
32 import com.android.wallpaper.picker.undo.ui.viewmodel.UndoViewModel
33 import kotlinx.coroutines.flow.Flow
34 import kotlinx.coroutines.flow.MutableStateFlow
35 import kotlinx.coroutines.flow.asStateFlow
36 import kotlinx.coroutines.flow.map
37 
38 /** Models UI state for the customization picker. */
39 class CustomizationPickerViewModel
40 @VisibleForTesting
41 constructor(
42     undoInteractor: UndoInteractor,
43     wallpaperInteractor: WallpaperInteractor,
44     private val savedStateHandle: SavedStateHandle,
45     private val logger: UserEventLogger,
46 ) : AnimationStateViewModel() {
47 
48     val undo: UndoViewModel =
49         UndoViewModel(
50             interactor = undoInteractor,
51             logger = logger,
52         )
53 
54     private val homeWallpaperQuickSwitchViewModel: WallpaperQuickSwitchViewModel =
55         WallpaperQuickSwitchViewModel(
56             interactor = wallpaperInteractor,
57             destination = WallpaperDestination.HOME,
58             coroutineScope = viewModelScope,
59         )
60 
61     private val lockWallpaperQuickSwitchViewModel: WallpaperQuickSwitchViewModel =
62         WallpaperQuickSwitchViewModel(
63             interactor = wallpaperInteractor,
64             destination = WallpaperDestination.LOCK,
65             coroutineScope = viewModelScope,
66         )
67 
68     fun getWallpaperQuickSwitchViewModel(screen: Screen): WallpaperQuickSwitchViewModel {
69         return if (screen == Screen.LOCK_SCREEN) lockWallpaperQuickSwitchViewModel
70         else homeWallpaperQuickSwitchViewModel
71     }
72 
73     private val _isOnLockScreen = MutableStateFlow(true)
74     /** Whether we are on the lock screen. If `false`, we are on the home screen. */
75     val isOnLockScreen: Flow<Boolean> = _isOnLockScreen.asStateFlow()
76 
77     /** A view-model for the "lock screen" tab. */
78     val lockScreenTab: Flow<CustomizationPickerTabViewModel> =
79         isOnLockScreen.map { onLockScreen ->
80             CustomizationPickerTabViewModel(
81                 isSelected = onLockScreen,
82                 onClicked =
83                     if (!onLockScreen) {
84                         {
85                             _isOnLockScreen.value = true
86                             savedStateHandle[KEY_SAVED_STATE_IS_ON_LOCK_SCREEN] = true
87                         }
88                     } else {
89                         null
90                     }
91             )
92         }
93     /** A view-model for the "home screen" tab. */
94     val homeScreenTab: Flow<CustomizationPickerTabViewModel> =
95         isOnLockScreen.map { onLockScreen ->
96             CustomizationPickerTabViewModel(
97                 isSelected = !onLockScreen,
98                 onClicked =
99                     if (onLockScreen) {
100                         {
101                             _isOnLockScreen.value = false
102                             savedStateHandle[KEY_SAVED_STATE_IS_ON_LOCK_SCREEN] = false
103                         }
104                     } else {
105                         null
106                     }
107             )
108         }
109 
110     init {
111         savedStateHandle.get<Boolean>(KEY_SAVED_STATE_IS_ON_LOCK_SCREEN)?.let {
112             _isOnLockScreen.value = it
113         }
114     }
115 
116     /**
117      * Sets the initial screen we should be on, unless there's already a selected screen from a
118      * previous saved state, in which case we ignore the passed-in one.
119      */
120     fun setInitialScreen(onLockScreen: Boolean) {
121         _isOnLockScreen.value =
122             savedStateHandle[KEY_SAVED_STATE_IS_ON_LOCK_SCREEN]
123                 ?: run {
124                     savedStateHandle[KEY_SAVED_STATE_IS_ON_LOCK_SCREEN] = onLockScreen
125                     onLockScreen
126                 }
127     }
128 
129     companion object {
130         @JvmStatic
131         fun newFactory(
132             owner: SavedStateRegistryOwner,
133             defaultArgs: Bundle? = null,
134             undoInteractor: UndoInteractor,
135             wallpaperInteractor: WallpaperInteractor,
136             logger: UserEventLogger,
137         ): AbstractSavedStateViewModelFactory =
138             object : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
139                 @Suppress("UNCHECKED_CAST")
140                 override fun <T : ViewModel> create(
141                     key: String,
142                     modelClass: Class<T>,
143                     handle: SavedStateHandle,
144                 ): T {
145                     return CustomizationPickerViewModel(
146                         undoInteractor = undoInteractor,
147                         wallpaperInteractor = wallpaperInteractor,
148                         savedStateHandle = handle,
149                         logger = logger,
150                     )
151                         as T
152                 }
153             }
154 
155         private const val KEY_SAVED_STATE_IS_ON_LOCK_SCREEN = "is_on_lock_screen"
156     }
157 }
158