From b57ca01596e9e89e33a2346dcb1349cce0ed4cea Mon Sep 17 00:00:00 2001 From: denis0001-dev Date: Thu, 25 Dec 2025 15:36:46 +0300 Subject: [PATCH] Remove duplicate AsyncSettings implementation, clean up --- .../kotlin/ru/fromchat/Constants.kt | 18 --- .../kotlin/ru/fromchat/api/Models.kt | 4 +- .../kotlin/ru/fromchat/api/WebSocketData.kt | 5 - .../kotlin/ru/fromchat/core/Settings.kt | 64 ++++++++- .../kotlin/ru/fromchat/core/config/Config.kt | 20 +-- .../kotlin/ru/fromchat/ui/chat/ChatScreen.kt | 9 +- .../fromchat/ui/setup/ServerConfigScreen.kt | 2 +- .../kotlin/ru/fromchat/MainViewController.kt | 3 +- .../com/pr0gramm3r101/utils/Utils.android.kt | 1 + .../utils/settings/AndroidSettings.kt | 11 ++ .../utils/settings/AsyncSettings.android.kt | 128 ------------------ .../utils/settings/SettingsFactory.android.kt | 4 +- .../utils/settings/AsyncSettings.kt | 37 ----- .../pr0gramm3r101/utils/settings/Settings.kt | 2 + .../utils/settings/SettingsFactory.kt | 3 +- .../utils/storage/AuthStorage.kt | 29 ---- .../utils/storage/ServerConfigStorage.kt | 52 ------- .../pr0gramm3r101/utils/storage/Storage.kt | 59 -------- .../utils/settings/AsyncSettings.ios.kt | 99 -------------- .../utils/settings/IosSettings.kt | 6 + .../utils/settings/SettingsFactory.ios.kt | 4 +- 21 files changed, 103 insertions(+), 457 deletions(-) delete mode 100644 app/shared/src/commonMain/kotlin/ru/fromchat/Constants.kt delete mode 100644 utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/settings/AsyncSettings.android.kt delete mode 100644 utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/settings/AsyncSettings.kt delete mode 100644 utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/storage/AuthStorage.kt delete mode 100644 utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/storage/ServerConfigStorage.kt delete mode 100644 utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/storage/Storage.kt delete mode 100644 utils/shared/src/iosMain/kotlin/com/pr0gramm3r101/utils/settings/AsyncSettings.ios.kt diff --git a/app/shared/src/commonMain/kotlin/ru/fromchat/Constants.kt b/app/shared/src/commonMain/kotlin/ru/fromchat/Constants.kt deleted file mode 100644 index 909c8d1..0000000 --- a/app/shared/src/commonMain/kotlin/ru/fromchat/Constants.kt +++ /dev/null @@ -1,18 +0,0 @@ -package ru.fromchat - -import kotlinx.datetime.LocalDateTime -import kotlinx.datetime.format.char - -val DATETIME_FORMAT = LocalDateTime.Format { - day() - char('.') - monthNumber() - char('.') - year() - - char(' ') - - hour() - char(':') - minute() -} \ No newline at end of file diff --git a/app/shared/src/commonMain/kotlin/ru/fromchat/api/Models.kt b/app/shared/src/commonMain/kotlin/ru/fromchat/api/Models.kt index 916145c..6a04866 100644 --- a/app/shared/src/commonMain/kotlin/ru/fromchat/api/Models.kt +++ b/app/shared/src/commonMain/kotlin/ru/fromchat/api/Models.kt @@ -60,9 +60,7 @@ data class Message( val reply_to: Message? = null, val client_message_id: String? = null, val reactions: List? = null -) { - val utcTimestamp = "${timestamp}Z" -} +) @Serializable data class SendMessageRequest( diff --git a/app/shared/src/commonMain/kotlin/ru/fromchat/api/WebSocketData.kt b/app/shared/src/commonMain/kotlin/ru/fromchat/api/WebSocketData.kt index 83f25c3..7297bbf 100644 --- a/app/shared/src/commonMain/kotlin/ru/fromchat/api/WebSocketData.kt +++ b/app/shared/src/commonMain/kotlin/ru/fromchat/api/WebSocketData.kt @@ -35,9 +35,4 @@ data class ReactionUser( data class TypingUpdateData( val userId: Int, val username: String -) - -@Serializable -data class WebSocketAuthMessage( - val token: String ) \ No newline at end of file diff --git a/app/shared/src/commonMain/kotlin/ru/fromchat/core/Settings.kt b/app/shared/src/commonMain/kotlin/ru/fromchat/core/Settings.kt index cd26482..84b2923 100644 --- a/app/shared/src/commonMain/kotlin/ru/fromchat/core/Settings.kt +++ b/app/shared/src/commonMain/kotlin/ru/fromchat/core/Settings.kt @@ -8,19 +8,75 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import ru.fromchat.ui.Theme +/** + * Server configuration data + */ +data class ServerConfigData( + val serverUrl: String, + val httpsEnabled: Boolean +) + object Settings { + private const val MATERIAL_YOU_KEY = "materialYou" + private const val THEME_KEY = "theme" + private const val SERVER_URL_KEY = "server_url" + private const val HTTPS_ENABLED_KEY = "https_enabled" + private val settings = Settings() private fun runIO(block: suspend CoroutineScope.() -> Unit) { CoroutineScope(Dispatchers.IO).launch(block = block) } + private fun serverConfigNotInitialized(): Nothing + = throw IllegalStateException("Server config not initialized") + var materialYou: Boolean - get() = runBlocking { settings.getBoolean("materialYou", true) } - set(value) = runIO { settings.putBoolean("materialYou", value) } + get() = runBlocking { settings.getBoolean(MATERIAL_YOU_KEY, true) } + set(value) = runIO { settings.putBoolean(MATERIAL_YOU_KEY, value) } var theme: Theme - get() = runBlocking { Theme.entries[settings.getInt("theme", Theme.AsSystem.ordinal)] } - set(value) = runIO { settings.putInt("theme", value.ordinal) } + get() = runBlocking { Theme.entries[settings.getInt(THEME_KEY, Theme.AsSystem.ordinal)] } + set(value) = runIO { settings.putInt(THEME_KEY, value.ordinal) } + + var serverUrl: String + get() = runBlocking { + settings.getString(SERVER_URL_KEY).ifEmpty { + serverConfigNotInitialized() + } + } + set(value) = runIO { settings.putString(SERVER_URL_KEY, value) } + + var httpsEnabled: Boolean + get() = runBlocking { + if (settings.contains(HTTPS_ENABLED_KEY)) + settings.getBoolean(HTTPS_ENABLED_KEY, true) + else serverConfigNotInitialized() + } + set(value) = runIO { settings.putBoolean(HTTPS_ENABLED_KEY, value) } + + val hasServerConfig get() = try { + serverUrl + httpsEnabled + true + } catch (_: IllegalStateException) { + false + } + + var serverConfig: ServerConfigData + get() { + if (!hasServerConfig) { + serverUrl = "fromchat.ru" + httpsEnabled = true + + return ServerConfigData("fromchat.ru", true) + } + + return ServerConfigData(serverUrl, httpsEnabled) + } + set(value) { + serverUrl = value.serverUrl + httpsEnabled = value.httpsEnabled + } } diff --git a/app/shared/src/commonMain/kotlin/ru/fromchat/core/config/Config.kt b/app/shared/src/commonMain/kotlin/ru/fromchat/core/config/Config.kt index 9fd35c4..b841e78 100644 --- a/app/shared/src/commonMain/kotlin/ru/fromchat/core/config/Config.kt +++ b/app/shared/src/commonMain/kotlin/ru/fromchat/core/config/Config.kt @@ -1,10 +1,10 @@ package ru.fromchat.core.config -import com.pr0gramm3r101.utils.storage.ServerConfigData -import com.pr0gramm3r101.utils.storage.ServerConfigStorage import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import ru.fromchat.core.ServerConfigData +import ru.fromchat.core.Settings /** * Application configuration @@ -19,18 +19,15 @@ object Config { /** * Initialize configuration by loading from storage */ - suspend fun initialize() { - _serverConfig.value = ServerConfigStorage.getConfig() - - // Set default values and prevent corruption - ServerConfigStorage.getConfig() + fun initialize() { + _serverConfig.value = Settings.serverConfig } /** * Update server configuration */ - suspend fun updateServerConfig(config: ServerConfigData) { - ServerConfigStorage.saveConfig(config) + fun updateServerConfig(config: ServerConfigData) { + Settings.serverConfig = config _serverConfig.value = config } @@ -45,9 +42,4 @@ object Config { */ val webSocketUrl get() = "${if (config.httpsEnabled) "wss" else "ws"}://${config.serverUrl}/api/chat/ws" - - /** - * Checks if server configuration exists - */ - suspend fun hasServerConfig() = ServerConfigStorage.hasConfiguration() } diff --git a/app/shared/src/commonMain/kotlin/ru/fromchat/ui/chat/ChatScreen.kt b/app/shared/src/commonMain/kotlin/ru/fromchat/ui/chat/ChatScreen.kt index cabbe0e..44dcc0f 100644 --- a/app/shared/src/commonMain/kotlin/ru/fromchat/ui/chat/ChatScreen.kt +++ b/app/shared/src/commonMain/kotlin/ru/fromchat/ui/chat/ChatScreen.kt @@ -307,12 +307,13 @@ fun ChatScreen( LazyColumn( state = listState, modifier = Modifier.fillMaxSize(), // Fill the entire space of the Box - verticalArrangement = Arrangement.spacedBy(4.dp, alignment = Alignment.Bottom) + verticalArrangement = Arrangement.spacedBy(4.dp, alignment = Alignment.Bottom), + reverseLayout = true ) { - item { Spacer(Modifier.height(innerPadding.calculateTopPadding())) } // Spacer for TopAppBar + item { Spacer(Modifier.height(innerPadding.calculateBottomPadding())) } // Spacer for chat input items( - items = panelState.messages, + items = panelState.messages.reversed(), key = { it.id } ) { message -> val isAuthor = message.user_id == currentUserId @@ -349,7 +350,7 @@ fun ChatScreen( } } - item { Spacer(Modifier.height(innerPadding.calculateBottomPadding())) } // Spacer for chat input + item { Spacer(Modifier.height(innerPadding.calculateTopPadding())) } // Spacer for TopAppBar } } diff --git a/app/shared/src/commonMain/kotlin/ru/fromchat/ui/setup/ServerConfigScreen.kt b/app/shared/src/commonMain/kotlin/ru/fromchat/ui/setup/ServerConfigScreen.kt index b1afccf..1de15ef 100644 --- a/app/shared/src/commonMain/kotlin/ru/fromchat/ui/setup/ServerConfigScreen.kt +++ b/app/shared/src/commonMain/kotlin/ru/fromchat/ui/setup/ServerConfigScreen.kt @@ -40,13 +40,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.unit.dp import com.pr0gramm3r101.utils.navigateAndWipeBackStack -import com.pr0gramm3r101.utils.storage.ServerConfigData import kotlinx.coroutines.launch import org.jetbrains.compose.resources.stringResource import ru.fromchat.Res import ru.fromchat.api.ApiClient import ru.fromchat.api.WebSocketManager import ru.fromchat.back +import ru.fromchat.core.ServerConfigData import ru.fromchat.core.config.Config import ru.fromchat.https_enabled import ru.fromchat.save_continue diff --git a/app/shared/src/iosMain/kotlin/ru/fromchat/MainViewController.kt b/app/shared/src/iosMain/kotlin/ru/fromchat/MainViewController.kt index ec3d9a8..85ab9c7 100644 --- a/app/shared/src/iosMain/kotlin/ru/fromchat/MainViewController.kt +++ b/app/shared/src/iosMain/kotlin/ru/fromchat/MainViewController.kt @@ -1,7 +1,8 @@ package ru.fromchat -import ru.fromchat.ui.App import androidx.compose.ui.window.ComposeUIViewController +import ru.fromchat.ui.App +@Suppress("unused") fun MainViewController() = ComposeUIViewController { App() } diff --git a/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/Utils.android.kt b/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/Utils.android.kt index b93c4a9..ac858ee 100644 --- a/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/Utils.android.kt +++ b/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/Utils.android.kt @@ -720,6 +720,7 @@ val ActivityInfo.launchIntent get() = Intent().apply { flags = FLAG_ACTIVITY_NEW_TASK } +@SuppressLint("QueryPermissionsNeeded") @RequiresPermission(Manifest.permission.QUERY_ALL_PACKAGES) fun ActivityInfo.isLauncher(context: Context): Boolean { with (context) { diff --git a/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/settings/AndroidSettings.kt b/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/settings/AndroidSettings.kt index fe8d7b2..3ffe097 100644 --- a/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/settings/AndroidSettings.kt +++ b/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/settings/AndroidSettings.kt @@ -93,4 +93,15 @@ class AndroidSettings(): Settings { preferences.remove(stringSetPreferencesKey(key)) } } + + override suspend fun contains(key: String): Boolean { + return dataStore.data.map { preferences -> + preferences.contains(stringPreferencesKey(key)) || + preferences.contains(intPreferencesKey(key)) || + preferences.contains(longPreferencesKey(key)) || + preferences.contains(floatPreferencesKey(key)) || + preferences.contains(booleanPreferencesKey(key)) || + preferences.contains(stringSetPreferencesKey(key)) + }.first() + } } \ No newline at end of file diff --git a/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/settings/AsyncSettings.android.kt b/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/settings/AsyncSettings.android.kt deleted file mode 100644 index 7e5858f..0000000 --- a/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/settings/AsyncSettings.android.kt +++ /dev/null @@ -1,128 +0,0 @@ -package com.pr0gramm3r101.utils.settings - -import androidx.datastore.core.DataStore -import androidx.datastore.preferences.core.Preferences -import androidx.datastore.preferences.core.booleanPreferencesKey -import androidx.datastore.preferences.core.edit -import androidx.datastore.preferences.core.floatPreferencesKey -import androidx.datastore.preferences.core.intPreferencesKey -import androidx.datastore.preferences.core.longPreferencesKey -import androidx.datastore.preferences.core.stringPreferencesKey -import androidx.datastore.preferences.core.stringSetPreferencesKey -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.map - -class AndroidAsyncSettings : AsyncSettings { - private val dataStore: DataStore - get() = DataStoreSingleton.dataStore - - override suspend fun putString(key: String, value: String) { - dataStore.edit { preferences -> - preferences[stringPreferencesKey(key)] = value - } - } - - override suspend fun getString(key: String, default: String): String { - return dataStore.data.map { preferences -> - preferences[stringPreferencesKey(key)] ?: default - }.first() - } - - override suspend fun putInt(key: String, value: Int) { - dataStore.edit { preferences -> - preferences[intPreferencesKey(key)] = value - } - } - - override suspend fun getInt(key: String, default: Int): Int { - return dataStore.data.map { preferences -> - preferences[intPreferencesKey(key)] ?: default - }.first() - } - - override suspend fun putLong(key: String, value: Long) { - dataStore.edit { preferences -> - preferences[longPreferencesKey(key)] = value - } - } - - override suspend fun getLong(key: String, default: Long): Long { - return dataStore.data.map { preferences -> - preferences[longPreferencesKey(key)] ?: default - }.first() - } - - override suspend fun putFloat(key: String, value: Float) { - dataStore.edit { preferences -> - preferences[floatPreferencesKey(key)] = value - } - } - - override suspend fun getFloat(key: String, default: Float): Float { - return dataStore.data.map { preferences -> - preferences[floatPreferencesKey(key)] ?: default - }.first() - } - - override suspend fun putBoolean(key: String, value: Boolean) { - dataStore.edit { preferences -> - preferences[booleanPreferencesKey(key)] = value - } - } - - override suspend fun getBoolean(key: String, default: Boolean): Boolean { - return dataStore.data.map { preferences -> - preferences[booleanPreferencesKey(key)] ?: default - }.first() - } - - override suspend fun putStringSet(key: String, value: Set) { - dataStore.edit { preferences -> - preferences[stringSetPreferencesKey(key)] = value - } - } - - override suspend fun getStringSet(key: String, default: Set): Set { - return dataStore.data.map { preferences -> - preferences[stringSetPreferencesKey(key)] ?: default - }.first() - } - - override suspend fun putStringList(key: String, value: List) { - putStringSet(key, value.toSet()) - } - - override suspend fun getStringList(key: String, default: List): List { - return getStringSet(key, default.toSet()).toList() - } - - override suspend fun remove(key: String) { - dataStore.edit { preferences -> - preferences.remove(stringPreferencesKey(key)) - preferences.remove(intPreferencesKey(key)) - preferences.remove(longPreferencesKey(key)) - preferences.remove(floatPreferencesKey(key)) - preferences.remove(booleanPreferencesKey(key)) - preferences.remove(stringSetPreferencesKey(key)) - } - } - - override suspend fun contains(key: String): Boolean { - return dataStore.data.map { preferences -> - preferences.contains(stringPreferencesKey(key)) || - preferences.contains(intPreferencesKey(key)) || - preferences.contains(longPreferencesKey(key)) || - preferences.contains(floatPreferencesKey(key)) || - preferences.contains(booleanPreferencesKey(key)) || - preferences.contains(stringSetPreferencesKey(key)) - }.first() - } - - override suspend fun clear() { - dataStore.edit { preferences -> - preferences.clear() - } - } -} - -actual val asyncSettings: AsyncSettings = AndroidAsyncSettings() diff --git a/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/settings/SettingsFactory.android.kt b/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/settings/SettingsFactory.android.kt index b8bed87..36270ec 100644 --- a/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/settings/SettingsFactory.android.kt +++ b/utils/shared/src/androidMain/kotlin/com/pr0gramm3r101/utils/settings/SettingsFactory.android.kt @@ -1,3 +1,5 @@ package com.pr0gramm3r101.utils.settings -actual val settings: Settings get() = AndroidSettings() \ No newline at end of file +actual val settings: Settings get() = AndroidSettings() +actual val secureSettings: Settings + get() = TODO("Not yet implemented") \ No newline at end of file diff --git a/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/settings/AsyncSettings.kt b/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/settings/AsyncSettings.kt deleted file mode 100644 index e0d8e27..0000000 --- a/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/settings/AsyncSettings.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.pr0gramm3r101.utils.settings - -/** - * Async version of Settings API using suspend functions - */ -interface AsyncSettings { - suspend fun putString(key: String, value: String) - suspend fun getString(key: String, default: String = ""): String - - suspend fun putInt(key: String, value: Int) - suspend fun getInt(key: String, default: Int = 0): Int - - suspend fun putLong(key: String, value: Long) - suspend fun getLong(key: String, default: Long = 0L): Long - - suspend fun putFloat(key: String, value: Float) - suspend fun getFloat(key: String, default: Float = 0f): Float - - suspend fun putBoolean(key: String, value: Boolean) - suspend fun getBoolean(key: String, default: Boolean = false): Boolean - - suspend fun putStringSet(key: String, value: Set) - suspend fun getStringSet(key: String, default: Set = emptySet()): Set - - suspend fun putStringList(key: String, value: List) - suspend fun getStringList(key: String, default: List = emptyList()): List - - suspend fun remove(key: String) - - suspend fun contains(key: String): Boolean - suspend fun clear() -} - -/** - * Global async settings instance - */ -expect val asyncSettings: AsyncSettings diff --git a/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/settings/Settings.kt b/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/settings/Settings.kt index 19ea352..a72a212 100644 --- a/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/settings/Settings.kt +++ b/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/settings/Settings.kt @@ -30,4 +30,6 @@ interface Settings { suspend fun getStringList(key: String, default: List = emptyList()): List suspend fun remove(key: String) + + suspend fun contains(key: String): Boolean } \ No newline at end of file diff --git a/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/settings/SettingsFactory.kt b/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/settings/SettingsFactory.kt index 7dd5e78..5c77c8b 100644 --- a/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/settings/SettingsFactory.kt +++ b/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/settings/SettingsFactory.kt @@ -1,3 +1,4 @@ package com.pr0gramm3r101.utils.settings -expect val settings: Settings \ No newline at end of file +expect val settings: Settings +expect val secureSettings: Settings \ No newline at end of file diff --git a/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/storage/AuthStorage.kt b/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/storage/AuthStorage.kt deleted file mode 100644 index 0e67139..0000000 --- a/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/storage/AuthStorage.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.pr0gramm3r101.utils.storage - -/** - * Authentication token storage - */ -object AuthStorage { - private val storage = NamespacedStorage("auth") - - suspend fun getToken(): String? { - val token = storage.getString("token") - return token.ifEmpty { null } - } - - suspend fun setToken(token: String?) { - if (token != null) { - storage.putString("token", token) - } else { - storage.remove("token") - } - } - - suspend fun clearToken() { - storage.remove("token") - } - - suspend fun putString(key: String, value: String) = storage.putString(key, value) - suspend fun getString(key: String, default: String = ""): String = storage.getString(key, default) - suspend fun remove(key: String) = storage.remove(key) -} diff --git a/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/storage/ServerConfigStorage.kt b/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/storage/ServerConfigStorage.kt deleted file mode 100644 index 26818a9..0000000 --- a/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/storage/ServerConfigStorage.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.pr0gramm3r101.utils.storage - -/** - * Server configuration data - */ -data class ServerConfigData( - val serverUrl: String, - val httpsEnabled: Boolean -) - -/** - * Server configuration storage - */ -object ServerConfigStorage { - private val storage = NamespacedStorage("server_config") - - private const val SERVER_URL_KEY = "server_url" - private const val HTTPS_ENABLED_KEY = "https_enabled" - - suspend fun getServerUrl() = storage.getString(SERVER_URL_KEY).ifEmpty { null } - - suspend fun setServerUrl(url: String) = storage.putString(SERVER_URL_KEY, url) - - suspend fun getHttpsEnabled() = - if (storage.contains(HTTPS_ENABLED_KEY)) - storage.getBoolean(HTTPS_ENABLED_KEY, true) - else null - - suspend fun setHttpsEnabled(enabled: Boolean) { - storage.putBoolean(HTTPS_ENABLED_KEY, enabled) - } - - suspend fun hasConfiguration() = getServerUrl() != null && getHttpsEnabled() != null - - suspend fun getConfig(): ServerConfigData { - var url = getServerUrl() - var https = getHttpsEnabled() - - if (url == null || https == null) { - url = "fromchat.ru" - https = true - saveConfig(ServerConfigData(url, https)) - } - - return ServerConfigData(url, https) - } - - suspend fun saveConfig(config: ServerConfigData) { - setServerUrl(config.serverUrl) - setHttpsEnabled(config.httpsEnabled) - } -} diff --git a/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/storage/Storage.kt b/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/storage/Storage.kt deleted file mode 100644 index d729012..0000000 --- a/utils/shared/src/commonMain/kotlin/com/pr0gramm3r101/utils/storage/Storage.kt +++ /dev/null @@ -1,59 +0,0 @@ -package com.pr0gramm3r101.utils.storage - -import com.pr0gramm3r101.utils.settings.AsyncSettings -import com.pr0gramm3r101.utils.settings.asyncSettings - -/** - * Generic key-value storage using AsyncSettings - */ -class Storage(private val settings: AsyncSettings = asyncSettings) { - suspend fun putString(key: String, value: String) = settings.putString(key, value) - suspend fun getString(key: String, default: String = ""): String = settings.getString(key, default) - - suspend fun putInt(key: String, value: Int) = settings.putInt(key, value) - suspend fun getInt(key: String, default: Int = 0): Int = settings.getInt(key, default) - - suspend fun putLong(key: String, value: Long) = settings.putLong(key, value) - suspend fun getLong(key: String, default: Long = 0L): Long = settings.getLong(key, default) - - suspend fun putFloat(key: String, value: Float) = settings.putFloat(key, value) - suspend fun getFloat(key: String, default: Float = 0f): Float = settings.getFloat(key, default) - - suspend fun putBoolean(key: String, value: Boolean) = settings.putBoolean(key, value) - suspend fun getBoolean(key: String, default: Boolean = false): Boolean = settings.getBoolean(key, default) - - suspend fun putStringSet(key: String, value: Set) = settings.putStringSet(key, value) - suspend fun getStringSet(key: String, default: Set = emptySet()): Set = settings.getStringSet(key, default) - - suspend fun putStringList(key: String, value: List) = settings.putStringList(key, value) - suspend fun getStringList(key: String, default: List = emptyList()): List = settings.getStringList(key, default) - - suspend fun remove(key: String) = settings.remove(key) - suspend fun contains(key: String): Boolean = settings.contains(key) - suspend fun clear() = settings.clear() -} - -/** - * Namespaced storage for specific features - */ -class NamespacedStorage(private val prefix: String, private val storage: Storage = Storage()) { - private fun key(name: String) = "$prefix:$name" - - suspend fun putString(name: String, value: String) = storage.putString(key(name), value) - suspend fun getString(name: String, default: String = ""): String = storage.getString(key(name), default) - - suspend fun putInt(name: String, value: Int) = storage.putInt(key(name), value) - suspend fun getInt(name: String, default: Int = 0): Int = storage.getInt(key(name), default) - - suspend fun putLong(name: String, value: Long) = storage.putLong(key(name), value) - suspend fun getLong(name: String, default: Long = 0L): Long = storage.getLong(key(name), default) - - suspend fun putFloat(name: String, value: Float) = storage.putFloat(key(name), value) - suspend fun getFloat(name: String, default: Float = 0f): Float = storage.getFloat(key(name), default) - - suspend fun putBoolean(name: String, value: Boolean) = storage.putBoolean(key(name), value) - suspend fun getBoolean(name: String, default: Boolean = false): Boolean = storage.getBoolean(key(name), default) - - suspend fun remove(name: String) = storage.remove(key(name)) - suspend fun contains(name: String): Boolean = storage.contains(key(name)) -} diff --git a/utils/shared/src/iosMain/kotlin/com/pr0gramm3r101/utils/settings/AsyncSettings.ios.kt b/utils/shared/src/iosMain/kotlin/com/pr0gramm3r101/utils/settings/AsyncSettings.ios.kt deleted file mode 100644 index 228a897..0000000 --- a/utils/shared/src/iosMain/kotlin/com/pr0gramm3r101/utils/settings/AsyncSettings.ios.kt +++ /dev/null @@ -1,99 +0,0 @@ -package com.pr0gramm3r101.utils.settings - -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import platform.Foundation.NSBundle -import platform.Foundation.NSUserDefaults - -class IosAsyncSettings : AsyncSettings { - private val defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults - - override suspend fun putString(key: String, value: String): Unit = withContext(Dispatchers.Default) { - defaults.setObject(value, key) - defaults.synchronize() - } - - override suspend fun getString(key: String, default: String): String = withContext(Dispatchers.Default) { - defaults.stringForKey(key) ?: default - } - - override suspend fun putInt(key: String, value: Int): Unit = withContext(Dispatchers.Default) { - defaults.setInteger(value.toLong(), key) - defaults.synchronize() - } - - override suspend fun getInt(key: String, default: Int): Int = withContext(Dispatchers.Default) { - defaults.integerForKey(key).toInt() - } - - override suspend fun putLong(key: String, value: Long): Unit = withContext(Dispatchers.Default) { - defaults.setObject(value, key) - defaults.synchronize() - } - - override suspend fun getLong(key: String, default: Long): Long = withContext(Dispatchers.Default) { - (defaults.objectForKey(key) as? platform.Foundation.NSNumber)?.longValue ?: default - } - - override suspend fun putFloat(key: String, value: Float): Unit = withContext(Dispatchers.Default) { - defaults.setFloat(value, key) - defaults.synchronize() - } - - override suspend fun getFloat(key: String, default: Float): Float = withContext(Dispatchers.Default) { - defaults.floatForKey(key) - } - - override suspend fun putBoolean(key: String, value: Boolean): Unit = withContext(Dispatchers.Default) { - defaults.setBool(value, key) - defaults.synchronize() - } - - override suspend fun getBoolean(key: String, default: Boolean): Boolean = withContext(Dispatchers.Default) { - if (defaults.objectForKey(key) != null) { - defaults.boolForKey(key) - } else { - default - } - } - - override suspend fun putStringSet(key: String, value: Set): Unit = withContext(Dispatchers.Default) { - defaults.setObject(value.toList(), key) - defaults.synchronize() - } - - override suspend fun getStringSet(key: String, default: Set): Set = withContext(Dispatchers.Default) { - val list = defaults.objectForKey(key) as? List<*> ?: return@withContext default - list.filterIsInstance().toSet() - } - - override suspend fun putStringList(key: String, value: List): Unit = withContext(Dispatchers.Default) { - defaults.setObject(value, key) - defaults.synchronize() - } - - override suspend fun getStringList(key: String, default: List): List = withContext(Dispatchers.Default) { - val list = defaults.objectForKey(key) as? List<*> ?: return@withContext default - list.filterIsInstance() - } - - override suspend fun remove(key: String): Unit = withContext(Dispatchers.Default) { - defaults.removeObjectForKey(key) - defaults.synchronize() - } - - override suspend fun contains(key: String): Boolean = withContext(Dispatchers.Default) { - defaults.objectForKey(key) != null - } - - override suspend fun clear(): Unit = withContext(Dispatchers.Default) { - val bundleId = NSBundle.mainBundle.bundleIdentifier ?: "" - val domain = defaults.persistentDomainForName(bundleId) - domain?.keys?.forEach { key -> - defaults.removeObjectForKey(key as String) - } - defaults.synchronize() - } -} - -actual val asyncSettings: AsyncSettings = IosAsyncSettings() \ No newline at end of file diff --git a/utils/shared/src/iosMain/kotlin/com/pr0gramm3r101/utils/settings/IosSettings.kt b/utils/shared/src/iosMain/kotlin/com/pr0gramm3r101/utils/settings/IosSettings.kt index 333b769..90c510a 100644 --- a/utils/shared/src/iosMain/kotlin/com/pr0gramm3r101/utils/settings/IosSettings.kt +++ b/utils/shared/src/iosMain/kotlin/com/pr0gramm3r101/utils/settings/IosSettings.kt @@ -1,5 +1,7 @@ package com.pr0gramm3r101.utils.settings +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import platform.Foundation.NSUserDefaults // TODO fix @@ -42,4 +44,8 @@ class IosSettings : Settings { } override suspend fun remove(key: String) = defaults.removeObjectForKey(key) + + override suspend fun contains(key: String): Boolean = withContext(Dispatchers.Default) { + defaults.objectForKey(key) != null + } } \ No newline at end of file diff --git a/utils/shared/src/iosMain/kotlin/com/pr0gramm3r101/utils/settings/SettingsFactory.ios.kt b/utils/shared/src/iosMain/kotlin/com/pr0gramm3r101/utils/settings/SettingsFactory.ios.kt index 0d678c9..922511a 100644 --- a/utils/shared/src/iosMain/kotlin/com/pr0gramm3r101/utils/settings/SettingsFactory.ios.kt +++ b/utils/shared/src/iosMain/kotlin/com/pr0gramm3r101/utils/settings/SettingsFactory.ios.kt @@ -1,3 +1,5 @@ package com.pr0gramm3r101.utils.settings -actual val settings: Settings get() = IosSettings() \ No newline at end of file +actual val settings: Settings get() = IosSettings() +actual val secureSettings: Settings + get() = TODO("Not yet implemented") \ No newline at end of file