Reset support for themed icons (2/3).
Fix: 267804366
Test: unit tests
Test: manually verified starting with themed icons on or off, reset
button shows when different from original value, button hides when the
same as the original value, resetting and confirming returns to the
original value
Change-Id: I6c6610265e2a279b6a8732d35e128482ac35396f
diff --git a/Android.bp b/Android.bp
index 6d9ff8f..f6c8558 100644
--- a/Android.bp
+++ b/Android.bp
@@ -77,6 +77,7 @@
"SettingsLibSettingsTheme",
"SystemUI-statsd",
"styleprotoslite",
+ "androidx.lifecycle_lifecycle-livedata-ktx",
"androidx.lifecycle_lifecycle-runtime-ktx",
"androidx.lifecycle_lifecycle-viewmodel-ktx",
"androidx.recyclerview_recyclerview",
diff --git a/src/com/android/customization/model/themedicon/ThemedIconSectionController.java b/src/com/android/customization/model/themedicon/ThemedIconSectionController.java
index a1623d1..5d551a6 100644
--- a/src/com/android/customization/model/themedicon/ThemedIconSectionController.java
+++ b/src/com/android/customization/model/themedicon/ThemedIconSectionController.java
@@ -20,11 +20,13 @@
import android.view.LayoutInflater;
import androidx.annotation.Nullable;
+import androidx.lifecycle.Observer;
+import com.android.customization.model.themedicon.domain.interactor.ThemedIconInteractor;
+import com.android.customization.model.themedicon.domain.interactor.ThemedIconSnapshotRestorer;
import com.android.customization.picker.themedicon.ThemedIconSectionView;
import com.android.wallpaper.R;
import com.android.wallpaper.model.CustomizationSectionController;
-import com.android.wallpaper.model.WorkspaceViewModel;
/** The {@link CustomizationSectionController} for themed icon section. */
public class ThemedIconSectionController implements
@@ -33,16 +35,26 @@
private static final String KEY_THEMED_ICON_ENABLED = "SAVED_THEMED_ICON_ENABLED";
private final ThemedIconSwitchProvider mThemedIconOptionsProvider;
- private final WorkspaceViewModel mWorkspaceViewModel;
+ private final ThemedIconInteractor mInteractor;
+ private final ThemedIconSnapshotRestorer mSnapshotRestorer;
+ private final Observer<Boolean> mIsActivatedChangeObserver;
private ThemedIconSectionView mThemedIconSectionView;
private boolean mSavedThemedIconEnabled = false;
-
- public ThemedIconSectionController(ThemedIconSwitchProvider themedIconOptionsProvider,
- WorkspaceViewModel workspaceViewModel, @Nullable Bundle savedInstanceState) {
+ public ThemedIconSectionController(
+ ThemedIconSwitchProvider themedIconOptionsProvider,
+ ThemedIconInteractor interactor,
+ @Nullable Bundle savedInstanceState,
+ ThemedIconSnapshotRestorer snapshotRestorer) {
mThemedIconOptionsProvider = themedIconOptionsProvider;
- mWorkspaceViewModel = workspaceViewModel;
+ mInteractor = interactor;
+ mSnapshotRestorer = snapshotRestorer;
+ mIsActivatedChangeObserver = isActivated -> {
+ if (mThemedIconSectionView.isAttachedToWindow()) {
+ mThemedIconSectionView.getSwitch().setChecked(isActivated);
+ }
+ };
if (savedInstanceState != null) {
mSavedThemedIconEnabled = savedInstanceState.getBoolean(
@@ -64,15 +76,22 @@
mThemedIconSectionView.getSwitch().setChecked(mSavedThemedIconEnabled);
mThemedIconOptionsProvider.fetchThemedIconEnabled(
enabled -> mThemedIconSectionView.getSwitch().setChecked(enabled));
+ mInteractor.isActivatedAsLiveData().observeForever(mIsActivatedChangeObserver);
return mThemedIconSectionView;
}
+ @Override
+ public void release() {
+ mInteractor.isActivatedAsLiveData().removeObserver(mIsActivatedChangeObserver);
+ }
+
private void onViewActivated(Context context, boolean viewActivated) {
if (context == null) {
return;
}
mThemedIconOptionsProvider.setThemedIconEnabled(viewActivated);
- mWorkspaceViewModel.getUpdateWorkspace().setValue(viewActivated);
+ mInteractor.setActivated(viewActivated);
+ mSnapshotRestorer.store(viewActivated);
}
@Override
diff --git a/src/com/android/customization/model/themedicon/ThemedIconSwitchProvider.java b/src/com/android/customization/model/themedicon/ThemedIconSwitchProvider.java
index 9acd319..5e2a60a 100644
--- a/src/com/android/customization/model/themedicon/ThemedIconSwitchProvider.java
+++ b/src/com/android/customization/model/themedicon/ThemedIconSwitchProvider.java
@@ -118,7 +118,7 @@
*
* <p>The value would also be stored in SharedPreferences.
*/
- protected void setThemedIconEnabled(boolean enabled) {
+ public void setThemedIconEnabled(boolean enabled) {
mExecutorService.submit(() -> {
ContentValues values = new ContentValues();
values.put(COL_ICON_THEMED_VALUE, enabled);
diff --git a/src/com/android/customization/model/themedicon/data/repository/ThemedIconRepository.kt b/src/com/android/customization/model/themedicon/data/repository/ThemedIconRepository.kt
new file mode 100644
index 0000000..9108811
--- /dev/null
+++ b/src/com/android/customization/model/themedicon/data/repository/ThemedIconRepository.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.customization.model.themedicon.data.repository
+
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+class ThemeIconRepository {
+ private val _isActivated = MutableStateFlow(false)
+ val isActivated = _isActivated.asStateFlow()
+
+ fun setActivated(isActivated: Boolean) {
+ _isActivated.value = isActivated
+ }
+}
diff --git a/src/com/android/customization/model/themedicon/domain/interactor/ThemedIconInteractor.kt b/src/com/android/customization/model/themedicon/domain/interactor/ThemedIconInteractor.kt
new file mode 100644
index 0000000..1cfe877
--- /dev/null
+++ b/src/com/android/customization/model/themedicon/domain/interactor/ThemedIconInteractor.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.customization.model.themedicon.domain.interactor
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.asLiveData
+import com.android.customization.model.themedicon.data.repository.ThemeIconRepository
+
+class ThemedIconInteractor(
+ private val repository: ThemeIconRepository,
+) {
+ val isActivated = repository.isActivated
+
+ private var isActivatedAsLiveData: LiveData<Boolean>? = null
+
+ fun isActivatedAsLiveData(): LiveData<Boolean> {
+ return isActivatedAsLiveData ?: isActivated.asLiveData().also { isActivatedAsLiveData = it }
+ }
+
+ fun setActivated(isActivated: Boolean) {
+ repository.setActivated(isActivated)
+ }
+}
diff --git a/src/com/android/customization/model/themedicon/domain/interactor/ThemedIconSnapshotRestorer.kt b/src/com/android/customization/model/themedicon/domain/interactor/ThemedIconSnapshotRestorer.kt
new file mode 100644
index 0000000..639a92d
--- /dev/null
+++ b/src/com/android/customization/model/themedicon/domain/interactor/ThemedIconSnapshotRestorer.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.customization.model.themedicon.domain.interactor
+
+import com.android.wallpaper.picker.undo.domain.interactor.SnapshotRestorer
+import com.android.wallpaper.picker.undo.domain.interactor.SnapshotStore
+import com.android.wallpaper.picker.undo.shared.model.RestorableSnapshot
+
+class ThemedIconSnapshotRestorer(
+ private val isActivated: () -> Boolean,
+ private val setActivated: (isActivated: Boolean) -> Unit,
+ private val interactor: ThemedIconInteractor,
+) : SnapshotRestorer {
+
+ private lateinit var store: SnapshotStore
+
+ override suspend fun setUpSnapshotRestorer(store: SnapshotStore): RestorableSnapshot {
+ this.store = store
+ return snapshot()
+ }
+
+ override suspend fun restoreToSnapshot(snapshot: RestorableSnapshot) {
+ val isActivated = snapshot.args[KEY]?.toBoolean() == true
+ setActivated(isActivated)
+ interactor.setActivated(isActivated)
+ }
+
+ fun store(
+ isActivated: Boolean,
+ ) {
+ store.store(snapshot(isActivated = isActivated))
+ }
+
+ private fun snapshot(
+ isActivated: Boolean? = null,
+ ): RestorableSnapshot {
+ return RestorableSnapshot(
+ args = buildMap { put(KEY, (isActivated ?: isActivated()).toString()) }
+ )
+ }
+
+ companion object {
+ private const val KEY = "is_activated"
+ }
+}
diff --git a/src/com/android/customization/module/DefaultCustomizationSections.java b/src/com/android/customization/module/DefaultCustomizationSections.java
index d05e459..ebe1b17 100644
--- a/src/com/android/customization/module/DefaultCustomizationSections.java
+++ b/src/com/android/customization/module/DefaultCustomizationSections.java
@@ -15,6 +15,8 @@
import com.android.customization.model.mode.DarkModeSnapshotRestorer;
import com.android.customization.model.themedicon.ThemedIconSectionController;
import com.android.customization.model.themedicon.ThemedIconSwitchProvider;
+import com.android.customization.model.themedicon.domain.interactor.ThemedIconInteractor;
+import com.android.customization.model.themedicon.domain.interactor.ThemedIconSnapshotRestorer;
import com.android.customization.picker.clock.data.repository.ClockRegistryProvider;
import com.android.customization.picker.notifications.ui.section.NotificationSectionController;
import com.android.customization.picker.notifications.ui.viewmodel.NotificationSectionViewModel;
@@ -32,7 +34,6 @@
import com.android.wallpaper.model.WallpaperColorsViewModel;
import com.android.wallpaper.model.WallpaperPreviewNavigator;
import com.android.wallpaper.model.WallpaperSectionController;
-import com.android.wallpaper.model.WorkspaceViewModel;
import com.android.wallpaper.module.CurrentWallpaperInfoFactory;
import com.android.wallpaper.module.CustomizationSections;
import com.android.wallpaper.picker.customization.ui.section.ConnectedSectionController;
@@ -58,6 +59,8 @@
private final PreviewWithClockCarouselSectionController.ClockViewFactoryProvider
mClockViewFactoryProvider;
private final DarkModeSnapshotRestorer mDarkModeSnapshotRestorer;
+ private final ThemedIconSnapshotRestorer mThemedIconSnapshotRestorer;
+ private final ThemedIconInteractor mThemedIconInteractor;
public DefaultCustomizationSections(
KeyguardQuickAffordancePickerInteractor keyguardQuickAffordancePickerInteractor,
@@ -68,7 +71,9 @@
ClockRegistryProvider clockRegistryProvider,
ClockCarouselViewModelProvider clockCarouselViewModelProvider,
ClockViewFactoryProvider clockViewFactoryProvider,
- DarkModeSnapshotRestorer darkModeSnapshotRestorer) {
+ DarkModeSnapshotRestorer darkModeSnapshotRestorer,
+ ThemedIconSnapshotRestorer themedIconSnapshotRestorer,
+ ThemedIconInteractor themedIconInteractor) {
mKeyguardQuickAffordancePickerInteractor = keyguardQuickAffordancePickerInteractor;
mKeyguardQuickAffordancePickerViewModelFactory =
keyguardQuickAffordancePickerViewModelFactory;
@@ -78,6 +83,8 @@
mClockCarouselViewModelProvider = clockCarouselViewModelProvider;
mClockViewFactoryProvider = clockViewFactoryProvider;
mDarkModeSnapshotRestorer = darkModeSnapshotRestorer;
+ mThemedIconSnapshotRestorer = themedIconSnapshotRestorer;
+ mThemedIconInteractor = themedIconInteractor;
}
@Override
@@ -86,7 +93,6 @@
FragmentActivity activity,
LifecycleOwner lifecycleOwner,
WallpaperColorsViewModel wallpaperColorsViewModel,
- WorkspaceViewModel workspaceViewModel,
PermissionRequester permissionRequester,
WallpaperPreviewNavigator wallpaperPreviewNavigator,
CustomizationSectionNavigationController sectionNavigationController,
@@ -167,9 +173,12 @@
mDarkModeSnapshotRestorer));
// Themed app icon section.
- sectionControllers.add(new ThemedIconSectionController(
- ThemedIconSwitchProvider.getInstance(activity), workspaceViewModel,
- savedInstanceState));
+ sectionControllers.add(
+ new ThemedIconSectionController(
+ ThemedIconSwitchProvider.getInstance(activity),
+ mThemedIconInteractor,
+ savedInstanceState,
+ mThemedIconSnapshotRestorer));
// App grid section.
sectionControllers.add(new GridSectionController(
@@ -185,7 +194,6 @@
FragmentActivity activity,
LifecycleOwner lifecycleOwner,
WallpaperColorsViewModel wallpaperColorsViewModel,
- WorkspaceViewModel workspaceViewModel,
PermissionRequester permissionRequester,
WallpaperPreviewNavigator wallpaperPreviewNavigator,
CustomizationSectionNavigationController sectionNavigationController,
@@ -194,10 +202,17 @@
List<CustomizationSectionController<?>> sectionControllers = new ArrayList<>();
// Wallpaper section.
- sectionControllers.add(new WallpaperSectionController(
- activity, lifecycleOwner, permissionRequester, wallpaperColorsViewModel,
- workspaceViewModel, sectionNavigationController, wallpaperPreviewNavigator,
- savedInstanceState, displayUtils));
+ sectionControllers.add(
+ new WallpaperSectionController(
+ activity,
+ lifecycleOwner,
+ permissionRequester,
+ wallpaperColorsViewModel,
+ mThemedIconInteractor.isActivatedAsLiveData(),
+ sectionNavigationController,
+ wallpaperPreviewNavigator,
+ savedInstanceState,
+ displayUtils));
// Theme color section.
sectionControllers.add(new ColorSectionController(
@@ -211,8 +226,10 @@
// Themed app icon section.
sectionControllers.add(new ThemedIconSectionController(
- ThemedIconSwitchProvider.getInstance(activity), workspaceViewModel,
- savedInstanceState));
+ ThemedIconSwitchProvider.getInstance(activity),
+ mThemedIconInteractor,
+ savedInstanceState,
+ mThemedIconSnapshotRestorer));
// App grid section.
sectionControllers.add(new GridSectionController(
diff --git a/src/com/android/customization/module/ThemePickerInjector.kt b/src/com/android/customization/module/ThemePickerInjector.kt
index 007b419..1a8fe6f 100644
--- a/src/com/android/customization/module/ThemePickerInjector.kt
+++ b/src/com/android/customization/module/ThemePickerInjector.kt
@@ -27,6 +27,10 @@
import com.android.customization.model.theme.OverlayManagerCompat
import com.android.customization.model.theme.ThemeBundleProvider
import com.android.customization.model.theme.ThemeManager
+import com.android.customization.model.themedicon.ThemedIconSwitchProvider
+import com.android.customization.model.themedicon.data.repository.ThemeIconRepository
+import com.android.customization.model.themedicon.domain.interactor.ThemedIconInteractor
+import com.android.customization.model.themedicon.domain.interactor.ThemedIconSnapshotRestorer
import com.android.customization.picker.clock.data.repository.ClockPickerRepositoryImpl
import com.android.customization.picker.clock.data.repository.ClockRegistryProvider
import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
@@ -89,6 +93,8 @@
private var colorPickerInteractor: ColorPickerInteractor? = null
private var colorPickerViewModelFactory: ColorPickerViewModel.Factory? = null
private var darkModeSnapshotRestorer: DarkModeSnapshotRestorer? = null
+ private var themedIconSnapshotRestorer: ThemedIconSnapshotRestorer? = null
+ private var themedIconInteractor: ThemedIconInteractor? = null
override fun getCustomizationSections(activity: ComponentActivity): CustomizationSections {
return customizationSections
@@ -117,6 +123,8 @@
}
},
getDarkModeSnapshotRestorer(activity),
+ getThemedIconSnapshotRestorer(activity),
+ getThemedIconInteractor(),
)
.also { customizationSections = it }
}
@@ -178,6 +186,7 @@
this[KEY_WALLPAPER_SNAPSHOT_RESTORER] = getWallpaperSnapshotRestorer(context)
this[KEY_NOTIFICATIONS_SNAPSHOT_RESTORER] = getNotificationsSnapshotRestorer(context)
this[KEY_DARK_MODE_SNAPSHOT_RESTORER] = getDarkModeSnapshotRestorer(context)
+ this[KEY_THEMED_ICON_SNAPSHOT_RESTORER] = getThemedIconSnapshotRestorer(context)
}
}
@@ -365,6 +374,29 @@
.also { darkModeSnapshotRestorer = it }
}
+ protected fun getThemedIconSnapshotRestorer(
+ context: Context,
+ ): ThemedIconSnapshotRestorer {
+ val optionProvider = ThemedIconSwitchProvider.getInstance(context)
+ return themedIconSnapshotRestorer
+ ?: ThemedIconSnapshotRestorer(
+ isActivated = { optionProvider.isThemedIconEnabled },
+ setActivated = { isActivated ->
+ optionProvider.isThemedIconEnabled = isActivated
+ },
+ interactor = getThemedIconInteractor(),
+ )
+ .also { themedIconSnapshotRestorer = it }
+ }
+
+ protected fun getThemedIconInteractor(): ThemedIconInteractor {
+ return themedIconInteractor
+ ?: ThemedIconInteractor(
+ repository = ThemeIconRepository(),
+ )
+ .also { themedIconInteractor = it }
+ }
+
companion object {
@JvmStatic
private val KEY_QUICK_AFFORDANCE_SNAPSHOT_RESTORER =
@@ -375,11 +407,13 @@
private val KEY_NOTIFICATIONS_SNAPSHOT_RESTORER = KEY_WALLPAPER_SNAPSHOT_RESTORER + 1
@JvmStatic
private val KEY_DARK_MODE_SNAPSHOT_RESTORER = KEY_NOTIFICATIONS_SNAPSHOT_RESTORER + 1
+ @JvmStatic
+ private val KEY_THEMED_ICON_SNAPSHOT_RESTORER = KEY_DARK_MODE_SNAPSHOT_RESTORER + 1
/**
* When this injector is overridden, this is the minimal value that should be used by
* restorers returns in [getSnapshotRestorers].
*/
- @JvmStatic protected val MIN_SNAPSHOT_RESTORER_KEY = KEY_DARK_MODE_SNAPSHOT_RESTORER + 1
+ @JvmStatic protected val MIN_SNAPSHOT_RESTORER_KEY = KEY_THEMED_ICON_SNAPSHOT_RESTORER + 1
}
}
diff --git a/tests/src/com/android/customization/model/themedicon/domain/interactor/ThemedIconInteractorTest.kt b/tests/src/com/android/customization/model/themedicon/domain/interactor/ThemedIconInteractorTest.kt
new file mode 100644
index 0000000..e6e30c3
--- /dev/null
+++ b/tests/src/com/android/customization/model/themedicon/domain/interactor/ThemedIconInteractorTest.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.customization.model.themedicon.domain.interactor
+
+import androidx.test.filters.SmallTest
+import com.android.customization.model.themedicon.data.repository.ThemeIconRepository
+import com.android.wallpaper.testing.collectLastValue
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class ThemedIconInteractorTest {
+
+ private lateinit var underTest: ThemedIconInteractor
+
+ @Before
+ fun setUp() {
+ underTest =
+ ThemedIconInteractor(
+ repository = ThemeIconRepository(),
+ )
+ }
+
+ @Test
+ fun `end-to-end`() = runTest {
+ val isActivated = collectLastValue(underTest.isActivated)
+
+ underTest.setActivated(isActivated = true)
+ assertThat(isActivated()).isTrue()
+
+ underTest.setActivated(isActivated = false)
+ assertThat(isActivated()).isFalse()
+ }
+}
diff --git a/tests/src/com/android/customization/model/themedicon/domain/interactor/ThemedIconSnapshotRestorerTest.kt b/tests/src/com/android/customization/model/themedicon/domain/interactor/ThemedIconSnapshotRestorerTest.kt
new file mode 100644
index 0000000..df1fd20
--- /dev/null
+++ b/tests/src/com/android/customization/model/themedicon/domain/interactor/ThemedIconSnapshotRestorerTest.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.customization.model.themedicon.domain.interactor
+
+import androidx.test.filters.SmallTest
+import com.android.customization.model.themedicon.data.repository.ThemeIconRepository
+import com.android.wallpaper.testing.FakeSnapshotStore
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class ThemedIconSnapshotRestorerTest {
+
+ private lateinit var underTest: ThemedIconSnapshotRestorer
+ private var isActivated = false
+
+ @Before
+ fun setUp() {
+ isActivated = false
+ underTest =
+ ThemedIconSnapshotRestorer(
+ isActivated = { isActivated },
+ setActivated = { isActivated = it },
+ interactor =
+ ThemedIconInteractor(
+ repository = ThemeIconRepository(),
+ )
+ )
+ }
+
+ @Test
+ fun `set up and restore - active`() = runTest {
+ isActivated = true
+
+ val store = FakeSnapshotStore()
+ store.store(underTest.setUpSnapshotRestorer(store = store))
+ val storedSnapshot = store.retrieve()
+
+ underTest.restoreToSnapshot(snapshot = storedSnapshot)
+ assertThat(isActivated).isTrue()
+ }
+
+ @Test
+ fun `set up and restore - inactive`() = runTest {
+ isActivated = false
+
+ val store = FakeSnapshotStore()
+ store.store(underTest.setUpSnapshotRestorer(store = store))
+ val storedSnapshot = store.retrieve()
+
+ underTest.restoreToSnapshot(snapshot = storedSnapshot)
+ assertThat(isActivated).isFalse()
+ }
+
+ @Test
+ fun `set up - deactivate - restore to active`() = runTest {
+ isActivated = true
+ val store = FakeSnapshotStore()
+ store.store(underTest.setUpSnapshotRestorer(store = store))
+ val initialSnapshot = store.retrieve()
+
+ underTest.store(isActivated = false)
+
+ underTest.restoreToSnapshot(snapshot = initialSnapshot)
+ assertThat(isActivated).isTrue()
+ }
+
+ @Test
+ fun `set up - activate - restore to inactive`() = runTest {
+ isActivated = false
+ val store = FakeSnapshotStore()
+ store.store(underTest.setUpSnapshotRestorer(store = store))
+ val initialSnapshot = store.retrieve()
+
+ underTest.store(isActivated = true)
+
+ underTest.restoreToSnapshot(snapshot = initialSnapshot)
+ assertThat(isActivated).isFalse()
+ }
+}