From ab47a5a27e76620d11edefcea257fc3773cb059a Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Fri, 24 May 2024 22:59:37 +0100 Subject: [PATCH 01/21] Revert "ui: comment smp proxy ui (#4204)" This reverts commit a0d6ae15ab10b711b596ca3d5052e3950aee43c3. --- .../UserSettings/NetworkAndServers.swift | 46 +++++++++---------- .../views/usersettings/NetworkAndServers.kt | 22 ++++----- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift index 54a4ef1489..6d849479e5 100644 --- a/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift +++ b/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift @@ -82,29 +82,29 @@ struct NetworkAndServers: View { Text("Using .onion hosts requires compatible VPN provider.") } -// Section { -// Picker("Private routing", selection: $proxyMode) { -// ForEach(SMPProxyMode.values, id: \.self) { Text($0.text) } -// } -// .frame(height: 36) -// -// Picker("Allow downgrade", selection: $proxyFallback) { -// ForEach(SMPProxyFallback.values, id: \.self) { Text($0.text) } -// } -// .disabled(proxyMode == .never) -// .frame(height: 36) -// -// Toggle("Show message status", isOn: $showSentViaProxy) -// } header: { -// Text("Private message routing") -// } footer: { -// VStack(alignment: .leading) { -// Text("To protect your IP address, private routing uses your SMP servers to deliver messages.") -// if showSentViaProxy { -// Text("Show → on messages sent via private routing.") -// } -// } -// } + Section { + Picker("Private routing", selection: $proxyMode) { + ForEach(SMPProxyMode.values, id: \.self) { Text($0.text) } + } + .frame(height: 36) + + Picker("Allow downgrade", selection: $proxyFallback) { + ForEach(SMPProxyFallback.values, id: \.self) { Text($0.text) } + } + .disabled(proxyMode == .never) + .frame(height: 36) + + Toggle("Show message status", isOn: $showSentViaProxy) + } header: { + Text("Private message routing") + } footer: { + VStack(alignment: .leading) { + Text("To protect your IP address, private routing uses your SMP servers to deliver messages.") + if showSentViaProxy { + Text("Show → on messages sent via private routing.") + } + } + } Section("Calls") { NavigationLink { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NetworkAndServers.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NetworkAndServers.kt index b2124df988..d07fad8623 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NetworkAndServers.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NetworkAndServers.kt @@ -250,17 +250,17 @@ fun NetworkAndServersView() { Divider(Modifier.padding(start = DEFAULT_PADDING_HALF, top = 24.dp, end = DEFAULT_PADDING_HALF, bottom = 30.dp)) } -// if (currentRemoteHost == null) { -// SectionView(generalGetString(MR.strings.settings_section_title_private_message_routing)) { -// SMPProxyModePicker(smpProxyMode, showModal, updateSMPProxyMode) -// SMPProxyFallbackPicker(smpProxyFallback, showModal, updateSMPProxyFallback, enabled = remember { mutableStateOf(smpProxyMode.value != SMPProxyMode.Never) }) -// SettingsPreferenceItem(painterResource(MR.images.ic_arrow_forward), stringResource(MR.strings.private_routing_show_message_status), chatModel.controller.appPrefs.showSentViaProxy) -// } -// SectionCustomFooter { -// Text(stringResource(MR.strings.private_routing_explanation)) -// } -// Divider(Modifier.padding(start = DEFAULT_PADDING_HALF, top = 32.dp, end = DEFAULT_PADDING_HALF, bottom = 30.dp)) -// } + if (currentRemoteHost == null) { + SectionView(generalGetString(MR.strings.settings_section_title_private_message_routing)) { + SMPProxyModePicker(smpProxyMode, showModal, updateSMPProxyMode) + SMPProxyFallbackPicker(smpProxyFallback, showModal, updateSMPProxyFallback, enabled = remember { mutableStateOf(smpProxyMode.value != SMPProxyMode.Never) }) + SettingsPreferenceItem(painterResource(MR.images.ic_arrow_forward), stringResource(MR.strings.private_routing_show_message_status), chatModel.controller.appPrefs.showSentViaProxy) + } + SectionCustomFooter { + Text(stringResource(MR.strings.private_routing_explanation)) + } + Divider(Modifier.padding(start = DEFAULT_PADDING_HALF, top = 32.dp, end = DEFAULT_PADDING_HALF, bottom = 30.dp)) + } SectionView(generalGetString(MR.strings.settings_section_title_calls)) { SettingsActionItem(painterResource(MR.images.ic_electrical_services), stringResource(MR.strings.webrtc_ice_servers), { ModalManager.start.showModal { RTCServersView(m) } }) From bf91666f07528f6229b38177b152c987c9bcb691 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Sat, 25 May 2024 15:52:16 +0700 Subject: [PATCH 02/21] android, desktop: wallpapers (#4109) * android, desktop: wallpapers * changes * removed unused * changes * backgrounds moved to themes. can be exported/imported * changes and refactoring * scrollable * change * reorder * theme per background * changes * don't drop customization in same cases * changes * changes * fix state update * different defaults * fix Android * removed migration * temporary * returned theme name as uppercase back * resilient to wrong preset name * more * live color change without button * fix * Revert "temporary" This reverts commit 705c92ee569ba6210b18b74ececd7cb890dffb2b. * changes * changes * almost candy * old picker and ability to specify hex color * different image * picker * user theme override, fixes, import/export theme with image * revert when about to merge: useful layout for theming * custom image displaying and deletion work correctly * performance * moved code up * changes * color changes in picker when changing themes * reset color without closing modal * unused * log * currentTheme instead of MaterialTheme * different inheritance logic * fix and move sent/received message colors to top * remove background * performance * fix wrong base * changes * fix * small * custom image selection made normally * better color picker * better picker * refactor, fixes, optimizations * working with unknown base theme + tests * change * delete wallpaper dir when importing archive * function rename * fix bug with state update * update colors * fix text colors * update images * changes * remote desktop and theme mode dropdown * default theme * additional accent 2 changes * fix default wallpaper * removed ChatListAlwaysVisible * renaming * update messages * changes * default theme * unused * member icon background color * image quality * fix wallpaper on empty notes screen * update colors * change * update colors * fix update on android * fix update on both platforms * update colors, remove serializable * fix color --------- Co-authored-by: Evgeny Poberezkin --- .../chat/simplex/app/MessagesFetcherWorker.kt | 4 +- .../main/java/chat/simplex/app/SimplexApp.kt | 6 +- .../java/chat/simplex/app/SimplexService.kt | 2 +- apps/multiplatform/common/build.gradle.kts | 3 + .../simplex/common/platform/Files.android.kt | 2 + .../common/platform/Resources.android.kt | 7 + .../views/usersettings/Appearance.android.kt | 31 +- .../chat/simplex/common/model/ChatModel.kt | 33 +- .../chat/simplex/common/model/SimpleXAPI.kt | 126 ++- .../other/wheel-picker/FWheelPickerDefault.kt | 4 +- .../chat/simplex/common/platform/AppCommon.kt | 6 + .../chat/simplex/common/platform/Core.kt | 15 +- .../chat/simplex/common/platform/Files.kt | 58 +- .../chat/simplex/common/platform/Resources.kt | 4 + .../chat/simplex/common/ui/theme/Color.kt | 13 +- .../chat/simplex/common/ui/theme/Theme.kt | 613 +++++++++-- .../simplex/common/ui/theme/ThemeManager.kt | 293 ++++-- .../simplex/common/views/chat/ChatInfoView.kt | 65 ++ .../common/views/chat/ChatItemInfoView.kt | 2 +- .../simplex/common/views/chat/ChatView.kt | 711 ++++++------- ...ComposeContextInvitingContactMemberView.kt | 2 +- .../common/views/chat/ComposeFileView.kt | 2 +- .../common/views/chat/ComposeImageView.kt | 2 +- .../simplex/common/views/chat/ComposeView.kt | 6 +- .../common/views/chat/ComposeVoiceView.kt | 2 +- .../common/views/chat/ContextItemView.kt | 4 +- .../views/chat/group/GroupChatInfoView.kt | 11 +- .../views/chat/item/CIGroupInvitationView.kt | 9 +- .../common/views/chat/item/CIMetaView.kt | 6 +- .../views/chat/item/CIRcvDecryptionError.kt | 11 +- .../common/views/chat/item/CIVoiceView.kt | 8 +- .../common/views/chat/item/ChatItemView.kt | 66 +- .../common/views/chat/item/DeletedItemView.kt | 4 +- .../common/views/chat/item/FramedItemView.kt | 26 +- .../views/chat/item/IntegrityErrorItemView.kt | 5 +- .../views/chat/item/MarkedDeletedItemView.kt | 4 +- .../common/views/chat/item/TextItemView.kt | 2 +- .../common/views/database/DatabaseView.kt | 2 + .../common/views/helpers/ChatInfoImage.kt | 8 +- .../common/views/helpers/ChatWallpaper.kt | 415 ++++++++ .../common/views/helpers/CloseSheetBar.kt | 2 +- .../common/views/helpers/LinkPreviews.kt | 2 +- .../simplex/common/views/helpers/ModalView.kt | 5 +- .../common/views/helpers/ThemeModeEditor.kt | 463 +++++++++ .../simplex/common/views/helpers/Utils.kt | 58 +- .../common/views/localauth/LocalAuthView.kt | 2 +- .../common/views/migration/MigrateToDevice.kt | 2 +- .../common/views/usersettings/Appearance.kt | 972 +++++++++++++++--- .../common/views/usersettings/SettingsView.kt | 2 +- .../commonMain/resources/MR/ar/strings.xml | 1 - .../commonMain/resources/MR/base/strings.xml | 43 +- .../commonMain/resources/MR/bg/strings.xml | 1 - .../commonMain/resources/MR/cs/strings.xml | 1 - .../commonMain/resources/MR/de/strings.xml | 1 - .../commonMain/resources/MR/es/strings.xml | 1 - .../commonMain/resources/MR/fi/strings.xml | 1 - .../commonMain/resources/MR/fr/strings.xml | 1 - .../commonMain/resources/MR/hi/strings.xml | 1 - .../commonMain/resources/MR/hu/strings.xml | 1 - .../resources/MR/images/wallpaper_cats@4x.png | Bin 0 -> 51580 bytes .../MR/images/wallpaper_flowers@4x.png | Bin 0 -> 177014 bytes .../MR/images/wallpaper_hearts@4x.png | Bin 0 -> 80475 bytes .../resources/MR/images/wallpaper_kids@4x.png | Bin 0 -> 171840 bytes .../MR/images/wallpaper_school@4x.png | Bin 0 -> 238390 bytes .../MR/images/wallpaper_travel@4x.png | Bin 0 -> 80606 bytes .../commonMain/resources/MR/it/strings.xml | 1 - .../commonMain/resources/MR/iw/strings.xml | 1 - .../commonMain/resources/MR/ja/strings.xml | 1 - .../commonMain/resources/MR/ko/strings.xml | 1 - .../commonMain/resources/MR/lt/strings.xml | 1 - .../commonMain/resources/MR/ml/strings.xml | 1 - .../commonMain/resources/MR/nl/strings.xml | 1 - .../commonMain/resources/MR/pl/strings.xml | 1 - .../resources/MR/pt-rBR/strings.xml | 1 - .../commonMain/resources/MR/pt/strings.xml | 1 - .../commonMain/resources/MR/ru/strings.xml | 1 - .../commonMain/resources/MR/th/strings.xml | 1 - .../commonMain/resources/MR/tr/strings.xml | 1 - .../commonMain/resources/MR/uk/strings.xml | 1 - .../resources/MR/zh-rCN/strings.xml | 1 - .../resources/MR/zh-rTW/strings.xml | 1 - .../kotlin/chat/simplex/app/ThemesTest.kt | 38 + .../kotlin/chat/simplex/common/DesktopApp.kt | 3 +- .../common/platform/AppCommon.desktop.kt | 2 +- .../simplex/common/platform/Files.desktop.kt | 2 + .../common/platform/Resources.desktop.kt | 18 +- .../simplex/common/ui/theme/Theme.desktop.kt | 4 + .../common/views/call/CallView.desktop.kt | 5 - .../views/usersettings/Appearance.desktop.kt | 24 +- .../kotlin/chat/simplex/desktop/Main.kt | 1 + 90 files changed, 3379 insertions(+), 887 deletions(-) create mode 100644 apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatWallpaper.kt create mode 100644 apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ThemeModeEditor.kt create mode 100644 apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_cats@4x.png create mode 100644 apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_flowers@4x.png create mode 100644 apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_hearts@4x.png create mode 100644 apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_kids@4x.png create mode 100644 apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_school@4x.png create mode 100644 apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_travel@4x.png create mode 100644 apps/multiplatform/common/src/commonTest/kotlin/chat/simplex/app/ThemesTest.kt diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/MessagesFetcherWorker.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/MessagesFetcherWorker.kt index 0152f5e8c2..64b6639a58 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/MessagesFetcherWorker.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/MessagesFetcherWorker.kt @@ -7,7 +7,7 @@ import chat.simplex.app.SimplexService.Companion.showPassphraseNotification import chat.simplex.common.model.ChatController import chat.simplex.common.views.helpers.DBMigrationResult import chat.simplex.common.platform.chatModel -import chat.simplex.common.platform.initChatControllerAndRunMigrations +import chat.simplex.common.platform.initChatControllerOnStart import chat.simplex.common.views.helpers.DatabaseUtils import kotlinx.coroutines.* import java.util.Date @@ -60,7 +60,7 @@ class MessagesFetcherWork( try { // In case of self-destruct is enabled the initialization process will not start in SimplexApp, Let's start it here if (DatabaseUtils.ksSelfDestructPassword.get() != null && chatModel.chatDbStatus.value == null) { - initChatControllerAndRunMigrations() + initChatControllerOnStart() } withTimeout(durationSeconds * 1000L) { val chatController = ChatController diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt index 83105c678a..95bba8e8a2 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt @@ -6,7 +6,6 @@ import android.content.Context import chat.simplex.common.platform.Log import android.content.Intent import android.content.pm.ActivityInfo -import android.media.AudioManager import android.os.* import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect @@ -66,6 +65,7 @@ class SimplexApp: Application(), LifecycleEventObserver { context = this initHaskell() initMultiplatform() + runMigrations() tmpDir.deleteRecursively() tmpDir.mkdir() @@ -74,7 +74,7 @@ class SimplexApp: Application(), LifecycleEventObserver { // It's important, otherwise, user may be locked in undefined state appPrefs.onboardingStage.set(OnboardingStage.Step1_SimpleXInfo) } else if (DatabaseUtils.ksAppPassword.get() == null || DatabaseUtils.ksSelfDestructPassword.get() == null) { - initChatControllerAndRunMigrations() + initChatControllerOnStart() } ProcessLifecycleOwner.get().lifecycle.addObserver(this@SimplexApp) } @@ -254,7 +254,7 @@ class SimplexApp: Application(), LifecycleEventObserver { override fun androidSetNightModeIfSupported() { if (Build.VERSION.SDK_INT < 31) return - val light = if (CurrentColors.value.name == DefaultTheme.SYSTEM.name) { + val light = if (CurrentColors.value.name == DefaultTheme.SYSTEM_THEME_NAME) { null } else { CurrentColors.value.colors.isLight diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt index f56bf4fe00..a5f5d84ec2 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt @@ -77,7 +77,7 @@ class SimplexService: Service() { isServiceStarted = true // In case of self-destruct is enabled the initialization process will not start in SimplexApp, Let's start it here if (DatabaseUtils.ksSelfDestructPassword.get() != null && chatModel.chatDbStatus.value == null) { - initChatControllerAndRunMigrations() + initChatControllerOnStart() } } } diff --git a/apps/multiplatform/common/build.gradle.kts b/apps/multiplatform/common/build.gradle.kts index 1f55a7195c..4fa865a6d3 100644 --- a/apps/multiplatform/common/build.gradle.kts +++ b/apps/multiplatform/common/build.gradle.kts @@ -53,6 +53,9 @@ kotlin { val commonTest by getting { dependencies { implementation(kotlin("test")) + implementation(kotlin("test-junit")) + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) } } val androidMain by getting { diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/Files.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/Files.android.kt index dfc8c1d4e7..ea092453ee 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/Files.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/Files.android.kt @@ -15,8 +15,10 @@ actual val dataDir: File = androidAppContext.dataDir actual val tmpDir: File = androidAppContext.getDir("temp", Application.MODE_PRIVATE) actual val filesDir: File = File(dataDir.absolutePath + File.separator + "files") actual val appFilesDir: File = File(filesDir.absolutePath + File.separator + "app_files") +actual val wallpapersDir: File = File(filesDir.absolutePath + File.separator + "assets" + File.separator + "wallpapers").also { it.mkdirs() } actual val coreTmpDir: File = File(filesDir.absolutePath + File.separator + "temp_files") actual val dbAbsolutePrefixPath: String = dataDir.absolutePath + File.separator + "files" +actual val preferencesDir = File(dataDir.absolutePath + File.separator + "shared_prefs") actual val chatDatabaseFileName: String = "files_chat.db" actual val agentDatabaseFileName: String = "files_agent.db" diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/Resources.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/Resources.android.kt index e15d1f9268..91d19759ea 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/Resources.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/Resources.android.kt @@ -7,6 +7,8 @@ import android.content.SharedPreferences import android.content.res.Configuration import android.text.BidiFormatter import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.Font @@ -14,9 +16,11 @@ import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import androidx.core.graphics.drawable.toBitmap import chat.simplex.common.model.AppPreferences import com.russhwolf.settings.Settings import com.russhwolf.settings.SharedPreferencesSettings +import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.desc.desc @@ -51,3 +55,6 @@ actual fun windowWidth(): Dp = LocalConfiguration.current.screenWidthDp.dp actual fun desktopExpandWindowToWidth(width: Dp) {} actual fun isRtl(text: CharSequence): Boolean = BidiFormatter.getInstance().isRtl(text) + +actual fun ImageResource.toComposeImageBitmap(): ImageBitmap? = + getDrawable(androidAppContext)?.toBitmap()?.asImageBitmap() diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/Appearance.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/Appearance.android.kt index 5a60e1d1b0..7cb5c77f6e 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/Appearance.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/Appearance.android.kt @@ -19,14 +19,10 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow -import androidx.compose.ui.graphics.* import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import dev.icerock.moko.resources.compose.stringResource import androidx.compose.ui.unit.dp -import androidx.core.content.ContextCompat -import androidx.core.graphics.drawable.toBitmap -import chat.simplex.common.R import chat.simplex.common.model.* import chat.simplex.common.ui.theme.* import chat.simplex.common.views.helpers.* @@ -34,7 +30,6 @@ import chat.simplex.common.model.ChatModel import chat.simplex.common.platform.* import chat.simplex.common.helpers.APPLICATION_ID import chat.simplex.common.helpers.saveAppLocale -import chat.simplex.common.views.usersettings.AppearanceScope.ColorEditor import chat.simplex.res.MR import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.resources.compose.painterResource @@ -46,9 +41,8 @@ enum class AppIcon(val image: ImageResource) { } @Composable -actual fun AppearanceView(m: ChatModel, showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit)) { +actual fun AppearanceView(m: ChatModel) { val appIcon = remember { mutableStateOf(findEnabledIcon()) } - fun setAppIcon(newIcon: AppIcon) { if (appIcon.value == newIcon) return val newComponent = ComponentName(APPLICATION_ID, "chat.simplex.app.MainActivity_${newIcon.name.lowercase()}") @@ -65,18 +59,11 @@ actual fun AppearanceView(m: ChatModel, showSettingsModal: (@Composable (ChatMod appIcon.value = newIcon } - AppearanceScope.AppearanceLayout( appIcon, m.controller.appPrefs.appLanguage, m.controller.appPrefs.systemDarkTheme, changeIcon = ::setAppIcon, - showSettingsModal = showSettingsModal, - editColor = { name, initialColor -> - ModalManager.start.showModalCloseable { close -> - ColorEditor(name, initialColor, close) - } - }, ) } @@ -86,8 +73,6 @@ fun AppearanceScope.AppearanceLayout( languagePref: SharedPreference, systemDarkTheme: SharedPreference, changeIcon: (AppIcon) -> Unit, - showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), - editColor: (ThemeColor, Color) -> Unit, ) { ColumnWithScrollBar( Modifier.fillMaxWidth(), @@ -120,6 +105,13 @@ fun AppearanceScope.AppearanceLayout( } // } } + + SectionDividerSpaced(maxTopPadding = true) + ThemesSection(systemDarkTheme) + + SectionDividerSpaced(maxTopPadding = true) + ProfileImageSection() + SectionDividerSpaced() SectionView(stringResource(MR.strings.settings_section_title_icon), padding = PaddingValues(horizontal = DEFAULT_PADDING_HALF)) { @@ -145,11 +137,6 @@ fun AppearanceScope.AppearanceLayout( } } - SectionDividerSpaced(maxTopPadding = true) - ProfileImageSection() - - SectionDividerSpaced(maxTopPadding = true) - ThemesSection(systemDarkTheme, showSettingsModal, editColor) SectionBottomSpacer() } } @@ -169,8 +156,6 @@ fun PreviewAppearanceSettings() { languagePref = SharedPreference({ null }, {}), systemDarkTheme = SharedPreference({ null }, {}), changeIcon = {}, - showSettingsModal = { {} }, - editColor = { _, _ -> }, ) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt index 56487874ba..74a54e54cf 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt @@ -4,7 +4,7 @@ import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.runtime.snapshots.SnapshotStateList import androidx.compose.runtime.snapshots.SnapshotStateMap -import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.* import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.font.* import androidx.compose.ui.text.style.TextDecoration @@ -399,6 +399,18 @@ object ChatModel { currentUser.value = updated } + fun updateCurrentUserUiThemes(rhId: Long?, uiThemes: ThemeModeOverrides?) { + val current = currentUser.value ?: return + val updated = current.copy( + uiThemes = uiThemes + ) + val i = users.indexOfFirst { it.user.userId == current.userId && it.user.remoteHostId == rhId } + if (i != -1) { + users[i] = users[i].copy(user = updated) + } + currentUser.value = updated + } + suspend fun addLiveDummy(chatInfo: ChatInfo): ChatItem { val cItem = ChatItem.liveDummy(chatInfo is ChatInfo.Direct) withContext(Dispatchers.Main) { @@ -682,7 +694,8 @@ data class User( override val showNtfs: Boolean, val sendRcptsContacts: Boolean, val sendRcptsSmallGroups: Boolean, - val viewPwdHash: UserPwdHash? + val viewPwdHash: UserPwdHash?, + val uiThemes: ThemeModeOverrides? = null, ): NamedChat, UserLike { override val displayName: String get() = profile.displayName override val fullName: String get() = profile.fullName @@ -709,6 +722,7 @@ data class User( sendRcptsContacts = true, sendRcptsSmallGroups = false, viewPwdHash = null, + uiThemes = null, ) } } @@ -1041,7 +1055,8 @@ data class Contact( override val updatedAt: Instant, val chatTs: Instant?, val contactGroupMemberId: Long? = null, - val contactGrpInvSent: Boolean + val contactGrpInvSent: Boolean, + val uiThemes: ThemeModeOverrides? = null, ): SomeChat, NamedChat { override val chatType get() = ChatType.Direct override val id get() = "@$contactId" @@ -1113,7 +1128,8 @@ data class Contact( createdAt = Clock.System.now(), updatedAt = Clock.System.now(), chatTs = Clock.System.now(), - contactGrpInvSent = false + contactGrpInvSent = false, + uiThemes = null, ) } } @@ -1253,7 +1269,8 @@ data class GroupInfo ( val chatSettings: ChatSettings, override val createdAt: Instant, override val updatedAt: Instant, - val chatTs: Instant? + val chatTs: Instant?, + val uiThemes: ThemeModeOverrides? = null, ): SomeChat, NamedChat { override val chatType get() = ChatType.Group override val id get() = "#$groupId" @@ -1295,7 +1312,8 @@ data class GroupInfo ( chatSettings = ChatSettings(enableNtfs = MsgFilter.All, sendRcpts = null, favorite = false), createdAt = Clock.System.now(), updatedAt = Clock.System.now(), - chatTs = Clock.System.now() + chatTs = Clock.System.now(), + uiThemes = null, ) } } @@ -1915,12 +1933,13 @@ data class ChatItem ( itemDeleted: CIDeleted? = null, itemEdited: Boolean = false, itemTimed: CITimed? = null, + itemLive: Boolean = false, deletable: Boolean = true, editable: Boolean = true ) = ChatItem( chatDir = dir, - meta = CIMeta.getSample(id, ts, text, status, sentViaProxy, itemForwarded, itemDeleted, itemEdited, itemTimed, deletable, editable), + meta = CIMeta.getSample(id, ts, text, status, sentViaProxy, itemForwarded, itemDeleted, itemEdited, itemTimed, itemLive, deletable, editable), content = CIContent.SndMsgContent(msgContent = MsgContent.MCText(text)), quotedItem = quotedItem, reactions = listOf(), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index ca237cd52f..40207a25ce 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -26,8 +26,7 @@ import kotlinx.coroutines.sync.withLock import kotlinx.datetime.Clock import kotlinx.datetime.Instant import kotlinx.serialization.* -import kotlinx.serialization.builtins.MapSerializer -import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.builtins.* import kotlinx.serialization.json.* import java.util.Date @@ -168,13 +167,20 @@ class AppPreferences { val selfDestruct = mkBoolPreference(SHARED_PREFS_SELF_DESTRUCT, false) val selfDestructDisplayName = mkStrPreference(SHARED_PREFS_SELF_DESTRUCT_DISPLAY_NAME, null) - val currentTheme = mkStrPreference(SHARED_PREFS_CURRENT_THEME, DefaultTheme.SYSTEM.name) - val systemDarkTheme = mkStrPreference(SHARED_PREFS_SYSTEM_DARK_THEME, DefaultTheme.SIMPLEX.name) - val themeOverrides = mkMapPreference(SHARED_PREFS_THEMES, mapOf(), encode = { + 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 = { + json.encodeToString(MapSerializer(String.serializer(), String.serializer()), it) + }, decode = { + json.decodeFromString(MapSerializer(String.serializer(), String.serializer()), it) + }) + // Deprecated. Remove key from preferences in 2025 + val themeOverridesOld = mkMapPreference(SHARED_PREFS_THEMES_OLD, mapOf(), encode = { json.encodeToString(MapSerializer(String.serializer(), ThemeOverrides.serializer()), it) }, decode = { - json.decodeFromString(MapSerializer(String.serializer(), ThemeOverrides.serializer()), it) + jsonCoerceInputValues.decodeFromString(MapSerializer(String.serializer(), ThemeOverrides.serializer()), it) }, settingsThemes) + val themeOverrides = mkThemeOverridesPreference() val profileImageCornerRadius = mkFloatPreference(SHARED_PREFS_PROFILE_IMAGE_CORNER_RADIUS, 22.5f) val whatsNewVersion = mkStrPreference(SHARED_PREFS_WHATS_NEW_VERSION, null) @@ -269,6 +275,12 @@ class AppPreferences { set = fun(value) = prefs.putString(prefName, encode(value)) ) + private fun mkThemeOverridesPreference(): SharedPreference> = + SharedPreference( + get = fun() = themeOverridesStore ?: (readThemeOverrides()).also { themeOverridesStore = it }, + set = fun(value) { if (writeThemeOverrides(value)) { themeOverridesStore = value } } + ) + companion object { const val SHARED_PREFS_ID = "chat.simplex.app.SIMPLEX_APP_PREFS" internal const val SHARED_PREFS_THEMES_ID = "chat.simplex.app.THEMES" @@ -345,8 +357,10 @@ class AppPreferences { private const val SHARED_PREFS_SELF_DESTRUCT_DISPLAY_NAME = "LocalAuthenticationSelfDestructDisplayName" private const val SHARED_PREFS_PQ_EXPERIMENTAL_ENABLED = "PQExperimentalEnabled" // no longer used private const val SHARED_PREFS_CURRENT_THEME = "CurrentTheme" + private const val SHARED_PREFS_CURRENT_THEME_IDs = "CurrentThemeIds" private const val SHARED_PREFS_SYSTEM_DARK_THEME = "SystemDarkTheme" - private const val SHARED_PREFS_THEMES = "Themes" + private const val SHARED_PREFS_THEMES_OLD = "Themes" + private const val SHARED_PREFS_THEME_OVERRIDES = "ThemeOverrides" private const val SHARED_PREFS_PROFILE_IMAGE_CORNER_RADIUS = "ProfileImageCornerRadius" private const val SHARED_PREFS_WHATS_NEW_VERSION = "WhatsNewVersion" private const val SHARED_PREFS_LAST_MIGRATED_VERSION_CODE = "LastMigratedVersionCode" @@ -361,6 +375,8 @@ class AppPreferences { private const val SHARED_PREFS_IOS_CALL_KIT_ENABLED = "iOSCallKitEnabled" private const val SHARED_PREFS_IOS_CALL_KIT_CALLS_IN_RECENTS = "iOSCallKitCallsInRecents" + + private var themeOverridesStore: List? = null } } @@ -445,8 +461,13 @@ object ChatController { Log.d(TAG, "startChatWithTemporaryDatabase") val migrationActiveUser = apiGetActiveUser(null, ctrl) ?: apiCreateActiveUser(null, Profile(displayName = "Temp", fullName = ""), ctrl = ctrl) apiSetNetworkConfig(netCfg, ctrl) - apiSetTempFolder(getMigrationTempFilesDirectory().absolutePath, ctrl) - apiSetFilesFolder(getMigrationTempFilesDirectory().absolutePath, ctrl) + apiSetAppFilePaths( + getMigrationTempFilesDirectory().absolutePath, + getMigrationTempFilesDirectory().absolutePath, + wallpapersDir.parentFile.absolutePath, + remoteHostsDir.absolutePath, + ctrl + ) apiStartChat(ctrl) return migrationActiveUser } @@ -665,22 +686,10 @@ object ChatController { } } - suspend fun apiSetTempFolder(tempFolder: String, ctrl: ChatCtrl? = null) { - val r = sendCmd(null, CC.SetTempFolder(tempFolder), ctrl) + suspend fun apiSetAppFilePaths(filesFolder: String, tempFolder: String, assetsFolder: String, remoteHostsFolder: String, ctrl: ChatCtrl? = null) { + val r = sendCmd(null, CC.ApiSetAppFilePaths(filesFolder, tempFolder, assetsFolder, remoteHostsFolder), ctrl) if (r is CR.CmdOk) return - throw Exception("failed to set temp folder: ${r.responseType} ${r.details}") - } - - suspend fun apiSetFilesFolder(filesFolder: String, ctrl: ChatCtrl? = null) { - val r = sendCmd(null, CC.SetFilesFolder(filesFolder), ctrl) - if (r is CR.CmdOk) return - throw Exception("failed to set files folder: ${r.responseType} ${r.details}") - } - - suspend fun apiSetRemoteHostsFolder(remoteHostsFolder: String) { - val r = sendCmd(null, CC.SetRemoteHostsFolder(remoteHostsFolder)) - if (r is CR.CmdOk) return - throw Exception("failed to set remote hosts folder: ${r.responseType} ${r.details}") + throw Exception("failed to set app file paths: ${r.responseType} ${r.details}") } suspend fun apiSetEncryptLocalFiles(enable: Boolean) = sendCommandOkResp(null, CC.ApiSetEncryptLocalFiles(enable)) @@ -1166,6 +1175,20 @@ object ChatController { return null } + suspend fun apiSetUserUIThemes(rh: Long?, userId: Long, themes: ThemeModeOverrides?): Boolean { + val r = sendCmd(rh, CC.ApiSetUserUIThemes(userId, themes)) + if (r is CR.CmdOk) return true + Log.e(TAG, "apiSetUserUIThemes bad response: ${r.responseType} ${r.details}") + return false + } + + suspend fun apiSetChatUIThemes(rh: Long?, chatId: ChatId, themes: ThemeModeOverrides?): Boolean { + val r = sendCmd(rh, CC.ApiSetChatUIThemes(chatId, themes)) + if (r is CR.CmdOk) return true + Log.e(TAG, "apiSetChatUIThemes bad response: ${r.responseType} ${r.details}") + return false + } + suspend fun apiCreateUserAddress(rh: Long?): String? { val userId = kotlin.runCatching { currentUserId("apiCreateUserAddress") }.getOrElse { return null } val r = sendCmd(rh, CC.ApiCreateMyAddress(userId)) @@ -2437,9 +2460,8 @@ sealed class CC { class ApiDeleteUser(val userId: Long, val delSMPQueues: Boolean, val viewPwd: String?): CC() class StartChat(val mainApp: Boolean): CC() class ApiStopChat: CC() - class SetTempFolder(val tempFolder: String): CC() - class SetFilesFolder(val filesFolder: String): CC() - class SetRemoteHostsFolder(val remoteHostsFolder: String): CC() + @Serializable + class ApiSetAppFilePaths(val appFilesFolder: String, val appTempFolder: String, val appAssetsFolder: String, val appRemoteHostsFolder: String): CC() class ApiSetEncryptLocalFiles(val enable: Boolean): CC() class ApiExportArchive(val config: ArchiveConfig): CC() class ApiImportArchive(val config: ArchiveConfig): CC() @@ -2507,6 +2529,8 @@ sealed class CC { class ApiSetContactPrefs(val contactId: Long, val prefs: ChatPreferences): CC() class ApiSetContactAlias(val contactId: Long, val localAlias: String): CC() class ApiSetConnectionAlias(val connId: Long, val localAlias: String): CC() + class ApiSetUserUIThemes(val userId: Long, val themes: ThemeModeOverrides?): CC() + class ApiSetChatUIThemes(val chatId: String, val themes: ThemeModeOverrides?): CC() class ApiCreateMyAddress(val userId: Long): CC() class ApiDeleteMyAddress(val userId: Long): CC() class ApiShowMyAddress(val userId: Long): CC() @@ -2574,9 +2598,7 @@ sealed class CC { is ApiDeleteUser -> "/_delete user $userId del_smp=${onOff(delSMPQueues)}${maybePwd(viewPwd)}" is StartChat -> "/_start main=${onOff(mainApp)}" is ApiStopChat -> "/_stop" - is SetTempFolder -> "/_temp_folder $tempFolder" - is SetFilesFolder -> "/_files_folder $filesFolder" - is SetRemoteHostsFolder -> "/remote_hosts_folder $remoteHostsFolder" + is ApiSetAppFilePaths -> "/set file paths ${json.encodeToString(this)}" is ApiSetEncryptLocalFiles -> "/_files_encrypt ${onOff(enable)}" is ApiExportArchive -> "/_db export ${json.encodeToString(config)}" is ApiImportArchive -> "/_db import ${json.encodeToString(config)}" @@ -2656,6 +2678,8 @@ sealed class CC { is ApiSetContactPrefs -> "/_set prefs @$contactId ${json.encodeToString(prefs)}" is ApiSetContactAlias -> "/_set alias @$contactId ${localAlias.trim()}" is ApiSetConnectionAlias -> "/_set alias :$connId ${localAlias.trim()}" + is ApiSetUserUIThemes -> "/_set theme user $userId ${if (themes != null) json.encodeToString(themes) else ""}" + is ApiSetChatUIThemes -> "/_set theme $chatId ${if (themes != null) json.encodeToString(themes) else ""}" is ApiCreateMyAddress -> "/_address $userId" is ApiDeleteMyAddress -> "/_delete_address $userId" is ApiShowMyAddress -> "/_show_address $userId" @@ -2720,9 +2744,7 @@ sealed class CC { is ApiDeleteUser -> "apiDeleteUser" is StartChat -> "startChat" is ApiStopChat -> "apiStopChat" - is SetTempFolder -> "setTempFolder" - is SetFilesFolder -> "setFilesFolder" - is SetRemoteHostsFolder -> "setRemoteHostsFolder" + is ApiSetAppFilePaths -> "apiSetAppFilePaths" is ApiSetEncryptLocalFiles -> "apiSetEncryptLocalFiles" is ApiExportArchive -> "apiExportArchive" is ApiImportArchive -> "apiImportArchive" @@ -2790,6 +2812,8 @@ sealed class CC { is ApiSetContactPrefs -> "apiSetContactPrefs" is ApiSetContactAlias -> "apiSetContactAlias" is ApiSetConnectionAlias -> "apiSetConnectionAlias" + is ApiSetUserUIThemes -> "apiSetUserUIThemes" + is ApiSetChatUIThemes -> "apiSetChatUIThemes" is ApiCreateMyAddress -> "apiCreateMyAddress" is ApiDeleteMyAddress -> "apiDeleteMyAddress" is ApiShowMyAddress -> "apiShowMyAddress" @@ -4061,6 +4085,15 @@ val json = Json { explicitNulls = false } +// Can decode unknown enum to default value specified for this field +val jsonCoerceInputValues = Json { + prettyPrint = true + ignoreUnknownKeys = true + encodeDefaults = true + explicitNulls = false + coerceInputValues = true +} + val jsonShort = Json { prettyPrint = false ignoreUnknownKeys = true @@ -5521,6 +5554,11 @@ data class AppSettings( var androidCallOnLockScreen: AppSettingsLockScreenCalls? = null, var iosCallKitEnabled: Boolean? = null, var iosCallKitCallsInRecents: Boolean? = null, + var uiProfileImageCornerRadius: Float? = null, + var uiColorScheme: String? = null, + var uiDarkColorScheme: String? = null, + var uiCurrentThemeIds: Map? = null, + var uiThemes: List? = null, ) { fun prepareForExport(): AppSettings { val empty = AppSettings() @@ -5545,6 +5583,11 @@ data class AppSettings( if (androidCallOnLockScreen != def.androidCallOnLockScreen) { empty.androidCallOnLockScreen = androidCallOnLockScreen } if (iosCallKitEnabled != def.iosCallKitEnabled) { empty.iosCallKitEnabled = iosCallKitEnabled } if (iosCallKitCallsInRecents != def.iosCallKitCallsInRecents) { empty.iosCallKitCallsInRecents = iosCallKitCallsInRecents } + if (uiProfileImageCornerRadius != def.uiProfileImageCornerRadius) { empty.uiProfileImageCornerRadius = uiProfileImageCornerRadius } + if (uiColorScheme != def.uiColorScheme) { empty.uiColorScheme = uiColorScheme } + if (uiDarkColorScheme != def.uiDarkColorScheme) { empty.uiDarkColorScheme = uiDarkColorScheme } + if (uiCurrentThemeIds != def.uiCurrentThemeIds) { empty.uiCurrentThemeIds = uiCurrentThemeIds } + if (uiThemes != def.uiThemes) { empty.uiThemes = uiThemes } return empty } @@ -5577,6 +5620,11 @@ data class AppSettings( androidCallOnLockScreen?.let { def.callOnLockScreen.set(it.toCallOnLockScreen()) } iosCallKitEnabled?.let { def.iosCallKitEnabled.set(it) } iosCallKitCallsInRecents?.let { def.iosCallKitCallsInRecents.set(it) } + uiProfileImageCornerRadius?.let { def.profileImageCornerRadius.set(it) } + uiColorScheme?.let { def.currentTheme.set(it) } + uiDarkColorScheme?.let { def.systemDarkTheme.set(it) } + uiCurrentThemeIds?.let { def.currentThemeIds.set(it) } + uiThemes?.let { def.themeOverrides.set(it.skipDuplicates()) } } companion object { @@ -5601,7 +5649,12 @@ data class AppSettings( confirmDBUpgrades = false, androidCallOnLockScreen = AppSettingsLockScreenCalls.SHOW, iosCallKitEnabled = true, - iosCallKitCallsInRecents = false + iosCallKitCallsInRecents = false, + uiProfileImageCornerRadius = 22.5f, + uiColorScheme = DefaultTheme.SYSTEM_THEME_NAME, + uiDarkColorScheme = DefaultTheme.SIMPLEX.themeName, + uiCurrentThemeIds = null, + uiThemes = null, ) val current: AppSettings @@ -5628,6 +5681,11 @@ data class AppSettings( androidCallOnLockScreen = AppSettingsLockScreenCalls.from(def.callOnLockScreen.get()), iosCallKitEnabled = def.iosCallKitEnabled.get(), iosCallKitCallsInRecents = def.iosCallKitCallsInRecents.get(), + uiProfileImageCornerRadius = def.profileImageCornerRadius.get(), + uiColorScheme = def.currentTheme.get() ?: DefaultTheme.SYSTEM_THEME_NAME, + uiDarkColorScheme = def.systemDarkTheme.get() ?: DefaultTheme.SIMPLEX.themeName, + uiCurrentThemeIds = def.currentThemeIds.get(), + uiThemes = def.themeOverrides.get(), ) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/other/wheel-picker/FWheelPickerDefault.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/other/wheel-picker/FWheelPickerDefault.kt index 9760e9c9f2..052e388f97 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/other/wheel-picker/FWheelPickerDefault.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/other/wheel-picker/FWheelPickerDefault.kt @@ -2,7 +2,6 @@ package com.sd.lib.compose.wheel_picker import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.background -import chat.simplex.common.ui.theme.isSystemInDarkTheme import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -12,6 +11,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import chat.simplex.common.ui.theme.isInDarkTheme /** * The default implementation of focus view in vertical. @@ -76,7 +76,7 @@ fun FWheelPickerFocusHorizontal( */ private val DefaultDividerColor: Color @Composable - get() = (if (isSystemInDarkTheme()) { + get() = (if (isInDarkTheme()) { Color.White } else { Color.Black diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/AppCommon.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/AppCommon.kt index 7d5b1b0196..10cb17df1d 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/AppCommon.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/AppCommon.kt @@ -42,6 +42,12 @@ fun runMigrations() { ChatController.appPrefs.currentTheme.set(DefaultTheme.SIMPLEX.name) } lastMigration.set(117) + } else if (lastMigration.get() < 203) { + // Moving to a different key for storing themes as a List + val oldOverrides = ChatController.appPrefs.themeOverridesOld.get().values.toList() + ChatController.appPrefs.themeOverrides.set(oldOverrides) + ChatController.appPrefs.currentThemeIds.set(oldOverrides.associate { it.base.themeName to it.themeId }) + lastMigration.set(203) } else { lastMigration.set(BuildConfigCommon.ANDROID_VERSION_CODE) break diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt index 0d447a4a5a..85179d66c7 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt @@ -43,14 +43,13 @@ val appPreferences: AppPreferences val chatController: ChatController = ChatController -fun initChatControllerAndRunMigrations() { +fun initChatControllerOnStart() { withLongRunningApi { if (appPreferences.chatStopped.get() && appPreferences.storeDBPassphrase.get() && ksDatabasePassword.get() != null) { initChatController(startChat = ::showStartChatAfterRestartAlert) } else { initChatController() } - runMigrations() } } @@ -88,11 +87,13 @@ suspend fun initChatController(useKey: String? = null, confirmMigrations: Migrat return } platform.androidRestartNetworkObserver() - controller.apiSetTempFolder(coreTmpDir.absolutePath) - controller.apiSetFilesFolder(appFilesDir.absolutePath) - if (appPlatform.isDesktop) { - controller.apiSetRemoteHostsFolder(remoteHostsDir.absolutePath) - } + controller.apiSetAppFilePaths( + appFilesDir.absolutePath, + coreTmpDir.absolutePath, + wallpapersDir.parentFile.absolutePath, + remoteHostsDir.absolutePath, + ctrl + ) controller.apiSetEncryptLocalFiles(controller.appPrefs.privacyEncryptLocalFiles.get()) // If we migrated successfully means previous re-encryption process on database level finished successfully too if (appPreferences.encryptionStartedAt.get() != null) appPreferences.encryptionStartedAt.set(null) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Files.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Files.kt index c788a6902e..250afe03c4 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Files.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Files.kt @@ -1,10 +1,12 @@ package chat.simplex.common.platform import androidx.compose.runtime.Composable -import chat.simplex.common.model.CIFile -import chat.simplex.common.model.CryptoFile +import chat.simplex.common.model.* +import chat.simplex.common.ui.theme.* import chat.simplex.common.views.helpers.generalGetString import chat.simplex.res.MR +import com.charleskorn.kaml.* +import kotlinx.serialization.encodeToString import java.io.* import java.net.URI import java.net.URLDecoder @@ -14,8 +16,10 @@ expect val dataDir: File expect val tmpDir: File expect val filesDir: File expect val appFilesDir: File +expect val wallpapersDir: File expect val coreTmpDir: File expect val dbAbsolutePrefixPath: String +expect val preferencesDir: File expect val chatDatabaseFileName: String expect val agentDatabaseFileName: String @@ -78,6 +82,20 @@ fun getAppFilePath(fileName: String): String { } } +fun getWallpaperFilePath(fileName: String): String { + val rh = chatModel.currentRemoteHost.value + val s = File.separator + val path = if (rh == null) { + wallpapersDir.absolutePath + s + fileName + } else { + remoteHostsDir.absolutePath + s + rh.storePath + s + "simplex_v1_assets" + s + "wallpapers" + s + fileName + } + File(path).parentFile.mkdirs() + return path +} + +fun getPreferenceFilePath(fileName: String = "themes.yaml"): String = preferencesDir.absolutePath + File.separator + fileName + fun getLoadedFilePath(file: CIFile?): String? { val f = file?.fileSource?.filePath return if (f != null && file.loaded) { @@ -98,6 +116,42 @@ fun getLoadedFileSource(file: CIFile?): CryptoFile? { } } +fun readThemeOverrides(): List { + return try { + val file = File(getPreferenceFilePath("themes.yaml")) + if (!file.exists()) return emptyList() + + file.inputStream().use { + val map = yaml.parseToYamlNode(it).yamlMap + val list = map.get("themes") + val res = ArrayList() + list?.items?.forEach { + try { + res.add(yaml.decodeFromYamlNode(ThemeOverrides.serializer(), it)) + } catch (e: Throwable) { + Log.e(TAG, "Error while reading specific theme: ${e.stackTraceToString()}") + } + } + res.skipDuplicates() + } + } catch (e: Throwable) { + Log.e(TAG, "Error while reading themes file: ${e.stackTraceToString()}") + emptyList() + } +} + +fun writeThemeOverrides(overrides: List): Boolean = + try { + File(getPreferenceFilePath("themes.yaml")).outputStream().use { + val string = yaml.encodeToString(ThemesFile(themes = overrides)) + it.bufferedWriter().use { it.write(string) } + } + true + } catch (e: Throwable) { + Log.e(TAG, "Error while writing themes file: ${e.stackTraceToString()}") + false + } + private fun fileReady(file: CIFile, filePath: String) = File(filePath).exists() && CIFile.cachedRemoteFileRequests[file.fileSource] != false diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Resources.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Resources.kt index 2ee668fb23..8e45ded4f0 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Resources.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/Resources.kt @@ -1,11 +1,13 @@ package chat.simplex.common.platform import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.Dp import com.russhwolf.settings.Settings +import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.resources.StringResource @Composable @@ -31,3 +33,5 @@ expect fun windowWidth(): Dp expect fun desktopExpandWindowToWidth(width: Dp) expect fun isRtl(text: CharSequence): Boolean + +expect fun ImageResource.toComposeImageBitmap(): ImageBitmap? diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Color.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Color.kt index 5eeedbb2a0..c50ea5c349 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Color.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Color.kt @@ -31,17 +31,6 @@ val WarningOrange = Color(255, 127, 0, 255) val WarningYellow = Color(255, 192, 0, 255) val FileLight = Color(183, 190, 199, 255) val FileDark = Color(101, 101, 106, 255) -val SentMessageColor = Color(0x1E45B8FF) val MenuTextColor: Color @Composable get () = if (isInDarkTheme()) LocalContentColor.current.copy(alpha = 0.8f) else Color.Black -val NoteFolderIconColor: Color @Composable get() = with(CurrentColors.collectAsState().value.appColors.sentMessage) { - // Default color looks too light and better to have it here a little bit brighter - if (alpha == SentMessageColor.alpha) { - copy(min(SentMessageColor.alpha + 0.1f, 1f)) - } else { - // Color is non-standard and theme maker can choose color without alpha at all since the theme bound to dark/light variant, - // and it shouldn't be universal - this - } -} - +val NoteFolderIconColor: Color @Composable get() = MaterialTheme.appColors.primaryVariant2 diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt index 62acc13bfe..5099513884 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt @@ -6,53 +6,136 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.* -import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp import chat.simplex.common.model.ChatController -import chat.simplex.common.platform.isInNightMode +import chat.simplex.common.model.ChatController.appPrefs +import chat.simplex.common.platform.* +import chat.simplex.common.ui.theme.ThemeManager.colorFromReadableHex +import chat.simplex.common.ui.theme.ThemeManager.toReadableHex import chat.simplex.common.views.helpers.* import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import chat.simplex.res.MR +import kotlinx.serialization.Transient +import java.util.UUID enum class DefaultTheme { - SYSTEM, LIGHT, DARK, SIMPLEX; + LIGHT, DARK, SIMPLEX, BLACK; + + companion object { + const val SYSTEM_THEME_NAME: String = "SYSTEM" + } + + val themeName: String + get() = name + + val mode: DefaultThemeMode get() = if (this == LIGHT) DefaultThemeMode.LIGHT else DefaultThemeMode.DARK // Call it only with base theme, not SYSTEM - fun hasChangedAnyColor(colors: Colors, appColors: AppColors): Boolean { - val palette = when (this) { - SYSTEM -> return false - LIGHT -> LightColorPalette - DARK -> DarkColorPalette - SIMPLEX -> SimplexColorPalette - } - val appPalette = when (this) { - SYSTEM -> return false - LIGHT -> LightColorPaletteApp - DARK -> DarkColorPaletteApp - SIMPLEX -> SimplexColorPaletteApp - } - return colors.primary != palette.primary || - colors.primaryVariant != palette.primaryVariant || - colors.secondary != palette.secondary || - colors.secondaryVariant != palette.secondaryVariant || - colors.background != palette.background || - colors.surface != palette.surface || - appColors != appPalette + fun hasChangedAnyColor(overrides: ThemeOverrides?): Boolean { + if (overrides == null) return false + return overrides.colors != ThemeColors() || + overrides.wallpaper != null && (overrides.wallpaper.background != null || overrides.wallpaper.tint != null) } } -data class AppColors( - val title: Color, - val sentMessage: Color, - val receivedMessage: Color -) +@Serializable +enum class DefaultThemeMode { + @SerialName("light") LIGHT, + @SerialName("dark") DARK +} + +@Stable +class AppColors( + title: Color, + primaryVariant2: Color, + sentMessage: Color, + sentQuote: Color, + receivedMessage: Color, + receivedQuote: Color, +) { + var title by mutableStateOf(title, structuralEqualityPolicy()) + internal set + var primaryVariant2 by mutableStateOf(primaryVariant2, structuralEqualityPolicy()) + internal set + var sentMessage by mutableStateOf(sentMessage, structuralEqualityPolicy()) + internal set + var sentQuote by mutableStateOf(sentQuote, structuralEqualityPolicy()) + internal set + var receivedMessage by mutableStateOf(receivedMessage, structuralEqualityPolicy()) + internal set + var receivedQuote by mutableStateOf(receivedQuote, structuralEqualityPolicy()) + internal set + + fun copy( + title: Color = this.title, + primaryVariant2: Color = this.primaryVariant2, + sentMessage: Color = this.sentMessage, + sentQuote: Color = this.sentQuote, + receivedMessage: Color = this.receivedMessage, + receivedQuote: Color = this.receivedQuote, + ): AppColors = AppColors( + title, + primaryVariant2, + sentMessage, + sentQuote, + receivedMessage, + receivedQuote, + ) + + override fun toString(): String { + return buildString { + append("AppColors(") + append("title=$title, ") + append("primaryVariant2=$primaryVariant2, ") + append("sentMessage=$sentMessage, ") + append("sentQuote=$sentQuote, ") + append("receivedMessage=$receivedMessage, ") + append("receivedQuote=$receivedQuote") + append(")") + } + } +} + +@Stable +class AppWallpaper( + background: Color? = null, + tint: Color? = null, + type: WallpaperType = WallpaperType.Empty, +) { + var background by mutableStateOf(background, structuralEqualityPolicy()) + internal set + var tint by mutableStateOf(tint, structuralEqualityPolicy()) + internal set + var type by mutableStateOf(type, structuralEqualityPolicy()) + internal set + + fun copy( + background: Color? = this.background, + tint: Color? = this.tint, + type: WallpaperType = this.type, + ): AppWallpaper = AppWallpaper( + background, + tint, + type, + ) + + override fun toString(): String { + return buildString { + append("AppWallpaper(") + append("background=$background, ") + append("tint=$tint, ") + append("type=$type") + append(")") + } + } +} enum class ThemeColor { - PRIMARY, PRIMARY_VARIANT, SECONDARY, SECONDARY_VARIANT, BACKGROUND, SURFACE, TITLE, SENT_MESSAGE, RECEIVED_MESSAGE; + PRIMARY, PRIMARY_VARIANT, SECONDARY, SECONDARY_VARIANT, BACKGROUND, SURFACE, TITLE, SENT_MESSAGE, SENT_QUOTE, RECEIVED_MESSAGE, RECEIVED_QUOTE, PRIMARY_VARIANT2, WALLPAPER_BACKGROUND, WALLPAPER_TINT; - fun fromColors(colors: Colors, appColors: AppColors): Color { + fun fromColors(colors: Colors, appColors: AppColors, appWallpaper: AppWallpaper): Color? { return when (this) { PRIMARY -> colors.primary PRIMARY_VARIANT -> colors.primaryVariant @@ -61,8 +144,13 @@ enum class ThemeColor { BACKGROUND -> colors.background SURFACE -> colors.surface TITLE -> appColors.title + PRIMARY_VARIANT2 -> appColors.primaryVariant2 SENT_MESSAGE -> appColors.sentMessage + SENT_QUOTE -> appColors.sentQuote RECEIVED_MESSAGE -> appColors.receivedMessage + RECEIVED_QUOTE -> appColors.receivedQuote + WALLPAPER_BACKGROUND -> appWallpaper.background + WALLPAPER_TINT -> appWallpaper.tint } } @@ -75,8 +163,13 @@ enum class ThemeColor { BACKGROUND -> generalGetString(MR.strings.color_background) SURFACE -> generalGetString(MR.strings.color_surface) TITLE -> generalGetString(MR.strings.color_title) + PRIMARY_VARIANT2 -> generalGetString(MR.strings.color_primary_variant2) SENT_MESSAGE -> generalGetString(MR.strings.color_sent_message) + SENT_QUOTE -> generalGetString(MR.strings.color_sent_quote) RECEIVED_MESSAGE -> generalGetString(MR.strings.color_received_message) + RECEIVED_QUOTE -> generalGetString(MR.strings.color_received_quote) + WALLPAPER_BACKGROUND -> generalGetString(MR.strings.color_wallpaper_background) + WALLPAPER_TINT -> generalGetString(MR.strings.color_wallpaper_tint) } } @@ -92,45 +185,232 @@ data class ThemeColors( @SerialName("menus") val surface: String? = null, val title: String? = null, + @SerialName("accentVariant2") + val primaryVariant2: String? = null, val sentMessage: String? = null, + @SerialName("sentReply") + val sentQuote: String? = null, val receivedMessage: String? = null, + @SerialName("receivedReply") + val receivedQuote: String? = null, ) { - fun toColors(base: DefaultTheme): Colors { + companion object { + fun from(colors: Colors, appColors: AppColors): ThemeColors = + ThemeColors( + primary = colors.primary.toReadableHex(), + primaryVariant = colors.primaryVariant.toReadableHex(), + secondary = colors.secondary.toReadableHex(), + secondaryVariant = colors.secondaryVariant.toReadableHex(), + background = colors.background.toReadableHex(), + surface = colors.surface.toReadableHex(), + title = appColors.title.toReadableHex(), + primaryVariant2 = appColors.primaryVariant2.toReadableHex(), + sentMessage = appColors.sentMessage.toReadableHex(), + sentQuote = appColors.sentQuote.toReadableHex(), + receivedMessage = appColors.receivedMessage.toReadableHex(), + receivedQuote = appColors.receivedQuote.toReadableHex(), + ) + } +} + +@Serializable +data class ThemeWallpaper ( + val preset: String? = null, + val scale: Float? = null, + val scaleType: WallpaperScaleType? = null, + val background: String? = null, + val tint: String? = null, + val image: String? = null, + val imageFile: String? = null, +) { + fun toAppWallpaper(): AppWallpaper { + return AppWallpaper( + background = background?.colorFromReadableHex(), + tint = tint?.colorFromReadableHex(), + type = WallpaperType.from(this) ?: WallpaperType.Empty + ) + } + + fun withFilledWallpaperBase64(): ThemeWallpaper { + val aw = toAppWallpaper() + val type = aw.type + return ThemeWallpaper( + image = if (type is WallpaperType.Image && type.image != null) resizeImageToStrSize(type.image!!, 5_000_000) else null, + imageFile = null, + preset = if (type is WallpaperType.Preset) type.filename else null, + scale = if (type is WallpaperType.Preset) type.scale else if (type is WallpaperType.Image) type.scale else 1f, + scaleType = if (type is WallpaperType.Image) type.scaleType else null, + background = aw.background?.toReadableHex(), + tint = aw.tint?.toReadableHex(), + ) + } + + fun withFilledWallpaperPath(): ThemeWallpaper { + val aw = toAppWallpaper() + val type = aw.type + return ThemeWallpaper( + image = null, + imageFile = if (type is WallpaperType.Image) type.filename else null, + preset = if (type is WallpaperType.Preset) type.filename else null, + scale = if (scale == null) null else if (type is WallpaperType.Preset) type.scale else if (type is WallpaperType.Image) scale else null, + scaleType = if (scaleType == null) null else if (type is WallpaperType.Image) type.scaleType else null, + background = aw.background?.toReadableHex(), + tint = aw.tint?.toReadableHex(), + ) + } + + fun importFromString(): ThemeWallpaper = + if (preset == null && image != null) { + // Need to save image from string and to save its path + try { + val parsed = base64ToBitmap(image) + val filename = saveWallpaperFile(parsed) + copy(image = null, imageFile = filename) + } catch (e: Exception) { + Log.e(TAG, "Error while parsing/copying the image: ${e.stackTraceToString()}") + ThemeWallpaper() + } + } else this + + companion object { + fun from(type: WallpaperType, background: String?, tint: String?): ThemeWallpaper { + return ThemeWallpaper( + image = null, + imageFile = if (type is WallpaperType.Image) type.filename else null, + preset = if (type is WallpaperType.Preset) type.filename else null, + scale = if (type is WallpaperType.Preset) type.scale else if (type is WallpaperType.Image) type.scale else null, + scaleType = if (type is WallpaperType.Image) type.scaleType else null, + background = background, + tint = tint, + ) + } + } +} + +@Serializable +data class ThemesFile( + val themes: List = emptyList() +) + +@Serializable +data class ThemeOverrides ( + val themeId: String = UUID.randomUUID().toString(), + val base: DefaultTheme, + val colors: ThemeColors = ThemeColors(), + val wallpaper: ThemeWallpaper? = null, +) { + + fun isSame(type: WallpaperType?, themeName: String): Boolean = + ( + (wallpaper?.preset != null && type is WallpaperType.Preset && wallpaper.preset == type.filename) || + (wallpaper?.imageFile != null && type is WallpaperType.Image) || + (wallpaper?.preset == null && wallpaper?.imageFile == null && (type == WallpaperType.Empty || type == null)) + ) && base.themeName == themeName + + fun withUpdatedColor(name: ThemeColor, color: String?): ThemeOverrides { + return copy( + colors = when (name) { + ThemeColor.PRIMARY -> colors.copy(primary = color) + ThemeColor.PRIMARY_VARIANT -> colors.copy(primaryVariant = color) + ThemeColor.SECONDARY -> colors.copy(secondary = color) + ThemeColor.SECONDARY_VARIANT -> colors.copy(secondaryVariant = color) + ThemeColor.BACKGROUND -> colors.copy(background = color) + ThemeColor.SURFACE -> colors.copy(surface = color) + ThemeColor.TITLE -> colors.copy(title = color) + ThemeColor.PRIMARY_VARIANT2 -> colors.copy(primaryVariant2 = color) + ThemeColor.SENT_MESSAGE -> colors.copy(sentMessage = color) + ThemeColor.SENT_QUOTE -> colors.copy(sentQuote = color) + ThemeColor.RECEIVED_MESSAGE -> colors.copy(receivedMessage = color) + ThemeColor.RECEIVED_QUOTE -> colors.copy(receivedQuote = color) + ThemeColor.WALLPAPER_BACKGROUND -> colors.copy() + ThemeColor.WALLPAPER_TINT -> colors.copy() + }, wallpaper = when (name) { + ThemeColor.WALLPAPER_BACKGROUND -> wallpaper?.copy(background = color) + ThemeColor.WALLPAPER_TINT -> wallpaper?.copy(tint = color) + else -> wallpaper?.copy() + } + ) + } + + fun toColors(base: DefaultTheme, perChatTheme: ThemeColors?, perUserTheme: ThemeColors?, presetWallpaperTheme: ThemeColors?): Colors { val baseColors = when (base) { DefaultTheme.LIGHT -> LightColorPalette DefaultTheme.DARK -> DarkColorPalette DefaultTheme.SIMPLEX -> SimplexColorPalette - // shouldn't be here - DefaultTheme.SYSTEM -> LightColorPalette + DefaultTheme.BLACK -> BlackColorPalette } return baseColors.copy( - primary = primary?.colorFromReadableHex() ?: baseColors.primary, - primaryVariant = primaryVariant?.colorFromReadableHex() ?: baseColors.primaryVariant, - secondary = secondary?.colorFromReadableHex() ?: baseColors.secondary, - secondaryVariant = secondaryVariant?.colorFromReadableHex() ?: baseColors.secondaryVariant, - background = background?.colorFromReadableHex() ?: baseColors.background, - surface = surface?.colorFromReadableHex() ?: baseColors.surface, + primary = perChatTheme?.primary?.colorFromReadableHex() ?: perUserTheme?.primary?.colorFromReadableHex() ?: colors.primary?.colorFromReadableHex() ?: presetWallpaperTheme?.primary?.colorFromReadableHex() ?: baseColors.primary, + primaryVariant = perChatTheme?.primaryVariant?.colorFromReadableHex() ?: perUserTheme?.primaryVariant?.colorFromReadableHex() ?: colors.primaryVariant?.colorFromReadableHex() ?: presetWallpaperTheme?.primaryVariant?.colorFromReadableHex() ?: baseColors.primaryVariant, + secondary = perChatTheme?.secondary?.colorFromReadableHex() ?: perUserTheme?.secondary?.colorFromReadableHex() ?: colors.secondary?.colorFromReadableHex() ?: presetWallpaperTheme?.secondary?.colorFromReadableHex() ?: baseColors.secondary, + secondaryVariant = perChatTheme?.secondaryVariant?.colorFromReadableHex() ?: perUserTheme?.secondaryVariant?.colorFromReadableHex() ?: colors.secondaryVariant?.colorFromReadableHex() ?: presetWallpaperTheme?.secondaryVariant?.colorFromReadableHex() ?: baseColors.secondaryVariant, + background = perChatTheme?.background?.colorFromReadableHex() ?: perUserTheme?.background?.colorFromReadableHex() ?: colors.background?.colorFromReadableHex() ?: presetWallpaperTheme?.background?.colorFromReadableHex() ?: baseColors.background, + surface = perChatTheme?.surface?.colorFromReadableHex() ?: perUserTheme?.surface?.colorFromReadableHex() ?: colors.surface?.colorFromReadableHex() ?: presetWallpaperTheme?.surface?.colorFromReadableHex() ?: baseColors.surface, ) } - fun toAppColors(base: DefaultTheme): AppColors { + fun toAppColors(base: DefaultTheme, perChatTheme: ThemeColors?, perChatWallpaperType: WallpaperType?, perUserTheme: ThemeColors?, perUserWallpaperType: WallpaperType?, presetWallpaperTheme: ThemeColors?): AppColors { val baseColors = when (base) { DefaultTheme.LIGHT -> LightColorPaletteApp DefaultTheme.DARK -> DarkColorPaletteApp DefaultTheme.SIMPLEX -> SimplexColorPaletteApp - // shouldn't be here - DefaultTheme.SYSTEM -> LightColorPaletteApp + DefaultTheme.BLACK -> BlackColorPaletteApp } + + val sentMessageFallback = colors.sentMessage?.colorFromReadableHex() ?: presetWallpaperTheme?.sentMessage?.colorFromReadableHex() ?: baseColors.sentMessage + val sentQuoteFallback = colors.sentQuote?.colorFromReadableHex() ?: presetWallpaperTheme?.sentQuote?.colorFromReadableHex() ?: baseColors.sentQuote + val receivedMessageFallback = colors.receivedMessage?.colorFromReadableHex() ?: presetWallpaperTheme?.receivedMessage?.colorFromReadableHex() ?: baseColors.receivedMessage + val receivedQuoteFallback = colors.receivedQuote?.colorFromReadableHex() ?: presetWallpaperTheme?.receivedQuote?.colorFromReadableHex() ?: baseColors.receivedQuote return baseColors.copy( - title = title?.colorFromReadableHex() ?: baseColors.title, - sentMessage = sentMessage?.colorFromReadableHex() ?: baseColors.sentMessage, - receivedMessage = receivedMessage?.colorFromReadableHex() ?: baseColors.receivedMessage, + title = perChatTheme?.title?.colorFromReadableHex() ?: perUserTheme?.title?.colorFromReadableHex() ?: colors.title?.colorFromReadableHex() ?: presetWallpaperTheme?.title?.colorFromReadableHex() ?: baseColors.title, + primaryVariant2 = perChatTheme?.primaryVariant2?.colorFromReadableHex() ?: perUserTheme?.primaryVariant2?.colorFromReadableHex() ?: colors.primaryVariant2?.colorFromReadableHex() ?: presetWallpaperTheme?.primaryVariant2?.colorFromReadableHex() ?: baseColors.primaryVariant2, + sentMessage = if (perChatTheme?.sentMessage != null) perChatTheme.sentMessage.colorFromReadableHex() + else if (perUserTheme != null && (perChatWallpaperType == null || perUserWallpaperType == null || perChatWallpaperType.sameType(perUserWallpaperType))) perUserTheme.sentMessage?.colorFromReadableHex() ?: sentMessageFallback + else sentMessageFallback, + sentQuote = if (perChatTheme?.sentQuote != null) perChatTheme.sentQuote.colorFromReadableHex() + else if (perUserTheme != null && (perChatWallpaperType == null || perUserWallpaperType == null || perChatWallpaperType.sameType(perUserWallpaperType))) perUserTheme.sentQuote?.colorFromReadableHex() ?: sentQuoteFallback + else sentQuoteFallback, + receivedMessage = if (perChatTheme?.receivedMessage != null) perChatTheme.receivedMessage.colorFromReadableHex() + else if (perUserTheme != null && (perChatWallpaperType == null || perUserWallpaperType == null || perChatWallpaperType.sameType(perUserWallpaperType))) perUserTheme.receivedMessage?.colorFromReadableHex() ?: receivedMessageFallback + else receivedMessageFallback, + receivedQuote = if (perChatTheme?.receivedQuote != null) perChatTheme.receivedQuote.colorFromReadableHex() + else if (perUserTheme != null && (perChatWallpaperType == null || perUserWallpaperType == null || perChatWallpaperType.sameType(perUserWallpaperType))) perUserTheme.receivedQuote?.colorFromReadableHex() ?: receivedQuoteFallback + else receivedQuoteFallback, ) } - fun withFilledColors(base: DefaultTheme): ThemeColors { - val c = toColors(base) - val ac = toAppColors(base) + fun toAppWallpaper(themeOverridesForType: WallpaperType?, perChatTheme: ThemeModeOverride?, perUserTheme: ThemeModeOverride?, materialBackgroundColor: Color): AppWallpaper { + val mainType = when { + themeOverridesForType != null -> themeOverridesForType + // type can be null if override is empty `"wallpaper": "{}"`, in this case no wallpaper is needed, empty. + // It's not null to override upper level wallpaper + perChatTheme?.wallpaper != null -> perChatTheme.wallpaper.toAppWallpaper().type + perUserTheme?.wallpaper != null -> perUserTheme.wallpaper.toAppWallpaper().type + else -> wallpaper?.toAppWallpaper()?.type ?: return AppWallpaper() + } + val first: ThemeWallpaper? = if (mainType.sameType(perChatTheme?.wallpaper?.toAppWallpaper()?.type)) perChatTheme?.wallpaper else null + val second: ThemeWallpaper? = if (mainType.sameType(perUserTheme?.wallpaper?.toAppWallpaper()?.type)) perUserTheme?.wallpaper else null + val third: ThemeWallpaper? = if (mainType.sameType(this.wallpaper?.toAppWallpaper()?.type)) this.wallpaper else null + + return AppWallpaper(type = when (mainType) { + is WallpaperType.Preset -> mainType.copy( + scale = mainType.scale ?: first?.scale ?: second?.scale ?: third?.scale + ) + is WallpaperType.Image -> mainType.copy( + scale = if (themeOverridesForType == null) mainType.scale ?: first?.scale ?: second?.scale ?: third?.scale else second?.scale ?: third?.scale ?: mainType.scale, + scaleType = if (themeOverridesForType == null) mainType.scaleType ?: first?.scaleType ?: second?.scaleType ?: third?.scaleType else second?.scaleType ?: third?.scaleType ?: mainType.scaleType, + filename = if (themeOverridesForType == null) mainType.filename else first?.imageFile ?: second?.imageFile ?: third?.imageFile ?: mainType.filename, + ) + is WallpaperType.Empty -> mainType + }, + background = (first?.background ?: second?.background ?: third?.background)?.colorFromReadableHex() ?: mainType.defaultBackgroundColor(base, materialBackgroundColor), + tint = (first?.tint ?: second?.tint ?: third?.tint)?.colorFromReadableHex() ?: mainType.defaultTintColor(base) + ) + } + + fun withFilledColors(base: DefaultTheme, perChatTheme: ThemeColors?, perChatWallpaperType: WallpaperType?, perUserTheme: ThemeColors?, perUserWallpaperType: WallpaperType?, presetWallpaperTheme: ThemeColors?): ThemeColors { + val c = toColors(base, perChatTheme, perUserTheme, presetWallpaperTheme) + val ac = toAppColors(base, perChatTheme, perChatWallpaperType, perUserTheme, perUserWallpaperType, presetWallpaperTheme) return ThemeColors( primary = c.primary.toReadableHex(), primaryVariant = c.primaryVariant.toReadableHex(), @@ -139,23 +419,71 @@ data class ThemeColors( background = c.background.toReadableHex(), surface = c.surface.toReadableHex(), title = ac.title.toReadableHex(), + primaryVariant2 = ac.primaryVariant2.toReadableHex(), sentMessage = ac.sentMessage.toReadableHex(), - receivedMessage = ac.receivedMessage.toReadableHex() + sentQuote = ac.sentQuote.toReadableHex(), + receivedMessage = ac.receivedMessage.toReadableHex(), + receivedQuote = ac.receivedQuote.toReadableHex(), ) } } -private fun String.colorFromReadableHex(): Color = - Color(this.replace("#", "").toLongOrNull(16) ?: Color.White.toArgb().toLong()) +fun List.getTheme(themeId: String?): ThemeOverrides? = + firstOrNull { it.themeId == themeId } -private fun Color.toReadableHex(): String = "#" + Integer.toHexString(toArgb()) +fun List.getTheme(themeId: String?, type: WallpaperType?, base: DefaultTheme): ThemeOverrides? = + firstOrNull { it.themeId == themeId || it.isSame(type, base.themeName)} + +fun List.replace(theme: ThemeOverrides): List { + val index = indexOfFirst { it.themeId == theme.themeId || + // prevent situation when two themes has the same type but different theme id (maybe something was changed in prefs by hand) + it.isSame(WallpaperType.from(theme.wallpaper), theme.base.themeName) + } + return if (index != -1) { + val a = ArrayList(this) + a[index] = theme + a + } else { + this + theme + } +} + +fun List.sameTheme(type: WallpaperType?, themeName: String): ThemeOverrides? = firstOrNull { it.isSame(type, themeName) } + +/** See [ThemesTest.testSkipDuplicates] */ +fun List.skipDuplicates(): List { + val res = ArrayList() + forEach { theme -> + val themeType = WallpaperType.from(theme.wallpaper) + if (res.none { it.themeId == theme.themeId || it.isSame(themeType, theme.base.themeName) }) { + res.add(theme) + } + } + return res +} @Serializable -data class ThemeOverrides ( - val base: DefaultTheme, - val colors: ThemeColors +data class ThemeModeOverrides ( + val light: ThemeModeOverride? = null, + val dark: ThemeModeOverride? = null ) { - fun withUpdatedColor(name: ThemeColor, color: String): ThemeOverrides { + fun preferredMode(darkTheme: Boolean): ThemeModeOverride? = when (darkTheme) { + false -> light + else -> dark + } +} + +@Serializable +data class ThemeModeOverride ( + val mode: DefaultThemeMode = CurrentColors.value.base.mode, + val colors: ThemeColors = ThemeColors(), + val wallpaper: ThemeWallpaper? = null, +) { + + @Transient + val type = WallpaperType.from(wallpaper) + + fun withUpdatedColor(name: ThemeColor, color: String?): ThemeModeOverride { return copy(colors = when (name) { ThemeColor.PRIMARY -> colors.copy(primary = color) ThemeColor.PRIMARY_VARIANT -> colors.copy(primaryVariant = color) @@ -164,9 +492,27 @@ data class ThemeOverrides ( ThemeColor.BACKGROUND -> colors.copy(background = color) ThemeColor.SURFACE -> colors.copy(surface = color) ThemeColor.TITLE -> colors.copy(title = color) + ThemeColor.PRIMARY_VARIANT2 -> colors.copy(primaryVariant2 = color) ThemeColor.SENT_MESSAGE -> colors.copy(sentMessage = color) + ThemeColor.SENT_QUOTE -> colors.copy(sentQuote = color) ThemeColor.RECEIVED_MESSAGE -> colors.copy(receivedMessage = color) - }) + ThemeColor.RECEIVED_QUOTE -> colors.copy(receivedQuote = color) + ThemeColor.WALLPAPER_BACKGROUND -> colors.copy() + ThemeColor.WALLPAPER_TINT -> colors.copy() + }, wallpaper = when (name) { + ThemeColor.WALLPAPER_BACKGROUND -> wallpaper?.copy(background = color) + ThemeColor.WALLPAPER_TINT -> wallpaper?.copy(tint = color) + else -> wallpaper?.copy() + } + ) + } + companion object { + fun withFilledAppDefaults(mode: DefaultThemeMode, base: DefaultTheme): ThemeModeOverride = + ThemeModeOverride( + mode = mode, + colors = ThemeOverrides(base = base).withFilledColors(base, null, null, null, null, null), + wallpaper = ThemeWallpaper(preset = PresetWallpaper.SCHOOL.filename) + ) } } @@ -204,7 +550,6 @@ val DarkColorPalette = darkColors( // background = Color.Black, surface = Color(0xFF222222), // background = Color(0xFF121212), -// surface = Color(0xFF121212), error = Color.Red, onBackground = Color(0xFFFFFBFA), onSurface = Color(0xFFFFFBFA), @@ -212,8 +557,11 @@ val DarkColorPalette = darkColors( ) val DarkColorPaletteApp = AppColors( title = SimplexBlue, - sentMessage = SentMessageColor, - receivedMessage = Color(0x20B1B0B5) + primaryVariant2 = Color(0xFF18262E), + sentMessage = Color(0xFF18262E), + sentQuote = Color(0xFF1D3847), + receivedMessage = Color(0xff262627), + receivedQuote = Color(0xff373739), ) val LightColorPalette = lightColors( @@ -231,8 +579,11 @@ val LightColorPalette = lightColors( ) val LightColorPaletteApp = AppColors( title = SimplexBlue, - sentMessage = SentMessageColor, - receivedMessage = Color(0x20B1B0B5) + primaryVariant2 = Color(0xFFE9F7FF), + sentMessage = Color(0xFFE9F7FF), + sentQuote = Color(0xFFD6F0FF), + receivedMessage = Color(0xfff5f5f6), + receivedQuote = Color(0xffececee), ) val SimplexColorPalette = darkColors( @@ -251,11 +602,39 @@ val SimplexColorPalette = darkColors( ) val SimplexColorPaletteApp = AppColors( title = Color(0xFF267BE5), - sentMessage = SentMessageColor, - receivedMessage = Color(0x20B1B0B5) + primaryVariant2 = Color(0xFF172941), + sentMessage = Color(0xFF172941), + sentQuote = Color(0xFF1C3A57), + receivedMessage = Color(0xff25283a), + receivedQuote = Color(0xff36394a), ) -val CurrentColors: MutableStateFlow = MutableStateFlow(ThemeManager.currentColors(isInNightMode())) +val BlackColorPalette = darkColors( + primary = Color(0xff0077e0), // If this value changes also need to update #0088ff in string resource files + primaryVariant = Color(0xff0077e0), + secondary = HighOrLowlight, + secondaryVariant = DarkGray, + background = Color(0xff070707), + surface = Color(0xff161617), + // background = Color(0xFF121212), + // surface = Color(0xFF121212), + error = Color.Red, + onBackground = Color(0xFFFFFBFA), + onSurface = Color(0xFFFFFBFA), + // onError: Color = Color.Black, +) +val BlackColorPaletteApp = AppColors( + title = Color(0xff0077e0), + primaryVariant2 = Color(0xff243747), + sentMessage = Color(0xFF18262E), + sentQuote = Color(0xFF1D3847), + receivedMessage = Color(0xff1b1b1b), + receivedQuote = Color(0xff29292b), +) + +var systemInDarkThemeCurrently: Boolean = isInNightMode() + +val CurrentColors: MutableStateFlow = MutableStateFlow(ThemeManager.currentColors(null, null, chatModel.currentUser.value?.uiThemes, appPreferences.themeOverrides.get())) @Composable fun isInDarkTheme(): Boolean = !CurrentColors.collectAsState().value.colors.isLight @@ -263,31 +642,113 @@ fun isInDarkTheme(): Boolean = !CurrentColors.collectAsState().value.colors.isLi @Composable expect fun isSystemInDarkTheme(): Boolean +internal val LocalAppColors = staticCompositionLocalOf { LightColorPaletteApp } +internal val LocalAppWallpaper = staticCompositionLocalOf { AppWallpaper() } + +val MaterialTheme.appColors: AppColors + @Composable + @ReadOnlyComposable + get() = LocalAppColors.current + +fun AppColors.updateColorsFrom(other: AppColors) { + title = other.title + primaryVariant2 = other.primaryVariant2 + sentMessage = other.sentMessage + sentQuote = other.sentQuote + receivedMessage = other.receivedMessage + receivedQuote = other.receivedQuote +} + +fun AppWallpaper.updateWallpaperFrom(other: AppWallpaper) { + background = other.background + tint = other.tint + type = other.type +} + +val MaterialTheme.wallpaper: AppWallpaper + @Composable + @ReadOnlyComposable + get() = LocalAppWallpaper.current + fun reactOnDarkThemeChanges(isDark: Boolean) { - if (ChatController.appPrefs.currentTheme.get() == DefaultTheme.SYSTEM.name && CurrentColors.value.colors.isLight == isDark) { + systemInDarkThemeCurrently = isDark + if (ChatController.appPrefs.currentTheme.get() == DefaultTheme.SYSTEM_THEME_NAME && CurrentColors.value.colors.isLight == isDark) { // Change active colors from light to dark and back based on system theme - ThemeManager.applyTheme(DefaultTheme.SYSTEM.name, isDark) + ThemeManager.applyTheme(DefaultTheme.SYSTEM_THEME_NAME) } } @Composable fun SimpleXTheme(darkTheme: Boolean? = null, content: @Composable () -> Unit) { - LaunchedEffect(darkTheme) { - // For preview - if (darkTheme != null) - CurrentColors.value = ThemeManager.currentColors(darkTheme) - } - val systemDark = isSystemInDarkTheme() - LaunchedEffect(systemDark) { - reactOnDarkThemeChanges(systemDark) +// TODO: Fix preview working with dark/light theme + +// LaunchedEffect(darkTheme) { +// // For preview +// if (darkTheme != null) +// CurrentColors.value = ThemeManager.currentColors(darkTheme, null, null, chatModel.currentUser.value?.uiThemes, appPreferences.themeOverrides.get()) +// } + val systemDark = rememberUpdatedState(isSystemInDarkTheme()) + LaunchedEffect(Unit) { + // snapshotFlow vs LaunchedEffect reduce number of recomposes + snapshotFlow { systemDark.value } + .collect { + reactOnDarkThemeChanges(systemDark.value) + } } val theme by CurrentColors.collectAsState() + LaunchedEffect(Unit) { + // snapshotFlow vs LaunchedEffect reduce number of recomposes when user is changed or it's themes + snapshotFlow { chatModel.currentUser.value?.uiThemes } + .collect { + ThemeManager.applyTheme(appPrefs.currentTheme.get()!!) + } + } MaterialTheme( colors = theme.colors, typography = Typography, shapes = Shapes, content = { - CompositionLocalProvider(LocalContentColor provides MaterialTheme.colors.onBackground, content = content) + val rememberedAppColors = remember { + // Explicitly creating a new object here so we don't mutate the initial [appColors] + // provided, and overwrite the values set in it. + theme.appColors.copy() + }.apply { updateColorsFrom(theme.appColors) } + val rememberedWallpaper = remember { + // Explicitly creating a new object here so we don't mutate the initial [wallpaper] + // provided, and overwrite the values set in it. + theme.wallpaper.copy() + }.apply { updateWallpaperFrom(theme.wallpaper) } + CompositionLocalProvider( + LocalContentColor provides MaterialTheme.colors.onBackground, + LocalAppColors provides rememberedAppColors, + LocalAppWallpaper provides rememberedWallpaper, + content = content) + } + ) +} + +@Composable +fun SimpleXThemeOverride(theme: ThemeManager.ActiveTheme, content: @Composable () -> Unit) { + MaterialTheme( + colors = theme.colors, + typography = Typography, + shapes = Shapes, + content = { + val rememberedAppColors = remember { + // Explicitly creating a new object here so we don't mutate the initial [appColors] + // provided, and overwrite the values set in it. + theme.appColors.copy() + }.apply { updateColorsFrom(theme.appColors) } + val rememberedWallpaper = remember { + // Explicitly creating a new object here so we don't mutate the initial [wallpaper] + // provided, and overwrite the values set in it. + theme.wallpaper.copy() + }.apply { updateWallpaperFrom(theme.wallpaper) } + CompositionLocalProvider( + LocalContentColor provides MaterialTheme.colors.onBackground, + LocalAppColors provides rememberedAppColors, + LocalAppWallpaper provides rememberedWallpaper, + content = content) } ) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/ThemeManager.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/ThemeManager.kt index 49d3203455..2f8f6ed0bf 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/ThemeManager.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/ThemeManager.kt @@ -1,14 +1,14 @@ package chat.simplex.common.ui.theme import androidx.compose.material.Colors +import androidx.compose.runtime.MutableState import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.text.font.FontFamily -import chat.simplex.res.MR -import chat.simplex.common.model.AppPreferences -import chat.simplex.common.model.ChatController -import chat.simplex.common.platform.platform -import chat.simplex.common.views.helpers.generalGetString +import chat.simplex.common.model.* +import chat.simplex.common.platform.* +import chat.simplex.common.views.helpers.* +import java.io.File // https://github.com/rsms/inter // I place it here because IDEA shows an error (but still works anyway) when this declaration inside Type.kt @@ -18,140 +18,215 @@ expect val EmojiFont: FontFamily object ThemeManager { private val appPrefs: AppPreferences = ChatController.appPrefs - data class ActiveTheme(val name: String, val base: DefaultTheme, val colors: Colors, val appColors: AppColors) + data class ActiveTheme(val name: String, val base: DefaultTheme, val colors: Colors, val appColors: AppColors, val wallpaper: AppWallpaper = AppWallpaper()) private fun systemDarkThemeColors(): Pair = when (appPrefs.systemDarkTheme.get()) { - DefaultTheme.DARK.name -> DarkColorPalette to DefaultTheme.DARK - DefaultTheme.SIMPLEX.name -> SimplexColorPalette to DefaultTheme.SIMPLEX + DefaultTheme.DARK.themeName -> DarkColorPalette to DefaultTheme.DARK + DefaultTheme.SIMPLEX.themeName -> SimplexColorPalette to DefaultTheme.SIMPLEX + DefaultTheme.BLACK.themeName -> BlackColorPalette to DefaultTheme.BLACK else -> SimplexColorPalette to DefaultTheme.SIMPLEX } - fun currentColors(darkForSystemTheme: Boolean): ActiveTheme { + private fun nonSystemThemeName(): String { val themeName = appPrefs.currentTheme.get()!! - val themeOverrides = appPrefs.themeOverrides.get() - - val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.name) { + return if (themeName != DefaultTheme.SYSTEM_THEME_NAME) { themeName } else { - if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.name + if (systemInDarkThemeCurrently) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.themeName } - val theme = themeOverrides[nonSystemThemeName] + } + + fun defaultActiveTheme(appSettingsTheme: List): ThemeOverrides? { + val nonSystemThemeName = nonSystemThemeName() + val defaultThemeId = appPrefs.currentThemeIds.get()[nonSystemThemeName] + return appSettingsTheme.getTheme(defaultThemeId) + } + + fun defaultActiveTheme(perUserTheme: ThemeModeOverrides?, appSettingsTheme: List): ThemeModeOverride { + val perUserTheme = if (!CurrentColors.value.colors.isLight) perUserTheme?.dark else perUserTheme?.light + if (perUserTheme != null) { + return perUserTheme + } + val defaultTheme = defaultActiveTheme(appSettingsTheme) + return ThemeModeOverride(colors = defaultTheme?.colors ?: ThemeColors(), wallpaper = defaultTheme?.wallpaper) + } + + fun currentColors(themeOverridesForType: WallpaperType?, perChatTheme: ThemeModeOverride?, perUserTheme: ThemeModeOverrides?, appSettingsTheme: List): ActiveTheme { + val themeName = appPrefs.currentTheme.get()!! + val nonSystemThemeName = nonSystemThemeName() + val defaultTheme = defaultActiveTheme(appSettingsTheme) + val baseTheme = when (nonSystemThemeName) { - DefaultTheme.LIGHT.name -> Triple(DefaultTheme.LIGHT, LightColorPalette, LightColorPaletteApp) - DefaultTheme.DARK.name -> Triple(DefaultTheme.DARK, DarkColorPalette, DarkColorPaletteApp) - DefaultTheme.SIMPLEX.name -> Triple(DefaultTheme.SIMPLEX, SimplexColorPalette, SimplexColorPaletteApp) - else -> Triple(DefaultTheme.LIGHT, LightColorPalette, LightColorPaletteApp) + DefaultTheme.LIGHT.themeName -> ActiveTheme(DefaultTheme.LIGHT.themeName, DefaultTheme.LIGHT, LightColorPalette, LightColorPaletteApp, AppWallpaper(type = PresetWallpaper.SCHOOL.toType(DefaultTheme.LIGHT))) + DefaultTheme.DARK.themeName -> ActiveTheme(DefaultTheme.DARK.themeName, DefaultTheme.DARK, DarkColorPalette, DarkColorPaletteApp, AppWallpaper(type = PresetWallpaper.SCHOOL.toType(DefaultTheme.DARK))) + DefaultTheme.SIMPLEX.themeName -> ActiveTheme(DefaultTheme.SIMPLEX.themeName, DefaultTheme.SIMPLEX, SimplexColorPalette, SimplexColorPaletteApp, AppWallpaper(type = PresetWallpaper.SCHOOL.toType(DefaultTheme.SIMPLEX))) + DefaultTheme.BLACK.themeName -> ActiveTheme(DefaultTheme.BLACK.themeName, DefaultTheme.BLACK, BlackColorPalette, BlackColorPaletteApp, AppWallpaper(type = PresetWallpaper.SCHOOL.toType(DefaultTheme.BLACK))) + else -> ActiveTheme(DefaultTheme.LIGHT.themeName, DefaultTheme.LIGHT, LightColorPalette, LightColorPaletteApp, AppWallpaper(type = PresetWallpaper.SCHOOL.toType(DefaultTheme.LIGHT))) } - if (theme == null) { - return ActiveTheme(themeName, baseTheme.first, baseTheme.second, baseTheme.third) + + val perUserTheme = if (baseTheme.colors.isLight) perUserTheme?.light else perUserTheme?.dark + val theme = (appSettingsTheme.sameTheme(themeOverridesForType ?: perChatTheme?.type ?: perUserTheme?.type ?: defaultTheme?.wallpaper?.toAppWallpaper()?.type, nonSystemThemeName) ?: defaultTheme) + + if (theme == null && perUserTheme == null && perChatTheme == null && themeOverridesForType == null) { + return ActiveTheme(themeName, baseTheme.base, baseTheme.colors, baseTheme.appColors, baseTheme.wallpaper) } - return ActiveTheme(themeName, baseTheme.first, theme.colors.toColors(theme.base), theme.colors.toAppColors(theme.base)) + val presetWallpaperTheme = when { + perChatTheme?.wallpaper != null -> if (perChatTheme.wallpaper.preset != null) PresetWallpaper.from(perChatTheme.wallpaper.preset)?.colors?.get(baseTheme.base) else null + perUserTheme?.wallpaper != null -> if (perUserTheme.wallpaper.preset != null) PresetWallpaper.from(perUserTheme.wallpaper.preset)?.colors?.get(baseTheme.base) else null + else -> if (theme?.wallpaper?.preset != null) PresetWallpaper.from(theme.wallpaper.preset)?.colors?.get(baseTheme.base) else null + } + val themeOrEmpty = theme ?: ThemeOverrides(base = baseTheme.base) + val colors = themeOrEmpty.toColors(themeOrEmpty.base, perChatTheme?.colors, perUserTheme?.colors, presetWallpaperTheme) + return ActiveTheme( + themeName, + baseTheme.base, + colors, + themeOrEmpty.toAppColors(themeOrEmpty.base, perChatTheme?.colors, perChatTheme?.type, perUserTheme?.colors, perUserTheme?.type, presetWallpaperTheme), + themeOrEmpty.toAppWallpaper(themeOverridesForType, perChatTheme, perUserTheme, colors.background) + ) } - fun currentThemeOverridesForExport(darkForSystemTheme: Boolean): ThemeOverrides { - val themeName = appPrefs.currentTheme.get()!! - val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.name) { - themeName - } else { - if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.name - } - val overrides = appPrefs.themeOverrides.get().toMutableMap() - val nonFilledTheme = overrides[nonSystemThemeName] ?: ThemeOverrides(base = CurrentColors.value.base, colors = ThemeColors()) - return nonFilledTheme.copy(colors = nonFilledTheme.colors.withFilledColors(CurrentColors.value.base)) + fun currentThemeOverridesForExport(perChatTheme: ThemeModeOverride?, perUserTheme: ThemeModeOverrides?): ThemeOverrides { + val current = currentColors(null, perChatTheme, perUserTheme, appPrefs.themeOverrides.get()) + val wType = current.wallpaper.type + val wBackground = current.wallpaper.background + val wTint = current.wallpaper.tint + return ThemeOverrides( + themeId = "", + base = current.base, + colors = ThemeColors.from(current.colors, current.appColors), + wallpaper = if (wType !is WallpaperType.Empty) ThemeWallpaper.from(wType, wBackground?.toReadableHex(), wTint?.toReadableHex()).withFilledWallpaperBase64() else null + ) } - // colors, default theme enum, localized name of theme - fun allThemes(darkForSystemTheme: Boolean): List> { - val allThemes = ArrayList>() - allThemes.add( - Triple( - if (darkForSystemTheme) systemDarkThemeColors().first else LightColorPalette, - DefaultTheme.SYSTEM, - generalGetString(MR.strings.theme_system) - ) - ) - allThemes.add( - Triple( - LightColorPalette, - DefaultTheme.LIGHT, - generalGetString(MR.strings.theme_light) - ) - ) - allThemes.add( - Triple( - DarkColorPalette, - DefaultTheme.DARK, - generalGetString(MR.strings.theme_dark) - ) - ) - allThemes.add( - Triple( - SimplexColorPalette, - DefaultTheme.SIMPLEX, - generalGetString(MR.strings.theme_simplex) - ) - ) - return allThemes - } - - fun applyTheme(theme: String, darkForSystemTheme: Boolean) { + fun applyTheme(theme: String) { appPrefs.currentTheme.set(theme) - CurrentColors.value = currentColors(darkForSystemTheme) + CurrentColors.value = currentColors(null, null, chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) platform.androidSetNightModeIfSupported() } - fun changeDarkTheme(theme: String, darkForSystemTheme: Boolean) { + fun changeDarkTheme(theme: String) { appPrefs.systemDarkTheme.set(theme) - CurrentColors.value = currentColors(darkForSystemTheme) + CurrentColors.value = currentColors(null, null, chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) } - fun saveAndApplyThemeColor(name: ThemeColor, color: Color? = null, darkForSystemTheme: Boolean) { - val themeName = appPrefs.currentTheme.get()!! - val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.name) { - themeName - } else { - if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.name + fun saveAndApplyThemeColor(baseTheme: DefaultTheme, name: ThemeColor, color: Color? = null, pref: SharedPreference> = appPrefs.themeOverrides) { + val nonSystemThemeName = baseTheme.themeName + val overrides = pref.get() + val themeId = appPrefs.currentThemeIds.get()[nonSystemThemeName] + val prevValue = overrides.getTheme(themeId) ?: ThemeOverrides(base = baseTheme) + pref.set(overrides.replace(prevValue.withUpdatedColor(name, color?.toReadableHex()))) + val themeIds = appPrefs.currentThemeIds.get().toMutableMap() + themeIds[nonSystemThemeName] = prevValue.themeId + appPrefs.currentThemeIds.set(themeIds) + CurrentColors.value = currentColors(null, null, chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) + } + + fun applyThemeColor(name: ThemeColor, color: Color? = null, pref: MutableState) { + pref.value = pref.value.withUpdatedColor(name, color?.toReadableHex()) + } + + fun saveAndApplyWallpaper(baseTheme: DefaultTheme, type: WallpaperType?, pref: SharedPreference> = appPrefs.themeOverrides) { + val nonSystemThemeName = baseTheme.themeName + val overrides = pref.get() + val theme = overrides.sameTheme(type, baseTheme.themeName) + val prevValue = theme ?: ThemeOverrides(base = baseTheme) + pref.set(overrides.replace(prevValue.copy(wallpaper = if (type != null && type !is WallpaperType.Empty) ThemeWallpaper.from(type, prevValue.wallpaper?.background, prevValue.wallpaper?.tint) else null))) + val themeIds = appPrefs.currentThemeIds.get().toMutableMap() + themeIds[nonSystemThemeName] = prevValue.themeId + appPrefs.currentThemeIds.set(themeIds) + CurrentColors.value = currentColors( null, null, chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) + } + + fun copyFromSameThemeOverrides(type: WallpaperType?, lowerLevelOverride: ThemeModeOverride?, pref: MutableState): Boolean { + val overrides = appPrefs.themeOverrides.get() + val sameWallpaper = if (lowerLevelOverride?.type?.sameType(type) == true) lowerLevelOverride.wallpaper else overrides.sameTheme(type, CurrentColors.value.base.themeName)?.wallpaper + if (sameWallpaper == null) { + if (type != null) { + pref.value = ThemeModeOverride(wallpaper = ThemeWallpaper.from(type, null, null).copy(scale = null, scaleType = null)) + } else { + // Make an empty wallpaper to override any top level ones + pref.value = ThemeModeOverride(wallpaper = ThemeWallpaper()) + } + return true } - var colorToSet = color - if (colorToSet == null) { - // Setting default color from a base theme - colorToSet = when(nonSystemThemeName) { - DefaultTheme.LIGHT.name -> name.fromColors(LightColorPalette, LightColorPaletteApp) - DefaultTheme.DARK.name -> name.fromColors(DarkColorPalette, DarkColorPaletteApp) - DefaultTheme.SIMPLEX.name -> name.fromColors(SimplexColorPalette, SimplexColorPaletteApp) - // Will not be here - else -> return + var type = sameWallpaper.toAppWallpaper().type + if (type is WallpaperType.Image && sameWallpaper.imageFile == type.filename) { + // same image file. Needs to be copied first in order to be able to remove the file once it's not needed anymore without affecting main theme override + val filename = saveWallpaperFile(File(getWallpaperFilePath(type.filename)).toURI()) + if (filename != null) { + type = WallpaperType.Image(filename, type.scale, type.scaleType) + } else { + Log.e(TAG, "Error while copying wallpaper from global overrides to chat overrides") + return false } } - val overrides = appPrefs.themeOverrides.get().toMutableMap() - val prevValue = overrides[nonSystemThemeName] ?: ThemeOverrides(base = CurrentColors.value.base, colors = ThemeColors()) - overrides[nonSystemThemeName] = prevValue.withUpdatedColor(name, colorToSet.toReadableHex()) - appPrefs.themeOverrides.set(overrides) - CurrentColors.value = currentColors(!CurrentColors.value.colors.isLight) + val prevValue = pref.value + pref.value = prevValue.copy( + colors = ThemeColors(), + wallpaper = ThemeWallpaper.from(type, null, null).copy(scale = null, scaleType = null) + ) + return true } - fun saveAndApplyThemeOverrides(theme: ThemeOverrides, darkForSystemTheme: Boolean) { - val overrides = appPrefs.themeOverrides.get().toMutableMap() - val prevValue = overrides[theme.base.name] ?: ThemeOverrides(base = CurrentColors.value.base, colors = ThemeColors()) - overrides[theme.base.name] = prevValue.copy(colors = theme.colors) - appPrefs.themeOverrides.set(overrides) - appPrefs.currentTheme.set(theme.base.name) - CurrentColors.value = currentColors(!CurrentColors.value.colors.isLight) + fun applyWallpaper(type: WallpaperType?, pref: MutableState) { + val prevValue = pref.value + pref.value = prevValue.copy( + wallpaper = if (type != null) + ThemeWallpaper.from(type, prevValue.wallpaper?.background, prevValue.wallpaper?.tint) + else null + ) } - fun resetAllThemeColors(darkForSystemTheme: Boolean) { - val themeName = appPrefs.currentTheme.get()!! - val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.name) { - themeName - } else { - if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.name + fun saveAndApplyThemeOverrides(theme: ThemeOverrides, pref: SharedPreference> = appPrefs.themeOverrides) { + val wallpaper = theme.wallpaper?.importFromString() + val nonSystemThemeName = theme.base.themeName + val overrides = pref.get() + val prevValue = overrides.getTheme(null, wallpaper?.toAppWallpaper()?.type, theme.base) ?: ThemeOverrides(base = theme.base) + if (prevValue.wallpaper?.imageFile != null) { + File(getWallpaperFilePath(prevValue.wallpaper.imageFile)).delete() + } + pref.set(overrides.replace(prevValue.copy(base = theme.base, colors = theme.colors, wallpaper = wallpaper))) + appPrefs.currentTheme.set(nonSystemThemeName) + val currentThemeIds = appPrefs.currentThemeIds.get().toMutableMap() + currentThemeIds[nonSystemThemeName] = prevValue.themeId + appPrefs.currentThemeIds.set(currentThemeIds) + CurrentColors.value = currentColors(null, null, chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) + } + + fun resetAllThemeColors(pref: SharedPreference> = appPrefs.themeOverrides) { + val nonSystemThemeName = nonSystemThemeName() + val themeId = appPrefs.currentThemeIds.get()[nonSystemThemeName] ?: return + val overrides = pref.get() + val prevValue = overrides.getTheme(themeId) ?: return + pref.set(overrides.replace(prevValue.copy(colors = ThemeColors(), wallpaper = prevValue.wallpaper?.copy(background = null, tint = null)))) + CurrentColors.value = currentColors(null, null, chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) + } + + fun resetAllThemeColors(pref: MutableState) { + val prevValue = pref.value + pref.value = prevValue.copy(colors = ThemeColors(), wallpaper = prevValue.wallpaper?.copy(background = null, tint = null)) + } + + fun removeTheme(themeId: String?) { + val themes = ArrayList(appPrefs.themeOverrides.get()) + themes.removeAll { it.themeId == themeId } + appPrefs.themeOverrides.set(themes) + } + + fun String.colorFromReadableHex(): Color = + Color(this.replace("#", "").toLongOrNull(16) ?: Color.White.toArgb().toLong()) + + fun Color.toReadableHex(): String { + val s = Integer.toHexString(toArgb()) + return when { + this == Color.Transparent -> "#00ffffff" + s.length == 1 -> "#ff$s$s$s$s$s$s" + s.length == 2 -> "#ff$s$s$s" + s.length == 3 -> "#ff$s$s" + s.length == 6 && this.alpha == 0f -> "#00$s" + s.length == 6 -> "#ff$s" + else -> "#$s" } - val overrides = appPrefs.themeOverrides.get().toMutableMap() - val prevValue = overrides[nonSystemThemeName] ?: return - overrides[nonSystemThemeName] = prevValue.copy(colors = ThemeColors()) - appPrefs.themeOverrides.set(overrides) - CurrentColors.value = currentColors(!CurrentColors.value.colors.isLight) } } - -private fun Color.toReadableHex(): String = "#" + Integer.toHexString(toArgb()) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt index dcd36e026b..9b1e908e6b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt @@ -29,6 +29,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.common.model.* +import chat.simplex.common.model.ChatController.appPrefs import chat.simplex.common.model.ChatModel.controller import chat.simplex.common.ui.theme.* import chat.simplex.common.views.helpers.* @@ -337,6 +338,16 @@ fun ChatInfoLayout( if (cStats != null && cStats.ratchetSyncAllowed) { SynchronizeConnectionButton(syncContactConnection) } + + WallpaperButton { + ModalManager.end.showModal { + val chat = remember { derivedStateOf { chatModel.chats.firstOrNull { it.id == chat.id } } } + val c = chat.value + if (c != null) { + ChatWallpaperEditorModal(c) + } + } + } // } else if (developerTools) { // SynchronizeConnectionButtonForce(syncContactConnectionForce) // } @@ -642,6 +653,15 @@ private fun SendReceiptsOption(currentUser: User, state: State, on ) } +@Composable +fun WallpaperButton(onClick: () -> Unit) { + SettingsActionItem( + painterResource(MR.images.ic_image), + stringResource(MR.strings.settings_section_title_chat_theme), + click = onClick + ) +} + @Composable fun ClearChatButton(onClick: () -> Unit) { SettingsActionItem( @@ -675,6 +695,51 @@ fun ShareAddressButton(onClick: () -> Unit) { ) } +@Composable +fun ModalData.ChatWallpaperEditorModal(chat: Chat) { + val themes = remember(CurrentColors.collectAsState().value.base) { + (chat.chatInfo as? ChatInfo.Direct)?.contact?.uiThemes + ?: (chat.chatInfo as? ChatInfo.Group)?.groupInfo?.uiThemes + ?: ThemeModeOverrides() + } + val globalThemeUsed = remember { stateGetOrPut("globalThemeUsed") { false } } + val initialTheme = remember(CurrentColors.collectAsState().value.base) { + val preferred = themes.preferredMode(!CurrentColors.value.colors.isLight) + globalThemeUsed.value = preferred == null + preferred ?: ThemeManager.defaultActiveTheme(chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) + } + ChatWallpaperEditor( + initialTheme, + applyToMode = if (themes.light == themes.dark) null else initialTheme.mode, + globalThemeUsed = globalThemeUsed, + save = { applyToMode, newTheme -> + save(applyToMode, newTheme, chatModel.getChat(chat.id) ?: chat) + }) +} + +suspend fun save(applyToMode: DefaultThemeMode?, newTheme: ThemeModeOverride?, chat: Chat) { + val unchangedThemes: ThemeModeOverrides = ((chat.chatInfo as? ChatInfo.Direct)?.contact?.uiThemes ?: (chat.chatInfo as? ChatInfo.Group)?.groupInfo?.uiThemes) ?: ThemeModeOverrides() + val wallpaperFiles = listOf(unchangedThemes.light?.wallpaper?.imageFile, unchangedThemes.dark?.wallpaper?.imageFile) + var changedThemes: ThemeModeOverrides? = unchangedThemes + val changed = newTheme?.copy(wallpaper = newTheme.wallpaper?.withFilledWallpaperPath()) + changedThemes = when (applyToMode) { + null -> changedThemes?.copy(light = changed?.copy(mode = DefaultThemeMode.LIGHT), dark = changed?.copy(mode = DefaultThemeMode.DARK)) + DefaultThemeMode.LIGHT -> changedThemes?.copy(light = changed?.copy(mode = applyToMode)) + DefaultThemeMode.DARK -> changedThemes?.copy(dark = changed?.copy(mode = applyToMode)) + } + changedThemes = if (changedThemes?.light != null || changedThemes?.dark != null) changedThemes else null + val wallpaperFilesToDelete = wallpaperFiles - changedThemes?.light?.wallpaper?.imageFile - changedThemes?.dark?.wallpaper?.imageFile + wallpaperFilesToDelete.forEach(::removeWallpaperFile) + + if (controller.apiSetChatUIThemes(chat.remoteHostId, chat.id, changedThemes)) { + if (chat.chatInfo is ChatInfo.Direct) { + chatModel.updateChatInfo(chat.remoteHostId, chat.chatInfo.copy(contact = chat.chatInfo.contact.copy(uiThemes = changedThemes))) + } else if (chat.chatInfo is ChatInfo.Group) { + chatModel.updateChatInfo(chat.remoteHostId, chat.chatInfo.copy(groupInfo = chat.chatInfo.groupInfo.copy(uiThemes = changedThemes))) + } + } +} + private fun setContactAlias(chat: Chat, localAlias: String, chatModel: ChatModel) = withBGApi { val chatRh = chat.remoteHostId chatModel.controller.apiSetContactAlias(chatRh, chat.chatInfo.apiId, localAlias)?.let { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatItemInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatItemInfoView.kt index e00592bce9..1e564db134 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatItemInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatItemInfoView.kt @@ -42,7 +42,7 @@ sealed class CIInfoTab { @Composable fun ChatItemInfoView(chatRh: Long?, ci: ChatItem, ciInfo: ChatItemInfo, devTools: Boolean) { val sent = ci.chatDir.sent - val appColors = CurrentColors.collectAsState().value.appColors + val appColors = MaterialTheme.appColors val uriHandler = LocalUriHandler.current val selection = remember { mutableStateOf(CIInfoTab.History) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt index 6c3a884a0e..60f741b9af 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt @@ -5,25 +5,24 @@ import androidx.compose.foundation.* import androidx.compose.foundation.gestures.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.* -import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.runtime.saveable.mapSaver import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.* -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.graphics.* import androidx.compose.ui.platform.* import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.text.* import androidx.compose.ui.unit.* import chat.simplex.common.model.* +import chat.simplex.common.model.ChatController.appPrefs import chat.simplex.common.model.ChatModel.controller import chat.simplex.common.ui.theme.* import chat.simplex.common.views.call.* @@ -118,369 +117,373 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId: val clipboard = LocalClipboardManager.current when (chat.chatInfo) { is ChatInfo.Direct, is ChatInfo.Group, is ChatInfo.Local -> { - ChatLayout( - chat, - unreadCount, - composeState, - composeView = { - Column( - Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - if ( - chat.chatInfo is ChatInfo.Direct - && !chat.chatInfo.contact.ready - && chat.chatInfo.contact.active - && !chat.chatInfo.contact.nextSendGrpInv + val perChatTheme = remember(chat.chatInfo, CurrentColors.value.base) { if (chat.chatInfo is ChatInfo.Direct) chat.chatInfo.contact.uiThemes?.preferredMode(!CurrentColors.value.colors.isLight) else if (chat.chatInfo is ChatInfo.Group) chat.chatInfo.groupInfo.uiThemes?.preferredMode(!CurrentColors.value.colors.isLight) else null } + val overrides = if (perChatTheme != null) ThemeManager.currentColors(null, perChatTheme, chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) else null + SimpleXThemeOverride(overrides ?: CurrentColors.collectAsState().value) { + ChatLayout( + chat, + unreadCount, + composeState, + composeView = { + Column( + Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally ) { - Text( - generalGetString(MR.strings.contact_connection_pending), - Modifier.padding(top = 4.dp), - fontSize = 14.sp, - color = MaterialTheme.colors.secondary + if ( + chat.chatInfo is ChatInfo.Direct + && !chat.chatInfo.contact.ready + && chat.chatInfo.contact.active + && !chat.chatInfo.contact.nextSendGrpInv + ) { + Text( + generalGetString(MR.strings.contact_connection_pending), + Modifier.padding(top = 4.dp), + fontSize = 14.sp, + color = MaterialTheme.colors.secondary + ) + } + ComposeView( + chatModel, chat, composeState, attachmentOption, + showChooseAttachment = { scope.launch { attachmentBottomSheetState.show() } } ) } - ComposeView( - chatModel, chat, composeState, attachmentOption, - showChooseAttachment = { scope.launch { attachmentBottomSheetState.show() } } - ) - } - }, - attachmentOption, - attachmentBottomSheetState, - searchText, - useLinkPreviews = useLinkPreviews, - linkMode = chatModel.simplexLinkMode.value, - back = { - hideKeyboard(view) - AudioPlayer.stop() - chatModel.chatId.value = null - chatModel.groupMembers.clear() - }, - info = { - if (ModalManager.end.hasModalsOpen()) { - ModalManager.end.closeModals() - return@ChatLayout - } - hideKeyboard(view) - withBGApi { - // The idea is to preload information before showing a modal because large groups can take time to load all members - var preloadedContactInfo: Pair? = null - var preloadedCode: String? = null - var preloadedLink: Pair? = null - if (chat.chatInfo is ChatInfo.Direct) { - preloadedContactInfo = chatModel.controller.apiContactInfo(chatRh, chat.chatInfo.apiId) - preloadedCode = chatModel.controller.apiGetContactCode(chatRh, chat.chatInfo.apiId)?.second - } else if (chat.chatInfo is ChatInfo.Group) { - setGroupMembers(chatRh, chat.chatInfo.groupInfo, chatModel) - preloadedLink = chatModel.controller.apiGetGroupLink(chatRh, chat.chatInfo.groupInfo.groupId) + }, + attachmentOption, + attachmentBottomSheetState, + searchText, + useLinkPreviews = useLinkPreviews, + linkMode = chatModel.simplexLinkMode.value, + back = { + hideKeyboard(view) + AudioPlayer.stop() + chatModel.chatId.value = null + chatModel.groupMembers.clear() + }, + info = { + if (ModalManager.end.hasModalsOpen()) { + ModalManager.end.closeModals() + return@ChatLayout } - ModalManager.end.showModalCloseable(true) { close -> - val chat = remember { activeChat }.value - if (chat?.chatInfo is ChatInfo.Direct) { - var contactInfo: Pair? by remember { mutableStateOf(preloadedContactInfo) } - var code: String? by remember { mutableStateOf(preloadedCode) } - KeyChangeEffect(chat.id, ChatModel.networkStatuses.toMap()) { - contactInfo = chatModel.controller.apiContactInfo(chatRh, chat.chatInfo.apiId) - preloadedContactInfo = contactInfo - code = chatModel.controller.apiGetContactCode(chatRh, chat.chatInfo.apiId)?.second - preloadedCode = code - } - ChatInfoView(chatModel, (chat.chatInfo as ChatInfo.Direct).contact, contactInfo?.first, contactInfo?.second, chat.chatInfo.localAlias, code, close) - } else if (chat?.chatInfo is ChatInfo.Group) { - var link: Pair? by remember(chat.id) { mutableStateOf(preloadedLink) } - KeyChangeEffect(chat.id) { - setGroupMembers(chatRh, (chat.chatInfo as ChatInfo.Group).groupInfo, chatModel) - link = chatModel.controller.apiGetGroupLink(chatRh, chat.chatInfo.groupInfo.groupId) - preloadedLink = link - } - GroupChatInfoView(chatModel, chatRh, chat.id, link?.first, link?.second, { - link = it - preloadedLink = it - }, close) - } - } - } - }, - showMemberInfo = { groupInfo: GroupInfo, member: GroupMember -> - hideKeyboard(view) - withBGApi { - val r = chatModel.controller.apiGroupMemberInfo(chatRh, groupInfo.groupId, member.groupMemberId) - val stats = r?.second - val (_, code) = if (member.memberActive) { - val memCode = chatModel.controller.apiGetGroupMemberCode(chatRh, groupInfo.apiId, member.groupMemberId) - member to memCode?.second - } else { - member to null - } - setGroupMembers(chatRh, groupInfo, chatModel) - ModalManager.end.closeModals() - ModalManager.end.showModalCloseable(true) { close -> - remember { derivedStateOf { chatModel.getGroupMember(member.groupMemberId) } }.value?.let { mem -> - GroupMemberInfoView(chatRh, groupInfo, mem, stats, code, chatModel, close, close) - } - } - } - }, - loadPrevMessages = { - if (chatModel.chatId.value != activeChat.value?.id) return@ChatLayout - val c = chatModel.getChat(chatModel.chatId.value ?: return@ChatLayout) - val firstId = chatModel.chatItems.value.firstOrNull()?.id - if (c != null && firstId != null) { + hideKeyboard(view) withBGApi { - apiLoadPrevMessages(c, chatModel, firstId, searchText.value) + // The idea is to preload information before showing a modal because large groups can take time to load all members + var preloadedContactInfo: Pair? = null + var preloadedCode: String? = null + var preloadedLink: Pair? = null + if (chat.chatInfo is ChatInfo.Direct) { + preloadedContactInfo = chatModel.controller.apiContactInfo(chatRh, chat.chatInfo.apiId) + preloadedCode = chatModel.controller.apiGetContactCode(chatRh, chat.chatInfo.apiId)?.second + } else if (chat.chatInfo is ChatInfo.Group) { + setGroupMembers(chatRh, chat.chatInfo.groupInfo, chatModel) + preloadedLink = chatModel.controller.apiGetGroupLink(chatRh, chat.chatInfo.groupInfo.groupId) + } + ModalManager.end.showModalCloseable(true) { close -> + val chat = remember { activeChat }.value + if (chat?.chatInfo is ChatInfo.Direct) { + var contactInfo: Pair? by remember { mutableStateOf(preloadedContactInfo) } + var code: String? by remember { mutableStateOf(preloadedCode) } + KeyChangeEffect(chat.id, ChatModel.networkStatuses.toMap()) { + contactInfo = chatModel.controller.apiContactInfo(chatRh, chat.chatInfo.apiId) + preloadedContactInfo = contactInfo + code = chatModel.controller.apiGetContactCode(chatRh, chat.chatInfo.apiId)?.second + preloadedCode = code + } + ChatInfoView(chatModel, (chat.chatInfo as ChatInfo.Direct).contact, contactInfo?.first, contactInfo?.second, chat.chatInfo.localAlias, code, close) + } else if (chat?.chatInfo is ChatInfo.Group) { + var link: Pair? by remember(chat.id) { mutableStateOf(preloadedLink) } + KeyChangeEffect(chat.id) { + setGroupMembers(chatRh, (chat.chatInfo as ChatInfo.Group).groupInfo, chatModel) + link = chatModel.controller.apiGetGroupLink(chatRh, chat.chatInfo.groupInfo.groupId) + preloadedLink = link + } + GroupChatInfoView(chatModel, chatRh, chat.id, link?.first, link?.second, { + link = it + preloadedLink = it + }, close) + } + } } - } - }, - deleteMessage = { itemId, mode -> - withBGApi { - val cInfo = chat.chatInfo - val toDeleteItem = chatModel.chatItems.value.firstOrNull { it.id == itemId } - val toModerate = toDeleteItem?.memberToModerate(chat.chatInfo) - val groupInfo = toModerate?.first - val groupMember = toModerate?.second - val deletedChatItem: ChatItem? - val toChatItem: ChatItem? - if (mode == CIDeleteMode.cidmBroadcast && groupInfo != null && groupMember != null) { - val r = chatModel.controller.apiDeleteMemberChatItem( - chatRh, - groupId = groupInfo.groupId, - groupMemberId = groupMember.groupMemberId, - itemId = itemId - ) - deletedChatItem = r?.first - toChatItem = r?.second - } else { - val r = chatModel.controller.apiDeleteChatItem( - chatRh, + }, + showMemberInfo = { groupInfo: GroupInfo, member: GroupMember -> + hideKeyboard(view) + withBGApi { + val r = chatModel.controller.apiGroupMemberInfo(chatRh, groupInfo.groupId, member.groupMemberId) + val stats = r?.second + val (_, code) = if (member.memberActive) { + val memCode = chatModel.controller.apiGetGroupMemberCode(chatRh, groupInfo.apiId, member.groupMemberId) + member to memCode?.second + } else { + member to null + } + setGroupMembers(chatRh, groupInfo, chatModel) + ModalManager.end.closeModals() + ModalManager.end.showModalCloseable(true) { close -> + remember { derivedStateOf { chatModel.getGroupMember(member.groupMemberId) } }.value?.let { mem -> + GroupMemberInfoView(chatRh, groupInfo, mem, stats, code, chatModel, close, close) + } + } + } + }, + loadPrevMessages = { + if (chatModel.chatId.value != activeChat.value?.id) return@ChatLayout + val c = chatModel.getChat(chatModel.chatId.value ?: return@ChatLayout) + val firstId = chatModel.chatItems.value.firstOrNull()?.id + if (c != null && firstId != null) { + withBGApi { + apiLoadPrevMessages(c, chatModel, firstId, searchText.value) + } + } + }, + deleteMessage = { itemId, mode -> + withBGApi { + val cInfo = chat.chatInfo + val toDeleteItem = chatModel.chatItems.value.firstOrNull { it.id == itemId } + val toModerate = toDeleteItem?.memberToModerate(chat.chatInfo) + val groupInfo = toModerate?.first + val groupMember = toModerate?.second + val deletedChatItem: ChatItem? + val toChatItem: ChatItem? + if (mode == CIDeleteMode.cidmBroadcast && groupInfo != null && groupMember != null) { + val r = chatModel.controller.apiDeleteMemberChatItem( + chatRh, + groupId = groupInfo.groupId, + groupMemberId = groupMember.groupMemberId, + itemId = itemId + ) + deletedChatItem = r?.first + toChatItem = r?.second + } else { + val r = chatModel.controller.apiDeleteChatItem( + chatRh, + type = cInfo.chatType, + id = cInfo.apiId, + itemId = itemId, + mode = mode + ) + deletedChatItem = r?.deletedChatItem?.chatItem + toChatItem = r?.toChatItem?.chatItem + } + if (toChatItem == null && deletedChatItem != null) { + chatModel.removeChatItem(chatRh, cInfo, deletedChatItem) + } else if (toChatItem != null) { + chatModel.upsertChatItem(chatRh, cInfo, toChatItem) + } + } + }, + deleteMessages = { itemIds -> + if (itemIds.isNotEmpty()) { + val chatInfo = chat.chatInfo + withBGApi { + val deletedItems: ArrayList = arrayListOf() + for (itemId in itemIds) { + val di = chatModel.controller.apiDeleteChatItem( + chatRh, chatInfo.chatType, chatInfo.apiId, itemId, CIDeleteMode.cidmInternal + )?.deletedChatItem?.chatItem + if (di != null) { + deletedItems.add(di) + } + } + for (di in deletedItems) { + chatModel.removeChatItem(chatRh, chatInfo, di) + } + } + } + }, + receiveFile = { fileId -> + withBGApi { chatModel.controller.receiveFile(chatRh, user, fileId) } + }, + cancelFile = { fileId -> + withBGApi { chatModel.controller.cancelFile(chatRh, user, fileId) } + }, + joinGroup = { groupId, onComplete -> + withBGApi { + chatModel.controller.apiJoinGroup(chatRh, groupId) + onComplete.invoke() + } + }, + startCall = out@{ media -> + withBGApi { + val cInfo = chat.chatInfo + if (cInfo is ChatInfo.Direct) { + val contactInfo = chatModel.controller.apiContactInfo(chat.remoteHostId, cInfo.contact.contactId) + val profile = contactInfo?.second ?: chatModel.currentUser.value?.profile?.toProfile() ?: return@withBGApi + chatModel.activeCall.value = Call(remoteHostId = chatRh, contact = cInfo.contact, callState = CallState.WaitCapabilities, localMedia = media, userProfile = profile) + chatModel.showCallView.value = true + chatModel.callCommand.add(WCallCommand.Capabilities(media)) + } + } + }, + endCall = { + val call = chatModel.activeCall.value + if (call != null) withBGApi { chatModel.callManager.endCall(call) } + }, + acceptCall = { contact -> + hideKeyboard(view) + withBGApi { + val invitation = chatModel.callInvitations.remove(contact.id) + ?: controller.apiGetCallInvitations(chatModel.remoteHostId()).firstOrNull { it.contact.id == contact.id } + if (invitation == null) { + AlertManager.shared.showAlertMsg(generalGetString(MR.strings.call_already_ended)) + } else { + chatModel.callManager.acceptIncomingCall(invitation = invitation) + } + } + }, + acceptFeature = { contact, feature, param -> + withBGApi { + chatModel.controller.allowFeatureToContact(chatRh, contact, feature, param) + } + }, + openDirectChat = { contactId -> + withBGApi { + openDirectChat(chatRh, contactId, chatModel) + } + }, + updateContactStats = { contact -> + withBGApi { + val r = chatModel.controller.apiContactInfo(chatRh, chat.chatInfo.apiId) + if (r != null) { + val contactStats = r.first + if (contactStats != null) + chatModel.updateContactConnectionStats(chatRh, contact, contactStats) + } + } + }, + updateMemberStats = { groupInfo, member -> + withBGApi { + val r = chatModel.controller.apiGroupMemberInfo(chatRh, groupInfo.groupId, member.groupMemberId) + if (r != null) { + val memStats = r.second + if (memStats != null) { + chatModel.updateGroupMemberConnectionStats(chatRh, groupInfo, r.first, memStats) + } + } + } + }, + syncContactConnection = { contact -> + withBGApi { + val cStats = chatModel.controller.apiSyncContactRatchet(chatRh, contact.contactId, force = false) + if (cStats != null) { + chatModel.updateContactConnectionStats(chatRh, contact, cStats) + } + } + }, + syncMemberConnection = { groupInfo, member -> + withBGApi { + val r = chatModel.controller.apiSyncGroupMemberRatchet(chatRh, groupInfo.apiId, member.groupMemberId, force = false) + if (r != null) { + chatModel.updateGroupMemberConnectionStats(chatRh, groupInfo, r.first, r.second) + } + } + }, + findModelChat = { chatId -> + chatModel.getChat(chatId) + }, + findModelMember = { memberId -> + chatModel.groupMembers.find { it.id == memberId } + }, + setReaction = { cInfo, cItem, add, reaction -> + withBGApi { + val updatedCI = chatModel.controller.apiChatItemReaction( + rh = chatRh, type = cInfo.chatType, id = cInfo.apiId, - itemId = itemId, - mode = mode + itemId = cItem.id, + add = add, + reaction = reaction ) - deletedChatItem = r?.deletedChatItem?.chatItem - toChatItem = r?.toChatItem?.chatItem + if (updatedCI != null) { + chatModel.updateChatItem(cInfo, updatedCI) + } } - if (toChatItem == null && deletedChatItem != null) { - chatModel.removeChatItem(chatRh, cInfo, deletedChatItem) - } else if (toChatItem != null) { - chatModel.upsertChatItem(chatRh, cInfo, toChatItem) - } - } - }, - deleteMessages = { itemIds -> - if (itemIds.isNotEmpty()) { - val chatInfo = chat.chatInfo - withBGApi { - val deletedItems: ArrayList = arrayListOf() - for (itemId in itemIds) { - val di = chatModel.controller.apiDeleteChatItem( - chatRh, chatInfo.chatType, chatInfo.apiId, itemId, CIDeleteMode.cidmInternal - )?.deletedChatItem?.chatItem - if (di != null) { - deletedItems.add(di) + }, + showItemDetails = { cInfo, cItem -> + suspend fun loadChatItemInfo(): ChatItemInfo? { + val ciInfo = chatModel.controller.apiGetChatItemInfo(chatRh, cInfo.chatType, cInfo.apiId, cItem.id) + if (ciInfo != null) { + if (chat.chatInfo is ChatInfo.Group) { + setGroupMembers(chatRh, chat.chatInfo.groupInfo, chatModel) } } - for (di in deletedItems) { - chatModel.removeChatItem(chatRh, chatInfo, di) - } + return ciInfo } - } - }, - receiveFile = { fileId -> - withBGApi { chatModel.controller.receiveFile(chatRh, user, fileId) } - }, - cancelFile = { fileId -> - withBGApi { chatModel.controller.cancelFile(chatRh, user, fileId) } - }, - joinGroup = { groupId, onComplete -> - withBGApi { - chatModel.controller.apiJoinGroup(chatRh, groupId) - onComplete.invoke() - } - }, - startCall = out@{ media -> - withBGApi { - val cInfo = chat.chatInfo - if (cInfo is ChatInfo.Direct) { - val contactInfo = chatModel.controller.apiContactInfo(chat.remoteHostId, cInfo.contact.contactId) - val profile = contactInfo?.second ?: chatModel.currentUser.value?.profile?.toProfile() ?: return@withBGApi - chatModel.activeCall.value = Call(remoteHostId = chatRh, contact = cInfo.contact, callState = CallState.WaitCapabilities, localMedia = media, userProfile = profile) - chatModel.showCallView.value = true - chatModel.callCommand.add(WCallCommand.Capabilities(media)) - } - } - }, - endCall = { - val call = chatModel.activeCall.value - if (call != null) withBGApi { chatModel.callManager.endCall(call) } - }, - acceptCall = { contact -> - hideKeyboard(view) - withBGApi { - val invitation = chatModel.callInvitations.remove(contact.id) - ?: controller.apiGetCallInvitations(chatModel.remoteHostId()).firstOrNull { it.contact.id == contact.id } - if (invitation == null) { - AlertManager.shared.showAlertMsg(generalGetString(MR.strings.call_already_ended)) - } else { - chatModel.callManager.acceptIncomingCall(invitation = invitation) - } - } - }, - acceptFeature = { contact, feature, param -> - withBGApi { - chatModel.controller.allowFeatureToContact(chatRh, contact, feature, param) - } - }, - openDirectChat = { contactId -> - withBGApi { - openDirectChat(chatRh, contactId, chatModel) - } - }, - updateContactStats = { contact -> - withBGApi { - val r = chatModel.controller.apiContactInfo(chatRh, chat.chatInfo.apiId) - if (r != null) { - val contactStats = r.first - if (contactStats != null) - chatModel.updateContactConnectionStats(chatRh, contact, contactStats) - } - } - }, - updateMemberStats = { groupInfo, member -> - withBGApi { - val r = chatModel.controller.apiGroupMemberInfo(chatRh, groupInfo.groupId, member.groupMemberId) - if (r != null) { - val memStats = r.second - if (memStats != null) { - chatModel.updateGroupMemberConnectionStats(chatRh, groupInfo, r.first, memStats) - } - } - } - }, - syncContactConnection = { contact -> - withBGApi { - val cStats = chatModel.controller.apiSyncContactRatchet(chatRh, contact.contactId, force = false) - if (cStats != null) { - chatModel.updateContactConnectionStats(chatRh, contact, cStats) - } - } - }, - syncMemberConnection = { groupInfo, member -> - withBGApi { - val r = chatModel.controller.apiSyncGroupMemberRatchet(chatRh, groupInfo.apiId, member.groupMemberId, force = false) - if (r != null) { - chatModel.updateGroupMemberConnectionStats(chatRh, groupInfo, r.first, r.second) - } - } - }, - findModelChat = { chatId -> - chatModel.getChat(chatId) - }, - findModelMember = { memberId -> - chatModel.groupMembers.find { it.id == memberId } - }, - setReaction = { cInfo, cItem, add, reaction -> - withBGApi { - val updatedCI = chatModel.controller.apiChatItemReaction( - rh = chatRh, - type = cInfo.chatType, - id = cInfo.apiId, - itemId = cItem.id, - add = add, - reaction = reaction - ) - if (updatedCI != null) { - chatModel.updateChatItem(cInfo, updatedCI) - } - } - }, - showItemDetails = { cInfo, cItem -> - suspend fun loadChatItemInfo(): ChatItemInfo? { - val ciInfo = chatModel.controller.apiGetChatItemInfo(chatRh, cInfo.chatType, cInfo.apiId, cItem.id) - if (ciInfo != null) { - if (chat.chatInfo is ChatInfo.Group) { - setGroupMembers(chatRh, chat.chatInfo.groupInfo, chatModel) - } - } - return ciInfo - } - withBGApi { - var initialCiInfo = loadChatItemInfo() ?: return@withBGApi - ModalManager.end.closeModals() - ModalManager.end.showModalCloseable(endButtons = { - ShareButton { - clipboard.shareText(itemInfoShareText(chatModel, cItem, initialCiInfo, chatModel.controller.appPrefs.developerTools.get())) - } - }) { close -> - var ciInfo by remember(cItem.id) { mutableStateOf(initialCiInfo) } - ChatItemInfoView(chatRh, cItem, ciInfo, devTools = chatModel.controller.appPrefs.developerTools.get()) - LaunchedEffect(cItem.id) { - withContext(Dispatchers.Default) { - for (apiResp in controller.messagesChannel) { - val msg = apiResp.resp - if (apiResp.remoteHostId == chatRh && - msg is CR.ChatItemStatusUpdated && - msg.chatItem.chatItem.id == cItem.id - ) { - ciInfo = loadChatItemInfo() ?: return@withContext - initialCiInfo = ciInfo + withBGApi { + var initialCiInfo = loadChatItemInfo() ?: return@withBGApi + ModalManager.end.closeModals() + ModalManager.end.showModalCloseable(endButtons = { + ShareButton { + clipboard.shareText(itemInfoShareText(chatModel, cItem, initialCiInfo, chatModel.controller.appPrefs.developerTools.get())) + } + }) { close -> + var ciInfo by remember(cItem.id) { mutableStateOf(initialCiInfo) } + ChatItemInfoView(chatRh, cItem, ciInfo, devTools = chatModel.controller.appPrefs.developerTools.get()) + LaunchedEffect(cItem.id) { + withContext(Dispatchers.Default) { + for (apiResp in controller.messagesChannel) { + val msg = apiResp.resp + if (apiResp.remoteHostId == chatRh && + msg is CR.ChatItemStatusUpdated && + msg.chatItem.chatItem.id == cItem.id + ) { + ciInfo = loadChatItemInfo() ?: return@withContext + initialCiInfo = ciInfo + } } } } - } - KeyChangeEffect(chatModel.chatId.value) { - close() + KeyChangeEffect(chatModel.chatId.value) { + close() + } } } - } - }, - addMembers = { groupInfo -> - hideKeyboard(view) - withBGApi { - setGroupMembers(chatRh, groupInfo, chatModel) - ModalManager.end.closeModals() - ModalManager.end.showModalCloseable(true) { close -> - AddGroupMembersView(chatRh, groupInfo, false, chatModel, close) + }, + addMembers = { groupInfo -> + hideKeyboard(view) + withBGApi { + setGroupMembers(chatRh, groupInfo, chatModel) + ModalManager.end.closeModals() + ModalManager.end.showModalCloseable(true) { close -> + AddGroupMembersView(chatRh, groupInfo, false, chatModel, close) + } } - } - }, - openGroupLink = { groupInfo -> - hideKeyboard(view) - withBGApi { - val link = chatModel.controller.apiGetGroupLink(chatRh, groupInfo.groupId) - ModalManager.end.closeModals() - ModalManager.end.showModalCloseable(true) { - GroupLinkView(chatModel, chatRh, groupInfo, link?.first, link?.second, onGroupLinkUpdated = null) + }, + openGroupLink = { groupInfo -> + hideKeyboard(view) + withBGApi { + val link = chatModel.controller.apiGetGroupLink(chatRh, groupInfo.groupId) + ModalManager.end.closeModals() + ModalManager.end.showModalCloseable(true) { + GroupLinkView(chatModel, chatRh, groupInfo, link?.first, link?.second, onGroupLinkUpdated = null) + } } - } - }, - markRead = { range, unreadCountAfter -> - chatModel.markChatItemsRead(chat, range, unreadCountAfter) - ntfManager.cancelNotificationsForChat(chat.id) - withBGApi { - chatModel.controller.apiChatRead( - chatRh, - chat.chatInfo.chatType, - chat.chatInfo.apiId, - range - ) - } - }, - changeNtfsState = { enabled, currentValue -> toggleNotifications(chat, enabled, chatModel, currentValue) }, - onSearchValueChanged = { value -> - if (searchText.value == value) return@ChatLayout - if (chatModel.chatId.value != activeChat.value?.id) return@ChatLayout - val c = chatModel.getChat(chatModel.chatId.value ?: return@ChatLayout) ?: return@ChatLayout - withBGApi { - apiFindMessages(c, chatModel, value) - searchText.value = value - } - }, - onComposed, - developerTools = chatModel.controller.appPrefs.developerTools.get(), - showViaProxy = chatModel.controller.appPrefs.showSentViaProxy.get(), - ) + }, + markRead = { range, unreadCountAfter -> + chatModel.markChatItemsRead(chat, range, unreadCountAfter) + ntfManager.cancelNotificationsForChat(chat.id) + withBGApi { + chatModel.controller.apiChatRead( + chatRh, + chat.chatInfo.chatType, + chat.chatInfo.apiId, + range + ) + } + }, + changeNtfsState = { enabled, currentValue -> toggleNotifications(chat, enabled, chatModel, currentValue) }, + onSearchValueChanged = { value -> + if (searchText.value == value) return@ChatLayout + if (chatModel.chatId.value != activeChat.value?.id) return@ChatLayout + val c = chatModel.getChat(chatModel.chatId.value ?: return@ChatLayout) ?: return@ChatLayout + withBGApi { + apiFindMessages(c, chatModel, value) + searchText.value = value + } + }, + onComposed, + developerTools = chatModel.controller.appPrefs.developerTools.get(), + showViaProxy = chatModel.controller.appPrefs.showSentViaProxy.get(), + ) + } } is ChatInfo.ContactConnection -> { val close = { chatModel.chatId.value = null } @@ -598,9 +601,19 @@ fun ChatLayout( floatingActionButton = { floatingButton.value() }, contentColor = LocalContentColor.current, drawerContentColor = LocalContentColor.current, + backgroundColor = Color.Unspecified ) { contentPadding -> + val wallpaperImage = MaterialTheme.wallpaper.type.image + val wallpaperType = MaterialTheme.wallpaper.type + val backgroundColor = MaterialTheme.wallpaper.background ?: wallpaperType.defaultBackgroundColor(CurrentColors.value.base, MaterialTheme.colors.background) + val tintColor = MaterialTheme.wallpaper.tint ?: wallpaperType.defaultTintColor(CurrentColors.value.base) BoxWithConstraints(Modifier - .fillMaxHeight() + .fillMaxSize() + .background(MaterialTheme.colors.background) + .then(if (wallpaperImage != null) + Modifier.drawBehind { chatViewBackground(wallpaperImage, wallpaperType, backgroundColor, tintColor) } + else + Modifier) .padding(contentPadding) ) { ChatItemsList( @@ -1262,7 +1275,7 @@ val MEMBER_IMAGE_SIZE: Dp = 38.dp @Composable fun MemberImage(member: GroupMember) { - ProfileImage(MEMBER_IMAGE_SIZE, member.memberProfile.image) + ProfileImage(MEMBER_IMAGE_SIZE, member.memberProfile.image, backgroundColor = MaterialTheme.colors.background) } @Composable diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeContextInvitingContactMemberView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeContextInvitingContactMemberView.kt index 20316dd524..bc82bc593f 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeContextInvitingContactMemberView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeContextInvitingContactMemberView.kt @@ -16,7 +16,7 @@ import dev.icerock.moko.resources.compose.stringResource @Composable fun ComposeContextInvitingContactMemberView() { - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage + val sentColor = MaterialTheme.appColors.sentMessage Row( Modifier .height(60.dp) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeFileView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeFileView.kt index 83076f885b..7ab7963547 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeFileView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeFileView.kt @@ -16,7 +16,7 @@ import chat.simplex.res.MR @Composable fun ComposeFileView(fileName: String, cancelFile: () -> Unit, cancelEnabled: Boolean) { - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage + val sentColor = MaterialTheme.appColors.sentMessage Row( Modifier .height(60.dp) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeImageView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeImageView.kt index 906065f741..97b6f9afda 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeImageView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeImageView.kt @@ -20,7 +20,7 @@ import chat.simplex.common.views.helpers.UploadContent @Composable fun ComposeImageView(media: ComposePreview.MediaPreview, cancelImages: () -> Unit, cancelEnabled: Boolean) { - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage + val sentColor = MaterialTheme.appColors.sentMessage Row( Modifier .padding(top = 8.dp) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeView.kt index d9ea35096b..24533247ba 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeView.kt @@ -776,7 +776,7 @@ fun ComposeView( @Composable fun MsgNotAllowedView(reason: String, icon: Painter) { - val color = CurrentColors.collectAsState().value.appColors.receivedMessage + val color = MaterialTheme.appColors.receivedMessage Row(Modifier.padding(top = 5.dp).fillMaxWidth().background(color).padding(horizontal = DEFAULT_PADDING_HALF, vertical = DEFAULT_PADDING_HALF * 1.5f), verticalAlignment = Alignment.CenterVertically) { Icon(icon, null, tint = MaterialTheme.colors.secondary) Spacer(Modifier.width(DEFAULT_PADDING_HALF)) @@ -862,7 +862,7 @@ fun ComposeView( } } Row( - modifier = Modifier.padding(end = 8.dp), + modifier = Modifier.background(MaterialTheme.colors.background).padding(end = 8.dp), verticalAlignment = Alignment.Bottom, ) { val isGroupAndProhibitedFiles = chat.chatInfo is ChatInfo.Group && !chat.chatInfo.groupInfo.fullGroupPreferences.files.on(chat.chatInfo.groupInfo.membership) @@ -974,7 +974,7 @@ fun ComposeView( val timedMessageAllowed = remember(chat.chatInfo) { chat.chatInfo.featureEnabled(ChatFeature.TimedMessages) } val sendButtonColor = if (chat.chatInfo.incognito) - if (isSystemInDarkTheme()) Indigo else Indigo.copy(alpha = 0.7F) + if (isInDarkTheme()) Indigo else Indigo.copy(alpha = 0.7F) else MaterialTheme.colors.primary SendMsgView( composeState, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeVoiceView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeVoiceView.kt index a4c90d30dd..b71d090a4e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeVoiceView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeVoiceView.kt @@ -35,7 +35,7 @@ fun ComposeVoiceView( ) { val progress = rememberSaveable { mutableStateOf(0) } val duration = rememberSaveable(recordedDurationMs) { mutableStateOf(recordedDurationMs) } - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage + val sentColor = MaterialTheme.appColors.sentMessage Box { Box( Modifier diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContextItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContextItemView.kt index ce34ecf0c3..0c4efa7d0d 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContextItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContextItemView.kt @@ -30,8 +30,8 @@ fun ContextItemView( cancelContextItem: () -> Unit ) { val sent = contextItem.chatDir.sent - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage - val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage + val sentColor = MaterialTheme.appColors.sentMessage + val receivedColor = MaterialTheme.appColors.receivedMessage @Composable fun MessageText(attachment: ImageResource?, lines: Int) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt index c52dd941fd..69b4de6803 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt @@ -9,7 +9,6 @@ import SectionSpacer import SectionTextFooter import SectionView import androidx.compose.desktop.ui.tooling.preview.Preview -import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.* import androidx.compose.material.* @@ -233,6 +232,16 @@ fun GroupChatInfoLayout( } else { SendReceiptsOptionDisabled() } + + WallpaperButton { + ModalManager.end.showModal { + val chat = remember { derivedStateOf { chatModel.chats.firstOrNull { it.id == chat.id } } } + val c = chat.value + if (c != null) { + ChatWallpaperEditorModal(c) + } + } + } } SectionTextFooter(stringResource(MR.strings.only_group_owners_can_change_prefs)) SectionDividerSpaced(maxTopPadding = true) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIGroupInvitationView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIGroupInvitationView.kt index a2338bb895..577327c159 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIGroupInvitationView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIGroupInvitationView.kt @@ -83,8 +83,8 @@ fun CIGroupInvitationView( } } - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage - val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage + val sentColor = MaterialTheme.appColors.sentMessage + val receivedColor = MaterialTheme.appColors.receivedMessage Surface( modifier = if (action && !inProgress.value) Modifier.clickable(onClick = { inProgress.value = true @@ -110,6 +110,7 @@ fun CIGroupInvitationView( .padding(bottom = 4.dp), ) { groupInfoView() + val secondaryColor = MaterialTheme.colors.secondary Column(Modifier.padding(top = 2.dp, start = 5.dp)) { Divider(Modifier.fillMaxWidth().padding(bottom = 4.dp)) if (action) { @@ -117,7 +118,7 @@ fun CIGroupInvitationView( Text( buildAnnotatedString { append(generalGetString(if (chatIncognito) MR.strings.group_invitation_tap_to_join_incognito else MR.strings.group_invitation_tap_to_join)) - withStyle(reserveTimestampStyle) { append(reserveSpaceForMeta(ci.meta, timedMessagesTTL, encrypted = null, showStatus = false, showEdited = false)) } + withStyle(reserveTimestampStyle) { append(reserveSpaceForMeta(ci.meta, timedMessagesTTL, encrypted = null, showStatus = false, showEdited = false, secondaryColor = secondaryColor)) } }, color = if (inProgress.value) MaterialTheme.colors.secondary @@ -128,7 +129,7 @@ fun CIGroupInvitationView( Text( buildAnnotatedString { append(groupInvitationStr()) - withStyle(reserveTimestampStyle) { append(reserveSpaceForMeta(ci.meta, timedMessagesTTL, encrypted = null, showStatus = false, showEdited = false)) } + withStyle(reserveTimestampStyle) { append(reserveSpaceForMeta(ci.meta, timedMessagesTTL, encrypted = null, showStatus = false, showEdited = false, secondaryColor = secondaryColor)) } } ) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIMetaView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIMetaView.kt index 14fa6910da..def3b14ebc 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIMetaView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIMetaView.kt @@ -12,7 +12,6 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.desktop.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import chat.simplex.common.ui.theme.CurrentColors import chat.simplex.common.model.* import chat.simplex.common.ui.theme.isInDarkTheme import chat.simplex.res.MR @@ -86,7 +85,7 @@ private fun CIMetaText( Spacer(Modifier.width(4.dp)) } if (showViaProxy && meta.sentViaProxy == true) { - Icon(painterResource(MR.images.ic_arrow_forward), null, Modifier.height(17.dp), tint = CurrentColors.value.colors.secondary) + Icon(painterResource(MR.images.ic_arrow_forward), null, Modifier.height(17.dp), tint = MaterialTheme.colors.secondary) } if (showStatus) { val statusIcon = meta.statusIcon(MaterialTheme.colors.primary, color, paleColor) @@ -115,6 +114,7 @@ fun reserveSpaceForMeta( meta: CIMeta, chatTTL: Int?, encrypted: Boolean?, + secondaryColor: Color, showStatus: Boolean = true, showEdited: Boolean = true, showViaProxy: Boolean = false @@ -132,7 +132,7 @@ fun reserveSpaceForMeta( if (showViaProxy && meta.sentViaProxy == true) { res += iconSpace } - if (showStatus && (meta.statusIcon(CurrentColors.value.colors.secondary) != null || !meta.disappearing)) { + if (showStatus && (meta.statusIcon(secondaryColor) != null || !meta.disappearing)) { res += iconSpace } if (encrypted != null) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIRcvDecryptionError.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIRcvDecryptionError.kt index eb5d1e731a..dd0e9cf1a2 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIRcvDecryptionError.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIRcvDecryptionError.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.common.model.* import chat.simplex.common.ui.theme.CurrentColors +import chat.simplex.common.ui.theme.appColors import chat.simplex.common.views.helpers.AlertManager import chat.simplex.common.views.helpers.generalGetString import chat.simplex.res.MR @@ -137,7 +138,7 @@ fun DecryptionErrorItemFixButton( onClick: () -> Unit, syncSupported: Boolean ) { - val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage + val receivedColor = MaterialTheme.appColors.receivedMessage Surface( Modifier.clickable(onClick = onClick), shape = RoundedCornerShape(18.dp), @@ -164,10 +165,11 @@ fun DecryptionErrorItemFixButton( tint = if (syncSupported) MaterialTheme.colors.primary else MaterialTheme.colors.secondary ) Spacer(Modifier.padding(2.dp)) + val secondaryColor = MaterialTheme.colors.secondary Text( buildAnnotatedString { append(generalGetString(MR.strings.fix_connection)) - withStyle(reserveTimestampStyle) { append(reserveSpaceForMeta(ci.meta, null, encrypted = null)) } + withStyle(reserveTimestampStyle) { append(reserveSpaceForMeta(ci.meta, null, encrypted = null, secondaryColor = secondaryColor)) } withStyle(reserveTimestampStyle) { append(" ") } // for icon }, color = if (syncSupported) MaterialTheme.colors.primary else MaterialTheme.colors.secondary @@ -184,7 +186,7 @@ fun DecryptionErrorItem( ci: ChatItem, onClick: () -> Unit ) { - val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage + val receivedColor = MaterialTheme.appColors.receivedMessage Surface( Modifier.clickable(onClick = onClick), shape = RoundedCornerShape(18.dp), @@ -195,10 +197,11 @@ fun DecryptionErrorItem( Modifier.padding(vertical = 6.dp, horizontal = 12.dp), contentAlignment = Alignment.BottomEnd, ) { + val secondaryColor = MaterialTheme.colors.secondary Text( buildAnnotatedString { withStyle(SpanStyle(fontStyle = FontStyle.Italic, color = Color.Red)) { append(ci.content.text) } - withStyle(reserveTimestampStyle) { append(reserveSpaceForMeta(ci.meta, null, encrypted = null)) } + withStyle(reserveTimestampStyle) { append(reserveSpaceForMeta(ci.meta, null, encrypted = null, secondaryColor = secondaryColor)) } }, style = MaterialTheme.typography.body1.copy(lineHeight = 22.sp) ) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVoiceView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVoiceView.kt index f973a6ea66..96aaf586e9 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVoiceView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVoiceView.kt @@ -154,8 +154,8 @@ private fun VoiceLayout( } when { hasText -> { - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage - val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage + val sentColor = MaterialTheme.appColors.sentMessage + val receivedColor = MaterialTheme.appColors.receivedMessage Spacer(Modifier.width(6.dp)) VoiceMsgIndicator(file, audioPlaying.value, sent, hasText, progress, duration, brokenAudio, play, pause, longClick, receiveFile) Row(verticalAlignment = Alignment.CenterVertically) { @@ -224,8 +224,8 @@ private fun PlayPauseButton( longClick: () -> Unit, icon: ImageResource = MR.images.ic_play_arrow_filled, ) { - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage - val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage + val sentColor = MaterialTheme.appColors.sentMessage + val receivedColor = MaterialTheme.appColors.receivedMessage Surface( Modifier.drawRingModifier(angle, strokeColor, strokeWidth), color = if (sent) sentColor else receivedColor, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt index 0bc0415590..7fbec84c4d 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt @@ -819,40 +819,38 @@ expect fun copyItemToClipboard(cItem: ChatItem, clipboard: ClipboardManager) @Preview @Composable -fun PreviewChatItemView() { - SimpleXTheme { - ChatItemView( - rhId = null, - ChatInfo.Direct.sampleData, - ChatItem.getSampleData( - 1, CIDirection.DirectSnd(), Clock.System.now(), "hello" - ), - useLinkPreviews = true, - linkMode = SimplexLinkMode.DESCRIPTION, - composeState = remember { mutableStateOf(ComposeState(useLinkPreviews = true)) }, - revealed = remember { mutableStateOf(false) }, - range = 0..1, - deleteMessage = { _, _ -> }, - deleteMessages = { _ -> }, - receiveFile = { _ -> }, - cancelFile = {}, - joinGroup = { _, _ -> }, - acceptCall = { _ -> }, - scrollToItem = {}, - acceptFeature = { _, _, _ -> }, - openDirectChat = { _ -> }, - updateContactStats = { }, - updateMemberStats = { _, _ -> }, - syncContactConnection = { }, - syncMemberConnection = { _, _ -> }, - findModelChat = { null }, - findModelMember = { null }, - setReaction = { _, _, _, _ -> }, - showItemDetails = { _, _ -> }, - developerTools = false, - showViaProxy = false - ) - } +fun PreviewChatItemView( + chatItem: ChatItem = ChatItem.getSampleData(1, CIDirection.DirectSnd(), Clock.System.now(), "hello") +) { + ChatItemView( + rhId = null, + ChatInfo.Direct.sampleData, + chatItem, + useLinkPreviews = true, + linkMode = SimplexLinkMode.DESCRIPTION, + composeState = remember { mutableStateOf(ComposeState(useLinkPreviews = true)) }, + revealed = remember { mutableStateOf(false) }, + range = 0..1, + deleteMessage = { _, _ -> }, + deleteMessages = { _ -> }, + receiveFile = { _ -> }, + cancelFile = {}, + joinGroup = { _, _ -> }, + acceptCall = { _ -> }, + scrollToItem = {}, + acceptFeature = { _, _, _ -> }, + openDirectChat = { _ -> }, + updateContactStats = { }, + updateMemberStats = { _, _ -> }, + syncContactConnection = { }, + syncMemberConnection = { _, _ -> }, + findModelChat = { null }, + findModelMember = { null }, + setReaction = { _, _, _, _ -> }, + showItemDetails = { _, _ -> }, + developerTools = false, + showViaProxy = false, + ) } @Preview diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/DeletedItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/DeletedItemView.kt index 644c1997c4..9b7db099b6 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/DeletedItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/DeletedItemView.kt @@ -18,8 +18,8 @@ import chat.simplex.common.ui.theme.* @Composable fun DeletedItemView(ci: ChatItem, timedMessagesTTL: Int?, showViaProxy: Boolean) { val sent = ci.chatDir.sent - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage - val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage + val sentColor = MaterialTheme.appColors.sentMessage + val receivedColor = MaterialTheme.appColors.receivedMessage Surface( shape = RoundedCornerShape(18.dp), color = if (sent) sentColor else receivedColor, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/FramedItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/FramedItemView.kt index 4dc0fd9cf5..8969ca9b21 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/FramedItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/FramedItemView.kt @@ -46,9 +46,6 @@ fun FramedItemView( return if (chatInfo is ChatInfo.Group) chatInfo.groupInfo.membership else null } - @Composable - fun Color.toQuote(): Color = if (isInDarkTheme()) lighter(0.12f) else darker(0.12f) - @Composable fun ciQuotedMsgTextView(qi: CIQuote, lines: Int) { MarkdownText( @@ -89,11 +86,11 @@ fun FramedItemView( @Composable fun FramedItemHeader(caption: String, italic: Boolean, icon: Painter? = null, pad: Boolean = false) { - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage - val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage + val sentColor = MaterialTheme.appColors.sentQuote + val receivedColor = MaterialTheme.appColors.receivedQuote Row( Modifier - .background(if (sent) sentColor.toQuote() else receivedColor.toQuote()) + .background(if (sent) sentColor else receivedColor) .fillMaxWidth() .padding(start = 8.dp, top = 6.dp, end = 12.dp, bottom = if (pad || (ci.quotedItem == null && ci.meta.itemForwarded == null)) 6.dp else 0.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), @@ -122,11 +119,11 @@ fun FramedItemView( @Composable fun ciQuoteView(qi: CIQuote) { - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage - val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage + val sentColor = MaterialTheme.appColors.sentQuote + val receivedColor = MaterialTheme.appColors.receivedQuote Row( Modifier - .background(if (sent) sentColor.toQuote() else receivedColor.toQuote()) + .background(if (sent) sentColor else receivedColor) .fillMaxWidth() .combinedClickable( onLongClick = { showMenu.value = true }, @@ -188,10 +185,17 @@ fun FramedItemView( val transparentBackground = (ci.content.msgContent is MsgContent.MCImage || ci.content.msgContent is MsgContent.MCVideo) && !ci.meta.isLive && ci.content.text.isEmpty() && ci.quotedItem == null && ci.meta.itemForwarded == null - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage - val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage + val sentColor = MaterialTheme.appColors.sentMessage + val receivedColor = MaterialTheme.appColors.receivedMessage Box(Modifier .clip(RoundedCornerShape(18.dp)) + .background( + when { + transparentBackground -> Color.Transparent + sent -> MaterialTheme.colors.background + else -> MaterialTheme.colors.background + } + ) .background( when { transparentBackground -> Color.Transparent diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/IntegrityErrorItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/IntegrityErrorItemView.kt index bd2aaf140c..dc585358c4 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/IntegrityErrorItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/IntegrityErrorItemView.kt @@ -17,8 +17,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.common.model.ChatItem import chat.simplex.common.model.MsgErrorType -import chat.simplex.common.ui.theme.CurrentColors -import chat.simplex.common.ui.theme.SimpleXTheme +import chat.simplex.common.ui.theme.* import chat.simplex.common.views.helpers.AlertManager import chat.simplex.common.views.helpers.generalGetString import chat.simplex.res.MR @@ -51,7 +50,7 @@ fun IntegrityErrorItemView(msgError: MsgErrorType, ci: ChatItem, timedMessagesTT @Composable fun CIMsgError(ci: ChatItem, timedMessagesTTL: Int?, onClick: () -> Unit) { - val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage + val receivedColor = MaterialTheme.appColors.receivedMessage Surface( Modifier.clickable(onClick = onClick), shape = RoundedCornerShape(18.dp), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/MarkedDeletedItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/MarkedDeletedItemView.kt index 6ecec47b6f..5b5438d76f 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/MarkedDeletedItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/MarkedDeletedItemView.kt @@ -21,8 +21,8 @@ import kotlinx.datetime.Clock @Composable fun MarkedDeletedItemView(ci: ChatItem, timedMessagesTTL: Int?, revealed: MutableState, showViaProxy: Boolean) { - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage - val receivedColor = CurrentColors.collectAsState().value.appColors.receivedMessage + val sentColor = MaterialTheme.appColors.sentMessage + val receivedColor = MaterialTheme.appColors.receivedMessage Surface( shape = RoundedCornerShape(18.dp), color = if (ci.chatDir.sent) sentColor else receivedColor, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/TextItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/TextItemView.kt index 343fc47f76..c0e222d7d1 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/TextItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/TextItemView.kt @@ -78,7 +78,7 @@ fun MarkdownText ( val reserve = if (textLayoutDirection != LocalLayoutDirection.current && meta != null) { "\n" } else if (meta != null) { - reserveSpaceForMeta(meta, chatTTL, null, showViaProxy = showViaProxy) + reserveSpaceForMeta(meta, chatTTL, null, secondaryColor = MaterialTheme.colors.secondary, showViaProxy = showViaProxy) } else { " " } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt index 40dfbeac73..330003b743 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt @@ -486,6 +486,8 @@ fun deleteChatDatabaseFilesAndState() { tmpDir.deleteRecursively() getMigrationTempFilesDirectory().deleteRecursively() tmpDir.mkdir() + wallpapersDir.deleteRecursively() + wallpapersDir.mkdirs() DatabaseUtils.ksDatabasePassword.remove() controller.appPrefs.storeDBPassphrase.set(true) controller.ctrl = null diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatInfoImage.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatInfoImage.kt index 34d916781b..3d57f0f8b7 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatInfoImage.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatInfoImage.kt @@ -2,12 +2,14 @@ package chat.simplex.common.views.helpers import androidx.compose.desktop.ui.tooling.preview.Preview import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.* import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Size @@ -51,7 +53,8 @@ fun ProfileImage( size: Dp, image: String? = null, icon: ImageResource = MR.images.ic_account_circle_filled, - color: Color = MaterialTheme.colors.secondaryVariant + color: Color = MaterialTheme.colors.secondaryVariant, + backgroundColor: Color? = null ) { Box(Modifier.size(size)) { if (image == null) { @@ -61,6 +64,9 @@ fun ProfileImage( else -> null } if (iconToReplace != null) { + if (backgroundColor != null) { + Box(Modifier.size(size * 0.7f).align(Alignment.Center).background(backgroundColor, CircleShape)) + } Icon( iconToReplace, contentDescription = stringResource(MR.strings.icon_descr_profile_image_placeholder), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatWallpaper.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatWallpaper.kt new file mode 100644 index 0000000000..cd18ad1dab --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatWallpaper.kt @@ -0,0 +1,415 @@ +package chat.simplex.common.views.helpers + +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.* +import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.graphics.drawscope.clipRect +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.IntSize +import chat.simplex.common.model.ChatController.appPrefs +import chat.simplex.common.platform.* +import chat.simplex.common.ui.theme.* +import chat.simplex.common.ui.theme.ThemeManager.colorFromReadableHex +import chat.simplex.res.MR +import dev.icerock.moko.resources.ImageResource +import dev.icerock.moko.resources.StringResource +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import java.io.File +import kotlin.math.* + +enum class PresetWallpaper( + val res: ImageResource, + val filename: String, + val text: StringResource, + val scale: Float, + val background: Map, + val tint: Map, + val colors: Map, +) { + CATS(MR.images.wallpaper_cats, "cats", MR.strings.wallpaper_cats, 0.63f, + wallpaperBackgrounds(light = "#ffF8F6EA"), + tint = mapOf( + DefaultTheme.LIGHT to "#ffefdca6".colorFromReadableHex(), + DefaultTheme.DARK to "#ff4b3b0e".colorFromReadableHex(), + DefaultTheme.SIMPLEX to "#ff51400f".colorFromReadableHex(), + DefaultTheme.BLACK to "#ff4b3b0e".colorFromReadableHex() + ), + mapOf( + DefaultTheme.LIGHT to ThemeColors( + sentMessage = "#fffffaed", + sentQuote = "#fffaf0d6", + receivedMessage = "#ffF8F7F4", + receivedQuote = "#ffefede9", + ), + DefaultTheme.DARK to ThemeColors( + sentMessage = "#ff2f2919", + sentQuote = "#ff473a1d", + receivedMessage = "#ff272624", + receivedQuote = "#ff373633", + ), + DefaultTheme.SIMPLEX to ThemeColors( + sentMessage = "#ff41371b", + sentQuote = "#ff654f1c", + receivedMessage = "#ff272624", + receivedQuote = "#ff373633", + ), + DefaultTheme.BLACK to ThemeColors( + sentMessage = "#ff41371b", + sentQuote = "#ff654f1c", + receivedMessage = "#ff1f1e1b", + receivedQuote = "#ff2f2d27", + ), + ) + ), + FLOWERS(MR.images.wallpaper_flowers, "flowers", MR.strings.wallpaper_flowers, 0.53f, + wallpaperBackgrounds(light = "#ffE2FFE4"), + tint = mapOf( + DefaultTheme.LIGHT to "#ff9CEA59".colorFromReadableHex(), + DefaultTheme.DARK to "#ff31560D".colorFromReadableHex(), + DefaultTheme.SIMPLEX to "#ff36600f".colorFromReadableHex(), + DefaultTheme.BLACK to "#ff31560D".colorFromReadableHex() + ), + mapOf( + DefaultTheme.LIGHT to ThemeColors( + sentMessage = "#fff1ffe5", + sentQuote = "#ffdcf9c4", + receivedMessage = "#ffF4F8F2", + receivedQuote = "#ffe7ece7", + ), + DefaultTheme.DARK to ThemeColors( + sentMessage = "#ff163521", + sentQuote = "#ff1B5330", + receivedMessage = "#ff242523", + receivedQuote = "#ff353733", + ), + DefaultTheme.SIMPLEX to ThemeColors( + sentMessage = "#ff184739", + sentQuote = "#ff1F6F4B", + receivedMessage = "#ff242523", + receivedQuote = "#ff353733", + ), + DefaultTheme.BLACK to ThemeColors( + sentMessage = "#ff184739", + sentQuote = "#ff1F6F4B", + receivedMessage = "#ff1c1f1a", + receivedQuote = "#ff282b25", + ), + ) + ), + HEARTS(MR.images.wallpaper_hearts, "hearts", MR.strings.wallpaper_hearts, 0.59f, + wallpaperBackgrounds(light = "#ffFDECEC"), + tint = mapOf( + DefaultTheme.LIGHT to "#fffde0e0".colorFromReadableHex(), + DefaultTheme.DARK to "#ff3c0f0f".colorFromReadableHex(), + DefaultTheme.SIMPLEX to "#ff411010".colorFromReadableHex(), + DefaultTheme.BLACK to "#ff3C0F0F".colorFromReadableHex() + ), + mapOf( + DefaultTheme.LIGHT to ThemeColors( + sentMessage = "#fffff4f4", + sentQuote = "#ffffdfdf", + receivedMessage = "#fff8f6f6", + receivedQuote = "#ffefebeb", + ), + DefaultTheme.DARK to ThemeColors( + sentMessage = "#ff301515", + sentQuote = "#ff4C1818", + receivedMessage = "#ff242121", + receivedQuote = "#ff3b3535", + ), + DefaultTheme.SIMPLEX to ThemeColors( + sentMessage = "#ff491A28", + sentQuote = "#ff761F29", + receivedMessage = "#ff242121", + receivedQuote = "#ff3b3535", + ), + DefaultTheme.BLACK to ThemeColors( + sentMessage = "#ff491A28", + sentQuote = "#ff761F29", + receivedMessage = "#ff1f1b1b", + receivedQuote = "#ff2e2626", + ), + ) + ), + KIDS(MR.images.wallpaper_kids, "kids", MR.strings.wallpaper_kids, 0.53f, + wallpaperBackgrounds(light = "#ffdbfdfb"), + tint = mapOf( + DefaultTheme.LIGHT to "#ffadeffc".colorFromReadableHex(), + DefaultTheme.DARK to "#ff16404B".colorFromReadableHex(), + DefaultTheme.SIMPLEX to "#ff184753".colorFromReadableHex(), + DefaultTheme.BLACK to "#ff16404B".colorFromReadableHex() + ), + mapOf( + DefaultTheme.LIGHT to ThemeColors( + sentMessage = "#ffeafeff", + sentQuote = "#ffcbf4f7", + receivedMessage = "#fff3fafa", + receivedQuote = "#ffe4efef", + ), + DefaultTheme.DARK to ThemeColors( + sentMessage = "#ff16302F", + sentQuote = "#ff1a4a49", + receivedMessage = "#ff252626", + receivedQuote = "#ff373A39", + ), + DefaultTheme.SIMPLEX to ThemeColors( + sentMessage = "#ff1a4745", + sentQuote = "#ff1d6b69", + receivedMessage = "#ff252626", + receivedQuote = "#ff373a39", + ), + DefaultTheme.BLACK to ThemeColors( + sentMessage = "#ff1a4745", + sentQuote = "#ff1d6b69", + receivedMessage = "#ff1e1f1f", + receivedQuote = "#ff262b29", + ), + ) + ), + SCHOOL(MR.images.wallpaper_school, "school", MR.strings.wallpaper_school, 0.53f, + wallpaperBackgrounds(light = "#ffE7F5FF"), + tint = mapOf( + DefaultTheme.LIGHT to "#ffCEEBFF".colorFromReadableHex(), + DefaultTheme.DARK to "#ff0F293B".colorFromReadableHex(), + DefaultTheme.SIMPLEX to "#ff112f43".colorFromReadableHex(), + DefaultTheme.BLACK to "#ff0F293B".colorFromReadableHex() + ), + mapOf( + DefaultTheme.LIGHT to ThemeColors( + sentMessage = "#ffeef9ff", + sentQuote = "#ffD6EDFA", + receivedMessage = "#ffF3F5F9", + receivedQuote = "#ffe4e8ee", + ), + DefaultTheme.DARK to ThemeColors( + sentMessage = "#ff172833", + sentQuote = "#ff1C3E4F", + receivedMessage = "#ff26282c", + receivedQuote = "#ff393c40", + ), + DefaultTheme.SIMPLEX to ThemeColors( + sentMessage = "#ff1A3C5D", + sentQuote = "#ff235b80", + receivedMessage = "#ff26282c", + receivedQuote = "#ff393c40", + ), + DefaultTheme.BLACK to ThemeColors( + sentMessage = "#ff1A3C5D", + sentQuote = "#ff235b80", + receivedMessage = "#ff1d1e22", + receivedQuote = "#ff292b2f", + ), + ) + ), + TRAVEL(MR.images.wallpaper_travel, "travel", MR.strings.wallpaper_travel, 0.68f, + wallpaperBackgrounds(light = "#fff9eeff"), + tint = mapOf( + DefaultTheme.LIGHT to "#ffeedbfe".colorFromReadableHex(), + DefaultTheme.DARK to "#ff311E48".colorFromReadableHex(), + DefaultTheme.SIMPLEX to "#ff35204e".colorFromReadableHex(), + DefaultTheme.BLACK to "#ff311E48".colorFromReadableHex() + ), + mapOf( + DefaultTheme.LIGHT to ThemeColors( + sentMessage = "#fffcf6ff", + sentQuote = "#fff2e0fc", + receivedMessage = "#ffF6F4F7", + receivedQuote = "#ffede9ee", + ), + DefaultTheme.DARK to ThemeColors( + sentMessage = "#ff33263B", + sentQuote = "#ff53385E", + receivedMessage = "#ff272528", + receivedQuote = "#ff3B373E", + ), + DefaultTheme.SIMPLEX to ThemeColors( + sentMessage = "#ff3C255D", + sentQuote = "#ff623485", + receivedMessage = "#ff26273B", + receivedQuote = "#ff3A394F", + ), + DefaultTheme.BLACK to ThemeColors( + sentMessage = "#ff3C255D", + sentQuote = "#ff623485", + receivedMessage = "#ff231f23", + receivedQuote = "#ff2c2931", + ), + ) + ); + + fun toType(base: DefaultTheme, scale: Float? = null): WallpaperType = + WallpaperType.Preset( + filename, + scale ?: appPrefs.themeOverrides.get().firstOrNull { it.wallpaper != null && it.wallpaper.preset == filename && it.base == base }?.wallpaper?.scale ?: 1f + ) + + companion object { + fun from(filename: String): PresetWallpaper? = + entries.firstOrNull { it.filename == filename } + } +} + +fun wallpaperBackgrounds(light: String): Map = + mapOf( + DefaultTheme.LIGHT to light.colorFromReadableHex(), + DefaultTheme.DARK to "#ff121212".colorFromReadableHex(), + DefaultTheme.SIMPLEX to "#ff111528".colorFromReadableHex(), + DefaultTheme.BLACK to "#ff070707".colorFromReadableHex() + ) + +@Serializable +enum class WallpaperScaleType(val contentScale: ContentScale, val text: StringResource) { + @SerialName("fill") FILL(ContentScale.Crop, MR.strings.wallpaper_scale_fill), + @SerialName("fit") FIT(ContentScale.Fit, MR.strings.wallpaper_scale_fit), + @SerialName("repeat") REPEAT(ContentScale.Fit, MR.strings.wallpaper_scale_repeat), +} + +sealed class WallpaperType { + abstract val scale: Float? + + val image by lazy { + val filename = when (this) { + is Preset -> filename + is Image -> filename + else -> return@lazy null + } + if (filename == "") return@lazy null + if (cachedImages[filename] != null) { + cachedImages[filename] + } else { + val res = if (this is Preset) { + (PresetWallpaper.from(filename) ?: PresetWallpaper.CATS).res.toComposeImageBitmap()!! + } else { + try { + // In case of unintentional image deletion don't crash the app + File(getWallpaperFilePath(filename)).inputStream().use { loadImageBitmap(it) } + } catch (e: Exception) { + Log.e(TAG, "Error while loading wallpaper file: ${e.stackTraceToString()}") + null + } + } + res?.prepareToDraw() + cachedImages[filename] = res ?: return@lazy null + res + } + } + + fun sameType(other: WallpaperType?): Boolean = + if (this is Preset && other is Preset) this.filename == other.filename + else this.javaClass == other?.javaClass + + fun samePreset(other: PresetWallpaper?): Boolean = this is Preset && filename == other?.filename + + data class Preset( + val filename: String, + override val scale: Float?, + ): WallpaperType() { + val predefinedImageScale = PresetWallpaper.from(filename)?.scale ?: 1f + } + + data class Image( + val filename: String, + override val scale: Float?, + val scaleType: WallpaperScaleType?, + ): WallpaperType() + + object Empty: WallpaperType() { + override val scale: Float? + get() = null + } + + fun defaultBackgroundColor(theme: DefaultTheme, materialBackground: Color): Color = + if (this is Preset) { + (PresetWallpaper.from(filename) ?: PresetWallpaper.CATS).background[theme]!! + } else { + materialBackground + } + + fun defaultTintColor(theme: DefaultTheme): Color = + if (this is Preset) { + (PresetWallpaper.from(filename) ?: PresetWallpaper.CATS).tint[theme]!! + } else if (this is Image && scaleType == WallpaperScaleType.REPEAT) { + Color.Transparent + } else { + Color.Transparent + } + + companion object { + var cachedImages: MutableMap = mutableMapOf() + + fun from(wallpaper: ThemeWallpaper?): WallpaperType? { + return if (wallpaper == null) { + null + } else if (wallpaper.preset != null) { + Preset(wallpaper.preset, wallpaper.scale) + } else if (wallpaper.imageFile != null) { + Image(wallpaper.imageFile, wallpaper.scale, wallpaper.scaleType) + } else { + Empty + } + } + } +} + +fun DrawScope.chatViewBackground(image: ImageBitmap, imageType: WallpaperType, background: Color, tint: Color) = clipRect { + val quality = FilterQuality.High + fun repeat(imageScale: Float) { + val scale = imageScale * density + for (h in 0..(size.height / image.height / scale).roundToInt()) { + for (w in 0..(size.width / image.width / scale).roundToInt()) { + drawImage( + image, + dstOffset = IntOffset(x = (w * image.width * scale).roundToInt(), y = (h * image.height * scale).roundToInt()), + dstSize = IntSize((image.width * scale).roundToInt(), (image.height * scale).roundToInt()), + colorFilter = ColorFilter.tint(tint, BlendMode.SrcIn), + filterQuality = quality + ) + } + } + } + + drawRect(background) + when (imageType) { + is WallpaperType.Preset -> repeat((imageType.scale ?: 1f) * imageType.predefinedImageScale) + is WallpaperType.Image -> when (val scaleType = imageType.scaleType ?: WallpaperScaleType.FILL) { + WallpaperScaleType.REPEAT -> repeat(imageType.scale ?: 1f) + WallpaperScaleType.FILL, WallpaperScaleType.FIT -> { + val scale = scaleType.contentScale.computeScaleFactor(Size(image.width.toFloat(), image.height.toFloat()), Size(size.width, size.height)) + val scaledWidth = (image.width * scale.scaleX).roundToInt() + val scaledHeight = (image.height * scale.scaleY).roundToInt() + drawImage(image, dstOffset = IntOffset(x = ((size.width - scaledWidth) / 2).roundToInt(), y = ((size.height - scaledHeight) / 2).roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality) + if (scaleType == WallpaperScaleType.FIT) { + if (scaledWidth < size.width) { + // has black lines at left and right sides + var x = (size.width - scaledWidth) / 2 + while (x > 0) { + drawImage(image, dstOffset = IntOffset(x = (x - scaledWidth).roundToInt(), y = ((size.height - scaledHeight) / 2).roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality) + x -= scaledWidth + } + x = size.width - (size.width - scaledWidth) / 2 + while (x < size.width) { + drawImage(image, dstOffset = IntOffset(x = x.roundToInt(), y = ((size.height - scaledHeight) / 2).roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality) + x += scaledWidth + } + } else { + // has black lines at top and bottom sides + var y = (size.height - scaledHeight) / 2 + while (y > 0) { + drawImage(image, dstOffset = IntOffset(x = ((size.width - scaledWidth) / 2).roundToInt(), y = (y - scaledHeight).roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality) + y -= scaledHeight + } + y = size.height - (size.height - scaledHeight) / 2 + while (y < size.height) { + drawImage(image, dstOffset = IntOffset(x = ((size.width - scaledWidth) / 2).roundToInt(), y = y.roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality) + y += scaledHeight + } + } + } + drawRect(tint) + } + } + is WallpaperType.Empty -> {} + } +} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/CloseSheetBar.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/CloseSheetBar.kt index 2fb27e29b1..b26a047b0e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/CloseSheetBar.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/CloseSheetBar.kt @@ -51,7 +51,7 @@ fun CloseSheetBar(close: (() -> Unit)?, showClose: Boolean = true, tintColor: Co @Composable fun AppBarTitle(title: String, hostDevice: Pair? = null, withPadding: Boolean = true, bottomPadding: Dp = DEFAULT_PADDING * 1.5f) { val theme = CurrentColors.collectAsState() - val titleColor = CurrentColors.collectAsState().value.appColors.title + val titleColor = MaterialTheme.appColors.title val brush = if (theme.value.base == DefaultTheme.SIMPLEX) Brush.linearGradient(listOf(titleColor.darker(0.2f), titleColor.lighter(0.35f)), Offset(0f, Float.POSITIVE_INFINITY), Offset(Float.POSITIVE_INFINITY, 0f)) else // color is not updated when changing themes if I pass null here diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/LinkPreviews.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/LinkPreviews.kt index 93d0a56766..20b8f7c09f 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/LinkPreviews.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/LinkPreviews.kt @@ -76,7 +76,7 @@ suspend fun getLinkPreview(url: String): LinkPreview? { @Composable fun ComposeLinkView(linkPreview: LinkPreview?, cancelPreview: () -> Unit, cancelEnabled: Boolean) { - val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage + val sentColor = MaterialTheme.appColors.sentMessage Row( Modifier.fillMaxWidth().padding(top = 8.dp).background(sentColor), verticalAlignment = Alignment.CenterVertically diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt index 887a5bfdd9..6ee60c4596 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt @@ -41,9 +41,12 @@ enum class ModalPlacement { } class ModalData { - private val state = mutableMapOf>() + private val state = mutableMapOf>() fun stateGetOrPut (key: String, default: () -> T): MutableState = state.getOrPut(key) { mutableStateOf(default() as Any) } as MutableState + + fun stateGetOrPutNullable (key: String, default: () -> T?): MutableState = + state.getOrPut(key) { mutableStateOf(default() as Any?) } as MutableState } class ModalManager(private val placement: ModalPlacement? = null) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ThemeModeEditor.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ThemeModeEditor.kt new file mode 100644 index 0000000000..9df4c80b0e --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ThemeModeEditor.kt @@ -0,0 +1,463 @@ +package chat.simplex.common.views.helpers + +import SectionBottomSpacer +import SectionItemView +import SectionSpacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import chat.simplex.common.model.ChatController.appPrefs +import chat.simplex.common.platform.* +import chat.simplex.common.ui.theme.* +import chat.simplex.common.views.usersettings.* +import chat.simplex.common.views.usersettings.AppearanceScope.WallpaperPresetSelector +import chat.simplex.common.views.usersettings.AppearanceScope.editColor +import chat.simplex.res.MR +import dev.icerock.moko.resources.compose.painterResource +import dev.icerock.moko.resources.compose.stringResource +import java.net.URI + +@Composable +fun ModalData.UserWallpaperEditor( + theme: ThemeModeOverride, + applyToMode: DefaultThemeMode?, + globalThemeUsed: MutableState, + save: suspend (applyToMode: DefaultThemeMode?, ThemeModeOverride?) -> Unit +) { + ColumnWithScrollBar( + Modifier + .fillMaxSize() + ) { + val applyToMode = remember { stateGetOrPutNullable("applyToMode") { applyToMode } } + var showMore by remember { stateGetOrPut("showMore") { false } } + val themeModeOverride = remember { stateGetOrPut("themeModeOverride") { theme } } + val currentTheme by CurrentColors.collectAsState() + + AppBarTitle(stringResource(MR.strings.settings_section_title_user_theme)) + val wallpaperImage = MaterialTheme.wallpaper.type.image + val wallpaperType = MaterialTheme.wallpaper.type + + val onTypeCopyFromSameTheme = { type: WallpaperType? -> + if (type is WallpaperType.Image && chatModel.remoteHostId() != null) { + false + } else { + ThemeManager.copyFromSameThemeOverrides(type, null, themeModeOverride) + withBGApi { save(applyToMode.value, themeModeOverride.value) } + globalThemeUsed.value = false + true + } + } + val preApplyGlobalIfNeeded = { type: WallpaperType? -> + if (globalThemeUsed.value) { + onTypeCopyFromSameTheme(type) + } + } + val onTypeChange: (WallpaperType?) -> Unit = { type: WallpaperType? -> + if (globalThemeUsed.value) { + preApplyGlobalIfNeeded(type) + // Saves copied static image instead of original from global theme + ThemeManager.applyWallpaper(themeModeOverride.value.type, themeModeOverride) + } else { + ThemeManager.applyWallpaper(type, themeModeOverride) + } + withBGApi { save(applyToMode.value, themeModeOverride.value) } + } + + val importWallpaperLauncher = rememberFileChooserLauncher(true) { to: URI? -> + if (to != null) { + val filename = saveWallpaperFile(to) + if (filename != null) { + onTypeChange(WallpaperType.Image(filename, 1f, WallpaperScaleType.FILL)) + } + } + } + + val currentColors = { type: WallpaperType? -> + // If applying for : + // - all themes: no overrides needed + // - specific user: only user overrides for currently selected theme are needed, because they will NOT be copied when other wallpaper is selected + val perUserOverride = if (wallpaperType.sameType(type)) chatModel.currentUser.value?.uiThemes else null + ThemeManager.currentColors(type, null, perUserOverride, appPrefs.themeOverrides.get()) + } + val onChooseType: (WallpaperType?) -> Unit = { type: WallpaperType? -> + when { + // don't have image in parent or already selected wallpaper with custom image + type is WallpaperType.Image && chatModel.remoteHostId() != null -> { /* do nothing */ } + type is WallpaperType.Image && (wallpaperType is WallpaperType.Image || currentColors(type).wallpaper.type.image == null) -> withLongRunningApi { importWallpaperLauncher.launch("image/*") } + type is WallpaperType.Image -> onTypeCopyFromSameTheme(currentColors(type).wallpaper.type) + themeModeOverride.value.type != type || currentTheme.wallpaper.type != type -> onTypeCopyFromSameTheme(type) + else -> onTypeChange(type) + } + } + + val editColor = { name: ThemeColor -> + editColor( + name, + wallpaperType, + wallpaperImage, + onColorChange = { color -> + preApplyGlobalIfNeeded(themeModeOverride.value.type) + ThemeManager.applyThemeColor(name, color, themeModeOverride) + withBGApi { save(applyToMode.value, themeModeOverride.value) } + } + ) + } + + WallpaperPresetSelector( + selectedWallpaper = wallpaperType, + baseTheme = currentTheme.base, + currentColors = { type -> + // If applying for : + // - all themes: no overrides needed + // - specific user: only user overrides for currently selected theme are needed, because they will NOT be copied when other wallpaper is selected + val perUserOverride = if (wallpaperType.sameType(type)) chatModel.currentUser.value?.uiThemes else null + ThemeManager.currentColors(type, null, perUserOverride, appPrefs.themeOverrides.get()) + }, + onChooseType = onChooseType + ) + + WallpaperSetupView( + themeModeOverride.value.type, + CurrentColors.collectAsState().value.base, + currentTheme.wallpaper, + currentTheme.appColors.sentMessage, + currentTheme.appColors.sentQuote, + currentTheme.appColors.receivedMessage, + currentTheme.appColors.receivedQuote, + editColor = { name -> editColor(name) }, + onTypeChange = onTypeChange, + ) + + SectionSpacer() + + if (!globalThemeUsed.value) { + ResetToGlobalThemeButton { + themeModeOverride.value = ThemeManager.defaultActiveTheme(chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) + globalThemeUsed.value = true + withBGApi { save(applyToMode.value, null) } + } + } + + SetDefaultThemeButton { + globalThemeUsed.value = false + val lightBase = DefaultTheme.LIGHT + val darkBase = if (CurrentColors.value.base != DefaultTheme.LIGHT) CurrentColors.value.base else if (appPrefs.systemDarkTheme.get() == DefaultTheme.DARK.themeName) DefaultTheme.DARK else if (appPrefs.systemDarkTheme.get() == DefaultTheme.BLACK.themeName) DefaultTheme.BLACK else DefaultTheme.SIMPLEX + val mode = themeModeOverride.value.mode + withBGApi { + // Saving for both modes in one place by changing mode once per save + if (applyToMode.value == null) { + val oppositeMode = if (mode == DefaultThemeMode.LIGHT) DefaultThemeMode.DARK else DefaultThemeMode.LIGHT + save(oppositeMode, ThemeModeOverride.withFilledAppDefaults(oppositeMode, if (oppositeMode == DefaultThemeMode.LIGHT) lightBase else darkBase)) + } + themeModeOverride.value = ThemeModeOverride.withFilledAppDefaults(mode, if (mode == DefaultThemeMode.LIGHT) lightBase else darkBase) + save(themeModeOverride.value.mode, themeModeOverride.value) + } + } + + KeyChangeEffect(theme.mode) { + themeModeOverride.value = theme + if (applyToMode.value != null) { + applyToMode.value = theme.mode + } + } + + // Applies updated global theme if current one tracks global theme + KeyChangeEffect(CurrentColors.collectAsState().value) { + if (globalThemeUsed.value) { + themeModeOverride.value = ThemeManager.defaultActiveTheme(chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) + globalThemeUsed.value = true + } + } + + SectionSpacer() + + if (showMore) { + val values by remember { mutableStateOf( + listOf( + null to generalGetString(MR.strings.chat_theme_apply_to_all_modes), + DefaultThemeMode.LIGHT to generalGetString(MR.strings.chat_theme_apply_to_light_mode), + DefaultThemeMode.DARK to generalGetString(MR.strings.chat_theme_apply_to_dark_mode), + ) + ) + } + ExposedDropDownSettingRow( + generalGetString(MR.strings.chat_theme_apply_to_mode), + values, + applyToMode, + icon = null, + enabled = remember { mutableStateOf(true) }, + onSelected = { + applyToMode.value = it + if (it != null && it != CurrentColors.value.base.mode) { + val lightBase = DefaultTheme.LIGHT + val darkBase = if (CurrentColors.value.base != DefaultTheme.LIGHT) CurrentColors.value.base else if (appPrefs.systemDarkTheme.get() == DefaultTheme.DARK.themeName) DefaultTheme.DARK else if (appPrefs.systemDarkTheme.get() == DefaultTheme.BLACK.themeName) DefaultTheme.BLACK else DefaultTheme.SIMPLEX + ThemeManager.applyTheme(if (it == DefaultThemeMode.LIGHT) lightBase.themeName else darkBase.themeName) + } + } + ) + + SectionSpacer() + + AppearanceScope.CustomizeThemeColorsSection(currentTheme, editColor = editColor) + } else { + AdvancedSettingsButton { showMore = true } + } + + SectionBottomSpacer() + } +} + +@Composable +fun ModalData.ChatWallpaperEditor( + theme: ThemeModeOverride, + applyToMode: DefaultThemeMode?, + globalThemeUsed: MutableState, + save: suspend (applyToMode: DefaultThemeMode?, ThemeModeOverride?) -> Unit +) { + ColumnWithScrollBar( + Modifier + .fillMaxSize() + ) { + val applyToMode = remember { stateGetOrPutNullable("applyToMode") { applyToMode } } + var showMore by remember { stateGetOrPut("showMore") { false } } + val themeModeOverride = remember { stateGetOrPut("themeModeOverride") { theme } } + val currentTheme by remember(themeModeOverride.value, CurrentColors.collectAsState().value) { + mutableStateOf( + ThemeManager.currentColors(null, if (themeModeOverride.value == ThemeModeOverride()) null else themeModeOverride.value, chatModel.currentUser.value?.uiThemes, appPreferences.themeOverrides.get()) + ) + } + + AppBarTitle(stringResource(MR.strings.settings_section_title_chat_theme)) + + val onTypeCopyFromSameTheme: (WallpaperType?) -> Boolean = { type -> + if (type is WallpaperType.Image && chatModel.remoteHostId() != null) { + false + } else { + val success = ThemeManager.copyFromSameThemeOverrides(type, chatModel.currentUser.value?.uiThemes?.preferredMode(!CurrentColors.value.colors.isLight), themeModeOverride) + if (success) { + withBGApi { save(applyToMode.value, themeModeOverride.value) } + globalThemeUsed.value = false + } + success + } + } + val preApplyGlobalIfNeeded = { type: WallpaperType? -> + if (globalThemeUsed.value) { + onTypeCopyFromSameTheme(type) + } + } + val onTypeChange: (WallpaperType?) -> Unit = { type -> + if (globalThemeUsed.value) { + preApplyGlobalIfNeeded(type) + // Saves copied static image instead of original from global theme + ThemeManager.applyWallpaper(themeModeOverride.value.type, themeModeOverride) + } else { + ThemeManager.applyWallpaper(type, themeModeOverride) + } + withBGApi { save(applyToMode.value, themeModeOverride.value) } + } + + val editColor: (ThemeColor) -> Unit = { name: ThemeColor -> + ModalManager.end.showModal { + val currentTheme by remember(themeModeOverride.value, CurrentColors.collectAsState().value) { + mutableStateOf( + ThemeManager.currentColors(null, themeModeOverride.value, chatModel.currentUser.value?.uiThemes, appPreferences.themeOverrides.get()) + ) + } + val initialColor: Color = when (name) { + ThemeColor.WALLPAPER_BACKGROUND -> currentTheme.wallpaper.background ?: Color.Transparent + ThemeColor.WALLPAPER_TINT -> currentTheme.wallpaper.tint ?: Color.Transparent + ThemeColor.PRIMARY -> currentTheme.colors.primary + ThemeColor.PRIMARY_VARIANT -> currentTheme.colors.primaryVariant + ThemeColor.SECONDARY -> currentTheme.colors.secondary + ThemeColor.SECONDARY_VARIANT -> currentTheme.colors.secondaryVariant + ThemeColor.BACKGROUND -> currentTheme.colors.background + ThemeColor.SURFACE -> currentTheme.colors.surface + ThemeColor.TITLE -> currentTheme.appColors.title + ThemeColor.PRIMARY_VARIANT2 -> currentTheme.appColors.primaryVariant2 + ThemeColor.SENT_MESSAGE -> currentTheme.appColors.sentMessage + ThemeColor.SENT_QUOTE -> currentTheme.appColors.sentQuote + ThemeColor.RECEIVED_MESSAGE -> currentTheme.appColors.receivedMessage + ThemeColor.RECEIVED_QUOTE -> currentTheme.appColors.receivedQuote + } + AppearanceScope.ColorEditor( + name, + initialColor, + CurrentColors.collectAsState().value.base, + themeModeOverride.value.type, + themeModeOverride.value.type?.image, + currentTheme.wallpaper.background, + currentTheme.wallpaper.tint, + currentColors = { + ThemeManager.currentColors(null, themeModeOverride.value, chatModel.currentUser.value?.uiThemes, appPreferences.themeOverrides.get()) + }, + onColorChange = { color -> + preApplyGlobalIfNeeded(themeModeOverride.value.type) + ThemeManager.applyThemeColor(name, color, themeModeOverride) + withBGApi { save(applyToMode.value, themeModeOverride.value) } + } + ) + } + } + + val importWallpaperLauncher = rememberFileChooserLauncher(true) { to: URI? -> + if (to != null) { + val filename = saveWallpaperFile(to) + if (filename != null) { + // Delete only non-user image + if (!globalThemeUsed.value) { + removeWallpaperFile((themeModeOverride.value.type as? WallpaperType.Image)?.filename) + } + globalThemeUsed.value = false + onTypeChange(WallpaperType.Image(filename, 1f, WallpaperScaleType.FILL)) + } + } + } + + val currentColors = { type: WallpaperType? -> + ThemeManager.currentColors(type, if (type?.sameType(themeModeOverride.value.type) == true) themeModeOverride.value else null, chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) + } + + WallpaperPresetSelector( + selectedWallpaper = currentTheme.wallpaper.type, + activeBackgroundColor = currentTheme.wallpaper.background, + activeTintColor = currentTheme.wallpaper.tint, + baseTheme = CurrentColors.collectAsState().value.base, + currentColors = { type -> currentColors(type) }, + onChooseType = { type -> + when { + type is WallpaperType.Image && chatModel.remoteHostId() != null -> { /* do nothing */ } + type is WallpaperType.Image && ((themeModeOverride.value.type is WallpaperType.Image && !globalThemeUsed.value) || currentColors(type).wallpaper.type.image == null) -> { + withLongRunningApi { importWallpaperLauncher.launch("image/*") } + } + type is WallpaperType.Image -> { + if (!onTypeCopyFromSameTheme(currentColors(type).wallpaper.type)) { + withLongRunningApi { importWallpaperLauncher.launch("image/*") } + } + } + globalThemeUsed.value || themeModeOverride.value.type != type -> { + onTypeCopyFromSameTheme(type) + } + else -> { + onTypeChange(type) + } + } + }, + ) + + WallpaperSetupView( + themeModeOverride.value.type, + CurrentColors.collectAsState().value.base, + currentTheme.wallpaper, + currentTheme.appColors.sentMessage, + currentTheme.appColors.sentQuote, + currentTheme.appColors.receivedMessage, + currentTheme.appColors.receivedQuote, + editColor = editColor, + onTypeChange = onTypeChange, + ) + + SectionSpacer() + + if (!globalThemeUsed.value) { + ResetToGlobalThemeButton { + themeModeOverride.value = ThemeManager.defaultActiveTheme(chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) + globalThemeUsed.value = true + withBGApi { save(applyToMode.value, null) } + } + } + + SetDefaultThemeButton { + globalThemeUsed.value = false + val lightBase = DefaultTheme.LIGHT + val darkBase = if (CurrentColors.value.base != DefaultTheme.LIGHT) CurrentColors.value.base else if (appPrefs.systemDarkTheme.get() == DefaultTheme.DARK.themeName) DefaultTheme.DARK else if (appPrefs.systemDarkTheme.get() == DefaultTheme.BLACK.themeName) DefaultTheme.BLACK else DefaultTheme.SIMPLEX + val mode = themeModeOverride.value.mode + withBGApi { + // Saving for both modes in one place by changing mode once per save + if (applyToMode.value == null) { + val oppositeMode = if (mode == DefaultThemeMode.LIGHT) DefaultThemeMode.DARK else DefaultThemeMode.LIGHT + save(oppositeMode, ThemeModeOverride.withFilledAppDefaults(oppositeMode, if (oppositeMode == DefaultThemeMode.LIGHT) lightBase else darkBase)) + } + themeModeOverride.value = ThemeModeOverride.withFilledAppDefaults(mode, if (mode == DefaultThemeMode.LIGHT) lightBase else darkBase) + save(themeModeOverride.value.mode, themeModeOverride.value) + } + } + + KeyChangeEffect(theme.mode) { + themeModeOverride.value = theme + if (applyToMode.value != null) { + applyToMode.value = theme.mode + } + } + + // Applies updated global theme if current one tracks global theme + KeyChangeEffect(CurrentColors.collectAsState()) { + if (globalThemeUsed.value) { + themeModeOverride.value = ThemeManager.defaultActiveTheme(chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) + globalThemeUsed.value = true + } + } + + SectionSpacer() + + if (showMore) { + val values by remember { mutableStateOf( + listOf( + null to generalGetString(MR.strings.chat_theme_apply_to_all_modes), + DefaultThemeMode.LIGHT to generalGetString(MR.strings.chat_theme_apply_to_light_mode), + DefaultThemeMode.DARK to generalGetString(MR.strings.chat_theme_apply_to_dark_mode), + ) + ) + } + ExposedDropDownSettingRow( + generalGetString(MR.strings.chat_theme_apply_to_mode), + values, + applyToMode, + icon = null, + enabled = remember { mutableStateOf(true) }, + onSelected = { + applyToMode.value = it + if (it != null && it != CurrentColors.value.base.mode) { + val lightBase = DefaultTheme.LIGHT + val darkBase = if (CurrentColors.value.base != DefaultTheme.LIGHT) CurrentColors.value.base else if (appPrefs.systemDarkTheme.get() == DefaultTheme.DARK.themeName) DefaultTheme.DARK else if (appPrefs.systemDarkTheme.get() == DefaultTheme.BLACK.themeName) DefaultTheme.BLACK else DefaultTheme.SIMPLEX + ThemeManager.applyTheme(if (it == DefaultThemeMode.LIGHT) lightBase.themeName else darkBase.themeName) + } + } + ) + + SectionSpacer() + + AppearanceScope.CustomizeThemeColorsSection(currentTheme, editColor = editColor) + } else { + AdvancedSettingsButton { showMore = true } + } + + SectionBottomSpacer() + } +} + +@Composable +private fun ResetToGlobalThemeButton(onClick: () -> Unit) { + SectionItemView(onClick) { + Text(stringResource(MR.strings.chat_theme_reset_to_global_theme), color = MaterialTheme.colors.primary) + } +} + +@Composable +private fun SetDefaultThemeButton(onClick: () -> Unit) { + SectionItemView(onClick) { + Text(stringResource(MR.strings.chat_theme_set_default_theme), color = MaterialTheme.colors.primary) + } +} + +@Composable +private fun AdvancedSettingsButton(onClick: () -> Unit) { + SettingsActionItem( + painterResource(MR.images.ic_arrow_downward), + stringResource(MR.strings.wallpaper_advanced_settings), + click = onClick + ) +} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt index 9a6e3a0f9a..4740280bb5 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt @@ -19,6 +19,7 @@ import kotlinx.serialization.encodeToString import java.io.* import java.net.URI import java.nio.file.Files +import java.nio.file.StandardCopyOption import java.text.SimpleDateFormat import java.util.* import java.util.concurrent.Executors @@ -280,6 +281,38 @@ fun saveFileFromUri(uri: URI, withAlertOnException: Boolean = true): CryptoFile? } } +fun saveWallpaperFile(uri: URI): String? { + val destFileName = generateNewFileName("wallpaper", "jpg", File(getWallpaperFilePath(""))) + val destFile = File(getWallpaperFilePath(destFileName)) + try { + val inputStream = uri.inputStream() + Files.copy(inputStream!!, destFile.toPath(), StandardCopyOption.REPLACE_EXISTING) + } catch (e: Exception) { + Log.e(TAG, "Error saving wallpaper file: ${e.stackTraceToString()}") + AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error), e.stackTraceToString()) + return null + } + return destFile.name +} + +fun saveWallpaperFile(image: ImageBitmap): String { + val destFileName = generateNewFileName("wallpaper", "jpg", File(getWallpaperFilePath(""))) + val destFile = File(getWallpaperFilePath(destFileName)) + val dataResized = resizeImageToDataSize(image, false, maxDataSize = 5_000_000) + val output = FileOutputStream(destFile) + dataResized.use { + it.writeTo(output) + } + return destFile.name +} + +fun removeWallpaperFile(fileName: String? = null) { + File(getWallpaperFilePath("_")).parentFile.listFiles()?.forEach { + if (it.name == fileName) it.delete() + } + WallpaperType.cachedImages.remove(fileName) +} + fun createTmpFileAndDelete(onCreated: (File) -> T): T { val tmpFile = File(tmpDir, UUID.randomUUID().toString()) tmpFile.deleteOnExit() @@ -550,10 +583,33 @@ fun KeyChangeEffect( val initialKey = remember { key1 } val initialKey2 = remember { key2 } var anyChange by remember { mutableStateOf(false) } - LaunchedEffect(key1) { + LaunchedEffect(key1, key2) { if (anyChange || key1 != initialKey || key2 != initialKey2) { block() anyChange = true } } } + +/** + * Runs the [block] only after initial value of the [key1], or [key2], or [key3] changes, not after initial launch + * */ +@Composable +@NonRestartableComposable +fun KeyChangeEffect( + key1: Any?, + key2: Any?, + key3: Any?, + block: suspend CoroutineScope.() -> Unit +) { + val initialKey = remember { key1 } + val initialKey2 = remember { key2 } + val initialKey3 = remember { key3 } + var anyChange by remember { mutableStateOf(false) } + LaunchedEffect(key1, key2, key3) { + if (anyChange || key1 != initialKey || key2 != initialKey2 || key3 != initialKey3) { + block() + anyChange = true + } + } +} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/LocalAuthView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/LocalAuthView.kt index 5a37c860a0..65e1864935 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/LocalAuthView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/LocalAuthView.kt @@ -34,7 +34,7 @@ fun LocalAuthView(m: ChatModel, authRequest: LocalAuthRequest) { } else { val r: LAResult = if (passcode.value == authRequest.password) { if (authRequest.selfDestruct && sdPassword != null && controller.ctrl == -1L) { - initChatControllerAndRunMigrations() + initChatControllerOnStart() } LAResult.Success } else { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt index 9d204ad42c..f3a992d451 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt @@ -669,7 +669,7 @@ private suspend fun MutableState.cleanUpOnBack(chatReceiver: if (state is MigrationToState.ArchiveImportFailed) { // Original database is not exist, nothing is set up correctly for showing to a user yet. Return to clean state deleteChatDatabaseFilesAndState() - initChatControllerAndRunMigrations() + initChatControllerOnStart() } else if (state is MigrationToState.DownloadProgress && state.ctrl != null) { stopArchiveDownloading(state.fileId, state.ctrl) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt index 78e24e5e7e..ad7804de00 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt @@ -1,37 +1,52 @@ package chat.simplex.common.views.usersettings import SectionBottomSpacer +import SectionDividerSpaced import SectionItemView import SectionItemViewSpaceBetween import SectionSpacer import SectionView -import androidx.compose.foundation.Image +import androidx.compose.foundation.* import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.grid.* +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.material.MaterialTheme.colors import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.* import androidx.compose.ui.graphics.* -import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.unit.* import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource -import androidx.compose.ui.unit.dp import chat.simplex.common.model.* +import chat.simplex.common.model.ChatController.appPrefs import chat.simplex.common.ui.theme.* import chat.simplex.common.views.helpers.* import chat.simplex.common.model.ChatModel +import chat.simplex.common.model.ChatModel.controller import chat.simplex.common.platform.* +import chat.simplex.common.ui.theme.ThemeManager.colorFromReadableHex +import chat.simplex.common.ui.theme.ThemeManager.toReadableHex +import chat.simplex.common.views.chat.item.PreviewChatItemView import chat.simplex.res.MR -import com.godaddy.android.colorpicker.* +import com.godaddy.android.colorpicker.ClassicColorPicker +import com.godaddy.android.colorpicker.HsvColor +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.datetime.Clock import kotlinx.serialization.encodeToString import java.net.URI import java.util.* import kotlin.collections.ArrayList +import kotlin.math.* @Composable -expect fun AppearanceView(m: ChatModel, showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit)) +expect fun AppearanceView(m: ChatModel) object AppearanceScope { @Composable @@ -55,6 +70,7 @@ object AppearanceScope { onValueChange = { val diff = it % 2.5f appPreferences.profileImageCornerRadius.set(it + (if (diff >= 1.25f) -diff + 2.5f else -diff)) + saveThemeToDatabase(null) }, colors = SliderDefaults.colors( activeTickColor = Color.Transparent, @@ -66,90 +82,424 @@ object AppearanceScope { } @Composable - fun ThemesSection( - systemDarkTheme: SharedPreference, - showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), - editColor: (ThemeColor, Color) -> Unit + fun ChatThemePreview( + theme: DefaultTheme, + wallpaperImage: ImageBitmap?, + wallpaperType: WallpaperType?, + backgroundColor: Color? = MaterialTheme.wallpaper.background, + tintColor: Color? = MaterialTheme.wallpaper.tint, + withMessages: Boolean = true ) { - val currentTheme by CurrentColors.collectAsState() - SectionView(stringResource(MR.strings.settings_section_title_themes)) { - val darkTheme = isSystemInDarkTheme() - val state = remember { derivedStateOf { currentTheme.name } } - ThemeSelector(state) { - ThemeManager.applyTheme(it, darkTheme) - } - if (state.value == DefaultTheme.SYSTEM.name) { - DarkThemeSelector(remember { systemDarkTheme.state }) { - ThemeManager.changeDarkTheme(it, darkTheme) + val themeBackgroundColor = MaterialTheme.colors.background + val backgroundColor = backgroundColor ?: wallpaperType?.defaultBackgroundColor(theme, MaterialTheme.colors.background) + val tintColor = tintColor ?: wallpaperType?.defaultTintColor(theme) + Column(Modifier + .drawBehind { + if (wallpaperImage != null && wallpaperType != null && backgroundColor != null && tintColor != null) { + chatViewBackground(wallpaperImage, wallpaperType, backgroundColor, tintColor) + } else { + drawRect(themeBackgroundColor) } } + .padding(DEFAULT_PADDING_HALF) + ) { + if (withMessages) { + val alice = remember { ChatItem.getSampleData(1, CIDirection.DirectRcv(), Clock.System.now(), generalGetString(MR.strings.wallpaper_preview_hello_bob)) } + PreviewChatItemView(alice) + PreviewChatItemView( + ChatItem.getSampleData(2, CIDirection.DirectSnd(), Clock.System.now(), stringResource(MR.strings.wallpaper_preview_hello_alice), + quotedItem = CIQuote(alice.chatDir, alice.id, sentAt = alice.meta.itemTs, formattedText = alice.formattedText, content = MsgContent.MCText(alice.content.text)) + ) + ) + } else { + Box(Modifier.fillMaxSize()) + } } - SectionItemView(showSettingsModal { _ -> CustomizeThemeView(editColor) }) { Text(stringResource(MR.strings.customize_theme_title)) } } @Composable - fun CustomizeThemeView(editColor: (ThemeColor, Color) -> Unit) { + fun WallpaperPresetSelector( + selectedWallpaper: WallpaperType?, + baseTheme: DefaultTheme, + activeBackgroundColor: Color? = null, + activeTintColor: Color? = null, + currentColors: (WallpaperType?) -> ThemeManager.ActiveTheme, + onChooseType: (WallpaperType?) -> Unit, + ) { + val cornerRadius = 22 + + @Composable + fun Plus(tint: Color = MaterialTheme.colors.primary) { + Icon(painterResource(MR.images.ic_add), null, Modifier.size(25.dp), tint = tint) + } + + val backgrounds = PresetWallpaper.entries.toList() + + fun LazyGridScope.gridContent(width: Dp, height: Dp) { + @Composable + fun BackgroundItem(background: PresetWallpaper?) { + val checked = (background == null && (selectedWallpaper == null || selectedWallpaper == WallpaperType.Empty)) || selectedWallpaper?.samePreset(background) == true + Box( + Modifier + .size(width, height) + .clip(RoundedCornerShape(percent = cornerRadius)) + .border(1.dp, if (checked) MaterialTheme.colors.primary.copy(0.8f) else MaterialTheme.colors.onBackground.copy(if (isInDarkTheme()) 0.2f else 0.1f), RoundedCornerShape(percent = cornerRadius)) + .clickable { onChooseType(background?.toType(baseTheme)) }, + contentAlignment = Alignment.Center + ) { + if (background != null) { + val type = background.toType(baseTheme, if (checked) selectedWallpaper?.scale else null) + SimpleXThemeOverride(remember(background, selectedWallpaper, CurrentColors.collectAsState().value) { currentColors(type) }) { + ChatThemePreview( + baseTheme, + type.image, + type, + withMessages = false, + backgroundColor = if (checked) activeBackgroundColor ?: MaterialTheme.wallpaper.background else MaterialTheme.wallpaper.background, + tintColor = if (checked) activeTintColor ?: MaterialTheme.wallpaper.tint else MaterialTheme.wallpaper.tint + ) + } + } + } + } + + @Composable + fun OwnBackgroundItem(type: WallpaperType?) { + val overrides = remember(type, baseTheme, CurrentColors.collectAsState().value.wallpaper) { + currentColors(WallpaperType.Image("", null, null)) + } + val appWallpaper = overrides.wallpaper + val backgroundColor = appWallpaper.background + val tintColor = appWallpaper.tint + val wallpaperImage = appWallpaper.type.image + val checked = type is WallpaperType.Image && wallpaperImage != null + val remoteHostConnected = chatModel.remoteHostId != null + Box( + Modifier + .size(width, height) + .clip(RoundedCornerShape(percent = cornerRadius)) + .border(1.dp, if (type is WallpaperType.Image) MaterialTheme.colors.primary.copy(0.8f) else MaterialTheme.colors.onBackground.copy(0.1f), RoundedCornerShape(percent = cornerRadius)) + .clickable { onChooseType(WallpaperType.Image("", null, null)) }, + contentAlignment = Alignment.Center + ) { + + if (checked || wallpaperImage != null) { + ChatThemePreview( + baseTheme, + wallpaperImage, + if (checked) type else appWallpaper.type, + backgroundColor = if (checked) activeBackgroundColor ?: backgroundColor else backgroundColor, + tintColor = if (checked) activeTintColor ?: tintColor else tintColor, + withMessages = false + ) + } else if (remoteHostConnected) { + Plus(MaterialTheme.colors.error) + } else { + Plus() + } + } + } + + item { + BackgroundItem(null) + } + items(items = backgrounds) { background -> + BackgroundItem(background) + } + item { + OwnBackgroundItem(selectedWallpaper) + } + } + + SimpleXThemeOverride(remember(selectedWallpaper, CurrentColors.collectAsState().value) { currentColors(selectedWallpaper) }) { + ChatThemePreview( + baseTheme, + MaterialTheme.wallpaper.type.image, + selectedWallpaper, + backgroundColor = activeBackgroundColor ?: MaterialTheme.wallpaper.background, + tintColor = activeTintColor ?: MaterialTheme.wallpaper.tint, + ) + } + + if (appPlatform.isDesktop) { + val itemWidth = (DEFAULT_START_MODAL_WIDTH - DEFAULT_PADDING * 2 - DEFAULT_PADDING_HALF * 3) / 4 + val itemHeight = (DEFAULT_START_MODAL_WIDTH - DEFAULT_PADDING * 2) / 4 + val rows = ceil((PresetWallpaper.entries.size + 2) / 4f).roundToInt() + LazyVerticalGrid( + columns = GridCells.Fixed(4), + Modifier.height(itemHeight * rows + DEFAULT_PADDING_HALF * (rows - 1) + DEFAULT_PADDING * 2), + contentPadding = PaddingValues(DEFAULT_PADDING), + verticalArrangement = Arrangement.spacedBy(DEFAULT_PADDING_HALF), + horizontalArrangement = Arrangement.spacedBy(DEFAULT_PADDING_HALF), + ) { + gridContent(itemWidth, itemHeight) + } + } else { + LazyHorizontalGrid( + rows = GridCells.Fixed(1), + Modifier.height(80.dp + DEFAULT_PADDING * 2), + contentPadding = PaddingValues(DEFAULT_PADDING), + horizontalArrangement = Arrangement.spacedBy(DEFAULT_PADDING_HALF), + ) { + gridContent(80.dp, 80.dp) + } + } + } + + @Composable + fun ThemesSection(systemDarkTheme: SharedPreference) { + val currentTheme by CurrentColors.collectAsState() + val baseTheme = currentTheme.base + val wallpaperType = MaterialTheme.wallpaper.type + val themeUserDestination: MutableState?> = rememberSaveable(stateSaver = serializableSaver()) { + val currentUser = chatModel.currentUser.value + mutableStateOf( + if (currentUser?.uiThemes?.preferredMode(!currentTheme.colors.isLight) == null) null else currentUser.userId to currentUser.uiThemes + ) + } + val perUserTheme = remember(CurrentColors.collectAsState().value.base, chatModel.currentUser.value) { + mutableStateOf( + chatModel.currentUser.value?.uiThemes?.preferredMode(!CurrentColors.value.colors.isLight) ?: ThemeModeOverride() + ) + } + + fun updateThemeUserDestination() { + var (userId, themes) = themeUserDestination.value ?: return + themes = if (perUserTheme.value.mode == DefaultThemeMode.LIGHT) { + (themes ?: ThemeModeOverrides()).copy(light = perUserTheme.value) + } else { + (themes ?: ThemeModeOverrides()).copy(dark = perUserTheme.value) + } + themeUserDestination.value = userId to themes + } + + val onTypeCopyFromSameTheme = { type: WallpaperType? -> + if (themeUserDestination.value == null) { + ThemeManager.saveAndApplyWallpaper(baseTheme, type) + } else { + val wallpaperFiles = listOf(perUserTheme.value.wallpaper?.imageFile) + ThemeManager.copyFromSameThemeOverrides(type, null, perUserTheme) + val wallpaperFilesToDelete = wallpaperFiles - perUserTheme.value.wallpaper?.imageFile + wallpaperFilesToDelete.forEach(::removeWallpaperFile) + updateThemeUserDestination() + } + saveThemeToDatabase(themeUserDestination.value) + true + } + + val onTypeChange = { type: WallpaperType? -> + if (themeUserDestination.value == null) { + ThemeManager.saveAndApplyWallpaper(baseTheme, type) + } else { + ThemeManager.applyWallpaper(type, perUserTheme) + updateThemeUserDestination() + } + saveThemeToDatabase(themeUserDestination.value) + } + + val importWallpaperLauncher = rememberFileChooserLauncher(true) { to: URI? -> + if (to != null) { + val filename = saveWallpaperFile(to) + if (filename != null) { + if (themeUserDestination.value == null) { + removeWallpaperFile((currentTheme.wallpaper.type as? WallpaperType.Image)?.filename) + } else { + removeWallpaperFile((perUserTheme.value.type as? WallpaperType.Image)?.filename) + } + onTypeChange(WallpaperType.Image(filename, 1f, WallpaperScaleType.FILL)) + } + } + } + + val currentColors = { type: WallpaperType? -> + // If applying for : + // - all themes: no overrides needed + // - specific user: only user overrides for currently selected theme are needed, because they will NOT be copied when other wallpaper is selected + val perUserOverride = if (themeUserDestination.value == null) null else if (wallpaperType.sameType(type)) chatModel.currentUser.value?.uiThemes else null + ThemeManager.currentColors(type, null, perUserOverride, appPrefs.themeOverrides.get()) + } + + val onChooseType: (WallpaperType?) -> Unit = { type: WallpaperType? -> + when { + // don't have image in parent or already selected wallpaper with custom image + type is WallpaperType.Image && + ((wallpaperType is WallpaperType.Image && themeUserDestination.value?.second != null && chatModel.remoteHostId() == null) || + currentColors(type).wallpaper.type.image == null || + (currentColors(type).wallpaper.type.image != null && wallpaperType is WallpaperType.Image && themeUserDestination.value == null)) -> + withLongRunningApi { importWallpaperLauncher.launch("image/*") } + type is WallpaperType.Image && themeUserDestination.value == null -> onTypeChange(currentColors(type).wallpaper.type) + type is WallpaperType.Image && chatModel.remoteHostId() != null -> { /* do nothing when remote host connected */ } + type is WallpaperType.Image -> onTypeCopyFromSameTheme(currentColors(type).wallpaper.type) + (themeUserDestination.value != null && themeUserDestination.value?.second?.preferredMode(!CurrentColors.value.colors.isLight)?.type != type) || currentTheme.wallpaper.type != type -> onTypeCopyFromSameTheme(type) + else -> onTypeChange(type) + } + } + + SectionView(stringResource(MR.strings.settings_section_title_themes)) { + Spacer(Modifier.height(DEFAULT_PADDING_HALF)) + ThemeDestinationPicker(themeUserDestination) + Spacer(Modifier.height(DEFAULT_PADDING_HALF)) + + WallpaperPresetSelector( + selectedWallpaper = wallpaperType, + baseTheme = currentTheme.base, + currentColors = { type -> + currentColors(type) + }, + onChooseType = onChooseType, + ) + val type = MaterialTheme.wallpaper.type + if (type is WallpaperType.Image && (themeUserDestination.value == null || perUserTheme.value.wallpaper?.imageFile != null)) { + SectionItemView(disabled = chatModel.remoteHostId != null && themeUserDestination.value != null, click = { + if (themeUserDestination.value == null) { + val defaultActiveTheme = ThemeManager.defaultActiveTheme(appPrefs.themeOverrides.get()) + ThemeManager.saveAndApplyWallpaper(baseTheme, null) + ThemeManager.removeTheme(defaultActiveTheme?.themeId) + removeWallpaperFile(type.filename) + } else { + removeUserThemeModeOverrides(themeUserDestination, perUserTheme) + } + saveThemeToDatabase(themeUserDestination.value) + }) { + Text( + stringResource(MR.strings.theme_remove_image), + color = if (chatModel.remoteHostId != null && themeUserDestination.value != null) MaterialTheme.colors.secondary else MaterialTheme.colors.primary + ) + } + SectionSpacer() + } + + val state: State = remember(appPrefs.currentTheme.get()) { + derivedStateOf { + if (appPrefs.currentTheme.get() == DefaultTheme.SYSTEM_THEME_NAME) null else currentTheme.base.mode + } + } + ColorModeSelector(state) { + val newTheme = when (it) { + null -> DefaultTheme.SYSTEM_THEME_NAME + DefaultThemeMode.LIGHT -> DefaultTheme.LIGHT.themeName + DefaultThemeMode.DARK -> appPrefs.systemDarkTheme.get()!! + } + ThemeManager.applyTheme(newTheme) + saveThemeToDatabase(null) + } + + // Doesn't work on desktop when specified like remember { systemDarkTheme.state }, this is workaround + val darkModeState: State = remember(systemDarkTheme.get()) { derivedStateOf { systemDarkTheme.get() } } + DarkModeThemeSelector(darkModeState) { + ThemeManager.changeDarkTheme(it) + if (appPrefs.currentTheme.get() == DefaultTheme.SYSTEM_THEME_NAME) { + ThemeManager.applyTheme(appPrefs.currentTheme.get()!!) + } else if (appPrefs.currentTheme.get() != DefaultTheme.LIGHT.themeName) { + ThemeManager.applyTheme(appPrefs.systemDarkTheme.get()!!) + } + saveThemeToDatabase(null) + } + } + SectionItemView(click = { + val user = themeUserDestination.value + if (user == null) { + ModalManager.start.showModal { + CustomizeThemeView(onChooseType) + } + } else { + ModalManager.start.showModalCloseable { close -> + UserWallpaperEditorModal(chatModel.remoteHostId(), user.first, close) + } + } + }) { + Text(stringResource(MR.strings.customize_theme_title)) + } + } + + @Composable + fun CustomizeThemeView(onChooseType: (WallpaperType?) -> Unit) { ColumnWithScrollBar( Modifier.fillMaxWidth(), ) { val currentTheme by CurrentColors.collectAsState() AppBarTitle(stringResource(MR.strings.customize_theme_title)) + val wallpaperImage = MaterialTheme.wallpaper.type.image + val wallpaperType = MaterialTheme.wallpaper.type + val baseTheme = CurrentColors.collectAsState().value.base - SectionView(stringResource(MR.strings.theme_colors_section_title)) { - SectionItemViewSpaceBetween({ editColor(ThemeColor.PRIMARY, currentTheme.colors.primary) }) { - val title = generalGetString(MR.strings.color_primary) - Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = colors.primary) - } - SectionItemViewSpaceBetween({ editColor(ThemeColor.PRIMARY_VARIANT, currentTheme.colors.primaryVariant) }) { - val title = generalGetString(MR.strings.color_primary_variant) - Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = colors.primaryVariant) - } - SectionItemViewSpaceBetween({ editColor(ThemeColor.SECONDARY, currentTheme.colors.secondary) }) { - val title = generalGetString(MR.strings.color_secondary) - Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = colors.secondary) - } - SectionItemViewSpaceBetween({ editColor(ThemeColor.SECONDARY_VARIANT, currentTheme.colors.secondaryVariant) }) { - val title = generalGetString(MR.strings.color_secondary_variant) - Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = colors.secondaryVariant) - } - SectionItemViewSpaceBetween({ editColor(ThemeColor.BACKGROUND, currentTheme.colors.background) }) { - val title = generalGetString(MR.strings.color_background) - Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = colors.background) - } - SectionItemViewSpaceBetween({ editColor(ThemeColor.SURFACE, currentTheme.colors.surface) }) { - val title = generalGetString(MR.strings.color_surface) - Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = colors.surface) - } - SectionItemViewSpaceBetween({ editColor(ThemeColor.TITLE, currentTheme.appColors.title) }) { - val title = generalGetString(MR.strings.color_title) - Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = currentTheme.appColors.title) - } - SectionItemViewSpaceBetween({ editColor(ThemeColor.SENT_MESSAGE, currentTheme.appColors.sentMessage) }) { - val title = generalGetString(MR.strings.color_sent_message) - Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = currentTheme.appColors.sentMessage) - } - SectionItemViewSpaceBetween({ editColor(ThemeColor.RECEIVED_MESSAGE, currentTheme.appColors.receivedMessage) }) { - val title = generalGetString(MR.strings.color_received_message) - Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = currentTheme.appColors.receivedMessage) - } + val editColor = { name: ThemeColor -> + editColor( + name, + wallpaperType, + wallpaperImage, + onColorChange = { color -> + ThemeManager.saveAndApplyThemeColor(baseTheme, name, color) + saveThemeToDatabase(null) + } + ) } - val isInDarkTheme = isInDarkTheme() - if (currentTheme.base.hasChangedAnyColor(currentTheme.colors, currentTheme.appColors)) { - SectionItemView({ ThemeManager.resetAllThemeColors(darkForSystemTheme = isInDarkTheme) }) { + + WallpaperPresetSelector( + selectedWallpaper = wallpaperType, + baseTheme = currentTheme.base, + currentColors = { type -> + ThemeManager.currentColors(type, null, null, appPrefs.themeOverrides.get()) + }, + onChooseType = onChooseType + ) + + val type = MaterialTheme.wallpaper.type + if (type is WallpaperType.Image) { + SectionItemView(disabled = chatModel.remoteHostId != null, click = { + val defaultActiveTheme = ThemeManager.defaultActiveTheme(appPrefs.themeOverrides.get()) + ThemeManager.saveAndApplyWallpaper(baseTheme, null) + ThemeManager.removeTheme(defaultActiveTheme?.themeId) + removeWallpaperFile(type.filename) + saveThemeToDatabase(null) + }) { + Text( + stringResource(MR.strings.theme_remove_image), + color = if (chatModel.remoteHostId == null) MaterialTheme.colors.primary else MaterialTheme.colors.secondary + ) + } + SectionSpacer() + } + + SectionView(stringResource(MR.strings.settings_section_title_chat_colors).uppercase()) { + WallpaperSetupView( + wallpaperType, + baseTheme, + MaterialTheme.wallpaper, + MaterialTheme.appColors.sentMessage, + MaterialTheme.appColors.sentQuote, + MaterialTheme.appColors.receivedMessage, + MaterialTheme.appColors.receivedQuote, + editColor = { name -> + editColor(name) + }, + onTypeChange = { type -> + ThemeManager.saveAndApplyWallpaper(baseTheme, type) + saveThemeToDatabase(null) + }, + ) + } + SectionDividerSpaced(maxTopPadding = true) + + CustomizeThemeColorsSection(currentTheme) { name -> + editColor(name) + } + + SectionSpacer() + + val currentOverrides = remember(currentTheme) { ThemeManager.defaultActiveTheme(appPrefs.themeOverrides.get()) } + val canResetColors = currentTheme.base.hasChangedAnyColor(currentOverrides) + if (canResetColors) { + SectionItemView({ + ThemeManager.resetAllThemeColors() + saveThemeToDatabase(null) + }) { Text(generalGetString(MR.strings.reset_color), color = colors.primary) } + SectionSpacer() } - SectionSpacer() + SectionView { val theme = remember { mutableStateOf(null as String?) } val exportThemeLauncher = rememberFileChooserLauncher(false) { to: URI? -> @@ -161,9 +511,11 @@ object AppearanceScope { } } SectionItemView({ - val overrides = ThemeManager.currentThemeOverridesForExport(isInDarkTheme) - theme.value = yaml.encodeToString(overrides) - withLongRunningApi { exportThemeLauncher.launch("simplex.theme")} + val overrides = ThemeManager.currentThemeOverridesForExport(null, null/*chatModel.currentUser.value?.uiThemes*/) + val lines = yaml.encodeToString(overrides).lines() + // Removing theme id without using custom serializer or data class + theme.value = lines.subList(1, lines.size).joinToString("\n") + withLongRunningApi { exportThemeLauncher.launch("simplex.theme") } }) { Text(generalGetString(MR.strings.export_theme), color = colors.primary) } @@ -171,7 +523,8 @@ object AppearanceScope { if (to != null) { val theme = getThemeFromUri(to) if (theme != null) { - ThemeManager.saveAndApplyThemeOverrides(theme, isInDarkTheme) + ThemeManager.saveAndApplyThemeOverrides(theme) + saveThemeToDatabase(null) } } } @@ -184,49 +537,318 @@ object AppearanceScope { } } - @Composable - fun ColorEditor( - name: ThemeColor, - initialColor: Color, - close: () -> Unit, - ) { - Column( - Modifier - .fillMaxWidth() - ) { - AppBarTitle(name.text) - var currentColor by remember { mutableStateOf(initialColor) } - ColorPicker(initialColor) { - currentColor = it + private var updateBackendJob: Job = Job() + private fun saveThemeToDatabase(themeUserDestination: Pair?) { + val remoteHostId = chatModel.remoteHostId() + val oldThemes = chatModel.currentUser.value?.uiThemes + if (themeUserDestination != null) { + // Update before save to make it work seamless + chatModel.updateCurrentUserUiThemes(remoteHostId, themeUserDestination.second) + } + updateBackendJob.cancel() + updateBackendJob = withBGApi { + delay(300) + if (themeUserDestination == null) { + controller.apiSaveAppSettings(AppSettings.current.prepareForExport()) + } else if (!controller.apiSetUserUIThemes(remoteHostId, themeUserDestination.first, themeUserDestination.second)) { + // If failed to apply for some reason return the old themes + chatModel.updateCurrentUserUiThemes(remoteHostId, oldThemes) } + } + } - SectionSpacer() - val isInDarkTheme = isInDarkTheme() - TextButton( - onClick = { - ThemeManager.saveAndApplyThemeColor(name, currentColor, isInDarkTheme) - close() - }, - Modifier.align(Alignment.CenterHorizontally), - colors = ButtonDefaults.textButtonColors(contentColor = currentColor) - ) { - Text(generalGetString(MR.strings.save_color)) + fun editColor(name: ThemeColor, wallpaperType: WallpaperType, wallpaperImage: ImageBitmap?, onColorChange: (Color?) -> Unit) { + ModalManager.start.showModal { + val baseTheme = CurrentColors.collectAsState().value.base + val wallpaperBackgroundColor = MaterialTheme.wallpaper.background ?: wallpaperType.defaultBackgroundColor(baseTheme, MaterialTheme.colors.background) + val wallpaperTintColor = MaterialTheme.wallpaper.tint ?: wallpaperType.defaultTintColor(baseTheme) + val initialColor: Color = when (name) { + ThemeColor.WALLPAPER_BACKGROUND -> wallpaperBackgroundColor + ThemeColor.WALLPAPER_TINT -> wallpaperTintColor + ThemeColor.PRIMARY -> MaterialTheme.colors.primary + ThemeColor.PRIMARY_VARIANT -> MaterialTheme.colors.primaryVariant + ThemeColor.SECONDARY -> MaterialTheme.colors.secondary + ThemeColor.SECONDARY_VARIANT -> MaterialTheme.colors.secondaryVariant + ThemeColor.BACKGROUND -> MaterialTheme.colors.background + ThemeColor.SURFACE -> MaterialTheme.colors.surface + ThemeColor.TITLE -> MaterialTheme.appColors.title + ThemeColor.PRIMARY_VARIANT2 -> MaterialTheme.appColors.primaryVariant2 + ThemeColor.SENT_MESSAGE -> MaterialTheme.appColors.sentMessage + ThemeColor.SENT_QUOTE -> MaterialTheme.appColors.sentQuote + ThemeColor.RECEIVED_MESSAGE -> MaterialTheme.appColors.receivedMessage + ThemeColor.RECEIVED_QUOTE -> MaterialTheme.appColors.receivedQuote + } + ColorEditor(name, initialColor, baseTheme, MaterialTheme.wallpaper.type, wallpaperImage, currentColors = { CurrentColors.value }, + onColorChange = onColorChange + ) + } + } + + @Composable + fun ModalData.UserWallpaperEditorModal(remoteHostId: Long?, userId: Long, close: () -> Unit) { + val themes = remember(chatModel.currentUser.value) { chatModel.currentUser.value?.uiThemes ?: ThemeModeOverrides() } + val globalThemeUsed = remember { stateGetOrPut("globalThemeUsed") { false } } + val initialTheme = remember(CurrentColors.collectAsState().value.base) { + val preferred = themes.preferredMode(!CurrentColors.value.colors.isLight) + globalThemeUsed.value = preferred == null + preferred ?: ThemeManager.defaultActiveTheme(chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) + } + UserWallpaperEditor( + initialTheme, + applyToMode = if (themes.light == themes.dark) null else initialTheme.mode, + globalThemeUsed = globalThemeUsed, + save = { applyToMode, newTheme -> + save(applyToMode, newTheme, themes, userId, remoteHostId) + }) + KeyChangeEffect(chatModel.currentUser.value?.userId, chatModel.remoteHostId) { + close() + } + } + + suspend fun save( + applyToMode: DefaultThemeMode?, + newTheme: ThemeModeOverride?, + themes: ThemeModeOverrides?, + userId: Long, + remoteHostId: Long? + ) { + val unchangedThemes: ThemeModeOverrides = themes ?: ThemeModeOverrides() + val wallpaperFiles = listOf(unchangedThemes.light?.wallpaper?.imageFile, unchangedThemes.dark?.wallpaper?.imageFile) + var changedThemes: ThemeModeOverrides? = unchangedThemes + val changed = newTheme?.copy(wallpaper = newTheme.wallpaper?.withFilledWallpaperPath()) + changedThemes = when (applyToMode) { + null -> changedThemes?.copy(light = changed?.copy(mode = DefaultThemeMode.LIGHT), dark = changed?.copy(mode = DefaultThemeMode.DARK)) + DefaultThemeMode.LIGHT -> changedThemes?.copy(light = changed?.copy(mode = applyToMode)) + DefaultThemeMode.DARK -> changedThemes?.copy(dark = changed?.copy(mode = applyToMode)) + } + changedThemes = if (changedThemes?.light != null || changedThemes?.dark != null) changedThemes else null + + val wallpaperFilesToDelete = wallpaperFiles - changedThemes?.light?.wallpaper?.imageFile - changedThemes?.dark?.wallpaper?.imageFile + wallpaperFilesToDelete.forEach(::removeWallpaperFile) + + val oldThemes = chatModel.currentUser.value?.uiThemes + // Update before save to make it work seamless + chatModel.updateCurrentUserUiThemes(remoteHostId, changedThemes) + updateBackendJob.cancel() + updateBackendJob = withBGApi { + delay(300) + if (!controller.apiSetUserUIThemes(remoteHostId, userId, changedThemes)) { + // If failed to apply for some reason return the old themes + chatModel.updateCurrentUserUiThemes(remoteHostId, oldThemes) } } } @Composable - fun ColorPicker(initialColor: Color, onColorChanged: (Color) -> Unit) { - ClassicColorPicker(modifier = Modifier - .fillMaxWidth() - .height(300.dp), - color = HsvColor.from(color = initialColor), showAlphaBar = true, - onColorChanged = { color: HsvColor -> - onColorChanged(color.toColor()) + fun ThemeDestinationPicker(themeUserDestination: MutableState?>) { + val themeUserDest = remember(themeUserDestination.value?.first) { mutableStateOf(themeUserDestination.value?.first) } + LaunchedEffect(themeUserDestination.value) { + if (themeUserDestination.value == null) { + // Easiest way to hide per-user customization. + // Otherwise, it would be needed to make global variable and to use it everywhere for making a decision to include these overrides into active theme constructing or not + chatModel.currentUser.value = chatModel.currentUser.value?.copy(uiThemes = null) + } else { + chatModel.updateCurrentUserUiThemes(chatModel.remoteHostId(), chatModel.users.firstOrNull { it.user.userId == chatModel.currentUser.value?.userId }?.user?.uiThemes) } - ) + } + DisposableEffect(Unit) { + onDispose { + // Skip when Appearance screen is not hidden yet + if (ModalManager.start.hasModalsOpen()) return@onDispose + // Restore user overrides from stored list of users + chatModel.updateCurrentUserUiThemes(chatModel.remoteHostId(), chatModel.users.firstOrNull { it.user.userId == chatModel.currentUser.value?.userId }?.user?.uiThemes) + themeUserDestination.value = if (chatModel.currentUser.value?.uiThemes == null) null else chatModel.currentUser.value?.userId!! to chatModel.currentUser.value?.uiThemes + } + } + + val values by remember(chatModel.users.toList()) { mutableStateOf( + listOf(null as Long? to generalGetString(MR.strings.theme_destination_all_profiles)) + + + chatModel.users.filter { it.user.activeUser || it.user.viewPwdHash == null }.map { + it.user.userId to it.user.chatViewName + }, + ) + } + if (values.any { it.first == themeUserDestination.value?.first }) { + ExposedDropDownSettingRow( + generalGetString(MR.strings.chat_theme_apply_to_mode), + values, + themeUserDest, + icon = null, + enabled = remember { mutableStateOf(true) }, + onSelected = { userId -> + themeUserDest.value = userId + if (userId != null) { + themeUserDestination.value = userId to chatModel.users.firstOrNull { it.user.userId == userId }?.user?.uiThemes + } else { + themeUserDestination.value = null + } + if (userId != null && userId != chatModel.currentUser.value?.userId) { + withBGApi { + controller.showProgressIfNeeded { + chatModel.controller.changeActiveUser(chatModel.remoteHostId(), userId, null) + } + } + } + } + ) + } else { + themeUserDestination.value = null + } } + @Composable + fun CustomizeThemeColorsSection(currentTheme: ThemeManager.ActiveTheme, editColor: (ThemeColor) -> Unit) { + SectionView(stringResource(MR.strings.theme_colors_section_title)) { + SectionItemViewSpaceBetween({ editColor(ThemeColor.PRIMARY) }) { + val title = generalGetString(MR.strings.color_primary) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = currentTheme.colors.primary) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.PRIMARY_VARIANT) }) { + val title = generalGetString(MR.strings.color_primary_variant) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = currentTheme.colors.primaryVariant) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.PRIMARY_VARIANT2) }) { + val title = generalGetString(MR.strings.color_primary_variant2) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = currentTheme.appColors.primaryVariant2) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.SECONDARY) }) { + val title = generalGetString(MR.strings.color_secondary) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = currentTheme.colors.secondary) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.SECONDARY_VARIANT) }) { + val title = generalGetString(MR.strings.color_secondary_variant) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = currentTheme.colors.secondaryVariant) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.BACKGROUND) }) { + val title = generalGetString(MR.strings.color_background) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = currentTheme.colors.background) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.SURFACE) }) { + val title = generalGetString(MR.strings.color_surface) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = currentTheme.colors.surface) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.TITLE) }) { + val title = generalGetString(MR.strings.color_title) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = currentTheme.appColors.title) + } + } + } + + @Composable + fun ColorEditor( + name: ThemeColor, + initialColor: Color, + theme: DefaultTheme, + wallpaperType: WallpaperType?, + wallpaperImage: ImageBitmap?, + previewBackgroundColor: Color? = MaterialTheme.wallpaper.background, + previewTintColor: Color? = MaterialTheme.wallpaper.tint, + currentColors: () -> ThemeManager.ActiveTheme, + onColorChange: (Color?) -> Unit, + ) { + ColumnWithScrollBar( + Modifier + .fillMaxWidth() + ) { + AppBarTitle(name.text) + + val supportedLiveChange = name in listOf(ThemeColor.SECONDARY, ThemeColor.BACKGROUND, ThemeColor.SURFACE, ThemeColor.RECEIVED_MESSAGE, ThemeColor.SENT_MESSAGE, ThemeColor.SENT_QUOTE, ThemeColor.WALLPAPER_BACKGROUND, ThemeColor.WALLPAPER_TINT) + if (supportedLiveChange) { + SimpleXThemeOverride(currentColors()) { + ChatThemePreview(theme, wallpaperImage, wallpaperType, previewBackgroundColor, previewTintColor) + } + SectionSpacer() + } + + var currentColor by remember { mutableStateOf(initialColor) } + val togglePicker = remember { mutableStateOf(false) } + Box(Modifier.padding(horizontal = DEFAULT_PADDING)) { + if (togglePicker.value) { + ColorPicker(currentColor, showAlphaBar = wallpaperType is WallpaperType.Image || currentColor.alpha < 1f) { + currentColor = it + onColorChange(currentColor) + } + } else { + ColorPicker(currentColor, showAlphaBar = wallpaperType is WallpaperType.Image || currentColor.alpha < 1f) { + currentColor = it + onColorChange(currentColor) + } + } + } + var allowReloadPicker by remember { mutableStateOf(false) } + KeyChangeEffect(wallpaperType) { + allowReloadPicker = true + } + KeyChangeEffect(initialColor) { + if (initialColor != currentColor && allowReloadPicker) { + currentColor = initialColor + togglePicker.value = !togglePicker.value + } + allowReloadPicker = false + } + val clipboard = LocalClipboardManager.current + val hexTrimmed = currentColor.toReadableHex().replaceFirst("#ff", "#") + val savedColor by remember(wallpaperType) { mutableStateOf(initialColor) } + + Row(Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).height(46.dp)) { + Box(Modifier.weight(1f).fillMaxHeight().background(savedColor).clickable { + currentColor = savedColor + onColorChange(currentColor) + togglePicker.value = !togglePicker.value + }) + Box(Modifier.weight(1f).fillMaxHeight().background(currentColor).clickable { + clipboard.shareText(hexTrimmed) + }) + } + if (appPrefs.developerTools.get()) { + Row(Modifier.fillMaxWidth().padding(start = DEFAULT_PADDING_HALF, end = DEFAULT_PADDING), horizontalArrangement = Arrangement.SpaceEvenly, verticalAlignment = Alignment.CenterVertically) { + val textFieldState = remember { mutableStateOf(TextFieldValue(hexTrimmed)) } + KeyChangeEffect(hexTrimmed) { + textFieldState.value = textFieldState.value.copy(hexTrimmed) + } + DefaultBasicTextField( + Modifier.fillMaxWidth(), + textFieldState, + leadingIcon = { + IconButton(onClick = { clipboard.shareText(hexTrimmed) }) { + Icon(painterResource(MR.images.ic_content_copy), generalGetString(MR.strings.copy_verb), Modifier.size(26.dp), tint = MaterialTheme.colors.primary) + } + }, + onValueChange = { value -> + val color = value.text.trim('#', ' ') + if (color.length == 6 || color.length == 8) { + currentColor = if (color.length == 6) ("ff$color").colorFromReadableHex() else color.colorFromReadableHex() + onColorChange(currentColor) + textFieldState.value = value.copy(currentColor.toReadableHex().replaceFirst("#ff", "#")) + togglePicker.value = !togglePicker.value + } else { + textFieldState.value = value + } + } + ) + } + } + SectionItemView({ + allowReloadPicker = true + onColorChange(null) + }) { + Text(generalGetString(MR.strings.reset_single_color), color = colors.primary) + } + SectionSpacer() + } + } + + + @Composable fun LangSelector(state: State, onSelected: (String) -> Unit) { // Should be the same as in app/build.gradle's `android.defaultConfig.resConfigs` @@ -254,7 +876,7 @@ object AppearanceScope { "uk" to "Українська", "zh-CN" to "简体中文" ) - val values by remember(ChatController.appPrefs.appLanguage.state.value) { mutableStateOf(supportedLanguages.map { it.key to it.value }) } + val values by remember(appPrefs.appLanguage.state.value) { mutableStateOf(supportedLanguages.map { it.key to it.value }) } ExposedDropDownSettingRow( generalGetString(MR.strings.settings_section_title_language).lowercase().replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.US) else it.toString() }, values, @@ -266,13 +888,18 @@ object AppearanceScope { } @Composable - private fun ThemeSelector(state: State, onSelected: (String) -> Unit) { - val darkTheme = chat.simplex.common.ui.theme.isSystemInDarkTheme() - val values by remember(ChatController.appPrefs.appLanguage.state.value) { - mutableStateOf(ThemeManager.allThemes(darkTheme).map { it.second.name to it.third }) + private fun ColorModeSelector(state: State, onSelected: (DefaultThemeMode?) -> Unit) { + val values by remember(appPrefs.appLanguage.state.value) { + mutableStateOf( + listOf( + null to generalGetString(MR.strings.color_mode_system), + DefaultThemeMode.LIGHT to generalGetString(MR.strings.color_mode_light), + DefaultThemeMode.DARK to generalGetString(MR.strings.color_mode_dark) + ) + ) } ExposedDropDownSettingRow( - generalGetString(MR.strings.theme), + generalGetString(MR.strings.color_mode), values, state, icon = null, @@ -282,15 +909,16 @@ object AppearanceScope { } @Composable - private fun DarkThemeSelector(state: State, onSelected: (String) -> Unit) { + private fun DarkModeThemeSelector(state: State, onSelected: (String) -> Unit) { val values by remember { val darkThemes = ArrayList>() - darkThemes.add(DefaultTheme.DARK.name to generalGetString(MR.strings.theme_dark)) - darkThemes.add(DefaultTheme.SIMPLEX.name to generalGetString(MR.strings.theme_simplex)) + darkThemes.add(DefaultTheme.DARK.themeName to generalGetString(MR.strings.theme_dark)) + darkThemes.add(DefaultTheme.SIMPLEX.themeName to generalGetString(MR.strings.theme_simplex)) + darkThemes.add(DefaultTheme.BLACK.themeName to generalGetString(MR.strings.theme_black)) mutableStateOf(darkThemes.toList()) } ExposedDropDownSettingRow( - generalGetString(MR.strings.dark_theme), + generalGetString(MR.strings.dark_mode_colors), values, state, icon = null, @@ -303,3 +931,109 @@ object AppearanceScope { //} } +@Composable +fun WallpaperSetupView( + wallpaperType: WallpaperType?, + theme: DefaultTheme, + initialWallpaper: AppWallpaper?, + initialSentColor: Color, + initialSentQuoteColor: Color, + initialReceivedColor: Color, + initialReceivedQuoteColor: Color, + editColor: (ThemeColor) -> Unit, + onTypeChange: (WallpaperType?) -> Unit, +) { + if (wallpaperType is WallpaperType.Image) { + val state = remember(wallpaperType.scaleType, initialWallpaper?.type) { mutableStateOf(wallpaperType.scaleType ?: (initialWallpaper?.type as? WallpaperType.Image)?.scaleType ?: WallpaperScaleType.FILL) } + val values = remember { + WallpaperScaleType.entries.map { it to generalGetString(it.text) } + } + ExposedDropDownSettingRow( + stringResource(MR.strings.wallpaper_scale), + values, + state, + onSelected = { scaleType -> + onTypeChange(wallpaperType.copy(scaleType = scaleType)) + } + ) + } + + if (wallpaperType is WallpaperType.Preset || (wallpaperType is WallpaperType.Image && wallpaperType.scaleType == WallpaperScaleType.REPEAT)) { + val state = remember(wallpaperType, initialWallpaper?.type?.scale) { mutableStateOf(wallpaperType.scale ?: initialWallpaper?.type?.scale ?: 1f) } + Row(Modifier.padding(horizontal = DEFAULT_PADDING), verticalAlignment = Alignment.CenterVertically) { + Text("${state.value}".substring(0, min("${state.value}".length, 4)), Modifier.width(50.dp)) + Slider( + state.value, + valueRange = 0.5f..2f, + onValueChange = { + if (wallpaperType is WallpaperType.Preset) { + onTypeChange(wallpaperType.copy(scale = it)) + } else if (wallpaperType is WallpaperType.Image) { + onTypeChange(wallpaperType.copy(scale = it)) + } + } + ) + } + } + + if (wallpaperType is WallpaperType.Preset || wallpaperType is WallpaperType.Image) { + val wallpaperBackgroundColor = initialWallpaper?.background ?: wallpaperType.defaultBackgroundColor(theme, MaterialTheme.colors.background) + SectionItemViewSpaceBetween({ editColor(ThemeColor.WALLPAPER_BACKGROUND) }) { + val title = generalGetString(MR.strings.color_wallpaper_background) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = wallpaperBackgroundColor) + } + val wallpaperTintColor = initialWallpaper?.tint ?: wallpaperType.defaultTintColor(theme) + SectionItemViewSpaceBetween({ editColor(ThemeColor.WALLPAPER_TINT) }) { + val title = generalGetString(MR.strings.color_wallpaper_tint) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = wallpaperTintColor) + } + SectionSpacer() + } + + SectionItemViewSpaceBetween({ editColor(ThemeColor.SENT_MESSAGE) }) { + val title = generalGetString(MR.strings.color_sent_message) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = initialSentColor) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.SENT_QUOTE) }) { + val title = generalGetString(MR.strings.color_sent_quote) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = initialSentQuoteColor) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.RECEIVED_MESSAGE) }) { + val title = generalGetString(MR.strings.color_received_message) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = initialReceivedColor) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.RECEIVED_QUOTE) }) { + val title = generalGetString(MR.strings.color_received_quote) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = initialReceivedQuoteColor) + } +} + +@Composable +private fun ColorPicker(initialColor: Color, showAlphaBar: Boolean, onColorChanged: (Color) -> Unit) { + ClassicColorPicker(modifier = Modifier + .fillMaxWidth() + .height(300.dp), + color = HsvColor.from(color = initialColor), + showAlphaBar = showAlphaBar, + onColorChanged = { color: HsvColor -> + onColorChanged(color.toColor()) + } + ) +} + +private fun removeUserThemeModeOverrides(themeUserDestination: MutableState?>, perUserTheme: MutableState) { + val dest = themeUserDestination.value ?: return + perUserTheme.value = ThemeModeOverride() + themeUserDestination.value = dest.first to null + val wallpaperFilesToDelete = listOf( + (chatModel.currentUser.value?.uiThemes?.light?.type as? WallpaperType.Image)?.filename, + (chatModel.currentUser.value?.uiThemes?.dark?.type as? WallpaperType.Image)?.filename + ) + wallpaperFilesToDelete.forEach(::removeWallpaperFile) +} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt index 298eb39737..0b5033aca3 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt @@ -144,7 +144,7 @@ fun SettingsLayout( SettingsActionItem(painterResource(MR.images.ic_wifi_tethering), stringResource(MR.strings.network_and_servers), showSettingsModal { NetworkAndServersView() }, disabled = stopped, extraPadding = true) SettingsActionItem(painterResource(MR.images.ic_videocam), stringResource(MR.strings.settings_audio_video_calls), showSettingsModal { CallSettingsView(it, showModal) }, disabled = stopped, extraPadding = true) SettingsActionItem(painterResource(MR.images.ic_lock), stringResource(MR.strings.privacy_and_security), showSettingsModal { PrivacySettingsView(it, showSettingsModal, setPerformLA) }, disabled = stopped, extraPadding = true) - SettingsActionItem(painterResource(MR.images.ic_light_mode), stringResource(MR.strings.appearance_settings), showSettingsModal { AppearanceView(it, showSettingsModal) }, extraPadding = true) + SettingsActionItem(painterResource(MR.images.ic_light_mode), stringResource(MR.strings.appearance_settings), showSettingsModal { AppearanceView(it) }, extraPadding = true) DatabaseItem(encrypted, passphraseSaved, showSettingsModal { DatabaseView(it, showSettingsModal) }, stopped) } SectionDividerSpaced() diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml index 52dd8e6479..0c4c4176a5 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml @@ -847,7 +847,6 @@ افتح ملفات تعريف الدردشة اسحب الوصول حفظ الأرشيف - حفظ اللون كشف سيتم إيقاف استلام الملف. رفض diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml index 9308f5886e..b00f1a9438 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -746,7 +746,7 @@ To protect your IP address, private routing uses your SMP servers to deliver messages. Appearance Customize theme - THEME COLORS + INTERFACE COLORS App version App version: v%s App build: %s @@ -1072,6 +1072,9 @@ APP ICON THEMES Profile images + Chat theme + Profile theme + Chat colors MESSAGES AND FILES PRIVATE MESSAGE ROUTING CALLS @@ -1201,6 +1204,7 @@ Incompatible database version Confirm database upgrades Show console in new window + Show chat list in new window Invalid migration confirmation Upgrade and open chat Downgrade and open chat @@ -1543,23 +1547,30 @@ When you share an incognito profile with somebody, this profile will be used for the groups they invite you to. + System + Light + Dark System Light Dark SimpleX + Black System Theme + Color mode Dark theme - Save color + Dark mode colors Import theme Import theme error Make sure the file has correct YAML syntax. Export theme to have an example of the theme file structure. Export theme Reset colors + Reset color + All chat profiles Accent Additional accent Secondary @@ -1567,8 +1578,36 @@ Background Menus & alerts Title + Additional accent 2 Sent message + Sent reply Received message + Received reply + Wallpaper background + Wallpaper accent + Remove image + + + Cats + Flowers + Hearts + Kids + School + Travel + Good afternoon! + Good morning! + Scale + Repeat + Fill + Fit + Advanced settings + Reset to global theme + Set default theme + Apply to + All color modes + Light mode + Dark mode + You allow diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/bg/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/bg/strings.xml index c087e0d896..ca9070cbd6 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/bg/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/bg/strings.xml @@ -1150,7 +1150,6 @@ Отмени промените Запази Нулирай цветовете - Запази цвета Вторичен Избери За да започнете нов чат diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml index cd642f8828..ccb703337c 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml @@ -55,7 +55,6 @@ Aktualizovat nastavení sítě\? Inkognito Váš náhodný profil - Uložit barvu Obnovit barvu Zbarvení Povolujete diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml index 6f4afec2f3..860759431a 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml @@ -842,7 +842,6 @@ Dunkel Design - Farbe speichern Farben zurücksetzen Akzent diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml index 54512aca34..85fcdceb6f 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml @@ -607,7 +607,6 @@ secreto Abrir SimpleX Chat para aceptar llamada Restablecer valores por defecto - Guardar color Pendiente Notificaciones periódicas Guarda la contraseña de forma segura, NO podrás cambiarla si la pierdes. diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/fi/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/fi/strings.xml index 1434963263..62a01fdd64 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/fi/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/fi/strings.xml @@ -873,7 +873,6 @@ Kiitos käyttäjille – osallistu Weblaten kautta! Profiilin salasana Oletusvärit - Tallenna väri Estä ääniviestien lähettäminen. Lähetetyt viestit poistetaan asetetun ajan kuluttua. Aloita uusi keskustelu diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml index 77f0abbf2d..a9008d4808 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml @@ -783,7 +783,6 @@ Clair Sombre Thème - Enregistrer la couleur Réinitialisation des couleurs Principale Vous autorisez diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/hi/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/hi/strings.xml index 56dfb51e2e..61b9ad8de6 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/hi/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/hi/strings.xml @@ -69,7 +69,6 @@ स्वागत %1$s! शुरुआत भेजना - रंग बचाओ साझा करना अस्वीकार आवश्यक diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml index e3a1f124aa..8bbe0c6e8e 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml @@ -1196,7 +1196,6 @@ Kód beolvasása Port megnyitása a tűzfalon indítás… - Szín mentése Leállítás elküldve SOCKS proxy használata diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_cats@4x.png b/apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_cats@4x.png new file mode 100644 index 0000000000000000000000000000000000000000..9bff3eb3d0c99f89786f8db543f45fe268a04908 GIT binary patch literal 51580 zcmV)ZK&!urP)00Hy}1^@s6%hunD00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPTk^LMWru$Ll}rE8XW_1!en+3<^YxhDuE)IN{&?cj7M?oMaiZ=2o@1kZM`grM zOh^0XSGwheaCv?|^R|C}zJ6~JDlC1*ar&TMScbd)p8e);1ILB}zt{Eqzwy|p;M+@? zG)y-Nzmji!Xdmq|5_RBcU(#ob&p4!Y`%4Z^wTiy+xCoav4Q!8RdWZdd{Z6j6@98!e^s{dRzwNm6jrM143tPAt0VVKU zgkH_cN88P@Ek`hPv_I;z>+4gF%NQ%^r5;6@D?)VKj%-{xra3=tL$gnzcYWS499_)j zE8_#mQ{LkG`FhTu2aYKnb`O;I`j3JREFEA)tiTzV2bGH+J5_)=-Wq`)n3rDYGX5IM z^&h>)vHrg|dqi@yP3D9-w?eq|r-n;kX!k93dbHh4xR;3h97&lQj+kOSGB4zh`M|A0 z?+Up)V#wXl=Q~G6b)qL8yI{Hg;AhGr3|nxf^h*(VT!n7l?j8{e&$JGktIQo2V^oj- zdfmD_`Z->LyPnH({>}C8kCdZC8f#6qR_I5lacPKAAj`AbGZbzkV2@Xp`;fR*j}OQ!}3Ih zW6H;|9j2VDLU>C&`CgX^usPPM5Eb#9FrU?SSiXI$Q1~l#hTVnb-ttsIwU@z}i>KQF z)9W@*OIrKprdIAjnJYq^op4kf`=p;{BjkI+daUJ+wh%;)au!}-JB2R9Fs&8(1Y-Es zibizcu4%n`qKBZ@v9InrW!`I8aGCt z!SR7%<*T1hNp&4D%&tcGhn{^FdUqTbiv}JB%U4V0@t&xZKC&*QJf8BvXxzj_+ z+HtwJVg(T$==nb;|L@rjA%7s}D*iU+k-O{P?>Uz6P$5{O0n$|zXw(195S5X0Oi8ua zb1RlhT!D7D-Dnt=D^pU3R_o$97S@lYXTSBEqlVsv`iofKFtyQbff!TlKd}yhGS-o2 z8-?C5O*sYn3nQMGUnwfwhE4U}J=@{QYi~!{Vklc!z0 zUrDwp&%sl7{@lE9X?^bLuV_wb7@kd(u9Z-;Q8UC)uGw+?6hfeUJ%FA|pSS1IMnw%C zo7yxqXSWMIHV~&N2xT#$CoIF!9Y!q8oI<|72#I|@2Ng1@m$kJ*&&`Q8l%3uZI9Axb z#!z!kRLp8>bkp|!qhrgxFDpE(5l5Vc_S)L?zQ1Ig!_#lDNOC^mxCq0>snr??$3^== ziFyFlY1(hP#*G?9LLr1026jwCh+ckaD^t%KScWie7&w+s&zmctyYi_^rt$=C73$U@ z_ndYR-iBH~al7JDnl{M6+HA^q_N1XMWhUfB4b0H~sr6k+_IdK?3uo_%ClsK6Df)6Lue4xWcnM^!J5m5b355P217JlhX6OzFgbf+>OoAHcA*px#WhDJ-6-s z%xy=1pB(cvaxOjI+TJYPBd}F%M=qYc>(S%7l$4S4{FT0N_MT`zw3I>D{duP6{8QN@ zM5DE~=*$wjruL--j$a^WQPVm4O|IW<7&hPng=e2%raVP#f~X8&+>4s z@OBwM3)NVduJ1uLyba;at*~skRp?#kUJFOw^D-kR{f=}Tr=MxN_2nwx6Fn)%_@YHi zaa^w3p6Sc=|L0iMp1M*5dOtaa{L8>`Q;OUg>N38}sFZ{9_WGo7k9ieY^XWnv)65o;#J;r`=S?(B>3yr5QWu; ziRUcU=a%wBo}kkGL!Ooiy)i73GxvFvCinj5pyS>mM~?f&G5kzzf8co7ECh=Ls*#pE zZavc?QN{FULm3OIFN8c79S}=BOvku#EMYhdA@mDF+m~LSwWDVmfm;QxO7h~txCF|1=|2}Z zSB`SD@adXpN9YrrT|&jex>NAnDsabkq1}e@>s2rATgUhGUR}?3x>6?kSzlWU-AYQB zR=jA(2g;LMZ?Gm7mCNa4!njxcN}f?OMIf$8iDIWQO31IHpwD&43m0PAp>~AZSqK(= z3QT*?$&@iJ6pCDx7FvDPopaEJETNFbLK%+ry#_THLeIYTgEu2&YCD=onVx4W#gSu; zb_qDWMhi`Lc}k(LIdE_AtRu8a zJusn+ao`viB)L}CT&5^=%j^BdG@;X#^62t#*Fb+~EW8-#SNeTX6vx{>Fw~a%`B0zE zO$n7q_Y5&)l&p;--y84@hoyylr(kXG+zdng_d{!+<1()F`G4cSbJ}}g27O@o86Pe5 z-lu5IdFoT@j&A4S9q|oq=?tB*v|bjuVX{3bWzk!Q>%+0G*QCGyQ^)7#MVr7BqOc82 zk5IG~_>jk1k{rXK={d%%S=aNuw8p`rHs)dJ-(QLC=NUEv8}bzOP*|VqwFY7sZYp~! z^jyU%#3hZpcuy=88pE?q-GC#`>oxgi9{CGz`eY%Myj|8TP8}+}aK%ECRRl&*gfo_3J*5QrqVj#%btQWNC`v8}lO|dnxoO<6iHt zZ#)Qj^K0$cTrYkuj?43M$!|8qX{4^_d+9Vp>rWb~t6kaDM(QvH##5Ysusm9$ec7{b zw8hgcqlIzDV(I6benj)32}s(ZkW>+QPPBS{|;;LiXG)GdRUS z$R$^ycPYs+k1-8Rd4_p6a-1iB5tVjm&=I{0$1?U(=$`S2jkcja54}d|IY#&87Lqos z?~yrf-@>QYuO7E&cskv?j`P?v7EW@}wzsiua?}kRZ~62m=JCw!x*vN!FHg5pAL{ek zRymGEHhRLM7Q#xDROrI^Dr|a;34{^?NEl9Sq#@0Qw@O6+{|}}q;gFp7V{#rx6s{_a zOA6Q=g|7SCea6527_lEM{Ej#X>!_AI2GDZ|3v?x zQ1x6aBt3Lap^TL-40|$;Tfu0@x3AAU)Z77T9+riMKTo`_IeaCr%Drusj(O+8wBo?A ze7s}YK>Bd~?N5{q?Tt;PToW@;B>7DL-<0o|(c;J}R(&EbsI{|;nu6Mho9T&Q-tmce*L`U0B9KRPi?E+lQ;Wdisjuf>>1>E4qLFN@X`L%5JQ#b z$-ZP>lZ90K`lE2WD97IDwV2^36Ta7Q+=XG%5cn2o|7jaPLY~qJ#J)ImtoA#-uRcd) zEc&_yfqbQ|#}9t)hT0K}JURA7xEMIPO*NXW!rf9kfhbdQy!@>R zM5U1%@q5Q{i{k>@8LmV9*^|Gtuo;#n`#xOHssDarJZf5lLRUO_^X;|WK2QipJxeh5 z(NMT>AVKdtSE=iM&uxdZ5VLLi*>A+9LS^K9<}vgUc&m8E7H$|qug|wW)AN@a0G>Pn zlBN^JEZH&T+{Q8P@vl9|6EjspvJQ-j{WlgAz+hWS_-_XuoYsdDilRxjm2Kn0Inj8bd5p#ZB z#|TlW_no5)J^mwc=}WVCOOYE!wve}D*r2co$P``}Upz?98?Kv0JpN#Mesu{yQ%4^E z5iv(*E7`Iq!Zva(SC2Hzb4JEcXR0ReJVhuwYijhzwhGHkWlT7i##3&NaTku;sZW7h zFFy_0k0}>nS{1%^_%wXA#vr%*8bXNgIUgE?bD}eI@5>RVsC{PrfmgF3{RnJjz}JA) z-b@`!QMzR0`($Hlh=!As86^E`&e8;to}7Gaw(3eEL4zuA}aB8)6b_A zCrNUx&)461*YVqWj8z+dVBIzidGH)i4YZ`g-aay2$#-gihRv*t|MNn zdEc+e|Bn^umA;moz7&Yjil2IpnWNB4q!DaNmqiiQ;K=iv?*Yf-r$rtu$`aV1SWc)1Pd)h%74Dwfs!OYIPp9hW_S`zo!p~b8N^1GJ>n7|&d%9g0 zX&$rBQ`N!lnMR;obS1D(sM1kyzVA_RT%N%%JQj}IH3v%c?Io#E;Wo-R=D9lJVp%U7 zcMPecpwHpR_mG9K{!1K|kXE>x0=Eu5Cv1L?1oBp5)8mG`q=tE6=?_F9u~c9M##a@b z%2^P%KUTjHcuY(wF0CUFhSO$K&eIU1i)rDi%2o5mE#l}nK0>_byRGH;#;f@w|f+h&u2EO0z6rrK%N)sSkF@u%FW+ZQJt9aY*YW834cVV;L5oPD_zLM#&g>vGC#7hbK6T8*Vcn zNK;sK|5Ai9!pn1p+xNyXUbv|qqAg#059u=@7NPpqzQ8=AW$(h}dqlW84*EY9zI@_X zid{R!sm$+>K)#~ZV}!nR#`n}q^>O!43F4t)JcZ;wE)|oZKsp{qk(Jg#@?o&dtlz-!WrZ z$Jo781}hd0H=%7aOXRv=h;QdIPhF2|D}Gb{HU-sjKeJPWsJz1Uv%b~bv<)2jY|)RW zqWVp*%hsV7dybyiK2ID7N4#)b%UjqFPi*)(g%~HtqjZ&c4o}n-67;O=o!eqKrsTd{ ze^WPAZ1*sCS20H*5NAO+F86CoC!4bVjoY^(>UTW*uFb_-`J=1DBY8zLI zFyA@!Y`7$ANrbqDt_|$1l)DfIVy*>saz9w;{e|^;&+vb_(=jbaIwjf_uHQLSaS*o( z-Mp$#)FV@b{o2$M9VWYmr`F#>RN~LXcRS>uZ9cW1ZGli`VH@p3cd-VFHiT7nrs1mg z@}_!>@7O*O3r)<*v2d5=w}g|E7))Ec63CKysfkiOHD}YdsD;7R+|y1mvo$&N1he~wh_i_ zY-%$YPwoV@Fm+%CV&3pxI$GeqmAXE=A)&F9p+cZ^T9;l!UmL%p+)8>|;@K}<@Q&Ll zPhH+|X&i6oSC8ese`_71|DUVS&C5Mf-|$RZG)CK^uSi#ovtKwlDTsOIKKab%)ZPn$ zw}R&$&}X!^!s#>a?6(8AdBi^N@rYq}B@m0d0&!J1EBexZU$|WzY)bXJ9w$UaVFsGj z2id&!H87(gt>RCgX%0VMzw`O}9V==ZGoU?>@mf!ze|-#XyH`$53Zd3`S4FA*eQ%ay z;DC!e3}6a%?Z|`8OfggmSSay*>+_*J{uj2HPPhh+Sm&edZiTy!+d3et0kYIps_@&J z83bvX%g+Cjd|yBNNSW7$ejqLe^vZ1!S75&3@H5?u>Dcr&h^ZMJf7UJ^c?|5iw()cq z+HJ<)ani=D@!x-Jf8jXjb*u3CPu?nY&tyw{mOpmeX2lFW92`7Y~MK^+J-71 zv_19ttlj4V7bWm7*WZ4={;R+Jy>+a$??3dM=U*w?r)oy7+q>)b_r!Mje*M>E#_!iH zMZcrZSe5WU6P4}v>t^5i-;Uq@$JRASvhVx#H-G)H{ZI1yC9rF@-!?UQ!W%_IknVk-xDF;`_ViEVf)pl z%=1pYIq5mp(O=>Gh2whYwcvRBQkX99Kb;MvibThta8^|BMPF#$bB5fjKzLhms{dL( z>4~~&7@k_9R`t?QkPzqc24cu<*AP=e;8?E$wgNP5)2#)w5JSvE=>EQbb<`aC$;nb0 zx{cYuY2;Rc=OVbe5bBDGPIxQb#@sXM_mT?yI^T5>0HV&9Jj9lOcnf4k0wxo)@=15N$+GbsbT*Db! zJb6rXOgwjd?&yzZo$N#)77VrX=Cvs=VLa461@#zJk*gB7qPMYPEt{h%)Qu1eR;&*}AJ)XIhZ90L+x|1={Z9<`fCqr zMU4>kI!(FTyzCDw3xf-BPH?(1m*be|wRd?Up0kqo2jctd-@g;*^8WAj-|rpYv$@Fc zlfU)2Uw>@>&BaXw|{oeTzQYhZ~3TI9sENEpT#A2*Y#FYcM2FPPSl7nJW$ZJ9(QUMDItpG)%dacib+CSmK;Q zcTU8!@52+~9P1i5r)k_D4c)~(j?+6oc^riCRU9=sch_S=h;REb%jS=f&F1B*lG3on zSYeXm;-#k3t@_Ss#ZFU|d_%VnOVeg5~!IW51N zRvdq1SQ+Z?e5U`cS2mY^jhTBZ+| zJGyiFY9buxq8TUmi#c+p8-}8ejyqE3?NzS=>ke{9EKV!+JC0b$U?F<*d_N3)@0EQY z;tO?!JOgJ4_TJDj?K(d9oO91l?vGTT!AKmE}`k)*&lm-r*8j9T-f6; zKeqoNE)KF3wcylq{}cORA)xT${|8VjMeCINjv>*Q3u|J(@(j^#w zPqx2saV{Yd_Z#s|VnYgAxP8r~us^n9S&H44 z3D70jx&Twq-#iuiePL5QyU_7u<0!2=Nmt4n3tPVDb_PmnkUm-(?_^yZv5!ru_iE?W z9S28mNE@OC&$JKWa($mOkGIPCwny=eSZtQgo3Bm4bO~Dh+wS9;`832%?#-y>$+rgL(0!<0)9 zVm19E7T!+95ucAaB99s|YtOz?M`MmNs^78xCmb9hS|>FswJx*+>jON>_0C0~OQ1ZK zH??hw$L$!-xt<&o;Wn)9*cR=RfoMnwCn@bY({lY>|9$20W+J4DJh1%!g%~mV%t6~z zFZyW8+|W)v#j~uPG}q|4bka2!G6=-fgD?$CSDf4rX(7;_vOtL5Qmv`Ktw}w|4;}k; zEdIn};D|++f%1LTb6{`Xa^^?0MjZF$DOzsaiZblk3>htE0Bnupu|s|LhW4?Vo~Ozq z9S=Gd_UPX=VT+n*?Mk1VZm4{obOD5zYItT{Wh+E){V+1l7EKY3OT&G6itPd0Fucra z*D|c1c-sjZ%I79c;GSO8u~FeTwJ>rk0*~9rgjmcwrc@g4TcO)aQ&iSDwnN)pmHHD0 zU}*Z+Q4sDgpKFC4R=@Cw9#Gdt$j9^Fp zI5--@G6i-|3SFqT%3K&PRNfM+gS)%Pl`ScGujG2^bJtma$L+GYX$W1IjwdR1ix`~L zfv3JV_~r7#{f%=WdVaz@?j__d)IViRxHync?2B;6>w!4#d!ZReo)Dhc2k| z=X=h@C+FCE0GwQ~0-qz|xGy0l#3`yvWLHD}a@aM~mP57T*uR*xrbxjm+;iAnvDNXU zXTM|qyQ_uhnYR`1(kVm2t=BJ{?1ks}Ve5PG(uH!y)jcd-ss_oCW-|o#yI#)&$kK-U ze`!cV|AXwBlRlLXtS1G$x<73|7k#QW~OBc#lO$$*zIF5xD?(XgJ&S5X( z^4<$X|BC0%%J+M)sc7xaua$(M2~8` zTV?WE9#$YPJ?FS6Qk5B|nD*$~!n#XbuZgg|gW`D%J@>aFfk&9D8i-2K?zgnEajZvR z`RiY|LWoOm299Tp7!CI$2rT_{M7CI=vu}knM_j1K3{)M1f#@h~t<=r9IVxMfDD22i z#bh37nMg+*4CX-|>E1nWSGB7V&#h;xZG6NcKMn65!GOxa-WKRM7M|^97DuS-#VF50Z}^A>S4(NwcfI2!cW zHq;u1qj-sq<3(`BINI714f}+a19{chmQvaZ9q-y6Q9FuJY7#3)8U3$65&Y zyRcF(4G&QL*MTY=TQ>5DH3WfrUsb4W`b*Egv8jZ$V8+Ki)tBf!9VL(M*|&<@ir)HA z<+^l+%oK#_xnNb~7HMc$?|N+tpw$>i=Jy=y%HM|jUOcUnhR0LrX+CkzI?%OHF<1F_otO|BY#e z!w*6^Yo z4;XG&v@t!8MVd?W9Ctd8V#Q{Gd6-9S+miLM6;IyW?KR&yUjom%3SIAC6_-ti(suuH z{arP%T(arkpRW7Au}mS?UIZ)D^ENDfMrrg*6>7#??v(8{Hf#uMJ z@;G8U2ewrZ+V?&6(ooI={#58Z!hXtJ3FL>{J;VK0KQB?kA`FjRRi?QSg*BqY4;gM( zrdWRWfbjO7kDNz0v;)tvNF8qlKw!9vUWHmZPuDgZn2vnZaM(H@nS-$2*f0-tk9%H2 zc$PxAw0WQmQ$oK(IQH$MQPB5Qwx+yr#ZH* zXm68~!crXLip-{$;uvB)XzP6{aKISs~^~y9z&>aWy2|ox|Bg*+Bi5Ak5&-Zmx~haBj;kB zdFsH($%k!`KeSL;E%|gu*-+pZR$!?03EEH1m9{CudwEUfFHEDRmyqc7 zFAb5F!UXx6A!?hxmewYyU{+=R+}iZBZ^?0U>JIdN9ChK@&Y+g-_HN{ucH8b%Yt)c8 zp4T*pmXMpz4osI@T{J!C5n?f)KFhz#m=COn%`@Ff!8Vj>z@yOTog4bFJ;x_7-J58r zr-neNOX-+*yauYsf8(|;A$R=iv2)~+3bP!qbW7H3<2jhKV+Eg|*-xS87s4prf%+LJ_F+~xsTPc|)Tx5dD<-Nv7Zpd0VHu@ZwDs-WH zta`eq<`%bttYG7XI7OiJfYWoe6_w}yihcSJ@>ZT|xQ_xsVR}EEV+5>CZtidkYok@O~o$MVh_@)m`tNr5ay2Zo<;yii{aK}}QHY)-!8*m&xjo;gL58{P_8^z%>j=fs3=We(*QIg#r%y>fdq z4fmtC#_;3|Vtcmtz#OA+?c%RFIO>_ori$?B<0epF-HeXUx&6)x3a!xTmFcU)b;;+i z$>&13rD*3cR{L`=IF>8)F5{=mJO3M2EMcJ@s}62gqM9PLW9_()#AO7Vp5F*8v!dPg z+5`G#lT(5fR^(T;TyroFVpb3Y1ws!+4vMou+m2wtJ z;h0~aU=bYMJ~6*t8g2!?=Qi#6nQ?_`dp)Mz*rdM@o^TGQ8V=u1B{y&6?JoDL>a z@w$(7P(b zuDQ#fC|5M+xOkoE^tAS7UWYIZJ!ef(n85ro_l`0Jg`QZ^ZqHZ$)@N#t*}H-7nq0F@ z$B|GDy{6jIBx|4%?9VkY)pxED}g7ry~?dG#K>x2%G9pi6TNf&f0K13ukBtOjUiMQER9UJ+sPv1 zyCUR=#kCV@r?UL#3&R$;p7$f=5#oTb^~7J3{~x-aK)FFZSD7o0VTE40SaD7CK7L{v zTUfJ86iO|jcj0zUt9`aK9Iy8_$Lr3e%Y)e)n}1&mX%1HCc0%m)&~pwwzNFz~&rO(z zaJesA`nEJeT=3|L`2?1Y@3ui8RARsic@I$cn>A>j&rpucv#ev}T!(AzGbKM{C7H79 zJGYR>5@oJ9h9e_g6_hn1%b{n?(<`?r0ii5S>->&+4C$^M0=M${0~HytV-1rQ zgh=vvU)aKqA5yGy>ADWXkyrHcTkAV%F3a-n`oQ~yxr|vt}k?m0&2%Q3Gb2g)e) zuXHa->RCR(9Q7+kHwt6P9_dLzorh296mUutN0i&7-#*q7bWm z8@h{595Dnc%xA19Ls-YcEsfPBOeIi8q3iRug;*T1$g3?V=c0r5Gj$-uRm6TK&a9~A z`V4(0Iz9sRpzZYs^({@>H+>>9Ubs9 zw~m)2`?O6yT(8S&tG-Slws&dHsJIKn=^iq8vpy^jvB|pY zDp#!PziX4$v0e8zl@|{7axJ00s!+##1)}If4@}3rw36O(&OGd;g&S*Q7O^lL3ww1v zOO1r|STPeKb=+K;m2xy242vSAeN+Y9R{3?4 z7m|GDsHe^J+SXQrb7@Bpp6I_;&o;F+W;g`aqn#eo|5qpBJ?qg>Mvfm!p?kLJG;rsTdtyx9r_6VMnzdhwwgezs_Sd?K1VV!9oj_Gv>UB`Ns7bvQ5GHY2zj`hT%#IHmH zU`h^8SSFlmERZv7v5hu?brpcN$t(R)4i$POJffvoZod|^-PFKTnWgRb8_}S31K-;+ zbzuE{t0>RfG?Xih)czhg0BRw&6=jVGu{u<)pP8aGf$u1bd4@|Ev%rmpyv{eZz|X#u z8{rUc7ZWlpf4)RPI`ZcRn-?Fhf4^hiZ(AW*drOVMA!<=jZTiBarf|Ew3E^TW>G$;h zZTy&mv6M&}(NH5y+t8lb6T^nC8Nz#ed3p^sc~m-n%yIJMhne*`l#bdB;i;=YbuL0V z?_6m(z)Ng|_46hrX?wat6hv!udL2xj`3QM}#g5Av3)LT(l3UAtWQm z)ezOVCxyPHhpq_64!v9Lj8G0wx$ymJL@36opZIwHb4MObU#DVq<;WvN1U|gOzZgCJh z@LCUPjKK1O!9ZMq!*Q|nv!-xz|=6DuWuLOxjAZ zH`K4xEy^jZ$CT*k>UeGk*w)h_rjRN($2RY%wgJ^eV12JBwaP7D>xtFI=E>{-3zuuP z4rbH&`Zf!xo0puc41{u3wx772cWcFQM%6l3RiR5sqX&Aej{JrA9n)~! zzKrFS?sIsy5u`%&reBEbyLyraYe_v0;W#raQug-JYmTg? zsNmnz@Tk3=+H&m!)BBXrz2Mebm@&D9gO!UZ^DPXGNqO|Y>p8*iKeoU8*#6&j|99d79=}ZZ?b0~j4#w{t$LV$IeOd==xP+nfy8m+B z_r3L9{mwsf`?jM$bGctVE?m#?>-Bv9bv>Uw%zx^+mOXG>?p?1}ukTkb_uMf58Z9jD ze{BE3x=|c$&;QHx7c=ZlX#Kk-Ixcj))+AKB5H5=5AJ|8ZG(Wa~deOpm+Ks|TpcmgqDswjz52O%xfX>;J#hUz&~It! z`I_W=7QLv!;@7s&d$TaRg~Wwr2r<8%GuOBTrNa4JW5(Sc||&n7}bpI&)FO zdn-@H;%3N=(%L-4GwQhZ( z2BH6E?SZ8E8_Tge>MyuSNyE&6@@V@y_Rk%)3(9ON%aZe@dHCOm&wndQhV-|lVV`S1 zk`c70LiaoW{vKF8%@zpb#d!_W`l`yx#DIAYA%WAX?37q1*?yZ$IHU>mYRD$X`34Bu7%{ zdaZjI!loRK+P~&tk)yzN1ftGTMP|?2F|Sa~l%gZbEh`F6e`ilT{SmrAbh=huJir>s zesm9EbTSPgcI0RBl&+;@QqSAc3|3qx?9UU&_n@?W9oup$^gOKa_h%jp3;k|spbOop z-Z^bA#MwUSxm5l+>S1ggI#$GSD?9_ILa!aQLWipEQ*^)O&@9&<*vIqE!MvxV?N=}CP$>Px+iF11V^x4237dfsdiJM< zA+?2}h7e-xj$nun#uiF1DM2*TPz-g{!jzxP~U(}m}B*h(YB6sDyTOjd7})-g}7 zoyYR*KiE#*A`GuvZ~OPG@SHn7~Q&up8g)u_x?mCQ>}nbUR}go_aLZ1c=4 zwc~j#gvT^w*24O-%4KU))2+5tuVY2@N1y3m)y6uya8eVV{^z2f9VvgR2)A=fOOj6G z+tVA-vGfb&Q6nhub_T~DMNf0^#Pom~AXfQn&r8?_E2w%jx*WNa=?HJ-ZdF;aFibA@)N@S!Bg?&tVOZ*=8wNrSHr2vrlZ`5fmU@RKym+ z+QSHGc+B*ow!Po?{q5r8yOPd7kK(X*&MD zktqxGAhXazvZdiHTM$P7{m3|W>`5I6!-B`Wog>gNtjs?!Z!L0ReBlfW!*3aGY*zR^ zTggv1mu&CJkJgl|FVOR-QK5Y>FnnIe+c*B1foHO8E8}#^d~};Cbq|~hy*%2cL%Q{i zQkR|sbr1*Qdbhe+wW|&?mmC|&bN%%@k7&8piZJ{~k#!|zZ3G_t=BVK}O! zZDLiZfo%zt7oMKsSK^M1-Ot>H>xKCUZZ0y?0 zds3x7m!ElSOnmG)R)`9}7Kb4>8X34Bd1%J}$@Z8I{+qyFYS{{x4m|ciA9bE)tyt7$ z2uJjmK2jGpd&2eXZ9u{?7`pqe4vbVWyM2JBR^WgfH*0GBX3HQu+jX-i3Iu;wlLoa z`NFUvp!>I0s4243@2m0|Q00bxHkBL%(qu z*k8uzwf&ND%$|l}piDb;jYHw~&5e%x#uJscwuhtJSb9%X`1<^XjV?^Lr8j%EpYdGZzyG+jN_n!g;#> zwu~GX*uRa2`pF0O??+bC}bl}WPxKj!lf-X ztxfSnC2hH%z6T)0hpgXwCN4^IQa{4Qg9t>y{egN3lvi-7G)&;wzhecTTjAI@QsRlq zO8>t^RAdMthBalv_X7JFJ}(Ua_S6vVTBHSSbFoP7ocnP^H52U4vetxItD2v+Q*z;r_+U{mp z36DX;W4-vts%ZD5O9^;xy)|JTLJVo9f;}+ZXxMscn2tXUoeo74Y^H#)Ekd^CrR5w{k?xFMFN>a-8*J)2@rBN%-I>RRjL zWGA%4YlpFl%e}mSJ!p6=550x~uc7au@SyfV74&9Y{xPuWc~syH&EIYR_7nxA=l86O z3h8wGja^S*Kcm}o>pfa@b?&u{t#~Kb-!!F`dha=TXh$6@(0PW(p2=M8_g#HJ7&lOC z=7Df>7ntXgYsKnuIyl-PP+|Xhu3Hg!oYe<~I;x{{a<73~0hoH_w#~)X8ps(Zs&Llq zA42~6^`0oObu({y?}&>qzv$DEH3>ZCT$RORT z?&D-3+DSdP@0qs_ZvU^JTS&`sJMbO-D-ONqaTK}=p&FFj7N{36N9eA>*aAFytxGGY z`!ItdWE|^QcR{3(d4A#TS`PNv-rlET74O1y)Tx+r55leYo)ePZtF2Vd{?xOtVOl|( zMMt`L<$M)wRS1`dZ_3o>Fh5`SIigo>p(jWGQh~ZJw7z2lpfAMdxLwgKH6C8LuXUC^ zk29;HhJrZ5F&rMW@ZnlUWgss)R(8;x1+yLT9M&NMQEqf2c{3%LP|D&(Ukby4yl&3g&g%)9Z1J=k%W#ekHGBbqVQ$MtjgO-wO_unNRMC ztCV)}jcp5Ig?>3KZS%Qs_P?^gx?d**qm@2=nV z#3^iPA+AOB^q7X*7pmmauzXAo)ju?BYs72&_>RvV^HP3+Zl~(q%=7Jv1#;JJvWqx0( zp*l?XS}{xdpc?KcY^sVnCx>K~w{2U5RE7Ilyub<#b^A*9fV&rjdY8li)j%r0RD|32 zJoFX)tns^JW5;u!Ga<~=c3ke!qMd!49<#)=m+Nn&sReV$0=KK8HO$9m23ZYI7h5|e zp6-4Yn3ul%K))dnIDi2vTyDH;-n6nso@)z)e1#d<-a}V|>gf4%$J?oU!u@;cisRNB zt`T8d`of`x?z^X&ks1)*t~zJR-7%lkNDuV?_8w#1q8uNIhLlAtregIU(y?!D<@{y{ zZx>Z)6SxnB-Z1SxJllF))*+8b8eZ4I)nzSLZ`l?=h=of}oQ&n_AECzL9xx?mMtUC> z0o@wmHVS2qm@u6&rEOD>vm+^L-Fx1KWE|_f>otrVr~7{yImQuRlC zA-J&tB$O%0;rd&aCfW)sD6%}I_H`LJJ}|y$$-Sc<_>iG$a_ppT8it>fBY!cWBM=xa z=oDglO?9*;k`mgj0Ka@TRJ>s9@f)&Qt^0jj?N2KPNgT;Ws#|Gt-l@jhmLo>$C7F8NeJW9XUrQE^6|vb>e$0G4{Ys5cz6A+ zKwJmCPr$3-$Q7to87izly~jfBM-ld(e#JKTT)BNw+e)9y+Rr4#5$6Ywh0O!~;dSAD zrX$Wl`-`@tWa|)mLSJG!Q#o!@tRe$CKe^I zMH|w&mtBU;6c5-DLxexGZnQx?zp2L6o-B=8vQ z>sU8DZmw9{qv7q+tAUe~y0KcFF&VW9p4&I$Wawq#?>Q9pfsStN_kkHhIh%uEX@UY`n~nF^XIAWawL-n1>Y^&e0dMk54O#WH5yJuwsK2S!f3*C!^G_0FH*K@lG#|PGp7|cc6uC{BM zgAgrK{r{z%S6F{KT6^sT9gvQ)^cibgL>p>nicx-YQUj?nuMP`o3d^u!fpl={V4dm> zPeHHyrwPZKx8$e?wd_t0a=S%bWxeMXUrO!h@75X-jmy?rHcn%OveWBbO z>xQV*m*yYG2u!wrqFPDC|xv^9XMS|T-)8TE{=YK?S;qAq1R|&pPcj|E~)D_+~59Q=7RtP7V z$G4Y2PODG9u#eGXxwgJ#P9Hroqel0dH8v+FrBJz2M0fljwn2rSDqj^ce_|QG|JeSG zi(vhKtWQH+Q`->Y6193Qf8ionf2SU5yPlf(cVfk;)?xh5kL`Q1Uw&-=$fXV66BWN6 z^Xrf8&)4s*-M;TSHodM7*K7Jy&ouR)J1pQYP!@p3U0MTnX!;Rg1=hAOH7eiCGw5@)>9`nCk6u2t=u9qK^K;SPS3{*?n-{E1VU1~0C+i|if1_c_S>1jiaDOvA9C0;C zTL?-24#auNw({UynR>Dvj(NqoA^D!B{&v%WR%jNkf7@zcbE{Dub>zuxAl0VOwS7zE zQYG0=uYX+{=Dh>K7Ib>giK2b~UKF}L+uXGbJlntW_hdSA*9g)6V1}Fa33ZACI~j4F zxGZJE@|P#n;DwrDQkz0I18Rzp7cS38Eq;4#p>-bH%y{|8DKJXoxb&sZ6Tj1NK8qC3 zeH6uMigM1&g7jEhg8MYW>%%kO;B?%s7^nZQ{iB5QHVgC89dXK!FppAR=n~9gs&T52 zDs#QAKI=`0mHer)w&{6&!oU$14r*8YpDe=`1k!fxGRCax{)vks-^DVo9LMpet?Bb! z5>mApLA5y=C($9AipgkG=%r?lEy5GMblc`)%5-lupH*v!Pl(g)UWgUm)-i11f5*IM z5ttqcI2lH`j1zq}FUh8VtD?8(b<&Mc-$GAQ@RVCR`&==vF7%nsNvkR5WT~O14pl=X zvUl!EZ$b<&nDWsZa_mds7$H6(PQ@zey$EM9&PiR&%~9@+kaz7mem!v-V;_NY3Fw+= zSQb@ouY%Z6L3B7U?;_MHvD|^be%7%6!1bIfQwg_G0NX5=mu?mcJiX16wXn+Xqv07= zz{1tubQ0$Y{qrFBdocH*Cs&%UrP7DjpWu(RcN zeX_ahW|4vS+`iA(1g{kqe&j6VIa!Y5m`1kMuymng!%}5BcJ$taIDXu~IhS~aCuMNl z@d}2X{!o!EuW6fwaH7C08#_kG9b!bQgPDSLB( zy08M)tq?ATyBh62+4OJ6<2pY29Dd;eN$05RHq;27^%eU2>+jf{zd-ap4IMChM+)u* zA%-5GI60YzXL%*CMU=LpPmYXv*^YiM-Lu}i9W0lhE^hNj=BBAPE%a1}O}KxweO5~k z{~dMXi4Xe!(y!D5mo=_SE`MjCV^!cfpucljYVUtr$Nckk|F6V~{eR)a(Du+a6mFNt z)pq;~Q3e( z%zK5iEv+iV#XM}f?V1R;Q%X&)gpBX@dGW&hsZuG9xcscuyqLkh1Z`85p$)Of?<4nx z)mfd4V1-mA(7~{z3h`7px7a!X(zD+YUmvKQeMqqjbxct_IUb(dTAVQ)Z*$I$?doKN z7{b;u@gehjdi*av=UY;=D@0{$Q;yd%Y=m3I?zj)k={p%fC|6znnR$!lp9~Yot8vid zY!LT7PvP{`Pv#N0^slFkW4oe$=3)Iry)^U}#?8HUHMngF=)iUnNFgfrDN7;OO5i~Y z;-=s!Q@yFyQ;Cq&$y>}z&k+Pd^wvKP9P^DcwQ({XO973gcvLC2m7k}68PU+M&~?mA zNjnH}I-D9edyO|wT)#p%E|$W12(0L1D)yiq%h-Ba$D=W&x>E&**=d|qu4}xd9LVdb^r{T7c zLYPj&yn+{7*g-fw#vxPzPYE}fQXk5{>i}_Vhs|O*xeo#{8kD}zKsPI*)6brXMY6R& zf4$~DIV$AU5vannqCBA_5ykncCJw0z_{I`B9#?<@u#&zoi_W zdiD#^6Ry>G2}~<+tOadT&jGO&f~MfeFX=aBZejAaC8@tXC0ArvzUVV=2Za8ugTMy8 z{%bjrKwN(IgV4HJyC9cCCV-{ zYHIV$y9gXlscYLh4#-g0rw>P-LjTOI2QHM$^;k$J^|YUf`P@Iq5A(X@d$s4?wqkDn z>xKUQq3?Wy*Z)do>X_mQp{g6Cg}qV8t=4 z&~?9sJ%8@_z2^G;Ii7hNPkg_*Zf5b$2|%eaZux2ph3mgEa1KwMLRO7~LqE(y z==1Z;V&i(w3X|Yq~6jfthR$t9=*mn z4owwk2bps5Dme9qRe@VBdTN-vR?Lg6xzJ<_mMC-^w0-+L<@v4WybWg>cbYrDN`?Ag>qV1ssdA$`@JYY$Nj8$G?%#{ zcg52m_0fH6cZ^qhxH zy-xMeHRN&cMMh?{I35$Tg6AOgucPf)$762j4)g2hXF=TKAjIjg`mfDbf7d!jH%-TQ zVx;jo*=$CP9<%1mj4nL!9xQ!jHA%Hc4u!ZBuM8Y#YgbHF>Rq95NBM#~tHnAbQxw-b z9;0yV(L?W33nf#A`iQX3d~{FuH9NL>>()`wc6ef3;2s^%Z7OhVv$6h-sA$^zRnZIE zVN;3&v5>f=(prOtXn^STJ`Ef@RjHd?aUJ_?T6C##-f+-Voi);s6{_JM>qw5r@mw8` z8G3gtuSV|+4GQbL#b~I~`OwyOVH%>>SK2UF8S>2f>kUjn`-LNVLRRwXg_5&1ieHuhEmI)NShV zhmrIDHn2ZXPPWWhpQR{%<^_0$Jtp0sD*X0~5bm8v481QcDzd1L@7O1-XZgOT-;hvc zZ%Yq9DqTt;uw3~Hx8A-mJazHt2zeppQdqxs)Qvvxu39YZ7dg?Oz-^lfv6@}CuMGDo z^U@v5aV$$aE+#N9l-V%sjio|B$Y1jHo^ZsMLfku!<(8?VUjXT6YYO^?{+zjvk4HxC8Jb_7GymLiJIB0h3k(w|lhPZ?*Bio$ zH4SrP{(AF$mXmhWG`HcoU#okJtp@MjsL}GwGRz|HQmUSHQ#QgyaD49Br~P@$P-!g; zg=~fSA>_|=D;x8cmiDFEX;{BlO=WKF?Pv;c2usJjYkf~;s=ZS~k5T#XiM$$zuInh3 zOCOUJo)vY13gW4GPocjc&cZxDw|?Uhg`uIH?VgpoXWrb-K?*;0xR;A07MJ-qQ0M z4S6A3GazgZcHp)$yuEdW+EW~Lhut0BQ``PRG@1gpZQV6SgjoGv8Z$s^m%G|GUowt! z#G=Ai*6SNXPDL(e zM87JD5XZ3Ho28np@G1=fTiZEeh`p`Y1M3(sA2>$c(v+DoUsyj%C%k=?@|<%_d8U?@ z{f*m2fh>jKXvv%B)}{x4OHSa(M>@WvR^aRPylvsqH6`JZv4^*&mAM6ua!V%)!@1h6 z`_R~w!@%}RT?e*#CxNozXdS-|x4FM3_MJjz-fb;d``c`thW-}@X?q6VE+;EQ#cl?p z!6ZHV8@8FwCdsv|?VWhydf=rZ zFLN0xklY$IZc-U%g?yps9Zc{a&%@KeC*lp*vC^7 z-U{M24VN(>tb=)lCiu5Nh>-wcKZJ4FvIVBhQ*ZY}^0#?Z4KWPgHqwPSE%HP1JxiN7 z%HOMbc(oI#b2UcCGWq717X7vm`ywpwm5b-rDz$u)^c?RvhLyM{p0|ZFLVY;mGZ&)3 zU7~1AnTLU6(p==$n9v>a#2eO8ex^vaHuU8ByGwG2rPw=sT5(FNB;)Tv<{>~rtNKy&CP9i?D^+&@Z3&` zQK4YUed~PUyX$Xv<**&|l&zg}%=;9|OouChCmLCO1eRCFDtjt(rIt2V_ROQ(a}X}$ zG3~1=2TjS_SnX;zq5B0QU%0K$NXNTShK6G(^xBK21It!JoU&NWqOiLuiX4RQe1d)M zd%mZg{xc_Y5TfVzN3z*N@0!ja#P>Dpeto`X`A-$nHg~=+N9>rc(BCE3<3^6va|h}n zFs{@sZ1%)F_EzTFZ{`?jYcW+Imi*nc|LK_X$^O^Y-$Ja1dFHJF((qQPzYrCLqim6> z5;#V>Q~O-aQC#bTj(JQec$^(}AM>o+H1rFyp*)vxoPw{K(dVTKS`DQ3G={P5m3bA? z4a2!(VS32D%UkKf43XLhj4O3vyqK;F$38jpl!p4er6~fj6rNjeS;t-aT-pj9q5*DW zPFnjLZkI0=Ze{QbWuO1g)McFYVa8LEphZ)DLigw8AWLu^vbRl|}V^(Qy=M(b051aoi z)Jw17CJ9T}D6Z~OnTK9!45 zHYfk+%u=*h`ual`s{DUp0*?F#opY?^7=|uZ_m#>GolIwn0q40qFUPo{ru%X%&%m&S z`;J&SEF6PCo&Xl&9OR#S_Um~*a?*!mW+-w7rgYQ(`i|R`yiAz~y8E<#=IDOr`kho( z>i?TpJ|;(}V(UemET?VMO-0B{eR?LQAi{(%dROD_xS$%{xEo#}sO*{PGZv7(Nfl=ayRRTj)o> zr~TlSx2woWa$LK}DlLSvBGgj6a4x$&2TP>{;{-7bIL0wCRid3S$E7z# zoO=U-SP-JWp&iLWQn`87wGl3YwJZ0W=Af;Dy!PBqE)99lT(}Kw+TUY>)N(}j{GaI- zV!BV;*0;VBI4)+abP4%3!mYP%-eBNl4C_~GW4Y(Rt)caqZll6x2IxLjpq}_XZi_s% zuRATW5@HloKP#!wQ)A&IkB{6I9;bakKUZf*pQ|StaCUsovuhZRM0zInft*}`V_t|$ zh@JH-?w@x;E8)8F-YQvzQ(9;L^0&iO2Fy*8fciJ9T`#M`M$LX<0k{(Eq|_3RwC zg~ApZ*Yo8V-nq1+0Vl%<-7|%ZR6ppZdPDV#$~;HDjcjlV@$lq@i&Vjej?eY8DUlZ8@d|Qm+zeUYDSAxc zcu^o7OJ)=c%Xv!9H`Kp!jnbt!q7V;6q3&A8SiW02&S5!pl{prv46XgCqWwn9tq01I zMg#5<^OkjUEJNF>t;|#9+R&|tm;9FLrccb9?)tY5+Z7fyOEhpyJTU~KMvJ2yj{bKV z*G{{-wvUGXBAP({N@$M9Q|OAe^Q=L65Ik=eIa-3_ZN9mWz{K3*OoZ5X?f*lv|0Dg= z%N$XGr|Bp2$Wl~^TloHkn1b?@MYvxtU3gowuw?87-uCZzt^N9$%0M&Lbkk?|amMd@ zV${-pPnbdAHl&<}5ytYRHR6bhJg~0UBit%>;TUM!d>J{WVOXF9V)5fp8+V1=9|hrl zmAVR?wg9ezl%^coQ;Mq8C3&TEfya%q=`DX$B#)2t?HH~0>4r|nF=rb1f!O^YI+s0Fh zer^@)Q)N`3UxpS@%8!hNH(%ISXr{T4njffDW4n=Ka;;3y+i;h8DEFkq<|52rN557A zx6gX0NKKMs`n*F&zGoHKPN7?+`!CnOtyn3Ia0$_{bv@_NabPoQ+TU-uRp@`PZWX_< z&P;)Zb+3DjK)#2r&*Hb%vA>W{?hLV$iKu|ADcA3rRuHuZR*3VQamIq3DAU6_|bJE8SzGAqrPdKYHAd0Z|eg2d0443s04V5S@vxKJU4G z3!7Ewr^>))0m0j7z*@-lw?0!2&;IE(A?CD)BF$|FME{=ReCRU`oD{{Bxu-6K`g5m& zaW7rH6TJr=^rwO@gGF)fL8&W_;lAOyC}2Z~s}IgOpVC%{YZHh@OFCwRsHEFC`fGXG z(Jw2Cd&m0Td5X=(DAgAm)~TY`c2Qa6lTBELr3F3HqlosLe&VDUrp#*%=?XE#SmQOC z=P@>4TB!5QTSq2v5eOx{qenrwwB6RJ3p3DDh1JlVLaj<-2<{r8vae)Bl3&R`ELO7Mkvt$isCM|bh7V>*4Fu7$(f zzpK}0hR0Sl6m5ikB1Csf!|}qu!rO3NO$4IA(QsjEp{LVvP7l2-M>0%npke=LSD<@Z zU0az8aSGa(*0K8e&)hCA+OQwOZL~=L9vbUSa{LmRpzSiIm>t9O`nRUxao5!-j^%rV zmV?#5^*-Knn`_@2RjgC` zqIt_pLf_gxzYOeuB5z**RtTqeUKAZPM{Z23aCX#-Bd(D2eEomN$r>~qCl}}FU*CUi zg!*QU2+>nbXWD#ZSV=o#_4_yK8C#y|vMCUYJB8_J-ycdde50-!6HASp6u@&IjcJ|Y z3}2t9xA`0OqJ7kJ8}f8)J8L7YL9y$o#bZ+(aeaYQQGXy7Z+UL>)B10Xj!9tpTJN5? z?uL5QlK<61rJVHM^ge}?A{^a2H-u>mI(RMu=iHmoZkvU(x9HPL2~1xn!Exy)4bk9o8Q;^knOX>FGYPgFGd7*@ z9`sKYIPNRdVbjIj$Z?iKvbmUn`^R&e!xz>;4Jz|29Q$Bv0R-wtJV}2*H++dfNVe>Ox>-eL1b8~Ur zF4o~GzoJ^(P;%^RfjjChl(hNPTZK4<_#&J4J^O3TLEkGXk1X|}ZLeOdT~O`{z*Qzrn(jQS-)N4!FraZ)`a+u_cX*m2S?O7dXM)W z4c!dOTWF(NzPToZ7>aR3g)nDMrYCx#+JPGS!%()OQ{euvdvmSNg(&2g(q|}n_Vtqe z&cDAWsUn~HcE6MR!0I!em`{5~hB;d55Ckqd#V4D7_RQ`3?zHE0GN~8g_JufI=>9W0R1gh0w_j|asG#4|b84gBMOwJkrrmMUkfMcw%qo1} zI**X&rC4a_o)|My0@2_ZGKkX66o*yW4$-jxdi6(GNpK3nmZGt-F*mZ~=`Jc3E@S^E zP8K8dPf@86?M!1SfWW#QiQ~RJxrV$2CbW;tF^Y1GLW{iY9d;99_`fDYb`Iv5pP|f? zQV6#T*Gw&>YZqR=<6NV?C=JJY<5X^FMpzfiG2H`tFEv=lI@oJyQ=86sWTmbVswH!b zPfo@V;*>SX{LUAm?6iWpts-KMSo}KG5IF?Ga6Y<5^kLMXd;<3oc6Zb>Ez$CIHE?95 zuEO%3(gr7We z*uN4w#VWm3h&qmmcIq0Qt>USpFfK)}#io1-b)#YSQ<;C4ZpS`43Dgt}5LRv7203n9KlW~&fkANu=U z25pxYa&odYp4)|EbhGOCz_tj(I?EPRnuEDfYAuca`qjS!#j8U;0yag3)sg7Ja+A{!@B~gP;+2=h3<*(2k%0NbA8Q&vlZwX>Q(I42Ws=`G-_2-okSNFDVh@E z_H+vmAuk;HLbrgjis6%!lM6!L*tE!2j;t|d-aG51VZVXs81{nNlmCYhZeO35Go>tD z1AL0$4s6?I!tFAqeb;I=5np(FPx^P0oac!;s4abAIF7MulrT-H>oHwLI944zgr~dK z;mn(#oV=wWPfs}FOQ9^^pRRzZ`%RV)Ds$z9{icMeFz@qp&2w{1Lx^*;`@)f)+t=&a zmYZ{K*tYJ#b9gV5xhCvN9)alt-UBZ^nc`kz?xDL9;d`@($%L^Bl zSLvRd+#A9)BU{I>DRNWnmi9~a)95+(Tp-2MA5ynUwI>ZvNvji&5@MLdpxP4CRf`v-3C%Q4;` ze9ti^h)zyUA`NAAgy|<4J8)0y+S4x#9A%V_aQoUu&C8F4*FDi2={j~!R71E}USnR+ z&^5Jl=#KcBO54&fv0nRU-p&YEYAj8q;nMD(TE8jOou}3?^pU(zA#VzdMIWp$HjLM* zbSZAn8EQ9#SW)d;o4anc)rp*}gRoN?(FFTm0@c&6(1mhdqzSNQ!gqxJLLXI*xw(Bq z&t=~8QjgU0_BE`5xIVE(CCp=Ut?vulDysL_YqRi?wd)i6&KA&q;YRlB^#+bZU^t4C z9`{NN*AMk)p}W7l@_4VBv_7N8srF%u=%o>~*N!bc#?}A{oT-X?q+zFZKrBqRSIErM zFVKZ@USvZQUQ-ad3-k1vJ^2W?Iq)TU*{9?jefQ&uH3UP~KG#{8p;H@y5s?e3xL!WECeIj2GyMbec z?G(BxzxTW~K*m-n6mAWnlKJcx@{Fu--Jg17b}bf$7V5%M1u}A+Bi{cInl5RF>nO4t@*SV*hDT;k0t4a>s1!du~}gMF%j zAS}zFE2>PU7+#iN@4A+)6uJqjR4Loki!lZLp0_g*N~MRI)_MEdRfyNE1J!d3fooph z7@qNbUwfr1VZR8^+6b3%V_vu#a$BV&h1f4okNucb6SdmQ;vO<2`V>+w!nokkV|37l zp5yuo$hHo%I^HU@F~dUWR)Tg%^SJp6`M^1BC_Wx}qU`k>t!sP*%RQ&0=JTV76gkF2Q2+y&HlA^s+E&yI1!tzlR> zJKpvc{mztrT`SuE^xn0vIO;^0wrEg|s672fJ*!i$#hkRYungfU|GT^+PZWk*<&GS~ z;k!WIG@Lei4_`Yz7lw@l$8F)$7vfYC>G_UX_bL^|o)!UvE_1F`8CP%~iP#=Ne`?An|O2hG@W8eR){`{@yM^Xi#|5|l#U_H8&PWzgsgf(rjO2?h;l^59$Nb>+VIrzy-##^G859mJ~SN9!wW1+ z|Lld(-ERyPutPIV0&n|JZWVov2=#mAeFToB)Kw;>UhB`ybIy){-rE$JW{#q5zc3Bo z`hKr)(#~!b$mW?ov#w^EjK=xx7-5VMQeu5 z8y)gSw9#^mf-yYZiaocu#;$WLQqX3|!WC}kRu2sv&v-H2T3AHkh?p`s8rom<+Q0F( z?~K(m^a){02^|HC+69hJV4rEmQ)uXp4wfpY6mH+kVKUXRKCZQSq63%fFa~ZF@^jB| z!lmz~j-kyMx>4wTKRPzR*P>zE!V26LJb7XfndPwiEF`n6gmQRp6}w)?nDyy+D_GuT zURREVn{zG;neIVgdU&Z80{e`O5||;?HO5pBg@NyO3E{wT3^NnR28f)V^#6swAIlAAM$fOlMBTo?&0a$mD(Mq@~CC>vz90!q@;`17UpSFgvaxR(|TH z4^b8QP$y|v?_qn!L-EkRKD;T|C&u~8^7{zvCycdkedL(fzzrM|Pj^2H3`fYcf4=sd zt9C3Tdqg8_j9Q~44gCdTX-(9eXOhlPYWLT!e!2yY=^^u6QfGB)ME7q5_US10KuTMk z!ZzU;&#+>*{q6g6L`!T;sW+5S=zDa0p?s8NYjj*3HD#a#;uJi&er6&0z6e>{^Lcmu z{-|fLB98Hu7w=h_D?)vX&j|hAxe>VaI<wu(N=l!G1n6-~8;M+q9XRbZYxk6i`L3sJyYXwcD*b^av;_EG3M7}m06x5BYq zu5K-C+MwRYH*Sky^>Y=*j!QqbSr{gGztZm^ZG|c7FZ4&O?p>K1R@5lefhSM4SRPo9 zx0Ft*w~hG^JO*ZH)xc8Otq7<(TDR|5}5l z;gPkFcd;O9||w(DgT$8Y4Aed96Ja+an@$PnXlb zpOa&(^7&B^^6HP)#!=pR(lMsGCXoO3z^%!hdb}%+=s^ZzMY$?T3%jX+eqtT;K{mt? zpiKDQ6LH<`TJuZqMvgNB>Y2FOQoE{iE`jY8y0Bjwr!}#`79W@x;)J4rWz`?Z&fwjCoELrm0Qf3i%eS9_xv# z^f}70M>VMD`1$h`iy)nBgJ*b&OnV+41t#Tv007>@ne+nDm~V^AE%Q3;F- zVPPBL=7<*HA3d8z6SQ$X(aWtR%z+ zkC3wx*f-p6*RY2|FL~dZ(oW}{dtx!_C!%tnUBmW5UL(CyuW%EFU#_whj(runu-~f~ z_qN{GKnLA3Cu<^%&udm}!4fMxwW&oa6w~QXW9RtH+j;sa=Bd|+h24ei(RSH;EZE%e zEpe1l=(e^)U$JzGXF+|KBTpEAqkeBi@4+mbu|``1$G&T*+r10h;yCtVEPdzz+}kU; zcN+5B*ybxc;+rCEuDaFX=)cc&zf#!7ha32fniaaTha5ITV($o?KIg!;ILbtZY<|0B z9hb?p@ltDeer3Rf9ubh-+uGg|Aj{0Xdc($J&8mJ=zw}-5AEW3BT=FqcG9R^|i z`<@w?H}ZkoDs$mJ5TeoY#5y?ESLlv7)g~u|xCJFvQgXyfTD>=YMoaGPBe9K^kXtl* zl8;rj3w5!_`VCX@Y=4b9hSI2j>IjXjtnDDR$*J`!jbpw6_!eAa#IjNc=kysFnJIM!K& zKs_1@ug{*JxDvuTMvM@rc}y9^Lf(p2ru4_WjI%JVEc$GosS~}nJ!?^NaO|tlJ#SO8 zB^P!-6XpG41I7_U@Ar-nSD+db>^V5f3V%mjvp!H~ zFhsU6SyH67;Uq+9yjJ`fd;u#A`1?+k^g_n01Q zmF82Gt9@@w7HxJ<`Xg(;l%+<5I7RP?=?Kddx)2QuZGT7oc&2qo;nK++@m}4?cXCrf zdL21AP_u+{$;ro`4CARgbrCp5@nc~9>l7|yG##f?Y75dOOvmJydFQE-KXhF=O0qO_ zoLiMyIYrBXjf`9qqP1GoYvP$#I48^#TD9lNhfoW1%3yC}MQ39j-!ZKGr>ti6!nDxc zqmF};yim8obktd>*Jg{bbGjm*DrZ~eESJFBY0rK9+&Xsb8N9H)ajoNjt(03}L)jv% zJI$+hJktv2gz0&>bg}-x@ggFDWgSxQx2wvtiy=kq$Ty~5nO6Ly!fc7r^5_V8!un*K z+(N4*q#<|xy@u&CJ=7@)^*0^kIPx5TlBf~2R+~FEUROZF8;`8ig=uee%k>f+ z^%uP55Lj+uHsmSHKz|XAt)n0eBTP5CYWFT{$5VH>{YXshyK^uP{ay0+7QdT|j>WO` zTS?T|xT^@=qbqeq$Sa)FcJlqFIaI-04uR#J-H}%<>*+6C$`v|I=5M8(3Vj(3+plhR zj|lq}?rk0FRuA8D@TySN)0gW$(?@GZDh$sZ_TN*fUl8K@>7RM4ko&^9j;P3AxF2sN zP{w-Ad9#pbSfGt5USVG7_f+W1I8zp7*wa&1nKm`-z62q@P0tFn({bzRm%(dX%bZI0 z>N%Bq#1ZrBX?tkL3$5c)MeevSbfA||=z;MUbuJ+azc=nUOfpryUiV$mF#=`w}>{_)+o;#1yc}}I? zg({AH?Dh0G&_ z)E*sE=Areu4xG6KXEoCm>a$n6u6eKNQovS=F*T&#F3J?vBdtnqU#Bhjc>1=ZlqA|H7qTtwmmAc)?eIwS%F%hD2>Ds4* zWsZQZnTEFoe~xt{QbO4k1U=K1FP?){C0i=Mylz`}d}=6q?4GUgOgi>CVp?L${;2I6 zr~}V-#+-1RRRBG4u^M3>HAf_hVwJ!T5t4X7^w~ZS>>pbp?}(T}YV#ZGgx$^iTqD|H ziuEJwVxj*)oMm8&WeokE83oqgq~katrWL+kk9%g{RKr>dUE6Q2SLui;j~CW4=!E@N zubYE#X^U6p^^w2>={VtBc;+6_=Q%b2w3Ba@Tiy!2r!H&UqERK0>p7bV-M zchPIioyyhlHpf2H?>upxZL2NVD?-?3{4J$~ks`dE*If!rsT_^KyeN)vpV7!(JZF*I zJt5=?0abjp=hCLq*N?5jx1{pOjcz$^y;0j#VX8urk?((D-PD-lQf1$Djbpzl+=lMW z13v=VuB9vW9kCCtq1c7x2**_DN?=~?*9(ucuEJkgTWFkYM^5#wDti;c_hPv^`jyZJ z%HFGIT);YFZuraf8sxgYCoX)U*Y%nHvA4z&o{o#6X@|={UH4ggdGa}$>~NHKWUL(x z&uyw<%FKWip-hpOo$IIyU74e+9CuP2ryVFKT%$MIS3qT`5OSQ<&X{*@!deH0Dx9CV z4;uPCW(zZxy4NuU`$U{wFeXGi@ zbjP?sX6XLF?Yj#;G7Vw*s%l%$C@76EedRmP9eC-1X%=Xg6=T-WyX2hb9QF%37`4r` zJ=(7e+=GVU>SWKYK)1-u(L+(5@iapzh2GFVe_5D6O=fJ?Nnp7*>A9_&a0AEcK8rGJ zg$n4>dF?*5y*0&P3%pFl5oZK^Vfq--driIeDYC<6SIiCJYa4rxjinZ+wEN+`bPKEI z(p4zcRZvhWRCRRBD%UL#i(vLrka|5sVPzf2ZDn*1VfUPYs?TPQqHQy@oTO)2HNB(X zW3+us`c}j3^Ec1(x#u@6JikVN7A^`kbrvAsSy*ySsu0Z(R~ebBOw9-|MXvukmLbH# z!YPVlycOQ|Sx)$^H1_P? zjqGnLBhRsoGws`B?QQq&S}@4(sSlwnLUamp<;UD;kmo+$MCO>Tp!GR^ z=Ah_9vjL=oLNdRTb`nRoqF8Gl=TQ*4t3~y5?KE508aRf%L*3t{j4bT#I37aY;wyIC z(ny3boP#bA${d#86Mo~Y4u(2T)_bI3VTW*#ERiD9AyTv zF#OE*dOXVr^c!Xk^WSCfm>#k>C9i$w6H(c!a(hX(*JNuee*KOoUwK$R&5>18@r)M* z>OH5cwS8ir5N*SFNL`qphMB4eYsE3$OIMjO*0$B*c`F#Kacz zExpjC=(VQ8NZZ3PpRv$bAkTv=foJ$-6GIAJ8OjY05s03Y3coG-gB6hFh7IlBmkwZI zoij+_1VV(669C0SW&@s7=&)S%L^&`iP87O@??#CgUYMhw-I8^9e zFSu*)TS15^b{jZ)lb`AC@Sg66Un0b~C3?Lo+#NADXT>OKTMUur)Lt`=4{Q_S@eB+5 z_Y4b4>leawgxlAEnu52qjJ0_QwEeB^a}{($Ib}A~h7I!-uHorUo9i-E7xWZ&v4khuP83XDrbfH2+?4&Sr)0Hw-CKB z4ZZ#+q5<|Y;k$jt?Hu%6eQoGiUPbHaSLhA%?_=n?YeN;yPZPf*yj{XJ&Dp=>?Yk@V zGf!0XAE*oM<73ZkN&SoGK4vSKY!jwYLf);8Fm1k_<;mXDFNk!1SAzwPWA!UzxnkjV z>+X#Vc>GDrLWWanYCvsSaZH(g;^ho;nN%}GT|tL87X~C z8GBuL`W1SP$JT{#tU{oMaYfedPiBnk-=2OU{WDS7+ZL!VpE_2=m>#p_+O^GUGi2s4 zH(LBcnO`l*7EPpIV=L<_q4y zvF06nVu7dQ)(f{Nh2wq^V(M>*hBERu=eKIdGrx~(6t8P0S5b6ePbtvQ2b)%%TL|_u z%dAkLzf#+Zo{ofL-w;bq*n2MeJjOa@AV2(SUi4an-3$!9?xB=V7h_f1!t(I<&~FcU z=~hKMSJ-O*NFyYUW%r`zJCfn;xDAQxwb$%Tm!@G{ISJ)v1B|62kAS7t=3=Rs67AVZ zZfU&`^Rw?e_Px?y?3Q~CeZoNZ{lxJY62@!eSudZdopMZY+cVA0=bK^p#5y$0x2zkw zQv;6ml(}J5{Cx=XmAVk?4AMOBT-G$o*1)l>*z3sXILnEQ>2al$uo>2l<1)7}E+w$? zRBW?4x&~uf^*a=5HBVp9^GyB?>v7-c4;?zng)^<%^h2TZjiCdA5umj@Tb^ z5aP77(u$#BSvWWlYet@l;rms?XS}VL?mOm{`Sl2n>5+>zCPP*eQY#=FE9YMVN1PEN zBgg9g($6$-d@sF(gBj@8xka$>o;^I_R*`=q&lAw^HQY`edf#)LonM7ypD-yI#xtR3 zd9t;9kwFUkVfier7bfM2B=iV&DG^MT8;4<&NREO8+zO)|+aV0a)cF`A$UJPBo zP`=Hk;MitNm1Jr7^eD8QvOr$nZ782Y5!RDQTcNU~gj}B^8z&KnUY#lAw6ask_XKqR zm+P^A5DSqk#AoMs1LyFR^UgiDoztQTj`h$77T5+exb&W^AkD%;%|Zf%4(_J-Opa61=Y|5gKO3(q+)yv9N;=yl~fC`U%Pb*@rbKE|43 zCf6CLm4v}lIX(H)IE1qKNxkOxt!vWzEcIZz@NA>d zRVdlCD^C zh)N_?Bzw2NrQ2+*XrDN;QW-$tY3f49R_RcCO5oUrl**!#*Dpjl_>j+VxnUWWl;h0wVC)_RvEKEo5Q-#%6 zVhB_%{}Qk7 zJIm1D{d+FYKNo!tDs<#}4gay=I`rPtx(}}BvhAptBG4;7<$C}5`u~#b|NVLm_V52A-s^AIzf-i&{loSD|B<-lst^shza-m#aqRw(i*On5 zIv%Gg9qn&luHS7~4=bwG=U1XXZ;j_NcK$?pgcwmRIxdA6;*^2o=2o|N;WB@7%K5Z$ znvQ+KdiiCe)O{>P2hXpp(@RcJT8Ih;ox_~NQPq@j+_Sbth<0xs#8Bxus;j=bBXoX zugrTfh9ia)rxs2Poo{GfY(u$%yP<2CiV9X!auz1Eh{arNTHtfCnE))InL z(;WGcL*;W2qVk&CmUFPQ%w9_Uq#Qbq{Dk9eMoEbj+!VB*dya{xTsn9NVTGA1=7HrZ zCr4E5CZP3iRUm;l?dJ=(`L(6qh+2E8XY-MMh46{>3*zh=rl5+<@_ahb9I?H|l$#Ea zpL+H+#0W~deWRR3uI)c$K;_+sPEWqX5F?!T&Vzdyb1BR)PG&+mM-dyro{EBX-Q3 zf)`WfV?}>U@J#p4J<}^ot?0)yY{fNfQ-mUvE4C6Y3S6J5gCl*zjV#uwDUPlea#mRhxn8GsS*Z#Fym6G!B>3ZJOQF}LXeR^zQd(7KiLSTD^ zZU|AaYn#s&div#B6uKiSu^dHiLR0TOurB&rV~V+poN$Wnw+E>MCpTpf*iNCRzc~~& zSOZ5~I###Zi|lGs=7#0eYrC$KX_!~8o3IX+CJe-NMl2%RcTF~}RM;M?uy@SIQpkHE zTy>cvYIyUc+{l+LBv^yzV<96qa-8nhMo)9}YYQl0{r7u&F3&7X_>LaCwL(`M>w4=$ z1TObnt5VnNs#$3^0dkITTghaCp?={?k-3vUo&azD*Urp0TP zzudyJ%|R8zkiu+xJZjPsB`c&9HW}tv+pZ_?*(l?m9L)rnkzpflXc9c#91n<)afJ~iqG^v1RWfv$lH~jTVb77n2(;rA|$10sAs7~p{H7NCH`Q4 zgEYlL?ZPqGs~Y*}sKQa@offCP5@+OC|39*^G*sB8_w@(y{`A2~5YaymKSh zvv~v@@#QwDA>W=Bo3p+~V87{4B~T~fmy!LRSdY==p$qxbBt7%TPi|$pr(fqd>WOq7 z5=VE3@g(!`c0v{KE6b`ityV#ueOWT?{rmm_aV&pHfy0_xLBt~mGy zZ&!|cC9WJ-V~F^u;kvPq=_4R?8;NFgPBEB;OJ8U>b}GX&>@hoT(=~d0*VqjVBShI~ zW8G3$`rS{&IquJKXnj>>Wn^f%F)GiHDF+$sYu$HzEb9GaBXaE zWa)b{&+3_zy-^SD$obO1v9Es#s#N;CyD8BNRmf9PK~Kb-{8#Gq5F3UK8oBO&8aRh1 zDpgB4rrvnTbfFNJjn?gjSc^6E9leg)464J?rO+F;pHppCb>LWdE^T$hFz>yQ<`a*I z)`;6iac$T#Rr$EN5GrMgOSS6rLla_fRtYSvx{r zy-uKC(OT|R$is?bL&rW(y#~6<$sEP!iHcpFv#nC6j<`NRu2Eq!^oY(}mFNR#hl{Pl zua$GQ3U=+Fj^omB%sJ2ZiuS3ar#>1U%Rp?%Q=p#i`N^K?vtgd-|4mQ53SD?RH-896 z%)jfFPD@=X*WVGRzdm!jB)H2wht)L&PKx2^o@;K6os<6b8LiIjr=FZ+v8*#RJi;H!_~C4qXJHa-9K^vsNDI^MfQy0xQsb%m*20O z=i+ToX{+YP_OAoq3D^C9qFz*S+WH|4mp=cU>Bx0^N1U!U#&<4l|2_HtDOi5pb9wH+ za#9@6@QQG{-=-euW~+*&)|**=7T(e0wbME7uWHxY!f{d)_mD&P++UHU8uV?C*uu0z z9(vp#+{z%!)qco4kK^_QE?r)F!*L=co*06EqJBJ4HwY)IqK!P(DO52#Zs!>4mQH~X z?i+2REeZxtreit6BhwdJJ~E!$H=kJr^qf4d$)G?C0h^NVQ_{+3Zr6afaqL>hy>P5P zB*a=COFz`)K&3TPW_+D&fHu4i4jpvDNf#yrzH(9{8WB2rL7C@%JoMDS*MF_hwsf(r z)#%v5Fs9h-cVFmUJf$n5qo4i6@epnm``&UqHQdtYu@yp`Zy(5y;@lm9{pT_6fj)2x z#p#wVX(&Wxt^T_+(8@H6?3){7&8FiM*X&3xiB-{u{C4UOJA|&&*+aNId($b*%=p<2J+>9PCL$ z%<<`qky%qg`P4iRsY*M~t!tCZHa=3H$#?v>yI){r_L7m(&7M z>qjU4Kf2e~MxUd$iyA!Y9dD%w^tt@XTg%csiuaW1Teir=cOD0A!&)kvh5PXmRS0We z`WNcLap~Xxm3(G7;s4>J7E*om`}N;HPx!8_fAHb@_pe+Q4ElBCdvg8m-*a6k?wPmw zhxUBQKwWuhAuh|hRW4+2gt!*5ZtAJ!TIlvnw?OEx)J^l~KH0PrJMy2U5U2g<_L*Zc z$3u72;YAATSAlPZQ18;7`mEdi+j0DY%6mfPvK6{b=|e(%L5#^oo2k@?<6?ZK#hVrl z7>&ff=eD%JhA@x*zFxfNF%Y^RURvxi_Dmexg}Sw~g^tfv0k;cO+G{Q6OkHur&aeO9 zT>n0zVK=GZ<%&&N+#AR7i~5WjL+y&EyN?7OXAS+D5u$8XnKflBJaIc+ZtS~0`K{ls zzxRO!j6hN$G* z{p=HO@58E+kJcv~^Sms*_ZRlZaUavBtWOE`(dTvP^RF?Q@JN_!RtLl}4bx*T<5*9W zhtI6!lm%k3m9ReVuD|t-ItN~9gxjcyj2v%sD~GT-oonI?{)Q@QYXb{A{>EFw6q{R&q9cE{nqSU zdLt^t8XhBGZkFGa3P;OL4?Tw$*7xkRF9>C^5OZJ3Kv=d2h$GIDuyEFzIeB6JdI_Fs zF9}%_$MIK*YpC}gROW?_&udA!JR(9IyN-DThR43ja+N<8ju-Oz>#=G6(sGkuuRrWE zP7)Y?XYUe(%gqPwA63SwS3cE9>RRhLWo?D-SuX;hec)@)K4HE>|40mFSz(@MU8UYI zub5LPI~F{#j$zK&bsXD6w^YpjbaGRBJL9 z&v1xJn5WQ%{wRoJoxG}rOC8e?;u5+gcp}b`wJO`G28N|Nj!IvCx)yXi*}_oiv(f85 zT6*c|nBm`04jn&fJzB0;?znaQ(&9K7`OUwT)!Ppbd5wW`;XvWOmATDXvb8|j92tz^stAbf@$tv<(6XsLf-n|7Q$OfU;bzgHu*l?_81VU z5>NBBHVsW!#!z0zvu@#7!+xPlVY>1a#s&Hs?d8Z*B-U5Vkam>&{Vt>XXXb^^`@+KZ zTcxkR6t#QjilxwO@g$|;oUXPd=9vf9#p=Xf>DEo=&CjW*A4CWKkWv?xFTtwk4opWI zLPHPgg|_nwecLx;y?}nVRB@lJ{NuTOyN@Yxn`bSQOI7H-bSWTV{du z^xR*r=lR6#>SneD;%iL%3<(Qqy4F23lvA`;_mH-`W4J=R1lpd@?8^(&l*ZVUF*Od> zFo1Ftr_ERhlubM7c>OxCU)yhLO2!I>(mrQ~gBeVYb^G5`j^Ld;V$?~Wiwbpperp=# zClO(|5O<5;|HyU`g1=e0T^2ZS40Q{X)`H-r^Q6&&3o{$u>$!BOxVfCYIuu<^^iI z|J1WjCZ205_I&#A-1dv#SYDjhFg~_~dCJc6?~dGkla@;zgr>#eZ<<};5U%0+tC z4Q)Dxy>8E~F}yTdAmqz3p%*8Wq5LgkXMsz}J`$G5I7%ipqN9+GT_WVYPNW&5u zj+cYBdW68q7FejgCSI5r-7-&6n9h)5nyLVYl!K>izPXP;zc(ZF*A4XH>3$f(aTR*t zR-pex9ZU(Q4y9N0c?H(R(chn+xK-d*cs7?;*6U|x2-xhBvATpQ27XB_*T1&>D2*C@ zM>9f>il@#jx{`ZN$FL<5C{rLbgjvLW*D*B& z;^-cbW506*9Cgi!osz;B8n|029;@5XYgUEmufN+?^ul<3M<0%Q6vCVcS1Gi8YZTT) zm|PZ4wqS}wur-0VeL;1I8hqNX%?Y`2Hs{VCZ|D~6=Dkl5M0#OQJ^Qu_Q=1|3)N>8m zu(<^)LcdYtIIfqjsPd`F^PwkXCXzYSjS!lp8x$ zU89@#)TPvIuzetpp^)d13*+?Kg?i9-&QV@M|5QR)p0i$qhI##DsPApfRt9+&xqZVt z`PXDi>jP|xtgs$7Whrp775bcOiZ=G4eZv!{X!jz_pXcc4SG02nu;=ak@2!h!!u5AG ztnsd6-wS!@v3)D4={b(jk=j_Kq9*iNg^c4I!wTKAEN8t2Lq>BSLVfqqm!4ab65g(P z?tv(m)W8zT;@MA`ZykXU>cDY_(Gc~{=jPDO@@^ML*+80;`!gJuPX2*?LUo>Ksed8n zId#zGhTRp5I(#CoQfHx7;dnUeGDL*@0zJpDqI1+2eiNpTB~wB*vB!LLi?)@-5ksJ* z%w9ZVA`S^b*!|y+~f8o+VAAf9r`LX?9 zPVN;I0^g|vPh3}DJ9zVB`w#lB&y3F@{)hS&A^DZdIMXo}I4<9RZ2!bIn6mocfn&5k z2(eJ>A6xtXAD4cmeM05h@08>Ddd|T1I4<|{m)7UM{@DJ^<=Xzlay*x@)b-5&i%SlF zuV|PWdcRU1s?hb?z7sul;ntYfeSg0Gs}4%ZetGgh2z5>CGVfgRjC(v^85f|IldsJi z4wMVKs~}ynO5|J`w)4uyJTUW8ZK|5KN81y6Ax@e7n6tM|?q#(A^%IpC3!TZap2@s5O7C zGVN66C!67@W6GM4KleOE2TP8kPAhV2qD0=&bF0uxMOQn}fp!cN$drYVsYTW!Za=z3^=o3tV?G$<` zW2Gc}=Z({AsG)D`INL*sHPmIW3kAIM|BsWCY1AMDtUC2O(=g@rJ>%G4iLVE(jsN75 ztDgES(tPpnTs)({bQ~ww^QV71ZmXUhw@T^v>;C_|ZhaNf`kkSw^HSJ-)>Oc$s1fxm z`_2;4w)vepDxXGREq|=qYa}grHCdbM3ygF6u9dY$A^&Y-l|Nr^=``?rAeP?_M zk_ytVtdA*(9HE^?EB=wU%H=zk_R{wFm1X?vkL|zN7oppb+XK6ft;d-@KO=+j6RotW;((&V?>{|qs~06&b8Mn zV!gIpPfNXK9SdpXp-X}NdfmFJoGm=6ZPR5`39*gk`tSE-zy5Abf>af`8Yg;hf4Oct z)~!wTb8RCvRD?^rESaC}xIDW(5$f?ywVl7Sy+Rk}IR$GVT<$-xkb6?-R*<2a4nUhu zVSI0G7WUITsda8u_WzKaPtT)@&sch$#J=VGgNFA;M)X|MocDiTf4j@D)i8bA_|fBkPOiZOcrASA za*a8Lk+3ZH?XLgs?G#LjRBeH_#~cHF2{pBW8P|&=H%C|Kj!Ov35eLh6F2YI&s48t! zz9ldtLI2ebXjZ$0Fn{5q1io{!CMJAs&gQRN+Fp&T@4Rh);WB{#nQ7kPUx?mpjgcAk z^wf*iKKJX$v5s!z_R&P=dLk0W?_9@ts>u)#2Dqp>}Pu%C?0BXbp>cJCV zMf=CdrpHXFB7JxL&d=0~_Wd;rzx3YIHtcH)6-xFD^m#mUy9%AK?dyVt`W6QY)KOWj z*WjrK$F^1X@2{o+U-x^Ni~Hb6D(s-ebT*_ZFc^>h^#Y#KFC!KcFZS1u21 zQT1X)s1+%!iw-z_&N*$?TsOt?!_qqDJM+9N^G3H02Tmanr?Caf)An9p2aeMk6@3Pd zw`-!SA*EyFJKORP)Pqn5LVY23Wve{;9**A_HC5cNiV&AuRADk_y3SrWZm)fccUUVL zjd*4qgxFrHq-uE1f%+DpXyaIK8A~gK8(J)83}IXE+^ES5)0z)!!zcD-@7I=gp?z$t zNLY;?`dTuz8Z5Ma56V!ueXZ=#@1=BzSD&>BJPkcL>cO%9LLfP4H0YIe5aKkoIczDc zQ-)FmTVk~yj<_W1UP|4RnNSxE+bXqM`i9a_$8y@Mpt~{iL&9$FxrCe<+{~h~zLf_dR$E7XOdXUiicgyi_)3t2I zj{g1kjMp0IcWmtc+H;H$>sajXE^Mms@5#3HGRyj#|41GD%4MuL#%lI5YtzVb#d(f zwmOR>?RgD~r@w+Zuw7Keyt;HYh@}AS4QWH$YwNqIk@l4A`)%Sm)A|hk?larS!iKt* z1-3RB!}0dIZHCE~DT_fqa=9SAP~ou~3|K*vP~ zEOi!gP#IQJv8!;op0QM{rPkVQ9jGLgqG4CPkcQ(_udjg)5`CcWsUNfU=U^Q&3>;$y z-WR(2gbn_!I9eWEMvl|{Ux~FGA6Pc_-1R(G^RnkSw)BEUzJ6g}Ji}u}hFRky@ zV30S&XxGo|pDJ;TE7HI=mFL)`D{u@?T{~8wEM{efp8dk5{TsGd9u0N9Ke>;FJj28D z_I}zq)^@J-HTnCQ`c^}<3T{(2j%^g>5T-cZXB@M(!D!>_BlFPfR3otI_y==pd3f%@??H-R>jOii_!Z!04twRg-;wW2GA`DMcG@ zbv8cnR^A2HcWi7-*V>^jHVNji@63>z)xNjmDo>IYow^COHSWs4B78GC_P$R;D-aYRGTu1&91ot?B+ z!EswKmwWCP`kj}+x{gg>pE(l3&PCPDoo_g+!Ir8st0=ALCaoUPD@+?Nhe z0Z~%9XlMRJcRtdDkx(ZV249LW+$Z!m0{c_Tb&R0`>PyCP)|XR(Y67?qN1a}cr@Jq1 z;rW)Ll<}d;vt1AIjcy0Qap^1R@s`@^D|9qZ{2R9(dK-T|&o^%8np+>U)Z!4rx~oXm zV(?A*eMdBi^j~2o^x-{IH)=f&g?1g~Udw2f>~F*c8QQi)CM=U}vA-77AYizBlbZasAtmsIF=L$g!GtDJc<|%28E2Y+4y0Gp*aMWeY97&-&^3pY3mcITyLU}r(>M;M;VY1h&9TQzyAhS0q@$!G2peRhFkA;e1IKrBZ3 z%J{v=^_Z{MO%;u&-t>=-znXHyb7)vc@z#{ON->3=KxZxWoqH?Kp7md0<`VHzcOst2>pgdjlxQJtI!?CpWE4oJ_FBjkz~6^%xF0>4dtV8 za~zhfaO68HIY#Ib0{gCY(S;CKfisVNR~+>U_|nR}jS%OA>L6_x?<{?ls5ORr9o@pm zjF(zHxjEd!A{6&d;272HLo}54(AAl$H9|V2z*6PP(saZS=A{Sf!)8RO4AM3bcES?; zwIS5`@cP0^eFbxS;^-b=Rw;c?p?C9gYOVu$bR2ch2+3g$!@Wjlz?hN>2&`X>8Q6bb zy5-8d@WjPrp4dULTll#qgnIL#ePN{rwZjLIUR^KO+U-!e~5EI|M|!E7fx!&W|ugQhvPENOZGDzcmK_OpyTj&*5zNh zDE04bPwJ6>C+`}XAKO3u*#68lRjUI)Ex5IEgK9af9VW@eQ~zAmzOa&`zL4+O^a;He zz2(6PS!Tf2Z;h~aT_bc&~bZPL214mnn*=d(X84va8rAcyAuj@Pjek{0LR2WF@4;x;W>%6XKT@pEEietCoF4MTG=~*}Zh{S} zF>E!pIe3P>J#GB90RF(SgmPg25TbCo2JJ+C_hAC3A$H6swimv79aHmup6=+w zNquO4-7=!0eMvHpRYP{I<%DhR{WY+cmvoFFuhG%{kiK0vX?^~V`UG|96{O~n zlOuD)Ld&6J`u4wP`+~VZd{droD*R>SJ0{4MTH9Nq&rkc2YD-L zi1h(E7I5G=)1w@>UYq`FN_{HAZOUQExwb-ht7xa9{Wixa5Mm#)A}CV=j&%(mVf{YY zaO+&G;icO-e`0$YhMkvOeYOVHuXZJnmq%aHF)Zw^2(jw#k7Vmph>rNK=ugxqpgnaI z#Cf_Eog*4XIf~GtHhURO+7B9HAL)vG1ja+^)?fEdh2+o`3KlNUYii`D;cbzUP=8gq zkZ-JY;mB8(7A_uA3~SJ^zG0>J)Rv`z@?LsiA0yGmb)WHPbptuZT^nJ35uvA&;%-O& zK=91-Muq+yyzU$GE|(HmZ{Y4}5w;1$DsSD)Xqp;Ev_X**-Y$V~JHc+o?P-(3Gy?gx6GE&A-vVL%StCMse_zW>Upv~+hsh`D z*>7^B%eWaLl|NJZg|K5GTo*6oTU&bERLjmqc|PgDJ9SP#-*oUsaTqMZI?H0)Ri*M(U;If8FaWvVKKwDHX-(0?sIKGjGt3o+gL8nqeNC)ewklMiaB z?>*?H@x=8C{utO^lg$joZ`>}Y*!3MV6olyn@)pn$>cufU_Dm5whOy&@1X18vvqx01 zr|Ba7|G=eBez^YYd21Y6bSg*4T3=n8wY_s?$gy#hH(r)hlrKe}e_u38F&!gBIW*S( zdOuUsbi%$V%1)+Q@0Npl$~e{<-i;g=m~QQT;jNPBQp{$A=>8YtGKnwDUtU+(FXXfr z+KyJ~ZUQwBUs|KvOKY>w^*HnJ-&01ZIED?XBPetgB4b5}fpMkd88^ypoO_OiUbps} zz(r}9u-46H26RQE^!Tw5ykq@7;@L*=jTtbye@-N{4|A%7eHhYNj$8TciAJGN4(p56 z5y;O!DY;7BDwFkCvmm>yDpR_`G#pW(j9Ez^h>F~VfMXsF$C?&(k654S!%=_8Jtw4Y zg7f{rF=jlK_`Q3gA@98gKeHZcbgb>c3FC^Tq5KRMZQC{5Zit5dd+sWV6{0RGam}8} z9R>@R=3>e^$Lew1dc`(f#Jo4p#W;8+PG?KE57g6e!sB`8wK62cJmvF-rLl-n&T*k< zpU@wjYU4OYT|p^wQV|X7rOvjB5;?|Yx60|#3jP0Y?_8`S#knoKLvRQu1c#surZTWH z@MK_R(9XbQFn2dKWN=WA|p?$Yj+vR+BtS>X| zM^wLPUwDU4$;6E06igX5i$QtGzQBjSO03XV+=tQnIalW0`(fO<;qfs`g;|HjALJ7e z6HrI+M)m$}WWV-Rffq)0V$<#A5=cNB0eW&z}W6qxsjpu$MuNI&~y#e}xq1EXyFH-U>2-0iP$CTxs z=so?wexdJ_$NGq9JBOkYekl%jh3SAr{m>WymWeLQwZuP zbbZcyMTjhh^YR7taM*6F8N?Mbc@G>n_SQpKR^E zU-&&bjtX2N-^D_rseK*%GLtcAiKRNx90cJ)M1yiKQ;*d)(YD#c`>Ty0yi{ucm=?qB zg7wGKT{miV}Hh;PnK(cI`{5 z69iX<-lF3WM6itzVl}V9aN&~img~url<;RxCZwzd^@<+^>70DYcQcB>j@Nn)xfDiS zE{WrqzGw}4<}G=}7W0dOj)ZzqA;D{~eo>skLGr6BV6pvpqo=Lg`|Td|U-o5n7S|kS z0$+F4cR-n=KNN!e<@5GJAD$|EgW+os^}ffJ93upT*47yPOn-B&kV=R2KyXM427#~K zzl^T`h2vw8A0if{7h&0hA85lf4jW$8N{cB9)b9nss zJP?C@6#B^u82ACz!hq+!a5|c9^wc#3!@5YbzxnglFh0YwgL-{lPK${_Li{lwp zMBsCVZ`coqdv90!JlB!XXD<`y84TaLHHDzg)FX#ep`RQO3!lT#!J|TXtNdlk@-D$* zo%MZF%w5ESQ3kpF%_)1aoU+Anl!-pa)H(oDP_VbC%$1hwPI7U`n+;NnSn9}PI6aFg z8h)n#F9_42&KPlc9)&(vrkym5;2O4~a@Rqkf>ss0!Ez-jw`*AVSFMJoq?KTB9rO&b zuUQ#61tS`z2!?`7|NSR%j=?c3XKjCnax8qEL+$4_2TcQM`?q*+rEpQEwX277Fi0y5 zJw|1XgJ0hwc07q_>qoL+a!K5e#2d+As6}#{Ijpr#5<|-?*Qj z&SRDoKpAX5UB_a%CuwkRIE8Y}2JI{KA1G7iTv&+x$e>+1JXT?pAf4u^g&GoTD-1?< zY7kqj>(kE>0RnJC1>WHLB}vRM4Nj&p5Y`llZ3uh+eD2 zGBxlopZR_Jf5CRF9ex!I=Mj&UyP$0k(IP)up?%;3erk$A`>5hu^Le*`U>~KuBXSYZFHSH8O)a%+`o`O zKXVu^2EaW3)=JKzuEkEzm4!n3U0nW9&?Zw;?fS6do!&#v424#pKsOWn^fN}O1jj?L zu5vB?-X-nE!q?mi`6cMRmMYmfidiX5Tj{vc{;6XsXKjaXq?NkCMs*47Ao zg|aI3mfA!IeaI6L9CPk=AA{-o1uFXfw&c0|8eL1U9R~ZY%I7ewsTrr{xRRH}FwN$$ z9R}sEsWmgsQ3QE8Y{C3?kc@LXJWqB1$rB>jf9jH8zhb5k4q@T5WkFFb45k%2bHP-= zONHOqIG7WzT>=YV_dwwDykoQFdZ=7AdA*ZzI+XPVJ=Wd+Uxj#St;09=H6~-;+sPF{S@@lycR?BB z)LQQBkDdUc7%s>o@T*gj2#vuoI-!3v zMNyJQIXMveVAt|`4g8BF{$RL9{Zh+N;DxWjNlnzl(&u)`IM%>>0ZR-+6|NTElMrmf znaU|cjkcU(LKeDxp^UMY&NUNK2!`*-;Izb;L1FROtHcSW$C5>vadvV5w4-ynm0&q6 zY|;ULf%neUdbaSdOfAi=z4p%K=5SIQ3hq?6Q?a-T?zM8>f^F$=uIF8Xg;xkBa-87W zhf2Lc2d~6y8eIK!(W4TIKnVP+W>0VZ;8?8t7AGBaIYk!^Ws8@vD2CV8?@>?i6u#Tg zAz!H<8H=;hc@7SKW`YSE!!cZPQhrL%2mMwqMeCeB{zfP z{8;9$&26*rOKmb7UL$9oi+b<5c{Q$L*2m#2jN20C+}85GTjbGmsWlOJPfz=b%9*hN z$k`7iN}a`O`fR9l*6M?-#NSH>Zb?pEi{QaR@Y-ou-p~BYuiM`&?qG*irD)Iw0w3pPcajC z0sjx$CdZQ*!@@7^w-@+Vqb@Oi9s$Zq?L(Xe(RVh!GOod?R;Kq^hh=@AecIu95R?^} zI`j;$DVN=#T>-2&J*R^Re10*f5_l=}0;t4Q_!t~}stv<%|K9$ef?o$af9uq9nIm|Q zjKTeYWC$`>v6dp3_G0vNdh030PETkr!?zTR@`~pU)2pHh&MM+5n9kI8iFxXRa3P#S zI&VM5z#A2{4dK>cdchQ&qsRW$+3dvqut*0#s9oR!7QVqL1ZoK@@{Z*p9Jj(XV)PZc zwn<6;c~1m+OMf~Hm;BUcqE@-~q0qpi<$jd5Sc)ppDTA0wy++^b5PzA)cW>jA#QyUT zq{Es9Z7F*SzLGu_QaXyj_vL5krzOys*RgCy`}A+73PT9I1E9xpW{rWbAF}X~OgajJ z=YkQ5Ipgew|LNd8FM$uYF~`(L;1#)ppXTIHH>@aF&sytHCjvo(qr?*3lYTCdd9NBq z8T%2#cmLhK=TU{GK7SY3rvhtjg&~N0|J~?2FTKz7Jl1l2BFx+E*w`^!Q(738b38-x zHRQw55qMp}LS6PD7Q^LSg9h&(+^>B>C*j!)D#6MT35VeuoMMwEs+})goUkfEeed7_LeQWWBLpfqh>HuT-R;g{|5HB3- z5Dza~loy_DNr!oh7FqbIu2aw81*ew*MhCh0eo_zZUktHZR7P+wcrVBs*fwz72hxJv zVLEiEpZya#k6!<4k6_-im#OPc z!CbAwGE&~YL%dinmL34wU!=xie!iPk{XYWxf8xxgpRA8y2ggP*48c0&O+D&x@A>9> z_k#P-dP+b_#jv>qWQ-i+rqy+ZF$UKBSKeK;8+I7Ts%_M2GUfP=yJ z;%Sf6*qIu83_}arz+$;VryQB;4>4ou3*a8)Vtkckqa8gb3I?q zOwqia^gd$^Oz8e&3Y}wSichpN7A%%4bRgUo`uRUNIq?YM^25R_*)P;n<_Zmn|5xa1 zkP5F_#PeJ%Fp$ybF`=RuP9osfqvI799y(`f%Uk^O?}7-D3v78j(K-Y$YlS1l0<9Agl- zXhOLKo)^NROfVbF3z=H9UEsAhg7^x8tzpofLZ_GRunYqqiAvESth7_LD+X=UNmzIz z=7M=xOpkAabZX}0Ir+o`r(Z4n3T;!0ox;il&JX3~4B~?Kf^7uz>79q6w{{d|t{AkZ z&=rn@t=iFG+5;8jDeDgV&(qd6W3(Vtkd%T2j#Jk@r>zZ<-uBEGJVDxJCsVsH-X5UP0kYZV*?gEkeq!d&=PIQaa%dZO>hj}!>@4@o=t;#SrY zd?Vkh{zAC_h7|pyBk*rN`JW2~<`%c&EYy&NJ{Y zrICsK7SEMGH}C~qd{KxhbPGQ%Q#ZdQEaqxqY`T3B=_k#L4F1`1&%5{ifhouX9=yO*AqJ4x$g?8#UHK{*EdzQiQ7IF4Yr;D;XP;5~9iAwu`fKK01xZ&#(usmGj_xfH>DrMKYmFxWSG ztIv+@YjHEI=PE>Y23iNS>fQp!TX-dqdcbnKIfis%9z$xK_a)GvI7)7K3k3TuT`2Hx zZ|i#yx;gm%l{<~G)#u9lW04ofn*O%`p*{3jSnPv-w~Oo-T-#Cm$`^c}i9LG?O2K0y z@WzhHS%Z35#1~vSI(voPE$(&W-#$G@p&JZeMt`||=8(=i34CXYg~R|KrjJ?5->A2U zNo?xQGr|QD_9%d(C-I4R3MSS66e>)?HoTy`kce}=`yP}-n?^{7{nApgsdsbW8Wj$Y z2MxnLyk?7iqk6TVW3e?;a!$CT1Xh;2z8jf@A0r& zgvz|b_DY3?IVR&+?VqVIm|z=)ZZTXgmRl^6MObw6jrM0)aK7!<2;wVLmhyJHUWdoS zz^4%m_CerZ8G6BEu=UIo{T|JgPZ>sk<%A#~LEeHAC7!L`UGoxXPSShgy-$QXI-x>TDGn-nGZ0!LVqtUpUTmT(KUs$n)q8%8QN!!%)2R_QgDY zgF5+8&aW;_M?4zZ4yv3wY>!2Gh|VIfkA9Pj#$9<(qpenBuWkAGQyM=&t1>@YAV#xO8~DKIbu4jHX# z!hZ$!=DKngN=h({e`ypLI9Oa5_`ekF-xDU(8V2ECGz`pNOMef9_z)Q6zb)?H%OD5# ze>8L8{#z4{G6(*@Y1rw1K;jw_a&muL4WN^`xxKR$$mN$;73tqF?5s6)U38Tc1%V(t zRueOjsW~gy&fy;jj4)X6FKK7)VnPA7v$b~?1dCApOGEH4{STXsisD}?E;b@mx=N}P z5+EmY3SL%rR(2{;Gztm|VJ9;SL3K&#|APO$6QQzlad8l2V{>zJV|C+V1vy!=aR>+q zu(5NpadNW!)nIXUw|6lCv)DUR|J%ra+mSSP20B?gxLAYiDgLo*VhVC~5uu{`$I<^j z{@qV=u=W3VvUmQku>J(gO#1_{{?fgw)p?R{*n9}_OH19?N0a~V}h#IU~^kt zNo%{mqx!dNqMTd;oWlR|^M8r{r>FmhYB`%bNr3GBB3(rPColg6{!iim3H+B&z5nsa z!6m@)pFaOX^nXGnK(-(!4F?mTx#)jG{)6=&+W&+ssN!V(w{s@{jQKz6{}=DS^o7~} zNyvXB=-=7@7x!=aMbU)W{`XW8MGNA%xq^ZD1S2OYt_g^*Ip)JL$zTyq?soc>hR(56&iqF$ZF5>S&V+G3oUQlOVJR1P&15&tVK7vm+J`ZU{g0q5A&9uZfAHF}AMfxQ6dm z8aYb-yoiPXwDzk}rY_gI;=^n^dt0v~H<#z$yO&MxtF0dRtip|~glf?h@Ktu_{Z1sC zO17x?>-b1QSHj7WEG1U*#b(!Ad1%m*p~rFP@#N%%tBZ@7`o8A3NQbxA(Wwg&ulq=X z5ZR#$>dl8qH^bxOlgG``&Np(g*ZbWr*m*2biQg*P#Tqw(JZ&NKM$J)?Uh0s2M2xC z7n^R#Q}89=K_TbIEH_YsbfV6lO73-k`1=>dZYW%C{QPUzKf|>00W3=I=YLr~@7A@t zu)h4VSunc4Nl%R;5f)^J6XHx&szrsJW?p@0?=UyhX;D~1ZTW`e- zacRMoa&E@)8_@d&bQvei_$WGQ+KWFZkB0MwwJRLvT}0}5HP?FTQ@@cER_E;cdgfJ@ zusde!+jH)H4>Ea0*X@dp@8r(C=YD0S^GC5ceZ}HVU47rHHy0PT?18CEv0#&wn7rX5 z1}J2{RD+>Q_chu@@LGNgu^#c_IIm^(&d5aW_2*sx6GM(2e1ZE06`4D0N3x<@0znlMm|77xe3&Yi61H{{4Gr(q;R_?xJ8OYu(qrt!@A3R;Gm( z9?1Gd=db5w%eQIaR~h(+Tm9|kFRX>_?kU`YM9eFdjSSO8-5hz{kE5fbQ$j}W`;-dJ zZ=(B2uL9^hl`ga|4~qwjFP_1@Mm59nI(;5~?@l%=JUZB*9XG5Sv2Gr19&hdfS{vQz zbq{91m&5GJ3NOc~$GhHKr@Qm@A(xX2U4P$(UoAgby|m&6nl>I*Y>t)1I$CRM9pmqK zRxdY9K_`w6+lv;p4Kq*jOI?4!S67=qg~qb;`6V!>d<|~LX0AGfjD{eDjaIXq-)$dm z>sb-mk=v7(^Sqj(I8?6`$dkDC+2lOcb@iF*6yncMP6Wf>7nHY8{-FnnFxYK($>Ryt z+_00XZ-PH|y@&spfcZFCuspFmp7?^iF7kC#Y<;QeXKOZNwY$xC>@fgs>~G|bw#Tg= z8R0h*==O{6@84_pbxrxFO^u`acM8Wh$OYuYbL0yA6fV@lw&cQu6vv58sy7{lF3W9; zOXSaz4~Ls5p-)c%+nrpn)haA|t!5y)e+@CZ9Bg=V0-Xmk*YSAQRmas*x_-Lv_lwt; zuI;d4Qb7YyaQg%J<&^dODE< z`x0zhI7e!!v2V)PI%*&K(D9X2Y;Sx@p?uQ|O75wg!M{4Ue#wY-6s7 zlU-d^bc62c%Fk@xh_Y0Od5Q5m?yN^o zOxy(0sccxnjn;te8}-b*YOWIpN?KWXFBLXCZ57P%Liq_qqw@3yrb4$N+B2sLPa9#` zR~C*qcw5alYZVVzqS03Y)}jBbg7?~LIfoNVMsH1|sgs+As|HilzR>l|V;9Fr7PdcO^`ug7JdG@E?NGggE_;? zGh6^hOLlp7HeQ9VrJ7iik(iVI1za??8~R^g7@maQn&}p<-CYhRRch%4h-Tk5QZ^!-$G8;k-`{=U0>VzSWrx(syhfQjBU1!CD@&lL`-jf8(0a3!V1NSylSXiVj1m!*I z?JTqsBG<~6hpCl{cVmWS&!iPULJeC^(>LCyviUP~_E?)5XclwsD{>?$i}cgWRfFu@ zkCnO-&kNWW<#3u7lbaQMl5S_ayh8%1@5qGjiP(m-yDkTbH+>(*QzN;Znw}?CWQa+| z^WeM(8b7Bw`jZm0j-uzqRvW-eHhW`B&4I9jnkHHf0n1T`!6d1v-!bC8@oC1MOuuiM znbscES6tLXw3qq23HH!KI@n3nlYK~~a95s)QnGR{Jb{2GQS=btwyW^!-1TGW`T6E{ zWF&^?B)U;W73-Y!NF$~wAIX;Hx&TgYqWt>9^Yzrei3soNWN$fXqnfeJ!(`^$)oiJT z+r3w-FYs(8K}Ag8oxG$`ttDFX>8I+(pOY2l>SVISxq+z;r{j%;oyR33Z^(l5@a=d) zR#qps(KrNgxvZ;E`{d|s;0Cfd$DgAvia&CkKsUASdk5?=_navd~LT{49}!r`{-A? z?a^=I#ThoAeSNoz9eoij0~B701AQe9x^5#ko;#j`hY{zOv7-`onAR7+a8urHV-0Cp5W)PI$ysuWE|J^*&KL_6JkwTFV#g3To{eCo=C5Ph8fj#yY3(xI<|f7lZI2P z&1x0cUk=+xs+I3n8|)h~es|WC zh496I4<;OE`#%5zK^rXg8mSLkyH){tu&W$;-B-_A@P`se{)ByBGb(9u!<($v3cj~1 z`2%HO?_EC2_HHO4ZSVj92IxZHKNerOo8XsftBSE^jG6BsD zPsbtCB%FhR-Zs1WT*WHBU0#nj7t_gERg;r^%`|3q(CxmrwU*A#XZj?@I-_egLC&wB zt3u;0R(6}hDZAf)>tF{o3c+?IOmm&ivadWHN*p>K{E^E#%$Bo%`qx&$?X^Au66FTx zvmUSmn4ki1x%-GC6^_gzlB`@NwvOkQ(7t3^RzBFD*Kk{OOtV)HX1>QoT>f0ElJeq5E z;|(PTzHUzR5aRLeF&OY00HS5o2+SVgDQL+`gStxL#`c#4H(Igi&L(^W0{#*TU2G@si3j zS@xD!^36Fv=w&ifsLRyorkeSWn#iU*7s)QnH`Zm*&)la^8;G4@sZ?1qDbn&1qaDdX z<^u#j@JE4Euqg-SMD)e=6ehThFB?VOYU(gQG1Ba^*}4x@Q~X6%Yc&KG#-?};mO2C` z3FCT|&9ites3)y1OT8xVE`ti%bDd_;OSyWjMokNXdXd``zpLi{-NH7W37W$;-Ro*E zEy3cig8Rjt21cvH&Rs#vPU{9nZ|R{nHolFuhR?S7x(~b8tJ%IS9-#2_{0s6Are_|j zAHd@DIc)=v&31p3FiW#;m!4&aJ35H30&3E)a0lgLHzNhqS*r^lg7^mBS!UOY&0VGFYeF~fa{Hhb8t=SmN74t(NctUzK*3Z~ zi4ZfMU;a5eX%#FIIJ7w9)5zd3{h_;1V0`;TpY!MTghSKqZ>RCAF$|zkPbt|+ zM@)~;!X!cbo?J_ZMvLVH5SAlgYLOY!>h!aKU8Abqub1&YrlKyT+XZ~v+lSFquE5lo z`8(dmM*EG2KaSTX^xq(>L>dvFn!Y z;)%w&5F3pxeR|fneVEKIPAQO4T%Gxy%sH5HddbV5^)MnITJiqcpJed3E3qtQPDL{|e`$lX>0q z$tIY=nsL3meWeyACBG~k+ni0DY&+iCnG$%vc~pNjLt55cKs zq6f3P^uJ}_>emc1wn8tZMIc_o!WE_)rg7NO@A^wK6me7?gbadCLPOJJYq`OIS(;`? zSfdB1Q$vZHy<*2X<)vx{PA_YDU9F=Uy~%VUry)MpFwH9e3;mok%1BwxVh1&Vj_G!X zE9s>XNrHMxKNz3q(5j64_V+d2urYISyV}}WxrZ1UHDZR#k9GcuyXy=asJh@B@+NwL z6S-kZ<Zi+p+#4MFuoLERj#r(m}@}f8}u(M7IpUz|pqy?IU0ZG5NbL`+Ed3RyMwYG`4~ZKBWe(rW>H#y(36G z#%&%FDKBqTFsr{lU$0hwdATEZa8Iqmq|Dekc}_S^HgbQ+-obVkT5!JN$Ua~lGGn+> zSTGt|Y9KGa*!fsv@MCH%I!_P)! zXd+eqIjT?oWh~D|)Fy)6TSMxlhThg2LhNq>(U&d!4b(?&S+Q^TJ2?(b(1?qGxgPQe zpFFnvDWKvrrOIV4NBmR<+Qz`|$Uj2Bn(qf@*eegYttsS7Iep}?8hve)upkri%>&kD z-n%E%b!kJ3s>_isA9Zn)XrKMm*d@;A3^-}uyU~{bd^A{Rhp^6rDTJOjfWBDpl8@}0 zZ!-6~$FkEF+~B8dIGp_Ce~UwMmGdK&OS9L=SJpH--;*7w3+FapWNClg zkQc$2sL%{*?=WWxqlrWub$uoqo6}bN?3Rn`fhX(pZGlSn2Wms1p9Isc^t8ofs)tH$0Ge)PX25LtS4V#lW+V^M^uSI)zRq(ZQB{IZxAMj=tme? z0f^e!eOG0Y*^<{uiMMY*;VRNXA%3>{N~>O{l~>+u$ZHu&OB&oEja>9I9EQb7-{buC z1*=O)mP&8LutODj79@I=WWKN<*W+`Q`9qm zs4@X7GQ7JOj%!bhaCYD^t~$XOX&;m@#EB}2gg#Q-OZ$7GleHhXzja5P=vx|d=Y=aR z36LI%j2J`%2uN`|zg@3P<>$j(3&v%9UPLm^75f^weO;=ZI-m;cT}W=qLP8qyPJi(D z%+BZWxR_Iv2$7Hxt48v?$RYf>ca^^Li=k0<7OJ)8Ny*$tde@`Lom|*%N?dl`+}W^L zhr3VFJuo~!S=zlv&;HmKm$VzrME?k$(TL!VZW>T}&m0oB?B+JtrR2z9@<@EPX!$kr zVs<&0z|I|Oy&*7+*nlHwtraSTw8|*7;oQfLJP0lYTA{kNBL&)LhT`b7L5>BsEmnb| zijLn+HLbzls3y6Bd8hDHuMAAQ@MI%xJH6#mf4Bkkv5UOHRK;f$7_k-1n1l`EbD#7% zd&32UgT!$es)SW}j{`1Sjsa{d?;eR6yMiJ2_Ny?<(yW*70-Oy(NOzqGB^UqZ& zGHeR7kCPU78M~uIW71`JG2KTWlKFTRqXFN%Qu__&hIvHYsX8Zz2y9WmrhSe9&Q;y)vR zJEORo0zV%9fF)K6wb%QdnKf;zwSn;@;4n_^KDuX3B}4qazh0M;@=(n74Nkv!Fup6} zklHV`K5-^BC13(1reEx*y#m;q`xyghU3P0$j7hW5ude*MqsIWFVpFy7jFdK85I8L+ zFvy@ze5r9MFldAEqEqFD^0j7&|3k|MD935sA)RsIA&zQ-v4Ixmp!p=My0#N#Io-Q0 z8X)h$9+5Nz6W&PHkptH{nSpL?R0#_LPRA2FDIcs@MVIAE=AQV zVZw3b#Q72q^@-UOZ2A)*nJ>kk1}M6A@FhuDTb}n1mYdrx&<>KI7T{wM+!d=?hpnC8_{3(^k|GiACYmbv)E1=RFaCz4Xuta%~1**@fM)EgEKNjV-%QP_KDf}zr*|AWB=;mw*X zr-rVZfH|uwO7;}F3q6PXEbn6$67yjZ1LiZ$XAoIF)oj}b6@gvE@gJ~;$p#lFcEQu? zNW+Q7cL1{^nZ$)`5q)ZdXdL;MFJ@*hiEfeHD!bu_)YV`TIARk6BtU3D;XxNA+cRiodSBb&VBk*hX|Mh@A$s8Wii;Am$hB@>sYivw1WXYCS!SD>XwK2Lt0Ml zC1DG6&^-aSgud}(=Uz*N*h!iU!x%qNAMm?>J7QrQxD85TK?3ZyAJa@vn(>3hDG^(c zq`KKHdaB|dd@hOQh_U<}iZjGxFG@xoRW5KcV=%JHIZp?_H_JstQ6#uveyT-GH9vla3PwuO3BerNEsN`%-&M0 zaFM%|t_6V+b6(F>e=&TMLGl}2JRsRf$FT1tA@&cgdseD{Bun5F6UO*%FSj9oB-q5I zY0iQ1S|1OR^Z2$lFJ^Yc?anfVxCw$BG*24AKjO80PO}lR8qy-~Eq?UDn zBkni$GF09?tvUVejH^oz1A-nq?ReM%Gga+m!f_(nq-~8Rd;J;o*C6rg@K+T2nM3)y zwl7KYpMJP4Z2V>rZ0h|@pPPZ8U3X5qITjV$LLFH9MODOuu9HS3IY`Cnnfo@aVX@mG zsoEH)K~OSPiSdB;Qb3g*io9a6F3p}(&4~n5P79g|xIQ0&+4k18ESZ(M{Zd$lfj`{D4~)Apn(2=rD$7d$s4O8lYn<*1iL+Q6*C7nvb$y?x&KWRh~C*}Uh-{eY*9B`K=XA)$;OdO0VQ=m#y!b8cu zWib$yPU>&SwauM^F?ixGI)i9$P=ot8fqN?znE&=Tfko)6$ABS(WH09WgCJrTuA#%i z`Xi#a@EGGB$*#Htu&E-t+2_)7#A;ec&u-Yu@rP4U_{n z*$NqE!)YJSkC~%f0X$V6P$;ZOPTDbdu|JN^M-%p z3NXiziSluV8Q~0(Egx+8;SaEgXHa%UCM(36Qu&09SdoavI_MO;Tb9JZ5vJ9-r+`{# zgi+5-QSs<^X1NoDQf95M+;0&V8qFT{-lUn?dKL3lb;$hWkA_g=v$)813&nfS?`5BF zbBJtm4c*aI4IVt0%$tamFgDm)txjCi$Q{SmQ4ez4b_O6qe7F`C4B>(9ZA8P9Xd5+o*1d8Glaz`a0#6eLg$>Z>qF} z!-z}v-I7W`6V#hr}$3sY12yvX0EBq8Sic@9Dp3qqLCifF{ zlT`E%3~YCWfmr(u@&0#HkHg@`vC~nd12L<;lg8*!gZ+g4$$WG_qrLJG!s0ayG^33S zVJKe4jfl*^>L0?xb+jBy<%T$N=6ddOLVrx3nxSqS|y1N)&wDe!x43NF1sH?r%+N&L7(2 zO-MzB;W6m~Jq|Tt!B(~G2&|O%q8)q%LAXEeg5p?BRg0L)zwA7=Yg+2!<225h9U@)} zBaFPa5-E8-nKO6bMfzQRA-S_EfjX>V7rXF|$k!~62HBWjLnD#Fr#1UU7cf?XQ>^Sh+nvH{2}UA|}5*5zLF za8Slz&2$iv#n^rb0{X&f`>6S)S{{0q73Q<6L&i*F{D{macGhK@KPDYR5#MyrtQ8m# z4R_E9e1}O~y2ntINXL`t9HR84Tn**PN`7#ct3{onK59eFN)?e}iJj^Cx89YseOgCH zwu6i|A8y?>SdmWAVP#c6C?;1)pRhTDaSB~w4O}xlliq^rQ78aA5|Yl{K{poxvoX$L zLmHv2$bbZ4B)@jiYf@Y4JPe6fTGhPP(2q;9+awlmrn@C8G`md(-nBS@DWqr#YWV){ zEj{<2Eq1G=?s@Pz3rYM+PL`~JK7K<7Y1@|f#l}`-Iys`pqRo^>89s{=O z1@2=8s|sf>y)OSBIM*K9VA$eds7r?ST*fTSrDk$@*Pf%~tx{YQ$}n$>j)vTGz_Y&N z9D|LS0RPGDPN&CN8>DjZ??Wn?8HpOl10NQN4{xGq_bqCE9>V9#TzUkRwmI}Ng$vx9Uttu#oRF1EP&tH~y zkVo!_zk7^+Fj7u&r#3)oO|;uO7sk5PzPX1O;y6s1aV^Lwj3 zAy*t9Av6(=s}Vk3LNtPN%D-z2527GABv|#({oX56IIG>GUbfFl2UpEKgMS51B~7={@J)gEF#&`=R}x8IIjdB{jdodyDLQ zYA{mk)-&Ej!!?(=AtL!C4%uDTO}*vPu$i#4sN2z4qrDF{Jo%RD!>0Bf&ZKaP9@#NJ zq-JS>hSUtATD*elj?}&M)q26EX`lNbGl>3PE7(f-;;Kxc*{>Wk;4ZyYZ-3OUzb5)- z(g2m^UB7;Xc0Hx|b*fZ990jZ|Vh>p|#q%DiF{YOJxN`Hr%h-z3cx39!MxaUqR{1;@ zWQ^*{A!Usu;&X`O-seGU_rlWHVYT&%562>e1#2CoiJrKf!EVtHjXCKJA8m5-C-cwf zy8y)Qs-HFFM&<~<&orX#BG@q`&EoAg;V5z)f5U1o6C8+X8~qkzCCX_@kN{+RkeuCZ#+c&BIsk(3{%hIN+3HOf5B&YZ9Ws!>Y#QvSOeUwq+4(v@{orXwDfBIKg2={HU} zSDo^TaS7V)8)etVc*~W=`}&tzS@uTtO_Sb$3zDiFn(;${B7u{{3hJ znVE753jylw_~=Xc5D{FR3!d> zdIJCu2f>(~i|+8KE0o{Lvw|HQ)tI&t`trGonja;WGj<9>Aq6;Fjbw1UfXK?FdU2bbyvBhd?S(o{+AaEdEhb;Zp zmM3b)N1lP*Aoi;+_p-ds+DDCcIr}UDFHuMSOuN-~GTLeA`2{@c8hNL87(M=6id@Wn zu*n|F>^t>gr|}BP=&vkLXtTj}t9RKdWVryUi}sT8)xs($j|u=I$1ee>W{t`sZD0QG z&2%fRHQ~tmPWg!(p>y@F{&yTW%eP)gwEZNKq=y2l{syL>t;pM_4tqb+#)`6Cvwx;S z6<(FVAuMF;IShe2ZOV*eKQzP=yxUUkeLt~-cIq@k5V*7Z?leJE2^g$qaw^JuuypUv*+_o5fe;O z(^9vWfthRJLvmAqw(w*Iu|;QesiAR$NGtu?2X^h72Rjtd{rHe9JN>QA;}@ml@mQY& zu;hbZ(rwIhNnI#m!(%Z>kQ(po*H2c%}s`U$qCPGtA-pa!u2 zDGj?irs%ks#hjaG8QCaOThH0g*jb_h3U4eArRJKPD(?ri*~f?S)N$4|$Jn74K&Ykm zHnf(elk=0VYfMdRTb?jxhV<LKB{G4S!5=RMwlRwWhPH6)&G^*e&W#ndA4|pHE z)57~8h6yWZgP9U6#dQw=3rj&Cb6V)60zdyCxRd9C@}R?4669`ULmoWLb8K>4W|C$4 zvx!5tc~m0Clw5Y>f3+uXFX-`gEb!mpka5!FNiLI4P2|2Wn#*!a=OnmKS4phwG*x_8 zqoi9xJ0C8)G`+;&G8Tv5G2B7|)X;j~`3i1hh~+Rx_MiBylPRKKGFQ!r`tXj5 zb205!(OL06Zb@pDSnmgbG}-*&7|TSE*8IXIo%YPSd+;GWvHXKHigAuYqwVv&F+zC5 zi!UOb!v%aOrPgG|q8&In9MgovJlu!|QLy;Q zPFe%BdTLXqix|d1W?tx|TrSg;5)`sre<1%|N&Qxspdrm70O_B6238Bh;c~bBwptm` z@y1c%$|W%S)K*TK?JR?@4b%=O2D6orp=zVjPT-*LiV|K3v||$B_(%lgXHHLmK2|mM zd}Mpg?KC+_UzDGy)Cf>_{=)t!!EQK1C4PnyGa#LP&=`e-(9+U8z17L*V}tne(>V7O zWpuxl@Ih;7I@(sOurS9)32Pu%9ol2Wp&MG?cxZYw zjG`xVMG(9lrj7qcL)UF6<|mChqCm?L2w!r`fU~%?#e{*wsrKKZ_ll1-;g<^qTivxh z^mm>75PTiYvehgEU%g2BycF|j7hRj(qnI2K-WTPKqmfOvBxA42v1MB-u8lpuoc!@% zK_dm6qP0Wy^cAPtV!tOS4X7Z^SAto*Y!49>{sRX}*+F(sp8dC8=dc; zXWZ#(UPJqAjS4Kn26Ygc#BTEj(d{CY7!*W^pfYUwT;jEL*mYU0Mq!;zUIzL{Hu{L* zl;uJq)(3R7LLA8~&ZBS^2ylS_#%qpqnOAI|X?t9W=R7H-K2XqJ`&qJ5lS;ObCegkg zfPrEJ?x+?-h9hBgg3v^?Y`uE(;|FBU^`5@Y+9TrNMkO*{k8eGCYl@EqhuVDPHE=ua|S+uEl5*w~^GJm4woOGKpbE%q7v-ujmwOLEw! zPgpN+;ZXN0>VzNnD(yKmTSF;AT2o=OT3rX6R}{rp zoG}Q0UpJnAiV@(Ip0Q5SG0rHpzO(H|9lJqjE(An^no?7OKH0{vkOwM_}x)^kOkj z;$#>SEb$$LaWv@q{2M@S8#{6oclXH}a#^D-8Nt;3wzDswEkWIWkW>USrJ|sUGjUz) zCIUU2F@S0B3_+Po)Jc0sKPN&=QPwxkgXukY3kP&T2Ws)v6Rp{`r48+sufzE=F&19} zr83PoMn7e%8XN~C1(#9RgZuE^aWUTm_D(&#yw(wDW`C?m&*lO$S(}*pj_RJUY4fl$gh^D#&4NO$I8XYr% z0CK$*!l2?JvlKPAPQ#ZS0elafXP&*7@Zbefweegy_oCPxi2?TzVQMbX)=iX+YB$lb z#eBL3jI}!t#|6|4lMZ2>@3UPdTde-+*&BOV*@6Vi;pCcF!W>0{mD}R#yvnB%WaB6? z!Al6oJPkBTtL!?Oq3@#X=t<6=#KpL(J8r-H{Sm-z$?8Zz!}V8zzlCX9L{hOnxg!tt zT0;b`^TD?qM-EQog+N17UO`YhX15eiO(-M}_Rxl;QrB{8M-I54lNcacNi=BwrH?<< zZ}wb?A_F5Un`nOl+pu9^wsR06YsDHaJ^Z|4ilIP7$Z07WnxSG*cE3ag%!k}^2H z)$i0L!n8$l=5S}>Rz;ucbBddDBO=g)Fi^pW%-rn+1x_kJr(Ehfoxf`PqrVmi!=Fvn z(x=!X`y-ZNGviXk6s1#TNopi4bc8E`&oC}F`zrBKA#3dzxP>QY^$19f$Q}Y*s;OqU z6V5!PMGYMl>C;KClK?s7zHBHh-Pb_?I)r@Q#rHnMRKucnYWB$q z6egV{J#a`vA0rb|%ZKG4DZi}GxyX{;!CX#rcSJ*V|W4@PP@zPQl61DX%ftp~y8T~Q@vDIr`!W5mHQ zIbwkX*EHq)FT-uuy4KJroI+Gz_Z4$&PO>jxMH|X0m!$lv6Ms;LjV%YnIf7h!_{M^B zdll66Qd3-fxWVRg89BuLyhcP_OEKEoFCjZ3V#LEwlUR!}WXi;0lT!WX>#VhB(^~FO zOBE@S;WN)F5=16RJbJa>sdywezd<7q*I>Mvnf)Pii~UoTf#{uC$+N7A4P4FVn1NGo<+(?wg=^10RmNpw`WzGZcKFNQhBCY3T_HyI|RDIUh{WX+1?ht^mNKt`MF2_*5uxPFZt&S2rbqy;HC4*vt?7u$GwD1T1aM z4W8^gYX1bSBIrBB18w3pd6hd}hMd2Ax;0y``+fG`M_G*uDDgcM>N z78Ha*YvCbF5Mve~jAD6JCY)=yvPI9Y_ZbuL24oY=7dT!lvBpMRXsbV)ROVQPWgb+m z=hb#U;`q|X`WzlL*~gyu=|Xbn%!n@1%hAp6&s{L3_$9I_Pl$?Q0xsjXqX)Y66|Y(b zrohP1AHh*%?Ml#-yUT#*_g%WeBT0dD3Wk@C3`viWzduB|8F5SW1}l!JqicR z=vRE*>aT;uf@Zl>1FjxSEh1={_`5p8KsQ`)= zHrkxBNKFU9?GanyZn=T&h*z!VT3tt5vjdIR z*Jggx_6nB9-NhC-mX9L=@GZQO9fH`*ON!lZOk3^D?a-#>ZGUyf|k<>{LBV?+>{k)4Qd5l3! zOAxV4#Q4dbG3jwXl-%c@=V7?vJ3ks)N>49jNbH6dt55M;U^$Lwa(zwsN^N1WCXx;}@TkI5!Z3<}joT0Laf) z`G=~Dwqtu0bopAgd#E$K2g>{07pi6I%yaaUes&3#f*6dVC5P`|lkph7ZwJ(^A0P_I z!uQ`A4Pxn|zHf_e`XL35loT3UTA55Rp>(I*#U@MRl&DF-mq(W>~AvwG) ziaW`GvulF*Kz><#CkmE!rc=)fI7L*`2QVai*}bVZHP)R#*FUW7`c8wR^2`bAU+*^W zUrz_rIeuk*xj4BI3Un%3>suUOisj`?7N{xXqB?Vs{18S6L_|sf;Ugwpdar@lNuzjG zmWLUsgQT=W-)ygu;1-HS3lJ@>jV`B515 z!;}}cT}ZXzBYXmmNR+=aN0`N3Hgxf6I5$?Lwjxl&OGYFenKwn@^N}G7RsP-5;W8R$ zPqM5X$IfL8UV`{;e)RApLbVpG_efRT*?ReUP5yqMatS;Qa-jBAUQOWq*k*~I$s5Ii^EQmWd!RD^RniJ$G)XVvg^G1TCyrrjklg6=t+5(m^&8Av z#Y$v!dwNv&oaBgC<^sg{VXj)RF{DfuFx2>%PY|tMQ^*5!$`RA6~VuV zLG$RSaQ7w%KI~8XGQU2~p@{L3YECR81ihkgmNMk8vH1RWoRC6j#`HM1uFAcs%7>|L z2yko9TLgtErVfNgguXYvO6A;6jR1{sGR_NU+kp>b)4)Z)D-+L?DkBZBj=u)&O>S5_RV-9%nb|FhhK>6Og zutT3pCnoZA7%PEE!pE}33bCB2$)m)?B7f4o<(rojrR-7yb74l!h%C~jA<}KXCTJ_IhLer?5|rj{82O3E33Z0UdzDRfOP}w39~pphh2Y$D3Wa~-@5iY z<^|kdtC1bFp6&+eh!{xfB<^s_I~ExJF92XbpTGWYX(-p0jS$u88X|g^l9rNf#TWr~ zV7hldL0Ggb5zw7-fVDf4eEjk4bD9D~|Fh@d`Uhzugfj7LQ8$T$5~SmYWa&_ZWi zE(s39Y8;uUFP5&vN;iyg%kvyI@ruEAMRC!9I!F042QkfiiRxO=oJT90r2mGJf z)p?fKV^h-_hC`uLG=_+7Nj8T@wUE#});sckLFa@hG|Zojkw``)&uTE<7rY=O7-NMo zo`Ft_I?(I3O`iwpcmX{6sav6}&vAi`WE?4&)II#?zx~!*|3lIDix?p5Ub(zpE@d`S znbO%}$?xbWZT|hQKK)eNHSKUj6p%u}mtL6!^rZ#1xy}B(N)JY9=96edblkK5xjjUcB3d->EBVnVl>@O z3jJpBh|exeAlqA3b|{u<=Kq{~_RAO}C8LaL?i*=@5AY)>`U^&Z9t<0@002M$Nkl#huB3b1qh1ybbCqI4Ry*-Cos>6ru>CznDe6;1gk#VPWIgx z3;OCzx7${{Avt+>EI#TZI^lLq6LVRn4m$gs(}0$t;Iue#`N)>lli~q(!w}`|7d>va zJSkB#MvDLTYj3~hb<^19W=GlU?7__KDS4&WQ>k(a3+&eW%gf8uj3Lwxd!>K|i@_X+ z5zeU&2CdL6LsM2Os>$61FP8oU^{-HQj){2==FrOJI?Y9-MKGd-N813|>mcq@&Wuyh ze9AWD<06Ij%S`6JYB4_d)3`H6=8lw|CU><=ixF_JE7&7f5-pRkqi3=wNUsE-&_H^6;F@m)fJ{$`QQqIm(jj8gY|%;Vf)Z#yON zq-)Y4qokXIqvjlpO=Cdem09{+FlSX#cs4PZ;+Ms1s1w8@WmT5 z)TR4G%Eq9Rkx}_%SO6GnTkOXVv{hG4)o>iY44rNxAR)307GkxOG^4odWF1JArc1W zt-*hWCp-+6%H%FHZZodXY*4JJWUYANsa#XQ&l!+4LZDZ6HyR&@t_fdo&4KG;tN4gV zP&#`)zZH85%vT=B~9r5LE>X%Sv z+vOJWFGS8pdMd4jkcS>q$Hw?TzA#S4&`|%3L9#t<0y!iZ6yg1zq~FW*dl3U{objvi zg2eoB6M7h0=^hw(b(r!p3hX^RW5kVtC%VPnG4X_lK{D5hL83BlP#>%pg*LW_@4xoi zOI}yk>&4B~qjhin4(CGjl}tPAfdaBNu_z@pqc}c6HDV$Suzo14<_6b#O*G@0l@XG3 zrN_)V&MmR?N40-juRqUwnpth|^Wi>*Bx5-DEVN~ejIx0yd-|H;d8cJ7_>0E{A1n4q z@#7qt-AZlLhgJ@y*Qz$K5&o!3?aaie5g z#4o~Y{2n5^&|E_)z7H>A0Sa(#WcuWdQ&W&b+)K$f*k~VlS$k4d$Fr z#mgllEx=G&U|vn5mqyS@oPzbt?{CHOsm2&l9aVz_qovW0>)Ez;dtxw|og?sg8eZ+| z>n^3!eOswg`N@+f4zP=#%+|odb5(W8( zFxCv8H2$(txpsQ<6wr8{?F+8^X|D$%^+(Y4$M*__&zrAdJEX>o@&7Tru}s}JcrMs6 z+z$QiPGPQxo^S3bC_|(7k2^K`&IA$ie3J2<-3zYF=~vI540fFNJJpLkSoD4G-|Z$} z8r31*J{tsoz$gEI^gQt7N};ewU+0mR@1acp0A6{QzH!)~r62?3A_mAa&Fhw0OaLQh zq}Tp1o%Vi;_h}y5uSuQL(@F^s=xnq zFlqHHwEm^idH(dw+2CDZ$E1T^IuWehd(fIpG+)PLHZ~r0Z*CTT{>2yac$DM`DR*|h zfhXkghQIO2QFuZ`bh(FiTJ_*rxQ@j;B`%3+3<>TzDNCoQS@>*J zPs%M|M2sMN=FmGAm@C8Xc|z51z78sRQ$|kdydb}zOnk~-WNAJ2l-HKAK8K!B-3qj$ zFO$MXdfDnKK!tb1L#?K=_`md-)29bZzJGeXtLx;MGiOe}eBwm+R#z7nlaxHZ)}TH@*~`&jy1Z&8?G5x&aGLtw(U8mtA`-xvG< z%k5{?j6;a@p9+Ry{vTpt{(Dvwm-~ZYKo%>Wn;)G$6|AwMUcwUX;&9Fgxc#INN~eRM z0OO1TqcbIS!%Js^ZVZ}981rY)?T=Z-M0Ek%i7in;lUCjjgutId*MARtZM!!|0)f?+ zeh^BR11*YgHCBby!kqo%J+CxY604fr@awo;Rak_?yQKX@-ZGv))4R=UKe6J^1fL^d z$8a4lt=un|dEW|MkSqF3a~gr`^EY%R2>uV~e4w5u=KObe^I|sY1H-?Dthk7*D7Y)x zM)390pT!$OyCcYyW%%}|_3A$EX_`OC!JmTv4D)jtzFB28pwCQsRJLh|M|c5d@P1ro z)jubiA6363Ymg1sFeLu13=nOH@s(2+g)eXRkA;_D996igiz&&m+5w}rEGX&Eitab%bUBqO zl``C#D&ynO3=knJLjqeNuebvE>8IY!&2^QOhX3m`qrm1$=-_5rlmVhN>Rgm!u=$7a zRGYM;)5hmumI)bF91_hlxo?sl$SsDEqTgMZfC0>bqegfEx7;YtFbuzJX$Q3tTsysa z3K*ru_6w_uta#8ZsY%XwX7OZ2D77)W?M2$81h@E1c}(ynJmyYk;UUbdG$vp)0?e(R_t1Kx!-jH*WP7id8{{ zBXVu&S$Kgy&d|rPYNahi)P4)#&kZQuG9HoRg0SQb2FMin1dO%5s+xBf;xbV1a!6Oq z3TJpa!~nQ%l{tBn$f_BV1JZ_d^*Ya-U~Lc&NZ;@-`EpxN<)PqpHc?xYdCG@MGct{O z^e!Hd5sZ;DqIc!nApI&s2b*UMytB!C3uo%6z)lEf@RbaeOdO|PucR{{AAJ77S08=! z(I=gqop(vZT~qqn@9_`aH6>zz@S;UtPZ0#fM{F7$4Tu{8+BC}OUFn_(0l{TO=Jjp^ zb%^kX7KD?}HMk7&Z3bOm$BgPr3K(IDLA^-c6zPiwA-M{73Y4c?VLcG`==53UY`wg8 zTI&>GV(9bc1uFz>4Uk^~Vv<#c&gWz;e`#D~d|*&4XtJX4B32=T7@?717@Ij6D-sHt zeBuLJr`qsgS-DPvq;BHgsldre5BDrTG;jU}CTJ$q=TF zOX9P=)S<-?+;S<3$F^Z0h{^^QTFteG|%^Po8A9 ze80rsz5Dm?AIY!iLgVd>QBlGsosJHHylw|g29qzsaiTltW~xkPYZpcD7TBk_lnf_o z-osEBgpn2)z-bs^0Hzo*$_WLfrZ7}?TrI&U5nzLYb%Rk}ctPB>c6{#?(D>++W+^AP z7I{D5D^0W+Gp2E-1OmcChe@xfj0A#Qq13U!V@%_0>#>uM*~U%97&CEzFS7CV$~LL; zEH>o=5qe#-FdxJ*=F)&6rdl@F+|I*=T+M; z=!Id@^zlVOb67iQ6@ah^B`{9asz9XjIz@C5S>_Fr9;($jbRHsxAoiB!vP~57CL9&?GwhDh^<r8X9JRswEFUtXe^)vIvGH89Hv=jCr2=OnEoG9p6p?_)M}zXRU5ZQOGl;za&k! zmwcL{Is`9auD@2wKCPvG4B4bDk*eWYAF6RGJQBf6GxYIVW2nYCD7j_L#l{d%a||4E zm{7y(Pa$567>1#AO4z73THr~MYB9k)oY(wE56$?H zvea49-5|)z{Ru*r{>fD|1C9j*#TbMRd9OM2C!*5mAgxAj%OWoDS<*!0A?lcO^A*Qx zlwcpD^SNz#>8A!tGVd_ng+C-%gt2abUl#nMR@xQ3=;f9XO)+T7t=8q%v0rg9E@OGY zXKWaVRmP$KZdD=1cn@GOkzGl{*vw1Gf_oKazi`=0J=&9HY-$V;(HA45;U}|(*D8k^ zO&^kzUwANqb5e}tEpWg!*TJOcB>E(-&MVMFKR0e@pgaV?2u1QLry$xe<|f|$uQ3JU zak>tzrytL(V8Cq!ISlD>C7!;in)*-2|F5b167)G^8Vl0HqtbIR|7@D75fFG)R^0sWNPx#;}2G2FhU2e6k zg$Kv!Sn#)Gh?vElv)^y)OFq@#d;;rQ8B#GyP~O%kk!;fTjlIP-HaraPx(gxIr+PIHkU3ho=LCy^oyWVQ z#bQ+Ae4AiwfWPwGrg~j+-Q77*Tgd7hRZdWk!A)g=&yp5Wf0jjPj=ad$WuI}{nBZgw z09yuj*21Rl+_`g?TTy?#f8ggqgaktVvR0cy&?4RN$>+9! z1*{lXk}xJ+tIVe^rz(h;icZf}6P$?3K@{UACmuRk2NI>rvKlA!2d>Lvx^oO}s&eow zXsOY(cgbaxmdZXOuxKTBcRAw?=rE?3QRCT6wW5KTT{K{;>Iw>ADYlfaYpj~7qg5E6 ztvam+DHpnBHKCapKKM-AbgeQF1l4_4o9;eQ1jF!QUTLZW9-2k~ji|(YQ6NMPE&soN~1@ON8Ek^x<`$0(SiqKf1++aE_qhA z?`bUR<*Q!FC|1Se_3~RuQ(cU=&V|*-rOC>`HLLAB>XAXyRM6@dK*N7K6)*-J3U4Qv z7bP#=QVF;9hplp};FT9LZ$%e$NOl|SJ|r-fbByJr6tvEIP-UR)TggK7!zK8)x=06? zkj37h#ZNGt_YiAEl1bE&7fQle^+~R&47%o)(yfug;z-*t@>T~bOIAVoCU8xEIpvM1 z4x6MWb4UkOxACsZLz`)E9ob1H2o9MqV`Wyj3D(G8>Mnip#TSpbBV;90F0Uf2?`@^G z9;i(VE{n^(V4C+}xp$A_wV(WFCZ<6}af8i@+Lq zEJAZaSHxjew2km?nf;DS@WFI5xA}4cBjjSe0Zz0TSjOO~6-yzJe<-g~(lFeF#*GOw z`>c)11EH@+WRRe=0~GenotW8ePjrwG2fPkJRrtpRuyNn~kkvVt4^&oXYV3p-sQSh# z=p5scwMFYaDK`wSEvZfYK7$M@jiq3XFu>L@MwY&eK?(ZtXOiMM+@Mpo&YeEJwlGKe zRR6Rpa&b@^?*#-^e;jwS4?pf#gl?mTg(GuoRED786`qWP5zdW_54SGKDBt%Q^Og&| zOI%8Ux-KPYx=XQb*{X;0OS76Q^e@~7P$vO0_0>tPCSf>Ff}1?EQ8n=ej$oJ-k~A@k zAis9Y3f>u)tP>v`1UbZmQp^|%i?lz6jvFqek*}QburfvMYMiAbtjyIrUg*&Buw;^5 zlnRbIr&UhIK~gWO9Q|2TejJ|iHy?pu7)`4Vo2e)85j;0nPd1ZP0M}_6)1mtbP{|0}S$2Iz6U*x%HC- zP`Z?rEIGxKf$a=!C2d;~X`mR~+b+D)Sb6J|?<@nDRr|_EAw-$@@T&`d7;*KDfiGwP z8?_g&y=!B{nblM0kbte-R^Ao|L?suPqo3 zg4LwOf+B$DX6W0nRseCCf>YLwn`E`)4gMucvWmu7z3@D1PWjB^rcA z4G(>a2U*}$KcAMtFVCG;pIY52KT%!XSLDvV^%GflS^MtIwp|w?5+yUF9N~Yt%CBo) zHG(BQ*dfn&^Wc3cwCSDTUa&lUH59siVw}wvBuZm^%t96Yu>_w-F5G^{RX?(CPM2-! zkNKsfdE1U~VZL2Meq@!#yXK#6M}0b8@eYAxEpR!?7fgA^m3TxE@qkS;S=D#@##3iS zFwk_KElL{8;yKCYWV$Ub`Ayq%(%-_-rq_E4Cv@&Yimzfi-+ue;Q=4ALYo#C0Zer&1~W+_fo8+YoH}WT`Mql|7aUvOl`Wr zGH|RV>82l6Tmk@r8a5hW?dyWepzs0i!eQfT3=qCb+DS3?6nl=z%;Cg{H(_iHQqF;Z$X#`RXth6|K=nolq;G^w{$zcm^mw=@j|wag4e8z zi_f_>;T|9OkDNR+cjE=qVw@hhPjqKQwI+@7I>bCA8O%ZLA;|`(F3+Y54>#S$#gk@d zfdwM?jNA0&(;7>u%}0;kP8Cz{V1VEZ@mJQ@*R>Uc&G2l&2!1+%a9E=ABM?#7(9Y5D zNTZr#LE)=&z~(i9>cRRP08FME1r+bm*W}R?5k+aLmx0v2+e8fvFIFif(+~R{fii(o z9T%?2w&gyAj^|7|=NOXt2l+1g(6(5)WOeV4M8QKUMO`Onik{5Q!Ww(g>)nSMxyp^TR_*38AL@|YbN zO`IbM^lMx=2^Yzd*aI?^?33i6Yi6rl{teIDTrZW%k#0*RZQX5buW@-Mv?7cNvM6F` z^~Z|1kMEEEyhAE?*hqULxEg!)8crL6yj0}OuU@(Y18bdX^>+0>O*44Jhn3)v z45TCsS?0HWe2=XyehS*=8^x=u=vhI+#5#qptu$?c=g$ zP}@!N_JFS@MOJxQ=`|9Ve2O+*k8YGL#C50%=AWlYoii_buWZZI2xtV-B)FS%9TqO; zNBb(AOppRpg!~DwaxX|;X~GwUJxsp~@O5=8Ne*P@D<6^=0YSN8aLlQmYN(f1&D`IJ z3_BIJ2Px=#rYh=?HuW+mA-AZw;$)+9V6EX&j;W%4z!~88kOA|z2 z_;z6@T#zT?yFvbd^w(U|#ANHi9d?>_4&V!&UCP6w%iwm2ct3s1 z!;7=c;zR#}jJ>4OH9YE^tF(2(>IL+Mef4BapmU^;htQwXHUnBsk)}msR%L9u`y@T$ zeT?!G$n+IE7W8L=F*0?f_*Q0%U(EeHlgWJg!3Q5aq`)(KL4<@{LNqj{xPm5z8buKf z#coIqeBB@g0m7pYTr1leIBiKFV}_CieY_*|chOC^!jd}7N|$=GZoZ9c6>JAq?LpW{ z5tlz>2BhiyPGbQs`mwewX;&Cq9bn3;4!2G*t(aag z<%}1q55So5R-RURR6R!7Nw=KhWNVLi-tAvpf3*$XLm3yUOJ!uFA-t;FGD_2m2syUu z3MAFzyB@guXPg3PF|9fj)P}qZ^gq%&b%bgUdTND`6J0Sl7nBY?ZVJW*lZL*x?+5+V z{M6XMBT|fEO?wc-284-L);asGr&d_Zp{l_q9#B8G)#Dc0r?}dXu*UPGEAuak*F|?* zJ^dN5@p?~IV^4*&10WuvPx>NaI#%jV?*2uEYrHLV-N?NCt9r+pO#d`@UjPq??WnvL zx_MaRg*=yc^s?kkEJH#ISLbPrF?YV#fjQJ9*rFhQW^pjDt!(&Em!)N`oNX2vb3QFo zkw2XESheM}n2+PzJR+J?=?eU-_`?OS;;e!sxsE*xlhS-WTRQ=NOo&p ziT4G=Z{_;G^dENqn%|Atmu(o^u!soK1y>=cQGE^v0Tw{~nuSe11&3njNA@kchK%6i zPtCkKoi4cbNLW%fuQY^|ejeHEr@1hSLy&RhDgI7qK8YHIKz6$ztAW=auBWj&ZK~LT z1Th-|blU+S=%P2EI8GRB2hfz&jiL%xa9OgekkLJGP5Q#PUGQg(%3XTHPO^po2HdYk~fuS zX<^}{j7!iPT(j`=B?%N6X3A%L1sT?Vg+6K^c?S%slx&v&{J(l;lR`9noyX}goS89AFm+;CgJBp>EAOU+(Kcs-mm{5Rrm}sPhm! zG;r~G1-0SA#qsI@*2z1NBnCGtVc}LzzmS{89bOMd11fsMS>~cFa~^}#n3hXg)W*M= z;8xo(o-TUB^}fQ9az$v?co4*#DCg;#%5;vTvN|<)gMj-vn=eMx*idf5rqz4G3t7f# z+GYOO*wFUN4fWS82VRi`trQf~?m7gk(u(%wF^dEbEo5-!6jz`cZ7pSW*tL>k(zFG1 zLt|mfDUZ17tWj{ZJ7CM{NqrR~2Sdsjvz&#|L?+oNPp!O&hZ+;NZlyuTRX5G8cR%8q zAI9L&;o(FOO{|bn7Pv%u3NJkshz6pcYuszW0o}7?7kEw}Y~}=eP=WTxJwB)0iB8Oe zhF{KT{`-|rQVoC5PkrV;D4v8ivj>HDqk6^X@R<~*@rsDXjbQhZuJJ+P-ehsOETady znSSr3uH#xp^NTUB`K(<0!I)}`TZYIsnj#;TcjBSr+Sg|Aia%yBmqYsQ?rD}sFj>u=|5$GNieSn1K!lKjl#pSg57kFz85rUY+vg=F&u_uIAHA#sZTLI zZowp%^uvBqdd&vaQI{e8r=PMpbp>&IhUs9?Tv8E%dn5x!V+vjdKIt)Y>Z?Xoub7{4 zJtu}%hSD725?WvsK~rV>z%ekeUhj;^sb;u#AM2v7ybiJeg2zO zJuaNh*My=>6`rwK0=Eg}tA4yN+YU66TwT3en4}w+@u@M6YQ?%%^BC0|BD@T3s?WyM21QBYJeh%tam8 zMa~VEIJe{WdB?)fX{P3|7H{gi?SlA}vE8=dVL`SGt#4Sk-Ja4Zc8>1`dmQq$b0B?y zfn6iVky`_r50b|Yo<_exJ9#@z+{vqnichUEB5$)~rvQurjeJ+#{AKlrSdj5Cql5qT z>Lvf+144G{Jci$@NXvV`-)-ufr#_t*$!h#0oaxh)(#XH; z@)t=3%IEb2uRMZx7#I(n#TQw{jd9@^91<=V5yrD~{ta{PVVJ(>X>UyM^@8fBYwCmX z)BropSjknHqb}ik*)6AfV;ruMUeJVE!2>Ml?%bR+WZ9*QclEmjsaMPYRx5t^uD_o*Pszu$S!Exq15%ulx$?u2pGVKqZ&K zpw=F_7AEkjWYM;Hr2YeI4vSK8&G_xw&^`i){#2I(7kSh4V|=M$kaZfcdV-tO^^{+kwaRnROgq71y6gBsUl0` zUi|;;y?=0AS$5y|UZcTZGaNjSGdr`p9HKcp(n__7*-TW~m7^4!<%%Rb6%({ekz8>Z zjlZ1y6E^=zRF$gW;jhSlvGJGV{KJNw#E~my0;!a&jjPN?*;1`+S!}GV)XF6~ z5u%2>86xTgK;Mx-<~plq7f=YU^Co5_@a(x5AWrWwPuhGu>&%R@o~a{;hojCw)k&Bo zo5x;`#dBrOInmcD0{ph> z0U_phZm7l zpx!r-F^3Z;S%$kLtAHu(PP#iKcWFSv50}W#1#5Nx_#xWM*WoRWY;jL)BrFd+H zFUwUj0=#+9QLo;&4G|2oDl$~#xguN`o_2JJ;?e^3%#l}KlNHIcv^>W(jz0TLM6Utg zqLF7hV=9(!sEH!+Rdh;@tMU5dJz3NJL4$aAbQE3`Hkz)hK#gbc!=Z0!w4iY}MvbS@PuEXYPxtS4IrepFFGDFeUe;gcSH|ZQ^Cq zB8n`e`nt^zkLIOVjqas`}<_fGKN5EdA?d#xk8XT=~UkCoHw(l-nI&h9Lqgi+k97f)l z_fUB9S^9DF4eTCI2t1IB;ciz;lnkIb49jVh@IpJGj~n3E7q9aa84m1yz+znLZO<_BG4fJWi>!7j-*H61$jj!3oDGR6+B=y#`zq1DsjF&Cw0n$0n&O~4)2u422pjz zpOk>CG#*-wMNJ%#Me~B4aU)Oe61rtZxJDaXqz5?kv1f@PFA5vdrBIAFuWXb1SW#FdS zdl?_hR%iH$P@#=K4p##pY-Kd~EEzFyZ@DnK_swli=goR+ zZk+C8;hxpS~ocK4H?FHxEH>Y zuPJt`YuNF?SZ5*;(Y-+T`?UxEM$qK?e)+x(=`nq8U{p`T8^yTK>pZ(Bj&_xClAl^0 zWr7o`EUccVo?2YbiMezem%)KJ7&dN8PFHs2fy!vdm6+V^#M;A_Az2Qd!iq4dm5Fa&+8y*~Yn786O~D2FM!3 znuRDj&tY1#2{#{gN5o0+PI6y!jVL$YFz(f72F?`TRvpULbaJB( zv|qFB=&G3#OLQ_4?${+iH(mFtOCA*3y@}dgfltcGJZaA=N4@$e-ZgMpu?pViB|RtD zP^h~+BR0<{uLhnS#sUTg`-;|m-^*cmY%->_1S92M1LwkD9TL??30tzQm`7&E*l@|% zxF=&4*K>RS19VLmX+Qh&c(vroopz*qg9net(2Y9Ed*g)?Eqd_G=#98cLUtV`?8l*P z#_JMr=w||QDU^(dwV1iL1OMyb&sM2uY(@Y~8X<`BjP6y1q6Z z-mq!PtC;tyrj;+oMU++s!MUK>I#*+8q~)=37N44(1M6Mf>g(VjwCTNG!R?Z)Wb)T+8Q}&x z7Th?wImuTdZdn^)t-IdP4P0YbR!BpZ;+25jz$DyD2r9ZcnwpRcKyAPxQPhLfF>($(aWEmp_p(p+C@Qft$4fDBU2?c>nU!(2T zNylbWvy2fCan<0(_w+{D6l2QZhqwTv%!a0>iO?~1)1+hrhO6;}+5&^PIy_QIsc%EH zuwx;S9zYk3W9?fhyJ?b3@NhG(+f6#Mdl`S3){*+P{eTeM@VlYWetAcgE?$?iXY5zH z;T2ltfX9s2VZ$X^2<;8s;rU(iRItc<%DGlII$&w-E30?JJ%2b929Ujj2@v!)17#Jf zvC^$Z5tcj!@)nhc8M-zBR^+}XDRh}rOcEO+cM%e1w&LRri4|Q)@fIUAyj=87R5MD> zaj&W^%`lk}bnG!vJax!pq9e9zzLqI`<9@GFXHP*(J1}mwr_B3g(m+6V8{=afrH7?0 z3teARTuK%NC&my%DQqUw>@$YcI$bn^m#e`6{gV=`+C2SSMH6tFbIT|WxRY^p;yjwv zk>r7!U$YS6Ybs~s>7#aM8#lV*R5lqXlatYa@G{;f)eEjfchz5)R{}aj+#6iUxDhY$ zJZ(HCu@S+u*%u<%Ff61*Z_?f>(HrF3GI7h)K-4`PbElfWZSk7ieq z;GsUj+Yw9|coY6x1UJQw#1T9Q5AhgS$H=JT*;sPn6nx;P1b(aZMQ>NE0M>PIX975j z_VO4ZRPxvx1;)t~G_F(b8iv*b_#g;Y>4Qs zgL`;KW{nb#Usu(viz=k>>Z*$=_Eq)>6je^oC>nDL9*iF;PQnj?t2J$pWtSxc@0GLx zqrBaMsaG4`^qrIgDs{JRGkCRpgu%h!oZI4rQw*x&H*&fAv{g-m55c-j`#0Ts+88gse(dH#CN-7l1au~cin`H@F&hfmU{KV|=0O#ZU0aq!OoSx0An+;m-f z+0y?DZt`j0Nqu_&bV+Zed#q>z&Ws=hjzx=4TLKj7wQ2FzCbSND&asJaP5W5ru=viL zJ(J0LGB`u(s3iLw*IBi7##b%Ll@aP|jjZuHCX$Eqh={1b2luGG>bAhR(>lLVJd!c$ zCo4u+k=w33 zyyAH`?)m-UF#xX)E}-~|%$($DsP;44k%b9?r+vA5#n8OH;tn3_mD^q?pWZ@g$W?k% zf*ipSVT2SY<1+|Cm5CLU-afdco=E}H$t&c22$Sy;yvnm*&|s#Xn;2TMeGXJdS{pJp zk2JPDCP}NwW^)g2z7lqSHeX*uV>`d0!HD}yuKOVn{y{@J!x&3x-S_+ zQpU%sj1LQoj2NZ6w2AATraglLo;CYdo1yZKDyUrvU4-l|xJLzpZAXRxJiLZ*HO8Th z*HvQ-x=pz_l%XMf3BSZIlkFBh=L<_|gnB)S&IAFyG|$QNCDfjI1OaW-yNp{)@oCmcy{n zDVcX{nsbI_GDxCU)-V1`>AC_Bygh)2mdL-a*W!y>`oE)}mUlD;^bIA=uB-jmG~5#L zeh}@2*|k)PnKQ9BM2GqMd%Y9$3DjJ$q<=FCQKk()-}Fh7sEpb z#jxRVmi02c0fzCGqy7SQaf@fu@ffOp;aN*PX*{a*UIWUp$ymA4OFdGg028o;bK|gm z-3vbPx?~m;rwU_p8r)XW;FJ8;ezv5nuytF5*FGQiYQ`XwHPHuIqa{*}#R=eBNWurM zHZVFS)n+Vv@~-TX+`>?~mo!Wc3u8a!js9zRSChQePaVfKFS28}!4Q=h6ob?d8RMb` z(?;5yx>w682jdjU)5NeapLFkLjp9KFVYCU~H`aEQwiaAvwO2bf%`n;y29S?HQD_++ zLseEX)__&+{TtTHU_3clGs`MTu*3Mfj19`&W0`5zz?t}$X2mD69QaZ2LKB@4F>fpB zCS1r{q;Jy*1fz1r}ox{jscVf&`BWbQHOt(U;2>FO#4 z`gjxc=o1Sixz*L@q>)UVX1hiDzxFH&N*6cw9;5alMs1bx&^F9tzAs<^JVY_Cu+K;v z3JAIw8!hBJrot1=_=Q) z5u1cTMs6&xqqH=1F4nvrF%ukgnC+ZVEkQ6BoNv+p$wFSSFDD)11J(Q7) zV3Tot#pfV5>M*cjpsea%g2=7c8mHnJ46$|K&l$dn^L7)WZXL(z-WreeN3W$Xy0E!Q zLHSst_n>P{@pg$2QfSk#eKV>^sto>P4*DyQBv!+b){V; zU+o0XrbC+$FJF7h0P^&{WUpjb%=vo?==m8;z-1s$5C z0ZZT-=&E|!ZL|_{MCz4XDV$co^MOJVtb%KuUxzVdvkm$Ru8acrTf(IXTvH5)TNUcxKZ$DRr+JZV>_$F}(| zHcYhM+m1`ZX7YF~_bohg6~4=pr;f`;-nAvhz2V1Xxo7Fw^@6yDhw$p|ClS5bG+a#z zL!*H4f?+JKU@X>2uRTlnQC~C$8K>ra8Z&lVlZaUt7iMg;Q5!+D%p~VFe0QT?Jg5#$ z+BCTW{~?C+L)uvGR!?j+3XHnODfqAGzFYpi;>8DyfkIZpm^BnQJ635s5)&xLruT@E3wRI^y=A%5aSf}q!B#q^`jy*4NyE2YK zHzSHXlyRdz$wSJ7Pu>M>=9MuO;w`Cw>pA*46a%FFYCQeoNQh0N2bp*#jXM`+=x;oc zii?ff5STk?tNs!fx#f=gJ^FcYAtrc<8ujKtEf!E6NIGb1w(f3Bj!;-*u!mT^%SpoY z+osymz?TujPu>z&X$^cMn(Z6Jn7{}r!jw1cVAL!qX?V$UN1)wu`z2*DY%hr0o>A5a z74SWuWct_`$t%BvRIhu2Z2iIqMwphyT6MGzpsL#RZdX(8i&tNlz*7@NamB(%x;$nZ z7QcE{UHkEisaJ0%FdKs(#Lsp5HBdvVTb}@%KxDs09UspGs}^U_a>fdO(Utp(3zKWG zxbZR0uG_M1+DX2T4dOYJrcQM>9yPsLh4QGTc?0cOIH(sSi7WB!e*Bs&bI@m(7t{~< zznNSHisP?K4lpKmEBi}$95Y@4*`_y;A{2YY@|NJT{3Ch7*wXmw@XS&FeaasAhyk@B zV~lz?TwW9&SwgxSd#OShI@U{r+}J>uEYhcN7`O(n+Mjfj`eooqo|s@{Dsm=i^x1TG z5+L|ve3xyyuEG~|(%VWMb-Q_v+x@_dkk~q&hRI}6wh?>S4ojGUY^~v6GlcWKYt$dP z^+KGv4Bii;AR4U=V%*nIWaeNrH}7HZMSKhty`fW3T`+IWt~nmIZhhlrjM)|LZ*|e& z5T?4v;F)#nj$=Flz5oC~07*naR4w;VnQXk=jtr=xeICU%rcDvrr0xSq;3|k=YV(E$ zzGeV%ywa5xXlV?3uI{z87MC#>wF8fsx1bn&r8e$bM#wbJ?U`fjG4nJll>kMVXcP2` z;T;*zJ?vRhzsK;hAT09qeS$W38DcJcC*?lwSBK$Xm4y1>Dka+|QwFa`QaRc5XX&c` z`(uV*-U+qv{}B1L9}S= zqyA9(3O%8N)B^ft4$y?Q(`m~?{kFMR{{5CzjN#<$XHi}5Sk$xdXE%@QSwVT|V_7_@ zD}6QiCSG2sN#ZKD|E9n(_=i3nOxSDZbFVGH^Sd_rp&TCK)?Gze6fi<&wPyl^RzUKq z>IJDcQ5@GukI1_QBNY`d0>S*#DCZK7P5!h2v1*B;JO>GJ`6^}g^E6O_M?$Eq=febT zAfqq$vYZ4;J=I?8QeWx&gI@CwDqqaZW;V#|;Q=_7A+%`gPvXkP>ngm(&-H`Sger{j zLA%rN$Q_Ip;mrh7f6K*t#m4E%-kVhfqd5(f{5t=n;2JK5Z`foiz5%CZ07H|i>n4r+ zT~U2%he1??2gHk&I88|>E-~IH#J4f1`liqLj$M#KqVZ7K=u5Tv|5qZeqm-?9R-9{D! z$ZCDsVAkS5^>7A~8BaD210c_R#XjpQHUN7lLrLB$#&)Fo&>4C3 ziKnl6W1vV$d)hxE<*j>QkP%koHqbLc9{wrhO+c|62i$f2%tI@C_y6>BUWN!ww2dM+ zw{R_Z`OR1l4l=GPlxyDlwStfOIXMvj!_nktoicoEKTSe9P^aR`&si< z*l8(lI-$>vSG}y4V*r>gTE5F=nnXlnA4!H5oDeE)%F=O3)_Dt10n)N5uo~ zhL{gH%b-IzncA-+29REjEAN+YSm_qmQs82I@S&43%^OYK+Kl_!ExBvFXqnZy8(D8g z#s?V}nR)K|Dl$Bg<3O-7Lgq$CWw?a1zW-ontQiuo*T741%W`i7rtOO@y162j`A3F^1p!txC1USm-nI?Wo%P>ZwKi;Vw;xQ=9+ z&2!?fD4-g0W9Daaxn+#mcF;JrI1)cFepkT7Kqe;bMvlpi-YQ|72WkC7nMZuwaj|E) z$|mt~ma+(%h(xxFGWumKB=^vOck`MrvTljⅇ1T~!X`P2tAMF-_=ykJop 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∾hIk&Lzmv`sy{g;`!*+0KMJNrKAyM{Gm?;MNG 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 O000000Hy}1^@s6%hunD00009a7bBm000XU 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⋘j&jG_)GH2D>b9x5o(+@Q)W#9@v2D(MsM|IW@;v=x7;kj;Zm1oEC9U`BAoKw7SF6yd-SE^zz(K{xwIVJ@t4Y6w-2&tO_M*Jrn* z_5Q{cxa>BU0vgZbl~pw^cCkTi<0*{`5i3aMcAo@+U8Zo#bf{e*2f=ZU#2-PO`7fCE zx1_};{J&|R`$G%)ksZZalGnBk7I-OG>xJsB!#S+DV1*Tq&Qp##CjlmE?)DbiNg7#iI7E)>r-?^}d^rT2ixDwlYWya+`W zd-FLyH+duYetmUg=zEwD`bLs_cE_&UPkK3@WJhp7yDUbNx__2}zCZQ@pUlO`1I#DL z70?Uyjs@m5|Lu#J?#FO@LmgoZTF5_t-hfX?*rYFYLUqUAH}T24wdqwBIs5#TI3g=0 zspr^R2!;8}mO3FLmbl3TIyf%;=mgsckA`FjTqxY)5H@W>cz8LMZ4N z6dCgEq%exldj&17cqCRbmUD|$ZniJZt>>9`#RB))`o1X6#~JxjpdY4+Ls@QHa?gHb z*X@>Fn0t2Fej8}n$@<8+64yKj*yTBDs!5ConBDfXe3=aE)?R<^?j9^EOjpUE=leAq zKm*zkPv3YbSARuY^ew2y-^b< zY$Zws@oWeG~L5)|OL(bn0M%C>5O@OaQGN+g_R@*LSwQ zOiTf~^$2#Y5f4$+Scp~`-blMXfS>*Cm9wo+sBXpg^`&N2#c&7plc�ugkh`a;^12 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 ^Z)|4C4&STFWaJnQ}0kqNOgc_iq@1ioO+Nndqgs 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

+5`yQPfmA6l@GW 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%0ARdlYN~d!R-;I)|YM z+h|8V??Ey#w1tj9t=b5%bl`U`cp=q&y~_uvfH;Kjmw0gOZcoLo2M7lg9M$~@xhS#L z{f-5mdHBeh_u#89b==*9dU!XKG_sg_zvn>?rojmB0d{x#o8jw z^~aE=)E3UV;()XHudMx4doBqyXg_hEUy6NCMVJG7M9g2`UW=%c$9s55awYx>YK=4&r9iN(Ph0cO z*fU~hL^|XkBg;;tQi7J!#aJ&2Kfms}{-)C50>^>A?havYXk1hA-l585cZEC&Z8sEf z4@9{t@6r8}5#|Vc@%{_e0zIEpZ)0x9(}se2TxUR@0bE0|>H`(eH$ZD=`}d0imH3;fm;sc5KRX-+`&BGA3&+4@vdJxk$LI&sg%)B77rN@86nxh}w2$&P?qCFj z7HWiH1|#wehM%ZIn2RjuR$=bTfTskXeM87o_HGJpZ844AUqRlZ^0Vc+ui%NGsN3`M zj^ZC!3wD3(6rM6D(>&GNbvVYK1N!Ke0Clczx1W7?`WsElf&+TtW6X|m|bs#H=cK2PU5|otkZrYEhc7>{~ZE@!yfNEZ<$Q?TzqaX z-q*=--gAD4ICyQ16rU zVnDKPHovO2isDxoi7G5bab$U)@HgF_7+vok>N#>T;(Hg>+#M&h+i+ZCOqAzDo{1F9 zJs_ceKDBR0!0U3|?l{&$3-m!oVH^v629i1!wRh?eb-7i!FGzC$P8QjLLqGzdVV5%G zFc*@Mk7-VmW*qv~vPh)@K*E0tl-Lg6qu8GTZ-ot50sGT=|Gjp_`Qqj1LL_&wI~h{z zFVn)c*$`%YX;CCNf+?%t=v<)5{YncAeH<4abYpij0FF+^i3oY`2ah}ES};nUZ!yI2 zvM&Wfx<%3_AMkl~gfpkYWX7j3R7o(6URD4S>6Fj**J@0ohpkjrST3wLPvc~}E3usp z`9iQd^cYB}0gP^n!Mo03MgtffGrGCCWdfO7Xm(Ok5D=_1NUL)XGvINB-uMQw)}HPA zCXvH5sQLt2PzD2A-I=rd;0W^+Y<4&*vuWpY$4Rw^KFyZy;ag5F+=+L#Bh0B$#t)z| zo54I>Xax_I|BwnQBLymvUK4wwA%0Wn- z(Egolfow*)-Teu=Q;u0DLJp|%I0=Ey*g?&OJdNOlC=b7jJ-U+(TPH}Y@BkCR^rASy zGUu(30%E+CO!TJN=ZgBK`Ns+!3*#5tdKe7z=_X%fk}&|TH4Y=|cBu-8H5Rw{C zBF)qRmR4Iu@gD?6;&1=h-9Uzf^G(Z1>V1|9@PN4ZTZ=fAIhS002ov JPDHLkV1n0f`U(I5 literal 0 HcmV?d00001 diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_kids@4x.png b/apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_kids@4x.png new file mode 100644 index 0000000000000000000000000000000000000000..f5f15d3643e170195d00317b12edf16c4657b716 GIT binary patch literal 171840 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

afh#-7FOIpY&$N4FrbR%HATA*=X)fAv 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

llw55LGCg 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 literal 0 HcmV?d00001 diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_school@4x.png b/apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_school@4x.png new file mode 100644 index 0000000000000000000000000000000000000000..f6e1cce38315d6ababea563acebd8623bef01dd4 GIT binary patch literal 238390 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

8Fp|G%`i#`IxmGgX0WZ4R_jsLQ-YRo;{c^BK0| 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

m4vRaDjH zag_w=j$O7hOF8NmT{2;(h2|3lQP0^C)bXZeKX=tRI)4sMgT78Cl$3^2ggO=M zMU5+OS_EyS7=IL3$uqx0>sm zNTU_QK$#;Ls~1Q@hQT_V`9Tytc8>1}$hGj5HhuxZkp5{k z7unjbS%gLv)Nql735oc|>d8{;S}QE>DOogxsN7?YDyUHi%xB2oz`&}Es$&T&d2_fC zh)3`v1>a`!pK1dD)pnLr(`GNMo)15Oglaw!fg{N~O}<(`mGhz`h7Sh0dTL2hc2cnZ z3Vk0=7HY)R_8L$?_no|PESs^KHm-+|dkP8Ku$igP)WzTr^;*YzkFMRzyb1~eHL4^( zrbNpTjl-91!XH^??DoCyXEKV~bQbu+1}YkhqfVRl!y+bB*E0`?0%U~8^hS0BXl60X zy(iu2$SfP_7?7xEbj+u1$gtJ5ki}iJs|~cP>3Tp83u+2=dw^ll<@DUppiFOC{WF<6 z1I=;Zw9w#?7h|=m#Rr=KIkpu_W?<^xPu@c3CQ=XxS2tdPC!PyUAW> zHPo%V%+NBPdtythmGr%n0afq(o*b(^8avzM_%5tV-iEpJJy)wXodl9#0H#XSq^#|W zlN=^h0b5y+*P&rbDexR7d6$092$qUtpZ2u1OsI zO|6+NR6)n4lv^?X5Fa66$K%!!pz0Q7U|f&vxkA>)N;ZwFeisF?5A4r)Atxg26O+n! z)!s3#wv$C4RT?IuZKZPFv4xd;n5~Y)vyK?_%iUwr55*bXIcBrA&Z#z4rD2lqbUzPQ z5oDRz><7of$AAhsFJ`J7>Tav(UYe~{gHF21Ko@5cPA!`R)~FX&L4c3XCR2cIta zyI^)JY1Pc21*c}e??{XAoUo^&UwI|RtcwHKb=s>KHQQ1W(u8fdLF;bTxBw@y0Z0ic zPU9A0aPgqM&;LG|loq+XpWba1UD|XhE?B5o7@~1jE!)_{8U^UMF(7cUjDY!pIZG6A zMHYk~r+1i`i54jiCM+4#nTe}iFy}OE^JgvCho+VNPB`krKP+^5UgjxlA3vrimrRm* z$0iUicO(WoR|?l+!%EAJ`rXLw^jGEWfNtH!I@=87O<({ z80=yOmiuC;JKoFArfCQ28(Nqo2yCOv#mSxXbLk_UXD+C+=!#&GURDpJ^trlLktgiv zuXw{0*s+jxaS#H+Jt3CM^zUbl+b06DxIUY3F$^Qi(b2}|F=1Q>39r7Hka(&NEleC? zePePtpuqrfq=4Nq>)Q4r)-2cKMUY~=elV0?afKY?J$sH=GhJ`GZx_S-05=Mf?$?2O zTHT?{p>{1vyQv3R^77hX*b4@UTvBQB*znw-WP8D0-?ce~5NY+3LQJLkz&*v8;QaEv zNukO>#%Vbz^d1OG`wVG^r4kO5JZy`+uFOA>mY>w?1B8kmq}wFm`wnmF9?!Qh)t$$C-jGol# ze>RS!ut~pM8^-e*l73KLfTItUgC02fQZe+b+DbSeg8u!2F-6y(=k&1WFn7MmX-J7b$XE1VRYTGrl5|tkT>>!fqLA1dAA2=yVj>bE13KR`Ev2$cpZ- zOI*JA=G%J*n2SiJgP6|00Au63dj`HM`>*W#>bs(vBrg-+n7KZdIF_Kk!{?WymJzV} zE3bX;ESkm(`EJ?5p%^6oBq4xUVqx@y^R?~1(!Rfq7Eh-_b-d`Yt~*iZ+yGsO-@qOX zeM)1U+dY9u+_*V-kObz)&ct6K0B7j!XNDd2X*6v-@O%}SZq~vqu1Quq1^Zh#sG($q zsnVn5dzT#&09mad=`d6g+5r@ZH>y<6k!ciZj{L)-do?gGnEe~9-{f%lf3!$C&GSu` zSpXAfPdALPicRN}>oj81vm0tR&>OB2V?28(xk7u#f$Go%?NRBqjF`|Vc+x5YORNcw z2unERGzj0A@ztgyJlg0KfykbJx7}~Ki!&vy*t+VI;|n=ZYhFJ#ZI&!3^vH= z-p#%qdrj9ZPwQ&jLMRer+FV@z9v{tnPf7}^Wp$P+=G(&z!+}kh)a9gAhNMh_z${M< z=3U9)nWt?KZVIZ^{$<8( z%I${h@1pI@SHTJc^b{jI7OU9ykprfO>>nfnSo_s75!%UP()~0Dtl+RO;%p4H=9|B0 zMFAE?#>#S0wU`+SU3O)Wg;Zn?s=?$PgCYgx0%ez^gBzF!Y8r8m$Gqw}CSI7aEj8nq z8jT`n!ffNGeV8VhW7AhXw_s7&C<;PofwuiImK>>d!+3@cxR;@$ie*=htAplLYXM;{ z1uVi=o~8)uv@8?&tgApgS*CXUJWKVdYoD0gD3#z?7jhBq4{K9)4LaXfw~9XfJfjI4 zRE}2>kh&z&S8cAxA+p6jV#Zue&#CT++*uf?!=yEYle|}eMLEyBzatV-R^II)-wW63 zlFL9o(|hh7*4IIMs!fP|Bm}ZWqLCE~5(S`bjC&N* z2H{vS`q2KcNX)R3-j?~8LfLA4oBIkr%R}?&KK{L>wnlJy;2Md-m1@z}5!Eykpw9&6 zka(gXPIO46|J+U{qgYBzGGZ;mer*uDSU+B9j#P_v#xcMsJI52e=D&>Iz2^#A^p7Kxok197yT(}lB z4|PWnk`we<9dIlC)m2c)L3(U<{FomOI{6+6va5_uRuSNXu@I?`1N+`4vK?)iROMLz z)|lPAKG;>7J(h%Eg#wUq_BGOjxGv-(L4Q~)m0(v*+V~WD(Zxcp0@j9ISgx-hW@QnX zIPqK|@#nPAi_l0Cs4HcHs*V{mnVchByejZ_?9HwUYN6_sz^6p^mPKU+rp@dguUVof z$MW~6PtJ^<@K5qnW&_+GxWx#6v;MM`B|Gr_xl5FL4J`~l6bJ$%bxTM``4N*yQ>EVM zk~+(j9_zxa@{$db$Zve8IyHA4b1LLE5Vula4w|kq2cDVC!?NC$)pNc_bPw2p#Nrv7J6NOw$7}W+0c(NY z{2Ifp#8QN9=tl=@ea3_^tIHlXET)i6F;k|kXDTE9>Wnh*G|Xcc|%$6$<~&Jq1vpi@3^FWE#uAu#WC4@hx8 z9Wk7T?UtRJW1+v33QklS{?18^IfRRSv~261?Y%d?7=dIjldmEf?$(K1`Oz|-5ZZ&T z$@V13)=#aTvN|-eI)RiK{sHx+4HqXk2*W&t?}>Lrm*!Zl$XxJYE9p)NgnYD;J;F?| z&&?!t*34`nNk0$>cH4dtC*d!$R;cia0T{W(2 zJQk8lx^l<#6s;b1e>N&N5m?K#zdzv~jbJxS2y}($VA81GbI+)6t$__w8s_APqKZ3J#@|r?yvbG`fMJIIn{HVr)Z#CP4%RDZZ)sj=^okd zjn2=1`sX=*cgOn`h)UAEQ08nM;OlkFUcW7?^Q|Lf<42Ss^@|{acybzXFGdd0@s;Yp z9GP7wpAEBm#`n}9;_-D}_FAY2Xr05O(36azo4;Ry^u@_Jji+(EbU8mUNr;7yL3diU zpd-F&<8kwk@gb6Y;7C}wdH_NgtxvC}E_%GpD>!BA-Cl-&$M`2Y<#g^K?UaBNkj#mh zs;59YsWmh==XS|CI*Nz-g`68XR^uWqbkTOFYjWVU+aClh=bQ8yn{=HX(RhPI7FC}? za5;U`w}c_?=?y)&Z|r>^`+9<5?h+4!&H6-K8IAMhuu$d8fjD2A82lm~;X*yS{Gg7` z&;K=<_ZHgs!1-~pXix5<2H%P1$*~!tV8Y{lreaP>n6q%~th1%~7mPk!RGXdW(dTM2 zY~vgh^@V5VU=!n*A%JvuQ8jL0LDkaw^QldGx=uuX1zo>eCsp7A~*M_J8 zWSQvt1Ns#lgC#=?uOm-Z>u~Zpt(uj+D+APh_@}x{vv1QuHIV?Z*FU&dxWBl*YugV7 zSfGjKCIL7}WTKh5r(^XW)gzOI+|WW^77%o4q2y1-HnQ_c%t~Laj{&vt&39Y(X?}ns z;bajx&x`U(vq2D@h1t;p?bE<<3jFCMrl^q=I$3?rt0KoKR4P1f#O+@;N>C#>Dz8GShQ7 zN?jwmFwfzzatm67y#o9z3^i3s_Q*_7fcX#oT~6Nd%b>}v4{0AgDmq?3ROvOj$Iw=5 z-a4CKKWL0NlD(t3Z_+5ttd>Vb%*~T62{xr|EQ;c@kH2?6j+bdD6!9G4;?UwS{lQJ} zDCtLB__9TYy%|5cg}@xfXv!ogeL8)gE+DSLGRFkO@fIf$fPkHvouB`A@dQ-JedXHp z&OCn=KUk~))uu7xh~m0|R;Rp|kY7%L`hnX6tPR}iI|pdpX0JHy?VG&ZYjd`4a}{yl zkjdXN6NF`l2IdJ}sgZreyj-Lb>oZ#w5%4m=D4^X@9a$o!0-g4MZNcFfYE7AScEpe= z9r=O8KXILODuW7$20vAD^QC(3E9BqZdt6jKcY*kbAt`U|#_q`Aa<3gK#9!b3|MsT8 zU%qlE2U`_HvgJc_t;4<>s^oOPc4RSdiIx#RnYm7m$^2Zcp+V+LSAQ=XSjefGu9jX+r+M-$S=TaV37;nZ&q~CP{WR$94*pQDY10Oa?452(vtqk7vS%2NB}CjZlFTeE`}QB{Deq^|mmIYt#~@WCL#j5SZ|-(r*W zd#AK)GlqaE()vqU|Ne$vVa>$^RP_;zyHGsb6Sz-UJqLUm!55C*?z^_CuH9=OGiU?z z(~_bCqumPE=V%%~Ro5o#$JmkN&JX+yx0bB5dY(16eooXCwXeS$Zwv1c5VWcVL-LaL z`TJb>$}!6-zBs}Y@d}W6{(Dy#oLhgN)~hJGE2v|s<_|w7|AM)r)L~VL>3QZ5JkIoe zTFXyDbl~(uJH6ahjM01FjvvBTPzzYAh$L+h&PWccH8I{-Y7k z0*e~S47s2eFynFZs5vWhh+IJXpsVb27P3zp^Beqh-*x2v*<LP-faYA?OvPMX&HZ zSH*C@QW?7RKPcbo@wUdOhI#uemENOUq%prE4e-*4y3iTmfFty&MhH|$Gr(s`8a*S3zB zC2F+EaLxZAjMu56bg>#NUdDA9om6K0Te$+R&MDD(MnU`;Wh`F_q!hjmdgqaFq2PXl zS6gVt8~uD2IV&nDW_7)N&qpI&QWxf5^)`3Ny_o&XgB}kP#l$LAL<95TD zHzG)F0eX$rPnx&Sd=d`DtrZ35?9XfUjMuBgAGg6dB$O#Q=cGi7kaNT)L%%+n@i2;> zB;UP!gon&^wcz}13;F7jwPZGi>$6EF8XOGT+;ozOF`KHUaaJqh ziIdzYSJ^Fkk8FBvX7REHra@)Y-1BjR<6MQurqY#4OAyESiAmmP}8o_qB{T`(b^QDf^gn1?!27t-UQ3XFsEw^u(n7Yl;)gCJ{oLD%8JUndY;k>k0J zP(x#?ky;q$MhO0?9Jh?Jebhma(f;O~yTq*8xR7aoALcP<$I?cnAk7oLE9o8R7oN=$Y3)H2e&d_(Q zCV3n!GoO=G8}ZLqkv&XUtBptvZgJIHQPo@9Af3YUk%NqvJ9k_Kr%JnGwr2c(4u*A9 z-)%)HKEK3ayiKk--zP(fz}xpA&n#rGa49(qlHOBRzg2u8yPSv#m?lZ{`=n1<^RR0;Mnm<*?SHsd!$&BShb|9j_)U5=hVj- zE$g+{HQ@~s%L&e(x6KLV;)-*fAV~cj(-mcU+cvv4SN(2A%3P>~(}ax@4ZCW=mbwrn zH&v@qgs5UkVH}({+*Y+uh_#3d~t=J26b2x8<3m zqz9%OVmJqD=irWC$`HiU~rU&e<;*R7y0`;mot8%nS$=#C$ul0=Tn z(K=Mt3j=k_X3ZQeRfF}^=hlP?OQIxmTyqVM*^S}gJ_X~O+AzF+(b8}`Tqs&D}PKJ|W zt?Y`rj+m5=bZ$GP&s|~i2;93!`@0RJ?EHh^j|u-Uy3*zx()9C)l(W{I{-Y=arnbqbs&ja~OFWE-H`is8E z4VIbP|91oVIlfl7E+Rce=VDmXni6anTWyXF1oSut`B(N@fviI|4fl(6hi!YpE%iqmcXzgS9rUn&SB!8>CZXH`=x-v*Nfqy~E;JsU(?ptqV)C z;fML?WHHMhr61%!r$)55EQmH>&I=lL(__^m!(Qbj%Qf#$hjvf;7jq|slIKIK`?*+# zC4tCO#lSFjo-%O}u=Fh3_U`Tc$>Vy}soWej?v~;*R7^be$)uXjy`e@wYNMK7wc3?3S4EGe z@fkV$YTeC|Dq6mVfqDV5vnEMU3esL`9c{0>JL4WTn(U}fWGh09&v#_>R82l zAUd)#YxhoQ&wM&>&vd=cyZGI+gKKr)!M8zbv|R@_zDmoY1k(NYFs_V^K>`Op6f3ue ztC+*258V)n+%;WaNMyox+iNBNcWB zw;#D|Tj_+REc9b>M5gg|a2^^Q<8S^k-q%c)p;OPTTTdJMD2J5fss;-T4ag4DD~Yu_ z#<1*f$0rIK{sO(}BG+gkcIIdvheKdoMgJJXQOsXA*3Fo&0WC6r!ikE&(mf)_rj}EN z>hL$Wx1OxK_zcCZO4OB6EyE4CKncI<=H1S|V zMHZo!VQJ5WtfP+{0Xg^kzwPqcabiMUTRkHmXyhbd=dw!MzS^y)^!i6Y7cQ(qac#NA z0R!_fEe-+38iyosNTh6iUKRwFTDLWixe2sWzFLyZT$xn~%u{{n z-snnxef$5r|L({CSDT98ejvjqe8vP&IApaglOY_Q_>QoqmKixGzknR(GB$U*a!io* z8vYUe=CXP_tqe5dB8gpnbqGi(bRy&8S0p z4bC0JNx~(uu7)`__=9_3A2C8;4x4n=WFFEc`IS5dD6Xo;zI<`{KK_a-g1_Mp`u%TL z#YyznfYy<^n>NOy4Z_xU?QvC5s_Li;R_Q>g;FDN`tB`Q#84}|l>jWV-#YU&$xlpa`cwUjluQfI}=YnzQ`z_nTz}&I2 zA7tlQDtK3Z-yg~I!)bi^M%6H@d8&^>=yM>@oyTnY)*9d?3$@#yc#5Q?j($ z*8D!Zu+N1O1=qoOp`lklsCtd~L8BhgJ)f-8b#siEqgwA#ocMXA*4&&1b*h^F&41t9 z%(BJinLwP7xep&lpO2H1I-OHZcVw6DFH2T+B?5F@16oV)>j7=3s_Ldq)z2phDbM;! zt|buVL>qPR$6##Bu@tnItPk(ra%KG_O9-by3I|PehIgw80_%B|@UXHTYKbeUuA|pm z8}z^{A*}0rz#i=Rlk9Wi%n$v(7xB+z9|WU2SKpmurr}>;{reS;OBBUtAAeuIbdZ>> zI9|(tWz9-mS?&gw8MLis=#3pY=agS}Sp(vnYRjRyWw{%Y&vptowq=njgnz$%Z{y!T zu6IIunbsEP)8KQ>QiWgNzIUumLck0uF(k<4ceQ}^EjYKwqhDl$b8v9@;2dqIOI)XH zRsY`8(&B?r2jmlX2Ki>hV#DB^4c&w$LUCzAlN$TTSe`;lvTHHJYJpV{ek*$I|RGv*;a zD4CEV6;`e9Jd{;yQyVbPyzZ?|dd?Y^vpK#q_=9D-9(g&Ll1d#73WnhYJ?W<^JfBGI zp${LEz*aUBUCBiEoIh#o-gZKnwukd3b1FEu3)GRiwo((_V#yRMuH-DnX1#19hZRn0 zDNllJC%L+ony0Z&vBl=S-b0*}I?RK+hRpGEHneT|br5kS@LXLHLy(TmTC3<8B|SFg zRiIqraW8qqjMr5LNnm*CzO-8{5w}`Xv`x}=k-@;y(qFII7fv@zoh-@H{*SzM9v;0 zgSAP>5*byOOvOBqN}GDl*H^Qw;eB%I;k<8LzK~|_> zkCe%@2pY7R*aEfiI^g$V)h|Xb5I5Z$*5%$|ja^&)egJ5@{LYzx52jM)LVDHprMaWJ zHtlY@(VJig6lQv<($T~_@>R8*KwYx@Ae^y(+bT@-G102#jEGHM?C~{oEbXc1Q^!gZlSF_x!-G6+}FWmp3>%WhDDIF zsjn$x{V=--b0remtT8lQ%jZdrYC5g8(MlMZJq%g_d9BZ;e@-WDIiN^jVYAk8^sJ}? z<*FB%;N04}lEsNUW+<`dpxBUudZB7sDp=2}gma&{*|pl}_s%GAIh#ie=PJ?o$BG@P zfZZk-;HZGJWLpi>#B5YKm`tPT*)=yw+otc0BE3%m&U9+5QxK7ywnSFknlDC^{DXF?-Ta+A5j5&W?KQ{h${2k9-v2J1gX-*8g zL^%h;9ToCKp(AhHaNF*{JPS3>*~k~i@i6JLCBnN{C1G==D!Sqz{fLTGt)Q^LkEDi! zyO#8N*6%b(R#!kB>3o?u*a?lPm-aQ_{K7sB@;8kFsZ023aG7k14_B4@tSze*m|O;{v7_;YJoO3L1ew^ zyyx0x&Gnc*Q_3#(>(Wzfd+F7GetvtpUHBUGLIraZ(nsh?|M{n@Iacht#1OO1Y+n`4 z^A|MlHtTMbTuqNmVfNYRc>CRtliFMzi&&?grJu0s{#DhI>UsqB>eL*z6~JaJ?u7(xIiIgC^~*LBJD;Mtfb+EU zMXawL-h)|wnyX@dZOZs0u9&c^oK!6MeyX%O&NB!5t-@GqM z$&R0YJYBdrh9C{nhWMSOQa@K0me0eyEc09DS$fWyv&;A0!N%EVQg&~RKE_YO;C04# zhq-Z|RMai!)T+l^rCxMp_lCN2#4BfL1j7_4YrUze%h$s8>AjDuwF%MvE>W_|S~vz5 z;Z&$&Gd<>0v;XdYCo=`3Ffg~rS3TyoQAu@I}D186%2ZB+(Uu5v9Y z(;>YPmN7kkrLFGx6LQqP%=TX*(@U?PP)7E^!lIpoj7me+3}6;P52IwQG+if#*wWWd zKiJFS+0rM6#eJ*l=Rzga3ZcNB=gDQ9f zx9G%!4INGSnu2}4%Zm>7}00=Z&aBq09hzK!(3mKaGad^EigydUW4c6!7^2 zs@_BX?7JT(8W8$5fyDR8s=(VVA5Ws)o#m&wDki~s=*NiEu4~CaG3Rjl!5qD7X`hu! z`Y=+jt>ocgqyiM2>rj=`BqG-%Not8RC zIJu750F5MO+ti|G*6(K6_)e!j8x=IL_hE0PKyR1V%FF3KR6Y>vWL~|G7Sp~3=P<6K z|6_cpB3-I~j=cvl35}zfq=!KIqk*~=BN%u6-KlrO>h)FPJ8o48&J#pV_4^$ULHeB_ zI8=u=Oa3;S5XcM6#lWeeD%vpb%P}zkSHPDGoPFj1`HRhN2yL$lKM9G{mNBRYda%jV zS;|%_YyeK#SaOKq+-G~vr3ZjscQCX}^}L{AP}@oyWsd;oFy?vse0Xq7kg(vMg7ec0 zKoc$e1qqC5Ozp5#a86Fub#UH}ty?fbbL2ldD%ahmG4+PViha!oW=!s^|1n&6OtA1k z1KF~C*hK}9TLXTD7Aw73W3sb)3{>z;G|eWu1Wa zB8%fpJAR?+k-wKtyS3|p%6;Fl3i{S%oY@4oIi~&Q;_KV@PO?>;JR97MUQ0WRn}3p- z$9FI+UIKP*@nT{v`p#kX-uP=1n*(o$+-gh-`yh%BTPUuI1*o2sA2U!)cr;dU#AEo3 zrxVq(Ir+7h@HdNIVb{IxToOrVFP#=SHG2Y9++q$pvbp4lK1}Zjzn~2IQZ-focho+_I0_amic+cXL_>;VbT`xn|Dl2InsRdeC*j zw@F|g#?UnsguMCfL^7cMrcy@f@BAsX$i(WDMgi<|0Ekm+r zk1MtCu{>HE^JQkm=*83=83t#b#b| zI~)at$wOC52DJ#*4$G`bemq4+pT$%4E6`PoAgjVT5;7jodHpkYJSXIv?XPE_w)mJ|o50TnIfwNjbvyxFo{PMa z|M%Pc4H^>?xfNt8gyc=2Emgj7kOZ?!qrj&C;(HM2gpcJ`%N#kJHu1yoqIx#)jKi)S zJkh?&ILD5wc^9;y10KJ}X(-=l54J7p4t!CfuQv)Rx5!di`*IzTb>P`#)hqqLtRAV+vu1L zSmxsiHu=lg+@XXp?J@dGJVx{Hd6nQ?uDc!rx8NxK9E!UE5 zu>(r!scK-%hHjG9E;`2pwPd?g@$pbae*X(0*Xt0R!*E<7dEb09wAM$*v6}v>F*hT1 zv52H)xYxjh%N|mY^|F>&@|DI8Qx4L zeR0o@CqknGr3F_DDO%MFEAL-sR?Jrvm3a#IlPWy6JaV|{VcrFG4*R1_72-nKhM6E! zWZ+O$)+^5=qM`dS&o@|_r8Wt%NFB|SXu1jpjY~Z+FSr`~J7wdS6sV&*PCuTMk=n_) z0fK`A^p>ldU*Ep>jFVB;E_hrQ6NDh!`ij($lo2yhAo@Y4(vomH{dDU22 z4z3bG+`Qnt%%p{f_RWn*4Q>g-N?EP@4a>$nn}C)UEfUGJ&Q}+ppoS#lxTWc4nnD3JxcHADCaXi+R@tG>Ts=UJM zGe;R{dsW7~F!KbKbG0P%Nrj3FMqZ$92hS|@y$G5pW^_c~`Tr^{Qi+~uCg|yjE@t z%0QVyXnO_%*-DV^lO|3%LG{S8%&%#vn7)s(ROBS(E&h4VWjH3gP$l^0ALBh``}+&W zyCjg*66eGs=93!YP|ESQ#Aw`=h5h7V`$%A@b|1G9ti!Su_L+d4jrK+r&-5Z*H4}#C zGIR5L6g;r@DjFF`_5L~&u6=WR>-9P@yr&eDRKokQ=$m2>mL!A2+Qikc%r93h*kV#V;^;a_l#O4T5PgmLp{6hdIp21Dm@kq2Q{j-*nO8hAefeoB}e(-?fE zBXwU$bg)Tv5gdiYaYf_(^0WAO_@{<+iYJ^wg|%xY|3xjBA9wLTN;Fm4A68|7F8VS4 z7AP_Odfz$8khMCZF>=IO>qZ|fLjLC7hkxuF1QmU$u#Z8cq}iF#kA^oDv&4HH_Nyf8 zHY1;wHG})|N(D}^(Pl%fv8Bju*DL`qn$}`qq^3gB8_mi)iUUC!&%NdKA)nDEMFh@H zfx^3=+JkzV1$~30_3IuLv(&TH=P^2h)~njg^5DNpBPrS@LM=8!l~VOU2Pq3yC~zc* z9zkNv*|b5=|EdkhVG7bWiVBIVnA@BjzrA(QL_LM}H%kiae7{BShi$6>;jIMb>hSVC z+Gvt?z8O|_2W2UXw0Cd$x}0FKzo7?|EwllLm&6Hz^^lzx@6GgKjTM4+jley6Y=*WE%R{&{ zMC+42UIhs8fSh6Xw`n2Jf(40yvEs}V_jFyrk;_8|6d5X}^83_G&&VNEs-70&TA2+5 zEu*%m6i^lJE^V57bWIPt-sH8JUeK7MOYB(M=b7P3c01o4sYe)qb+Y$CAn`OnqddWw zN03g7;SP%WG8t-&JXA-iIb)iJvL%I(yTt@o{1IP87p4DAnmTguplUC+S zbF9|Lf*!v;X^l|H_@YX?K_8_JnhOwMbn0WUbw*f$ z+?DdOFN%66jg`T?pMDQJ!+UBC%{r{C5CFTtJ*G8iEM%ax_g#pjCai8Uc$f*q!oAHC zjVhPq(Aqn`=t+0)*f1(k5XpSrjIqLjPJLq^EmTnA2Xf?%7d2dKjo_k1OMf2wAGP)) zw_lF=-O4a9bgAf4itt&7r1`pV2y zZiR4Th1XTA%ZvDaQmLl>(XP{GHZX_fwD#`*{G;W6ut*m*w*{)ou{d6$2ewn%Je~e- z4u*5zXakf3egkERQ32y8YG|G_ahhgm$e~)IIY}Lm*fk=ofVlyH_diWJ+Ci`$DSZ?| z3$p|X+)JPb-&-jIa%RBvE}PBlUa^q`=jM4?-+UDd+4(`(B2ZiHAjz810{0H)!oI-9 zh)qr#KM-AzWcw56n1i%Dat`r`-(%Fd!D4=?UoJm!Q_TeVK^x^)$)g$z%9tkiF8w@G z9U7b;zQlTd62#pPe%+!$tJQ|aqQkNmjiAfe!k`vOTzUar}7EgCMRdRD4?2^fU!nv$n!4bjIuWU%m=++D`;KV=rUlq7z_b9<0!#}q??vI2@s@OcaFK%T(zoH zC6%NqNj4te2iCtzRqJQ|j5#LT*8L;s7JPg^YAwJkLbp+kwmRpb%Zjw7v|uot%V1lK zLJPtG(D&Q!9bSa^X39#kX|3@RE4Jf0y?H(Vo?R41FDvm@%DW^rGe7MhF7=7T_~v%d zrBt(P5eU+@Y#4(BJU21d7Fw!-+WyYoz#^h;F6!2Nu2RHF>kHdxpOaDGGfF!lyI|AD zbqyeiRHuAVM5Qzlu@t_2*Kha>x1rOz8Hoa*JrbokwS6bxlI-Y&ountAb$Ib>>b6<( zl$2dhA32fsTx7n=wc?u4=5AGpT9)MmEJS$bL-NP6gn)4FCy5+}dS|{4uC)a{ShOY? zwYmsyH6b37wfsmVd5T{Bfb zC)bjeeF&R!@X9kBW<`$9?z__z_n&e72P8FprwMBxHnm@Q+WeD9XJTybPjt{#u~GVa zQ_}Y$VYKeTa0(R!YC}Ltp++c0MvxlUvt|lnVX0X~6N=DwZE=f;s@Fyo+A}jux5|t* zzbFT#Ip|J2XI1^rmx&S@yueQBwcZpalzD`J0kZq+u3fN9c;VRF zysqzzW$6Q)h;7rXgm1pv`opH?XclGVWkCCIr=4Uoro%f-R(f|f%z8NJN@owjjfOZKUien^-PjSvAv7W%K|&o1rlTXu}Pt?$;YkhJso1Lu}N|_(%1 zs6CnXdS7QMR5sh~AgVRKfq9`EZ{Xs521%aU^#FDY#%A|w=UM47 zED?_W>U0yzuf_6c?kGv%#j`*Cg_aFEBQ>@3p5`9&&QTPKdUI?B^l&zGUwg^(rVi1b zK3xz5YCGoK9Oo^b2Vk{uHtMd5!(lDqb)+9QPm~H7anLvLy~}cFT;KDp$8Mc)nU5&K zyP8|G7 zcMGA^Q{I&h9|<*Kf4Np^?;-nUs{$R%L0odEYiHY8^B5REe4aLF0jNIHRCVwP$SJmu z?B40W+uy^``nAIe3@uMJ$^&qYxY%&M=KMlC=RlRd4PTf3*WdooI+IoRUcNQ9R{0F} z-4K|>b>cN}ME2g>*RzikopT(BM_JO|n_rG|_WGD(PU`0#Hy)hKvgUT%>j+Jp``xM^ zi4+R;C6JZ{_%nS& z@U6JK$~R$=xVuWaJJiSV7cB+Lp67FW#IJe839Zv%^l{mpn%Ic`UzJHnkZvSNfnvKlyq|YNX@Ad4ld!84cYz z>)tpKJp>NGkaO6Z?|trr1<2-8B*MDwSs~<&vVGn&x6ecCz9tcugK=WxF~kceINXo5 zOicoMY-{j!+xh0dZXLY&e?Kj>4)K2fipRz6IqO-?pZosRAUFZm)zHfE6zWZv0l#-_XrP=H z09ZE&>{YWn$`Mq!xt4o^W{6#SEoGaF_iQnuZyf3g*_Xl_C`@~u~=fF;H>@c)G+cQkoJW4 z*?VuMumQ##bfuoCGcJyintz{KM>61(dEbkR4T{eORou{~&(1yP zvcT5purgJhSPnX)tQ?@*7jo-;mpbK<8GJ7;z6<1TH4k1qS+uyU0_q^-&}Ce z&DrSlbc?g(`v@w4!NX4a7z<DvkWmMc)Zw*411NE8yGbnuJ4CKE1T&{e>U;Nnaz7+zjJeq*^PBiYv9bYJLu3y}?`bZb z4V`zqma;u!Plg4dtajm&=Oys>cuk%^_DvUYk-mwf0 zuvQKD|A$h)^?I_iRT?Rc+MpES>yY+Aqk(F-M&>3t>RErp<8M8Io&)sd}K8tdWk+uD>CvRHV*du!Qe#oYWfXsqxMWaan^jY#Cuu<(w<2i50luvH$OK~ zhA=ziTCsgKZy+OfHqFiuAQpch~$sZik9dnNH<#WC@saPtR{=719j3*Y}Zw9O6b z;L@>Xmp)O1^@B_(vBTqF@3DWfgS8%PDjJSn)G4FUvX@TU*_0BOz!r{d`@-DdZ+l@z z>Crr8I+9#Y635zwc(?oPv!QkE@q(zQ_kWB_NIo3Bx4{wjU5EDh`I}wuV)y=7d2ut?L8d z!{bWFli%j{oRh>%uXkZ51Y^qyjrjUWd{$IjCR`a%MbYAD-YBFufCgw;gp3j|l&ARv z5o!>50i0Tqxk^|U;7LD|dcIs1Cn%fxg_IZF+vo?+*Z=ov3ZUv7g+q2_9jA1T5k=i0 za1!L`| zgcjDF zF9Va7%jt4j-9d~C`cIfUICf{7*%MWn&)U3=XIVc*P_Ffg+X)VKY`iL_Z42r={%oKML%7u(4|Wj3Ysh9Rd#fEr?cxTe8V{4REgjjzus z2{9d&nkqSDeHCgHsu=(GrZuMBm+TrF36^ zyYS{QrE^|H zT>dnn1IMNspN^iMOTc6hS~s0q*xE>HnbC{6?Cl!IjB+S2h%hFx?}%SQj>-E5t!}&bZBGy|ZZ7jCGYRa)>_Zi)Hc_K(^7Fwa=cbkXn=3bDk_u`M(FQ zC$l)hm>|+d!uJE+_AiAPklf~M`kC=P%K6T7Gewl84rF3G31&Ss(i^wMMXA&3{KDtOKtDtj;5Ovo~ zz!J-NT>bafO>eB0o}~SmR(qob6g_#?6TM z%$cWBJJtyti%ZM}f8CD!KN=IA6IiD*e$}arPhk;BP+7~fOkic4gMEBnNa+`Xp5trx zcu7$uwjpX7mm8^*-uXZ;4FY7}_HWFxPPkGO-mjB-nN}@LW5*B4hC`YWN{8(VV>9XD zvEa~o#djl=RY|-^#!lZWj5yI@rze|Z|-XP%ENz4mOjtD+WvJj#Ut5YVP}~2`8Xk1WH)tvaBBVbu)1H!b!QdMG3GNziA7ASW2CqB^0Lq#Mhslrk6W)%%JclYTW4{5 zEUWGGIG8{s0i0#DDFnQNJ2E{32{?HnvP+S}<`8FH%A9qrWvq16rN-T4s`_4K|Dpo+ z687RU?Ftp^r74u{95DZ`-|DOKy*TMEqx6z9?GT`wNt99MxQ(37DX=L$$J)-vu#3Q# zwpSCusi>`5_mx)J{)ax3WJ}2m-~DP?t2G3ux5n?_uRECBGfe>RUV)* z$f8nHLUNS>lsRfmX8|;xoF0kk+pd)8Y|Zk1uW7R}j|PZR!y^nd2ur5JcAPMh?y@b1 z^9hbt-iuuaAn79VlE>gfde6bvBzuh=@-_LlbI!3ANgew5@43VTL?us0 zw5IU3{ym7m@f^MJ=6?nU?4+X=#3Q#KHRoISe)9Y3*N9_I4GQY{1*XUU_B=%(M{TeB zL2e?VZ=D&eqODpEKAO7f8qKNj*>eemG-xPF=889FRoTTxqU{9Ox!7$UI zFzsxj1|3dI*+$Es_b1wB3B`LvzbAHdT8!!z`kn6+=rR%*f-3Ono{Sx|_acG=^mydO zM4E&+6FhPGd!Jwt|N7e>cH3&@mTRft&-dGZpATmM<42t?4lw-Y)h!>MzOFDhU`UrZ z?+WJ-;kuebDL;|yZ@NQkhNy!@&t>?N2cpz(%|0l)$nb$e63A(Um) z#65iLKQZ!#pWA(oSl{;Qr%-tRQ|n$$rZZ4VEnP;NLLex(Q~Ii7I-Z($S%2OZ%AEC} z5Uec&*?0=#Jg)3zL*JWI*{8IXKK1yHj~|<-TGoNuS*F6q!XBBU3R^Ga>g@z&PnA$l zH@jCmaK`0xUCEm(HDMcIe-_nji+!D)+PYdW?3^8np=vA#9+ETEo{BJ=IES-lG}egyL?UpbU{3 z3GN#><$bA99+}6cn}Vsh&EN5dJYArcw}E_{Uen`;9--tS3*@+VZc?h}Td93&YVDsA zeB$7RviihHzrF=qsgD3nV$BJB73dStj0j1bs5NL1e|+7n<{6lVyV~y@56nw#*9~Q8 zM>9q9nnuW!EZ7UWZ8+L+xVZb&Fmm)FuOvDxx)VF&sZ(5ZN{Ahob7vQ zTSx%f%Qm!B_@()B4_7{r^xA55CjG9z+qx;WJQdka#kO^zoOE^=aBg z#uueD^n%t1UV!PP3r5Iw8%X^U=yAp#f}*R46<}8dP_=mcZZAXhs0`Wzm!s1C)03YD zv2i3V3Vl}G(IWf2Zj>9}LX%(00lV%5eBj3>wKvpRr%SXBb=G-rKJs2q$jf}nXYr*gj*>gze~Y1(QB;S9){7($pn(&0m8s0o8#{Nv zC)YA5dc4iHX^ypJ9ywZZ_`cJG=4Wt$if$;85;j^8d@P&BUv{?t?%UMvp^Ha+&M}7H zwoG-_jwiatgeQDyUg)^;3H3Sulrj3;?($gpO@%U*c?dly=c@?YVP4;P~~=?J#RdV>sz-y!{W)= z&B2gBxyoM~Fa97|xL9$~mFq~2_*2yJvr|8)b6vGQ#aI}_7E%2jhz0q6;e*%__8Xa3 zcW1+%vy^N^&@v1q&~&^*v5(0r^?TQEJ)B4FHio0|Cr(VQMVg!co@2Kqx?qUYTd-%y zY&K;mfHu}O^o&OKA*f+xuR#XKAQ(1j^A%AuGjQTux=yS{K(Y*hPU<54=!3eW&!IP{ zN!U0F*}O~vb{)Xya^?td6Uf>jO6#}%Vg@75mitzd0lo(OEb4c?3`p4%+HTseQ)x99 zpv~WTf}o_*Z5J9LjWDpC^IA>b-u+Pm>5+gbja!Yh-YS(URPwYwcoQVK(LXYxvd>%j6?zK^_ zr4)KzT@pZfED+_Br@|uj9r}&wUv^{B=of<-B&nMhKpG zXFSu5xpdAy75H*Zu!o+gh;b0E1?JEwW2Zg@`&?rCcxDDm9mu@mwWh0)t+-ZX7HT^n z&L#vH)h8n}f_obkug6wNgokGimtO~-1ui}fi| zzkG!w&8Yiujxc(&9t=n6_rM!RhpSKX1eMBv0 z&ENs*sw;2)<}7W7f0X_NNEpy5oN23Qx>0O@dW zi`Vco_9M19C;0@K>%c@KpMYwSZKkCjdR}~ec~72H=UjDTE}ipF4!&Ho-*ug2w&LjckdN?J`J@XIcCrXY=8jWX0s9k5XD&`eNIC&;4f7 z^9xeJId|=$q)h%k~9N%ef@^OQHIIyGSF-Q0M z?g{zZ`uXcR#a^nStNS`jWB?9_qTIb6ESnfIA8c^G$1-R>8zh-7W5-!2t3b?HYQuS{ zi{X{@p!>Js%!D{L*YKF{*?u(by*9P4IB>Ta*QK@vM;V6EW(Jv997)SRy2Nr}>`igg z3d}L1ZSOcp>~t!ekUcJqR=bo-<{Mb_{>esC)A6-e0x*ue2<6wHw1c0+lQQJFq z%6e=WoJqjV%Hu)785!%i>j<4Q1V`D9iCZ2GQ`>kO;bl1HF+?EPcWR+IF+x`Q9i6>B z6+yx~Dqb3%pE21tE4o*bT?rC{MF{A5^Uk;=9*L7xm(KYoi;>gFdHLBF!fw4c3Yt08 z_u5>*t`ELVEVESsI_X@{u;84+mtsguV`;PIvs`z525EnW&mvWLUK_y$iNe~YO8d`( zID6ita=XI!RqbP8kNQ=+Z1xwDDcq^5Ynu+#YzU>5@-(mM(2O-3UkA49>c5f6(rkII zEex3l)B0*R2{t;uhlRLEW>=jRHmdIOu^+T?>^>+G!8zo7J-1Q&A0D0F3wB|sC?rjA zxV;148}fP8tkF7U&rwfA#;u$W%;pzfpq=W?o2^7 zpNZo=@hfT>p}yJL7g4P<{kp>7#wQC^W-sclc!h17q%Wmx#y>o?>C|A)tZ>~^^3?fY zw3!4{@fU6GJ))xhw{ayNXqDLO=Yr&p<*{{Uot>~xGXhB$o|g~dxWugwa}IY6$e!Hm zi^2M-wV|3sXK%wUEcn*Rx zLh+aaj)op!;Kj2vV9BzD1 zm6I428g<}(CVgEpDRO)r>#mbmcrCuBbJZL;$|l;wtj7kA`6SuDit)N^ATUL)_wa*R z#++scA#_KrBkALR=lpd%^>VuC)g_t*GUMKmJ{!F+)HHjAZP31r$>{B^jB#HE7YAst ze*1DWUcWn)POR*gydUU4ngjSQWH0^Q4KJ3L$H+d!+7s`cvmngNly-Gq%J>n)FF51}vuFz;peu8=VOw7lLdrZz zRDInQyw|68iSq=byCspcd5~?G>)SrZCN8?zM)oTNOd{hwsz-+!H)^JGG~Ulfged-l z&ei1QGy@x-$%FVBoWfsU|5z*9B>kk*e82>Tf=mX~P;<~A=cMDfy>a5B|E&V!U+Nqy z959?0(8|BQe(Sfdzx`q2Mix0M+ie6FtQWNcRS~r`SY+^z&*cuBb_gsfB~&xktznA8 ztz{e-=Q=LeDSO^=r2@Sw=i42#5mwP~P3q27CuGuiT{a{zH4^QSjah zp;f!GCw9Udz5P-kZt3v-r$yK>-h;$(cR2glp)+;XrISKCxQXmu@xjb!vpMHm+mxbh z6bD~_!+xOuurJUY7)ecR=;{3+ItT7p{%3F?$AaGG84a^G#2HUr5JdKP4|Y7y;`^7# zfb%TZm$KgPxCX<&?6tN^?mXjh(|_0LFts<9Ro*AyqyiE*O$7A8>@uoB0LOpWz9y9f ztbO*}JLfwY^UYFO+1h!5CWrJNu95s(LgMNo0;NpwIlz*_dMiGN?gNHq>g*8NJ)1~y zQUd_B-OryrwX3^Ix1QB_?p~2vnVuQi8?-J^fw(ml|4~P!txO{Nh{xpy>YS_7URH)6 zbh>YEJv52E-x+`K8*Cz;hg}zR3EHrsr)%lCxUg zagnpQJsmb1ZMVe+*?yTo9^h0X9mQ)=@s%=+?C7Lxq}|t8A6IsGUZIW?lu*gw8@ov@ z!5gnV-rY+Bb57Zn$71TnIiE98abK70xv%l*Rf)chv5MB@xV@Mi2h?osNbfR$`O4!S zbLsx9LR-irwr)Tzz3x1(od6gc5Petx0!yU)Y>S30ubEfA${|1WF0#AbAEFX1vzm zSh|1H&AG)>T^Y$)u9O3UYn@96J%$qzlh$e3o~eC}TUHJiLp1{ zu4$?3G~~3RJi2=0s<1BHZJy)SX+PwG&TPBNZ4)KOLQp(4XC@hiYcnj^{O3_GqAuWb zz*ez-z2$x99*^6XQff3q3rhJc^;4{QFzb7Z2uxm-CVPQt*xBxy&)D-krmwzPuR1=- zlnmd~S~}=z^tX{o6!D|KZJ*N2c#oa)Nf|fqMDNoIF#O!!DXTlzo`n#g;*ID=8;iYW z&tnFNDz;jw??#5h>~RGBkgnJb$2Ku{5oQ1SyIY54{nJB#=mo`B%AoD3_!zdSu$c;F zm^ZGDZ($T7*)0GyqU6ropzL`uvPDcVeX7p9HKVm~DkWp#H@+&-w^(G6H~6(+2gz|m z%x*@e)3Ojb6Wd_K{QC1x6OBEzZtPM*^QcPC0x=vV!=l+(?O$rvbC0;d@Jjk)0-=d7pZrO%f+8T>wk_);|)sBHf{@K;eU9nAk z&?tT$?QEg#Gs_r>lL|cc<}RDkL=SGi{iQuUDs-!1TL-G#JJF*j!*`An3>9|?v@Ef; zThqW^&ki<%e-Akbcw%fU%9!*d$!9FvSLQ38%hFO#)-;o92@!~C4kr8DaI=Falkj-A z@cqI0pA*G08VwvEXn=qL%45-u0b-aRKbCilY7^*>4xa-`>1?OmP`!@g`dbU=TxKvH zr7UWT=7calccXU{wDlWm>=XS%WQBtvAr zR}_m|H^i!l@gUa>16rW@8ohmL5I*87O4zucQ&7d=PU#^p`Uj_{$2ykq7gVtQ4ip@H z+qj~mp7n>OxiTx$V5^jUji?~=Vx71ikETrr#N34NO7+vO@3|M#I2338=Rxg0x@|#w zOS)uTx#*kEuJ_kT_%hDuuicvK5jzu(5%WWDXh)T*_b%9U>j*)InFZ!%fM#dm{K*3< zQf4j{+?NT*RzlFLL^#TL1$SdHb`G4u*-rhr9*3RKhBdTSwCUrrH6pHW9noSm-Y7ub ztL3C$|Diu=Ud6`<$A63+#{1G`_W}plNIcF|y;B}KL7V6H4Od@J%1C-BU#&w+jnI* zMojt^9`AhwI1>=;_iT2ET&GoTvGMufxQZqTTX5HIH);?!V>(ARZu<`j`tj|%lTvjR; zi(6O7Apg()9&zBuPmXB|jc|AZ)v)SX!;-Zy%0_aetU2X7c% zL+@Pll2=EaH~SM9m&s`K%GZi-qCY499Z-Wn4IzvyI5mjAOGK3ybb@lf`#o6f#@g#O zgZ9+c3`w(gt|0PRgr}*QFYA(1MS%;ZMQwlEKr@0bz5_b$eaoE!?oKu z-*G#|B8LA+?{z+))tY&PsC_$5dfFGOKpirzS2XEwbcv;*V>+ASRg?+18aBAC0Uh&C z^1ZM@_oap*L0H~n*g!oU{WZCVEsw=gyC~Ny zlG5mRWLK@wA zJA3YgMl9)OoZ94>WFgk9=kz4R^&FhtKGJb%{KV<_9){E~P&ezCAaj>Dk3)9+qv&?hr-mJLg7A-{u|Gl-()eE?;7L9d+IF-3Sz~xZ`>bjckLd4D zC5XUCMrljEjO#-c*=18N$$I5ls&Rm$&2u;l;ue_a!SL{X(C@Ipw2$^{&~4zX-;N#8 zLP$T@k$8}IitG|xxL=!D)k!-O)vzc!pd-(Q>bK3!so@PU#-X@S@jY?w)R z5YyQ(VexD(&|d5>&10=H06PsDEaP?dT2p&#=v_{dCEswtICj#bOpc#dJ8V>*uu*v* zRA%U*@auNp{`}uLb`t+q(0tk6usiYNZlAI*=o3fLId3A+vIycVdfavoPN&fCtvgO6 zU`FrgdBxa03hX{IJbn!J-T~DFpM!liU2gMk4LfUnbfr8(P{od4x2#Mdt3y9;P&<-; z$6a0~FJu7C&#}`CL3N;>9zzh*@5mjivB|WfchMul8@e{H#%4CW20@P zXMhiI&DC~IZO%B6s*k~c>(UI!6yNg;|60Hc#I2<|?-H};LCIYnF3)nVD>M?tPA;hK zvPtOXg-rD#HBv<&Tle+#{wX5Ri}bhllX1Ws$ZqE0SaP;%)jAa}bL6rMJdU20Ip4hbJK;E~ z@m`{e?lkzd!`Ss_!o&dG5yC0Hp1*H8)OS=iHX1FxiYaWywQiJ+mm}pns7)6kod3FY z0Qwm%1ecitHO@0yNbl1nmIi5^CcbypdmPZrIx^-~op_)Dp;wvr#ypTQklKMU$^OT8 zqq#*1J?#+d$X?S99qMJ-N#9C|o{576SlZ_~uo2Gz7?sd!;h>gKp7}f-aR6-K)~z3( zdYbPxzx1f6t%A}dYtw!DgyBp7*2Xyx$g=1g=w9RNfF-~!)cbeSsrN3E?8*hF)w7qr zS2K#9_Dd^<(*r`l!1xTS(zUbehL%}QC@!l*KTmLMR|rLl-RNKql)+!}a_QDUYyU(U z!bKKuQ%rK=c|06|mM%d|V|vs8RObxgV+aqRVPQaKGNwpnxc4m}9bF_{kMdStI)=j~E+1YbPcb2NlAmYV~{WCid9TyeerG|i3Wz-P-=6U4*wFb?k(25|zhYFU87{s6uC+U&PjENz% z^6a@6R`IvT7k?jt-<3u2y$u0vhuUCz=%5KX282v5QtkOfa2Sd?fQ-f1OASMdrAjY zWmn(YN&pW|dQ5kh2UFVRO!;=)ImG`}JrpEO?s8xh0k8w-#E7$!3+Q!if_c{)5`F3! z^vr%(qYfQTyXMx3?3rnFj1}E?sxZ95fyfW@iNs1q@w;0$Wz2osKUt=o4|Y?L%_}w3 zs5h5+>>i7Q6)pgm9IA7E-qv(!n@W-`-SDM}8(Hf`lzwSI*+97VE+>Jmeaicm7fF`e z){YLT0pz-Ayr)C)HTbsa*e7fke&uWQ`@?smJCn}6)6%;27_7lMS#;Mj7j}HU>y}d6 zb!|$hHe5sYp-tDufXzW`*Vae?Wf|g5aLADr#BJA0)n$x~^mFybk+H~N%}m``7Np0l zr$a}*#2@JMZm@F(gk+K0pi8U{21?B3EEPv@=du15z0f}B$JV#CS>*|8D$)LgR+mr*P7LNJx zRwFgFdTcgrb$x(QhII)0UG~+XF1=rTE#?*G3~FzEhViJ(S+R-i|DQw_t_owlzLVx{ zMc5~>!{Xl6b>D04Soy)xtYT-U>?qh8t#YdXT@b0sXU7-WX<7m#fZI)8avzCprjNlrehXTF8FMPJHJI2iZPh zh=1cX0G2>$zhp)Y1{x8V!g>plYPs#~gAK6@EgWXs?|k7Cz!M<83*c(eCqmiiu?C!H z8&ceR zuK{nceywml&(#?$6)L+#i%9zT-=<}qB_yDH_VGX1sqn^ERgdyIU}Lr?pPJBVlVVqr zn2^A6@<@ZpZ2@!O&FkYW1hMq7s4o3M+3Uqof0zCf;&#RL0uGQQF0eRUCb9MXCkhG#djWbRremK4 zVOM`XV&{CF7;m!zT0Q>eb9W!=^o}VPGZamd93W^>*GatCaQ;mj{*?GjNDOxDBUfIP ztrN3!I%A*Z(A}ucqHCsHe@D!;E|%R)bXc6(uWR<)c2qoKeH7f6kv+GjBflH8 zevOjL{c|P`S46gv+P-d}h_d1@pU;`ZPcG3Mbi5Ib(|w|>`i5_(^l)K{a)VIgNA9qZ ziy%VS{NJxn*-mb;_JFaXS%phSeFmuFZ<4-r?2qg|U1E9g^zgCPW+B*WpX(m(UOvCj ztIIzBbjRBCo)LPe&&aW}zUcfx5LumcDE}^_+$wXHGHnx4F=mIb?r*``2S*oBW6?+J?ha06V8qp{N7m)fv#_Vn7g)Cm|i3M zQ0l^6>(AC9L5H7zx>KaQ&*E%*2S{qwk(n%`%6|&T1!{o>v*;*Aa*l&N8UAIjVc%23 z8)HSB+$AFI_-;lKU4Cx7rwyxRCmhUhc4oVfa~Ct5Ad>g*!BHltX6f8J=OhUYmt3Rd zd#Bx#cRZ2Yz}h8cE596{Tc$u$P{u)1;&5dU9|HkA>k}ld)RqJK$!z*9cKD}@3`9=ia)osQHo#bbh1RU@+-JmgeO;P};RNH{2NovP zqFy3H+U@l47w1y0apV9l!_d5hgY71L`D;r=eSA<)D1{Lv zM7^%xdWJe;IPjCQg(@lphku#bXbF1SbSqkeH)eIVh1CQ{e*#thq9YfmT_B6@yOv1p zFn?yL%Clnw($a(}rOjyrNgC-pZjwMTr>KiSn<&tI2N22AaFHNm8gbhH_d=90Gv_Ho2Wr=aR=jsL_Rr#VqE}Z!)0O8JD!4d zC7S%NTS zaAX=tsCBOKY+f;KE>*~ryHa*;Kf*!a&FsE8q4_LR!T{`G12Gq8Zi9xNW ztC{=h+MAz`|2b<*m}Nt2z1C6iG7gBw>qbs#UNT=%1`S!TPr06S5{xo$#+|Wl;>u<& zu>|+NfGRayO2udkxhtc+rH=GkF`@$ANrW(u@ zIPPE!x%N9^Trb_QcC4D?8!_b_y{o^ueye_6`u_|Lq(=G^txJ#ExdL-#(Sr!(gsh&9 z^JOGXcwKwcgtG@>Me9j%!#0D8p$vwdYuLKNmJ;S7`^25JRv=W^nwmxDAg>4~QxGwANf)qCqsPin>Y#@f z0PEaV%_EDhtO=HxJ&$RD#u+tD(gP;}5ohi7Ne#e#mWxp7UBILZmuLGjaX4iAy}(hQn9>B!(+3dfbeJBEQ0 zXVW-i_Fx(9gFbZxVZO5Z^GvhC>&Ao(`dMqVP6Jj&Ufo(~hnz{4`NaW7d^a2cwEaWy z5rIcI?FfuXaLm#@{Rankl|q=B36C7jO*k}l*8}`czm`1z)aufscCHR{WYM!a;w*_! zgx1cMvNq-b_FU|}aW+qEvFl(^*#0DAzYg3!>9c~(`d$fghNy^G|W z2P9C_T}%}7qC*p~{_Z1fVJPcdn|^@LqPsGdOjxqWZk&YC=XTev&AiviT9GjTH0d(U z$LBq)ky7q|%2>$imt;1h`{;BrB9s4|F4>@{@+iWQCpcH|)v4}qZo-_H0SLAzF zcAY+^cOj<0(qL4??~dyBGr$Yikb z+!uAv*BLv(E85=Sd5x&-hHv4skYRS=Agn51e@-qc&YSI)m4Juo5!we`zjdF-!+;I- z!H7mLE((2eT_6-eQ&E4eEpt+*nF0ow>|Q2nDb_If^S`$?`+PsY_SHGBdY`u`2DFAi zCY+7fqmH3tjB76*_ZvIg`}~`x+HZc$!{NhUl+93`_gw@ai{AYktNVDksG$Yu{ z`l{@42~d5YZK1F>P=5K%^{r!`Cw;Z@U@P(UI#WB09oajl|DJyhgZ(VE-mXRJ0l>+Ah(b}(-nIGx&6gb1x5k1qG0 zaYz?2fj!|d$?K9q8Ip9!>RyraH=q_E_QLfo&Y~xe-n{6qBFEc(Ap&2j%oKoZ6~{1d|V+Jg+Oryjp{NZtk8L5 zC^?NEkJtxK-SgCwe!ILric@p_hhqqYT{04yLeiH%*5=yUx$ZE|Kv5ebWFgzE)it!q z-y@&@^|yU=r#YDBoSz3sE4I(=jU3$`b?Mh{J*(e}?WcXH-OpOjex3mXnr)Z(oXwO) zH>qRgl!*=ko%e}LGT0XB?QqVey<57qs3VKIbDfu?ckKy7TS~WuvB7&5e1u%x`MdO< zcVKp9Zmx6ps2Slz!jfmsHqU&OD5xfy7pTX-+=CP@kc(0a(9JnXcZ&N<=~m?u)SIvg zhMGB_(BHfau63IO*v+xMSBIgJ%b+`Yi#T?tZ+|}Crv+fJ@EHT6aX>90i>^5M-lR8H zkwsrs_Ph*i&<{FNzioQ*059N8o)gprp^u!Ax_|S1Y-r5`P@H(7W@kU?B}sZxq%)0) z2E9Lj*>j0bU*Qeg(JXJf4N1ViJ3VvseFHiS0v{Wu19jNMXQt^06x~&hD`W%A2YNzw z^6S=3WnU?K$eeMsa&DGKThKMENOh`{@yFud`G9D$>G9nMJjM<$RbMmZaK0ra81Z@4 zj3Gb1FSU;b-3K(tYxzF)yE5;77~q;*X4V&gu{R}5GRk)r>6p%@6pS!qj4 z#$_|j2E^!mc5e3~IOhtl7Va|PCInHp+4;d7s8!N~eV79mY)B?g{`K9hjagZ7>Qp#Q z9Nx=~`7$N6i8Nn&Hs6Nd}%CPI9}GI%aTPt%#h1o;6IjJG3C$ z?t`p7+T+J05_MH-u*i?b8djt_;ksMv9-kB_brh=pJsw-A zsMpdYG2+5GyuTLaE^J&o5GKNb%0Pn3cuIP3iW!%><(ymZuOgb^BNNq3cW z+m&Ov%pzLi86Wv;s~%J4%6D65>?q!M8Ar3nYw3l_&M9DbvD0|MWBCcF+dez@lCwa& zb;{f%SpJ{=4Vxq=0qLV|5)O9pbw->Cv!MZ5Q((Dyr;9}Bl^xiuw7`nEEwZR=Lmfxy;X3bK7QME^>qMl+q3lj?h!1E+IET(|B7mUlmJh=0Q^RX~a2|mr zlz_=O|L)dFM)A&UNR&?USb4l?f^eOXZyjeIzWwF+DbKBaDP8;J7~+nngkVJsW9d_e z2Dr2ZT_y;=MAdr^Ch=M-%({^s?IUnPu9vyLL1e{15zpNn(VQCs)693$HwA$ zko?yuJRpKCL^=snC}n9vP^%KvU5IH>8K?7gATe>z%^^ANT&pccZ7XoGZ^Hz&{vGyTnElFXn%)g7#$%YJYGe z-HHtkWTv_w%pZP3#y>voGjayzjK<|fgkE#K zFZ+UsfF(O$UzhCSfQIJz=b0R6>$3jOqJAw|kW`*C zG3&-Z)(RjBX6XB2YWGfmIX7gB zGiLg5js3pRmzhEN@{p#Ha~{c_yjg-{EZPsg4QA||yI?x|A1f4I1Yo~?_8Hp^9olGu z;lV*(Bocdahu1e>`r9)jS0XX|JU#6GZ61VHsxHgE_bKn=j#U)`Tw=S;JEs;wNf!OF ztcmV82K?W{Y1e5y2xx1!E)Nd6{`gr`>Q;*pX$d`V2-tY`c~jvmULvZ;u5VrcUfUF^ zSb=%@t($~0Cbu;6uq=vkWYo3@i_Ie#Y?4to>*D~HK{g*zLA7EK4&SGZI7~2_*!hsL zwi+t4xm{Mi;V3+y;X|p?U;$Z57lCPr`%X?1;#f8$faChi_KRXXaj>uMB98hf7`OC^ zXVC+7S>ZCJ1Gi4HlS0B`*`bcz;qxyvcHS&su%UFMS>D)LharVt$I8^Ybkyr3Fm7y; zTc^BmmKf*JT5?mLFScWA5^b~k7J)hisp<5R4t|pxt>mo6W(NRs+j?zIQYI2iy4dRX|f`l#EU|_<2*bAE?AR z=SNU$Oe=t2>mfjfwJ4O_hzK9i!6IW3Wy6{|MY*P9Dw{#rbJ&LZ`g$Kp#{2xeuSV(e znI!9mv}<<9lN4T9bV6IhR-jq*@BZ)Y(LaX!-M{HBF6x_Kj<@Q5gtO7;iM3`XdsH0s zu%I}ja6ofF)Cr}RsQD7S{DhLUWUake1NX3P@o!|!wTQ4qrW^s?x#BtTl|ZAK68aW*K&G|`e1D8cgGn+91b z!$Fd6@<6le@!sU;-azWrol!OBs3#xO$EzOe>xra~|FzG#qVu8Ccg(j)ILipjK@9eb zI&LK>cLkZ^&iAQMmu3F+SEnpC4Kp{XX>jV7!*aHQ(}nN+5a& z%?;GD-gHg@*6d737h|_`HR;!77$T^_&db22<_VAYjWz>QnWB83f3tbQ0f_CPO_x)y z=-3rnyT4GNQ(ONUS6@64G24!>_lB>p<@239R+aNsAtH1Bwkro(DEKHHemeFpU$?#Z zGfX#q(zVG(_O;$Qe@|y9OC?`gyUe}1$aD{d3OvDqDYR2Hc=b@?`K_mDw@Y>&{Vs%(WeQg*fQlB!MdT z+!ci?8#3 zco5|ziQOyfo9pLGFoY0PHjaL{tyFk8-s~9UL>Xhp0kmIrc;M`?bC1`b@Eks*;poMs zv+iMJ4WRLw^0e>lgJ>Q1wWvka{qv688gC?c#sO#9&t9=f^ukaI1N2m0{C@WS?~$Q; zI_)?(k+7={s4@&Wkb0+TylOxJj0VgDIP{$TME~J_+swr9eTI&gRjycQxwcpqJ?Ift zJ6vOBaPpmwGP_FQJPkh1o!Cl5Ut*g-qtD}OD;r<34&-RoVS?C5{cJNCI_Dz9EhdYuv2++>b4$))w^Jib;F#E?32 z3s!bt*9z02C-61fT$>Wfd|TRHBr<`GCccjeh+0+NgzxZHyd8b}(eb||KgTTEd>m9@W+_9BSF`8qc^>AbK!z~h{mx~6qg_)KHdBlHGuvVDPO>6#Ep zTLcBA;*GZ3+bst$vd~OL}*^P1w1(x<#n=KlbmyDt%jCr*SC&2YWxQ~+E4i3 zUCEkQX;*iTBhS}{@6vyw<&B$1LQ8xiE!j9?$AcU+AC2%Y1v0jf-GM50VICG+!L8aU zmT{7BHbSDW%Pu*YjL>!`!1i^nYAZNtA2Nq}t=sS&!@)==j*AThg|TOlch05dqfK`} zJ1cX}We+K={m5GIe7%D?7v`J8wq%p8-}(*WF#39&<2SF5x8(J4ODkt!9V(s!8HL#a4HkRqQx$;a$8-}es-lp$| zna}&^irw{NY$NR^(&kUrLObr9W1S?oc0OHJ-MO@N3;Tx9b{-D@ve)qaG9L@`(EAd* z@MRFa;5jqXIgwU=K7i)LOTkojqGy+=g0@z3HTpTh#h(X_CRytu*jJ|WAX+On+HNb% zDc9uDqQ)!^UV3Qy>_lSh9h-J|;pu!y`4$u#AwtPcxEeC<0z|5X>vqJxbXP_C!pYA6>9(>X#}@P&UH zYL!kkTG@?6HfT+t&NnTo*nU3#XKb{ov4(ODF^D+$ zMOt^Wx@!1#2Bi*2+g;_Vbo4sW9PO(H^ozb&a)ONr{fr}3&&oDN$ zE^iS56wbU8USywSF!j=ka0sij9;hBC=(Hr`g6}d&{}ga zrLuQMY^ie$Ugu%7?FySCa>`fDuE-J^xy)NB-1B>o9}Kt!`dZm3ZKYY zwqvf4l8aCtk^Y7?4UT9QsI>iAgCiIt7-PDAV$CI=$SOMLZkl-i*(sBj)8qw98Kd{K5-0OKpp44C3URnnNMCf9RLRzgEXmRa3@@@M zTyDJQAdHjXOiY1@oESQ!R76ckX(rgvIqUQY!c)b1+%g0~6aSeU4A|G!B42;o-|?!X zz343`Y}6ji+UwR+ntyW#pKh&+t|9{ii=V%KUw^xG=voEQ8E1z68NXK4QYpE=jy01o zpeZpYTGpWF*JWc}FIE?sw$G4VUY9yW8RN!o3{!ifYWyrJ8s}8flRrwIl&E(`Zv>MC z2Jy#_)ObcFjI|2Hn=h>hz83kVL|Vb1StH2C1H+8$$?%=s>RgqY=3J0v(c_k}^0)a- zf}j_ykE|Pi8NIxU4l1uplAB(s{5>Yx}&A@*3%Pyx#LKwv{}N`263)`FG>qIptno zt`BF4_kjP~6(-);SY^|v^d zHJG0{#P;#%o!wvcc+XwygbvgOE1ZWjJ2LlXsfo|o$W-l|FJq3VK9D3j_&AV2tV*U# zLpU!pjEneOU>|t<`lq$BP1XtOHzN3ru_EU#F)w9K`NwF55MPBS%A40eZs}Mk`kGBa zY)0N7e`~{-7016Gj(F1ij!jyA=*a9XB90-Bs5Q@mBW~!#d`$1DQ(9E!&0q!w41gMS zgppeCm?OMQWCnS1;s#9QL=_eg9r%doubYFe*DM)Ysfi2DO!ON(74N|+&vy(FvE!^Z zLE-atxn6>9M2l|5y6MwwIN|So(PVE~SF|`J4pLit+k#6zpwCX2mBc) za$dl;xWeyU!nw%>IpuijJCS7pDEZ9TIY+>QGqLMbgRH?8jDvU#$bOHOZ`rx1U6=0l zJ)YtAN}cnd4+Mc>`(pUsZZ9&1Lc)ZTBXzq%#OH!>#*XHVPhF+G3_5>ui8=2JOj=Wy zi7>}`jtsBRN#}!k8Tp!xj%o4PID&R}USl?EO^|p&7&`j(^^Za|FEKvH04kw4%IM)8 zFWw7grPZLyJK<(Pb`&x$6EhxiJiIwj`U;z8I-=iAGIEpJWoP!?@vlA_rsr85ZvAvF?+7TF~f5-irfoBC|cm5 zL4Yy`S^&X0BB|k8dBk}hgnh*eYvD0$&?uiM{+_YcL@^9#jOBr&5=PY-zkX^v9iLUt z?HSXu<7Mv&@2ha~&okUw4F*F#GM?B8#Voc5^sOvlUJSy%xm5{8w{I(Nm%PD_T4qnp9I;>a4>~Y%pODca%D#Q#Ii|7s^@x=DS-j zMHH&Aj~D5`lNev;4a%ykV(<7ivvbYGS=R2@5f>exj;Q8W?QL3KSe4zbWQUD?Z}2c)~H{9&KxHZ8;rVYXsvhVKsx=EWz6%ebcP<9kLi&HtrvBo>e`~29V_2D zkYn-tRNV3~U`}5mSL?53hsJJHts~B9M<*n-mb1TufysgG6EK8}E#{U94P?dhL<7C+ z$OMeD=uw?Ksr`m=GL3~>1w9w|-E%wW@`n}=Rd=`@>z7cP?#&_wRAjDrOcWzk2cHW2Qeb<%=k?&6tlu$% zBS%%tN>HNub3bp-dHuQm=Bi9jyeDYzsVea56oCtYVUIHBA`Wtt!5QRG8#bpf$faZt zb?+6~>=NeV%t)r3P;R)}td)6dRRFQg}GJtiE%bLfDiDGF`LI=Z9 z`j~C1yRmaVR&%~g=UiE9l$Ckql2!`@!Lg3<9DXp(7FFjG*PgT3PveZMdp@r#G;iP_ zB#KIcX{x^84GBi44PmYQrz?pxoN%-_28hb`ytr&A?hh>B$bPGPeV~4do7IFRUoUMr<(<1%E1rRT%^ejYJR=%>9{6Q(IU+~ z_m~4Oj_KCA8+ldKaGAW828(QRv5{|6I>MqktCJcGEuEA_W2UI3K+btEDgDli`c2;0 zHgnIy=WJv!<`vx48IO$AP?mBI9hex=UR&zSMjdT%4fpC^!{RtBE2%4HdXcRg`PR1c zj+G+oY92>h#&KdE@$nz3GWdBzuKcn_P`fNxvd(qq(@>zchp}6(@#GNy-ry(~7*1^> zcFqOfCeAZ{=PxC5oqOo%r1!_c9qcW}CYZB1fn#;(xe@_po^&jJ7YRms+e< zDEo}|F7FSS;b^aEdn&LEqU%z$wP_6zXVJ6!^D~g-Gf*ai1f?&B`D7jR7+K~cxy?pn zzougLTGe+JY3}k^-hnK2(gXdDrVAv^i@1OAq}QmUmCK$_sP&%Z`!k^ySI-Cf37&%> zobAvC>U5?pJVn*~qR7`&xRx~o1B2g;Ud-F-V-cv64l2}nVpdckPbI5>3!Ds48@!Bc zh)0g{(&lz3DZ?6{gy3z+m`5zNxk^9rn|NQ?nHF#%u%jO1dw7Uz72YCv{+SAi*gQhv;a5}C#l_=JA3Z?B0r;g%DGb& z&wVDS9~+uu0xG!=bk4}C9P%<`(cAOgimMoSk*sP=*Q!99s`j%|+hc@{YQcKkTm*kb zqIqN4Z%^$tqx5K!gDda5nmi!a#{V?+*R@VPD>un2S&s<-MVa>VUUE~UCFY)+qb*bE=X=AixJL(N{1y!7VsOCD z+3)u}Q{E#gaxH3f-rhRjoe2~^5pfXPkt(#D)j!AV&B?;3Z9!?$*mt`qVe}bl^1+pS z0A)7YC$Kw5>7BR#9vn@6Z5$v^A=-S{R-i_85By#1ho`(hogp~gRBd@)C#+eUG20t5 z=HRUC!&L(7FDJZun(WHfy4lLMg0EB1F-hnWW59`q!GM3rJ{AA1W7ZM1oBrkljm!aj zv3JnUPF};~0M5hL-~JF8d+ES^0M*_&F{uy`Kz&jCU1dP8Ko}4FuQaHE#Vpr`gwk*v z-77HgdBKeyn+0xBMV*Lq5L`Ww*|n735dj91-oQl4-odx6?PI|Z!IM(Bnw^*xzzgJI z=_`3LfAh=n7FrLki*pXV`Jcgor$hF?`LA1#=$xXbeP_fY=| z!yngLsh|2j)WqQ$%lP%zv9V(^{+O)YpWSgXLQ&J;;Ji3J8Jt-!b~u)SZW&k)Fn8EF z|IO7TTItF${L5a0gEGlEm$g7Psn|Kk#{HAQe8oD3HA2>kZu0V*>pvX3nq3c*R5{vg zTNqwnI$sqZA5wZ){hn0TdbCNzriqq`^8Is;AB+dA$NE`1Ch>dpGx3|^^;z~Heh+>> z&ZBifD0f}?{KoHTdMwWcqxFvID}AVAI(|Ich=K`qaR=#heU5?a>H{X*#r+U-QG!!O zO5^7Kd@!#{pEQ20NYW!}82DZonX&y~j6KAjF>T+Efq5@;$J(7`?>AT<)K-~ijzroN z2slo4w#D9(-@D$x7Fehf2zhY0=q?N#$4_Kp3umsi-4B)eNQ?lphfq7!>LyS9J8)U7+9?ijw zum8^v+jTz%zK+_B@#B{n^a}*dq8HUQB_mT=Cp}kwoM{OT^kub?>{zf;I)ltOhdhN z*U;#9r3IH|d&+9(=FJL~Vczz7@$tD9gNtV#G?Q6Yx7r3&IXx(&Pf%hXd++3|xm;Vl zKH+;}YNhci*zxzW@lm zXdPYBAtETcTl->~UQb5nZuYkn#o^Yqwb~^3y=+q%Hg#CTF(y&^FCFv?hRE<4tNkgV zb8=*#H>(+Gl9A}m%rvgj+DZ|NvU|D!2I}$@F^=iq!wbrU%|adSVtsqAJqjH0lwR=S zcbl?alQUx;gQjid+C!XE(YUcXxB|-P!=;Y;g0%N|kzK?%aT~kSIG_a(pO-d`_px(1 zgJUkoi70c&K8n^8c1#mlx7fJYjfL7Elm-RrTs?aMRqIi~SS!8sb@$_Wd!l~|C@&A7tX1(UK3Jfj-E?6y$!+w?1PAUe+du<#X))snA zI?h_=6n|z}7pHYc7*CN7K(N1RXah_V#JhCRFBsyQ=(3*BRW;MIhz~_==4!RhP~oMN z>~1dGTw=^O;hY0mB(6FGU!};Y24(zMR^wbWgzaM}hL4F+`SCjC=0;##L4wrfi}mb>LF#$H(5U(6%_TBlC1#R!U{v`Gf#K z)DL@ik+pph#D;GW{Lvchs3tFVm*^hrph@=zgJuSL{z;p10>FFHqjnvoe((#A~0Cx zc$e%G2r5Re6|EC>FvmV?l}g9HY~5)wyZC+67z39M`UOSoq*rB>d@bXnN(J&5u2t2k8WGkw zv7)h;@g~TFaWj`Gk5Qqf45}*|(ofXrUt|*u2H*rIN7NUsIW2RjK<5#I-ljR)YfMGS zw^JF9_~p(mJ8vi>$e0W36(Ni%nCFRF1VH@9*S$UE=>2Y0Z|Sj`xq=g3N-wUFU1^Hi zu81<<3$>>ywt8tIds?KUSIyjyZoW z#(F+i80-Fg;<{93<@7kpT6UIEU#nI+u9|1FX469kwn2sWVn6cY zo>s~NDCrCljxp{yK(rRED=!fT#;4DLLU1)OT*k(NYlZu;vAs9Lk&*R!^lBbeb+?wA zC%jjkF0*XOsf&XtmTV+RdeW5Gagq73%79~2$kt@nb`6ik?2Y0&RHxp4=?=Qkoj;>q zYC1hiY(A@+nlrQoKu_vo*7g#!Be(cK7-f_`F0EsnWY9JNr=b26O7lfy!}no-p9~1W~F`$dDDHB}GeWqsbn{tA6(O!`H zo690Ccx+?35equzx#KLf@bNg3ok=wxD!wnbc2MRVKqRNcKmscJ-;M`p%s^N~#%|;? z2_+(QHf1N+*t_w2g;nr=^jwUaLJ)Kj%6SmIGtk6{oc}5H=2bzeCLML96~_j1k@^?E zj@DdsOG~qOF7{zuPhyP4h=SwJzVQLtri|)XDSOq%Y!l-uoG;!(>x#EcLTnUQ8NZe7 zQA+{^B^mh(QwRy0ex&=e z1lGo#e%@m!eZ}_YZ|R7Bmv(AiJ^nl-Sb{Ez2IJ46I9w4*Yi9@jOoe&l>sAa#*QvK( zii7TZQQt%hE23rA*4=RM9Eth5IfV@XZ%xedCL&&pI)q&9IgNVi8*3IJx%RMa0V{hMzPr9CJMk zM?ojoQ(cT_oiL1QX2SzS^%0wi=5B3$mCWA`T1ONV4{{_SQa2IuivkIEYUce zHeZVYz6fJ1ny5PgQOlxy*aOl|l4BvF+;EhPPR~*e4%73;zfpXT^(yVs@{;FPG8(;F2ewjq z@ALB~4p)ZAz7Gkw5EzQ=#JT~A_SAhRZ*=Pm7*&?er2POnDz`~FLIo#3id3D4L8OMO z>jN#g9aA}x6`s6*i>piMSPjZ3#E1UeqS=69FLNzX>_Xi&Amma4crgpGNT znrQ#tyOS0_ZLL9eyknGoC?QWV(6btQ+uvbY_^3Kb7RhFNw%zlo=E=nwdQM;8oN6t z=_7m^uYYwi;FC~Qa~?AJCC+-&j(SD|&c>;`6&snaJY4g!9IKULg2iBD`0N z{WQUGg@HY&OL;BReUM{ZvrO)!E(8cnXol~z5p94$nRH0nK=FIN%<0rDurFp=EUGQ= zRYiG^1Gl-hS=4;%%BpKz#G-4(ML-DV%rQ=iL9QmU=8A}Y=|4JizDo9$*&K8&AFBAx zV&i?mHlC#(^r0kSDeXdKFW-#VJYnrAv;CKWVtG#4-f^B0d;!nai`JLW>Q4hX(*hEW zJLo=gyc7E2M$oKk?93TUVPjH_F-%t~{rdjmh81wj@C3;?loReP0e#o`viX0COxU|&oRkAgaQ!@|d zbkP5pCxhKI${ibaW{f#_`}2S2N>Ym26)?DX{2qapOy~p8&Ot2FRwgEge&eO>+Z;Xd zcgnMhCJIVTD;d(PXH|=|MY61ugb}M)15G*VkzPPlYp#Y@RFfXn2d{$|(3rvQAfjxz z(Ycaft$&bPLuXVn_WLfJugZB8vRy@OmooOn932yug{Y0%{h8kA=GrURA!UranT~;N zj#=Md-ZG3r5HG(rHtR?fGp|)z8&$_fpBU;0!%ad|8rNumD=T-iFL+J8SzO<8nkq8} z7nBk{uV#lEV<;;M;%}S&IA#hKHUWR0f)KO{>a9voqiKY4STMdVJ%tcv#;R~ZO1WQS z3^eATS7t`N!L$m6#~4_&;SB2i&k}a_Q?Ei?3=Bx!AzJrHV8CaS<_rLM=T~SZqhtV8 z^k6Ki^O_`g`9i*GvL-n=)p_u?nhT)0sDmF3!ya11eD9N?zkOX>+r<`Rchu zw5yvWIENb()!$1TqHsO5%|~dFGdoRDgggGx>5C(dj5z8!H}KGGJUqx+8dKUTS#|Tq+vLb+N{dc@en)RI%T3-T~$FX`ixTen=~Z1g8`8 zsJJFb(9F_K^hjetOILpny8t$5HB(9FGZjk^&yhlS6VL#?9hp0`D*wy;`yzQH*Rlon zVkm=fPA`=vdiXld!@$+gZc;_v@2#6=N>B7jLZq{z*wtgvlGb%a)mjqafXBzwdApE< zuC$z73mf^=^RtoEMNIqVEb6AGkMtID-Xkbbzz${!7+K@xVh{T|F&5T2oIMH zfJ1J7hcH~7s9Zj~?|UO#`CFR`6xHum8c<<@C>Mx(hGQ;9RYTUtExa358+4ZWPfp65 z+c>*Ft^eWJXZuzrr6nVg6RzwOC~kiIYr4>4sfd&Q-ZjgjXT8Ro6B3CWhEf5sd`+W_ z>z;qAHIct29P~-zB$e+es2|6eq;k9rOrwogF&V@FpkzmD&~4m)tz)Zd%_}o2V;OR7 zOUZ$+d=%TRU>#ux=Btt#*yvamqqLSOxleNbr_q$l)`OU>k*_shZ-F@7Bl+K6 zV(8TO1K!Tq75Q-$4Dg25#iD|{bJ}AVDYu)X=6+rf5+rM`^;0Px7on+4Um-wLuWX`> zp>Pf~W14^puyJDTXx9DTuTf}`+bafgn?kM(qG7SKrp0K>5cNdIev}IYH5C{rwo=oi z)_E3(tHM|iB*)IHcOB<)(2D|J;XA#m^~ZOkr=OAnyKX*Rr7^G*FLfX@Il9f!rlOim zS@ajK*@=QLT1Qrj1vlT)KEpE{bD&gCY_H~=kTR!53`%QWlxNm+tvD*_#}l*Y?zj4@zRJ-YU1`Dqlq6)sN0w>{$B2XPYyYHsg4CkNi$*s7rUe>S zfgEMKq3CxmBTwUXhhjiqO>o`w&RWab0qWTBxR^VD8n*_jySWzBijRy*A6ha`r2NFg z&e%q&X_PyV_14a@wr%0U8Tx}G7Nhn&+L2exz^$B#9+-^~NiTzP-qE(`1w6^5htxGdIXAM6W_ zX=N(SIV&1)PVddiAjq#j7o&D}5*+&kj4(^HmX%3z%GiBgvrdQB-f3&^%5@KDxO^wr z#sx<1=jkPG(fry%0^AN;9&`}eI%LqKI6TFb@{kr3DCIhfq^yK1Y%$tNp${n4Y zkfGkpQwf``Wz|6sClm_x5~bzEsYx-bwh$s}B{b8i@15X$D|BNkbABYFV(DQq`wr?a zAJa{~`P^-a)f-|YQuDN!h0EymZZXnhDQ@`1wk~zbM8;|F$QIh3XgEv|ok14Q*FWCR zWxCc((LHb6JK8m$x1)LI%oKX78#`rX14|J0Yr;W~v*ELBu2B{sqa~NsXRf&Z5eAD* z%>79%^J1uhS9ZPCm@3`hN`9xyG$hX|#ttAg%w^}iC?r%w@tT+QKi91KytV4Mo;g+f z3Ee%)`>$6aTNlfOf7V4HZW^0R<{z({aS%49Vy<&*xJxvL^0JR+#%<_AGUt9WO~mw~ zAuC0z&t8bjZgJg4@9ch?{z<&&F0yx5etwlsg0ok64X0PdCp3tvWvH{z>$BSMX0qEw zzJLboij(G+AqA9yeJ_mIRO2iKm2}&l0M%*)Ym!DB0;60pA+8; znQ$wFO=I2JFz(M3n46=|)1B_$bk{m+(*TbSucQa;5I=xEfWsIY9hfRb-_j_$n<66Q^`Jc!7Oh$<{19FuA zyL_Gw@m|bHURMrt&MWT)d_8s+sgqs=Z~kX+z{hmdVIvpEgloy;;UyatWA*Y=9cr5# zeEsbY8~%6f@aOJ_-|BxSgyckvBS~)Zu-G-ES{w)@8h&5OV+g`8V$g4MFktgv|LTX5 z09QjQnR9mxQg3Qr$j!)E=JEU_9?w3rb{IPgF5`eY%47#~0>?Is#!GfRvvbGex%Ow^_WR+kH}bL z=7cT)d`&a1(QN}=1hkL)gq6X|fU(cxWzZ2OWO5VbV{d;s-lqn@=X(eH^Sr@cXJ_>9 z@tWWQUMAbSFB&A6A&eeQp1hv!oX5;Jw?3y^Z1MoCDnto7FlG{Q_;`=RBhoUGhUR&!i=}YuqzDYth|)#^@o0-c zc{9!q`SaOd7x9h?5i^H`4u=2B24;=p%(9r}J=C?VBWp95o-RY(G#sC!*!C95)G1AO z*64Sk4t=aAu{Z3W6sgy7yS`;(yob6w9+cb^1Isuc(m{f4Tz8E#AvIx=*fg+qrq-ic zdRSzQmDZ@c*G3NgI5Vi2sV<|~7g!`E$P3p|4OFq>Cf1y5a1er^61%KEuqGGwm)0j*vE9NrfRAjB=YkW}|eQog8e8`?O;4@f}hm;KYBBopW`%DeZFb zYn#`tiHp6D#!F!e+Ug(3*@Nd}p=K2rfbc?9n z-*!yAOxF1zY-V|0Q=hLHGV!(AwdwH+YapsSH&KSZ$dZT{VWo)1-&yYaUC9WrlJ=t# zh%j~o?HTnrc^y2&G4VMAE9yY^0d1eE@ENO&GI|c6PPw!XL^l#DgY)a30&SSmq(FKFkPO=AJ8@>Hyx^s?Tn@N%be$N??`5V8! zUhW#>ZHtwy5q_+cjhEA^_XLe8n@IUBQQ8XuX<v@^1kmITRAR|=a3`t$U<&jKU7*eov61^T8l-X0aZofsYhKrEene~U z$pcR4>mmR3S)b%fY8Y={pBpM}V-QE$<_)VD-S^UtjMt*{<=A_D`#7|cD?T?CK(Uh@ zbpNjB{K7}Yo~$EE2VF{@=;H?ULslH|Lhn|*pN(zNE+Ebb+I!uEp2dP)lc1Tx3ThVz z0B${rUVC@+`RJhgH=?H*RZiN$eYeG9HMvP^0AII%>S(^EH}o~fv9pMIR^_A%3&Gg^ z;NYz3df}u0a|_Jq<|nmXb5Q$`iSaBB1d_JP&S@$2nw>g0m8)>n{dZl9>hv}Wf#tI* z7Lia{H`&4eAe8U>`a9?<70Mh$d7XS~!rMhUdJJolv$8;%=~^gtSFX+8aY8B7zAtqV zr<*#_u~@qwDClmTKg!YaNy=O@2fKy}ynpVH;vhjpf9KEHr- zG;yDayKB>Q2ghG5HM1uD4S&;a2fgDF>qi87JVz&0?( zDdzkJ#`Hx=fZ?~GEQzpJzqfa$yW*KOhRC`HAbH=gDcBQ`qE*=m@ieADR*2Fh!v68 zS2i^#ZHey9i_&CVtVZZw<&>kLz9)B${7BS2)N&S<1uu4W3TGbOuy!bPPD?oqGvF;!njM?2CQ z^fx=Tz^Hi#j9z#%LEl}&r#OB86sJ?G1FLr0r9>XRw#>#rlmmORDnDlrT#*FF3 z?Y-3DS(K8B7I;l$&GIVPk@CFjYb^l`5e$2m-iXgZ2s-kFLk4YK4ViFl7NE(^BdAk_ zT&A22py6NX40`8D77 z(e@7Bw!FS(k8}4~=%$cws(-K+}y^U&Y@F*quFG=_6+G?z>P4Qp|< zH}G}lwL&_qoZ?uOYFxG6MeTs*>Ve)iVnM9B@6kCLJAhdS4?`EJFY&q|I?vuN%(d{$ zV}bx&)Ul^Ab@_P_3)QkACgoXbgV!k$QyU>JMVUr_Zo9YnBuo^V4J~=Y{ZFFIv8XhrNRj@cYb0QxtE_>WfI0(da{z(ZA|5_&j++upy$d#nF{nj!9Vor6>qZ zVZnK;;xyKt$q}r1RQ^0b11S)4sd|mERx;>ij-oZ44MVo_b3ymE*8IuuzgcI}N<>_; z&jt%naL|?3ZaX5FbmDp_lL{ye;@7dGb>fZVUHwb~9kthY_wyTGZRfXJGPcnx8MXPy z*5$ML>44|Z1N&LBJpPy(BxY^!wuRtGG~}>Y4Pz^Cb+XHsMS4PDdQf z#C@09O8Y}=Z}4*nXk>wVp?Qu|@L|iC@_fch;dE`xft3D8Fi2PsFGL$4<=+)+7$Cd; z1@+PtOfo+&c#i(-yIZ|qe|CWj6*)yPVqHp`E+U*Au=SKjl(b6oOcfDb_IqxhRI%H1 z@OMCKhLE9zu7L}7^<~w=lYXkG4c>LOw+NG!1^2YpT-GLDuRv3u=A5hWrg0@md%VXS z&=SGPw`W=T6NHC3Vd;{Y8&N_Ig28v$cEsAbPcuNyZ<2sz(T~~2c~}TM@^{)l;YSFo z7`Hhn0ygM6FpC4DPwDMOT8Q%f(IGVm1ijJ^UJN$u!4mj7fxoA|LA)>FwQg;XYw}&G z7(`RQ`LA0?!x1MXR^+IcI_Q~mY6hH5o0!=}CYTz67+DD$(Qx>^K-2g!WzYbCI{ZGc z(3|>2sPQC?uH>BZ)=(yfpn;I{RM)ny2#$@R>cz-ZE4cG&u~9Yv&^uge5^y6X(zAHl({k--ko}-K~C6;T*w>iqey_A}h+j z?@peTU=R8DcPUNxFxQG1c%G$C*~#D4Iq!^OE7?+92do{~#C`vU?8~ej49N!JKBr`F zcC}WW$5~$tW@`?nU6U$DT@4wWZ&kU+xh!4FoZ~APrSyuH1Y{TqK?|Ev+nwmGd5GFa zKKDJMsJzYzrj5-#{>@*xzv(Hh2~e_Qy7md28L(wW@96oYZaRJpo%nw;FHB+{@fbi5 z?RU-aNe7R=!RlI%(x!_F?c##lC5bSUbM-LS%58%ZyrqK7qLX??^?Roky`9rB->df%yFCnq@0NLhGnKMrMoYtV1H&_-%vH=S5_^ zoFj8wq_kJbGs}uK^Wk4Mix%MM_ zr`)lVxp7mnoL+FuMV%AsT%}W9lkaHOOtf&6(tcIgH-5~`zvizBDv*aZQtY6-Tt&uf zRE-GySbS-ft`4TTpI4r5bSi zAJ${Twiw+Mr`-ieUE}7g{5TnwzTEcy_~|rO#EhPOG54*TLxX(SWmD zWA){7?I@y*Tl<0!;O@ARJGq74KT1m>vz;Z+DSIu z>9fz@{&MW1%k1cAWO5PZ?-J#1654HC1V@gcavs!evtWjOOmjd>2@nvZmN7#_2?Z};}7=%~Bj zlRd_U+1Tf_0Xeq@HJ@e>)XLp?3;S_sspj`ezH3h!v2wKacTcNeJxrtH+VcgaSqn4P2cVnb5j^2by}`16+TEDUnc|* zKI3CX+0U%Oat*YTV;eO-cK!Z`f3hxuRb;aEwU6I4NO@O!d*+ZkySE8_oHE!kvBkw& zz!ux4;W*QBet9L-HmkS4N`hKyG{12tg@s%P3w)9dl5}_C4$=Vo}t-=JGqcRvb)x&Ja#<$(#>kf}I(C3}XzNtEXy)V=BJR z2M>PBt>fWy+1M(nCxoswg?s$~)v{f{166KyXBE*pUQUR6LQ_ws4)%QcYf>qIJH0vCIkA zbGE8rcIep-hmFTotVsZxw4=kKa|2&*o?{qGSocsGg)xhNcptfI(u+SE>pRK5maWk` zmh;B$>VbU_HY4T_emCX@e!EF+4=uJp2i7s{kNpwmPLum*+mK8#T87E`mR7ds68qX3 zaSodx&YhFnDmD80oZPF0-CL3EQ3DJg6s#89B|s9 z?~T805_=!fJ%v~A+vXquHkW~mawo@KlEJ-2=L8{Yo0_w@m#8Ak8cvB6xy)&A{Be3X zr1Y@tEh?fHUOK7X#0lO^*_iCbpw%16{+w1l9hYuQK&9~o1C)*SM}}rREGS48GT=VS zmt8|PjzFVNKclaxNG;NmGn~BnrJ5eApCi4kKbX>5buoB=j^P;E*MHb69Pvr4xp2W5>l%$RbCHR;jbLlBVd$vtFU9o5}D zp<*jPrM;K$TX<~WGk>07eJnDka^-3!d8X?O0*$;adJa{7LP_lsFivrwqn${;ZBr7x*|^88l?b)Za+bW$ z_Dku#D@LYR=?xD|kc1sz*W-1AI+p&$2AsAiQE1i>lWEcdTb_+I9PR#bpPKv)s3Y_B zn(=e4MNTsjGuI|V`~0S_Xp{_=OP^<>!zPu6NhsYglWNq*pOboRev{CToxmW?h!+?y zx$$j~#kZvD>`Eu3G#L|5QkC~q+p@I`j7k2@H_IO9L%vJ1!qL;V{k^d^SCd*fbtklP zx@eGKrPTPDLz)qB6ue18VIE}l+TOuKOE7l6i>=nOI`&BIJ=Aum_o_C{!v1stEmX2fSq; zBY*}cogcnIYXZMUB1m*Qml$J*cNBGCD1Wb`z*m(}&U-w(SEKwvYt6&DAoiVfKZtC| z$&Psrx}G3tVmN5Rf!3T3i8|@%z`~AQpb#UY%WKr_c@l?h!netL?AWUIKTEvx8oz812zzH^iw@xJ5tJW-23$nF2JW{S28{q7d_#1jK{ksZAnPVn2D5!(NL<1zj|ux0pl zN1F8>%eue*@fw77hIv)p{O5W{9krLzmlnoKaEvXS2JDIQJFvFEScQ-rS|y3A{N@^%r@V}tv(YvtCt0_v#Nepa9FWM~g;*9XlEX@9@EoXLHL36@Xk>RB4bl=<=k0(h8va zg$6v_gGQWl&@Q#rt!w90{W(fGRgpY}Qa+{amxtHGSbEQTMNXIukW6lJgt>&fU<^VG z&L@5NHHNd#b{q2{&dxd!y#5^?ytv+*-~89DM{oY$PkXc?6z68RTxvVf^o*X@;Mm7| zMrkwRr`m_yuM@dW1z-(Xw4t=wu}X)DUycuGMnr8moe6;;Phdyp4xCJF9}ovJFc8fL{hd=bbR)ea!(E}7G}zW|EW6MU8MF_>2u43Gpu=ANW>sIo#nm$`fla=KgW)DL^bk;!Ht-f%g_%NT8!eP5(jf1CvmAcS{o`(rxZilz_%IQCig1Gj#-MZ{&i0yTX% z%n3dp5R#*-?ulquIN^2a-mkASqegq7qh*}IzJxk;lbj)oDEqews=WH0IZ-kH_mJWq z@li=a@-cl3LkH)Jo%2k@E_GTNN@>pQs|WYHA|95zJw-c zV|a1Nv)Cy^eLe!q%j{VnBWs@seFl4H+FBp)E&Se>e1BJeCw>>-zbCCXA-;J1*6+&} zj?3+5I%j;)LB!K)W?&%{h`^kCzj@e%k~y;R(uX_$_VU%0iWE#hGdTZTG)HKvYC9?aEsl0&)$#MwgV7lHI}W zWie~&cBU$}n0EUX>^50H`sAK)e_9Iacit!4ZWD9#b_7Y~OIz$VkimdS)R*JRBMcR@cSsipn)rt|xX-BQ@rdQVF!4NfLKIjm`j+pG`mhDppA#p<&W zZKz0B0pi$~IYz5SCYFaDl;{`j+jH@zD0SyovPgT}dZqh5%eY%xQTs=pVrQ~*<$JI0 zP(x7XJfDRzFkZ80-<2ssbTttv&u_<%V-mpl=FRX9grp(?q^Fir$p9@P+@J`h5);IqYmUyl&H)P%E=w&0;-1QH zb&BuDu?P;bD_$@tI1oi)H$Vm0VsW}C%l%u~xIl)8GgrSs)JSS9{pVn9$^`DHN=WV+ zu|pn-!=a_$%dDm@54>kWtGwLC?t&9ZRYp(h(_<$r9Fwf8$2TxP5r}+IoqyGm)peWRvvhn^t-4o;QsuyjFU{gZ&tB=g9Gp4iot)CGKw6z9b zm#d{7etd1`=l_ics>#(eXuNHVlTG#%!xC4 zrEIht<@p8;2?&YR`F-*^(7a>&;W~4ch895F^KuEh!r<0%IQM3Ud)975-dpK{yo* zrPv+`+7L@(b4+y5>o3kWzB#thAp#sbuH;)?sbjB^`E|mWBWIDF;!L`AMn?C&(3IqY z{aQiUsLJT7=u5QmKWth(am+dQ3%ZTO4Z0oo8y3arN~)VXHj!slim7T?s&Or4s%(3X`95hEuC-Joq)!brGN~kpDbuCaXn$1>nQV_#x-}zY(>R88$ z??n~&GG+Bi&bO)nd&4{%7yMde?d9L~tz$8$WDO8U^Qib4k#S%8eFz?CfWf~F>&c_C z@du}fC?Bj;h*B{dqq;`AYiJ)(IiyZ-!SUU%^L`%?%hc=(8F(1)$TE0F)@Jejq9P8# zG6?I*IWxIHgtYJZS*V+>K?7ZJRtN#CIOCDap38yx4jQ9s8oRD}%c!5PK#sDn!G!UW zE>QdJ27aTcZ1da-3fophV;>g#rtA5L4RtLOSQd@5cs%48K~)_Z032hPodIXWkKv89 zo8)W}XJbj=XrpU7PiP5{47BxY0ZKsFF$c@AuG6V%>JnfPC3Aa*^|Oh&Rz`nDNc8RO&m(D9Ya75b(!1(~8jCtP275H00L$IpBg(LFIn# zIWRBA9du(novJ>K6$i}|$uE9(An%Qg{4u8}6OHRh9nFe`jmm(5goO}I?)5$*P;hcV z-F8t&qFEI*H8Pn|?AUQ`*l=-bt{JU8UeI%NoRlEI@!O&ciEGmmunk&cozKMJ$A+pI z92`&_Wu=-rF9$8xR3Vy9l)O!_R)G^1ZXgS-KjclP`J@c=_~?A|cL zYkhXbLFNov4Vhhik1#-l`hDvqTCGuBO2uAS;sihxc-YjIYq^i8vNPbI71kcnQLrlt`bEm*Wx`fi=Y`$D zW7@SJy!EnZD{uyOSND*yc1TvsfNXzS>%c|ff(`yU;QVvOysm?yt>irOVP66)zO7>1 zi+mAiIY{wbivS&h3P#qEKT%GxsAGcPt?kt00qd3B$z3lnQz>FL46mdIe*Iy4x$}%x ziNuQ^^E{Dj2-X$a&Pppx*P7DLyQL=MMLwOSX>rhOX`NB$Yd+dxub_=25H>CQjRZM`1~PI&({^tjm+S)CrV+RmAdW& zAY0Ny6M1W;z}ASK>I70X-ctCC(4y3oc{0eL$>SK~-%`>u7{8vK+BxXE+sjK-OU-Ne9dc_WYp`3 z)~Qfv+X8o0fVgg)*|(;XOQL8dRGyT8JSfz(AMNvdWp+kc_S~z3b1*b(=e8_lK?c++ z=j|$C1zr`Q*8KuYb5nz8frY~f0|+9@vzBr!!MOY)?PmR^+kgg)By(8P&Qtb-r^Me^ z$6P7#joQjCc$qubek|={?oyf#oZuxrY~p*R^v7o73PPA7;>FjC*P1(6q?FkZXVDQ% zDfUlaD!fmm^lTUS<9Xx7^n{XM1~Xl>_+lc}fX0jX{xaz8@;xSIf6cG673Knw?|8NR zfMpUNOr&fo2E?LBB4w;$w2>-EmWXdtZQG&NdQeu>J-WhkGMA7m|px;h)hyD zls~_@?)uL!trx;|K=xMe3qAJd!9s!u9n*283dZi|jA>6@myEa=g43OKjET&Uwdh|u zm5Qd>@kwI|M%E&eHGEEu3{nwFllMyQ{z1^j#sWB#obaVM=*ZSosp0cA{hb=5+8f_? zv5Y#ZH27i-kUA=G)OmdG7aggbBg2`Mb#~S@!!l3y9L9~iwVFE7rck7pEA72#kj0LA z2;5X;m&ZTTLFncGb?Z@`pr1J5Scl@z@U(aBWKhi77cnffN^)y&x#*Tj%u$)>92{;x z2Tt|;1j=&u!yc9y@2dY%)N#mQ` zhe&vcA)KH!8B~bVt+HC>;M7OXm)H+%kS507S;d+X9NGf4UP}VqxRNB#e)RNF$d+@) zQnTWbBfc?icWC)Vd$q&vIDGcJ2FnuH19PpwemKJ1Z6nC#IvXIcJ<6?--Um35xy!-h zS%M37Ak5S#(5egv8E+#gBkgC`D{9AuwfEcp+~tprz-vJu@E7mdjzQ`*syrm%nl`VF zejcFp=gH6>#$|X*qqj$U<03)TpzlMgYhNo4It)cn<%-US(hjlMthx^5yuj5LYbMu* z^QN1hJPNh;hADrA&#$bNh$$O3>f^f@T!d`&my4JcMVyRmpfCg_3k6!*Gte`u9CnGQ z{)3Op8HC%@9D7k+^qHxNubV@Ruhvj1-YdBaY_S)u�Gub`ybx+Az{0u+&I3 z9N1YF)m|Y&gJoiI-Z`Trx#_Z*89m;;6Drp(>n=1%(2xJm58LbFu*ZlzsiAd>0r;*cZ|2h{`kk3T1St zc$$bjdDg=ie7R9sQ0e1eXmMz&bss3foXPawvQ@GjH9vF4L$*9}_Bddk)p8q|KWDQf2!_jC zhhsR!_N;u%2Nw`<5XaSuGjL=0K0ScCKK5Bk?a9cNt6v9)*E;7*1;}7O;M&b90@efq z1ENGvqjS|9sB;dM2?yk_;c=lHbFjz-^o7;2VY^Ahz;TXv2+VkBALe<2?RCM~`H(27 zlX+uj0I%PSAA?2{O1s+Fv)FNw{@wBT(0zs1h&y^cW-Z~Y_1)I1&;t>}0XiSz=qA!x zBM!2N0}O$@RXFLH{bg>;dEwv}C3zhaUibDKgOp$E*U|GFIG-0{tE1(y*XBYQ1s-3D zK&ZlGjNpl^+6f5dQADjN-Pb`^=rklf@y6h2YW5I4IJ;dw`M#$$FOa7ubw)g&_&>Ba z5xtE{cIcO+99RqaC8VFKcUTxwyLlvO{%p6vpDDaIx4i(SOgL=v-Ww} zXK4#1F$%6?oEb!Jzvtn0fS!Y{KcnHOYWj+7@-i8XUSVRp_F`M0%ip(-syL`V0%Q-8 zvndCO8ko6$tM38c)B7{G8Uw511CAlDvKuoj;QV5OWMW0}>z0!}cO@<`25If)p0=>U z?YO0mw#UL4BGxwZCE`AT28nhV9eban-)HPBZTULO~tfjpXd5;KjGI2!vldB zYm+DZ1w1cM(y*F!Q4RTGovOdKcfDP62c2isaMr-4*TA{M_QD~a^EBzL;pgdL_XC_g z$&@#m5SfJ7xUcKrnv?^83D0Q+j(iYY*D186Mf*c-MM?`I1VhqvCw~x`9s$l}-QdEk zz;DQURnrE7l40EvjR143om}`_Aee?=`yP+`V?zo0sJ~d|8e?30+#Z7dD(*abm+yV< zgIYJ}6Nj$5I*-}JN0|l<)8&=n>H3KAJFkDU4%u_efv%5|4cO^^JmO9NvxGKMD~4lV zD5!8WHEZTJVNmR3)VhaIFHAFI{C$pXFLumT4Fma%%uHU$$H%GyM2|)+nPU!(zT~o&$a|xn;A-%G9ipLyO zj8l1?jJxc$U?!QpH?NNmXaxW@8g@b6naF3fjKwpLTbPgOOeGbw-B;Ln007FXx+qTb*KWCoF@%&sT5L<;~DPbPFY`XLk zUs@TSU)y_fXCYBKFP7>9y0k?2by~`m;SV3Z`Q^CiG-C1xM+#9^IPJzJ`0-!yV%pQ^ zoPbFlrsl#Y8=urpnR2JZ^}?h$AmIKKoO#K@hD;}n1?TK|kp^|{vyaYaKdYkWxh#Kb z&P*~ogCaeYz$ex_^J|J36WfABzc=*v-Iv-kc1`ZQeLdMZ*C0Vt3rx9jR1e;0#=pnX zUpFx?F&6yw=+*rk|N7sj9Os5jXIJQrBWdyX@usoEH}|PF%xO`RAO`9M5wMDTqqhM} ze$>JX-JUc0C=c)vM>qv)R1C`AD*?NC+RU{8KaZdUI|xoqK<2FT`T*g=7x5aiN>Me8 zb7(c7&VTf7HX){1v}D=sK2`w<#BBDDy6?>{pR>E{s0&-7m`(EM;hJXC@tAX1rFG)~ zb(Z>C&AjIvbaW@T z_*eRL(lu~SpXgRdaF0H7nLzh3Y(T%R&*EtsjwK-3)Uz_mHRXiNv`k?Q42=2t|mkS8E zyS5G}J^BPaO!;ZC6pp)Rsu6}hpvL_}I}J>2g?_(?LEa6CKF<`iY7 zJ$)nRv^RcWa2&qii<@$$6IoSj|Ea+MAHnWT`;6>0E-wo%mGAe(FoB?A+j=XoI;t}5&D=R>W%tahw!hJ7An#!^u~1RAHU193J+#{t$`wzH00qQ!{lAdf{VvQw4?*Op1BTX~02OL@#l z##mXO`y$LJJ>qfyz$9+3Mf*|%Bd(L&{`&v?fcg6!}u}t!HDn~?z{P8pSL*{(AB9cWq&f3x4lllK%Vni^Uf8Sr-x#5 z7^7_)AM$O82k($)94rH7X!mT_yquK4_|$=GsPuLjQ;yA&V`?nnC~m7=JHPmK($8+s zKiB4g3$$nZP1jM2&3$n^<5y~Cnw?L{?s+BZVpdumBi-17qdz0{+`m>G%t6^}Vkh3h zsJF>R{9~-k#^>5Z#o2y$yrxGrF>zz|bbooB9eXaiDfF>Mvt2F=mplm@ZiRCmXV}}w z;A?hyXcrIMWK?;yGjOzD{+*{CG7l0{?KFP&zi7EsZdeszrqrO9wotQdG?Zk%rv?PZ zK8Aw>6KX-c;YDQ2YS7)7o)$G02QckyqHdLcOFv}B-KT`(maGCBcx=?3psb~i!C>v(%(f9SlpN5LUfeUz!%(x% z0R|5A9nvR;@@%nlzTv2w;b>2^D?GD;9J`|LjLp0Qt`2Tx-MAB+JCpSYUoH_X$tXW` zndjLvH~zbBl;|fQ+s#I*I1+c``43?>bSgmK>tg-91QMLebD-wCAm^<^vgOPk9(VWR zW7mKH)(ZWNc4+VE9Qo!y`_CzHC2)K+4@d9WsP@h|f<#UAV_pPGjZQu~dqfRGFjU^e zG+-&!W1Hj`sXv#XtG>s5PI-Gt4FD6ZR+oeAEeS6BYh9~MF3y_E1O7V3!KJ8-1VW2_ z1Ur}Sq>EMv_Q+5sr;cviWu}q_9|5)}_R%ph)06`g9VsiySS0VAL)s)nVPDyv2z*?> z)sF*ybAPV4zkx*@o?tJTEO-?HBq8HyZrV2K?c~`G>|gLT|6N+n+Ds?FCu=a@d|=&W z+p%7G3jCQ(%|fk#>p<*>fAG0UEc^}mKE4i*=@O+75l+ctrbnIk99%KZo?q5_5`+x} zcK+a-59R{%ipOKNw;8SUY2F)N+994=fK9Q^|I+`l%^&*kxwK7mC# zdUhE687UjtsiT<>KeA(S`qNT2O)+G|NTQ8|I$vekeK{|FBap0}+~&>URI;_4ksQ6Z zjkb~tZB?@1!Cskj4wd0J!`?=aK-woXGy%&tU;nxHCcQ81cKA4~1cqqBvC_2fmzr?8 zIsP~lM=O+0W%2D@y(Q_GT zrHYO_;LgDv*;LlVAWp{_^+0|4(iacm*csTq)C&=)fs{I91*xe-FX>ufdDu=K9j0WKWfWyze;q@FNmkKLI``{YUgfTPw2DF z2V<{=^PJcxda99OZ+gSk?D?cNIGaSb(MOAEFalQEY>RDB}> zop4tp%H{91C*-ngaKtyo1<#`N>O>4su98sl8%HZ%pfyvYi;DqUBpEcjV0nr=4*>*} z-v0Z?g%)!-6nw4tJh7Ah-K{U#nSDqrL`*N`f1LRa4p(hRTN$)JBKtUU*cwNU3Y%M( zrM#jKmQ^q^-;Y)_hx`ea@-RtYNc*{!KO!;T|IU>S{|I2fP z&w;9-qoWVz`Z7hhRMbfnm$lTxu@<&*8@-hAH#5HNM8`4G7wGvUMG%BrhHgjI+}6OL zD6(T6H8kKkI;gXj#%(nhRg^9d_;AMDpZ~9~Z|%xHzr+9yU;kHd&|_T=*fNF^$yz&+ zU7Rytw!qI(p(S0D@XXT#vZcq0_P{6W5UgG&XxWeiK}9^(+w*hN%x8zL{fx8Gdz$}y zeV}34Yd!~^z7J!LlLttKg$#N$Ax~*eNXrh;&)p)>Q-^-4s9cp$Tn%K-zpZ|aExaSn z{(Gk%h%^6r$KTbNSJC3my0IJ- zGWjAk8FM9(VR1ZpQwRcbCOu0GoqkLmWs_P)#+DfEP?NCfV^Ve0j(x)4v#>*iHcwKI z&Wx2Xl-e54<&*K2UyjyhM(L6H%m<-ejWWX-`c z=E{1*)qX<|uBv5Xn~3S{JWu9kEoU7*XsK&{XanlL`MKI4m2Qjcg*tjQi?PyBb)6#aVo}Kwym3mOkG=TKMicZ(F-T+4IIrYwNA!5n4E;3t9>e%8=tsOk zDLX)9=Mr@D{fQ4H^E0E`d+u|1!|@r!o^+)c(eI;V6apdI7db?Y>%f&g?P%MdMW~xi zq14&+&UZ0L6SZdBSK7OZwyh%QP}culgCSLI)5hw@ZS`1F{R0a7!t|_pKGTkNUUsjp zFy8Wzr$&cb+Ja%InF&yM17$tRj%0P_yUK?P}>V^skCvM zaS}8LHGYkX9b=NHO>O>nGzF|7Va^YoW(Nm!Ph~h#dWVyAJwiKLIdIo$%AjQGyZ?Lk z_UHdzs^a&$Aa;(i7IzbR=G>db*|l|%W$+jKUM-n*pR>F*ztEjy5FRgkF&hPsq)#tr z_%xdw-s&=k2g{(3wrTJc1?RN3oJ0&lvfS9ndy7(=YeDM-2};^<;+If}F|(fbyRoYCiYpR+c%)hUS$Mw%0vDa~qjsc$;e*Uk%k{|LcH1h^LYp1eXn z)(w->a7yty+s+pxqusW8f4W zMSgvKT)JkeW9|%f>F%(y{^paQqLnci!0M2Gmke@~5?ejdTzsh}r!QVOB^d7L37fu5S%MbJcbm^XNLzn%I_S93b$a*~3^ov2A$9;2Gv; z{t0_idZjNJvB+OY?66PZ%1OO==C`*tqV?ImBu#G+(I@Gkhm1L{p#+Pi40EY!_d%m! z!S6K`v%QyC)|@eaa{3VE8T3M%uw1mt8K7`ZCOYWaZ&?R9GT%z;&M4i+e{M$UcHfsN zR-%3!)N;-KgkI#G`BYUwcTP>G2c_%Orq?KOHT9`xw4o|#jYMhf$ebYSrXq3rJMcHA zsLzVfU)`i={F4+*a96-BCQ#Hu{BC;P*?SoD5cNMyOC!tR_0yYEHZ%L&fA=v2h|6j|BHrY&5Pxa`C~;{Hfa;^b&rPvU8i zR$D@YoWEu=?xk6QP5EbO3aqr>%LFmAwp&HS4z4q3R!93&XSb+QU8Id`@A15`oTLhfN9NwSkW5Y!5$-XI_9WIYh1LW9qZOXL8C`&oy+LcqLlq@ z{~n*TW6<4sygbatk({f3-1@2wgljk^#^lDJX3JGWU>Z}-y~H9g_hn-2!?!DHr&$+4 z^Ws1IyL>Vpz_trPYV3*Rn2LC96WQ}p_<#oNXFFj|WYn zB+KOU{_|Dw{gaX%^CHi{NJLPPZ?f%>Zs}`=S5mgc&Ha4xZn^Ea)(Khp31`pEc*#oJ zP#p{Ry{>E3yoj%Voz75=!Oue=E|o5K&{KAnOal>UT|tUACi|g+BAH0LvCc0 z?np2$_X$}PL#gGO{Rtv*G#^|`E~j*D+y@t6!oh%&&e5`mZ(Q52Q)&_DZ_8i%80yoU z>3hI~eTVO#4Q(ndnH>FW>nT5WzxZBR&@|HOBF78&C9i_2t75~5YGi4C0V$XDP%)TU z5S-_nBI!8hQNmT^sV5$84)BB$I`e>LL7L=(I`nUZ?zE__4OD?jbW_HfbItbTAy*$HgoZ0v^VdJ#3f1(X#VE{kWwWtq5bP=>-M% z_;ut3*w(>O&r$YeJn%Jyo{O-n(!uZ@*dOK2bEHGklLuUuy;OO9%rSSZ+xAvju22u2 z2JH>wT&6tUe|%;_oo{u<sN5i`0nM`IA`XVDHoZ1F zUhB^bP?o^g^(YslP7=r1unlL=y%r7sS7>MELR(bb662G5Y?aa^14N=LV5km)-H3XB&}Wg)&=^mB2hpL6>#?o;S11 zunS-L`sW*Omr%b~=A^gL@<&^5>3vt9OTAFy;vojTXSir*2c?m=b#0nZY{%H)y>iE| zA7>D`>0YI0G$Hd{2?$AnUR}sKs}byI^a;vS?w9E+DE%D{aWYKrEGsipL>Zl3YtD;K z%bGgshjm{Mjt< z<8Mc@z|blJ7QtDK1V-bmD%J@xiY@O^3BjQry!qwFeSNJf!I9ujWuJ3?{~nNyR*ut)L%ZYPV5mhoryURYNKmEMKg8`-cQjcg zz^FwlI@xDn)2@KtPF{;d%a~{p_<$_Up!?A@;-p<=BD!eE&H~@IV}~wL3m^Z32ln5{ zazMq~E6#f43<=byXHRW-1344_A(|?pvIyeVYI<9ai|h^??c!vH?3(ueG&HDk*1Z7A z2LGm+)!W_oy3Bapa)(J-5HB`Y_WaH4``B@MeY`7I&K!7c!^qP+f_Wa_r;YlfumEzMC#vNM@{Mf5yE>dEoZ1!(- zKF~oV-u3dE>$e_)Swbzq3tQH59R0ay<$Or3KP3ljtUg_&JS8^Z85>exno0nuPjeu4 zvWsGH{x7b}!B{9iN4*Z528rF(dCc?sDF@hg<2iiZ z9rFxMtv##N^?_7tHu-u!LA|~N`pHxL+0f?4ZyK;Zkl~3a>q?(3(%6-uwbWX~2%$VM z3LJ#F%~?AQ;_)>lVHOrL%u#UX5V{8ZJ0D;@WxL@<+_B)B?{1x-lqYt^we=PD5o(L( z?u}s+Ywna~%e@9nc>v|&Aac_8Lq`X`&Q11hcdUt9r=npYJ;j~F?!FJ%^K>bt9C6R* zxI|IbCpdXg#~971>l)=m<&s)^_N*9PNsqdJBMWS#&fFbic{cb{cFZ$41}p+9ov^1Y zkKP`)AmnlLJ1qR2{q}F`9NRs2=t7EhNw72C#Gitb9 ztWgKz8ir6eU)E>c)#2Wt_x7xFm0)0NZ~4cQ`UoNmRD3K%MjM8R@}Sm)C!fpy3SCrw z2M?$t5iuH?=c9Kcj(q-f6r%UU#$bgJOrDls*7LUx7G_Z7fDF3*v*b&9nd541^Y8c) z#!M99-ekjgcPh0`6=G;5y&)GTOp#?BDCsI&U;e^c` z`N4G24sk~u+*^;^3b;&zA78t?J{?T!pAN*m(KE-^ zIqItpI4Gh(?Pm1w-rGpr?czA*{CQ+1TJZ6I4=|60SLg)EA$N{Z(pI0XGcUAFFK)YD*%@2R zwE`?;)TO_5rcoqg#0o>VaR__l+gpz*5`nwyc|Hm5Itr!T?Ju+pdV45UG;}vC^LDZF zj971K>8%Eh1O)E-yPNRsppVoQVhk2;S*h{0YajO}hOoOwA4lYS!zJ6g7d2H}xSUR0nE7U?iu*>;v6P zZmmIYN0HEQ67WjS7yoRO=ulB<4;u(PV8gC@lF;5g$Z?*Kwe%@`{^_|Y z?!qVw6Wv*f{j!kqDOWb&g=T~V_7^EJ_wZv!Nv8(qeU}z7XW8_vV&PfcONy1)YbnN{ zg5<=QOmQfm#$MK*vn|Mb4+{rkNtHV;GDnLAN&590JH718x$~8#LO|q|s55N6#u54r zv;Cbw98=t93GWAGdUZ+A?plI*Z`yZs=gDaJ?;Tpl>GvW%k>+97TQ2yXVf;pJw=p5c zE#f`7%?ri_x7oFwTfF_IWwow=r6zioPZYX8LzE?$K=@2|fM zYB6yIsWBW^9qX1iuaT-@EjFFJW(3}n+tu9XGMQ(txIu8ou<$Wy z&vHHU^-a~6u7%{gGr3}TfD}jAQ@!XbM9`&e0M^7jb{0rf&1ZBU=p51N50@|P=1E_k0$Yu3T`-!zD=Ifx{kC3@f!}u6v7Uc2sDL7l1-A-40x>J#?F9#WQ_s3 zj;LcCEiFN(bC{izAY2)q+q@rUy60Gv!x?p9&onLI%R=Yt_!gt8e%{1$|3?3CLPLv? zh;DK6oN^i{F3=o^M`syu^3>}e;To6D`jici6$%>KnZVV;ozvHflA=|6Zxm|eO?j_5QE zMIuvO>g@BYHRz@TlBnZn$M`|9tY0*L&kT?4{z>-}6(rqv>^tx`?;ecl^SAMNgmppd z(7wOXx=Mh7afEf3uGIVX#|N6dn2ENm~}6#`rNQs!iTeOKeOzo9rk4 zGr9sqw|gbpry%!R_XZOm;8?l)B~N0kXW@t*c*cI@Jhw#~+oyIE??mj%zIJ*RDw|B{ zNSz_s2$N#}zQZDeOQ!k$l~n1M16L{f&ELQQmVS-zomICJ(J$aNEv`qHf%cDYgN_3w zOFGV4Mc42WoT$%1C^G1(lTU0%&%E-=kFXC}gYUnnawZgXZA5^`_N}?o03ThtR&ZP< zpW>6!pTiZj@(_w{@pp#vIEo(4>V&d-W{o0;d%rUST*IOp#qW37$eVK(?`?1M7bH>Z zf@EGw^O%UersJKqlO{`P?GH67&sB=sKL~N}#z^(bS*@|a@wF-_2UGK0^ z{PovUPSjIXa0k~-M*-}B*0V#kVq_UXV$Vihf)TyPV@bZXs4!8>+moO3t~Z%8S9$8y z!Cd<)U@7{USx5~v>oomRXz%5p7|n=eJ&@utMWx>)uPt-!t$6_>07enQe?Gqt2gky* z11_+F`zjDnYGD;i1xRyfS(r`{yJe(>EAQGduZ&$;*IIe@#wj{GtpChHROT!^<(}fM z_rLu3n8zx*(E;L9DCl=1{SxAnZrz3J&35NX^jfWmS-1`mWqte%JG|~yt8|~T##{6? z!Vy3djBmYd#|7LT z_cAn`GfxqtZ(3` zgyFTRneEYzYWX4vlS4Nuaf>~FJ>A-lRjevmX9m*M&I6_&YiJh0sQ^qJ>O>oJvdnI# zj8Fvjbv0o2`Fb^0yf3`|r4YyGk?!210^+{Bj@@+hBh%H7a7-{J^6u^FPN9$-CAO3R zt93}y0bvBC7yvH$P9^G|v5=aN>xJF-MH2Poc~wYfAE}9XJo!rv0v&@3o0todv7_m( zHgy9*QQa=Gra{4I@-e<0u9sdZJ%`5b?blY+z2$vZWs0v{Xv-*VyFx-manZARug(8X z+FJkF)-=UD6JPXDpeZRnEJt1ZvLF;gqe9|?ceFl97rm@?Y!h&u^Zl%~sMv+7zyn@p zp2w!yF0HUR_1MOvreo>;NX}Vf=|=yM&cT=AVRj#gExofjW`iw` zCk|EN_?Bu3Jo@qd-9yhhq+E=OH9KwD!*XFtCzjeFc>M(0g`T{%vLM^ zPsH=oT(N~H99M%`gzKj;frlVS*@G=YYCxWvy3opt9$)w!IHo{&lUHL8&_oiz^w+Oh zpkmv;CrX6t*e%6sp8^r?RI5oem_(D|Lhn!Lo0jHRs(YUQJfKQP17|PB-scO8N$6&S z2NS8a=@y3=|J~fT)??}x6-tIEY=o8OvarhfQ6I-bqf#!mYe7US*QUEBdO9+#EKW@z zWND;4e_04m_1$drkglcIZ6?Ni?f#86DHiVI4#c+6F~s`lSfLU>`KiwFY6>|X^VN`^ zOFyRX^dB-eE{q+w#-OwDETu)^UysK`*y1S^l2cg)rDlAR|g7bfabP>}O6 z?7WAGdQ~rYKBsLlGZ_sC3UhD}q2!#3cS;yOhl>{M)*d+maUQla?EWmu)WJi+)X3O| z`L3;=7MDeVQmqIQ(}bO45lovB=5_D0N-}NcB?vze>1v1Fb1ud=;dLFrc7p9X;p2L3?ntbP zUnhT8gU)9#NOjNty;0ze zEt5{L`*lvRqro&=Y{z%V^lhy$l7w))86H-#~D0+jiH{#pUaCh#9ho3LQwC%d&X{+#Ual zzMCmqyQC7y)!skT{?n^QA|9tKU2icwrH=SLWk3HGI^yBF5Nc6S_koIqJU56WbE^|s zkx2Y4w0;Voyj5$b1yGczQ}VqRcFE=QL)_4O#p4CrypERig6C`Z>j>1-{gBSitPl#K zAy#?)|NO8^#k1#JV8i&4F%K_^9gwBq=4gIkBnM0~>V)0?@?UDy{Y(93{fv`jJ)6YJ zEOfqOjP3HaNb@d)Z!`qn-=5_(MfbMvvx>@jK4m=VQfqbyX{R_Fh{0t>Bkku%`<=UE zP|?w6gZT)%=wcOn{l?BSXrz4i-*=zB`=1{hV`2)XG&CsL&FUGsxbs1n2(!&E6yD=d z&AnN4B6W*i2XCrxRP1T=&IWl0LcUPIUuCg<9U#j3^y3+9plSc(x?(q>(-3H?h=Rg5{+ZA@kx8f_%$uGrd>-@zc6d^88yn6axWpw0*8nQ8S}}_^jOt^+mQRw#5|6>G1FzEN!;ihQ5ob>0NwnP?NAv7Z_vSc40OF-LloVi zNVO09H5a_wI~cVHL;$R}F7)GB5D~oYl|;ZR0MC%wqFt0?3?OJ_yF<6w^IGMt7ZVkI z`&Gi}!P@W9+V;u{zu6?}{V%5v)f&RB-?u3UJCgTXABlQ6ch$eYdkwW!15E%EGsPNf zzl?~`Yo6gXdA953-I1I}(#1)2=~s{tRY7i|?z-gK#6D4W8~W`kito8|=JfrIP0WhN zxXvvt)a<+O|AaR7hnGgM$X*k53u>DGa45<8Q|?)=f)qj?uYI{Tpq zx))4KC9nxfp9B24;t%qx2<1@`_V?gUeY%)i*`ot7xKVh!v&GANW_#PFgWe9X{&qgI zASRT`PbPmi2c6IAo{lxNskWLFLrYmgig;xv+2!QVX&!}%dsfZ8DL6)_%>|6!=_t)i z+iU@AA(w~?22pH>db>|F7i2bAwiu5n_458cog+=Nv_l6hB(~C!K{AiAnMg&yp(%sC zW8OI(G&EqNyoDqk?7yZ)CdI{qKZ%VQ_w(*on4sf}Z=z!0KG0~^eNw9N=$=>#?zcSu z%G5J6m{1^$1dBU@6gYFWL`^>E%#3W2_}eV;wCwA*QV_^Ns!)+pt&hG`P>#Jq-@#}5 zBUPGTPzT|}boCqi8fKL887+y>r(7)2CN;e$p#o1A5O*qt-u|wEbIUOgYJ)Z)bfEUq z&zT5etvmP_WfF3G&FkER+=v&j6B*KhI&tX80I-L;yT0i7Kj&^V=*Kti{;^71tg^th zPJ!o9_j4o(`eV$lNoNY{2rR?6Q>1K%Qz2Ln7JK|F-ttgRrk@9N`v+O*CAeT#h%%h; z*1blS3D60@`&WOYBBnAn1I-GgmP4Q;>csT_pfcP`%>8P%a7*T=?RoS=pS{M15MtbU zLHBv&p6BqqbST0^9U^g>Z40B*Z1SB)=|`eY0ZAVedHp4R#of`&oH>0_L%OyfOTzE1 z`D{SM%I)XjT5J?{1gt=m)^%X%y9}wTl+a?-gzu4koEKb;;@@+guUEA*-4tXVI~2T= zxFk$q?H@D*S4XNeOwR;Db0U-{`+-zkpbQ(Dbk zXZ+C{g|Sw-{2G`?2V7x39G?X?R%=*p%mc?PdLi@rwEooYo=b8r*SZy?*1hBf>70o* z3jMDk^3AuIXe+tDYog>geYb5hg+1CiLF}?-+7API{K*$Hc~x{war-}S_IK!uGE;vA6moqwL8#g&_&yZI1!)Skc+0hO;=A7oLKQIwXus+!5utcpp6*KZA02q^L! zVj0U6fmfmhw7Nyf`5pg9V-9K^Hyyc-;N)0G`iP1bwfzQJghQFvLT{(@a;Zs7-o}sQ zTxXJV4tghM?I`Xc68fvzb;_bDHzDU)RW+pU=1EvJiFfMn_$9?A`u~z~BAv;0PTPnYB{Q zVhhPResI@bZ@OTFqEg~DPNj_Hmg9{TOiG92U zo>~oy;j+NG)qvWrJheTgSwe+vFTDDR@_-rFLwd9>-bLfUAm+2$8O|On(>!D6B0JK9 z`_Y-P^FE-q+s>*Pv?Y9LZA6)}jo8%2JF(gi-H`-|b{4L|q%#X@bz~-^D%x4+5khZw zY=!|9n8Ef^aB5LCkV?+^95MH`E#M{11EcBK|M*ZsxTa)x~*+K7)cT z&e5!M+X`IwA8T$>DSof?+_x7##;kLom3)sycgs!Ct-uYV56T@q$q~IVoUGSyBOR2N z^ntdsil`gZ$M}jGc0VV-R|)jvu0LMDu4G!4I#GR5bDQNZD*{t5Rk3waJ;imm$?jSY z^_bsV(<+>E;lyX86T-CiY;rE1)cP!Nd6utFIiXhel zJ;M&Pw@t+c_H#$0GS4eTjueI0b+kQekAg?DzzpX+$a)#hm4|kC^15N;VHGTf%LGu{ zyML)Wlti=Nw;MsamW<~(;nk~FcvUH#(he|4ZrRRQ^r;*bEj9x*3BLRpzsUMlr);!T zxc0f^9Dmo*OFY+@3X-ZNfZ;^zMaosgu``F(A<61gWVE$Xomo(;4XD*=kzJLZm(GKo zp%#nlaE`jFSoSg?^mZi8Vzq|jR+kYQSlm$^$n3x8V$t2_nbmriZu_l@8%idoOXVBb zyLNd4W!4;>A)HF(-!Nl0QXRcO2M6=a)KT%auiHWVk=1o?WT zF8g;kcKS-FJ$ygqx^rCp9f^fnNOkv5nW4P%{dl9Y3mU9h)>$-esgPM!Rbeb;O&|&5 zcmL`S>B4`~kS+)IfHZwxibptySiyN(VH=4$1&90NIKF?Lsf0pl4-<9x!b_zd*G-tr z>qtNKB4#KO+QLasJmY=WT%&8gTILEJ9~)3xzk3h+bA-QBS4m9;InBT_Rgz9`2DURS z<2$$P8#AYrblfjmIwd%qnoaMB2EdB!y|AXJOu?^+%3k4`jXTjc7bM1sO_X%BJu8a6 z)|>M)&ce@?2glK?>4*30BsvV6Mo_zOLTL9Lwf%rP>05~9!?lbO?R!ZVGJUMv8pTXh zH$L%t@+m&aJ8n}Vm^qfQzH?4-2qo>e+ujeb?tY(6M&;bcv+dV?3=cv6{Hm#}BvFC(dnGZf>KL!tNJElyPp1nxi2tVUY2$D+c9 z*CpPonc1h+Kp1eYfc1da+F0$;Ieb`mO-khg(d=erZi4PlE^Kx|Vt@sc4$8K_<0l*7 zQ$n}Ti9pPc+a%~U5Yo9!$u1I3a7i|&=QiqDK{#sP9qFFqT&QiWret0v8t}zzRr?!D z>e7o~K4g}j762B!@r#OwdDV7ujtvQ2u%c!z3SS7Eto8!bb3=hQoxi@bueN#tY7qjf zY*Lkc84}icy}&JAqI`t(S45SbG;NBYX{C0T~%DY;a^3Gj{NDY(k z#k`<^XD_^u_poOV+91JzkF}0|E2DP4?wCr{T^CBc(Lt%heW);tpl274q3;A@j3|&N z!D~QwUnN+aj@6g3rkF$MQy?f5XBWdAG>y;ES2Kk0>Ozw4Jbf0we~Lf46wPAwM^Shj z(yFJ{F+V50nhrYC)>XPIZg0y|UoQ__Z`qC)t>CyJ&C=eJ?z(tj zYqt6`JImMu*aQ1t{l~1!V)QmfAd|S)q=m@%q>SZHs<3gQ z`16JW+OdkSVU07E@zV>Q#CPoNt7*ySQ%+No%!Q4tQJA&< z`?|4nYTr#gcC88oe9=ryHP5Iy`2LquJnwNR#wufB6eApz9lMx?K>Y83V_U01wd-Cd z8CCm)W~Ub$1@mK%{;jts>m-Ms{5iW2I+dV@iK5%=d>0LKtlg_3=3~4Pp08GKP#*yu zx6C{l3ujohUk-q^rQ&hdDyx851?YIw0t6A6VDh9F+8 zdEnv&RTt?#P&^(@jNyw(1TOq@w7mHXMYX7y;QoGU-;wrjst~T)JT~SSi+kMF)S2Ue ze%s~qsJ5Qa!u6`Cg1rdP`J;qm3rRW^1SnWvT-lVX zUQEx8-8j1YD&fv^K8|{99?qaN^7@W*h>rgg2;ns)tYeuM`9WkrNgwbHt~kW==mk#~ ztPfLb%}jOoCBW_%@lVsYrQgp~qBH|Ozz*D4+;QC&TPYbMC}b%th>*6PQsOr@{t06r z*)ta{N^DRbS*MSpVriM{IqNJ#F=e0sP>`4dtn{u7bxGMJWye`oE(Iu3)4GN8@X3@u zQBBx$*g2*+*BGRu-L!r4D0aac|GyTo-=P3nO*EPO z1cnh?q}qbSK%ANCvTMb{*}V^LCNhm(O^@bgT~p}iJGOvf!m*1JSOHJeMp$i@ zy^*|*2)fc|_wR|`;{rLa^N=s0Z!(pjr>NGb9!Ch8_!q8Hz-ozqH$fHKZk(HibPm|N zwxb@6KThuF_}%sVFBx^yEO;i_S`wfmJ*4FGz=}O7Ui>h}qiP~lXrzl4uW_tuLb}zC z`n$UbRXz`4VF;Cf{EHC`5gd_OYg9u0Me8~%$#dujbU_|95kRIqvRySap{V9Vx&#V= zE$F`m9@WVg06HCyP77V*c-Ll|&QsVkpT1Y%}2yXhu5=gqXY zXBK{AWUU1QhQ)b!fGqWOZ!)!|t zoi$KJcQLJ}aJ%M0PGau;(V_NkxS_JMilQv9TQ_#LO4^W~aI9h1ioQ~6OVz+s^QNKX zJO^O4y@Ho}(6#qYHo@y}**%>0VA_C9*Ur`lh2z(q&z(NsP?O#+4FIP*a4ZQs|E|no z-a{l&$InvKS3X&{R=_BHaIAph!Xz3%xUZ_9aripYtgsaOq-jBg0lfA@RR=x?na|Fe z>4R>C60FrowlbZfeu~`6@2_!DW2UF5i;Il} z+6$eyW0law5)gCld`#RsQ?t_Y1n#(ENlgx*6lH&_R#cZORUe&kOU2n(A(%O1?)pDVSUxY+mes?OyPcd(Yv6ac6 z^NSiQg;9@Cz?pY#So;1Big@Uv_ZA7bC6O$OF~qh8^!M%MXc-Y4Q?cEjNS2SjD z*@1nX3S+lBpVg5Q5#8qhG&fsZ=QWK`bk;bbHH{cBuqDj`jVo%Vfc@D6YiRPx++XGT z$1G1>DnZ{Z8|Te&1lZEmJg150ySMu_$+hg{EKs$vik(SO?^^^F(yTQ`+PZ~Z}_)k z9vP>L5;6j+blFj``R?YtRt zE;N6z{Q~}_3kg1uZkA-aVpaj6C|sn?eLCS#spQ{56`>QicHk-%cD7cdjoZ=N2dXX* zaK`aIo-66fHv`ut>G3b7IDwcF%CjOnxIpOKW^YdIXs1ZDw{cN}?qj_YXNdN70-lgk z3og?(0GXbTPrYw1rh*0X{V&T;%0swCb)a+y-~B)}03_#F5Y+;Z0*VB#b}rU>W{U6~ zHZx1V<^oSox%o$#GqcAsQj*Lo+btZSb6{dUlmd>uTjVLp=b46Ggay0lwJi%%)pG7Q z+pfATv@|0Yvn~*uHnq;ULWyd!&ohJT`u9J~EtJru@qvq|YMP#14N>1dp~~nm>$V+Z*V`3F{l6lFv6diPd5M|hH&x3TR##6$v`i_h%`aRX?_H=}t zqsnxl#d+9==ZJKg^zw@&8(4r*s~{r!J&R^ZoOQx`p)0Jzvd@c_>G&+tYV_sL+3Mpd z5nQ(1$>^P97`Md};%w_uZY3vFt4nyPHH$RD3OkK~5Xy%He_ ze1GO>0fih;Yy=62ktozzr^aSlTbxo)SWx`Z_Cl!S#e$I<3;H0EY5}^k1`)z zRqm`wRo{RrHv`kY)Q*y5|Ei;7W8%H{Z%?nK{X4OE8OI9IJ^yTF3oBkJorO92_*d(A z$58doxMVPRKlmJf*!N>+{^a>Y-Rn$Iht_&ikDDx&whalx?}t#j5o24hkfp;9d5-=RH7c9+6AU8`ptLz@te% z_1ak=4c#v;Cb5hyw)4`t590e}lUt$Fn-wu)yf1lMAJSn79w2<;g6j40zleYBr<-LB;G~nOUy`X}}Xf-z+uKq^2nCIg5YoL`+KB>X= z8MXvku2MzGCLOyu)=^s!ty0d{@Unpx zt>X>{kGePOeqwJ`1p!5#t9n?_I#;7N?qVM12{BcDes|Kn>gdk4z1kBima4E7Eb}S} zEb_f;>*D>}f1glQ_fXBE-{$z``e4noM51E~@cRhx!%AHE7?~|MU+GhoXK7=fYXB;j z(v#PrunBczOBqo<7xM5^fXJUg2>86C|U+e?+1Cl>CCu!dx}{_{u>u{ z8$_X4Odu%Nj=k3gfW!qKXjbG?}KUegx1sJ#2*=SNh(MhM~8KyLJO}CPUoiR zI&uY@SMC?5O=4b6-6!|KX8B9J->cG{Z zvxN~rW{=uEbC+YEWR7`2NA~qPCFTi|j(N#h^oxj-cR#1ujE+{0n0B`=z1_#_!5EEL zw<*=^2rQ6I*a6>Vx4B8rjtHnN-;^`7?x$EG*6NM_hR2xrP*@dJg_2q0?dHyz%Oket z#m@N@_k;$Vx)Ib-sLD!!h5&5xH%cb{a>|>|%TQfXh)qSts^~GgYMrax`KfiWdrwGP zb%cn*Lkfscf%bFgiv~amz1_T|9dTDW>8d7R-D2YSh)(=Hu7cxv8-|?^xqGj0rX!E3 zfZJ$sc=z+^Z7%>33Q@@%a^&b+PVB_kpWSnSYObi79Gzqn@+n~MUb_(lV`tu{-jdcm zD(oE4k7rEzkx`PEI@I)92^Dj_z%+MSY*-jiEzlv$2=}cU@{VsV<3g&lIU*~CRQWk` z?(0_k2$N*->6X9YI-%?FcR7~YMAuXc2;M`l%O2v6re^{VQ*?C~P;}iO2L}5*9pzZD z1(Sh&kTHj2+K((<)m{fq#Bn=$*yLC(0B`*z9r6tPdg*7CEnOO8d9$8ZM99)zTcyMX zXAwcRMd0;c!o<{f`_p@x6dm%!?3|_vm{@(M#WG0W!`i7rk)K^p5MSs?Yw=r1@60kP zeDTB;CA@f@x>(vC=N;T=_`ZK%!HSL6Shl;Of;3xeN}Qy)h{yjjd(<)}&fpA$IqNTG z@@lQuWus;{e&#~6NEz0ZJTbl0J?Xj?3)m!Cr0#jr>1`Lb=$d*Rms8}9xmcS-PF5?^ z+r{#jU&Gkk!mSCr_O`|LiLwZi_EMntc+&lxG$b6w-zM2c-%(XzEiC)^vGX;WJ;kGd zxd}RT#vW6J>?b){P*H%gUT{(Ex&Q13==HB%G+Jj}gh@JnfA9Qjp%mVA!V^`LVI?`& zNix3U><+f&_a+uQ9VworjUq}O*oLKkC7lB%qk8VS`nYZKss21_UF0$q>|*o*KL+!) z2ex}a$+*lRrxHd8dFUZFm$?b~?Dz8lLRUF|>08?UbOn*#1_VUzskMb3#T^dD7w8Z> zD&si{#4?px&$tk}e2nwI3{_s`XdTd|Dd#SVGn5RSO+LoA*Dz7vaWv*9K2c8#`8}fV zqczIE%x=?W`FmO<(9WrQMb~q#{=PPFg*2u%qQd|tiH;t1U=yUNBR1AAA`_3;Nh2tn zEK=wN;!d>9xthtRam&oMw+0he84-9Z8Ywf$cwYKut0+E~Hr^5>SskY+?(&{8v4dj^ zgkpB0g`>o8T1{)QNU-d^o*^K|_N;@}_URz$PARyDiMtdfLQ4Op$hKZ!0HQ!$zwx;5 z`?qbQPJK(U5gjWtGNA}?(1E0LZ_t+LU>iu{LbZ)OoQ2qIG4I<{A-)iPy+Va0@r$;-9agpzJacj(1733}UYI`=dHEcf|BEHZiY>k(;0g=Iy1hNzT)dna%8N z*Kh1R!v$8Bg2@-Cj?j7b$vInyQKzWMe}HEqcyfnum=OyAG9@@MJT_<$1yGNpf7^>tM0IYN4m32P-LAc_h4Z*o zi$I%g+Y!%K^Ogi23hs6sd(ZojwD%c2|nr0+S&y=MpBdr#t}BLMein`h7gDJ0!48AT9q>N+q+I>bU}!fO&rEGi}y3Xcn{Ph|?l4W}7!njS3B_b=G>Kd&O17wK356F)Xi=!^o6=c)yS;u5)UBX4$%1Dg0*-u>%##>+zH z-;sdJZLX_s|4yA%T9~(tETmM0HbnwQYXS{cfvVr(Px**XE_N{H&M*8|SbcW>o=>x* z5DSZJwT!Ilx^qT=02OA^x4_D3qZ7tOfuxIYf@_*Bs%D?v z=goaj;S7FKSm(XtxpfxdN$xWV`SXqe&zobW(k1S6Jv>=P2P;Wj(zbSCQX$98`=aaB zj2X0za9(>;Fg$9VDi+Vhc2FU!-|JSK8CsPcyF$UXSnCNj(No}cbawsb-II+1{Ct>h)aQR=J#+1J zx)km~&T(YX*H*eWHIp5{jVGN!G!>&&_NDWSU}168KYwNvN?vbev(G$AkolgOrIen* zcXR*A4OGad_x?gnqBGqwFNI~7eR_<{@!w)|JVkYH5t4LgXZuBoJ{)oK%(6U>`Z@5k z_jK*U=5-m=SwB|5qlXEj%qC6j>hhCZJGyI7fY~=LDRT5#d`@{BJgQ%d3r6Eiz73X! zz*UBSE%O*Ye`h4~i9M`CPN!a%3K^Zdl$p9YVerZQ!u!-%*F#MS$5V#M;qio zL#QTwr5F=GoESBrgL$fOFk48@`E_79fVV)$j;m@52)aQT78kHk=-Q>OfHD(5w6wYD z1U(yIF;l>KzN#g{+xWO+oTVPw`>2N@#e4iw@%y9zYRgEaZVeGl;vog^TfMqsW=@ca z@oAHw3#Sk=w5=Gdvacri1#9g5v1uzt7Lq$@* zD_wOFh*V~Bxanr)19}3M5}ozYP9q4q&YDP!tSC_sjAkHqp7=Q#3t`4tuE-In;7Z0% z3dAW>!S5=-UGdl#wUaTRM9dD#?6i{{@ZF6%#&O}G5#L7_V{!Q`J5h8;LT<A zocYgioGW#^ODs~V`Cjj!S_j<=>MBe9*E%|)z3Elkdw%DtKBCuqUF(yc%b9@5J}8tob=*j9=%?WwTGo*mZ#SnJD;BK zqT=)cR0T+$hZyyJjXhF|a2B><6<8&oozL@{*DDlG`>HC8eyyAy6^g0UfIVT>gGnEo zE`pp{3|i+^IP>p9(N$UDBYr_tOOguWCV|g~Hk2Hv6R{yGz!cm*wPH5yBn4 z?V=)EtAvQjg|v6&T@&s?eDSCb)jU*$rSIvmNYo~agrPv|hbxI#ptVy&#ymqp9wzH* ziO^Z`JulW5dxk{bv6%;}@e#eu6j-*ZS|L@1FnO4j@Ta+5WE*z<#?Dd5^yBlDN5mj1 zM#t-Ia=gB~dH0PUUtq>hblSZ-htg~kVK$ue7#X_=_MRK$W1ct+MgYh#1-bu zdDWQ+Xz!t}R2ht~#7EuF(Uah&-B6Q2&@RQ@*$pZCy3@+VQwt40D0hA$|M}C^2G0a= zoqQ}%Oq>054k|QJbSG0;MHQ9RXdNAGr;VaULZyj+lG(Sqi~98&KkV8nuor_FwzWZ^ zm{7Sp&y@J(1|zmhXU}h(k0$qui<-q3+#}mPgWkpj% zmXcFJPW?Sq5Lf}EtCV6jI+hU?n77$p)jGJmn0z$*m~W+I4uRgj%!lU13P{eWn|zF< zo*sALlXYvqw%T)CeCvavgd7`PQc2$y>^V8#;!yyjPgF$TkF~vgLhH+&@yE&iR^mX% zKfTJeT0$yNWT!1Gf;KDej@0 zit`v2X!u?c->FG7h|FZPN!mA9Hgc_k3tTkT5i<4^uFIi*R8?@?{IC9F%KM(qx?dO6 zTD2fNts*ddpPG}%LxIX+x%mnA$~yI%g)0QGkOF?6syr$b0fz9qwr?X{C2vwq+QgkL z+9(16hUxEwJ-1DPBBm3FYpuW_6l1nMpdx`06U;M9IcNxM7AGN)8~Mvz*j(MzsJwPRdYS!jhHrMIfrrnad#YZ;@;C; zsCI@nZtBj$LN1DjU*dEzOJzhSFbo3GyD`5c0LUu;~L)C&4Y69r0^&9P|-1hv{hZHLu zWn+aTIp?){NS)Z1IL|qmS7vU}rG4ax^;NKs`sa-w9?@qx^39BoNR&@89`>5Pr&ITY z{i%RZx$79tZ#JVbLN1(FO z{>wlhexOYvS}=XyG&l3>=ZJS}7`6wLY zC24Gnnv2&m#%#$fOrGf46fImw+pFqE8Xf z`xgq#G3EDX>#)HT;w#jhb?+xk)U)i7iwy5?Z|t00neKVeeQuPow&-`BVlKsMpSp^B zD&zkvB45T8d~i;@TS4JZ_G1xEa{KCTcpsOP@7Z5?=K0z9BNFpzYBeW@I#{bU9;Zt) z4w^(^$I1EDQ#HBr_Z`mS^HWjBSL!dGa_&r1tcZv^C5WQny6{RB;Chh37Pol|iGlsfB z8!#%ZMWK}{U5r~5BrXkwN{ci#s$ibpKRqspZB|e-NiZL1^0^X2Rm4%om;>*cQ59y_Oy_qiL4mo zIF6513&`4o`A$3Q51Cs$Bi}KPn91b!PGj^*G@1Ogp~i1e8-WNm2+ zj#?pF6ge1`y`v-qUqzHW#bHn~t+YK)(Y^>-x^?(Gtd3YQfoc?5+nKEeAe2)*j&H}T zAd5Y*MdfL&9!%1z&3CeQnNokXbjVuWwnc!zUILF9_G&er*9jjPtM*&gmor34AP&m0 z#?5yE!u+6rsbdLoqT6=foVuDStqy8f-Bb5e1IXBt_?wIFpA;r+$AqautThlMd6t4m z!Cdsj3hn&hI|U+IxlTG2VrkW`1H$?t>!qIUV$->I#CLQFR@wQ~ERgg_fp%=-`$hM2 zo!e`nz@2sicNZm5PmRh5lPgJ7c?Py@ktnUyyIz2!0R3}dM=NMerUc0)fA@IpqNLZv z`b5;w)v93a)JFbSqeswkq0%Gv=~v8t`g3-y0NWlNndhlO1U}!Gj^%#_Cu)rl+ArnV zY=#y_Qb@8wYrHN@0poSFPM{#W>x5OP*-Gl8E`BnMyg>fE+E>p_P#H@4|+jDaA{!GQlpW-LC2Mo zNCdptcqo(eHV>0e?aa>F*+KImH3RMFz$s|ssVIIn(#@syB?~CTK+6-KH23&hZ%=4z?U8t?bEj;NXU;R7Px^}P(K&xq{TOI2 z=#`nPmiIzy$VvB;-j~ih5_L*!`%QbhFB4&MZbwa03e%Ol$l_9AGMX~$1jp#Ze{yZ@ z;~XpML@yJ0c4|^sDD`;XHKzh)u%0K(y!B3|LXUbEy!Y@~C^7uqX$SSD9)!Y!QMmr@ z`GTx*_d|02Gk<@LLs(AqA~RzO8{Esjqr7H@jahWY;U-G%=fst@EgT)wUOr?yV`CdU z!X)F*8&ML^Gy8!6^8zDZ!8Kw(gDZk-WwmJNJHIEz?(@h{+hF-f`-amgMdy^W=;gns z>@U|Dp%t(&Nlm>*K^a{71bu@JHxZ?9DjZUcg_&MUELSgDtTS^FFGcaY(5PG7(Nb6_2zl}>6fk9=t9D( za`Ypzb4BZbV7|vEy3#@ONjuL!27*Kx;Yw}4KwCm75}))BO{%LbmMIBkko3<}(+vW; zv-dv_E|frA9k?zwM7<7d=i7( zymiwt%g@O<)bp>HgYIXWpj&0{>J)ETlkl8am(R<*{<^%+&`zz&<5=fMvH0D7vgWJ_ zBVZ0feSpvjL?h|;qb!MbQ2N2vPL6Hnw)+R&ztnHCmUE~2=XN^h{QREfG<$Ad^fCm{ zBt@S3A4LaUiB z`?K)1B3+cUQ-Pa0?XXtf%(HL6U=db3a)Wc{S2(G-q+RLtY5HW*4dQBv<-HvyVA>n$ z+9c?g9Gd+z)ixGf_j9j`r(ah^2$*|gV~)B}^wQ>pacdnV+P=Ph7bGsp%zH7UbG_`! zE;<5nH%QuYe9$qYPJbwzjYpzq%$*c^LIEZOFD-Df53inRgEEroe{4MtzIv3uJ9*Y|6s?e*#O zBLxFU67)+Bs@A`T-+K4!XkUJIRo~-zk7YG=sKOd| zU+3M~mar9+m+AR`3SU3dQOkv;a8?%^Tojl&2SshxeQZ*fQJhab$^5x>1i;sC?2Jmy zfjfaAN;Y3iKE)^5&DRDG(eCuyu)&qg4NZx9==JNMmqj3CSqfPpJLp%iMV(4lTLlGT zm7uaZ)%u`Y?@&fH`!Zr?qVDFy#Zx`Mt1k5R#WXV9`W}ZiiHIr%->S+Jrk+^NRj#Z{}?9jI(%^hC!I1 zaz~E4|Ly3G6lv6?y6!O*h%|)aGF|r|xt`@Ll=m7TJ>CnvcH;-eL|fUUebZ@Q4OrXZ zZ=Jq~0>A&yzgub!!~?J_@DmC|_BM?|TAxQ*)|Pb@_ic0*#_9Gp01jBHC2SJ(OAc&g zU9BI{u0j9l$6VQEai;kRx`-`}DVY!|mu4HUmY~%WSi{J#6vR9#x@$%@{%m?{ zs;g!b)HC}UdPJ{rM_m%k(XAM%3c#i$KJ%QY)3GwKc~;8P`4XcjQMa(3>f&KOQIprW zzxOOw&1q!teERqOK}V}J?fvH6{<O26KANzv`^zNha^sVBk;sMG~F z@iSN810w`QihHyMa^Zr$r*k(3uw29g!{?Ch$t_vNjxCUKr+g@DIwh(Dbq-+lZl;mY z*?Hdl33ZTD#Yyb*bS~|?J7ax(>@+GEc5KOs)2_fiZZ-@x2lR*;RE`Rp$HJ1194D(w zM5(TOm|REt0TqsHA;D4DXLZAi3Ilx1V(zy0HAH?h%JDMOK97FCL49~DO|7@t6$qfh z-}RgS-|qXL|8L_A6x&F$#W=bawo#P&^7r_-`xopy!Mf@oc^{}XgLY0=bUywueOtTd z=Y>wt*~aZ^=Rs^>XK_A-eAU^n9AqDC?uUT~6R*Rc{5 zNFb86E2|IcFrp)4zfS}e>AyPlc=z5%YJ-I!GuFz{1UIOLS&6zN%S^GPt~$@T@%pA4 zbG8*yJ)|K_=4b6GxmE!yL5dx-p3~FZ(G~l8a?ts#j_?`~ zq+>UTjfhk(#5F)&P`DAgDZLUZ@E_YI0e9FBC`sS9Vx)=aEP&)YQszE=Pd*@qof;Lw zkB|VbA~{ErF*87CQ7rSC{=H}SPIq%=@1)N3wjDp8!KPa>W_8`IEh8n@c3i8U2-ES% z)?l6}T`+2PEVm(H#7uik--WjG`1j0Ls)vGrjDi_$Mmkm><`o7uCR!5N7bsiTaH^>A95%A;twM@joFO7^$ASED`p{YY(a`CvG}-OlQj zSawVQv9`YLGS-zivp5R>-^XT&r43uwK)O%#B@7P>Ab%`yXX{sqtt9w zR+(uh+@V-?fMP!D3`FXic}1~h!+q9NLm*^=85N_bw;hVol}XxzVs#1}|3TOl-tjE# zO5atN3IjPbc_i&{&Dj(Ir{O#1%IhMWfbk^9#9IHU-8N^cowkICKR$vB3l*o1m3E_Q z+8ohsuh!-GC8H+_6reZ$Huv|o87~(yK~H(RD!X`(zihgFvyjXmCJNo@4pgF6jZ2%Y zTRxftzUa|;r(}^f$V1fvs6xx0u13ed;dhxmr^@>^`*-s}XA*ETqockw@SIw45}jwe zmU};w;}6Rf_hzeiuJ9tk`M$-<2QT$GwO*kBzIdZ~-}pA$yf_tarptj*?OOx+h-n9>~VjY*A^ISRM>h(`}ZSpl9+s& z6eJebGR;u3UG#i`fZnd@M!USnc5E6DimZv4XjSX9wvlCmCB?d^4|RHKRvhFh$(QMb z=Lx&=Yaq@?AqR;&W}4k>d$%jEk=V?|6ZHWWsd$`;JG?GmmSmpo7o+H@i2qt9RJvg7 z#x42plRwpK)e@}cgk^2fuUpW*f+%A4HdWGEvTcN7aM46@G7d|)pm=zyT14eo`#jLb z!{i(Z(j=zJ>ZYPL6Ec5D7s`?N;bMb~ls>ZaNBUdmMf!nfgXr(wtNJCV9+@(~dJQ_hyy=?YyMk!eF+dKT5PMVl*X#u$OwTwfck6$0_U0sZ$Z6m$cX_WF&x==AKjF>jY0 zxe=vz3bYT}Dhw=w)GWQxEVh@Es2{uk9Fxl0ImvVIei6mPFMm!4y%RGTcGTlW!on8q^~dzSkQkm&bKoSJOe|wF z85g6lDe}yL>F>a4)dUu6G6IL|j2;WdT+fP(D(Y0ncYK#R>>``!jaHKns}|eJ6^uio z2rzGRyoo|aA>&@M^9yy!1z69qYyC1YK5C>FB&|M|w z4JBl-VlIaRA@z{y~Q zgp)2Jh_ks1o|3x#@yGbZ`xcM!yZ;>=eRpH$o{IH8ZGyZpQw8w8{GAI2Ijv~1s-eGs z&}*PFZmnR_-6k_9LAUh$oLiX!7&kh%%-1!-C{|y_E%5DTF)37|UwDfcm7betdY*|c zU4kxMf{l&T`2Z)O+x?U7C%x|}=q5gCT4h|W5e9-H&B6Ds{as-sXM1eo$LkgpN`gf1 z|Co~wm#F8>p9kmsNtx&Fu0g?c*}(n-8_W&m)uoFKR(>XY83+>UL3q1Yl4r)Iw%u_0e%SskU=GOVn3cE}b=&22q{+~= zuZ3c5ALkUsy!S8C2&^rjGV`Z&@U3**`{ z76#`pdEjrLYUKO>3`zwM8zgWi-Hxqz(nhLLt@SgVLlr|nA|5O=F<}b+XP!~p#c>s} zI3SwDL)rL4bRxcx_B#~#x3lOWDoa20y8#~hZ}|J`bb&VwOG`3Od%FQ>qhz| z=jXtuj&ge*>i|v z5zR{NJ-z|4-Or~7YE2-Cy8O-wlG3}ZP_ATbP*Vc0_QzM$u=^JnXA$PtcSM+xk`}l? z^s9{D%u9NcZnfU+Ue*1u+rBO|`HYghN1*i1v*$vS_rC3}08y6mpK)J-u<>)O)4Z>D zqc`-NkKeuhu~N}!-4HTNwAF4ngm%NM<15{Bh^H=VKbriVI_7_=2b@zt@9O{j@cP~V z{@XU%sfCKVF;l9Fvc6O8J;Sk2Vk9{d{^`Eg8-y{bl%F!ZVpJ z^cUxOa|;6+D|C}2;AKI_a^v@05zd|AL86Lk0lM_W#H~{gQ?z&Yy6Aw76L*G{cP z^!~$u$0fX{p^X*_%IipZ58>9ao@E2z7O!AC5V5$Tz%CIcVm8)NVu3cn3f5PmU8+^w z(I^&6hm@(zoG1xpxj*&bO-!O(r}=qs(+STabEh{w$_0&UJ=Ftyj<~9vx z?N@Chvlg6<4XekiaF5jE`1UH!#qfJUL7MX1hxR=qUQzBn$5hZ6v>NkPO3(qSaGVD6 z{D-Lgg@3me448v)G$a%6Eu#uT)yHF@X@p? zc(mi9qMxrVbKyneN}I{Eu!w~OU9Oul2|DgiiLXxIhHFs$@$T*Eu39qe^`f4H@7aE) zf%hdL!8#0ts%M#mLN zy*s|Kem4FTugP3tHHhv`DpBOmq=pn=o+v$e9q1j{$JpciG8A1cIw#shY6g`GD(k@X z5tjp16*(U0=LOmL1Z#_C8&kE*_Dyih`80XOw0BG6&mtwPhNQEp&UbFoj?^GfM{n}= z+QQW5$RzF|@`{CWUdr(}Px*i??$CL|>uvc0R+4a1_x$a@chr)R)x5$!_*DdkqAyed zOJz3L^N5OP%8mz!J4BeRugelW~UX1XjzwfV=oy7(fV3=-_O<1=atAaNbPRIfpTKn$_G`5@?m{z4W zIV29|^Yk1VEnYqLlUxC~@D>QdiRHw)C+8s*mA=4!(jBi{qx9g7T&n>VMP<*id*{Ui zyDi8_K-A%}hh0%H#&!7JjUPtNi+l_8J7dfXZOjQ(p$FOLp?g~ZMN84%mEMy? zU8wIY{4~)o-v8&{C$pZ1XZd&(2+atS8&J6UyBAP@mfO}@Kn`n=`s}=%9ip*;M#&@W zwe(3JYt{e(^MqYBzIC>iBRamXaeT)g5!j!eyTm-x{l~gHqR;j$`Ao&hiq-45`^qLe zs{zD5l?g@H4A0xHS`-V#X;EgFcKd^-ZQ^KARn1=zi*!?qK8)mW6sNoY9u#eG*NERlcXZxowy1Zu4AyC#Gv4ZJSnB zfqj`MRC~|Po}+LUgD#(jZJP84^xZxOvtga>F+;%7fX;|8HiWW?vLH#A^{Xn?5)O)B^W}}{%)z`b?w>b)c*OH8CZkII zsa)c;Z1DSKI^E=OBS=*M6F;NM^HfJULsLdU=~yidI(0rdD~ptE+AJFNSO1R|gRiF5 z(QO59zJN>{U}g6}5YAdov_Fee6~03rP*Gzf6vn)w0Q;e}f2q;MNxLj>z3xcIxaC+&z-fa^1gLIyYy4+CQ+b(#r5m(y$9kWFrdP{Y_uRf=lLr(Q z66*V|?wH-{H|}ylM#u4sy!X>p(F3=qoXspuBcRT!3pr)^b?T;fKcS=Nict=xkNJm{QIXMR^C+LZfo$UZ%v8To6kT*2rI_p4*L^<_FY;pz4DZZf6 z2|BBKx-Zp=@)QR~QW3|DDOJ!0DRo_K)|S3Q3-|#SL~w#q^?TiubWdRgby#SQZpNvt zg$~~d1@wd5**^!`RN&>kv}B1E%|G&!H#=)5)$$^+2V=$qU6TClyxy_^yFGemfB4_2 zW4I0iaeg+`T43DsMGQ*Fslokt@+m&a9QOfj!m3h|&J;_10=E`zyTCnV^qhy##&R`U zTMz6e;O4dL24``i$MK;AXw$RTre8+Ic}#^A+E;#4x`SghP)kB+DQ4&7^aDqm>~YeA zpv?uqm=lGq5oHp0kYL+q(6a+m4OT(^c_ZEQwFwHfwNb<9f!t)*c0v@Ns0)U$cn__R z$w!J~YU~$D@S9*+0(rbggkrhM3~4R=$tyKmKjf7r=po$qyB5jZvLMC4%*_K;5qVwX z(1V;}$6e|eA8@zbb-%fwKAya;l0fI#riHI%6L;gR(?AoC6t9t>@_&h6t&5X^W&G*6 zpF3oEcsGmxzI!yD#Lw1cANK`uy1prCtZs8`_iTm6pIRZ1Q}(v|l%#VGxy$=($Gq%D z(b4$-#kV_G%x-9pO2^^=`y=!cDvOn>;QHV_oA=^=(BK`wicWGYEB45A_pN0o=RoBI z9RS6PzOYC3XG;SN|8DIss!`k7stFyJ={e#;WG&TD6v(?@$~)7FxjcUN%juC5zi|&$ zuT=|>#33g^C=L2f&Uju4(9z3fsp3~f*m>~bXChM$mD}w$E0P@0N9v6#K8Lna)+Q|j z9_F+`{w}|>3j$qnun8&kc=(>0bfkV!2bX{~XPP3yf z2$HI^*-g#aTI`x`v>RUMC{Rc>+}-ENJQZiA33Jg+ZRhzWF9V{^EQ;pJQF0ygrAI}Y zUG~>C;iJqp61|uUbhel#;zV}+aUQTU;OX@%roH=pIq0BkXEQU2)rE0xkiCnG_r?tA zxITRM^8y_}*aeyNO%v5ljFCm6%Iuho9}O#oQ)5NBBz-GnK5lTake5t{^Vz&+ccUZU z`8MWt-L7|0;_k%UkPL5A_w8x7n<&VyveV8@kCOLIY$usH^#sb|lr$oKJy~_})F<@Q-{V`leL`V{niQ*&dN^%)Fx(*stUwE{MK)>$MOyP%l+ckH{^ zb4}dYg8L4hiW@f8Cc5ugtCr1Y8)ZB)ns%nL%w=w3lVSxUv#0*FQ9^_j0+;0es z@%F_+v&$ynu`cQ9K49b@Pz7j{^Q7}NkEgs+D?&)gbqpc=Tr@w6YWtD)kziyu+N-KM;G6z^|MjYZC>?md zCO5Ku|@@KPghH3QxdETn1Dv*(y8UdHzY%>ezE)j@DC>=^)bJ&rtaV@=2THfRTV zop!8atQ|q?E2!}lzio?s8Q6{ylIe<__MF#K+1H~^`)x4qq|?4k>o?6h0A*8j|Da?I zG#m%)t&;jq#|Vx9`?SZrc>l}ko~nT^Tm`U3thjrgg)kSq1*#hr?5JqOiTcOM?d}z` zo!Ni4`9BT8MWgJ#8&RmAu8?Z?t7TTIL8SHYi^*r(N%~Hc zNjf$LB`L-=69KRF+=g2I$Km=t0aO_5(%YE9q6RPdBSw$IjkO8@X<(R!8lrQ zoKU7zYfmPh;#P&umJQY-`5Zk*0fIKV-^0_`1!sGhvjnx>S-;%I?NkUkG)x%>)zV;O zr#~zCoKRI8RdO9iP`_STf*wMA!trx5&J+3_Hw&u#f1_3e7NiV*x1w&FyV$O|lOXj=j8ltz2uy2<;?nY&$Dp3-|f%>RT6b-PM#Tz(8cjFz4tv~hCqXXZvR&E+Go4w z##l!Y!mP7iU>orzOz&nKKc#jJb9TqG1Zd0`rbR7j%T8p!H zZ_8VVF!kFizHjlxrSJB(gl;hfDo30eh7n3 zD@;g587LoPJVk+xLER{4A199qKMU&^D4z)Tre1)~w^dTfnXO_tspB= zgu*{)EZE|Td9`RaEN?HQ@9S{%b~#-(b`kJDYabI?N~_r8nipz=4KkQTjYk4R=hH3K zi7B?$+q9l5E=n(G`<9oqC(89|OT_PJ{qY_5Zdcj)cI&Ee=BdpS^?~09K1$JbjOQ}t z*&}@2%qh@or%QtU&#Lb?@7y95U&Fbmrj(?pQJ_q&5 zSWRj%l*HXfEHr~M%!zf4u+6BZ5em~8;{Jbhfl_-1pWFA3f$AlkFVxi>bf}srIZ5a`+3T%Qvxp9G}ggQ!3pdDR3Z5- z?=Inc;e(U2z+pavl7?qNWqz$@$S8<=kf9CbdX@4lDvLp=-(=Clv7XmOs{{Al>^PB! z9?zsmbu3oiBcVMyE%Nw-q+2QkHXvdJf`nx{3(5I%1kIFL{I6nJ*%=Q z7I}Y%dI2H*2mZcA700AgW7TGxhMlqEBHLps{2f_U)#$is#zh{`O}~C)hk^s>Z0Iu- z`B-?4))YF2P^{RtYgUkq=MW(-T5_IJJH@9n)On!}2c0Y5Sau9m_Pf!W?{3`nzNNUX z>AQS}?-C3JTFXZ1wQM${#m=GM#TxSuwdM%Lgs$HM9$5-(-wYZNu^vQ|$xjQ+wX5vwa{j^b64d@FM}VsgHTSrw(4~FZ zQ1@Li4P2>=cRX$|wz)M>WpRbp;Lm06Z2DjoQ}N&+Qu-*5K3x~I?;_{wF-!R)TxjY+ z3W&}Ed!Wt%LLC^FOz&|))v}Uzp##$uQ9=}LpsB!3rD-8$B4vE1U>WwExJz?AtW7B;t}ZwB0i(j3A0s8j^hFvUEB{7!ih;X zKr9B=Z}jg^W{5;NJB#3kcIfRgR}W-6p$VeC{G?TJr-VCCpCiBdFWu977VJ!70uvW5 z$T`IZ<-UV~Y5|!G4ave8UBr(}w}UETsdKds#GWXG6;#uus;g{YmPbX@=ER9i?ZQ?r zp@QK$V#@rP(cS_K3qUVRQ}@>n0@N6rn0}2!yKJ)WRDyB*&RSuf+_?Lc7R}vAo7*lx zaDr}kRU2awd7$I;yZf59xO&UivhHb9@(HX>$G*A%$R_3#cu`@<9A(axXLM~HJ9^j? zdd#u>ee!p6Kt;I+U1j%&>{>Qg(Ot9E;97Rjo5Z3Cek-5?0fKJ?pUy_L#}w(e>rou8 z3b(dkesdHlbN|=3r$bjHUs%M=i3;^nH=24X@O2=cgI|_D-#fQPIx*b`{{1vq@Bzz7 zbq#mzDaPSAip7`|??2oH<)1Y(1Q8FNiOs0(fa1NzKY?M=2!(lrr65;5-WC|Qx!bPH z9TicdOh;SUx%Ne7%rka%xo`q?TUkpuX$qMJc!F9$OhuW8Uqui=ik!fj>Hm{9@n3)bac+g@-Tw}7()ttk zyBj;F{xxEBzE1~5kEMY5PLdE#d-%P7JD5`;&dhL|`L+v-qHvB-=ECN@4^C`DVLrW1 zH1}%48xWMDiq{jh0w7uFd{(gG>VNm&cc13Z{5KC=N4#)HaXB$Uo_m@u9O2x?j0!4= zes0S!J$75#xY;DqE=o|ULG`WH4x|M!Or4+=KZyqq^Icq zl8_5Z2p@WI(L+Cb_si*lI_F3w=2TEMarE&0e}2qeTP;(?ud68`OJ2MF)jy0*{>0u@Q#ouRpij=;8O4mqR-{H`~0|r|!ln#>LzO-BP21Cw7DLuql(9 zDENA;B0JXrm1U|p^(Q8-dBtd2qo0P&xB$l z`ebewyz!^=D)K5w-0RM_X921-?N@_tr0Kedo)^UrS+QJ&eJa)Q_7kLk^WsxWhIBbn`W@6OSr%7VIY z{p@YCY@&>D^k63h5pEPvw46kfVbS|_;#%%~P6wDWXDq+Z69XDwp`_t2p+uDHptB#Z z>$Zb}CJP=C$1k0z5sqQ+21p`q?x|aI%&+Zg;oePZSIUY+V{eW(GdSwXmpr z;yP~U_Io|=h{lrdLc}5dL^lZi%db=$=ad6zj?>aJtd$R<;;cc4Z zq~&#~te91>UYQ8jUC+Lm=96=NT8M_(@y)~cKUZfAxwUd;2P+gQqc0UriFyM%tb1B#)$6MXfo%jy+>TtfD$M}@_zzMPwhU0j)#At-OChub$i{ifD zoOtPBN-Rvoa&>%0F*B(76z7;hTZwoPlDTvBc+pO;Xi!kT^z6Jh5Y7WqR&8u&XBp=? zdjjXzuJAp`KF{0)ow~-)s5_1)c^!7mrx2URNvqx_q_cvqEZhk=H`vb3_Et?|lu~JW z`y87n&`LV&hZo)9IVwv%?lUc`V;-?M!S_Gx`jh?nfOBV~~E6DOZ%=bI5 z=zXA@u{DpTBZ7H4prBcAz(^rM&O7*>t7=3G%ogATj;keU<6DF7B(IQ5L3Zoxav9lQeEq>Vj zOaGP~Q;=g2b=0?59C_}a5 z3MYLvgVKTG2qp15*|`ig!>+G=s&KD3Xj|~B2=3S(;J@$w)!&yf4F~4~ zjtn|dX=Tu?7@O`{b#~B=rlaxM&z~C7QwMat9Ju?~`yz3_@k7r{)U!HW0zOyc z&bEromYsiB-{Ld5YhcSZKY~}x2xlN6Z&Hag3)qHG=Nv__+m)-jpXfYBen$lm+LZUg zIdN=6G3Miqel=0?{+5nBlt>6zf8Jwbbn@8mSiG?e+@3*ESI(?Z+}=Lwm6I zq~0Xz7Y`W z4dT*<))E(QMq_hdZO|%G#a)H3-t4^lPyTroI(QWcl-Bk^&jVc$FSHI4bQAxsng%@M z!VY@XfFV6odRCRDTSaMiO4v=Qr<6=QL4|LsurNdUJasob)(?J7cjdFl^_ff*5UFFT zzj0o?R#1UDrIQwC$aymjKKs~A9;!6}k7;~=cT43`(Nox-7GpD|o2}Jh`cx(E3#HGC z=43khsg5{0@6JL(b%J7+@ozVIcIR;p%Ge^}aaAFrdFW2np>}-$zTUZ5mgT+C6JJ#v`M4b_*y)q`AkeCJ1I`U*0Zc)%P1uS~WbWSFcClKGPoUCkLBEeSLtgEyp3T z9<<>LE+{i5ah@Qej!ms4&cT6&;okka9tDVtjC6iuUd<}{ByM8G?CHky3e3;Kix9zb z8$upT*U;*DaMKwDaHTwQc|-0-i4dFS3e|1ZB3y;{6v~k^?oMjy;t(6XPOK6`t) zVZ(5XPZA`xG#ghJpzVP+ofW;S45#SHKQf()Q}`{OrBzmyI!ubAC?0-^Z8sh|07z;u zUu7R>`Y!mY^`626oM*O-`9ofB)xis#8&KJve2hzvREQe0hIkMsi}BH-Nix<2)$QD| zEEA1_Ur#xYc&oN)ZRpOUFp(s@JX?oCA$=YbN6#jIO=gbvgo!yNXJ>To9DVsXc~Q!S z&y6lHMK7~H^ELK4`ke}rJId0)7?fKaYg-uPnRdKS9ht}L($(1D{2=K-h0ud{Z~wg$ z-oo?eI({NCfILo;^LguIb}y!e#NH|rR%hRHI_o}mOlfv(Q5N#K%YNR(yE*}8hTCAy z`Hs3}HJs7$Ji?5z+F)sLc8q($O~diWc;`G7vsVG@ieU2-T9R=;*hy>)EP+ z_)A7D>4Sd*Myluxu+G<_E5F36#}PeYVEAy}f#A1qv=<1>heETWiR1Wrn?C<-Q{ zdvtzm7ZrOX8Aq3$)kQz5wO-hQ;uRLM`}58_v3Ntpk-FCh3oFw{(F4CGWR58pNY;q< zRu%TUvX*hox-sfSnPP@}+#UzG&I+VTVM5gSQw*WZ`h5My-QP55irPF$6`r`TrCw}Q znm4G6qzDZ60gdEQ*77MP#`POJ{5$sBs>wO8$ycK{e%6~U)#lsFwt;L+z z>u{(fVB|fbs>4nexPI|W^u1jxx{qTD?oBZTr=SOID6@x_T1|ZB4a#Av2_sn3cyC>h zp++~t8gu(>Z&iiES>QM$jKAgpdD?kk#N-!C^?(-T*AVE&Z_r0_mYhAO3sAU@p1TCy zcVI%yx%g8a>-i|%g^={Pfsf~d?q za;?oP6!7Cs!3mtL+x*!gNV?tz*KV&$vg>EkVf$#Q?87`baQzoolkSyh-xiOWjVUh@!eZaN23=YB>vV;M!z{AS zFLFCy_f|7#C~JkY;KTWHCu~TaheSQGo=v~^Jj^>jjn1Gi13cG#^X@QhDKdK&8`f|T zc4J>(%vyt1tToh}Kj`Wz@RcC++0ecrM?~y|I*5g)(x?s~a6Z zTz7UsS@@!#hEKH@d^;{fM^9~-v7yZ|I{EVFzS4|A}pbJy9<_LYAt)1tR1hSU2ViOWu1Az1#7p$&nc zvV>@9*(4i<6=gbiSW(~TJ=oc@GP}_S6E%5V_q&z(bSh8`xSLMT_uY*j`p~`E6at%v z%-_1M;2v)K4&S|so|qPOjm|qdSM^cwy)B%avjDX=2gac*)S-IQW27ehQ5HF~fSZ}p4W_^<(cky)QvvPN*&?N8LS2FB@x0{Rd$pu$CFGTJ2W<&aWdA5)>npG#7>pDs9y zZ+KGdR)C>wNC?!@#0Q4H(zAb5L-K^ASC+T7uqH5gywc&j~84B2Z<2 z76{lrp~A^A+t}W`d%Q?j9R&({-a*IiB@b|}peVda(wl==c_~*Q^MBBhjm@<=RU1sf ziMTxw7LIBFZ1F`gfnI~6x3GAX9ko$)#^xN`_E<)FtP_$srgfn|`IB;|HEy)H?;rmS z=)Y$n+X>zCdB>+#f-duo$w0sB2rO%$pXWqVw`^7MTyG0S6pl1_HZCYA=t0?wNUQi! z7}!#9{c_%8@_aBZe3E+VS+PHCOG$VZ^Azq?=sA)%rh!;AcgK5HqVyp&iR)7bGi z^Kg;1I%U;H*Z24%CE7vv{i})EGTrQB?%G*d>n}ZkXF4TD19ic{>!E|S?~0DV;KJ`H zp3?u_q2tmAtxtDg?ieZS+@OcpTQOz>_lC`E{xn2+JxsDg3mcA2vX8OJrbW((T#9|8 zGz%8dHTQy!(@&J-K9c)26;#(p+z(=cIl`Y2eK+QTssY*0%LJ8+AZ(_1J&a6Oy-w#$ zx>~gUz+USK1e$1{**HWrfRuG^#+Aie3CB_EBc$gIb|lBf$dpVs!s-y!cFSU0?OqYG zAF=1*Glu(@Ut?j1ryx}`yD#(Ahe{UWh%u z=#2kA+Y#uPN3>av%e`1!3@b;o@W!1^%(1S;J9+N~Yclo;3W&EYy&K66)-W?1 z{|OrMY3<^`d4rotQ!<;bWL?shxkfOU}J;B(4>7-VM8NoKVpzHS%Hg6Z{h&F2j;?791na z{W5#xO`FLX&LQ`}O4lCF-(~OPViD^t)X@E>&KX?;yJcC2)6epJW7+a)w3@kW^l{n^Fm4Fp#(l3K2 zXYXO2;?Zx4KK2FOLj(_ zXSQl|%bQY0pH9q+scMc!|1z~EGP|J}YrOLWKk9?P>6g>W9al-(ou0^@6a&l7^AG5{ zI9X&~_dLSeedUO>L80Aux&s%1^j-}H$K=o!zPRAWZU;q{is8uCJoVjWAyw?BnCt!9 z9}C|TeJ964aW4~h2)zB%ij}yV6n#tC-)_X?Y9nPAl~D^96><4JPpI*-f|5|=09eOQ zC^lZ$@0^cA6up5Z>Z&c({5qKtgqAt<@SF&>3Bud+kQImvv-qWyOIMt*W)~v%@YT^to={V`NtRJqoJ!8|xJi7!XkKm|5Pn9W zN-(g&1|d8(xCQ&Vb;WeIyn+%t&z7q`i@p`CLABpc*~DD#3%ET)NAbyJ)SoCyBDurB z)V_F7wa}FA_GS`xbk}KLx#-Ed1f&Sf^7eik9{{>P{uuv*yEi#|sgG%9ixs635r!$J z_s}+S9BQU$+wQ&FLZ2!ZcZ4WotF}yp$@L@bobvJvS zZsx4_`SsmRD#|!nCuX8ww8dgu6*3;= zx%(j)cG^S;6v5u&I470NRun4=i}34YU6ji}FyfLBSL7kW=6 zo|`vjYwL2B6@t0U2-f={t=qTd_UxEbE*y2ePQvcRwJ`Td$xGAz(yNC5UJEGKQUEb3 zzOPjD6twS*qe!KFG)rw?HH9<;K5OT*elyQ+mqFL^Sd|x}^13=DyXQIGd|xbROEaN~ zZn`aU>NlL|uL(2aJRm7rr4tU{MGcBN!MSlp-NS2_X~ap8Vem8(%X_N)ipNj<7>t76 zKzy4!=V5`m0e|;I5nk4q>J10Ud!_kOQLTIS*==2&g8!3G}E zEvHW0p7NDt3Jm9nhD_N#$>SPW7p5F2N<6nPe2k7^uXY#;1YLG`+ablBlGKc$i065L zaS%t(CedWr<=`#q)2&SHQ}9jiCW`J5&6!7w7jZ57KKhiXN0g|mL(X?5u|i89IR!h7ZQn|Gfx zQ+3tJxgFPXpGOZotzAcO$EJ8)~N;LMG^!GAI`KgzD?y$oiDzvH%7%2*N zX1&jJQBLNmQ75$FsPC-Uw!Jv2P?<|4?cy(OkF)P`f>M86wL`xulodkactfi@)X_QA zDrH4lDRIkC>48QBo!W-zb}W(r3p20@I{&gpFj92?NFBZVpK8LizRSCrN1qG%uCgPH z(pAr+Z}Uh(6g}l%E*VoHHFy5e++K9QL~^dV=(@V(+;+{WsFh*OxCY%Fh0cCWVbpoZ zuyu}T9eFJ|t6IY@Iu#9#{9INb4wy>N({ppp%vy2M`4?3;OfvE|bUv_W;N5vdkc(*Y-h}&Qh6#5`vbmj7kh%99s-O@5aX;$=&HooJ@C-rLC z^W{a4sX~{%ObCOqFnFDnxK}|&)%{i`K*D+QdRE6YFIksP>pFMVCHS8g;Mm|TV*m3x zw8G@|F0a_>tVC;3xL66t;*L<$(bQ-{*burzU~IY~){p}AowDm?NOgx06-GjEI|Qp> zcSvjBH`M*=O+V6{889|t^?_dd_jp48Mw2r=QDEGLIvC zjBj6tSjIOz8xpf#i{#wRo0qvSuBGTp{H&>cC0Fb-ixsm9vhc2Bh?_pay0hGQKb4@% zrquMTm9K7I;L2G>aKz)hQPdYjV)JD5Ms%eda;)i!Vdqmv>=QYKbg+P=9)ZHf-ekGR zcD>80v8OE3)?mK8?qe=1X4wwOykHaac&XRScG*)2`)pPB!eo8TX4aFr*7;2XPA0`PjsPJLVMI z(D~iNI8|14J-MG1LZu&mlHc=QN2_?m#jP)D6kfNkVSey*i;8fWXIdsdg#q_a;_ z6kIHdM7X8d;AGv933!l5{dAc+;o0gI1ym0ypgL9?%!H@xI138g7E#4MR`E6Nl7-aP zx)8x0O$8%L;7zQD=Pfu`chse$XX)=vd6x@p!V%7{&rY)Q=iN7n`8*_D*NkwI%t5zA z`OCtePk{~Fyu>?~1|RsWV{B^`Yeg8Bl<`t_-CwMgTXnitQ+wDYaw4fJ4A<=ICLZUD zChDmqy+SgRuswsl*4gI9YVsk{YV;*mel7nhQd@AU;JZ<$9eXzH6YUJX{uWC5rS|R$ z<0`8}QH~G@Db8hyrUbJl`u;_8nFtXGZ7-DfIF}R@Hd>uI=i|$B^48|eMCw~@=iGZm zNpY5ClY0#<0GHVJR7Et&%vlvu33|ZmPpQr}1^4{hmsQ2_G9Y7luu0HM0y8S}0zvMs zeoc#JTwFc$3u_V}^z7m~cd;BwWnWFA0VsMKI(>O~!$p|^M&8$D6(^48{Jba%)4K7gu!bVv^4E|TjzbvO1vkZCR1Y*1vBeYiNrDrHi>Gx z8NU1ZbZ%U7{d>B<_SE#sYROq@dzqrZMS<^*t|)QJChE9u#(&1o>a0Ir^;zrJRT7#c z4mQKFG54FgUS%{zn+OTdEl%FEs`qK&oEvFo!K}x4Tb@l=SkNkStz;6owd!;>iK0=b zs%SDf$8)JGHh%2Ho$aWjzKu0?yk{lhROF<6;;bl1#(98$S>Tj9+z`LbSUYlu-Tv(2 zQ>DK3Pp|QsMqYQTWV}lIP<%goP0096xPB*}L(%6@XToCP_e0Gp{u4Ek*B{496 zwkv8|>&`7OUY5Bo`UE|sp0qV02wtk=IR_to(DG-?gxJ6Tlvp5QstBXIVkUAz9^CeT~ry{OcK08`SL#C z2FpcuhU+p3>(oV199xOcy#xr6>U>*=QZGRR=HD^WVSkTD7qtT~2@5kt@I962GS}&5 zS49<1^{H8Ru9DAAyy7GgQ9af#TWrvnkP-Xmdkar zeX>w;lpyRVrQBB3`gxwWiICd9PM;Zx93Ape7$ChMF*+)LEHWEh(IFjMx+BDoN}kt%qMePF}PX_hr=EQ*-Sy(;klH>4|xq yy&mM+GU(i!XiLUY-1B`)kMF7Z&8wxv>i<6oYQb%|K_1rt00006;3t) literal 0 HcmV?d00001 diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_travel@4x.png b/apps/multiplatform/common/src/commonMain/resources/MR/images/wallpaper_travel@4x.png new file mode 100644 index 0000000000000000000000000000000000000000..64ec1373312855069a0f079ea1f8bf6cf55f0955 GIT binary patch literal 80606 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 z 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μy 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%0AZP9GDx(de+*du1H`)3*E!9m(ih_F; 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%0At?Qucb^IfYw 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 CHP}}G literal 0 HcmV?d00001 diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml index 310a021ff2..ba11e0e29b 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml @@ -847,7 +847,6 @@ Proibisci l\'invio di messaggi vocali. ricevuto, vietato Ripristina i colori - Salva colore Imposta 1 giorno Imposta le preferenze del gruppo Tema diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/iw/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/iw/strings.xml index 7899c374b2..e335c199d0 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/iw/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/iw/strings.xml @@ -898,7 +898,6 @@ שמור סיסמה ופתח את הצ׳אט שמור ארכיון בחירת אנשי קשר - שמור צבע קוד גישה להשמדה עצמית שניות אישור diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml index 83d59b3705..eebb40a1c5 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml @@ -792,7 +792,6 @@ 保存 ネットワーク設定を更新しますか? 設定を更新すると、全サーバにクライントの再接続が行われます。 - 色を保存 あなたが次を許可しています: オン グループ設定を行う diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ko/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ko/strings.xml index af3972035f..3caa99bc59 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ko/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ko/strings.xml @@ -757,7 +757,6 @@ 저장하고 대화 상대에게 알리기 지우기 아카이브 저장하기 - 색상 저장하기 암호 저장소에 비밀번호 저장하기 데이터베이스 백업 복원하기 데이터베이스 백업을 복원한 후 이전 비밀번호를 입력해 주세요. 이 작업은 되돌릴 수 없어요. diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/lt/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/lt/strings.xml index 43237fa2a9..b5191f342d 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/lt/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/lt/strings.xml @@ -189,7 +189,6 @@ Daugiau neberodyti Tamsus Atstatyti spalvas - Įrašyti spalvą Grupės parinktys Ištrinti visiems Tiesioginės žinutės diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ml/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ml/strings.xml index 92bd3e381a..455f9d53bd 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ml/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ml/strings.xml @@ -323,7 +323,6 @@ പഴയപടിയാക്കുക സംവിധാനം സംവിധാനം - നിറം സംരക്ഷിക്കുക ശീർഷകം രണ്ടാംതരമായ അതെ diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml index ab10a01a66..8c803bdeea 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml @@ -814,7 +814,6 @@ Wanneer je een incognito profiel met iemand deelt, wordt dit profiel gebruikt voor de groepen waarvoor ze je uitnodigen. Thema Kleuren resetten - Kleur opslaan Systeem ja gekregen, verboden diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml index d667126730..825b5200c4 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml @@ -799,7 +799,6 @@ Zabroń wysyłania znikających wiadomości. otrzymane, zabronione Resetuj kolory - Zapisz kolor Ustaw 1 dzień System System diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/pt-rBR/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/pt-rBR/strings.xml index cc0bd49454..7d4570e561 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/pt-rBR/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/pt-rBR/strings.xml @@ -485,7 +485,6 @@ Reverter Salvar Redefinir cores - Salvar cor interface italiana Notificações periódicas Câmera diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/pt/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/pt/strings.xml index 7889ef396e..4bb442faf8 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/pt/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/pt/strings.xml @@ -370,7 +370,6 @@ Você está a tentar convidar um contato com quem partilhou um perfil anónimo para o grupo no qual voçê está a usar o seu perfil principal Conexão O modo anónimo protege a privacidade do nome e da imagem do seu perfil principal — para cada novo contato um novo perfil aleatório é criado. - Salvar cor você partilhou ligação de utilização única você partilhou ligação anónima de utilização única Ligação de conexão inválida diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml index a71638eae0..33b511c1e5 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml @@ -848,7 +848,6 @@ Темная Тема - Сохранить цвет Сбросить цвета Акцент diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/th/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/th/strings.xml index 5701c0ca78..f6988ca367 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/th/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/th/strings.xml @@ -855,7 +855,6 @@ เปลี่ยนกลับ บันทึก รีเซ็ตสี - บันทึกสี ได้รับ, ห้าม ผู้รับจะเห็นการอัปเดตเมื่อคุณพิมพ์ ลดการใช้แบตเตอรี่ diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml index 9ae8707c11..f659db0e2a 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml @@ -122,7 +122,6 @@ SimpleX Koyu tema Tema - Rengi kaydet Temayı içe aktar Temayı içe aktarırken hata oluştu Dosyanın doğru YAML sözdizimine sahip olduğundan emin olun. Tema dosyası yapısının bir örneğine sahip olmak için temayı dışa aktarın. diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml index 948f91b89a..2d52051098 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml @@ -450,7 +450,6 @@ Змінити роль у групі\? Помилка при вилученні учасника Ваш профіль чату буде відправлений учасникам групи - Зберегти колір Видалення для всіх Голосові повідомлення Голосові повідомлення заборонені в цьому чаті. diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml index 536207892d..1002e458f5 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml @@ -831,7 +831,6 @@ 恢复 重置颜色 - 保存颜色 减少电池使用量 为了保护时区,图像/语音文件使用 UTC。 使用聊天 diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml index c9d4298bc7..b6434c39db 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml @@ -827,7 +827,6 @@ 儲存群組檔案時出錯 恢復 主題 - 儲存顏色 你允許 修改群組內的設定 私訊 diff --git a/apps/multiplatform/common/src/commonTest/kotlin/chat/simplex/app/ThemesTest.kt b/apps/multiplatform/common/src/commonTest/kotlin/chat/simplex/app/ThemesTest.kt new file mode 100644 index 0000000000..ae838dcff5 --- /dev/null +++ b/apps/multiplatform/common/src/commonTest/kotlin/chat/simplex/app/ThemesTest.kt @@ -0,0 +1,38 @@ +package chat.simplex.app + +import chat.simplex.common.ui.theme.* +import kotlin.test.Test +import kotlin.test.assertEquals + +// use this command for testing: +// ./gradlew desktopTest +class ThemesTest { + @Test + fun testSkipDuplicates() { + val r = ArrayList() + r.add(ThemeOverrides("UUID", DefaultTheme.DARK)) + r.add(ThemeOverrides("UUID", DefaultTheme.DARK)) + r.add(ThemeOverrides("UUID", DefaultTheme.LIGHT)) + r.add(ThemeOverrides("UUID2", DefaultTheme.DARK)) + r.add(ThemeOverrides("UUID3", DefaultTheme.LIGHT, wallpaper = ThemeWallpaper())) + r.add(ThemeOverrides("UUID4", DefaultTheme.LIGHT, wallpaper = null)) + r.add(ThemeOverrides("UUID5", DefaultTheme.LIGHT, wallpaper = ThemeWallpaper(preset = "something"))) + r.add(ThemeOverrides("UUID5", DefaultTheme.LIGHT, wallpaper = ThemeWallpaper(preset = "something2"))) + r.add(ThemeOverrides("UUID6", DefaultTheme.LIGHT, wallpaper = ThemeWallpaper(preset = "something2"))) + r.add(ThemeOverrides("UUID7", DefaultTheme.DARK, wallpaper = ThemeWallpaper(preset = "something2"))) + r.add(ThemeOverrides("UUID8", DefaultTheme.DARK, wallpaper = ThemeWallpaper(imageFile = "image"))) + r.add(ThemeOverrides("UUID9", DefaultTheme.DARK, wallpaper = ThemeWallpaper(imageFile = "image2"))) + r.add(ThemeOverrides("UUID10", DefaultTheme.LIGHT, wallpaper = ThemeWallpaper(imageFile = "image"))) + assertEquals( + r.skipDuplicates(), listOf( + ThemeOverrides("UUID", DefaultTheme.DARK), + ThemeOverrides("UUID3", DefaultTheme.LIGHT, wallpaper = ThemeWallpaper()), + ThemeOverrides("UUID5", DefaultTheme.LIGHT, wallpaper = ThemeWallpaper(preset = "something")), + ThemeOverrides("UUID6", DefaultTheme.LIGHT, wallpaper = ThemeWallpaper(preset = "something2")), + ThemeOverrides("UUID7", DefaultTheme.DARK, wallpaper = ThemeWallpaper(preset = "something2")), + ThemeOverrides("UUID8", DefaultTheme.DARK, wallpaper = ThemeWallpaper(imageFile = "image")), + ThemeOverrides("UUID10", DefaultTheme.LIGHT, wallpaper = ThemeWallpaper(imageFile = "image")) + ) + ) + } +} diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/DesktopApp.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/DesktopApp.kt index 7b7762eefc..eba22603d8 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/DesktopApp.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/DesktopApp.kt @@ -4,8 +4,7 @@ import androidx.compose.desktop.ui.tooling.preview.Preview import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text +import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/AppCommon.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/AppCommon.desktop.kt index 71f862b30a..33a3ae2578 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/AppCommon.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/AppCommon.desktop.kt @@ -26,7 +26,7 @@ fun initApp() { } applyAppLocale() if (DatabaseUtils.ksSelfDestructPassword.get() == null) { - initChatControllerAndRunMigrations() + initChatControllerOnStart() } // LALAL //testCrypto() diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Files.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Files.desktop.kt index 9b2368fcd3..5f33e2a943 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Files.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Files.desktop.kt @@ -13,8 +13,10 @@ actual val dataDir: File = File(desktopPlatform.dataPath) actual val tmpDir: File = File(System.getProperty("java.io.tmpdir") + File.separator + "simplex").also { it.deleteOnExit() } actual val filesDir: File = File(dataDir.absolutePath + File.separator + "simplex_v1_files") actual val appFilesDir: File = filesDir +actual val wallpapersDir: File = File(dataDir.absolutePath + File.separator + "simplex_v1_assets" + File.separator + "wallpapers").also { it.mkdirs() } actual val coreTmpDir: File = File(dataDir.absolutePath + File.separator + "tmp") actual val dbAbsolutePrefixPath: String = dataDir.absolutePath + File.separator + "simplex_v1" +actual val preferencesDir = File(desktopPlatform.configPath).also { it.parentFile.mkdirs() } actual val chatDatabaseFileName: String = "simplex_v1_chat.db" actual val agentDatabaseFileName: String = "simplex_v1_agent.db" diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Resources.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Resources.desktop.kt index b758988227..f8c123eea1 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Resources.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Resources.desktop.kt @@ -1,12 +1,17 @@ package chat.simplex.common.platform import androidx.compose.runtime.* +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.toComposeImageBitmap import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.* import chat.simplex.common.simplexWindowState +import chat.simplex.common.ui.theme.reactOnDarkThemeChanges +import com.jthemedetecor.OsThemeDetector import com.russhwolf.settings.* +import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.desc.desc import java.io.File @@ -18,7 +23,15 @@ actual fun font(name: String, res: String, weight: FontWeight, style: FontStyle) actual fun StringResource.localized(): String = desc().toString() -actual fun isInNightMode() = false +private val detector: OsThemeDetector = OsThemeDetector.getDetector() +actual fun isInNightMode() = try { + detector.isDark +} +catch (e: Exception) { + Log.e(TAG, e.stackTraceToString()) + /* On Mac this code can produce exception */ + false +} private val settingsFile = File(desktopPlatform.configPath + File.separator + "settings.properties") @@ -58,3 +71,6 @@ actual fun isRtl(text: CharSequence): Boolean { dir == Character.DIRECTIONALITY_RIGHT_TO_LEFT || dir == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC } } + +actual fun ImageResource.toComposeImageBitmap(): ImageBitmap? = + image.toComposeImageBitmap() diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/ui/theme/Theme.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/ui/theme/Theme.desktop.kt index 358c20d769..d7dc1ca859 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/ui/theme/Theme.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/ui/theme/Theme.desktop.kt @@ -10,6 +10,10 @@ private val detector: OsThemeDetector = OsThemeDetector.getDetector() registerListener(::reactOnDarkThemeChanges) } +// TODO: explore possibility to use +//@Composable +//actual fun isSystemInDarkTheme(): Boolean = androidx.compose.foundation.isSystemInDarkTheme() + @Composable actual fun isSystemInDarkTheme(): Boolean = try { detector.isDark diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/call/CallView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/call/CallView.desktop.kt index d3bf1bf01e..d6331616cc 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/call/CallView.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/call/CallView.desktop.kt @@ -25,11 +25,6 @@ val connections = ArrayList() @Composable actual fun ActiveCallView() { - val endCall = { - val call = chatModel.activeCall.value - if (call != null) withBGApi { chatModel.callManager.endCall(call) } - } - BackHandler(onBack = endCall) val scope = rememberCoroutineScope() WebRTCController(chatModel.callCommand) { apiMsg -> Log.d(TAG, "received from WebRTCController: $apiMsg") diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/Appearance.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/Appearance.desktop.kt index 4e4846bc9f..669dd1949d 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/Appearance.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/Appearance.desktop.kt @@ -4,34 +4,23 @@ import SectionBottomSpacer import SectionDividerSpaced import SectionView import androidx.compose.foundation.layout.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import chat.simplex.common.model.ChatModel import chat.simplex.common.model.SharedPreference -import chat.simplex.common.platform.ColumnWithScrollBar -import chat.simplex.common.platform.defaultLocale -import chat.simplex.common.ui.theme.ThemeColor +import chat.simplex.common.platform.* import chat.simplex.common.views.helpers.* -import chat.simplex.common.views.usersettings.AppearanceScope.ColorEditor import chat.simplex.res.MR import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.delay import java.util.Locale @Composable -actual fun AppearanceView(m: ChatModel, showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit)) { +actual fun AppearanceView(m: ChatModel) { AppearanceScope.AppearanceLayout( m.controller.appPrefs.appLanguage, m.controller.appPrefs.systemDarkTheme, - showSettingsModal = showSettingsModal, - editColor = { name, initialColor -> - ModalManager.start.showModalCloseable { close -> - ColorEditor(name, initialColor, close) - } - }, ) } @@ -39,8 +28,6 @@ actual fun AppearanceView(m: ChatModel, showSettingsModal: (@Composable (ChatMod fun AppearanceScope.AppearanceLayout( languagePref: SharedPreference, systemDarkTheme: SharedPreference, - showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), - editColor: (ThemeColor, Color) -> Unit, ) { ColumnWithScrollBar( Modifier.fillMaxWidth(), @@ -63,10 +50,11 @@ fun AppearanceScope.AppearanceLayout( } } SectionDividerSpaced(maxTopPadding = true) - ProfileImageSection() + ThemesSection(systemDarkTheme) SectionDividerSpaced(maxTopPadding = true) - ThemesSection(systemDarkTheme, showSettingsModal, editColor) + ProfileImageSection() + SectionBottomSpacer() } } diff --git a/apps/multiplatform/desktop/src/jvmMain/kotlin/chat/simplex/desktop/Main.kt b/apps/multiplatform/desktop/src/jvmMain/kotlin/chat/simplex/desktop/Main.kt index 7171f17991..9925a6346b 100644 --- a/apps/multiplatform/desktop/src/jvmMain/kotlin/chat/simplex/desktop/Main.kt +++ b/apps/multiplatform/desktop/src/jvmMain/kotlin/chat/simplex/desktop/Main.kt @@ -18,6 +18,7 @@ import java.io.File fun main() { initHaskell() + runMigrations() initApp() tmpDir.deleteRecursively() tmpDir.mkdir() From b0516b64408b8b41350ef04450a1b15a5f1d8c7a Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Sat, 25 May 2024 11:18:49 +0100 Subject: [PATCH 03/21] core: 5.7.4.1 --- cabal.project | 2 +- package.yaml | 2 +- scripts/nix/sha256map.nix | 2 +- simplex-chat.cabal | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cabal.project b/cabal.project index 62764bb139..9efbb332ff 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: 6309f92c6860fce39d6675eb92fc460bdc3db01d + tag: df35c50b99a1291aac3ff86ed71387bb4f03c984 source-repository-package type: git diff --git a/package.yaml b/package.yaml index fa4d066c6b..606cd16b4e 100644 --- a/package.yaml +++ b/package.yaml @@ -1,5 +1,5 @@ name: simplex-chat -version: 5.7.4.0 +version: 5.7.4.1 #synopsis: #description: homepage: https://github.com/simplex-chat/simplex-chat#readme diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 74286532bd..7c11ea0e9f 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."6309f92c6860fce39d6675eb92fc460bdc3db01d" = "0aiyjcjraispkripv1viry6357nxvydv2sb6k5ali0hr8cnsskg3"; + "https://github.com/simplex-chat/simplexmq.git"."df35c50b99a1291aac3ff86ed71387bb4f03c984" = "0a3vvay14a0f7ypl94fag23g0z7b1kpq3l36kw6jgb0fjhr84m83"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; diff --git a/simplex-chat.cabal b/simplex-chat.cabal index 86b2b9668e..681bcc9e57 100644 --- a/simplex-chat.cabal +++ b/simplex-chat.cabal @@ -5,7 +5,7 @@ cabal-version: 1.12 -- see: https://github.com/sol/hpack name: simplex-chat -version: 5.7.4.0 +version: 5.7.4.1 category: Web, System, Services, Cryptography homepage: https://github.com/simplex-chat/simplex-chat#readme author: simplex.chat From dccd6631afbac678fb774e3e18f2ba242dcdb362 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Sat, 25 May 2024 17:06:11 +0100 Subject: [PATCH 04/21] 5.7.4: ios 219, android 212, desktop 48 --- apps/ios/SimpleX.xcodeproj/project.pbxproj | 64 +++++++++++----------- apps/multiplatform/gradle.properties | 8 +-- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 30345d6895..be1ca4c444 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -53,6 +53,11 @@ 5C5E5D3B2824468B00B0488A /* ActiveCallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5E5D3A2824468B00B0488A /* ActiveCallView.swift */; }; 5C5F2B6D27EBC3FE006A9D5F /* ImagePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5F2B6C27EBC3FE006A9D5F /* ImagePicker.swift */; }; 5C5F2B7027EBC704006A9D5F /* ProfileImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5F2B6F27EBC704006A9D5F /* ProfileImage.swift */; }; + 5C614CFB2C021C1C000E7758 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C614CF62C021C1C000E7758 /* libffi.a */; }; + 5C614CFC2C021C1C000E7758 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C614CF72C021C1C000E7758 /* libgmpxx.a */; }; + 5C614CFD2C021C1C000E7758 /* libHSsimplex-chat-5.7.4.1-FMTNcSSNT86KdfUI39X2r7-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C614CF82C021C1C000E7758 /* libHSsimplex-chat-5.7.4.1-FMTNcSSNT86KdfUI39X2r7-ghc9.6.3.a */; }; + 5C614CFE2C021C1C000E7758 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C614CF92C021C1C000E7758 /* libgmp.a */; }; + 5C614CFF2C021C1C000E7758 /* libHSsimplex-chat-5.7.4.1-FMTNcSSNT86KdfUI39X2r7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C614CFA2C021C1C000E7758 /* libHSsimplex-chat-5.7.4.1-FMTNcSSNT86KdfUI39X2r7.a */; }; 5C65DAF929D0CC20003CEE45 /* DeveloperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C65DAF829D0CC20003CEE45 /* DeveloperView.swift */; }; 5C65F343297D45E100B67AF3 /* VersionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C65F341297D3F3600B67AF3 /* VersionView.swift */; }; 5C6BA667289BD954009B8ECC /* DismissSheets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C6BA666289BD954009B8ECC /* DismissSheets.swift */; }; @@ -115,11 +120,6 @@ 5CD67B8F2B0E858A00C510B1 /* hs_init.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CD67B8D2B0E858A00C510B1 /* hs_init.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5CD67B902B0E858A00C510B1 /* hs_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 5CD67B8E2B0E858A00C510B1 /* hs_init.c */; }; 5CDCAD482818589900503DA2 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CDCAD472818589900503DA2 /* NotificationService.swift */; }; - 5CE0E8AB2BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8A62BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg-ghc9.6.3.a */; }; - 5CE0E8AC2BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8A72BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg.a */; }; - 5CE0E8AD2BF0C1B5008D6E06 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8A82BF0C1B5008D6E06 /* libgmp.a */; }; - 5CE0E8AE2BF0C1B5008D6E06 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8A92BF0C1B5008D6E06 /* libffi.a */; }; - 5CE0E8AF2BF0C1B5008D6E06 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8AA2BF0C1B5008D6E06 /* libgmpxx.a */; }; 5CE2BA702845308900EC33A6 /* SimpleXChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; }; 5CE2BA712845308900EC33A6 /* SimpleXChat.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 5CE2BA77284530BF00EC33A6 /* SimpleXChat.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CE2BA76284530BF00EC33A6 /* SimpleXChat.h */; }; @@ -316,6 +316,11 @@ 5C5E5D3C282447AB00B0488A /* CallTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallTypes.swift; sourceTree = ""; }; 5C5F2B6C27EBC3FE006A9D5F /* ImagePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePicker.swift; sourceTree = ""; }; 5C5F2B6F27EBC704006A9D5F /* ProfileImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileImage.swift; sourceTree = ""; }; + 5C614CF62C021C1C000E7758 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; + 5C614CF72C021C1C000E7758 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; + 5C614CF82C021C1C000E7758 /* libHSsimplex-chat-5.7.4.1-FMTNcSSNT86KdfUI39X2r7-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.7.4.1-FMTNcSSNT86KdfUI39X2r7-ghc9.6.3.a"; sourceTree = ""; }; + 5C614CF92C021C1C000E7758 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; + 5C614CFA2C021C1C000E7758 /* libHSsimplex-chat-5.7.4.1-FMTNcSSNT86KdfUI39X2r7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.7.4.1-FMTNcSSNT86KdfUI39X2r7.a"; sourceTree = ""; }; 5C636F662AAB3D2400751C84 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = "uk.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = ""; }; 5C636F672AAB3D2400751C84 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/InfoPlist.strings; sourceTree = ""; }; 5C65DAE429C77136003CEE45 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; @@ -420,11 +425,6 @@ 5CDCAD7428188D2900503DA2 /* APITypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APITypes.swift; sourceTree = ""; }; 5CDCAD7D2818941F00503DA2 /* API.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = API.swift; sourceTree = ""; }; 5CDCAD80281A7E2700503DA2 /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = ""; }; - 5CE0E8A62BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg-ghc9.6.3.a"; sourceTree = ""; }; - 5CE0E8A72BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg.a"; sourceTree = ""; }; - 5CE0E8A82BF0C1B5008D6E06 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; - 5CE0E8A92BF0C1B5008D6E06 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; - 5CE0E8AA2BF0C1B5008D6E06 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; 5CE1330328E118CC00FFFD8C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = "de.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = ""; }; 5CE1330428E118CC00FFFD8C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = ""; }; 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SimpleXChat.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -529,13 +529,13 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 5C614CFD2C021C1C000E7758 /* libHSsimplex-chat-5.7.4.1-FMTNcSSNT86KdfUI39X2r7-ghc9.6.3.a in Frameworks */, + 5C614CFF2C021C1C000E7758 /* libHSsimplex-chat-5.7.4.1-FMTNcSSNT86KdfUI39X2r7.a in Frameworks */, + 5C614CFC2C021C1C000E7758 /* libgmpxx.a in Frameworks */, 5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */, - 5CE0E8AE2BF0C1B5008D6E06 /* libffi.a in Frameworks */, - 5CE0E8AD2BF0C1B5008D6E06 /* libgmp.a in Frameworks */, + 5C614CFB2C021C1C000E7758 /* libffi.a in Frameworks */, + 5C614CFE2C021C1C000E7758 /* libgmp.a in Frameworks */, 5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */, - 5CE0E8AC2BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg.a in Frameworks */, - 5CE0E8AB2BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg-ghc9.6.3.a in Frameworks */, - 5CE0E8AF2BF0C1B5008D6E06 /* libgmpxx.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -601,11 +601,11 @@ 5C764E5C279C70B7000C6508 /* Libraries */ = { isa = PBXGroup; children = ( - 5CE0E8A92BF0C1B5008D6E06 /* libffi.a */, - 5CE0E8A82BF0C1B5008D6E06 /* libgmp.a */, - 5CE0E8AA2BF0C1B5008D6E06 /* libgmpxx.a */, - 5CE0E8A62BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg-ghc9.6.3.a */, - 5CE0E8A72BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg.a */, + 5C614CF62C021C1C000E7758 /* libffi.a */, + 5C614CF92C021C1C000E7758 /* libgmp.a */, + 5C614CF72C021C1C000E7758 /* libgmpxx.a */, + 5C614CF82C021C1C000E7758 /* libHSsimplex-chat-5.7.4.1-FMTNcSSNT86KdfUI39X2r7-ghc9.6.3.a */, + 5C614CFA2C021C1C000E7758 /* libHSsimplex-chat-5.7.4.1-FMTNcSSNT86KdfUI39X2r7.a */, ); path = Libraries; sourceTree = ""; @@ -1552,7 +1552,7 @@ CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 215; + CURRENT_PROJECT_VERSION = 219; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; @@ -1577,7 +1577,7 @@ "@executable_path/Frameworks", ); LLVM_LTO = YES_THIN; - MARKETING_VERSION = 5.7.3; + MARKETING_VERSION = 5.7.4; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_NAME = SimpleX; SDKROOT = iphoneos; @@ -1601,7 +1601,7 @@ CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 215; + CURRENT_PROJECT_VERSION = 219; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; @@ -1626,7 +1626,7 @@ "@executable_path/Frameworks", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.7.3; + MARKETING_VERSION = 5.7.4; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_NAME = SimpleX; SDKROOT = iphoneos; @@ -1687,7 +1687,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 215; + CURRENT_PROJECT_VERSION = 219; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; GCC_OPTIMIZATION_LEVEL = s; @@ -1702,7 +1702,7 @@ "@executable_path/../../Frameworks", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.7.3; + MARKETING_VERSION = 5.7.4; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1724,7 +1724,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 215; + CURRENT_PROJECT_VERSION = 219; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; ENABLE_CODE_COVERAGE = NO; @@ -1739,7 +1739,7 @@ "@executable_path/../../Frameworks", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.7.3; + MARKETING_VERSION = 5.7.4; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1761,7 +1761,7 @@ CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 215; + CURRENT_PROJECT_VERSION = 219; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1787,7 +1787,7 @@ "$(PROJECT_DIR)/Libraries/sim", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.7.3; + MARKETING_VERSION = 5.7.4; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; @@ -1812,7 +1812,7 @@ CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 215; + CURRENT_PROJECT_VERSION = 219; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1838,7 +1838,7 @@ "$(PROJECT_DIR)/Libraries/sim", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.7.3; + MARKETING_VERSION = 5.7.4; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; diff --git a/apps/multiplatform/gradle.properties b/apps/multiplatform/gradle.properties index fcbf8b9d9e..2c44f841f9 100644 --- a/apps/multiplatform/gradle.properties +++ b/apps/multiplatform/gradle.properties @@ -26,11 +26,11 @@ android.enableJetifier=true kotlin.mpp.androidSourceSetLayoutVersion=2 kotlin.jvm.target=11 -android.version_name=5.7.3 -android.version_code=206 +android.version_name=5.7.4 +android.version_code=212 -desktop.version_name=5.7.3 -desktop.version_code=44 +desktop.version_name=5.7.4 +desktop.version_code=48 kotlin.version=1.9.23 gradle.plugin.version=8.2.0 From a03ccd0ba606b24296060d7df06de46413df6d81 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Sat, 25 May 2024 18:55:15 +0100 Subject: [PATCH 05/21] ios: update core library 5.8.0.3 --- apps/ios/SimpleX.xcodeproj/project.pbxproj | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 3ea66b6087..70c5df74ae 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -76,11 +76,6 @@ 5C9CC7AD28C55D7800BEF955 /* DatabaseEncryptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C9CC7AC28C55D7800BEF955 /* DatabaseEncryptionView.swift */; }; 5C9D13A3282187BB00AB8B43 /* WebRTC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C9D13A2282187BB00AB8B43 /* WebRTC.swift */; }; 5C9D811A2AA8727A001D49FD /* CryptoFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C9D81182AA7A4F1001D49FD /* CryptoFile.swift */; }; - 5C9F3DD62BFBCDD90003B86B /* libHSsimplex-chat-5.8.0.2-8RkLdmy05dJBsgWrGV50Uf-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C9F3DD12BFBCDD80003B86B /* libHSsimplex-chat-5.8.0.2-8RkLdmy05dJBsgWrGV50Uf-ghc9.6.3.a */; }; - 5C9F3DD72BFBCDD90003B86B /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C9F3DD22BFBCDD80003B86B /* libffi.a */; }; - 5C9F3DD82BFBCDD90003B86B /* libHSsimplex-chat-5.8.0.2-8RkLdmy05dJBsgWrGV50Uf.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C9F3DD32BFBCDD80003B86B /* libHSsimplex-chat-5.8.0.2-8RkLdmy05dJBsgWrGV50Uf.a */; }; - 5C9F3DD92BFBCDD90003B86B /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C9F3DD42BFBCDD90003B86B /* libgmpxx.a */; }; - 5C9F3DDA2BFBCDD90003B86B /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C9F3DD52BFBCDD90003B86B /* libgmp.a */; }; 5C9FD96E27A5D6ED0075386C /* SendMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C9FD96D27A5D6ED0075386C /* SendMessageView.swift */; }; 5CA059DC279559F40002BEB4 /* Tests_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CA059DB279559F40002BEB4 /* Tests_iOS.swift */; }; 5CA059DE279559F40002BEB4 /* Tests_iOSLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CA059DD279559F40002BEB4 /* Tests_iOSLaunchTests.swift */; }; @@ -144,6 +139,11 @@ 5CEACCED27DEA495000BD591 /* MsgContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEACCEC27DEA495000BD591 /* MsgContentView.swift */; }; 5CEBD7462A5C0A8F00665FE2 /* KeyboardPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */; }; 5CEBD7482A5F115D00665FE2 /* SetDeliveryReceiptsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEBD7472A5F115D00665FE2 /* SetDeliveryReceiptsView.swift */; }; + 5CEE87942C024F4F00583B8A /* libHSsimplex-chat-5.8.0.3-3OkzEeUKATkEGDdUZR1g6G-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CEE878F2C024F4F00583B8A /* libHSsimplex-chat-5.8.0.3-3OkzEeUKATkEGDdUZR1g6G-ghc9.6.3.a */; }; + 5CEE87952C024F4F00583B8A /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CEE87902C024F4F00583B8A /* libgmp.a */; }; + 5CEE87962C024F4F00583B8A /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CEE87912C024F4F00583B8A /* libgmpxx.a */; }; + 5CEE87972C024F4F00583B8A /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CEE87922C024F4F00583B8A /* libffi.a */; }; + 5CEE87982C024F4F00583B8A /* libHSsimplex-chat-5.8.0.3-3OkzEeUKATkEGDdUZR1g6G.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CEE87932C024F4F00583B8A /* libHSsimplex-chat-5.8.0.3-3OkzEeUKATkEGDdUZR1g6G.a */; }; 5CF937202B24DE8C00E1D781 /* SharedFileSubscriber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF9371F2B24DE8C00E1D781 /* SharedFileSubscriber.swift */; }; 5CF937232B2503D000E1D781 /* NSESubscriber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF937212B25034A00E1D781 /* NSESubscriber.swift */; }; 5CFA59C42860BC6200863A68 /* MigrateToAppGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */; }; @@ -354,11 +354,6 @@ 5C9CC7AC28C55D7800BEF955 /* DatabaseEncryptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseEncryptionView.swift; sourceTree = ""; }; 5C9D13A2282187BB00AB8B43 /* WebRTC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebRTC.swift; sourceTree = ""; }; 5C9D81182AA7A4F1001D49FD /* CryptoFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoFile.swift; sourceTree = ""; }; - 5C9F3DD12BFBCDD80003B86B /* libHSsimplex-chat-5.8.0.2-8RkLdmy05dJBsgWrGV50Uf-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.8.0.2-8RkLdmy05dJBsgWrGV50Uf-ghc9.6.3.a"; sourceTree = ""; }; - 5C9F3DD22BFBCDD80003B86B /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; - 5C9F3DD32BFBCDD80003B86B /* libHSsimplex-chat-5.8.0.2-8RkLdmy05dJBsgWrGV50Uf.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.8.0.2-8RkLdmy05dJBsgWrGV50Uf.a"; sourceTree = ""; }; - 5C9F3DD42BFBCDD90003B86B /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; - 5C9F3DD52BFBCDD90003B86B /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; 5C9FD96A27A56D4D0075386C /* JSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; 5C9FD96D27A5D6ED0075386C /* SendMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendMessageView.swift; sourceTree = ""; }; 5CA059C3279559F40002BEB4 /* SimpleXApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleXApp.swift; sourceTree = ""; }; @@ -440,6 +435,11 @@ 5CEACCEC27DEA495000BD591 /* MsgContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MsgContentView.swift; sourceTree = ""; }; 5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardPadding.swift; sourceTree = ""; }; 5CEBD7472A5F115D00665FE2 /* SetDeliveryReceiptsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetDeliveryReceiptsView.swift; sourceTree = ""; }; + 5CEE878F2C024F4F00583B8A /* libHSsimplex-chat-5.8.0.3-3OkzEeUKATkEGDdUZR1g6G-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.8.0.3-3OkzEeUKATkEGDdUZR1g6G-ghc9.6.3.a"; sourceTree = ""; }; + 5CEE87902C024F4F00583B8A /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; + 5CEE87912C024F4F00583B8A /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; + 5CEE87922C024F4F00583B8A /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; + 5CEE87932C024F4F00583B8A /* libHSsimplex-chat-5.8.0.3-3OkzEeUKATkEGDdUZR1g6G.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.8.0.3-3OkzEeUKATkEGDdUZR1g6G.a"; sourceTree = ""; }; 5CF9371F2B24DE8C00E1D781 /* SharedFileSubscriber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedFileSubscriber.swift; sourceTree = ""; }; 5CF937212B25034A00E1D781 /* NSESubscriber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSESubscriber.swift; sourceTree = ""; }; 5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrateToAppGroupView.swift; sourceTree = ""; }; @@ -529,13 +529,13 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5C9F3DD92BFBCDD90003B86B /* libgmpxx.a in Frameworks */, - 5C9F3DDA2BFBCDD90003B86B /* libgmp.a in Frameworks */, - 5C9F3DD82BFBCDD90003B86B /* libHSsimplex-chat-5.8.0.2-8RkLdmy05dJBsgWrGV50Uf.a in Frameworks */, + 5CEE87942C024F4F00583B8A /* libHSsimplex-chat-5.8.0.3-3OkzEeUKATkEGDdUZR1g6G-ghc9.6.3.a in Frameworks */, + 5CEE87972C024F4F00583B8A /* libffi.a in Frameworks */, + 5CEE87962C024F4F00583B8A /* libgmpxx.a in Frameworks */, 5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */, - 5C9F3DD62BFBCDD90003B86B /* libHSsimplex-chat-5.8.0.2-8RkLdmy05dJBsgWrGV50Uf-ghc9.6.3.a in Frameworks */, + 5CEE87952C024F4F00583B8A /* libgmp.a in Frameworks */, 5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */, - 5C9F3DD72BFBCDD90003B86B /* libffi.a in Frameworks */, + 5CEE87982C024F4F00583B8A /* libHSsimplex-chat-5.8.0.3-3OkzEeUKATkEGDdUZR1g6G.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -601,11 +601,11 @@ 5C764E5C279C70B7000C6508 /* Libraries */ = { isa = PBXGroup; children = ( - 5C9F3DD22BFBCDD80003B86B /* libffi.a */, - 5C9F3DD52BFBCDD90003B86B /* libgmp.a */, - 5C9F3DD42BFBCDD90003B86B /* libgmpxx.a */, - 5C9F3DD12BFBCDD80003B86B /* libHSsimplex-chat-5.8.0.2-8RkLdmy05dJBsgWrGV50Uf-ghc9.6.3.a */, - 5C9F3DD32BFBCDD80003B86B /* libHSsimplex-chat-5.8.0.2-8RkLdmy05dJBsgWrGV50Uf.a */, + 5CEE87922C024F4F00583B8A /* libffi.a */, + 5CEE87902C024F4F00583B8A /* libgmp.a */, + 5CEE87912C024F4F00583B8A /* libgmpxx.a */, + 5CEE878F2C024F4F00583B8A /* libHSsimplex-chat-5.8.0.3-3OkzEeUKATkEGDdUZR1g6G-ghc9.6.3.a */, + 5CEE87932C024F4F00583B8A /* libHSsimplex-chat-5.8.0.3-3OkzEeUKATkEGDdUZR1g6G.a */, ); path = Libraries; sourceTree = ""; From 373070f388302aec985d0dec82c7432f80587f36 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Sat, 25 May 2024 19:54:05 +0100 Subject: [PATCH 06/21] ui: show UI for additional group preferences (SimpleX links and per-role permissions) --- .../Views/Chat/Group/GroupPreferencesView.swift | 5 +---- .../common/views/chat/group/GroupPreferences.kt | 15 ++++++--------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift b/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift index b4e1992848..6ae5032be5 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift @@ -34,8 +34,7 @@ struct GroupPreferencesView: View { featureSection(.reactions, $preferences.reactions.enable) featureSection(.voice, $preferences.voice.enable, $preferences.voice.role) featureSection(.files, $preferences.files.enable, $preferences.files.role) - // TODO enable simplexLinks preference in 5.8 - // featureSection(.simplexLinks, $preferences.simplexLinks.enable, $preferences.simplexLinks.role) + featureSection(.simplexLinks, $preferences.simplexLinks.enable, $preferences.simplexLinks.role) featureSection(.history, $preferences.history.enable) if groupInfo.canEdit { @@ -102,8 +101,6 @@ struct GroupPreferencesView: View { } } .frame(height: 36) - // remove in v5.8 - .disabled(true) } } else { settingsRow(icon, color: color) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt index 265d0cdeae..82646a99c5 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt @@ -123,13 +123,12 @@ private fun GroupPreferencesLayout( applyPrefs(preferences.copy(files = RoleGroupPreference(enable = enable, role))) } - // TODO enable simplexLinks preference in 5.8 -// SectionDividerSpaced(true, maxBottomPadding = false) -// val allowSimplexLinks = remember(preferences) { mutableStateOf(preferences.simplexLinks.enable) } -// val simplexLinksRole = remember(preferences) { mutableStateOf(preferences.simplexLinks.role) } -// FeatureSection(GroupFeature.SimplexLinks, allowSimplexLinks, simplexLinksRole, groupInfo, preferences, onTTLUpdated) { enable, role -> -// applyPrefs(preferences.copy(simplexLinks = RoleGroupPreference(enable = enable, role))) -// } + SectionDividerSpaced(true, maxBottomPadding = false) + val allowSimplexLinks = remember(preferences) { mutableStateOf(preferences.simplexLinks.enable) } + val simplexLinksRole = remember(preferences) { mutableStateOf(preferences.simplexLinks.role) } + FeatureSection(GroupFeature.SimplexLinks, allowSimplexLinks, simplexLinksRole, groupInfo, preferences, onTTLUpdated) { enable, role -> + applyPrefs(preferences.copy(simplexLinks = RoleGroupPreference(enable = enable, role))) + } SectionDividerSpaced(true, maxBottomPadding = false) val enableHistory = remember(preferences) { mutableStateOf(preferences.history.enable) } @@ -189,8 +188,6 @@ private fun FeatureSection( generalGetString(MR.strings.feature_enabled_for), featureRoles, enableForRole, - // remove in v5.8 - enabled = remember { mutableStateOf(false) }, onSelected = { value -> onSelected(enableFeature.value, value) } From a1d4f52185b9efab9eeec2f83e023fa83fac0904 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Sat, 25 May 2024 20:57:07 +0100 Subject: [PATCH 07/21] 5.8-beta.3: ios 220, android 214, desktop 49 --- apps/ios/SimpleX.xcodeproj/project.pbxproj | 12 ++++++------ apps/multiplatform/gradle.properties | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 70c5df74ae..523f099226 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -1552,7 +1552,7 @@ CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 218; + CURRENT_PROJECT_VERSION = 220; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; @@ -1601,7 +1601,7 @@ CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 218; + CURRENT_PROJECT_VERSION = 220; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; @@ -1687,7 +1687,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 218; + CURRENT_PROJECT_VERSION = 220; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; GCC_OPTIMIZATION_LEVEL = s; @@ -1724,7 +1724,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 218; + CURRENT_PROJECT_VERSION = 220; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; ENABLE_CODE_COVERAGE = NO; @@ -1761,7 +1761,7 @@ CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 218; + CURRENT_PROJECT_VERSION = 220; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1812,7 +1812,7 @@ CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 218; + CURRENT_PROJECT_VERSION = 220; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; diff --git a/apps/multiplatform/gradle.properties b/apps/multiplatform/gradle.properties index 01e3b17296..c90510566a 100644 --- a/apps/multiplatform/gradle.properties +++ b/apps/multiplatform/gradle.properties @@ -26,11 +26,11 @@ android.enableJetifier=true kotlin.mpp.androidSourceSetLayoutVersion=2 kotlin.jvm.target=11 -android.version_name=5.8-beta.2 -android.version_code=210 +android.version_name=5.8-beta.3 +android.version_code=214 -desktop.version_name=5.8-beta.2 -desktop.version_code=47 +desktop.version_name=5.8-beta.3 +desktop.version_code=49 kotlin.version=1.9.23 gradle.plugin.version=8.2.0 From c70e7223d9a3d07eb17a03e13aacac8f8246c1b3 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Mon, 27 May 2024 15:32:09 +0100 Subject: [PATCH 08/21] core: delete connection records when connecting (JOIN) fails (#4233) * core: delete connection records when connecting (JOIN) fails * show errors in commands --- src/Simplex/Chat.hs | 41 ++++++++++++++++++--------- src/Simplex/Chat/Store/Connections.hs | 5 ++++ src/Simplex/Chat/Store/Direct.hs | 4 +-- src/Simplex/Chat/Store/Groups.hs | 4 +-- src/Simplex/Chat/View.hs | 22 +++++++------- 5 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index e259629d2b..77fac9ddc2 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -1550,8 +1550,8 @@ processChatCommand' vr = \case let chatV = agentToChatVersion agentV dm <- encodeConnInfoPQ pqSup' chatV $ XInfo profileToSend connId <- withAgent $ \a -> prepareConnectionToJoin a (aUserId user) True cReq pqSup' - conn <- withStore' $ \db -> createDirectConnection db user connId cReq ConnJoined (incognitoProfile $> profileToSend) subMode chatV pqSup' - void . withAgent $ \a -> joinConnection a (aUserId user) (Just connId) True cReq dm pqSup' subMode + conn@PendingContactConnection {pccConnId} <- withStore' $ \db -> createDirectConnection db user connId cReq ConnJoined (incognitoProfile $> profileToSend) subMode chatV pqSup' + joinPreparedAgentConnection user pccConnId connId cReq dm pqSup' subMode pure $ CRSentConfirmation user conn APIConnect userId incognito (Just (ACR SCMContact cReq)) -> withUserId userId $ \user -> connectViaContact user incognito cReq APIConnect _ _ Nothing -> throwChatError CEInvalidConnReq @@ -1806,12 +1806,20 @@ processChatCommand' vr = \case dm <- encodeConnInfo $ XGrpAcpt membershipMemId agentConnId <- withAgent $ \a -> prepareConnectionToJoin a (aUserId user) True connRequest PQSupportOff let chatV = vr `peerConnChatVersion` peerChatVRange - withStore' $ \db -> do - createMemberConnection db userId fromMember agentConnId chatV peerChatVRange subMode + cId <- withStore' $ \db -> do + Connection {connId = cId} <- createMemberConnection db userId fromMember agentConnId chatV peerChatVRange subMode updateGroupMemberStatus db userId fromMember GSMemAccepted updateGroupMemberStatus db userId membership GSMemAccepted - void . withAgent $ \a -> joinConnection a (aUserId user) (Just agentConnId) True connRequest dm PQSupportOff subMode - updateCIGroupInvitationStatus user g CIGISAccepted `catchChatError` \_ -> pure () + pure cId + void (withAgent $ \a -> joinConnection a (aUserId user) (Just agentConnId) True connRequest dm PQSupportOff subMode) + `catchChatError` \e -> do + withStore' $ \db -> do + deleteConnectionRecord db user cId + updateGroupMemberStatus db userId fromMember GSMemInvited + updateGroupMemberStatus db userId membership GSMemInvited + withAgent $ \a -> deleteConnectionAsync a False agentConnId + throwError e + updateCIGroupInvitationStatus user g CIGISAccepted `catchChatError` (toView . CRChatError (Just user)) pure $ CRUserAcceptedGroupSent user g {membership = membership {memberStatus = GSMemAccepted}} Nothing Nothing -> throwChatError $ CEContactNotActive ct APIMemberRole groupId memberId memRole -> withUser $ \user -> do @@ -2338,8 +2346,8 @@ processChatCommand' vr = \case -- [incognito] generate profile to send incognitoProfile <- if incognito then Just <$> liftIO generateRandomProfile else pure Nothing subMode <- chatReadVar subscriptionMode - conn <- withStore' $ \db -> createConnReqConnection db userId connId cReqHash xContactId incognitoProfile groupLinkId subMode chatV pqSup - joinContact user connId cReq incognitoProfile xContactId inGroup pqSup chatV + conn@PendingContactConnection {pccConnId} <- withStore' $ \db -> createConnReqConnection db userId connId cReqHash xContactId incognitoProfile groupLinkId subMode chatV pqSup + joinContact user pccConnId connId cReq incognitoProfile xContactId inGroup pqSup chatV pure $ CRSentInvitation user conn incognitoProfile connectContactViaAddress :: User -> IncognitoEnabled -> Contact -> ConnectionRequestUri 'CMContact -> CM ChatResponse connectContactViaAddress user incognito ct cReq = @@ -2351,8 +2359,8 @@ processChatCommand' vr = \case -- [incognito] generate profile to send incognitoProfile <- if incognito then Just <$> liftIO generateRandomProfile else pure Nothing subMode <- chatReadVar subscriptionMode - ct' <- withStore $ \db -> createAddressContactConnection db vr user ct connId cReqHash newXContactId incognitoProfile subMode chatV pqSup - joinContact user connId cReq incognitoProfile newXContactId False pqSup chatV + (pccConnId, ct') <- withStore $ \db -> createAddressContactConnection db vr user ct connId cReqHash newXContactId incognitoProfile subMode chatV pqSup + joinContact user pccConnId connId cReq incognitoProfile newXContactId False pqSup chatV pure $ CRSentInvitationToContact user ct' incognitoProfile prepareContact :: User -> ConnectionRequestUri 'CMContact -> PQSupport -> CM (ConnId, VersionChat) prepareContact user cReq pqSup = do @@ -2365,12 +2373,19 @@ processChatCommand' vr = \case let chatV = agentToChatVersion agentV connId <- withAgent $ \a -> prepareConnectionToJoin a (aUserId user) True cReq pqSup pure (connId, chatV) - joinContact :: User -> ConnId -> ConnectionRequestUri 'CMContact -> Maybe Profile -> XContactId -> Bool -> PQSupport -> VersionChat -> CM () - joinContact user connId cReq incognitoProfile xContactId inGroup pqSup chatV = do + joinContact :: User -> Int64 -> ConnId -> ConnectionRequestUri 'CMContact -> Maybe Profile -> XContactId -> Bool -> PQSupport -> VersionChat -> CM () + joinContact user pccConnId connId cReq incognitoProfile xContactId inGroup pqSup chatV = do let profileToSend = userProfileToSend user incognitoProfile Nothing inGroup dm <- encodeConnInfoPQ pqSup chatV (XContact profileToSend $ Just xContactId) subMode <- chatReadVar subscriptionMode - void . withAgent $ \a -> joinConnection a (aUserId user) (Just connId) True cReq dm pqSup subMode + joinPreparedAgentConnection user pccConnId connId cReq dm pqSup subMode + joinPreparedAgentConnection :: User -> Int64 -> ConnId -> ConnectionRequestUri m -> ByteString -> PQSupport -> SubscriptionMode -> CM () + joinPreparedAgentConnection user pccConnId connId cReq connInfo pqSup subMode = do + void (withAgent $ \a -> joinConnection a (aUserId user) (Just connId) True cReq connInfo pqSup subMode) + `catchChatError` \e -> do + withStore' $ \db -> deleteConnectionRecord db user pccConnId + withAgent $ \a -> deleteConnectionAsync a False connId + throwError e contactMember :: Contact -> [GroupMember] -> Maybe GroupMember contactMember Contact {contactId} = find $ \GroupMember {memberContactId = cId, memberStatus = s} -> diff --git a/src/Simplex/Chat/Store/Connections.hs b/src/Simplex/Chat/Store/Connections.hs index 1c3e949562..0d085d216c 100644 --- a/src/Simplex/Chat/Store/Connections.hs +++ b/src/Simplex/Chat/Store/Connections.hs @@ -14,6 +14,7 @@ module Simplex.Chat.Store.Connections getContactConnEntityByConnReqHash, getConnectionsToSubscribe, unsetConnectionToSubscribe, + deleteConnectionRecord, ) where @@ -225,3 +226,7 @@ getConnectionsToSubscribe db vr = do unsetConnectionToSubscribe :: DB.Connection -> IO () unsetConnectionToSubscribe db = DB.execute_ db "UPDATE connections SET to_subscribe = 0 WHERE to_subscribe = 1" + +deleteConnectionRecord :: DB.Connection -> User -> Int64 -> IO () +deleteConnectionRecord db User {userId} cId = do + DB.execute db "DELETE FROM connections WHERE user_id = ? AND connection_id = ?" (userId, cId) diff --git a/src/Simplex/Chat/Store/Direct.hs b/src/Simplex/Chat/Store/Direct.hs index ecba9be7fa..afbd3f7960 100644 --- a/src/Simplex/Chat/Store/Direct.hs +++ b/src/Simplex/Chat/Store/Direct.hs @@ -130,11 +130,11 @@ deletePendingContactConnection db userId connId = |] (userId, connId, ConnContact) -createAddressContactConnection :: DB.Connection -> VersionRangeChat -> User -> Contact -> ConnId -> ConnReqUriHash -> XContactId -> Maybe Profile -> SubscriptionMode -> VersionChat -> PQSupport -> ExceptT StoreError IO Contact +createAddressContactConnection :: DB.Connection -> VersionRangeChat -> User -> Contact -> ConnId -> ConnReqUriHash -> XContactId -> Maybe Profile -> SubscriptionMode -> VersionChat -> PQSupport -> ExceptT StoreError IO (Int64, Contact) createAddressContactConnection db vr user@User {userId} Contact {contactId} acId cReqHash xContactId incognitoProfile subMode chatV pqSup = do PendingContactConnection {pccConnId} <- liftIO $ createConnReqConnection db userId acId cReqHash xContactId incognitoProfile Nothing subMode chatV pqSup liftIO $ DB.execute db "UPDATE connections SET contact_id = ? WHERE connection_id = ?" (contactId, pccConnId) - getContact db vr user contactId + (pccConnId,) <$> getContact db vr user contactId createConnReqConnection :: DB.Connection -> UserId -> ConnId -> ConnReqUriHash -> XContactId -> Maybe Profile -> Maybe GroupLinkId -> SubscriptionMode -> VersionChat -> PQSupport -> IO PendingContactConnection createConnReqConnection db userId acId cReqHash xContactId incognitoProfile groupLinkId subMode chatV pqSup = do diff --git a/src/Simplex/Chat/Store/Groups.hs b/src/Simplex/Chat/Store/Groups.hs index 5e603a40c9..5efc915066 100644 --- a/src/Simplex/Chat/Store/Groups.hs +++ b/src/Simplex/Chat/Store/Groups.hs @@ -944,10 +944,10 @@ getMemberInvitation db User {userId} groupMemberId = fmap join . maybeFirstRow fromOnly $ DB.query db "SELECT sent_inv_queue_info FROM group_members WHERE group_member_id = ? AND user_id = ?" (groupMemberId, userId) -createMemberConnection :: DB.Connection -> UserId -> GroupMember -> ConnId -> VersionChat -> VersionRangeChat -> SubscriptionMode -> IO () +createMemberConnection :: DB.Connection -> UserId -> GroupMember -> ConnId -> VersionChat -> VersionRangeChat -> SubscriptionMode -> IO Connection createMemberConnection db userId GroupMember {groupMemberId} agentConnId chatV peerChatVRange subMode = do currentTs <- getCurrentTime - void $ createMemberConnection_ db userId groupMemberId agentConnId chatV peerChatVRange Nothing 0 currentTs subMode + createMemberConnection_ db userId groupMemberId agentConnId chatV peerChatVRange Nothing 0 currentTs subMode createMemberConnectionAsync :: DB.Connection -> User -> GroupMemberId -> (CommandId, ConnId) -> VersionChat -> VersionRangeChat -> SubscriptionMode -> IO () createMemberConnectionAsync db user@User {userId} groupMemberId (cmdId, agentConnId) chatV peerChatVRange subMode = do diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index 08980f21d2..671706c5f2 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -388,9 +388,9 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe CRAgentConnDeleted acId -> ["completed deleting connection, agent connection id: " <> sShow acId | logLevel <= CLLInfo] CRAgentUserDeleted auId -> ["completed deleting user" <> if logLevel <= CLLInfo then ", agent user id: " <> sShow auId else ""] CRMessageError u prefix err -> ttyUser u [plain prefix <> ": " <> plain err | prefix == "error" || logLevel <= CLLWarning] - CRChatCmdError u e -> ttyUserPrefix' u $ viewChatError logLevel testView e - CRChatError u e -> ttyUser' u $ viewChatError logLevel testView e - CRChatErrors u errs -> ttyUser' u $ concatMap (viewChatError logLevel testView) errs + CRChatCmdError u e -> ttyUserPrefix' u $ viewChatError True logLevel testView e + CRChatError u e -> ttyUser' u $ viewChatError False logLevel testView e + CRChatErrors u errs -> ttyUser' u $ concatMap (viewChatError False logLevel testView) errs CRArchiveImported archiveErrs -> if null archiveErrs then ["ok"] else ["archive import errors: " <> plain (show archiveErrs)] CRAppSettings as -> ["app settings: " <> plain (LB.unpack $ J.encode as)] CRTimedAction _ _ -> [] @@ -1894,8 +1894,8 @@ viewRemoteCtrl CtrlAppInfo {deviceName, appVersionRange = AppVersionRange _ (App | otherwise = "" showCompatible = if compatible then "" else ", " <> bold' "not compatible" -viewChatError :: ChatLogLevel -> Bool -> ChatError -> [StyledString] -viewChatError logLevel testView = \case +viewChatError :: Bool -> ChatLogLevel -> Bool -> ChatError -> [StyledString] +viewChatError isCmd logLevel testView = \case ChatError err -> case err of CENoActiveUser -> ["error: active user is required"] CENoConnectionUser agentConnId -> ["error: message user not found, conn id: " <> sShow agentConnId | logLevel <= CLLError] @@ -2034,14 +2034,14 @@ viewChatError logLevel testView = \case <> "error: connection authorization failed - this could happen if connection was deleted,\ \ secured with different credentials, or due to a bug - please re-create the connection" ] - BROKER _ NETWORK -> [] - BROKER _ TIMEOUT -> [] - AGENT A_DUPLICATE -> [withConnEntity <> "error: AGENT A_DUPLICATE" | logLevel == CLLDebug] - AGENT (A_PROHIBITED e) -> [withConnEntity <> "error: AGENT A_PROHIBITED, " <> plain e | logLevel <= CLLWarning] - CONN NOT_FOUND -> [withConnEntity <> "error: CONN NOT_FOUND" | logLevel <= CLLWarning] + BROKER _ NETWORK | not isCmd -> [] + BROKER _ TIMEOUT | not isCmd -> [] + AGENT A_DUPLICATE -> [withConnEntity <> "error: AGENT A_DUPLICATE" | logLevel == CLLDebug || isCmd] + AGENT (A_PROHIBITED e) -> [withConnEntity <> "error: AGENT A_PROHIBITED, " <> plain e | logLevel <= CLLWarning || isCmd] + CONN NOT_FOUND -> [withConnEntity <> "error: CONN NOT_FOUND" | logLevel <= CLLWarning || isCmd] CRITICAL restart e -> [plain $ "critical error: " <> e] <> ["please restart the app" | restart] INTERNAL e -> [plain $ "internal error: " <> e] - e -> [withConnEntity <> "smp agent error: " <> sShow e | logLevel <= CLLWarning] + e -> [withConnEntity <> "smp agent error: " <> sShow e | logLevel <= CLLWarning || isCmd] where withConnEntity = case entity_ of Just entity@(RcvDirectMsgConnection conn contact_) -> case contact_ of From 01cadefde707d948a33150ca75565412c1dfd10a Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Mon, 27 May 2024 18:42:39 +0400 Subject: [PATCH 09/21] core: avoid creating duplicate introductions between group members connecting concurrently (#4235) --- src/Simplex/Chat/Store/Groups.hs | 39 +++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/Simplex/Chat/Store/Groups.hs b/src/Simplex/Chat/Store/Groups.hs index 5efc915066..21b50113b0 100644 --- a/src/Simplex/Chat/Store/Groups.hs +++ b/src/Simplex/Chat/Store/Groups.hs @@ -1090,20 +1090,33 @@ createIntroductions db chatV members toMember = do then pure [] else do currentTs <- getCurrentTime - mapM (insertIntro_ currentTs) reMembers + catMaybes <$> mapM (createIntro_ currentTs) reMembers where - insertIntro_ :: UTCTime -> GroupMember -> IO GroupMemberIntro - insertIntro_ ts reMember = do - DB.execute - db - [sql| - INSERT INTO group_member_intros - (re_group_member_id, to_group_member_id, intro_status, intro_chat_protocol_version, created_at, updated_at) - VALUES (?,?,?,?,?,?) - |] - (groupMemberId' reMember, groupMemberId' toMember, GMIntroPending, chatV, ts, ts) - introId <- insertedRowId db - pure GroupMemberIntro {introId, reMember, toMember, introStatus = GMIntroPending, introInvitation = Nothing} + createIntro_ :: UTCTime -> GroupMember -> IO (Maybe GroupMemberIntro) + createIntro_ ts reMember = + -- when members connect concurrently, host would try to create introductions between them in both directions; + -- this check avoids creating second (redundant) introduction + checkInverseIntro >>= \case + Just _ -> pure Nothing + Nothing -> do + DB.execute + db + [sql| + INSERT INTO group_member_intros + (re_group_member_id, to_group_member_id, intro_status, intro_chat_protocol_version, created_at, updated_at) + VALUES (?,?,?,?,?,?) + |] + (groupMemberId' reMember, groupMemberId' toMember, GMIntroPending, chatV, ts, ts) + introId <- insertedRowId db + pure $ Just GroupMemberIntro {introId, reMember, toMember, introStatus = GMIntroPending, introInvitation = Nothing} + where + checkInverseIntro :: IO (Maybe Int64) + checkInverseIntro = + maybeFirstRow fromOnly $ + DB.query + db + "SELECT 1 FROM group_member_intros WHERE re_group_member_id = ? AND to_group_member_id = ? LIMIT 1" + (groupMemberId' toMember, groupMemberId' reMember) updateIntroStatus :: DB.Connection -> Int64 -> GroupMemberIntroStatus -> IO () updateIntroStatus db introId introStatus = do From b58ccedf2385932a8e952f16e49fdbc4b1004607 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Tue, 28 May 2024 14:02:45 +0700 Subject: [PATCH 10/21] android, desktop: enhancements to wallpapers (#4234) * android, desktop: enhancements to wallpapers * fixes * unneeded --- apps/multiplatform/common/build.gradle.kts | 2 +- .../chat/simplex/common/model/SimpleXAPI.kt | 2 + .../chat/simplex/common/ui/theme/Theme.kt | 70 +++++++++++++++++ .../simplex/common/views/chat/ChatInfoView.kt | 26 ++++++- .../simplex/common/views/chat/ChatView.kt | 12 ++- .../common/views/chat/item/ChatItemView.kt | 15 ++-- .../common/views/helpers/ChatWallpaper.kt | 3 + .../common/views/helpers/ThemeModeEditor.kt | 67 +++++++++++++++-- .../simplex/common/views/helpers/Utils.kt | 1 + .../common/views/usersettings/Appearance.kt | 75 +++++++++++++------ .../commonMain/resources/MR/base/strings.xml | 5 +- 11 files changed, 237 insertions(+), 41 deletions(-) diff --git a/apps/multiplatform/common/build.gradle.kts b/apps/multiplatform/common/build.gradle.kts index 4fa865a6d3..ac131c9748 100644 --- a/apps/multiplatform/common/build.gradle.kts +++ b/apps/multiplatform/common/build.gradle.kts @@ -37,7 +37,7 @@ kotlin { api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") api("org.jetbrains.kotlinx:kotlinx-datetime:0.5.0") api("com.russhwolf:multiplatform-settings:1.1.1") - api("com.charleskorn.kaml:kaml:0.58.0") + api("com.charleskorn.kaml:kaml:0.59.0") api("org.jetbrains.compose.ui:ui-text:${rootProject.extra["compose.version"] as String}") implementation("org.jetbrains.compose.components:components-animatedimage:${rootProject.extra["compose.version"] as String}") //Barcode diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index 40207a25ce..78d76a4b5d 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -4104,6 +4104,8 @@ val jsonShort = Json { val yaml = Yaml(configuration = YamlConfiguration( strictMode = false, encodeDefaults = false, + /** ~5.5 MB limitation since wallpaper is limited by 5 MB, see [saveWallpaperFile] */ + codePointLimit = 5500000, )) @Serializable diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt index 5099513884..45f656a011 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt @@ -506,6 +506,76 @@ data class ThemeModeOverride ( } ) } + + fun removeSameColors(base: DefaultTheme): ThemeModeOverride { + val c = when (base) { + DefaultTheme.LIGHT -> LightColorPalette + DefaultTheme.DARK -> DarkColorPalette + DefaultTheme.SIMPLEX -> SimplexColorPalette + DefaultTheme.BLACK -> BlackColorPalette + } + val ac = when (base) { + DefaultTheme.LIGHT -> LightColorPaletteApp + DefaultTheme.DARK -> DarkColorPaletteApp + DefaultTheme.SIMPLEX -> SimplexColorPaletteApp + DefaultTheme.BLACK -> BlackColorPaletteApp + } + val w = when (val wallpaperType = WallpaperType.from(wallpaper)) { + is WallpaperType.Preset -> { + val p = PresetWallpaper.from(wallpaperType.filename) + ThemeWallpaper( + preset = wallpaperType.filename, + scale = p?.scale ?: wallpaper?.scale, + scaleType = null, + background = p?.background?.get(base)?.toReadableHex(), + tint = p?.tint?.get(base)?.toReadableHex(), + image = null, + imageFile = null, + ) + } + is WallpaperType.Image -> { + ThemeWallpaper( + preset = null, + scale = null, + scaleType = WallpaperScaleType.FILL, + background = Color.Transparent.toReadableHex(), + tint = Color.Transparent.toReadableHex(), + image = null, + imageFile = null, + ) + } + else -> { + ThemeWallpaper() + } + } + + return copy( + colors = ThemeColors( + primary = if (colors.primary?.colorFromReadableHex() != c.primary) colors.primary else null, + primaryVariant = if (colors.primaryVariant?.colorFromReadableHex() != c.primaryVariant) colors.primaryVariant else null, + secondary = if (colors.secondary?.colorFromReadableHex() != c.secondary) colors.secondary else null, + secondaryVariant = if (colors.secondaryVariant?.colorFromReadableHex() != c.secondaryVariant) colors.secondaryVariant else null, + background = if (colors.background?.colorFromReadableHex() != c.background) colors.background else null, + surface = if (colors.surface?.colorFromReadableHex() != c.surface) colors.surface else null, + title = if (colors.title?.colorFromReadableHex() != ac.title) colors.title else null, + primaryVariant2 = if (colors.primaryVariant2?.colorFromReadableHex() != ac.primaryVariant2) colors.primary else null, + sentMessage = if (colors.sentMessage?.colorFromReadableHex() != ac.sentMessage) colors.sentMessage else null, + sentQuote = if (colors.sentQuote?.colorFromReadableHex() != ac.sentQuote) colors.sentQuote else null, + receivedMessage = if (colors.receivedMessage?.colorFromReadableHex() != ac.receivedMessage) colors.receivedMessage else null, + receivedQuote = if (colors.receivedQuote?.colorFromReadableHex() != ac.receivedQuote) colors.receivedQuote else null, + ), + wallpaper = wallpaper?.copy( + preset = wallpaper.preset, + scale = if (wallpaper.scale != w.scale) wallpaper.scale else null, + scaleType = if (wallpaper.scaleType != w.scaleType) wallpaper.scaleType else null, + background = if (wallpaper.background != w.background) wallpaper.background else null, + tint = if (wallpaper.tint != w.tint) wallpaper.tint else null, + image = wallpaper.image, + imageFile = wallpaper.imageFile, + ) + ) + } + companion object { fun withFilledAppDefaults(mode: DefaultThemeMode, base: DefaultTheme): ThemeModeOverride = ThemeModeOverride( diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt index 9b1e908e6b..12b5747787 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt @@ -42,6 +42,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import kotlinx.datetime.Clock +import java.io.File @Composable fun ChatInfoView( @@ -719,7 +720,7 @@ fun ModalData.ChatWallpaperEditorModal(chat: Chat) { suspend fun save(applyToMode: DefaultThemeMode?, newTheme: ThemeModeOverride?, chat: Chat) { val unchangedThemes: ThemeModeOverrides = ((chat.chatInfo as? ChatInfo.Direct)?.contact?.uiThemes ?: (chat.chatInfo as? ChatInfo.Group)?.groupInfo?.uiThemes) ?: ThemeModeOverrides() - val wallpaperFiles = listOf(unchangedThemes.light?.wallpaper?.imageFile, unchangedThemes.dark?.wallpaper?.imageFile) + val wallpaperFiles = setOf(unchangedThemes.light?.wallpaper?.imageFile, unchangedThemes.dark?.wallpaper?.imageFile) var changedThemes: ThemeModeOverrides? = unchangedThemes val changed = newTheme?.copy(wallpaper = newTheme.wallpaper?.withFilledWallpaperPath()) changedThemes = when (applyToMode) { @@ -727,7 +728,28 @@ suspend fun save(applyToMode: DefaultThemeMode?, newTheme: ThemeModeOverride?, c DefaultThemeMode.LIGHT -> changedThemes?.copy(light = changed?.copy(mode = applyToMode)) DefaultThemeMode.DARK -> changedThemes?.copy(dark = changed?.copy(mode = applyToMode)) } - changedThemes = if (changedThemes?.light != null || changedThemes?.dark != null) changedThemes else null + changedThemes = if (changedThemes?.light != null || changedThemes?.dark != null) { + val light = changedThemes.light + val dark = changedThemes.dark + val currentMode = CurrentColors.value.base.mode + // same image file for both modes, copy image to make them as different files + if (light?.wallpaper?.imageFile != null && dark?.wallpaper?.imageFile != null && light.wallpaper.imageFile == dark.wallpaper.imageFile) { + val imageFile = if (currentMode == DefaultThemeMode.LIGHT) { + dark.wallpaper.imageFile + } else { + light.wallpaper.imageFile + } + val filePath = saveWallpaperFile(File(getWallpaperFilePath(imageFile)).toURI()) + changedThemes = if (currentMode == DefaultThemeMode.LIGHT) { + changedThemes.copy(dark = dark.copy(wallpaper = dark.wallpaper.copy(imageFile = filePath))) + } else { + changedThemes.copy(light = light.copy(wallpaper = light.wallpaper.copy(imageFile = filePath))) + } + } + changedThemes + } else { + null + } val wallpaperFilesToDelete = wallpaperFiles - changedThemes?.light?.wallpaper?.imageFile - changedThemes?.dark?.wallpaper?.imageFile wallpaperFilesToDelete.forEach(::removeWallpaperFile) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt index 60f741b9af..3b3060c81a 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt @@ -339,6 +339,10 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId: openDirectChat(chatRh, contactId, chatModel) } }, + forwardItem = { cItem, cInfo -> + chatModel.chatId.value = null + chatModel.sharedContent.value = SharedContent.Forward(cInfo, cItem) + }, updateContactStats = { contact -> withBGApi { val r = chatModel.controller.apiContactInfo(chatRh, chat.chatInfo.apiId) @@ -537,6 +541,7 @@ fun ChatLayout( acceptCall: (Contact) -> Unit, acceptFeature: (Contact, ChatFeature, Int?) -> Unit, openDirectChat: (Long) -> Unit, + forwardItem: (ChatInfo, ChatItem) -> Unit, updateContactStats: (Contact) -> Unit, updateMemberStats: (GroupInfo, GroupMember) -> Unit, syncContactConnection: (Contact) -> Unit, @@ -619,7 +624,7 @@ fun ChatLayout( ChatItemsList( chat, unreadCount, composeState, searchValue, useLinkPreviews, linkMode, showMemberInfo, loadPrevMessages, deleteMessage, deleteMessages, - receiveFile, cancelFile, joinGroup, acceptCall, acceptFeature, openDirectChat, + receiveFile, cancelFile, joinGroup, acceptCall, acceptFeature, openDirectChat, forwardItem, updateContactStats, updateMemberStats, syncContactConnection, syncMemberConnection, findModelChat, findModelMember, setReaction, showItemDetails, markRead, setFloatingButton, onComposed, developerTools, showViaProxy, ) @@ -888,6 +893,7 @@ fun BoxWithConstraintsScope.ChatItemsList( acceptCall: (Contact) -> Unit, acceptFeature: (Contact, ChatFeature, Int?) -> Unit, openDirectChat: (Long) -> Unit, + forwardItem: (ChatInfo, ChatItem) -> Unit, updateContactStats: (Contact) -> Unit, updateMemberStats: (GroupInfo, GroupMember) -> Unit, syncContactConnection: (Contact) -> Unit, @@ -991,7 +997,7 @@ fun BoxWithConstraintsScope.ChatItemsList( tryOrShowError("${cItem.id}ChatItem", error = { CIBrokenComposableView(if (cItem.chatDir.sent) Alignment.CenterEnd else Alignment.CenterStart) }) { - ChatItemView(chat.remoteHostId, chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, revealed = revealed, range = range, deleteMessage = deleteMessage, deleteMessages = deleteMessages, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = joinGroup, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, developerTools = developerTools, showViaProxy = showViaProxy) + ChatItemView(chat.remoteHostId, chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, revealed = revealed, range = range, deleteMessage = deleteMessage, deleteMessages = deleteMessages, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = joinGroup, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, forwardItem = forwardItem, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, developerTools = developerTools, showViaProxy = showViaProxy) } } @@ -1544,6 +1550,7 @@ fun PreviewChatLayout() { acceptCall = { _ -> }, acceptFeature = { _, _, _ -> }, openDirectChat = { _ -> }, + forwardItem = { _, _ -> }, updateContactStats = { }, updateMemberStats = { _, _ -> }, syncContactConnection = { }, @@ -1617,6 +1624,7 @@ fun PreviewGroupChatLayout() { acceptCall = { _ -> }, acceptFeature = { _, _, _ -> }, openDirectChat = { _ -> }, + forwardItem = { _, _ -> }, updateContactStats = { }, updateMemberStats = { _, _ -> }, syncContactConnection = { }, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt index 7fbec84c4d..c195a1a299 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt @@ -59,6 +59,7 @@ fun ChatItemView( scrollToItem: (Long) -> Unit, acceptFeature: (Contact, ChatFeature, Int?) -> Unit, openDirectChat: (Long) -> Unit, + forwardItem: (ChatInfo, ChatItem) -> Unit, updateContactStats: (Contact) -> Unit, updateMemberStats: (GroupInfo, GroupMember) -> Unit, syncContactConnection: (Contact) -> Unit, @@ -68,7 +69,8 @@ fun ChatItemView( setReaction: (ChatInfo, ChatItem, Boolean, MsgReaction) -> Unit, showItemDetails: (ChatInfo, ChatItem) -> Unit, developerTools: Boolean, - showViaProxy: Boolean + showViaProxy: Boolean, + preview: Boolean = false, ) { val uriHandler = LocalUriHandler.current val sent = cItem.chatDir.sent @@ -260,8 +262,7 @@ fun ChatItemView( !cItem.isLiveDummy && !live ) { ItemAction(stringResource(MR.strings.forward_chat_item), painterResource(MR.images.ic_forward), onClick = { - chatModel.chatId.value = null - chatModel.sharedContent.value = SharedContent.Forward(cItem, cInfo) + forwardItem(cInfo, cItem) showMenu.value = false }) } @@ -272,7 +273,7 @@ fun ChatItemView( if (cItem.meta.itemDeleted == null && cItem.file != null && cItem.file.cancelAction != null && !cItem.localNote) { CancelFileItemAction(cItem.file.fileId, showMenu, cancelFile = cancelFile, cancelAction = cItem.file.cancelAction) } - if (!(live && cItem.meta.isLive)) { + if (!(live && cItem.meta.isLive) && !preview) { DeleteItemAction(cItem, revealed, showMenu, questionText = deleteMessageQuestionText(), deleteMessage, deleteMessages) } val groupInfo = cItem.memberToModerate(cInfo)?.first @@ -840,6 +841,7 @@ fun PreviewChatItemView( scrollToItem = {}, acceptFeature = { _, _, _ -> }, openDirectChat = { _ -> }, + forwardItem = { _, _ -> }, updateContactStats = { }, updateMemberStats = { _, _ -> }, syncContactConnection = { }, @@ -850,6 +852,7 @@ fun PreviewChatItemView( showItemDetails = { _, _ -> }, developerTools = false, showViaProxy = false, + preview = true, ) } @@ -875,6 +878,7 @@ fun PreviewChatItemViewDeletedContent() { scrollToItem = {}, acceptFeature = { _, _, _ -> }, openDirectChat = { _ -> }, + forwardItem = { _, _ -> }, updateContactStats = { }, updateMemberStats = { _, _ -> }, syncContactConnection = { }, @@ -884,7 +888,8 @@ fun PreviewChatItemViewDeletedContent() { setReaction = { _, _, _, _ -> }, showItemDetails = { _, _ -> }, developerTools = false, - showViaProxy = false + showViaProxy = false, + preview = true, ) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatWallpaper.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatWallpaper.kt index cd18ad1dab..b06bc46202 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatWallpaper.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatWallpaper.kt @@ -379,6 +379,9 @@ fun DrawScope.chatViewBackground(image: ImageBitmap, imageType: WallpaperType, b val scale = scaleType.contentScale.computeScaleFactor(Size(image.width.toFloat(), image.height.toFloat()), Size(size.width, size.height)) val scaledWidth = (image.width * scale.scaleX).roundToInt() val scaledHeight = (image.height * scale.scaleY).roundToInt() + // Large image will cause freeze + if (image.width > 4320 || image.height > 4320) return@clipRect + drawImage(image, dstOffset = IntOffset(x = ((size.width - scaledWidth) / 2).roundToInt(), y = ((size.height - scaledHeight) / 2).roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality) if (scaleType == WallpaperScaleType.FIT) { if (scaledWidth < size.width) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ThemeModeEditor.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ThemeModeEditor.kt index 9df4c80b0e..24f9bf539b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ThemeModeEditor.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ThemeModeEditor.kt @@ -3,13 +3,16 @@ package chat.simplex.common.views.helpers import SectionBottomSpacer import SectionItemView import SectionSpacer +import SectionView import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.MaterialTheme +import androidx.compose.material.MaterialTheme.colors import androidx.compose.material.Text import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import chat.simplex.common.model.ChatController.appPrefs +import chat.simplex.common.model.yaml import chat.simplex.common.platform.* import chat.simplex.common.ui.theme.* import chat.simplex.common.views.usersettings.* @@ -18,6 +21,7 @@ import chat.simplex.common.views.usersettings.AppearanceScope.editColor import chat.simplex.res.MR import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource +import kotlinx.serialization.encodeToString import java.net.URI @Composable @@ -134,7 +138,7 @@ fun ModalData.UserWallpaperEditor( SectionSpacer() if (!globalThemeUsed.value) { - ResetToGlobalThemeButton { + ResetToGlobalThemeButton(true) { themeModeOverride.value = ThemeManager.defaultActiveTheme(chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) globalThemeUsed.value = true withBGApi { save(applyToMode.value, null) } @@ -202,6 +206,14 @@ fun ModalData.UserWallpaperEditor( SectionSpacer() AppearanceScope.CustomizeThemeColorsSection(currentTheme, editColor = editColor) + + SectionSpacer() + ImportExportThemeSection(null, remember { chatModel.currentUser }.value?.uiThemes) { + withBGApi { + themeModeOverride.value = it + save(applyToMode.value, it) + } + } } else { AdvancedSettingsButton { showMore = true } } @@ -226,7 +238,7 @@ fun ModalData.ChatWallpaperEditor( val themeModeOverride = remember { stateGetOrPut("themeModeOverride") { theme } } val currentTheme by remember(themeModeOverride.value, CurrentColors.collectAsState().value) { mutableStateOf( - ThemeManager.currentColors(null, if (themeModeOverride.value == ThemeModeOverride()) null else themeModeOverride.value, chatModel.currentUser.value?.uiThemes, appPreferences.themeOverrides.get()) + ThemeManager.currentColors(null, if (globalThemeUsed.value) null else themeModeOverride.value, chatModel.currentUser.value?.uiThemes, appPreferences.themeOverrides.get()) ) } @@ -363,7 +375,7 @@ fun ModalData.ChatWallpaperEditor( SectionSpacer() if (!globalThemeUsed.value) { - ResetToGlobalThemeButton { + ResetToGlobalThemeButton(remember { chatModel.currentUser }.value?.uiThemes?.preferredMode(isInDarkTheme()) == null) { themeModeOverride.value = ThemeManager.defaultActiveTheme(chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) globalThemeUsed.value = true withBGApi { save(applyToMode.value, null) } @@ -431,6 +443,14 @@ fun ModalData.ChatWallpaperEditor( SectionSpacer() AppearanceScope.CustomizeThemeColorsSection(currentTheme, editColor = editColor) + + SectionSpacer() + ImportExportThemeSection(themeModeOverride.value, remember { chatModel.currentUser }.value?.uiThemes) { + withBGApi { + themeModeOverride.value = it + save(applyToMode.value, it) + } + } } else { AdvancedSettingsButton { showMore = true } } @@ -440,9 +460,46 @@ fun ModalData.ChatWallpaperEditor( } @Composable -private fun ResetToGlobalThemeButton(onClick: () -> Unit) { +private fun ImportExportThemeSection(perChat: ThemeModeOverride?, perUser: ThemeModeOverrides?, save: (ThemeModeOverride) -> Unit) { + SectionView { + val theme = remember { mutableStateOf(null as String?) } + val exportThemeLauncher = rememberFileChooserLauncher(false) { to: URI? -> + val themeValue = theme.value + if (themeValue != null && to != null) { + copyBytesToFile(themeValue.byteInputStream(), to) { + theme.value = null + } + } + } + SectionItemView({ + val overrides = ThemeManager.currentThemeOverridesForExport(perChat, perUser) + val lines = yaml.encodeToString(overrides).lines() + // Removing theme id without using custom serializer or data class + theme.value = lines.subList(1, lines.size).joinToString("\n") + withLongRunningApi { exportThemeLauncher.launch("simplex.theme") } + }) { + Text(generalGetString(MR.strings.export_theme), color = colors.primary) + } + val importThemeLauncher = rememberFileChooserLauncher(true) { to: URI? -> + if (to != null) { + val theme = getThemeFromUri(to) + if (theme != null) { + val res = ThemeModeOverride(mode = theme.base.mode, colors = theme.colors, wallpaper = theme.wallpaper?.importFromString()).removeSameColors(theme.base) + save(res) + } + } + } + // Can not limit to YAML mime type since it's unsupported by Android + SectionItemView({ withLongRunningApi { importThemeLauncher.launch("*/*") } }) { + Text(generalGetString(MR.strings.import_theme), color = colors.primary) + } + } +} + +@Composable +private fun ResetToGlobalThemeButton(app: Boolean, onClick: () -> Unit) { SectionItemView(onClick) { - Text(stringResource(MR.strings.chat_theme_reset_to_global_theme), color = MaterialTheme.colors.primary) + Text(stringResource(if (app) MR.strings.chat_theme_reset_to_app_theme else MR.strings.chat_theme_reset_to_user_theme), color = MaterialTheme.colors.primary) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt index 4740280bb5..884551f600 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt @@ -146,6 +146,7 @@ fun getThemeFromUri(uri: URI, withAlertOnException: Boolean = true): ThemeOverri runCatching { return yaml.decodeFromStream(it!!) }.onFailure { + Log.e(TAG, "Error while decoding theme: ${it.stackTraceToString()}") if (withAlertOnException) { AlertManager.shared.showAlertMsg( title = generalGetString(MR.strings.import_theme_error), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt index ad7804de00..1de2c7c489 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt @@ -40,6 +40,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.datetime.Clock import kotlinx.serialization.encodeToString +import java.io.File import java.net.URI import java.util.* import kotlin.collections.ArrayList @@ -277,7 +278,7 @@ object AppearanceScope { if (themeUserDestination.value == null) { ThemeManager.saveAndApplyWallpaper(baseTheme, type) } else { - val wallpaperFiles = listOf(perUserTheme.value.wallpaper?.imageFile) + val wallpaperFiles = setOf(perUserTheme.value.wallpaper?.imageFile) ThemeManager.copyFromSameThemeOverrides(type, null, perUserTheme) val wallpaperFilesToDelete = wallpaperFiles - perUserTheme.value.wallpaper?.imageFile wallpaperFilesToDelete.forEach(::removeWallpaperFile) @@ -297,17 +298,15 @@ object AppearanceScope { saveThemeToDatabase(themeUserDestination.value) } - val importWallpaperLauncher = rememberFileChooserLauncher(true) { to: URI? -> - if (to != null) { - val filename = saveWallpaperFile(to) - if (filename != null) { - if (themeUserDestination.value == null) { - removeWallpaperFile((currentTheme.wallpaper.type as? WallpaperType.Image)?.filename) - } else { - removeWallpaperFile((perUserTheme.value.type as? WallpaperType.Image)?.filename) - } - onTypeChange(WallpaperType.Image(filename, 1f, WallpaperScaleType.FILL)) + val onImport = { to: URI -> + val filename = saveWallpaperFile(to) + if (filename != null) { + if (themeUserDestination.value == null) { + removeWallpaperFile((currentTheme.wallpaper.type as? WallpaperType.Image)?.filename) + } else { + removeWallpaperFile((perUserTheme.value.type as? WallpaperType.Image)?.filename) } + onTypeChange(WallpaperType.Image(filename, 1f, WallpaperScaleType.FILL)) } } @@ -319,18 +318,18 @@ object AppearanceScope { ThemeManager.currentColors(type, null, perUserOverride, appPrefs.themeOverrides.get()) } - val onChooseType: (WallpaperType?) -> Unit = { type: WallpaperType? -> + val onChooseType: (WallpaperType?, FileChooserLauncher) -> Unit = { type: WallpaperType?, importWallpaperLauncher: FileChooserLauncher -> when { // don't have image in parent or already selected wallpaper with custom image type is WallpaperType.Image && ((wallpaperType is WallpaperType.Image && themeUserDestination.value?.second != null && chatModel.remoteHostId() == null) || currentColors(type).wallpaper.type.image == null || - (currentColors(type).wallpaper.type.image != null && wallpaperType is WallpaperType.Image && themeUserDestination.value == null)) -> + (currentColors(type).wallpaper.type.image != null && CurrentColors.value.wallpaper.type is WallpaperType.Image && themeUserDestination.value == null)) -> withLongRunningApi { importWallpaperLauncher.launch("image/*") } type is WallpaperType.Image && themeUserDestination.value == null -> onTypeChange(currentColors(type).wallpaper.type) type is WallpaperType.Image && chatModel.remoteHostId() != null -> { /* do nothing when remote host connected */ } type is WallpaperType.Image -> onTypeCopyFromSameTheme(currentColors(type).wallpaper.type) - (themeUserDestination.value != null && themeUserDestination.value?.second?.preferredMode(!CurrentColors.value.colors.isLight)?.type != type) || currentTheme.wallpaper.type != type -> onTypeCopyFromSameTheme(type) + (themeUserDestination.value != null && themeUserDestination.value?.second?.preferredMode(!CurrentColors.value.colors.isLight)?.type != type) || CurrentColors.value.wallpaper.type != type -> onTypeCopyFromSameTheme(type) else -> onTypeChange(type) } } @@ -340,13 +339,17 @@ object AppearanceScope { ThemeDestinationPicker(themeUserDestination) Spacer(Modifier.height(DEFAULT_PADDING_HALF)) + val importWallpaperLauncher = rememberFileChooserLauncher(true) { to: URI? -> + if (to != null) onImport(to) + } + WallpaperPresetSelector( selectedWallpaper = wallpaperType, baseTheme = currentTheme.base, currentColors = { type -> currentColors(type) }, - onChooseType = onChooseType, + onChooseType = { onChooseType(it, importWallpaperLauncher) }, ) val type = MaterialTheme.wallpaper.type if (type is WallpaperType.Image && (themeUserDestination.value == null || perUserTheme.value.wallpaper?.imageFile != null)) { @@ -400,7 +403,10 @@ object AppearanceScope { val user = themeUserDestination.value if (user == null) { ModalManager.start.showModal { - CustomizeThemeView(onChooseType) + val importWallpaperLauncher = rememberFileChooserLauncher(true) { to: URI? -> + if (to != null) onImport(to) + } + CustomizeThemeView { onChooseType(it, importWallpaperLauncher) } } } else { ModalManager.start.showModalCloseable { close -> @@ -586,19 +592,19 @@ object AppearanceScope { @Composable fun ModalData.UserWallpaperEditorModal(remoteHostId: Long?, userId: Long, close: () -> Unit) { - val themes = remember(chatModel.currentUser.value) { chatModel.currentUser.value?.uiThemes ?: ThemeModeOverrides() } + val themes = remember(chatModel.currentUser.value) { mutableStateOf(chatModel.currentUser.value?.uiThemes ?: ThemeModeOverrides()) } val globalThemeUsed = remember { stateGetOrPut("globalThemeUsed") { false } } val initialTheme = remember(CurrentColors.collectAsState().value.base) { - val preferred = themes.preferredMode(!CurrentColors.value.colors.isLight) + val preferred = themes.value.preferredMode(!CurrentColors.value.colors.isLight) globalThemeUsed.value = preferred == null preferred ?: ThemeManager.defaultActiveTheme(chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) } UserWallpaperEditor( initialTheme, - applyToMode = if (themes.light == themes.dark) null else initialTheme.mode, + applyToMode = if (themes.value.light == themes.value.dark) null else initialTheme.mode, globalThemeUsed = globalThemeUsed, save = { applyToMode, newTheme -> - save(applyToMode, newTheme, themes, userId, remoteHostId) + save(applyToMode, newTheme, themes.value, userId, remoteHostId) }) KeyChangeEffect(chatModel.currentUser.value?.userId, chatModel.remoteHostId) { close() @@ -613,7 +619,7 @@ object AppearanceScope { remoteHostId: Long? ) { val unchangedThemes: ThemeModeOverrides = themes ?: ThemeModeOverrides() - val wallpaperFiles = listOf(unchangedThemes.light?.wallpaper?.imageFile, unchangedThemes.dark?.wallpaper?.imageFile) + val wallpaperFiles = setOf(unchangedThemes.light?.wallpaper?.imageFile, unchangedThemes.dark?.wallpaper?.imageFile) var changedThemes: ThemeModeOverrides? = unchangedThemes val changed = newTheme?.copy(wallpaper = newTheme.wallpaper?.withFilledWallpaperPath()) changedThemes = when (applyToMode) { @@ -621,7 +627,28 @@ object AppearanceScope { DefaultThemeMode.LIGHT -> changedThemes?.copy(light = changed?.copy(mode = applyToMode)) DefaultThemeMode.DARK -> changedThemes?.copy(dark = changed?.copy(mode = applyToMode)) } - changedThemes = if (changedThemes?.light != null || changedThemes?.dark != null) changedThemes else null + changedThemes = if (changedThemes?.light != null || changedThemes?.dark != null) { + val light = changedThemes.light + val dark = changedThemes.dark + val currentMode = CurrentColors.value.base.mode + // same image file for both modes, copy image to make them as different files + if (light?.wallpaper?.imageFile != null && dark?.wallpaper?.imageFile != null && light.wallpaper.imageFile == dark.wallpaper.imageFile) { + val imageFile = if (currentMode == DefaultThemeMode.LIGHT) { + dark.wallpaper.imageFile + } else { + light.wallpaper.imageFile + } + val filePath = saveWallpaperFile(File(getWallpaperFilePath(imageFile)).toURI()) + changedThemes = if (currentMode == DefaultThemeMode.LIGHT) { + changedThemes.copy(dark = dark.copy(wallpaper = dark.wallpaper.copy(imageFile = filePath))) + } else { + changedThemes.copy(light = light.copy(wallpaper = light.wallpaper.copy(imageFile = filePath))) + } + } + changedThemes + } else { + null + } val wallpaperFilesToDelete = wallpaperFiles - changedThemes?.light?.wallpaper?.imageFile - changedThemes?.dark?.wallpaper?.imageFile wallpaperFilesToDelete.forEach(::removeWallpaperFile) @@ -662,9 +689,9 @@ object AppearanceScope { } val values by remember(chatModel.users.toList()) { mutableStateOf( - listOf(null as Long? to generalGetString(MR.strings.theme_destination_all_profiles)) + listOf(null as Long? to generalGetString(MR.strings.theme_destination_app_theme)) + - chatModel.users.filter { it.user.activeUser || it.user.viewPwdHash == null }.map { + chatModel.users.filter { it.user.activeUser }.map { it.user.userId to it.user.chatViewName }, ) diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml index b00f1a9438..dca3e95156 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -1570,7 +1570,7 @@ Export theme Reset colors Reset color - All chat profiles + App theme Accent Additional accent Secondary @@ -1601,7 +1601,8 @@ Fill Fit Advanced settings - Reset to global theme + Reset to app theme + Reset to user theme Set default theme Apply to All color modes From da1cad96fced205180b487e37f5c89643d0df22f Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Tue, 28 May 2024 14:04:23 +0700 Subject: [PATCH 11/21] android: fix showing empty notification (#4237) * android: fix showing empty notification * fix desktop concurrent notifications --- .../simplex/app/model/NtfManager.android.kt | 2 +- .../common/model/NtfManager.desktop.kt | 37 +++++++++++++------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/model/NtfManager.android.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/model/NtfManager.android.kt index f83933b2e0..69ad8defbf 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/model/NtfManager.android.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/model/NtfManager.android.kt @@ -77,7 +77,7 @@ object NtfManager { val msgNtfs = manager.activeNotifications.filter { ntf -> ntf.notification.channelId == MessageChannel } - if (msgNtfs.count() == 1) { + if (msgNtfs.size <= 1) { // Have a group notification with no children so cancel it manager.cancel(0) } diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/model/NtfManager.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/model/NtfManager.desktop.kt index 3fab849361..3913c0dc9b 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/model/NtfManager.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/model/NtfManager.desktop.kt @@ -8,6 +8,8 @@ import chat.simplex.common.views.call.RcvCallInvitation import chat.simplex.common.views.helpers.* import chat.simplex.res.MR import com.sshtools.twoslices.* +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import java.awt.* import java.awt.TrayIcon.MessageType import java.io.File @@ -15,6 +17,7 @@ import javax.imageio.ImageIO object NtfManager { private val prevNtfs = arrayListOf>() + private val prevNtfsMutex: Mutex = Mutex() fun notifyCallInvitation(invitation: RcvCallInvitation): Boolean { if (simplexWindowState.windowFocused.value) return false @@ -55,21 +58,29 @@ object NtfManager { fun hasNotificationsForChat(chatId: ChatId) = false//prevNtfs.any { it.first == chatId } fun cancelNotificationsForChat(chatId: ChatId) { - val ntf = prevNtfs.firstOrNull { it.first == chatId } - if (ntf != null) { - prevNtfs.remove(ntf) - /*try { - ntf.second.close() - } catch (e: Exception) { - // Can be java.lang.UnsupportedOperationException, for example. May do nothing - println("Failed to close notification: ${e.stackTraceToString()}") - }*/ + withBGApi { + prevNtfsMutex.withLock { + val ntf = prevNtfs.firstOrNull { it.first == chatId } + if (ntf != null) { + prevNtfs.remove(ntf) + /*try { + ntf.second.close() + } catch (e: Exception) { + // Can be java.lang.UnsupportedOperationException, for example. May do nothing + println("Failed to close notification: ${e.stackTraceToString()}") + }*/ + } + } } } fun cancelAllNotifications() { // prevNtfs.forEach { try { it.second.close() } catch (e: Exception) { println("Failed to close notification: ${e.stackTraceToString()}") } } - prevNtfs.clear() + withBGApi { + prevNtfsMutex.withLock { + prevNtfs.clear() + } + } } fun displayNotification(user: UserLike, chatId: String, displayName: String, msgText: String, image: String?, actions: List Unit>>) { @@ -110,7 +121,11 @@ object NtfManager { builder.action(it.first, it.second) } try { - prevNtfs.add(chatId to builder.toast()) + withBGApi { + prevNtfsMutex.withLock { + prevNtfs.add(chatId to builder.toast()) + } + } } catch (e: Throwable) { Log.e(TAG, e.stackTraceToString()) if (e !is Exception) { From 57c80786dc041cc3e7896eea7845bc85dc41348e Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Tue, 28 May 2024 11:20:52 +0100 Subject: [PATCH 12/21] ui: translations, remove translations for wallpaper names used in exported themes (#4239) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Translated using Weblate (Hungarian) Currently translated at 100.0% (1741 of 1741 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Persian) Currently translated at 54.1% (943 of 1741 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fa/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1515 of 1515 strings) Translation: SimpleX Chat/SimpleX Chat iOS Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/ * Translated using Weblate (Persian) Currently translated at 65.5% (1141 of 1741 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fa/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1741 of 1741 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1515 of 1515 strings) Translation: SimpleX Chat/SimpleX Chat iOS Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/ * Translated using Weblate (Persian) Currently translated at 76.3% (1330 of 1741 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fa/ * Translated using Weblate (Persian) Currently translated at 83.0% (1446 of 1741 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fa/ * Translated using Weblate (German) Currently translated at 100.0% (1751 of 1751 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/ * Translated using Weblate (Italian) Currently translated at 100.0% (1751 of 1751 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1751 of 1751 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Italian) Currently translated at 100.0% (1772 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (1772 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/zh_Hans/ * Translated using Weblate (Hungarian) Currently translated at 99.3% (1760 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Persian) Currently translated at 88.3% (1566 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fa/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1772 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Persian) Currently translated at 100.0% (1772 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fa/ * Translated using Weblate (Polish) Currently translated at 98.3% (1743 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pl/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1772 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (1772 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/zh_Hans/ * Translated using Weblate (Spanish) Currently translated at 100.0% (1772 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/ * Translated using Weblate (Dutch) Currently translated at 100.0% (1772 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/nl/ * Translated using Weblate (Japanese) Currently translated at 98.8% (1751 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ja/ * Translated using Weblate (Polish) Currently translated at 99.9% (1771 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pl/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1772 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1515 of 1515 strings) Translation: SimpleX Chat/SimpleX Chat iOS Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/ * Translated using Weblate (German) Currently translated at 100.0% (1772 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1772 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1515 of 1515 strings) Translation: SimpleX Chat/SimpleX Chat iOS Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 95.6% (1449 of 1515 strings) Translation: SimpleX Chat/SimpleX Chat iOS Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/zh_Hans/ * Translated using Weblate (Turkish) Currently translated at 100.0% (1772 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1772 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Romanian) Currently translated at 9.8% (175 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ro/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1515 of 1515 strings) Translation: SimpleX Chat/SimpleX Chat iOS Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/ * Translated using Weblate (Vietnamese) Currently translated at 10.6% (189 of 1772 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/vi/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1778 of 1778 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1515 of 1515 strings) Translation: SimpleX Chat/SimpleX Chat iOS Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/ * Translated using Weblate (Italian) Currently translated at 100.0% (1778 of 1778 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (1778 of 1778 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/zh_Hans/ * Translated using Weblate (Spanish) Currently translated at 100.0% (1778 of 1778 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/ * Translated using Weblate (Dutch) Currently translated at 100.0% (1778 of 1778 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/nl/ * Translated using Weblate (Polish) Currently translated at 99.9% (1777 of 1778 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pl/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1778 of 1778 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1515 of 1515 strings) Translation: SimpleX Chat/SimpleX Chat iOS Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/ * Translated using Weblate (German) Currently translated at 100.0% (1778 of 1778 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/ * Translated using Weblate (German) Currently translated at 100.0% (1515 of 1515 strings) Translation: SimpleX Chat/SimpleX Chat iOS Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/de/ * Translated using Weblate (French) Currently translated at 100.0% (1515 of 1515 strings) Translation: SimpleX Chat/SimpleX Chat iOS Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/ * Translated using Weblate (Arabic) Currently translated at 100.0% (1778 of 1778 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1778 of 1778 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1515 of 1515 strings) Translation: SimpleX Chat/SimpleX Chat iOS Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1778 of 1778 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (French) Currently translated at 100.0% (1778 of 1778 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/ * Translated using Weblate (Persian) Currently translated at 100.0% (1778 of 1778 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fa/ * Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ * Translated using Weblate (Hungarian) Currently translated at 98.8% (1794 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Czech) Currently translated at 94.2% (1710 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/cs/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1814 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Polish) Currently translated at 99.9% (1813 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pl/ * Translated using Weblate (Italian) Currently translated at 100.0% (1814 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/ * Translated using Weblate (Turkish) Currently translated at 99.6% (1807 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/ * Translated using Weblate (German) Currently translated at 100.0% (1814 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/ * Translated using Weblate (Italian) Currently translated at 100.0% (1814 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (1814 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/zh_Hans/ * Translated using Weblate (Spanish) Currently translated at 100.0% (1814 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/ * Translated using Weblate (Spanish) Currently translated at 100.0% (1515 of 1515 strings) Translation: SimpleX Chat/SimpleX Chat iOS Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/es/ * Translated using Weblate (Arabic) Currently translated at 100.0% (1814 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/ * Translated using Weblate (Turkish) Currently translated at 100.0% (1814 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1814 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (1515 of 1515 strings) Translation: SimpleX Chat/SimpleX Chat iOS Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/ * Translated using Weblate (Vietnamese) Currently translated at 11.2% (204 of 1814 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/vi/ * Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ * Translated using Weblate (Ukrainian) Currently translated at 97.1% (1764 of 1815 strings) Translation: SimpleX Chat/SimpleX Chat Android Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/uk/ * process localizations * removed wallpapers names --------- Co-authored-by: summoner001 Co-authored-by: Siavash Co-authored-by: mlanp Co-authored-by: Random Co-authored-by: 大王叫我来巡山 Co-authored-by: Ghost of Sparta Co-authored-by: B.O.S.S Co-authored-by: No name Co-authored-by: M1K4 Co-authored-by: Miyu Sakatsuki Co-authored-by: sith-on-mars Co-authored-by: z0rden Co-authored-by: Flavian <3zorro.1@gmail.com> Co-authored-by: tuananh-ng <158744840+tuananh-ng@users.noreply.github.com> Co-authored-by: indiandoc Co-authored-by: jonnysemon Co-authored-by: Ophiushi <41908476+ishi-sama@users.noreply.github.com> Co-authored-by: Hosted Weblate Co-authored-by: zenobit Co-authored-by: Maksym Lukashenko Co-authored-by: Avently <7953703+avently@users.noreply.github.com> --- .../bg.xcloc/Localized Contents/bg.xliff | 151 ++- .../cs.xcloc/Localized Contents/cs.xliff | 150 +- .../de.xcloc/Localized Contents/de.xliff | 157 ++- .../en.xcloc/Localized Contents/en.xliff | 186 ++- .../es.xcloc/Localized Contents/es.xliff | 165 ++- .../fi.xcloc/Localized Contents/fi.xliff | 150 +- .../fr.xcloc/Localized Contents/fr.xliff | 161 ++- .../hu.xcloc/Localized Contents/hu.xliff | 255 +++- .../it.xcloc/Localized Contents/it.xliff | 151 ++- .../ja.xcloc/Localized Contents/ja.xliff | 150 +- .../nl.xcloc/Localized Contents/nl.xliff | 151 ++- .../pl.xcloc/Localized Contents/pl.xliff | 151 ++- .../ru.xcloc/Localized Contents/ru.xliff | 151 ++- .../th.xcloc/Localized Contents/th.xliff | 150 +- .../tr.xcloc/Localized Contents/tr.xliff | 151 ++- .../uk.xcloc/Localized Contents/uk.xliff | 150 +- .../Localized Contents/zh-Hans.xliff | 249 +++- apps/ios/bg.lproj/Localizable.strings | 11 +- apps/ios/cs.lproj/Localizable.strings | 8 +- apps/ios/de.lproj/Localizable.strings | 17 +- apps/ios/es.lproj/Localizable.strings | 25 +- apps/ios/fi.lproj/Localizable.strings | 8 +- apps/ios/fr.lproj/Localizable.strings | 21 +- apps/ios/hu.lproj/Localizable.strings | 113 +- apps/ios/it.lproj/Localizable.strings | 11 +- apps/ios/ja.lproj/Localizable.strings | 8 +- apps/ios/nl.lproj/Localizable.strings | 11 +- apps/ios/pl.lproj/Localizable.strings | 11 +- apps/ios/ru.lproj/Localizable.strings | 11 +- apps/ios/th.lproj/Localizable.strings | 8 +- apps/ios/tr.lproj/Localizable.strings | 11 +- apps/ios/uk.lproj/Localizable.strings | 8 +- apps/ios/zh-Hans.lproj/Localizable.strings | 305 ++++- .../common/views/helpers/ChatWallpaper.kt | 13 +- .../commonMain/resources/MR/ar/strings.xml | 71 +- .../commonMain/resources/MR/base/strings.xml | 8 +- .../commonMain/resources/MR/cs/strings.xml | 2 + .../commonMain/resources/MR/de/strings.xml | 85 +- .../commonMain/resources/MR/es/strings.xml | 83 +- .../commonMain/resources/MR/fa/strings.xml | 1205 ++++++++++++++++- .../commonMain/resources/MR/fr/strings.xml | 40 + .../commonMain/resources/MR/hu/strings.xml | 209 ++- .../commonMain/resources/MR/it/strings.xml | 73 +- .../commonMain/resources/MR/ja/strings.xml | 10 + .../commonMain/resources/MR/nl/strings.xml | 40 + .../commonMain/resources/MR/pl/strings.xml | 71 +- .../commonMain/resources/MR/ro/strings.xml | 16 + .../commonMain/resources/MR/tr/strings.xml | 71 +- .../commonMain/resources/MR/uk/strings.xml | 83 +- .../commonMain/resources/MR/vi/strings.xml | 27 + .../resources/MR/zh-rCN/strings.xml | 81 +- 51 files changed, 4908 insertions(+), 696 deletions(-) diff --git a/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff b/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff index 3d0bb2bf2c..8657b17c03 100644 --- a/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff +++ b/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff @@ -713,6 +713,10 @@ Позволи изчезващи съобщения само ако вашият контакт ги разрешава. No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) Позволи необратимо изтриване на съобщение само ако вашият контакт го рарешава. (24 часа) @@ -808,6 +812,10 @@ Вече се присъединихте към групата! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay Винаги използвай реле @@ -1088,6 +1096,10 @@ Файлът не може да бъде получен No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular Мобилна мрежа @@ -1948,6 +1960,10 @@ This cannot be undone! Настолни устройства No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop Разработване @@ -2053,11 +2069,19 @@ This cannot be undone! Откриване през локалната мрежа No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. НЕ използвайте SimpleX за спешни повиквания. No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later Отложи @@ -2621,7 +2645,7 @@ This cannot be undone! Error: %@ Грешка: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2713,6 +2737,10 @@ This cannot be undone! Файл: %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media Файлове и медия @@ -2818,6 +2846,16 @@ This cannot be undone! Препратено от No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop Намерено настолно устройство @@ -3633,6 +3671,10 @@ This is your link for group %@! Потвърждениe за доставка на съобщения! No comment provided by engineer. + + Message delivery warning + item status text + Message draft Чернова на съобщение @@ -3653,6 +3695,14 @@ This is your link for group %@! Реакциите на съобщения са забранени в тази група. No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. Източникът на съобщението остава скрит. @@ -3783,11 +3833,6 @@ This is your link for group %@! Най-вероятно тази връзка е изтрита. item status description - - Most likely this contact has deleted the connection with you. - Най-вероятно този контакт е изтрил връзката с вас. - No comment provided by engineer. - Multiple chat profiles Множество профили за чат @@ -3818,6 +3863,10 @@ This is your link for group %@! Мрежова връзка No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management Управление на мрежата @@ -4359,11 +4408,19 @@ Error: %@ Поверителни имена на файлове No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes Лични бележки name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections Профилни и сървърни връзки @@ -4444,6 +4501,10 @@ Error: %@ Забрани изпращането на гласови съобщения. No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen Защити екрана на приложението @@ -4554,11 +4615,6 @@ Error: %@ Получаващият адрес ще бъде променен към друг сървър. Промяната на адреса ще завърши, след като подателят е онлайн. No comment provided by engineer. - - Receiving concurrency - Паралелност на получаване - No comment provided by engineer. - Receiving file will be stopped. Получаващият се файл ще бъде спрян. @@ -5019,6 +5075,14 @@ Error: %@ Изпрати съобщение на живо No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Изпращай известия @@ -5124,6 +5188,10 @@ Error: %@ Изпратените съобщения ще бъдат изтрити след зададеното време. No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password Сървърът изисква оторизация за създаване на опашки, проверете паролата @@ -5139,6 +5207,10 @@ Error: %@ Тестът на сървъра е неуспешен! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers Сървъри @@ -5259,11 +5331,19 @@ Error: %@ Показване на последните съобщения в листа с чатовете No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview Показване на визуализация No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Покажи: @@ -5586,6 +5666,10 @@ It can happen because of some bug or when the connection is compromised.Приложението може да ви уведоми, когато получите съобщения или заявки за контакт - моля, отворете настройките, за да активирате. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. Опитът за промяна на паролата на базата данни не беше завършен. @@ -5771,6 +5855,10 @@ It can happen because of some bug or when the connection is compromised.За да не се разкрива часовата зона, файловете с изображения/глас използват UTC. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5863,11 +5951,6 @@ You will be prompted to complete authentication before this feature is enabled.< Отблокирай член? No comment provided by engineer. - - Unexpected error: %@ - Неочаквана грешка: %@ - item status description - Unexpected migration state Неочаквано състояние на миграция @@ -5913,6 +5996,10 @@ You will be prompted to complete authentication before this feature is enabled.< Непозната грешка No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. Освен ако не използвате интерфейса за повикване на iOS, активирайте режима "Не безпокой", за да избегнете прекъсвания. @@ -6060,6 +6147,14 @@ To connect, please ask your contact to create another connection link and check Използвай само локални известия? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server Използвай сървър @@ -6295,11 +6390,23 @@ To connect, please ask your contact to create another connection link and check С намален разход на батерията. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Грешна парола за базата данни No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! Грешна парола! @@ -7455,11 +7562,19 @@ SimpleX сървърите не могат да видят вашия профи неизвестен connection info + + unknown relays + No comment provided by engineer. + unknown status неизвестен статус No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile актуализиран профил на групата @@ -7525,6 +7640,10 @@ SimpleX сървърите не могат да видят вашия профи седмици time unit + + when IP hidden + No comment provided by engineer. + yes да diff --git a/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff b/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff index a1ef39b2fb..8d52e045b1 100644 --- a/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff +++ b/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff @@ -690,6 +690,10 @@ Povolte mizící zprávy, pouze pokud vám to váš kontakt dovolí. No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) Povolte nevratné smazání zprávy pouze v případě, že vám to váš kontakt dovolí. (24 hodin) @@ -782,6 +786,10 @@ Already joining the group! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay Spojení přes relé @@ -1047,6 +1055,10 @@ Nelze přijmout soubor No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular No comment provided by engineer. @@ -1870,6 +1882,10 @@ This cannot be undone! Desktop devices No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop Vyvinout @@ -1973,11 +1989,19 @@ This cannot be undone! Discover via local network No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. NEpoužívejte SimpleX pro tísňová volání. No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later Udělat později @@ -2519,7 +2543,7 @@ This cannot be undone! Error: %@ Chyba: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2608,6 +2632,10 @@ This cannot be undone! Soubor: %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media Soubory a média @@ -2706,6 +2734,16 @@ This cannot be undone! Forwarded from No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop No comment provided by engineer. @@ -3490,6 +3528,10 @@ This is your link for group %@! Potvrzení o doručení zprávy! No comment provided by engineer. + + Message delivery warning + item status text + Message draft Návrh zprávy @@ -3510,6 +3552,14 @@ This is your link for group %@! Reakce na zprávy jsou v této skupině zakázány. No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. No comment provided by engineer. @@ -3627,11 +3677,6 @@ This is your link for group %@! Pravděpodobně je toto spojení smazáno. item status description - - Most likely this contact has deleted the connection with you. - Tento kontakt s největší pravděpodobností smazal spojení s vámi. - No comment provided by engineer. - Multiple chat profiles Více chatovacích profilů @@ -3661,6 +3706,10 @@ This is your link for group %@! Network connection No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management No comment provided by engineer. @@ -4181,10 +4230,18 @@ Error: %@ Soukromé názvy souborů No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections Profil a připojení k serveru @@ -4261,6 +4318,10 @@ Error: %@ Zakázat odesílání hlasových zpráv. No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen Ochrana obrazovky aplikace @@ -4368,10 +4429,6 @@ Error: %@ Přijímací adresa bude změněna na jiný server. Změna adresy bude dokončena po připojení odesílatele. No comment provided by engineer. - - Receiving concurrency - No comment provided by engineer. - Receiving file will be stopped. Příjem souboru bude zastaven. @@ -4817,6 +4874,14 @@ Error: %@ Odeslat živou zprávu No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Odeslat oznámení @@ -4921,6 +4986,10 @@ Error: %@ Odeslané zprávy se po uplynutí nastavené doby odstraní. No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password Server vyžaduje autorizaci pro vytváření front, zkontrolujte heslo @@ -4936,6 +5005,10 @@ Error: %@ Test serveru se nezdařil! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers Servery @@ -5051,11 +5124,19 @@ Error: %@ Zobrazit poslední zprávy No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview Zobrazení náhledu No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Zobrazit: @@ -5369,6 +5450,10 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován Aplikace vás může upozornit na přijaté zprávy nebo žádosti o kontakt - povolte to v nastavení. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. Pokus o změnu přístupové fráze databáze nebyl dokončen. @@ -5545,6 +5630,10 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován K ochraně časového pásma používají obrazové/hlasové soubory UTC. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5631,11 +5720,6 @@ Před zapnutím této funkce budete vyzváni k dokončení ověření. Unblock member? No comment provided by engineer. - - Unexpected error: %@ - Neočekávaná chyba: %@ - item status description - Unexpected migration state Neočekávaný stav přenášení @@ -5681,6 +5765,10 @@ Před zapnutím této funkce budete vyzváni k dokončení ověření. Neznámá chyba No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. Při nepoužívání rozhraní volání iOS, povolte režim Nerušit, abyste se vyhnuli vyrušování. @@ -5821,6 +5909,14 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu Use only local notifications? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server Použít server @@ -6038,11 +6134,23 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu With reduced battery usage. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Špatná přístupová fráze k databázi No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! Špatná přístupová fráze! @@ -7158,10 +7266,18 @@ Servery SimpleX nevidí váš profil. neznámý connection info + + unknown relays + No comment provided by engineer. + unknown status No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile aktualizoval profil skupiny @@ -7225,6 +7341,10 @@ Servery SimpleX nevidí váš profil. týdnů time unit + + when IP hidden + No comment provided by engineer. + yes ano diff --git a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff index 29384aecc4..b21e35382a 100644 --- a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff +++ b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff @@ -695,7 +695,7 @@ All your contacts, conversations and files will be securely encrypted and uploaded in chunks to configured XFTP relays. - Alle Ihre Kontakte, Unterhaltungen und Dateien werden sicher verschlüsselt und in Daten-Paketen auf die konfigurierten XTFP-Server hochgeladen. + Alle Ihre Kontakte, Unterhaltungen und Dateien werden sicher verschlüsselt und in Daten-Paketen auf die konfigurierten XTFP-Relais hochgeladen. No comment provided by engineer. @@ -713,6 +713,10 @@ Erlauben Sie verschwindende Nachrichten nur dann, wenn es Ihr Kontakt ebenfalls erlaubt. No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) Erlauben Sie das unwiederbringliche Löschen von Nachrichten nur dann, wenn es Ihnen Ihr Kontakt ebenfalls erlaubt. (24 Stunden) @@ -808,6 +812,10 @@ Sie sind bereits Mitglied der Gruppe! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay Über ein Relais verbinden @@ -1088,6 +1096,10 @@ Datei kann nicht empfangen werden No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular Zellulär @@ -1948,6 +1960,10 @@ Das kann nicht rückgängig gemacht werden! Desktop-Geräte No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop Entwicklung @@ -2053,11 +2069,19 @@ Das kann nicht rückgängig gemacht werden! Lokales Netzwerk durchsuchen No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. Nutzen Sie SimpleX nicht für Notrufe. No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later Später wiederholen @@ -2621,7 +2645,7 @@ Das kann nicht rückgängig gemacht werden! Error: %@ Fehler: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2713,6 +2737,10 @@ Das kann nicht rückgängig gemacht werden! Datei: %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media Dateien & Medien @@ -2818,6 +2846,16 @@ Das kann nicht rückgängig gemacht werden! Weitergeleitet aus No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop Gefundener Desktop @@ -3633,6 +3671,10 @@ Das ist Ihr Link für die Gruppe %@! Empfangsbestätigungen für Nachrichten! No comment provided by engineer. + + Message delivery warning + item status text + Message draft Nachrichtenentwurf @@ -3653,6 +3695,14 @@ Das ist Ihr Link für die Gruppe %@! In dieser Gruppe sind Reaktionen auf Nachrichten nicht erlaubt. No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. Die Nachrichtenquelle bleibt privat. @@ -3783,11 +3833,6 @@ Das ist Ihr Link für die Gruppe %@! Wahrscheinlich ist diese Verbindung gelöscht worden. item status description - - Most likely this contact has deleted the connection with you. - Dieser Kontakt hat sehr wahrscheinlich die Verbindung mit Ihnen gelöscht. - No comment provided by engineer. - Multiple chat profiles Mehrere Chat-Profile @@ -3818,6 +3863,10 @@ Das ist Ihr Link für die Gruppe %@! Netzwerkverbindung No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management Netzwerk-Verwaltung @@ -4004,12 +4053,12 @@ Das ist Ihr Link für die Gruppe %@! Onion hosts will be required for connection. Requires enabling VPN. - Für die Verbindung werden Onion-Hosts benötigt. Dies erfordert die Aktivierung eines VPNs. + Für diese Verbindung werden Onion-Hosts benötigt. Dies erfordert die Aktivierung eines VPNs. No comment provided by engineer. Onion hosts will be used when available. Requires enabling VPN. - Onion-Hosts werden verwendet, sobald sie verfügbar sind. Dies erfordert die Aktivierung eines VPNs. + Wenn Onion-Hosts verfügbar sind, werden sie verwendet. Dies erfordert die Aktivierung eines VPNs. No comment provided by engineer. @@ -4359,11 +4408,19 @@ Fehler: %@ Neutrale Dateinamen No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes Private Notizen name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections Profil und Serververbindungen @@ -4444,6 +4501,10 @@ Fehler: %@ Das Senden von Sprachnachrichten nicht erlauben. No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen App-Bildschirm schützen @@ -4554,11 +4615,6 @@ Fehler: %@ Die Empfängeradresse wird auf einen anderen Server geändert. Der Adresswechsel wird abgeschlossen, wenn der Absender wieder online ist. No comment provided by engineer. - - Receiving concurrency - Gleichzeitiger Empfang - No comment provided by engineer. - Receiving file will be stopped. Der Empfang der Datei wird beendet. @@ -5019,6 +5075,14 @@ Fehler: %@ Live Nachricht senden No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Benachrichtigungen senden @@ -5124,6 +5188,10 @@ Fehler: %@ Gesendete Nachrichten werden nach der eingestellten Zeit gelöscht. No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password Um Warteschlangen zu erzeugen benötigt der Server eine Authentifizierung. Bitte überprüfen Sie das Passwort @@ -5139,6 +5207,10 @@ Fehler: %@ Server Test ist fehlgeschlagen! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers Server @@ -5259,11 +5331,19 @@ Fehler: %@ Letzte Nachrichten anzeigen No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview Vorschau anzeigen No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Anzeigen: @@ -5586,6 +5666,10 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro Wenn sie Nachrichten oder Kontaktanfragen empfangen, kann Sie die App benachrichtigen - Um dies zu aktivieren, öffnen Sie bitte die Einstellungen. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. Die Änderung des Datenbank-Passworts konnte nicht abgeschlossen werden. @@ -5771,6 +5855,10 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro Bild- und Sprachdateinamen enthalten UTC, um Informationen zur Zeitzone zu schützen. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5863,11 +5951,6 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt Mitglied freigeben? No comment provided by engineer. - - Unexpected error: %@ - Unerwarteter Fehler: %@ - item status description - Unexpected migration state Unerwarteter Migrationsstatus @@ -5913,6 +5996,10 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt Unbekannter Fehler No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. Aktivieren Sie den Modus "Bitte nicht stören", um Unterbrechungen zu vermeiden, es sei denn, Sie verwenden die iOS Anrufschnittstelle. @@ -6060,6 +6147,14 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s Nur lokale Benachrichtigungen nutzen? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server Server nutzen @@ -6295,11 +6390,23 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s Mit reduziertem Akkuverbrauch. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Falsches Datenbank-Passwort No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! Falsches Passwort! @@ -7455,11 +7562,19 @@ SimpleX-Server können Ihr Profil nicht einsehen. Unbekannt connection info + + unknown relays + No comment provided by engineer. + unknown status unbekannter Gruppenmitglieds-Status No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile Aktualisiertes Gruppenprofil @@ -7525,6 +7640,10 @@ SimpleX-Server können Ihr Profil nicht einsehen. Wochen time unit + + when IP hidden + No comment provided by engineer. + yes Ja diff --git a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff index 2b5677dd61..396d419a09 100644 --- a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff +++ b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff @@ -713,6 +713,11 @@ Allow disappearing messages only if your contact allows it to you. No comment provided by engineer. + + Allow downgrade + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) Allow irreversible message deletion only if your contact allows it to you. (24 hours) @@ -808,6 +813,11 @@ Already joining the group! No comment provided by engineer. + + Always use private routing. + Always use private routing. + No comment provided by engineer. + Always use relay Always use relay @@ -1088,6 +1098,11 @@ Cannot receive file No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular Cellular @@ -1948,6 +1963,11 @@ This cannot be undone! Desktop devices No comment provided by engineer. + + Destination server error: %@ + Destination server error: %@ + snd error text + Develop Develop @@ -2053,11 +2073,21 @@ This cannot be undone! Discover via local network No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. Do NOT use SimpleX for emergency calls. No comment provided by engineer. + + Do NOT use private routing. + Do NOT use private routing. + No comment provided by engineer. + Do it later Do it later @@ -2621,7 +2651,7 @@ This cannot be undone! Error: %@ Error: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2713,6 +2743,11 @@ This cannot be undone! File: %@ No comment provided by engineer. + + Files + Files + No comment provided by engineer. + Files & media Files & media @@ -2818,6 +2853,20 @@ This cannot be undone! Forwarded from No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop Found desktop @@ -3633,6 +3682,11 @@ This is your link for group %@! Message delivery receipts! No comment provided by engineer. + + Message delivery warning + Message delivery warning + item status text + Message draft Message draft @@ -3653,6 +3707,16 @@ This is your link for group %@! Message reactions are prohibited in this group. No comment provided by engineer. + + Message routing fallback + Message routing fallback + No comment provided by engineer. + + + Message routing mode + Message routing mode + No comment provided by engineer. + Message source remains private. Message source remains private. @@ -3783,11 +3847,6 @@ This is your link for group %@! Most likely this connection is deleted. item status description - - Most likely this contact has deleted the connection with you. - Most likely this contact has deleted the connection with you. - No comment provided by engineer. - Multiple chat profiles Multiple chat profiles @@ -3818,6 +3877,11 @@ This is your link for group %@! Network connection No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + Network issues - message expired after many attempts to send it. + snd error text + Network management Network management @@ -4359,11 +4423,21 @@ Error: %@ Private filenames No comment provided by engineer. + + Private message routing + Private message routing + No comment provided by engineer. + Private notes Private notes name of notes to self + + Private routing + Private routing + No comment provided by engineer. + Profile and server connections Profile and server connections @@ -4444,6 +4518,11 @@ Error: %@ Prohibit sending voice messages. No comment provided by engineer. + + Protect IP address + Protect IP address + No comment provided by engineer. + Protect app screen Protect app screen @@ -4554,11 +4633,6 @@ Error: %@ Receiving address will be changed to a different server. Address change will complete after sender comes online. No comment provided by engineer. - - Receiving concurrency - Receiving concurrency - No comment provided by engineer. - Receiving file will be stopped. Receiving file will be stopped. @@ -5019,6 +5093,16 @@ Error: %@ Send live message No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Send notifications @@ -5124,6 +5208,11 @@ Error: %@ Sent messages will be deleted after set time. No comment provided by engineer. + + Server address is incompatible with network settings. + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password Server requires authorization to create queues, check password @@ -5139,6 +5228,11 @@ Error: %@ Server test failed! No comment provided by engineer. + + Server version is incompatible with network settings. + Server version is incompatible with network settings. + srv error text + Servers Servers @@ -5259,11 +5353,21 @@ Error: %@ Show last messages No comment provided by engineer. + + Show message status + Show message status + No comment provided by engineer. + Show preview Show preview No comment provided by engineer. + + Show → on messages sent via private routing. + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Show: @@ -5586,6 +5690,11 @@ It can happen because of some bug or when the connection is compromised.The app can notify you when you receive messages or contact requests - please open settings to enable. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. The attempt to change database passphrase was not completed. @@ -5771,6 +5880,11 @@ It can happen because of some bug or when the connection is compromised.To protect timezone, image/voice files use UTC. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5863,11 +5977,6 @@ You will be prompted to complete authentication before this feature is enabled.< Unblock member? No comment provided by engineer. - - Unexpected error: %@ - Unexpected error: %@ - item status description - Unexpected migration state Unexpected migration state @@ -5913,6 +6022,11 @@ You will be prompted to complete authentication before this feature is enabled.< Unknown error No comment provided by engineer. + + Unknown servers! + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -6060,6 +6174,16 @@ To connect, please ask your contact to create another connection link and check Use only local notifications? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + Use private routing with unknown servers. + No comment provided by engineer. + Use server Use server @@ -6295,11 +6419,26 @@ To connect, please ask your contact to create another connection link and check With reduced battery usage. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Wrong database passphrase No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! Wrong passphrase! @@ -7455,11 +7594,21 @@ SimpleX servers cannot see your profile. unknown connection info + + unknown relays + unknown relays + No comment provided by engineer. + unknown status unknown status No comment provided by engineer. + + unprotected + unprotected + No comment provided by engineer. + updated group profile updated group profile @@ -7525,6 +7674,11 @@ SimpleX servers cannot see your profile. weeks time unit + + when IP hidden + when IP hidden + No comment provided by engineer. + yes yes diff --git a/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff b/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff index 5d2482ae27..da42957714 100644 --- a/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff +++ b/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff @@ -713,6 +713,10 @@ Se permiten los mensajes temporales pero sólo si tu contacto también los permite para tí. No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) Se permite la eliminación irreversible de mensajes pero sólo si tu contacto también la permite para tí. (24 horas) @@ -808,6 +812,10 @@ ¡Ya en proceso de unirte al grupo! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay Usar siempre retransmisor @@ -1040,7 +1048,7 @@ By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA). - Mediante perfil (por defecto) o [por conexión](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA). + Mediante perfil (predeterminado) o [por conexión](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA). No comment provided by engineer. @@ -1088,6 +1096,10 @@ No se puede recibir el archivo No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular Móvil @@ -1948,6 +1960,10 @@ This cannot be undone! Ordenadores No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop Desarrollo @@ -2053,11 +2069,19 @@ This cannot be undone! Descubrir en red local No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. NO uses SimpleX para llamadas de emergencia. No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later Hacer más tarde @@ -2205,7 +2229,7 @@ This cannot be undone! Enabled for - Activar para + Activado para No comment provided by engineer. @@ -2621,7 +2645,7 @@ This cannot be undone! Error: %@ Error: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2713,6 +2737,10 @@ This cannot be undone! Archivo: %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media Archivos y multimedia @@ -2818,6 +2846,16 @@ This cannot be undone! Reenviado por No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop Ordenador encontrado @@ -3633,6 +3671,10 @@ This is your link for group %@! ¡Confirmación de entrega de mensajes! No comment provided by engineer. + + Message delivery warning + item status text + Message draft Borrador de mensaje @@ -3653,6 +3695,14 @@ This is your link for group %@! Las reacciones a los mensajes no están permitidas en este grupo. No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. El autor del mensaje se mantiene privado. @@ -3783,11 +3833,6 @@ This is your link for group %@! Probablemente la conexión ha sido eliminada. item status description - - Most likely this contact has deleted the connection with you. - Lo más probable es que este contacto haya eliminado la conexión contigo. - No comment provided by engineer. - Multiple chat profiles Múltiples perfiles @@ -3818,6 +3863,10 @@ This is your link for group %@! Conexión de red No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management Gestión de la red @@ -4359,11 +4408,19 @@ Error: %@ Nombres de archivos privados No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes Notas privadas name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections Datos del perfil y conexiones @@ -4376,7 +4433,7 @@ Error: %@ Profile images - Imágenes del perfil + Forma de los perfiles No comment provided by engineer. @@ -4444,6 +4501,10 @@ Error: %@ No se permiten mensajes de voz. No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen Proteger la pantalla de la aplicación @@ -4554,11 +4615,6 @@ Error: %@ La dirección de recepción pasará a otro servidor. El cambio se completará cuando el remitente esté en línea. No comment provided by engineer. - - Receiving concurrency - Concurrencia en la recepción - No comment provided by engineer. - Receiving file will be stopped. Se detendrá la recepción del archivo. @@ -4716,7 +4772,7 @@ Error: %@ Reset to defaults - Restablecer valores por defecto + Restablecer valores predetarminados No comment provided by engineer. @@ -5019,6 +5075,14 @@ Error: %@ Mensaje en vivo No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Enviar notificaciones @@ -5124,6 +5188,10 @@ Error: %@ Los mensajes enviados se eliminarán una vez transcurrido el tiempo establecido. No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password El servidor requiere autorización para crear colas, comprueba la contraseña @@ -5139,6 +5207,10 @@ Error: %@ ¡Error en prueba del servidor! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers Servidores @@ -5259,11 +5331,19 @@ Error: %@ Mostrar último mensaje No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview Mostrar vista previa No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Mostrar: @@ -5586,6 +5666,10 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida. La aplicación puede notificarte cuando recibas mensajes o solicitudes de contacto: por favor, abre la configuración para activarlo. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. El intento de cambiar la contraseña de la base de datos no se ha completado. @@ -5771,6 +5855,10 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida. Para proteger la zona horaria, los archivos de imagen/voz usan la hora UTC. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5863,11 +5951,6 @@ Se te pedirá que completes la autenticación antes de activar esta función.¿Desbloquear miembro? No comment provided by engineer. - - Unexpected error: %@ - Error inesperado: %@ - item status description - Unexpected migration state Estado de migración inesperado @@ -5913,6 +5996,10 @@ Se te pedirá que completes la autenticación antes de activar esta función.Error desconocido No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. A menos que utilices la interfaz de llamadas de iOS, activa el modo No molestar para evitar interrupciones. @@ -6061,6 +6148,14 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb ¿Usar sólo notificaciones locales? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server Usar servidor @@ -6296,11 +6391,23 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb Con uso reducido de batería. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Contraseña de base de datos incorrecta No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! ¡Contraseña incorrecta! @@ -6986,17 +7093,17 @@ Los servidores de SimpleX no pueden ver tu perfil. default (%@) - por defecto (%@) + predeterminado (%@) pref value default (no) - por defecto (no) + predeterminado (no) No comment provided by engineer. default (yes) - por defecto (sí) + predeterminado (sí) No comment provided by engineer. @@ -7456,11 +7563,19 @@ Los servidores de SimpleX no pueden ver tu perfil. desconocido connection info + + unknown relays + No comment provided by engineer. + unknown status estado desconocido No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile ha actualizado el perfil del grupo @@ -7526,6 +7641,10 @@ Los servidores de SimpleX no pueden ver tu perfil. semanas time unit + + when IP hidden + No comment provided by engineer. + yes diff --git a/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff b/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff index a239bebbcf..fbdb5dfe19 100644 --- a/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff +++ b/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff @@ -685,6 +685,10 @@ Salli katoavat viestit vain, jos kontaktisi sallii sen sinulle. No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) Salli peruuttamaton viestien poisto vain, jos kontaktisi sallii ne sinulle. (24 tuntia) @@ -777,6 +781,10 @@ Already joining the group! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay Käytä aina relettä @@ -1040,6 +1048,10 @@ Tiedostoa ei voi vastaanottaa No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular No comment provided by engineer. @@ -1863,6 +1875,10 @@ This cannot be undone! Desktop devices No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop Kehitä @@ -1966,11 +1982,19 @@ This cannot be undone! Discover via local network No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. Älä käytä SimpleX-sovellusta hätäpuheluihin. No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later Tee myöhemmin @@ -2509,7 +2533,7 @@ This cannot be undone! Error: %@ Virhe: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2598,6 +2622,10 @@ This cannot be undone! Tiedosto: %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media Tiedostot & media @@ -2696,6 +2724,16 @@ This cannot be undone! Forwarded from No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop No comment provided by engineer. @@ -3480,6 +3518,10 @@ This is your link for group %@! Viestien toimituskuittaukset! No comment provided by engineer. + + Message delivery warning + item status text + Message draft Viestiluonnos @@ -3500,6 +3542,14 @@ This is your link for group %@! Viestireaktiot ovat kiellettyjä tässä ryhmässä. No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. No comment provided by engineer. @@ -3617,11 +3667,6 @@ This is your link for group %@! Todennäköisesti tämä yhteys on poistettu. item status description - - Most likely this contact has deleted the connection with you. - Todennäköisesti tämä kontakti on poistanut yhteyden sinuun. - No comment provided by engineer. - Multiple chat profiles Useita keskusteluprofiileja @@ -3651,6 +3696,10 @@ This is your link for group %@! Network connection No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management No comment provided by engineer. @@ -4169,10 +4218,18 @@ Error: %@ Yksityiset tiedostonimet No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections Profiili- ja palvelinyhteydet @@ -4249,6 +4306,10 @@ Error: %@ Estä ääniviestien lähettäminen. No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen Suojaa sovellusnäyttö @@ -4356,10 +4417,6 @@ Error: %@ Vastaanotto-osoite vaihdetaan toiseen palvelimeen. Osoitteenmuutos tehdään sen jälkeen, kun lähettäjä tulee verkkoon. No comment provided by engineer. - - Receiving concurrency - No comment provided by engineer. - Receiving file will be stopped. Tiedoston vastaanotto pysäytetään. @@ -4804,6 +4861,14 @@ Error: %@ Lähetä live-viesti No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Lähetys ilmoitukset @@ -4908,6 +4973,10 @@ Error: %@ Lähetetyt viestit poistetaan asetetun ajan kuluttua. No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password Palvelin vaatii valtuutuksen jonojen luomiseen, tarkista salasana @@ -4923,6 +4992,10 @@ Error: %@ Palvelintesti epäonnistui! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers Palvelimet @@ -5038,11 +5111,19 @@ Error: %@ Näytä viimeiset viestit No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview Näytä esikatselu No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Näytä: @@ -5355,6 +5436,10 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.Sovellus voi ilmoittaa sinulle, kun saat viestejä tai yhteydenottopyyntöjä - avaa asetukset ottaaksesi ne käyttöön. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. Tietokannan tunnuslauseen muuttamista ei suoritettu loppuun. @@ -5531,6 +5616,10 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.Aikavyöhykkeen suojaamiseksi kuva-/äänitiedostot käyttävät UTC:tä. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5616,11 +5705,6 @@ Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus ote Unblock member? No comment provided by engineer. - - Unexpected error: %@ - Odottamaton virhe: %@ - item status description - Unexpected migration state Odottamaton siirtotila @@ -5666,6 +5750,10 @@ Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus ote Tuntematon virhe No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. Ellet käytä iOS:n puhelinkäyttöliittymää, ota Älä häiritse -tila käyttöön keskeytysten välttämiseksi. @@ -5806,6 +5894,14 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja Use only local notifications? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server Käytä palvelinta @@ -6023,11 +6119,23 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja With reduced battery usage. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Väärä tietokannan tunnuslause No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! Väärä tunnuslause! @@ -7142,10 +7250,18 @@ SimpleX-palvelimet eivät näe profiiliasi. tuntematon connection info + + unknown relays + No comment provided by engineer. + unknown status No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile päivitetty ryhmäprofiili @@ -7209,6 +7325,10 @@ SimpleX-palvelimet eivät näe profiiliasi. viikkoa time unit + + when IP hidden + No comment provided by engineer. + yes kyllä diff --git a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff index ac7fc8cc8b..81bd0f3741 100644 --- a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff +++ b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff @@ -713,6 +713,10 @@ Autorise les messages éphémères seulement si votre contact vous l’autorise. No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) Autoriser la suppression irréversible des messages uniquement si votre contact vous l'autorise. (24 heures) @@ -808,6 +812,10 @@ Groupe déjà rejoint ! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay Se connecter via relais @@ -1088,6 +1096,10 @@ Impossible de recevoir le fichier No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular Cellulaire @@ -1925,7 +1937,7 @@ Cette opération ne peut être annulée ! Delivery receipts! - Justificatifs de réception! + Justificatifs de réception ! No comment provided by engineer. @@ -1948,6 +1960,10 @@ Cette opération ne peut être annulée ! Appareils de bureau No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop Développer @@ -2053,11 +2069,19 @@ Cette opération ne peut être annulée ! Rechercher sur le réseau No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. N'utilisez PAS SimpleX pour les appels d'urgence. No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later Faites-le plus tard @@ -2621,7 +2645,7 @@ Cette opération ne peut être annulée ! Error: %@ Erreur : %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2713,6 +2737,10 @@ Cette opération ne peut être annulée ! Fichier : %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media Fichiers & médias @@ -2775,7 +2803,7 @@ Cette opération ne peut être annulée ! Fix connection? - Réparer la connexion? + Réparer la connexion ? No comment provided by engineer. @@ -2818,6 +2846,16 @@ Cette opération ne peut être annulée ! Transféré depuis No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop Bureau trouvé @@ -3633,6 +3671,10 @@ Voici votre lien pour le groupe %@ ! Accusés de réception des messages ! No comment provided by engineer. + + Message delivery warning + item status text + Message draft Brouillon de message @@ -3653,6 +3695,14 @@ Voici votre lien pour le groupe %@ ! Les réactions aux messages sont interdites dans ce groupe. No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. La source du message reste privée. @@ -3783,11 +3833,6 @@ Voici votre lien pour le groupe %@ ! Connexion probablement supprimée. item status description - - Most likely this contact has deleted the connection with you. - Il est fort probable que ce contact ait supprimé la connexion avec vous. - No comment provided by engineer. - Multiple chat profiles Différents profils de chat @@ -3818,6 +3863,10 @@ Voici votre lien pour le groupe %@ ! Connexion au réseau No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management Gestion du réseau @@ -4359,11 +4408,19 @@ Erreur : %@ Noms de fichiers privés No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes Notes privées name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections Profil et connexions au serveur @@ -4444,6 +4501,10 @@ Erreur : %@ Interdire l'envoi de messages vocaux. No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen Protéger l'écran de l'app @@ -4554,11 +4615,6 @@ Erreur : %@ L'adresse de réception sera changée pour un autre serveur. Le changement d'adresse sera terminé lorsque l'expéditeur sera en ligne. No comment provided by engineer. - - Receiving concurrency - Réception simultanée - No comment provided by engineer. - Receiving file will be stopped. La réception du fichier sera interrompue. @@ -4591,7 +4647,7 @@ Erreur : %@ Reconnect servers? - Reconnecter les serveurs? + Reconnecter les serveurs ? No comment provided by engineer. @@ -4666,7 +4722,7 @@ Erreur : %@ Renegotiate encryption? - Renégocier le chiffrement? + Renégocier le chiffrement ? No comment provided by engineer. @@ -5019,6 +5075,14 @@ Erreur : %@ Envoyer un message dynamique No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Envoi de notifications @@ -5124,6 +5188,10 @@ Erreur : %@ Les messages envoyés seront supprimés après une durée déterminée. No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password Le serveur requiert une autorisation pour créer des files d'attente, vérifiez le mot de passe @@ -5139,6 +5207,10 @@ Erreur : %@ Échec du test du serveur ! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers Serveurs @@ -5259,11 +5331,19 @@ Erreur : %@ Voir les derniers messages No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview Afficher l'aperçu No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Afficher : @@ -5586,6 +5666,10 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise. L'application peut vous avertir lorsque vous recevez des messages ou des demandes de contact - veuillez ouvrir les paramètres pour les activer. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. La tentative de modification de la phrase secrète de la base de données n'a pas abouti. @@ -5771,6 +5855,10 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise. Pour préserver le fuseau horaire, les fichiers image/voix utilisent le système UTC. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5863,11 +5951,6 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s Débloquer ce membre ? No comment provided by engineer. - - Unexpected error: %@ - Erreur inattendue : %@ - item status description - Unexpected migration state État de la migration inattendu @@ -5913,6 +5996,10 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s Erreur inconnue No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. À moins que vous utilisiez l'interface d'appel d'iOS, activez le mode "Ne pas déranger" pour éviter les interruptions. @@ -6060,6 +6147,14 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Utilisation de notifications locales uniquement ? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server Utiliser ce serveur @@ -6212,7 +6307,7 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Warning: starting chat on multiple devices is not supported and will cause message delivery failures - Attention: démarrer une session de chat sur plusieurs appareils n'est pas pris en charge et entraînera des dysfonctionnements au niveau de la transmission des messages + Attention : démarrer une session de chat sur plusieurs appareils n'est pas pris en charge et entraînera des dysfonctionnements au niveau de la transmission des messages No comment provided by engineer. @@ -6295,11 +6390,23 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Consommation réduite de la batterie. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Mauvaise phrase secrète pour la base de données No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! Mauvaise phrase secrète ! @@ -7455,11 +7562,19 @@ Les serveurs SimpleX ne peuvent pas voir votre profil. inconnu connection info + + unknown relays + No comment provided by engineer. + unknown status statut inconnu No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile mise à jour du profil de groupe @@ -7525,6 +7640,10 @@ Les serveurs SimpleX ne peuvent pas voir votre profil. semaines time unit + + when IP hidden + No comment provided by engineer. + yes oui diff --git a/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff b/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff index ad3148d891..bd8b71fe65 100644 --- a/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff +++ b/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff @@ -570,7 +570,7 @@ Accept connection request? - Kapcsolatfelvétel elfogadása? + Kapcsolódási kérelem elfogadása? No comment provided by engineer. @@ -705,22 +705,26 @@ Allow calls only if your contact allows them. - Hívások engedélyezése kizárólag abban az esetben, ha ismerőse is engedélyezi. + A hívások kezdeményezése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. No comment provided by engineer. Allow disappearing messages only if your contact allows it to you. - Eltűnő üzenetek engedélyezése kizárólag abban az esetben, ha ismerőse is engedélyezi az ön számára. + Az eltűnő üzenetek küldése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi az ön számára. + No comment provided by engineer. + + + Allow downgrade No comment provided by engineer. Allow irreversible message deletion only if your contact allows it to you. (24 hours) - Üzenet végleges törlésének engedélyezése kizárólag abban az esetben, ha ismerőse is engedélyezi. (24 óra) + Az üzenetek végleges törlése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. (24 óra) No comment provided by engineer. Allow message reactions only if your contact allows them. - Üzenetreakciók engedélyezése kizárólag abban az esetben, ha ismerőse is engedélyezi. + Az üzenetreakciók küldése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. No comment provided by engineer. @@ -735,7 +739,7 @@ Allow sending disappearing messages. - Eltűnő üzenetek küldésének engedélyezése. + Az eltűnő üzenetek küldése engedélyezve van. No comment provided by engineer. @@ -760,7 +764,7 @@ Allow voice messages only if your contact allows them. - Hangüzenetek küldésének engedélyezése kizárólag abban az esetben, ha ismerőse is engedélyezi. + A hangüzenetek küldése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. No comment provided by engineer. @@ -770,27 +774,27 @@ Allow your contacts adding message reactions. - Ismerősök általi üzenetreakciók hozzáadásának engedélyezése. + Az üzenetreakciók küldése engedélyezve van az ismerősei számára. No comment provided by engineer. Allow your contacts to call you. - Hívások engedélyezése ismerősök számára. + A hívások kezdeményezése engedélyezve van az ismerősei számára. No comment provided by engineer. Allow your contacts to irreversibly delete sent messages. (24 hours) - Elküldött üzenetek végleges törlésének engedélyezése az ismerősök számára. (24 óra) + Az elküldött üzenetek végleges törlése engedélyezve van az ismerősei számára. (24 óra) No comment provided by engineer. Allow your contacts to send disappearing messages. - Eltűnő üzenetek engedélyezése ismerősök számára. + Az eltűnő üzenetek küldésének engedélyezése az ismerősei számára. No comment provided by engineer. Allow your contacts to send voice messages. - Hangüzenetek küldésének engedélyezése ismerősök számára. + A hangüzenetek küldése engedélyezve van az ismerősei számára. No comment provided by engineer. @@ -808,6 +812,10 @@ A csatlakozás folyamatban van a csoporthoz! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay Mindig használjon átjátszó kiszolgálót @@ -905,12 +913,12 @@ Audio/video calls are prohibited. - A hang- és videóhívások le vannak tiltva. + A hívások kezdeményezése le van tiltva ebben a csevegésben. No comment provided by engineer. Authentication cancelled - Hitelesítés megszakítva + Hitelesítés visszavonva PIN entry @@ -935,7 +943,7 @@ Auto-accept contact requests - Ismerős jelölések automatikus elfogadása + Kapcsolódási kérelmek automatikus elfogadása No comment provided by engineer. @@ -995,7 +1003,7 @@ Block member for all? - Tag letiltása mindenki számára? + Mindenki számára letiltja ezt a tagot? No comment provided by engineer. @@ -1020,7 +1028,7 @@ Both you and your contact can make calls. - Mindkét fél tud hívásokat indítani. + Mindkét fél tud hívásokat kezdeményezni. No comment provided by engineer. @@ -1088,6 +1096,10 @@ Nem lehet fogadni a fájlt No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular Mobilhálózat @@ -1465,7 +1477,7 @@ Ez az egyszer használatos hivatkozása! Contacts can mark messages for deletion; you will be able to view them. - Az ismerősök törlésre jelölhetnek üzeneteket ; megtekintheti őket. + Az ismerősei törlésre jelölhetnek üzeneteket; ön majd meg tudja nézni azokat. No comment provided by engineer. @@ -1738,7 +1750,7 @@ Ez az egyszer használatos hivatkozása! Delete after - Törlés miután + Törlés ennyi idő után No comment provided by engineer. @@ -1865,7 +1877,7 @@ Ez a művelet nem vonható vissza! Delete messages after - Üzenetek törlése miután + Üzenetek törlése ennyi idő után No comment provided by engineer. @@ -1948,6 +1960,10 @@ Ez a művelet nem vonható vissza! Számítógépek No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop Fejlesztés @@ -1985,7 +2001,7 @@ Ez a művelet nem vonható vissza! Direct messages between members are prohibited in this group. - Ebben a csoportban tiltott a tagok közötti közvetlen üzenetek küldése. + A közvetlen üzenetek küldése a tagok között le van tiltva ebben a csoportban. No comment provided by engineer. @@ -2015,7 +2031,7 @@ Ez a művelet nem vonható vissza! Disappearing messages are prohibited in this chat. - Az eltűnő üzenetek le vannak tiltva ebben a csevegésben. + Az eltűnő üzenetek küldése le van tiltva ebben a csevegésben. No comment provided by engineer. @@ -2053,11 +2069,19 @@ Ez a művelet nem vonható vissza! Felfedezés helyi hálózaton keresztül No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. NE használja a SimpleX-et segélyhívásokhoz. No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later Későbbre halaszt @@ -2621,7 +2645,7 @@ Ez a művelet nem vonható vissza! Error: %@ Hiba: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2713,6 +2737,10 @@ Ez a művelet nem vonható vissza! Fájl: %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media Fájlok és média @@ -2818,6 +2846,16 @@ Ez a művelet nem vonható vissza! Továbbítva innen: No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop Megtalált számítógép @@ -3090,7 +3128,7 @@ Ez a művelet nem vonható vissza! If you enter your self-destruct passcode while opening the app: - Ha az alkalmazás megnyitásakor az önmegsemmisítő jelkódot megadásra kerül: + Ha az alkalmazás megnyitásakor megadja az önmegsemmisítő jelkódot: No comment provided by engineer. @@ -3337,12 +3375,12 @@ Ez a művelet nem vonható vissza! Irreversible message deletion is prohibited in this chat. - Ebben a csevegésben az üzenetek végleges törlése le van tiltva. + Az üzenetek végleges törlése le van tiltva ebben a csevegésben. No comment provided by engineer. Irreversible message deletion is prohibited in this group. - Ebben a csoportban az üzenetek végleges törlése le van tiltva. + Az üzenetek végleges törlése le van tiltva ebben a csoportban. No comment provided by engineer. @@ -3470,7 +3508,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Leave - Elhagy + Elhagyás No comment provided by engineer. @@ -3585,12 +3623,12 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Mark read - Megjelölés olvasottként + Olvasottként jelölés No comment provided by engineer. Mark verified - Ellenőrzöttként jelölve + Hitelesítés No comment provided by engineer. @@ -3633,6 +3671,10 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Üzenetkézbesítési bizonylatok! No comment provided by engineer. + + Message delivery warning + item status text + Message draft Üzenetvázlat @@ -3645,12 +3687,20 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Message reactions are prohibited in this chat. - Az üzenetreakciók ebben a csevegésben le vannak tiltva. + Az üzenetreakciók küldése le van tiltva ebben a csevegésben. No comment provided by engineer. Message reactions are prohibited in this group. - Ebben a csoportban az üzenetreakciók le vannak tiltva. + Az üzenetreakciók küldése le van tiltva ebben a csoportban. + No comment provided by engineer. + + + Message routing fallback + No comment provided by engineer. + + + Message routing mode No comment provided by engineer. @@ -3783,11 +3833,6 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Valószínűleg ez a kapcsolat törlésre került. item status description - - Most likely this contact has deleted the connection with you. - Valószínűleg ez az ismerős törölte önnel a kapcsolatot. - No comment provided by engineer. - Multiple chat profiles Több csevegőprofil @@ -3818,6 +3863,10 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Internetkapcsolat No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management Hálózatkezelés @@ -4079,7 +4128,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Only your contact can send disappearing messages. - Csak az ismerős tud eltűnő üzeneteket küldeni. + Csak az ismerőse tud eltűnő üzeneteket küldeni. No comment provided by engineer. @@ -4359,11 +4408,19 @@ Hiba: %@ Privát fájl nevek No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes Privát jegyzetek name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections Profil és kiszolgálókapcsolatok @@ -4401,7 +4458,7 @@ Hiba: %@ Prohibit audio/video calls. - Hang- és videóhívások tiltása. + A hívások kezdeményezése le van tiltva. No comment provided by engineer. @@ -4411,7 +4468,7 @@ Hiba: %@ Prohibit message reactions. - Üzenetreakciók tiltása. + Az üzenetreakciók küldése le van tiltva. No comment provided by engineer. @@ -4426,12 +4483,12 @@ Hiba: %@ Prohibit sending direct messages to members. - Közvetlen üzenetek küldésének letiltása a tagok számára. + A közvetlen üzenetek küldése le van tiltva a tagok között. No comment provided by engineer. Prohibit sending disappearing messages. - Eltűnő üzenetek küldésének letiltása. + Az eltűnő üzenetek küldése le van tiltva. No comment provided by engineer. @@ -4441,7 +4498,11 @@ Hiba: %@ Prohibit sending voice messages. - Hangüzenetek küldésének letiltása. + A hangüzenetek küldése le van tiltva. + No comment provided by engineer. + + + Protect IP address No comment provided by engineer. @@ -4554,11 +4615,6 @@ Hiba: %@ A fogadó cím egy másik kiszolgálóra változik. A címváltoztatás a feladó online állapotba kerülése után fejeződik be. No comment provided by engineer. - - Receiving concurrency - Egyidejű fogadás - No comment provided by engineer. - Receiving file will be stopped. A fájl fogadása leállt. @@ -4641,12 +4697,12 @@ Hiba: %@ Remove member - Tag eltávolítása + Eltávolítás No comment provided by engineer. Remove member? - Tag eltávolítása? + Biztosan eltávolítja? No comment provided by engineer. @@ -4911,7 +4967,7 @@ Hiba: %@ Scan code - Kód beolvasása + Beolvasás No comment provided by engineer. @@ -5019,6 +5075,14 @@ Hiba: %@ Élő üzenet küldése No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Értesítések küldése @@ -5051,7 +5115,7 @@ Hiba: %@ Sender cancelled file transfer. - A küldő megszakította a fájl átvitelt. + A fájl küldője visszavonta az átvitelt. No comment provided by engineer. @@ -5124,6 +5188,10 @@ Hiba: %@ Az elküldött üzenetek törlésre kerülnek a beállított idő után. No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password A kiszolgálónak engedélyre van szüksége a várólisták létrehozásához, ellenőrizze jelszavát @@ -5139,6 +5207,10 @@ Hiba: %@ Sikertelen kiszolgáló-teszt! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers Kiszolgálók @@ -5259,11 +5331,19 @@ Hiba: %@ Utolsó üzenetek megjelenítése No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview Előnézet megjelenítése No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Megjelenítés: @@ -5326,7 +5406,7 @@ Hiba: %@ SimpleX links are prohibited in this group. - A SimpleX hivatkozások küldése ebben a csoportban le van tiltva. + A SimpleX hivatkozások küldése le van tiltva ebben a csoportban. No comment provided by engineer. @@ -5586,6 +5666,10 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő. Az alkalmazás értesíteni fogja, amikor üzeneteket vagy kapcsolatfelvételi kéréseket kap – beállítások megnyitása az engedélyezéshez. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. Az adatbázis jelmondatának megváltoztatására tett kísérlet nem fejeződött be. @@ -5598,7 +5682,7 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő. The connection you accepted will be cancelled! - Az ön által elfogadott kapcsolat megszakad! + Az ön által elfogadott kapcsolat vissza lesz vonva! No comment provided by engineer. @@ -5771,6 +5855,10 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő. Az időzóna védelme érdekében a kép-/hangfájlok UTC-t használnak. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5863,11 +5951,6 @@ A funkció engedélyezése előtt a rendszer felszólítja a hitelesítés befej Tag feloldása? No comment provided by engineer. - - Unexpected error: %@ - Váratlan hiba: %@ - item status description - Unexpected migration state Váratlan átköltöztetési állapot @@ -5913,6 +5996,10 @@ A funkció engedélyezése előtt a rendszer felszólítja a hitelesítés befej Ismeretlen hiba No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. Hacsak nem az iOS hívási felületét használja, engedélyezze a Ne zavarjanak módot a megszakítások elkerülése érdekében. @@ -6060,6 +6147,14 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Csak helyi értesítések használata? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server Kiszolgáló használata @@ -6167,7 +6262,7 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Voice messages are prohibited in this chat. - A hangüzenetek le vannak tiltva ebben a csevegésben. + A hangüzenetek küldése le van tiltva ebben a csevegésben. No comment provided by engineer. @@ -6295,11 +6390,23 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Csökkentett akkumulátorhasználattal. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Téves adatbázis jelmondat No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! Téves jelmondat! @@ -6642,8 +6749,8 @@ Kapcsolódási kérés megismétlése? Your contact needs to be online for the connection to complete. You can cancel this connection and remove the contact (and try later with a new link). - Az ismerősnek online kell lennie ahhoz, hogy a kapcsolat létrejöjjön. -Megszakíthatja ezt a kapcsolatfelvételt és törölheti az ismerőst (ezt később ismét megpróbálhatja egy új hivatkozással). + Az ismerősének online kell lennie ahhoz, hogy a kapcsolat létrejöjjön. +Visszavonhatja ezt a kapcsolatfelvételt és törölheti az ismerőst (ezt később ismét megpróbálhatja egy új hivatkozással). No comment provided by engineer. @@ -6850,7 +6957,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. cancelled %@ - %@ törölve + %@ visszavonva feature offered item @@ -6965,7 +7072,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. creator - szerző + készítő No comment provided by engineer. @@ -7185,12 +7292,12 @@ A SimpleX kiszolgálók nem látjhatják profilját. invited - meghívta + meghíva No comment provided by engineer. invited %@ - meghívta %@-t + meghívta őt: %@ rcv group event chat item @@ -7200,7 +7307,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. invited via your group link - meghívta a csoport hivatkozásán keresztül + meghíva az ön csoport hivatkozásán keresztül rcv group event chat item @@ -7455,14 +7562,22 @@ A SimpleX kiszolgálók nem látjhatják profilját. ismeretlen connection info + + unknown relays + No comment provided by engineer. + unknown status ismeretlen státusz No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile - módosított csoport profil + frissítette a csoport profilját rcv group event chat item @@ -7507,7 +7622,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. waiting for answer… - várakozás válaszra… + várakozás a válaszra… No comment provided by engineer. @@ -7525,6 +7640,10 @@ A SimpleX kiszolgálók nem látjhatják profilját. hét time unit + + when IP hidden + No comment provided by engineer. + yes igen diff --git a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff index a5fe0ec830..dda9effd4c 100644 --- a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff +++ b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff @@ -713,6 +713,10 @@ Consenti i messaggi a tempo solo se il contatto li consente a te. No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) Consenti l'eliminazione irreversibile dei messaggi solo se il contatto la consente a te. (24 ore) @@ -808,6 +812,10 @@ Già in ingresso nel gruppo! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay Connetti via relay @@ -1088,6 +1096,10 @@ Impossibile ricevere il file No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular Mobile @@ -1948,6 +1960,10 @@ Non è reversibile! Dispositivi desktop No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop Sviluppa @@ -2053,11 +2069,19 @@ Non è reversibile! Individua via rete locale No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. NON usare SimpleX per chiamate di emergenza. No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later Fallo dopo @@ -2621,7 +2645,7 @@ Non è reversibile! Error: %@ Errore: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2713,6 +2737,10 @@ Non è reversibile! File: %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media File e multimediali @@ -2818,6 +2846,16 @@ Non è reversibile! Inoltrato da No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop Desktop trovato @@ -3633,6 +3671,10 @@ Questo è il tuo link per il gruppo %@! Ricevute di consegna dei messaggi! No comment provided by engineer. + + Message delivery warning + item status text + Message draft Bozza dei messaggi @@ -3653,6 +3695,14 @@ Questo è il tuo link per il gruppo %@! Le reazioni ai messaggi sono vietate in questo gruppo. No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. La fonte del messaggio resta privata. @@ -3783,11 +3833,6 @@ Questo è il tuo link per il gruppo %@! Probabilmente questa connessione è stata eliminata. item status description - - Most likely this contact has deleted the connection with you. - Probabilmente questo contatto ha eliminato la connessione con te. - No comment provided by engineer. - Multiple chat profiles Profili di chat multipli @@ -3818,6 +3863,10 @@ Questo è il tuo link per il gruppo %@! Connessione di rete No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management Gestione della rete @@ -4359,11 +4408,19 @@ Errore: %@ Nomi di file privati No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes Note private name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections Profilo e connessioni al server @@ -4444,6 +4501,10 @@ Errore: %@ Proibisci l'invio di messaggi vocali. No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen Proteggi la schermata dell'app @@ -4554,11 +4615,6 @@ Errore: %@ L'indirizzo di ricezione verrà cambiato in un server diverso. La modifica dell'indirizzo verrà completata dopo che il mittente sarà in linea. No comment provided by engineer. - - Receiving concurrency - Ricezione concomitanza - No comment provided by engineer. - Receiving file will be stopped. La ricezione del file verrà interrotta. @@ -5019,6 +5075,14 @@ Errore: %@ Invia messaggio in diretta No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Invia notifiche @@ -5124,6 +5188,10 @@ Errore: %@ I messaggi inviati verranno eliminati dopo il tempo impostato. No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password Il server richiede l'autorizzazione di creare code, controlla la password @@ -5139,6 +5207,10 @@ Errore: %@ Test del server fallito! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers Server @@ -5259,11 +5331,19 @@ Errore: %@ Mostra ultimi messaggi No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview Mostra anteprima No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Mostra: @@ -5586,6 +5666,10 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.L'app può avvisarti quando ricevi messaggi o richieste di contatto: apri le impostazioni per attivare. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. Il tentativo di cambiare la password del database non è stato completato. @@ -5771,6 +5855,10 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.Per proteggere il fuso orario, i file immagine/vocali usano UTC. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5863,11 +5951,6 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio Sbloccare il membro? No comment provided by engineer. - - Unexpected error: %@ - Errore imprevisto: % @ - item status description - Unexpected migration state Stato di migrazione imprevisto @@ -5913,6 +5996,10 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio Errore sconosciuto No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. A meno che non utilizzi l'interfaccia di chiamata iOS, attiva la modalità Non disturbare per evitare interruzioni. @@ -6060,6 +6147,14 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e Usare solo notifiche locali? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server Usa il server @@ -6295,11 +6390,23 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e Con consumo di batteria ridotto. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Password del database sbagliata No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! Password sbagliata! @@ -7455,11 +7562,19 @@ I server di SimpleX non possono vedere il tuo profilo. sconosciuto connection info + + unknown relays + No comment provided by engineer. + unknown status stato sconosciuto No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile ha aggiornato il profilo del gruppo @@ -7525,6 +7640,10 @@ I server di SimpleX non possono vedere il tuo profilo. settimane time unit + + when IP hidden + No comment provided by engineer. + yes diff --git a/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff b/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff index 3f32998707..35afbf2827 100644 --- a/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff +++ b/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff @@ -703,6 +703,10 @@ 連絡先が許可している場合のみ消えるメッセージを許可する。 No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) 送信相手も永久メッセージ削除を許可する時のみに許可する。 @@ -798,6 +802,10 @@ すでにグループに参加しています! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay 常にリレーを経由する @@ -1064,6 +1072,10 @@ ファイル受信ができません No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular No comment provided by engineer. @@ -1887,6 +1899,10 @@ This cannot be undone! Desktop devices No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop 開発 @@ -1990,11 +2006,19 @@ This cannot be undone! Discover via local network No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. 緊急通報にSimpleXを使用しないでください。 No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later 後で行う @@ -2534,7 +2558,7 @@ This cannot be undone! Error: %@ エラー : %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2623,6 +2647,10 @@ This cannot be undone! ファイル: %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media ファイルとメディア @@ -2721,6 +2749,16 @@ This cannot be undone! Forwarded from No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop No comment provided by engineer. @@ -3504,6 +3542,10 @@ This is your link for group %@! Message delivery receipts! No comment provided by engineer. + + Message delivery warning + item status text + Message draft メッセージの下書き @@ -3524,6 +3566,14 @@ This is your link for group %@! このグループではメッセージへのリアクションは禁止されています。 No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. No comment provided by engineer. @@ -3641,11 +3691,6 @@ This is your link for group %@! おそらく、この接続は削除されています。 item status description - - Most likely this contact has deleted the connection with you. - 恐らくこの連絡先があなたとの接続を削除しました。 - No comment provided by engineer. - Multiple chat profiles 複数チャットのプロフィール @@ -3675,6 +3720,10 @@ This is your link for group %@! Network connection No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management No comment provided by engineer. @@ -4195,10 +4244,18 @@ Error: %@ プライベートなファイル名 No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections プロフィールとサーバ接続 @@ -4275,6 +4332,10 @@ Error: %@ 音声メッセージを使用禁止にする。 No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen アプリ画面を守る @@ -4381,10 +4442,6 @@ Error: %@ 開発中の機能です!相手のクライアントが4.2でなければ機能しません。アドレス変更が完了すると、会話にメッセージが出ます。連絡相手 (またはグループのメンバー) からメッセージを受信できないかをご確認ください。 No comment provided by engineer. - - Receiving concurrency - No comment provided by engineer. - Receiving file will be stopped. ファイルの受信を停止します。 @@ -4829,6 +4886,14 @@ Error: %@ ライブメッセージを送信 No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications 通知を送信する @@ -4926,6 +4991,10 @@ Error: %@ 一定時間が経ったら送信されたメッセージが削除されます。 No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password キューを作成するにはサーバーの認証が必要です。パスワードを確認してください @@ -4941,6 +5010,10 @@ Error: %@ サーバテスト失敗! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers サーバ @@ -5056,11 +5129,19 @@ Error: %@ 最新のメッセージを表示 No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview プレビューを表示 No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: 表示する: @@ -5374,6 +5455,10 @@ It can happen because of some bug or when the connection is compromised.アプリは、メッセージや連絡先のリクエストを受信したときに通知することができます - 設定を開いて有効にしてください。 No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. データベースのパスフレーズ変更が完了してません。 @@ -5549,6 +5634,10 @@ It can happen because of some bug or when the connection is compromised.時間帯を漏らさないために、画像と音声ファイルはUTCを使います。 No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5634,11 +5723,6 @@ You will be prompted to complete authentication before this feature is enabled.< Unblock member? No comment provided by engineer. - - Unexpected error: %@ - 予期しないエラー: %@ - item status description - Unexpected migration state 予期しない移行状態 @@ -5684,6 +5768,10 @@ You will be prompted to complete authentication before this feature is enabled.< 不明なエラー No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. iOS 通話インターフェイスを使用しない場合は、中断を避けるために「おやすみモード」を有効にしてください。 @@ -5824,6 +5912,14 @@ To connect, please ask your contact to create another connection link and check Use only local notifications? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server サーバを使う @@ -6041,11 +6137,23 @@ To connect, please ask your contact to create another connection link and check With reduced battery usage. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase データベースのパスフレーズが違います No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! パスフレーズが違います! @@ -7160,10 +7268,18 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 不明 connection info + + unknown relays + No comment provided by engineer. + unknown status No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile グループプロフィールを更新しました @@ -7227,6 +7343,10 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 time unit + + when IP hidden + No comment provided by engineer. + yes はい diff --git a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff index c5a9ba4ea8..7e3775188b 100644 --- a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff +++ b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff @@ -713,6 +713,10 @@ Sta verdwijnende berichten alleen toe als uw contact dit toestaat. No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) Sta het onomkeerbaar verwijderen van berichten alleen toe als uw contact dit toestaat. (24 uur) @@ -808,6 +812,10 @@ Al lid van de groep! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay Altijd relay gebruiken @@ -1088,6 +1096,10 @@ Kan bestand niet ontvangen No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular Mobiel @@ -1948,6 +1960,10 @@ Dit kan niet ongedaan gemaakt worden! Desktop apparaten No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop Ontwikkelen @@ -2053,11 +2069,19 @@ Dit kan niet ongedaan gemaakt worden! Ontdek via het lokale netwerk No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. Gebruik SimpleX NIET voor noodoproepen. No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later Doe het later @@ -2621,7 +2645,7 @@ Dit kan niet ongedaan gemaakt worden! Error: %@ Fout: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2713,6 +2737,10 @@ Dit kan niet ongedaan gemaakt worden! Bestand: %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media Bestanden en media @@ -2818,6 +2846,16 @@ Dit kan niet ongedaan gemaakt worden! Doorgestuurd vanuit No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop Desktop gevonden @@ -3633,6 +3671,10 @@ Dit is jouw link voor groep %@! Ontvangst bevestiging voor berichten! No comment provided by engineer. + + Message delivery warning + item status text + Message draft Concept bericht @@ -3653,6 +3695,14 @@ Dit is jouw link voor groep %@! Reacties op berichten zijn verboden in deze groep. No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. Berichtbron blijft privé. @@ -3783,11 +3833,6 @@ Dit is jouw link voor groep %@! Hoogstwaarschijnlijk is deze verbinding verwijderd. item status description - - Most likely this contact has deleted the connection with you. - Hoogstwaarschijnlijk heeft dit contact de verbinding met jou verwijderd. - No comment provided by engineer. - Multiple chat profiles Meerdere chat profielen @@ -3818,6 +3863,10 @@ Dit is jouw link voor groep %@! Netwerkverbinding No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management Netwerkbeheer @@ -4359,11 +4408,19 @@ Fout: %@ Privé bestandsnamen No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes Privé notities name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections Profiel- en serververbindingen @@ -4444,6 +4501,10 @@ Fout: %@ Verbieden het verzenden van spraak berichten. No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen App scherm verbergen @@ -4554,11 +4615,6 @@ Fout: %@ Het ontvangstadres wordt gewijzigd naar een andere server. Adres wijziging wordt voltooid nadat de afzender online is. No comment provided by engineer. - - Receiving concurrency - Gelijktijdig ontvangen - No comment provided by engineer. - Receiving file will be stopped. Het ontvangen van het bestand wordt gestopt. @@ -5019,6 +5075,14 @@ Fout: %@ Stuur een livebericht No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Meldingen verzenden @@ -5124,6 +5188,10 @@ Fout: %@ Verzonden berichten worden na ingestelde tijd verwijderd. No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password Server vereist autorisatie om wachtrijen te maken, controleer wachtwoord @@ -5139,6 +5207,10 @@ Fout: %@ Servertest mislukt! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers Servers @@ -5259,11 +5331,19 @@ Fout: %@ Laat laatste berichten zien No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview Toon voorbeeld No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Toon: @@ -5586,6 +5666,10 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast. De app kan u op de hoogte stellen wanneer u berichten of contact verzoeken ontvangt - open de instellingen om dit in te schakelen. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. De poging om het wachtwoord van de database te wijzigen is niet voltooid. @@ -5771,6 +5855,10 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast. Om de tijdzone te beschermen, gebruiken afbeeldings-/spraakbestanden UTC. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5863,11 +5951,6 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc Lid deblokkeren? No comment provided by engineer. - - Unexpected error: %@ - Onverwachte fout: %@ - item status description - Unexpected migration state Onverwachte migratiestatus @@ -5913,6 +5996,10 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc Onbekende fout No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. Schakel de modus Niet storen in om onderbrekingen te voorkomen, tenzij u de iOS-oproepinterface gebruikt. @@ -6060,6 +6147,14 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak Alleen lokale meldingen gebruiken? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server Gebruik server @@ -6295,11 +6390,23 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak Met verminderd batterijgebruik. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Verkeerd wachtwoord voor de database No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! Verkeerd wachtwoord! @@ -7455,11 +7562,19 @@ SimpleX servers kunnen uw profiel niet zien. onbekend connection info + + unknown relays + No comment provided by engineer. + unknown status onbekende status No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile bijgewerkt groep profiel @@ -7525,6 +7640,10 @@ SimpleX servers kunnen uw profiel niet zien. weken time unit + + when IP hidden + No comment provided by engineer. + yes Ja diff --git a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff index d71bd5843a..72add6a8ad 100644 --- a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff +++ b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff @@ -713,6 +713,10 @@ Zezwól na znikające wiadomości tylko wtedy, gdy Twój kontakt Ci na to pozwoli. No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) Zezwalaj na nieodwracalne usuwanie wiadomości tylko wtedy, gdy Twój kontakt Ci na to pozwoli. (24 godziny) @@ -808,6 +812,10 @@ Już dołączono do grupy! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay Zawsze używaj przekaźnika @@ -1088,6 +1096,10 @@ Nie można odebrać pliku No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular Sieć komórkowa @@ -1948,6 +1960,10 @@ To nie może być cofnięte! Urządzenia komputerowe No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop Deweloperskie @@ -2053,11 +2069,19 @@ To nie może być cofnięte! Odkryj przez sieć lokalną No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. NIE używaj SimpleX do połączeń alarmowych. No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later Zrób to później @@ -2621,7 +2645,7 @@ To nie może być cofnięte! Error: %@ Błąd: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2713,6 +2737,10 @@ To nie może być cofnięte! Plik: %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media Pliki i media @@ -2818,6 +2846,16 @@ To nie może być cofnięte! Przekazane dalej od No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop Znaleziono komputer @@ -3633,6 +3671,10 @@ To jest twój link do grupy %@! Potwierdzenia dostarczenia wiadomości! No comment provided by engineer. + + Message delivery warning + item status text + Message draft Wersja robocza wiadomości @@ -3653,6 +3695,14 @@ To jest twój link do grupy %@! Reakcje wiadomości są zabronione w tej grupie. No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. Źródło wiadomości pozostaje prywatne. @@ -3783,11 +3833,6 @@ To jest twój link do grupy %@! Najprawdopodobniej to połączenie jest usunięte. item status description - - Most likely this contact has deleted the connection with you. - Najprawdopodobniej ten kontakt usunął połączenie z Tobą. - No comment provided by engineer. - Multiple chat profiles Wiele profili czatu @@ -3818,6 +3863,10 @@ To jest twój link do grupy %@! Połączenie z siecią No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management Zarządzenie sieciowe @@ -4359,11 +4408,19 @@ Błąd: %@ Prywatne nazwy plików No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes Prywatne notatki name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections Profil i połączenia z serwerem @@ -4444,6 +4501,10 @@ Błąd: %@ Zabroń wysyłania wiadomości głosowych. No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen Chroń ekran aplikacji @@ -4554,11 +4615,6 @@ Błąd: %@ Adres odbiorczy zostanie zmieniony na inny serwer. Zmiana adresu zostanie zakończona gdy nadawca będzie online. No comment provided by engineer. - - Receiving concurrency - Konkurencyjne odbieranie - No comment provided by engineer. - Receiving file will be stopped. Odbieranie pliku zostanie przerwane. @@ -5019,6 +5075,14 @@ Błąd: %@ Wyślij wiadomość na żywo No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Wyślij powiadomienia @@ -5124,6 +5188,10 @@ Błąd: %@ Wysłane wiadomości zostaną usunięte po ustawionym czasie. No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password Serwer wymaga autoryzacji do tworzenia kolejek, sprawdź hasło @@ -5139,6 +5207,10 @@ Błąd: %@ Test serwera nie powiódł się! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers Serwery @@ -5259,11 +5331,19 @@ Błąd: %@ Pokaż ostatnie wiadomości No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview Pokaż podgląd No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Pokaż: @@ -5586,6 +5666,10 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom Aplikacja może powiadamiać Cię, gdy otrzymujesz wiadomości lub prośby o kontakt — otwórz ustawienia, aby włączyć. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. Próba zmiany hasła bazy danych nie została zakończona. @@ -5771,6 +5855,10 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom Aby chronić strefę czasową, pliki obrazów/głosów używają UTC. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5863,11 +5951,6 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.Odblokować członka? No comment provided by engineer. - - Unexpected error: %@ - Nieoczekiwany błąd: %@ - item status description - Unexpected migration state Nieoczekiwany stan migracji @@ -5913,6 +5996,10 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.Nieznany błąd No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. O ile nie korzystasz z interfejsu połączeń systemu iOS, włącz tryb Nie przeszkadzać, aby uniknąć przerywania. @@ -6060,6 +6147,14 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Używać tylko lokalnych powiadomień? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server Użyj serwera @@ -6295,11 +6390,23 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Ze zmniejszonym zużyciem baterii. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Nieprawidłowe hasło bazy danych No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! Nieprawidłowe hasło! @@ -7455,11 +7562,19 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. nieznany connection info + + unknown relays + No comment provided by engineer. + unknown status nieznany status No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile zaktualizowano profil grupy @@ -7525,6 +7640,10 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. tygodnie time unit + + when IP hidden + No comment provided by engineer. + yes tak diff --git a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff index ba1ac7a929..c0a9df6b88 100644 --- a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff +++ b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff @@ -713,6 +713,10 @@ Разрешить исчезающие сообщения, только если Ваш контакт разрешает их Вам. No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) Разрешить необратимое удаление сообщений, только если Ваш контакт разрешает это Вам. (24 часа) @@ -808,6 +812,10 @@ Вступление в группу уже начато! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay Всегда соединяться через relay @@ -1088,6 +1096,10 @@ Невозможно получить файл No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular Мобильная сеть @@ -1948,6 +1960,10 @@ This cannot be undone! Компьютеры No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop Для разработчиков @@ -2053,11 +2069,19 @@ This cannot be undone! Обнаружение по локальной сети No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. Не используйте SimpleX для экстренных звонков. No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later Отложить @@ -2621,7 +2645,7 @@ This cannot be undone! Error: %@ Ошибка: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2713,6 +2737,10 @@ This cannot be undone! Файл: %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media Файлы и медиа @@ -2818,6 +2846,16 @@ This cannot be undone! Переслано из No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop Компьютер найден @@ -3633,6 +3671,10 @@ This is your link for group %@! Отчеты о доставке сообщений! No comment provided by engineer. + + Message delivery warning + item status text + Message draft Черновик сообщения @@ -3653,6 +3695,14 @@ This is your link for group %@! Реакции на сообщения запрещены в этой группе. No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. Источник сообщения остаётся конфиденциальным. @@ -3783,11 +3833,6 @@ This is your link for group %@! Скорее всего, соединение удалено. item status description - - Most likely this contact has deleted the connection with you. - Скорее всего, этот контакт удалил соединение с Вами. - No comment provided by engineer. - Multiple chat profiles Много профилей чата @@ -3818,6 +3863,10 @@ This is your link for group %@! Интернет-соединение No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management Статус сети @@ -4359,11 +4408,19 @@ Error: %@ Защищенные имена файлов No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes Личные заметки name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections Профиль и соединения на сервере @@ -4444,6 +4501,10 @@ Error: %@ Запретить отправлять голосовые сообщений. No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen Защитить экран приложения @@ -4554,11 +4615,6 @@ Error: %@ Адрес получения сообщений будет перемещён на другой сервер. Изменение адреса завершится после того как отправитель будет онлайн. No comment provided by engineer. - - Receiving concurrency - Одновременный приём - No comment provided by engineer. - Receiving file will be stopped. Приём файла будет прекращён. @@ -5019,6 +5075,14 @@ Error: %@ Отправить живое сообщение No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Отправлять уведомления @@ -5124,6 +5188,10 @@ Error: %@ Отправленные сообщения будут удалены через заданное время. No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password Сервер требует авторизации для создания очередей, проверьте пароль @@ -5139,6 +5207,10 @@ Error: %@ Ошибка теста сервера! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers Серверы @@ -5259,11 +5331,19 @@ Error: %@ Показывать последние сообщения No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview Показывать уведомления No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Показать: @@ -5586,6 +5666,10 @@ It can happen because of some bug or when the connection is compromised.Приложение может посылать Вам уведомления о сообщениях и запросах на соединение - уведомления можно включить в Настройках. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. Попытка поменять пароль базы данных не была завершена. @@ -5771,6 +5855,10 @@ It can happen because of some bug or when the connection is compromised.Чтобы защитить Ваш часовой пояс, файлы картинок и голосовых сообщений используют UTC. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5863,11 +5951,6 @@ You will be prompted to complete authentication before this feature is enabled.< Разблокировать члена группы? No comment provided by engineer. - - Unexpected error: %@ - Неожиданная ошибка: %@ - item status description - Unexpected migration state Неожиданная ошибка при перемещении данных чата @@ -5913,6 +5996,10 @@ You will be prompted to complete authentication before this feature is enabled.< Неизвестная ошибка No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. Если Вы не используете интерфейс iOS, включите режим Не отвлекать, чтобы звонок не прерывался. @@ -6060,6 +6147,14 @@ To connect, please ask your contact to create another connection link and check Использовать только локальные нотификации? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server Использовать сервер @@ -6295,11 +6390,23 @@ To connect, please ask your contact to create another connection link and check С уменьшенным потреблением батареи. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Неправильный пароль базы данных No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! Неправильный пароль! @@ -7455,11 +7562,19 @@ SimpleX серверы не могут получить доступ к Ваше неизвестно connection info + + unknown relays + No comment provided by engineer. + unknown status неизвестный статус No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile обновил(а) профиль группы @@ -7525,6 +7640,10 @@ SimpleX серверы не могут получить доступ к Ваше недель time unit + + when IP hidden + No comment provided by engineer. + yes да diff --git a/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff b/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff index 1f62fad60f..c2a2d47bdc 100644 --- a/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff +++ b/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff @@ -677,6 +677,10 @@ อนุญาตให้ข้อความที่หายไปเฉพาะในกรณีที่ผู้ติดต่อของคุณอนุญาตเท่านั้น. No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) อนุญาตให้ลบข้อความแบบถาวรเฉพาะในกรณีที่ผู้ติดต่อของคุณอนุญาตให้คุณเท่านั้น @@ -769,6 +773,10 @@ Already joining the group! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay ใช้รีเลย์เสมอ @@ -1032,6 +1040,10 @@ ไม่สามารถรับไฟล์ได้ No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular No comment provided by engineer. @@ -1851,6 +1863,10 @@ This cannot be undone! Desktop devices No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop พัฒนา @@ -1953,11 +1969,19 @@ This cannot be undone! Discover via local network No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. อย่าใช้ SimpleX สําหรับการโทรฉุกเฉิน No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later ทำในภายหลัง @@ -2494,7 +2518,7 @@ This cannot be undone! Error: %@ ข้อผิดพลาด: % @ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2583,6 +2607,10 @@ This cannot be undone! ไฟล์: % @ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media ไฟล์และสื่อ @@ -2681,6 +2709,16 @@ This cannot be undone! Forwarded from No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop No comment provided by engineer. @@ -3463,6 +3501,10 @@ This is your link for group %@! ใบเสร็จการส่งข้อความ! No comment provided by engineer. + + Message delivery warning + item status text + Message draft ร่างข้อความ @@ -3483,6 +3525,14 @@ This is your link for group %@! ปฏิกิริยาบนข้อความเป็นสิ่งต้องห้ามในกลุ่มนี้ No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. No comment provided by engineer. @@ -3599,11 +3649,6 @@ This is your link for group %@! Most likely this connection is deleted. item status description - - Most likely this contact has deleted the connection with you. - เป็นไปได้มากว่าผู้ติดต่อนี้ได้ลบการเชื่อมต่อกับคุณ - No comment provided by engineer. - Multiple chat profiles โปรไฟล์การแชทหลายรายการ @@ -3633,6 +3678,10 @@ This is your link for group %@! Network connection No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management No comment provided by engineer. @@ -4150,10 +4199,18 @@ Error: %@ ชื่อไฟล์ส่วนตัว No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections การเชื่อมต่อโปรไฟล์และเซิร์ฟเวอร์ @@ -4230,6 +4287,10 @@ Error: %@ ห้ามส่งข้อความเสียง No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen ปกป้องหน้าจอแอป @@ -4336,10 +4397,6 @@ Error: %@ ที่อยู่ผู้รับจะถูกเปลี่ยนเป็นเซิร์ฟเวอร์อื่น การเปลี่ยนแปลงที่อยู่จะเสร็จสมบูรณ์หลังจากที่ผู้ส่งออนไลน์ No comment provided by engineer. - - Receiving concurrency - No comment provided by engineer. - Receiving file will be stopped. การรับไฟล์จะหยุดลง @@ -4783,6 +4840,14 @@ Error: %@ ส่งข้อความสด No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications ส่งการแจ้งเตือน @@ -4885,6 +4950,10 @@ Error: %@ ข้อความที่ส่งจะถูกลบหลังเกินเวลาที่กําหนด No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password เซิร์ฟเวอร์ต้องการการอนุญาตในการสร้างคิว โปรดตรวจสอบรหัสผ่าน @@ -4900,6 +4969,10 @@ Error: %@ การทดสอบเซิร์ฟเวอร์ล้มเหลว! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers เซิร์ฟเวอร์ @@ -5014,11 +5087,19 @@ Error: %@ Show last messages No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview แสดงตัวอย่าง No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: แสดง: @@ -5331,6 +5412,10 @@ It can happen because of some bug or when the connection is compromised.แอปสามารถแจ้งให้คุณทราบเมื่อคุณได้รับข้อความหรือคำขอติดต่อ - โปรดเปิดการตั้งค่าเพื่อเปิดใช้งาน No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. ความพยายามในการเปลี่ยนรหัสผ่านของฐานข้อมูลไม่เสร็จสมบูรณ์ @@ -5505,6 +5590,10 @@ It can happen because of some bug or when the connection is compromised.ไฟล์ภาพ/เสียงใช้ UTC เพื่อป้องกันเขตเวลา No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5590,11 +5679,6 @@ You will be prompted to complete authentication before this feature is enabled.< Unblock member? No comment provided by engineer. - - Unexpected error: %@ - ข้อผิดพลาดที่ไม่คาดคิด: %@ - item status description - Unexpected migration state สถานะการย้ายข้อมูลที่ไม่คาดคิด @@ -5640,6 +5724,10 @@ You will be prompted to complete authentication before this feature is enabled.< ข้อผิดพลาดที่ไม่รู้จัก No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. ยกเว้นกรณีที่คุณใช้อินเทอร์เฟซการโทรของ iOS ให้เปิดใช้งานโหมดห้ามรบกวนเพื่อหลีกเลี่ยงการรบกวน @@ -5778,6 +5866,14 @@ To connect, please ask your contact to create another connection link and check Use only local notifications? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server ใช้เซิร์ฟเวอร์ @@ -5995,11 +6091,23 @@ To connect, please ask your contact to create another connection link and check With reduced battery usage. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase รหัสผ่านฐานข้อมูลไม่ถูกต้อง No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! รหัสผ่านผิด! @@ -7110,10 +7218,18 @@ SimpleX servers cannot see your profile. ไม่ทราบ connection info + + unknown relays + No comment provided by engineer. + unknown status No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile อัปเดตโปรไฟล์กลุ่มแล้ว @@ -7177,6 +7293,10 @@ SimpleX servers cannot see your profile. สัปดาห์ time unit + + when IP hidden + No comment provided by engineer. + yes ใช่ diff --git a/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff index df5076fb07..f0954e750f 100644 --- a/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff +++ b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff @@ -713,6 +713,10 @@ Eğer kişide izin verirse kaybolan mesajlara izin ver. No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) Konuştuğun kişi, kalıcı olarak silinebilen mesajlara izin veriyorsa sen de ver. (24 saat içinde) @@ -808,6 +812,10 @@ Zaten gruba bağlanılıyor! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay Her zaman yönlendirici kullan @@ -1088,6 +1096,10 @@ Dosya alınamıyor No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular Hücresel Veri @@ -1948,6 +1960,10 @@ Bu geri alınamaz! Bilgisayar cihazları No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop Geliştir @@ -2053,11 +2069,19 @@ Bu geri alınamaz! Yerel ağ aracılığıyla keşfet No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. Acil aramalar için SimpleX'i KULLANMAYIN. No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later Sonra yap @@ -2621,7 +2645,7 @@ Bu geri alınamaz! Error: %@ Hata: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2713,6 +2737,10 @@ Bu geri alınamaz! Dosya: %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media Dosyalar & medya @@ -2818,6 +2846,16 @@ Bu geri alınamaz! Şuradan iletildi No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop Bilgisayar bulundu @@ -3633,6 +3671,10 @@ Bu senin grup için bağlantın %@! Mesaj alındı bilgisi! No comment provided by engineer. + + Message delivery warning + item status text + Message draft Mesaj taslağı @@ -3653,6 +3695,14 @@ Bu senin grup için bağlantın %@! Mesaj tepkileri bu grupta yasaklandı. No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. Mesaj kaynağı gizli kalır. @@ -3783,11 +3833,6 @@ Bu senin grup için bağlantın %@! Büyük ihtimalle bu bağlantı silinmiş. item status description - - Most likely this contact has deleted the connection with you. - Büyük ihtimalle bu kişi seninle bağlantını sildi. - No comment provided by engineer. - Multiple chat profiles Çoklu sohbet profili @@ -3818,6 +3863,10 @@ Bu senin grup için bağlantın %@! Ağ bağlantısı No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management Ağ yönetimi @@ -4359,11 +4408,19 @@ Hata: %@ Gizli dosya adları No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes Gizli notlar name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections Profil ve sunucu bağlantıları @@ -4444,6 +4501,10 @@ Hata: %@ Sesli mesajların gönderimini yasakla. No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen Uygulama ekranını koru @@ -4554,11 +4615,6 @@ Hata: %@ Alıcı adresi farklı bir sunucuya değiştirilecektir. Gönderici çevrimiçi olduktan sonra adres değişikliği tamamlanacaktır. No comment provided by engineer. - - Receiving concurrency - Eşzamanlılık alınıyor - No comment provided by engineer. - Receiving file will be stopped. Dosya alımı durdurulacaktır. @@ -5019,6 +5075,14 @@ Hata: %@ Canlı mesaj gönder No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Bildirimler gönder @@ -5124,6 +5188,10 @@ Hata: %@ Gönderilen mesajlar ayarlanan süreden sonra silinecektir. No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password Sunucunun sıra oluşturması için yetki gereklidir, şifreyi kontrol edin @@ -5139,6 +5207,10 @@ Hata: %@ Sunucu testinde hata oluştu! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers Sunucular @@ -5259,11 +5331,19 @@ Hata: %@ Son mesajları göster No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview Ön gösterimi göser No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Göster: @@ -5586,6 +5666,10 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir. Uygulama, mesaj veya iletişim isteği aldığınızda sizi bilgilendirebilir - etkinleştirmek için lütfen ayarları açın. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. Veritabanı parolasını değiştirme girişimi tamamlanmadı. @@ -5771,6 +5855,10 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir. Zaman bölgesini korumak için,fotoğraf/ses dosyaları UTC kullanır. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5863,11 +5951,6 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec Üyenin engeli kaldırılsın mı? No comment provided by engineer. - - Unexpected error: %@ - Beklenmeyen hata: %@ - item status description - Unexpected migration state Beklenmeyen geçiş durumu @@ -5913,6 +5996,10 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec Bilinmeyen hata No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. iOS arama arayüzünü kullanmadığınız sürece, kesintileri önlemek için Rahatsız Etmeyin modunu etkinleştirin. @@ -6060,6 +6147,14 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Sadece yerel bildirimler kullanılsın mı? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server Sunucu kullan @@ -6295,11 +6390,23 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Azaltılmış pil kullanımı ile birlikte. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Yanlış veritabanı parolası No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! Yanlış parola! @@ -7455,11 +7562,19 @@ SimpleX sunucuları profilinizi göremez. bilinmeyen connection info + + unknown relays + No comment provided by engineer. + unknown status bilinmeyen durum No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile grup profili güncellendi @@ -7525,6 +7640,10 @@ SimpleX sunucuları profilinizi göremez. haftalar time unit + + when IP hidden + No comment provided by engineer. + yes evet diff --git a/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff b/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff index 1ed1f5ffd6..80686b6f5a 100644 --- a/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff +++ b/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff @@ -713,6 +713,10 @@ Дозволяйте зникати повідомленням, тільки якщо контакт дозволяє вам це робити. No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) Дозволяйте безповоротне видалення повідомлень, тільки якщо контакт дозволяє вам це зробити. (24 години) @@ -807,6 +811,10 @@ Вже приєднуємося до групи! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay Завжди використовуйте реле @@ -1087,6 +1095,10 @@ Не вдається отримати файл No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular No comment provided by engineer. @@ -1946,6 +1958,10 @@ This cannot be undone! Настільні пристрої No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop Розробник @@ -2051,11 +2067,19 @@ This cannot be undone! Відкриття через локальну мережу No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. НЕ використовуйте SimpleX для екстрених викликів. No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later Зробіть це пізніше @@ -2617,7 +2641,7 @@ This cannot be undone! Error: %@ Помилка: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2709,6 +2733,10 @@ This cannot be undone! Файл: %@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media Файли та медіа @@ -2809,6 +2837,16 @@ This cannot be undone! Forwarded from No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop Знайдено робочий стіл @@ -3622,6 +3660,10 @@ This is your link for group %@! Підтвердження доставки повідомлення! No comment provided by engineer. + + Message delivery warning + item status text + Message draft Чернетка повідомлення @@ -3642,6 +3684,14 @@ This is your link for group %@! Реакції на повідомлення в цій групі заборонені. No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. No comment provided by engineer. @@ -3770,11 +3820,6 @@ This is your link for group %@! Швидше за все, це з'єднання видалено. item status description - - Most likely this contact has deleted the connection with you. - Швидше за все, цей контакт видалив зв'язок з вами. - No comment provided by engineer. - Multiple chat profiles Кілька профілів чату @@ -3804,6 +3849,10 @@ This is your link for group %@! Network connection No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management No comment provided by engineer. @@ -4342,11 +4391,19 @@ Error: %@ Приватні імена файлів No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes Приватні нотатки name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections З'єднання профілю та сервера @@ -4425,6 +4482,10 @@ Error: %@ Заборонити надсилання голосових повідомлень. No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen Захистіть екран програми @@ -4535,10 +4596,6 @@ Error: %@ Адреса отримувача буде змінена на інший сервер. Зміна адреси завершиться після того, як відправник з'явиться в мережі. No comment provided by engineer. - - Receiving concurrency - No comment provided by engineer. - Receiving file will be stopped. Отримання файлу буде зупинено. @@ -4996,6 +5053,14 @@ Error: %@ Надіслати живе повідомлення No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications Надсилати сповіщення @@ -5101,6 +5166,10 @@ Error: %@ Надіслані повідомлення будуть видалені через встановлений час. No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password Сервер вимагає авторизації для створення черг, перевірте пароль @@ -5116,6 +5185,10 @@ Error: %@ Тест сервера завершився невдало! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers Сервери @@ -5235,11 +5308,19 @@ Error: %@ Показати останні повідомлення No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview Показати попередній перегляд No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: Показати: @@ -5559,6 +5640,10 @@ It can happen because of some bug or when the connection is compromised.Додаток може сповіщати вас, коли ви отримуєте повідомлення або запити на контакт - будь ласка, відкрийте налаштування, щоб увімкнути цю функцію. No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. Спроба змінити пароль до бази даних не була завершена. @@ -5744,6 +5829,10 @@ It can happen because of some bug or when the connection is compromised.Для захисту часового поясу у файлах зображень/голосу використовується UTC. No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5836,11 +5925,6 @@ You will be prompted to complete authentication before this feature is enabled.< Розблокувати учасника? No comment provided by engineer. - - Unexpected error: %@ - Неочікувана помилка: %@ - item status description - Unexpected migration state Неочікуваний стан міграції @@ -5886,6 +5970,10 @@ You will be prompted to complete authentication before this feature is enabled.< Невідома помилка No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. Якщо ви не користуєтеся інтерфейсом виклику iOS, увімкніть режим "Не турбувати", щоб уникнути переривань. @@ -6033,6 +6121,14 @@ To connect, please ask your contact to create another connection link and check Використовувати лише локальні сповіщення? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server Використовувати сервер @@ -6263,11 +6359,23 @@ To connect, please ask your contact to create another connection link and check З меншим споживанням заряду акумулятора. No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase Неправильний пароль до бази даних No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! Неправильний пароль! @@ -7417,11 +7525,19 @@ SimpleX servers cannot see your profile. невідомий connection info + + unknown relays + No comment provided by engineer. + unknown status невідомий статус No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile оновлений профіль групи @@ -7487,6 +7603,10 @@ SimpleX servers cannot see your profile. тижнів time unit + + when IP hidden + No comment provided by engineer. + yes так diff --git a/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff b/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff index 4bf9e05665..edb01ac8ab 100644 --- a/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff +++ b/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff @@ -623,6 +623,7 @@ Admins can block a member for all. + 管理员可以为所有人封禁一名成员。 No comment provided by engineer. @@ -681,6 +682,7 @@ All your contacts, conversations and files will be securely encrypted and uploaded in chunks to configured XFTP relays. + 你的所有联系人、对话和文件将被安全加密并分块上传到配置的 XFTP 中继。 No comment provided by engineer. @@ -698,6 +700,10 @@ 仅当您的联系人允许时才允许限时消息。 No comment provided by engineer. + + Allow downgrade + No comment provided by engineer. + Allow irreversible message deletion only if your contact allows it to you. (24 hours) 仅有您的联系人许可后才允许不可撤回消息移除。 @@ -730,6 +736,7 @@ Allow to send SimpleX links. + 允许发送 SimpleX 链接。 No comment provided by engineer. @@ -792,6 +799,10 @@ 已经加入了该群组! No comment provided by engineer. + + Always use private routing. + No comment provided by engineer. + Always use relay 一直使用中继 @@ -814,6 +825,7 @@ App data migration + 应用数据迁移 No comment provided by engineer. @@ -853,14 +865,17 @@ Apply + 应用 No comment provided by engineer. Archive and upload + 存档和上传 No comment provided by engineer. Archiving database + 正在存档数据库 No comment provided by engineer. @@ -1055,6 +1070,7 @@ Cancel migration + 取消迁移 No comment provided by engineer. @@ -1067,8 +1083,13 @@ 无法接收文件 No comment provided by engineer. + + Capacity exceeded - recipient did not receive previously sent messages. + snd error text + Cellular + 移动网络 No comment provided by engineer. @@ -1164,6 +1185,7 @@ Chat migrated! + 已迁移聊天! No comment provided by engineer. @@ -1262,6 +1284,7 @@ Confirm network settings + 确认网络设置 No comment provided by engineer. @@ -1276,10 +1299,12 @@ Confirm that you remember database passphrase to migrate it. + 请在迁移前确认你记得数据库的密码短语。 No comment provided by engineer. Confirm upload + 确认上传 No comment provided by engineer. @@ -1535,6 +1560,7 @@ This is your own one-time link! Creating archive link + 正在创建存档链接 No comment provided by engineer. @@ -1756,6 +1782,7 @@ This cannot be undone! Delete database from this device + 从这部设备上删除数据库 No comment provided by engineer. @@ -1907,6 +1934,10 @@ This cannot be undone! 桌面设备 No comment provided by engineer. + + Destination server error: %@ + snd error text + Develop 开发 @@ -2012,11 +2043,19 @@ This cannot be undone! 通过本地网络发现 No comment provided by engineer. + + Do NOT send messages directly, even if your or destination server does not support private routing. + No comment provided by engineer. + Do NOT use SimpleX for emergency calls. 请勿使用 SimpleX 进行紧急通话。 No comment provided by engineer. + + Do NOT use private routing. + No comment provided by engineer. + Do it later 稍后再做 @@ -2049,10 +2088,12 @@ This cannot be undone! Download + 下载 chat item action Download failed + 下载失败了 No comment provided by engineer. @@ -2062,10 +2103,12 @@ This cannot be undone! Downloading archive + 正在下载存档 No comment provided by engineer. Downloading link details + 正在下载链接详情 No comment provided by engineer. @@ -2125,6 +2168,7 @@ This cannot be undone! Enable in direct chats (BETA)! + 在私聊中开启(公测)! No comment provided by engineer. @@ -2159,6 +2203,7 @@ This cannot be undone! Enabled for + 启用对象 No comment provided by engineer. @@ -2246,6 +2291,7 @@ This cannot be undone! Enter passphrase + 输入密码短语 No comment provided by engineer. @@ -2399,6 +2445,7 @@ This cannot be undone! Error downloading the archive + 下载存档出错 No comment provided by engineer. @@ -2477,6 +2524,7 @@ This cannot be undone! Error saving settings + 保存设置出错 when migrating @@ -2550,10 +2598,12 @@ This cannot be undone! Error uploading the archive + 上传存档出错 No comment provided by engineer. Error verifying passphrase: + 验证密码短语出错: No comment provided by engineer. @@ -2564,7 +2614,7 @@ This cannot be undone! Error: %@ 错误: %@ - No comment provided by engineer. + snd error text Error: URL is invalid @@ -2608,6 +2658,7 @@ This cannot be undone! Exported file doesn't exist + 导出的文件不存在 No comment provided by engineer. @@ -2655,6 +2706,10 @@ This cannot be undone! 文件:%@ No comment provided by engineer. + + Files + No comment provided by engineer. + Files & media 文件和媒体 @@ -2672,6 +2727,7 @@ This cannot be undone! Files and media not allowed + 不允许文件和媒体 No comment provided by engineer. @@ -2686,10 +2742,12 @@ This cannot be undone! Finalize migration + 完成迁移 No comment provided by engineer. Finalize migration on another device. + 在另一部设备上完成迁移 No comment provided by engineer. @@ -2739,20 +2797,34 @@ This cannot be undone! Forward + 转发 chat item action Forward and save messages + 转发并保存消息 No comment provided by engineer. Forwarded + 已转发 No comment provided by engineer. Forwarded from + 转发自 No comment provided by engineer. + + Forwarding server: %1$@ +Destination server error: %2$@ + snd error text + + + Forwarding server: %1$@ +Error: %2$@ + snd error text + Found desktop 找到了桌面 @@ -2864,6 +2936,7 @@ This cannot be undone! Group members can send SimpleX links. + 群成员可发送 SimpleX 链接。 No comment provided by engineer. @@ -3072,10 +3145,12 @@ This cannot be undone! Import failed + 导入失败了 No comment provided by engineer. Importing archive + 正在导入存档 No comment provided by engineer. @@ -3095,6 +3170,7 @@ This cannot be undone! In order to continue, chat should be stopped. + 必须停止聊天才能继续。 No comment provided by engineer. @@ -3104,6 +3180,7 @@ This cannot be undone! In-call sounds + 通话声音 No comment provided by engineer. @@ -3210,10 +3287,12 @@ This cannot be undone! Invalid link + 无效链接 No comment provided by engineer. Invalid migration confirmation + 迁移确认无效 No comment provided by engineer. @@ -3554,6 +3633,10 @@ This is your link for group %@! 消息送达回执! No comment provided by engineer. + + Message delivery warning + item status text + Message draft 消息草稿 @@ -3574,8 +3657,17 @@ This is your link for group %@! 该群组禁用了消息回应。 No comment provided by engineer. + + Message routing fallback + No comment provided by engineer. + + + Message routing mode + No comment provided by engineer. + Message source remains private. + 消息来源保持私密。 No comment provided by engineer. @@ -3585,6 +3677,7 @@ This is your link for group %@! Message too large + 消息太大了 No comment provided by engineer. @@ -3611,26 +3704,32 @@ This is your link for group %@! Migrate device + 迁移设备 No comment provided by engineer. Migrate from another device + 从另一台设备迁移 No comment provided by engineer. Migrate here + 迁移到此处 No comment provided by engineer. Migrate to another device + 迁移到另一部设备 No comment provided by engineer. Migrate to another device via QR code. + 通过二维码迁移到另一部设备。 No comment provided by engineer. Migrating + 迁移中 No comment provided by engineer. @@ -3640,6 +3739,7 @@ This is your link for group %@! Migration complete + 迁移完毕 No comment provided by engineer. @@ -3684,6 +3784,7 @@ This is your link for group %@! More reliable network connection. + 更可靠的网络连接。 No comment provided by engineer. @@ -3691,11 +3792,6 @@ This is your link for group %@! 此连接很可能已被删除。 item status description - - Most likely this contact has deleted the connection with you. - 很可能此联系人已经删除了与您的联系。 - No comment provided by engineer. - Multiple chat profiles 多个聊天资料 @@ -3723,10 +3819,16 @@ This is your link for group %@! Network connection + 网络连接 No comment provided by engineer. + + Network issues - message expired after many attempts to send it. + snd error text + Network management + 网络管理 No comment provided by engineer. @@ -3841,6 +3943,7 @@ This is your link for group %@! No network connection + 无网络连接 No comment provided by engineer. @@ -4037,6 +4140,7 @@ This is your link for group %@! Or paste archive link + 或粘贴存档链接 No comment provided by engineer. @@ -4046,6 +4150,7 @@ This is your link for group %@! Or securely share this file link + 或安全地分享此文件链接 No comment provided by engineer. @@ -4055,6 +4160,7 @@ This is your link for group %@! Other + 其他 No comment provided by engineer. @@ -4138,6 +4244,7 @@ This is your link for group %@! Picture-in-picture calls + 画中画通话 No comment provided by engineer. @@ -4162,6 +4269,7 @@ This is your link for group %@! Please confirm that network settings are correct for this device. + 请确认网络设置对此这台设备正确无误。 No comment provided by engineer. @@ -4254,11 +4362,19 @@ Error: %@ 私密文件名 No comment provided by engineer. + + Private message routing + No comment provided by engineer. + Private notes 私密笔记 name of notes to self + + Private routing + No comment provided by engineer. + Profile and server connections 资料和服务器连接 @@ -4271,6 +4387,7 @@ Error: %@ Profile images + 个人资料图 No comment provided by engineer. @@ -4336,6 +4453,10 @@ Error: %@ 禁止发送语音消息。 No comment provided by engineer. + + Protect IP address + No comment provided by engineer. + Protect app screen 保护应用程序屏幕 @@ -4367,6 +4488,7 @@ Error: %@ Quantum resistant encryption + 抗量子加密 No comment provided by engineer. @@ -4444,10 +4566,6 @@ Error: %@ 接收地址将变更到不同的服务器。地址更改将在发件人上线后完成。 No comment provided by engineer. - - Receiving concurrency - No comment provided by engineer. - Receiving file will be stopped. 即将停止接收文件。 @@ -4464,6 +4582,7 @@ Error: %@ Recipient(s) can't see who this message is from. + 收件人看不到这条消息来自何人。 No comment provided by engineer. @@ -4563,10 +4682,12 @@ Error: %@ Repeat download + 重复下载 No comment provided by engineer. Repeat import + 重复导入 No comment provided by engineer. @@ -4576,6 +4697,7 @@ Error: %@ Repeat upload + 重复上传 No comment provided by engineer. @@ -4680,6 +4802,7 @@ Error: %@ Safer groups + 更安全的群组 No comment provided by engineer. @@ -4764,6 +4887,7 @@ Error: %@ Saved + 已保存 No comment provided by engineer. @@ -4773,6 +4897,7 @@ Error: %@ Saved from + 保存自 No comment provided by engineer. @@ -4900,6 +5025,14 @@ Error: %@ 发送实时消息 No comment provided by engineer. + + Send messages directly when IP address is protected and your or destination server does not support private routing. + No comment provided by engineer. + + + Send messages directly when your or destination server does not support private routing. + No comment provided by engineer. + Send notifications 发送通知 @@ -5005,6 +5138,10 @@ Error: %@ 已发送的消息将在设定的时间后被删除。 No comment provided by engineer. + + Server address is incompatible with network settings. + srv error text. + Server requires authorization to create queues, check password 服务器需要授权才能创建队列,检查密码 @@ -5020,6 +5157,10 @@ Error: %@ 服务器测试失败! No comment provided by engineer. + + Server version is incompatible with network settings. + srv error text + Servers 服务器 @@ -5057,6 +5198,7 @@ Error: %@ Set passphrase + 设置密码短语 No comment provided by engineer. @@ -5081,6 +5223,7 @@ Error: %@ Shape profile images + 改变个人资料图形状 No comment provided by engineer. @@ -5120,6 +5263,7 @@ Error: %@ Show QR code + 显示二维码 No comment provided by engineer. @@ -5137,11 +5281,19 @@ Error: %@ 显示最近的消息 No comment provided by engineer. + + Show message status + No comment provided by engineer. + Show preview 显示预览 No comment provided by engineer. + + Show → on messages sent via private routing. + No comment provided by engineer. + Show: 显示: @@ -5204,10 +5356,12 @@ Error: %@ SimpleX links are prohibited in this group. + 此群禁止 SimpleX 链接。 No comment provided by engineer. SimpleX links not allowed + 不允许SimpleX 链接 No comment provided by engineer. @@ -5247,6 +5401,7 @@ Error: %@ Square, circle, or anything in between. + 方形、圆形、或两者之间的任意形状 No comment provided by engineer. @@ -5276,6 +5431,7 @@ Error: %@ Stop chat + 停止聊天程序 No comment provided by engineer. @@ -5320,6 +5476,7 @@ Error: %@ Stopping chat + 正在停止聊天 No comment provided by engineer. @@ -5459,6 +5616,10 @@ It can happen because of some bug or when the connection is compromised.该应用可以在您收到消息或联系人请求时通知您——请打开设置以启用通知。 No comment provided by engineer. + + The app will ask to confirm downloads from unknown file servers (except .onion). + No comment provided by engineer. + The attempt to change database passphrase was not completed. 更改数据库密码的尝试未完成。 @@ -5571,10 +5732,12 @@ It can happen because of some bug or when the connection is compromised. This chat is protected by end-to-end encryption. + 此聊天受端到端加密保护。 E2EE info chat item This chat is protected by quantum resistant end-to-end encryption. + 此聊天受抗量子的端到端加密保护。 E2EE info chat item @@ -5642,6 +5805,10 @@ It can happen because of some bug or when the connection is compromised.为了保护时区,图像/语音文件使用 UTC。 No comment provided by engineer. + + To protect your IP address, private routing uses your SMP servers to deliver messages. + No comment provided by engineer. + To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. @@ -5733,11 +5900,6 @@ You will be prompted to complete authentication before this feature is enabled.< 解封成员吗? No comment provided by engineer. - - Unexpected error: %@ - 意外错误: %@ - item status description - Unexpected migration state 未预料的迁移状态 @@ -5783,6 +5945,10 @@ You will be prompted to complete authentication before this feature is enabled.< 未知错误 No comment provided by engineer. + + Unknown servers! + No comment provided by engineer. + Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. 除非您使用 iOS 通话界面,否则请启用请勿打扰模式以避免打扰。 @@ -5872,6 +6038,7 @@ To connect, please ask your contact to create another connection link and check Upload failed + 上传失败了 No comment provided by engineer. @@ -5881,6 +6048,7 @@ To connect, please ask your contact to create another connection link and check Uploading archive + 正在上传存档 No comment provided by engineer. @@ -5927,6 +6095,14 @@ To connect, please ask your contact to create another connection link and check Use only local notifications? No comment provided by engineer. + + Use private routing with unknown servers when IP address is not protected. + No comment provided by engineer. + + + Use private routing with unknown servers. + No comment provided by engineer. + Use server 使用服务器 @@ -5934,6 +6110,7 @@ To connect, please ask your contact to create another connection link and check Use the app while in the call. + 通话时使用本应用 No comment provided by engineer. @@ -5973,10 +6150,12 @@ To connect, please ask your contact to create another connection link and check Verify database passphrase + 验证数据库密码短语 No comment provided by engineer. Verify passphrase + 验证密码短语 No comment provided by engineer. @@ -6041,6 +6220,7 @@ To connect, please ask your contact to create another connection link and check Voice messages not allowed + 不允许语音消息 No comment provided by engineer. @@ -6074,6 +6254,7 @@ To connect, please ask your contact to create another connection link and check Warning: starting chat on multiple devices is not supported and will cause message delivery failures + 警告:不支持在多部设备上启动聊天,这么做会导致消息传送失败。 No comment provided by engineer. @@ -6098,6 +6279,7 @@ To connect, please ask your contact to create another connection link and check Welcome message is too long + 欢迎消息太大了 No comment provided by engineer. @@ -6112,6 +6294,7 @@ To connect, please ask your contact to create another connection link and check When connecting audio and video calls. + 连接音频和视频通话时。 No comment provided by engineer. @@ -6126,14 +6309,17 @@ To connect, please ask your contact to create another connection link and check WiFi + WiFi No comment provided by engineer. Will be enabled in direct chats! + 将在私聊中启用! No comment provided by engineer. Wired ethernet + 有线以太网 No comment provided by engineer. @@ -6151,11 +6337,23 @@ To connect, please ask your contact to create another connection link and check 降低了电量使用。 No comment provided by engineer. + + Without Tor or VPN, your IP address will be visible to file servers. + No comment provided by engineer. + + + Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. + No comment provided by engineer. + Wrong database passphrase 数据库密码错误 No comment provided by engineer. + + Wrong key or unknown connection - most likely this connection is deleted. + snd error text + Wrong passphrase! 密码错误! @@ -6258,6 +6456,7 @@ Repeat join request? You can give another try. + 你可以再试一次。 No comment provided by engineer. @@ -6609,6 +6808,7 @@ SimpleX 服务器无法看到您的资料。 admins + 管理员 feature role @@ -6623,6 +6823,7 @@ SimpleX 服务器无法看到您的资料。 all members + 所有成员 feature role @@ -6955,6 +7156,7 @@ SimpleX 服务器无法看到您的资料。 forwarded + 已转发 No comment provided by engineer. @@ -7165,6 +7367,7 @@ SimpleX 服务器无法看到您的资料。 owners + 所有者 feature role @@ -7174,6 +7377,7 @@ SimpleX 服务器无法看到您的资料。 quantum resistant e2e encryption + 抗量子端到端加密 chat item text @@ -7218,6 +7422,7 @@ SimpleX 服务器无法看到您的资料。 saved + 已保存 No comment provided by engineer. @@ -7261,6 +7466,7 @@ SimpleX 服务器无法看到您的资料。 standard end-to-end encryption + 标准端到端加密 chat item text @@ -7287,11 +7493,19 @@ SimpleX 服务器无法看到您的资料。 未知 connection info + + unknown relays + No comment provided by engineer. + unknown status 未知状态 No comment provided by engineer. + + unprotected + No comment provided by engineer. + updated group profile 已更新的群组资料 @@ -7356,6 +7570,10 @@ SimpleX 服务器无法看到您的资料。 time unit + + when IP hidden + No comment provided by engineer. + yes @@ -7363,6 +7581,7 @@ SimpleX 服务器无法看到您的资料。 you + No comment provided by engineer. diff --git a/apps/ios/bg.lproj/Localizable.strings b/apps/ios/bg.lproj/Localizable.strings index 06d9f1f43e..5fe8fe909c 100644 --- a/apps/ios/bg.lproj/Localizable.strings +++ b/apps/ios/bg.lproj/Localizable.strings @@ -1779,7 +1779,7 @@ /* No comment provided by engineer. */ "Error: " = "Грешка: "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "Грешка: %@"; /* No comment provided by engineer. */ @@ -2568,9 +2568,6 @@ /* item status description */ "Most likely this connection is deleted." = "Най-вероятно тази връзка е изтрита."; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "Най-вероятно този контакт е изтрил връзката с вас."; - /* No comment provided by engineer. */ "Multiple chat profiles" = "Множество профили за чат"; @@ -3077,9 +3074,6 @@ /* No comment provided by engineer. */ "Receiving address will be changed to a different server. Address change will complete after sender comes online." = "Получаващият адрес ще бъде променен към друг сървър. Промяната на адреса ще завърши, след като подателят е онлайн."; -/* No comment provided by engineer. */ -"Receiving concurrency" = "Паралелност на получаване"; - /* No comment provided by engineer. */ "Receiving file will be stopped." = "Получаващият се файл ще бъде спрян."; @@ -3920,9 +3914,6 @@ /* rcv group event chat item */ "unblocked %@" = "отблокиран %@"; -/* item status description */ -"Unexpected error: %@" = "Неочаквана грешка: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "Неочаквано състояние на миграция"; diff --git a/apps/ios/cs.lproj/Localizable.strings b/apps/ios/cs.lproj/Localizable.strings index e2087547bd..bbe46b225f 100644 --- a/apps/ios/cs.lproj/Localizable.strings +++ b/apps/ios/cs.lproj/Localizable.strings @@ -1461,7 +1461,7 @@ /* No comment provided by engineer. */ "Error: " = "Chyba: "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "Chyba: %@"; /* No comment provided by engineer. */ @@ -2082,9 +2082,6 @@ /* item status description */ "Most likely this connection is deleted." = "Pravděpodobně je toto spojení smazáno."; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "Tento kontakt s největší pravděpodobností smazal spojení s vámi."; - /* No comment provided by engineer. */ "Multiple chat profiles" = "Více chatovacích profilů"; @@ -3179,9 +3176,6 @@ /* No comment provided by engineer. */ "Unable to record voice message" = "Nelze nahrát hlasovou zprávu"; -/* item status description */ -"Unexpected error: %@" = "Neočekávaná chyba: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "Neočekávaný stav přenášení"; diff --git a/apps/ios/de.lproj/Localizable.strings b/apps/ios/de.lproj/Localizable.strings index 5fc393fa1f..e6d98cc96a 100644 --- a/apps/ios/de.lproj/Localizable.strings +++ b/apps/ios/de.lproj/Localizable.strings @@ -438,7 +438,7 @@ "All your contacts will remain connected. Profile update will be sent to your contacts." = "Alle Ihre Kontakte bleiben verbunden. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet."; /* No comment provided by engineer. */ -"All your contacts, conversations and files will be securely encrypted and uploaded in chunks to configured XFTP relays." = "Alle Ihre Kontakte, Unterhaltungen und Dateien werden sicher verschlüsselt und in Daten-Paketen auf die konfigurierten XTFP-Server hochgeladen."; +"All your contacts, conversations and files will be securely encrypted and uploaded in chunks to configured XFTP relays." = "Alle Ihre Kontakte, Unterhaltungen und Dateien werden sicher verschlüsselt und in Daten-Paketen auf die konfigurierten XTFP-Relais hochgeladen."; /* No comment provided by engineer. */ "Allow" = "Erlauben"; @@ -1779,7 +1779,7 @@ /* No comment provided by engineer. */ "Error: " = "Fehler: "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "Fehler: %@"; /* No comment provided by engineer. */ @@ -2568,9 +2568,6 @@ /* item status description */ "Most likely this connection is deleted." = "Wahrscheinlich ist diese Verbindung gelöscht worden."; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "Dieser Kontakt hat sehr wahrscheinlich die Verbindung mit Ihnen gelöscht."; - /* No comment provided by engineer. */ "Multiple chat profiles" = "Mehrere Chat-Profile"; @@ -2730,10 +2727,10 @@ "One-time invitation link" = "Einmal-Einladungslink"; /* No comment provided by engineer. */ -"Onion hosts will be required for connection. Requires enabling VPN." = "Für die Verbindung werden Onion-Hosts benötigt. Dies erfordert die Aktivierung eines VPNs."; +"Onion hosts will be required for connection. Requires enabling VPN." = "Für diese Verbindung werden Onion-Hosts benötigt. Dies erfordert die Aktivierung eines VPNs."; /* No comment provided by engineer. */ -"Onion hosts will be used when available. Requires enabling VPN." = "Onion-Hosts werden verwendet, sobald sie verfügbar sind. Dies erfordert die Aktivierung eines VPNs."; +"Onion hosts will be used when available. Requires enabling VPN." = "Wenn Onion-Hosts verfügbar sind, werden sie verwendet. Dies erfordert die Aktivierung eines VPNs."; /* No comment provided by engineer. */ "Onion hosts will not be used." = "Onion-Hosts werden nicht verwendet."; @@ -3077,9 +3074,6 @@ /* No comment provided by engineer. */ "Receiving address will be changed to a different server. Address change will complete after sender comes online." = "Die Empfängeradresse wird auf einen anderen Server geändert. Der Adresswechsel wird abgeschlossen, wenn der Absender wieder online ist."; -/* No comment provided by engineer. */ -"Receiving concurrency" = "Gleichzeitiger Empfang"; - /* No comment provided by engineer. */ "Receiving file will be stopped." = "Der Empfang der Datei wird beendet."; @@ -3920,9 +3914,6 @@ /* rcv group event chat item */ "unblocked %@" = "%@ wurde freigegeben"; -/* item status description */ -"Unexpected error: %@" = "Unerwarteter Fehler: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "Unerwarteter Migrationsstatus"; diff --git a/apps/ios/es.lproj/Localizable.strings b/apps/ios/es.lproj/Localizable.strings index 8a61d6c438..42002cd282 100644 --- a/apps/ios/es.lproj/Localizable.strings +++ b/apps/ios/es.lproj/Localizable.strings @@ -675,7 +675,7 @@ "Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "Búlgaro, Finlandés, Tailandés y Ucraniano - gracias a los usuarios y [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"; /* No comment provided by engineer. */ -"By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)." = "Mediante perfil (por defecto) o [por conexión](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)."; +"By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)." = "Mediante perfil (predeterminado) o [por conexión](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)."; /* No comment provided by engineer. */ "Call already ended!" = "¡La llamada ha terminado!"; @@ -1162,13 +1162,13 @@ "Decryption error" = "Error descifrado"; /* pref value */ -"default (%@)" = "por defecto (%@)"; +"default (%@)" = "predeterminado (%@)"; /* No comment provided by engineer. */ -"default (no)" = "por defecto (no)"; +"default (no)" = "predeterminado (no)"; /* No comment provided by engineer. */ -"default (yes)" = "por defecto (sí)"; +"default (yes)" = "predeterminado (sí)"; /* chat item action */ "Delete" = "Eliminar"; @@ -1492,7 +1492,7 @@ "enabled" = "activado"; /* No comment provided by engineer. */ -"Enabled for" = "Activar para"; +"Enabled for" = "Activado para"; /* enabled status */ "enabled for contact" = "activado para el contacto"; @@ -1779,7 +1779,7 @@ /* No comment provided by engineer. */ "Error: " = "Error: "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "Error: %@"; /* No comment provided by engineer. */ @@ -2568,9 +2568,6 @@ /* item status description */ "Most likely this connection is deleted." = "Probablemente la conexión ha sido eliminada."; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "Lo más probable es que este contacto haya eliminado la conexión contigo."; - /* No comment provided by engineer. */ "Multiple chat profiles" = "Múltiples perfiles"; @@ -2961,7 +2958,7 @@ "Profile image" = "Imagen del perfil"; /* No comment provided by engineer. */ -"Profile images" = "Imágenes del perfil"; +"Profile images" = "Forma de los perfiles"; /* No comment provided by engineer. */ "Profile name" = "Nombre del perfil"; @@ -3077,9 +3074,6 @@ /* No comment provided by engineer. */ "Receiving address will be changed to a different server. Address change will complete after sender comes online." = "La dirección de recepción pasará a otro servidor. El cambio se completará cuando el remitente esté en línea."; -/* No comment provided by engineer. */ -"Receiving concurrency" = "Concurrencia en la recepción"; - /* No comment provided by engineer. */ "Receiving file will be stopped." = "Se detendrá la recepción del archivo."; @@ -3192,7 +3186,7 @@ "Reset colors" = "Restablecer colores"; /* No comment provided by engineer. */ -"Reset to defaults" = "Restablecer valores por defecto"; +"Reset to defaults" = "Restablecer valores predetarminados"; /* No comment provided by engineer. */ "Restart the app to create a new chat profile" = "Reinicia la aplicación para crear un perfil nuevo"; @@ -3920,9 +3914,6 @@ /* rcv group event chat item */ "unblocked %@" = "ha desbloqueado a %@"; -/* item status description */ -"Unexpected error: %@" = "Error inesperado: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "Estado de migración inesperado"; diff --git a/apps/ios/fi.lproj/Localizable.strings b/apps/ios/fi.lproj/Localizable.strings index c71f9e089c..12d17aac36 100644 --- a/apps/ios/fi.lproj/Localizable.strings +++ b/apps/ios/fi.lproj/Localizable.strings @@ -1434,7 +1434,7 @@ /* No comment provided by engineer. */ "Error: " = "Virhe: "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "Virhe: %@"; /* No comment provided by engineer. */ @@ -2058,9 +2058,6 @@ /* item status description */ "Most likely this connection is deleted." = "Todennäköisesti tämä yhteys on poistettu."; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "Todennäköisesti tämä kontakti on poistanut yhteyden sinuun."; - /* No comment provided by engineer. */ "Multiple chat profiles" = "Useita keskusteluprofiileja"; @@ -3137,9 +3134,6 @@ /* No comment provided by engineer. */ "Unable to record voice message" = "Ääniviestiä ei voi tallentaa"; -/* item status description */ -"Unexpected error: %@" = "Odottamaton virhe: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "Odottamaton siirtotila"; diff --git a/apps/ios/fr.lproj/Localizable.strings b/apps/ios/fr.lproj/Localizable.strings index 5e6c9c1b40..ba34d03a78 100644 --- a/apps/ios/fr.lproj/Localizable.strings +++ b/apps/ios/fr.lproj/Localizable.strings @@ -1306,7 +1306,7 @@ "Delivery receipts are disabled!" = "Les accusés de réception sont désactivés !"; /* No comment provided by engineer. */ -"Delivery receipts!" = "Justificatifs de réception!"; +"Delivery receipts!" = "Justificatifs de réception !"; /* No comment provided by engineer. */ "Description" = "Description"; @@ -1779,7 +1779,7 @@ /* No comment provided by engineer. */ "Error: " = "Erreur : "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "Erreur : %@"; /* No comment provided by engineer. */ @@ -1876,7 +1876,7 @@ "Fix connection" = "Réparer la connexion"; /* No comment provided by engineer. */ -"Fix connection?" = "Réparer la connexion?"; +"Fix connection?" = "Réparer la connexion ?"; /* No comment provided by engineer. */ "Fix encryption after restoring backups." = "Réparer le chiffrement après la restauration des sauvegardes."; @@ -2568,9 +2568,6 @@ /* item status description */ "Most likely this connection is deleted." = "Connexion probablement supprimée."; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "Il est fort probable que ce contact ait supprimé la connexion avec vous."; - /* No comment provided by engineer. */ "Multiple chat profiles" = "Différents profils de chat"; @@ -3077,9 +3074,6 @@ /* No comment provided by engineer. */ "Receiving address will be changed to a different server. Address change will complete after sender comes online." = "L'adresse de réception sera changée pour un autre serveur. Le changement d'adresse sera terminé lorsque l'expéditeur sera en ligne."; -/* No comment provided by engineer. */ -"Receiving concurrency" = "Réception simultanée"; - /* No comment provided by engineer. */ "Receiving file will be stopped." = "La réception du fichier sera interrompue."; @@ -3099,7 +3093,7 @@ "Reconnect all connected servers to force message delivery. It uses additional traffic." = "Reconnecter tous les serveurs connectés pour forcer la livraison des messages. Cette méthode utilise du trafic supplémentaire."; /* No comment provided by engineer. */ -"Reconnect servers?" = "Reconnecter les serveurs?"; +"Reconnect servers?" = "Reconnecter les serveurs ?"; /* No comment provided by engineer. */ "Record updated at" = "Enregistrement mis à jour le"; @@ -3162,7 +3156,7 @@ "Renegotiate encryption" = "Renégocier le chiffrement"; /* No comment provided by engineer. */ -"Renegotiate encryption?" = "Renégocier le chiffrement?"; +"Renegotiate encryption?" = "Renégocier le chiffrement ?"; /* No comment provided by engineer. */ "Repeat connection request?" = "Répéter la demande de connexion ?"; @@ -3920,9 +3914,6 @@ /* rcv group event chat item */ "unblocked %@" = "%@ débloqué"; -/* item status description */ -"Unexpected error: %@" = "Erreur inattendue : %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "État de la migration inattendu"; @@ -4170,7 +4161,7 @@ "wants to connect to you!" = "veut établir une connexion !"; /* No comment provided by engineer. */ -"Warning: starting chat on multiple devices is not supported and will cause message delivery failures" = "Attention: démarrer une session de chat sur plusieurs appareils n'est pas pris en charge et entraînera des dysfonctionnements au niveau de la transmission des messages"; +"Warning: starting chat on multiple devices is not supported and will cause message delivery failures" = "Attention : démarrer une session de chat sur plusieurs appareils n'est pas pris en charge et entraînera des dysfonctionnements au niveau de la transmission des messages"; /* No comment provided by engineer. */ "Warning: you may lose some data!" = "Attention : vous risquez de perdre des données !"; diff --git a/apps/ios/hu.lproj/Localizable.strings b/apps/ios/hu.lproj/Localizable.strings index b590785606..f7d1b35f4a 100644 --- a/apps/ios/hu.lproj/Localizable.strings +++ b/apps/ios/hu.lproj/Localizable.strings @@ -345,7 +345,7 @@ "Accept" = "Elfogadás"; /* No comment provided by engineer. */ -"Accept connection request?" = "Kapcsolatfelvétel elfogadása?"; +"Accept connection request?" = "Kapcsolódási kérelem elfogadása?"; /* notification body */ "Accept contact request from %@?" = "Elfogadja %@ kapcsolat kérését?"; @@ -444,16 +444,16 @@ "Allow" = "Engedélyezés"; /* No comment provided by engineer. */ -"Allow calls only if your contact allows them." = "Hívások engedélyezése kizárólag abban az esetben, ha ismerőse is engedélyezi."; +"Allow calls only if your contact allows them." = "A hívások kezdeményezése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi."; /* No comment provided by engineer. */ -"Allow disappearing messages only if your contact allows it to you." = "Eltűnő üzenetek engedélyezése kizárólag abban az esetben, ha ismerőse is engedélyezi az ön számára."; +"Allow disappearing messages only if your contact allows it to you." = "Az eltűnő üzenetek küldése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi az ön számára."; /* No comment provided by engineer. */ -"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "Üzenet végleges törlésének engedélyezése kizárólag abban az esetben, ha ismerőse is engedélyezi. (24 óra)"; +"Allow irreversible message deletion only if your contact allows it to you. (24 hours)" = "Az üzenetek végleges törlése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. (24 óra)"; /* No comment provided by engineer. */ -"Allow message reactions only if your contact allows them." = "Üzenetreakciók engedélyezése kizárólag abban az esetben, ha ismerőse is engedélyezi."; +"Allow message reactions only if your contact allows them." = "Az üzenetreakciók küldése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi."; /* No comment provided by engineer. */ "Allow message reactions." = "Üzenetreakciók engedélyezése."; @@ -462,7 +462,7 @@ "Allow sending direct messages to members." = "Közvetlen üzenetek küldésének engedélyezése a tagok számára."; /* No comment provided by engineer. */ -"Allow sending disappearing messages." = "Eltűnő üzenetek küldésének engedélyezése."; +"Allow sending disappearing messages." = "Az eltűnő üzenetek küldése engedélyezve van."; /* No comment provided by engineer. */ "Allow to irreversibly delete sent messages. (24 hours)" = "Elküldött üzenetek végleges törlésének engedélyezése. (24 óra)"; @@ -477,25 +477,25 @@ "Allow to send voice messages." = "Hangüzenetek küldésének engedélyezése."; /* No comment provided by engineer. */ -"Allow voice messages only if your contact allows them." = "Hangüzenetek küldésének engedélyezése kizárólag abban az esetben, ha ismerőse is engedélyezi."; +"Allow voice messages only if your contact allows them." = "A hangüzenetek küldése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi."; /* No comment provided by engineer. */ "Allow voice messages?" = "Hangüzenetek engedélyezése?"; /* No comment provided by engineer. */ -"Allow your contacts adding message reactions." = "Ismerősök általi üzenetreakciók hozzáadásának engedélyezése."; +"Allow your contacts adding message reactions." = "Az üzenetreakciók küldése engedélyezve van az ismerősei számára."; /* No comment provided by engineer. */ -"Allow your contacts to call you." = "Hívások engedélyezése ismerősök számára."; +"Allow your contacts to call you." = "A hívások kezdeményezése engedélyezve van az ismerősei számára."; /* No comment provided by engineer. */ -"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "Elküldött üzenetek végleges törlésének engedélyezése az ismerősök számára. (24 óra)"; +"Allow your contacts to irreversibly delete sent messages. (24 hours)" = "Az elküldött üzenetek végleges törlése engedélyezve van az ismerősei számára. (24 óra)"; /* No comment provided by engineer. */ -"Allow your contacts to send disappearing messages." = "Eltűnő üzenetek engedélyezése ismerősök számára."; +"Allow your contacts to send disappearing messages." = "Az eltűnő üzenetek küldésének engedélyezése az ismerősei számára."; /* No comment provided by engineer. */ -"Allow your contacts to send voice messages." = "Hangüzenetek küldésének engedélyezése ismerősök számára."; +"Allow your contacts to send voice messages." = "A hangüzenetek küldése engedélyezve van az ismerősei számára."; /* No comment provided by engineer. */ "Already connected?" = "Már kapcsolódott?"; @@ -573,10 +573,10 @@ "Audio/video calls" = "Hang-/videóhívások"; /* No comment provided by engineer. */ -"Audio/video calls are prohibited." = "A hang- és videóhívások le vannak tiltva."; +"Audio/video calls are prohibited." = "A hívások kezdeményezése le van tiltva ebben a csevegésben."; /* PIN entry */ -"Authentication cancelled" = "Hitelesítés megszakítva"; +"Authentication cancelled" = "Hitelesítés visszavonva"; /* No comment provided by engineer. */ "Authentication failed" = "Sikertelen hitelesítés"; @@ -594,7 +594,7 @@ "Auto-accept" = "Automatikus elfogadás"; /* No comment provided by engineer. */ -"Auto-accept contact requests" = "Ismerős jelölések automatikus elfogadása"; +"Auto-accept contact requests" = "Kapcsolódási kérelmek automatikus elfogadása"; /* No comment provided by engineer. */ "Auto-accept images" = "Fotók automatikus elfogadása"; @@ -636,7 +636,7 @@ "Block member" = "Tag blokkolása"; /* No comment provided by engineer. */ -"Block member for all?" = "Tag letiltása mindenki számára?"; +"Block member for all?" = "Mindenki számára letiltja ezt a tagot?"; /* No comment provided by engineer. */ "Block member?" = "Tag blokkolása?"; @@ -663,7 +663,7 @@ "Both you and your contact can irreversibly delete sent messages. (24 hours)" = "Mindkét fél törölheti véglegesen az elküldött üzeneteket. (24 óra)"; /* No comment provided by engineer. */ -"Both you and your contact can make calls." = "Mindkét fél tud hívásokat indítani."; +"Both you and your contact can make calls." = "Mindkét fél tud hívásokat kezdeményezni."; /* No comment provided by engineer. */ "Both you and your contact can send disappearing messages." = "Mindkét fél küldhet eltűnő üzeneteket."; @@ -708,7 +708,7 @@ "Cancel migration" = "Átköltöztetés visszavonása"; /* feature offered item */ -"cancelled %@" = "%@ törölve"; +"cancelled %@" = "%@ visszavonva"; /* No comment provided by engineer. */ "Cannot access keychain to save database password" = "Nem lehet hozzáférni a kulcstartóhoz az adatbázis jelszavának mentéséhez"; @@ -1006,7 +1006,7 @@ "Contacts" = "Ismerősök"; /* No comment provided by engineer. */ -"Contacts can mark messages for deletion; you will be able to view them." = "Az ismerősök törlésre jelölhetnek üzeneteket ; megtekintheti őket."; +"Contacts can mark messages for deletion; you will be able to view them." = "Az ismerősei törlésre jelölhetnek üzeneteket; ön majd meg tudja nézni azokat."; /* No comment provided by engineer. */ "Continue" = "Folytatás"; @@ -1075,7 +1075,7 @@ "Creating link…" = "Hivatkozás létrehozása…"; /* No comment provided by engineer. */ -"creator" = "szerző"; +"creator" = "készítő"; /* No comment provided by engineer. */ "Current Passcode" = "Jelenlegi jelkód"; @@ -1183,7 +1183,7 @@ "Delete address?" = "Azonosító törlése?"; /* No comment provided by engineer. */ -"Delete after" = "Törlés miután"; +"Delete after" = "Törlés ennyi idő után"; /* No comment provided by engineer. */ "Delete all files" = "Minden fájl törlése"; @@ -1261,7 +1261,7 @@ "Delete messages" = "Üzenetek törlése"; /* No comment provided by engineer. */ -"Delete messages after" = "Üzenetek törlése miután"; +"Delete messages after" = "Üzenetek törlése ennyi idő után"; /* No comment provided by engineer. */ "Delete old database" = "Régi adatbázis törlése"; @@ -1348,7 +1348,7 @@ "Direct messages" = "Közvetlen üzenetek"; /* No comment provided by engineer. */ -"Direct messages between members are prohibited in this group." = "Ebben a csoportban tiltott a tagok közötti közvetlen üzenetek küldése."; +"Direct messages between members are prohibited in this group." = "A közvetlen üzenetek küldése a tagok között le van tiltva ebben a csoportban."; /* No comment provided by engineer. */ "Disable (keep overrides)" = "Letiltás (felülírások megtartásával)"; @@ -1369,7 +1369,7 @@ "Disappearing messages" = "Eltűnő üzenetek"; /* No comment provided by engineer. */ -"Disappearing messages are prohibited in this chat." = "Az eltűnő üzenetek le vannak tiltva ebben a csevegésben."; +"Disappearing messages are prohibited in this chat." = "Az eltűnő üzenetek küldése le van tiltva ebben a csevegésben."; /* No comment provided by engineer. */ "Disappearing messages are prohibited in this group." = "Az eltűnő üzenetek küldése le van tiltva ebben a csoportban."; @@ -1779,7 +1779,7 @@ /* No comment provided by engineer. */ "Error: " = "Hiba: "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "Hiba: %@"; /* No comment provided by engineer. */ @@ -2077,7 +2077,7 @@ "If you enter this passcode when opening the app, all app data will be irreversibly removed!" = "Ha az alkalmazás megnyitásakor megadja ezt a jelkódot, az összes alkalmazásadat véglegesen törlődik!"; /* No comment provided by engineer. */ -"If you enter your self-destruct passcode while opening the app:" = "Ha az alkalmazás megnyitásakor az önmegsemmisítő jelkódot megadásra kerül:"; +"If you enter your self-destruct passcode while opening the app:" = "Ha az alkalmazás megnyitásakor megadja az önmegsemmisítő jelkódot:"; /* No comment provided by engineer. */ "If you need to use the chat now tap **Do it later** below (you will be offered to migrate the database when you restart the app)." = "Ha most kell használnia a csevegést, koppintson a ** Csináld később** elemre (az alkalmazás újraindításakor felajánlásra kerül az adatbázis áttelepítése)."; @@ -2245,16 +2245,16 @@ "Invite to group" = "Meghívás a csoportba"; /* No comment provided by engineer. */ -"invited" = "meghívta"; +"invited" = "meghíva"; /* rcv group event chat item */ -"invited %@" = "meghívta %@-t"; +"invited %@" = "meghívta őt: %@"; /* chat list item title */ "invited to connect" = "meghívta, hogy csatlakozzon"; /* rcv group event chat item */ -"invited via your group link" = "meghívta a csoport hivatkozásán keresztül"; +"invited via your group link" = "meghíva az ön csoport hivatkozásán keresztül"; /* No comment provided by engineer. */ "iOS Keychain is used to securely store passphrase - it allows receiving push notifications." = "Az iOS kulcstár a jelmondat biztonságos tárolására szolgál - lehetővé teszi a push-értesítések fogadását."; @@ -2266,10 +2266,10 @@ "Irreversible message deletion" = "Végleges üzenettörlés"; /* No comment provided by engineer. */ -"Irreversible message deletion is prohibited in this chat." = "Ebben a csevegésben az üzenetek végleges törlése le van tiltva."; +"Irreversible message deletion is prohibited in this chat." = "Az üzenetek végleges törlése le van tiltva ebben a csevegésben."; /* No comment provided by engineer. */ -"Irreversible message deletion is prohibited in this group." = "Ebben a csoportban az üzenetek végleges törlése le van tiltva."; +"Irreversible message deletion is prohibited in this group." = "Az üzenetek végleges törlése le van tiltva ebben a csoportban."; /* No comment provided by engineer. */ "It allows having many anonymous connections without any shared data between them in a single chat profile." = "Lehetővé teszi, hogy egyetlen csevegőprofilon belül több anonim kapcsolat legyen, anélkül, hogy megosztott adatok lennének közöttük."; @@ -2344,7 +2344,7 @@ "Learn more" = "Tudjon meg többet"; /* No comment provided by engineer. */ -"Leave" = "Elhagy"; +"Leave" = "Elhagyás"; /* No comment provided by engineer. */ "Leave group" = "Csoport elhagyása"; @@ -2419,10 +2419,10 @@ "Mark deleted for everyone" = "Jelölje meg mindenki számára töröltként"; /* No comment provided by engineer. */ -"Mark read" = "Megjelölés olvasottként"; +"Mark read" = "Olvasottként jelölés"; /* No comment provided by engineer. */ -"Mark verified" = "Ellenőrzöttként jelölve"; +"Mark verified" = "Hitelesítés"; /* No comment provided by engineer. */ "Markdown in messages" = "Markdown az üzenetekben"; @@ -2467,10 +2467,10 @@ "Message reactions" = "Üzenetreakciók"; /* No comment provided by engineer. */ -"Message reactions are prohibited in this chat." = "Az üzenetreakciók ebben a csevegésben le vannak tiltva."; +"Message reactions are prohibited in this chat." = "Az üzenetreakciók küldése le van tiltva ebben a csevegésben."; /* No comment provided by engineer. */ -"Message reactions are prohibited in this group." = "Ebben a csoportban az üzenetreakciók le vannak tiltva."; +"Message reactions are prohibited in this group." = "Az üzenetreakciók küldése le van tiltva ebben a csoportban."; /* notification */ "message received" = "üzenet érkezett"; @@ -2568,9 +2568,6 @@ /* item status description */ "Most likely this connection is deleted." = "Valószínűleg ez a kapcsolat törlésre került."; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "Valószínűleg ez az ismerős törölte önnel a kapcsolatot."; - /* No comment provided by engineer. */ "Multiple chat profiles" = "Több csevegőprofil"; @@ -2775,7 +2772,7 @@ "Only your contact can make calls." = "Csak az ismerős tud hívást indítani."; /* No comment provided by engineer. */ -"Only your contact can send disappearing messages." = "Csak az ismerős tud eltűnő üzeneteket küldeni."; +"Only your contact can send disappearing messages." = "Csak az ismerőse tud eltűnő üzeneteket küldeni."; /* No comment provided by engineer. */ "Only your contact can send voice messages." = "Csak az ismerős tud hangüzeneteket küldeni."; @@ -2976,22 +2973,22 @@ "Profile update will be sent to your contacts." = "A profilfrissítés elküldésre került az ismerősök számára."; /* No comment provided by engineer. */ -"Prohibit audio/video calls." = "Hang- és videóhívások tiltása."; +"Prohibit audio/video calls." = "A hívások kezdeményezése le van tiltva."; /* No comment provided by engineer. */ "Prohibit irreversible message deletion." = "Az üzenetek véglegesen való törlése le van tiltva."; /* No comment provided by engineer. */ -"Prohibit message reactions." = "Üzenetreakciók tiltása."; +"Prohibit message reactions." = "Az üzenetreakciók küldése le van tiltva."; /* No comment provided by engineer. */ "Prohibit messages reactions." = "Az üzenetreakciók tiltása."; /* No comment provided by engineer. */ -"Prohibit sending direct messages to members." = "Közvetlen üzenetek küldésének letiltása a tagok számára."; +"Prohibit sending direct messages to members." = "A közvetlen üzenetek küldése le van tiltva a tagok között."; /* No comment provided by engineer. */ -"Prohibit sending disappearing messages." = "Eltűnő üzenetek küldésének letiltása."; +"Prohibit sending disappearing messages." = "Az eltűnő üzenetek küldése le van tiltva."; /* No comment provided by engineer. */ "Prohibit sending files and media." = "Fájlok- és a médiatartalom küldés letiltása."; @@ -3000,7 +2997,7 @@ "Prohibit sending SimpleX links." = "A SimpleX hivatkozások küldése le van tiltva."; /* No comment provided by engineer. */ -"Prohibit sending voice messages." = "Hangüzenetek küldésének letiltása."; +"Prohibit sending voice messages." = "A hangüzenetek küldése le van tiltva."; /* No comment provided by engineer. */ "Protect app screen" = "Alkalmazás képernyőjének védelme"; @@ -3077,9 +3074,6 @@ /* No comment provided by engineer. */ "Receiving address will be changed to a different server. Address change will complete after sender comes online." = "A fogadó cím egy másik kiszolgálóra változik. A címváltoztatás a feladó online állapotba kerülése után fejeződik be."; -/* No comment provided by engineer. */ -"Receiving concurrency" = "Egyidejű fogadás"; - /* No comment provided by engineer. */ "Receiving file will be stopped." = "A fájl fogadása leállt."; @@ -3132,10 +3126,10 @@ "Remove" = "Eltávolítás"; /* No comment provided by engineer. */ -"Remove member" = "Tag eltávolítása"; +"Remove member" = "Eltávolítás"; /* No comment provided by engineer. */ -"Remove member?" = "Tag eltávolítása?"; +"Remove member?" = "Biztosan eltávolítja?"; /* No comment provided by engineer. */ "Remove passphrase from keychain?" = "Jelmondat eltávolítása a kulcstárolóból?"; @@ -3306,7 +3300,7 @@ "Saved WebRTC ICE servers will be removed" = "A mentett WebRTC ICE kiszolgálók eltávolításra kerülnek"; /* No comment provided by engineer. */ -"Scan code" = "Kód beolvasása"; +"Scan code" = "Beolvasás"; /* No comment provided by engineer. */ "Scan QR code" = "QR-kód beolvasása"; @@ -3411,7 +3405,7 @@ "Send up to 100 last messages to new members." = "Az utolsó 100 üzenet elküldése az új tagoknak."; /* No comment provided by engineer. */ -"Sender cancelled file transfer." = "A küldő megszakította a fájl átvitelt."; +"Sender cancelled file transfer." = "A fájl küldője visszavonta az átvitelt."; /* No comment provided by engineer. */ "Sender may have deleted the connection request." = "A küldő törölhette a kapcsolódási kérelmet."; @@ -3570,7 +3564,7 @@ "SimpleX links" = "SimpleX hivatkozások"; /* No comment provided by engineer. */ -"SimpleX links are prohibited in this group." = "A SimpleX hivatkozások küldése ebben a csoportban le van tiltva."; +"SimpleX links are prohibited in this group." = "A SimpleX hivatkozások küldése le van tiltva ebben a csoportban."; /* No comment provided by engineer. */ "SimpleX links not allowed" = "A SimpleX hivatkozások küldése le van tiltva"; @@ -3753,7 +3747,7 @@ "The code you scanned is not a SimpleX link QR code." = "A beolvasott kód nem egy SimpleX hivatkozás QR-kód."; /* No comment provided by engineer. */ -"The connection you accepted will be cancelled!" = "Az ön által elfogadott kapcsolat megszakad!"; +"The connection you accepted will be cancelled!" = "Az ön által elfogadott kapcsolat vissza lesz vonva!"; /* No comment provided by engineer. */ "The contact you shared this link with will NOT be able to connect!" = "Ismerőse, akivel megosztotta ezt a hivatkozást, NEM fog tudni kapcsolódni!"; @@ -3920,9 +3914,6 @@ /* rcv group event chat item */ "unblocked %@" = "%@ feloldva"; -/* item status description */ -"Unexpected error: %@" = "Váratlan hiba: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "Váratlan átköltöztetési állapot"; @@ -3999,7 +3990,7 @@ "Update transport isolation mode?" = "Kapcsolat izolációs mód frissítése?"; /* rcv group event chat item */ -"updated group profile" = "módosított csoport profil"; +"updated group profile" = "frissítette a csoport profilját"; /* profile update event chat item */ "updated profile" = "frissített profil"; @@ -4137,7 +4128,7 @@ "Voice messages" = "Hangüzenetek"; /* No comment provided by engineer. */ -"Voice messages are prohibited in this chat." = "A hangüzenetek le vannak tiltva ebben a csevegésben."; +"Voice messages are prohibited in this chat." = "A hangüzenetek küldése le van tiltva ebben a csevegésben."; /* No comment provided by engineer. */ "Voice messages are prohibited in this group." = "A hangüzenetek küldése le van tiltva ebben a csoportban."; @@ -4149,7 +4140,7 @@ "Voice messages prohibited!" = "A hangüzenetek le vannak tilva!"; /* No comment provided by engineer. */ -"waiting for answer…" = "várakozás válaszra…"; +"waiting for answer…" = "várakozás a válaszra…"; /* No comment provided by engineer. */ "waiting for confirmation…" = "várakozás a visszaigazolásra…"; @@ -4461,7 +4452,7 @@ "Your chat profiles" = "Csevegési profiljai"; /* No comment provided by engineer. */ -"Your contact needs to be online for the connection to complete.\nYou can cancel this connection and remove the contact (and try later with a new link)." = "Az ismerősnek online kell lennie ahhoz, hogy a kapcsolat létrejöjjön.\nMegszakíthatja ezt a kapcsolatfelvételt és törölheti az ismerőst (ezt később ismét megpróbálhatja egy új hivatkozással)."; +"Your contact needs to be online for the connection to complete.\nYou can cancel this connection and remove the contact (and try later with a new link)." = "Az ismerősének online kell lennie ahhoz, hogy a kapcsolat létrejöjjön.\nVisszavonhatja ezt a kapcsolatfelvételt és törölheti az ismerőst (ezt később ismét megpróbálhatja egy új hivatkozással)."; /* No comment provided by engineer. */ "Your contact sent a file that is larger than currently supported maximum size (%@)." = "Ismerőse olyan fájlt küldött, amely meghaladja a jelenleg támogatott maximális méretet (%@)."; diff --git a/apps/ios/it.lproj/Localizable.strings b/apps/ios/it.lproj/Localizable.strings index e27b2e04a8..15bef7719e 100644 --- a/apps/ios/it.lproj/Localizable.strings +++ b/apps/ios/it.lproj/Localizable.strings @@ -1779,7 +1779,7 @@ /* No comment provided by engineer. */ "Error: " = "Errore: "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "Errore: %@"; /* No comment provided by engineer. */ @@ -2568,9 +2568,6 @@ /* item status description */ "Most likely this connection is deleted." = "Probabilmente questa connessione è stata eliminata."; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "Probabilmente questo contatto ha eliminato la connessione con te."; - /* No comment provided by engineer. */ "Multiple chat profiles" = "Profili di chat multipli"; @@ -3077,9 +3074,6 @@ /* No comment provided by engineer. */ "Receiving address will be changed to a different server. Address change will complete after sender comes online." = "L'indirizzo di ricezione verrà cambiato in un server diverso. La modifica dell'indirizzo verrà completata dopo che il mittente sarà in linea."; -/* No comment provided by engineer. */ -"Receiving concurrency" = "Ricezione concomitanza"; - /* No comment provided by engineer. */ "Receiving file will be stopped." = "La ricezione del file verrà interrotta."; @@ -3920,9 +3914,6 @@ /* rcv group event chat item */ "unblocked %@" = "ha sbloccato %@"; -/* item status description */ -"Unexpected error: %@" = "Errore imprevisto: % @"; - /* No comment provided by engineer. */ "Unexpected migration state" = "Stato di migrazione imprevisto"; diff --git a/apps/ios/ja.lproj/Localizable.strings b/apps/ios/ja.lproj/Localizable.strings index f8bacda7b8..bfb6ef4a3a 100644 --- a/apps/ios/ja.lproj/Localizable.strings +++ b/apps/ios/ja.lproj/Localizable.strings @@ -1509,7 +1509,7 @@ /* No comment provided by engineer. */ "Error: " = "エラー : "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "エラー : %@"; /* No comment provided by engineer. */ @@ -2130,9 +2130,6 @@ /* item status description */ "Most likely this connection is deleted." = "おそらく、この接続は削除されています。"; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "恐らくこの連絡先があなたとの接続を削除しました。"; - /* No comment provided by engineer. */ "Multiple chat profiles" = "複数チャットのプロフィール"; @@ -3191,9 +3188,6 @@ /* No comment provided by engineer. */ "Unable to record voice message" = "音声メッセージを録音できません"; -/* item status description */ -"Unexpected error: %@" = "予期しないエラー: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "予期しない移行状態"; diff --git a/apps/ios/nl.lproj/Localizable.strings b/apps/ios/nl.lproj/Localizable.strings index e12b8058f6..e19473fe4b 100644 --- a/apps/ios/nl.lproj/Localizable.strings +++ b/apps/ios/nl.lproj/Localizable.strings @@ -1779,7 +1779,7 @@ /* No comment provided by engineer. */ "Error: " = "Fout: "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "Fout: %@"; /* No comment provided by engineer. */ @@ -2568,9 +2568,6 @@ /* item status description */ "Most likely this connection is deleted." = "Hoogstwaarschijnlijk is deze verbinding verwijderd."; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "Hoogstwaarschijnlijk heeft dit contact de verbinding met jou verwijderd."; - /* No comment provided by engineer. */ "Multiple chat profiles" = "Meerdere chat profielen"; @@ -3077,9 +3074,6 @@ /* No comment provided by engineer. */ "Receiving address will be changed to a different server. Address change will complete after sender comes online." = "Het ontvangstadres wordt gewijzigd naar een andere server. Adres wijziging wordt voltooid nadat de afzender online is."; -/* No comment provided by engineer. */ -"Receiving concurrency" = "Gelijktijdig ontvangen"; - /* No comment provided by engineer. */ "Receiving file will be stopped." = "Het ontvangen van het bestand wordt gestopt."; @@ -3920,9 +3914,6 @@ /* rcv group event chat item */ "unblocked %@" = "gedeblokkeerd %@"; -/* item status description */ -"Unexpected error: %@" = "Onverwachte fout: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "Onverwachte migratiestatus"; diff --git a/apps/ios/pl.lproj/Localizable.strings b/apps/ios/pl.lproj/Localizable.strings index 15262085eb..bd534a77e9 100644 --- a/apps/ios/pl.lproj/Localizable.strings +++ b/apps/ios/pl.lproj/Localizable.strings @@ -1779,7 +1779,7 @@ /* No comment provided by engineer. */ "Error: " = "Błąd: "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "Błąd: %@"; /* No comment provided by engineer. */ @@ -2568,9 +2568,6 @@ /* item status description */ "Most likely this connection is deleted." = "Najprawdopodobniej to połączenie jest usunięte."; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "Najprawdopodobniej ten kontakt usunął połączenie z Tobą."; - /* No comment provided by engineer. */ "Multiple chat profiles" = "Wiele profili czatu"; @@ -3077,9 +3074,6 @@ /* No comment provided by engineer. */ "Receiving address will be changed to a different server. Address change will complete after sender comes online." = "Adres odbiorczy zostanie zmieniony na inny serwer. Zmiana adresu zostanie zakończona gdy nadawca będzie online."; -/* No comment provided by engineer. */ -"Receiving concurrency" = "Konkurencyjne odbieranie"; - /* No comment provided by engineer. */ "Receiving file will be stopped." = "Odbieranie pliku zostanie przerwane."; @@ -3920,9 +3914,6 @@ /* rcv group event chat item */ "unblocked %@" = "odblokowano %@"; -/* item status description */ -"Unexpected error: %@" = "Nieoczekiwany błąd: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "Nieoczekiwany stan migracji"; diff --git a/apps/ios/ru.lproj/Localizable.strings b/apps/ios/ru.lproj/Localizable.strings index 2c703f0095..baa9f89eac 100644 --- a/apps/ios/ru.lproj/Localizable.strings +++ b/apps/ios/ru.lproj/Localizable.strings @@ -1779,7 +1779,7 @@ /* No comment provided by engineer. */ "Error: " = "Ошибка: "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "Ошибка: %@"; /* No comment provided by engineer. */ @@ -2568,9 +2568,6 @@ /* item status description */ "Most likely this connection is deleted." = "Скорее всего, соединение удалено."; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "Скорее всего, этот контакт удалил соединение с Вами."; - /* No comment provided by engineer. */ "Multiple chat profiles" = "Много профилей чата"; @@ -3077,9 +3074,6 @@ /* No comment provided by engineer. */ "Receiving address will be changed to a different server. Address change will complete after sender comes online." = "Адрес получения сообщений будет перемещён на другой сервер. Изменение адреса завершится после того как отправитель будет онлайн."; -/* No comment provided by engineer. */ -"Receiving concurrency" = "Одновременный приём"; - /* No comment provided by engineer. */ "Receiving file will be stopped." = "Приём файла будет прекращён."; @@ -3920,9 +3914,6 @@ /* rcv group event chat item */ "unblocked %@" = "%@ разблокирован"; -/* item status description */ -"Unexpected error: %@" = "Неожиданная ошибка: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "Неожиданная ошибка при перемещении данных чата"; diff --git a/apps/ios/th.lproj/Localizable.strings b/apps/ios/th.lproj/Localizable.strings index 93c56a730d..fa31dccf96 100644 --- a/apps/ios/th.lproj/Localizable.strings +++ b/apps/ios/th.lproj/Localizable.strings @@ -1386,7 +1386,7 @@ /* No comment provided by engineer. */ "Error: " = "ผิดพลาด: "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "ข้อผิดพลาด: % @"; /* No comment provided by engineer. */ @@ -1998,9 +1998,6 @@ /* No comment provided by engineer. */ "More improvements are coming soon!" = "การปรับปรุงเพิ่มเติมกำลังจะมาเร็ว ๆ นี้!"; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "เป็นไปได้มากว่าผู้ติดต่อนี้ได้ลบการเชื่อมต่อกับคุณ"; - /* No comment provided by engineer. */ "Multiple chat profiles" = "โปรไฟล์การแชทหลายรายการ"; @@ -3050,9 +3047,6 @@ /* No comment provided by engineer. */ "Unable to record voice message" = "ไม่สามารถบันทึกข้อความเสียง"; -/* item status description */ -"Unexpected error: %@" = "ข้อผิดพลาดที่ไม่คาดคิด: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "สถานะการย้ายข้อมูลที่ไม่คาดคิด"; diff --git a/apps/ios/tr.lproj/Localizable.strings b/apps/ios/tr.lproj/Localizable.strings index 714a1bc739..0350dc836c 100644 --- a/apps/ios/tr.lproj/Localizable.strings +++ b/apps/ios/tr.lproj/Localizable.strings @@ -1779,7 +1779,7 @@ /* No comment provided by engineer. */ "Error: " = "Hata: "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "Hata: %@"; /* No comment provided by engineer. */ @@ -2568,9 +2568,6 @@ /* item status description */ "Most likely this connection is deleted." = "Büyük ihtimalle bu bağlantı silinmiş."; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "Büyük ihtimalle bu kişi seninle bağlantını sildi."; - /* No comment provided by engineer. */ "Multiple chat profiles" = "Çoklu sohbet profili"; @@ -3077,9 +3074,6 @@ /* No comment provided by engineer. */ "Receiving address will be changed to a different server. Address change will complete after sender comes online." = "Alıcı adresi farklı bir sunucuya değiştirilecektir. Gönderici çevrimiçi olduktan sonra adres değişikliği tamamlanacaktır."; -/* No comment provided by engineer. */ -"Receiving concurrency" = "Eşzamanlılık alınıyor"; - /* No comment provided by engineer. */ "Receiving file will be stopped." = "Dosya alımı durdurulacaktır."; @@ -3920,9 +3914,6 @@ /* rcv group event chat item */ "unblocked %@" = "engeli kaldırıldı %@"; -/* item status description */ -"Unexpected error: %@" = "Beklenmeyen hata: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "Beklenmeyen geçiş durumu"; diff --git a/apps/ios/uk.lproj/Localizable.strings b/apps/ios/uk.lproj/Localizable.strings index d52efd2b65..488a2b1c82 100644 --- a/apps/ios/uk.lproj/Localizable.strings +++ b/apps/ios/uk.lproj/Localizable.strings @@ -1761,7 +1761,7 @@ /* No comment provided by engineer. */ "Error: " = "Помилка: "; -/* No comment provided by engineer. */ +/* snd error text */ "Error: %@" = "Помилка: %@"; /* No comment provided by engineer. */ @@ -2520,9 +2520,6 @@ /* item status description */ "Most likely this connection is deleted." = "Швидше за все, це з'єднання видалено."; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "Швидше за все, цей контакт видалив зв'язок з вами."; - /* No comment provided by engineer. */ "Multiple chat profiles" = "Кілька профілів чату"; @@ -3821,9 +3818,6 @@ /* rcv group event chat item */ "unblocked %@" = "розблоковано %@"; -/* item status description */ -"Unexpected error: %@" = "Неочікувана помилка: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "Неочікуваний стан міграції"; diff --git a/apps/ios/zh-Hans.lproj/Localizable.strings b/apps/ios/zh-Hans.lproj/Localizable.strings index 5af77e4e51..74d9970b93 100644 --- a/apps/ios/zh-Hans.lproj/Localizable.strings +++ b/apps/ios/zh-Hans.lproj/Localizable.strings @@ -353,6 +353,12 @@ /* member role */ "admin" = "管理员"; +/* feature role */ +"admins" = "管理员"; + +/* No comment provided by engineer. */ +"Admins can block a member for all." = "管理员可以为所有人封禁一名成员。"; + /* No comment provided by engineer. */ "Admins can create the links to join groups." = "管理员可以创建链接以加入群组。"; @@ -377,6 +383,9 @@ /* No comment provided by engineer. */ "All group members will remain connected." = "所有群组成员将保持连接。"; +/* feature role */ +"all members" = "所有成员"; + /* No comment provided by engineer. */ "All messages will be deleted - this cannot be undone!" = "所有消息都将被删除 - 这无法被撤销!"; @@ -389,6 +398,9 @@ /* No comment provided by engineer. */ "All your contacts will remain connected. Profile update will be sent to your contacts." = "您的所有联系人将保持连接。个人资料更新将发送给您的联系人。"; +/* No comment provided by engineer. */ +"All your contacts, conversations and files will be securely encrypted and uploaded in chunks to configured XFTP relays." = "你的所有联系人、对话和文件将被安全加密并分块上传到配置的 XFTP 中继。"; + /* No comment provided by engineer. */ "Allow" = "允许"; @@ -419,6 +431,9 @@ /* No comment provided by engineer. */ "Allow to send files and media." = "允许发送文件和媒体。"; +/* No comment provided by engineer. */ +"Allow to send SimpleX links." = "允许发送 SimpleX 链接。"; + /* No comment provided by engineer. */ "Allow to send voice messages." = "允许发送语音消息。"; @@ -467,6 +482,9 @@ /* No comment provided by engineer. */ "App build: %@" = "应用程序构建:%@"; +/* No comment provided by engineer. */ +"App data migration" = "应用数据迁移"; + /* No comment provided by engineer. */ "App encrypts new local files (except videos)." = "应用程序为新的本地文件(视频除外)加密。"; @@ -488,6 +506,15 @@ /* No comment provided by engineer. */ "Appearance" = "外观"; +/* No comment provided by engineer. */ +"Apply" = "应用"; + +/* No comment provided by engineer. */ +"Archive and upload" = "存档和上传"; + +/* No comment provided by engineer. */ +"Archiving database" = "正在存档数据库"; + /* No comment provided by engineer. */ "Attach" = "附件"; @@ -635,6 +662,9 @@ /* No comment provided by engineer. */ "Cancel" = "取消"; +/* No comment provided by engineer. */ +"Cancel migration" = "取消迁移"; + /* feature offered item */ "cancelled %@" = "已取消 %@"; @@ -644,6 +674,9 @@ /* No comment provided by engineer. */ "Cannot receive file" = "无法接收文件"; +/* No comment provided by engineer. */ +"Cellular" = "移动网络"; + /* No comment provided by engineer. */ "Change" = "更改"; @@ -714,6 +747,9 @@ /* No comment provided by engineer. */ "Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." = "聊天已停止。如果你已经在另一台设备商使用过此数据库,你应该在启动聊天前将数据库传输回来。"; +/* No comment provided by engineer. */ +"Chat migrated!" = "已迁移聊天!"; + /* No comment provided by engineer. */ "Chat preferences" = "聊天偏好设置"; @@ -771,6 +807,9 @@ /* No comment provided by engineer. */ "Confirm database upgrades" = "确认数据库升级"; +/* No comment provided by engineer. */ +"Confirm network settings" = "确认网络设置"; + /* No comment provided by engineer. */ "Confirm new passphrase…" = "确认新密码……"; @@ -780,6 +819,12 @@ /* No comment provided by engineer. */ "Confirm password" = "确认密码"; +/* No comment provided by engineer. */ +"Confirm that you remember database passphrase to migrate it." = "请在迁移前确认你记得数据库的密码短语。"; + +/* No comment provided by engineer. */ +"Confirm upload" = "确认上传"; + /* server test step */ "Connect" = "连接"; @@ -957,6 +1002,9 @@ /* No comment provided by engineer. */ "Created on %@" = "创建于 %@"; +/* No comment provided by engineer. */ +"Creating archive link" = "正在创建存档链接"; + /* No comment provided by engineer. */ "Creating link…" = "创建链接中…"; @@ -1098,6 +1146,9 @@ /* No comment provided by engineer. */ "Delete database" = "删除数据库"; +/* No comment provided by engineer. */ +"Delete database from this device" = "从这部设备上删除数据库"; + /* server test step */ "Delete file" = "删除文件"; @@ -1287,9 +1338,21 @@ /* No comment provided by engineer. */ "Downgrade and open chat" = "降级并打开聊天"; +/* chat item action */ +"Download" = "下载"; + +/* No comment provided by engineer. */ +"Download failed" = "下载失败了"; + /* server test step */ "Download file" = "下载文件"; +/* No comment provided by engineer. */ +"Downloading archive" = "正在下载存档"; + +/* No comment provided by engineer. */ +"Downloading link details" = "正在下载链接详情"; + /* No comment provided by engineer. */ "Duplicate display name!" = "重复的显示名!"; @@ -1323,6 +1386,9 @@ /* No comment provided by engineer. */ "Enable for all" = "全部启用"; +/* No comment provided by engineer. */ +"Enable in direct chats (BETA)!" = "在私聊中开启(公测)!"; + /* No comment provided by engineer. */ "Enable instant notifications?" = "启用即时通知?"; @@ -1350,6 +1416,9 @@ /* enabled status */ "enabled" = "已启用"; +/* No comment provided by engineer. */ +"Enabled for" = "启用对象"; + /* enabled status */ "enabled for contact" = "已为联系人启用"; @@ -1431,6 +1500,9 @@ /* No comment provided by engineer. */ "Enter Passcode" = "输入密码"; +/* No comment provided by engineer. */ +"Enter passphrase" = "输入密码短语"; + /* No comment provided by engineer. */ "Enter passphrase…" = "输入密码……"; @@ -1521,6 +1593,9 @@ /* No comment provided by engineer. */ "Error deleting user profile" = "删除用户资料错误"; +/* No comment provided by engineer. */ +"Error downloading the archive" = "下载存档出错"; + /* No comment provided by engineer. */ "Error enabling delivery receipts!" = "启用送达回执出错!"; @@ -1563,6 +1638,9 @@ /* No comment provided by engineer. */ "Error saving passphrase to keychain" = "保存密码到钥匙串错误"; +/* when migrating */ +"Error saving settings" = "保存设置出错"; + /* No comment provided by engineer. */ "Error saving user password" = "保存用户密码时出错"; @@ -1603,9 +1681,15 @@ "Error updating user privacy" = "更新用户隐私时出错"; /* No comment provided by engineer. */ -"Error: " = "错误: "; +"Error uploading the archive" = "上传存档出错"; /* No comment provided by engineer. */ +"Error verifying passphrase:" = "验证密码短语出错:"; + +/* No comment provided by engineer. */ +"Error: " = "错误: "; + +/* snd error text */ "Error: %@" = "错误: %@"; /* No comment provided by engineer. */ @@ -1635,6 +1719,9 @@ /* No comment provided by engineer. */ "Exported database archive." = "导出数据库归档。"; +/* No comment provided by engineer. */ +"Exported file doesn't exist" = "导出的文件不存在"; + /* No comment provided by engineer. */ "Exporting database archive…" = "导出数据库档案中…"; @@ -1671,12 +1758,21 @@ /* No comment provided by engineer. */ "Files and media are prohibited in this group." = "此群组中禁止文件和媒体。"; +/* No comment provided by engineer. */ +"Files and media not allowed" = "不允许文件和媒体"; + /* No comment provided by engineer. */ "Files and media prohibited!" = "禁止文件和媒体!"; /* No comment provided by engineer. */ "Filter unread and favorite chats." = "过滤未读和收藏的聊天记录。"; +/* No comment provided by engineer. */ +"Finalize migration" = "完成迁移"; + +/* No comment provided by engineer. */ +"Finalize migration on another device." = "在另一部设备上完成迁移"; + /* No comment provided by engineer. */ "Finally, we have them! 🚀" = "终于我们有它们了! 🚀"; @@ -1704,6 +1800,21 @@ /* No comment provided by engineer. */ "For console" = "用于控制台"; +/* chat item action */ +"Forward" = "转发"; + +/* No comment provided by engineer. */ +"Forward and save messages" = "转发并保存消息"; + +/* No comment provided by engineer. */ +"forwarded" = "已转发"; + +/* No comment provided by engineer. */ +"Forwarded" = "已转发"; + +/* No comment provided by engineer. */ +"Forwarded from" = "转发自"; + /* No comment provided by engineer. */ "Found desktop" = "找到了桌面"; @@ -1779,6 +1890,9 @@ /* No comment provided by engineer. */ "Group members can send files and media." = "群组成员可以发送文件和媒体。"; +/* No comment provided by engineer. */ +"Group members can send SimpleX links." = "群成员可发送 SimpleX 链接。"; + /* No comment provided by engineer. */ "Group members can send voice messages." = "群组成员可以发送语音消息。"; @@ -1896,6 +2010,12 @@ /* No comment provided by engineer. */ "Import database" = "导入数据库"; +/* No comment provided by engineer. */ +"Import failed" = "导入失败了"; + +/* No comment provided by engineer. */ +"Importing archive" = "正在导入存档"; + /* No comment provided by engineer. */ "Improved message delivery" = "改进了消息传递"; @@ -1905,9 +2025,15 @@ /* No comment provided by engineer. */ "Improved server configuration" = "改进的服务器配置"; +/* No comment provided by engineer. */ +"In order to continue, chat should be stopped." = "必须停止聊天才能继续。"; + /* No comment provided by engineer. */ "In reply to" = "答复"; +/* No comment provided by engineer. */ +"In-call sounds" = "通话声音"; + /* No comment provided by engineer. */ "Incognito" = "隐身聊天"; @@ -1986,6 +2112,12 @@ /* No comment provided by engineer. */ "Invalid display name!" = "无效的显示名!"; +/* No comment provided by engineer. */ +"Invalid link" = "无效链接"; + +/* No comment provided by engineer. */ +"Invalid migration confirmation" = "迁移确认无效"; + /* No comment provided by engineer. */ "Invalid name!" = "无效名称!"; @@ -2232,18 +2364,45 @@ /* notification */ "message received" = "消息已收到"; +/* No comment provided by engineer. */ +"Message source remains private." = "消息来源保持私密。"; + /* No comment provided by engineer. */ "Message text" = "消息正文"; +/* No comment provided by engineer. */ +"Message too large" = "消息太大了"; + /* No comment provided by engineer. */ "Messages" = "消息"; /* No comment provided by engineer. */ "Messages & files" = "消息"; +/* No comment provided by engineer. */ +"Migrate device" = "迁移设备"; + +/* No comment provided by engineer. */ +"Migrate from another device" = "从另一台设备迁移"; + +/* No comment provided by engineer. */ +"Migrate here" = "迁移到此处"; + +/* No comment provided by engineer. */ +"Migrate to another device" = "迁移到另一部设备"; + +/* No comment provided by engineer. */ +"Migrate to another device via QR code." = "通过二维码迁移到另一部设备。"; + +/* No comment provided by engineer. */ +"Migrating" = "迁移中"; + /* No comment provided by engineer. */ "Migrating database archive…" = "迁移数据库档案中…"; +/* No comment provided by engineer. */ +"Migration complete" = "迁移完毕"; + /* No comment provided by engineer. */ "Migration error:" = "迁移错误:"; @@ -2283,12 +2442,12 @@ /* No comment provided by engineer. */ "More improvements are coming soon!" = "更多改进即将推出!"; +/* No comment provided by engineer. */ +"More reliable network connection." = "更可靠的网络连接。"; + /* item status description */ "Most likely this connection is deleted." = "此连接很可能已被删除。"; -/* No comment provided by engineer. */ -"Most likely this contact has deleted the connection with you." = "很可能此联系人已经删除了与您的联系。"; - /* No comment provided by engineer. */ "Multiple chat profiles" = "多个聊天资料"; @@ -2304,6 +2463,12 @@ /* No comment provided by engineer. */ "Network & servers" = "网络和服务器"; +/* No comment provided by engineer. */ +"Network connection" = "网络连接"; + +/* No comment provided by engineer. */ +"Network management" = "网络管理"; + /* No comment provided by engineer. */ "Network settings" = "网络设置"; @@ -2382,6 +2547,9 @@ /* No comment provided by engineer. */ "No history" = "无历史记录"; +/* No comment provided by engineer. */ +"No network connection" = "无网络连接"; + /* No comment provided by engineer. */ "No permission to record voice message" = "没有录制语音消息的权限"; @@ -2510,15 +2678,27 @@ /* No comment provided by engineer. */ "Open-source protocol and code – anybody can run the servers." = "开源协议和代码——任何人都可以运行服务器。"; +/* No comment provided by engineer. */ +"Or paste archive link" = "或粘贴存档链接"; + /* No comment provided by engineer. */ "Or scan QR code" = "或者扫描二维码"; +/* No comment provided by engineer. */ +"Or securely share this file link" = "或安全地分享此文件链接"; + /* No comment provided by engineer. */ "Or show this code" = "或者显示此码"; +/* No comment provided by engineer. */ +"Other" = "其他"; + /* member role */ "owner" = "群主"; +/* feature role */ +"owners" = "所有者"; + /* No comment provided by engineer. */ "Passcode" = "密码"; @@ -2561,6 +2741,9 @@ /* message decrypt error item */ "Permanent decryption error" = "解密错误"; +/* No comment provided by engineer. */ +"Picture-in-picture calls" = "画中画通话"; + /* No comment provided by engineer. */ "PING count" = "PING 次数"; @@ -2579,6 +2762,9 @@ /* No comment provided by engineer. */ "Please check yours and your contact preferences." = "请检查您和您的联系人偏好设置。"; +/* No comment provided by engineer. */ +"Please confirm that network settings are correct for this device." = "请确认网络设置对此这台设备正确无误。"; + /* No comment provided by engineer. */ "Please contact group admin." = "请联系群组管理员。"; @@ -2639,6 +2825,9 @@ /* No comment provided by engineer. */ "Profile image" = "资料图片"; +/* No comment provided by engineer. */ +"Profile images" = "个人资料图"; + /* No comment provided by engineer. */ "Profile name:" = "显示名:"; @@ -2687,6 +2876,12 @@ /* No comment provided by engineer. */ "Push notifications" = "推送通知"; +/* chat item text */ +"quantum resistant e2e encryption" = "抗量子端到端加密"; + +/* No comment provided by engineer. */ +"Quantum resistant encryption" = "抗量子加密"; + /* No comment provided by engineer. */ "Rate the app" = "评价此应用程序"; @@ -2744,6 +2939,9 @@ /* No comment provided by engineer. */ "Receiving via" = "接收通过"; +/* No comment provided by engineer. */ +"Recipient(s) can't see who this message is from." = "收件人看不到这条消息来自何人。"; + /* No comment provided by engineer. */ "Recipients see updates as you type them." = "对方会在您键入时看到更新。"; @@ -2819,9 +3017,18 @@ /* No comment provided by engineer. */ "Repeat connection request?" = "重复连接请求吗?"; +/* No comment provided by engineer. */ +"Repeat download" = "重复下载"; + +/* No comment provided by engineer. */ +"Repeat import" = "重复导入"; + /* No comment provided by engineer. */ "Repeat join request?" = "重复加入请求吗?"; +/* No comment provided by engineer. */ +"Repeat upload" = "重复上传"; + /* chat item action */ "Reply" = "回复"; @@ -2879,6 +3086,9 @@ /* No comment provided by engineer. */ "Run chat" = "运行聊天程序"; +/* No comment provided by engineer. */ +"Safer groups" = "更安全的群组"; + /* chat item action */ "Save" = "保存"; @@ -2927,6 +3137,15 @@ /* No comment provided by engineer. */ "Save welcome message?" = "保存欢迎信息?"; +/* No comment provided by engineer. */ +"saved" = "已保存"; + +/* No comment provided by engineer. */ +"Saved" = "已保存"; + +/* No comment provided by engineer. */ +"Saved from" = "保存自"; + /* message info title */ "Saved message" = "已保存的消息"; @@ -3119,6 +3338,9 @@ /* No comment provided by engineer. */ "Set passcode" = "设置密码"; +/* No comment provided by engineer. */ +"Set passphrase" = "设置密码短语"; + /* No comment provided by engineer. */ "Set passphrase to export" = "设置密码来导出"; @@ -3131,6 +3353,9 @@ /* No comment provided by engineer. */ "Settings" = "设置"; +/* No comment provided by engineer. */ +"Shape profile images" = "改变个人资料图形状"; + /* chat item action */ "Share" = "分享"; @@ -3164,6 +3389,9 @@ /* No comment provided by engineer. */ "Show preview" = "显示预览"; +/* No comment provided by engineer. */ +"Show QR code" = "显示二维码"; + /* No comment provided by engineer. */ "Show:" = "显示:"; @@ -3188,6 +3416,12 @@ /* chat feature */ "SimpleX links" = "SimpleX 链接"; +/* No comment provided by engineer. */ +"SimpleX links are prohibited in this group." = "此群禁止 SimpleX 链接。"; + +/* No comment provided by engineer. */ +"SimpleX links not allowed" = "不允许SimpleX 链接"; + /* No comment provided by engineer. */ "SimpleX Lock" = "SimpleX 锁定"; @@ -3224,6 +3458,12 @@ /* notification title */ "Somebody" = "某人"; +/* No comment provided by engineer. */ +"Square, circle, or anything in between." = "方形、圆形、或两者之间的任意形状"; + +/* chat item text */ +"standard end-to-end encryption" = "标准端到端加密"; + /* No comment provided by engineer. */ "Start chat" = "开始聊天"; @@ -3239,6 +3479,9 @@ /* No comment provided by engineer. */ "Stop" = "停止"; +/* No comment provided by engineer. */ +"Stop chat" = "停止聊天程序"; + /* No comment provided by engineer. */ "Stop chat to enable database actions" = "停止聊天以启用数据库操作"; @@ -3266,6 +3509,9 @@ /* authentication reason */ "Stop SimpleX" = "停止 SimpleX"; +/* No comment provided by engineer. */ +"Stopping chat" = "正在停止聊天"; + /* No comment provided by engineer. */ "strike" = "删去"; @@ -3416,6 +3662,12 @@ /* No comment provided by engineer. */ "This action cannot be undone - your profile, contacts, messages and files will be irreversibly lost." = "此操作无法撤消——您的个人资料、联系人、消息和文件将不可撤回地丢失。"; +/* E2EE info chat item */ +"This chat is protected by end-to-end encryption." = "此聊天受端到端加密保护。"; + +/* E2EE info chat item */ +"This chat is protected by quantum resistant end-to-end encryption." = "此聊天受抗量子的端到端加密保护。"; + /* notification title */ "this contact" = "这个联系人"; @@ -3509,9 +3761,6 @@ /* No comment provided by engineer. */ "Unblock member?" = "解封成员吗?"; -/* item status description */ -"Unexpected error: %@" = "意外错误: %@"; - /* No comment provided by engineer. */ "Unexpected migration state" = "未预料的迁移状态"; @@ -3602,9 +3851,15 @@ /* No comment provided by engineer. */ "Upgrade and open chat" = "升级并打开聊天"; +/* No comment provided by engineer. */ +"Upload failed" = "上传失败了"; + /* server test step */ "Upload file" = "上传文件"; +/* No comment provided by engineer. */ +"Uploading archive" = "正在上传存档"; + /* No comment provided by engineer. */ "Use .onion hosts" = "使用 .onion 主机"; @@ -3632,6 +3887,9 @@ /* No comment provided by engineer. */ "Use SimpleX Chat servers?" = "使用 SimpleX Chat 服务器?"; +/* No comment provided by engineer. */ +"Use the app while in the call." = "通话时使用本应用"; + /* No comment provided by engineer. */ "User profile" = "用户资料"; @@ -3656,6 +3914,12 @@ /* No comment provided by engineer. */ "Verify connections" = "验证连接"; +/* No comment provided by engineer. */ +"Verify database passphrase" = "验证数据库密码短语"; + +/* No comment provided by engineer. */ +"Verify passphrase" = "验证密码短语"; + /* No comment provided by engineer. */ "Verify security code" = "验证安全码"; @@ -3710,6 +3974,9 @@ /* No comment provided by engineer. */ "Voice messages are prohibited in this group." = "语音信息在该群组中被禁用。"; +/* No comment provided by engineer. */ +"Voice messages not allowed" = "不允许语音消息"; + /* No comment provided by engineer. */ "Voice messages prohibited!" = "语音消息禁止发送!"; @@ -3731,6 +3998,9 @@ /* No comment provided by engineer. */ "wants to connect to you!" = "想要与您连接!"; +/* No comment provided by engineer. */ +"Warning: starting chat on multiple devices is not supported and will cause message delivery failures" = "警告:不支持在多部设备上启动聊天,这么做会导致消息传送失败。"; + /* No comment provided by engineer. */ "Warning: you may lose some data!" = "警告:您可能会丢失部分数据!"; @@ -3746,18 +4016,33 @@ /* No comment provided by engineer. */ "Welcome message" = "欢迎消息"; +/* No comment provided by engineer. */ +"Welcome message is too long" = "欢迎消息太大了"; + /* No comment provided by engineer. */ "What's new" = "更新内容"; /* No comment provided by engineer. */ "When available" = "当可用时"; +/* No comment provided by engineer. */ +"When connecting audio and video calls." = "连接音频和视频通话时。"; + /* No comment provided by engineer. */ "When people request to connect, you can accept or reject it." = "当人们请求连接时,您可以接受或拒绝它。"; /* No comment provided by engineer. */ "When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." = "当您与某人共享隐身聊天资料时,该资料将用于他们邀请您加入的群组。"; +/* No comment provided by engineer. */ +"WiFi" = "WiFi"; + +/* No comment provided by engineer. */ +"Will be enabled in direct chats!" = "将在私聊中启用!"; + +/* No comment provided by engineer. */ +"Wired ethernet" = "有线以太网"; + /* No comment provided by engineer. */ "With encrypted files and media." = "加密的文件和媒体。"; @@ -3779,6 +4064,9 @@ /* pref value */ "yes" = "是"; +/* No comment provided by engineer. */ +"you" = "您"; + /* No comment provided by engineer. */ "You" = "您"; @@ -3824,6 +4112,9 @@ /* No comment provided by engineer. */ "You can enable them later via app Privacy & Security settings." = "您可以稍后通过应用程序的 \"隐私与安全 \"设置启用它们。"; +/* No comment provided by engineer. */ +"You can give another try." = "你可以再试一次。"; + /* No comment provided by engineer. */ "You can hide or mute a user profile - swipe it to the right." = "您可以隐藏或静音用户个人资料——只需向右滑动。"; diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatWallpaper.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatWallpaper.kt index b06bc46202..89796baf4e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatWallpaper.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatWallpaper.kt @@ -22,13 +22,12 @@ import kotlin.math.* enum class PresetWallpaper( val res: ImageResource, val filename: String, - val text: StringResource, val scale: Float, val background: Map, val tint: Map, val colors: Map, ) { - CATS(MR.images.wallpaper_cats, "cats", MR.strings.wallpaper_cats, 0.63f, + CATS(MR.images.wallpaper_cats, "cats", 0.63f, wallpaperBackgrounds(light = "#ffF8F6EA"), tint = mapOf( DefaultTheme.LIGHT to "#ffefdca6".colorFromReadableHex(), @@ -63,7 +62,7 @@ enum class PresetWallpaper( ), ) ), - FLOWERS(MR.images.wallpaper_flowers, "flowers", MR.strings.wallpaper_flowers, 0.53f, + FLOWERS(MR.images.wallpaper_flowers, "flowers", 0.53f, wallpaperBackgrounds(light = "#ffE2FFE4"), tint = mapOf( DefaultTheme.LIGHT to "#ff9CEA59".colorFromReadableHex(), @@ -98,7 +97,7 @@ enum class PresetWallpaper( ), ) ), - HEARTS(MR.images.wallpaper_hearts, "hearts", MR.strings.wallpaper_hearts, 0.59f, + HEARTS(MR.images.wallpaper_hearts, "hearts", 0.59f, wallpaperBackgrounds(light = "#ffFDECEC"), tint = mapOf( DefaultTheme.LIGHT to "#fffde0e0".colorFromReadableHex(), @@ -133,7 +132,7 @@ enum class PresetWallpaper( ), ) ), - KIDS(MR.images.wallpaper_kids, "kids", MR.strings.wallpaper_kids, 0.53f, + KIDS(MR.images.wallpaper_kids, "kids", 0.53f, wallpaperBackgrounds(light = "#ffdbfdfb"), tint = mapOf( DefaultTheme.LIGHT to "#ffadeffc".colorFromReadableHex(), @@ -168,7 +167,7 @@ enum class PresetWallpaper( ), ) ), - SCHOOL(MR.images.wallpaper_school, "school", MR.strings.wallpaper_school, 0.53f, + SCHOOL(MR.images.wallpaper_school, "school", 0.53f, wallpaperBackgrounds(light = "#ffE7F5FF"), tint = mapOf( DefaultTheme.LIGHT to "#ffCEEBFF".colorFromReadableHex(), @@ -203,7 +202,7 @@ enum class PresetWallpaper( ), ) ), - TRAVEL(MR.images.wallpaper_travel, "travel", MR.strings.wallpaper_travel, 0.68f, + TRAVEL(MR.images.wallpaper_travel, "travel", 0.68f, wallpaperBackgrounds(light = "#fff9eeff"), tint = mapOf( DefaultTheme.LIGHT to "#ffeedbfe".colorFromReadableHex(), diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml index 0c4c4176a5..1a63ceb87b 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml @@ -1123,7 +1123,7 @@ السمات بفضل المستخدمين - المساهمة عبر Weblate! قاعدة البيانات لا تعمل بشكل صحيح. انقر لمعرفة المزيد - ألوان السمة + ألوان الواجهة انقر لتنشيط الملف الشخصي. عزل النقل هذه السلسلة ليست رابط اتصال! @@ -1766,4 +1766,73 @@ شكل الصور الشخصية واجهة المستخدم الليتوانية مربع أو دائرة أو أي شيء بينهما. + عنوان الخادم غير متوافق مع إعدادات الشبكة. + إصدار الخادم غير متوافق مع إعدادات الشبكة. + مفتاح خاطئ أو اتصال غير معروف - على الأرجح حُذف هذا الاتصال. + تم تجاوز السعة - لم يتلق المُستلم الرسائل المُرسلة مسبقًا. + خطأ في خادم الوجهة: %1$s + خطأ: %1$s + خادم إعادة التوجيه: %1$s +\nخطأ في الخادم الوجهة: %2$s + خادم إعادة التوجيه: %1$s +\nخطأ: %2$s + تحذير تسليم الرسالة + مشكلات الشبكة - انتهت صلاحية الرسالة بعد عِدة محاولات لإرسالها. + نعم + لحماية عنوان IP الخاص بك، يستخدم التوجيه الخاص خوادم SMP الخاصة بك لتسليم الرسائل. + توجيه الرسائل الخاصة + التوجيه الخاص + غير محمي + السماح بالرجوع إلى إصدار سابق + لا تستخدم التوجيه الخاص. + وضع توجيه الرسائل + لا + عندما يكون IP مخفيًا + لا ترسل رسائل مباشرةً، حتى لو كان خادمك أو خادم الوجهة لا يدعم التوجيه الخاص. + أرسل الرسائل مباشرة عندما لا يدعم الخادم الوجهة الخاص بك أو الخادم الوجهة التوجيه الخاص. + احتياطي توجيه الرسالة + أظهِر حالة الرسالة + احمِ عنوان IP + بدون تور أو VPN، سيكون عنوان IP الخاص بك مرئيًا لخوادم الملفات. + استخدم التوجيه الخاص مع خوادم غير معروفة. + استخدم التوجيه الخاص مع خوادم غير معروفة عندما لا يكون عنوان IP محميًا. + دائمًا + استخدم دائمًا التوجيه الخاص. + الملفات + مطلقًا + سيطلب التطبيق تأكيد التنزيلات من خوادم ملفات غير معروفة (باستثناء .onion أو عند تفعيل وكيل SOCKS). + أرسل الرسائل مباشرة عندما يكون عنوان IP محميًا ولا يدعم الخادم الوجهة لديك التوجيه الخاص. + مُرحلات غير معروفة + خوادم غير معروفة! + بدون تور أو VPN، سيكون عنوان IP الخاص بك مرئيًا لمُرحلات XFTP هذه: +\n%1$s. + أظهِر قائمة الدردشة في نافذة جديدة + ألوان الدردشة + سمة الدردشة + تلقى الرد + أزِل الصورة + تكرار + إعادة تعيين اللون + أرسلت رد + تعيين السمة الافتراضية + النظام + لون تمييز خلفية الشاشة + لون إضافي ثانوي 2 + الإعدادات المتقدمة + جميع أوضاع الألوان + أسود + وضع اللون + داكن + الوضع الداكن + ألوان الوضع الداكن + ملائمة + طاب يومك! + صباح الخير! + صورة خلفية الشاشة + الوضع الفاتح + السمة الملف الشخصي + فاتح + طبّق لِ + ملء + المقياس \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml index dca3e95156..123e9bc80d 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -1587,13 +1587,7 @@ Wallpaper accent Remove image - - Cats - Flowers - Hearts - Kids - School - Travel + Good afternoon! Good morning! Scale diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml index ccb703337c..e80b2d88ff 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml @@ -1769,4 +1769,6 @@ Kamera a mikrofon SimpleX odkazy jsou v této skupině zakázány. koncovým šifrováním s dokonalým dopředným utajením, odmítnutím a obnovením po vloupání.]]> + Pokročilé nastavení + Všechny barevné režimy \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml index 860759431a..7bb6aaa128 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml @@ -400,11 +400,11 @@ Wenn verfügbar Nein Erforderlich - Onion-Hosts werden verwendet, wenn sie verfügbar sind. + Wenn Onion-Hosts verfügbar sind, werden sie verwendet. Onion-Hosts werden nicht verwendet. Für die Verbindung werden Onion-Hosts benötigt. \nBitte beachten Sie: Ohne .onion-Adresse können Sie keine Verbindung mit den Servern herstellen. - Onion-Hosts werden verwendet, wenn sie verfügbar sind. + Wenn Onion-Hosts verfügbar sind, werden sie verwendet. Onion-Hosts werden nicht verwendet. Für die Verbindung werden Onion-Hosts benötigt. Erscheinungsbild @@ -502,7 +502,7 @@ Audio- & Videoanrufe Ihre Anrufe - Über ein Relais verbinden + Immer über ein Relais verbinden Anrufe auf Sperrbildschirm: Akzeptieren Anzeigen @@ -1207,7 +1207,7 @@ Wenn Personen eine Verbindung anfordern, können Sie diese annehmen oder ablehnen. Sie werden Ihre damit verbundenen Kontakte nicht verlieren, wenn Sie diese Adresse später löschen. Design anpassen - DESIGN-FARBEN + INTERFACE-FARBEN Fügen Sie die Adresse Ihrem Profil hinzu, damit Ihre Kontakte sie mit anderen Personen teilen können. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet. Alle Ihre Kontakte bleiben verbunden. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet. Erstellen Sie eine Adresse, damit sich Personen mit Ihnen verbinden können. @@ -1459,7 +1459,7 @@ Datenbank-Ordner öffnen Das Passwort wird in Klartext in den Einstellungen gespeichert, nachdem Sie es geändert oder die App neu gestartet haben. Das Passwort wurde in Klartext in den Einstellungen gespeichert. - Bitte beachten Sie: Die Nachrichten- und Dateirelais sind per SOCKS Proxy verbunden. Anrufe und gesendete Link-Vorschaubilder nutzen eine direkte Verbindung.]]> + Bitte beachten Sie: Die Nachrichten- und Datei-Relais sind per SOCKS-Proxy verbunden. Anrufe und gesendete Link-Vorschaubilder nutzen eine direkte Verbindung.]]> Lokale Dateien verschlüsseln Öffnen Gespeicherte Dateien & Medien verschlüsseln @@ -1528,7 +1528,7 @@ Freigeben Ungültiger Datei-Pfad Sie haben über diese Adresse bereits eine Verbindung beantragt! - Die Konsole in einem neuen Fenster anzeigen + Konsole in einem neuen Fenster anzeigen Von %s werden alle neuen Nachrichten ausgeblendet! Blockiert Fehler bei der Neuverhandlung der Verschlüsselung @@ -1669,7 +1669,7 @@ Ehemaliges Mitglied %1$s Die Ausführung dieser Funktion dauert zu lange: %1$d Sekunden: %2$s Langsame Funktion - Zeige langsame API-Aufrufe an + Langsame API-Aufrufe anzeigen unbekannt Optionen für Entwickler unbekannter Gruppenmitglieds-Status @@ -1728,7 +1728,7 @@ Link-Details werden heruntergeladen Archiv wird heruntergeladen Anwenden - Alle Ihre Kontakte, Unterhaltungen und Dateien werden sicher verschlüsselt und in Daten-Paketen auf die konfigurierten XTFP-Server hochgeladen. + Alle Ihre Kontakte, Unterhaltungen und Dateien werden sicher verschlüsselt und in Daten-Paketen auf die konfigurierten XTFP-Relais hochgeladen. Archivieren und Hochladen Warnung: Das Archiv wird gelöscht.]]> Überprüfen Sie Ihre Internet-Verbindung und probieren Sie es nochmals @@ -1849,4 +1849,73 @@ Profil-Bilder Form der Profil-Bilder Quadratisch, kreisförmig oder irgendetwas dazwischen. + Fehler auf dem Zielserver: %1$s + Fehler: %1$s + Warnung bei der Nachrichtenzustellung + Falscher Schlüssel oder unbekannte Verbindung - höchstwahrscheinlich ist diese Verbindung gelöscht. + Die Server-Version ist nicht mit den Netzwerk-Einstellungen kompatibel. + Kapazität überschritten - der Empfänger hat die zuvor gesendeten Nachrichten nicht empfangen. + Weiterleitungsserver: %1$s +\nFehler auf dem Zielserver: %2$s + Weiterleitungsserver: %1$s +\nFehler: %2$s + Netzwerk-Fehler - die Nachricht ist nach vielen Sende-Versuchen abgelaufen. + Die Server-Adresse ist nicht mit den Netzwerk-Einstellungen kompatibel. + Immer + Privates Routing + Nie + Unbekannte Relais + Ungeschützt + Privates Routing mit unbekannten Servern nutzen. + Nutzen Sie kein privates Routing. + Modus für das Nachrichten-Routing + Ja + Nein + Wenn die IP-Adresse versteckt ist + Fallback für das Nachrichten-Routing + Nachrichtenstatus anzeigen + Herunterstufung erlauben + Immer privates Routing nutzen. + Senden Sie keine direkten Nachrichten, selbst wenn Ihr oder der Zielserver kein privates Routing unterstützt. + PRIVATES NACHRICHTEN-ROUTING + Nachrichten direkt versenden, wenn die IP-Adresse geschützt ist und Ihr oder der Zielserver kein privates Routing unterstützt. + Nachrichten direkt versenden, wenn Ihr oder der Zielserver kein privates Routing unterstützt. + Für die Auslieferung Ihrer Nachrichten wird privates Routing Ihrer SMP-Server genutzt, um Ihre IP-Adresse zu schützen. + Privates Routing mit unbekannten Servern nutzen, wenn die IP-Adresse nicht geschützt ist. + IP-Adresse schützen + DATEIEN + Die App wird bei unbekannten Datei-Servern nach einer Download-Bestätigung fragen (außer bei .onion oder wenn ein SOCKS-Proxy aktiviert ist). + Unbekannte Server! + Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für Datei-Server sichtbar sein. + Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für diese XFTP-Relais sichtbar sein: +\n%1$s. + Profil-Design + Schwarz + Farbvariante + Dunkel + Hell + Farbe zurücksetzen + Gesendete Antwort + System + Dunkle Variante + Füllen + Helle Variante + Empfangene Antwort + Bild entfernen + Wiederholen + Skalieren + Default-Design einstellen + Wallpaper-Akzent + Wallpaper-Hintergrund + Anwenden auf + Zusätzlicher Akzent 2 + Erweiterte Einstellungen + Alle Farbvarianten + Chat-Farben + Chat-Design + Passend + Chat-Liste in einem neuen Fenster anzeigen + Guten Nachmittag! + Guten Morgen! + Farben für die dunkle Variante \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml index 85fcdceb6f..3bf05bf793 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml @@ -220,7 +220,7 @@ conectado directa El contacto permite - predefinido (%s) + predeterminado (%s) Eliminar para todos activado Tus contactos sólo pueden marcar los mensajes para eliminar. Tu podrás verlos. @@ -274,7 +274,7 @@ Chat está parado rol de %s cambiado a %s Cambiar rol - Mediante perfil (por defecto) o por conexión (BETA) + Mediante perfil (predeterminado) o por conexión (BETA) cambiando de servidor… Preferencias de Chat cancelado %s @@ -606,7 +606,7 @@ llamada rechazada secreto Abrir SimpleX Chat para aceptar llamada - Restablecer valores por defecto + Restablecer valores predetarminados Pendiente Notificaciones periódicas Guarda la contraseña de forma segura, NO podrás cambiarla si la pierdes. @@ -1161,7 +1161,7 @@ Mensaje enviado Dejar de compartir ¿Dejar de compartir la dirección\? - COLORES DEL TEMA + COLORES DEL INTERFAZ Puedes crearla más tarde ¿Compartir la dirección con los contactos\? Compartir con contactos @@ -1509,7 +1509,7 @@ autor Pegar dirección de ordenador %1$s!]]> - Verificar código con ordenador + Verifica el código en el ordenador Escanear código QR desde ordenador Desbloquear Detectable mediante red local @@ -1739,7 +1739,7 @@ WiFi Ethernet por cable administradores - Activar para + Activado para No permitir el envío de enlaces SimpleX todos los miembros Permitir enviar enlaces SimpleX. @@ -1766,7 +1766,76 @@ Al iniciar llamadas de audio y vídeo. ¡Será habilitado en los chats directos! Conexión de red más fiable. - Imágenes del perfil + Forma de los perfiles Dar forma a las imágenes de perfil Cuadrada, circular o cualquier forma intermedia. + Capacidad excedida - el destinatario no ha recibido el mensaje previo. + Error del servidor de destino: %1$s + Error: %1$s + Servidor de reenvío: %1$s +\nError del servidor de destino: %2$s + Servidor de reenvío: %1$s +\nError: %2$s + Problema en la red - el mensaje ha expirado tras muchos intentos de envío. + La versión del servidor es incompatible con la configuración de red. + Enrutamiento privado + Servidor de retransmisión desconocido + NO usar enrutamiento privado. + Enrutamiento de mensajes alternativo + Modo de enrutamiento de mensajes + No + Mostrar estado del mensaje + Usar enrutamiento privado con servidores desconocidos cuando la dirección IP no está protegida. + Con IP oculta + Si + Enviar los mensajes directamente cuando tu servidor o el de destino no soporten enrutamiento privado + Para proteger tu dirección IP, el enrutamiento privado usa tu servidor SMP para enviar mensajes. + NO enviar mensajes directos incluso si tu servidor o el de destino no soportan enrutamiento privado. + Siempre + Permitir versión anterior + Usar siempre enrutamiento privado. + Aviso de entrega de mensaje + Nunca + ENRUTAMIENTO PRIVADO DE MENSAJES + La dirección del servidor es incompatible con la configuración de la red. + Desprotegido + Clave incorrecta o conexión desconocida - probablemente esta conexión fue eliminada + Usar enrutamiento privado con servidores desconocidos. + Enviar los mensajes directamente cuando tu dirección IP está protegida y tu servidor o el de destino no soporten enrutamiento privado. + Servidores desconocidos! + Sin Tor o VPN, tu dirección IP será visible para estos relés XFTP: +\n%1$s. + Proteger dirección IP + Sin Tor o VPN, tu dirección IP será visible para los servidores de archivos. + ARCHIVOS + La aplicación pedirá confirmar las descargas de servidores de archivos desconocidos (excepto .onion o cuando se active SOCKS proxy). + Colores del chat + Tema del chat + Aplicar a + Negro + Todos los modos + Modo de color + Oscuro + Modo oscuro + Colores en modo oscuro + Relleno + ¡Buenas tardes! + ¡Buenos días! + Claro + Modo claro + Respuesta recibida + Mosaico + Quitar imagen + Restablecer color + Escala + Respuesta enviada + Establecer tema predeterminado + Sistema + Color de fondo + Encaje + Color adicional 2 + Configuración avanzada + Tema del perfil + Listado del chat en ventana nueva + Color imagen de fondo \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/fa/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/fa/strings.xml index 8ef94b53fe..4e15bb27f8 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/fa/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/fa/strings.xml @@ -5,8 +5,8 @@ %1$d پیام از قلم افتاده %1$s عضو %1$s می‌خواهد به شما متصل شود، به وسیله - 1 روز - 1 دقیقه + ۱ روز + ۱ دقیقه لغو لغو تغییر نشانی تغییر نشانی را لغو می‌کنید؟ @@ -36,7 +36,7 @@ مسیر نامعتبر پرونده برنامه از کار افتاد در حال تلاش برای اتصال به سرور مورد استفاده برای دریافت پیام‌ها از این مخاطب (خطا: %1$s). - حذف شده + حذف شد علامت گذاشته شده به عنوان حذف شده توسط %s حذف شد مسدود @@ -49,15 +49,15 @@ داده نامعتبر خطا در نمایش محتوا خطا در رمزگشایی - 5 دقیقه + ۵ دقیقه درباره نشانی سیمپل‌اکس(SimpleX) لینک یک بار مصرف درباره سیمپل‌اکس چت(SimpleX Chat) %1$d پیام از قلم افتاد. - 1 ماه - 1 هفته - 6 زبان جدید برای رابط کاربری - 30 ثانیه + ۱ ماه + ۱ هفته + ۶ زبان جدید برای رابط کاربری + ۳۰ ثانیه شما لینک یک بار مصرف ناشناس به اشتراک گذاشتید به وسیله لینک گروه ناشناس به وسیله لینک گروه @@ -229,25 +229,25 @@ توقف دریافت پرونده متوقف خواهد شد. خوش آمدید! - خطا در رمزگشایی + خطا در کدبرداری ارسال پیام مستقیم برای اتصال لطفا، تا زمانی که پرونده در حال بارگیری از موبایل متصل است، منتظر باشید. حذف مخاطب - مشاهده رمز امنیتی - تایید رمز امنیتی + مشاهده کد امنیتی + تایید کد امنیتی ارسال پیام ناپدید شونده لینک دعوت یک‌بارمصرف ایجاد گروه محرمانه (برای اشتراک‌گذاری با مخاطبتان) اگر لینک دعوت SimpleX Chat دریافت کردید، می‌توانید آن را در مرورگر خود باز کنید: - ورود رمز عبور + ورود کد عبور %d ثانیه - رمز عبور فعلی + کد عبور فعلی کپی پیام به عنوان حذف شده علامت‌گذاری خواهد شد. گیرنده‌ها قادر خواهند بود این پیام را آشکار کنند. ارسال غیرموفق برای اتصال لمس کنید - امکان رمزگشایی ویدئو وجود ندارد. لطفا، ویدئوی دیگری را امتحان کنید یا با توسعه‌دهندگان تماس بگیرید. + امکان کدبرداری ویدئو وجود ندارد. لطفا، ویدئوی دیگری را امتحان کنید یا با توسعه‌دهندگان تماس بگیرید. تصویر پرونده پیدا نشد لمس دکمه @@ -278,10 +278,10 @@ تماس تصویری برای محافظت از اطلاعاتتان، قفل SimpleX را روشن کنید. \nاز شما خواسته خواهد شد قبل از فعال شدن این ویژگی، تصدیق را تکمیل کنید. - عدم وجود رمز عبور + عدم وجود کد عبور %d دقیقه فعال‌سازی قفل SimpleX - وارد کردن رمز عبور + وارد کردن کد عبور ذخیره شده فرستاده شده فرستاده شده از @@ -323,7 +323,7 @@ مخاطب و تمام پیام‌ها حذف خواهند شد - این عمل قابل برگشت نیست! پیام‌های صوتی مجازند؟ پیام‌های صوتی ممنوع هستند! - اسکن رمز QR.]]> + اسکن کد QR.]]> اشتراک‌گذاری پرونده… تعداد تصویر بیش از اندازه! برای اسکن لمس کنید @@ -376,7 +376,7 @@ در انتظار تصویر پیام صوتی… تعیین نام مخاطب… - قطع اتصال + قطع شد در حال انتظار نشانی‌ دریافت تغییر کند؟ تغییر نشانی‌ لغو خواهد شد. نشانی‌ دریافت پیشین استفاده خواهد شد. @@ -384,7 +384,7 @@ فقط صاحبان گروه می‌توانند پیام‌های صوتی را فعال کنند. تایید بازنشاندن - اسکن رمز QR + اسکن کد QR (اسکن یا الصاق از حافظه) (تنها ذخیره شده توسط اعضای گروه) فعال کردن دسترسی دوربین @@ -404,7 +404,7 @@ ضبط پیام صوتی ارسال پیام بدون جزئیات - اتصال به وسیله لینک / رمز QR + اتصال به وسیله لینک / کد QR دوربین موجود نیست تصویر ایجاد لینک دعوت یک‌بارمصرف @@ -413,14 +413,14 @@ اتصال از طریق لینک تصویر وقتی دریافت خواهد شد که مخاطبتان آنلاین شود، لطفا صبر کنید یا بعدا بررسی کنید! نوع قفل SimpleX - تصدیق سامانه - تغییر رمز عبور + تصدیق سیستم + تغییر کد عبور در پاسخ به فوری تصدیق دستگاه فعال نیست. زمانی که تصدیق دستگاه را فعال کنید می‌توانید قفل SimpleX را از طریق تنظیمات روشن کنید. اجازه دادن ضمیمه - امکان رمزگشایی تصویر وجود ندارد. لطفا، تصویر دیگری را امتحان کنید یا با توسعه‌دهندگان تماس بگیرید. + امکان کدبرداری تصویر وجود ندارد. لطفا، تصویر دیگری را امتحان کنید یا با توسعه‌دهندگان تماس بگیرید. پرونده‌ها و رسانه ممنوع است! تصویر ارسال شد در انتظار ویدئو @@ -470,7 +470,7 @@ راهنمای مارکداون لینک نامعتبر! اشتراک‌گذاری لینک یک بار مصرف - یا رمز QR را اسکن کنید + یا کد QR را اسکن کنید تلاش مجدد عبارت عبور و صدور پایگاه داده افزودن سرورهای از پیش تنظیم شده @@ -483,7 +483,7 @@ SimpleX Chat را برای ترمینال نصب کنید در GitHub ستاره بزنید همکاری کنید - رمز QR + کد QR یک نمایه تصادفی جدید به اشتراک گذاشته خواهد شد. اتصال از طریق لینک لینک دعوت یک‌بارمصرف @@ -506,11 +506,11 @@ وقتی دستگاه میزبان گروه آنلاین شد، به گروه متصل خواهید شد، لطفا صبر کنید یا بعدا بررسی کنید! لینکی که دریافت کردید را الصاق کنید تا به مخاطبتان متصل شوید… نمایه شما %1$s به اشتراک گذاشته خواهد شد. - برای اتصال، مخاطبتان می‌تواند رمز QR را اسکن یا از لینک در برنامه استفاده کند. - اگر نمی‌توانید ملاقات حضوری داشته باشید، رمز QR را در یک تماس تصویری نمایش دهید، یا لینک را به اشتراک بگذارید. - می‌توانید نشانی‌ خود را به صورت لینک یا رمز QR به اشتراک بگذارید - هر کسی می‌تواند به شما متصل شود. + برای اتصال، مخاطبتان می‌تواند کد QR را اسکن یا از لینک در برنامه استفاده کند. + اگر نمی‌توانید ملاقات حضوری داشته باشید، کد QR را در یک تماس تصویری نمایش دهید، یا لینک را به اشتراک بگذارید. + می‌توانید نشانی خود را به صورت لینک یا کد QR به اشتراک بگذارید - هر کسی می‌تواند به شما متصل شود. وقتی اشخاص درخواست اتصال کنند، شما می‌توانید آن را بپذیرید یا رد کنید. - یا این رمز را نشان دهید + یا این کد را نشان دهید می‌توانید دوباره لینک دعوت را در جزئیات اتصال مشاهده کنید. نگه‌داشتن در حال ایجاد لینک… @@ -520,19 +520,19 @@ سرور از پیش تنظیم شده نشانی‌ سرور نامعتبر! به‌کارگیری برای اتصال‌های جدید - رمز QR نامعتبر - رمز امنیتی نادرست! - رمز امنیتی را از برنامه مخاطبتان اسکن کنید. + کد QR نامعتبر + کد امنیتی نادرست! + کد امنیتی را از برنامه مخاطبتان اسکن کنید. علامت‌گذاری به عنوان تایید شده %s تایید نشده است برای تایید رمزگذاری سرتاسر، روی دستگاه‌های خود، کد را با مخاطبتان مقایسه(یا اسکن) کنید. سرورهای XFTP شما - چگونه + روش استفاده در حال استفاده از سرورهای SimpleX Chat. تنظیم سرورهای ICE می‌خواهد به شما متصل شود! وقتی دستگاه مخاطبتان آنلاین شد، متصل خواهید شد، لطفا صبر کنید یا بعدا بررسی کنید! - رمز QR را در تماس تصویری اسکن کنید، یا مخاطبتان می‌تواند یک لینک دعوت به اشتراک بگذارد.]]> + کد QR را در تماس تصویری اسکن کنید، یا مخاطبتان می‌تواند یک لینک دعوت به اشتراک بگذارد.]]> دعوت استعمال نشده نگه داشته شود؟ نشانی‌ SimpleX شما مارکداون در پیام‌ها @@ -544,7 +544,7 @@ ذخیره سرورها عدم موفقیت آزمایش سرور! عدم موفقیت آزمایش چند سرور: - اسکن رمز QR سرور + اسکن کد QR سرور سرورهای SMP شما سرورهای XFTP از سرورهای SimpleX Chat استفاده شود؟ @@ -557,7 +557,7 @@ نشانی‌ SimpleX پاک‌سازی تایید نشانی‌ سرور از پیش تنظیم شده - رمز امنیتی + کد امنیتی به‌کارگیری از سرور سرورها برای اتصال‌های جدید نمایه گپ فعلی شما سرورها ذخیره شوند؟ @@ -567,17 +567,17 @@ لازم است مخاطبتان آنلاین باشد تا اتصال کامل شود. \nمی‌توانید این اتصال را لغو و مخاطب را حذف کنید (و بعدا با یک لینک جدید امتحان کنید). نشانی‌ SimpleX - این رمز QR یک لینک نیست! + این کد QR یک لینک نیست! راهنمای کاربر.]]> این رشته متن، یک لینک اتصال نیست! - رمزی که اسکن کردید یک رمز QR لینک SimpleX نیست. - اسکن رمز + کدی که اسکن کردید یک کد QR لینک SimpleX نیست. + اسکن کد تصویر نمایه بیشتر - نمایش رمز QR - رمز QR نامعتبر + نمایش کد QR + کد QR نامعتبر وقتی درخواست اتصال شما پذیرفته شد، متصل خواهید شد، لطفا صبر کنید یا بعدا بررسی کنید! - رمز QR را در تماس تصویری نمایش دهید، یا لینک را به اشتراک بگذارید.]]> + کد QR را در تماس تصویری نمایش دهید، یا لینک را به اشتراک بگذارید.]]> نمایه گپ شما ارسال خواهد شد \nبه مخاطبتان اطلاعات بیشتر @@ -682,4 +682,1125 @@ یک نشانی ایجاد کنید تا اشخاص بتوانند به شما متصل شوند. نمایه شما روی دستگاهتان ذخیره شده و فقط با مخاطبانتان به اشتراک گذاشته می‌شود. سرورهای SimpleX قادر به دیدن نمایه شما نیستند. خطا در ذخیره کردن کلمه عبور کاربر + تماس‌های صوتی و تصویری + تماس‌های شما + همیشه از واسطه استفاده شود + همتا به همتا + متناوب + تماس در حال انتظار + تماس ناموفق + تماس پایان یافت + پاسخ به تماس + فوری + از طریق واسطه + صدا روشن + چرخش دوربین + پیش‌نویس پیام + وقتی برنامه در حال اجراست + تماس صوتی رمزگذاری سرتاسر شده + پذیرفتن + حریم خصوصی شما + حالت قفل + ارسال + کد عبور نادرست + کد عبور + مخاطبان + غیرفعال کردن (نگه‌داشتن مقدارهای جایگزین شده) + فعال کردن (نگه‌داشتن مقدارهای جایگزین شده گروه) + غیرفعال برای همه گروه‌ها + کمک + گپ‌ها + اجرای گپ + گپ در حال اجراست + توقف + حذف تمام پرونده‌ها + اصلاح نام به %s؟ + بعدا از طریق تنظیمات قابل تغییر است. + تماس بی‌پاسخ + هش پیام ناصحیح + هش پیام قبلی متفاوت است. + شناسه پیام ناصحیح + رسیدها فعال شوند؟ + شما + پیام‌ها و پرونده‌ها + تماس‌ها + حالت ناشناس + عبارت عبور پایگاه داده + صدور پایگاه داده + نمایه گپ حذف شود؟ + نام خود را وارد کنید: + ایجاد + روش استفاده از مارکداون + می‌توانید از مارکداون برای آرایش پیام‌ها استفاده کنید: + تماس بی‌پاسخ + تماس پذیرفته + نامتمرکز + نمایه خود را ایجاد کنید + SimpleX چگونه کار می‌کند + اگر SimpleX هیچ شناسه کاربری ندارد، چگونه می‌تواند پیام‌ها را تحویل دهد؟]]> + مطالعه بیشتر در مخزن GitHub ما. + مخزن GitHub ما.]]> + استفاده از گپ + بهترین گزینه برای باتری. شما اعلان‌ها را فقط وقتی دریافت می‌کنید که برنامه در حال اجراست (بدون سرویس پس‌زمینه).]]> + تماس‌ها روی صفحه قفل: + پذیرفتن + سرور واسط از نشانی IP شما محافظت می‌کند، اما سرور می‌تواند مدت تماس را مشاهده کند. + گشودن + رمزگذاری سرتاسر شده + قطع تماس + ویدئو خاموش + ویدئو روشن + صدا خاموش + بلندگو خاموش + بلندگو روشن + در حال اتصال + فعال کردن قفل + کد عبور تعیین شد! + کد عبور تغییر کرد! + تغییر حالت قفل + خودتخریبی + فعال کردن کد عبور خودتخریبی + تغییر حالت خودتخریبی + کد عبور خودتخریبی فعال شد! + کد عبور خودتخریبی + نام نمایشی جدید: + اگر کد عبور خودتخریبی خود را زمان باز کردن برنامه وارد کنید: + تمام اطلاعات برنامه حذف می‌شود. + این تنظیمات برای نمایه فعلی شما هستند + ارسال رسید برای %d مخاطب فعال است + غیرفعال برای همه + فعال برای همه گروه‌ها + غیرفعال کردن (نگه‌داشتن مقدارهای جایگزین شده گروه) + توقف برنامه + تم‌ها + حذف پایگاه داده + پایگاه داده گپ وارد شد + %d پرونده با اندازه کل %s + رمزگذاری سرتاسر دو لایه را ذخیره می‌کنند.]]> + نادیده گرفتن + بلوتوث + وارد کردن پایگاه داده + اشخاص فقط از طریق لینک‌هایی که به اشتراک می‌گذارید می‌توانند به شما متصل شوند. + دریافت شوند و از چه سرورهایی به مخاطبان خود پیام می‌فرستید.]]> + تماس از پیش پایان یافته! + هش پیام ناصحیح + پذیرفتن خودکار تصاویر + ارسال پیش‌نمایش‌های لینک + سیستم + کد عبور برنامه + خاموش + ارسال رسید برای %d گروه فعال است + ارسال رسید برای %d گروه غیرفعال است + حمایت از SIMPLEX CHAT + پروکسی SOCKS + استفاده از کامپیوتر + آرشیو پایگاه داده جدید + آرشیو پایگاه داده قدیمی + خطا در شروع گپ + ایمن در برابر اسپم و سو استفاده + چگونه کار می‌کند + تماس تصویری + گوشی + بلندگو + هدفون‌ها + نسل بعدی پیام‌رسانی خصوصی + پایان یافت + خطا در باز کردن مرورگر + جهت صدور عبارت عبور تعیین کنید + محافظت از صفحه برنامه + شروع مجدد + ویژگی‌های آزمایشی + باز کردن پوشه پایگاه داده + گپ متوقف شده است + خطا در حذف پایگاه داده گپ + خطا در وارد کردن پایگاه داده گپ + شما گپ خود را کنترل می‌کنید! + نمایه، مخاطبان و پیام‌های تحویل داده شده شما روی دستگاهتان ذخیره می‌شوند. + نمایه فقط با مخاطبانتان به اشتراک گذاشته می‌شود. + نام نمایشی نمی‌تواند شامل نویسه‌های فاصله باشد. + ایجاد نمایه + نام نامعتبر! + برجسته + در انتظار تایید… + پاسخ دریافت شد… + تایید دریافت شد… + در حال اتصال… + در انتظار پاسخ… + تعیین عبارت عبور پایگاه داده + استفاده از عبارت عبور تصادفی + تماس صوتی + سرورهای ICE شما + تماس در جریان است + شناسه پیام ناصحیح + حریم خصوصی و امنیت + کد عبور جدید + تصدیق لغو شد + نمایش آخرین پیام‌ها + فعال کردن خودتخریبی + کد عبور برنامه با کد عبور خودتخریبی جایگزین می‌شود. + اگر کد عبور خودتخریبی خود را زمان باز کردن برنامه وارد کنید، تمام اطلاعات برنامه به صورت غیر قابل بازگشت حذف خواهد شد! + کد عبور خودتخریبی تغییر کرد! + رسیدها برای گروه‌ها فعال شوند؟ + فعال برای همه + آن‌ها در تنظیمات مخاطب و گروه قابل جایگزینی هستند. + گروه‌های کوچک (حداکثر ۲۰) + تنظیمات + اولین بن‌سازه بدون هیچ شناسه کاربری - با طرح‌ریزی خصوصی + اعلان‌های خصوصی + عبارت عبور تصادفی در تنظیمات به صورت متن آشکار ذخیره می‌شود. +\nمی‌توانید بعدا آن را تغییر دهید. + تماس تصویری رسیده + تماس صوتی رسیده + تماس تصویری رمزگذاری سرتاسر شده + تماس صوتی (رمزگذاری سرتاسر نشده) + بدون رمزگذاری سرتاسر + مخاطب رمزگذاری سرتاسر دارد + این اتفاق وقتی می‌افتد که شما یا اتصالتان از پشتیبان پایگاه داده قدیمی استفاده کرده باشید. + مذاکره مجدد رمزگذاری ناموفق بود. + رمزگذاری پرونده‌های محلی + پشتیبان‌گیری اطلاعات برنامه + قفل بعد از + تایید کد عبور + کد عبور تغییر نکرد! + ایجاد نمایه + مورب + ما هیچکدام از مخاطبان و پیام‌های(وقتی تحویل داده شدند) شما را روی سرورها ذخیره نمی‌کنیم. + رنگی + محرمانه + در حال تماس… + تماس ناموفق + تماس در جریان است + تماس پایان یافت %1$s + خطا در تماس + در حال راه‌اندازی… + متصل + در حال برقراری تماس… + تماس تصویری (رمزگذاری سرتاسر نشده) + رد کردن + تعیین کد عبور + رسیدها برای گروه‌ها غیرفعال شوند؟ + تغییر کد عبور خودتخریبی + رسیدهای تحویل ارسال شوند به + ابزارهای توسعه‌دهنده + برنامه + دستگاه + آزمایشی + اتصال شبکه + آیکون برنامه + پایگاه داده گپ + بن‌سازه پیام‌رسانی و کاربردی که از حریم خصوصی و امنیت شما محافظت می‌کند. + گزینه خوب برای باتری. سرویس پس‌زمینه هر ۱۰ دقیقه پیام‌ها را بررسی می‌کند. ممکن است تماس‌ها یا پیام‌های ضروری را از دست دهید.]]> + پیام‌ها از قلم افتادند + مرورگر وب پیش‌فرض برای تماس‌ها لازم است. لطفا مرورگر پیش‌فرض را در سیستم تنظیم کنید، و اطلاعات بیشتر را با توسعه‌دهندگان به اشتراک بگذارید. + سرور واسط فقط در زمان نیاز مورد استفاده قرار می‌گیرد. طرف دیگری قادر به مشاهده نشانی IP شما خواهد بود. + نمایش + غیرفعال + گشودن SimpleX Chat برای پذیرفتن تماس + تماس‌ها از صفحه قفل را از طریق تنظیمات فعال کنید. + مخاطب رمزگذاری سرتاسر ندارد + سرورهای WebRTC ICE + شناسه پیام بعدی نادرست است (کمتر یا برابر است با قبلی). +\nبروز این اتفاق می‌تواند به دلیل وجود اشکال نرم‌افزاری یا مورد حمله قرار گرفتن اتصال باشد. + لطفا آن را به توسعه‌دهندگان گزارش دهید. + پیام همسان + گپ متوقف شود؟ + پایگاه داده با استفاده از یک عبارت عبور تصادفی رمزگذاری شده، لطفا پیش از صدور آن را تغییر دهید. + خطا در متوقف کردن گپ + خطا در صدور پایگاه داده گپ + پایگاه داده گپ وارد شود؟ + وارد کردن + به منظور استفاده از پایگاه داده گپ وارد شده، برنامه را شروع مجدد کنید. + چند خطای غیر مهلک هنگام وارد کردن رخ داد - برای اطلاعات بیشتر می‌توانید کنسول گپ را ببینید. + پایگاه داده گپ حذف شد + به منظور ایجاد نمایه گپ جدید، برنامه را شروع مجدد کنید. + پرونده‌ها و رسانه + حذف پرونده‌ها برای تمام نمایه‌های گپ + پرونده‌ها و رسانه حذف شوند؟ + هیچ پرونده دریافتی یا ارسالی وجود ندارد + هرگز + %s ثانیه + اجرای اتصال خصوصی + جابه‌جایی از دستگاهی دیگر + یک نمایه گپ خالی با نام فراهم شده ایجاد می‌شود، و برنامه به طور معمول باز می‌شود. + اعطای اجازه‌ها در تنظیمات + این مجوز را در تنظیمات اندروید پیدا و به صورت دستی آن را اعطا کنید. + باز کردن تنظیمات + پروتکل و کد متن‌باز - هر کسی می‌تواند سرورها را راه‌اندازی کند. + رسیدها غیرفعال شوند؟ + فعال کردن (نگه‌داشتن مقدارهای جایگزین شده) + اعطای اجازه‌ها + میکروفون + دوربین + دوربین و میکروفون + اعطای اجازه‌ها برای برقراری تماس‌ها + حریم خصوصی باز تعریف شده + برای حفاظت از حریم خصوصی، به جای شناسه‌های کاربری مورد استفاده در بن‌سازه‌های دیگر، SimpleX شناسه‌هایی برای صفوف پیام دارد، جدا برای هر کدام از مخاطبان شما. + از باتری بیشتر استفاده می‌کند! سرویس پس‌زمینه همیشه در حال اجراست - اعلان‌ها به محض موجود شدن، نمایش داده می‌شوند.]]> + وقتی می‌تواند اتفاق بیفتد که: +\n۱. پیام‌ها در کلاینت فرستنده بعد از ۲ روز یا روی سرور بعد از ۳۰ روز منقضی شده باشند. +\n۲. رمزگشایی پیام ناموفق بود، چون شما یا مخاطبتان از پشتیبان پایگاه داده قدیمی استفاده استفاده کردید. +\n۳. اتصال مورد حمله قرار گرفته باشد. + تصاویر نمایه + به منظور صدور، ورود و حذف پایگاه داده گپ، گپ را متوقف کنید. هنگامی که گپ متوقف شده است، شما قادر به دریافت و ارسال پیام نخواهید بود. + پایگاه داده گپ فعلی شما حذف و توسط پایگاه داده وارد شده جایگزین خواهد شد. +\nاین عمل قابل برگشت نیست - نمایه، مخاطبان، پیام‌ها و پرونده‌های شما به صورت غیر قابل بازگشت از بین خواهند رفت. + پایگاه داده گپ شما + این عمل قابل برگشت نیست - نمایه، مخاطبان، پیام‌ها و پرونده‌های شما به صورت غیر قابل بازگشت از بین خواهند رفت. + ارسال رسید برای %d مخاطب غیرفعال است + این عمل قابل برگشت نیست - تمام پرونده‌ها و رسانه دریافتی حذف خواهند شد. عکس‌های با کیفیت پایین باقی خواهند ماند. + شما باید از تازه‌ترین نسخه پایگاه داده گپ خود روی فقط یک دستگاه استفاده کنید، در غیر این صورت ممکن است از بعضی از مخاطب‌ها ‌دیگر پیامی دریافت نکنید. + پیام‌ها + به منظور فعال‌سازی اقدامات پایگاه داده، گپ را متوقف کنید. + این عمل قابل برگشت نیست - پیام‌های ارسالی و دریافتی قدیمی‌تر از زمان انتخابی حذف خواهند شد. این کار ممکن است چندین دقیقه زمان ببرد. + خطا در تغییر تنظیمات + ذخیره عبارت عبور در تنظیمات + حذف پیام‌ها + ذخیره عبارت عبور در مخزن کلید + این تنظیمات بر پیام‌های موجود در نمایه گپ فعلی شما اعمال می‌شود + حذف خودکار پیام فعال شود؟ + برگرداندن + ارتقا و گشودن گپ + آرشیو گپ + ذخیره آرشیو + حذف آرشیو + دعوت به گروه %1$s + به گروه می‌پیوندید؟ + ترک + دریافت پیام‌ها از این گروه برای شما متوقف خواهد شد. تاریخچه گپ حفظ خواهد شد. + دعوت اعضا + %d رویداد گروه + %s، %s و %d عضو دیگر متصل شدند + %s و %s + %s، %s و %d عضو + و %d رویداد دیگر + گشودن + کد امنیتی تغییر پیدا کرد + وضعیت ناشناخته + سازنده + عبارت عبور جدید… + پایگاه داده رمزگذاری و عبارت عبور در تنظیمات ذخیره خواهد شد. + عبارت عبور رمزگذاری پایگاه داده به‌روز و در تنظیمات ذخیره خواهد شد. + امکان دسترسی مخزن کلید برای ذخیره کلمه عبور پایگاه داده وجود ندارد + خطای پایگاه داده ناشناخته: %s + تایید جابه‌جایی نامعتبر + شما به این گروه پیوستید + شما ترک کردید + نمایه گروه به‌روز شد + عضو + مدیر + صاحب + حذف شد + نقش عضو جدید + عبارت عبور از تنظیمات پاک شود؟ + لطفا توجه داشته باشید: اگر عبارت عبور را از دست بدهید، قادر نخواهید بود آن را بازیابی کنید یا تغییر دهید.]]> + عبارت عبور پایگاه داده اشتباه + پرونده: %s + عبارت عبور پایگاه داده برای گشودن گپ الزامی است. + خطای ناشناخته + گشودن گپ + تلاش برای تغییر عبارت عبور پایگاه داده کامل نشد. + ارتقای پایگاه داده + تنزل پایگاه داده + تایید ارتقای پایگاه داده + گروه را ترک می‌کنید؟ + امکان دعوت مخاطبان وجود ندارد! + در حال استفاده از نمایه ناشناس برای این گروه هستید - برای جلوگیری از اشتراک‌گذاری نمایه اصلی شما، دعوت مخاطبان مجاز نیست + مخاطب حذف شد + متصل شد + ترک کرد + %1$s حذف شد + شما حذف شدید + توافق رمزگذاری + ناظر + عضو پیشین %1$s + بسط دادن انتخاب نقش + عبارت عبور رمزگذاری پایگاه داده به‌روز خواهد شد. + مستقیما متصل شد + %s متصل شد + پیوستن به گروه + به‌روزرسانی + تایید عبارت عبور جدید… + پایگاه داده رمزگذاری شود؟ + نسخه پایگاه داده ناسازگار + نمایه گروه به‌روز شد + شما نشانی را برای %s تغییر دادید + شما نشانی را تغییر دادید + مذاکره مجدد رمزگذاری مجاز است + گروه حذف شد + در حال اتصال (دعوت معرفی) + رمزگذاری سرتاسر استاندارد + در حال اتصال (پذیرفته شد) + در حال اتصال (اعلام شد) + متصل شد + کامل + در حال اتصال + ناشناخته + دعوت به گروه + %d مخاطب انتخاب شد + امکان دعوت مخاطب وجود ندارد! + پیوستن + گروه غیرفعال + دعوت‌نامه گروه دیگر اعتبار ندارد، توسط فرستنده پاک شد. + گروه پیدا نشد! + شما به گروه دعوت شیده‌اید + شما دعوت گروه را رد کردید + از %1$s دعوت شده + نقش %s به %s تغییر کرد + گروه حذف شد + مذاکره مجدد رمزگذاری الزامی است + رمزگذاری برای %s بی‌عیب است + مذاکره مجدد رمزگذاری برای %s مجاز است + رمزگذاری سرتاسر مقاوم در برابر کوانتوم + مخاطبی برای افزودن وجود ندارد + رد شدن از دعوت اعضا + انتخاب مخاطبان + پایگاه داده رمزگذاری شده! + عبارت عبور فعلی… + عضو %1$s به %2$s تغییر کرد + رمزگذاری + به‌روزرسانی عبارت عبور پایگاه داده + تعیین عبارت عبور + از مخزن کلید اندروید برای ذخیره امن عبارت عبور استفاده می‌شود - به سرویس اعلان اجازه عمل می‌دهد. + باید هر بار که برنامه شروع می‌شود عبارت عبور را وارد کنید - در دستگاه ذخیره نمی‌شود. + پایگاه داده رمزگذاری شده + مخاطب بررسی شد + پاک کردن + نمایش کنسول در پنجره جدید + می‌توانید گپ را از طریق تنظیمات برنامه / پایگاه داده یا با شروع مجدد برنامه شروع کنید. + گپ شروع شود؟ + هشدار: ممکن است بعضی از اطلاعات را از دست بدهید! + گپ متوقف شده است + خطا در رمزگذاری پایگاه داده + عبارت عبور از مخزن کلید پاک شود؟ + اعلان‌ها فقط تا زمان توقف برنامه تحویل داده خواهند شد! + پاک کردن + تعیین عبارت عبور پایگاه داده + لطفا عبارت عبور فعلی درست را وارد کنید. + پایگاه داده گپ شما رمزگذاری نشده است - برای محافظت از آن عبارت عبور تعیین کنید. + عبارت عبور به صورت متن آشکار در تنظیمات ذخیره شده است. + بعد از تغییر عبارت عبور یا شروع مجدد برنامه، عبارت عبور به صورت متن آشکار در تنظیمات ذخیره خواهد شد. + عبارت عبور پایگاه داده تغییر داده شود؟ + پایگاه داده رمزگذاری خواهد شد. + لطفا عبارت عبور را به صورت امن ذخیره کنید، اگر آن را از دست دهید، قادر نخواهید بود به گپ دسترسی پیدا کنید. + خطا در پایگاه داده + خطا در Keychain + عبارت عبور پایگاه داده با آنچه در مخزن کلید ذخیره شده متفاوت است. + خطا: %s + عبارت عبور اشتباه! + ورود عبارت عبور… + ذخیره عبارت عبور و گشودن گپ + برگرداندن پشتیبان پایگاه داده + پشتیبان پایگاه داده برگردانده شود؟ + لطفا بعد از برگرداندن پشتیبان پایگاه داده، کلمه عبور قبلی را وارد کنید. این عمل قابل برگشت نیست. + خطا در برگرداندن پایگاه داده + نسخه پایگاه داده از برنامه جدیدتر است، اما بدون جابه‌جایی تنزلی برای: %s + جابه‌جایی متفاوت در برنامه/پایگاه داده: %s / %s + جابه‌جایی‌ها: %s + آرشیو گپ + ایجاد شده در %1$s + آرشیو گپ حذف شود؟ + شما به گروه دعوت شده‌اید. برای متصل شدن به اعضای گروه، به گروه بپیوندید. + پیوستن به صورت ناشناس + این گروه دیگر وجود ندارد. + شما دعوت گروه ارسال کردید + برای پیوستن لمس کنید + برای پیوستن به صورت ناشناس لمس کنید + %s مسدود شد + مسدود سازی %s لغو شد + نقش شما به %s تغییر کرد + شما نقش خود را به %s تغییر دادید + شما مسدود سازی %s را لغو کردید + %s و %s متصل شدند + %s، %s و %s متصل شدند + نشانی برای شما تغییر داده شد + در حال تغییر نشانی… + در حال تغییر نشانی برای %s… + در حال تغییر نشانی… + رمزگذاری بی‌عیب است + در حال توافق رمزگذاری برای %s… + توافق رمزگذاری برای %s + نویسنده + دعوت شد + در حال اتصال (معرفی شد) + نقش آغازین + مخاطبی انتخاب نشده + در حال توافق رمزگذاری… + ترک کرد + مخاطب %1$s به %2$s تغییر کرد + نشانی مخاطب حذف شد + تعیین نشانی مخاطب جدید + پایگاه داده با استفاده از عبارت عبور تصادفی رمزگذاری شده، می‌توانید آن را تغییر دهید. + بعد از شروع مجدد برنامه یا تغییر عبارت عبور، از مخزن کلید اندروید برای ذخیره امن عبارت عبور استفاده خواهد شد - اجازه دریافت اعلان‌ها را خواهد داد. + پایگاه داده رمزگذاری و عبارت عبور در مخزن کلید ذخیره خواهد شد. + عبارت عبور رمزگذاری پایگاه داده به‌روز و در مخزن کلید ذخیره خواهد شد. + عبارت عبور درست را وارد کنید. + لطفا عبارت عبور را به صورت امن ذخیره کنید، اگر آن را از دست دهید، قادر به تغییرش نخواهید بود. + عبارت عبور در مخزن کلید پیدا نشد، لطفا به صورت دستی آن را وارد کنید. دلیل این اتفاق ممکن است برگرداندن اطلاعات برنامه با استفاده از یک ابزار پشتیبان‌گیری باشد. اگر این طور نیست، لطفا با توسعه دهندگان تماس بگیرید. + تنزل و گشودن گپ + گپ متوقف شده است. اگر از پیش از این پایگاه داده روی دستگاه دیگری استفاده می‌کردید، بهتر است قبل از شروع گپ، آن را برگردانید. + به این گروه پیوستید. در حال اتصال به عضوی از گروه که از شما دعوت کرد. + دعوت منقضی شد! + دعوت گروه منقضی شد + از طریق لینک گروهتان دعوت شد + شما نقش %s را به %s تغییر دادید + شما %s را مسدود کردید + شما %1$s را حذف کردید + عکس نمایه حذف شد + تعیین عکس نمایه جدید + نمایه به‌روز شد + مذاکره مجدد رمزگذاری برای %s الزامی است + در حال ارسال از طریق + اتصال اصلاح شود؟ + اصلاح توسط عضو گروه پشتیبانی نمی‌شود + نمایه گپ شما به اعضای گروه ارسال خواهد شد + ایجاد لینک + خطا در به‌روزرسانی لینک گروه + زمان توقف پروتکل + می‌توانید این نشانی را با مخاطبان خود به اشتراک بگذارید تا به آن‌ها اجازه دهید به %s متصل شوند. + غیرفعال + رسیدها غیرفعال هستند + برای کنسول + حذف + به‌روزرسانی تنظیمات کلاینت را دوباره به سرورها متصل خواهد کرد. + نمایه گپ حذف شود؟ + خصوصی کردن نمایه! + می‌توانید نمایه کاربر را پنهان یا بی‌صدا کنید - برای نمایش منو لمس کنید و‍ نگه دارید. + لغو پنهان‌سازی نمایه + لغو پنهان‌سازی نمایه گپ + کلمه عبور نمایه + نمایه تصادفی شما + ابتدایی + پیام ارسالی + خیر + همیشه + روشن + پیام خوشامدگویی + حذف عضو + سیستم + تم + پیام دریافتی + لینک حذف شود؟ + می‌توانید یک لینک یا کد QR به اشتراک بگذارید - هر کسی می‌تواند به گروه بپیوندد. اگر بعدا گروه را حذف کنید، اعضای گروه را از دست نخواهید داد. + خطا در ایجاد لینک گروه + خطا در ارسال دعوت + اشتراک‌گذاری نشانی + این گروه بیش از %1$d عضو دارد، رسیدهای تحویل ارسال نمی‌شوند. + نام محلی + شناسه پایگاه داده + ایجاد شد در + دریافت شد در: %s + حذف شد در: %s + توسط مدیر حذف شد در: %s + ناپدید می‌شود در: %s + عضو حذف شود؟ + حذف عضو + مسدودسازی عضو + مسدودسازی + عضو برای همه مسدود شود؟ + لغو مسدودسازی + مسدودسازی عضو برای همه لغو شود؟ + مسدود شده توسط مدیر + مسدود + تغییر + تعویض + نقش گروه تغییر داده شود؟ + اتصال مستقیم؟ + درخواست اتصال به این عضو گروه ارسال خواهد شد. + پیام خوشامدگویی ذخیره شود؟ + مذاکره مجدد رمزگذاری + ذخیره نمایه گروه + به‌روزرسانی + شما هنوز تماس‌ها و اعلان‌های نمایه‌های بی‌صدا را وقتی فعال هستند دریافت می‌کنید. + ناشناس + سیستم + وارد کردن تم + شما اجازه می‌دهید + پیش‌فرض (%s) + گروه برای شما حذف خواهد شد - این عمل قابل برگشت نیست! + ترک گروه + لینک گروه + نشانی + در حال دریافت از طریق + بی‌صدا + بازنشاندن رنگ‌ها + اصلاح + شناسه پایگاه داده: %d + رکورد به‌روز شد در: %s + بدون متن + ارسال پیام مستقیم + پنهان کردن + ارسال شد در + روشن + خطا در وارد کردن تم + مخاطب اجازه می‌دهد + شما در حال دعوت از مخاطبی که با او نمایه ناشناسی به اشتراک گذاشته‌اید به گروهی هستید که در آن از نمایه اصلی خود استفاده می‌کنید + حذف گروه + افزودن پیام خوشامدگویی + وضعیت شبکه + نمایه گروه روی دستگاه‌های اعضا ذخیره می‌شود، نه روی سرورها. + اتصال‌های نمایه و سرور + (فعلی) + عضو + عضو از گروه حذف خواهد شد - این عمل قابل برگشت نیست! + مسدود برای همه + اصلاح توسط مخاطب پشتیبانی نمی‌شود + ثانیه + تمام گپ‌ها و پیام‌ها حذف خواهند شد - این عمل قابل برگشت نیست! + فقط اطلاعات نمایه محلی + دعوت اعضا + گروه حذف شود؟ + گروه برای تمام اعضا حذف خواهد شد - این عمل قابل برگشت نیست! + ایجاد لینک گروه + خطا در حذف لینک گروه + دریافت شد در + حذف شد در + توسط مدیر حذف شد در + ایجاد شد در: %s + عضو مسدود شود؟ + ویرایش نمایه گروه + حذف لینک + خطا در ایجاد مخاطب عضو + %s در %s + %s (فعلی) + نقش + ذخیره و به‌روزرسانی نمایه گروه + وقتی نمایه ناشناسی را با کسی به اشتراک می‌گذارید، این نمایه برای گروه‌هایی که شما را به آن‌ها دعوت می‌کند استفاده خواهد شد. + نام گروه را وارد کنید: + ایجاد گروه + خطا در ذخیره نمایه گروه + بازنشاندن به پیش‌فرض‌ها + صدور تم + خطا در حذف عضو + خطا در تغییر نقش + ثانوی + ارسال شد در: %s + %s: %s + پیام ذخیره شده + تغییر نقش + حذف نمایه + شما: %1$s + تمام اعضای گروه متصل باقی خواهند ماند. + تنها صاحبان گروه می‌توانند تنظیمات گروه را تغییر دهند. + رسیدهای ارسال + رکورد به‌روز شد در + ناپدید می‌شود در + تمام پیام‌های %s پنهان خواهند شد! + مسدودسازی عضو لغو شود؟ + لغو مسدودسازی عضو + لغو مسدودسازی برای همه + پیام‌های %s نشان داده خواهند شد! + نقش به «%s» تغییر داده خواهد شد. تمام افراد گروه مطلع خواهند شد. + نقش به «%s» تغییر داده خواهد شد. عضو یک دعوت جدید دریافت خواهد کرد. + خطا در مسدودسازی عضو برای همه + گروه + اتصال + مستقیم + غیرمستقیم (%1$s) + پیام خوشامدگویی + پیام خوشامدگویی بیش از حد طولانی است + پیش‌نمایش + پیام خوشامدگویی را وارد کنید… + پیام بیش از حد بزرگ است + سرورها + تغییر نشانی دریافتی + اصلاح اتصال + ایجاد گروه محرمانه + تماما نامتمرکز - قابل مشاهده فقط توسط اعضا. + نام کامل گروه: + زمان توقف پروتکل در کیلوبایت + دریافت همزمان + زمان توقف اتصال TCP + وقفه پینگ + شمار پینگ + فعال کردن زنده نگه‌داشتن TCP + برگشت + ذخیره + تنظیمات شبکه به‌روزرسانی شود؟ + افزودن نمایه + لغو پنهان‌سازی + لغو بی‌صدا + کلمه عبور را در جستجو وارد کنید + برای فعال‌سازی نمایه لمس کنید. + دوباره نمایش داده نشود + بی‌صدا هنگام غیرفعال بودن! + حذف نمایه گپ + حالت ناشناس از حریم خصوصی شما با استفاده از یک نمایه تصادفی جدید برای هر مخاطب محافظت می‌کند. + اجازه می‌دهد اتصال‌های بی‌نام زیادی داشته باشید بدون اطلاعات مشترک بین آن‌ها در تنها یک نمایه گپ. + تاریک + SimpleX + تم تاریک + مطمئن شوید پرونده دارای ترکیب YAML صحیح است. برای داشتن یک نمونه از ساختار پرونده تم، تم را صادر کنید. + ثانوی اضافی + ابتدایی اضافی + پس‌زمینه + منوها و هشدارها + عنوان + بله + تنظیمات مخاطب + حذف برای همه + به مخاطبان خود اجازه حذف پیام‌های ارسالی به صورت غیرقابل برگشت دهید. (۲۴ ساعت) + به مخاطبان خود اجازه افزودن واکنش‌های پیام می‌دهید. + فقط مخاطب شما می‌توانید پیام‌های ناپدید شونده ارسال کنید. + فقط شما می‌توانید پیام‌ها را به صورت غیرقابل برگشت حذف کنید (مخاطبتان می‌تواند آن‌ها را برای حذف علامت‌گذاری کند). (۲۴ ساعت) + فقط مخاطبتان می‌تواند پیام‌ها را به صورت غیرقابل برگشت حذف کند (شما می‌توانید آن‌ها را برای حذف علامت‌گذاری کنید). (۲۴ ساعت) + فقط شما می‌توانید پیام‌های صوتی ارسال کنید. + هر دوی شما و مخاطبتان می‌توانید واکنش‌های پیام اضافه کنید. + فقط شما می‌توانید واکنش‌های پیام اضافه کنید. + ارسال پیام‌های ناپدید شونده را منع می‌کنید. + اجازه ارسال پیام‌های مستقیم را به اعضا می‌دهید. + اجازه ارسال پرونده‌ها و رسانه را می‌دهید. + اعضای گروه می‌توانند پیام‌های ارسالی را به صورت غیرقابل برگشت حذف کنند. (۲۴ ساعت) + حذف بعد از + تنظیمات گپ + پرونده‌ها و رسانه + تماس‌های صوتی/تصویری + " +\nموجود در v5.1" + به مخاطبان خود اجازه ارسال پیام‌های صوتی می‌دهید. + فقط زمانی اجازه حذف پیام‌ها به صورت غیرقابل برگشت را می‌دهید که مخاطب شما این اجازه را به شما بدهد. (۲۴ ساعت) + پیام‌های ناپدید شونده در این گروه ممنوع هستند. + تعیین تنظیمات گروه + واکنش‌های پیام + حذف پیام به صورت غیرقابل برگشت در این گپ ممنوع است. + %d هفته + به مخاطبان خود اجازه ارسال پیام‌های ناپدید شونده دهید. + فقط وقتی پیام‌های صوتی را مجاز می‌دانید که مخاطب شما آن‌ها را مجاز می‌داند. + واکنش‌های پیام در این گپ ممنوع هستند. + ارسال پیام‌های صوتی را منع می‌کنید. + اعضای گروه می‌توانند پیام‌های صوتی ارسال کنند. + پذیرفتن + هر دوی شما و مخاطبتان می‌توانید پیام‌های ناپدید شونده ارسال کنید. + فقط شما می‌توانید پیام‌های ناپدید شونده ارسال کنید. + حذف پیام به صورت غیرقابل برگشت را منع می‌کنید. + واکنش‌های پیام‌ها را منع می‌کنید. + ارسال ۱۰۰ پیام آخر به اعضای جدید. + تا ۱۰۰ پیام آخر به اعضای جدید ارسال خواهد شد. + %d ماه + %d ماه + %d دقیقه + فقط وقتی تماس‌ها را مجاز می‌دانید که مخاطب شما آن‌ها را مجاز می‌داند. + منع تماس‌های صوتی/تصویری. + ارسال پرونده‌ها و رسانه را منع می‌کنید. + اجازه ارسال لینک‌های SimpleX را می‌دهید. + تاریخچه به اعضای جدید ارسال نمی‌شود. + اعضای گروه می‌توانند واکنش‌های پیام اضافه کنند. + اعضای گروه می‌توانند لینک‌های SimpleX ارسال کنند. + لینک‌های SimpleX در این گروه ممنوع هستند. + %d ثانیه + %d دقیقه + %d ماه + مدیران + صاحبان + جدید در %s + مطالعه بیشتر + هر دوی شما و مخاطبتان می‌توانید پیام‌های صوتی ارسال کنید. + فقط وقتی واکنش‌های پیام را مجاز می‌دانید که مخاطب شما آن‌ها را مجاز می‌داند. + منع واکنش‌های پیام. + فقط زمانی پیام‌های ناپدید شونده را مجاز می‌دانید که مخاطب شما آن‌ها را مجاز بداند. + ارسال پیام‌های ناپدید شونده را منع می‌کنید. + فقط مخاطبتان می‌تواند پیام‌های صوتی ارسال کند. + %d روز + مخاطبان می‌توانند پیام‌ها را برای حذف علامت بگذارند؛ شما قادر به مشاهده آن‌ها خواهید بود. + خاموش` + تنظیمات گروه + تنظیمات شما + پیام‌های ناپدید شونده + پیام‌های مستقیم + پیام‌های صوتی + لینک‌های SimpleX + تاریخچه قابل رویت + فعال + فعال برای شما + فعال برای مخاطب + خاموش + دریافتی، ممنوع + تعیین ۱ روز + منع ارسال پیام‌ها صوتی. + به مخاطبان خود اجازه تماس با شما را می‌دهید. + پیام‌های ناپدید شونده در این گپ ممنوع هستند. + هر دوی شما و مخاطبتان می‌توانید پیام‌ها را به صورتی غیرقابل برگشت حذف کنید. (۲۴ ساعت) + هر دوی شما و مخاطبتان می‌توانید تماس برقرار کنید. + فقط شما می‌توانید تماس برقرار کنید. + فقط مخاطبتان می‌تواند تماس برقرار کند. + تماس‌های صوتی/تصویری ممنوع هستند. + اجازه ارسال پیام‌های ناپدید شونده می‌دهید. + اجازه ارسال پیام‌های صوتی را می‌دهید. + اجازه واکنش‌های پیام را می‌دهید. + ارسال لینک‌های SimpleX را منع می‌کنید + عدم ارسال تاریخچه به اعضای جدید. + اعضای گروه می‌توانند پیام‌های ناپدید شونده ارسال کنند. + اعضای گروه می‌توانند پیام‌های مستقیم ارسال کنند. + پیام‌های مستقیم بین اعضا در این گروه ممنوع هستند. + حذف غیرقابل برگشت در این گروه ممنوع است. + پیام‌های صوتی در این گروه ممنوع هستند. + واکنش‌های پیام در این گروه ممنوع هستند. + اعضای گروه می‌توانند پرونده‌ها و رسانه ارسال کنند. + پرونده‌ها و رسانه در این گروه ممنوع هستند. + %d ثانیه + %d ساعت + %d ساعت + %d ساعت + %d روز + %d روز + %d هفته + %d هفته + پیشنهاد %s + پیشنهاد %s: %2s + لغو %s + تمام اعضا + فعال برای + چی جدید است + پیام‌های صوتی در این گپ ممنوع هستند. + فقط مخاطبتان می‌تواند واکنش‌های پیام اضافه کند. + اجازه حذف پیام‌های ارسالی به صورت غیرقابل برگشت را می‌دهید. (۲۴ ساعت) + ارسال پیام‌های مستقیم به اعضا را منع می‌کنید. + ظرفیت از محدودیت فراتر رفت - گیرنده پیام‌های ارسالی پیشین را دریافت نکرد. + خطای سرور مقصد: %1$s + خطا: %1$s + هم اکنون در حال پیوستن به گروه هستید! + خطای بسیار مهم + اتصال خاتمه یافت + از مسیریابی خصوصی استفاده نشود. + رسیدهای تحویل! + فعال نشود + خطا در فعال‌سازی رسیدهای تحویل! + دستگاه‌ها + اتصال کامپیوتر قطع شود؟اتصال کامپیوتر قطع شود؟ + قطع شد، به دلیل: %s + نسخه برنامه کامپیوتر %s با این برنامه سازگار نیست. + در انتظار کامپیوتر… + اتصال به کامپیوتر + کامپیوترهای متصل + اتصال کامپیوتر قطع شد + %s در وضع بدی است]]> + به خودتان متصل می‌شوید؟ + خطا در بارگیری آرشیو + لغو جابه‌جایی + هشدار: آرشیو حذف خواهد شد.]]> + هم اکنون در حال اتصال هستید! + همیشه + همیشه از مسیریابی خصوصی استفاده شود. + اعمال + کد عبور برنامه + تماس‌های صوتی و تصویری + سرورها را به وسیله اسکن کد QR اضافه کنید. + مدیران می‌توانند یک عضو را برای همه مسدود کنند. + اجازه تنزل + لطفا توجه داشته باشید: به منظور حفاظت امنیت، استفاده از پایگاه داده یکسان در دو دستگاه، رمزگشایی پیام‌های اتصال‌های شما را از کار خواهد انداخت.]]> + جابه‌جایی از دستگاهی دیگر را انتخاب و کد QR را اسکن کنید.]]> + تایید تنظیمات شبکه + تایید کنید که عبارت عبور پایگاه داده رای برای جابه‌جایی آن به خاطر دارید. + کامپیوتر متصل شد + در حال اتصال به کامپیوتر + اتصال متوقف شد + کامپیوتر غیرفعال است + اتصال متوقف شد + دستگاه‌های کامپیوتر + کامپیوتر پیدا شد + به کامپیوتر متصل شد + تنظیمات کامپیوتر متصل + اسکن کد QR از کامپیوتر + کامپیوتر دارای کد دعوت اشتباه است + کامپیوتر دارای نسخه پشتیبانی نشده است. لطفا، اطمینان حاصل کنید که از نسخه یکسان روی هر دو دستگاه استفاده می‌کنید. + از طریق لینک متصل می‌شوید؟ + رسیدهای تحویل غیرفعال هستند! + در حال بارگیری جزئیات لینک + عبارت عبور را وارد کنید + خطا در حذف پایگاه داده + کدهای امنیتی را با مخاطبان خود مقایسه کنید. + برنامه پرونده‌های جدید محلی (به جز ویدئوها) را رمزگذاری می‌کند. + رمزگذاری پرونده‌ها و رسانه ذخیره شده + به وسیله پروتکل امن مقاوم در برابر کوانتوم. + مسدودسازی اعضای گروه + خطا + %s قطع شد، به دلیل: %s]]> + کامپیوتر + رابط چینی و اسپانیایی + به وسیله نمایه گپ (پیش‌فرض) یا به وسیله اتصال (آزمایشی). + در حین اتصال به کامپیوتر، مهلت زمان اتصال تمام شد. + روز‍ + فعال کردن + سفارشی + قطع اتصال + تایید کد با کامپیوتر + خطا در بارگذاری آرشیو + در حال آرشیو پایگاه داده + ایجاد لینک آرشیو + حذف پایگاه داده از این دستگاه + اتصال به کامپیوتر در وضع بدی است + نام‌ها، آواتارها و انزوای ترابری متفاوت. + چند چیز دیگر + کامپیوتر مشغول است + پیام‌های ناپدید شونده + قطع اتصال + پیام‌های بهتر + اتصال به صورت خودکار + قابل کشف از طریق شبکه محلی + سلولی + ایجاد نمایه جدید در برنامه کامپیوتر. 💻 + نشانی کامپیوتر + الصاق نشانی کامپیوتر + یافتن از طریق شبکه محلی + تمام اطلاعات وقتی وارد می‌شوند پاک می‌شوند. + سفارشی کردن و اشتراک‌گذاری تم‌های رنگ. + تم‌های سفارشی + - اتصال به سرویس فهرست راهنما (آزمایشی)! +\n- رسیدهای تحویل (تا ۲۰ دقیقه). +\n- سریع‌تر و پایداری بیشتر. + گروه‌های بهتر + فعال کردن در گپ های مستقیم (آزمایشی)! + اتصال با کامپیوتر قطع شود؟ + به زودی! + بارگیری موفق نبود + گپ جابه‌جا شد! + آرشیو و بارگذاری + تایید بارگذاری + اتصال اینترنت خود را بررسی و دوباره امتحان کنید + برنامه کامپیوتر جدید + وصل کردن برنامه‌های موبایل و کامپیوتر! 🔗 + یافتن و پیوستن به گروه‌ها + ایجاد یک گروه با استفاده از یک نمایه تصادفی. + جابه‌جایی اطلاعات برنامه + استفاده از کامپیوتر را در برنامه موبایل باز و کد QR را اسکن کنید.]]> + در حال بارگیری آرشیو + خطا در صدور پایگاه داده گپ + خطا در ذخیره تنظیمات + تمام مخاطبان، مکالمات و پرونده‌های شما به صورت امن، رمزگذاری و به صورت بسته‌های داده به واسطه‌های XFTP تنظیم شده، بارگذاری خواهند شد. + موبایل متصل شد + مدیران می‌توانند لینک‌ها را برای پیوستن به گروه‌ها ایجاد کنند. + قطع اتصال موبایل‌ها + به موبایل متصل شد + نام این دستگاه را وارد کنید… + (جدید)]]> + پذیرفتن خودکار درخواست‌های مخاطب + نشانی کامپیوتر ناصحیح + نسخه ناسازگار + عربی، بلغاری، فنلاندی، عبری، تایلندی و اوکراینی - با سپاس از کاربران و Weblate + سرور فرستادن: %1$s +\nخطای سرور مقصد: %2$s + سرور فرستادن: %1$s +\nخطا: %2$s + هشدار تحویل پیام + مشکلات شبکه - پیام بعد از تلاش‌های زیاد برای ارسالش منقضی شد. + نشانی سرور با تنظیمات شبکه ناسازگار است. + نسخه سرور با تنظیمات شبکه ناسازگار است. + کلید اشتباه یا اتصال ناشناخته - به احتمال زیاد این اتصال حذف شده است. + لطفا آن را به توسعه‌دهندگان گزارش دهید: +\n%s + نگه‌داشتن اتصال‌های خود + هرگز + استفاده از مسیریابی خصوصی با سرورهای ناشناخته. + استفاده از مسیریابی خصوصی با سرورهای ناشناخته وقتی نشانی IP محافظت نشده است. + حالت مسیریابی پیام + بله + پیام‌ها مستقیما فرستاده نشود، حتی اگر سرور مقصد شما از مسیریابی خصوصی پشتیبانی نکند. + گزینه پس‌رفت مسیریابی پیام + نمایش وضعیت پیام + برای محافظت از نشانی IP شما، مسیریابی خصوصی از سرورهای SMP شما به منظور تحویل پیام‌ها استفاده می‌کند. + مسیریابی پیام خصوصی + مسیریابی خصوصی + تنظیمات سرور بهبودیافته + با پیام خوشامدگویی اختیاری. + مخاطبان شما می‌توانند اجازه حذف کامل پیام را بدهند. + چندین نمایه گپ + نام‌های پرونده خصوصی + پالایش گپ‌های خوانده نشده و برگزیده. + اصلاح رمزگذاری بعد از برگرداندن پشتیبان‌ها. + مدیریت گروه + رابط کاربری ژاپنی و پرتقالی + ناپدید کردن یک پیام + استفاده باتری کاهش یافته + به جای تصدیق سیستم آن را تعیین کنید. + پشتیبانی از بلوتوث و دیگر بهبودها. + - پیام‌های صوتی تا ۵ دقیقه. +\n- زمان سفارشی برای ناپدید کردن. +\n- ویرایش تاریخچه. + پیوستن سریع‌تر و پیام‌های قابل اطمینان تر. + باز فرستادن و ذخیره پیام‌ها + مربع، دایره، و هر چیزی در این بین. + در گپ‌های مستقیم فعال خواهد شد! + ارسال رسیدهای تحویل برای تمام مخاطبان فعال خواهد شد. + می‌توانید بعدا از طریق تنظیمات آن را فعال کنید + نام این دستگاه + تایید کد در موبایل + %s قطع شد]]> + این دستگاه + در انتظار متصل شدن موبایل: + %s مشغول است]]> + تصادفی + تجدید + %s نسخه پشتیبانی نشده دارد. لطفا، اطمینان حاصل کنید که از نسخه یکسان روی هر دو دستگاه استفاده می‌کنید]]> + %s قطع شد]]> + این ویژگی هنوز پشتیبانی نمی‌شود. انتشار بعدی را امتحان کنید. + %1$s هستید.]]> + گروه از قبل وجود دارد! + شما هم اکنون در حال پیوستن به گروه از طریق این لینک هستید. + در حال وارد کردن آرشیو + یا لینک آرشیو را الصاق کنید + الصاق لینک آرشیو + می‌توانید دوباره امتحان کنید. + پرونده حذف شد یا لینک نامعتبر است + جابه‌جایی دستگاه + در حال آماده‌سازی بارگذاری + نهایی‌سازی جابه‌جایی + یا لینک پرونده را به صورت امن به اشتراک بگذارید + شروع گپ + اترنت باسیم + بهبودهای بیشتر به زودی! + سازگار نیست! + تایید اتصال‌ها + %s غیرفعال است]]> + شما از پیش اتصال به وسیله این نشانی را درخواست کرده‌اید! + شروع مجدد گپ + حتی وقتی در مکالمه غیرفعال باشند. + خیر + موبایل متصلی وجود ندارد + مدیران حالا می‌توانند: +\n- پیام‌های اعضا را حذف کنند. +\n- اعضا را غیرفعال کنند ( نقش «ناظر») + لطفا تایید کنید که تنظیمات شبکه برای این دستگاه درست هستند. + محفوظ نگه داشتن پیش‌نویس پیام آخر، به همراه ضمیمه‌ها. + درخواست اتصال تکرار شود؟ + از موبایل اسکن کنید + ارسال رسیدهای تحویل برای تمام مخاطبان در تمام نمایه‌های گپ قابل مشاهده، فعال خواهد شد. + پیام‌ها مستقیما ارسال شود وقتی نشانی IP محافظت می‌شود و سرور مقصد شما از مسیریابی خصوصی پشتیبانی نمی‌کند. + پیام‌ها مستقیما ارسال شود وقتی سرور مقصد شما از مسیریابی خصوصی پشتیبانی نمی‌کند. + شکل دادن به تصاویر نمایه + با سپاس از کاربران - از طریق Weblate همکاری کنید! + با سپاس از کاربران - از طریق Weblate همکاری کنید! + این لینک یک‌بارمصرف خودتان است! + این نشانی‌ SimpleX خودتان است! + واسطه‌های ناشناخته + محافظت نشده + تایید اتصال + تایید عبارت عبور پایگاه داده + وقتی IP پنهان است + شما هم اکنون در حال اتصال از طریق لینک یک‌بارمصرف هستید! + نمایه‌های گپ پنهان + (این دستگاه v%s)]]> + متصل کردن یک موبایل + پیش‌نویس پیام + حداکثر ۴۰ ثانیه، دریافت فوری. + پیام‌های صوتی + پیام‌های ارسال شده بعد زمان تعیین شده حذف خواهند شد. + رابط فرانسوی + به وسیله یک کلمه عبور از نمایه‌های گپ خود محافظت کنید! + بهبودهای بیشتر به زودی! + با سپاس از کاربران - از طریق Weblate همکاری کنید! + رسیدهای تحویل پیام! + %s به پایان رسید]]> + لطفا آن را به توسعه‌دهندگان گزارش دهید: +\n%s +\n +\nپیشنهاد می‌شود که برنامه را شروع مجدد کنید. + رابط ایتالیایی + - تحویل پیام پایدارتر +\n- گروه‌های کمی بهتر +\n- و بیشتر! + کد عبور خودتخریبی + با سپاس از کاربران - از طریق Weblate همکاری کنید! + ویدئوها و پرونده‌ها تا ۱ گیگابایت + تایید عبارت عبور + لینک نامعتبر + هنگام برقراری تماس‌های صوتی و تصویری. + صداهای تماس + منبع پیام خصوصی باقی خواهد ماند. + رابط کاربری لیتوانی + دقیقه + اتصال شبکه پایدارتر. + مدیریت شبکه + هفته + ماه + انتخاب + دستگاه موبایل جدید + در حال متوقف کردن گپ + بدون اتصال شبکه + دیگر + تایید امنیت اتصال + در حال آماده‌سازی بارگیری + جابه‌جایی کامل شد + نباید از یک پایگاه داده روی دو دستگاه استفاده کنید.]]> + پیام خوشامدگویی گروه + - مطلع کردن اختیاری مخاطبان حذف شده. +\n- نام‌های نمایه شامل فاصله. +\n- و بیشتر! + رابط کاربری مجارستانی و ترکی + جابه‌جایی به دستگاه دیگر از طریق کد QR. + گشودن گروه + WiFi + تماس‌های تصویر در تصویر + استفاده از برنامه در حین مکالمه. + در حال جابه‌جایی + %1$s!]]> + امنیت و حریم خصوصی بهبودیافته + پنهان کردن صفحه برنامه در برنامه‌های اخیر. + پیام‌های زنده + گیرنده‌ها به‌روزرسانی‌ها را هم‌زمان با تایپ کردن شما مشاهده می‌کنند. + برای محافظت از منطقه زمانی، پرونده‌های تصویر/صدا از UTC استفاده می‌کنند. + سریع و بدون منتظر ماندن تا زمانی که فرستنده آنلاین شود. + کاهش بیشتر استفاده باتری + تعیین پیام نمایش داده شده به اعضای جدید! + رابط لهستانی + با سپاس از کاربران - از طریق Weblate همکاری کنید! + واکنش‌های پیام + بالاخره، ما آن‌ها را داریم! 🚀 + تیک دومی که ما نداشتیم! ✅ + برای پنهان کردن پیام‌های ناخواسته. + یادداشت‌های خصوصی + با پرونده‌ها و رسانه رمزگذاری شده. + تحویل پیام بهبود یافته + ساعت + می‌توانید بعدا از طریق تنظیمات حریم خصوصی و امنیت برنامه آن‌ها را فعال کنید. + گشودن پورت در فایروال + %s مفقود است]]> + برای اجازه دادن به برنامه موبایل به کامپیوتر متصل شوید، این پورت را در فایروال خود باز کنید، اگر فعال است + خطای داخلی + جابه‌جایی به اینجا + %1$s هستید.]]> + تکرار بارگیری + وارد کردن ناموفق بود + تکرار وارد کردن + نهایی‌سازی جابه‌جایی در دستگاه دیگر. + برای ادامه دادن، گپ باید متوقف شود. + تکرار بارگذاری + %s بارگذاری شد + بارگذاری ناموفق بود + در حال بارگذاری آرشیو + می‌توانید دوباره امتحان کنید. + خطا در تایید عبارت عبور: + ارزیابی امنیت + گروه‌های ناشناس + حالت ناشناس ساده‌شده + تغییر حالت ناشناس هنگام اتصال. + پیوستن به مکالمات گروه + جهت اتصال لینک را الصاق کنید + تاریخچه اخیر و روبات فهرست راهنمای بهبودیافته. + نوار جستجو لینک‌های دعوت قبول می‌کند. + با استفاده باتری کاهش یافته. + ثانیه + رمزگذاری مقاوم در برابر کوانتوم + گروه‌های امن‌تر + تنها یک دستگاه در هر زمان می‌تواند مورد استفاده قرار گیرد + درخواست پیوستن تکرار شود؟ + به گروه خود می‌پیوندید؟ + %s بارگیری شد + پرونده صادر شده وجود ندارد + جابه‌جایی به دستگاه دیگر + هشدار: شروع گپ روی چندین دستگاه پشتیبانی نمی‌شود و باعث عدم موفقیت در تحویل پیام خواهد شد + نام دستگاه با کلاینت موبایل متصل شده به اشتراک گذاشته خواهد شد. + پیدا کردن سریع‌تر گپ‌ها + لینک‌های گروه + حذف غیرقابل برگشت پیام + امنیت SimpleX Chat به وسیله Tails of Bits مورد سنجش قرار گرفت. + انزوای ترابری + کد نشست + %1$s هستید.]]> + موبایل‌های متصل + سرورهای ناشناخته! + حفاظت از نشانی IP + برنامه از شما خواهد خواست تا بارگیری‌ها از سرورهای پرونده ناشناخته را تایید کنید (به جز .onion یا وقتی پروکسی SOCKS فعال است). + پرونده‌ها + بدون تور یا VPN، نشانی IP شما برای سرورهای پرونده قابل رویت خواهد بود. + بدون تور یا VPN، نشانی IP شما برای این واسطه‌های XFTP قابل رویت خواهد بود: +\n%1$s. \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml index a9008d4808..2d279412cc 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml @@ -1768,4 +1768,44 @@ Carré, circulaire, ou toute autre forme intermédiaire. Lors des appels audio et vidéo. Interface utilisateur en lituanien + Avertissement sur la distribution des messages + L\'adresse du serveur est incompatible avec les paramètres du réseau. + La version du serveur est incompatible avec les paramètres du réseau. + Toujours utiliser le routage privé. + Ne pas utiliser de routage privé. + Utiliser le routage privé avec des serveurs inconnus lorsque l\'adresse IP n\'est pas protégée. + Envoyez les messages de manière directe lorsque votre serveur ou le serveur de destination ne prend pas en charge le routage privé. + Envoyer les messages de manière directe lorsque l\'adresse IP est protégée et que votre serveur ou le serveur de destination ne prend pas en charge le routage privé. + Problèmes de réseau - le message a expiré après plusieurs tentatives d\'envoi. + Clé erronée ou connexion non identifiée - il est très probable que cette connexion soit supprimée. + Serveur de transfert : %1$s +\nErreur au niveau du serveur de destination : %2$s + Serveur de transfert : %1$s +\nErreur : %2$s + Toujours + Routage privé + Autoriser la rétrogradation + Mode de routage des messages + Jamais + Relais inconnus + Non + Lorsque l\'IP est masquée + Oui + Rabattement du routage des messages + Afficher le statut du message + Protection de l\'adresse IP + FICHIERS + ROUTAGE PRIVÉ DES MESSAGES + Erreur au niveau du serveur de destination : %1$s + Erreur : %1$s + Capacité dépassée - le destinataire n\'a pas pu recevoir les messages envoyés précédemment. + L\'app demandera une confirmation pour les téléchargements depuis des serveurs de fichiers inconnus (sauf .onion ou lorsque le proxy SOCKS est activé). + Ne pas envoyer de messages directement, même si votre serveur ou le serveur de destination ne prend pas en charge le routage privé. + Pour protéger votre adresse IP, le routage privé utilise vos serveurs SMP pour délivrer les messages. + Non protégé + Serveurs inconnus ! + Sans Tor ou un VPN, votre adresse IP sera visible par les serveurs de fichiers. + Utiliser le routage privé avec des serveurs inconnus. + Sans Tor ou un VPN, votre adresse IP sera visible par ces relais XFTP : +\n%1$s. \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml index 8bbe0c6e8e..401d426b79 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml @@ -6,7 +6,7 @@ %1$s TAG 1 hónap 1 hét - 6 új felületi nyelv + 6 új kezelőfelületi nyelv 5 perc 1 perc A SimpleX azonosítóról @@ -26,7 +26,7 @@ Elfogadás gombra fent, majd: Elfogadás inkognítóban - Kapcsolatfelvétel elfogadása? + Kapcsolódási kérelem elfogadása? Elfogadás Elfogadás Azonosító hozzáadása a profilhoz, hogy az ismerősei megoszthassák másokkal. A profilfrissítés elküldésre kerül az ismerősök számára. @@ -35,9 +35,9 @@ Csoporttagok letiltása Hitelesítés Egy üres csevegési profil jön létre a megadott névvel, és az alkalmazás a szokásos módon megnyílik. - megszakítva %s + %s visszavonva Előre beállított kiszolgálók hozzáadása - A hang- és videóhívások le vannak tiltva. + A hívások kezdeményezése le van tiltva ebben a csevegésben. Külön TCP kapcsolat (és SOCKS bejelentkezési adatok) lesz használva minden ismerős és csoporttag számára. \nFigyelem: ha sok ismerőse van, az akkumulátor- és adathasználat jelentősen megnövekedhet és néhány kapcsolódási kísérlet sikertelen lehet. hivatkozás előnézet visszavonása @@ -52,15 +52,15 @@ Ismerőseivel kapcsolatban marad. A profil változtatások frissítésre kerülnek az ismerősöknél. A csevegési profil által (alap beállítás), vagy a kapcsolat által (BÉTA). Egy új véletlenszerű profil lesz megosztva. - Hangüzenetek küldésének engedélyezése kizárólag abban az esetben, ha az ismerőse is engedélyezi. + A hangüzenetek küldése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. Az alkalmazás build száma: %s Hang-/videóhívások Speciális hálózati beállítások - Hangüzenetek küldésének engedélyezése az ismerősei számára. + A hangüzenetek küldése engedélyezve van az ismerősei számára. Hang- és videóhívások Az alkalmazás titkosítja a helyi fájlokat (a videók kivételével). Hívás fogadása - Eltűnő üzenetek engedélyezése az ismerősei számára. + Az eltűnő üzenetek küldésének engedélyezése az ismerősei számára. Kapcsolódás folyamatban! Nem lehet fogadni a fájlt Hitelesítés elérhetetlen @@ -78,13 +78,13 @@ Cím Csatlakozás folyamatban! Automatikus elfogadás - A háttérszolgáltatás mindig fut - az értesítések azonnal megjelennek, amint üzenetek vannak. + A háttérszolgáltatás mindig fut - az értesítések megjelennek, amint az üzenetek elérhetővé válnak. Az elküldött üzenetek végleges törlése engedélyezve van. (24 óra) Mindkét fél küldhet hangüzeneteket. Téves üzenet ID - Ismerősök általi üzenetreakciók küldésének engedélyezése. + Az üzenetreakciók küldése engedélyezve van az ismerősei számára. A hangüzenetek küldése engedélyezve van. - Üzenetreakciók engedélyezése kizárólag abban az esetben, ha az ismerőse is engedélyezi. + Az üzenetreakciók küldése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. Vissza Kikapcsolható a beállításokban – az értesítések továbbra is megjelenítésre kerülnek amíg az alkalmazás fut.]]> Az adminok hivatkozásokat hozhatnak létre a csoportokhoz való csatlakozáshoz. @@ -92,7 +92,7 @@ titkosítás elfogadása… Ismerősök meghívása le van tiltva! téves üzenet ID - Ismerős jelölések automatikus elfogadása + Kapcsolódási kérelmek automatikus elfogadása Figyelem: NEM fogja tudni helyreállítani, vagy megváltoztatni a jelmondatot abban az esetben, ha elveszíti.]]> hívás… További másodlagos @@ -100,15 +100,15 @@ Az üzenetreakciók küldése engedélyezve van. Fájl előnézet visszavonása Minden csoporttag kapcsolatban marad. - Több akkumulátort használ! Háttérszolgáltatás mindig fut - az értesítések megjelennek, amint az üzenetek elérhetővé válnak.]]> + Több akkumulátort használ! A háttérszolgáltatás mindig fut - az értesítések megjelennek, amint az üzenetek elérhetővé válnak.]]> Letiltás admin Fénykép előnézet visszavonása A jelkód megadása után minden adat törlésre kerül. Felkérték a videó fogadására - Tag letiltása + Letiltás Még néhány dolog - Hitelesítés megszakítva + Hitelesítés visszavonva A fájlok- és a médiatartalom küldése engedélyezve van. Minden csevegés és üzenet törlésre kerül - ez a művelet nem vonható vissza! hanghívás @@ -122,22 +122,22 @@ Engedélyezés Minden ismerősével kapcsolatban marad. Élő csevegési üzenet visszavonása - Üzenet végleges törlésének engedélyezése kizárólag abban az esetben, ha az ismerőse is engedélyezi. (24 óra) + Az üzenetek végleges törlése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. (24 óra) Hang- és videóhívások téves üzenet hash - Mindig bekapcsolva + Mindig fut Az Android Keystore biztonságosan fogja tárolni a jelmondatot az alkalmazás újraindítása, vagy a jelmondat megváltoztatás után - lehetővé téve az értesítések fogadását. Minden alkalmazásadat törölve. - Legjobb akkumulátoridő. Csak akkor kap értesítést, ha az alkalmazás fut (NINCS háttérszolgáltatás).]]> + Legjobb akkumulátoridő. Csak akkor kap értesítéseket, amikor az alkalmazás meg van nyitva. (NINCS háttérszolgáltatás.)]]> Megjelenés Az akkumulátor optimalizálása aktív, mely kikapcsolja a háttérszolgáltatást és az új üzenetek rendszeres kérését. A beállításokon keresztül újra engedélyezhetők. - Tag letiltása? + Biztosan letiltja? %1$s hívása befejeződött Jó akkumulátoridő. A háttérszolgáltatás 10 percenként ellenőrzi az új üzeneteket. Előfordulhat, hogy hívásokról, vagy a sürgős üzenetekről marad le.]]> szerző - Elküldött üzenetek végleges törlésének engedélyezése az ismerősei számára. (24 óra) + Az elküldött üzenetek végleges törlése engedélyezve van az ismerősei számára. (24 óra) Mégse - Az alkalmazás csak akkor tud értesítéseket fogadni amikor fut, háttérszolgáltatás nem indul el + Az alkalmazás csak akkor tud értesítéseket fogadni, amikor meg van nyitva. A háttérszolgáltatás nem indul el. Jobb üzenetek A cím módosítása megszakad. A régi fogadási cím kerül felhasználásra. Engedélyezés @@ -150,21 +150,21 @@ A Keystore-hoz nem sikerül hozzáférni az adatbázis jelszó mentése végett hívás folyamatban Fotók automatikus elfogadása - Hívások engedélyezése az ismerősei számára. + A hívások kezdeményezése engedélyezve van az ismerősei számára. ALKALMAZÁS IKON Kiszolgáló hozzáadása QR-kód beolvasásával. Az eltűnő üzenetek küldése engedélyezve van. - Eltűnő üzenetek engedélyezése kizárólag abban az esetben, ha az ismerőse is engedélyezi. + Az eltűnő üzenetek küldése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. Hang kikapcsolva A közvetlen üzenetek küldése a tagok számára engedélyezve van. Alkalmazás Hívás folyamatban Mindkét fél küldhet üzenetreakciókat. - Mindkét fél tud hívásokat indítani. + Mindkét fél tud hívásokat kezdeményezni. Sikertelen hitelesítés Minden %s által írt új üzenet elrejtésre kerül! Alkalmazás verzió: v%s - Hívások engedélyezése kizárólag abban az esetben, ha az ismerőse is engedélyezi. + A hívások kezdeményezése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. Kiszolgáló hozzáadása… Hang bekapcsolva hanghívás (nem e2e titkosított) @@ -200,7 +200,7 @@ az ismerős e2e titkosítással rendelkezik Csoport létrehozása véletlenszerű profillal. Az ismerős és az összes üzenet törlésre kerül - ez a művelet nem vonható vissza! - Az ismerősök törlésre jelölhetnek üzeneteket ; megtekintheti őket. + Az ismerősei törlésre jelölhetnek üzeneteket; ön majd meg tudja nézni azokat. Kapcsolódás egyszer használatos hivatkozással? Kapcsolódás egy hivatkozás / QR-kód által Kapcsolódási hiba (AUTH) @@ -291,7 +291,7 @@ ICE kiszolgálók beállítása Csoport törlése Hitelesítés törlése - szerző + készítő Megerősítés Törlés nálam %d üzenet törlése? @@ -364,8 +364,8 @@ Eszközhitelesítés kikapcsolva. SimpleX zárolás kikapcsolása. Letiltás Letiltás minden csoport számára - Engedélyezés minden csoport részére - engedélyezve ismerős részére + Engedélyezés minden csoport számára + engedélyezve az ismerős számára Az eltűnő üzenetek küldése le van tiltva ebben a csoportban. Azonosító törlése %d hét @@ -408,7 +408,7 @@ %d ismerős kiválasztva Engedélyezés %dhónap - Ebben a csoportban tiltott a tagok közötti közvetlen üzenetek küldése. + A közvetlen üzenetek küldése a tagok között le van tiltva ebben a csoportban. %d perc Az adatbázis egy véletlenszerű jelmondattal van titkosítva. Exportálás előtt változtassa meg a jelmondatot. Üzenet kézbesítés jelentéseket letiltása a csoportok számára? @@ -453,7 +453,7 @@ Látható helyi hálózaton Ne engedélyezze Archívum törlése - Az eltűnő üzenetek le vannak tiltva ebben a csevegésben. + Az eltűnő üzenetek küldése le van tiltva ebben a csevegésben. alap (%s) duplikálódott üzenet Számítógép leválasztása? @@ -462,7 +462,7 @@ %d fájl %s összméretben Adatbázis jelmondat szükséges a csevegés megnyitásához. %dnap - Engedélyezés mindenki részére + Engedélyezés mindenki számára Kézbesítési jelentések kikapcsolva! Kibontás Hiba az üzenet küldésekor @@ -521,7 +521,7 @@ Kísérleti funkciók Engedélyezés (felülírások megtartásával) Helyes jelmondat bevitele. - A csoport törlésre kerül az ön részére - ez a művelet nem vonható vissza! + A csoport törlésre kerül az ön számára - ez a művelet nem vonható vissza! Adatbázis titkosítása? A zárolási képernyőn megjelenő hívások engedélyezése a Beállításokban. titkosítás egyeztetve @@ -565,7 +565,7 @@ Hiba a tag(-ok) hozzáadásakor Fájl A csoport tagjai küldhetnek fájlokat és médiatartalmakat. - Törlés miután + Törlés ennyi idő után Hiba a beállítás megváltoztatásakor Hiba a csoport hivatkozás frissítésekor a csoport törölve @@ -679,7 +679,7 @@ A kép akkor érkezik meg, amikor a küldője befejezte annak feltöltését. QR kód beolvasásával.]]> Kapott SimpleX Chat meghívó hivatkozását megnyithatja böngészőjében: - Ha az alkalmazás megnyitásakor az önmegsemmisítő jelkódot megadásra kerül: + Ha az alkalmazás megnyitásakor megadja az önmegsemmisítő jelkódot: Megtalált számítógép Számítógépek A markdown használata @@ -690,7 +690,7 @@ Elutasítás esetén a feladó NEM kap értesítést. Szerepkör kiválasztásának bővítése A kép akkor érkezik meg, amikor a küldője elérhető lesz, várjon, vagy ellenőrizze később! - meghívta + meghíva Érvénytelen kapcsolati hivatkozás Némítás nincsenek részletek @@ -724,15 +724,15 @@ Társítsa össze a mobil és az asztali alkalmazásokat! 🔗 közvetett (%1$s) Hamarosan további fejlesztések érkeznek! - Az üzenetreakciók ebben a csevegésben le vannak tiltva. + Az üzenetreakciók küldése le van tiltva ebben a csevegésben. Helytelen biztonsági kód! Ez akkor fordulhat elő, ha ön, vagy az ismerőse régi adatbázis biztonsági mentést használt. Új asztali alkalmazás! Most már az adminok is: \n- törölhetik a tagok üzeneteit. \n- letilthatnak tagokat (\"megfigyelő\" szerepkör) - meghívta %1$s-t - Ebben a csoportban az üzenetreakciók le vannak tiltva. + meghívta őt: %1$s + Az üzenetreakciók küldése le van tiltva ebben a csoportban. Nem nincs szöveg TAG @@ -754,7 +754,7 @@ Új kapcsolattartási kérelem Csatlakozás a csoporthoz Összekapcsolt számítógép beállítások - meghívta a csoport hivatkozásán keresztül + meghíva az ön csoport hivatkozásán keresztül elhagyta a csoportot Összekapcsolt számítógépek Nincs alkalmazás jelkód @@ -763,8 +763,8 @@ (csak a csoporttagok tárolják) Moderálás be - Japán és Portugál kezelőfelület - Ebben a csoportban az üzenetek végleges törlése le van tiltva. + Japán és portugál kezelőfelület + Az üzenetek végleges törlése le van tiltva ebben a csoportban. Onion kiszolgálók nem lesznek használva. %s eszközzel megszakadt a kapcsolat]]> hónap @@ -774,7 +774,7 @@ Egyszerre csak 10 videó küldhető el Csak ön adhat hozzá üzenetreakciókat. elhagyta a csoportot - Ebben a csevegésben az üzenetek végleges törlése le van tiltva. + Az üzenetek végleges törlése le van tiltva ebben a csevegésben. Max 40 másodperc, azonnal fogadható. inkognitó a kapcsolattartási azonosító-hivatkozáson keresztül A kapcsolódáshoz Onion kiszolgálókra lesz szükség. @@ -785,7 +785,7 @@ Összekapcsolt mobil eszközök Lehetővé teszi, hogy egyetlen csevegőprofilon belül több anonim kapcsolat legyen, anélkül, hogy megosztott adatok lennének közöttük. Az üzenet törlésre lesz jelölve. A címzett(ek) képes(ek) lesz(nek) felfedni ezt az üzenetet. - Elhagy + Elhagyás Rendben Nincsenek szűrt csevegések érvénytelen adat @@ -813,9 +813,9 @@ Csak a csoporttulajdonosok módosíthatják a csoportbeállításokat. Nincsenek előzmények Érvénytelen QR-kód - Megjelölés olvasottként + Olvasottként jelölés ÉLŐ - Olvasatlannak jelölve + Olvasatlannak jelölés Több Bejelentkezés hitelesítő adatokkal érvénytelen üzenet formátum @@ -847,7 +847,7 @@ Beszélgessünk a SimpleX Chat-ben Moderálva lett ekkor: Élő üzenetek - Ellenőrzöttként jelölve + Hitelesítés Üzenetkézbesítési bizonylatok! hivatkozás előnézeti képe Csoport elhagyása? @@ -1008,7 +1008,7 @@ Küldés %s másodperc %s: %s - A SimpleX nem tud futni a háttérben. Csak akkor fog értesítéseket kapni, ha az alkalmazás fut. + A SimpleX nem tud a háttérben futni. Csak akkor fog értesítéseket kapni, amikor az alkalmazás meg van nyitva. Túl sok kép! Archívum mentése %s, %s és %d tag @@ -1026,7 +1026,7 @@ SimpleX csoport hivatkozás Képre várakozás Önmegsemmisítés - várakozás válaszra… + várakozás a válaszra… Ismerős nevének beállítása… Tag feloldása QR-kód beolvasása @@ -1040,21 +1040,21 @@ Biztonsági kód Adja meg a helyes aktuális jelmondatát. Az elküldött üzenetek végleges törlése le van tiltva. - Üzenetreakció tiltása. + Az üzenetreakciók küldése le van tiltva. Véletlenszerű jelmondat használata egyenrangú CSEVEGÉSI SZOLGÁLTATÁS INDÍTÁSA Fogadott hivatkozás beillesztése Kiszolgálók mentése? A SimpleX Chat biztonsága a Trail of Bits által lett auditálva. - módosított csoport profil + frissítette a csoport profilját TÁMOGASSA A SIMPLEX CHATET SimpleX Chat szolgáltatás Nem lehet üzeneteket küldeni! %s ellenőrzött Jelszó megjelenítése Adatvédelem és biztonság - Tag eltávolítása + Eltávolítás A jelkód beállítva! Elküldött üzenet Ismerősök kiválasztása @@ -1078,7 +1078,7 @@ Ennek az eszköznek a neve Jelenlegi profil Fájl feltöltése - Hang- és videóhívások tiltása. + A hívások kezdeményezése le van tiltva. Megkövetelt SimpleX Chat üzenetek Visszaállítás @@ -1097,7 +1097,7 @@ SimpleX egyszer használatos meghívó Hívások nem sikerült elküldeni - TÉMA SZÍNEK + KEZELŐFELÜLET SZÍNEI Visszaállít Előző jelszó megadása az adatbázis biztonsági mentésének visszaállítása után. Ez a művelet nem vonható vissza. Másodlagos @@ -1117,7 +1117,7 @@ Ismeretlen hiba Saját kiszolgáló cím Csevegés konzol megnyitása - Tag eltávolítása + Eltávolítás Adatbázis jelmondat beállítása Biztonsági kód megtekintése Tag feloldása? @@ -1143,7 +1143,7 @@ Csatlakozási kérés megismétlése? Képre várakozás Hangüzenetek - Tag eltávolítása? + Biztosan eltávolítja? Biztonsági kód ellenőrzése eltávolítottak SimpleX azonosító @@ -1158,12 +1158,12 @@ Változáslista Csoport megnyitása Elküldve ekkor: - Hangüzenetek küldése le van tiltva. + A hangüzenetek küldése le van tiltva. Utolsó üzenetek megjelenítése Az előre beállított kiszolgáló címe Rendszeres értesítések letiltva! A jelkód megváltozott! - Akkor fut, ha az alkalmazás nyitva van + Akkor fut, amikor az alkalmazás meg van nyitva Ez a QR-kód nem egy hivatkozás! Fájlra várakozás simplexmq: v%s (%2s) @@ -1193,7 +1193,7 @@ Mentés Váltás Kapott hivatkozás beillesztése az ismerősökhöz történő kapcsolódáshoz… - Kód beolvasása + Beolvasás Port megnyitása a tűzfalon indítás… Leállítás @@ -1205,7 +1205,7 @@ Alkalmazás képernyőjének védelme QR-kód megjelenítése videóhívás - Nem kedvenc + Kedvenc törlése Üzenet kézbesítési jelentések küldése SimpleX azonosító Koppintson a @@ -1229,7 +1229,7 @@ Jelmondat mentése és csevegés megnyitása Beállítások mentése? Az első csevegési rendszer bármiféle felhasználó azonosító nélkül - privátra lett tervezre. - A közvetlen üzenetek küldése a tagok számára le van tiltva. + A közvetlen üzenetek küldése le van tiltva a tagok között. SOCKS proxy használata? Hangszóró kikapcsolva hét @@ -1277,7 +1277,7 @@ Sikertelen kiszolgáló-teszt! Kapcsolat ellenőrzése Tudjon meg többet - A küldő megszakította a fájl átvitelt. + A fájl küldője visszavonta az átvitelt. Csevegési szolgáltatás megállítása? Fogadva ekkor: Beállítva 1 nap @@ -1315,8 +1315,8 @@ Számítógép azonosítójának beillesztése kapcsolattartási azonosító-hivatkozáson keresztül SimpleX háttérszolgáltatást használja - az akkumulátor néhány százalékát használja naponta.]]> - Az ismerősnek online kell lennie ahhoz, hogy a kapcsolat létrejöjjön. -\nMegszakíthatja ezt a kapcsolatfelvételt és törölheti az ismerőst (ezt később ismét megpróbálhatja egy új hivatkozással) + Az ismerősének online kell lennie ahhoz, hogy a kapcsolat létrejöjjön. +\nVisszavonhatja ezt a kapcsolatfelvételt és törölheti az ismerőst (ezt később ismét megpróbálhatja egy új hivatkozással). A jelszó nem található a Keystore-ban, ezért kézzel szükséges megadni. Ez akkor történhetett meg, ha visszaállította az alkalmazás adatait egy biztonsági mentési eszközzel. Ha nem így történt, akkor lépjen kapcsolatba a fejlesztőkkel. Az ismerősei továbbra is kapcsolódva maradnak. A kiszolgálónak engedélyre van szüksége a várólisták létrehozásához, ellenőrizze jelszavát @@ -1376,7 +1376,7 @@ Egy olyan ismerősét próbálja meghívni, akivel inkognitóprofilt osztott meg abban a csoportban, amelyben a saját fő profilja van használatban %1$s csoporthoz.]]> Amikor az alkalmazás fut - Inkognító profilt használ ehhez a csoporthoz - fő profilja megosztásának elkerülése érdekében meghívók küldése tiltott + Inkognító profilt használ ehhez a csoporthoz - fő profilja megosztásának elkerülése érdekében a meghívók küldése le van tiltva Kapcsolat izolációs mód Akkor lesz kapcsolódva, ha a kapcsolódási kérelme elfogadásra kerül, várjon, vagy ellenőrizze később! A hangüzenetek küldése le van tiltva ebben a csoportban. @@ -1436,11 +1436,11 @@ Megoszthat egy hivatkozást vagy QR-kódot - így bárki csatlakozhat a csoporthoz. Ha a csoport később törlésre kerül, akkor nem fogja elveszíteni annak tagjait. Csatlakozott ehhez a csoporthoz %1$s csoporthoz!]]> - A hangüzenetek le vannak tiltva ebben a csevegésben. + A hangüzenetek küldése le van tiltva ebben a csevegésben. Ön irányítja csevegését! Kód ellenőrzése a számítógépen Az időzóna védelme érdekében a kép-/hangfájlok UTC-t használnak. - Csoporttag részére a kapcsolódási kérelem elküldésre kerül. + A kapcsolódási kérelem elküldésre kerül ezen csoporttag számára Inkognitóprofil megosztása esetén a rendszer azt a profilt fogja használni azokhoz a csoportokhoz, amelyekbe meghívást kapott. Már kért egy kapcsolódási kérelmet ezen az azonosítón keresztül! Megoszthatja ezt a SimpleX azonosítót az ismerőseivel, hogy kapcsolatba léphessenek vele: %s. @@ -1488,13 +1488,13 @@ Kézbesítési jelentések engedélyezve vannak a(z) %d csoportban A szerepkör meg fog változni erre: \"%s\". A csoportban mindenki értesítve lesz. Profil és kiszolgálókapcsolatok - Üzenetküldő és alkalmazásplatform, amely védi az ön adatvédelmét és biztonságát. + Egy üzenetküldő- és alkalmazásplatform, amely védi az ön adatait és biztonságát. A profil aktiválásához koppintson az ikonra. Kézbesítési jelentések le vannak tiltva %d ismerősnél Munkamenet kód Köszönet a felhasználóknak - hozzájárulás a Weblaten! Kis csoportok (max. 20 tag) - Az ön által elfogadott kapcsolat megszakad! + Az ön által elfogadott kapcsolat vissza lesz vonva! Élő üzenet küldése - a címzett(ek) számára frissül, ahogy beírja A KÉZBESÍTÉSI JELENTÉSEKET A KÖVETKEZŐ CÍMRE KELL KÜLDENI A következő üzenet azonosítója hibás (kisebb vagy egyenlő az előzővel). @@ -1618,7 +1618,7 @@ Letiltva az admin által %s letiltva Mindenki számára letiltva - Tag letiltása mindenki számára? + Mindenki számára letiltja ezt a tagot? %d üzenet letiltva az admin által Letiltás feloldása mindenki számára Mindenki számára feloldja a tag letiltását? @@ -1732,7 +1732,7 @@ minden tag SimpleX hivatkozás A hangüzenetek küldése le van tiltva - A SimpleX hivatkozások küldése ebben a csoportban le van tiltva. + A SimpleX hivatkozások küldése le van tiltva ebben a csoportban. A SimpleX hivatkozások küldése le van tiltva Fájlok és média tartalom küldése le van tiltva A SimpleX hivatkozások küldése engedélyezve van. @@ -1763,4 +1763,73 @@ Profilképek Profilkép alakzat Négyzet, kör vagy bármi a kettő között. + Célkiszolgáló hiba: %1$s + Továbbító kiszolgáló: %1$s +\nHiba: %2$s + Hálózati problémák - az üzenet többszöri elküldési kísérlet után lejárt. + A kiszolgáló verziója nem kompatibilis a hálózati beállításokkal. + Rossz kulcs vagy ismeretlen kapcsolat - valószínűleg ez a kapcsolat törlődött. + Továbbító kiszolgáló: %1$s +\nCélkiszolgáló hiba: %2$s + Hiba: %1$s + Kapacitás túllépés - a címzett nem kapta meg a korábban elküldött üzeneteket. + Üzenet kézbesítési figyelmeztetés + A kiszolgáló címe nem kompatibilis a hálózati beállításokkal. + Soha + Ismeretlen átjátszók + Ha az IP-cím rejtett + Üzenet állapot megjelenítése + Korábbi verzióra történő visszatérés engedélyezése + Mindig + Nem + Nem védett + Igen + Ne használjon privát útválasztást. + Privát útválasztás + Használjon privát útválasztást ismeretlen kiszolgálókkal. + Mindig használjon privát útválasztást. + Üzenet útválasztási mód + Közvetlen üzenetküldés, ha az IP-cím védett és az ön kiszolgálója vagy a célkiszolgáló nem támogatja a privát útválasztást. + Közvetlen üzenetküldés, ha az ön kiszolgálója vagy a célkiszolgáló nem támogatja a privát útválasztást. + Az IP-címe védelme érdekében a privát útválasztás az SMP-kiszolgálókat használja az üzenetek kézbesítéséhez. + Üzenet útválasztási tartalék + PRIVÁT ÜZENET ÚTVÁLASZTÁS + Privát útválasztás használata ismeretlen kiszolgálókkal, ha az IP-cím nem védett. + Ne küldjön üzeneteket közvetlenül, még akkor sem, ha az ön kiszolgálója vagy a célkiszolgáló nem támogatja a privát útválasztást. + Tor vagy VPN nélkül az IP-címe látható lesz a fájlkiszolgálók számára. + FÁJLOK + Az IP-cím védelme + Az alkalmazás kérni fogja az ismeretlen fájlkiszolgálókról történő letöltések megerősítését (kivéve, ha az .onion vagy a SOCKS proxy engedélyezve van). + Ismeretlen kiszolgálók! + Tor vagy VPN nélkül az IP-címe látható lesz az XFTP átjátszók számára: +\n%1$s. + Minden színmód + Fekete + Színmód + Sötét + Sötét mód + Sötét mód színei + Illesztés + Jó napot! + Jó reggelt! + Haladó beállítások + Alkalmazás erre + Csevegés színei + Csevegés témája + Kitöltés + Profiltéma + Csevegőlista megjelenítése új ablakban + Világos + Világos mód + Kapott válasz + Kép eltávolítása + Mozaik + Szín visszaállítása + Méretezés + Elküldött válasz + Alapértelmezett téma beállítása + Rendszer + Háttérkép kiemelés + Háttérkép háttérszíne + További kiemelés 2 \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml index ba11e0e29b..eb72c9b851 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml @@ -1119,7 +1119,7 @@ Per connettervi, il tuo contatto può scansionare il codice QR o usare il link nell\'app. Quando le persone chiedono di connettersi, puoi accettare o rifiutare. Indirizzo SimpleX - COLORI DEL TEMA + COLORI DELL\'INTERFACCIA I tuoi contatti resteranno connessi. Aggiungi l\'indirizzo al tuo profilo, in modo che i tuoi contatti possano condividerlo con altre persone. L\'aggiornamento del profilo verrà inviato ai tuoi contatti. Crea un indirizzo per consentire alle persone di connettersi con te. @@ -1147,7 +1147,7 @@ Secondario Messaggio ricevuto Messaggio inviato - Titolo + Titoli Link una tantum Info sull\'indirizzo SimpleX Tutti i tuoi contatti resteranno connessi. L\'aggiornamento del profilo verrà inviato ai tuoi contatti. @@ -1768,4 +1768,73 @@ La fonte del messaggio resta privata. Forma delle immagini del profilo Quadrata, circolare o qualsiasi forma tra le due + Server di inoltro: %1$s +\nErrore del server di destinazione: %2$s + Server di inoltro: %1$s +\nErrore: %2$s + Problemi di rete - messaggio scaduto dopo molti tentativi di inviarlo. + L\'indirizzo del server non è compatibile con le impostazioni di rete. + La versione del server non è compatibile con le impostazioni di rete. + Chiave sbagliata o connessione sconosciuta - molto probabilmente questa connessione è stata eliminata. + Errore del server di destinazione: %1$s + Errore: %1$s + Quota superata - il destinatario non ha ricevuto i messaggi precedentemente inviati. + Avviso di consegna del messaggio + Instradamento privato + Mai + Relay sconosciuti + Usa l\'instradamento privato con server sconosciuti. + Modalità instradamento messaggio + Usa l\'instradamento privato con server sconosciuti quando l\'indirizzo IP non è protetto. + + Invia messaggi direttamente quando il tuo server o quello di destinazione non supporta l\'instradamento privato. + Quando l\'IP è nascosto + Ripiego instradamento messaggio + Mostra stato del messaggio + Consenti downgrade + Sempre + Usa sempre l\'instradamento privato. + NON inviare messaggi direttamente, anche se il tuo server o quello di destinazione non supporta l\'instradamento privato. + NON usare l\'instradamento privato. + No + INSTRADAMENTO PRIVATO MESSAGGI + Invia messaggi direttamente quando l\'indirizzo IP è protetto e il tuo server o quello di destinazione non supporta l\'instradamento privato. + Per proteggere il tuo indirizzo IP, l\'instradamento privato usa i tuoi server SMP per consegnare i messaggi. + Non protetto + Server sconosciuti! + Proteggi l\'indirizzo IP + L\'app chiederà di confermare i download da server di file sconosciuti (eccetto .onion o quando il proxy SOCKS è attivo). + Senza Tor o VPN, il tuo indirizzo IP sarà visibile ai server di file. + FILE + Senza Tor o VPN, il tuo indirizzo IP sarà visibile a questi relay XFTP: +\n%1$s. + Tema della chat + Nero + Modalità di colore + Scura + Modalità scura + Principale aggiuntivo 2 + Tutte le modalità di colore + Applica a + Colori modalità scura + Tema del profilo + Risposta ricevuta + Colori della chat + Riempi + Chiara + Modalità chiara + Ripristina colore + Impostazioni avanzate + Rimuovi immagine + Ripeti + Scala + Adatta + Risposta inviata + Imposta tema predefinito + Mostra la lista di chat in una nuova finestra + Sistema + Tinta dello sfondo + Buon pomeriggio! + Buongiorno! + Retro dello sfondo \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml index eebb40a1c5..ceb8ab1664 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml @@ -1768,4 +1768,14 @@ プロフィール画像 正方形、円形またはその中間 プロフィール画像をシェイプ + 宛先サーバエラー: %1$s + エラー: %1$s + プライベートルーティング + 不明なリレー + 未保護 + ダウングレードを許可 + 常時 + 常時プライベートルーティングを使用 + プライベートメッセージルーティング + メッセージステータスを表示 \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml index 8c803bdeea..d741001717 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml @@ -1766,4 +1766,44 @@ Vorm profiel afbeeldingen Profiel afbeeldingen Vierkant, cirkel of iets daartussenin. + Capaciteit overschreden - ontvanger heeft eerder verzonden berichten niet ontvangen. + Fout met bestemmingsserver: %1$s + Fout: %1$s + Doorstuurserver: %1$s +\nBestemmingsserverfout: %2$s + Doorstuurserver: %1$s +\nFout: %2$s + Waarschuwing voor berichtbezorging + Netwerkproblemen - bericht is verlopen na vele pogingen om het te verzenden. + Serveradres is niet compatibel met netwerkinstellingen. + Serverversie is incompatibel met netwerkinstellingen. + Verkeerde sleutel of onbekende verbinding - hoogstwaarschijnlijk is deze verbinding verwijderd. + Altijd + Privéroutering + Onbekende relays + Nooit + Onbeschermd + Gebruik altijd privéroutering. + Gebruik privéroutering met onbekende servers. + Gebruik GEEN privéroutering. + Berichtrouteringsmodus + Gebruik privéroutering met onbekende servers wanneer het IP-adres niet beveiligd is. + Downgraden toestaan + Wanneer IP verborgen is + Ja + Nee + Stuur berichten rechtstreeks wanneer uw of de doelserver geen privéroutering ondersteunt. + Toon berichtstatus + Om uw IP-adres te beschermen, gebruikt privéroutering uw SMP-servers om berichten te bezorgen. + Stuur GEEN berichten rechtstreeks, zelfs als uw of de bestemmingsserver geen privéroutering ondersteunt. + Terugval op berichtroutering + PRIVÉBERICHT ROUTING + Stuur berichten rechtstreeks als het IP-adres beschermd is en uw of bestemmingsserver geen privéroutering ondersteunt. + Onbekende servers! + Zonder Tor of VPN is uw IP-adres zichtbaar voor deze XFTP-relays: +\n%1$s. + Zonder Tor of VPN is uw IP-adres zichtbaar voor bestandsservers. + BESTANDEN + Bescherm het IP-adres + De app vraagt om downloads van onbekende bestandsservers te bevestigen (behalve .onion of wanneer SOCKS-proxy is ingeschakeld). \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml index 825b5200c4..ea968cfb67 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml @@ -1153,7 +1153,7 @@ Kiedy ludzie proszą o połączenie, możesz je zaakceptować lub odrzucić. Nie stracisz kontaktów, jeśli później usuniesz swój adres. Dostosuj motyw - KOLORY MOTYWU + KOLORY INTERFEJSU Twoje kontakty pozostaną połączone. Dodaj adres do swojego profilu, aby Twoje kontakty mogły go udostępnić innym osobom. Aktualizacja profilu zostanie wysłana do Twoich kontaktów. Utwórz adres, aby ludzie mogli się z Tobą połączyć. @@ -1768,4 +1768,73 @@ Kwadrat, okrąg lub cokolwiek pomiędzy. Źródło wiadomości pozostaje prywatne. Zostanie włączone w czatach bezpośrednich! + Zawsze używaj prywatnego trasowania. + Zezwól na obniżenie wersji + Zawsze + Przekroczono pojemność - odbiorca nie otrzymał wcześniej wysłanych wiadomości. + Błąd serwera docelowego: %1$s + Błąd: %1$s + Serwer przekazujący: %1$s +\nBłąd serwera docelowego: %2$s + Serwer przekazujący: %1$s +\nBłąd: %2$s + Ostrzeżenie dostarczenia wiadomości + Błąd sieciowy - wiadomość wygasła po wielu próbach wysłania jej. + Adres serwera jest niekompatybilny z ustawieniami sieciowymi. + Wersja serwera jest niekompatybilna z ustawieniami sieciowymi. + Zły klucz lub nieznane połączenie - najprawdopodobniej to połączenie jest usunięte. + Nigdy + Niezabezpieczony + NIE używaj prywatnego trasowania. + Tryb trasowania wiadomości + Tak + Nie + Gdy IP ukryty + Pokaż status wiadomości + TRASOWANIE PRYWATNYCH WIADOMOŚCI + NIE wysyłaj wiadomości bezpośrednio, nawet jeśli serwer docelowy nie obsługuje prywatnego trasowania. + Aby chronić Twój adres IP, prywatne trasowanie używa Twoich serwerów SMP, aby dostarczyć wiadomości. + Nieznane przekaźniki + Używaj prywatnego trasowania z nieznanymi serwerami. + Rezerwowe trasowania wiadomości + Prywatne trasowanie + Wysyłaj wiadomości bezpośrednio, gdy adres IP jest chroniony i Twój lub docelowy serwer nie obsługuje prywatnego trasowania. + Wysyłaj wiadomości bezpośrednio, gdy Twój lub docelowy serwer nie obsługuje prywatnego trasowania. + Używaj prywatnego trasowania z nieznanymi serwerami, gdy adres IP nie jest chroniony. + Nieznane serwery! + Bez Tor lub VPN, Twój adres IP będzie widoczny dla tych przekaźników XFTP: +\n%1$s. + Chroń adres IP + Aplikacja będzie prosić o potwierdzenie pobierań z nieznanych serwerów plików (z wyjątkiem .onion lub gdy proxy SOCKS jest włączone). + Bez Tor lub VPN, Twój adres IP będzie widoczny do serwerów plików. + PLIKI + Motyw profilu + Pokaż listę czatów w nowym oknie + Kolory ciemnego trybu + Jasny + Otrzymano odpowiedź + Usuń obraz + Zresetuj kolory + Wypełnij + Dopasuj + Dzień dobry! + Dzień dobry! + Jasny tryb + Powtórz + Dodatkowy akcent 2 + Wszystkie tryby kolorów + Ciemny tryb + Ustaw domyślny motyw + Systemowy + Tło tapety + Zaawansowane ustawienia + Zastosuj dla + Skaluj + Czarny + Akcent tapety + Wyślij odpowiedź + Kolory czatu + Motyw czatu + Tryb koloru + Ciemny \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ro/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ro/strings.xml index b6f268e6f1..cb6187ee85 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ro/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ro/strings.xml @@ -155,4 +155,20 @@ Arabă, Bulgară, Finlandeză, Ebraică, Thailandeză și Ucraineană - mulțumită utilizatorilor și Weblate. Apelurile audio/video sunt interzise. (prezent) + Poză de profil eliminată + Temă întunecată + eliminat + Întunecată + Adresă de contact eliminată + Personalizează și distribuie teme colorate. + Teme personalizate + Repetă descărcarea + Timp personalizat + Elimină membru + Repetă importarea + Personalizează tema + Elimină + Elimină + Elimină membru + Elimini membrul? \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml index f659db0e2a..dc9f488572 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml @@ -87,7 +87,7 @@ Konuştuğunuz kişinin uygulamasından güvenlik kodunu okut. WebRTC ICE sunucu adreslerinin doğru formatta olduğundan emin olun: Satırlara ayrılmış ve yinelenmemiş şekilde. Kaydet - TEMA RENKLERİ + ARAYÜZ RENKLERİ Otomatik-kabul ayarlarını kaydet Ayarlar kaydedilsin mi? Kaydet ve konuştuğun kişilere bildir @@ -1769,4 +1769,73 @@ Profil resimleri Profil resimlerini şekillendir Kare,daire, veya aralarında herhangi bir şey. + Kapasite aşıldı - alıcı önceden gönderilen mesajları almadı. + Hedef sunucu hatası: %1$s + Hata: %1$s + Yönlendirme sunucusu: %1$s +\nHedef sunucu hatası: %2$s + Yönlendirme sunucusu: %1$s +\nHata: %2$s + Mesaj iletimi uyarısı + Ağ sorunları - birçok gönderme denemesinden sonra mesajın süresi doldu. + Sunucu adresi ağ ayarlarıyla uyumlu değil. + Sunucu sürümü ağ ayarlarıyla uyumlu değil. + Yanlış anahtar veya bilinmeyen bağlantı - büyük olasılıkla bu bağlantı silinmiştir. + Gizli yönlendirme + Bilinmeyen röleler + Her zaman gizli yönlendirmeyi kullan. + Gizli yönlendirmeyi KULLANMA. + Mesaj yönlendirme modu + Hiçbir zaman + Bilinmeyen sunucularla gizli yönlendirme kullan. + Sürüm düşürmeye izin ver + Hayır + Mesaj yönlendirme yedeklemesi + Her zaman + Sizin veya hedef sunucunun özel yönlendirmeyi desteklememesi durumunda bile mesajları doğrudan GÖNDERMEYİN. + IP adresi korumalı olduğunda ve sizin veya hedef sunucunun özel yönlendirmeyi desteklemediği durumlarda mesajları doğrudan gönderin. + Sizin veya hedef sunucunun özel yönlendirmeyi desteklemediği durumlarda mesajları doğrudan gönderin. + GİZLİ MESAJ YÖNLENDİRME + Mesaj durumunu göster + IP adresinizi korumak için,özel yönlendirme mesajları iletmek için SMP sunucularınızı kullanır. + Korumasız + IP adresi korunmadığında bilinmeyen sunucularla gizli yönlendirme kullan. + IP gizliyken + Evet + Sohbet teması + Profil teması + Siyah + Renk modu + Karanlık mod renkleri + Aydınlık + Sistem + Ek vurgu 2 + Bütün renk modları + Şuna uygula + Karanlık mod + Doldur + Ölçeklendir + Gönderilen cevap + Varsayılan temaya ayarla + Gelişmiş ayarlar + Günaydın! + Karanlık + Aydınlık mod + IP adresini koru + DOSYALAR + Sohbet renkleri + Sığdır + Alınan cevap + İyi öğlenler! + Resmi kaldır + Tekrarla + Rengi sıfırla + Sohbet listesini yeni pencerede göster + Bilinmeyen sunucular! + Tor veya VPN olmadan, IP adresiniz bu XFTP aktarıcıları tarafından görülebilir: +\n%1$s. + Tor veya VPN olmadan, IP adresiniz dosya sunucularına görülebilir. + Duvar kağıdı vurgusu + Duvar kağıdı arkaplanı + Uygulama, bilinmeyen dosya sunucularından indirmeleri onaylamanızı isteyecektir (.onion veya SOCKS vekilleri etkin değilse). \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml index 2d52051098..8c2298afef 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml @@ -741,7 +741,7 @@ Показати профіль Показати профіль чату Коли ви ділитесь анонімним профілем з кимось, цей профіль буде використовуватися для груп, до яких вас запрошують. - Світла + Світлий Помилка імпорту теми Налаштування групи Повідомлення зникнення @@ -1037,7 +1037,7 @@ Хост Порт Обов\'язково - КОЛОРИ ТЕМИ + КОЛЬОРИ ІНТЕРФЕЙСУ Створіть адресу, щоб дозволити людям підключатися до вас. Ваші контакти залишаться підключеними. Створити SimpleX-адресу @@ -1663,7 +1663,7 @@ Імпорт архіву Повторний імпорт Завершіть міграцію на іншому пристрої. - Подати заявку + Застосувати Перенести пристрій Перехід на інший пристрій Помилка експорту бази даних чату @@ -1712,4 +1712,81 @@ Використовуйте додаток під час розмови. Підтвердіть парольну фразу Ви можете спробувати ще раз. + Перевищено ліміт - одержувач не отримав раніше надіслані повідомлення. + Помилка сервера призначення: %1$s + Помилка: %1$s + Попередження про доставку повідомлення + Проблеми з мережею - термін дії повідомлення закінчився після багатьох спроб надіслати його. + Сервер переадресації: %1$s +\nПомилка сервера призначення: %2$s + Сервер переадресації: %1$s +\nПомилка: %2$s + Мікрофон + Джерело повідомлення залишається приватним. + Завжди + Завжди використовуйте приватну маршрутизацію. + Режим маршрутизації повідомлень + НЕ використовуйте приватну маршрутизацію. + Ні + НЕ надсилайте повідомлення напряму, навіть якщо ваш сервер або сервер призначення не підтримує приватну маршрутизацію. + Камера + Надати в налаштуваннях + Навушники + Стільниковий + власники + Більш надійне з\'єднання з мережею. + Керування мережею + Пересилання та збереження повідомлень + Переадресувати повідомлення… + Дозволити зниження рейтингу + Тема програми + Темний режим + Завантажити + Навушник + Увімкнено для + Повідомлення про помилку, зв\'яжіться з розробниками. + Файли та медіафайли заборонені + Знайдіть цей дозвіл у налаштуваннях Android і надайте його вручну. + Переслати + Переслано + Переслано з + Учасники групи можуть надсилати посилання SimpleX. + Звуки вхідного дзвінка + Світлий режим + Запасний варіант маршрутизації повідомлень + МАРШРУТИЗАЦІЯ ПРИВАТНИХ ПОВІДОМЛЕНЬ + переслано + Інше + Дозволити надсилати посилання SimpleX. + Заборонити надсилання посилань SimpleX + Немає підключення до мережі + Ніколи + Приватна маршрутизація + Bluetooth + Камера та мікрофон + Надайте дозвіл(и) на здійснення дзвінків + Відкрити налаштування + ФАЙЛИ + Зображення профілю + Підключення до мережі + адміністратори + всі учасники + Литовський інтерфейс + Надавати дозволи + Кольори чату + Тема чату + Тема профілю + Темна + Додатковий акцент 2 + Розширені налаштування + Усі кольорові режими + Застосувати до + Колірний режим + Темна + Кольори темного режиму + Заповнити + Підходить + Доброго дня! + Доброго ранку! + Світлий \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/vi/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/vi/strings.xml index 939071da2b..735ef63237 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/vi/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/vi/strings.xml @@ -172,4 +172,31 @@ Cả bạn và liên hệ của bạn đều có thể thả cảm xúc tin nhắn. Xin lưu ý: relay tin nhắn và tệp được kết nối thông qua SOCKS proxy. Các cuộc gọi và bản xem trước liên kết sử dụng kết nối trực tiếp.]]> Tốt cho pin. Dịch vụ nền kiểm tra tin nhắn 10 phút một lần. Bạn có thể bỏ lỡ các cuộc gọi hoặc tin nhắn khẩn cấp.]]> + Luôn luôn + đang gọi… + Theo hồ sơ trò chuyện (mặc định) hoặc theo kết nối (BETA). + cuộc gọi đang chờ + Sử dụng nhiều pin hơn! Dịch vụ chạy nền luôn luôn chạy - thông báo sẽ được hiển thị ngay khi nhận được tin nhắn.]]> + Cảnh báo: kho lưu trữ sẽ bị xóa.]]> + Cuộc gọi đang chờ + Cho phép hạ cấp + Cuộc gọi đã kết thúc! + Luôn luôn sử dụng định tuyến riêng tư. + Cuộc gọi kết thúc + cuộc gọi kết thúc %1$s + lỗi cuộc gọi + CUỘC GỌI + Hủy xem trước ảnh + Hủy xem trước tệp + Hủy + Camera + Camera hiện đang bận + Camera + Cuộc gọi trên màn hình khóa: + Đen + Áp dụng cho + Biến thể của màu sơ cấp 2 + Cài đặt nâng cao + Tất cả chế độ màu + Camera và mic \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml index 1002e458f5..362d6a30f0 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml @@ -69,7 +69,7 @@ 总是通过中继连接 允许您的联系人不不可逆地删除已发送消息。(24小时) 联系人允许 - 仅有您的联系人许可后才允许语音消息。 + 允许语音消息,前提是你的联系人允许这样的消息。 您: %1$s 允许您的联系人发送语音消息。 始终 @@ -87,8 +87,8 @@ 删除联系人? 已删除群组 删除图片 - 仅有您的联系人许可后才允许限时消息。 - 只有您的联系人同意才允许不可逆地删除消息。(24小时) + 允许限时消息,前提是你的联系人允许这样的消息。 + 允许不可逆的消息删除,前提是你的联系人允许这样做。(24小时) 允许不可逆地删除已发送消息。(24小时) 为此删除聊天资料 删除数据库 @@ -1111,13 +1111,13 @@ 只有您可以拨打电话。 只有您的联系人可以拨打电话。 允许您的联系人与您进行语音通话。 - 仅当您的联系人允许时才允许呼叫。 + 允许通话,前提是你的联系人允许它们。 禁止音频/视频通话。 1分钟 一次性链接 您和您的联系人都可以添加消息回应。 允许消息回应。 - 只有您的联系人允许时才允许消息回应。 + 允许消息回应,前提是你的联系人允许它们。 应用程序密码被替换为自毁密码。 更改自毁模式 关于 SimpleX 地址 @@ -1194,7 +1194,7 @@ 当人们请求连接时,您可以接受或拒绝它。 如果您以后删除您的地址,您不会丢失您的联系人。 用户指南中阅读更多。]]> - 主题颜色 + 界面颜色 与您的联系人保持连接。 与联系人分享 邀请朋友 @@ -1768,4 +1768,73 @@ 个人资料图 改变个人资料图形状 方形、圆形、或两者之间的任意形状 + 超出了额度 — 收信人没收到之前发送的消息。 + 目标服务器错误:%1$s + 错误:%1$s + 转发服务器:%1$s +\n错误:%2$s + 消息传输警告 + 网络问题 — 许多发送消息的尝试后,消息过期了。 + 密钥错误或连接未知 — 连接被删除的可能性最大。 + 始终 + 从不 + 未知中继 + 始终使用私密路由。 + 不使用私密路由。 + 在未知服务器上使用私密路由。 + 当 IP 地址不受保护时,在未知服务器上使用私密路由。 + 当 IP 隐藏时 + + + 当你的服务器或目标服务器不支持私密路由时直接发送消息。 + 备用消息路由 + 显示消息状态 + 为了保护你的 IP 地址,私密路由使用你的 SMP 服务器来传送消息。 + 私密消息路由 + 私密路由 + 当 IP 地址受保护且你的服务器或目标服务器不支持私密路由时,直接发送消息。 + 服务器地址和网络设置不兼容。 + 允许降级 + 服务器版本和网络设置不兼容。 + 未受保护 + 不直接发送消息,即便你的服务器或目标服务器不支持私密路由。 + 转发服务器:%1$s +\n目标服务器错误:%2$s + 消息路由模式 + 未知服务器! + 没有 Tor 或 VPN,这些 XFTP 中继可以看到你的 IP 地址: +\n%1$s. + 没有 Tor 或 VPN,文件服务器可以看到你的 IP 地址。 + 保护 IP 地址 + 文件 + 应用将请求确认来自未知服务器的下载(.onion 或启用 SOCKS 代理时除外)。 + 个人资料主题 + 在新窗口中显示聊天列表 + 所有颜色模式 + 应用到 + + 颜色模式 + 深色 + 深色模式 + 深色模式颜色 + 填充 + 适配 + 下午好! + 早上好! + 浅色 + 浅色模式 + 收到的回复 + 删除图片 + 已发送回复 + 设置默认主题 + 系统 + 壁纸强调色 + 壁纸背景色 + 额外的强调色2 + 高级设置 + 聊天颜色 + 重复 + 聊天主题 + 重置颜色 + 缩放 \ No newline at end of file From 0ae9f5ebba60a9c03a6a432eb19b70576ec004da Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Tue, 28 May 2024 11:23:58 +0100 Subject: [PATCH 13/21] website: translations (#4241) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Translated using Weblate (German) Currently translated at 100.0% (257 of 257 strings) Translation: SimpleX Chat/SimpleX Chat website Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/de/ * Translated using Weblate (Italian) Currently translated at 100.0% (257 of 257 strings) Translation: SimpleX Chat/SimpleX Chat website Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/it/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (257 of 257 strings) Translation: SimpleX Chat/SimpleX Chat website Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/zh_Hans/ * Translated using Weblate (Japanese) Currently translated at 100.0% (257 of 257 strings) Translation: SimpleX Chat/SimpleX Chat website Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/ja/ * Translated using Weblate (German) Currently translated at 100.0% (257 of 257 strings) Translation: SimpleX Chat/SimpleX Chat website Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/de/ * Translated using Weblate (Italian) Currently translated at 100.0% (257 of 257 strings) Translation: SimpleX Chat/SimpleX Chat website Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/it/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (257 of 257 strings) Translation: SimpleX Chat/SimpleX Chat website Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/zh_Hans/ * Translated using Weblate (Japanese) Currently translated at 100.0% (257 of 257 strings) Translation: SimpleX Chat/SimpleX Chat website Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/ja/ --------- Co-authored-by: mlanp Co-authored-by: Random Co-authored-by: 大王叫我来巡山 Co-authored-by: Miyu Sakatsuki --- website/langs/de.json | 2 +- website/langs/it.json | 2 +- website/langs/ja.json | 2 +- website/langs/zh_Hans.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/website/langs/de.json b/website/langs/de.json index c6bcc9920f..0972423887 100644 --- a/website/langs/de.json +++ b/website/langs/de.json @@ -237,7 +237,7 @@ "f-droid-org-repo": "F-Droid.org Repository", "stable-versions-built-by-f-droid-org": "Von F-Droid.org erstellte stabile Versionen", "f-droid-page-f-droid-org-repo-section-text": "SimpleX Chat- und F-Droid.org-Repositorys signieren ihre Builds mit verschiedenen Schlüsseln. Zum Umschalten bitte die Chat-Datenbank exportieren und die App neu installieren.", - "releases-to-this-repo-are-done-1-2-days-later": "Die Versionen für dieses Repository werden 1..2 Tage später erstellt", + "releases-to-this-repo-are-done-1-2-days-later": "Die Versionen für dieses Repository werden einige Tage später erstellt", "docs-dropdown-8": "SimpleX Verzeichnisdienst", "simplex-chat-via-f-droid": "SimpleX Chat per F-Droid", "simplex-chat-repo": "SimpleX Chat Repository", diff --git a/website/langs/it.json b/website/langs/it.json index c2425f93fd..64d3b4b8a4 100644 --- a/website/langs/it.json +++ b/website/langs/it.json @@ -233,7 +233,7 @@ "guide-dropdown-8": "Impostazioni dell'app", "docs-dropdown-7": "Traduci SimpleX Chat", "glossary": "Glossario", - "releases-to-this-repo-are-done-1-2-days-later": "Le pubblicazioni su questo repo avvengono 1-2 giorni dopo", + "releases-to-this-repo-are-done-1-2-days-later": "Le pubblicazioni su questo repo avvengono diversi giorni dopo", "f-droid-page-f-droid-org-repo-section-text": "I repository di SimpleX Chat e F-Droid.org firmano i pacchetti con chiavi diverse. Per passare da uno all'altro, esporta il database della chat e reinstalla l'app.", "signing-key-fingerprint": "Impronta della chiave di firma (SHA-256)", "f-droid-org-repo": "Repo di F-Droid.org", diff --git a/website/langs/ja.json b/website/langs/ja.json index 3ac040272f..4b30104615 100644 --- a/website/langs/ja.json +++ b/website/langs/ja.json @@ -123,7 +123,7 @@ "no-resilient": "いいえ - 弾力性", "hide-info": "情報を隠す", "privacy-matters-overlay-card-3-p-4": "エンドツーエンドで暗号化されたメッセンジャーを使用するだけでは十分ではありません。私たちは皆、個人ネットワークのプライバシーを保護するメッセンジャーを使用する必要があります — 私たちがつながっているのは誰なのか。", - "releases-to-this-repo-are-done-1-2-days-later": "このリポジトリへのリリースは 1 ~ 2 日後に行われます", + "releases-to-this-repo-are-done-1-2-days-later": "このリポジトリへのリリースは数日後に行われます", "comparison-point-1-text": "グローバル ID が必要", "comparison-section-list-point-5": "ユーザーのメタデータのプライバシーを保護しない", "hero-overlay-card-2-p-2": "その後、この情報を既存の公開ソーシャル ネットワークと関連付けて、本当の身元を特定することができます。", diff --git a/website/langs/zh_Hans.json b/website/langs/zh_Hans.json index a81f4d123c..01f6149669 100644 --- a/website/langs/zh_Hans.json +++ b/website/langs/zh_Hans.json @@ -235,7 +235,7 @@ "glossary": "术语表", "signing-key-fingerprint": "签名密钥指纹 (SHA-256)", "simplex-chat-via-f-droid": "通过 F-Droid 下载 SimpleX", - "releases-to-this-repo-are-done-1-2-days-later": "此存储库的版本将延迟 1-2 天发布", + "releases-to-this-repo-are-done-1-2-days-later": "此存储库的版本将延迟数天发布", "f-droid-org-repo": "F-Droid.org 存储库", "stable-versions-built-by-f-droid-org": "由 F-Droid.org 构建的稳定版本", "simplex-chat-repo": "SimpleX 存储库", From d79b4dfb5aa02bc4933360e5eb89a60135d37500 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Tue, 28 May 2024 17:24:57 +0700 Subject: [PATCH 14/21] android: replace new line in Uri before transforming it to URI (#4240) --- .../kotlin/chat/simplex/common/helpers/Extensions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/helpers/Extensions.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/helpers/Extensions.kt index e237272eb0..eb87dd1e28 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/helpers/Extensions.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/helpers/Extensions.kt @@ -17,6 +17,6 @@ val NotificationsMode.requiresIgnoringBattery lateinit var APPLICATION_ID: String -fun Uri.toURI(): URI = URI(toString()) +fun Uri.toURI(): URI = URI(toString().replace("\n", "")) fun URI.toUri(): Uri = Uri.parse(toString()) From 3d395b0e450d33cc1a7687d5777279b3a19ffcb6 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Tue, 28 May 2024 16:42:07 +0400 Subject: [PATCH 15/21] core: inactive connections/members (#4009) --- cabal.project | 2 +- scripts/nix/sha256map.nix | 2 +- simplex-chat.cabal | 1 + src/Simplex/Chat.hs | 65 ++++++++++++--- src/Simplex/Chat/Controller.hs | 1 + .../Migrations/M20240528_quota_err_counter.hs | 18 +++++ src/Simplex/Chat/Migrations/chat_schema.sql | 1 + src/Simplex/Chat/Store/Connections.hs | 2 +- src/Simplex/Chat/Store/Direct.hs | 37 ++++++--- src/Simplex/Chat/Store/Groups.hs | 14 ++-- src/Simplex/Chat/Store/Messages.hs | 2 +- src/Simplex/Chat/Store/Migrations.hs | 4 +- src/Simplex/Chat/Store/Profiles.hs | 4 +- src/Simplex/Chat/Store/Shared.hs | 14 ++-- src/Simplex/Chat/Types.hs | 10 +++ src/Simplex/Chat/View.hs | 6 ++ tests/ChatClient.hs | 9 ++- tests/ChatTests/Groups.hs | 80 +++++++++++++++++++ 18 files changed, 226 insertions(+), 46 deletions(-) create mode 100644 src/Simplex/Chat/Migrations/M20240528_quota_err_counter.hs diff --git a/cabal.project b/cabal.project index a68df42bf7..9fd0c4928a 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: bd67844169d2206d8543c01e6ed966315115b0e3 + tag: 199f85ec62bcbadd11dc05bb97cce6556dafb384 source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 468ca71307..2733c6c1eb 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."bd67844169d2206d8543c01e6ed966315115b0e3" = "1g218q15hrg21h8gyidavfys5zx8dzmxq7iwfm5bfaw71grpd7pn"; + "https://github.com/simplex-chat/simplexmq.git"."199f85ec62bcbadd11dc05bb97cce6556dafb384" = "0x5c29x5h1832hks0wpxy84x16rn13pi9zd2j9x8lvb3y8h0ddk0"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; diff --git a/simplex-chat.cabal b/simplex-chat.cabal index 11c0cc0731..85873c2d1c 100644 --- a/simplex-chat.cabal +++ b/simplex-chat.cabal @@ -145,6 +145,7 @@ library Simplex.Chat.Migrations.M20240501_chat_deleted Simplex.Chat.Migrations.M20240510_chat_items_via_proxy Simplex.Chat.Migrations.M20240515_rcv_files_user_approved_relays + Simplex.Chat.Migrations.M20240528_quota_err_counter Simplex.Chat.Mobile Simplex.Chat.Mobile.File Simplex.Chat.Mobile.Shared diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 77fac9ddc2..c674b6a564 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -1472,14 +1472,14 @@ processChatCommand' vr = \case ct@Contact {activeConn} <- withStore $ \db -> getContact db vr user contactId case activeConn of Just conn -> do - withStore' $ \db -> setConnectionAuthErrCounter db user conn 0 + withStore' $ \db -> setAuthErrCounter db user conn 0 ok user Nothing -> throwChatError $ CEContactNotActive ct APIEnableGroupMember gId gMemberId -> withUser $ \user -> do GroupMember {activeConn} <- withStore $ \db -> getGroupMember db vr user gId gMemberId case activeConn of Just conn -> do - withStore' $ \db -> setConnectionAuthErrCounter db user conn 0 + withStore' $ \db -> setAuthErrCounter db user conn 0 ok user _ -> throwChatError CEGroupMemberNotActive SetShowMessages cName ntfOn -> updateChatSettings cName (\cs -> cs {enableNtfs = ntfOn}) @@ -3960,14 +3960,19 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = withAckMessage' "new contact msg" agentConnId meta $ void $ saveDirectRcvMSG conn meta msgBody - SENT msgId _proxy -> + SENT msgId _proxy -> do + void $ continueSending connEntity conn sentMsgDeliveryEvent conn msgId OK -> -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () + QCONT -> + void $ continueSending connEntity conn + MWARN _ err -> + processConnMWARN connEntity conn err MERR _ err -> do toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) - incAuthErrCounter connEntity conn err + processConnMERR connEntity conn err MERRS _ err -> do -- error cannot be AUTH error here toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) @@ -4098,6 +4103,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = let connectedIncognito = contactConnIncognito ct || incognitoMembership gInfo when (memberCategory m == GCPreMember) $ probeMatchingContactsAndMembers ct connectedIncognito True SENT msgId proxy -> do + void $ continueSending connEntity conn sentMsgDeliveryEvent conn msgId checkSndInlineFTComplete conn msgId ci_ <- withStore $ \db -> do @@ -4138,12 +4144,15 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = OK -> -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () - MWARN msgId err -> + QCONT -> + void $ continueSending connEntity conn + MWARN msgId err -> do updateDirectItemStatus ct conn msgId (CISSndWarning $ agentSndError err) + processConnMWARN connEntity conn err MERR msgId err -> do updateDirectItemStatus ct conn msgId (CISSndError $ agentSndError err) toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) - incAuthErrCounter connEntity conn err + processConnMERR connEntity conn err MERRS msgIds err -> do -- error cannot be AUTH error here updateDirectItemsStatus ct conn (L.toList msgIds) (CISSndError $ agentSndError err) @@ -4492,9 +4501,11 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = withAckMessage' "group rcvd" agentConnId msgMeta $ groupMsgReceived gInfo m conn msgMeta msgRcpt SENT msgId proxy -> do + continued <- continueSending connEntity conn sentMsgDeliveryEvent conn msgId checkSndInlineFTComplete conn msgId updateGroupItemStatus gInfo m conn msgId (CISSndSent SSPComplete) (Just $ isJust proxy) + when continued $ sendPendingGroupMessages user m conn SWITCH qd phase cStats -> do toView $ CRGroupMemberSwitch user gInfo m (SwitchProgress qd phase cStats) when (phase `elem` [SPStarted, SPCompleted]) $ case qd of @@ -4530,13 +4541,17 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = OK -> -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () - MWARN msgId err -> + QCONT -> do + continued <- continueSending connEntity conn + when continued $ sendPendingGroupMessages user m conn + MWARN msgId err -> do withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) (CISSndWarning $ agentSndError err) + processConnMWARN connEntity conn err MERR msgId err -> do withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) (CISSndError $ agentSndError err) -- group errors are silenced to reduce load on UI event log -- toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) - incAuthErrCounter connEntity conn err + processConnMERR connEntity conn err MERRS msgIds err -> do let newStatus = CISSndError $ agentSndError err -- error cannot be AUTH error here @@ -4666,7 +4681,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () MERR _ err -> do toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) - incAuthErrCounter connEntity conn err + processConnMERR connEntity conn err ERR err -> do toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () @@ -4718,7 +4733,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = _ -> pure () MERR _ err -> do toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) - incAuthErrCounter connEntity conn err + processConnMERR connEntity conn err ERR err -> do toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () @@ -4758,17 +4773,40 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = | memberRole <= GRObserver = messageError "member is not allowed to send messages" | otherwise = a - incAuthErrCounter :: ConnectionEntity -> Connection -> AgentErrorType -> CM () - incAuthErrCounter connEntity conn err = do + processConnMERR :: ConnectionEntity -> Connection -> AgentErrorType -> CM () + processConnMERR connEntity conn err = do case err of SMP _ SMP.AUTH -> do - authErrCounter' <- withStore' $ \db -> incConnectionAuthErrCounter db user conn + authErrCounter' <- withStore' $ \db -> incAuthErrCounter db user conn when (authErrCounter' >= authErrDisableCount) $ case connEntity of RcvDirectMsgConnection ctConn (Just ct) -> do toView $ CRContactDisabled user ct {activeConn = Just ctConn {authErrCounter = authErrCounter'}} _ -> toView $ CRConnectionDisabled connEntity + SMP _ SMP.QUOTA -> + unless (connInactive conn) $ do + withStore' $ \db -> setQuotaErrCounter db user conn quotaErrSetOnMERR + toView $ CRConnectionInactive connEntity True _ -> pure () + processConnMWARN :: ConnectionEntity -> Connection -> AgentErrorType -> CM () + processConnMWARN connEntity conn err = do + case err of + SMP _ SMP.QUOTA -> + unless (connInactive conn) $ do + quotaErrCounter' <- withStore' $ \db -> incQuotaErrCounter db user conn + when (quotaErrCounter' >= quotaErrInactiveCount) $ + toView $ CRConnectionInactive connEntity True + _ -> pure () + + continueSending :: ConnectionEntity -> Connection -> CM Bool + continueSending connEntity conn = + if connInactive conn + then do + withStore' $ \db -> setQuotaErrCounter db user conn 0 + toView $ CRConnectionInactive connEntity False + pure True + else pure False + -- TODO v5.7 / v6.0 - together with deprecating old group protocol establishing direct connections? -- we could save command records only for agent APIs we process continuations for (INV) withCompletedCommand :: forall e. AEntityI e => Connection -> ACommand 'Agent e -> (CommandData -> CM ()) -> CM () @@ -6726,6 +6764,7 @@ memberSendAction chatMsgEvent members m@GroupMember {invitedByGroupMemberId} = c Nothing -> pendingOrForwarded Just conn@Connection {connStatus} | connDisabled conn || connStatus == ConnDeleted -> Nothing + | connInactive conn -> Just MSAPending | connStatus == ConnSndReady || connStatus == ConnReady -> Just (MSASend conn) | otherwise -> pendingOrForwarded where diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index 2c4c09c79c..c83044d564 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -752,6 +752,7 @@ data ChatResponse | CRAgentMsgCounts {msgCounts :: [(Text, (Int, Int))]} | CRContactDisabled {user :: User, contact :: Contact} | CRConnectionDisabled {connectionEntity :: ConnectionEntity} + | CRConnectionInactive {connectionEntity :: ConnectionEntity, inactive :: Bool} | CRAgentRcvQueueDeleted {agentConnId :: AgentConnId, server :: SMPServer, agentQueueId :: AgentQueueId, agentError_ :: Maybe AgentErrorType} | CRAgentConnDeleted {agentConnId :: AgentConnId} | CRAgentUserDeleted {agentUserId :: Int64} diff --git a/src/Simplex/Chat/Migrations/M20240528_quota_err_counter.hs b/src/Simplex/Chat/Migrations/M20240528_quota_err_counter.hs new file mode 100644 index 0000000000..ea1f3a78e7 --- /dev/null +++ b/src/Simplex/Chat/Migrations/M20240528_quota_err_counter.hs @@ -0,0 +1,18 @@ +{-# LANGUAGE QuasiQuotes #-} + +module Simplex.Chat.Migrations.M20240528_quota_err_counter where + +import Database.SQLite.Simple (Query) +import Database.SQLite.Simple.QQ (sql) + +m20240528_quota_err_counter :: Query +m20240528_quota_err_counter = + [sql| +ALTER TABLE connections ADD COLUMN quota_err_counter INTEGER NOT NULL DEFAULT 0; +|] + +down_m20240528_quota_err_counter :: Query +down_m20240528_quota_err_counter = + [sql| +ALTER TABLE connections DROP COLUMN quota_err_counter; +|] diff --git a/src/Simplex/Chat/Migrations/chat_schema.sql b/src/Simplex/Chat/Migrations/chat_schema.sql index 96d55badf9..fdbc44a9c3 100644 --- a/src/Simplex/Chat/Migrations/chat_schema.sql +++ b/src/Simplex/Chat/Migrations/chat_schema.sql @@ -289,6 +289,7 @@ CREATE TABLE connections( pq_encryption INTEGER NOT NULL DEFAULT 0, pq_snd_enabled INTEGER, pq_rcv_enabled INTEGER, + quota_err_counter INTEGER NOT NULL DEFAULT 0, FOREIGN KEY(snd_file_id, connection_id) REFERENCES snd_files(file_id, connection_id) ON DELETE CASCADE diff --git a/src/Simplex/Chat/Store/Connections.hs b/src/Simplex/Chat/Store/Connections.hs index 0d085d216c..2c7543f08a 100644 --- a/src/Simplex/Chat/Store/Connections.hs +++ b/src/Simplex/Chat/Store/Connections.hs @@ -85,7 +85,7 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do [sql| SELECT connection_id, agent_conn_id, conn_level, via_contact, via_user_contact_link, via_group_link, group_link_id, custom_user_profile_id, conn_status, conn_type, contact_conn_initiated, local_alias, contact_id, group_member_id, snd_file_id, rcv_file_id, user_contact_link_id, - created_at, security_code, security_code_verified_at, pq_support, pq_encryption, pq_snd_enabled, pq_rcv_enabled, auth_err_counter, + created_at, security_code, security_code_verified_at, pq_support, pq_encryption, pq_snd_enabled, pq_rcv_enabled, auth_err_counter, quota_err_counter, conn_chat_version, peer_chat_min_version, peer_chat_max_version FROM connections WHERE user_id = ? AND agent_conn_id = ? diff --git a/src/Simplex/Chat/Store/Direct.hs b/src/Simplex/Chat/Store/Direct.hs index afbd3f7960..1145c2494b 100644 --- a/src/Simplex/Chat/Store/Direct.hs +++ b/src/Simplex/Chat/Store/Direct.hs @@ -51,8 +51,10 @@ module Simplex.Chat.Store.Direct updateContactStatus, updateGroupUnreadChat, setConnectionVerified, - incConnectionAuthErrCounter, - setConnectionAuthErrCounter, + incAuthErrCounter, + setAuthErrCounter, + incQuotaErrCounter, + setQuotaErrCounter, getUserContacts, createOrUpdateContactRequest, getContactRequest', @@ -183,7 +185,7 @@ getContactByConnReqHash db vr user@User {userId} cReqHash = cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.chat_deleted, ct.custom_data, -- Connection c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, - c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, + c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter, c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version FROM contacts ct JOIN contact_profiles cp ON ct.contact_profile_id = cp.contact_profile_id @@ -473,19 +475,32 @@ setConnectionVerified db User {userId} connId code = do updatedAt <- getCurrentTime DB.execute db "UPDATE connections SET security_code = ?, security_code_verified_at = ?, updated_at = ? WHERE user_id = ? AND connection_id = ?" (code, code $> updatedAt, updatedAt, userId, connId) -incConnectionAuthErrCounter :: DB.Connection -> User -> Connection -> IO Int -incConnectionAuthErrCounter db User {userId} Connection {connId, authErrCounter} = do +incAuthErrCounter :: DB.Connection -> User -> Connection -> IO Int +incAuthErrCounter db User {userId} Connection {connId, authErrCounter} = do updatedAt <- getCurrentTime (counter_ :: Maybe Int) <- maybeFirstRow fromOnly $ DB.query db "SELECT auth_err_counter FROM connections WHERE user_id = ? AND connection_id = ?" (userId, connId) let counter' = fromMaybe authErrCounter counter_ + 1 DB.execute db "UPDATE connections SET auth_err_counter = ?, updated_at = ? WHERE user_id = ? AND connection_id = ?" (counter', updatedAt, userId, connId) pure counter' -setConnectionAuthErrCounter :: DB.Connection -> User -> Connection -> Int -> IO () -setConnectionAuthErrCounter db User {userId} Connection {connId} counter = do +setAuthErrCounter :: DB.Connection -> User -> Connection -> Int -> IO () +setAuthErrCounter db User {userId} Connection {connId} counter = do updatedAt <- getCurrentTime DB.execute db "UPDATE connections SET auth_err_counter = ?, updated_at = ? WHERE user_id = ? AND connection_id = ?" (counter, updatedAt, userId, connId) +incQuotaErrCounter :: DB.Connection -> User -> Connection -> IO Int +incQuotaErrCounter db User {userId} Connection {connId, quotaErrCounter} = do + updatedAt <- getCurrentTime + (counter_ :: Maybe Int) <- maybeFirstRow fromOnly $ DB.query db "SELECT quota_err_counter FROM connections WHERE user_id = ? AND connection_id = ?" (userId, connId) + let counter' = fromMaybe quotaErrCounter counter_ + 1 + DB.execute db "UPDATE connections SET quota_err_counter = ?, updated_at = ? WHERE user_id = ? AND connection_id = ?" (counter', updatedAt, userId, connId) + pure counter' + +setQuotaErrCounter :: DB.Connection -> User -> Connection -> Int -> IO () +setQuotaErrCounter db User {userId} Connection {connId} counter = do + updatedAt <- getCurrentTime + DB.execute db "UPDATE connections SET quota_err_counter = ?, updated_at = ? WHERE user_id = ? AND connection_id = ?" (counter, updatedAt, userId, connId) + updateContactProfile_ :: DB.Connection -> UserId -> ProfileId -> Profile -> IO () updateContactProfile_ db userId profileId profile = do currentTs <- getCurrentTime @@ -609,7 +624,7 @@ createOrUpdateContactRequest db vr user@User {userId} userContactLinkId invId (V cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.chat_deleted, ct.custom_data, -- Connection c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, - c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, + c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter, c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version FROM contacts ct JOIN contact_profiles cp ON ct.contact_profile_id = cp.contact_profile_id @@ -794,7 +809,7 @@ getContact_ db vr user@User {userId} contactId deleted = cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.chat_deleted, ct.custom_data, -- Connection c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, - c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, + c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter, c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version FROM contacts ct JOIN contact_profiles cp ON ct.contact_profile_id = cp.contact_profile_id @@ -848,7 +863,7 @@ getContactConnections db vr userId Contact {contactId} = [sql| SELECT c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, - c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, + c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter, c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version FROM connections c JOIN contacts ct ON ct.contact_id = c.contact_id @@ -866,7 +881,7 @@ getConnectionById db vr User {userId} connId = ExceptT $ do [sql| SELECT connection_id, agent_conn_id, conn_level, via_contact, via_user_contact_link, via_group_link, group_link_id, custom_user_profile_id, conn_status, conn_type, contact_conn_initiated, local_alias, contact_id, group_member_id, snd_file_id, rcv_file_id, user_contact_link_id, - created_at, security_code, security_code_verified_at, pq_support, pq_encryption, pq_snd_enabled, pq_rcv_enabled, auth_err_counter, + created_at, security_code, security_code_verified_at, pq_support, pq_encryption, pq_snd_enabled, pq_rcv_enabled, auth_err_counter, quota_err_counter, conn_chat_version, peer_chat_min_version, peer_chat_max_version FROM connections WHERE user_id = ? AND connection_id = ? diff --git a/src/Simplex/Chat/Store/Groups.hs b/src/Simplex/Chat/Store/Groups.hs index 21b50113b0..42637d4169 100644 --- a/src/Simplex/Chat/Store/Groups.hs +++ b/src/Simplex/Chat/Store/Groups.hs @@ -201,7 +201,7 @@ getGroupLinkConnection db vr User {userId} groupInfo@GroupInfo {groupId} = [sql| SELECT c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, - c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, + c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter, c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version FROM connections c JOIN user_contact_links uc ON c.user_contact_link_id = uc.user_contact_link_id @@ -287,7 +287,7 @@ getGroupAndMember db User {userId, userContactId} groupMemberId vr = m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences, c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, - c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, + c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter, c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version FROM group_members m JOIN contact_profiles p ON p.contact_profile_id = COALESCE(m.member_profile_id, m.contact_profile_id) @@ -705,7 +705,7 @@ groupMemberQuery = m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences, c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, - c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, + c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter, c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version FROM group_members m JOIN contact_profiles p ON p.contact_profile_id = COALESCE(m.member_profile_id, m.contact_profile_id) @@ -1326,7 +1326,7 @@ getViaGroupMember db vr User {userId, userContactId} Contact {contactId} = m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences, c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, - c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, + c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter, c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version FROM group_members m JOIN contacts ct ON ct.contact_id = m.contact_id @@ -1970,7 +1970,8 @@ createMemberContact pqEncryption = PQEncOff, pqSndEnabled = Nothing, pqRcvEnabled = Nothing, - authErrCounter = 0 + authErrCounter = 0, + quotaErrCounter = 0 } mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito ctConn pure Contact {contactId, localDisplayName, profile = memberProfile, activeConn = Just ctConn, viaGroup = Nothing, contactUsed = True, contactStatus = CSActive, chatSettings = defaultChatSettings, userPreferences, mergedPreferences, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs, contactGroupMemberId = Just groupMemberId, contactGrpInvSent = False, uiThemes = Nothing, chatDeleted = False, customData = Nothing} @@ -2103,7 +2104,8 @@ createMemberContactConn_ pqEncryption = PQEncOff, pqSndEnabled = Nothing, pqRcvEnabled = Nothing, - authErrCounter = 0 + authErrCounter = 0, + quotaErrCounter = 0 } updateMemberProfile :: DB.Connection -> User -> GroupMember -> Profile -> ExceptT StoreError IO GroupMember diff --git a/src/Simplex/Chat/Store/Messages.hs b/src/Simplex/Chat/Store/Messages.hs index 0487b80c17..494e5635f4 100644 --- a/src/Simplex/Chat/Store/Messages.hs +++ b/src/Simplex/Chat/Store/Messages.hs @@ -295,7 +295,7 @@ getPendingGroupMessages db groupMemberId = FROM pending_group_messages pgm JOIN messages m USING (message_id) WHERE pgm.group_member_id = ? - ORDER BY pgm.message_id ASC + ORDER BY pgm.created_at ASC, pgm.message_id ASC |] (Only groupMemberId) where diff --git a/src/Simplex/Chat/Store/Migrations.hs b/src/Simplex/Chat/Store/Migrations.hs index a79a31f75d..5c9082b361 100644 --- a/src/Simplex/Chat/Store/Migrations.hs +++ b/src/Simplex/Chat/Store/Migrations.hs @@ -109,6 +109,7 @@ import Simplex.Chat.Migrations.M20240430_ui_theme import Simplex.Chat.Migrations.M20240501_chat_deleted import Simplex.Chat.Migrations.M20240510_chat_items_via_proxy import Simplex.Chat.Migrations.M20240515_rcv_files_user_approved_relays +import Simplex.Chat.Migrations.M20240528_quota_err_counter import Simplex.Messaging.Agent.Store.SQLite.Migrations (Migration (..)) schemaMigrations :: [(String, Query, Maybe Query)] @@ -217,7 +218,8 @@ schemaMigrations = ("20240430_ui_theme", m20240430_ui_theme, Just down_m20240430_ui_theme), ("20240501_chat_deleted", m20240501_chat_deleted, Just down_m20240501_chat_deleted), ("20240510_chat_items_via_proxy", m20240510_chat_items_via_proxy, Just down_m20240510_chat_items_via_proxy), - ("20240515_rcv_files_user_approved_relays", m20240515_rcv_files_user_approved_relays, Just down_m20240515_rcv_files_user_approved_relays) + ("20240515_rcv_files_user_approved_relays", m20240515_rcv_files_user_approved_relays, Just down_m20240515_rcv_files_user_approved_relays), + ("20240528_quota_err_counter", m20240528_quota_err_counter, Just down_m20240528_quota_err_counter) ] -- | The list of migrations in ascending order by date diff --git a/src/Simplex/Chat/Store/Profiles.hs b/src/Simplex/Chat/Store/Profiles.hs index 9b83e7299f..be06ea8878 100644 --- a/src/Simplex/Chat/Store/Profiles.hs +++ b/src/Simplex/Chat/Store/Profiles.hs @@ -342,7 +342,7 @@ getUserAddressConnections db vr User {userId} = do [sql| SELECT c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, - c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, + c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter, c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version FROM connections c JOIN user_contact_links uc ON c.user_contact_link_id = uc.user_contact_link_id @@ -358,7 +358,7 @@ getUserContactLinks db vr User {userId} = [sql| SELECT c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, - c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, + c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter, c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version, uc.user_contact_link_id, uc.conn_req_contact, uc.group_id FROM connections c diff --git a/src/Simplex/Chat/Store/Shared.hs b/src/Simplex/Chat/Store/Shared.hs index 113a84966d..c364cf10c2 100644 --- a/src/Simplex/Chat/Store/Shared.hs +++ b/src/Simplex/Chat/Store/Shared.hs @@ -163,12 +163,12 @@ toFileInfo (fileId, fileStatus, filePath) = CIFileInfo {fileId, fileStatus, file type EntityIdsRow = (Maybe Int64, Maybe Int64, Maybe Int64, Maybe Int64, Maybe Int64) -type ConnectionRow = (Int64, ConnId, Int, Maybe Int64, Maybe Int64, Bool, Maybe GroupLinkId, Maybe Int64, ConnStatus, ConnType, Bool, LocalAlias) :. EntityIdsRow :. (UTCTime, Maybe Text, Maybe UTCTime, PQSupport, PQEncryption, Maybe PQEncryption, Maybe PQEncryption, Int, Maybe VersionChat, VersionChat, VersionChat) +type ConnectionRow = (Int64, ConnId, Int, Maybe Int64, Maybe Int64, Bool, Maybe GroupLinkId, Maybe Int64, ConnStatus, ConnType, Bool, LocalAlias) :. EntityIdsRow :. (UTCTime, Maybe Text, Maybe UTCTime, PQSupport, PQEncryption, Maybe PQEncryption, Maybe PQEncryption, Int, Int, Maybe VersionChat, VersionChat, VersionChat) -type MaybeConnectionRow = (Maybe Int64, Maybe ConnId, Maybe Int, Maybe Int64, Maybe Int64, Maybe Bool, Maybe GroupLinkId, Maybe Int64, Maybe ConnStatus, Maybe ConnType, Maybe Bool, Maybe LocalAlias) :. EntityIdsRow :. (Maybe UTCTime, Maybe Text, Maybe UTCTime, Maybe PQSupport, Maybe PQEncryption, Maybe PQEncryption, Maybe PQEncryption, Maybe Int, Maybe VersionChat, Maybe VersionChat, Maybe VersionChat) +type MaybeConnectionRow = (Maybe Int64, Maybe ConnId, Maybe Int, Maybe Int64, Maybe Int64, Maybe Bool, Maybe GroupLinkId, Maybe Int64, Maybe ConnStatus, Maybe ConnType, Maybe Bool, Maybe LocalAlias) :. EntityIdsRow :. (Maybe UTCTime, Maybe Text, Maybe UTCTime, Maybe PQSupport, Maybe PQEncryption, Maybe PQEncryption, Maybe PQEncryption, Maybe Int, Maybe Int, Maybe VersionChat, Maybe VersionChat, Maybe VersionChat) toConnection :: VersionRangeChat -> ConnectionRow -> Connection -toConnection vr ((connId, acId, connLevel, viaContact, viaUserContactLink, viaGroupLink, groupLinkId, customUserProfileId, connStatus, connType, contactConnInitiated, localAlias) :. (contactId, groupMemberId, sndFileId, rcvFileId, userContactLinkId) :. (createdAt, code_, verifiedAt_, pqSupport, pqEncryption, pqSndEnabled, pqRcvEnabled, authErrCounter, chatV, minVer, maxVer)) = +toConnection vr ((connId, acId, connLevel, viaContact, viaUserContactLink, viaGroupLink, groupLinkId, customUserProfileId, connStatus, connType, contactConnInitiated, localAlias) :. (contactId, groupMemberId, sndFileId, rcvFileId, userContactLinkId) :. (createdAt, code_, verifiedAt_, pqSupport, pqEncryption, pqSndEnabled, pqRcvEnabled, authErrCounter, quotaErrCounter, chatV, minVer, maxVer)) = Connection { connId, agentConnId = AgentConnId acId, @@ -191,6 +191,7 @@ toConnection vr ((connId, acId, connLevel, viaContact, viaUserContactLink, viaGr pqSndEnabled, pqRcvEnabled, authErrCounter, + quotaErrCounter, createdAt } where @@ -203,8 +204,8 @@ toConnection vr ((connId, acId, connLevel, viaContact, viaUserContactLink, viaGr entityId_ ConnUserContact = userContactLinkId toMaybeConnection :: VersionRangeChat -> MaybeConnectionRow -> Maybe Connection -toMaybeConnection vr ((Just connId, Just agentConnId, Just connLevel, viaContact, viaUserContactLink, Just viaGroupLink, groupLinkId, customUserProfileId, Just connStatus, Just connType, Just contactConnInitiated, Just localAlias) :. (contactId, groupMemberId, sndFileId, rcvFileId, userContactLinkId) :. (Just createdAt, code_, verifiedAt_, Just pqSupport, Just pqEncryption, pqSndEnabled_, pqRcvEnabled_, Just authErrCounter, connChatVersion, Just minVer, Just maxVer)) = - Just $ toConnection vr ((connId, agentConnId, connLevel, viaContact, viaUserContactLink, viaGroupLink, groupLinkId, customUserProfileId, connStatus, connType, contactConnInitiated, localAlias) :. (contactId, groupMemberId, sndFileId, rcvFileId, userContactLinkId) :. (createdAt, code_, verifiedAt_, pqSupport, pqEncryption, pqSndEnabled_, pqRcvEnabled_, authErrCounter, connChatVersion, minVer, maxVer)) +toMaybeConnection vr ((Just connId, Just agentConnId, Just connLevel, viaContact, viaUserContactLink, Just viaGroupLink, groupLinkId, customUserProfileId, Just connStatus, Just connType, Just contactConnInitiated, Just localAlias) :. (contactId, groupMemberId, sndFileId, rcvFileId, userContactLinkId) :. (Just createdAt, code_, verifiedAt_, Just pqSupport, Just pqEncryption, pqSndEnabled_, pqRcvEnabled_, Just authErrCounter, Just quotaErrCounter, connChatVersion, Just minVer, Just maxVer)) = + Just $ toConnection vr ((connId, agentConnId, connLevel, viaContact, viaUserContactLink, viaGroupLink, groupLinkId, customUserProfileId, connStatus, connType, contactConnInitiated, localAlias) :. (contactId, groupMemberId, sndFileId, rcvFileId, userContactLinkId) :. (createdAt, code_, verifiedAt_, pqSupport, pqEncryption, pqSndEnabled_, pqRcvEnabled_, authErrCounter, quotaErrCounter, connChatVersion, minVer, maxVer)) toMaybeConnection _ _ = Nothing createConnection_ :: DB.Connection -> UserId -> ConnType -> Maybe Int64 -> ConnId -> VersionChat -> VersionRangeChat -> Maybe ContactId -> Maybe Int64 -> Maybe ProfileId -> Int -> UTCTime -> SubscriptionMode -> PQSupport -> IO Connection @@ -249,7 +250,8 @@ createConnection_ db userId connType entityId acId connChatVersion peerChatVRang pqEncryption = CR.pqSupportToEnc pqSup, pqSndEnabled = Nothing, pqRcvEnabled = Nothing, - authErrCounter = 0 + authErrCounter = 0, + quotaErrCounter = 0 } where ent ct = if connType == ct then entityId else Nothing diff --git a/src/Simplex/Chat/Types.hs b/src/Simplex/Chat/Types.hs index ca6cd2e375..047a9c68f7 100644 --- a/src/Simplex/Chat/Types.hs +++ b/src/Simplex/Chat/Types.hs @@ -1303,6 +1303,7 @@ data Connection = Connection pqSndEnabled :: Maybe PQEncryption, pqRcvEnabled :: Maybe PQEncryption, authErrCounter :: Int, + quotaErrCounter :: Int, -- if exceeds limit messages to group members are created as pending; sending to contacts is unaffected by this createdAt :: UTCTime } deriving (Eq, Show) @@ -1316,6 +1317,15 @@ authErrDisableCount = 10 connDisabled :: Connection -> Bool connDisabled Connection {authErrCounter} = authErrCounter >= authErrDisableCount +quotaErrInactiveCount :: Int +quotaErrInactiveCount = 5 + +quotaErrSetOnMERR :: Int +quotaErrSetOnMERR = 999 + +connInactive :: Connection -> Bool +connInactive Connection {quotaErrCounter} = quotaErrCounter >= quotaErrInactiveCount + data SecurityCode = SecurityCode {securityCode :: Text, verifiedAt :: UTCTime} deriving (Eq, Show) diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index 671706c5f2..90928c7f88 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -378,6 +378,7 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe CRAgentMsgCounts {msgCounts} -> ["received messages (total, duplicates):", plain . LB.unpack $ J.encode msgCounts] CRContactDisabled u c -> ttyUser u ["[" <> ttyContact' c <> "] connection is disabled, to enable: " <> highlight ("/enable " <> viewContactName c) <> ", to delete: " <> highlight ("/d " <> viewContactName c)] CRConnectionDisabled entity -> viewConnectionEntityDisabled entity + CRConnectionInactive entity inactive -> viewConnectionEntityInactive entity inactive CRAgentRcvQueueDeleted acId srv aqId err_ -> [ ("completed deleting rcv queue, agent connection id: " <> sShow acId) <> (", server: " <> sShow srv) @@ -2077,6 +2078,11 @@ viewConnectionEntityDisabled entity = case entity of where entityLabel = connEntityLabel entity +viewConnectionEntityInactive :: ConnectionEntity -> Bool -> [StyledString] +viewConnectionEntityInactive entity inactive + | inactive = ["[" <> connEntityLabel entity <> "] connection is marked as inactive"] + | otherwise = ["[" <> connEntityLabel entity <> "] inactive connection is marked as active"] + connEntityLabel :: ConnectionEntity -> StyledString connEntityLabel = \case RcvDirectMsgConnection _ (Just Contact {localDisplayName = c}) -> plain c diff --git a/tests/ChatClient.hs b/tests/ChatClient.hs index 83ac69ebe9..8f7bd1dc4e 100644 --- a/tests/ChatClient.hs +++ b/tests/ChatClient.hs @@ -401,8 +401,8 @@ testChatCfg4 cfg p1 p2 p3 p4 test = testChatN cfg testOpts [p1, p2, p3, p4] test concurrentlyN_ :: [IO a] -> IO () concurrentlyN_ = mapConcurrently_ id -serverCfg :: ServerConfig -serverCfg = +smpServerCfg :: ServerConfig +smpServerCfg = ServerConfig { transports = [(serverPort, transport @TLS)], tbqSize = 1, @@ -436,7 +436,10 @@ serverCfg = } withSmpServer :: IO () -> IO () -withSmpServer = serverBracket (`runSMPServerBlocking` serverCfg) +withSmpServer = withSmpServer' smpServerCfg + +withSmpServer' :: ServerConfig -> IO () -> IO () +withSmpServer' cfg = serverBracket (`runSMPServerBlocking` cfg) xftpTestPort :: ServiceName xftpTestPort = "7002" diff --git a/tests/ChatTests/Groups.hs b/tests/ChatTests/Groups.hs index 8cd853ade0..009a26cf0b 100644 --- a/tests/ChatTests/Groups.hs +++ b/tests/ChatTests/Groups.hs @@ -1,6 +1,9 @@ +{-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PostfixOperators #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} module ChatTests.Groups where @@ -13,11 +16,16 @@ import qualified Data.ByteString.Char8 as B import Data.List (isInfixOf) import qualified Data.Text as T import Simplex.Chat.Controller (ChatConfig (..)) +import Simplex.Chat.Options import Simplex.Chat.Protocol (supportedChatVRange) import Simplex.Chat.Store (agentStoreFile, chatStoreFile) import Simplex.Chat.Types (VersionRangeChat) import Simplex.Chat.Types.Shared (GroupMemberRole (..)) +import Simplex.Messaging.Agent.Env.SQLite +import Simplex.Messaging.Agent.RetryInterval import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB +import Simplex.Messaging.Server.Env.STM hiding (subscriptions) +import Simplex.Messaging.Transport import System.Directory (copyFile) import System.FilePath (()) import Test.Hspec hiding (it) @@ -150,6 +158,8 @@ chatGroupTests = do it "another admin can unblock" testBlockForAllAnotherAdminUnblocks it "member was blocked before joining group" testBlockForAllBeforeJoining it "can't repeat block, unblock" testBlockForAllCantRepeat + describe "group member inactivity" $ do + it "mark member inactive on reaching quota" testGroupMemberInactive where _0 = supportedChatVRange -- don't create direct connections _1 = groupCreateDirectVRange @@ -6072,3 +6082,73 @@ testBlockForAllCantRepeat = [alice, cath] *<# "#team bob> 3" bob #$> ("/_get chat #1 count=3", chat, [(1, "1"), (1, "2"), (1, "3")]) + +testGroupMemberInactive :: HasCallStack => FilePath -> IO () +testGroupMemberInactive tmp = do + withSmpServer' serverCfg' $ do + withNewTestChatCfgOpts tmp cfg' opts' "alice" aliceProfile $ \alice -> do + withNewTestChatCfgOpts tmp cfg' opts' "bob" bobProfile $ \bob -> do + createGroup2 "team" alice bob + + alice #> "#team hi" + bob <# "#team alice> hi" + bob #> "#team hey" + alice <# "#team bob> hey" + + -- bob is offline + alice #> "#team 1" + alice #> "#team 2" + alice #> "#team 3" + alice <## "[#team bob] connection is marked as inactive" + -- 4 and 5 will be sent to bob as pending messages + alice #> "#team 4" + alice #> "#team 5" + + pgmCount <- withCCTransaction alice $ \db -> + DB.query_ db "SELECT count(1) FROM pending_group_messages" :: IO [[Int]] + pgmCount `shouldBe` [[2]] + + threadDelay 1500000 + + withTestChatCfgOpts tmp cfg' opts' "bob" $ \bob -> do + bob <## "1 contacts connected (use /cs for the list)" + bob <## "#team: connected to server(s)" + bob <# "#team alice> 1" + bob <# "#team alice> 2" + bob <#. "#team alice> skipped message ID" + alice <## "[#team bob] inactive connection is marked as active" + + bob <# "#team alice> 4" + bob <# "#team alice> 5" + + pgmCount' <- withCCTransaction alice $ \db -> + DB.query_ db "SELECT count(1) FROM pending_group_messages" :: IO [[Int]] + pgmCount' `shouldBe` [[0]] + + -- delivery works + alice #> "#team hi" + bob <# "#team alice> hi" + bob #> "#team hey" + alice <# "#team bob> hey" + where + serverCfg' = + smpServerCfg + { transports = [("7003", transport @TLS)], + msgQueueQuota = 2 + } + fastRetryInterval = defaultReconnectInterval {initialInterval = 50_000} -- same as in agent tests + cfg' = + testCfg + { agentConfig = + testAgentCfg + { quotaExceededTimeout = 1, + messageRetryInterval = RetryInterval2 {riFast = fastRetryInterval, riSlow = fastRetryInterval} + } + } + opts' = + testOpts + { coreOptions = + testCoreOpts + { smpServers = ["smp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=:server_password@localhost:7003"] + } + } From 2143eb2d7af3472ef7a9a2ba57afdca204f87550 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Tue, 28 May 2024 18:32:29 +0400 Subject: [PATCH 16/21] core: batch send pending group messages (#4242) --- apps/ios/SimpleXChat/APITypes.swift | 1 - .../chat/simplex/common/model/SimpleXAPI.kt | 2 - src/Simplex/Chat.hs | 49 ++++++++++--------- src/Simplex/Chat/Controller.hs | 1 - src/Simplex/Chat/Messages.hs | 7 --- src/Simplex/Chat/Store/Messages.hs | 8 +-- src/Simplex/Chat/View.hs | 1 - 7 files changed, 30 insertions(+), 39 deletions(-) diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift index 7fa7e961ae..12683bc3a4 100644 --- a/apps/ios/SimpleXChat/APITypes.swift +++ b/apps/ios/SimpleXChat/APITypes.swift @@ -1743,7 +1743,6 @@ public enum ChatErrorType: Decodable { case groupMemberNotActive case groupMemberUserRemoved case groupMemberNotFound - case groupMemberIntroNotFound(contactName: ContactName) case groupCantResendInvitation(groupInfo: GroupInfo, contactName: ContactName) case groupInternal(message: String) case fileNotFound(message: String) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index 78d76a4b5d..b0557e2f67 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -4942,7 +4942,6 @@ sealed class ChatErrorType { is GroupMemberNotActive -> "groupMemberNotActive" is GroupMemberUserRemoved -> "groupMemberUserRemoved" is GroupMemberNotFound -> "groupMemberNotFound" - is GroupMemberIntroNotFound -> "groupMemberIntroNotFound" is GroupCantResendInvitation -> "groupCantResendInvitation" is GroupInternal -> "groupInternal" is FileNotFound -> "fileNotFound" @@ -5022,7 +5021,6 @@ sealed class ChatErrorType { @Serializable @SerialName("groupMemberNotActive") object GroupMemberNotActive: ChatErrorType() @Serializable @SerialName("groupMemberUserRemoved") object GroupMemberUserRemoved: ChatErrorType() @Serializable @SerialName("groupMemberNotFound") object GroupMemberNotFound: ChatErrorType() - @Serializable @SerialName("groupMemberIntroNotFound") class GroupMemberIntroNotFound(val contactName: String): ChatErrorType() @Serializable @SerialName("groupCantResendInvitation") class GroupCantResendInvitation(val groupInfo: GroupInfo, val contactName: String): ChatErrorType() @Serializable @SerialName("groupInternal") class GroupInternal(val message: String): ChatErrorType() @Serializable @SerialName("fileNotFound") class FileNotFound(val message: String): ChatErrorType() diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index c674b6a564..07f8586f33 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -6597,16 +6597,20 @@ sendGroupMemberMessages user conn events groupId = do let idsEvts = L.map (GroupId groupId,) events (errs, msgs) <- lift $ partitionEithers . L.toList <$> createSndMessages idsEvts unless (null errs) $ toView $ CRChatErrors (Just user) errs - forM_ (L.nonEmpty msgs) $ \msgs' -> do - -- TODO v5.7 based on version (?) - -- let shouldCompress = False - -- let batched = if shouldCompress then batchSndMessagesBinary msgs' else batchSndMessagesJSON msgs' - let batched = batchSndMessagesJSON msgs' - let (errs', msgBatches) = partitionEithers batched - -- shouldn't happen, as large messages would have caused createNewSndMessage to throw SELargeMsg - unless (null errs') $ toView $ CRChatErrors (Just user) errs' - forM_ msgBatches $ \batch -> - processSndMessageBatch conn batch `catchChatError` (toView . CRChatError (Just user)) + forM_ (L.nonEmpty msgs) $ \msgs' -> + batchSendGroupMemberMessages user conn msgs' + +batchSendGroupMemberMessages :: User -> Connection -> NonEmpty SndMessage -> CM () +batchSendGroupMemberMessages user conn msgs = do + -- TODO v5.7 based on version (?) + -- let shouldCompress = False + -- let batched = if shouldCompress then batchSndMessagesBinary msgs' else batchSndMessagesJSON msgs' + let batched = batchSndMessagesJSON msgs + let (errs', msgBatches) = partitionEithers batched + -- shouldn't happen, as large messages would have caused createNewSndMessage to throw SELargeMsg + unless (null errs') $ toView $ CRChatErrors (Just user) errs' + forM_ msgBatches $ \batch -> + processSndMessageBatch conn batch `catchChatError` (toView . CRChatError (Just user)) processSndMessageBatch :: Connection -> MsgBatch -> CM () processSndMessageBatch conn@Connection {connId} (MsgBatch batchBody sndMsgs) = do @@ -6795,21 +6799,20 @@ sendGroupMemberMessage user m@GroupMember {groupMemberId} chatMsgEvent groupId i MSASend conn -> deliverMessage conn (toCMEventTag chatMsgEvent) msgBody msgId >> postDeliver MSAPending -> withStore' $ \db -> createPendingGroupMessage db groupMemberId msgId introId_ +-- TODO ensure order - pending messages interleave with user input messages sendPendingGroupMessages :: User -> GroupMember -> Connection -> CM () -sendPendingGroupMessages user GroupMember {groupMemberId, localDisplayName} conn = do - pendingMessages <- withStore' $ \db -> getPendingGroupMessages db groupMemberId - -- TODO ensure order - pending messages interleave with user input messages - forM_ pendingMessages $ \pgm -> - processPendingMessage pgm `catchChatError` (toView . CRChatError (Just user)) +sendPendingGroupMessages user GroupMember {groupMemberId} conn = do + pgms <- withStore' $ \db -> getPendingGroupMessages db groupMemberId + forM_ (L.nonEmpty pgms) $ \pgms' -> do + let msgs = L.map (\(sndMsg, _, _) -> sndMsg) pgms' + batchSendGroupMemberMessages user conn msgs + lift . void . withStoreBatch' $ \db -> L.map (\SndMessage {msgId} -> deletePendingGroupMessage db groupMemberId msgId) msgs + lift . void . withStoreBatch' $ \db -> L.map (\(_, tag, introId_) -> updateIntro_ db tag introId_) pgms' where - processPendingMessage PendingGroupMessage {msgId, cmEventTag = ACMEventTag _ tag, msgBody, introId_} = do - void $ deliverMessage conn tag msgBody msgId - withStore' $ \db -> deletePendingGroupMessage db groupMemberId msgId - case tag of - XGrpMemFwd_ -> case introId_ of - Just introId -> withStore' $ \db -> updateIntroStatus db introId GMIntroInvForwarded - _ -> throwChatError $ CEGroupMemberIntroNotFound localDisplayName - _ -> pure () + updateIntro_ :: DB.Connection -> ACMEventTag -> Maybe Int64 -> IO () + updateIntro_ db tag introId_ = case (tag, introId_) of + (ACMEventTag _ XGrpMemFwd_, Just introId) -> updateIntroStatus db introId GMIntroInvForwarded + _ -> pure () -- TODO [batch send] refactor direct message processing same as groups (e.g. checkIntegrity before processing) saveDirectRcvMSG :: Connection -> MsgMeta -> MsgBody -> CM (Connection, RcvMessage) diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index c83044d564..71c198c47c 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -1118,7 +1118,6 @@ data ChatErrorType | CECantBlockMemberForSelf {groupInfo :: GroupInfo, member :: GroupMember, setShowMessages :: Bool} | CEGroupMemberUserRemoved | CEGroupMemberNotFound - | CEGroupMemberIntroNotFound {contactName :: ContactName} | CEGroupCantResendInvitation {groupInfo :: GroupInfo, contactName :: ContactName} | CEGroupInternal {message :: String} | CEFileNotFound {message :: String} diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index 9742439fb3..6c0e93e017 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -945,13 +945,6 @@ data RcvMessage = RcvMessage forwardedByMember :: Maybe GroupMemberId } -data PendingGroupMessage = PendingGroupMessage - { msgId :: MessageId, - cmEventTag :: ACMEventTag, - msgBody :: MsgBody, - introId_ :: Maybe Int64 - } - type MessageId = Int64 data ConnOrGroupId = ConnectionId Int64 | GroupId Int64 diff --git a/src/Simplex/Chat/Store/Messages.hs b/src/Simplex/Chat/Store/Messages.hs index 494e5635f4..84b2536380 100644 --- a/src/Simplex/Chat/Store/Messages.hs +++ b/src/Simplex/Chat/Store/Messages.hs @@ -285,13 +285,13 @@ createPendingGroupMessage db groupMemberId messageId introId_ = do |] (groupMemberId, messageId, introId_, currentTs, currentTs) -getPendingGroupMessages :: DB.Connection -> Int64 -> IO [PendingGroupMessage] +getPendingGroupMessages :: DB.Connection -> Int64 -> IO [(SndMessage, ACMEventTag, Maybe Int64)] getPendingGroupMessages db groupMemberId = map pendingGroupMessage <$> DB.query db [sql| - SELECT pgm.message_id, m.chat_msg_event, m.msg_body, pgm.group_member_intro_id + SELECT pgm.message_id, m.shared_msg_id, m.msg_body, m.chat_msg_event, pgm.group_member_intro_id FROM pending_group_messages pgm JOIN messages m USING (message_id) WHERE pgm.group_member_id = ? @@ -299,8 +299,8 @@ getPendingGroupMessages db groupMemberId = |] (Only groupMemberId) where - pendingGroupMessage (msgId, cmEventTag, msgBody, introId_) = - PendingGroupMessage {msgId, cmEventTag, msgBody, introId_} + pendingGroupMessage (msgId, sharedMsgId, msgBody, cmEventTag, introId_) = + (SndMessage {msgId, sharedMsgId, msgBody}, cmEventTag, introId_) deletePendingGroupMessage :: DB.Connection -> Int64 -> MessageId -> IO () deletePendingGroupMessage db groupMemberId messageId = diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index 90928c7f88..01519a7fcc 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -1954,7 +1954,6 @@ viewChatError isCmd logLevel testView = \case ] CEGroupMemberUserRemoved -> ["you are no longer a member of the group"] CEGroupMemberNotFound -> ["group doesn't have this member"] - CEGroupMemberIntroNotFound c -> ["group member intro not found for " <> ttyContact c] CEGroupCantResendInvitation g c -> viewCannotResendInvitation g c CEGroupInternal s -> ["chat group bug: " <> plain s] CEFileNotFound f -> ["file not found: " <> plain f] From 1b044237457e3a2591fa2edaeb994bacbf96eec5 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Tue, 28 May 2024 22:35:43 +0700 Subject: [PATCH 17/21] android, desktop: close notes tab on switching between chats (#4246) --- .../kotlin/chat/simplex/common/views/chat/ChatView.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt index 3b3060c81a..03d4e30a6c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt @@ -200,6 +200,10 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId: link = it preloadedLink = it }, close) + } else { + LaunchedEffect(Unit) { + close() + } } } } From cad3bc048fd0625eb04f630d5b43305fa5cc737a Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Wed, 29 May 2024 03:41:22 +0700 Subject: [PATCH 18/21] desktop: prevent corruption of settings file (#4243) * desktop: prevent corruption of settings file * check for existence * unneeded * simplify * unused --- .../kotlin/chat/simplex/common/DesktopApp.kt | 19 +++++++++------ .../common/platform/Resources.desktop.kt | 23 +++++++++++++++---- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/DesktopApp.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/DesktopApp.kt index eba22603d8..36149c8248 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/DesktopApp.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/DesktopApp.kt @@ -84,20 +84,25 @@ private fun ApplicationScope.AppWindow(closedByError: MutableState) { position = WindowPosition(state.x.dp, state.y.dp) ) + val storingJob: MutableState = remember { mutableStateOf(Job()) } LaunchedEffect( windowState.position.x.value, windowState.position.y.value, windowState.size.width.value, windowState.size.height.value ) { - storeWindowState( - WindowPositionSize( - x = windowState.position.x.value.toInt(), - y = windowState.position.y.value.toInt(), - width = windowState.size.width.value.toInt(), - height = windowState.size.height.value.toInt() + storingJob.value.cancel() + storingJob.value = launch { + delay(1000L) + storeWindowState( + WindowPositionSize( + x = windowState.position.x.value.toInt(), + y = windowState.position.y.value.toInt(), + width = windowState.size.width.value.toInt(), + height = windowState.size.height.value.toInt() + ) ) - ) + } } simplexWindowState.windowState = windowState diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Resources.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Resources.desktop.kt index f8c123eea1..a966c0a4e2 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Resources.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Resources.desktop.kt @@ -8,7 +8,7 @@ import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.* import chat.simplex.common.simplexWindowState -import chat.simplex.common.ui.theme.reactOnDarkThemeChanges +import chat.simplex.common.views.helpers.* import com.jthemedetecor.OsThemeDetector import com.russhwolf.settings.* import dev.icerock.moko.resources.ImageResource @@ -39,15 +39,28 @@ private val settingsFile = private val settingsThemesFile = File(desktopPlatform.configPath + File.separator + "themes.properties") .also { it.parentFile.mkdirs() } + private val settingsProps = Properties() - .also { try { it.load(settingsFile.reader()) } catch (e: Exception) { Properties() } } + .also { props -> + if (!settingsFile.exists()) return@also + + try { + settingsFile.reader().use { + // Force exception to happen + //it.close() + props.load(it) + } + } catch (e: Exception) { + Log.e(TAG, "Error reading settings file: ${e.stackTraceToString()}") + } + } private val settingsThemesProps = Properties() - .also { try { it.load(settingsThemesFile.reader()) } catch (e: Exception) { Properties() } } + .also { props -> try { settingsThemesFile.reader().use { props.load(it) } } catch (e: Exception) { /**/ } } -actual val settings: Settings = PropertiesSettings(settingsProps) { settingsProps.store(settingsFile.writer(), "") } -actual val settingsThemes: Settings = PropertiesSettings(settingsThemesProps) { settingsThemesProps.store(settingsThemesFile.writer(), "") } +actual val settings: Settings = PropertiesSettings(settingsProps) { withApi { settingsFile.writer().use { settingsProps.store(it, "") } } } +actual val settingsThemes: Settings = PropertiesSettings(settingsThemesProps) { withApi { settingsThemesFile.writer().use { settingsThemesProps.store(it, "") } } } actual fun windowOrientation(): WindowOrientation = if (simplexWindowState.windowState.size.width > simplexWindowState.windowState.size.height) { From 02267c526318c265016e17bfb2ca4b75f7379422 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Wed, 29 May 2024 04:01:45 +0700 Subject: [PATCH 19/21] android: show alert of exception while initializing WebView (#4245) * android: show alert of exception while initializing WebView * Update apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml --------- Co-authored-by: Evgeny Poberezkin --- .../common/views/call/CallView.android.kt | 63 ++++++++++--------- .../commonMain/resources/MR/base/strings.xml | 1 + 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt index c702264d82..d6af35432d 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt @@ -11,6 +11,7 @@ import android.media.* import android.os.Build import android.os.PowerManager import android.os.PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK +import android.view.View import android.view.ViewGroup import android.webkit.* import androidx.compose.desktop.ui.tooling.preview.Preview @@ -670,37 +671,43 @@ fun WebRTCView(callCommand: SnapshotStateList, onResponse: (WVAPIM Box(Modifier.fillMaxSize()) { AndroidView( factory = { AndroidViewContext -> - (staticWebView ?: WebView(androidAppContext)).apply { - layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT, - ) - this.webChromeClient = object: WebChromeClient() { - override fun onPermissionRequest(request: PermissionRequest) { - if (request.origin.toString().startsWith("file:/")) { - request.grant(request.resources) - } else { - Log.d(TAG, "Permission request from webview denied.") - request.deny() + try { + (staticWebView ?: WebView(androidAppContext)).apply { + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, + ) + this.webChromeClient = object: WebChromeClient() { + override fun onPermissionRequest(request: PermissionRequest) { + if (request.origin.toString().startsWith("file:/")) { + request.grant(request.resources) + } else { + Log.d(TAG, "Permission request from webview denied.") + request.deny() + } } } + this.webViewClient = LocalContentWebViewClient(webView, assetLoader) + this.clearHistory() + this.clearCache(true) + this.addJavascriptInterface(WebRTCInterface(onResponse), "WebRTCInterface") + this.setBackgroundColor(android.graphics.Color.BLACK) + val webViewSettings = this.settings + webViewSettings.allowFileAccess = true + webViewSettings.allowContentAccess = true + webViewSettings.javaScriptEnabled = true + webViewSettings.mediaPlaybackRequiresUserGesture = false + webViewSettings.cacheMode = WebSettings.LOAD_NO_CACHE + if (staticWebView == null) { + this.loadUrl("file:android_asset/www/android/call.html") + } else { + webView.value = this + } } - this.webViewClient = LocalContentWebViewClient(webView, assetLoader) - this.clearHistory() - this.clearCache(true) - this.addJavascriptInterface(WebRTCInterface(onResponse), "WebRTCInterface") - this.setBackgroundColor(android.graphics.Color.BLACK) - val webViewSettings = this.settings - webViewSettings.allowFileAccess = true - webViewSettings.allowContentAccess = true - webViewSettings.javaScriptEnabled = true - webViewSettings.mediaPlaybackRequiresUserGesture = false - webViewSettings.cacheMode = WebSettings.LOAD_NO_CACHE - if (staticWebView == null) { - this.loadUrl("file:android_asset/www/android/call.html") - } else { - webView.value = this - } + } catch (e: Exception) { + Log.e(TAG, "Error initializing WebView: ${e.stackTraceToString()}") + AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error), generalGetString(MR.strings.error_initializing_web_view).format(e.stackTraceToString())) + return@AndroidView View(androidAppContext) } } ) { /* WebView */ } diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml index 123e9bc80d..35e3591aea 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -874,6 +874,7 @@ Speaker Headphones Bluetooth + Error initializing WebView. Update your system to the new version. Please contact developers.\nError: %s The next generation of private messaging From 0495a4cd7821d0e81425518c6c5aff0f38e63df9 Mon Sep 17 00:00:00 2001 From: sh <37271604+shumvgolove@users.noreply.github.com> Date: Tue, 28 May 2024 21:26:15 +0000 Subject: [PATCH 20/21] docs/smp-server: expand tor configuration, add security practices (#4228) * docs/smp-server: expand tor configuration, add security practices * docs/smp-server: add TOC * update --------- Co-authored-by: Evgeny Poberezkin --- docs/SERVER.md | 444 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 354 insertions(+), 90 deletions(-) diff --git a/docs/SERVER.md b/docs/SERVER.md index c29a805452..b30d4212f5 100644 --- a/docs/SERVER.md +++ b/docs/SERVER.md @@ -1,9 +1,32 @@ --- title: Hosting your own SMP Server -revision: 31.07.2023 +revision: 28.05.2024 --- -| Updated 05.06.2023 | Languages: EN, [FR](/docs/lang/fr/SERVER.md), [CZ](/docs/lang/cs/SERVER.md), [PL](/docs/lang/pl/SERVER.md) | +| Updated 28.05.2024 | Languages: EN, [FR](/docs/lang/fr/SERVER.md), [CZ](/docs/lang/cs/SERVER.md), [PL](/docs/lang/pl/SERVER.md) | + +### Table of Contents + +- [Hosting your own SMP server](#hosting-your-own-smp-server) + - [Overview](#overview) + - [Installation](#installation) + - [Configuration](#configuration) + - [Interactively](#interactively) + - [Via command line options](#via-command-line-options) + - [Further configuration](#further-configuration) + - [Server security](#server-security) + - [Initialization](#initialization) + - [Private keys](#private-keys) + - [Online certificate rotation](#online-certificate-rotation) + - [Tor: installation and configuration](#tor-installation-and-configuration) + - [Installation for onion address](#installation-for-onion-address) + - [SOCKS port for SMP PROXY](#socks-port-for-smp-proxy) + - [Documentation](#documentation) + - [SMP server address](#smp-server-address) + - [Systemd commands](#systemd-commands) + - [Monitoring](#monitoring) + - [Updating your SMP server](#updating-your-smp-server) + - [Configuring the app to use the server](#configuring-the-app-to-use-the-server) # Hosting your own SMP Server @@ -13,7 +36,7 @@ SMP server is the relay server used to pass messages in SimpleX network. SimpleX SimpleX clients only determine which server is used to receive the messages, separately for each contact (or group connection with a group member), and these servers are only temporary, as the delivery address can change. -_Please note_: when you change the servers in the app configuration, it only affects which server will be used for the new contacts, the existing contacts will not automatically move to the new servers, but you can move them manually using ["Change receiving address"](../blog/20221108-simplex-chat-v4.2-security-audit-new-website.md#change-your-delivery-address-beta) button in contact/member information pages – it will be automated soon. +_Please note_: when you change the servers in the app configuration, it only affects which servers will be used for the new contacts, the existing contacts will not automatically move to the new servers, but you can move them manually using ["Change receiving address"](../blog/20221108-simplex-chat-v4.2-security-audit-new-website.md#change-your-delivery-address-beta) button in contact/member information pages – it will be automated in the future. ## Installation @@ -22,7 +45,7 @@ _Please note_: when you change the servers in the app configuration, it only aff - Manual deployment (see below) - Semi-automatic deployment: - - [Offical installation script](https://github.com/simplex-chat/simplexmq#using-installation-script) + - [Installation script](https://github.com/simplex-chat/simplexmq#using-installation-script) - [Docker container](https://github.com/simplex-chat/simplexmq#using-docker) - [Linode Marketplace](https://www.linode.com/marketplace/apps/simplex-chat/simplex-chat/) @@ -30,7 +53,7 @@ Manual installation requires some preliminary actions: 1. Install binary: - - Using offical binaries: + - Using pre-compiled binaries: ```sh curl -L https://github.com/simplex-chat/simplexmq/releases/latest/download/smp-server-ubuntu-20_04-x86-64 -o /usr/local/bin/smp-server && chmod +x /usr/local/bin/smp-server @@ -85,86 +108,6 @@ Manual installation requires some preliminary actions: And execute `sudo systemctl daemon-reload`. -## Tor installation - -smp-server can also be deployed to serve from [tor](https://www.torproject.org) network. Run the following commands as `root` user. - -1. Install tor: - - We're assuming you're using Ubuntu/Debian based distributions. If not, please refer to [offical tor documentation](https://community.torproject.org/onion-services/setup/install/) or your distribution guide. - - - Configure offical Tor PPA repository: - - ```sh - CODENAME="$(lsb_release -c | awk '{print $2}')" - echo "deb [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org ${CODENAME} main - deb-src [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org ${CODENAME} main" > /etc/apt/sources.list.d/tor.list - ``` - - - Import repository key: - - ```sh - curl --proto '=https' --tlsv1.2 -sSf https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --dearmor | tee /usr/share/keyrings/tor-archive-keyring.gpg >/dev/null - ``` - - - Update repository index: - - ```sh - apt update - ``` - - - Install `tor` package: - - ```sh - apt install -y tor deb.torproject.org-keyring - ``` - -2. Configure tor: - - - File configuration: - - Open tor configuration with your editor of choice (`nano`,`vim`,`emacs`,etc.): - - ```sh - vim /etc/tor/torrc - ``` - - And insert the following lines to the bottom of configuration. Please note lines starting with `#`: this is comments about each individual options. - - ```sh - # Enable log (otherwise, tor doesn't seemd to deploy onion address) - Log notice file /var/log/tor/notices.log - # Enable single hop routing (2 options below are dependencies of third). Will reduce latency in exchange of anonimity (since tor runs alongside smp-server and onion address will be displayed in clients, this is totally fine) - SOCKSPort 0 - HiddenServiceNonAnonymousMode 1 - HiddenServiceSingleHopMode 1 - # smp-server hidden service host directory and port mappings - HiddenServiceDir /var/lib/tor/simplex-smp/ - HiddenServicePort 5223 localhost:5223 - ``` - - - Create directories: - - ```sh - mkdir /var/lib/tor/simplex-smp/ && chown debian-tor:debian-tor /var/lib/tor/simplex-smp/ && chmod 700 /var/lib/tor/simplex-smp/ - ``` - -3. Start tor: - - Enable `systemd` service and start tor. Offical `tor` is a bit flunky on the first start and may not create onion host address, so we're restarting it just in case. - - ```sh - systemctl enable tor && systemctl start tor && systemctl restart tor - ``` - -4. Display onion host: - - Execute the following command to display your onion host address: - - ```sh - cat /var/lib/tor/simplex-smp/hostname - ``` - ## Configuration To see which options are available, execute `smp-server` without flags: @@ -205,11 +148,11 @@ There are several options to consider: Enter `y` to enable logging statistics in CSV format, e.g. they can be used to show aggregate usage charts in `Grafana`. -These statistics include daily counts of created, secured and deleted queues, sent and received messages, and also daily, weekly, and monthly counts of active queues (that is, the queues that were used for any messages). We believe that this information does not include anything that would allow correlating different queues as belonging to the same users, but please let us know, confidentially, if you believe that this can be exploited in any way. +These statistics include daily counts of created, secured and deleted queues, sent and received messages, and also daily, weekly, and monthly counts of active queues (that is, the queues that were used for any messages). We believe that this information does not include anything that would allow correlating different queues as belonging to the same users, but please [let us know](./SECURITY.md), confidentially, if you believe that this can be exploited in any way. - `Require a password to create new messaging queues?` - Enter `r` or your arbitrary password to password-protect `smp-server`, or `n` to disable password protection. + Press `Enter` or enter your arbitrary password to password-protect `smp-server`, or `n` to disable password protection. - `Enter server FQDN or IP address for certificate (127.0.0.1):` @@ -277,7 +220,328 @@ Fingerprint: d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss= Server address: smp://d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=:V8ONoJ6ICwnrZnTC_QuSHfCEYq53uLaJKQ_oIC6-ve8=@ ``` -The server address above should be used in your client configuration and if you added server password it should only be shared with the other people when you want to allow them to use your server to receive the messages (all your contacts will be able to send messages, as it does not require a password). If you passed IP address or hostnames during the initialisation, they will be printed as part of server address, otherwise replace `` with the actual server addresses. +The server address above should be used in your client configuration, and if you added server password it should only be shared with the other people who you want to allow using your server to receive the messages (all your contacts will be able to send messages - it does not require a password). If you passed IP address or hostnames during the initialisation, they will be printed as part of server address, otherwise replace `` with the actual server hostnames. + +## Further configuration + +All generated configuration, along with a description for each parameter, is available inside configuration file in `/etc/opt/simplex/smp-server.ini` for further customization. Depending on the smp-server version, the configuration file looks something like this: + +```ini +[STORE_LOG] +# The server uses STM memory for persistence, +# that will be lost on restart (e.g., as with redis). +# This option enables saving memory to append only log, +# and restoring it when the server is started. +# Log is compacted on start (deleted objects are removed). +enable: on + +# Undelivered messages are optionally saved and restored when the server restarts, +# they are preserved in the .bak file until the next restart. +restore_messages: on +expire_messages_days: 21 + +# Log daily server statistics to CSV file +log_stats: on + +[AUTH] +# Set new_queues option to off to completely prohibit creating new messaging queues. +# This can be useful when you want to decommission the server, but not all connections are switched yet. +new_queues: on + +# Use create_password option to enable basic auth to create new messaging queues. +# The password should be used as part of server address in client configuration: +# smp://fingerprint:password@host1,host2 +# The password will not be shared with the connecting contacts, you must share it only +# with the users who you want to allow creating messaging queues on your server. +# create_password: password to create new queues (any printable ASCII characters without whitespace, '@', ':' and '/') + +[TRANSPORT] +# host is only used to print server address on start +host: +port: 5223 +log_tls_errors: off +websockets: off +# control_port: 5224 + +[PROXY] +# Network configuration for SMP proxy client. +# `host_mode` can be 'public' (default) or 'onion'. +# It defines prefferred hostname for destination servers with multiple hostnames. +# host_mode: public +# required_host_mode: off + +# The domain suffixes of the relays you operate (space-separated) to count as separate proxy statistics. +# own_server_domains: + +# SOCKS proxy port for forwarding messages to destination servers. +# You may need a separate instance of SOCKS proxy for incoming single-hop requests. +# socks_proxy: localhost:9050 + +# `socks_mode` can be 'onion' for SOCKS proxy to be used for .onion destination hosts only (default) +# or 'always' to be used for all destination hosts (can be used if it is an .onion server). +# socks_mode: onion + +# Limit number of threads a client can spawn to process proxy commands in parrallel. +# client_concurrency: 32 + +[INACTIVE_CLIENTS] +# TTL and interval to check inactive clients +disconnect: off +# ttl: 43200 +# check_interval: 3600 +``` + +## Server security + +### Initialization + +Although it's convenient to initialize smp-server configuration directly on the server, operators **ARE ADVISED** to initialize smp-server fully offline to protect your SMP server CA private key. + +Follow the steps to quickly initialize the server offline: + +1. Install Docker on your system. + +2. Deploy [smp-server](https://github.com/simplex-chat/simplexmq#using-docker) locally. + +3. Destroy the container. All relevant configuration files and keys will be available at `$HOME/simplex/smp/config`. + +4. Move your `CA` private key (`ca.key`) to the safe place. For further explanation, see the next section: [Server security: Private keys](#private-keys). + +5. Copy all other configuration files **except** the CA key to the server: + + ```sh + rsync -hzasP $HOME/simplex/smp/config/ @:/etc/opt/simplex/ + ``` + +### Private keys + +Connection to the smp server occurs via a TLS connection. During the TLS handshake, the client verifies smp-server CA and server certificates by comparing its fingerprint with the one included in server address. If server TLS credential is compromised, this key can be used to sign a new one, keeping the same server identity and established connections. In order to protect your smp-server from bad actors, operators **ARE ADVISED** to move CA private key to a safe place. That could be: + +- [Tails](https://tails.net/) live usb drive with [persistent and encrypted storage](https://tails.net/doc/persistent_storage/create/index.en.html). +- Offline Linux laptop. +- Bitwarden. +- Any other safe storage that satisfy your security requirements. + +Follow the steps to secure your CA keys: + +1. Login to your server via SSH. + +2. Copy the CA key to a safe place from this file: + + ```sh + /etc/opt/simplex/ca.key + ``` + +3. Delete the CA key from the server. **Please make sure you've saved you CA key somewhere safe. Otherwise, you would lose the ability to [rotate the online certificate](#online-certificate-rotation)**: + + ```sh + rm /etc/opt/simplex/ca.key + ``` + +### Online certificate rotation + +Operators of smp servers **ARE ADVISED** to rotate online certificate regularly (e.g., every 3 months). In order to do this, follow the steps: + +1. Create relevant folders: + + ```sh + mkdir -p $HOME/simplex/smp/config + ``` + +1. Copy the configuration files from the server to the local machine (if not yet): + + ```sh + rsync -hzasP @:/etc/opt/simplex/ $HOME/simplex/smp/config/ + ``` + +2. **Copy** your CA private key from a safe place to the local machine and name it `ca.key`. + +3. Download latest `smp-server` binary [from Github releases](https://github.com/simplex-chat/simplexmq/releases): + + ```sh + curl -L 'https://github.com/simplex-chat/simplexmq/releases/latest/download/smp-server-ubuntu-20_04-x86-64' -o smp-server + ``` + +4. Put the `smp-server` binary to your `$PATH` and make it executable: + + ```sh + sudo mv smp-server /usr/local/bin/ && chmod +x /usr/local/bin/smp-server + ``` + +5. Export a variable to configure your path to smp-server configuration: + + ```sh + export SMP_SERVER_CFG_PATH=$HOME/simplex/smp/config + ``` + +6. Execute the following command: + + ```sh + smp-server cert + ``` + + This command should print: + + ```sh + Certificate request self-signature ok + subject=CN = + Generated new server credentials + ---------- + You should store CA private key securely and delete it from the server. + If server TLS credential is compromised this key can be used to sign a new one, keeping the same server identity and established connections. + CA private key location: + $HOME/simplex/smp/config/ca.key + ---------- + ``` + +7. Remove the CA key from the config folder (make sure you have a backup!): + + ```sh + rm $HOME/simplex/smp/config/ca.key + ``` + +8. Upload new certificates to the server: + + ```sh + rsync -hzasP $HOME/simplex/smp/config/ @:/etc/opt/simplex/ + ``` + +9. Connect to the server via SSH and restart the service: + + ```sh + ssh @ "systemctl restart smp-server" + ``` + +10. Done! + +## Tor: installation and configuration + +### Installation for onion address + +SMP-server can also be deployed to be available via [Tor](https://www.torproject.org) network. Run the following commands as `root` user. + +1. Install tor: + + We're assuming you're using Ubuntu/Debian based distributions. If not, please refer to [offical tor documentation](https://community.torproject.org/onion-services/setup/install/) or your distribution guide. + + - Configure offical Tor PPA repository: + + ```sh + CODENAME="$(lsb_release -c | awk '{print $2}')" + echo "deb [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org ${CODENAME} main + deb-src [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org ${CODENAME} main" > /etc/apt/sources.list.d/tor.list + ``` + + - Import repository key: + + ```sh + curl --proto '=https' --tlsv1.2 -sSf https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --dearmor | tee /usr/share/keyrings/tor-archive-keyring.gpg >/dev/null + ``` + + - Update repository index: + + ```sh + apt update + ``` + + - Install `tor` package: + + ```sh + apt install -y tor deb.torproject.org-keyring + ``` + +2. Configure tor: + + - File configuration: + + Open tor configuration with your editor of choice (`nano`,`vim`,`emacs`,etc.): + + ```sh + vim /etc/tor/torrc + ``` + + And insert the following lines to the bottom of configuration. Please note lines starting with `#`: this is comments about each individual options. + + ```sh + # Enable log (otherwise, tor doesn't seem to deploy onion address) + Log notice file /var/log/tor/notices.log + # Enable single hop routing (2 options below are dependencies of the third) - It will reduce the latency at the cost of lower anonimity of the server - as SMP-server onion address is used in the clients together with public address, this is ok. If you deploy SMP-server with onion-only address, you may want to keep standard configuration instead. + SOCKSPort 0 + HiddenServiceNonAnonymousMode 1 + HiddenServiceSingleHopMode 1 + # smp-server hidden service host directory and port mappings + HiddenServiceDir /var/lib/tor/simplex-smp/ + HiddenServicePort 5223 localhost:5223 + ``` + + - Create directories: + + ```sh + mkdir /var/lib/tor/simplex-smp/ && chown debian-tor:debian-tor /var/lib/tor/simplex-smp/ && chmod 700 /var/lib/tor/simplex-smp/ + ``` + +3. Start tor: + + Enable `systemd` service and start tor. Offical `tor` is a bit flaky on the first start and may not create onion host address, so we're restarting it just in case. + + ```sh + systemctl enable --now tor && systemctl restart tor + ``` + +4. Display onion host: + + Execute the following command to display your onion host address: + + ```sh + cat /var/lib/tor/simplex-smp/hostname + ``` + +### SOCKS port for SMP PROXY + +SMP-server versions starting from `v5.8.0-beta.0` can be configured to PROXY smp servers available exclusively through [Tor](https://www.torproject.org) network to be accessible to the clients that do not use Tor. Run the following commands as `root` user. + +1. Install tor as described in the [previous section](#installation-for-onion-address). + +2. Execute the following command to creatae a new Tor daemon instance: + + ```sh + tor-instance-create tor2 + ``` + +3. Open the `tor2` configuration and replace its content with the following lines: + + ```sh + vim /etc/tor/instances/tor2/torrc + ``` + + ```sh + # Log tor to systemd daemon + Log notice syslog + # Listen to local 9050 port for socks proxy + SocksPort 9050 + ``` + +3. Enable service at startup and start the daemon: + + ```sh + systemctl enable --now tor@tor2 + ``` + + You can check `tor2` logs with the following command: + + ```sh + journalctl -u tor@tor2 + ``` + +4. After [server initialization](#configuration), configure the `PROXY` section like so: + + ```ini + ... + [PROXY] + socks_proxy: 127.0.0.1:9050 + own_server_domains: + ... + ``` ## Documentation @@ -417,7 +681,7 @@ To import `csv` to `Grafana` one should: For further documentation, see: [CSV Data Source for Grafana - Documentation](https://grafana.github.io/grafana-csv-datasource/) -# Updating your SMP server +## Updating your SMP server To update your smp-server to latest version, choose your installation method and follow the steps: @@ -474,7 +738,7 @@ To update your smp-server to latest version, choose your installation method and docker image prune ``` -### Configuring the app to use the server +## Configuring the app to use the server To configure the app to use your messaging server copy it's full address, including password, and add it to the app. You have an option to use your server together with preset servers or without them - you can remove or disable them. From ad0a678c5f77a95e01e6cf10391866d3a05484e3 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Wed, 29 May 2024 08:20:51 +0100 Subject: [PATCH 21/21] core: 5.8.0.4 (simplexmq 5.8.0.7) --- cabal.project | 2 +- package.yaml | 2 +- scripts/nix/sha256map.nix | 2 +- simplex-chat.cabal | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cabal.project b/cabal.project index 9fd0c4928a..e04a03b210 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: 199f85ec62bcbadd11dc05bb97cce6556dafb384 + tag: 0f663bd569f5d282fc13cd969391f30d873d73a0 source-repository-package type: git diff --git a/package.yaml b/package.yaml index 39410d16e0..accab5f0c4 100644 --- a/package.yaml +++ b/package.yaml @@ -1,5 +1,5 @@ name: simplex-chat -version: 5.8.0.3 +version: 5.8.0.4 #synopsis: #description: homepage: https://github.com/simplex-chat/simplex-chat#readme diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 2733c6c1eb..a719aa9629 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."199f85ec62bcbadd11dc05bb97cce6556dafb384" = "0x5c29x5h1832hks0wpxy84x16rn13pi9zd2j9x8lvb3y8h0ddk0"; + "https://github.com/simplex-chat/simplexmq.git"."0f663bd569f5d282fc13cd969391f30d873d73a0" = "0xv3fjq6acr25hkkpb4grmdj0hls9z5qnq0dx7h7lxck60q0v9w8"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; diff --git a/simplex-chat.cabal b/simplex-chat.cabal index 85873c2d1c..b70c2dd71b 100644 --- a/simplex-chat.cabal +++ b/simplex-chat.cabal @@ -5,7 +5,7 @@ cabal-version: 1.12 -- see: https://github.com/sol/hpack name: simplex-chat -version: 5.8.0.3 +version: 5.8.0.4 category: Web, System, Services, Cryptography homepage: https://github.com/simplex-chat/simplex-chat#readme author: simplex.chat