From 9dc208deba0fd58bbc42a526d68d51153f50aca9 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Sun, 29 Mar 2026 10:43:38 -0400 Subject: [PATCH] Removing internal runBlockings --- .../com/vitorpamplona/amethyst/AppModules.kt | 8 +- .../amethyst/model/UiSettingsFlow.kt | 24 +-- .../model/preferences/TorSharedPreferences.kt | 135 ++++++++--------- .../model/preferences/UISharedPreferences.kt | 141 +++++++++--------- 4 files changed, 157 insertions(+), 151 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/AppModules.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/AppModules.kt index 59c4cd4d6..78a13e3f4 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/AppModules.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/AppModules.kt @@ -28,6 +28,7 @@ import com.vitorpamplona.amethyst.commons.model.NoteState import com.vitorpamplona.amethyst.commons.robohash.CachedRobohash import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.LocalCache +import com.vitorpamplona.amethyst.model.UiSettings import com.vitorpamplona.amethyst.model.accountsCache.AccountCacheState import com.vitorpamplona.amethyst.model.nip03Timestamp.IncomingOtsEventVerifier import com.vitorpamplona.amethyst.model.nip03Timestamp.TorAwareOkHttpOtsResolverBuilder @@ -67,6 +68,7 @@ import com.vitorpamplona.amethyst.ui.resourceCacheInit import com.vitorpamplona.amethyst.ui.screen.AccountSessionManager import com.vitorpamplona.amethyst.ui.screen.UiSettingsState import com.vitorpamplona.amethyst.ui.tor.TorManager +import com.vitorpamplona.amethyst.ui.tor.TorSettings import com.vitorpamplona.quartz.nip01Core.core.Address import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient @@ -117,12 +119,14 @@ class AppModules( // reduces total blocking time from (torPrefs + uiPrefs) to ~max(torPrefs, uiPrefs). private val uiPrefsDeferred = applicationIOScope.async { - UiSharedPreferences(appContext, applicationIOScope) + val prefs = UiSharedPreferences.uiPreferences(appContext) ?: UiSettings() + UiSharedPreferences(prefs, appContext, applicationIOScope) } private val torPrefsDeferred = applicationIOScope.async { - TorSharedPreferences(appContext, applicationIOScope) + val prefs = TorSharedPreferences.torPreferences(appContext) ?: TorSettings() + TorSharedPreferences(prefs, appContext, applicationIOScope) } // Blocking load of UI Preferences to avoid theme/language blinking diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/UiSettingsFlow.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/UiSettingsFlow.kt index c1981297e..467663f7e 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/UiSettingsFlow.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/UiSettingsFlow.kt @@ -151,19 +151,19 @@ class UiSettingsFlow( } companion object { - fun build(torSettings: UiSettings): UiSettingsFlow = + fun build(uiSettings: UiSettings): UiSettingsFlow = UiSettingsFlow( - MutableStateFlow(torSettings.theme), - MutableStateFlow(torSettings.preferredLanguage), - MutableStateFlow(torSettings.automaticallyShowImages), - MutableStateFlow(torSettings.automaticallyStartPlayback), - MutableStateFlow(torSettings.automaticallyShowUrlPreview), - MutableStateFlow(torSettings.automaticallyHideNavigationBars), - MutableStateFlow(torSettings.automaticallyShowProfilePictures), - MutableStateFlow(torSettings.dontShowPushNotificationSelector), - MutableStateFlow(torSettings.dontAskForNotificationPermissions), - MutableStateFlow(torSettings.featureSet), - MutableStateFlow(torSettings.gallerySet), + MutableStateFlow(uiSettings.theme), + MutableStateFlow(uiSettings.preferredLanguage), + MutableStateFlow(uiSettings.automaticallyShowImages), + MutableStateFlow(uiSettings.automaticallyStartPlayback), + MutableStateFlow(uiSettings.automaticallyShowUrlPreview), + MutableStateFlow(uiSettings.automaticallyHideNavigationBars), + MutableStateFlow(uiSettings.automaticallyShowProfilePictures), + MutableStateFlow(uiSettings.dontShowPushNotificationSelector), + MutableStateFlow(uiSettings.dontAskForNotificationPermissions), + MutableStateFlow(uiSettings.featureSet), + MutableStateFlow(uiSettings.gallerySet), ) } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/TorSharedPreferences.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/TorSharedPreferences.kt index 94d69ccca..0bb4d80f6 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/TorSharedPreferences.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/TorSharedPreferences.kt @@ -40,14 +40,31 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.runBlocking import kotlin.coroutines.cancellation.CancellationException @Stable class TorSharedPreferences( + prefs: TorSettings, val context: Context, val scope: CoroutineScope, ) { + // Tor Preferences. Makes sure to wait for it to avoid connecting with random IPs + val value = TorSettingsFlow.build(prefs) + + @OptIn(FlowPreview::class) + val saving = + value.propertyWatchFlow + .debounce(1000) + .distinctUntilChanged() + .onEach { + save(it, context) + }.flowOn(Dispatchers.IO) + .stateIn( + scope, + SharingStarted.Eagerly, + value.toSettings(), + ) + companion object { // loads faster when individualized val TOR_TYPE_KEY = stringPreferencesKey("tor.torType") @@ -63,74 +80,58 @@ class TorSharedPreferences( val MONEY_OPERATIONS_VIA_TOR_KEY = booleanPreferencesKey("tor.moneyOperationsViaTor") val NIP05_VERIFICATIONS_VIA_TOR_KEY = booleanPreferencesKey("tor.nip05VerificationsViaTor") val MEDIA_UPLOADS_VIA_TOR_KEY = booleanPreferencesKey("tor.mediaUploadsViaTor") - } - // Tor Preferences. Makes sure to wait for it to avoid connecting with random IPs - val value = - runBlocking { - TorSettingsFlow.build(torPreferences() ?: TorSettings()) - } - - @OptIn(FlowPreview::class) - val saving = - value.propertyWatchFlow - .debounce(1000) - .distinctUntilChanged() - .onEach(::save) - .flowOn(Dispatchers.IO) - .stateIn( - scope, - SharingStarted.Eagerly, - value.toSettings(), - ) - - suspend fun torPreferences(): TorSettings? = - try { - // Get the preference flow and take the first value. - val preferences = context.sharedPreferencesDataStore.data.first() - TorSettings( - torType = preferences[TOR_TYPE_KEY]?.let { TorType.valueOf(it) } ?: TorType.INTERNAL, - externalSocksPort = preferences[EXTERNAL_SOCKS_PORT_KEY] ?: 9050, - onionRelaysViaTor = preferences[ONION_RELAYS_VIA_TOR_KEY] ?: true, - dmRelaysViaTor = preferences[DM_RELAYS_VIA_TOR_KEY] ?: true, - newRelaysViaTor = preferences[NEW_RELAYS_VIA_TOR_KEY] ?: true, - trustedRelaysViaTor = preferences[TRUSTED_RELAYS_VIA_TOR_KEY] ?: false, - urlPreviewsViaTor = preferences[URL_PREVIEWS_VIA_TOR_KEY] ?: false, - profilePicsViaTor = preferences[PROFILE_PICS_VIA_TOR_KEY] ?: false, - imagesViaTor = preferences[IMAGES_VIA_TOR_KEY] ?: false, - videosViaTor = preferences[VIDEOS_VIA_TOR_KEY] ?: false, - moneyOperationsViaTor = preferences[MONEY_OPERATIONS_VIA_TOR_KEY] ?: false, - nip05VerificationsViaTor = preferences[NIP05_VERIFICATIONS_VIA_TOR_KEY] ?: false, - mediaUploadsViaTor = preferences[MEDIA_UPLOADS_VIA_TOR_KEY] ?: false, - ) - } catch (e: Exception) { - if (e is CancellationException) throw e - // Log any errors that occur while reading the DataStore. - Log.e("SharedPreferences") { "Error reading DataStore preferences: ${e.message}" } - null - } - - suspend fun save(torSettings: TorSettings) { - try { - context.sharedPreferencesDataStore.edit { preferences -> - preferences[TOR_TYPE_KEY] = torSettings.torType.name - preferences[EXTERNAL_SOCKS_PORT_KEY] = torSettings.externalSocksPort - preferences[ONION_RELAYS_VIA_TOR_KEY] = torSettings.onionRelaysViaTor - preferences[DM_RELAYS_VIA_TOR_KEY] = torSettings.dmRelaysViaTor - preferences[NEW_RELAYS_VIA_TOR_KEY] = torSettings.newRelaysViaTor - preferences[TRUSTED_RELAYS_VIA_TOR_KEY] = torSettings.trustedRelaysViaTor - preferences[URL_PREVIEWS_VIA_TOR_KEY] = torSettings.urlPreviewsViaTor - preferences[PROFILE_PICS_VIA_TOR_KEY] = torSettings.profilePicsViaTor - preferences[IMAGES_VIA_TOR_KEY] = torSettings.imagesViaTor - preferences[VIDEOS_VIA_TOR_KEY] = torSettings.videosViaTor - preferences[MONEY_OPERATIONS_VIA_TOR_KEY] = torSettings.moneyOperationsViaTor - preferences[NIP05_VERIFICATIONS_VIA_TOR_KEY] = torSettings.nip05VerificationsViaTor - preferences[MEDIA_UPLOADS_VIA_TOR_KEY] = torSettings.mediaUploadsViaTor + suspend fun torPreferences(context: Context): TorSettings? = + try { + // Get the preference flow and take the first value. + val preferences = context.sharedPreferencesDataStore.data.first() + TorSettings( + torType = preferences[TOR_TYPE_KEY]?.let { TorType.valueOf(it) } ?: TorType.INTERNAL, + externalSocksPort = preferences[EXTERNAL_SOCKS_PORT_KEY] ?: 9050, + onionRelaysViaTor = preferences[ONION_RELAYS_VIA_TOR_KEY] ?: true, + dmRelaysViaTor = preferences[DM_RELAYS_VIA_TOR_KEY] ?: true, + newRelaysViaTor = preferences[NEW_RELAYS_VIA_TOR_KEY] ?: true, + trustedRelaysViaTor = preferences[TRUSTED_RELAYS_VIA_TOR_KEY] ?: false, + urlPreviewsViaTor = preferences[URL_PREVIEWS_VIA_TOR_KEY] ?: false, + profilePicsViaTor = preferences[PROFILE_PICS_VIA_TOR_KEY] ?: false, + imagesViaTor = preferences[IMAGES_VIA_TOR_KEY] ?: false, + videosViaTor = preferences[VIDEOS_VIA_TOR_KEY] ?: false, + moneyOperationsViaTor = preferences[MONEY_OPERATIONS_VIA_TOR_KEY] ?: false, + nip05VerificationsViaTor = preferences[NIP05_VERIFICATIONS_VIA_TOR_KEY] ?: false, + mediaUploadsViaTor = preferences[MEDIA_UPLOADS_VIA_TOR_KEY] ?: false, + ) + } catch (e: Exception) { + if (e is CancellationException) throw e + // Log any errors that occur while reading the DataStore. + Log.e("SharedPreferences") { "Error reading DataStore preferences: ${e.message}" } + null + } + + suspend fun save( + torSettings: TorSettings, + context: Context, + ) { + try { + context.sharedPreferencesDataStore.edit { preferences -> + preferences[TOR_TYPE_KEY] = torSettings.torType.name + preferences[EXTERNAL_SOCKS_PORT_KEY] = torSettings.externalSocksPort + preferences[ONION_RELAYS_VIA_TOR_KEY] = torSettings.onionRelaysViaTor + preferences[DM_RELAYS_VIA_TOR_KEY] = torSettings.dmRelaysViaTor + preferences[NEW_RELAYS_VIA_TOR_KEY] = torSettings.newRelaysViaTor + preferences[TRUSTED_RELAYS_VIA_TOR_KEY] = torSettings.trustedRelaysViaTor + preferences[URL_PREVIEWS_VIA_TOR_KEY] = torSettings.urlPreviewsViaTor + preferences[PROFILE_PICS_VIA_TOR_KEY] = torSettings.profilePicsViaTor + preferences[IMAGES_VIA_TOR_KEY] = torSettings.imagesViaTor + preferences[VIDEOS_VIA_TOR_KEY] = torSettings.videosViaTor + preferences[MONEY_OPERATIONS_VIA_TOR_KEY] = torSettings.moneyOperationsViaTor + preferences[NIP05_VERIFICATIONS_VIA_TOR_KEY] = torSettings.nip05VerificationsViaTor + preferences[MEDIA_UPLOADS_VIA_TOR_KEY] = torSettings.mediaUploadsViaTor + } + } catch (e: Exception) { + if (e is CancellationException) throw e + // Log any errors that occur while reading the DataStore. + Log.e("SharedPreferences") { "Error saving DataStore preferences: ${e.message}" } } - } catch (e: Exception) { - if (e is CancellationException) throw e - // Log any errors that occur while reading the DataStore. - Log.e("SharedPreferences") { "Error saving DataStore preferences: ${e.message}" } } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/UISharedPreferences.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/UISharedPreferences.kt index c3519c0e6..2b673eb36 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/UISharedPreferences.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/UISharedPreferences.kt @@ -49,36 +49,18 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.runBlocking import kotlin.coroutines.cancellation.CancellationException val Context.sharedPreferencesDataStore: DataStore by preferencesDataStore(name = "shared_settings") @Stable class UiSharedPreferences( + prefs: UiSettings, val context: Context, val scope: CoroutineScope, ) { - companion object { - // loads faster when individualized - val UI_THEME = stringPreferencesKey("ui.theme") - val UI_LANGUAGE = stringPreferencesKey("ui.language") - val UI_SHOW_IMAGES = stringPreferencesKey("ui.show_images") - val UI_START_PLAYBACK = stringPreferencesKey("ui.start_playback") - val UI_SHOW_URL_PREVIEW = stringPreferencesKey("ui.show_url_preview") - val UI_HIDE_NAVIGATION_BARS = stringPreferencesKey("ui.hide_navigation_bars") - val UI_SHOW_PROFILE_PICTURES = stringPreferencesKey("ui.show_profile_pictures") - val UI_DONT_SHOW_PUSH_NOTIFICATION_SELECTOR = booleanPreferencesKey("ui.dont_show_push_notification_selector") - val UI_DONT_ASK_FOR_NOTIFICATION_PERMISSIONS = booleanPreferencesKey("ui.dont_ask_for_notification_permissions") - val UI_FEATURE_SET = stringPreferencesKey("ui.feature_set") - val UI_GALLERY_SET = stringPreferencesKey("ui.gallery_set") - } - // UI Preferences. Makes sure to wait for it to avoid blinking themes and language preferences - val value = - runBlocking { - UiSettingsFlow.build(uiPreferences() ?: UiSettings()) - } + val value = UiSettingsFlow.build(prefs) val languageUpdate = value.preferredLanguage @@ -98,68 +80,87 @@ class UiSharedPreferences( value.propertyWatchFlow .debounce(1000) .distinctUntilChanged() - .onEach(::save) - .flowOn(Dispatchers.IO) + .onEach { + save(it, context) + }.flowOn(Dispatchers.IO) .stateIn( scope, SharingStarted.Eagerly, value.toSettings(), ) - suspend fun uiPreferences(): UiSettings? = - try { - // Get the preference flow and take the first value. - val preferences = context.sharedPreferencesDataStore.data.first() - - UiSettings( - theme = preferences[UI_THEME]?.let { ThemeType.valueOf(it) } ?: ThemeType.SYSTEM, - preferredLanguage = preferences[UI_LANGUAGE]?.ifBlank { null }, - automaticallyShowImages = preferences[UI_SHOW_IMAGES]?.let { ConnectivityType.valueOf(it) } ?: ConnectivityType.ALWAYS, - automaticallyStartPlayback = preferences[UI_START_PLAYBACK]?.let { ConnectivityType.valueOf(it) } ?: ConnectivityType.ALWAYS, - automaticallyShowUrlPreview = preferences[UI_SHOW_URL_PREVIEW]?.let { ConnectivityType.valueOf(it) } ?: ConnectivityType.ALWAYS, - automaticallyHideNavigationBars = preferences[UI_HIDE_NAVIGATION_BARS]?.let { BooleanType.valueOf(it) } ?: BooleanType.ALWAYS, - automaticallyShowProfilePictures = preferences[UI_SHOW_PROFILE_PICTURES]?.let { ConnectivityType.valueOf(it) } ?: ConnectivityType.ALWAYS, - dontShowPushNotificationSelector = preferences[UI_DONT_SHOW_PUSH_NOTIFICATION_SELECTOR] ?: false, - dontAskForNotificationPermissions = preferences[UI_DONT_ASK_FOR_NOTIFICATION_PERMISSIONS] ?: false, - featureSet = preferences[UI_FEATURE_SET]?.let { FeatureSetType.valueOf(it) } ?: FeatureSetType.SIMPLIFIED, - gallerySet = preferences[UI_GALLERY_SET]?.let { ProfileGalleryType.valueOf(it) } ?: ProfileGalleryType.CLASSIC, - ) - } catch (e: Exception) { - if (e is CancellationException) throw e - // Log any errors that occur while reading the DataStore. - Log.e("SharedPreferences") { "Error reading DataStore preferences: ${e.message}" } + companion object { + // loads faster when individualized + val UI_THEME = stringPreferencesKey("ui.theme") + val UI_LANGUAGE = stringPreferencesKey("ui.language") + val UI_SHOW_IMAGES = stringPreferencesKey("ui.show_images") + val UI_START_PLAYBACK = stringPreferencesKey("ui.start_playback") + val UI_SHOW_URL_PREVIEW = stringPreferencesKey("ui.show_url_preview") + val UI_HIDE_NAVIGATION_BARS = stringPreferencesKey("ui.hide_navigation_bars") + val UI_SHOW_PROFILE_PICTURES = stringPreferencesKey("ui.show_profile_pictures") + val UI_DONT_SHOW_PUSH_NOTIFICATION_SELECTOR = booleanPreferencesKey("ui.dont_show_push_notification_selector") + val UI_DONT_ASK_FOR_NOTIFICATION_PERMISSIONS = booleanPreferencesKey("ui.dont_ask_for_notification_permissions") + val UI_FEATURE_SET = stringPreferencesKey("ui.feature_set") + val UI_GALLERY_SET = stringPreferencesKey("ui.gallery_set") + suspend fun uiPreferences(context: Context): UiSettings? = try { - val oldVersion = LocalPreferences.loadSharedSettings() - if (oldVersion != null) { - save(oldVersion) - } - oldVersion + // Get the preference flow and take the first value. + val preferences = context.sharedPreferencesDataStore.data.first() + + UiSettings( + theme = preferences[UI_THEME]?.let { ThemeType.valueOf(it) } ?: ThemeType.SYSTEM, + preferredLanguage = preferences[UI_LANGUAGE]?.ifBlank { null }, + automaticallyShowImages = preferences[UI_SHOW_IMAGES]?.let { ConnectivityType.valueOf(it) } ?: ConnectivityType.ALWAYS, + automaticallyStartPlayback = preferences[UI_START_PLAYBACK]?.let { ConnectivityType.valueOf(it) } ?: ConnectivityType.ALWAYS, + automaticallyShowUrlPreview = preferences[UI_SHOW_URL_PREVIEW]?.let { ConnectivityType.valueOf(it) } ?: ConnectivityType.ALWAYS, + automaticallyHideNavigationBars = preferences[UI_HIDE_NAVIGATION_BARS]?.let { BooleanType.valueOf(it) } ?: BooleanType.ALWAYS, + automaticallyShowProfilePictures = preferences[UI_SHOW_PROFILE_PICTURES]?.let { ConnectivityType.valueOf(it) } ?: ConnectivityType.ALWAYS, + dontShowPushNotificationSelector = preferences[UI_DONT_SHOW_PUSH_NOTIFICATION_SELECTOR] ?: false, + dontAskForNotificationPermissions = preferences[UI_DONT_ASK_FOR_NOTIFICATION_PERMISSIONS] ?: false, + featureSet = preferences[UI_FEATURE_SET]?.let { FeatureSetType.valueOf(it) } ?: FeatureSetType.SIMPLIFIED, + gallerySet = preferences[UI_GALLERY_SET]?.let { ProfileGalleryType.valueOf(it) } ?: ProfileGalleryType.CLASSIC, + ) } catch (e: Exception) { if (e is CancellationException) throw e - null - } - } + // Log any errors that occur while reading the DataStore. + Log.e("SharedPreferences") { "Error reading DataStore preferences: ${e.message}" } - suspend fun save(sharedSettings: UiSettings) { - try { - context.sharedPreferencesDataStore.edit { preferences -> - preferences[UI_THEME] = sharedSettings.theme.name - preferences[UI_LANGUAGE] = sharedSettings.preferredLanguage ?: "" - preferences[UI_SHOW_IMAGES] = sharedSettings.automaticallyShowImages.name - preferences[UI_START_PLAYBACK] = sharedSettings.automaticallyStartPlayback.name - preferences[UI_SHOW_URL_PREVIEW] = sharedSettings.automaticallyShowUrlPreview.name - preferences[UI_HIDE_NAVIGATION_BARS] = sharedSettings.automaticallyHideNavigationBars.name - preferences[UI_SHOW_PROFILE_PICTURES] = sharedSettings.automaticallyShowProfilePictures.name - preferences[UI_DONT_SHOW_PUSH_NOTIFICATION_SELECTOR] = sharedSettings.dontShowPushNotificationSelector - preferences[UI_DONT_ASK_FOR_NOTIFICATION_PERMISSIONS] = sharedSettings.dontAskForNotificationPermissions - preferences[UI_FEATURE_SET] = sharedSettings.featureSet.name - preferences[UI_GALLERY_SET] = sharedSettings.gallerySet.name + try { + val oldVersion = LocalPreferences.loadSharedSettings() + if (oldVersion != null) { + save(oldVersion, context) + } + oldVersion + } catch (e: Exception) { + if (e is CancellationException) throw e + null + } + } + + suspend fun save( + sharedSettings: UiSettings, + context: Context, + ) { + try { + context.sharedPreferencesDataStore.edit { preferences -> + preferences[UI_THEME] = sharedSettings.theme.name + preferences[UI_LANGUAGE] = sharedSettings.preferredLanguage ?: "" + preferences[UI_SHOW_IMAGES] = sharedSettings.automaticallyShowImages.name + preferences[UI_START_PLAYBACK] = sharedSettings.automaticallyStartPlayback.name + preferences[UI_SHOW_URL_PREVIEW] = sharedSettings.automaticallyShowUrlPreview.name + preferences[UI_HIDE_NAVIGATION_BARS] = sharedSettings.automaticallyHideNavigationBars.name + preferences[UI_SHOW_PROFILE_PICTURES] = sharedSettings.automaticallyShowProfilePictures.name + preferences[UI_DONT_SHOW_PUSH_NOTIFICATION_SELECTOR] = sharedSettings.dontShowPushNotificationSelector + preferences[UI_DONT_ASK_FOR_NOTIFICATION_PERMISSIONS] = sharedSettings.dontAskForNotificationPermissions + preferences[UI_FEATURE_SET] = sharedSettings.featureSet.name + preferences[UI_GALLERY_SET] = sharedSettings.gallerySet.name + } + } catch (e: Exception) { + if (e is CancellationException) throw e + // Log any errors that occur while reading the DataStore. + Log.e("SharedPreferences") { "Error saving DataStore preferences: ${e.message}" } } - } catch (e: Exception) { - if (e is CancellationException) throw e - // Log any errors that occur while reading the DataStore. - Log.e("SharedPreferences") { "Error saving DataStore preferences: ${e.message}" } } } }