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.model.mode
19 
20 import android.content.Context
21 import android.content.res.Configuration
22 import androidx.annotation.VisibleForTesting
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 com.android.wallpaper.system.UiModeManagerWrapper
27 import kotlinx.coroutines.CoroutineDispatcher
28 import kotlinx.coroutines.withContext
29 
30 class DarkModeSnapshotRestorer : SnapshotRestorer {
31 
32     private val backgroundDispatcher: CoroutineDispatcher
33     private val isActive: () -> Boolean
34     private val setActive: suspend (Boolean) -> Unit
35 
36     private var store: SnapshotStore = SnapshotStore.NOOP
37 
38     constructor(
39         context: Context,
40         manager: UiModeManagerWrapper,
41         backgroundDispatcher: CoroutineDispatcher,
42     ) : this(
43         backgroundDispatcher = backgroundDispatcher,
44         isActive = {
45             context.applicationContext.resources.configuration.uiMode and
46                 Configuration.UI_MODE_NIGHT_YES != 0
47         },
48         setActive = { isActive -> manager.setNightModeActivated(isActive) },
49     )
50 
51     @VisibleForTesting
52     constructor(
53         backgroundDispatcher: CoroutineDispatcher,
54         isActive: () -> Boolean,
55         setActive: suspend (Boolean) -> Unit,
56     ) {
57         this.backgroundDispatcher = backgroundDispatcher
58         this.isActive = isActive
59         this.setActive = setActive
60     }
61 
62     override suspend fun setUpSnapshotRestorer(store: SnapshotStore): RestorableSnapshot {
63         this.store = store
64         return snapshot(
65             isActivated = isActive(),
66         )
67     }
68 
69     override suspend fun restoreToSnapshot(snapshot: RestorableSnapshot) {
70         val isActivated = snapshot.args[KEY]?.toBoolean() == true
71         withContext(backgroundDispatcher) { setActive(isActivated) }
72     }
73 
74     fun store(
75         isActivated: Boolean,
76     ) {
77         store.store(
78             snapshot(
79                 isActivated = isActivated,
80             ),
81         )
82     }
83 
84     private fun snapshot(
85         isActivated: Boolean,
86     ): RestorableSnapshot {
87         return RestorableSnapshot(
88             args =
89                 buildMap {
90                     put(
91                         KEY,
92                         isActivated.toString(),
93                     )
94                 }
95         )
96     }
97 
98     companion object {
99         private const val KEY = "is_activated"
100     }
101 }
102