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.wallpaper.picker.customization.domain.interactor
19 
20 import android.stats.style.StyleEnums.SET_WALLPAPER_ENTRY_POINT_RESET
21 import com.android.wallpaper.picker.customization.data.repository.WallpaperRepository.Companion.DEFAULT_KEY
22 import com.android.wallpaper.picker.customization.shared.model.WallpaperDestination
23 import com.android.wallpaper.picker.undo.domain.interactor.SnapshotRestorer
24 import com.android.wallpaper.picker.undo.domain.interactor.SnapshotStore
25 import com.android.wallpaper.picker.undo.shared.model.RestorableSnapshot
26 import kotlinx.coroutines.CoroutineScope
27 import kotlinx.coroutines.flow.combine
28 import kotlinx.coroutines.flow.drop
29 import kotlinx.coroutines.flow.filter
30 import kotlinx.coroutines.flow.first
31 import kotlinx.coroutines.launch
32 
33 /** Stores and restores undo snapshots for wallpaper state. */
34 class WallpaperSnapshotRestorer(
35     private val scope: CoroutineScope,
36     private val interactor: WallpaperInteractor,
37 ) : SnapshotRestorer {
38 
39     private var store: SnapshotStore = SnapshotStore.NOOP
40 
41     override suspend fun setUpSnapshotRestorer(
42         store: SnapshotStore,
43     ): RestorableSnapshot {
44         this.store = store
45         startObserving()
46         return snapshot()
47     }
48 
49     override suspend fun restoreToSnapshot(
50         snapshot: RestorableSnapshot,
51     ) {
52         val homeWallpaperId = snapshot.args[SELECTED_HOME_SCREEN_WALLPAPER_ID]
53         if (!homeWallpaperId.isNullOrEmpty()) {
54             interactor.setRecentWallpaper(
55                 setWallpaperEntryPoint = SET_WALLPAPER_ENTRY_POINT_RESET,
56                 destination = WallpaperDestination.HOME,
57                 wallpaperId = homeWallpaperId
58             )
59         }
60 
61         val lockWallpaperId = snapshot.args[SELECTED_LOCK_SCREEN_WALLPAPER_ID]
62         if (!lockWallpaperId.isNullOrEmpty()) {
63             interactor.setRecentWallpaper(
64                 setWallpaperEntryPoint = SET_WALLPAPER_ENTRY_POINT_RESET,
65                 destination = WallpaperDestination.LOCK,
66                 wallpaperId = lockWallpaperId
67             )
68         }
69     }
70 
71     private fun startObserving() {
72         scope.launch {
73             combine(
74                     interactor.selectedWallpaperId(destination = WallpaperDestination.HOME),
75                     interactor.selectedWallpaperId(destination = WallpaperDestination.LOCK),
76                     ::Pair,
77                 )
78                 .drop(1) // We skip the first value because it's the same as the initial.
79                 .collect { (homeWallpaperId, lockWallpaperId) ->
80                     store.store(
81                         snapshot(
82                             homeWallpaperId,
83                             lockWallpaperId,
84                         )
85                     )
86                 }
87         }
88     }
89 
90     private suspend fun snapshot(
91         homeWallpaperId: String? = null,
92         lockWallpaperId: String? = null,
93     ): RestorableSnapshot {
94         return RestorableSnapshot(
95             args =
96                 buildMap {
97                     put(
98                         SELECTED_HOME_SCREEN_WALLPAPER_ID,
99                         homeWallpaperId
100                             ?: querySelectedWallpaperId(destination = WallpaperDestination.HOME),
101                     )
102                     put(
103                         SELECTED_LOCK_SCREEN_WALLPAPER_ID,
104                         lockWallpaperId
105                             ?: querySelectedWallpaperId(destination = WallpaperDestination.LOCK),
106                     )
107                 }
108         )
109     }
110 
111     private suspend fun querySelectedWallpaperId(destination: WallpaperDestination): String {
112         return interactor
113             .selectedWallpaperId(destination = destination)
114             .filter { it != DEFAULT_KEY }
115             .first()
116     }
117 
118     companion object {
119         private const val SELECTED_HOME_SCREEN_WALLPAPER_ID = "selected_home_screen_wallpaper_id"
120         private const val SELECTED_LOCK_SCREEN_WALLPAPER_ID = "selected_lock_screen_wallpaper_id"
121     }
122 }
123