Compare commits

...

6 Commits

Author SHA1 Message Date
Avently 0cc1fc2dbf rename 2024-12-12 19:01:18 +07:00
Avently 7ba960021f changes 2024-12-12 18:57:57 +07:00
Avently 46d7b8ddd9 unused 2024-12-12 18:05:49 +07:00
Avently eb4290ef72 enhancements 2024-12-12 17:49:01 +07:00
Avently 507b0c5f2a Merge branch 'master' into av/multiplatform-saving-prefs 2024-12-12 15:12:33 +07:00
Avently 7122721af7 desktop: saving settings in a safer way to handle process death 2024-08-14 21:50:09 +09:00
9 changed files with 73 additions and 24 deletions
@@ -19,6 +19,8 @@ actual val wallpapersDir: File = File(filesDir.absolutePath + File.separator + "
actual val coreTmpDir: File = File(filesDir.absolutePath + File.separator + "temp_files")
actual val dbAbsolutePrefixPath: String = dataDir.absolutePath + File.separator + "files"
actual val preferencesDir = File(dataDir.absolutePath + File.separator + "shared_prefs")
actual val preferencesTmpDir = File(tmpDir, "prefs_tmp")
.also { it.deleteRecursively() }
actual val chatDatabaseFileName: String = "files_chat.db"
actual val agentDatabaseFileName: String = "files_agent.db"
@@ -3115,8 +3115,12 @@ class SharedPreference<T>(val get: () -> T, set: (T) -> Unit) {
init {
this.set = { value ->
set(value)
_state.value = value
try {
set(value)
_state.value = value
} catch (e: Exception) {
Log.e(TAG, "Error saving settings: ${e.stackTraceToString()}")
}
}
}
}
@@ -3,7 +3,7 @@ package chat.simplex.common.platform
import androidx.compose.runtime.Composable
import chat.simplex.common.model.*
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.helpers.generalGetString
import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR
import com.charleskorn.kaml.*
import kotlinx.serialization.encodeToString
@@ -11,6 +11,8 @@ import java.io.*
import java.net.URI
import java.net.URLDecoder
import java.net.URLEncoder
import java.nio.file.Files
import java.nio.file.StandardCopyOption
expect val dataDir: File
expect val tmpDir: File
@@ -20,6 +22,7 @@ expect val wallpapersDir: File
expect val coreTmpDir: File
expect val dbAbsolutePrefixPath: String
expect val preferencesDir: File
expect val preferencesTmpDir: File
expect val chatDatabaseFileName: String
expect val agentDatabaseFileName: String
@@ -142,16 +145,23 @@ fun readThemeOverrides(): List<ThemeOverrides> {
}
}
private const val lock = "themesWriter"
fun writeThemeOverrides(overrides: List<ThemeOverrides>): Boolean =
try {
File(getPreferenceFilePath("themes.yaml")).outputStream().use {
val string = yaml.encodeToString(ThemesFile(themes = overrides))
it.bufferedWriter().use { it.write(string) }
synchronized(lock) {
try {
val themesFile = File(getPreferenceFilePath("themes.yaml"))
createTmpFileAndDelete(preferencesTmpDir) { tmpFile ->
val string = yaml.encodeToString(ThemesFile(themes = overrides))
tmpFile.bufferedWriter().use { it.write(string) }
themesFile.parentFile.mkdirs()
Files.move(tmpFile.toPath(), themesFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
}
true
} catch (e: Exception) {
Log.e(TAG, "Error writing themes file: ${e.stackTraceToString()}")
false
}
true
} catch (e: Throwable) {
Log.e(TAG, "Error while writing themes file: ${e.stackTraceToString()}")
false
}
private fun fileReady(file: CIFile, filePath: String) =
@@ -102,7 +102,9 @@ object ThemeManager {
}
fun applyTheme(theme: String) {
appPrefs.currentTheme.set(theme)
if (appPrefs.currentTheme.get() != theme) {
appPrefs.currentTheme.set(theme)
}
CurrentColors.value = currentColors(null, null, chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get())
platform.androidSetNightModeIfSupported()
val c = CurrentColors.value.colors
@@ -316,8 +316,9 @@ fun removeWallpaperFile(fileName: String? = null) {
WallpaperType.cachedImages.remove(fileName)
}
fun <T> createTmpFileAndDelete(onCreated: (File) -> T): T {
val tmpFile = File(tmpDir, UUID.randomUUID().toString())
fun <T> createTmpFileAndDelete(dir: File = tmpDir, onCreated: (File) -> T): T {
val tmpFile = File(dir, UUID.randomUUID().toString())
tmpFile.parentFile.mkdirs()
tmpFile.deleteOnExit()
ChatModel.filesToDelete.add(tmpFile)
try {
@@ -16,6 +16,8 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.common.model.ChatController.appPrefs
import chat.simplex.common.model.ChatModel
import chat.simplex.common.model.*
import chat.simplex.common.model.ChatController.setConditionsNotified
import chat.simplex.common.model.ServerOperator.Companion.dummyOperatorInfo
@@ -766,7 +768,9 @@ private val versionDescriptions: List<VersionDescription> = listOf(
private val lastVersion = versionDescriptions.last().version
fun setLastVersionDefault(m: ChatModel) {
m.controller.appPrefs.whatsNewVersion.set(lastVersion)
if (appPrefs.whatsNewVersion.get() != lastVersion) {
appPrefs.whatsNewVersion.set(lastVersion)
}
}
fun shouldShowWhatsNew(m: ChatModel): Boolean {
@@ -913,6 +913,7 @@
<string name="show_slow_api_calls">Show slow API calls</string>
<string name="shutdown_alert_question">Shutdown?</string>
<string name="shutdown_alert_desc">Notifications will stop working until you re-launch the app</string>
<string name="prefs_error_saving_settings">Error saving settings</string>
<!-- Address Items - UserAddressView.kt -->
<string name="create_address">Create address</string>
@@ -17,6 +17,8 @@ actual val wallpapersDir: File = File(dataDir.absolutePath + File.separator + "s
actual val coreTmpDir: File = File(dataDir.absolutePath + File.separator + "tmp")
actual val dbAbsolutePrefixPath: String = dataDir.absolutePath + File.separator + "simplex_v1"
actual val preferencesDir = File(desktopPlatform.configPath).also { it.parentFile.mkdirs() }
actual val preferencesTmpDir = File(desktopPlatform.configPath, "tmp")
.also { it.deleteRecursively() }
actual val chatDatabaseFileName: String = "simplex_v1_chat.db"
actual val agentDatabaseFileName: String = "simplex_v1_agent.db"
@@ -9,15 +9,16 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.*
import chat.simplex.common.simplexWindowState
import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR
import com.jthemedetecor.OsThemeDetector
import com.russhwolf.settings.*
import dev.icerock.moko.resources.ImageResource
import dev.icerock.moko.resources.StringResource
import dev.icerock.moko.resources.desc.desc
import kotlinx.coroutines.*
import java.io.File
import java.nio.file.Files
import java.nio.file.StandardCopyOption
import java.util.*
import java.util.concurrent.Executors
@Composable
actual fun font(name: String, res: String, weight: FontWeight, style: FontStyle): Font =
@@ -37,10 +38,8 @@ catch (e: Exception) {
private val settingsFile =
File(desktopPlatform.configPath + File.separator + "settings.properties")
.also { it.parentFile.mkdirs() }
private val settingsThemesFile =
File(desktopPlatform.configPath + File.separator + "themes.properties")
.also { it.parentFile.mkdirs() }
private val settingsProps =
Properties()
@@ -61,11 +60,35 @@ private val settingsThemesProps =
Properties()
.also { props -> try { settingsThemesFile.reader().use { props.load(it) } } catch (e: Exception) { /**/ } }
private val settingsWriterThread = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
actual val settings: Settings = PropertiesSettings(settingsProps) { CoroutineScope(settingsWriterThread).launch { settingsFile.writer().use { settingsProps.store(it, "") } } }
actual val settingsThemes: Settings = PropertiesSettings(settingsThemesProps) { CoroutineScope(settingsWriterThread).launch { settingsThemesFile.writer().use { settingsThemesProps.store(it, "") } } }
private const val lock = "settingsSaver"
actual val settings: Settings = PropertiesSettings(settingsProps) {
synchronized(lock) {
try {
createTmpFileAndDelete(preferencesTmpDir) { tmpFile ->
tmpFile.writer().use { settingsProps.store(it, "") }
settingsFile.parentFile.mkdirs()
Files.move(tmpFile.toPath(), settingsFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
}
} catch (e: Exception) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.prefs_error_saving_settings), e.stackTraceToString())
throw e
}
}
}
actual val settingsThemes: Settings = PropertiesSettings(settingsThemesProps) {
synchronized(lock) {
try {
createTmpFileAndDelete(preferencesTmpDir) { tmpFile ->
tmpFile.writer().use { settingsThemesProps.store(it, "") }
settingsThemesFile.parentFile.mkdirs()
Files.move(tmpFile.toPath(), settingsThemesFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
}
} catch (e: Exception) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.prefs_error_saving_settings), e.stackTraceToString())
throw e
}
}
}
actual fun windowOrientation(): WindowOrientation =
if (simplexWindowState.windowState.size.width > simplexWindowState.windowState.size.height) {