From a3eeb4ec6a16c030d2dc5b5a08e7b7deee5386d9 Mon Sep 17 00:00:00 2001 From: ShiftHackZ Date: Sat, 5 Oct 2024 14:46:39 +0300 Subject: [PATCH 1/2] SharedPreferences refactor | Patch 1 --- data/build.gradle.kts | 1 + .../data/preference/PreferenceManagerImpl.kt | 462 ++++++++---------- .../preference/PreferenceManagerImplTest.kt | 4 +- gradle/libs.versions.toml | 2 + 4 files changed, 209 insertions(+), 260 deletions(-) diff --git a/data/build.gradle.kts b/data/build.gradle.kts index c2ced2b7..7049652e 100755 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -22,6 +22,7 @@ dependencies { implementation(libs.koin.android) implementation(libs.rx.kotlin) implementation(libs.google.gson) + implementation(libs.shifthackz.preferences) testImplementation(libs.test.junit) testImplementation(libs.test.mockito) testImplementation(libs.test.mockk) diff --git a/data/src/main/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImpl.kt b/data/src/main/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImpl.kt index 3a434a90..467675ad 100644 --- a/data/src/main/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImpl.kt +++ b/data/src/main/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImpl.kt @@ -13,273 +13,217 @@ import com.shifthackz.aisdv1.domain.entity.HuggingFaceModel import com.shifthackz.aisdv1.domain.entity.ServerSource import com.shifthackz.aisdv1.domain.entity.Settings import com.shifthackz.aisdv1.domain.preference.PreferenceManager +import com.shifthackz.android.core.preferences.delegates import io.reactivex.rxjava3.core.BackpressureStrategy import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.subjects.BehaviorSubject class PreferenceManagerImpl( - private val preferences: SharedPreferences, + preferences: SharedPreferences, ) : PreferenceManager { - private val preferencesChangedSubject: BehaviorSubject = + private val preferencesChangedSubject: BehaviorSubject = BehaviorSubject.createDefault(Unit) - override var automatic1111ServerUrl: String - get() = (preferences.getString(KEY_SERVER_URL, "") ?: "").fixUrlSlashes() - set(value) = preferences.edit() - .putString(KEY_SERVER_URL, value.fixUrlSlashes()) - .apply() - .also { onPreferencesChanged() } - - override var swarmUiServerUrl: String - get() = (preferences.getString(KEY_SWARM_SERVER_URL, "") ?: "").fixUrlSlashes() - set(value) = preferences.edit() - .putString(KEY_SWARM_SERVER_URL, value.fixUrlSlashes()) - .apply() - .also { onPreferencesChanged() } - - override var swarmUiModel: String - get() = preferences.getString(KEY_SWARM_MODEL, "") ?: "" - set(value) = preferences - .edit() - .putString(KEY_SWARM_MODEL, value) - .apply() - .also { onPreferencesChanged() } - - override var demoMode: Boolean - get() = preferences.getBoolean(KEY_DEMO_MODE, false) - set(value) = preferences.edit() - .putBoolean(KEY_DEMO_MODE, value) - .apply() - .also { onPreferencesChanged() } - - override var developerMode: Boolean - get() = preferences.getBoolean(KEY_DEVELOPER_MODE, false) - set(value) = preferences.edit() - .putBoolean(KEY_DEVELOPER_MODE, value) - .apply() - .also { onPreferencesChanged() } - - override var localMediaPipeCustomModelPath: String - get() = preferences.getString( - KEY_MEDIA_PIPE_CUSTOM_MODEL_PATH, - LOCAL_DIFFUSION_CUSTOM_PATH - ) ?: LOCAL_DIFFUSION_CUSTOM_PATH - set(value) = preferences.edit() - .putString(KEY_MEDIA_PIPE_CUSTOM_MODEL_PATH, value) - .apply() - - override var localOnnxCustomModelPath: String - get() = preferences.getString( - KEY_LOCAL_DIFFUSION_CUSTOM_MODEL_PATH, - LOCAL_DIFFUSION_CUSTOM_PATH, - ) ?: LOCAL_DIFFUSION_CUSTOM_PATH - set(value) = preferences.edit() - .putString(KEY_LOCAL_DIFFUSION_CUSTOM_MODEL_PATH, value) - .apply() - - override var localOnnxAllowCancel: Boolean - get() = preferences.getBoolean(KEY_ALLOW_LOCAL_DIFFUSION_CANCEL, false) - set(value) = preferences.edit() - .putBoolean(KEY_ALLOW_LOCAL_DIFFUSION_CANCEL, value) - .apply() - .also { onPreferencesChanged() } - - override var localOnnxSchedulerThread: SchedulersToken - get() = preferences - .getInt(KEY_LOCAL_DIFFUSION_SCHEDULER_THREAD, SchedulersToken.COMPUTATION.ordinal) - .let { SchedulersToken.entries[it] } - set(value) = preferences.edit() - .putInt(KEY_LOCAL_DIFFUSION_SCHEDULER_THREAD, value.ordinal) - .apply() - .also { onPreferencesChanged() } - - override var monitorConnectivity: Boolean - get() = if (!source.featureTags.contains(FeatureTag.OwnServer)) false - else preferences.getBoolean(KEY_MONITOR_CONNECTIVITY, false) - set(value) = preferences.edit() - .putBoolean(KEY_MONITOR_CONNECTIVITY, value) - .apply() - .also { onPreferencesChanged() } - - override var autoSaveAiResults: Boolean - get() = preferences.getBoolean(KEY_AI_AUTO_SAVE, true) - set(value) = preferences.edit() - .putBoolean(KEY_AI_AUTO_SAVE, value) - .apply() - .also { onPreferencesChanged() } - - override var saveToMediaStore: Boolean - get() = preferences.getBoolean(KEY_SAVE_TO_MEDIA_STORE, shouldUseNewMediaStore()) - set(value) = preferences.edit() - .putBoolean(KEY_SAVE_TO_MEDIA_STORE, value) - .apply() - .also { onPreferencesChanged() } - - override var formAdvancedOptionsAlwaysShow: Boolean - get() = preferences.getBoolean(KEY_FORM_ALWAYS_SHOW_ADVANCED_OPTIONS, false) - set(value) = preferences.edit() - .putBoolean(KEY_FORM_ALWAYS_SHOW_ADVANCED_OPTIONS, value) - .apply() - .also { onPreferencesChanged() } - - override var formPromptTaggedInput: Boolean - get() = preferences.getBoolean(KEY_FORM_PROMPT_TAGGED_INPUT, true) - set(value) = preferences.edit() - .putBoolean(KEY_FORM_PROMPT_TAGGED_INPUT, value) - .apply() - .also { onPreferencesChanged() } - - override var source: ServerSource - get() = (preferences.getString(KEY_SERVER_SOURCE, ServerSource.AUTOMATIC1111.key) ?: ServerSource.AUTOMATIC1111.key) - .let(ServerSource.Companion::parse) - set(value) = preferences.edit() - .putString(KEY_SERVER_SOURCE, value.key) - .apply() - .also { onPreferencesChanged() } - - override var sdModel: String - get() = preferences.getString(KEY_SD_MODEL, "") ?: "" - set(value) = preferences.edit() - .putString(KEY_SD_MODEL, value) - .apply() - .also { onPreferencesChanged() } - - override var hordeApiKey: String - get() = preferences.getString(KEY_HORDE_API_KEY, "") ?: "" - set(value) = preferences.edit() - .putString(KEY_HORDE_API_KEY, value) - .apply() - .also { onPreferencesChanged() } - - override var openAiApiKey: String - get() = preferences.getString(KEY_OPEN_AI_API_KEY, "") ?: "" - set(value) = preferences.edit() - .putString(KEY_OPEN_AI_API_KEY, value) - .apply() - .also { onPreferencesChanged() } - - override var huggingFaceApiKey: String - get() = preferences.getString(KEY_HUGGING_FACE_API_KEY, "") ?: "" - set(value) = preferences.edit() - .putString(KEY_HUGGING_FACE_API_KEY, value) - .apply() - .also { onPreferencesChanged() } - - override var huggingFaceModel: String - get() { - return preferences.getString( - KEY_HUGGING_FACE_MODEL_KEY, - HuggingFaceModel.default.alias, - ) ?: HuggingFaceModel.default.alias - } - set(value) = preferences.edit() - .putString(KEY_HUGGING_FACE_MODEL_KEY, value) - .apply() - .also { onPreferencesChanged() } - - override var stabilityAiApiKey: String - get() = preferences.getString(KEY_STABILITY_AI_API_KEY, "") ?: "" - set(value) = preferences.edit() - .putString(KEY_STABILITY_AI_API_KEY, value) - .apply() - .also { onPreferencesChanged() } - - override var stabilityAiEngineId: String - get() = preferences.getString(KEY_STABILITY_AI_ENGINE_ID_KEY, "") ?: "" - set(value) = preferences.edit() - .putString(KEY_STABILITY_AI_ENGINE_ID_KEY, value) - .apply() - .also { onPreferencesChanged() } - - override var onBoardingComplete: Boolean - get() = preferences.getBoolean(KEY_ON_BOARDING_COMPLETE, false) - set(value) = preferences.edit() - .putBoolean(KEY_ON_BOARDING_COMPLETE, value) - .apply() - - override var forceSetupAfterUpdate: Boolean - get() = preferences.getBoolean(KEY_FORCE_SETUP_AFTER_UPDATE, true) - set(value) = preferences.edit() - .putBoolean(KEY_FORCE_SETUP_AFTER_UPDATE, value) - .apply() - .also { onPreferencesChanged() } - - override var localOnnxModelId: String - get() = preferences.getString(KEY_LOCAL_MODEL_ID, "") ?: "" - set(value) = preferences.edit() - .putString(KEY_LOCAL_MODEL_ID, value) - .apply() - .also { onPreferencesChanged() } - - override var localOnnxUseNNAPI: Boolean - get() = preferences.getBoolean(KEY_LOCAL_NN_API, false) - set(value) = preferences.edit() - .putBoolean(KEY_LOCAL_NN_API, value) - .apply() - .also { onPreferencesChanged() } - - override var localMediaPipeModelId: String - get() = preferences.getString(KEY_MEDIA_PIPE_MODEL_ID, "") ?: "" - set(value) = preferences.edit() - .putString(KEY_MEDIA_PIPE_MODEL_ID, value) - .apply() - .also { onPreferencesChanged() } - - override var designUseSystemColorPalette: Boolean - get() = preferences.getBoolean(KEY_DESIGN_DYNAMIC_COLORS, false) - set(value) = preferences.edit() - .putBoolean(KEY_DESIGN_DYNAMIC_COLORS, value) - .apply() - .also { onPreferencesChanged() } - - override var designUseSystemDarkTheme: Boolean - get() = preferences.getBoolean(KEY_DESIGN_SYSTEM_DARK_THEME, true) - set(value) = preferences.edit() - .putBoolean(KEY_DESIGN_SYSTEM_DARK_THEME, value) - .apply() - .also { onPreferencesChanged() } - - override var designDarkTheme: Boolean - get() = preferences.getBoolean(KEY_DESIGN_DARK_THEME, true) - set(value) = preferences.edit() - .putBoolean(KEY_DESIGN_DARK_THEME, value) - .apply() - .also { onPreferencesChanged() } - - override var designColorToken: String - get() = preferences.getString(KEY_DESIGN_COLOR_TOKEN, "${ColorToken.MAUVE}") ?: "${ColorToken.MAUVE}" - set(value) = preferences.edit() - .putString(KEY_DESIGN_COLOR_TOKEN, value) - .apply() - .also { onPreferencesChanged() } - - override var designDarkThemeToken: String - get() = preferences.getString(KEY_DESIGN_DARK_TOKEN, "${DarkThemeToken.FRAPPE}") ?: "${DarkThemeToken.FRAPPE}" - set(value) = preferences.edit() - .putString(KEY_DESIGN_DARK_TOKEN, value) - .apply() - .also { onPreferencesChanged() } - - override var backgroundGeneration: Boolean - get() = preferences.getBoolean(KEY_BACKGROUND_GENERATION, false) - set(value) = preferences.edit() - .putBoolean(KEY_BACKGROUND_GENERATION, value) - .apply() - .also { onPreferencesChanged() } - - override var backgroundProcessCount: Int - get() = preferences.getInt(KEY_BACKGROUND_PROCESS_COUNT, 0) - set(value) = preferences.edit() - .putInt(KEY_BACKGROUND_PROCESS_COUNT, value) - .apply() - - override var galleryGrid: Grid - get() = preferences.getInt(KEY_GALLERY_GRID, 0).let { Grid.entries[it] } - set(value) = preferences.edit() - .putInt(KEY_GALLERY_GRID, value.ordinal) - .apply() - .also { onPreferencesChanged() } + override var automatic1111ServerUrl: String by preferences.delegates.complexString( + key = KEY_SERVER_URL, + default = "", + serialize = { it.fixUrlSlashes() }, + deserialize = { it.fixUrlSlashes() }, + onChanged = ::onPreferencesChanged, + ) + + override var swarmUiServerUrl: String by preferences.delegates.complexString( + key = KEY_SWARM_SERVER_URL, + default = "", + serialize = { it.fixUrlSlashes() }, + deserialize = { it.fixUrlSlashes() }, + onChanged = ::onPreferencesChanged, + ) + + override var swarmUiModel: String by preferences.delegates.string( + key = KEY_SWARM_MODEL, + onChanged = ::onPreferencesChanged, + ) + + override var demoMode: Boolean by preferences.delegates.boolean( + key = KEY_DEMO_MODE, + onChanged = ::onPreferencesChanged, + ) + + override var developerMode: Boolean by preferences.delegates.boolean( + key = KEY_DEVELOPER_MODE, + onChanged = ::onPreferencesChanged, + ) + + override var localMediaPipeCustomModelPath: String by preferences.delegates.string( + key = KEY_MEDIA_PIPE_CUSTOM_MODEL_PATH, + default = LOCAL_DIFFUSION_CUSTOM_PATH, + ) + + override var localOnnxCustomModelPath: String by preferences.delegates.string( + key = KEY_LOCAL_DIFFUSION_CUSTOM_MODEL_PATH, + default = LOCAL_DIFFUSION_CUSTOM_PATH, + ) + + override var localOnnxAllowCancel: Boolean by preferences.delegates.boolean( + key = KEY_ALLOW_LOCAL_DIFFUSION_CANCEL, + onChanged = ::onPreferencesChanged, + ) + + override var localOnnxSchedulerThread: SchedulersToken by preferences.delegates.complexInt( + key = KEY_LOCAL_DIFFUSION_SCHEDULER_THREAD, + default = SchedulersToken.COMPUTATION, + serialize = { token -> token.ordinal }, + deserialize = { index -> SchedulersToken.entries[index] }, + onChanged = ::onPreferencesChanged, + ) + + override var monitorConnectivity: Boolean by preferences.delegates.complexBoolean( + key = KEY_MONITOR_CONNECTIVITY, + default = false, + serialize = { it }, + deserialize = { if (!source.featureTags.contains(FeatureTag.OwnServer)) false else it }, + onChanged = ::onPreferencesChanged, + ) + + override var autoSaveAiResults: Boolean by preferences.delegates.boolean( + key = KEY_AI_AUTO_SAVE, + default = true, + onChanged = ::onPreferencesChanged, + ) + + override var saveToMediaStore: Boolean by preferences.delegates.boolean( + key = KEY_SAVE_TO_MEDIA_STORE, + default = shouldUseNewMediaStore(), + onChanged = ::onPreferencesChanged, + ) + + override var formAdvancedOptionsAlwaysShow: Boolean by preferences.delegates.boolean( + key = KEY_FORM_ALWAYS_SHOW_ADVANCED_OPTIONS, + onChanged = ::onPreferencesChanged, + ) + + override var formPromptTaggedInput: Boolean by preferences.delegates.boolean( + key = KEY_FORM_PROMPT_TAGGED_INPUT, + default = true, + onChanged = ::onPreferencesChanged, + ) + + override var source: ServerSource by preferences.delegates.complexString( + key = KEY_SERVER_SOURCE, + default = ServerSource.AUTOMATIC1111, + serialize = { source -> source.key }, + deserialize = { key -> ServerSource.parse(key) }, + onChanged = ::onPreferencesChanged, + ) + + override var sdModel: String by preferences.delegates.string( + key = KEY_SD_MODEL, + onChanged = ::onPreferencesChanged, + ) + + override var hordeApiKey: String by preferences.delegates.string( + key = KEY_HORDE_API_KEY, + onChanged = ::onPreferencesChanged, + ) + + override var openAiApiKey: String by preferences.delegates.string( + key = KEY_OPEN_AI_API_KEY, + onChanged = ::onPreferencesChanged, + ) + + override var huggingFaceApiKey: String by preferences.delegates.string( + key = KEY_HUGGING_FACE_API_KEY, + onChanged = ::onPreferencesChanged, + ) + + override var huggingFaceModel: String by preferences.delegates.string( + key = KEY_HUGGING_FACE_MODEL_KEY, + default = HuggingFaceModel.default.alias, + onChanged = ::onPreferencesChanged, + ) + + override var stabilityAiApiKey: String by preferences.delegates.string( + key = KEY_STABILITY_AI_API_KEY, + onChanged = ::onPreferencesChanged, + ) + + override var stabilityAiEngineId: String by preferences.delegates.string( + key = KEY_STABILITY_AI_ENGINE_ID_KEY, + onChanged = ::onPreferencesChanged, + ) + + override var onBoardingComplete: Boolean by preferences.delegates.boolean( + key = KEY_ON_BOARDING_COMPLETE, + ) + + override var forceSetupAfterUpdate: Boolean by preferences.delegates.boolean( + key = KEY_FORCE_SETUP_AFTER_UPDATE, + default = true, + onChanged = ::onPreferencesChanged, + ) + + override var localOnnxModelId: String by preferences.delegates.string( + key = KEY_LOCAL_MODEL_ID, + onChanged = ::onPreferencesChanged, + ) + + override var localOnnxUseNNAPI: Boolean by preferences.delegates.boolean( + key = KEY_LOCAL_NN_API, + onChanged = ::onPreferencesChanged, + ) + + override var localMediaPipeModelId: String by preferences.delegates.string( + key = KEY_MEDIA_PIPE_MODEL_ID, + onChanged = ::onPreferencesChanged, + ) + + override var designUseSystemColorPalette: Boolean by preferences.delegates.boolean( + key = KEY_DESIGN_DYNAMIC_COLORS, + onChanged = ::onPreferencesChanged, + ) + + override var designUseSystemDarkTheme: Boolean by preferences.delegates.boolean( + key = KEY_DESIGN_SYSTEM_DARK_THEME, + default = true, + onChanged = ::onPreferencesChanged, + ) + + override var designDarkTheme: Boolean by preferences.delegates.boolean( + key = KEY_DESIGN_DARK_THEME, + default = true, + onChanged = ::onPreferencesChanged, + ) + + override var designColorToken: String by preferences.delegates.string( + key = KEY_DESIGN_COLOR_TOKEN, + default = "${ColorToken.MAUVE}", + onChanged = ::onPreferencesChanged, + ) + + override var designDarkThemeToken: String by preferences.delegates.string( + key = KEY_DESIGN_DARK_TOKEN, + default = "${DarkThemeToken.FRAPPE}", + onChanged = ::onPreferencesChanged, + ) + override var backgroundGeneration: Boolean by preferences.delegates.boolean( + key = KEY_BACKGROUND_GENERATION, + onChanged = ::onPreferencesChanged, + ) + + override var backgroundProcessCount: Int by preferences.delegates.int( + key = KEY_BACKGROUND_PROCESS_COUNT, + default = 0, + ) + + override var galleryGrid: Grid by preferences.delegates.complexInt( + key = KEY_GALLERY_GRID, + default = Grid.entries.first(), + serialize = { grid -> grid.ordinal }, + deserialize = { index -> Grid.entries[index] }, + onChanged = ::onPreferencesChanged, + ) override fun observe(): Flowable = preferencesChangedSubject .toFlowable(BackpressureStrategy.LATEST) @@ -309,7 +253,7 @@ class PreferenceManagerImpl( ) } - private fun onPreferencesChanged() = preferencesChangedSubject.onNext(Unit) + private fun onPreferencesChanged(value: T) = preferencesChangedSubject.onNext(value) companion object { const val KEY_SERVER_URL = "key_server_url" diff --git a/data/src/test/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImplTest.kt b/data/src/test/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImplTest.kt index 20b1f5b3..5f68e23b 100644 --- a/data/src/test/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImplTest.kt +++ b/data/src/test/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImplTest.kt @@ -42,7 +42,7 @@ class PreferenceManagerImplTest { private val stubEditor = mock() private val stubPreference = mock() - private val preferenceManager = PreferenceManagerImpl(stubPreference) + private lateinit var preferenceManager : PreferenceManagerImpl @Before fun initialize() { @@ -64,6 +64,8 @@ class PreferenceManagerImplTest { whenever(stubPreference.getBoolean(any(), any())) .thenReturn(false) + + preferenceManager = PreferenceManagerImpl(stubPreference) } @Test diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b15cb0f5..1b6bd097 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -40,6 +40,7 @@ apacheStringUtils = "3.17.0" composeGestures = "4.0.0" crop = "0.1.1" mvi = "1.0.2" +preferences = "1.0.1" dayNightSwitch = "1.0.0" imagepicker = "v2.0.3" catppuccin = "0.1.2" @@ -106,6 +107,7 @@ test-compose-manifest = { group = "androidx.compose.ui", name = "ui-test-manifes compose-gestures = { group = "com.github.SmartToolFactory", name = "Compose-Extended-Gestures", version.ref = "composeGestures" } compose-crop = { group = "io.github.mr0xf00", name = "easycrop", version.ref = "crop" } shifthackz-mvi = { group = "com.github.ShiftHackZ", name = "AndroidCoreMVI", version.ref = "mvi" } +shifthackz-preferences = { group = "com.github.ShiftHackZ", name = "AndroidPreferences", version.ref = "preferences" } shifthackz-imagepicker = { group = "com.github.ShiftHackZ", name = "ImagePicker", version.ref = "imagepicker" } shifthackz-daynightswitch = { group = "com.github.ShiftHackZ", name = "DayNightSwitch", version.ref = "dayNightSwitch" } shifthackz-catppuccin-legacy = { group = "com.github.ShiftHackZ.Catppuccin-Android-Library", name = "palette-legacy", version.ref = "catppuccin" } From 54bdef3a7cf175c52811a22b5060655a8ed1d91b Mon Sep 17 00:00:00 2001 From: ShiftHackZ Date: Sun, 6 Oct 2024 15:02:25 +0300 Subject: [PATCH 2/2] Add refresh option --- .../aisdv1/data/preference/PreferenceManagerImpl.kt | 5 +++++ .../aisdv1/domain/preference/PreferenceManager.kt | 2 ++ gradle/wrapper/gradle-wrapper.properties | 4 ++-- .../screen/home/HomeNavigationViewModel.kt | 10 ++++++++++ .../presentation/theme/global/AiSdAppThemeState.kt | 1 + .../presentation/theme/global/AiSdAppThemeViewModel.kt | 6 +++++- 6 files changed, 25 insertions(+), 3 deletions(-) diff --git a/data/src/main/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImpl.kt b/data/src/main/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImpl.kt index 467675ad..1c5ee337 100644 --- a/data/src/main/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImpl.kt +++ b/data/src/main/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImpl.kt @@ -15,6 +15,7 @@ import com.shifthackz.aisdv1.domain.entity.Settings import com.shifthackz.aisdv1.domain.preference.PreferenceManager import com.shifthackz.android.core.preferences.delegates import io.reactivex.rxjava3.core.BackpressureStrategy +import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.subjects.BehaviorSubject @@ -253,6 +254,10 @@ class PreferenceManagerImpl( ) } + override fun refresh(): Completable = Completable.fromAction { + preferencesChangedSubject.onNext(Unit) + } + private fun onPreferencesChanged(value: T) = preferencesChangedSubject.onNext(value) companion object { diff --git a/domain/src/main/java/com/shifthackz/aisdv1/domain/preference/PreferenceManager.kt b/domain/src/main/java/com/shifthackz/aisdv1/domain/preference/PreferenceManager.kt index 42c32959..b049cf33 100644 --- a/domain/src/main/java/com/shifthackz/aisdv1/domain/preference/PreferenceManager.kt +++ b/domain/src/main/java/com/shifthackz/aisdv1/domain/preference/PreferenceManager.kt @@ -4,6 +4,7 @@ import com.shifthackz.aisdv1.core.common.schedulers.SchedulersToken import com.shifthackz.aisdv1.domain.entity.Grid import com.shifthackz.aisdv1.domain.entity.ServerSource import com.shifthackz.aisdv1.domain.entity.Settings +import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Flowable interface PreferenceManager { @@ -44,4 +45,5 @@ interface PreferenceManager { var galleryGrid: Grid fun observe(): Flowable + fun refresh(): Completable } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 24f1e3bd..16ae8af4 100755 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Feb 08 12:27:05 EET 2024 +#Sun Oct 06 14:29:53 EEST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/presentation/src/main/java/com/shifthackz/aisdv1/presentation/screen/home/HomeNavigationViewModel.kt b/presentation/src/main/java/com/shifthackz/aisdv1/presentation/screen/home/HomeNavigationViewModel.kt index a118e1df..429c0fd6 100644 --- a/presentation/src/main/java/com/shifthackz/aisdv1/presentation/screen/home/HomeNavigationViewModel.kt +++ b/presentation/src/main/java/com/shifthackz/aisdv1/presentation/screen/home/HomeNavigationViewModel.kt @@ -7,14 +7,18 @@ import com.shifthackz.aisdv1.core.common.schedulers.SchedulersProvider import com.shifthackz.aisdv1.core.common.schedulers.subscribeOnMainThread import com.shifthackz.aisdv1.core.viewmodel.MviRxViewModel import com.shifthackz.aisdv1.domain.entity.AiGenerationResult +import com.shifthackz.aisdv1.domain.preference.PreferenceManager import com.shifthackz.aisdv1.presentation.core.GenerationFormUpdateEvent import com.shifthackz.aisdv1.presentation.navigation.NavigationEffect import com.shifthackz.aisdv1.presentation.navigation.router.home.HomeRouter import com.shifthackz.android.core.mvi.EmptyState +import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.kotlin.subscribeBy +import java.util.concurrent.TimeUnit class HomeNavigationViewModel( generationFormUpdateEvent: GenerationFormUpdateEvent, + preferenceManager: PreferenceManager, dispatchersProvider: DispatchersProvider, schedulersProvider: SchedulersProvider, private val homeRouter: HomeRouter, @@ -38,6 +42,12 @@ class HomeNavigationViewModel( .map(HomeNavigationIntent::Route) .subscribeOnMainThread(schedulersProvider) .subscribeBy(::errorLog, EmptyLambda, ::processIntent) + + !Observable + .timer(250L, TimeUnit.MILLISECONDS) + .flatMapCompletable { preferenceManager.refresh() } + .subscribeOnMainThread(schedulersProvider) + .subscribeBy(::errorLog) } override fun processIntent(intent: HomeNavigationIntent) { diff --git a/presentation/src/main/java/com/shifthackz/aisdv1/presentation/theme/global/AiSdAppThemeState.kt b/presentation/src/main/java/com/shifthackz/aisdv1/presentation/theme/global/AiSdAppThemeState.kt index 2be12705..19f84211 100644 --- a/presentation/src/main/java/com/shifthackz/aisdv1/presentation/theme/global/AiSdAppThemeState.kt +++ b/presentation/src/main/java/com/shifthackz/aisdv1/presentation/theme/global/AiSdAppThemeState.kt @@ -7,6 +7,7 @@ import com.shifthackz.android.core.mvi.MviState @Immutable data class AiSdAppThemeState( + val stateKey: Long = System.currentTimeMillis(), val systemColorPalette: Boolean = false, val systemDarkTheme: Boolean = true, val darkTheme: Boolean = true, diff --git a/presentation/src/main/java/com/shifthackz/aisdv1/presentation/theme/global/AiSdAppThemeViewModel.kt b/presentation/src/main/java/com/shifthackz/aisdv1/presentation/theme/global/AiSdAppThemeViewModel.kt index e7cdcccc..66a23085 100644 --- a/presentation/src/main/java/com/shifthackz/aisdv1/presentation/theme/global/AiSdAppThemeViewModel.kt +++ b/presentation/src/main/java/com/shifthackz/aisdv1/presentation/theme/global/AiSdAppThemeViewModel.kt @@ -5,6 +5,7 @@ import com.shifthackz.aisdv1.core.common.log.errorLog import com.shifthackz.aisdv1.core.common.schedulers.DispatchersProvider import com.shifthackz.aisdv1.core.common.schedulers.SchedulersProvider import com.shifthackz.aisdv1.core.common.schedulers.subscribeOnMainThread +import com.shifthackz.aisdv1.core.common.time.TimeProvider import com.shifthackz.aisdv1.core.viewmodel.MviRxViewModel import com.shifthackz.aisdv1.domain.entity.ColorToken import com.shifthackz.aisdv1.domain.entity.DarkThemeToken @@ -17,6 +18,7 @@ class AiSdAppThemeViewModel( preferenceManager: PreferenceManager, dispatchersProvider: DispatchersProvider, schedulersProvider: SchedulersProvider, + timeProvider: TimeProvider, ) : MviRxViewModel() { override val initialState = AiSdAppThemeState() @@ -24,11 +26,13 @@ class AiSdAppThemeViewModel( override val effectDispatcher = dispatchersProvider.immediate init { - !preferenceManager.observe() + !preferenceManager + .observe() .subscribeOnMainThread(schedulersProvider) .subscribeBy(::errorLog, EmptyLambda) { settings -> updateState { state -> state.copy( + stateKey = timeProvider.currentTimeMillis(), systemColorPalette = settings.designUseSystemColorPalette, systemDarkTheme = settings.designUseSystemDarkTheme, darkTheme = settings.designDarkTheme,