From 7ff8dcfb780816170361c9fe83b56d83b2b91b34 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Tue, 2 May 2023 18:38:20 +0300 Subject: [PATCH 1/6] android: floating button background (#2366) --- .../src/main/java/chat/simplex/app/views/chat/ChatView.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt index d2bc6bc0fa..c75e490849 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt @@ -854,6 +854,7 @@ private fun TopEndFloatingButton( FloatingActionButton( {}, // no action here modifier.size(48.dp), + backgroundColor = MaterialTheme.colors.secondaryVariant, elevation = FloatingActionButtonDefaults.elevation(0.dp, 0.dp), interactionSource = interactionSource, ) { @@ -880,7 +881,8 @@ private fun bottomEndFloatingButton( FloatingActionButton( onClick = onClickCounter, elevation = FloatingActionButtonDefaults.elevation(0.dp, 0.dp, 0.dp, 0.dp), - modifier = Modifier.size(48.dp) + modifier = Modifier.size(48.dp), + backgroundColor = MaterialTheme.colors.secondaryVariant, ) { Text( unreadCountStr(unreadCount), @@ -895,7 +897,8 @@ private fun bottomEndFloatingButton( FloatingActionButton( onClick = onClickArrowDown, elevation = FloatingActionButtonDefaults.elevation(0.dp, 0.dp, 0.dp, 0.dp), - modifier = Modifier.size(48.dp) + modifier = Modifier.size(48.dp), + backgroundColor = MaterialTheme.colors.secondaryVariant, ) { Icon( painter = painterResource(R.drawable.ic_keyboard_arrow_down), From e3011a1cb07a3ba0bf5576611d51ad912a604bab Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Tue, 2 May 2023 19:38:58 +0400 Subject: [PATCH 2/6] core: disable creation of decryption errors chat items (#2365) --- src/Simplex/Chat.hs | 24 ++++++++++++++---------- tests/ChatTests/Direct.hs | 2 +- tests/ChatTests/Groups.hs | 2 +- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 2cf37abb54..7b6f763a8e 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -2882,17 +2882,21 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do -- TODO add debugging output _ -> pure () + -- TODO revert to commented function to enable creation of decryption errors chat items agentMsgDecryptError :: AgentErrorType -> Maybe (MsgDecryptError, Word32) - agentMsgDecryptError = \case - AGENT (A_CRYPTO RATCHET_HEADER) -> Just (MDERatchetHeader, 1) - AGENT (A_CRYPTO (RATCHET_SKIPPED n)) -> Just (MDETooManySkipped, n) - -- we are not treating this as decryption error, as in many cases it happens as the result of duplicate or redundant delivery, - -- and we don't have a way to differentiate. - -- we could store the hashes of past messages in the agent, or delaying message deletion after ACK - -- A_DUPLICATE -> Nothing - -- earlier messages may be received in case of redundant delivery, and do not necessarily indicate an error - -- AGENT (A_CRYPTO (RATCHET_EARLIER n)) -> Nothing - _ -> Nothing + agentMsgDecryptError _ = Nothing + + -- agentMsgDecryptError :: AgentErrorType -> Maybe (MsgDecryptError, Word32) + -- agentMsgDecryptError = \case + -- AGENT (A_CRYPTO RATCHET_HEADER) -> Just (MDERatchetHeader, 1) + -- AGENT (A_CRYPTO (RATCHET_SKIPPED n)) -> Just (MDETooManySkipped, n) + -- -- we are not treating this as decryption error, as in many cases it happens as the result of duplicate or redundant delivery, + -- -- and we don't have a way to differentiate. + -- -- we could store the hashes of past messages in the agent, or delaying message deletion after ACK + -- -- A_DUPLICATE -> Nothing + -- -- earlier messages may be received in case of redundant delivery, and do not necessarily indicate an error + -- -- AGENT (A_CRYPTO (RATCHET_EARLIER n)) -> Nothing + -- _ -> Nothing mdeUpdatedCI :: (MsgDecryptError, Word32) -> CChatItem c -> Maybe (ChatItem c 'MDRcv, CIContent 'MDRcv) mdeUpdatedCI (mde', n') (CChatItem _ ci@ChatItem {content = CIRcvDecryptionError mde n}) diff --git a/tests/ChatTests/Direct.hs b/tests/ChatTests/Direct.hs index e54bddb386..0f5fe5f713 100644 --- a/tests/ChatTests/Direct.hs +++ b/tests/ChatTests/Direct.hs @@ -82,7 +82,7 @@ chatDirectTests = do it "mark contact verified" testMarkContactVerified it "mark group member verified" testMarkGroupMemberVerified describe "message errors" $ do - it "show message decryption error and update count" testMsgDecryptError + xit "show message decryption error and update count" testMsgDecryptError testAddContact :: HasCallStack => SpecWith FilePath testAddContact = versionTestMatrix2 runTestAddContact diff --git a/tests/ChatTests/Groups.hs b/tests/ChatTests/Groups.hs index a70117d8c8..e74071c3b5 100644 --- a/tests/ChatTests/Groups.hs +++ b/tests/ChatTests/Groups.hs @@ -52,7 +52,7 @@ chatGroupTests = do it "group link member role" testGroupLinkMemberRole it "leaving and deleting the group joined via link should NOT delete previously existing direct contacts" testGroupLinkLeaveDelete describe "group message errors" $ do - it "show message decryption error and update count" testGroupMsgDecryptError + xit "show message decryption error and update count" testGroupMsgDecryptError testGroup :: HasCallStack => SpecWith FilePath testGroup = versionTestMatrix3 runTestGroup From 7b83450a9ca77d45ac434ec377decedd563b7adc Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Wed, 3 May 2023 12:17:39 +0400 Subject: [PATCH 3/6] ios: AddGroupMembersView fixes (#2369) --- apps/ios/Shared/Model/SimpleXAPI.swift | 6 ------ .../Views/Chat/Group/AddGroupMembersView.swift | 18 +++++++++++++----- .../Views/Chat/Group/GroupChatInfoView.swift | 7 ++++++- .../Shared/Views/NewChat/AddGroupView.swift | 4 ++-- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 70f772286c..33d5b99ba8 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -953,12 +953,6 @@ func apiListMembers(_ groupId: Int64) async -> [GroupMember] { return [] } -func apiListMembersSync(_ groupId: Int64) -> [GroupMember] { - let r = chatSendCmdSync(.apiListMembers(groupId: groupId)) - if case let .groupMembers(_, group) = r { return group.members } - return [] -} - func filterMembersToAdd(_ ms: [GroupMember]) -> [Contact] { let memberContactIds = ms.compactMap{ m in m.memberCurrent ? m.memberContactId : nil } return ChatModel.shared.chats diff --git a/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift b/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift index e2ce4fc64d..f52b7c327c 100644 --- a/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift +++ b/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift @@ -10,13 +10,22 @@ import SwiftUI import SimpleXChat struct AddGroupMembersView: View { - @EnvironmentObject var chatModel: ChatModel @Environment(\.dismiss) var dismiss: DismissAction var chat: Chat + var groupInfo: GroupInfo + + var body: some View { + AddGroupMembersViewCommon(chat: chat, groupInfo: groupInfo, addedMembersCb: { _ in dismiss() }) + } +} + +struct AddGroupMembersViewCommon: View { + @EnvironmentObject var chatModel: ChatModel + var chat: Chat @State var groupInfo: GroupInfo var creatingGroup: Bool = false var showFooterCounter: Bool = true - var addedMembersCb: ((Set) -> Void)? = nil + var addedMembersCb: ((Set) -> Void) @State private var selectedContacts = Set() @State private var selectedRole: GroupMemberRole = .member @State private var alert: AddGroupMembersAlert? @@ -39,7 +48,7 @@ struct AddGroupMembersView: View { addGroupMembersView() .toolbar { ToolbarItem(placement: .navigationBarTrailing) { - Button ("Skip") { addedMembersCb?(selectedContacts) } + Button ("Skip") { addedMembersCb(selectedContacts) } } } } @@ -128,8 +137,7 @@ struct AddGroupMembersView: View { let member = try await apiAddMember(groupInfo.groupId, contactId, selectedRole) await MainActor.run { _ = ChatModel.shared.upsertGroupMember(groupInfo, member) } } - await MainActor.run { dismiss() } - if let cb = addedMembersCb { cb(selectedContacts) } + addedMembersCb(selectedContacts) } catch { let a = getErrorAlert(error, "Error adding member(s)") alert = .error(title: a.title, error: a.message) diff --git a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift index efbb3c1320..a6219175cc 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift @@ -142,7 +142,12 @@ struct GroupChatInfoView: View { NavigationLink { AddGroupMembersView(chat: chat, groupInfo: groupInfo) .onAppear { - ChatModel.shared.groupMembers = apiListMembersSync(groupInfo.groupId) + Task { + let groupMembers = await apiListMembers(groupInfo.groupId) + await MainActor.run { + ChatModel.shared.groupMembers = groupMembers + } + } } } label: { Label("Invite members", systemImage: "plus") diff --git a/apps/ios/Shared/Views/NewChat/AddGroupView.swift b/apps/ios/Shared/Views/NewChat/AddGroupView.swift index 998ae395bb..5b6c9b5dc3 100644 --- a/apps/ios/Shared/Views/NewChat/AddGroupView.swift +++ b/apps/ios/Shared/Views/NewChat/AddGroupView.swift @@ -24,14 +24,14 @@ struct AddGroupView: View { var body: some View { if let chat = chat, let groupInfo = groupInfo { - AddGroupMembersView( + AddGroupMembersViewCommon( chat: chat, groupInfo: groupInfo, creatingGroup: true, showFooterCounter: false ) { _ in dismiss() - DispatchQueue.main.async { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { m.chatId = groupInfo.id } } From 8b80efd5371610ced5f4c02950a8ba1b5feb8888 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Wed, 3 May 2023 11:42:43 +0300 Subject: [PATCH 4/6] android: contact address UX (#2363) * android: contact address UX * unneeded block * review changes --- .../java/chat/simplex/app/model/ChatModel.kt | 12 +- .../java/chat/simplex/app/model/SimpleXAPI.kt | 20 +- .../simplex/app/views/chat/ChatInfoView.kt | 27 +- .../app/views/chat/group/GroupChatInfoView.kt | 2 + .../views/chat/group/GroupMemberInfoView.kt | 16 +- .../views/chat/group/WelcomeMessageView.kt | 82 +++- .../app/views/chatlist/ChatHelpView.kt | 14 +- .../simplex/app/views/helpers/TextEditor.kt | 156 +++++-- .../app/views/newchat/AddContactLearnMore.kt | 23 + .../app/views/newchat/AddContactView.kt | 137 +++--- .../newchat/ContactConnectionInfoView.kt | 49 +- .../app/views/newchat/CreateLinkView.kt | 7 +- .../app/views/newchat/PasteToConnect.kt | 2 +- .../app/views/onboarding/HowItWorks.kt | 48 +- .../views/usersettings/AcceptRequestsView.kt | 160 ------- .../views/usersettings/ProtocolServerView.kt | 20 +- .../app/views/usersettings/RTCServers.kt | 2 +- .../app/views/usersettings/SettingsView.kt | 2 +- .../usersettings/UserAddressLearnMore.kt | 24 + .../app/views/usersettings/UserAddressView.kt | 437 +++++++++++++++--- .../app/src/main/res/drawable/ic_person.xml | 9 + .../app/src/main/res/values-ar/strings.xml | 1 - .../app/src/main/res/values-cs/strings.xml | 7 - .../app/src/main/res/values-de/strings.xml | 8 - .../app/src/main/res/values-es/strings.xml | 7 - .../app/src/main/res/values-fr/strings.xml | 7 - .../app/src/main/res/values-hi/strings.xml | 4 - .../app/src/main/res/values-it/strings.xml | 7 - .../app/src/main/res/values-ja/strings.xml | 7 - .../app/src/main/res/values-ko/strings.xml | 5 - .../app/src/main/res/values-lt/strings.xml | 1 - .../app/src/main/res/values-nl/strings.xml | 7 - .../app/src/main/res/values-pl/strings.xml | 7 - .../src/main/res/values-pt-rBR/strings.xml | 7 - .../app/src/main/res/values-ru/strings.xml | 10 +- .../src/main/res/values-zh-rCN/strings.xml | 7 - .../src/main/res/values-zh-rTW/strings.xml | 7 - .../app/src/main/res/values/strings.xml | 48 +- 38 files changed, 884 insertions(+), 512 deletions(-) create mode 100644 apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactLearnMore.kt delete mode 100644 apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AcceptRequestsView.kt create mode 100644 apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressLearnMore.kt create mode 100644 apps/android/app/src/main/res/drawable/ic_person.xml diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt index 8947c782fd..c6fb1ae2c2 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt @@ -461,6 +461,8 @@ data class User( val showNotifications: Boolean = activeUser || showNtfs + val addressShared: Boolean = profile.contactLink != null + companion object { val sampleData = User( userId = 1, @@ -734,6 +736,7 @@ data class Contact( override val displayName get() = localAlias.ifEmpty { profile.displayName } override val fullName get() = profile.fullName override val image get() = profile.image + val contactLink: String? = profile.contactLink override val localAlias get() = profile.localAlias val verified get() = activeConn.connectionCode != null @@ -814,6 +817,7 @@ data class Profile( override val fullName: String, override val image: String? = null, override val localAlias : String = "", + val contactLink: String? = null, val preferences: ChatPreferences? = null ): NamedChat { val profileViewName: String @@ -821,7 +825,7 @@ data class Profile( return if (fullName == "" || displayName == fullName) displayName else "$displayName ($fullName)" } - fun toLocalProfile(profileId: Long): LocalProfile = LocalProfile(profileId, displayName, fullName, image, localAlias, preferences) + fun toLocalProfile(profileId: Long): LocalProfile = LocalProfile(profileId, displayName, fullName, image, localAlias, contactLink, preferences) companion object { val sampleData = Profile( @@ -832,17 +836,18 @@ data class Profile( } @Serializable -class LocalProfile( +data class LocalProfile( val profileId: Long, override val displayName: String, override val fullName: String, override val image: String? = null, override val localAlias: String, + val contactLink: String? = null, val preferences: ChatPreferences? = null ): NamedChat { val profileViewName: String = localAlias.ifEmpty { if (fullName == "" || displayName == fullName) displayName else "$displayName ($fullName)" } - fun toProfile(): Profile = Profile(displayName, fullName, image, localAlias, preferences) + fun toProfile(): Profile = Profile(displayName, fullName, image, localAlias, contactLink, preferences) companion object { val sampleData = LocalProfile( @@ -952,6 +957,7 @@ data class GroupMember ( val displayName: String get() = memberProfile.localAlias.ifEmpty { memberProfile.displayName } val fullName: String get() = memberProfile.fullName val image: String? get() = memberProfile.image + val contactLink: String? = memberProfile.contactLink val verified get() = activeConn?.connectionCode != null val chatViewName: String diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt index 662867f368..8542bfcadd 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt @@ -855,6 +855,15 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a return null } + suspend fun apiSetProfileAddress(on: Boolean): User? { + val userId = try { currentUserId("apiSetProfileAddress") } catch (e: Exception) { return null } + return when (val r = sendCmd(CC.ApiSetProfileAddress(userId, on))) { + is CR.UserProfileNoChange -> null + is CR.UserProfileUpdated -> r.user + else -> throw Exception("failed to set profile address: ${r.responseType} ${r.details}") + } + } + suspend fun apiSetContactPrefs(contactId: Long, prefs: ChatPreferences): Contact? { val r = sendCmd(CC.ApiSetContactPrefs(contactId, prefs)) if (r is CR.ContactPrefsUpdated) return r.toContact @@ -890,12 +899,12 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a } } - suspend fun apiDeleteUserAddress(): Boolean { - val userId = kotlin.runCatching { currentUserId("apiDeleteUserAddress") }.getOrElse { return false } + suspend fun apiDeleteUserAddress(): User? { + val userId = try { currentUserId("apiDeleteUserAddress") } catch (e: Exception) { return null } val r = sendCmd(CC.ApiDeleteMyAddress(userId)) - if (r is CR.UserContactLinkDeleted) return true + if (r is CR.UserContactLinkDeleted) return r.user Log.e(TAG, "apiDeleteUserAddress bad response: ${r.responseType} ${r.details}") - return false + return null } private suspend fun apiGetUserAddress(): UserContactLinkRec? { @@ -1905,6 +1914,7 @@ sealed class CC { class ApiCreateMyAddress(val userId: Long): CC() class ApiDeleteMyAddress(val userId: Long): CC() class ApiShowMyAddress(val userId: Long): CC() + class ApiSetProfileAddress(val userId: Long, val on: Boolean): CC() class ApiAddressAutoAccept(val userId: Long, val autoAccept: AutoAccept?): CC() class ApiSendCallInvitation(val contact: Contact, val callType: CallType): CC() class ApiRejectCall(val contact: Contact): CC() @@ -1989,6 +1999,7 @@ sealed class CC { is ApiCreateMyAddress -> "/_address $userId" is ApiDeleteMyAddress -> "/_delete_address $userId" is ApiShowMyAddress -> "/_show_address $userId" + is ApiSetProfileAddress -> "/_profile_address $userId ${onOff(on)}" is ApiAddressAutoAccept -> "/_auto_accept $userId ${AutoAccept.cmdString(autoAccept)}" is ApiAcceptContact -> "/_accept $contactReqId" is ApiRejectContact -> "/_reject $contactReqId" @@ -2074,6 +2085,7 @@ sealed class CC { is ApiCreateMyAddress -> "apiCreateMyAddress" is ApiDeleteMyAddress -> "apiDeleteMyAddress" is ApiShowMyAddress -> "apiShowMyAddress" + is ApiSetProfileAddress -> "apiSetProfileAddress" is ApiAddressAutoAccept -> "apiAddressAutoAccept" is ApiAcceptContact -> "apiAcceptContact" is ApiRejectContact -> "apiRejectContact" diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt index 0474ff71cd..a97d591388 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt @@ -5,8 +5,11 @@ import InfoRowEllipsis import SectionBottomSpacer import SectionDividerSpaced import SectionItemView +import SectionItemViewWithIcon import SectionSpacer +import SectionTextFooter import SectionView +import TextIconSpaced import android.widget.Toast import androidx.activity.compose.BackHandler import androidx.compose.foundation.* @@ -18,8 +21,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.ClipboardManager -import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.platform.* import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString @@ -34,6 +36,7 @@ import chat.simplex.app.SimplexApp import chat.simplex.app.model.* import chat.simplex.app.ui.theme.* import chat.simplex.app.views.helpers.* +import chat.simplex.app.views.newchat.QRCode import chat.simplex.app.views.usersettings.* import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* @@ -195,6 +198,15 @@ fun ChatInfoLayout( } SectionDividerSpaced() + if (contact.contactLink != null) { + val context = LocalContext.current + SectionView(stringResource(R.string.address_section_title).uppercase()) { + QRCode(contact.contactLink, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f)) + ShareAddressButton { shareText(context, contact.contactLink) } + SectionTextFooter(stringResource(R.string.you_can_share_this_address_with_your_contacts).format(contact.displayName)) + } + SectionDividerSpaced() + } SectionView(title = stringResource(R.string.conn_stats_section_title_servers)) { SwitchAddressButton(switchContactAddress) @@ -416,6 +428,17 @@ private fun DeleteContactButton(onClick: () -> Unit) { ) } +@Composable +fun ShareAddressButton(onClick: () -> Unit) { + SettingsActionItem( + painterResource(R.drawable.ic_share_filled), + stringResource(R.string.share_address), + onClick, + iconColor = MaterialTheme.colors.primary, + textColor = MaterialTheme.colors.primary, + ) +} + private fun setContactAlias(contactApiId: Long, localAlias: String, chatModel: ChatModel) = withApi { chatModel.controller.apiSetContactAlias(contactApiId, localAlias)?.let { chatModel.updateContact(it) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt index 728056f1d9..4722820938 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt @@ -175,6 +175,8 @@ fun GroupChatInfoLayout( SectionView { if (groupInfo.canEdit) { EditGroupProfileButton(editGroupProfile) + } + if (groupInfo.groupProfile.description != null || groupInfo.canEdit) { AddOrEditWelcomeMessage(groupInfo.groupProfile.description, addOrEditWelcomeMessage) } GroupPreferencesButton(openPreferences) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt index 0ba92cc3fc..572b46dff4 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt @@ -4,6 +4,7 @@ import InfoRow import SectionBottomSpacer import SectionDividerSpaced import SectionSpacer +import SectionTextFooter import SectionView import androidx.activity.compose.BackHandler import androidx.compose.foundation.* @@ -13,6 +14,7 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -20,10 +22,12 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import chat.simplex.app.R +import chat.simplex.app.SimplexApp import chat.simplex.app.model.* import chat.simplex.app.ui.theme.* import chat.simplex.app.views.chat.* import chat.simplex.app.views.helpers.* +import chat.simplex.app.views.newchat.QRCode import chat.simplex.app.views.usersettings.SettingsActionItem import kotlinx.datetime.Clock @@ -173,10 +177,20 @@ fun GroupMemberInfoLayout( VerifyCodeButton(member.verified, verifyClicked) } } - SectionSpacer() + SectionDividerSpaced() } } + if (member.contactLink != null) { + val context = LocalContext.current + SectionView(stringResource(R.string.address_section_title).uppercase()) { + QRCode(member.contactLink, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f)) + ShareAddressButton { shareText(context, member.contactLink) } + SectionTextFooter(stringResource(R.string.you_can_share_this_address_with_your_contacts).format(member.displayName)) + } + SectionDividerSpaced() + } + SectionView(title = stringResource(R.string.member_info_section_title_member)) { InfoRow(stringResource(R.string.info_row_group), groupInfo.displayName) val roles = remember { member.canChangeRoleTo(groupInfo) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt index 9e9408e993..eb1cf95d7d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt @@ -1,22 +1,30 @@ package chat.simplex.app.views.chat.group import SectionBottomSpacer +import SectionDividerSpaced import SectionItemView import SectionSpacer import SectionView +import TextIconSpaced +import android.util.Log import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text +import androidx.compose.material.* import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import chat.simplex.app.* import chat.simplex.app.R import chat.simplex.app.model.* -import chat.simplex.app.ui.theme.* import chat.simplex.app.views.helpers.* +import kotlinx.coroutines.delay +import kotlinx.serialization.Serializable +import java.lang.Exception @Composable fun GroupWelcomeView(m: ChatModel, groupInfo: GroupInfo, close: () -> Unit) { @@ -49,6 +57,7 @@ fun GroupWelcomeView(m: ChatModel, groupInfo: GroupInfo, close: () -> Unit) { GroupWelcomeLayout( welcomeText, groupInfo, + m.controller.appPrefs.simplexLinkMode.get(), save = ::save ) } @@ -58,19 +67,43 @@ fun GroupWelcomeView(m: ChatModel, groupInfo: GroupInfo, close: () -> Unit) { private fun GroupWelcomeLayout( welcomeText: MutableState, groupInfo: GroupInfo, + linkMode: SimplexLinkMode, save: () -> Unit, ) { Column( Modifier.fillMaxWidth().verticalScroll(rememberScrollState()), ) { + val editMode = remember { mutableStateOf(true) } AppBarTitle(stringResource(R.string.group_welcome_title)) - val welcomeText = remember { welcomeText } - TextEditor(Modifier.padding(horizontal = DEFAULT_PADDING).height(160.dp), text = welcomeText) - SectionSpacer() - SaveButton( - save = save, - disabled = welcomeText.value == groupInfo.groupProfile.description || (welcomeText.value == "" && groupInfo.groupProfile.description == null) - ) + val welcomeText = rememberSaveable { welcomeText } + if (groupInfo.canEdit) { + if (editMode.value) { + val focusRequester = remember { FocusRequester() } + TextEditor(welcomeText, Modifier.heightIn(min = 100.dp), stringResource(R.string.enter_welcome_message), focusRequester = focusRequester) + LaunchedEffect(Unit) { + delay(300) + focusRequester.requestFocus() + } + } else { + TextEditorPreview(welcomeText.value, linkMode) + } + ChangeModeButton( + editMode.value, + click = { + editMode.value = !editMode.value + }, + welcomeText.value.isEmpty() + ) + CopyTextButton { copyText(SimplexApp.context, welcomeText.value) } + SectionDividerSpaced(maxBottomPadding = false) + SaveButton( + save = save, + disabled = welcomeText.value == groupInfo.groupProfile.description || (welcomeText.value == "" && groupInfo.groupProfile.description == null) + ) + } else { + TextEditorPreview(welcomeText.value, linkMode) + CopyTextButton { copyText(SimplexApp.context, welcomeText.value) } + } SectionBottomSpacer() } } @@ -84,6 +117,35 @@ private fun SaveButton(save: () -> Unit, disabled: Boolean) { } } +@Composable +private fun ChangeModeButton(editMode: Boolean, click: () -> Unit, disabled: Boolean) { + SectionItemView(click, disabled = disabled) { + Icon( + painterResource(if (editMode) R.drawable.ic_visibility else R.drawable.ic_edit), + contentDescription = generalGetString(R.string.edit_verb), + tint = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary, + ) + TextIconSpaced() + Text( + stringResource(if (editMode) R.string.group_welcome_preview else R.string.edit_verb), + color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary + ) + } +} + +@Composable +private fun CopyTextButton(click: () -> Unit) { + SectionItemView(click) { + Icon( + painterResource(R.drawable.ic_content_copy), + contentDescription = generalGetString(R.string.copy_verb), + tint = MaterialTheme.colors.primary, + ) + TextIconSpaced() + Text(stringResource(R.string.copy_verb), color = MaterialTheme.colors.primary) + } +} + private fun showUnsavedChangesAlert(save: () -> Unit, revert: () -> Unit) { AlertManager.shared.showAlertDialogStacked( title = generalGetString(R.string.save_welcome_message_question), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt index 6fd7212b8e..7e933413a4 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt @@ -8,7 +8,6 @@ import androidx.compose.ui.res.painterResource import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.font.FontWeight @@ -18,7 +17,7 @@ import androidx.compose.ui.unit.sp import chat.simplex.app.R import chat.simplex.app.ui.theme.SimpleXTheme import chat.simplex.app.views.helpers.annotatedStringResource -import chat.simplex.app.views.helpers.openUriCatching +import chat.simplex.app.views.onboarding.ReadableTextWithLink import chat.simplex.app.views.usersettings.MarkdownHelpView import chat.simplex.app.views.usersettings.simplexTeamUri @@ -29,17 +28,8 @@ fun ChatHelpView(addContact: (() -> Unit)? = null) { Column( verticalArrangement = Arrangement.spacedBy(10.dp) ) { - val uriHandler = LocalUriHandler.current - Text(stringResource(R.string.thank_you_for_installing_simplex), lineHeight = 22.sp) - Text( - annotatedStringResource(R.string.you_can_connect_to_simplex_chat_founder), - modifier = Modifier.clickable(onClick = { - uriHandler.openUriCatching(simplexTeamUri) - }), - lineHeight = 22.sp - ) - + ReadableTextWithLink(R.string.you_can_connect_to_simplex_chat_founder, simplexTeamUri) Column( Modifier.padding(top = 24.dp), verticalArrangement = Arrangement.spacedBy(10.dp) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/TextEditor.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/TextEditor.kt index e00f9ba454..d1fe5ebbde 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/TextEditor.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/TextEditor.kt @@ -1,64 +1,130 @@ package chat.simplex.app.views.helpers -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.background +import android.util.Log +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState +import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.* import androidx.compose.ui.graphics.* import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.input.KeyboardCapitalization +import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.unit.* -import chat.simplex.app.ui.theme.DEFAULT_PADDING +import chat.simplex.app.TAG +import chat.simplex.app.chatParseMarkdown +import chat.simplex.app.model.* +import chat.simplex.app.ui.theme.* +import chat.simplex.app.views.chat.item.MarkdownText +import com.google.accompanist.insets.navigationBarsWithImePadding +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.serialization.Serializable +import java.lang.Exception @Composable fun TextEditor( + value: MutableState, modifier: Modifier, - text: MutableState, - border: Boolean = true, - fontSize: TextUnit = 14.sp, - background: Color = MaterialTheme.colors.background, - onChange: ((String) -> Unit)? = null + placeholder: String? = null, + contentPadding: PaddingValues = PaddingValues(horizontal = DEFAULT_PADDING), + isValid: (String) -> Boolean = { true }, + focusRequester: FocusRequester? = null ) { - BasicTextField( - value = text.value, - onValueChange = { text.value = it; onChange?.invoke(it) }, - textStyle = TextStyle( - fontFamily = FontFamily.Monospace, fontSize = fontSize, - color = MaterialTheme.colors.onBackground - ), - keyboardOptions = KeyboardOptions.Default.copy( - capitalization = KeyboardCapitalization.None, - autoCorrect = false - ), - modifier = modifier, - cursorBrush = SolidColor(MaterialTheme.colors.secondary), - decorationBox = { innerTextField -> - Surface( - shape = if (border) RoundedCornerShape(10.dp) else RectangleShape, - border = if (border) BorderStroke(1.dp, MaterialTheme.colors.secondaryVariant) else null - ) { - Row( - Modifier.background(background), - verticalAlignment = Alignment.Top - ) { - Box( - Modifier - .weight(1f) - .padding(vertical = 5.dp, horizontal = if (border) 7.dp else DEFAULT_PADDING) - ) { - innerTextField() - } + var valid by rememberSaveable { mutableStateOf(true) } + var focused by rememberSaveable { mutableStateOf(false) } + val strokeColor by remember { + derivedStateOf { + if (valid) { + if (focused) { + CurrentColors.value.colors.secondary.copy(alpha = 0.6f) + } else { + CurrentColors.value.colors.secondary.copy(alpha = 0.3f) } - } + } else Color.Red } - ) + } + Box( + Modifier + .fillMaxWidth() + .padding(contentPadding) + .heightIn(min = 52.dp), +// .border(border = BorderStroke(1.dp, strokeColor), shape = RoundedCornerShape(26.dp)), + contentAlignment = Alignment.Center, + ) { + val modifier = modifier + .fillMaxWidth() + .navigationBarsWithImePadding() + .onFocusChanged { focused = it.isFocused } + + BasicTextField( + value = value.value, + onValueChange = { value.value = it }, + modifier = if (focusRequester == null) modifier else modifier.focusRequester(focusRequester), + textStyle = TextStyle(fontSize = 18.sp, color = MaterialTheme.colors.onBackground), + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.None, + autoCorrect = false + ), + singleLine = false, + maxLines = 5, + cursorBrush = SolidColor(MaterialTheme.colors.secondary), + decorationBox = @Composable { innerTextField -> + TextFieldDefaults.TextFieldDecorationBox( + value = value.value, + innerTextField = innerTextField, + placeholder = if (placeholder != null) {{ Text(placeholder, fontSize = 18.sp, color = MaterialTheme.colors.secondary) }} else null, + contentPadding = PaddingValues(), + label = null, + visualTransformation = VisualTransformation.None, + leadingIcon = null, + trailingIcon = null, + singleLine = false, + enabled = true, + isError = false, + interactionSource = remember { MutableInteractionSource() }, + ) + } + ) + } + LaunchedEffect(Unit) { + snapshotFlow { value.value } + .distinctUntilChanged() + .collect { + valid = isValid(it) + } + } +} + +@Composable +fun TextEditorPreview(text: String, linkMode: SimplexLinkMode, markdown: Boolean = true) { + SelectionContainer { + MarkdownText( + text, + formattedText = if (markdown) remember(text) { parseToMarkdown(text) } else null, + modifier = Modifier.heightIn(min = 100.dp).padding(horizontal = DEFAULT_PADDING), + linkMode = linkMode, + style = TextStyle(fontSize = 18.sp, color = MaterialTheme.colors.onBackground) + ) + } +} + +@Serializable +data class ParsedFormattedText( + val formattedText: List? = null +) + +fun parseToMarkdown(text: String): List? { + val formatted = chatParseMarkdown(text) + return try { + json.decodeFromString(ParsedFormattedText.serializer(), formatted).formattedText + } catch (e: Exception) { + Log.e(TAG, "Failed to parse into markdown: " + e.stackTraceToString()) + null + } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactLearnMore.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactLearnMore.kt new file mode 100644 index 0000000000..44e576198e --- /dev/null +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactLearnMore.kt @@ -0,0 +1,23 @@ +package chat.simplex.app.views.newchat + +import androidx.compose.foundation.* +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import chat.simplex.app.R +import chat.simplex.app.views.helpers.AppBarTitle +import chat.simplex.app.views.onboarding.ReadableText +import chat.simplex.app.views.onboarding.ReadableTextWithLink + +@Composable +fun AddContactLearnMore() { + Column( + Modifier.verticalScroll(rememberScrollState()), + ) { + AppBarTitle(stringResource(R.string.one_time_link)) + ReadableText(R.string.scan_qr_to_connect_to_contact) + ReadableText(R.string.if_you_cant_meet_in_person) + ReadableTextWithLink(R.string.read_more_in_user_guide_with_link, "https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/README.md#connect-to-friends") + } +} \ No newline at end of file diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt index 5ad769adb6..99eab4584d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt @@ -1,6 +1,8 @@ package chat.simplex.app.views.newchat import SectionBottomSpacer +import SectionSpacer +import SectionView import android.content.res.Configuration import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState @@ -15,10 +17,10 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import chat.simplex.app.R import chat.simplex.app.ui.theme.* import chat.simplex.app.views.helpers.* +import chat.simplex.app.views.usersettings.SettingsActionItem @Composable fun AddContactView(connReqInvitation: String, connIncognito: Boolean) { @@ -26,64 +28,94 @@ fun AddContactView(connReqInvitation: String, connIncognito: Boolean) { AddContactLayout( connReq = connReqInvitation, connIncognito = connIncognito, - share = { shareText(cxt, connReqInvitation) } + share = { shareText(cxt, connReqInvitation) }, + learnMore = { + ModalManager.shared.showModal { + Column( + Modifier + .fillMaxHeight() + .padding(horizontal = DEFAULT_PADDING), + verticalArrangement = Arrangement.SpaceBetween + ) { + AddContactLearnMore() + } + } + } ) } @Composable -fun AddContactLayout(connReq: String, connIncognito: Boolean, share: () -> Unit) { - BoxWithConstraints { - val screenHeight = maxHeight - Column( - Modifier - .verticalScroll(rememberScrollState()), - verticalArrangement = Arrangement.SpaceBetween, - ) { - AppBarTitle(stringResource(R.string.add_contact), false) - Text( - stringResource(R.string.show_QR_code_for_your_contact_to_scan_from_the_app__multiline), - ) - Row { - InfoAboutIncognito( - connIncognito, - true, - generalGetString(R.string.incognito_random_profile_description), - generalGetString(R.string.your_profile_will_be_sent) - ) - } - if (connReq.isNotEmpty()) { - QRCode( - connReq, Modifier - .aspectRatio(1f) - .padding(vertical = 3.dp) - ) - } else { - CircularProgressIndicator( - Modifier - .size(36.dp) - .padding(4.dp) - .align(Alignment.CenterHorizontally), - color = MaterialTheme.colors.secondary, - strokeWidth = 3.dp - ) - } - Text( - annotatedStringResource(R.string.if_you_cannot_meet_in_person_show_QR_in_video_call_or_via_another_channel), - lineHeight = 22.sp, - modifier = Modifier - .padding(top = DEFAULT_PADDING, bottom = if (screenHeight > 600.dp) DEFAULT_PADDING else 0.dp) - ) - Row( - Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - SimpleButton(stringResource(R.string.share_invitation_link), icon = painterResource(R.drawable.ic_share), click = share) - } - SectionBottomSpacer() +fun AddContactLayout(connReq: String, connIncognito: Boolean, share: () -> Unit, learnMore: () -> Unit) { + Column( + Modifier + .verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.SpaceBetween, + ) { + AppBarTitle(stringResource(R.string.add_contact)) + OneTimeLinkProfileText(connIncognito) + + SectionSpacer() + SectionView(stringResource(R.string.one_time_link_short).uppercase()) { + OneTimeLinkSection(connReq, share, learnMore) } + SectionBottomSpacer() } } +@Composable +fun OneTimeLinkProfileText(connIncognito: Boolean) { + Row(Modifier.padding(horizontal = DEFAULT_PADDING)) { + InfoAboutIncognito( + connIncognito, + true, + generalGetString(R.string.incognito_random_profile_description), + generalGetString(R.string.your_profile_will_be_sent) + ) + } +} + +@Composable +fun ColumnScope.OneTimeLinkSection(connReq: String, share: () -> Unit, learnMore: () -> Unit) { + if (connReq.isNotEmpty()) { + QRCode( + connReq, Modifier + .padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF) + .aspectRatio(1f) + ) + } else { + CircularProgressIndicator( + Modifier + .size(36.dp) + .padding(4.dp) + .align(Alignment.CenterHorizontally), + color = MaterialTheme.colors.secondary, + strokeWidth = 3.dp + ) + } + ShareLinkButton(share) + OneTimeLinkLearnMoreButton(learnMore) +} + +@Composable +fun ShareLinkButton(onClick: () -> Unit) { + SettingsActionItem( + painterResource(R.drawable.ic_share), + stringResource(R.string.share_invitation_link), + onClick, + iconColor = MaterialTheme.colors.primary, + textColor = MaterialTheme.colors.primary, + ) +} + +@Composable +fun OneTimeLinkLearnMoreButton(onClick: () -> Unit) { + SettingsActionItem( + painterResource(R.drawable.ic_info), + stringResource(R.string.learn_more), + onClick, + ) +} + @Composable fun InfoAboutIncognito(chatModelIncognito: Boolean, supportedIncognito: Boolean = true, onText: String, offText: String, centered: Boolean = false) { if (chatModelIncognito) { @@ -133,7 +165,8 @@ fun PreviewAddContactView() { AddContactLayout( connReq = "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D", connIncognito = false, - share = {} + share = {}, + learnMore = {}, ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt index 12aa97cc12..fa7ec6f01f 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt @@ -1,6 +1,7 @@ package chat.simplex.app.views.newchat import SectionBottomSpacer +import SectionDividerSpaced import SectionView import android.content.res.Configuration import androidx.compose.foundation.layout.* @@ -10,6 +11,7 @@ import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -43,13 +45,16 @@ fun ContactConnectionInfoView( } } } + val context = LocalContext.current ContactConnectionInfoLayout( connReq = connReqInvitation, contactConnection, + connIncognito = contactConnection.incognito, focusAlias, deleteConnection = { deleteContactConnectionAlert(contactConnection, chatModel, close) }, onLocalAliasChanged = { setContactAlias(contactConnection, it, chatModel) }, - showQr = { + share = { if (connReqInvitation != null) shareText(context, connReqInvitation) }, + learnMore = { ModalManager.shared.showModal { Column( Modifier @@ -57,7 +62,7 @@ fun ContactConnectionInfoView( .padding(horizontal = DEFAULT_PADDING), verticalArrangement = Arrangement.SpaceBetween ) { - AddContactView(connReqInvitation ?: return@showModal, contactConnection.incognito) + AddContactLearnMore() } } } @@ -68,10 +73,12 @@ fun ContactConnectionInfoView( private fun ContactConnectionInfoLayout( connReq: String?, contactConnection: PendingContactConnection, + connIncognito: Boolean, focusAlias: Boolean, deleteConnection: () -> Unit, onLocalAliasChanged: (String) -> Unit, - showQr: () -> Unit, + share: () -> Unit, + learnMore: () -> Unit, ) { Column( Modifier @@ -83,11 +90,6 @@ private fun ContactConnectionInfoLayout( else R.string.you_accepted_connection ) ) - if (contactConnection.groupLinkId == null) { - Row(Modifier.padding(bottom = DEFAULT_PADDING)) { - LocalAliasEditor(contactConnection.localAlias, center = false, leadingIcon = true, focus = focusAlias, updateValue = onLocalAliasChanged) - } - } Text( stringResource( if (contactConnection.viaContactUri) @@ -97,27 +99,28 @@ private fun ContactConnectionInfoLayout( ), Modifier.padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING, bottom = DEFAULT_PADDING) ) + OneTimeLinkProfileText(connIncognito) + + if (contactConnection.groupLinkId == null) { + LocalAliasEditor(contactConnection.localAlias, center = false, leadingIcon = true, focus = focusAlias, updateValue = onLocalAliasChanged) + } + SectionView { if (!connReq.isNullOrEmpty() && contactConnection.initiated) { - ShowQrButton(contactConnection.incognito, showQr) + OneTimeLinkSection(connReq, share, learnMore) + } else { + OneTimeLinkLearnMoreButton(learnMore) } - DeleteButton(deleteConnection) } + + SectionDividerSpaced(maxBottomPadding = false) + + DeleteButton(deleteConnection) + SectionBottomSpacer() } } -@Composable -fun ShowQrButton(incognito: Boolean, onClick: () -> Unit) { - SettingsActionItem( - painterResource(R.drawable.ic_qr_code), - stringResource(R.string.show_QR_code), - click = onClick, - textColor = if (incognito) Indigo else MaterialTheme.colors.primary, - iconColor = if (incognito) Indigo else MaterialTheme.colors.primary, - ) -} - @Composable fun DeleteButton(onClick: () -> Unit) { SettingsActionItem( @@ -147,10 +150,12 @@ private fun PreviewContactConnectionInfoView() { ContactConnectionInfoLayout( connReq = "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D", PendingContactConnection.getSampleData(), + connIncognito = false, focusAlias = false, deleteConnection = {}, onLocalAliasChanged = {}, - showQr = {}, + share = {}, + learnMore = {} ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt index 90e58a6986..61a236936b 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt @@ -45,14 +45,13 @@ fun CreateLinkView(m: ChatModel, initialSelection: CreateLinkTab) { when { it == CreateLinkTab.ONE_TIME && connReqInvitation.value.isNullOrEmpty() -> stringResource(R.string.create_one_time_link) it == CreateLinkTab.ONE_TIME -> stringResource(R.string.one_time_link) - it == CreateLinkTab.LONG_TERM -> stringResource(R.string.your_contact_address) + it == CreateLinkTab.LONG_TERM -> stringResource(R.string.your_simplex_contact_address) else -> "" } } Column( Modifier - .fillMaxHeight() - .padding(horizontal = DEFAULT_PADDING), + .fillMaxHeight(), verticalArrangement = Arrangement.SpaceBetween ) { Column(Modifier.weight(1f)) { @@ -61,7 +60,7 @@ fun CreateLinkView(m: ChatModel, initialSelection: CreateLinkTab) { AddContactView(connReqInvitation.value ?: "", m.incognito.value) } CreateLinkTab.LONG_TERM -> { - UserAddressView(m) + UserAddressView(m, viaCreateLinkView = true, close = {}) } } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/PasteToConnect.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/PasteToConnect.kt index 19a35a0f6d..54c24999b6 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/PasteToConnect.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/PasteToConnect.kt @@ -85,7 +85,7 @@ fun PasteToConnectLayout( ) Box(Modifier.padding(top = DEFAULT_PADDING, bottom = 6.dp)) { - TextEditor(Modifier.height(180.dp), text = connectionLink) + TextEditor(connectionLink, Modifier.height(180.dp), contentPadding = PaddingValues()) } Row( diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/HowItWorks.kt b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/HowItWorks.kt index 5e76c8b095..ad7465fd38 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/HowItWorks.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/HowItWorks.kt @@ -4,21 +4,23 @@ import android.content.res.Configuration import androidx.annotation.StringRes import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* +import androidx.compose.material.MaterialTheme import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.* import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.app.R +import chat.simplex.app.SimplexApp import chat.simplex.app.model.User -import chat.simplex.app.ui.theme.DEFAULT_PADDING -import chat.simplex.app.ui.theme.SimpleXTheme +import chat.simplex.app.ui.theme.* +import chat.simplex.app.views.chat.item.MarkdownText import chat.simplex.app.views.helpers.* @Composable @@ -33,12 +35,7 @@ fun HowItWorks(user: User?, onboardingStage: MutableState? = n ReadableText(R.string.you_control_servers_to_receive_your_contacts_to_send) ReadableText(R.string.only_client_devices_store_contacts_groups_e2e_encrypted_messages) if (onboardingStage == null) { - val uriHandler = LocalUriHandler.current - Text( - annotatedStringResource(R.string.read_more_in_github_with_link), - modifier = Modifier.padding(bottom = 12.dp).clickable { uriHandler.openUriCatching("https://github.com/simplex-chat/simplex-chat#readme") }, - lineHeight = 22.sp - ) + ReadableTextWithLink(R.string.read_more_in_github_with_link, "https://github.com/simplex-chat/simplex-chat#readme") } else { ReadableText(R.string.read_more_in_github) } @@ -59,11 +56,42 @@ fun ReadableText(@StringRes stringResId: Int, textAlign: TextAlign = TextAlign.S Text(annotatedStringResource(stringResId), modifier = Modifier.padding(padding), textAlign = textAlign, lineHeight = 22.sp) } +@Composable +fun ReadableTextWithLink(@StringRes stringResId: Int, link: String, textAlign: TextAlign = TextAlign.Start, padding: PaddingValues = PaddingValues(bottom = 12.dp)) { + val annotated = annotatedStringResource(stringResId) + val primary = MaterialTheme.colors.primary + // This replaces links in text highlighted with specific color, e.g. SimplexBlue + val newStyles = remember(stringResId) { + val newStyles = ArrayList>() + annotated.spanStyles.forEach { + if (it.item.color == SimplexBlue) { + newStyles.add(it.copy(item = it.item.copy(primary))) + } else { + newStyles.add(it) + } + } + newStyles + } + val uriHandler = LocalUriHandler.current + Text(AnnotatedString(annotated.text, newStyles), modifier = Modifier.padding(padding).clickable { uriHandler.openUriCatching(link) }, textAlign = textAlign, lineHeight = 22.sp) +} + @Composable fun ReadableText(text: String, textAlign: TextAlign = TextAlign.Start, padding: PaddingValues = PaddingValues(bottom = 12.dp)) { Text(text, modifier = Modifier.padding(padding), textAlign = textAlign, lineHeight = 22.sp) } +@Composable +fun ReadableMarkdownText(text: String, textAlign: TextAlign = TextAlign.Start, padding: PaddingValues = PaddingValues(bottom = 12.dp)) { + MarkdownText( + text, + formattedText = remember(text) { parseToMarkdown(text) }, + modifier = Modifier.padding(padding), + style = TextStyle(textAlign = textAlign, lineHeight = 22.sp, fontSize = 16.sp), + linkMode = SimplexApp.context.chatModel.controller.appPrefs.simplexLinkMode.get(), + ) +} + @Preview(showBackground = true) @Preview( uiMode = Configuration.UI_MODE_NIGHT_YES, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AcceptRequestsView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AcceptRequestsView.kt deleted file mode 100644 index c383370042..0000000000 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AcceptRequestsView.kt +++ /dev/null @@ -1,160 +0,0 @@ -package chat.simplex.app.views.usersettings - -import SectionBottomSpacer -import SectionCustomFooter -import SectionView -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.ui.res.painterResource -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import chat.simplex.app.R -import chat.simplex.app.model.* -import chat.simplex.app.ui.theme.* -import chat.simplex.app.views.helpers.* - -@Composable -fun AcceptRequestsView(m: ChatModel, contactLink: UserContactLinkRec) { - var contactLink by remember { mutableStateOf(contactLink) } - AcceptRequestsLayout( - contactLink, - saveState = { new: MutableState, old: MutableState -> - withApi { - val link = m.controller.userAddressAutoAccept(new.value.autoAccept) - if (link != null) { - contactLink = link - m.userAddress.value = link - old.value = new.value - } - } - } - ) -} - -@Composable -private fun AcceptRequestsLayout( - contactLink: UserContactLinkRec, - saveState: (new: MutableState, old: MutableState) -> Unit, -) { - Column( - Modifier.fillMaxWidth().verticalScroll(rememberScrollState()), - ) { - AppBarTitle(stringResource(R.string.contact_requests)) - val autoAcceptState = remember { mutableStateOf(AutoAcceptState(contactLink)) } - val autoAcceptStateSaved = remember { mutableStateOf(autoAcceptState.value) } - SectionView(stringResource(R.string.accept_requests).uppercase()) { - PreferenceToggleWithIcon(stringResource(R.string.accept_automatically), painterResource(R.drawable.ic_check), checked = autoAcceptState.value.enable) { - autoAcceptState.value = if (!it) - AutoAcceptState() - else - AutoAcceptState(it, autoAcceptState.value.incognito, autoAcceptState.value.welcomeText) - } - if (autoAcceptState.value.enable) { - PreferenceToggleWithIcon( - stringResource(R.string.incognito), - if (autoAcceptState.value.incognito) painterResource(R.drawable.ic_theater_comedy_filled) else painterResource(R.drawable.ic_theater_comedy), - if (autoAcceptState.value.incognito) Indigo else MaterialTheme.colors.secondary, - autoAcceptState.value.incognito, - ) { - autoAcceptState.value = AutoAcceptState(autoAcceptState.value.enable, it, autoAcceptState.value.welcomeText) - } - } - } - val welcomeText = remember { mutableStateOf(autoAcceptState.value.welcomeText) } - SectionCustomFooter(PaddingValues(horizontal = DEFAULT_PADDING)) { - ButtonsFooter( - cancel = { - autoAcceptState.value = autoAcceptStateSaved.value - welcomeText.value = autoAcceptStateSaved.value.welcomeText - }, - save = { saveState(autoAcceptState, autoAcceptStateSaved) }, - disabled = autoAcceptState.value == autoAcceptStateSaved.value - ) - } - Spacer(Modifier.height(DEFAULT_PADDING)) - if (autoAcceptState.value.enable) { - Text( - stringResource(R.string.section_title_welcome_message), color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, - modifier = Modifier.padding(start = DEFAULT_PADDING, bottom = 5.dp), fontSize = 12.sp - ) - TextEditor(Modifier.padding(horizontal = DEFAULT_PADDING).height(160.dp), text = welcomeText) - LaunchedEffect(welcomeText.value) { - if (welcomeText.value != autoAcceptState.value.welcomeText) { - autoAcceptState.value = AutoAcceptState(autoAcceptState.value.enable, autoAcceptState.value.incognito, welcomeText.value) - } - } - } - SectionBottomSpacer() - } -} - -@Composable -private fun ButtonsFooter(cancel: () -> Unit, save: () -> Unit, disabled: Boolean) { - Row( - Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - FooterButton(painterResource(R.drawable.ic_replay), stringResource(R.string.cancel_verb), cancel, disabled) - FooterButton(painterResource(R.drawable.ic_check), stringResource(R.string.save_verb), save, disabled) - } -} - -private class AutoAcceptState { - var enable: Boolean = false - private set - var incognito: Boolean = false - private set - var welcomeText: String = "" - private set - - constructor(enable: Boolean = false, incognito: Boolean = false, welcomeText: String = "") { - this.enable = enable - this.incognito = incognito - this.welcomeText = welcomeText - } - - constructor(contactLink: UserContactLinkRec) { - contactLink.autoAccept?.let { aa -> - enable = true - incognito = aa.acceptIncognito - aa.autoReply?.let { msg -> - welcomeText = msg.text - } ?: run { - welcomeText = "" - } - } - } - - val autoAccept: AutoAccept? - get() { - if (enable) { - var autoReply: MsgContent? = null - val s = welcomeText.trim() - if (s != "") { - autoReply = MsgContent.MCText(s) - } - return AutoAccept(incognito, autoReply) - } - return null - } - - override fun equals(other: Any?): Boolean { - if (other !is AutoAcceptState) return false - return this.enable == other.enable && this.incognito == other.incognito && this.welcomeText == other.welcomeText - } - - override fun hashCode(): Int { - var result = enable.hashCode() - result = 31 * result + incognito.hashCode() - result = 31 * result + welcomeText.hashCode() - return result - } -} diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt index dc960dfd8b..86a2cafad2 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt @@ -27,6 +27,8 @@ import chat.simplex.app.model.ServerAddress.Companion.parseServerAddress import chat.simplex.app.ui.theme.* import chat.simplex.app.views.helpers.* import chat.simplex.app.views.newchat.QRCode +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.isActive import kotlinx.coroutines.launch @@ -140,14 +142,16 @@ private fun CustomServer( ) { val testedPreviously = remember { mutableMapOf() } TextEditor( - Modifier.height(144.dp), - text = serverAddress, - border = false, - fontSize = 16.sp, - background = if (isInDarkTheme()) GroupDark else MaterialTheme.colors.background - ) { - testedPreviously[server.server] = server.tested - onUpdate(server.copy(server = it, tested = testedPreviously[serverAddress.value])) + serverAddress, + Modifier.height(144.dp) + ) + LaunchedEffect(Unit) { + snapshotFlow { serverAddress.value } + .distinctUntilChanged() + .collect { + testedPreviously[server.server] = server.tested + onUpdate(server.copy(server = it, tested = testedPreviously[serverAddress.value])) + } } } SectionDividerSpaced() diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt index bfecd10027..452a084910 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt @@ -120,7 +120,7 @@ fun RTCServersLayout( } else { Text(stringResource(R.string.enter_one_ICE_server_per_line)) if (editRTCServers) { - TextEditor(Modifier.height(160.dp), text = userRTCServersStr) + TextEditor(userRTCServersStr, Modifier.height(160.dp), contentPadding = PaddingValues()) Row( Modifier.fillMaxWidth(), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt index 1b1b272923..65482116a0 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt @@ -150,7 +150,7 @@ fun SettingsLayout( val profileHidden = rememberSaveable { mutableStateOf(false) } SettingsActionItem(painterResource(R.drawable.ic_manage_accounts), stringResource(R.string.your_chat_profiles), { withAuth(generalGetString(R.string.auth_open_chat_profiles), generalGetString(R.string.auth_log_in_using_credential)) { showSettingsModalWithSearch { it, search -> UserProfilesView(it, search, profileHidden) } } }, disabled = stopped, extraPadding = true) SettingsIncognitoActionItem(incognitoPref, incognito, stopped) { showModal { IncognitoView() }() } - SettingsActionItem(painterResource(R.drawable.ic_qr_code), stringResource(R.string.your_simplex_contact_address), showModal { CreateLinkView(it, CreateLinkTab.LONG_TERM) }, disabled = stopped, extraPadding = true) + SettingsActionItem(painterResource(R.drawable.ic_qr_code), stringResource(R.string.your_simplex_contact_address), showCustomModal { it, close -> UserAddressView(it, shareViaProfile = it.currentUser.value!!.addressShared, close = close) }, disabled = stopped, extraPadding = true) ChatPreferencesItem(showCustomModal, stopped = stopped) } SectionDividerSpaced() diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressLearnMore.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressLearnMore.kt new file mode 100644 index 0000000000..7a70fcc516 --- /dev/null +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressLearnMore.kt @@ -0,0 +1,24 @@ +package chat.simplex.app.views.usersettings + +import androidx.compose.foundation.* +import androidx.compose.foundation.layout.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import chat.simplex.app.R +import chat.simplex.app.views.helpers.* +import chat.simplex.app.views.onboarding.ReadableText +import chat.simplex.app.views.onboarding.ReadableTextWithLink + +@Composable +fun UserAddressLearnMore() { + Column( + Modifier.verticalScroll(rememberScrollState()), + ) { + AppBarTitle(stringResource(R.string.simplex_address)) + ReadableText(R.string.you_can_share_your_address) + ReadableText(R.string.you_wont_lose_your_contacts_if_delete_address) + ReadableText(R.string.you_can_accept_or_reject_connection) + ReadableTextWithLink(R.string.read_more_in_user_guide_with_link, "https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address") + } +} \ No newline at end of file diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt index 6a2cad337e..c2dd05a296 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt @@ -1,13 +1,19 @@ package chat.simplex.app.views.usersettings import SectionBottomSpacer +import SectionDividerSpaced +import SectionItemView +import SectionTextFooter +import SectionView import android.content.res.Configuration +import android.util.Log import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -16,103 +22,382 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import chat.simplex.app.R -import chat.simplex.app.model.ChatModel -import chat.simplex.app.model.UserContactLinkRec +import chat.simplex.app.TAG +import chat.simplex.app.model.* import chat.simplex.app.ui.theme.* +import chat.simplex.app.views.chat.ShareAddressButton import chat.simplex.app.views.helpers.* import chat.simplex.app.views.newchat.QRCode @Composable -fun UserAddressView(chatModel: ChatModel) { +fun UserAddressView( + chatModel: ChatModel, + viaCreateLinkView: Boolean = false, + shareViaProfile: Boolean = false, + close: () -> Unit +) { val cxt = LocalContext.current - UserAddressLayout( - userAddress = remember { chatModel.userAddress }.value, - createAddress = { - withApi { - val connReqContact = chatModel.controller.apiCreateUserAddress() - if (connReqContact != null) { - chatModel.userAddress.value = UserContactLinkRec(connReqContact) + val shareViaProfile = remember { mutableStateOf(shareViaProfile) } + var progressIndicator by remember { mutableStateOf(false) } + val onCloseHandler: MutableState<(close: () -> Unit) -> Unit> = remember { mutableStateOf({ _ -> }) } + + fun setProfileAddress(on: Boolean) { + progressIndicator = true + withBGApi { + try { + val u = chatModel.controller.apiSetProfileAddress(on) + if (u != null) { + chatModel.updateUser(u) } + } catch (e: Exception) { + Log.e(TAG, "UserAddressView apiSetProfileAddress: ${e.stackTraceToString()}") + } finally { + progressIndicator = false } - }, - share = { userAddress: String -> shareText(cxt, userAddress) }, - acceptRequests = { - chatModel.userAddress.value?.let { address -> - ModalManager.shared.showModal(settings = true) { AcceptRequestsView(chatModel, address) } - } - }, - deleteAddress = { - AlertManager.shared.showAlertDialog( - title = generalGetString(R.string.delete_address__question), - text = generalGetString(R.string.all_your_contacts_will_remain_connected), - confirmText = generalGetString(R.string.delete_verb), - onConfirm = { - withApi { - chatModel.controller.apiDeleteUserAddress() - chatModel.userAddress.value = null + } + } + val userAddress = remember { chatModel.userAddress } + val showLayout = @Composable { + UserAddressLayout( + userAddress = userAddress.value, + shareViaProfile, + onCloseHandler, + createAddress = { + withApi { + progressIndicator = true + val connReqContact = chatModel.controller.apiCreateUserAddress() + if (connReqContact != null) { + chatModel.userAddress.value = UserContactLinkRec(connReqContact) + + AlertManager.shared.showAlertDialog( + title = generalGetString(R.string.delete_address_with_contacts_question), + text = generalGetString(R.string.add_address_to_your_profile), + confirmText = generalGetString(R.string.share_verb), + onConfirm = { + setProfileAddress(true) + shareViaProfile.value = true + } + ) } - }, - destructive = true, + progressIndicator = false + } + }, + learnMore = { + ModalManager.shared.showModal { + Column( + Modifier + .fillMaxHeight() + .padding(horizontal = DEFAULT_PADDING), + verticalArrangement = Arrangement.SpaceBetween + ) { + UserAddressLearnMore() + } + } + }, + share = { userAddress: String -> shareText(cxt, userAddress) }, + setProfileAddress = ::setProfileAddress, + deleteAddress = { + AlertManager.shared.showAlertDialog( + title = generalGetString(R.string.delete_address__question), + text = if (shareViaProfile.value) generalGetString(R.string.all_your_contacts_will_remain_connected_update_sent) else generalGetString(R.string.all_your_contacts_will_remain_connected), + confirmText = generalGetString(R.string.delete_verb), + onConfirm = { + progressIndicator = true + withApi { + val u = chatModel.controller.apiDeleteUserAddress() + if (u != null) { + chatModel.userAddress.value = null + chatModel.updateUser(u) + shareViaProfile.value = false + progressIndicator = false + } + } + }, + destructive = true, + ) + }, + saveAas = { aas: AutoAcceptState, savedAAS: MutableState -> + withBGApi { + val address = chatModel.controller.userAddressAutoAccept(aas.autoAccept) + if (address != null) { + chatModel.userAddress.value = address + savedAAS.value = aas + } + } + }) + } + + if (viaCreateLinkView) { + showLayout() + } else { + ModalView(close = { onCloseHandler.value(close) }) { + showLayout() + } + } + + if (progressIndicator) { + Box( + Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + if (userAddress.value != null) { + Surface(Modifier.size(50.dp), color = MaterialTheme.colors.background.copy(0.9f), shape = RoundedCornerShape(50)){} + } + CircularProgressIndicator( + Modifier + .padding(horizontal = 2.dp) + .size(30.dp), + color = MaterialTheme.colors.secondary, + strokeWidth = 3.dp ) } - ) + } } @Composable -fun UserAddressLayout( +private fun UserAddressLayout( userAddress: UserContactLinkRec?, + shareViaProfile: MutableState, + onCloseHandler: MutableState<(close: () -> Unit) -> Unit>, createAddress: () -> Unit, + learnMore: () -> Unit, share: (String) -> Unit, - acceptRequests: () -> Unit, - deleteAddress: () -> Unit + setProfileAddress: (Boolean) -> Unit, + deleteAddress: () -> Unit, + saveAas: (AutoAcceptState, MutableState) -> Unit, ) { Column( Modifier.verticalScroll(rememberScrollState()), ) { - AppBarTitle(stringResource(R.string.your_contact_address), false) - Text( - stringResource(R.string.you_can_share_your_address_anybody_will_be_able_to_connect), - Modifier.padding(bottom = 12.dp), - lineHeight = 22.sp - ) + AppBarTitle(stringResource(R.string.simplex_address), false) Column( Modifier.fillMaxWidth().padding(bottom = DEFAULT_PADDING_HALF), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.SpaceEvenly ) { if (userAddress == null) { - SimpleButton(stringResource(R.string.create_address), icon = painterResource(R.drawable.ic_qr_code), click = createAddress) - } else { - QRCode(userAddress.connReqContact, Modifier.aspectRatio(1f)) - Row( - horizontalArrangement = Arrangement.spacedBy(10.dp), - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(vertical = DEFAULT_PADDING) - ) { - SimpleButton( - stringResource(R.string.share_link), - icon = painterResource(R.drawable.ic_share), - click = { share(userAddress.connReqContact) }) - SimpleButtonIconEnded( - stringResource(R.string.contact_requests), - icon = painterResource(R.drawable.ic_chevron_right), - click = acceptRequests - ) + SectionView { + CreateAddressButton(createAddress) + SectionTextFooter(stringResource(R.string.create_address_and_let_people_connect)) + } + SectionDividerSpaced(maxBottomPadding = false) + SectionView { + LearnMoreButton(learnMore) + } + LaunchedEffect(Unit) { + onCloseHandler.value = { close -> close() } + } + } else { + val autoAcceptState = remember { mutableStateOf(AutoAcceptState(userAddress)) } + val autoAcceptStateSaved = remember { mutableStateOf(autoAcceptState.value) } + SectionView(stringResource(R.string.address_section_title).uppercase()) { + QRCode(userAddress.connReqContact, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f)) + ShareAddressButton { share(userAddress.connReqContact) } + ShareWithContactsButton(shareViaProfile, setProfileAddress) + AutoAcceptToggle(autoAcceptState) { saveAas(autoAcceptState.value, autoAcceptStateSaved) } + LearnMoreButton(learnMore) + } + if (autoAcceptState.value.enable) { + SectionDividerSpaced() + AutoAcceptSection(autoAcceptState, autoAcceptStateSaved, saveAas) + } + + SectionDividerSpaced(maxBottomPadding = false) + + SectionView { + DeleteAddressButton(deleteAddress) + SectionTextFooter(stringResource(R.string.your_contacts_will_remain_connected)) + } + LaunchedEffect(Unit) { + onCloseHandler.value = { close -> + if (autoAcceptState.value == autoAcceptStateSaved.value) close() + else showUnsavedChangesAlert({ saveAas(autoAcceptState.value, autoAcceptStateSaved); close() }, close) + } } - SimpleButton( - stringResource(R.string.delete_address), - icon = painterResource(R.drawable.ic_delete), - color = Color.Red, - click = deleteAddress - ) } } SectionBottomSpacer() } } +@Composable +private fun CreateAddressButton(onClick: () -> Unit) { + SettingsActionItem( + painterResource(R.drawable.ic_qr_code), + stringResource(R.string.create_simplex_address), + onClick, + iconColor = MaterialTheme.colors.primary, + textColor = MaterialTheme.colors.primary, + ) +} + +@Composable +private fun LearnMoreButton(onClick: () -> Unit) { + SettingsActionItem( + painterResource(R.drawable.ic_info), + stringResource(R.string.learn_more_about_address), + onClick, + ) +} + +@Composable +fun ShareWithContactsButton(shareViaProfile: MutableState, setProfileAddress: (Boolean) -> Unit) { + PreferenceToggleWithIcon( + stringResource(R.string.share_with_contacts), + painterResource(R.drawable.ic_person), + checked = shareViaProfile.value, + ) { on -> + shareViaProfile.value = on + if (on) { + AlertManager.shared.showAlertDialog( + title = generalGetString(R.string.share_address_with_contacts_question), + text = generalGetString(R.string.profile_update_will_be_sent_to_contacts), + confirmText = generalGetString(R.string.share_verb), + onConfirm = { + setProfileAddress(on) + }, + onDismiss = { + shareViaProfile.value = !on + }, + onDismissRequest = { + shareViaProfile.value = !on + }) + } else { + AlertManager.shared.showAlertDialog( + title = generalGetString(R.string.stop_sharing_address), + text = generalGetString(R.string.profile_update_will_be_sent_to_contacts), + confirmText = generalGetString(R.string.stop_sharing), + onConfirm = { + setProfileAddress(on) + }, + onDismiss = { + shareViaProfile.value = !on + }, + onDismissRequest = { + shareViaProfile.value = !on + }) + } + } +} + +@Composable +private fun AutoAcceptToggle(autoAcceptState: MutableState, saveAas: (AutoAcceptState) -> Unit) { + PreferenceToggleWithIcon(stringResource(R.string.auto_accept_contact), painterResource(R.drawable.ic_check), checked = autoAcceptState.value.enable) { + autoAcceptState.value = if (!it) + AutoAcceptState() + else + AutoAcceptState(it, autoAcceptState.value.incognito, autoAcceptState.value.welcomeText) + saveAas(autoAcceptState.value) + } +} + +@Composable +private fun DeleteAddressButton(onClick: () -> Unit) { + SettingsActionItem( + painterResource(R.drawable.ic_delete), + stringResource(R.string.delete_address), + onClick, + iconColor = MaterialTheme.colors.error, + textColor = MaterialTheme.colors.error, + ) +} + +private class AutoAcceptState { + var enable: Boolean = false + private set + var incognito: Boolean = false + private set + var welcomeText: String = "" + private set + + constructor(enable: Boolean = false, incognito: Boolean = false, welcomeText: String = "") { + this.enable = enable + this.incognito = incognito + this.welcomeText = welcomeText + } + + constructor(contactLink: UserContactLinkRec) { + contactLink.autoAccept?.let { aa -> + enable = true + incognito = aa.acceptIncognito + aa.autoReply?.let { msg -> + welcomeText = msg.text + } ?: run { + welcomeText = "" + } + } + } + + val autoAccept: AutoAccept? + get() { + if (enable) { + var autoReply: MsgContent? = null + val s = welcomeText.trim() + if (s != "") { + autoReply = MsgContent.MCText(s) + } + return AutoAccept(incognito, autoReply) + } + return null + } + + override fun equals(other: Any?): Boolean { + if (other !is AutoAcceptState) return false + return this.enable == other.enable && this.incognito == other.incognito && this.welcomeText == other.welcomeText + } + + override fun hashCode(): Int { + var result = enable.hashCode() + result = 31 * result + incognito.hashCode() + result = 31 * result + welcomeText.hashCode() + return result + } +} + +@Composable +private fun AutoAcceptSection( + autoAcceptState: MutableState, + savedAutoAcceptState: MutableState, + saveAas: (AutoAcceptState, MutableState) -> Unit +) { + SectionView(stringResource(R.string.auto_accept_contact).uppercase()) { + AcceptIncognitoToggle(autoAcceptState) + WelcomeMessageEditor(autoAcceptState) + SaveAASButton(autoAcceptState.value == savedAutoAcceptState.value) { saveAas(autoAcceptState.value, savedAutoAcceptState) } + } +} + +@Composable +private fun AcceptIncognitoToggle(autoAcceptState: MutableState) { + PreferenceToggleWithIcon( + stringResource(R.string.accept_contact_incognito_button), + if (autoAcceptState.value.incognito) painterResource(R.drawable.ic_theater_comedy_filled) else painterResource(R.drawable.ic_theater_comedy), + if (autoAcceptState.value.incognito) Indigo else MaterialTheme.colors.secondary, + autoAcceptState.value.incognito, + ) { + autoAcceptState.value = AutoAcceptState(autoAcceptState.value.enable, it, autoAcceptState.value.welcomeText) + } +} + +@Composable +private fun WelcomeMessageEditor(autoAcceptState: MutableState) { + val welcomeText = rememberSaveable { mutableStateOf(autoAcceptState.value.welcomeText) } + TextEditor(welcomeText, Modifier.height(100.dp), placeholder = stringResource(R.string.enter_welcome_message_optional)) + LaunchedEffect(welcomeText.value) { + if (welcomeText.value != autoAcceptState.value.welcomeText) { + autoAcceptState.value = AutoAcceptState(autoAcceptState.value.enable, autoAcceptState.value.incognito, welcomeText.value) + } + } +} + +@Composable +private fun SaveAASButton(disabled: Boolean, onClick: () -> Unit) { + SectionItemView(onClick, disabled = disabled) { + Text(stringResource(R.string.save_verb), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary) + } +} + @Preview(showBackground = true) @Preview( uiMode = Configuration.UI_MODE_NIGHT_YES, @@ -126,12 +411,26 @@ fun PreviewUserAddressLayoutNoAddress() { userAddress = null, createAddress = {}, share = { _ -> }, - acceptRequests = {}, deleteAddress = {}, + saveAas = { _, _ -> }, + setProfileAddress = { _ -> }, + learnMore = {}, + shareViaProfile = remember { mutableStateOf(false) }, + onCloseHandler = remember { mutableStateOf({}) } ) } } +private fun showUnsavedChangesAlert(save: () -> Unit, revert: () -> Unit) { + AlertManager.shared.showAlertDialogStacked( + title = generalGetString(R.string.save_settings_question), + confirmText = generalGetString(R.string.save_auto_accept_settings), + dismissText = generalGetString(R.string.exit_without_saving), + onConfirm = save, + onDismiss = revert, + ) +} + @Preview(showBackground = true) @Preview( uiMode = Configuration.UI_MODE_NIGHT_YES, @@ -145,8 +444,12 @@ fun PreviewUserAddressLayoutAddressCreated() { userAddress = UserContactLinkRec("https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D"), createAddress = {}, share = { _ -> }, - acceptRequests = {}, deleteAddress = {}, + saveAas = { _, _ -> }, + setProfileAddress = { _ -> }, + learnMore = {}, + shareViaProfile = remember { mutableStateOf(false) }, + onCloseHandler = remember { mutableStateOf({}) } ) } } diff --git a/apps/android/app/src/main/res/drawable/ic_person.xml b/apps/android/app/src/main/res/drawable/ic_person.xml new file mode 100644 index 0000000000..12ca71b4f9 --- /dev/null +++ b/apps/android/app/src/main/res/drawable/ic_person.xml @@ -0,0 +1,9 @@ + + + diff --git a/apps/android/app/src/main/res/values-ar/strings.xml b/apps/android/app/src/main/res/values-ar/strings.xml index d4c79ee9fd..deb0223248 100644 --- a/apps/android/app/src/main/res/values-ar/strings.xml +++ b/apps/android/app/src/main/res/values-ar/strings.xml @@ -31,7 +31,6 @@ أضف إلى جهاز آخر سيتم حذف جميع الدردشات والرسائل - لا يمكن التراجع عن هذا! الوصول إلى الخوادم عبر بروكسي SOCKS على المنفذ 9050؟ يجب بدء تشغيل الوكيل قبل تمكين هذا الخيار. - قبول طلبات إضافة خادم … إعدادات الشبكة المتقدمة سيبقى جميع أعضاء المجموعة على اتصال. diff --git a/apps/android/app/src/main/res/values-cs/strings.xml b/apps/android/app/src/main/res/values-cs/strings.xml index 6a4f0eed48..ea1f4c5d60 100644 --- a/apps/android/app/src/main/res/values-cs/strings.xml +++ b/apps/android/app/src/main/res/values-cs/strings.xml @@ -14,7 +14,6 @@ Povolte svým kontaktům odesílat mizící zprávy. O SimpleX Chat Přidat do jiného zařízení - Přijímat žádosti Povolit Povolit hlasové zprávy\? O SimpleX @@ -241,8 +240,6 @@ Připojení simplexmq: v%s (%2s) Vytvořit adresu - Automaticky - UVÍTACÍ ZPRÁVA Uložit a upozornit členy skupiny Ukončit bez uložení Platforma pro zasílání zpráv a aplikace chránící vaše soukromí a bezpečnost. @@ -378,7 +375,6 @@ Smazat čekající připojení\? Nastavení QR kód - Váš kontakt může z aplikace naskenovat QR kód. Pokud se nemůžete setkat osobně, ukažte ve videohovoru QR kód nebo sdílejte odkaz. Skenovat kód Nesprávný bezpečnostní kód! @@ -396,7 +392,6 @@ Pro připojení budou vyžadováni Onion hostitelé. Aktualizovat režim dopravní izolace\? Sestavení aplikace: %s - Můžete sdílet svou adresu jako odkaz nebo jako QR kód - kdokoli se k vám bude moci připojit. O své kontakty nepřijdete, pokud ji později smažete. Sdílet odkaz Smazat adresu Celé jméno: @@ -659,7 +654,6 @@ Verze jádra: v%s Smazat adresu\? Všechny vaše kontakty zůstanou připojeny. - Žádosti o kontakt Zobrazované jméno: Váš profil je uložen v zařízení a je sdílen pouze s vašimi kontakty. SimpleX servery váš profil vidět nemohou. Uložit předvolby\? @@ -957,7 +951,6 @@ Italské rozhraní Díky uživatelům - překládejte prostřednictvím Weblate! Budete připojeni, jakmile bude zařízení vašeho kontaktu online, vyčkejte prosím nebo se podívejte později! - Vaše adresa Váš chat profil bude odeslán \nvašemu kontaktu Vaše konverzace diff --git a/apps/android/app/src/main/res/values-de/strings.xml b/apps/android/app/src/main/res/values-de/strings.xml index 34db0193f0..c705c14aeb 100644 --- a/apps/android/app/src/main/res/values-de/strings.xml +++ b/apps/android/app/src/main/res/values-de/strings.xml @@ -328,7 +328,6 @@ Sie werden mit der Gruppe verbunden, sobald das Endgerät des Gruppen-Hosts online ist. Bitte warten oder schauen Sie später nochmal nach! Sie werden verbunden, sobald Ihre Verbindungsanfrage akzeptiert wird. Bitte warten oder schauen Sie später nochmal nach! Sie werden verbunden, sobald das Endgerät Ihres Kontakts online ist. Bitte warten oder schauen Sie später nochmal nach! - Zeigen Sie Ihrem Kontakt den QR-Code aus der App zum Scannen. Wenn Sie sich nicht persönlich treffen können, können Sie den QR-Code während eines Videoanrufs anzeigen oder einen Einladungslink über einen anderen Kanal mit Ihrem Kontakt teilen. Ihr Chat-Profil wird \nan Ihren Kontakt gesendet @@ -345,7 +344,6 @@ Link / QR-Code erstellen Einmaliger Einladungs-Link - Meine Kontaktadresse Meine Einstellungen Meine SimpleX Kontaktadresse @@ -418,14 +416,8 @@ Adresse erstellen Adresse löschen? Alle Ihre Kontakte bleiben verbunden. - Sie können Ihre Adresse als Link oder als QR-Code teilen – Jede Person kann sich darüber mit Ihnen verbinden. Sie werden Ihre mit dieser Adresse verbundenen Kontakte nicht verlieren, wenn Sie diese Adresse später löschen. Link teilen Adresse löschen - - Kontaktanfragen - Anfragen annehmen - Automatisch - Begrüßungsmeldung Angezeigter Name: "Vollständiger Name: diff --git a/apps/android/app/src/main/res/values-es/strings.xml b/apps/android/app/src/main/res/values-es/strings.xml index a2d32f0ff1..6a503d1ba6 100644 --- a/apps/android/app/src/main/res/values-es/strings.xml +++ b/apps/android/app/src/main/res/values-es/strings.xml @@ -75,8 +75,6 @@ Sobre SimpleX Chat Añadir a otro dispositivo Versión de la aplicación: v%s - Aceptar solicitudes - Automáticamente Solicita recibir la imagen Ten en cuenta: NO podrás recuperar o cambiar la contraseña si la pierdes. Tanto tú como tu contacto podéis enviar mensajes de voz. @@ -254,7 +252,6 @@ \nContraseña Contribuye Core versión: v%s - Solicitud del contacto Eliminar imagen Editar imagen CHATS @@ -858,7 +855,6 @@ mediante enlace de un uso Tus chats Mensaje de voz… - Mi dirección de contacto Desactivar vídeo Activar vídeo Contraseña de base de datos incorrecta @@ -888,7 +884,6 @@ Tienes un perfil de chat con el mismo nombre mostrado. Debes elegir otro nombre. También puedes conectarte haciendo clic en el enlace. Si se abre en el navegador, haz clic en Abrir en aplicación móvil. Puedes ponerte en contacto con los desarrolladores de SimpleX Chat para consultas y para recibir actualizaciones. - Puedes compartir tu dirección como enlace o como código QR: cualquiera podrá conectarse contigo. Si lo eliminas más tarde tus contactos no se perderán. ¡No puedes enviar mensajes! Puedes usar la sintaxis markdown para dar formato a los mensajes: Debes usar la versión más reciente de tu base de datos ÚNICAMENTE en un dispositivo, de lo contrario podrías dejar de recibir mensajes de algunos contactos. @@ -923,7 +918,6 @@ Has aceptado la conexión Has invitado a tu contacto Te conectarás al grupo cuando el dispositivo del anfitrión esté en línea, por favor espera o compruébalo más tarde. - Tu contacto puede escanear el código QR desde la aplicación. Mi configuración Tus servidores SMP ¡Tú controlas tu chat! @@ -972,7 +966,6 @@ Mi dirección de contacto SimpleX Tu servidor Dirección de tu servidor - MENSAJE DE BIENVENIDA Tu perfil actual Tu perfil se almacena en tu dispositivo y sólo se comparte con tus contactos. Los servidores SimpleX no pueden ver tu perfil. Sistema diff --git a/apps/android/app/src/main/res/values-fr/strings.xml b/apps/android/app/src/main/res/values-fr/strings.xml index 3ccb23d11d..f15988b78e 100644 --- a/apps/android/app/src/main/res/values-fr/strings.xml +++ b/apps/android/app/src/main/res/values-fr/strings.xml @@ -240,7 +240,6 @@ Ce code QR n\'est pas un lien ! Vous serez connecté·e lorsque votre demande de connexion sera acceptée, veuillez attendre ou vérifier plus tard ! Vous serez connecté·e lorsque l\'appareil de votre contact sera en ligne, veuillez attendre ou vérifier plus tard ! - Votre contact peut scanner le code QR depuis l\'app. Votre profil de chat sera envoyé \nà votre contact Partager le lien d\'invitation @@ -260,7 +259,6 @@ Se connecter via un lien Retirer la vérification Lien d\'invitation unique - Votre adresse de contact Scanner le code Code de sécurité incorrect ! Code de sécurité @@ -361,7 +359,6 @@ Les hôtes .onion seront utilisés lorsqu\'ils sont disponibles. Apparence Créer une adresse - Vous pouvez partager votre adresse sous forme de lien ou de code QR - n\'importe qui pourra se connecter à vous. Vous ne perdrez pas vos contacts si vous la supprimez par la suite. Votre profil de chat Modifier l\'image Sauvegarder et notifier les contacts @@ -433,10 +430,6 @@ Tous vos contacts resteront connectés. Partager le lien Supprimer l\'adresse - Demandes de contact - Accepter les demandes - Automatiquement - MESSAGE DE BIENVENUE Nom affiché : Nom complet : Votre profil est stocké sur votre appareil et partagé uniquement avec vos contacts. Les serveurs SimpleX ne peuvent pas voir votre profil. diff --git a/apps/android/app/src/main/res/values-hi/strings.xml b/apps/android/app/src/main/res/values-hi/strings.xml index f75ce402b7..ac5cfc339d 100644 --- a/apps/android/app/src/main/res/values-hi/strings.xml +++ b/apps/android/app/src/main/res/values-hi/strings.xml @@ -10,7 +10,6 @@ ऊपर,तब: स्वीकार करना जुडिये - आपका संपर्क पता दूसरे उपकरण में जोड़ें निडर कॉल का उत्तर दें @@ -35,7 +34,6 @@ संबंध अनुरोध स्वीकार करें\? स्वीकृत कॉल गुप्त स्वीकार करें - निवेदन स्वीकार करो पूर्वनिर्धारित सर्वर जोड़ें प्रोफ़ाइल जोड़ें सर्वर जोड़े… @@ -67,7 +65,6 @@ आप आज्ञा दें स्वागत! चालू करो - स्वागत संदेश अज्ञात संदेश प्रारूप स्वागत %1$s! शुरुआत @@ -235,7 +232,6 @@ चैट कंसोल आपके सभी संपर्क जुड़े रहेंगे। चैट प्रोफ़ाइल - संपर्क अनुरोध बनाएं कॉल त्रुटि कॉल चल रहा है diff --git a/apps/android/app/src/main/res/values-it/strings.xml b/apps/android/app/src/main/res/values-it/strings.xml index 3c1c8728c5..0186f9e056 100644 --- a/apps/android/app/src/main/res/values-it/strings.xml +++ b/apps/android/app/src/main/res/values-it/strings.xml @@ -239,7 +239,6 @@ Consenti i messaggi a tempo solo se il tuo contatto li consente. Permetti di eliminare irreversibilmente i messaggi inviati. Permetti ai tuoi contatti di inviare messaggi a tempo. - Accetta le richieste Accedere ai server via proxy SOCKS sulla porta 9050\? Il proxy deve essere avviato prima di attivare questa opzione. Aggiungi server scansionando codici QR. Tutti i membri del gruppo resteranno connessi. @@ -284,7 +283,6 @@ cambio indirizzo… Chat fermata connessione (presentato) - Richieste del contatto Richiesta di connessione inviata! Eliminare il link\? Elimina link @@ -339,7 +337,6 @@ Come si fa Come usare i tuoi server Server ICE (uno per riga) - Automaticamente grassetto chiamata terminata %1$s errore di chiamata @@ -575,7 +572,6 @@ Hai invitato il contatto Il tuo profilo di chat verrà inviato \nal tuo contatto - Il tuo contatto può scansionare il codice QR dall\'app. Il tuo contatto deve essere in linea per completare la connessione. \nPuoi annullare questa connessione e rimuovere il contatto (e riprovare più tardi con un link nuovo). Verrai connesso/a quando la tua richiesta di connessione verrà accettata, attendi o controlla più tardi! @@ -612,7 +608,6 @@ Usa il server Puoi anche connetterti cliccando il link. Se si apre nel browser, clicca il pulsante Apri nell\'app mobile. Il tuo profilo di chat verrà inviato al tuo contatto - Il tuo indirizzo di contatto Il tuo server L\'indirizzo del tuo server Il tuo indirizzo di contatto di SimpleX @@ -642,7 +637,6 @@ Usare i server di SimpleX Chat\? Stai usando i server di SimpleX Chat. Quando disponibili - Puoi condividere il tuo indirizzo come link o come codice QR: chiunque potrà connettersi a te. Non perderai i tuoi contatti se in seguito lo elimini. I tuoi server ICE I tuoi server SMP corsivo @@ -662,7 +656,6 @@ in attesa di risposta… in attesa di conferma… Non memorizziamo nessuno dei tuoi contatti o messaggi (una volta recapitati) sui server. - MESSAGGIO DI BENVENUTO Puoi usare il markdown per formattare i messaggi: Sei tu a controllare la tua chat! Il tuo profilo attuale diff --git a/apps/android/app/src/main/res/values-ja/strings.xml b/apps/android/app/src/main/res/values-ja/strings.xml index 7d3e9590c6..fc9016a462 100644 --- a/apps/android/app/src/main/res/values-ja/strings.xml +++ b/apps/android/app/src/main/res/values-ja/strings.xml @@ -31,8 +31,6 @@ 添付する アプリ・ビルド番号: %s あなたの連絡先が繋がったまま継続します。 - リクエストを承諾 - 自動的に 音声オン メッセージのハッシュ値問題 メッセージIDの問題 @@ -227,7 +225,6 @@ 連絡先の設定 連絡先はエンドツーエンド暗号化がありません。 連絡先がまだ繋がってません! - 連絡先のリクエスト 追加情報アイコン オニオンのホストが利用可能時に使われます。 オニオンのホストが使われません。 @@ -729,7 +726,6 @@ このリンクは有効な接続リンクではありません! このQRコードはリンクではありません! グループのホスト端末がオンラインになったら、接続されます。後でチェックするか、しばらくお待ちください。 - 連絡相手がアプリからQRコードを読み込めます。 連絡先がオンラインになったら、接続されます。後でチェックするか、しばらくお待ちください。 あなたのチャットプロフィールが \n連絡相手に送られます。 @@ -739,7 +735,6 @@ 連絡相手のアプリからセキュリティコードを読み込む SimpleXロック %s は未認証 - あなたのチャットアドレス あなたの設定 テストサーバ サーバを保存 @@ -890,8 +885,6 @@ SimpleX Chatを使っています。 リンクを送る simplexmq: バージョン%s (%2s) - あなたと繋がるリンク、またはQRコードを共有できます。誰でも接続できます。後で削除しても、連絡先がそのままのこります。 - 歓迎メッセージ 応答待ち… 確認待ち… 世界初のユーザーIDのないプラットフォーム|設計も元からプライベート diff --git a/apps/android/app/src/main/res/values-ko/strings.xml b/apps/android/app/src/main/res/values-ko/strings.xml index 62e3ca0fe2..d0f6d57894 100644 --- a/apps/android/app/src/main/res/values-ko/strings.xml +++ b/apps/android/app/src/main/res/values-ko/strings.xml @@ -52,13 +52,10 @@ 고급 네트워크 설정 채팅 프로필 연결 - 요청 수락 앱 빌드 : %s 외관 앱 버전 앱 버전 : v%s - 자동 - 대화 상대의 요청 코어 버전 : v%s 전화 받음 굵게 @@ -828,12 +825,10 @@ 라이브 메시지 보내기 - 입력 과정을 실시간으로 상대에게 보여줘요. 보내기 초대 링크 공유 - 연락하고자 하는 사람이 앱에서 QR 코드를 스캔할 수 있어요. 보안 코드 서버 QR코드 스캔 일부 서버가 테스트에 통과하지 못했습니다 : 서버 테스트 실패! - 환영 메시지 링크 공유 표시하기 연락처 선택 diff --git a/apps/android/app/src/main/res/values-lt/strings.xml b/apps/android/app/src/main/res/values-lt/strings.xml index 4476facc13..d1a4f0b9df 100644 --- a/apps/android/app/src/main/res/values-lt/strings.xml +++ b/apps/android/app/src/main/res/values-lt/strings.xml @@ -12,7 +12,6 @@ Programėlės versija Programėlės versija: v%s Programėlės darinys: %s - Automatiškai skambinama… skambučio klaida Skambutis jau baigtas! diff --git a/apps/android/app/src/main/res/values-nl/strings.xml b/apps/android/app/src/main/res/values-nl/strings.xml index 1439d7ae68..bd80a475d0 100644 --- a/apps/android/app/src/main/res/values-nl/strings.xml +++ b/apps/android/app/src/main/res/values-nl/strings.xml @@ -75,7 +75,6 @@ Over SimpleX Over SimpleX Chat hier boven, dan: - Verzoeken accepteren Alle gesprekken en berichten worden verwijderd, dit kan niet ongedaan worden gemaakt! Alle berichten worden verwijderd, dit kan niet ongedaan worden gemaakt! De berichten worden ALLEEN voor jou verwijderd. Sta verdwijnende berichten alleen toe als uw contactpersoon dit toestaat. @@ -96,7 +95,6 @@ App versie: v%s Er wordt een aparte TCP-verbinding (en SOCKS-referentie) gebruikt voor elk chat profiel dat je in de app hebt . audio oproep (niet e2e versleuteld) - Automatisch Achtergrondservice is altijd actief, meldingen worden weergegeven zodra de berichten beschikbaar zijn. Nieuw contact toevoegen: om uw eenmalige QR-code voor uw contact te maken. Oproep beëindigd @@ -210,7 +208,6 @@ Maak een eenmalige uitnodiging link gekleurd Oproep verbinden… - Contact verzoeken Maak Maak een profiel aan Adres verwijderen @@ -625,10 +622,8 @@ SimpleX-Team Deze QR-code is geen link! Deze link is geen geldige link! - Uw contactpersoon kan de QR-code vanuit de app scannen. Uitnodiging link delen Code scannen - Uw contact adres Uw instellingen Deel link Jij beheert je gesprek! @@ -728,7 +723,6 @@ SOCKS-proxy gebruiken (poort 9050) Voorkeuren opslaan\? Opslaan en Contact melden - WELKOMST BERICHT Je huidige profiel Opslaan en Contacten melden Opslaan en Groepsleden melden @@ -927,7 +921,6 @@ SimpleX Chat servers gebruiken\? Spraak berichten zijn verboden in deze groep. Welkom %1$s! - U kunt uw adres delen als een link of als een QR-code. Iedereen kan verbinding met u maken. U verliest uw contacten niet als u deze later verwijdert. U kunt de chat starten via app Instellingen / Database of door de app opnieuw op te starten. je hebt het adres gewijzigd voor %s je hebt %1$s verwijderd diff --git a/apps/android/app/src/main/res/values-pl/strings.xml b/apps/android/app/src/main/res/values-pl/strings.xml index 6924ef1724..fed9fae6fe 100644 --- a/apps/android/app/src/main/res/values-pl/strings.xml +++ b/apps/android/app/src/main/res/values-pl/strings.xml @@ -290,7 +290,6 @@ Twój profil czatu zostanie wysłany \ndo Twojego kontaktu Twój profil czatu zostanie wysłany do Twojego kontaktu - Twój adres kontaktowy Zostaniesz połączony do grupy, gdy urządzenie gospodarza grupy będzie online, proszę czekać lub sprawdzić później! Zostaniesz połączony, gdy urządzenie Twojego kontaktu będzie online, proszę czekać lub sprawdzić później! Dodaj gotowe serwery @@ -364,10 +363,7 @@ Użyj hostów .onion Użyć proxy SOCKS\? Użyj proxy SOCKS (port 9050) - Akceptuj prośby Wszystkie Twoje kontakty pozostaną połączone. - Automatycznie - Prośby kontaktu Utwórz adres ID bazy danych i opcja izolacji transportu. Usuń adres @@ -387,8 +383,6 @@ Pokaż: Pokaż opcje dewelopera simplexmq: v%s (%2s) - WIADOMOŚĆ POWITALNA - Możesz udostępnić swój adres jako link lub jako kod QR - każdy będzie mógł się z Tobą połączyć. Nie stracisz swoich kontaktów, jeśli później go usuniesz. Twój obecny profil Potwierdź hasło Utwórz profil @@ -1041,7 +1035,6 @@ Musisz używać najnowszej wersji bazy danych czatu TYLKO na jednym urządzeniu, w przeciwnym razie możesz przestać otrzymywać wiadomości od niektórych kontaktów. Możesz rozpocząć czat poprzez Ustawienia aplikacji / Bazę danych lub poprzez ponowne uruchomienie aplikacji. Twoje ustawienia - Twój kontakt może zeskanować kod QR z aplikacji. Twoja obecna baza danych czatu zostanie USUNIĘTA i ZASTĄPIONA zaimportowaną. \nTej czynności nie można cofnąć - Twój profil, kontakty, wiadomości i pliki zostaną nieodwracalnie utracone. Twój kontakt wysłał plik, który jest większy niż obecnie obsługiwany maksymalny rozmiar (%1$s). diff --git a/apps/android/app/src/main/res/values-pt-rBR/strings.xml b/apps/android/app/src/main/res/values-pt-rBR/strings.xml index 4adb03c202..10b1a1ab2f 100644 --- a/apps/android/app/src/main/res/values-pt-rBR/strings.xml +++ b/apps/android/app/src/main/res/values-pt-rBR/strings.xml @@ -50,7 +50,6 @@ Botão Fechar Limpar verificação Versão do App - Automaticamente negrito erro de chamada Chamadas de áudio e vídeo @@ -67,7 +66,6 @@ Um perfil aleatório será enviado para o seu contato Preferências de chat perfil de chat - Aceitar solicitações Áudio desligado Aceitar imagens automaticamente Banco de dados de chat excluído @@ -123,7 +121,6 @@ Copiado para a área de transferência Aceitar solicitação de conexão\? Configurações de rede avançadas - Solicitações de contato Criar endereço Todos os seus contatos permanecerão conectados. chamada aceita @@ -462,7 +459,6 @@ Rejeitar ofereceu %s Endereço SimpleX - Seu contato pode escanear o código QR do aplicativo. ofereceu %s: %2s Cole o link que você recebeu na caixa abaixo para conectar com o seu contato. Novo em %s @@ -657,7 +653,6 @@ Esse código QR não é um link! Seu perfil de chat será enviado para seu \ncontato - Seu endereço de contato Você será conectado quando o dispositivo do seu contato estiver online, aguarde ou verifique mais tarde! Como Teste do servidor falhou! @@ -784,7 +779,6 @@ Hosts Onion não serão usados. Os hosts Onion serão usados quando disponíveis. Os hosts Onion serão usados quando disponíveis. - Você pode compartilhar seu endereço como um link ou como um código QR - qualquer pessoa poderá se conectar a você. Você não perderá seus contatos se excluí-los posteriormente. Seu perfil atual Privacidade redefinida Notificações privadas @@ -921,7 +915,6 @@ você é um observador Mensagem de voz (%1$s) Compartilhar link - MENSAGEM DE BOAS-VINDAS Para proteger a privacidade, em vez dos IDs de usuário usados por todas as outras plataformas, SimpleX tem identificadores para filas de mensagens, separados para cada um de seus contatos. chamada de vídeo Mostrar diff --git a/apps/android/app/src/main/res/values-ru/strings.xml b/apps/android/app/src/main/res/values-ru/strings.xml index a4df902c8a..ec80a7d96f 100644 --- a/apps/android/app/src/main/res/values-ru/strings.xml +++ b/apps/android/app/src/main/res/values-ru/strings.xml @@ -330,7 +330,6 @@ Соединение с группой будет установлено, когда хост группы будет онлайн. Пожалуйста, подождите или проверьте позже! Соединение будет установлено, когда Ваш запрос будет принят. Пожалуйста, подождите или проверьте позже! Соединение будет установлено, когда Ваш контакт будет онлайн. Пожалуйста, подождите или проверьте позже! - Ваш контакт может сосканировать QR код в приложении. Если Вы не можете встретиться лично, Вы можете показать QR код во время видеозвонка или поделиться ссылкой. Ваш профиль будет отправлен \nВашему контакту @@ -344,7 +343,6 @@ Создать одноразовую ссылку Одноразовая ссылка - Ваш SimpleX адрес Настройки Ваш SimpleX адрес @@ -417,14 +415,8 @@ Создать адрес Удалить адрес? Все контакты, которые соединились через этот адрес, сохранятся. - Вы можете использовать Ваш адрес как ссылку или как QR код - кто угодно сможет соединиться с Вами. Вы сможете удалить адрес, сохранив контакты, которые через него соединились. Поделиться\nссылкой - Удалить\nадрес - - Запросы контактов - Принимать запросы - Автоматически - ПРИВЕТСТВЕННОЕ СООБЩЕНИЕ + Удалить адрес Имя профиля: "Полное имя: diff --git a/apps/android/app/src/main/res/values-zh-rCN/strings.xml b/apps/android/app/src/main/res/values-zh-rCN/strings.xml index 2ebcaddde6..759422a3a6 100644 --- a/apps/android/app/src/main/res/values-zh-rCN/strings.xml +++ b/apps/android/app/src/main/res/values-zh-rCN/strings.xml @@ -23,7 +23,6 @@ 接受连接请求? 接受隐身聊天 管理员可以创建链接以加入群组。 - 接受请求 添加预设服务器 通过链接连接 已建立连接 @@ -112,7 +111,6 @@ 错误消息散列 错误消息 ID 语音和视频通话 - 自动 激活电池优化,关闭了后台服务和新消息的定期请求。您可以通过设置重新启用它们。 后台服务一直在运行——一旦有消息,就会显示通知。 关闭音频 @@ -328,7 +326,6 @@ 联系人和所有的消息都将被删除——这是不可逆回的! 联系人姓名 连接(介绍邀请) - 联系人请求 连接中…… 联系人可以将信息标记为删除;您将可以查看这些信息。 贡献 @@ -516,7 +513,6 @@ 您只能在一台设备上使用最新版本的聊天数据库,否则您可能会停止接收来自某些联系人的消息。 新密码…… 该角色将更改为“%s”。群组中每个人都会收到通知。 - 您的联系人地址 SimpleX 锁定 定期通知 定期启动 @@ -891,9 +887,7 @@ SimpleX 团队 %1$s 成员 - 您可以将您的地址作为链接或二维码共享——任何人都可以连接到您。 如果您以后删除它,您不会丢失您的联系人。 您可以控制通过哪些服务器接收消息,您的联系人 - 您用来向他们发送消息的服务器。 - 您的联系人可以从应用程序中扫描二维码。 您将在组主设备上线时连接到该群组,请稍等或稍后再检查! 当您启动应用或在应用程序驻留后台超过30 秒后,您将需要进行身份验证。 创建于 %1$s @@ -942,7 +936,6 @@ 使用 .onion 主机 您的 ICE 服务器 simplexmq: v%s (%2s) - 欢迎消息 您的聊天由您掌控! 您可以使用 markdown 来编排消息格式: %dh diff --git a/apps/android/app/src/main/res/values-zh-rTW/strings.xml b/apps/android/app/src/main/res/values-zh-rTW/strings.xml index c4e8727a53..2f8117f0df 100644 --- a/apps/android/app/src/main/res/values-zh-rTW/strings.xml +++ b/apps/android/app/src/main/res/values-zh-rTW/strings.xml @@ -1,7 +1,6 @@ 1 個星期 - 接受請求 a + b 關於 SimpleX 接受 @@ -70,7 +69,6 @@ 程式建構:%s 應用程式版本:v%s 分享連結 - 自動接受所有請求 你目前的個人檔案 顯示的名稱字與字中間不能有空白。 儲存設定? @@ -434,8 +432,6 @@ 核心版本:v%s simplexmq: v%s (%2s) 建立地址 - 聯絡人請求 - 歡迎訊息 編輯圖片 斜體 已拒絕通話 @@ -487,7 +483,6 @@ 這些字串不是連接連結! 你也可以點擊連結連接。如果在瀏覧器中開啟,點擊 程式內的開啟 按扭。 一次性邀請連結 - 你的聯絡人地址 掃描二碼碼 錯誤的安全碼! 在你聯絡人的程式內掃描安全碼 @@ -511,7 +506,6 @@ Onion 主機會當有的時侯啟用 連接時將需要 Onion 主機 刪除地址? - 你可以使用連結或二維碼分享你的地址 - 任何人也可以和你連線。如果你不主動刪除你的聯絡人,你並不會遺失你的聯絡人 你的個人檔案只會儲存於你的裝置和只會分享給你的聯絡人。 SimpleX 伺服器並不會看到你的個人檔案。 儲存並通知你的聯絡人 儲存並通知你的多個聯絡人 @@ -525,7 +519,6 @@ 收到回應 … 連接中 … 通話完結 - 你的聯絡人可以在程式內使用二維碼 連接 網路 & 伺服器 網路設定 diff --git a/apps/android/app/src/main/res/values/strings.xml b/apps/android/app/src/main/res/values/strings.xml index ea69b48417..e55407aadb 100644 --- a/apps/android/app/src/main/res/values/strings.xml +++ b/apps/android/app/src/main/res/values/strings.xml @@ -103,6 +103,7 @@ Server requires authorization to create queues, check password Server requires authorization to upload, check password Possibly, certificate fingerprint in server address is incorrect + Error setting address Connect Disconnect Create queue @@ -446,13 +447,24 @@ You will be connected to group when the group host\'s device is online, please wait or check later! You will be connected when your connection request is accepted, please wait or check later! You will be connected when your contact\'s device is online, please wait or check later! - Your contact can scan QR code from the app. If you can\'t meet in person, show QR code in the video call, or share the link. Your chat profile will be sent\nto your contact If you cannot meet in person, you can scan QR code in the video call, or your contact can share an invitation link. - Share invitation link + Share 1-time link Paste the link you received into the box below to connect with your contact. Your chat profile will be sent to your contact + Learn more + About SimpleX address + + + To connect, your contact can scan QR code or use the link in the app. + If you can\'t meet in person, show QR code in a video call, or share the link. + + + You can share your address as a link or QR code - anybody can connect to you. + You won\'t lose your contacts if you later delete your address. + When people request to connect, you can accept or reject it. + Read more in User Guide. Connect via link @@ -464,7 +476,8 @@ Create one-time invitation link One-time invitation link - Your contact address + 1-time link + SimpleX address Scan code @@ -481,7 +494,7 @@ Your settings - Your SimpleX contact address + Your SimpleX address Your chat profiles Database passphrase & export About SimpleX Chat @@ -579,17 +592,25 @@ Create address Delete address? + Your contacts will remain connected. All your contacts will remain connected. - You can share your address as a link or as a QR code - anybody will be able to connect to you. You won\'t lose your contacts if you later delete it. + All your contacts will remain connected. Profile update will be sent to your contacts. Share link + Share address with contacts? + Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts. + Create an address to let people connect with you. + Create SimpleX address + Share with contacts + Share address with contacts? + Profile update will be sent to your contacts. + Stop sharing address? + Stop sharing + Auto-accept + Enter welcome message… (optional) + Save settings? + Save auto-accept settings Delete address - - Contact requests - Accept requests - Automatically - WELCOME MESSAGE - Display name: "Full name: @@ -1050,6 +1071,9 @@ Error updating group link Error deleting group link Only group owners can change group preferences. + Address + Share address + You can share this address with your contacts to let them connect with %s. FOR CONSOLE @@ -1080,6 +1104,8 @@ Welcome message Save welcome message? Save and update group profile + Preview + Enter welcome message… SERVERS From f711f4d8a8eff0cef343fe0ab595aba32df6ca39 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Wed, 3 May 2023 13:23:23 +0300 Subject: [PATCH 5/6] android: socks proxy port (#2367) * android: socks proxy port * ability to specify socks host and port before enabling it * comment --- .../java/chat/simplex/app/model/SimpleXAPI.kt | 12 +++ .../views/usersettings/NetworkAndServers.kt | 80 ++++++++++--------- .../app/src/main/res/values-ar/strings.xml | 2 +- .../app/src/main/res/values-cs/strings.xml | 3 +- .../app/src/main/res/values-de/strings.xml | 3 +- .../app/src/main/res/values-es/strings.xml | 3 +- .../app/src/main/res/values-fr/strings.xml | 3 +- .../app/src/main/res/values-it/strings.xml | 3 +- .../app/src/main/res/values-ja/strings.xml | 3 +- .../app/src/main/res/values-ko/strings.xml | 3 +- .../app/src/main/res/values-lt/strings.xml | 1 - .../app/src/main/res/values-nl/strings.xml | 3 +- .../app/src/main/res/values-pl/strings.xml | 3 +- .../src/main/res/values-pt-rBR/strings.xml | 3 +- .../app/src/main/res/values-ru/strings.xml | 3 +- .../src/main/res/values-zh-rCN/strings.xml | 3 +- .../src/main/res/values-zh-rTW/strings.xml | 1 - .../app/src/main/res/values/strings.xml | 3 +- 18 files changed, 70 insertions(+), 65 deletions(-) diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt index 8542bfcadd..8603652ac2 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt @@ -1812,6 +1812,9 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a ) } + /** + * [AppPreferences.networkProxyHostPort] is not changed here, use appPrefs to set it + * */ fun setNetCfg(cfg: NetCfg) { appPrefs.networkUseSocksProxy.set(cfg.useSocksProxy) appPrefs.networkHostMode.set(cfg.hostMode.name) @@ -2355,6 +2358,15 @@ data class NetCfg( val useSocksProxy: Boolean get() = socksProxy != null val enableKeepAlive: Boolean get() = tcpKeepAlive != null + fun withHostPort(hostPort: String?, default: String? = ":9050"): NetCfg { + val socksProxy = if (hostPort?.startsWith("localhost:") == true) { + hostPort.removePrefix("localhost") + } else { + hostPort ?: default + } + return copy(socksProxy = socksProxy) + } + companion object { val defaults: NetCfg = NetCfg( diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt index c20e4eb0be..47c926cdd7 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt @@ -48,12 +48,13 @@ fun NetworkAndServersView( chatModel.userSMPServersUnsaved.value = null } + val proxyPort = remember { derivedStateOf { chatModel.controller.appPrefs.networkProxyHostPort.state.value?.split(":")?.lastOrNull()?.toIntOrNull() ?: 9050 } } NetworkAndServersLayout( developerTools = developerTools, networkUseSocksProxy = networkUseSocksProxy, onionHosts = onionHosts, sessionMode = sessionMode, - proxyPort = remember { derivedStateOf { chatModel.controller.appPrefs.networkProxyHostPort.state.value?.split(":")?.lastOrNull()?.toIntOrNull() ?: 9050 } }, + proxyPort = proxyPort, showModal = showModal, showSettingsModal = showSettingsModal, showCustomModal = showCustomModal, @@ -61,14 +62,15 @@ fun NetworkAndServersView( if (enable) { AlertManager.shared.showAlertDialog( title = generalGetString(R.string.network_enable_socks), - text = generalGetString(R.string.network_enable_socks_info), + text = generalGetString(R.string.network_enable_socks_info).format(proxyPort.value), confirmText = generalGetString(R.string.confirm_verb), onConfirm = { withApi { - chatModel.controller.apiSetNetworkConfig(NetCfg.proxyDefaults) - chatModel.controller.setNetCfg(NetCfg.proxyDefaults) + val conf = NetCfg.proxyDefaults.withHostPort(chatModel.controller.appPrefs.networkProxyHostPort.get()) + chatModel.controller.apiSetNetworkConfig(conf) + chatModel.controller.setNetCfg(conf) networkUseSocksProxy.value = true - onionHosts.value = NetCfg.proxyDefaults.onionHosts + onionHosts.value = conf.onionHosts } } ) @@ -79,10 +81,11 @@ fun NetworkAndServersView( confirmText = generalGetString(R.string.confirm_verb), onConfirm = { withApi { - chatModel.controller.apiSetNetworkConfig(NetCfg.defaults) - chatModel.controller.setNetCfg(NetCfg.defaults) + val conf = NetCfg.defaults + chatModel.controller.apiSetNetworkConfig(conf) + chatModel.controller.setNetCfg(conf) networkUseSocksProxy.value = false - onionHosts.value = NetCfg.defaults.onionHosts + onionHosts.value = conf.onionHosts } } ) @@ -206,35 +209,31 @@ fun UseSocksProxySwitch( ) { Icon( painterResource(R.drawable.ic_settings_ethernet), - stringResource(R.string.network_socks_toggle), + stringResource(R.string.network_socks_toggle_use_socks_proxy), tint = MaterialTheme.colors.secondary ) TextIconSpaced(false) - if (networkUseSocksProxy.value) { - val text = buildAnnotatedString { - append(generalGetString(R.string.network_socks_toggle_use_socks_proxy) + " (") - val style = SpanStyle(color = MaterialTheme.colors.primary) - withAnnotation(tag = "PORT", annotation = generalGetString(R.string.network_proxy_port).format(proxyPort.value)) { - withStyle(style) { append(generalGetString(R.string.network_proxy_port).format(proxyPort.value)) } - } - append(")") - } - ClickableText( - text, - style = TextStyle(color = MaterialTheme.colors.onBackground, fontSize = 16.sp, fontFamily = FontFamily(Font(R.font.inter_regular))), - onClick = { offset -> - text.getStringAnnotations(tag = "PORT", start = offset, end = offset) - .firstOrNull()?.let { _ -> - showSettingsModal { SockProxySettings(it) }() - } - }, - shouldConsumeEvent = { offset -> - text.getStringAnnotations(tag = "PORT", start = offset, end = offset).any() - } - ) - } else { - Text(stringResource(R.string.network_socks_toggle)) + val text = buildAnnotatedString { + append(generalGetString(R.string.network_socks_toggle_use_socks_proxy) + " (") + val style = SpanStyle(color = MaterialTheme.colors.primary) + withAnnotation(tag = "PORT", annotation = generalGetString(R.string.network_proxy_port).format(proxyPort.value)) { + withStyle(style) { append(generalGetString(R.string.network_proxy_port).format(proxyPort.value)) } + } + append(")") } + ClickableText( + text, + style = TextStyle(color = MaterialTheme.colors.onBackground, fontSize = 16.sp, fontFamily = FontFamily(Font(R.font.inter_regular))), + onClick = { offset -> + text.getStringAnnotations(tag = "PORT", start = offset, end = offset) + .firstOrNull()?.let { _ -> + showSettingsModal { SockProxySettings(it) }() + } + }, + shouldConsumeEvent = { offset -> + text.getStringAnnotations(tag = "PORT", start = offset, end = offset).any() + } + ) } DefaultSwitch( checked = networkUseSocksProxy.value, @@ -262,13 +261,15 @@ fun SockProxySettings(m: ChatModel) { val save = { withBGApi { m.controller.appPrefs.networkProxyHostPort.set(hostUnsaved.value.text + ":" + portUnsaved.value.text) - m.controller.apiSetNetworkConfig(m.controller.getNetCfg()) + if (m.controller.appPrefs.networkUseSocksProxy.get()) { + m.controller.apiSetNetworkConfig(m.controller.getNetCfg()) + } } } SectionView { SectionItemView { ResetToDefaultsButton({ - showUpdateNetworkSettingsDialog { + val reset = { m.controller.appPrefs.networkProxyHostPort.set(defaultHostPort) val newHost = defaultHostPort.split(":").first() val newPort = defaultHostPort.split(":").last() @@ -276,6 +277,13 @@ fun SockProxySettings(m: ChatModel) { portUnsaved.value = portUnsaved.value.copy(newPort, TextRange(newPort.length)) save() } + if (m.controller.appPrefs.networkUseSocksProxy.get()) { + showUpdateNetworkSettingsDialog { + reset() + } + } else { + reset() + } }, disabled = hostPort == defaultHostPort) } SectionItemView { @@ -307,7 +315,7 @@ fun SockProxySettings(m: ChatModel) { hostUnsaved.value = hostUnsaved.value.copy(prevHost, TextRange(prevHost.length)) portUnsaved.value = portUnsaved.value.copy(prevPort, TextRange(prevPort.length)) }, - save = { showUpdateNetworkSettingsDialog { save() } }, + save = { if (m.controller.appPrefs.networkUseSocksProxy.get()) showUpdateNetworkSettingsDialog { save() } else save() }, revertDisabled = hostPort == (hostUnsaved.value.text + ":" + portUnsaved.value.text), saveDisabled = hostPort == (hostUnsaved.value.text + ":" + portUnsaved.value.text) || remember { derivedStateOf { !validHost(hostUnsaved.value.text) } }.value || diff --git a/apps/android/app/src/main/res/values-ar/strings.xml b/apps/android/app/src/main/res/values-ar/strings.xml index deb0223248..60d7ffc7e8 100644 --- a/apps/android/app/src/main/res/values-ar/strings.xml +++ b/apps/android/app/src/main/res/values-ar/strings.xml @@ -30,7 +30,7 @@ أضف خوادم محددة مسبقًا أضف إلى جهاز آخر سيتم حذف جميع الدردشات والرسائل - لا يمكن التراجع عن هذا! - الوصول إلى الخوادم عبر بروكسي SOCKS على المنفذ 9050؟ يجب بدء تشغيل الوكيل قبل تمكين هذا الخيار. + الوصول إلى الخوادم عبر بروكسي SOCKS على المنفذ %d؟ يجب بدء تشغيل الوكيل قبل تمكين هذا الخيار. إضافة خادم … إعدادات الشبكة المتقدمة سيبقى جميع أعضاء المجموعة على اتصال. diff --git a/apps/android/app/src/main/res/values-cs/strings.xml b/apps/android/app/src/main/res/values-cs/strings.xml index ea1f4c5d60..7e79ca6c3d 100644 --- a/apps/android/app/src/main/res/values-cs/strings.xml +++ b/apps/android/app/src/main/res/values-cs/strings.xml @@ -9,7 +9,7 @@ Pokročilá nastavení sítě Přijmout Přidat server… - Přistupovat k serverům přes SOCKS proxy na portu 9050\? Před povolením této možnosti musí být spuštěna proxy. + Přistupovat k serverům přes SOCKS proxy na portu %d\? Před povolením této možnosti musí být spuštěna proxy. Přijmout Povolte svým kontaktům odesílat mizící zprávy. O SimpleX Chat @@ -635,7 +635,6 @@ Ujistěte se, že adresy serverů WebRTC ICE jsou ve správném formátu, oddělené na řádcích a nejsou duplicitní. Uložit Síť a servery - Použít proxy server SOCKS (port 9050) Aktualizovat nastavení hostitelů .onion\? Použít hostitele .onion Když bude dostupný diff --git a/apps/android/app/src/main/res/values-de/strings.xml b/apps/android/app/src/main/res/values-de/strings.xml index c705c14aeb..48bfbb7df2 100644 --- a/apps/android/app/src/main/res/values-de/strings.xml +++ b/apps/android/app/src/main/res/values-de/strings.xml @@ -395,9 +395,8 @@ Netzwerk & Server Erweiterte Netzwerkeinstellungen Netzwerkeinstellungen - SOCKS-Proxy verwenden (Port 9050) SOCKS-Proxy verwenden? - Zugriff auf die Server über SOCKS-Proxy auf Port 9050? Der Proxy muss gestartet werden, bevor diese Option aktiviert wird. + Zugriff auf die Server über SOCKS-Proxy auf Port %d? Der Proxy muss gestartet werden, bevor diese Option aktiviert wird. Direkte Internetverbindung verwenden? Wenn Sie dies bestätigen, können die Messaging-Server Ihre IP-Adresse und Ihren Provider sehen und mit welchen Servern Sie sich verbinden. Einstellung für .onion-Hosts aktualisieren? diff --git a/apps/android/app/src/main/res/values-es/strings.xml b/apps/android/app/src/main/res/values-es/strings.xml index 6a503d1ba6..f4ba29eb83 100644 --- a/apps/android/app/src/main/res/values-es/strings.xml +++ b/apps/android/app/src/main/res/values-es/strings.xml @@ -33,7 +33,7 @@ Aceptar incógnito Se eliminarán todos los mensajes SOLO para tí. ¡No puede deshacerse! Añadir servidor… - ¿Acceder a los servidores a través del proxy SOCKS en el puerto 9050\? El proxy debe iniciarse antes de activar esta opción. + ¿Acceder a los servidores a través del proxy SOCKS en el puerto %d\? El proxy debe iniciarse antes de activar esta opción. Todos tus contactos permanecerán conectados. Apariencia Versión @@ -738,7 +738,6 @@ Compartir envío no autorizado Escribe un nombre para el contacto - Usar proxy SOCKS (puerto 9050) Error desconocido El rol cambiará a \"%s\". Se notificará a todos los miembros del grupo. La seguridad de SimpleX Chat fue auditada por Trail of Bits. diff --git a/apps/android/app/src/main/res/values-fr/strings.xml b/apps/android/app/src/main/res/values-fr/strings.xml index f15988b78e..07a056fb65 100644 --- a/apps/android/app/src/main/res/values-fr/strings.xml +++ b/apps/android/app/src/main/res/values-fr/strings.xml @@ -324,7 +324,7 @@ Utiliser les serveurs SimpleX Chat \? Supprimer le serveur Assurez-vous que les adresses des serveurs WebRTC ICE sont au bon format et ne sont pas dupliquées, un par ligne. - Accéder aux serveurs via un proxy SOCKS sur le port 9050 \? Le proxy doit être démarré avant d\'activer cette option. + Accéder aux serveurs via un proxy SOCKS sur le port %d \? Le proxy doit être démarré avant d\'activer cette option. Utiliser les hôtes .onions Les hôtes .onion seront utilisés lorsqu\'ils sont disponibles. Les hôtes .onion seront nécessaires pour la connexion. @@ -350,7 +350,6 @@ Configurer les serveurs ICE Paramètres réseau avancés Paramètres réseau - Utiliser un proxy SOCKS (port 9050) Utiliser un proxy SOCKS \? Utiliser une connexion Internet directe \? Si vous confirmez, les serveurs de messagerie seront en mesure de voir votre adresse IP, votre fournisseur ainsi que les serveurs auxquels vous vous connectez. diff --git a/apps/android/app/src/main/res/values-it/strings.xml b/apps/android/app/src/main/res/values-it/strings.xml index 0186f9e056..9243a98fb9 100644 --- a/apps/android/app/src/main/res/values-it/strings.xml +++ b/apps/android/app/src/main/res/values-it/strings.xml @@ -239,7 +239,7 @@ Consenti i messaggi a tempo solo se il tuo contatto li consente. Permetti di eliminare irreversibilmente i messaggi inviati. Permetti ai tuoi contatti di inviare messaggi a tempo. - Accedere ai server via proxy SOCKS sulla porta 9050\? Il proxy deve essere avviato prima di attivare questa opzione. + Accedere ai server via proxy SOCKS sulla porta %d\? Il proxy deve essere avviato prima di attivare questa opzione. Aggiungi server scansionando codici QR. Tutti i membri del gruppo resteranno connessi. Consenti l\'eliminazione irreversibile dei messaggi solo se il contatto la consente a te. @@ -633,7 +633,6 @@ Usare una connessione internet diretta\? Usa gli host .onion Usare il proxy SOCKS\? - Usa il proxy SOCKS (porta 9050) Usare i server di SimpleX Chat\? Stai usando i server di SimpleX Chat. Quando disponibili diff --git a/apps/android/app/src/main/res/values-ja/strings.xml b/apps/android/app/src/main/res/values-ja/strings.xml index fc9016a462..1a48ad9846 100644 --- a/apps/android/app/src/main/res/values-ja/strings.xml +++ b/apps/android/app/src/main/res/values-ja/strings.xml @@ -22,7 +22,7 @@ 別の端末に追加 プロフィールを追加 サーバを追加… - SOCKSプロキシ(ポート9050)経由で接続しますか?(※設定する前にプロキシ起動が必要※) + SOCKSプロキシ(ポート%d)経由で接続しますか?(※設定する前にプロキシ起動が必要※) 全チャットとメッセージが削除されます(※元に戻せません※)! 送信相手からの音声メッセージを許可する。 あなたと連絡相手が音声メッセージを送信できます。 @@ -748,7 +748,6 @@ あなたのICEサーバ 直接にインタネットに繋がりますか? SOCKSプロキシを使いますか? - SOCKSプロキシ (ポート9050) を使う .onionのホスト設定を更新しますか? .onionホストを使う 利用可能時に diff --git a/apps/android/app/src/main/res/values-ko/strings.xml b/apps/android/app/src/main/res/values-ko/strings.xml index d0f6d57894..ed05450d1e 100644 --- a/apps/android/app/src/main/res/values-ko/strings.xml +++ b/apps/android/app/src/main/res/values-ko/strings.xml @@ -140,7 +140,7 @@ 응답 연결 요청을 수락할까요\? 수락 - SOCKS 프록시(포트 9050)를 통해 서버에 액세스할까요\? 이 설정을 활성화하기 전에 프록시를 시작해야 해요. + SOCKS 프록시(포트 %d)를 통해 서버에 액세스할까요\? 이 설정을 활성화하기 전에 프록시를 시작해야 해요. 다른 기기에 추가 QR 코드 스캔으로 서버 추가 환영 메시지 추가 @@ -667,7 +667,6 @@ 읽지 않음으로 표시 음소거 메시지에 사용된 마크다운 - SOCKS 프록시 사용 (포트 9050) 직접적인 인터넷 연결을 사용할까요\? SOCKS 프록시를 사용할까요\? 설정하면 메시징 서버에서 내 IP 주소와 내가 연결하려는 서버를 볼 수 있어요. diff --git a/apps/android/app/src/main/res/values-lt/strings.xml b/apps/android/app/src/main/res/values-lt/strings.xml index d1a4f0b9df..d4fb5b3bd2 100644 --- a/apps/android/app/src/main/res/values-lt/strings.xml +++ b/apps/android/app/src/main/res/values-lt/strings.xml @@ -278,7 +278,6 @@ Naudoti kamerą Dėkojame, kad įdiegėte SimpleX Chat! Naudoti serverį - Naudoti SOCKS įgaliotąjį serverį (prievadas 9050) Naudoti SOCKS įgaliotąjį serverį\? simplexmq: v%s (%2s) Bendrinti nuorodą diff --git a/apps/android/app/src/main/res/values-nl/strings.xml b/apps/android/app/src/main/res/values-nl/strings.xml index bd80a475d0..ca5147b956 100644 --- a/apps/android/app/src/main/res/values-nl/strings.xml +++ b/apps/android/app/src/main/res/values-nl/strings.xml @@ -16,7 +16,7 @@ Gevraagd om de afbeelding te ontvangen Wijziging Geavanceerde netwerk instellingen - Toegang tot de servers via SOCKS proxy op poort 9050\? De proxy moet worden gestart voordat u deze optie inschakelt. + Toegang tot de servers via SOCKS proxy op poort %d\? De proxy moet worden gestart voordat u deze optie inschakelt. Kan geen contacten uitnodigen! Sta het verzenden van directe berichten naar leden toe. Sta toe om verzonden berichten onomkeerbaar te verwijderen. @@ -720,7 +720,6 @@ Uw server adres Uw server Transport isolation - SOCKS-proxy gebruiken (poort 9050) Voorkeuren opslaan\? Opslaan en Contact melden Je huidige profiel diff --git a/apps/android/app/src/main/res/values-pl/strings.xml b/apps/android/app/src/main/res/values-pl/strings.xml index fed9fae6fe..95f53333d4 100644 --- a/apps/android/app/src/main/res/values-pl/strings.xml +++ b/apps/android/app/src/main/res/values-pl/strings.xml @@ -331,7 +331,7 @@ Twój adres serwera Twój adres kontaktowy SimpleX Przyczyń się - Uzyskiwać dostęp do serwerów przez SOCKS proxy na porcie 9050\? Proxy musi zostać uruchomione przed włączeniem tej opcji. + Uzyskiwać dostęp do serwerów przez SOCKS proxy na porcie %d\? Proxy musi zostać uruchomione przed włączeniem tej opcji. Zaawansowane ustawienia sieci Kompilacja aplikacji: %s Wygląd @@ -362,7 +362,6 @@ Użyć bezpośredniego połączenia z Internetem\? Użyj hostów .onion Użyć proxy SOCKS\? - Użyj proxy SOCKS (port 9050) Wszystkie Twoje kontakty pozostaną połączone. Utwórz adres ID bazy danych i opcja izolacji transportu. diff --git a/apps/android/app/src/main/res/values-pt-rBR/strings.xml b/apps/android/app/src/main/res/values-pt-rBR/strings.xml index 10b1a1ab2f..4bb272cc6f 100644 --- a/apps/android/app/src/main/res/values-pt-rBR/strings.xml +++ b/apps/android/app/src/main/res/values-pt-rBR/strings.xml @@ -154,7 +154,7 @@ Contato ainda não está conectado! Contribuir Criar - Acessar os servidores via proxy SOCKS na porta 9050\? O proxy deve ser iniciado antes de habilitar esta opção. + Acessar os servidores via proxy SOCKS na porta %d\? O proxy deve ser iniciado antes de habilitar esta opção. Permitir que seus contatos excluam de forma irreversível as mensagens enviadas. Adicionar a outro dispositivo Os administradores podem criar os links para ingressar em grupos. @@ -809,7 +809,6 @@ Configurações de conexão sem detalhes Link de convite de uso único - Usar proxy SOCKS (porta 9050) Seu endereço de servidor Suas configurações %s é verificado diff --git a/apps/android/app/src/main/res/values-ru/strings.xml b/apps/android/app/src/main/res/values-ru/strings.xml index ec80a7d96f..47996bfe7c 100644 --- a/apps/android/app/src/main/res/values-ru/strings.xml +++ b/apps/android/app/src/main/res/values-ru/strings.xml @@ -394,9 +394,8 @@ Сеть и серверы Настройки сети Настройки сети - Использовать SOCKS прокси (порт 9050) Использовать SOCKS прокси? - Соединяться с серверами через SOCKS прокси через порт 9050? Прокси должен быть запущен до включения этой опции. + Соединяться с серверами через SOCKS прокси через порт %d? Прокси должен быть запущен до включения этой опции. Использовать прямое соединение с Интернет? Если Вы подтвердите, серверы смогут видеть Ваш IP адрес, а провайдер - с какими серверами Вы соединяетесь. Обновить настройки .onion хостов? diff --git a/apps/android/app/src/main/res/values-zh-rCN/strings.xml b/apps/android/app/src/main/res/values-zh-rCN/strings.xml index 759422a3a6..579c4e51c6 100644 --- a/apps/android/app/src/main/res/values-zh-rCN/strings.xml +++ b/apps/android/app/src/main/res/values-zh-rCN/strings.xml @@ -14,7 +14,7 @@ 色调 已接受通话 接受 - 通过 SOCKS 代理访问服务器在端口9050?允许该选项前必须开始代理。 + 通过 SOCKS 代理访问服务器在端口%d?允许该选项前必须开始代理。 添加服务器…… 添加另一设备 管理员 @@ -872,7 +872,6 @@ 当您的联系人设备在线时,您将可以连接,请稍等或稍后查看! 评价此应用程序 使用 SOCKS 代理? - 使用 SOCKS 代理(端口 9050) %d 个文件,总大小为 %s 您已加入此群组 您被邀请加入群组 diff --git a/apps/android/app/src/main/res/values-zh-rTW/strings.xml b/apps/android/app/src/main/res/values-zh-rTW/strings.xml index 2f8117f0df..908d4e7d1b 100644 --- a/apps/android/app/src/main/res/values-zh-rTW/strings.xml +++ b/apps/android/app/src/main/res/values-zh-rTW/strings.xml @@ -522,7 +522,6 @@ 連接 網路 & 伺服器 網路設定 - 使用 SOCKS 代理伺服器 (端口 9050) 使用 SOCKS 代理伺服器 儲存並通知群組內的聯絡人 退出並且不儲存記錄 diff --git a/apps/android/app/src/main/res/values/strings.xml b/apps/android/app/src/main/res/values/strings.xml index e55407aadb..2eef854303 100644 --- a/apps/android/app/src/main/res/values/strings.xml +++ b/apps/android/app/src/main/res/values/strings.xml @@ -548,14 +548,13 @@ Network & servers Advanced network settings Network settings - Use SOCKS proxy (port 9050) SOCKS proxy settings Use SOCKS proxy port %d Host Port Use SOCKS proxy? - Access the servers via SOCKS proxy on port 9050? Proxy must be started before enabling this option. + Access the servers via SOCKS proxy on port %d? Proxy must be started before enabling this option. Use direct Internet connection? If you confirm, the messaging servers will be able to see your IP address, and your provider - which servers you are connecting to. Update .onion hosts setting? From 5af389ae3fda92a32a1050c01674b2ac77adaa93 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Wed, 3 May 2023 15:01:45 +0400 Subject: [PATCH 6/6] mobile: change links from repo to website (#2370) --- .../simplex/app/views/newchat/AddContactLearnMore.kt | 4 ++-- .../simplex/app/views/onboarding/WhatsNewView.kt | 6 +++--- .../app/views/usersettings/ProtocolServersView.kt | 2 +- .../simplex/app/views/usersettings/RTCServers.kt | 2 +- .../app/views/usersettings/UserAddressLearnMore.kt | 4 ++-- .../Shared/Views/NewChat/AddContactLearnMore.swift | 2 +- apps/ios/Shared/Views/Onboarding/WhatsNewView.swift | 6 +++--- .../Views/UserSettings/ProtocolServersView.swift | 2 +- apps/ios/Shared/Views/UserSettings/RTCServers.swift | 2 +- .../Views/UserSettings/UserAddressLearnMore.swift | 2 +- .../ar.xcloc/Localized Contents/ar.xliff | 4 ++-- .../cs.xcloc/Localized Contents/cs.xliff | 10 +++++----- .../de.xcloc/Localized Contents/de.xliff | 10 +++++----- .../en.xcloc/Localized Contents/en.xliff | 12 ++++++------ .../es.xcloc/Localized Contents/es.xliff | 8 ++++---- .../fi.xcloc/Localized Contents/fi.xliff | 4 ++-- .../fr.xcloc/Localized Contents/fr.xliff | 10 +++++----- .../hr.xcloc/Localized Contents/hr.xliff | 4 ++-- .../it.xcloc/Localized Contents/it.xliff | 10 +++++----- .../ko.xcloc/Localized Contents/ko.xliff | 4 ++-- .../lt.xcloc/Localized Contents/lt.xliff | 4 ++-- .../nl.xcloc/Localized Contents/nl.xliff | 10 +++++----- .../pl.xcloc/Localized Contents/pl.xliff | 10 +++++----- .../ru.xcloc/Localized Contents/ru.xliff | 10 +++++----- .../uk.xcloc/Localized Contents/uk.xliff | 4 ++-- .../zh-Hans.xcloc/Localized Contents/zh-Hans.xliff | 10 +++++----- apps/ios/cs.lproj/Localizable.strings | 2 +- apps/ios/de.lproj/Localizable.strings | 2 +- apps/ios/es.lproj/Localizable.strings | 2 +- apps/ios/fr.lproj/Localizable.strings | 2 +- apps/ios/it.lproj/Localizable.strings | 2 +- apps/ios/nl.lproj/Localizable.strings | 2 +- apps/ios/pl.lproj/Localizable.strings | 2 +- apps/ios/ru.lproj/Localizable.strings | 2 +- apps/ios/zh-Hans.lproj/Localizable.strings | 2 +- 35 files changed, 87 insertions(+), 87 deletions(-) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactLearnMore.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactLearnMore.kt index 44e576198e..3442e8833e 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactLearnMore.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactLearnMore.kt @@ -18,6 +18,6 @@ fun AddContactLearnMore() { AppBarTitle(stringResource(R.string.one_time_link)) ReadableText(R.string.scan_qr_to_connect_to_contact) ReadableText(R.string.if_you_cant_meet_in_person) - ReadableTextWithLink(R.string.read_more_in_user_guide_with_link, "https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/README.md#connect-to-friends") + ReadableTextWithLink(R.string.read_more_in_user_guide_with_link, "https://simplex.chat/docs/guide/readme.html#connect-to-friends") } -} \ No newline at end of file +} diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt index 1e7c8d6b22..72c28e846f 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt @@ -261,7 +261,7 @@ private val versionDescriptions: List = listOf( icon = R.drawable.ic_translate, titleId = R.string.v4_5_italian_interface, descrId = R.string.v4_5_italian_interface_descr, - link = "https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps" + link = "https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat" ) ) ), @@ -297,7 +297,7 @@ private val versionDescriptions: List = listOf( icon = R.drawable.ic_translate, titleId = R.string.v4_6_chinese_spanish_interface, descrId = R.string.v4_6_chinese_spanish_interface_descr, - link = "https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps" + link = "https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat" ) ) ), @@ -318,7 +318,7 @@ private val versionDescriptions: List = listOf( icon = R.drawable.ic_translate, titleId = R.string.v5_0_polish_interface, descrId = R.string.v5_0_polish_interface_descr, - link = "https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps" + link = "https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat" ) ) ) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt index 5e07e6fdba..306b0579ae 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt @@ -266,7 +266,7 @@ private fun HowToButton() { SettingsActionItem( painterResource(R.drawable.ic_open_in_new), stringResource(R.string.how_to_use_your_servers), - { uriHandler.openUriCatching("https://github.com/simplex-chat/simplex-chat/blob/stable/docs/SERVER.md") }, + { uriHandler.openUriCatching("https://simplex.chat/docs/server.html") }, textColor = MaterialTheme.colors.primary, iconColor = MaterialTheme.colors.primary ) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt index 452a084910..a187281e1d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt @@ -197,7 +197,7 @@ private fun howToButton() { val uriHandler = LocalUriHandler.current Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.clickable { uriHandler.openUriCatching("https://github.com/simplex-chat/simplex-chat/blob/stable/docs/WEBRTC.md#configure-mobile-apps") } + modifier = Modifier.clickable { uriHandler.openUriCatching("https://simplex.chat/docs/webrtc.html#configure-mobile-apps") } ) { Text(stringResource(R.string.how_to), color = MaterialTheme.colors.primary) Icon( diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressLearnMore.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressLearnMore.kt index 7a70fcc516..371a14548b 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressLearnMore.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressLearnMore.kt @@ -19,6 +19,6 @@ fun UserAddressLearnMore() { ReadableText(R.string.you_can_share_your_address) ReadableText(R.string.you_wont_lose_your_contacts_if_delete_address) ReadableText(R.string.you_can_accept_or_reject_connection) - ReadableTextWithLink(R.string.read_more_in_user_guide_with_link, "https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address") + ReadableTextWithLink(R.string.read_more_in_user_guide_with_link, "https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address") } -} \ No newline at end of file +} diff --git a/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift b/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift index c746bca825..182149cbde 100644 --- a/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift +++ b/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift @@ -14,7 +14,7 @@ struct AddContactLearnMore: View { VStack(alignment: .leading, spacing: 18) { Text("To connect, your contact can scan QR code or use the link in the app.") Text("If you can't meet in person, show QR code in a video call, or share the link.") - Text("Read more in [User Guide](https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/README.md#connect-to-friends).") + Text("Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).") } .listRowBackground(Color.clear) } diff --git a/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift b/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift index 295258bd24..db79fa03dc 100644 --- a/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift +++ b/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift @@ -126,7 +126,7 @@ private let versionDescriptions: [VersionDescription] = [ FeatureDescription( icon: "character", title: "Italian interface", - description: "Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" + description: "Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" ) ] ), @@ -161,7 +161,7 @@ private let versionDescriptions: [VersionDescription] = [ FeatureDescription( icon: "character", title: "Chinese and Spanish interface", - description: "Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" + description: "Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" ), ] ), @@ -181,7 +181,7 @@ private let versionDescriptions: [VersionDescription] = [ FeatureDescription( icon: "character", title: "Polish interface", - description: "Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" + description: "Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" ), ] ) diff --git a/apps/ios/Shared/Views/UserSettings/ProtocolServersView.swift b/apps/ios/Shared/Views/UserSettings/ProtocolServersView.swift index 2d8eba9014..382eaffbef 100644 --- a/apps/ios/Shared/Views/UserSettings/ProtocolServersView.swift +++ b/apps/ios/Shared/Views/UserSettings/ProtocolServersView.swift @@ -9,7 +9,7 @@ import SwiftUI import SimpleXChat -private let howToUrl = URL(string: "https://github.com/simplex-chat/simplex-chat/blob/stable/docs/SERVER.md")! +private let howToUrl = URL(string: "https://simplex.chat/docs/server.html")! struct ProtocolServersView: View { @Environment(\.dismiss) var dismiss: DismissAction diff --git a/apps/ios/Shared/Views/UserSettings/RTCServers.swift b/apps/ios/Shared/Views/UserSettings/RTCServers.swift index db36babbdb..1b4c65dc2e 100644 --- a/apps/ios/Shared/Views/UserSettings/RTCServers.swift +++ b/apps/ios/Shared/Views/UserSettings/RTCServers.swift @@ -8,7 +8,7 @@ import SwiftUI -private let howToUrl = URL(string: "https://github.com/simplex-chat/simplex-chat/blob/stable/docs/WEBRTC.md#configure-mobile-apps")! +private let howToUrl = URL(string: "https://simplex.chat/docs/webrtc.html#configure-mobile-apps")! let serversFont = Font.custom("Menlo", size: 14) diff --git a/apps/ios/Shared/Views/UserSettings/UserAddressLearnMore.swift b/apps/ios/Shared/Views/UserSettings/UserAddressLearnMore.swift index e944dcec95..15f6a1c7d7 100644 --- a/apps/ios/Shared/Views/UserSettings/UserAddressLearnMore.swift +++ b/apps/ios/Shared/Views/UserSettings/UserAddressLearnMore.swift @@ -15,7 +15,7 @@ struct UserAddressLearnMore: View { Text("You can share your address as a link or QR code - anybody can connect to you.") Text("You won't lose your contacts if you later delete your address.") Text("When people request to connect, you can accept or reject it.") - Text("Read more in [User Guide](https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address).") + Text("Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).") } .listRowBackground(Color.clear) } diff --git a/apps/ios/SimpleX Localizations/ar.xcloc/Localized Contents/ar.xliff b/apps/ios/SimpleX Localizations/ar.xcloc/Localized Contents/ar.xliff index 678d25b4b4..dbbb37fdc9 100644 --- a/apps/ios/SimpleX Localizations/ar.xcloc/Localized Contents/ar.xliff +++ b/apps/ios/SimpleX Localizations/ar.xcloc/Localized Contents/ar.xliff @@ -2573,8 +2573,8 @@ We will be adding server redundancy to prevent lost messages. Thank you for installing SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. 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 0980517f78..5ade7df926 100644 --- a/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff +++ b/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff @@ -2354,8 +2354,8 @@ Dostupné ve verzi 5.1 Velký soubor! No comment provided by engineer. - - Read more in [User Guide](https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address). + + Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). No comment provided by engineer. @@ -3778,9 +3778,9 @@ Dostupné ve verzi 5.1 Děkujeme, že jste si nainstalovali SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! - Díky uživatelům - [přispějte přes Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! + Díky uživatelům - [přispějte přes Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. 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 68ccbbb7a3..1a0d17824f 100644 --- a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff +++ b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff @@ -2354,8 +2354,8 @@ Verfügbar ab v5.1 Große Datei! No comment provided by engineer. - - Read more in [User Guide](https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address). + + Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). No comment provided by engineer. @@ -3778,9 +3778,9 @@ Verfügbar ab v5.1 Vielen Dank, dass Sie SimpleX Chat installiert haben! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! - Dank der Nutzer - [Tragen Sie per Weblate bei](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! + Dank der Nutzer - [Tragen Sie per Weblate bei](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. 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 d7c662591e..d77a6af73a 100644 --- a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff +++ b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff @@ -2363,9 +2363,9 @@ Available in v5.1 Large file! No comment provided by engineer. - - Read more in [User Guide](https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address). - Read more in [User Guide](https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address). + + Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). + Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). No comment provided by engineer. @@ -3797,9 +3797,9 @@ Available in v5.1 Thank you for installing SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. 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 148a814c74..021c4dff0e 100644 --- a/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff +++ b/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff @@ -2354,8 +2354,8 @@ Disponible en v5.1 ¡Archivo grande! No comment provided by engineer. - - Read more in [User Guide](https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address). + + Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). No comment provided by engineer. @@ -3778,8 +3778,8 @@ Disponible en v5.1 ¡Gracias por instalar SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! Gracias a los usuarios: [contribuye vía Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#traducir-el-aplicaciones)! No comment provided by engineer. 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 c82a08c4be..cf72da51a0 100644 --- a/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff +++ b/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff @@ -2640,8 +2640,8 @@ We will be adding server redundancy to prevent lost messages. Thank you for installing SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. 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 a5c44c9ff4..b325d578f9 100644 --- a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff +++ b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff @@ -2354,8 +2354,8 @@ Disponible dans la v5.1 Fichier trop lourd ! No comment provided by engineer. - - Read more in [User Guide](https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address). + + Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). No comment provided by engineer. @@ -3778,9 +3778,9 @@ Disponible dans la v5.1 Merci d'avoir installé SimpleX Chat ! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! - Merci aux utilisateurs - [contribuer via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps) ! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! + Merci aux utilisateurs - [contribuer via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat) ! No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/hr.xcloc/Localized Contents/hr.xliff b/apps/ios/SimpleX Localizations/hr.xcloc/Localized Contents/hr.xliff index 3ac706832f..32ffae38d7 100644 --- a/apps/ios/SimpleX Localizations/hr.xcloc/Localized Contents/hr.xliff +++ b/apps/ios/SimpleX Localizations/hr.xcloc/Localized Contents/hr.xliff @@ -2569,8 +2569,8 @@ We will be adding server redundancy to prevent lost messages. Thank you for installing SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. 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 bb549d4e9f..f030f17103 100644 --- a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff +++ b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff @@ -2354,8 +2354,8 @@ Disponibile nella v5.1 File grande! No comment provided by engineer. - - Read more in [User Guide](https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address). + + Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). No comment provided by engineer. @@ -3778,9 +3778,9 @@ Disponibile nella v5.1 Grazie per aver installato SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! - Grazie agli utenti – [contribuite via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! + Grazie agli utenti – [contribuite via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/ko.xcloc/Localized Contents/ko.xliff b/apps/ios/SimpleX Localizations/ko.xcloc/Localized Contents/ko.xliff index a6c13e55a8..2f4a9ed664 100644 --- a/apps/ios/SimpleX Localizations/ko.xcloc/Localized Contents/ko.xliff +++ b/apps/ios/SimpleX Localizations/ko.xcloc/Localized Contents/ko.xliff @@ -2645,8 +2645,8 @@ We will be adding server redundancy to prevent lost messages. Thank you for installing SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/lt.xcloc/Localized Contents/lt.xliff b/apps/ios/SimpleX Localizations/lt.xcloc/Localized Contents/lt.xliff index 184800bb1f..1e8e628d2d 100644 --- a/apps/ios/SimpleX Localizations/lt.xcloc/Localized Contents/lt.xliff +++ b/apps/ios/SimpleX Localizations/lt.xcloc/Localized Contents/lt.xliff @@ -2583,8 +2583,8 @@ We will be adding server redundancy to prevent lost messages. Thank you for installing SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. 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 ff753124e3..1125b8cb54 100644 --- a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff +++ b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff @@ -2354,8 +2354,8 @@ Beschikbaar in v5.1 Groot bestand! No comment provided by engineer. - - Read more in [User Guide](https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address). + + Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). No comment provided by engineer. @@ -3778,9 +3778,9 @@ Beschikbaar in v5.1 Bedankt voor het installeren van SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! - Dank aan de gebruikers - [draag bij via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! + Dank aan de gebruikers - [draag bij via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. 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 3e71f25887..682a41bc8a 100644 --- a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff +++ b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff @@ -2354,8 +2354,8 @@ Dostępny w v5.1 Duży plik! No comment provided by engineer. - - Read more in [User Guide](https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address). + + Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). No comment provided by engineer. @@ -3778,9 +3778,9 @@ Dostępny w v5.1 Dziękujemy za zainstalowanie SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! - Podziękowania dla użytkowników - [wkład za pośrednictwem Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! + Podziękowania dla użytkowników - [wkład za pośrednictwem Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. 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 a0e4c600b1..20b78346a8 100644 --- a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff +++ b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff @@ -2354,8 +2354,8 @@ Available in v5.1 Большой файл! No comment provided by engineer. - - Read more in [User Guide](https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address). + + Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). No comment provided by engineer. @@ -3778,9 +3778,9 @@ Available in v5.1 Спасибо, что установили SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! - Благодаря пользователям – [добавьте переводы через Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! + Благодаря пользователям – [добавьте переводы через Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. 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 81f326f766..d7ffea7d5a 100644 --- a/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff +++ b/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff @@ -2530,8 +2530,8 @@ We will be adding server redundancy to prevent lost messages. Thank you for installing SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. 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 1a525f62b6..b20c497ddd 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 @@ -2354,8 +2354,8 @@ Available in v5.1 大文件! No comment provided by engineer. - - Read more in [User Guide](https://github.com/simplex-chat/simplex-chat/blob/stable/docs/guide/app-settings.md#your-simplex-contact-address). + + Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). No comment provided by engineer. @@ -3778,9 +3778,9 @@ Available in v5.1 感谢您安装 SimpleX Chat! No comment provided by engineer. - - Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! - 感谢用户——[通过 Weblate 贡献](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)! + + Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! + 感谢用户——[通过 Weblate 贡献](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. diff --git a/apps/ios/cs.lproj/Localizable.strings b/apps/ios/cs.lproj/Localizable.strings index 9b15e546ef..86a01dfe95 100644 --- a/apps/ios/cs.lproj/Localizable.strings +++ b/apps/ios/cs.lproj/Localizable.strings @@ -2521,7 +2521,7 @@ "Thank you for installing SimpleX Chat!" = "Děkujeme, že jste si nainstalovali SimpleX Chat!"; /* No comment provided by engineer. */ -"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" = "Díky uživatelům - [přispějte přes Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!"; +"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "Díky uživatelům - [přispějte přes Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"; /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "Díky uživatelům - přispívejte prostřednictvím Weblate!"; diff --git a/apps/ios/de.lproj/Localizable.strings b/apps/ios/de.lproj/Localizable.strings index debc4b7289..3406425085 100644 --- a/apps/ios/de.lproj/Localizable.strings +++ b/apps/ios/de.lproj/Localizable.strings @@ -2521,7 +2521,7 @@ "Thank you for installing SimpleX Chat!" = "Vielen Dank, dass Sie SimpleX Chat installiert haben!"; /* No comment provided by engineer. */ -"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" = "Dank der Nutzer - [Tragen Sie per Weblate bei](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!"; +"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "Dank der Nutzer - [Tragen Sie per Weblate bei](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"; /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "Dank der Nutzer - Tragen Sie per Weblate bei!"; diff --git a/apps/ios/es.lproj/Localizable.strings b/apps/ios/es.lproj/Localizable.strings index de36d91914..f4176bc3df 100644 --- a/apps/ios/es.lproj/Localizable.strings +++ b/apps/ios/es.lproj/Localizable.strings @@ -2521,7 +2521,7 @@ "Thank you for installing SimpleX Chat!" = "¡Gracias por instalar SimpleX Chat!"; /* No comment provided by engineer. */ -"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" = "Gracias a los usuarios: [contribuye vía Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#traducir-el-aplicaciones)!"; +"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "Gracias a los usuarios: [contribuye vía Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#traducir-el-aplicaciones)!"; /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "Agradecimientos a los usuarios. ¡Contribuye a través de Weblate!"; diff --git a/apps/ios/fr.lproj/Localizable.strings b/apps/ios/fr.lproj/Localizable.strings index ba6104a895..700cd6a453 100644 --- a/apps/ios/fr.lproj/Localizable.strings +++ b/apps/ios/fr.lproj/Localizable.strings @@ -2521,7 +2521,7 @@ "Thank you for installing SimpleX Chat!" = "Merci d'avoir installé SimpleX Chat !"; /* No comment provided by engineer. */ -"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" = "Merci aux utilisateurs - [contribuer via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps) !"; +"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "Merci aux utilisateurs - [contribuer via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat) !"; /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "Merci aux utilisateurs - contribuez via Weblate !"; diff --git a/apps/ios/it.lproj/Localizable.strings b/apps/ios/it.lproj/Localizable.strings index c5f0f45cb5..afb6d4b33f 100644 --- a/apps/ios/it.lproj/Localizable.strings +++ b/apps/ios/it.lproj/Localizable.strings @@ -2521,7 +2521,7 @@ "Thank you for installing SimpleX Chat!" = "Grazie per aver installato SimpleX Chat!"; /* No comment provided by engineer. */ -"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" = "Grazie agli utenti – [contribuite via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!"; +"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "Grazie agli utenti – [contribuite via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"; /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "Grazie agli utenti – contribuite via Weblate!"; diff --git a/apps/ios/nl.lproj/Localizable.strings b/apps/ios/nl.lproj/Localizable.strings index e001c25e97..401fb25e7b 100644 --- a/apps/ios/nl.lproj/Localizable.strings +++ b/apps/ios/nl.lproj/Localizable.strings @@ -2521,7 +2521,7 @@ "Thank you for installing SimpleX Chat!" = "Bedankt voor het installeren van SimpleX Chat!"; /* No comment provided by engineer. */ -"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" = "Dank aan de gebruikers - [draag bij via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!"; +"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "Dank aan de gebruikers - [draag bij via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"; /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "Dank aan de gebruikers – draag bij via Weblate!"; diff --git a/apps/ios/pl.lproj/Localizable.strings b/apps/ios/pl.lproj/Localizable.strings index 1aab827e0d..8e51f0b918 100644 --- a/apps/ios/pl.lproj/Localizable.strings +++ b/apps/ios/pl.lproj/Localizable.strings @@ -2521,7 +2521,7 @@ "Thank you for installing SimpleX Chat!" = "Dziękujemy za zainstalowanie SimpleX Chat!"; /* No comment provided by engineer. */ -"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" = "Podziękowania dla użytkowników - [wkład za pośrednictwem Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!"; +"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "Podziękowania dla użytkowników - [wkład za pośrednictwem Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"; /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "Podziękowania dla użytkowników - wkład za pośrednictwem Weblate!"; diff --git a/apps/ios/ru.lproj/Localizable.strings b/apps/ios/ru.lproj/Localizable.strings index ca6a91282d..f48566e529 100644 --- a/apps/ios/ru.lproj/Localizable.strings +++ b/apps/ios/ru.lproj/Localizable.strings @@ -2521,7 +2521,7 @@ "Thank you for installing SimpleX Chat!" = "Спасибо, что установили SimpleX Chat!"; /* No comment provided by engineer. */ -"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" = "Благодаря пользователям – [добавьте переводы через Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!"; +"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "Благодаря пользователям – [добавьте переводы через Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"; /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "Благодаря пользователям – добавьте переводы через Weblate!"; diff --git a/apps/ios/zh-Hans.lproj/Localizable.strings b/apps/ios/zh-Hans.lproj/Localizable.strings index 0f01bab9d1..d1cf175647 100644 --- a/apps/ios/zh-Hans.lproj/Localizable.strings +++ b/apps/ios/zh-Hans.lproj/Localizable.strings @@ -2521,7 +2521,7 @@ "Thank you for installing SimpleX Chat!" = "感谢您安装 SimpleX Chat!"; /* No comment provided by engineer. */ -"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" = "感谢用户——[通过 Weblate 贡献](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!"; +"Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" = "感谢用户——[通过 Weblate 贡献](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"; /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "感谢用户——通过 Weblate 做出贡献!";