android, desktop: start/stop chat toggle refactoring (#5261)

* android, desktop: start/stop chat toggle refactoring

* changes

* translations

* better

* better

* do not start chat after export, always show run toggle (#5283)

* update heading

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
Stanislav Dmitrenko
2024-11-30 23:33:38 +07:00
committed by GitHub
parent 961bdbfc59
commit 4738286f4e
43 changed files with 236 additions and 446 deletions
@@ -28,6 +28,7 @@ import chat.simplex.common.model.ChatModel.withChats
import chat.simplex.common.platform.*
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.call.*
import chat.simplex.common.views.database.deleteOldChatArchive
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.onboarding.OnboardingStage
import com.jakewharton.processphoenix.ProcessPhoenix
@@ -72,6 +73,7 @@ class SimplexApp: Application(), LifecycleEventObserver {
runMigrations()
tmpDir.deleteRecursively()
tmpDir.mkdir()
deleteOldChatArchive()
// Present screen for continue migration if it wasn't finished yet
if (chatModel.migrationState.value != null) {
+3 -1
View File
@@ -266,7 +266,9 @@ afterEvaluate {
if (isBase) {
baseFormatting[lineId] = fixedLine.formatting(file.absolutePath)
} else if (baseFormatting[lineId] != fixedLine.formatting(file.absolutePath)) {
errors.add("Incorrect formatting in string: $fixedLine \nin ${file.absolutePath}")
errors.add("Incorrect formatting in string: $fixedLine \nin ${file.absolutePath}.\n" +
"If you want to remove non-base translation, search this Regex and replace with empty value in IDE:\n" +
"[ ]*<.*\"${line.substringAfter("\"").substringBefore("\"")}\"[^/]*\\n*.*string>\\n")
}
finalLines.add(fixedLine)
} else if (multiline.isEmpty() && startStringRegex.containsMatchIn(line)) {
@@ -211,6 +211,9 @@ class AppPreferences {
// Note that this situation can only happen if passphrase for the first database is incorrect because, otherwise, backend will re-create second database automatically
val newDatabaseInitialized = mkBoolPreference(SHARED_PREFS_NEW_DATABASE_INITIALIZED, false)
/** after importing new database, this flag will be set and unset only after importing app settings in [initChatController] */
val shouldImportAppSettings = mkBoolPreference(SHARED_PREFS_SHOULD_IMPORT_APP_SETTINGS, false)
val currentTheme = mkStrPreference(SHARED_PREFS_CURRENT_THEME, DefaultTheme.SYSTEM_THEME_NAME)
val systemDarkTheme = mkStrPreference(SHARED_PREFS_SYSTEM_DARK_THEME, DefaultTheme.SIMPLEX.themeName)
val currentThemeIds = mkMapPreference(SHARED_PREFS_CURRENT_THEME_IDs, mapOf(), encode = {
@@ -425,6 +428,7 @@ class AppPreferences {
private const val SHARED_PREFS_INITIALIZATION_VECTOR_SELF_DESTRUCT_PASSPHRASE = "InitializationVectorSelfDestructPassphrase"
private const val SHARED_PREFS_ENCRYPTION_STARTED_AT = "EncryptionStartedAt"
private const val SHARED_PREFS_NEW_DATABASE_INITIALIZED = "NewDatabaseInitialized"
private const val SHARED_PREFS_SHOULD_IMPORT_APP_SETTINGS = "ShouldImportAppSettings"
private const val SHARED_PREFS_CONFIRM_DB_UPGRADES = "ConfirmDBUpgrades"
private const val SHARED_PREFS_ONE_HAND_UI = "OneHandUI"
private const val SHARED_PREFS_SELF_DESTRUCT = "LocalAuthenticationSelfDestruct"
@@ -6909,7 +6913,7 @@ data class AppSettings(
uiDarkColorScheme?.let { def.systemDarkTheme.set(it) }
uiCurrentThemeIds?.let { def.currentThemeIds.set(it) }
uiThemes?.let { def.themeOverrides.set(it.skipDuplicates()) }
oneHandUI?.let { def.oneHandUI.set(if (appPlatform.isAndroid) it else false) }
oneHandUI?.let { def.oneHandUI.set(it) }
}
companion object {
@@ -119,6 +119,15 @@ suspend fun initChatController(useKey: String? = null, confirmMigrations: Migrat
val user = chatController.apiGetActiveUser(null)
chatModel.currentUser.value = user
chatModel.conditions.value = chatController.getServerOperators(null) ?: ServerOperatorConditionsDetail.empty
if (appPrefs.shouldImportAppSettings.get()) {
try {
val appSettings = controller.apiGetAppSettings(AppSettings.current.prepareForExport())
appSettings.importIntoApp()
appPrefs.shouldImportAppSettings.set(false)
} catch (e: Exception) {
Log.e(TAG, "Error while importing app settings: " + e.stackTraceToString())
}
}
if (user == null) {
chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.set(true)
chatModel.currentUser.value = null
@@ -26,7 +26,7 @@ expect val agentDatabaseFileName: String
/**
* This is used only for temporary storing db archive for export.
* Providing [tmpDir] instead crashes the app. Check db export before moving from this path to something else
* Providing [tmpDir] instead crashes the app on Android (only). Check db export before moving from this path to something else
* */
expect val databaseExportDir: File
@@ -1,108 +0,0 @@
package chat.simplex.common.views.database
import SectionBottomSpacer
import SectionTextFooter
import SectionView
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import chat.simplex.common.model.ChatModel
import chat.simplex.common.platform.*
import chat.simplex.common.ui.theme.SimpleXTheme
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.usersettings.*
import chat.simplex.res.MR
import kotlinx.datetime.*
import java.io.File
import java.net.URI
import java.text.SimpleDateFormat
import java.util.*
@Composable
fun ChatArchiveView(m: ChatModel, title: String, archiveName: String, archiveTime: Instant) {
val archivePath = filesDir.absolutePath + File.separator + archiveName
val saveArchiveLauncher = rememberFileChooserLauncher(false) { to: URI? ->
if (to != null) {
copyFileToFile(File(archivePath), to) {}
}
}
ChatArchiveLayout(
title,
archiveTime,
saveArchive = { withLongRunningApi { saveArchiveLauncher.launch(archivePath.substringAfterLast(File.separator)) }},
deleteArchiveAlert = { deleteArchiveAlert(m, archivePath) }
)
}
@Composable
fun ChatArchiveLayout(
title: String,
archiveTime: Instant,
saveArchive: () -> Unit,
deleteArchiveAlert: () -> Unit
) {
ColumnWithScrollBar {
AppBarTitle(title)
SectionView(stringResource(MR.strings.chat_archive_section)) {
SettingsActionItem(
painterResource(MR.images.ic_ios_share),
stringResource(MR.strings.save_archive),
saveArchive,
textColor = MaterialTheme.colors.primary,
iconColor = MaterialTheme.colors.primary,
)
SettingsActionItem(
painterResource(MR.images.ic_delete),
stringResource(MR.strings.delete_archive),
deleteArchiveAlert,
textColor = Color.Red,
iconColor = Color.Red,
)
}
val archiveTs = SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z", Locale.US).format(Date.from(archiveTime.toJavaInstant()))
SectionTextFooter(
String.format(generalGetString(MR.strings.archive_created_on_ts), archiveTs)
)
SectionBottomSpacer()
}
}
private fun deleteArchiveAlert(m: ChatModel, archivePath: String) {
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.delete_chat_archive_question),
confirmText = generalGetString(MR.strings.delete_verb),
onConfirm = {
val fileDeleted = File(archivePath).delete()
if (fileDeleted) {
m.controller.appPrefs.chatArchiveName.set(null)
m.controller.appPrefs.chatArchiveTime.set(null)
ModalManager.start.closeModal()
} else {
Log.e(TAG, "deleteArchiveAlert delete() error")
}
},
destructive = true,
)
}
@Preview/*(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
name = "Dark Mode"
)*/
@Composable
fun PreviewChatArchiveLayout() {
SimpleXTheme {
ChatArchiveLayout(
"New database archive",
archiveTime = Clock.System.now(),
saveArchive = {},
deleteArchiveAlert = {}
)
}
}
@@ -48,6 +48,7 @@ fun DatabaseEncryptionView(m: ChatModel, migration: Boolean) {
val currentKey = remember { mutableStateOf(if (initialRandomDBPassphrase.value) DatabaseUtils.ksDatabasePassword.get() ?: "" else "") }
val newKey = rememberSaveable { mutableStateOf("") }
val confirmNewKey = rememberSaveable { mutableStateOf("") }
val chatLastStart = remember { mutableStateOf(appPrefs.chatLastStart.get()) }
Box(
Modifier.fillMaxSize(),
@@ -63,8 +64,9 @@ fun DatabaseEncryptionView(m: ChatModel, migration: Boolean) {
progressIndicator,
migration,
onConfirmEncrypt = {
withLongRunningApi {
encryptDatabase(
// it will try to stop and start the chat in case of: non-migration && successful encryption. In migration the chat will remain stopped
stopChatRunBlockStartChat(migration, chatLastStart, progressIndicator, ) {
val success = encryptDatabase(
currentKey = currentKey,
newKey = newKey,
confirmNewKey = confirmNewKey,
@@ -74,6 +76,7 @@ fun DatabaseEncryptionView(m: ChatModel, migration: Boolean) {
progressIndicator = progressIndicator,
migration = migration
)
success && !migration
}
}
)
@@ -306,7 +309,6 @@ private fun operationEnded(m: ChatModel, progressIndicator: MutableState<Boolean
alert.invoke()
}
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun PassphraseField(
key: MutableState<String>,
@@ -26,7 +26,6 @@ import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.usersettings.*
import chat.simplex.common.platform.*
import chat.simplex.res.MR
import kotlinx.coroutines.sync.withLock
import kotlinx.datetime.*
import java.io.*
import java.net.URI
@@ -36,18 +35,14 @@ import java.util.*
import kotlin.collections.ArrayList
@Composable
fun DatabaseView(
m: ChatModel,
showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit)
) {
val currentRemoteHost by remember { chatModel.currentRemoteHost }
fun DatabaseView() {
val m = chatModel
val progressIndicator = remember { mutableStateOf(false) }
val prefs = m.controller.appPrefs
val useKeychain = remember { mutableStateOf(prefs.storeDBPassphrase.get()) }
val chatArchiveName = remember { mutableStateOf(prefs.chatArchiveName.get()) }
val chatArchiveTime = remember { mutableStateOf(prefs.chatArchiveTime.get()) }
val chatLastStart = remember { mutableStateOf(prefs.chatLastStart.get()) }
val chatArchiveFile = remember { mutableStateOf<String?>(null) }
val stopped = remember { m.chatRunning }.value == false
val saveArchiveLauncher = rememberFileChooserLauncher(false) { to: URI? ->
val file = chatArchiveFile.value
if (file != null && to != null) {
@@ -59,8 +54,11 @@ fun DatabaseView(
val appFilesCountAndSize = remember { mutableStateOf(directoryFileCountAndSize(appFilesDir.absolutePath)) }
val importArchiveLauncher = rememberFileChooserLauncher(true) { to: URI? ->
if (to != null) {
importArchiveAlert(m, to, appFilesCountAndSize, progressIndicator) {
startChat(m, chatLastStart, m.chatDbChanged)
importArchiveAlert {
stopChatRunBlockStartChat(stopped, chatLastStart, progressIndicator) {
importArchive(to, appFilesCountAndSize, progressIndicator)
true
}
}
}
}
@@ -71,27 +69,40 @@ fun DatabaseView(
val user = m.currentUser.value
val rhId = user?.remoteHostId
DatabaseLayout(
currentRemoteHost = currentRemoteHost,
progressIndicator.value,
remember { m.chatRunning }.value != false,
m.chatDbChanged.value,
stopped,
useKeychain.value,
m.chatDbEncrypted.value,
m.controller.appPrefs.storeDBPassphrase.state.value,
m.controller.appPrefs.initialRandomDBPassphrase,
importArchiveLauncher,
chatArchiveName,
chatArchiveTime,
chatLastStart,
appFilesCountAndSize,
chatItemTTL,
user,
m.users,
startChat = { startChat(m, chatLastStart, m.chatDbChanged, progressIndicator) },
stopChatAlert = { stopChatAlert(m, progressIndicator) },
exportArchive = { exportArchive(m, progressIndicator, chatArchiveName, chatArchiveTime, chatArchiveFile, saveArchiveLauncher) },
deleteChatAlert = { deleteChatAlert(m, progressIndicator) },
deleteAppFilesAndMedia = { deleteFilesAndMediaAlert(appFilesCountAndSize) },
exportArchive = {
stopChatRunBlockStartChat(stopped, chatLastStart, progressIndicator) {
exportArchive(m, progressIndicator, chatArchiveFile, saveArchiveLauncher)
}
},
deleteChatAlert = {
deleteChatAlert {
stopChatRunBlockStartChat(stopped, chatLastStart, progressIndicator) {
deleteChat(m, progressIndicator)
true
}
}
},
deleteAppFilesAndMedia = {
deleteFilesAndMediaAlert {
stopChatRunBlockStartChat(stopped, chatLastStart, progressIndicator) {
deleteFiles(appFilesCountAndSize)
true
}
}
},
onChatItemTTLSelected = {
val oldValue = chatItemTTL.value
chatItemTTL.value = it
@@ -101,7 +112,6 @@ fun DatabaseView(
setCiTTL(m, rhId, chatItemTTL, progressIndicator, appFilesCountAndSize)
}
},
showSettingsModal,
disconnectAllHosts = {
val connected = chatModel.remoteHosts.filter { it.sessionState is RemoteHostSessionState.Connected }
connected.forEachIndexed { index, h ->
@@ -128,18 +138,13 @@ fun DatabaseView(
@Composable
fun DatabaseLayout(
currentRemoteHost: RemoteHostInfo?,
progressIndicator: Boolean,
runChat: Boolean,
chatDbChanged: Boolean,
stopped: Boolean,
useKeyChain: Boolean,
chatDbEncrypted: Boolean?,
passphraseSaved: Boolean,
initialRandomDBPassphrase: SharedPreference<Boolean>,
importArchiveLauncher: FileChooserLauncher,
chatArchiveName: MutableState<String?>,
chatArchiveTime: MutableState<Instant?>,
chatLastStart: MutableState<Instant?>,
appFilesCountAndSize: MutableState<Pair<Int, Long>>,
chatItemTTL: MutableState<ChatItemTTL>,
currentUser: User?,
@@ -150,11 +155,9 @@ fun DatabaseLayout(
deleteChatAlert: () -> Unit,
deleteAppFilesAndMedia: () -> Unit,
onChatItemTTLSelected: (ChatItemTTL) -> Unit,
showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit),
disconnectAllHosts: () -> Unit,
) {
val stopped = !runChat
val operationsDisabled = (!stopped || progressIndicator) && !chatModel.desktopNoUserNoRemote
val operationsDisabled = progressIndicator && !chatModel.desktopNoUserNoRemote
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.your_chat_database))
@@ -178,13 +181,16 @@ fun DatabaseLayout(
}
val toggleEnabled = remember { chatModel.remoteHosts }.none { it.sessionState is RemoteHostSessionState.Connected }
if (chatModel.localUserCreated.value == true) {
// still show the toggle in case database was stopped when the user opened this screen because it can be in the following situations:
// - database was stopped after migration and the app relaunched
// - something wrong happened with database operations and the database couldn't be launched when it should
SectionView(stringResource(MR.strings.run_chat_section)) {
if (!toggleEnabled) {
SectionItemView(disconnectAllHosts) {
Text(generalGetString(MR.strings.disconnect_remote_hosts), Modifier.fillMaxWidth(), color = WarningOrange)
}
}
RunChatSetting(runChat, stopped, toggleEnabled && !progressIndicator, startChat, stopChatAlert)
RunChatSetting(stopped, toggleEnabled && !progressIndicator, startChat, stopChatAlert)
}
SectionTextFooter(
if (stopped) {
@@ -207,7 +213,7 @@ fun DatabaseLayout(
if (unencrypted) painterResource(MR.images.ic_lock_open_right) else if (useKeyChain) painterResource(MR.images.ic_vpn_key_filled)
else painterResource(MR.images.ic_lock),
stringResource(MR.strings.database_passphrase),
click = showSettingsModal() { DatabaseEncryptionView(it, false) },
click = { ModalManager.start.showModal { DatabaseEncryptionView(chatModel, false) } },
iconColor = if (unencrypted || (appPlatform.isDesktop && passphraseSaved)) WarningOrange else MaterialTheme.colors.secondary,
disabled = operationsDisabled
)
@@ -225,6 +231,9 @@ fun DatabaseLayout(
click = {
if (initialRandomDBPassphrase.get()) {
exportProhibitedAlert()
ModalManager.start.showModal {
DatabaseEncryptionView(chatModel, false)
}
} else {
exportArchive()
}
@@ -241,18 +250,6 @@ fun DatabaseLayout(
iconColor = Color.Red,
disabled = operationsDisabled
)
val chatArchiveNameVal = chatArchiveName.value
val chatArchiveTimeVal = chatArchiveTime.value
val chatLastStartVal = chatLastStart.value
if (chatArchiveNameVal != null && chatArchiveTimeVal != null && chatLastStartVal != null) {
val title = chatArchiveTitle(chatArchiveTimeVal, chatLastStartVal)
SettingsActionItem(
painterResource(MR.images.ic_inventory_2),
title,
click = showSettingsModal { ChatArchiveView(it, title, chatArchiveNameVal, chatArchiveTimeVal) },
disabled = operationsDisabled
)
}
SettingsActionItem(
painterResource(MR.images.ic_delete_forever),
stringResource(MR.strings.delete_database),
@@ -333,7 +330,6 @@ private fun TtlOptions(current: State<ChatItemTTL>, enabled: State<Boolean>, onS
@Composable
fun RunChatSetting(
runChat: Boolean,
stopped: Boolean,
enabled: Boolean,
startChat: () -> Unit,
@@ -346,7 +342,7 @@ fun RunChatSetting(
iconColor = if (stopped) Color.Red else MaterialTheme.colors.primary,
) {
DefaultSwitch(
checked = runChat,
checked = !stopped,
onCheckedChange = { runChatSwitch ->
if (runChatSwitch) {
startChat()
@@ -359,12 +355,12 @@ fun RunChatSetting(
}
}
@Composable
fun chatArchiveTitle(chatArchiveTime: Instant, chatLastStart: Instant): String {
return stringResource(if (chatArchiveTime < chatLastStart) MR.strings.old_database_archive else MR.strings.new_database_archive)
}
fun startChat(m: ChatModel, chatLastStart: MutableState<Instant?>, chatDbChanged: MutableState<Boolean>, progressIndicator: MutableState<Boolean>? = null) {
fun startChat(
m: ChatModel,
chatLastStart: MutableState<Instant?>,
chatDbChanged: MutableState<Boolean>,
progressIndicator: MutableState<Boolean>? = null
) {
withLongRunningApi {
try {
progressIndicator?.value = true
@@ -469,6 +465,40 @@ suspend fun stopChatAsync(m: ChatModel) {
controller.appPrefs.chatStopped.set(true)
}
fun stopChatRunBlockStartChat(
stopped: Boolean,
chatLastStart: MutableState<Instant?>,
progressIndicator: MutableState<Boolean>,
block: suspend () -> Boolean
) {
// if the chat was running, the sequence is: stop chat, run block, start chat.
// Otherwise, just run block and do nothing - the toggle will be visible anyway and the user can start the chat or not
if (stopped) {
withLongRunningApi {
try {
block()
} catch (e: Throwable) {
Log.e(TAG, e.stackTraceToString())
}
}
} else {
authStopChat(chatModel, progressIndicator) {
withLongRunningApi {
// if it throws, let's start chat again anyway
val canStart = try {
block()
} catch (e: Throwable) {
Log.e(TAG, e.stackTraceToString())
true
}
if (canStart) {
startChat(chatModel, chatLastStart, chatModel.chatDbChanged, progressIndicator)
}
}
}
}
}
suspend fun deleteChatAsync(m: ChatModel) {
m.controller.apiDeleteStorage()
DatabaseUtils.ksDatabasePassword.remove()
@@ -511,47 +541,42 @@ fun deleteChatDatabaseFilesAndState() {
ntfManager.cancelAllNotifications()
}
private fun exportArchive(
private suspend fun exportArchive(
m: ChatModel,
progressIndicator: MutableState<Boolean>,
chatArchiveName: MutableState<String?>,
chatArchiveTime: MutableState<Instant?>,
chatArchiveFile: MutableState<String?>,
saveArchiveLauncher: FileChooserLauncher
) {
): Boolean {
progressIndicator.value = true
withLongRunningApi {
try {
val (archiveFile, archiveErrors) = exportChatArchive(m, null, chatArchiveName, chatArchiveTime, chatArchiveFile)
chatArchiveFile.value = archiveFile
if (archiveErrors.isEmpty()) {
saveArchiveLauncher.launch(archiveFile.substringAfterLast(File.separator))
} else {
showArchiveExportedWithErrorsAlert(generalGetString(MR.strings.chat_database_exported_save), archiveErrors) {
withLongRunningApi {
saveArchiveLauncher.launch(archiveFile.substringAfterLast(File.separator))
}
try {
val (archiveFile, archiveErrors) = exportChatArchive(m, null, chatArchiveFile)
chatArchiveFile.value = archiveFile
if (archiveErrors.isEmpty()) {
saveArchiveLauncher.launch(archiveFile.substringAfterLast(File.separator))
} else {
showArchiveExportedWithErrorsAlert(generalGetString(MR.strings.chat_database_exported_save), archiveErrors) {
withLongRunningApi {
saveArchiveLauncher.launch(archiveFile.substringAfterLast(File.separator))
}
}
progressIndicator.value = false
} catch (e: Error) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_exporting_chat_database), e.toString())
progressIndicator.value = false
}
progressIndicator.value = false
} catch (e: Throwable) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_exporting_chat_database), e.toString())
progressIndicator.value = false
}
return false
}
suspend fun exportChatArchive(
m: ChatModel,
storagePath: File?,
chatArchiveName: MutableState<String?>,
chatArchiveTime: MutableState<Instant?>,
chatArchiveFile: MutableState<String?>
): Pair<String, List<ArchiveError>> {
val archiveTime = Clock.System.now()
val ts = SimpleDateFormat("yyyy-MM-dd'T'HHmmss", Locale.US).format(Date.from(archiveTime.toJavaInstant()))
val archiveName = "simplex-chat.$ts.zip"
val archivePath = "${(storagePath ?: filesDir).absolutePath}${File.separator}$archiveName"
val archivePath = "${(storagePath ?: databaseExportDir).absolutePath}${File.separator}$archiveName"
val config = ArchiveConfig(archivePath, parentTempDirectory = databaseExportDir.toString())
// Settings should be saved before changing a passphrase, otherwise the database needs to be migrated first
if (!m.chatDbChanged.value) {
@@ -560,42 +585,37 @@ suspend fun exportChatArchive(
wallpapersDir.mkdirs()
val archiveErrors = m.controller.apiExportArchive(config)
if (storagePath == null) {
deleteOldArchive(m)
deleteOldChatArchive()
m.controller.appPrefs.chatArchiveName.set(archiveName)
m.controller.appPrefs.chatArchiveTime.set(archiveTime)
}
chatArchiveName.value = archiveName
chatArchiveTime.value = archiveTime
chatArchiveFile.value = archivePath
return archivePath to archiveErrors
}
private fun deleteOldArchive(m: ChatModel) {
val chatArchiveName = m.controller.appPrefs.chatArchiveName.get()
// Deprecated. Remove in the end of 2025. All unused archives should be deleted for the most users til then.
/** Remove [AppPreferences.chatArchiveName] and [AppPreferences.chatArchiveTime] as well */
fun deleteOldChatArchive() {
val chatArchiveName = chatModel.controller.appPrefs.chatArchiveName.get()
if (chatArchiveName != null) {
val file = File("${filesDir.absolutePath}${File.separator}$chatArchiveName")
val fileDeleted = file.delete()
if (fileDeleted) {
m.controller.appPrefs.chatArchiveName.set(null)
m.controller.appPrefs.chatArchiveTime.set(null)
val file1 = File("${filesDir.absolutePath}${File.separator}$chatArchiveName")
val file2 = File("${databaseExportDir.absolutePath}${File.separator}$chatArchiveName")
val fileDeleted = file1.delete() || file2.delete()
if (fileDeleted || (!file1.exists() && !file2.exists())) {
chatModel.controller.appPrefs.chatArchiveName.set(null)
chatModel.controller.appPrefs.chatArchiveTime.set(null)
} else {
Log.e(TAG, "deleteOldArchive file.delete() error")
}
}
}
private fun importArchiveAlert(
m: ChatModel,
importedArchiveURI: URI,
appFilesCountAndSize: MutableState<Pair<Int, Long>>,
progressIndicator: MutableState<Boolean>,
startChat: () -> Unit,
) {
private fun importArchiveAlert(onConfirm: () -> Unit, ) {
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.import_database_question),
text = generalGetString(MR.strings.your_current_chat_database_will_be_deleted_and_replaced_with_the_imported_one),
confirmText = generalGetString(MR.strings.import_database_confirmation),
onConfirm = { importArchive(m, importedArchiveURI, appFilesCountAndSize, progressIndicator, startChat) },
onConfirm = onConfirm,
destructive = true,
)
}
@@ -622,52 +642,51 @@ private fun archiveErrorsText(errs: List<ArchiveError>): String = "\n" + errs.ma
}
}.joinToString(separator = "\n")
private fun importArchive(
m: ChatModel,
suspend fun importArchive(
importedArchiveURI: URI,
appFilesCountAndSize: MutableState<Pair<Int, Long>>,
progressIndicator: MutableState<Boolean>,
startChat: () -> Unit,
) {
): Boolean {
val m = chatModel
progressIndicator.value = true
val archivePath = saveArchiveFromURI(importedArchiveURI)
if (archivePath != null) {
withLongRunningApi {
try {
m.controller.apiDeleteStorage()
wallpapersDir.mkdirs()
try {
m.controller.apiDeleteStorage()
wallpapersDir.mkdirs()
try {
val config = ArchiveConfig(archivePath, parentTempDirectory = databaseExportDir.toString())
val archiveErrors = m.controller.apiImportArchive(config)
DatabaseUtils.ksDatabasePassword.remove()
appFilesCountAndSize.value = directoryFileCountAndSize(appFilesDir.absolutePath)
if (archiveErrors.isEmpty()) {
operationEnded(m, progressIndicator) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.chat_database_imported), text = generalGetString(MR.strings.restart_the_app_to_use_imported_chat_database))
}
if (chatModel.localUserCreated.value == false) {
chatModel.chatRunning.value = false
startChat()
}
} else {
operationEnded(m, progressIndicator) {
showArchiveImportedWithErrorsAlert(archiveErrors)
}
}
} catch (e: Error) {
val config = ArchiveConfig(archivePath, parentTempDirectory = databaseExportDir.toString())
val archiveErrors = m.controller.apiImportArchive(config)
appPrefs.shouldImportAppSettings.set(true)
DatabaseUtils.ksDatabasePassword.remove()
appFilesCountAndSize.value = directoryFileCountAndSize(appFilesDir.absolutePath)
if (archiveErrors.isEmpty()) {
operationEnded(m, progressIndicator) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_importing_database), e.toString())
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.chat_database_imported), text = generalGetString(MR.strings.restart_the_app_to_use_imported_chat_database))
}
if (chatModel.localUserCreated.value == false) {
chatModel.chatRunning.value = false
}
} else {
operationEnded(m, progressIndicator) {
showArchiveImportedWithErrorsAlert(archiveErrors)
}
}
return true
} catch (e: Error) {
operationEnded(m, progressIndicator) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_deleting_database), e.toString())
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_importing_database), e.toString())
}
} finally {
File(archivePath).delete()
}
} catch (e: Error) {
operationEnded(m, progressIndicator) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_deleting_database), e.toString())
}
} finally {
File(archivePath).delete()
}
}
return false
}
private fun saveArchiveFromURI(importedArchiveURI: URI): String? {
@@ -689,28 +708,26 @@ private fun saveArchiveFromURI(importedArchiveURI: URI): String? {
}
}
private fun deleteChatAlert(m: ChatModel, progressIndicator: MutableState<Boolean>) {
private fun deleteChatAlert(onConfirm: () -> Unit) {
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.delete_chat_profile_question),
text = generalGetString(MR.strings.delete_chat_profile_action_cannot_be_undone_warning),
confirmText = generalGetString(MR.strings.delete_verb),
onConfirm = { deleteChat(m, progressIndicator) },
onConfirm = onConfirm,
destructive = true,
)
}
private fun deleteChat(m: ChatModel, progressIndicator: MutableState<Boolean>) {
private suspend fun deleteChat(m: ChatModel, progressIndicator: MutableState<Boolean>) {
progressIndicator.value = true
withBGApi {
try {
deleteChatAsync(m)
operationEnded(m, progressIndicator) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.chat_database_deleted), generalGetString(MR.strings.restart_the_app_to_create_a_new_chat_profile))
}
} catch (e: Error) {
operationEnded(m, progressIndicator) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_deleting_database), e.toString())
}
try {
deleteChatAsync(m)
operationEnded(m, progressIndicator) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.chat_database_deleted), generalGetString(MR.strings.restart_the_app_to_create_a_new_chat_profile))
}
} catch (e: Error) {
operationEnded(m, progressIndicator) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_deleting_database), e.toString())
}
}
}
@@ -759,12 +776,12 @@ private fun afterSetCiTTL(
}
}
private fun deleteFilesAndMediaAlert(appFilesCountAndSize: MutableState<Pair<Int, Long>>) {
private fun deleteFilesAndMediaAlert(onConfirm: () -> Unit) {
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.delete_files_and_media_question),
text = generalGetString(MR.strings.delete_files_and_media_desc),
confirmText = generalGetString(MR.strings.delete_verb),
onConfirm = { deleteFiles(appFilesCountAndSize) },
onConfirm = onConfirm,
destructive = true
)
}
@@ -789,18 +806,13 @@ private fun operationEnded(m: ChatModel, progressIndicator: MutableState<Boolean
fun PreviewDatabaseLayout() {
SimpleXTheme {
DatabaseLayout(
currentRemoteHost = null,
progressIndicator = false,
runChat = true,
chatDbChanged = false,
stopped = false,
useKeyChain = false,
chatDbEncrypted = false,
passphraseSaved = false,
initialRandomDBPassphrase = SharedPreference({ true }, {}),
importArchiveLauncher = rememberFileChooserLauncher(true) {},
chatArchiveName = remember { mutableStateOf("dummy_archive") },
chatArchiveTime = remember { mutableStateOf(Clock.System.now()) },
chatLastStart = remember { mutableStateOf(Clock.System.now()) },
appFilesCountAndSize = remember { mutableStateOf(0 to 0L) },
chatItemTTL = remember { mutableStateOf(ChatItemTTL.None) },
currentUser = User.sampleData,
@@ -810,7 +822,6 @@ fun PreviewDatabaseLayout() {
exportArchive = {},
deleteChatAlert = {},
deleteAppFilesAndMedia = {},
showSettingsModal = { {} },
onChatItemTTLSelected = {},
disconnectAllHosts = {},
)
@@ -481,7 +481,7 @@ private fun MutableState<MigrationFromState>.exportArchive() {
withLongRunningApi {
try {
getMigrationTempFilesDirectory().mkdir()
val (archivePath, archiveErrors) = exportChatArchive(chatModel, getMigrationTempFilesDirectory(), mutableStateOf(""), mutableStateOf(Instant.DISTANT_PAST), mutableStateOf(""))
val (archivePath, archiveErrors) = exportChatArchive(chatModel, getMigrationTempFilesDirectory(), mutableStateOf(""))
if (archiveErrors.isEmpty()) {
uploadArchive(archivePath)
} else {
@@ -35,6 +35,7 @@ import kotlinx.datetime.Clock
import kotlinx.datetime.toJavaInstant
import kotlinx.serialization.*
import java.io.File
import java.net.URI
import java.text.SimpleDateFormat
import java.util.*
import kotlin.math.max
@@ -180,7 +181,7 @@ private fun ModalData.SectionByState(
) {
when (val s = migrationState.value) {
null -> {}
is MigrationToState.PasteOrScanLink -> migrationState.PasteOrScanLinkView()
is MigrationToState.PasteOrScanLink -> migrationState.PasteOrScanLinkView(close)
is MigrationToState.Onion -> OnionView(s.link, s.legacySocksProxy, s.networkProxy, s.hostMode, s.requiredHostMode, migrationState)
is MigrationToState.DatabaseInit -> migrationState.DatabaseInitView(s.link, tempDatabaseFile, s.netCfg, s.networkProxy)
is MigrationToState.LinkDownloading -> migrationState.LinkDownloadingView(s.link, s.ctrl, s.user, s.archivePath, tempDatabaseFile, chatReceiver, s.netCfg, s.networkProxy)
@@ -195,18 +196,30 @@ private fun ModalData.SectionByState(
}
@Composable
private fun MutableState<MigrationToState?>.PasteOrScanLinkView() {
if (appPlatform.isAndroid) {
SectionView(stringResource(MR.strings.scan_QR_code).replace('\n', ' ').uppercase()) {
QRCodeScanner(showQRCodeScanner = remember { mutableStateOf(true) }) { text ->
withBGApi { checkUserLink(text) }
private fun MutableState<MigrationToState?>.PasteOrScanLinkView(close: () -> Unit) {
Box {
val progressIndicator = remember { mutableStateOf(false) }
Column {
if (appPlatform.isAndroid) {
SectionView(stringResource(MR.strings.scan_QR_code).replace('\n', ' ').uppercase()) {
QRCodeScanner(showQRCodeScanner = remember { mutableStateOf(true) }) { text ->
withBGApi { checkUserLink(text) }
}
}
SectionSpacer()
}
SectionView(stringResource(if (appPlatform.isAndroid) MR.strings.or_paste_archive_link else MR.strings.paste_archive_link).uppercase()) {
PasteLinkView()
}
SectionSpacer()
SectionView(stringResource(MR.strings.chat_archive).uppercase()) {
ArchiveImportView(progressIndicator, close)
}
}
SectionSpacer()
}
SectionView(stringResource(if (appPlatform.isAndroid) MR.strings.or_paste_archive_link else MR.strings.paste_archive_link).uppercase()) {
PasteLinkView()
if (progressIndicator.value)
ProgressView()
}
}
@@ -221,6 +234,31 @@ private fun MutableState<MigrationToState?>.PasteLinkView() {
}
}
@Composable
private fun ArchiveImportView(progressIndicator: MutableState<Boolean>, close: () -> Unit) {
val importArchiveLauncher = rememberFileChooserLauncher(true) { to: URI? ->
if (to != null) {
withLongRunningApi {
val success = importArchive(to, mutableStateOf(0 to 0), progressIndicator)
if (success) {
startChat(
chatModel,
mutableStateOf(Clock.System.now()),
chatModel.chatDbChanged,
progressIndicator
)
hideView(close)
}
}
}
}
SectionItemView({
withLongRunningApi { importArchiveLauncher.launch("application/zip") }
}) {
Text(stringResource(MR.strings.import_database))
}
}
@Composable
private fun ModalData.OnionView(link: String, legacyLinkSocksProxy: String?, linkNetworkProxy: NetworkProxy?, hostMode: HostMode, requiredHostMode: Boolean, state: MutableState<MigrationToState?>) {
val onionHosts = remember { stateGetOrPut("onionHosts") {
@@ -109,7 +109,7 @@ fun SettingsLayout(
SectionDividerSpaced()
SectionView(stringResource(MR.strings.settings_section_title_chat_database)) {
DatabaseItem(encrypted, passphraseSaved, showSettingsModal { DatabaseView(it, showSettingsModal) }, stopped)
DatabaseItem(encrypted, passphraseSaved, showSettingsModal { DatabaseView() }, stopped)
SettingsActionItem(painterResource(MR.images.ic_ios_share), stringResource(MR.strings.migrate_from_device_to_another_device), { withAuth(generalGetString(MR.strings.auth_open_migration_to_another_device), generalGetString(MR.strings.auth_log_in_using_credential)) { ModalManager.fullscreen.showCustomModal { close -> MigrateFromDeviceView(close) } } }, disabled = stopped)
}
@@ -242,7 +242,6 @@
<string name="change_self_destruct_mode">تغيير وضع التدمير الذاتي</string>
<string name="change_self_destruct_passcode">تغيير رمز المرور التدمير الذاتي</string>
<string name="confirm_database_upgrades">تأكيد ترقيات قاعدة البيانات</string>
<string name="chat_archive_header">أرشيف الدردشة</string>
<string name="group_member_status_intro_invitation">الاتصال (دعوة مقدمة)</string>
<string name="clear_contacts_selection_button">مسح</string>
<string name="error_creating_link_for_group">خطأ في إنشاء رابط المجموعة</string>
@@ -252,8 +251,6 @@
<string name="group_connection_pending">جار الاتصال…</string>
<string name="connection_request_sent">أرسلت طلب الاتصال!</string>
<string name="chat_database_deleted">حُذفت قاعدة بيانات الدردشة</string>
<string name="chat_archive_section">أرشيف الدردشة</string>
<string name="archive_created_on_ts">نشأ في %1$s</string>
<string name="rcv_conn_event_switch_queue_phase_changing">جارِ تغيير العنوان…</string>
<string name="group_member_status_accepted">جار الاتصال (قُبِل)</string>
<string name="icon_descr_contact_checked">فُحصت جهة الاتصال</string>
@@ -349,7 +346,6 @@
<string name="passphrase_is_different">تختلف عبارة مرور قاعدة البيانات عن تلك المحفوظة في Keystore.</string>
<string name="database_error">خطأ في قاعدة البيانات</string>
<string name="database_upgrade">ترقية قاعدة البيانات</string>
<string name="delete_chat_archive_question">حذف أرشيف الدردشة؟</string>
<string name="num_contacts_selected">حُددت %d جهة اتصال</string>
<string name="button_delete_group">حذف المجموعة</string>
<string name="delete_group_question">حذف المجموعة؟</string>
@@ -372,7 +368,6 @@
<string name="custom_time_unit_days">أيام</string>
<string name="delete_address">حذف العنوان</string>
<string name="database_passphrase_will_be_updated">سيتم تحديث عبارة مرور تعمية قاعدة البيانات.</string>
<string name="delete_archive">حذف الأرشيف</string>
<string name="delete_link_question">حذف الرابط؟</string>
<string name="database_downgrade">الرجوع إلى إصدار سابق من قاعدة البيانات</string>
<string name="set_password_to_export_desc">قاعدة البيانات مُعمّاة باستخدام عبارة مرور عشوائية. يُرجى تغييره قبل التصدير.</string>
@@ -844,7 +839,6 @@
<string name="read_more_in_user_guide_with_link"><![CDATA[اقرأ المزيد في <font color="#0088ff">دليل المستخدم</font>.]]></string>
<string name="auth_open_chat_profiles">افتح ملفات تعريف الدردشة</string>
<string name="revoke_file__confirm">اسحب الوصول</string>
<string name="save_archive">حفظ الأرشيف</string>
<string name="reveal_verb">كشف</string>
<string name="stop_rcv_file__message">سيتم إيقاف استلام الملف.</string>
<string name="reject_contact_button">رفض</string>
@@ -1263,6 +1263,7 @@
<!-- DatabaseView.kt -->
<string name="your_chat_database">Your chat database</string>
<string name="run_chat_section">RUN CHAT</string>
<string name="remote_hosts_section">Remote mobiles</string>
<string name="chat_is_running">Chat is running</string>
<string name="chat_is_stopped">Chat is stopped</string>
<string name="chat_database_section">CHAT DATABASE</string>
@@ -1404,14 +1405,6 @@
<string name="start_chat_question">Start chat?</string>
<string name="chat_is_stopped_you_should_transfer_database">Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</string>
<!-- ChatArchiveView.kt -->
<string name="chat_archive_header">Chat archive</string>
<string name="chat_archive_section">CHAT ARCHIVE</string>
<string name="save_archive">Save archive</string>
<string name="delete_archive">Delete archive</string>
<string name="archive_created_on_ts">Created on %1$s</string>
<string name="delete_chat_archive_question">Delete chat archive?</string>
<!-- Groups -->
<string name="group_invitation_item_description">invitation to group %1$s</string>
<string name="join_group_question">Join group?</string>
@@ -2292,6 +2285,7 @@
<string name="or_paste_archive_link">Or paste archive link</string>
<string name="paste_archive_link">Paste archive link</string>
<string name="invalid_file_link">Invalid link</string>
<string name="chat_archive">Or import archive file</string>
<string name="migrate_to_device_migrating">Migrating</string>
<string name="migrate_to_device_database_init">Preparing download</string>
<string name="migrate_to_device_downloading_details">Downloading link details</string>
@@ -228,7 +228,6 @@
<string name="chat_database_imported">Базата данни на чат е импортирана</string>
<string name="confirm_new_passphrase">Потвърди новата парола…</string>
<string name="confirm_database_upgrades">Потвърди актуализаациите на базата данни</string>
<string name="chat_archive_header">Архив на чата</string>
<string name="rcv_group_event_member_connected">свързан</string>
<string name="snd_conn_event_switch_queue_phase_changing">промяна на адреса…</string>
<string name="snd_conn_event_switch_queue_phase_changing_for_member">промяна на адреса за %s…</string>
@@ -317,7 +316,6 @@
<string name="change_self_destruct_mode">Промени режима на самоунищожение</string>
<string name="change_self_destruct_passcode">Промени кода за достъп за самоунищожение</string>
<string name="settings_section_title_chats">ЧАТОВЕ</string>
<string name="chat_archive_section">АРХИВ НА ЧАТА</string>
<string name="rcv_conn_event_switch_queue_phase_changing">промяна на адреса…</string>
<string name="maximum_supported_file_size">В момента максималният поддържан размер на файла е %1$s.</string>
<string name="info_row_database_id">ID в базата данни</string>
@@ -341,9 +339,6 @@
<string name="database_downgrade">Понижаване на версията на базата данни</string>
<string name="database_upgrade">Актуализация на базата данни</string>
<string name="mtr_error_no_down_migration">версията на базата данни е по-нова от приложението, но няма миграция надолу за: %s</string>
<string name="archive_created_on_ts">Създаден на %1$s</string>
<string name="delete_archive">Изтрий архив</string>
<string name="delete_chat_archive_question">Изтриване на архива на чата\?</string>
<string name="rcv_group_event_group_deleted">групата изтрита</string>
<string name="icon_descr_contact_checked">Контактът е проверен</string>
<string name="group_member_status_creator">създател</string>
@@ -996,7 +991,6 @@
<string name="lock_mode">Режим на заключване</string>
<string name="alert_text_fragment_please_report_to_developers">Моля, докладвайте го на разработчиците.</string>
<string name="protect_app_screen">Защити екрана на приложението</string>
<string name="save_archive">Запази архив</string>
<string name="member_info_section_title_member">ЧЛЕН</string>
<string name="remove_member_confirmation">Премахване</string>
<string name="network_option_ping_count">PING бройка</string>
@@ -303,8 +303,6 @@
<string name="restore_database">Obnovte zálohu databáze</string>
<string name="restore_database_alert_desc">Po obnovení zálohy databáze zadejte předchozí frázi. Tuto akci nelze vrátit zpět.</string>
<string name="chat_is_stopped_indication">Chat je zastaven</string>
<string name="chat_archive_header">Chat se archivuje</string>
<string name="delete_chat_archive_question">Smazat archiv chatu?</string>
<string name="join_group_question">Připojit se ke skupině\?</string>
<string name="join_group_button">Připojte se na</string>
<string name="leave_group_button">Opustit</string>
@@ -352,7 +350,6 @@
<string name="chat_database_imported">Databáze chatu importována</string>
<string name="new_passphrase">Nová přístupová fráze…</string>
<string name="save_passphrase_and_open_chat">Uložte přístupovou frázi a otevřete chat</string>
<string name="chat_archive_section">ARCHIV CHATU</string>
<string name="no_contacts_selected">Nebyl vybrán žádný kontakt</string>
<string name="invite_prohibited_description">Snažíte se pozvat kontakt, se kterým jste sdíleli inkognito profil, do skupiny, ve které používáte svůj hlavní profil</string>
<string name="info_row_group">Skupina</string>
@@ -776,10 +773,7 @@
<string name="database_restore_error">Chyba při obnovování databáze</string>
<string name="restore_passphrase_not_found_desc">Přístupová fráze nebyla v klíčence nalezena, zadejte jej prosím ručně. K této situaci mohlo dojít, pokud jste obnovili data aplikace pomocí zálohovacího nástroje. Pokud tomu tak není, obraťte se na vývojáře.</string>
<string name="you_can_start_chat_via_setting_or_by_restarting_the_app">Chat můžete spustit v Nastavení / Databáze nebo restartováním aplikace.</string>
<string name="save_archive">Uložit archiv</string>
<string name="delete_archive">Smazat archiv</string>
<string name="group_invitation_item_description">pozvánka do skupiny %1$s</string>
<string name="archive_created_on_ts">Vytvořeno dne %1$s</string>
<string name="you_are_invited_to_group_join_to_connect_with_group_members">Jste zváni do skupiny. Připojte se k členům skupiny.</string>
<string name="join_group_incognito_button">Připojit se inkognito</string>
<string name="joining_group">Připojit ke skupině</string>
@@ -672,12 +672,6 @@
<string name="chat_is_stopped_indication">Der Chat wurde beendet</string>
<string name="you_can_start_chat_via_setting_or_by_restarting_the_app">Sie können den Chat über die App-Einstellungen/Datenbank oder durch Neustart der App starten.</string>
<!-- ChatArchiveView.kt -->
<string name="chat_archive_header">Datenbank-Archiv</string>
<string name="chat_archive_section">CHAT-ARCHIV</string>
<string name="save_archive">Archiv speichern</string>
<string name="delete_archive">Archiv löschen</string>
<string name="archive_created_on_ts">Erstellt am %1$s</string>
<string name="delete_chat_archive_question">Chat-Archiv löschen\?</string>
<!-- Groups -->
<string name="group_invitation_item_description">Einladung zur Gruppe %1$s</string>
<string name="join_group_question">Der Gruppe beitreten?</string>
@@ -100,7 +100,6 @@
<string name="database_initialization_error_title">Δεν είναι δυνατή η προετοιμασία της βάσης δεδομένων</string>
<string name="connect__a_new_random_profile_will_be_shared">Ένα νέο τυχαίο προφίλ θα μοιραστεί.</string>
<string name="alert_title_cant_invite_contacts">Δεν είναι δυνατή η πρόσκληση επαφών!</string>
<string name="chat_archive_header">Αρχείο συνομιλίας</string>
<string name="switch_receiving_address">Αλλαγή διεύθυνσης λήψης</string>
<string name="auth_unavailable">Πιστοποίηση μη διαθέσιμη</string>
<string name="change_verb">Αλλαγή</string>
@@ -112,7 +111,6 @@
<string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d αποτυχία κρυπτογράφησης μηνύματος</string>
<string name="snd_conn_event_switch_queue_phase_changing_for_member">αλλαγή διεύθυνσης για %s…</string>
<string name="change_member_role_question">Αλλαγή ρόλου ομάδας;</string>
<string name="chat_archive_section">ΑΡΧΕΙΟ ΣΥΝΟΜΙΛΙΑΣ</string>
<string name="invite_prohibited">Δεν είναι δυνατή η πρόσκληση επαφής!</string>
<string name="v4_2_auto_accept_contact_requests">Αυτόματη αποδοχή αιτήματος επαφής</string>
<string name="callstatus_calling">Κλήση…</string>
@@ -189,7 +187,6 @@
<string name="contact_connection_pending">συνδέεται…</string>
<string name="create_group_link">Δημιουργία σύνδεσμο ομάδας</string>
<string name="connect_to_desktop">Σύνδεση σε επιφάνεια εργασίας</string>
<string name="archive_created_on_ts">Δημιουργήθηκε στις %1$s</string>
<string name="connected_to_mobile">Συνδεδεμένο στο κινητό</string>
<string name="connect_via_link">Σύνδεση μέσω σύνδεσμο</string>
<string name="receipts_section_contacts">Επαφές</string>
@@ -191,7 +191,6 @@
<string name="callstate_connecting">conectando…</string>
<string name="decentralized">Descentralizada</string>
<string name="database_will_be_encrypted">La base de datos será cifrada.</string>
<string name="delete_chat_archive_question">¿Eliminar archivo del chat\?</string>
<string name="create_group_link">Crear enlace de grupo</string>
<string name="delete_link">Eliminar enlace</string>
<string name="users_delete_question">¿Eliminar perfil?</string>
@@ -215,8 +214,6 @@
<string name="ttl_d">%dd</string>
<string name="ttl_days">%d días</string>
<string name="delete_files_and_media_question">¿Eliminar archivos y multimedia\?</string>
<string name="archive_created_on_ts">Creado: %1$s</string>
<string name="delete_archive">Eliminar archivo</string>
<string name="group_member_status_connected">conectado</string>
<string name="conn_level_desc_direct">directa</string>
<string name="chat_preferences_contact_allows">El contacto permite</string>
@@ -289,8 +286,6 @@
<string name="icon_descr_call_progress">Llamada en curso</string>
<string name="change_database_passphrase_question">¿Cambiar contraseña de la base de datos\?</string>
<string name="cannot_access_keychain">No se puede acceder a Keystore para guardar la base de datos de contraseñas</string>
<string name="chat_archive_header">Archivo del chat</string>
<string name="chat_archive_section">ARCHIVOS DE CHAT</string>
<string name="cancel_verb">Cancelar</string>
<string name="icon_descr_cancel_live_message">Cancelar mensaje en directo</string>
<string name="confirm_verb">Confirmar</string>
@@ -662,7 +657,6 @@
<string name="icon_descr_call_pending_sent">Llamada pendiente</string>
<string name="privacy_and_security">Privacidad y Seguridad</string>
<string name="store_passphrase_securely_without_recover">Guarda la contraseña de forma segura, NO podrás acceder al chat si la pierdes.</string>
<string name="save_archive">Guardar archivo</string>
<string name="restore_database_alert_desc">Introduce la contraseña anterior después de restaurar la copia de seguridad de la base de datos. Esta acción no se puede deshacer.</string>
<string name="rcv_group_event_user_deleted">te ha expulsado</string>
<string name="receiving_via">Recibiendo vía</string>
@@ -956,9 +956,6 @@
<string name="enable_automatic_deletion_question">حذف خودکار پیام فعال شود؟</string>
<string name="restore_database_alert_confirm">برگرداندن</string>
<string name="upgrade_and_open_chat">ارتقا و گشودن گپ</string>
<string name="chat_archive_header">آرشیو گپ</string>
<string name="save_archive">ذخیره آرشیو</string>
<string name="delete_archive">حذف آرشیو</string>
<string name="group_invitation_item_description">دعوت به گروه %1$s</string>
<string name="join_group_question">به گروه می‌پیوندید؟</string>
<string name="leave_group_button">ترک</string>
@@ -1092,9 +1089,6 @@
<string name="mtr_error_no_down_migration">نسخه پایگاه داده از برنامه جدیدتر است، اما بدون جابه‌جایی تنزلی برای: %s</string>
<string name="mtr_error_different">جابه‌جایی متفاوت در برنامه/پایگاه داده: %s / %s</string>
<string name="database_migrations">جابه‌جایی‌ها: %s</string>
<string name="chat_archive_section">آرشیو گپ</string>
<string name="archive_created_on_ts">ایجاد شده در %1$s</string>
<string name="delete_chat_archive_question">آرشیو گپ حذف شود؟</string>
<string name="you_are_invited_to_group_join_to_connect_with_group_members">شما به گروه دعوت شده‌اید. برای متصل شدن به اعضای گروه، به گروه بپیوندید.</string>
<string name="join_group_incognito_button">پیوستن به صورت ناشناس</string>
<string name="alert_message_no_group">این گروه دیگر وجود ندارد.</string>
@@ -108,7 +108,6 @@
<string name="about_simplex">Tietoja SimpleX:stä</string>
<string name="decentralized">Hajautettu</string>
<string name="icon_descr_audio_off">Ääni pois päältä</string>
<string name="chat_archive_section">ARKISTO</string>
<string name="change_role">Vaihda rooli</string>
<string name="full_deletion">Poista kaikilta</string>
<string name="empty_chat_profile_is_created">Luodaan tyhjä chat-profiili annetulla nimellä, ja sovellus avautuu normaalisti.</string>
@@ -168,9 +167,6 @@
<string name="theme_dark">Tumma</string>
<string name="la_auth_failed">Tunnistautuminen epäonnistui</string>
<string name="smp_servers_preset_add">Lisää esiasetettuja palvelimia</string>
<string name="chat_archive_header">Arkisto</string>
<string name="delete_chat_archive_question">Poista keskusteluarkisto\?</string>
<string name="archive_created_on_ts">Luotu %1$s</string>
<string name="rcv_group_event_group_deleted">poistettu ryhmä</string>
<string name="group_member_status_connecting">yhdistää</string>
<string name="group_member_status_accepted">yhdistäminen (hyväksytty)</string>
@@ -326,7 +322,6 @@
<string name="database_downgrade">Tietokannan alentaminen</string>
<string name="database_upgrade">Tietokannan päivitys</string>
<string name="database_will_be_encrypted">Tietokanta salataan.</string>
<string name="delete_archive">Poista arkisto</string>
<string name="group_member_status_intro_invitation">yhdistäminen (esittelykutsu)</string>
<string name="info_row_deleted_at">Poistettu klo</string>
<string name="change_verb">Muuta</string>
@@ -969,7 +964,6 @@
<string name="smp_server_test_secure_queue">Turvallinen jono</string>
<string name="restore_passphrase_not_found_desc">Tunnuslausetta ei löydy Keystoresta, kirjoita se manuaalisesti. Tämä on saattanut tapahtua, jos olet palauttanut sovelluksen tiedot varmuuskopiointityökalulla. Jos näin ei ole, ota yhteyttä kehittäjiin.</string>
<string name="restore_database_alert_desc">Anna edellinen salasana tietokannan varmuuskopion palauttamisen jälkeen. Tätä toimintoa ei voi kumota.</string>
<string name="save_archive">Tallenna arkisto</string>
<string name="non_fatal_errors_occured_during_import">Tuonnin aikana tapahtui joitakin ei-vakavia virheitä saatat nähdä Chat-konsolissa lisätietoja.</string>
<string name="info_row_updated_at">Tietue päivitetty klo</string>
<string name="info_row_moderated_at">Moderoitu klo</string>
@@ -475,7 +475,6 @@
<string name="restore_passphrase_not_found_desc">La phrase secrète n\'a pas été trouvée dans le Keystore, veuillez la saisir manuellement. Cela a pu se produire si vous avez restauré les données de l\'app à l\'aide d\'un outil de sauvegarde. Si ce n\'est pas le cas, veuillez contacter les développeurs.</string>
<string name="restore_database_alert_desc">Veuillez entrer le mot de passe précédent après avoir restauré la sauvegarde de la base de données. Cette action ne peut pas être annulée.</string>
<string name="database_restore_error">Erreur de restauration de la base de données</string>
<string name="archive_created_on_ts">Créé le %1$s</string>
<string name="encrypted_video_call">appel vidéo (chiffrement de bout en bout)</string>
<string name="audio_call_no_encryption">appel audio (sans chiffrement)</string>
<string name="encrypted_audio_call">appel audio (chiffrement de bout en bout)</string>
@@ -653,11 +652,6 @@
<string name="restore_database_alert_confirm">Restaurer</string>
<string name="chat_is_stopped_indication">Le chat est arrêté</string>
<string name="you_can_start_chat_via_setting_or_by_restarting_the_app">Vous pouvez lancer le chat via les Paramètres / la Base de données de l\'app ou en la redémarrant.</string>
<string name="chat_archive_header">Archives du chat</string>
<string name="chat_archive_section">ARCHIVE DU CHAT</string>
<string name="save_archive">Enregistrer l\'archive</string>
<string name="delete_archive">Supprimer l\'archive</string>
<string name="delete_chat_archive_question">Supprimer l\'archive du chat \?</string>
<string name="group_invitation_item_description">Invitation au groupe %1$s</string>
<string name="join_group_question">Rejoindre le groupe \?</string>
<string name="you_are_invited_to_group_join_to_connect_with_group_members">Vous êtes invité·e dans un groupe. Rejoignez le pour vous connecter avec ses membres.</string>
@@ -117,7 +117,6 @@
<string name="network_status">नेटवर्क की स्थिति</string>
<string name="notification_new_contact_request">नया संपर्क अनुरोध</string>
<string name="delete_files_and_media_all">सभी फाइलों को मिटा दें</string>
<string name="delete_archive">संग्रह हटा देना</string>
<string name="new_database_archive">नया डेटाबेस संग्रह</string>
<string name="new_member_role">नए सदस्य की भूमिका</string>
<string name="settings_notifications_mode_title">अधिसूचना सेवा</string>
@@ -129,7 +128,6 @@
<string name="settings_notification_preview_title">अधिसूचना पूर्वावलोकन</string>
<string name="notifications">सूचनाएं</string>
<string name="full_deletion">सभी के लिए हटाएं</string>
<string name="delete_chat_archive_question">लिखचीत संग्रह हटा दे\?</string>
<string name="delete_chat_profile_question">चैट प्रोफ़ाइल हटाएं\?</string>
<string name="users_delete_question">चैट प्रोफ़ाइल हटाएं\?</string>
<string name="users_delete_profile_for">के लिए चैट प्रोफ़ाइल हटाएं</string>
@@ -218,9 +216,7 @@
<string name="icon_descr_call_ended">कॉल समाप्त</string>
<string name="icon_descr_call_progress">कॉल चल रहा है</string>
<string name="auto_accept_images">छवियों को स्वत: स्वीकार करें</string>
<string name="chat_archive_header">चैट संग्रह</string>
<string name="chat_is_stopped_indication">चैट रोक दी गई है</string>
<string name="chat_archive_section">चैट संग्रह</string>
<string name="you_will_stop_receiving_messages_from_this_group_chat_history_will_be_preserved">आप इस समूह से संदेश प्राप्त करना बंद कर देंगे। चैट इतिहास संरक्षित किया जाएगा।</string>
<string name="rcv_group_event_changed_member_role">%s की भूमिका को %s में बदला</string>
<string name="group_member_status_complete">पूर्ण</string>
@@ -262,7 +262,6 @@
<string name="full_deletion">Törlés az összes tagnál</string>
<string name="button_create_group_link">Hivatkozás létrehozása</string>
<string name="chat_preferences">Csevegési beállítások</string>
<string name="chat_archive_header">Csevegési archívum</string>
<string name="delete_profile">Profil törlése</string>
<string name="la_current_app_passcode">Jelenlegi jelkód</string>
<string name="group_member_status_connecting">kapcsolódás</string>
@@ -277,7 +276,6 @@
<string name="in_developing_title">Hamarosan!</string>
<string name="snd_conn_event_switch_queue_phase_changing_for_member">cím megváltoztatása nála: %s …</string>
<string name="chat_database_imported">Csevegési adatbázis importálva</string>
<string name="chat_archive_section">CSEVEGÉSI ARCHÍVUM</string>
<string name="delete_messages">Üzenetek törlése</string>
<string name="clear_chat_menu_action">Kiürítés</string>
<string name="icon_descr_close_button">Bezárás gomb</string>
@@ -329,7 +327,6 @@
<string name="delete_files_and_media_for_all_users">Fájlok törlése az összes csevegési profilból</string>
<string name="smp_server_test_delete_queue">Sorbaállítás törlése</string>
<string name="button_delete_contact">Ismerős törlése</string>
<string name="archive_created_on_ts">Létrehozva ekkor: %1$s</string>
<string name="rcv_conn_event_switch_queue_phase_changing">cím megváltoztatása…</string>
<string name="connected_to_mobile">Társítva a hordozható eszközhöz</string>
<string name="current_passphrase">Jelenlegi jelmondat…</string>
@@ -413,7 +410,6 @@
<string name="receipts_groups_title_disable">Kézbesítés jelentések letiltása a csoportok számára?</string>
<string name="custom_time_unit_days">nap</string>
<string name="ttl_day">%d nap</string>
<string name="delete_chat_archive_question">Csevegési archívum törlése?</string>
<string name="failed_to_create_user_duplicate_title">Duplikált megjelenített név!</string>
<string name="receipts_contacts_disable_keep_overrides">Letiltás (felülírások megtartásával)</string>
<string name="database_upgrade">Adatbázis fejlesztése</string>
@@ -451,7 +447,6 @@
<string name="devices">Eszközök</string>
<string name="multicast_discoverable_via_local_network">Látható a helyi hálózaton</string>
<string name="dont_enable_receipts">Ne engedélyezze</string>
<string name="delete_archive">Archívum törlése</string>
<string name="disappearing_prohibited_in_this_chat">Az eltűnő üzenetek küldése le van tiltva ebben a csevegésben.</string>
<string name="chat_preferences_default">alapértelmezett (%s)</string>
<string name="integrity_msg_duplicate">duplikált üzenet</string>
@@ -998,7 +993,6 @@
<string name="recipient_colon_delivery_status">%s: %s</string>
<string name="system_restricted_background_desc">A SimpleX nem tud a háttérben futni. Csak akkor fog értesítéseket kapni, amikor az alkalmazás meg van nyitva.</string>
<string name="images_limit_title">Túl sok kép!</string>
<string name="save_archive">Archívum mentése</string>
<string name="group_members_n">%s, %s és %d tag</string>
<string name="auth_stop_chat">Csevegési szolgáltatás megállítása</string>
<string name="simplex_link_mode">SimpleX-hivatkozások</string>
@@ -450,7 +450,6 @@
<string name="la_app_passcode">Kode sandi aplikasi</string>
<string name="la_mode_passcode">Kode sandi</string>
<string name="chat_item_ttl_seconds">%s detik</string>
<string name="save_archive">Simpan arsip</string>
<string name="group_invitation_tap_to_join">Ketuk untuk gabung</string>
<string name="rcv_group_event_member_blocked">diblokir %s</string>
<string name="rcv_group_event_open_chat">Buka</string>
@@ -548,7 +547,6 @@
<string name="info_view_message_button">pesan</string>
<string name="info_view_open_button">buka</string>
<string name="la_mode_system">Sistem</string>
<string name="chat_archive_header">Arsip obrolan</string>
<string name="profile_update_event_set_new_address">setel alamat kontak baru</string>
<string name="dark_theme">Tema gelap</string>
<string name="theme">Tema</string>
@@ -862,7 +860,6 @@
<string name="voice_messages_not_allowed">Pesan suara tidak diizinkan</string>
<string name="delete_address__question">Hapus alamat?</string>
<string name="leave_group_question">Keluar dari grup?</string>
<string name="chat_archive_section">ARSIP OBROLAN</string>
<string name="this_string_is_not_a_connection_link">Rangkaian ini bukan tautan koneksi!</string>
<string name="paste_the_link_you_received">Tempel tautan yang Anda terima</string>
<string name="share_with_contacts">Bagikan dengan kontak</string>
@@ -890,7 +887,6 @@
<string name="integrity_msg_duplicate">gandakan pesan</string>
<string name="integrity_msg_bad_hash">hash pesan buruk</string>
<string name="start_chat_question">Mulai obrolan?</string>
<string name="delete_archive">Hapus arsip</string>
<string name="v5_3_discover_join_groups">Jelajah dan gabung ke grup</string>
<string name="v5_8_private_routing">Perutean pesan pribadi 🚀</string>
<string name="v5_8_private_routing_descr">Lindungi alamat IP Anda dari relai pesan yang dipilih oleh kontak Anda.\nAktifkan di pengaturan *Jaringan &amp; server*.</string>
@@ -277,7 +277,6 @@
<string name="cannot_access_keychain">Impossibile accedere al Keystore per salvare la password del database</string>
<string name="alert_title_cant_invite_contacts">Impossibile invitare i contatti!</string>
<string name="change_role">Cambia ruolo</string>
<string name="chat_archive_section">ARCHIVIO CHAT</string>
<string name="snd_conn_event_switch_queue_phase_changing">cambio indirizzo…</string>
<string name="chat_is_stopped">Chat fermata</string>
<string name="group_member_status_introduced">in connessione (presentato)</string>
@@ -398,13 +397,9 @@
<string name="settings_experimental_features">Funzionalità sperimentali</string>
<string name="export_database">Esporta database</string>
<string name="settings_section_title_help">AIUTO</string>
<string name="chat_archive_header">Archivio chat</string>
<string name="chat_is_stopped_indication">Chat fermata</string>
<string name="archive_created_on_ts">Creato il %1$s</string>
<string name="database_error">Errore del database</string>
<string name="passphrase_is_different">La password del database è diversa da quella salvata nel Keystore.</string>
<string name="delete_archive">Elimina archivio</string>
<string name="delete_chat_archive_question">Eliminare l\'archivio della chat\?</string>
<string name="encrypted_database">Database crittografato</string>
<string name="enter_correct_passphrase">Inserisci la password giusta.</string>
<string name="enter_passphrase">Inserisci la password…</string>
@@ -745,7 +740,6 @@
<string name="restore_database">Ripristina backup del database</string>
<string name="restore_database_alert_title">Ripristinare il backup del database\?</string>
<string name="database_restore_error">Errore di ripristino del database</string>
<string name="save_archive">Salva archivio</string>
<string name="save_passphrase_and_open_chat">Salva la password e apri la chat</string>
<string name="database_backup_can_be_restored">Il tentativo di cambiare la password del database non è stato completato.</string>
<string name="unknown_database_error_with_info">Errore del database sconosciuto: %s</string>
@@ -165,8 +165,6 @@
<string name="chat_database_deleted">מסד הנתונים של הצ׳אט נמחק</string>
<string name="chat_database_imported">‬מסד הנתונים של הצ׳אט יובא</string>
<string name="confirm_database_upgrades">אשר שדרוגי מסד נתונים</string>
<string name="chat_archive_header">ארכיון צ׳אט</string>
<string name="chat_archive_section">ארכיון צ׳אט</string>
<string name="chat_is_stopped_indication">צ׳אט מופסק</string>
<string name="alert_title_cant_invite_contacts">לא ניתן להזמין את אנשי הקשר!</string>
<string name="rcv_group_event_changed_your_role">שונה תפקידך ל%s</string>
@@ -222,7 +220,6 @@
<string name="create_profile_button">צור</string>
<string name="create_profile">צור פרופיל</string>
<string name="create_your_profile">יצירת הפרופיל שלך</string>
<string name="archive_created_on_ts">נוצר ב־%1$s</string>
<string name="create_group_link">צור קישור קבוצה</string>
<string name="button_create_group_link">צור קישור</string>
<string name="group_member_status_creator">יוצר הקבוצה</string>
@@ -253,7 +250,6 @@
<string name="create_address_and_let_people_connect">צרו כתובת כדי לאפשר לאנשים להתחבר אליכם.</string>
<string name="decentralized">מבוזר</string>
<string name="set_password_to_export_desc">מסד הנתונים מוצפן באמצעות סיסמה אקראית. אנא שנו אותה לפני הייצוא.</string>
<string name="delete_chat_archive_question">למחוק ארכיון צ׳אט\?</string>
<string name="delete_chat_profile">מחק פרופיל צ׳אט</string>
<string name="chat_preferences_default">ברירת מחדל (%s)</string>
<string name="ttl_day">%d יום</string>
@@ -307,7 +303,6 @@
<string name="database_passphrase_and_export">סיסמה וייצוא של מסד הנתונים</string>
<string name="delete_after">מחק אחרי</string>
<string name="delete_files_and_media_all">מחק את כל הקבצים</string>
<string name="delete_archive">מחק ארכיון</string>
<string name="for_me_only">מחק עבורי</string>
<string name="delete_link">מחק קישור</string>
<string name="users_delete_question">למחוק פרופיל צ׳אט\?</string>
@@ -893,7 +888,6 @@
<string name="restore_database">שחזור גיבוי מסד נתונים</string>
<string name="restore_database_alert_title">לשחזר גיבוי מסד נתונים\?</string>
<string name="save_passphrase_and_open_chat">שמור סיסמה ופתח את הצ׳אט</string>
<string name="save_archive">שמור ארכיון</string>
<string name="select_contacts">בחירת אנשי קשר</string>
<string name="v5_1_self_destruct_passcode">קוד גישה להשמדה עצמית</string>
<string name="custom_time_unit_seconds">שניות</string>
@@ -77,8 +77,6 @@
<string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>電池消費が最少</b>:アプリがアクティブ時のみに通知が出ます(バックグラウンドサービス無し)。]]></string>
<string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b>設定メニューにてオフにできます。</b> アプリがアクティブ時に通知が出ます。]]></string>
<string name="both_you_and_your_contacts_can_delete">あなたと連絡相手が送信済みメッセージを永久削除できます。(24時間)</string>
<string name="chat_archive_section">チャットのアーカイブ</string>
<string name="delete_chat_archive_question">チャットのアーカイブを削除しますか?</string>
<string name="join_group_incognito_button">シークレットモードで参加</string>
<string name="group_member_status_intro_invitation">接続待ち (招待)</string>
<string name="group_member_status_accepted">接続待ち (承諾済み)</string>
@@ -369,8 +367,6 @@
<string name="database_passphrase_will_be_updated">データベース暗号化のパスフレーズが更新されます。</string>
<string name="database_passphrase_is_required">チャットを開くにはデータベースパスフレーズが必要です。</string>
<string name="file_with_path">ファイル: %s</string>
<string name="archive_created_on_ts">作成日時 %1$s</string>
<string name="delete_archive">アーカイブを削除</string>
<string name="join_group_button">参加</string>
<string name="join_group_question">グループに参加しますか?</string>
<string name="joining_group">グループに参加</string>
@@ -551,7 +547,6 @@
<string name="settings_section_title_device">端末</string>
<string name="no_received_app_files">送受信済みのファイルがありません</string>
<string name="delete_messages">メッセージを削除</string>
<string name="chat_archive_header">チャットのアーカイブ</string>
<string name="rcv_group_event_member_connected">接続中</string>
<string name="rcv_group_event_user_deleted">あなたを除名しました。</string>
<string name="group_link">グループのリンク</string>
@@ -921,7 +916,6 @@
<string name="stop_chat_to_export_import_or_delete_chat_database">データベースのエクスポート、読み込み、削除するにはチャット機能を停止する必要があります。チャット機能を停止すると送受信ができなくなります。</string>
<string name="delete_chat_profile_action_cannot_be_undone_warning">あなたのプロフィール、連絡先、メッセージ、ファイルが完全削除されます (※元に戻せません※)。</string>
<string name="update_database_passphrase">データベースパスフレーズを更新</string>
<string name="save_archive">アーカイブを保存</string>
<string name="snd_group_event_changed_role_for_yourself">あなたが自分の役割を次に変えました:%s</string>
<string name="snd_conn_event_switch_queue_phase_completed">アドレスを変えました</string>
<string name="snd_conn_event_switch_queue_phase_completed_for_member">%sのアドレスを変えました</string>
@@ -90,7 +90,6 @@
<string name="impossible_to_recover_passphrase"><![CDATA[<b>주의</b>: 암호를 분실하면 복구하거나 비밀번호 변경을 할 수 없어요.]]></string>
<string name="change_database_passphrase_question">데이터베이스 암호를 바꾸시겠습니까?</string>
<string name="confirm_new_passphrase">새로운 암호 확인…</string>
<string name="chat_archive_section">채팅 기록 보관함</string>
<string name="rcv_group_event_changed_your_role">내 역할이 %s 역할로 변경됨</string>
<string name="rcv_conn_event_switch_queue_phase_changing">주소 바꾸는 중…</string>
<string name="snd_conn_event_switch_queue_phase_changing">주소 바꾸는 중…</string>
@@ -179,7 +178,6 @@
<string name="chat_database_section">채팅 데이터베이스</string>
<string name="alert_title_cant_invite_contacts">대화 상대를 초대할 수 없습니다!</string>
<string name="change_verb">변경</string>
<string name="chat_archive_header">채팅 기록 보관함</string>
<string name="change_role">역할 변경</string>
<string name="chat_database_deleted">채팅 데이터베이스가 삭제됨</string>
<string name="chat_is_stopped">채팅이 멈춤</string>
@@ -197,7 +195,6 @@
<string name="delete_contact_all_messages_deleted_cannot_undo_warning">대화 상대와 모든 메시지가 삭제됩니다. 이 결정은 되돌릴 수 없습니다!</string>
<string name="status_contact_has_e2e_encryption">대화 상대와 종단 간 암호화됨</string>
<string name="alert_title_contact_connection_pending">대화 상대와 아직 연결되지 않았습니다!</string>
<string name="archive_created_on_ts">%1$s에 생성 완료</string>
<string name="create_secret_group_title">비밀 그룹 생성</string>
<string name="accept_contact_incognito_button">익명 수락</string>
<string name="chat_item_ttl_month">1개월</string>
@@ -232,8 +229,6 @@
<string name="database_error">데이터베이스 에러</string>
<string name="passphrase_is_different">데이터베이스 암호가 암호 저장소에 저장된 것과 일치하지 않습니다.</string>
<string name="database_passphrase_is_required">채팅을 열려면 데이터베이스 암호가 필요합니다.</string>
<string name="delete_archive">보관함 삭제</string>
<string name="delete_chat_archive_question">보관된 채팅을 삭제할까요\?</string>
<string name="num_contacts_selected">%d 개의 대화 상대가 선택되었습니다.</string>
<string name="info_row_database_id">데이터베이스 ID</string>
<string name="users_delete_profile_for">다음 채팅 프로필 삭제</string>
@@ -751,7 +746,6 @@
<string name="save_and_notify_group_members">저장하고 그룹 멤버들에게 알리기</string>
<string name="save_and_notify_contact">저장하고 대화 상대에게 알리기</string>
<string name="remove_passphrase">지우기</string>
<string name="save_archive">보관함 저장하기</string>
<string name="save_passphrase_in_keychain">암호 저장소에 암호 저장하기</string>
<string name="restore_database">데이터베이스 백업 복원하기</string>
<string name="restore_database_alert_desc">데이터베이스 백업을 복원한 후 이전 비밀번호를 입력해 주십시오. 이 결정은 되돌릴 수 없습니다.</string>
@@ -125,8 +125,6 @@
<string name="files_and_media_section">Failai ir medija</string>
<string name="delete_files_and_media_all">Ištrinti visus failus</string>
<string name="delete_files_and_media_question">Ištrinti failus ir mediją\?</string>
<string name="delete_archive">Ištrinti archyvą</string>
<string name="delete_chat_archive_question">Ištrinti pokalbio archyvą\?</string>
<string name="snd_group_event_group_profile_updated">grupės profilis atnaujintas</string>
<string name="info_row_group">Grupė</string>
<string name="users_delete_question">Ištrinti pokalbio profilį\?</string>
@@ -393,7 +391,6 @@
<string name="mark_code_verified">Žymėti kaip patvirtintą</string>
<string name="chat_lock">SimpleX užraktas</string>
<string name="saved_ICE_servers_will_be_removed">Įrašyti WebRTC ICE serveriai bus pašalinti.</string>
<string name="save_archive">Įrašyti archyvą</string>
<string name="button_send_direct_message">Siųsti tiesioginę žinutę</string>
<string name="button_remove_member">Šalinti narį</string>
<string name="theme_light">Šviesus</string>
@@ -834,7 +831,6 @@
<string name="restore_database_alert_desc">Prašome įvesti praeitą slaptažodį po duomenų bazės atsarginės kopijos atstatymo. Šis veiksmas negali būti atšauktas.</string>
<string name="mtr_error_no_down_migration">duomenų bazė naujesnė nei programėlė, bet nėra perkėlimo į senesnę versiją: %s</string>
<string name="mtr_error_different">skirtinga migracija programėlėje/duomenų bazėje: %s / %s</string>
<string name="chat_archive_header">Pokalbio archyvas</string>
<string name="icon_descr_group_inactive">Grupė neaktyvi</string>
<string name="info_row_received_at">Gauta</string>
<string name="member_blocked_by_admin">Užblokuota administratoriaus</string>
@@ -903,7 +899,6 @@
<string name="you_can_change_it_later">Atsitiktinė slaptafrazė yra saugoma nustatymuose kaip paprastas tekstas.
\nJūs galite tai pakeisti vėliau.</string>
<string name="chat_is_running">Pokalbiai veikia</string>
<string name="chat_archive_section">POKALBIO ARCHYVAS</string>
<string name="chat_is_stopped_you_should_transfer_database">Pokalbiai sustabdyti. Jei jau naudojote šią duomenų bazę kitame įrenginyje, turėtumėte perkelti ją atgal prieš pradedant pokalbius.</string>
<string name="rcv_group_event_member_blocked">užblokavo %s</string>
<string name="switch_receiving_address">Keisti gavimo adresą</string>
@@ -1061,7 +1056,6 @@
<string name="chat_is_stopped_indication">Pokalbiai sustabdyti</string>
<string name="group_member_status_accepted">jungiamasi (priimtas)</string>
<string name="icon_descr_contact_checked">Kontaktas patikrintas</string>
<string name="archive_created_on_ts">Sukurta %1$s</string>
<string name="passphrase_is_different">Duomenų bazės slaptafrazė yra kitokia nei išsaugota raktų saugykloje.</string>
<string name="database_will_be_encrypted_and_passphrase_stored_in_settings">Duomenų bazė bus užšifruota ir slaptafrazė bus saugoma nustatymuose.</string>
<string name="alert_message_group_invitation_expired">Grupės pakvietimas nebegalioja, siuntėjas jį pašalino.</string>
@@ -24,7 +24,6 @@
<string name="chat_is_running">Chat is actief</string>
<string name="clear_chat_menu_action">Wissen</string>
<string name="chat_database_section">CHAT DATABASE</string>
<string name="chat_archive_section">CHAT ARCHIEF</string>
<string name="chat_console">Chat console</string>
<string name="chat_database_imported">Chat database geïmporteerd</string>
<string name="chat_database_deleted">Chat database verwijderd</string>
@@ -117,7 +116,6 @@
<string name="chat_is_stopped">Chat is gestopt</string>
<string name="notifications_mode_periodic_desc">Controleert nieuwe berichten elke 10 minuten gedurende maximaal 1 minuut</string>
<string name="rcv_group_event_changed_your_role">je rol gewijzigd in %s</string>
<string name="chat_archive_header">Gesprek archief</string>
<string name="change_database_passphrase_question">Wachtwoord database wijzigen\?</string>
<string name="chat_is_stopped_indication">Chat is gestopt</string>
<string name="chat_preferences">Chat voorkeuren</string>
@@ -215,7 +213,6 @@
<string name="current_passphrase">Huidige wachtwoord…</string>
<string name="database_encrypted">Database versleuteld!</string>
<string name="rcv_group_event_member_connected">is toegetreden</string>
<string name="archive_created_on_ts">Gemaakt op %1$s</string>
<string name="group_member_status_complete">compleet</string>
<string name="clear_contacts_selection_button">Wissen</string>
<string name="group_member_status_connected">verbonden</string>
@@ -230,8 +227,6 @@
<string name="contacts_can_mark_messages_for_deletion">Contact personen kunnen berichten markeren voor verwijdering; u kunt ze wel bekijken.</string>
<string name="theme_dark">Donker</string>
<string name="chat_preferences_default">standaard (%s)</string>
<string name="delete_chat_archive_question">Chat archief verwijderen\?</string>
<string name="delete_archive">Archief verwijderen</string>
<string name="delete_contact_question">Verwijder contact\?</string>
<string name="delete_chat_profile_question">Chatprofiel verwijderen?</string>
<string name="full_deletion">Verwijderen voor iedereen</string>
@@ -621,7 +616,6 @@
<string name="icon_descr_video_on">Video aan</string>
<string name="delete_chat_profile_action_cannot_be_undone_warning">Deze actie kan niet ongedaan worden gemaakt. Uw profiel, contacten, berichten en bestanden gaan onomkeerbaar verloren.</string>
<string name="messages_section_description">Deze instelling is van toepassing op berichten in uw huidige chatprofiel</string>
<string name="save_archive">Bewaar archief</string>
<string name="rcv_group_event_updated_group_profile">bijgewerkt groep profiel</string>
<string name="group_member_status_removed">verwijderd</string>
<string name="group_main_profile_sent">Uw chatprofiel wordt verzonden naar de groepsleden</string>
@@ -601,14 +601,11 @@
<string name="wrong_passphrase">Nieprawidłowe hasło bazy danych</string>
<string name="wrong_passphrase_title">Nieprawidłowe hasło!</string>
<string name="you_have_to_enter_passphrase_every_time">Musisz wprowadzić hasło przy każdym uruchomieniu aplikacji - nie jest one przechowywane na urządzeniu.</string>
<string name="chat_archive_header">Archiwum czatu</string>
<string name="chat_archive_section">ARCHIWUM CZATU</string>
<string name="chat_is_stopped_indication">Czat jest zatrzymany</string>
<string name="confirm_database_upgrades">Potwierdź aktualizacje bazy danych</string>
<string name="database_downgrade">Obniż wersję bazy danych</string>
<string name="database_upgrade">Aktualizacja bazy danych</string>
<string name="mtr_error_no_down_migration">wersja bazy danych jest nowsza od aplikacji, ale nie ma migracji w dół dla: %s</string>
<string name="delete_archive">Usuń archiwum</string>
<string name="mtr_error_different">różne migracje w aplikacji/bazy danych: %s / %s</string>
<string name="downgrade_and_open_chat">Obniż wersję i otwórz czat</string>
<string name="icon_descr_group_inactive">Grupa nieaktywna</string>
@@ -630,7 +627,6 @@
<string name="restore_database">Przywróć kopię zapasową bazy danych</string>
<string name="restore_database_alert_title">Przywrócić kopię zapasową bazy danych\?</string>
<string name="database_restore_error">Błąd przywracania bazy danych</string>
<string name="save_archive">Zapisz archiwum</string>
<string name="database_backup_can_be_restored">Próba zmiany hasła bazy danych nie została zakończona.</string>
<string name="alert_message_no_group">Ta grupa już nie istnieje.</string>
<string name="upgrade_and_open_chat">Zaktualizuj i otwórz czat</string>
@@ -925,13 +921,11 @@
<string name="delete_contact_all_messages_deleted_cannot_undo_warning">Kontakt i wszystkie wiadomości zostaną usunięte - nie można tego cofnąć!</string>
<string name="connection_error_auth">Błąd połączenia (UWIERZYTELNIANIE)</string>
<string name="connect_via_link_or_qr">Połącz się przez link / kod QR</string>
<string name="archive_created_on_ts">Utworzony na %1$s</string>
<string name="create_group">Utwórz tajną grupę</string>
<string name="create_secret_group_title">Utwórz tajną grupę</string>
<string name="set_password_to_export_desc">Baza danych jest zaszyfrowana przy użyciu losowego hasła. Proszę zmienić je przed eksportem.</string>
<string name="ttl_days">%d dni</string>
<string name="delete_group_menu_action">Usuń</string>
<string name="delete_chat_archive_question">Usunąć archiwum czatu\?</string>
<string name="delete_messages_after">Usuń wiadomości po</string>
<string name="disappearing_messages_are_prohibited">Znikające wiadomości są zabronione w tej grupie.</string>
<string name="error_deleting_contact_request">Błąd usuwania prośby o kontakt</string>
@@ -57,7 +57,6 @@
<string name="keychain_is_storing_securely">Android Keystore é usada para armazenar a senha com segurança - permite que o serviço de notificação funcione.</string>
<string name="keychain_allows_to_receive_ntfs">A Android Keystore será usada para armazenar a senha com segurança depois que você reiniciar o aplicativo ou alterar a senha - isso permitirá o recebimento de notificações.</string>
<string name="cannot_access_keychain">Não é possível acessar a Keystore para salvar a senha do banco de dados</string>
<string name="chat_archive_section">ARQUIVO DE BATE-PAPO</string>
<string name="chat_is_stopped_indication">O bate-papo está parado</string>
<string name="clear_contacts_selection_button">Limpar</string>
<string name="chat_preferences">Preferências de bate-papo</string>
@@ -81,7 +80,6 @@
<string name="chat_is_running">O bate-papo está em execução</string>
<string name="chat_is_stopped">O bate-papo está parado</string>
<string name="change_database_passphrase_question">Alterar senha do banco de dados\?</string>
<string name="chat_archive_header">Arquivo de chat</string>
<string name="rcv_conn_event_switch_queue_phase_completed">endereço alterado para você</string>
<string name="both_you_and_your_contact_can_send_disappearing">Você e seu contato podem enviar mensagens temporárias.</string>
<string name="full_backup">Backup de dados do aplicativo</string>
@@ -180,8 +178,6 @@
<string name="confirm_new_passphrase">Confirmar nova senha…</string>
<string name="current_passphrase">Senha atual…</string>
<string name="database_passphrase_is_required">Senha do banco de dados é necessária para abrir o chat.</string>
<string name="delete_archive">Excluir arquivo</string>
<string name="delete_chat_archive_question">Excluir arquivo de chat\?</string>
<string name="rcv_group_event_changed_member_role">cargo alterado de %s para %s</string>
<string name="rcv_group_event_member_connected">conectado</string>
<string name="delete_link">Excluir link</string>
@@ -218,7 +214,6 @@
<string name="connection_error_auth">Erro de conexão (AUTH)</string>
<string name="display_name_connection_established">conexão estabelecida</string>
<string name="connection_local_display_name">conexão %1$d</string>
<string name="archive_created_on_ts">Criado em %1$s</string>
<string name="maximum_supported_file_size">Atualmente, o tamanho máximo de arquivo suportado é %1$s.</string>
<string name="delete_verb">Excluir</string>
<string name="database_encryption_will_be_updated">Ssnha de criptografia do banco de dados será atualizada e armazenada na Keystore.</string>
@@ -685,7 +680,6 @@
<string name="delete_chat_profile_action_cannot_be_undone_warning">Esta ação não pode ser desfeita - seu perfil, contatos, mensagens e arquivos serão irreversivelmente perdidos.</string>
<string name="remove_passphrase">Remover</string>
<string name="wrong_passphrase">Senha do banco de dados incorreta</string>
<string name="save_archive">Salvar arquivo</string>
<string name="restore_passphrase_not_found_desc">Senha não encontrada na Keystore, por favor digite-a manualmente. Isso pode ter ocorrido se você recuperou os dados do app usando uma ferramenta de backup. Se esse não é o caso, por favor, contate os desenvolvedores.</string>
<string name="youve_accepted_group_invitation_connecting_to_inviting_group_member">Você se juntou a este grupo. Conectando-se a um membro convidado do grupo.</string>
<string name="leave_group_question">Sair do grupo\?</string>
@@ -33,7 +33,6 @@
<string name="settings_section_title_icon">ÍCONE DA APLICAÇÃO</string>
<string name="chat_item_ttl_month">1 mês</string>
<string name="messages_section_title">Mensagens</string>
<string name="chat_archive_section">ARQUIVO DE CONVERSA</string>
<string name="button_add_welcome_message">Adicionar mensagem de boas-vindas</string>
<string name="users_add">Adicional perfil</string>
<string name="users_delete_data_only">Apenas dados de perfil local</string>
@@ -135,11 +134,8 @@
<string name="delete_after">Eliminar após</string>
<string name="delete_verb">Eliminar</string>
<string name="delete_contact_menu_action">Eliminar</string>
<string name="chat_archive_header">Arquivo de conversa</string>
<string name="delete_group_menu_action">Eliminar</string>
<string name="delete_files_and_media_all">Eliminar todos os ficheiros</string>
<string name="delete_archive">Eliminar arquivo</string>
<string name="delete_chat_archive_question">Eliminar arquivo de conversa\?</string>
<string name="delete_database">Eliminar base de dados</string>
<string name="chat_database_section">BASE DE DADOS DE CONVERSA</string>
<string name="chat_database_deleted">Base de dados de conversa eliminada</string>
@@ -355,7 +351,6 @@
<string name="contribute">Contribuir</string>
<string name="copy_verb">Copiar</string>
<string name="core_version">Versão principal: v%s</string>
<string name="archive_created_on_ts">Criado a %1$s</string>
<string name="create_group_link">Criar ligação de grupo</string>
<string name="v4_2_group_links">Ligações de grupo</string>
<string name="callstatus_connecting">conectando chamada…</string>
@@ -383,7 +378,6 @@
<string name="save_and_update_group_profile">Salvar e atualizar o perfil do grupo</string>
<string name="network_options_save">Salvar</string>
<string name="save_passphrase_and_open_chat">Salvar senha e abrir conversa</string>
<string name="save_archive">Salvar arquivo</string>
<string name="join_group_incognito_button">Junte-se em modo anónimo</string>
<string name="delete_link">Apagar ligação</string>
<string name="address_section_title">Endereço</string>
@@ -229,7 +229,6 @@
<string name="smp_save_servers_question">Salvezi servere?</string>
<string name="icon_descr_call_rejected">Apel respins</string>
<string name="saved_message_title">Mesaj salvat</string>
<string name="save_archive">Salvează arhiva</string>
<string name="restart_the_app_to_create_a_new_chat_profile">Repornește aplicația pentru a crea un nou profil</string>
<string name="save_passphrase_in_keychain">Salvează fraza de acces în Keystore</string>
<string name="save_group_profile">Salvează profilul grupului</string>
@@ -441,7 +440,6 @@
<string name="your_chat_database">Baza ta de date a conversațiilor</string>
<string name="database_is_not_encrypted">Baza ta de date a conversațiilor nu este criptată - setează frază de acces pentru a o proteja.</string>
<string name="database_encryption_will_be_updated_in_settings">Fraza de acces de criptare a bazei de date va fi actualizată și stocată în setări.</string>
<string name="archive_created_on_ts">Creat pe %1$s</string>
<string name="snd_group_event_changed_member_role">ai schimbat rolul %s la %s</string>
<string name="alert_title_cant_invite_contacts">Nu se pot invita contactele!</string>
<string name="you_joined_this_group">Te-ai alăturat grupului</string>
@@ -595,7 +593,6 @@
<string name="chat_console">Consolă conversație</string>
<string name="confirm_password">Confirmați parola</string>
<string name="colored_text">colorat</string>
<string name="chat_archive_header">Arhivă conversație</string>
<string name="migrate_from_device_all_data_will_be_uploaded">Toate contactele, conversațiile și fișierele dumneavoastră vor fi encriptate într-un mod sigur și încărcate pe bucăți pe releurile XFTP configurate.</string>
<string name="icon_descr_video_asked_to_receive">Rugat să primească videoclipul</string>
<string name="smp_server_test_compare_file">Comparați fișierul</string>
@@ -616,7 +613,6 @@
<string name="migrate_from_device_using_on_two_device_breaks_encryption"><![CDATA[<b>Vă rugăm să rețineți</b>: folosind aceeași bază de date pe două dispozitive, va intrerupe decripția mesajelor de la conexiunile dumneavoastră, ca protecție de securitate.]]></string>
<string name="migrate_from_device_confirm_upload">Confirmați încărcarea</string>
<string name="migrate_from_device_confirm_you_remember_passphrase">Confirmați că țineți minte parola de la baza de date pentru a o migra.</string>
<string name="chat_archive_section">ARHIVĂ CONVERSAȚIE</string>
<string name="info_row_connection">Conexiune</string>
<string name="delete_chat_profile_question">Ștergi profilul de conversație?</string>
<string name="for_me_only">Șterge pentru mine</string>
@@ -626,7 +622,6 @@
<string name="info_row_deleted_at">Șters la</string>
<string name="desktop_app_version_is_incompatible">Versiunea aplicației desktop %s nu este compatibilă cu această aplicație.</string>
<string name="delete_member_message__question">Ștergi mesajul membrului?</string>
<string name="delete_archive">Șterge arhiva</string>
<string name="button_delete_group">Șterge grup</string>
<string name="delete_and_notify_contact">Șterge și notifică contactele</string>
<string name="decentralized">Decentralizat</string>
@@ -652,7 +647,6 @@
<string name="delete_contact_menu_action">Șterge</string>
<string name="delete_group_menu_action">Șterge</string>
<string name="delete_files_and_media_question">Ștergi fișiere și media?</string>
<string name="delete_chat_archive_question">Ștergi arhiva conversației?</string>
<string name="ttl_days">%d zile</string>
<string name="ttl_day">%d zi</string>
<string name="delete_address">Șterge adresa</string>
@@ -676,12 +676,6 @@
<string name="chat_is_stopped_indication">Чат остановлен</string>
<string name="you_can_start_chat_via_setting_or_by_restarting_the_app">Вы можете запустить чат через Настройки приложения или перезапустив приложение.</string>
<!-- ChatArchiveView.kt -->
<string name="chat_archive_header">Архив чата</string>
<string name="chat_archive_section">АРХИВ ЧАТА</string>
<string name="save_archive">Сохранить архив</string>
<string name="delete_archive">Удалить архив</string>
<string name="archive_created_on_ts">Дата создания %1$s</string>
<string name="delete_chat_archive_question">Удалить архив чата?</string>
<!-- Groups -->
<string name="group_invitation_item_description">приглашение в группу %1$s</string>
<string name="join_group_question">Вступить в группу?</string>
@@ -160,7 +160,6 @@
<string name="connection_timeout">หมดเวลาการเชื่อมต่อ</string>
<string name="connect_via_group_link">เชื่อมต่อผ่านลิงค์กลุ่ม\?</string>
<string name="delete_contact_all_messages_deleted_cannot_undo_warning">ผู้ติดต่อและข้อความทั้งหมดจะถูกลบ - ไม่สามารถยกเลิกได้!</string>
<string name="archive_created_on_ts">สร้างเมื่อ %1$s</string>
<string name="maximum_supported_file_size">ขนาดไฟล์สูงสุดที่รองรับในปัจจุบันคือ %1$s</string>
<string name="v5_1_custom_themes">ธีมที่กำหนดเอง</string>
<string name="developer_options">ID ฐานข้อมูลและตัวเลือกการแยกการส่งผ่าน</string>
@@ -239,8 +238,6 @@
<string name="database_error">ความผิดพลาดในฐานข้อมูล</string>
<string name="confirm_database_upgrades">ยืนยันการอัพเกรดฐานข้อมูล</string>
<string name="database_downgrade">ดาวน์เกรดฐานข้อมูล</string>
<string name="chat_archive_header">ที่เก็บแชทถาวร</string>
<string name="chat_archive_section">ที่เก็บแชทถาวร</string>
<string name="chat_is_stopped_indication">การแชทหยุดทํางานแล้ว</string>
<string name="rcv_group_event_member_connected">เชื่อมต่อสำเร็จ</string>
<string name="rcv_conn_event_switch_queue_phase_changing">กำลังเปลี่ยนที่อยู่…</string>
@@ -432,8 +429,6 @@
<string name="mtr_error_no_down_migration">เวอร์ชันฐานข้อมูลใหม่กว่าแอป แต่ไม่มีการย้ายข้อมูลลงสำหรับ: %s</string>
<string name="mtr_error_different">การย้ายข้อมูลที่แตกต่างกันในแอป/ฐานข้อมูล: %s / %s</string>
<string name="downgrade_and_open_chat">ปรับลดรุ่นและเปิดแชท</string>
<string name="delete_archive">ลบที่เก็บถาวร</string>
<string name="delete_chat_archive_question">ลบที่เก็บแชทถาวร\?</string>
<string name="icon_descr_group_inactive">กลุ่มที่ไม่ได้ใช้งาน</string>
<string name="alert_title_no_group">ไม่พบกลุ่ม!</string>
<string name="group_invitation_expired">คำเชิญเข้าร่วมกลุ่มหมดอายุแล้ว</string>
@@ -837,7 +832,6 @@
<string name="restore_database_alert_confirm">คืนค่า</string>
<string name="restore_database_alert_title">คืนค่าฐานข้อมูลสำรองไหม\?</string>
<string name="database_restore_error">กู้คืนข้อผิดพลาดของฐานข้อมูล</string>
<string name="save_archive">บันทึกไฟล์เก็บถาวร</string>
<string name="rcv_group_event_member_deleted">ลบแล้ว %1$s</string>
<string name="rcv_group_event_user_deleted">ลบคุณออกแล้ว</string>
<string name="group_member_status_removed">ถูกลบแล้ว</string>
@@ -106,7 +106,6 @@
<string name="restore_database_alert_title">Veri tabanı yedeğini geri yükle\?</string>
<string name="database_restore_error">Veri tabanını geri yüklerken hata</string>
<string name="database_downgrade">Veritabanı sürüm düşürme</string>
<string name="save_archive">Arşivi kaydet</string>
<string name="current_version_timestamp">%s (mevcut)</string>
<string name="save_and_update_group_profile">Kaydet ve grup profilini güncelle</string>
<string name="save_welcome_message_question">Karşılama mesajı kaydedilsin mi?</string>
@@ -429,9 +428,6 @@
<string name="set_password_to_export_desc">Veri tabanı, rastgele bir parola ile şifrelendi. Dışa aktarmadan önce lütfen değiştir.</string>
<string name="delete_files_and_media_question">Dosyaları ve medyayı sil\?</string>
<string name="database_will_be_encrypted">Veri tabanı şifrelenecektir.</string>
<string name="archive_created_on_ts">%1$s tarihinde oluşturuldu</string>
<string name="delete_archive">Belgeliği sil</string>
<string name="delete_chat_archive_question">Konuşma belgeliğini sil\?</string>
<string name="rcv_group_event_changed_member_role">%s üyesinin yetkisi %s olarak değiştirildi</string>
<string name="rcv_group_event_group_deleted">silinmiş grup</string>
<string name="snd_group_event_changed_role_for_yourself">kendi yetkini, %s olarak değiştirdin</string>
@@ -740,8 +736,6 @@
<string name="status_contact_has_no_e2e_encryption">kişi uçtan uca şifrelemeye sahip değildir</string>
<string name="chat_is_stopped">Sohbet durduruldu</string>
<string name="impossible_to_recover_passphrase"><![CDATA[<b>Aklınızda bulunsun</b>: kaybederseniz, parolayı kurtaramaz veya değiştiremezsiniz.]]></string>
<string name="chat_archive_header">Sohbet arşivi</string>
<string name="chat_archive_section">SOHBET ARŞİVİ</string>
<string name="group_invitation_item_description">%1$s grubuna davet</string>
<string name="join_group_question">Gruba katıl\?</string>
<string name="rcv_group_event_member_added">%1$s davet edildi</string>
@@ -294,8 +294,6 @@
<string name="encrypt_database_question">Зашифрувати базу даних\?</string>
<string name="wrong_passphrase_title">Неправильна ключова фраза!</string>
<string name="enter_correct_passphrase">Введіть правильну ключову фразу.</string>
<string name="chat_archive_header">Архів чату</string>
<string name="chat_archive_section">АРХІВ ЧАТУ</string>
<string name="rcv_group_event_member_connected">підключив(лась)</string>
<string name="rcv_group_event_changed_your_role">змінив(ла) вашу роль на %s</string>
<string name="snd_group_event_changed_role_for_yourself">ви змінили свою роль на %s</string>
@@ -375,7 +373,6 @@
<string name="call_on_lock_screen">Виклики на екрані блокування:</string>
<string name="call_connection_peer_to_peer">від абонента до абонента</string>
<string name="icon_descr_hang_up">Завершити дзвінок</string>
<string name="archive_created_on_ts">Створено %1$s</string>
<string name="icon_descr_expand_role">Розгорнути вибір ролі</string>
<string name="chat_preferences_yes">так</string>
<string name="contact_preferences">Налаштування контакту</string>
@@ -528,7 +525,6 @@
<string name="icon_descr_video_on">Відео увімкнено</string>
<string name="alert_text_fragment_encryption_out_of_sync_old_database">Це може трапитися, якщо ви або ваше з\'єднання використовували застарілу резервну копію бази даних.</string>
<string name="restore_database">Відновити резервну копію бази даних</string>
<string name="save_archive">Зберегти архів</string>
<string name="group_invitation_item_description">запрошення до групи %1$s</string>
<string name="you_are_invited_to_group_join_to_connect_with_group_members">Вас запрошено в групу. Приєднуйтесь, щоб спілкуватися з учасниками групи.</string>
<string name="message_reactions">Реакції на повідомлення</string>
@@ -1070,8 +1066,6 @@
<string name="database_passphrase_is_required">Для відкриття чату потрібна ключова фраза бази даних.</string>
<string name="join_group_question">Приєднатися до групи\?</string>
<string name="database_upgrade">Оновлення бази даних</string>
<string name="delete_archive">Видалити архів</string>
<string name="delete_chat_archive_question">Видалити архів чату\?</string>
<string name="leave_group_question">Вийти з групи?</string>
<string name="alert_title_no_group">Групу не знайдено!</string>
<string name="alert_message_no_group">Ця група більше не існує.</string>
@@ -226,8 +226,6 @@
<string name="change_role">Thay đổi quyền hạn</string>
<string name="snd_conn_event_switch_queue_phase_changing">đang thay đổi địa chỉ…</string>
<string name="rcv_conn_event_switch_queue_phase_changing">đang thay đổi địa chỉ…</string>
<string name="chat_archive_section">KHO LƯU TRỮ SIMPLEX CHAT</string>
<string name="chat_archive_header">Kho lưu trữ SimpleX Chat</string>
<string name="chat_console">Bảng điều khiển trò chuyện</string>
<string name="chat_is_running">Ứng dụng SimpleX Chat đang hoạt động</string>
<string name="chat_database_deleted">Cơ sở dữ liệu SimpleX Chat đã bị xóa</string>
@@ -361,7 +359,6 @@
<string name="button_create_group_link">Tạo liên kết</string>
<string name="info_row_created_at">Được tạo ra tại</string>
<string name="create_address">Tạo địa chỉ</string>
<string name="archive_created_on_ts">Được tạo ra vào %1$s</string>
<string name="share_text_created_at">Được tạo ra tại: %s</string>
<string name="create_chat_profile">Tạo hồ sơ trò chuyện</string>
<string name="create_group_button">Tạo nhóm</string>
@@ -437,9 +434,7 @@
<string name="delete_database">Xóa cơ sở dữ liệu</string>
<string name="delete_files_and_media_all">Xóa tất cả các tệp</string>
<string name="delete_files_and_media_question">Xóa tệp và đa phương tiện?</string>
<string name="delete_archive">Xóa kho lữu trữ</string>
<string name="chat_preferences_default">mặc định (%s)</string>
<string name="delete_chat_archive_question">Xóa kho lữu trữ SimpleX Chat?</string>
<string name="rcv_group_event_group_deleted">đã xóa nhóm</string>
<string name="smp_server_test_delete_file">Xóa tệp</string>
<string name="delete_contact_question">Xóa liên hệ?</string>
@@ -47,7 +47,6 @@
<string name="delete_group_menu_action">删除</string>
<string name="delete_address__question">删除地址?</string>
<string name="delete_after">在此后删除</string>
<string name="delete_archive">删除档案</string>
<string name="deleted_description">已删除</string>
<string name="delete_files_and_media_question">删除文件和媒体文件?</string>
<string name="full_deletion">为所有人删除</string>
@@ -81,7 +80,6 @@
<string name="allow_direct_messages">允许向成员发送私信。</string>
<string name="allow_to_send_disappearing">允许发送限时消息。</string>
<string name="delete_address">删除地址</string>
<string name="delete_chat_archive_question">删除聊天档案?</string>
<string name="users_delete_question">删除聊天资料?</string>
<string name="button_delete_contact">删除联系人</string>
<string name="delete_contact_question">删除联系人?</string>
@@ -161,8 +159,6 @@
<string name="chat_database_deleted">聊天数据库已删除</string>
<string name="chat_database_imported">聊天数据库已导入</string>
<string name="keychain_error">钥匙串错误</string>
<string name="chat_archive_section">聊天档案</string>
<string name="chat_archive_header">聊天档案</string>
<string name="chat_console">聊天控制台</string>
<string name="chat_database_section">聊天数据库</string>
<string name="chat_is_stopped_indication">聊天已停止</string>
@@ -719,7 +715,6 @@
<string name="reply_verb">回复</string>
<string name="network_options_reset_to_defaults">重置为默认</string>
<string name="run_chat_section">运行聊天程序</string>
<string name="save_archive">保存存档</string>
<string name="scan_code">扫码</string>
<string name="scan_code_from_contacts_app">从您联系人的应用程序中扫描安全码。</string>
<string name="security_code">安全码</string>
@@ -873,7 +868,6 @@
<string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[您可以控制通过哪些服务器<b>接收</b>消息,您的联系人 - 您用来向他们发送消息的服务器。]]></string>
<string name="you_will_be_connected_when_group_host_device_is_online">您将在组主设备上线时连接到该群组,请稍等或稍后再检查!</string>
<string name="auth_you_will_be_required_to_authenticate_when_you_start_or_resume">当您启动应用或在应用程序驻留后台超过30 秒后,您将需要进行身份验证。</string>
<string name="archive_created_on_ts">创建于 %1$s</string>
<string name="you_can_connect_to_simplex_chat_founder"><![CDATA[您可以 <font color="#0088ff"> 连接到 SimpleX Chat 开发者提出任何问题并接收更新 </font>。]]></string>
<string name="you_accepted_connection">您已接受连接</string>
<string name="your_SMP_servers">您的 SMP 服务器</string>
@@ -632,7 +632,6 @@
<string name="chat_item_ttl_seconds">%s 秒(s)</string>
<string name="error_encrypting_database">加密數據庫時出錯</string>
<string name="save_passphrase_in_keychain">在金鑰庫儲存密碼</string>
<string name="archive_created_on_ts">建立於 %1$s</string>
<string name="restore_database">還原數據庫的備份</string>
<string name="icon_descr_group_inactive">群組為不活躍狀態</string>
<string name="alert_title_group_invitation_expired">邀請連結過時!</string>
@@ -700,8 +699,6 @@
<string name="restore_database_alert_confirm">還原</string>
<string name="restore_database_alert_title">還原數據庫的備份?</string>
<string name="database_restore_error">還原數據庫時出錯</string>
<string name="save_archive">儲存存檔</string>
<string name="delete_archive">刪除存檔</string>
<string name="join_group_button">加入</string>
<string name="join_group_question">確定要加入群組?</string>
<string name="join_group_incognito_button">加入匿名聊天模式</string>
@@ -777,7 +774,6 @@
<string name="error_exporting_chat_database">匯出數據庫時出錯</string>
<string name="error_importing_database">匯入數據庫時出錯</string>
<string name="database_passphrase_will_be_updated">受加密的數據庫密碼會再次更新。</string>
<string name="delete_chat_archive_question">刪除封存對話?</string>
<string name="encrypt_database_question">加密數據庫?</string>
<string name="group_invitation_item_description">邀請至群組 %1$s</string>
<string name="icon_descr_add_members">邀請成員</string>
@@ -799,13 +795,11 @@
<string name="status_contact_has_no_e2e_encryption">對話沒有經過端對端加密</string>
<string name="database_encrypted">數據庫已加密!</string>
<string name="encrypted_database">已加密數據庫</string>
<string name="chat_archive_section">封存對話</string>
<string name="snd_group_event_group_profile_updated">群組資料已經更新</string>
<string name="group_member_role_member">成員</string>
<string name="group_info_member_you">你:%1$s</string>
<string name="button_delete_group">刪除群組</string>
<string name="v4_4_live_messages">即時訊息</string>
<string name="chat_archive_header">封存對話</string>
<string name="error_removing_member">移除成員時出錯</string>
<string name="error_changing_role">修改身份時出錯</string>
<string name="info_row_group">群組</string>
@@ -3,6 +3,7 @@ package chat.simplex.common.platform
import chat.simplex.common.model.*
import chat.simplex.common.simplexWindowState
import chat.simplex.common.views.call.RcvCallInvitation
import chat.simplex.common.views.database.deleteOldChatArchive
import chat.simplex.common.views.helpers.*
import java.util.*
import chat.simplex.res.MR
@@ -30,6 +31,7 @@ fun initApp() {
override fun showMessage(title: String, text: String) = chat.simplex.common.model.NtfManager.showMessage(title, text)
}
applyAppLocale()
deleteOldChatArchive()
if (DatabaseUtils.ksSelfDestructPassword.get() == null) {
initChatControllerOnStart()
}
@@ -9,14 +9,14 @@ import kotlinx.datetime.Instant
actual fun restartChatOrApp() {
if (chatModel.chatRunning.value == false) {
chatModel.chatDbChanged.value = true
startChat(chatModel, mutableStateOf(Instant.DISTANT_PAST), chatModel.chatDbChanged)
startChat(chatModel, mutableStateOf(Instant.DISTANT_PAST), chatModel.chatDbChanged, mutableStateOf(false))
} else {
authStopChat(chatModel) {
withBGApi {
// adding delay in order to prevent locked database by previous initialization
delay(1000)
chatModel.chatDbChanged.value = true
startChat(chatModel, mutableStateOf(Instant.DISTANT_PAST), chatModel.chatDbChanged)
startChat(chatModel, mutableStateOf(Instant.DISTANT_PAST), chatModel.chatDbChanged, mutableStateOf(false))
}
}
}