diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift
index 53bb7db2d6..3ecfa70793 100644
--- a/apps/ios/Shared/Model/SimpleXAPI.swift
+++ b/apps/ios/Shared/Model/SimpleXAPI.swift
@@ -618,6 +618,16 @@ func apiUpdateProfile(profile: Profile) async throws -> Profile? {
}
}
+func apiSetProfileAddress(on: Bool) async throws -> User? {
+ let userId = try currentUserId("apiSetProfileAddress")
+ let r = await chatSendCmd(.apiSetProfileAddress(userId: userId, on: on))
+ switch r {
+ case .userProfileNoChange: return nil
+ case let .userProfileUpdated(user, _, _): return user
+ default: throw r
+ }
+}
+
func apiSetContactPrefs(contactId: Int64, preferences: Preferences) async throws -> Contact? {
let r = await chatSendCmd(.apiSetContactPrefs(contactId: contactId, preferences: preferences))
if case let .contactPrefsUpdated(_, _, toContact) = r { return toContact }
@@ -643,10 +653,10 @@ func apiCreateUserAddress() async throws -> String {
throw r
}
-func apiDeleteUserAddress() async throws {
+func apiDeleteUserAddress() async throws -> User? {
let userId = try currentUserId("apiDeleteUserAddress")
let r = await chatSendCmd(.apiDeleteMyAddress(userId: userId))
- if case .userContactLinkDeleted = r { return }
+ if case let .userContactLinkDeleted(user) = r { return user }
throw r
}
diff --git a/apps/ios/Shared/Views/Chat/ChatInfoView.swift b/apps/ios/Shared/Views/Chat/ChatInfoView.swift
index 5cab211e89..b72006b3fe 100644
--- a/apps/ios/Shared/Views/Chat/ChatInfoView.swift
+++ b/apps/ios/Shared/Views/Chat/ChatInfoView.swift
@@ -116,6 +116,21 @@ struct ChatInfoView: View {
contactPreferencesButton()
}
+ if let contactLink = contact.contactLink {
+ Section {
+ QRCode(uri: contactLink)
+ Button {
+ showShareSheet(items: [contactLink])
+ } label: {
+ Label("Share address", systemImage: "square.and.arrow.up")
+ }
+ } header: {
+ Text("Address")
+ } footer: {
+ Text("You can share this address with your contacts to let them connect with **\(contact.displayName)**.")
+ }
+ }
+
Section("Servers") {
networkStatusRow()
.onTapGesture {
diff --git a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift
index ed8dfd9221..efbb3c1320 100644
--- a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift
+++ b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift
@@ -45,8 +45,8 @@ struct GroupChatInfoView: View {
Section {
if groupInfo.canEdit {
editGroupButton()
- addOrEditWelcomeMessage()
}
+ addOrEditWelcomeMessage()
groupPreferencesButton($groupInfo)
} header: {
Text("")
diff --git a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift
index 9f367fb472..dd13741141 100644
--- a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift
+++ b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift
@@ -65,6 +65,21 @@ struct GroupMemberInfoView: View {
}
}
+ if let contactLink = member.contactLink {
+ Section {
+ QRCode(uri: contactLink)
+ Button {
+ showShareSheet(items: [contactLink])
+ } label: {
+ Label("Share address", systemImage: "square.and.arrow.up")
+ }
+ } header: {
+ Text("Address")
+ } footer: {
+ Text("You can share this address with your contacts to let them connect with **\(member.displayName)**.")
+ }
+ }
+
Section("Member") {
infoRow("Group", groupInfo.displayName)
diff --git a/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift b/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift
index 7aa372d5dc..7b90a4abe7 100644
--- a/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift
+++ b/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift
@@ -15,43 +15,101 @@ struct GroupWelcomeView: View {
var groupId: Int64
@Binding var groupInfo: GroupInfo
@State private var welcomeText: String = ""
+ @State private var editMode = true
@FocusState private var keyboardVisible: Bool
@State private var showSaveDialog = false
var body: some View {
- List {
- Section {
- TextEditor(text: $welcomeText)
- .focused($keyboardVisible)
- .padding(.horizontal, -5)
- .padding(.top, -8)
- .frame(height: 90, alignment: .topLeading)
- .frame(maxWidth: .infinity, alignment: .leading)
- }
- Section {
- saveButton()
+ VStack {
+ if groupInfo.canEdit {
+ editorView()
+ .modifier(BackButton {
+ if welcomeText == groupInfo.groupProfile.description || (welcomeText == "" && groupInfo.groupProfile.description == nil) {
+ dismiss()
+ } else {
+ showSaveDialog = true
+ }
+ })
+ .confirmationDialog("Save welcome message?", isPresented: $showSaveDialog) {
+ Button("Save and update group profile") {
+ save()
+ dismiss()
+ }
+ Button("Exit without saving") { dismiss() }
+ }
+ } else {
+ List {
+ Section {
+ textPreview()
+ copyButton()
+ }
+ }
}
}
.onAppear {
welcomeText = groupInfo.groupProfile.description ?? ""
- }
- .modifier(BackButton {
- if welcomeText == groupInfo.groupProfile.description || (welcomeText == "" && groupInfo.groupProfile.description == nil) {
- dismiss()
- } else {
- showSaveDialog = true
- }
- })
- .confirmationDialog("Save welcome message?", isPresented: $showSaveDialog) {
- Button("Save and update group profile") {
- save()
- dismiss()
- }
- Button("Exit without saving") { dismiss() }
+ keyboardVisible = true
}
}
- @ViewBuilder private func saveButton() -> some View {
+ private func textPreview() -> some View {
+ messageText(welcomeText, parseSimpleXMarkdown(welcomeText), nil)
+ .allowsHitTesting(false)
+ }
+
+ private func editorView() -> some View {
+ List {
+ Section {
+ if editMode {
+ ZStack {
+ Group {
+ if welcomeText.isEmpty {
+ TextEditor(text: Binding.constant(NSLocalizedString("Enter welcome message…", comment: "placeholder")))
+ .foregroundColor(.secondary)
+ .disabled(true)
+ }
+ TextEditor(text: $welcomeText)
+ .focused($keyboardVisible)
+ }
+ .padding(.horizontal, -5)
+ .padding(.top, -8)
+ .frame(height: 90, alignment: .topLeading)
+ .frame(maxWidth: .infinity, alignment: .leading)
+ }
+ } else {
+ textPreview()
+ .frame(height: 90, alignment: .topLeading)
+ }
+
+ Button {
+ editMode = !editMode
+ keyboardVisible = editMode
+ } label: {
+ if editMode {
+ Label ("Preview", systemImage: "character")
+ } else {
+ Label ("Edit", systemImage: "pencil")
+ }
+ }
+ .disabled(welcomeText.isEmpty)
+ copyButton()
+ }
+
+ Section {
+ saveButton()
+ }
+ }
+ }
+
+ private func copyButton() -> some View {
+ Button {
+ UIPasteboard.general.string = welcomeText
+ } label: {
+ Label ("Copy", systemImage: "doc.on.doc")
+ }
+ }
+
+ private func saveButton() -> some View {
Button("Save and update group profile") {
save()
}
diff --git a/apps/ios/Shared/Views/ChatList/ContactConnectionInfo.swift b/apps/ios/Shared/Views/ChatList/ContactConnectionInfo.swift
index 72be57b3f7..7d850719d6 100644
--- a/apps/ios/Shared/Views/ChatList/ContactConnectionInfo.swift
+++ b/apps/ios/Shared/Views/ChatList/ContactConnectionInfo.swift
@@ -39,6 +39,11 @@ struct ContactConnectionInfo: View {
.padding(.bottom, 16)
Text(contactConnectionText(contactConnection))
+ .padding(.bottom, 16)
+
+ if let connReqInv = contactConnection.connReqInv {
+ OneTimeLinkProfileText(contactConnection: contactConnection, connReqInvitation: connReqInv)
+ }
}
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
@@ -47,11 +52,7 @@ struct ContactConnectionInfo: View {
Section {
if contactConnection.groupLinkId == nil {
- HStack(spacing: 20) {
- Image(systemName: "pencil")
- .foregroundColor(.secondary)
- .padding(.leading, 6)
- .onTapGesture { aliasTextFieldFocused = true }
+ settingsRow("pencil") {
TextField("Set contact name…", text: $localAlias)
.autocapitalization(.none)
.autocorrectionDisabled(true)
@@ -59,20 +60,18 @@ struct ContactConnectionInfo: View {
.submitLabel(.done)
.onSubmit(setConnectionAlias)
}
+ .onTapGesture { aliasTextFieldFocused = true }
}
if contactConnection.initiated,
let connReqInv = contactConnection.connReqInv {
- NavigationLink {
- AddContactView(contactConnection: contactConnection, connReqInvitation: connReqInv)
- .navigationTitle(CreateLinkTab.oneTime.title)
- .navigationBarTitleDisplayMode(.large)
- } label: {
- Label("Show QR code", systemImage: "qrcode")
- .foregroundColor(contactConnection.incognito ? .indigo : .accentColor)
- }
+ oneTimeLinkSection(contactConnection: contactConnection, connReqInvitation: connReqInv)
+ } else {
+ oneTimeLinkLearnMoreButton()
}
+ }
+ Section {
Button(role: .destructive) {
alert = .deleteInvitationAlert
} label: {
@@ -81,7 +80,6 @@ struct ContactConnectionInfo: View {
}
}
}
- .listStyle(.insetGrouped)
}
.alert(item: $alert) { _alert in
switch _alert {
@@ -96,7 +94,6 @@ struct ContactConnectionInfo: View {
}
.onAppear {
localAlias = contactConnection.localAlias
- aliasTextFieldFocused = true
}
}
diff --git a/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift b/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift
new file mode 100644
index 0000000000..c746bca825
--- /dev/null
+++ b/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift
@@ -0,0 +1,28 @@
+//
+// AddContactLearnMore.swift
+// SimpleX (iOS)
+//
+// Created by spaced4ndy on 27.04.2023.
+// Copyright © 2023 SimpleX Chat. All rights reserved.
+//
+
+import SwiftUI
+
+struct AddContactLearnMore: View {
+ var body: some View {
+ List {
+ 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).")
+ }
+ .listRowBackground(Color.clear)
+ }
+ }
+}
+
+struct AddContactLearnMore_Previews: PreviewProvider {
+ static var previews: some View {
+ AddContactLearnMore()
+ }
+}
diff --git a/apps/ios/Shared/Views/NewChat/AddContactView.swift b/apps/ios/Shared/Views/NewChat/AddContactView.swift
index fb3011de51..44de3c4987 100644
--- a/apps/ios/Shared/Views/NewChat/AddContactView.swift
+++ b/apps/ios/Shared/Views/NewChat/AddContactView.swift
@@ -16,50 +16,73 @@ struct AddContactView: View {
var connReqInvitation: String
var body: some View {
- ScrollView {
- VStack(alignment: .leading) {
- Text("Your contact can scan it from the app.")
- .padding(.bottom, 4)
- if (contactConnection?.incognito ?? chatModel.incognito) {
- HStack {
- Image(systemName: "theatermasks").foregroundColor(.indigo).font(.footnote)
- Spacer().frame(width: 8)
- Text("A random profile will be sent to your contact").font(.footnote)
- }
- .padding(.bottom)
- } else {
- HStack {
- Image(systemName: "info.circle").foregroundColor(.secondary).font(.footnote)
- Spacer().frame(width: 8)
- Text("Your chat profile will be sent to your contact").font(.footnote)
- }
- .padding(.bottom)
- }
- if connReqInvitation != "" {
- QRCode(uri: connReqInvitation).padding(.bottom)
- } else {
- ProgressView()
- .progressViewStyle(.circular)
- .scaleEffect(2)
- .frame(maxWidth: .infinity)
- .padding(.vertical)
- }
- Text("If you can't meet in person, **show QR code in the video call**, or share the link.")
- .padding(.bottom)
- Button {
- showShareSheet(items: [connReqInvitation])
- } label: {
- Label("Share invitation link", systemImage: "square.and.arrow.up")
- }
- .frame(maxWidth: .infinity, alignment: .center)
+ List {
+ OneTimeLinkProfileText(contactConnection: contactConnection, connReqInvitation: connReqInvitation)
+ .listRowBackground(Color.clear)
+ .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
+
+ Section("1-time link") {
+ oneTimeLinkSection(contactConnection: contactConnection, connReqInvitation: connReqInvitation)
}
- .padding()
- .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
}
.onAppear { chatModel.connReqInv = connReqInvitation }
}
}
+@ViewBuilder func oneTimeLinkSection(contactConnection: PendingContactConnection? = nil, connReqInvitation: String) -> some View {
+ if connReqInvitation != "" {
+ QRCode(uri: connReqInvitation)
+ } else {
+ ProgressView()
+ .progressViewStyle(.circular)
+ .scaleEffect(2)
+ .frame(maxWidth: .infinity)
+ .padding(.vertical)
+ }
+ shareLinkButton(connReqInvitation)
+ oneTimeLinkLearnMoreButton()
+}
+
+private func shareLinkButton(_ connReqInvitation: String) -> some View {
+ Button {
+ showShareSheet(items: [connReqInvitation])
+ } label: {
+ settingsRow("square.and.arrow.up") {
+ Text("Share 1-time link")
+ }
+ }
+}
+
+func oneTimeLinkLearnMoreButton() -> some View {
+ NavigationLink {
+ AddContactLearnMore()
+ .navigationTitle("One-time invitation link")
+ .navigationBarTitleDisplayMode(.large)
+ } label: {
+ settingsRow("info.circle") {
+ Text("Learn more")
+ }
+ }
+}
+
+struct OneTimeLinkProfileText: View {
+ @EnvironmentObject private var chatModel: ChatModel
+ var contactConnection: PendingContactConnection? = nil
+ var connReqInvitation: String
+
+ var body: some View {
+ HStack {
+ if (contactConnection?.incognito ?? chatModel.incognito) {
+ Image(systemName: "theatermasks").foregroundColor(.indigo)
+ Text("A random profile will be sent to your contact")
+ } else {
+ Image(systemName: "info.circle").foregroundColor(.secondary)
+ Text("Your chat profile will be sent to your contact")
+ }
+ }
+ }
+}
+
struct AddContactView_Previews: PreviewProvider {
static var previews: some View {
AddContactView(connReqInvitation: "https://simplex.chat/invitation#/?v=1&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FFe5ICmvrm4wkrr6X1LTMii-lhBqLeB76%23MCowBQYDK2VuAyEAdhZZsHpuaAk3Hh1q0uNb_6hGTpuwBIrsp2z9U2T0oC0%3D&e2e=v%3D1%26x3dh%3DMEIwBQYDK2VvAzkAcz6jJk71InuxA0bOX7OUhddfB8Ov7xwQIlIDeXBRZaOntUU4brU5Y3rBzroZBdQJi0FKdtt_D7I%3D%2CMEIwBQYDK2VvAzkA-hDvk1duBi1hlOr08VWSI-Ou4JNNSQjseY69QyKm7Kgg1zZjbpGfyBqSZ2eqys6xtoV4ZtoQUXQ%3D")
diff --git a/apps/ios/Shared/Views/NewChat/CreateLinkView.swift b/apps/ios/Shared/Views/NewChat/CreateLinkView.swift
index 4504361bd7..71daf88a8c 100644
--- a/apps/ios/Shared/Views/NewChat/CreateLinkView.swift
+++ b/apps/ios/Shared/Views/NewChat/CreateLinkView.swift
@@ -15,7 +15,7 @@ enum CreateLinkTab {
var title: LocalizedStringKey {
switch self {
case .oneTime: return "One-time invitation link"
- case .longTerm: return "Your contact address"
+ case .longTerm: return "Your SimpleX address"
}
}
}
@@ -49,9 +49,9 @@ struct CreateLinkView: View {
)
}
.tag(CreateLinkTab.oneTime)
- UserAddress()
+ UserAddressView(viaCreateLinkView: true)
.tabItem {
- Label("Your contact address", systemImage: "infinity.circle")
+ Label("Your SimpleX address", systemImage: "infinity.circle")
}
.tag(CreateLinkTab.longTerm)
}
diff --git a/apps/ios/Shared/Views/UserSettings/AcceptRequestsView.swift b/apps/ios/Shared/Views/UserSettings/AcceptRequestsView.swift
deleted file mode 100644
index 0e61658c93..0000000000
--- a/apps/ios/Shared/Views/UserSettings/AcceptRequestsView.swift
+++ /dev/null
@@ -1,131 +0,0 @@
-//
-// AcceptRequestsView.swift
-// SimpleX (iOS)
-//
-// Created by Evgeny on 23/10/2022.
-// Copyright © 2022 SimpleX Chat. All rights reserved.
-//
-
-import SwiftUI
-import SimpleXChat
-
-struct AcceptRequestsView: View {
- @EnvironmentObject private var m: ChatModel
- @State var contactLink: UserContactLink
- @State private var a = AutoAcceptState()
- @State private var saved = AutoAcceptState()
- @FocusState private var keyboardVisible: Bool
-
- var body: some View {
- List {
- Section {
- settingsRow("checkmark") {
- Toggle("Automatically", isOn: $a.enable)
- }
- if a.enable {
- settingsRow(
- a.incognito ? "theatermasks.fill" : "theatermasks",
- color: a.incognito ? .indigo : .secondary
- ) {
- Toggle("Incognito", isOn: $a.incognito)
- }
- }
- } header: {
- Text("Accept requests")
- } footer: {
- saveButtons()
- }
- if a.enable {
- Section {
- TextEditor(text: $a.welcomeText)
- .focused($keyboardVisible)
- .padding(.horizontal, -5)
- .padding(.top, -8)
- .frame(height: 90, alignment: .topLeading)
- .frame(maxWidth: .infinity, alignment: .leading)
- } header: {
- Text("Welcome message")
- }
- }
- }
- .onAppear {
- a = AutoAcceptState(contactLink: contactLink)
- saved = a
- }
- .onChange(of: a.enable) { _ in
- if !a.enable { a = AutoAcceptState() }
- }
- }
-
- @ViewBuilder private func saveButtons() -> some View {
- HStack {
- Button {
- a = saved
- } label: {
- Label("Cancel", systemImage: "arrow.counterclockwise")
- }
- Spacer()
- Button {
- Task {
- do {
- if let link = try await userAddressAutoAccept(a.autoAccept) {
- contactLink = link
- m.userAddress = link
- saved = a
- }
- } catch let error {
- logger.error("userAddressAutoAccept error: \(responseError(error))")
- }
- }
- } label: {
- Label("Save", systemImage: "checkmark")
- }
- }
- .font(.body)
- .disabled(a == saved)
- }
-
- private struct AutoAcceptState: Equatable {
- var enable = false
- var incognito = false
- var welcomeText = ""
-
- init(enable: Bool = false, incognito: Bool = false, welcomeText: String = "") {
- self.enable = enable
- self.incognito = incognito
- self.welcomeText = welcomeText
- }
-
- init(contactLink: UserContactLink) {
- if let aa = contactLink.autoAccept {
- enable = true
- incognito = aa.acceptIncognito
- if let msg = aa.autoReply {
- welcomeText = msg.text
- } else {
- welcomeText = ""
- }
- } else {
- enable = false
- incognito = false
- welcomeText = ""
- }
- }
-
- var autoAccept: AutoAccept? {
- if enable {
- var autoReply: MsgContent? = nil
- let s = welcomeText.trimmingCharacters(in: .whitespacesAndNewlines)
- if s != "" { autoReply = .text(s) }
- return AutoAccept(acceptIncognito: incognito, autoReply: autoReply)
- }
- return nil
- }
- }
-}
-
-struct AcceptRequestsView_Previews: PreviewProvider {
- static var previews: some View {
- AcceptRequestsView(contactLink: UserContactLink(connReqContact: ""))
- }
-}
diff --git a/apps/ios/Shared/Views/UserSettings/SettingsView.swift b/apps/ios/Shared/Views/UserSettings/SettingsView.swift
index d25ea45f49..4f8bb4f503 100644
--- a/apps/ios/Shared/Views/UserSettings/SettingsView.swift
+++ b/apps/ios/Shared/Views/UserSettings/SettingsView.swift
@@ -147,10 +147,11 @@ struct SettingsView: View {
incognitoRow()
NavigationLink {
- CreateLinkView(selection: .longTerm, viaNavLink: true)
- .navigationBarTitleDisplayMode(.inline)
+ UserAddressView(shareViaProfile: chatModel.currentUser!.addressShared)
+ .navigationTitle("SimpleX address")
+ .navigationBarTitleDisplayMode(.large)
} label: {
- settingsRow("qrcode") { Text("Your SimpleX contact address") }
+ settingsRow("qrcode") { Text("Your SimpleX address") }
}
NavigationLink {
diff --git a/apps/ios/Shared/Views/UserSettings/UserAddress.swift b/apps/ios/Shared/Views/UserSettings/UserAddress.swift
deleted file mode 100644
index 7564bea358..0000000000
--- a/apps/ios/Shared/Views/UserSettings/UserAddress.swift
+++ /dev/null
@@ -1,128 +0,0 @@
-//
-// UserAddress.swift
-// SimpleX
-//
-// Created by Evgeny Poberezkin on 31/01/2022.
-// Copyright © 2022 SimpleX Chat. All rights reserved.
-//
-
-import SwiftUI
-import SimpleXChat
-
-struct UserAddress: View {
- @EnvironmentObject private var chatModel: ChatModel
- @State private var alert: UserAddressAlert?
- @State private var showAcceptRequests = false
-
- private enum UserAddressAlert: Identifiable {
- case deleteAddress
- case error(title: LocalizedStringKey, error: LocalizedStringKey = "")
-
- var id: String {
- switch self {
- case .deleteAddress: return "deleteAddress"
- case let .error(title, _): return "error \(title)"
- }
- }
- }
-
- var body: some View {
- ScrollView {
- VStack (alignment: .leading) {
- Text("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.")
- .padding(.bottom)
- if let userAdress = chatModel.userAddress {
- QRCode(uri: userAdress.connReqContact)
- HStack {
- Button {
- showShareSheet(items: [userAdress.connReqContact])
- } label: {
- HStack {
- Image(systemName: "square.and.arrow.up")
- Text("Share link")
- }
- }
- .padding()
- NavigationLink {
- if let contactLink = chatModel.userAddress {
- AcceptRequestsView(contactLink: contactLink)
- .navigationTitle("Contact requests")
- .navigationBarTitleDisplayMode(.large)
- }
- } label: {
- HStack {
- Text("Contact requests")
- Image(systemName: "chevron.right")
- }
- }
- .padding()
- }
- .frame(maxWidth: .infinity)
- Button(role: .destructive) { alert = .deleteAddress } label: {
- Label("Delete address", systemImage: "trash")
- }
- .frame(maxWidth: .infinity)
- } else {
- Button {
- Task {
- do {
- let connReqContact = try await apiCreateUserAddress()
- DispatchQueue.main.async {
- chatModel.userAddress = UserContactLink(connReqContact: connReqContact)
- }
- } catch let error {
- logger.error("UserAddress apiCreateUserAddress: \(responseError(error))")
- let a = getErrorAlert(error, "Error creating address")
- alert = .error(title: a.title, error: a.message)
- }
- }
- } label: { Label("Create address", systemImage: "qrcode") }
- .frame(maxWidth: .infinity)
- }
- }
- .padding()
- .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
- .sheet(isPresented: $showAcceptRequests) {
- if let contactLink = chatModel.userAddress {
- AcceptRequestsView(contactLink: contactLink)
- }
- }
- .alert(item: $alert) { alert in
- switch alert {
- case .deleteAddress:
- return Alert(
- title: Text("Delete address?"),
- message: Text("All your contacts will remain connected"),
- primaryButton: .destructive(Text("Delete")) {
- Task {
- do {
- try await apiDeleteUserAddress()
- DispatchQueue.main.async {
- chatModel.userAddress = nil
- }
- } catch let error {
- logger.error("UserAddress apiDeleteUserAddress: \(responseError(error))")
- }
- }
- }, secondaryButton: .cancel()
- )
- case let .error(title, error):
- return Alert(title: Text(title), message: Text(error))
- }
- }
- }
- }
-}
-
-struct UserAddress_Previews: PreviewProvider {
- static var previews: some View {
- let chatModel = ChatModel()
- chatModel.userAddress = UserContactLink(connReqContact: "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D")
- return Group {
- UserAddress()
- .environmentObject(chatModel)
- UserAddress()
- .environmentObject(ChatModel())
- }
- }
-}
diff --git a/apps/ios/Shared/Views/UserSettings/UserAddressLearnMore.swift b/apps/ios/Shared/Views/UserSettings/UserAddressLearnMore.swift
new file mode 100644
index 0000000000..e944dcec95
--- /dev/null
+++ b/apps/ios/Shared/Views/UserSettings/UserAddressLearnMore.swift
@@ -0,0 +1,29 @@
+//
+// UserAddressLearnMore.swift
+// SimpleX (iOS)
+//
+// Created by spaced4ndy on 27.04.2023.
+// Copyright © 2023 SimpleX Chat. All rights reserved.
+//
+
+import SwiftUI
+
+struct UserAddressLearnMore: View {
+ var body: some View {
+ List {
+ VStack(alignment: .leading, spacing: 18) {
+ 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).")
+ }
+ .listRowBackground(Color.clear)
+ }
+ }
+}
+
+struct UserAddressLearnMore_Previews: PreviewProvider {
+ static var previews: some View {
+ UserAddressLearnMore()
+ }
+}
diff --git a/apps/ios/Shared/Views/UserSettings/UserAddressView.swift b/apps/ios/Shared/Views/UserSettings/UserAddressView.swift
new file mode 100644
index 0000000000..802cf4d4a5
--- /dev/null
+++ b/apps/ios/Shared/Views/UserSettings/UserAddressView.swift
@@ -0,0 +1,414 @@
+//
+// UserAddressView.swift
+// SimpleX (iOS)
+//
+// Created by spaced4ndy on 26.04.2023.
+// Copyright © 2023 SimpleX Chat. All rights reserved.
+//
+
+import SwiftUI
+import SimpleXChat
+
+struct UserAddressView: View {
+ @Environment(\.dismiss) var dismiss: DismissAction
+ @EnvironmentObject private var chatModel: ChatModel
+ @State var viaCreateLinkView = false
+ @State var shareViaProfile = false
+ @State private var aas = AutoAcceptState()
+ @State private var savedAAS = AutoAcceptState()
+ @State private var ignoreShareViaProfileChange = false
+ @State private var alert: UserAddressAlert?
+ @State private var showSaveDialogue = false
+ @State private var progressIndicator = false
+ @FocusState private var keyboardVisible: Bool
+
+ private enum UserAddressAlert: Identifiable {
+ case deleteAddress
+ case profileAddress(on: Bool)
+ case shareOnCreate
+ case error(title: LocalizedStringKey, error: LocalizedStringKey = "")
+
+ var id: String {
+ switch self {
+ case .deleteAddress: return "deleteAddress"
+ case let .profileAddress(on): return "profileAddress \(on)"
+ case .shareOnCreate: return "shareOnCreate"
+ case let .error(title, _): return "error \(title)"
+ }
+ }
+ }
+
+ var body: some View {
+ ZStack {
+ if viaCreateLinkView {
+ userAddressScrollView()
+ } else {
+ userAddressScrollView()
+ .modifier(BackButton {
+ if savedAAS == aas {
+ dismiss()
+ } else {
+ keyboardVisible = false
+ showSaveDialogue = true
+ }
+ })
+ .confirmationDialog("Save settings?", isPresented: $showSaveDialogue) {
+ Button("Save auto-accept settings") {
+ saveAAS()
+ dismiss()
+ }
+ Button("Exit without saving") { dismiss() }
+ }
+ }
+ if progressIndicator {
+ ZStack {
+ if chatModel.userAddress != nil {
+ Circle()
+ .fill(.white)
+ .opacity(0.7)
+ .frame(width: 56, height: 56)
+ }
+ ProgressView().scaleEffect(2)
+ }
+ }
+ }
+ }
+
+ @Namespace private var bottomID
+
+ private func userAddressScrollView() -> some View {
+ ScrollViewReader { proxy in
+ userAddressView()
+ .onChange(of: keyboardVisible) { _ in
+ if keyboardVisible {
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
+ withAnimation {
+ proxy.scrollTo(bottomID, anchor: .top)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private func userAddressView() -> some View {
+ List {
+ if let userAddress = chatModel.userAddress {
+ existingAddressView(userAddress)
+ .onAppear {
+ aas = AutoAcceptState(userAddress: userAddress)
+ savedAAS = aas
+ }
+ .onChange(of: aas.enable) { _ in
+ if !aas.enable { aas = AutoAcceptState() }
+ }
+ } else {
+ Section {
+ createAddressButton()
+ } footer: {
+ Text("Create an address to let people connect with you.")
+ }
+
+ Section {
+ learnMoreButton()
+ }
+ }
+ }
+ .alert(item: $alert) { alert in
+ switch alert {
+ case .deleteAddress:
+ return Alert(
+ title: Text("Delete address?"),
+ message:
+ shareViaProfile
+ ? Text("All your contacts will remain connected. Profile update will be sent to your contacts.")
+ : Text("All your contacts will remain connected."),
+ primaryButton: .destructive(Text("Delete")) {
+ progressIndicator = true
+ Task {
+ do {
+ if let u = try await apiDeleteUserAddress() {
+ DispatchQueue.main.async {
+ chatModel.userAddress = nil
+ chatModel.updateUser(u)
+ if shareViaProfile {
+ ignoreShareViaProfileChange = true
+ shareViaProfile = false
+ }
+ }
+ }
+ await MainActor.run { progressIndicator = false }
+ } catch let error {
+ logger.error("UserAddressView apiDeleteUserAddress: \(responseError(error))")
+ await MainActor.run { progressIndicator = false }
+ }
+ }
+ }, secondaryButton: .cancel()
+ )
+ case let .profileAddress(on):
+ if on {
+ return Alert(
+ title: Text("Share address with contacts?"),
+ message: Text("Profile update will be sent to your contacts."),
+ primaryButton: .default(Text("Share")) {
+ setProfileAddress(on)
+ }, secondaryButton: .cancel() {
+ ignoreShareViaProfileChange = true
+ shareViaProfile = !on
+ }
+ )
+ } else {
+ return Alert(
+ title: Text("Stop sharing address?"),
+ message: Text("Profile update will be sent to your contacts."),
+ primaryButton: .default(Text("Stop sharing")) {
+ setProfileAddress(on)
+ }, secondaryButton: .cancel() {
+ ignoreShareViaProfileChange = true
+ shareViaProfile = !on
+ }
+ )
+ }
+ case .shareOnCreate:
+ return Alert(
+ title: Text("Share address with contacts?"),
+ message: Text("Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts."),
+ primaryButton: .default(Text("Share")) {
+ setProfileAddress(true)
+ ignoreShareViaProfileChange = true
+ shareViaProfile = true
+ }, secondaryButton: .cancel()
+ )
+ case let .error(title, error):
+ return Alert(title: Text(title), message: Text(error))
+ }
+ }
+ }
+
+ @ViewBuilder private func existingAddressView(_ userAddress: UserContactLink) -> some View {
+ Section {
+ QRCode(uri: userAddress.connReqContact)
+ shareQRCodeButton(userAddress)
+ shareWithContactsButton()
+ autoAcceptToggle()
+ learnMoreButton()
+ } header: {
+ Text("Address")
+ }
+
+ if aas.enable {
+ autoAcceptSection()
+ }
+
+ Section {
+ deleteAddressButton()
+ } footer: {
+ Text("Your contacts will remain connected.")
+ }
+ .id(bottomID)
+ }
+
+ private func createAddressButton() -> some View {
+ Button {
+ progressIndicator = true
+ Task {
+ do {
+ let connReqContact = try await apiCreateUserAddress()
+ DispatchQueue.main.async {
+ chatModel.userAddress = UserContactLink(connReqContact: connReqContact)
+ alert = .shareOnCreate
+ progressIndicator = false
+ }
+ } catch let error {
+ logger.error("UserAddressView apiCreateUserAddress: \(responseError(error))")
+ let a = getErrorAlert(error, "Error creating address")
+ alert = .error(title: a.title, error: a.message)
+ await MainActor.run { progressIndicator = false }
+ }
+ }
+ } label: {
+ Label("Create SimpleX address", systemImage: "qrcode")
+ }
+ }
+
+ private func deleteAddressButton() -> some View {
+ Button(role: .destructive) {
+ alert = .deleteAddress
+ } label: {
+ Label("Delete address", systemImage: "trash")
+ .foregroundColor(Color.red)
+ }
+ }
+
+ private func shareQRCodeButton(_ userAdress: UserContactLink) -> some View {
+ Button {
+ showShareSheet(items: [userAdress.connReqContact])
+ } label: {
+ settingsRow("square.and.arrow.up") {
+ Text("Share address")
+ }
+ }
+ }
+
+ private func autoAcceptToggle() -> some View {
+ settingsRow("checkmark") {
+ Toggle("Auto-accept", isOn: $aas.enable)
+ .onChange(of: aas.enable) { _ in
+ saveAAS()
+ }
+ }
+ }
+
+ private func learnMoreButton() -> some View {
+ NavigationLink {
+ UserAddressLearnMore()
+ .navigationTitle("SimpleX address")
+ .navigationBarTitleDisplayMode(.large)
+ } label: {
+ settingsRow("info.circle") {
+ Text("About SimpleX address")
+ }
+ }
+ }
+
+ private func shareWithContactsButton() -> some View {
+ settingsRow("person") {
+ Toggle("Share with contacts", isOn: $shareViaProfile)
+ .onChange(of: shareViaProfile) { on in
+ if ignoreShareViaProfileChange {
+ ignoreShareViaProfileChange = false
+ } else {
+ alert = .profileAddress(on: on)
+ }
+ }
+ }
+ }
+
+ private func setProfileAddress(_ on: Bool) {
+ progressIndicator = true
+ Task {
+ do {
+ if let u = try await apiSetProfileAddress(on: on) {
+ DispatchQueue.main.async {
+ chatModel.updateUser(u)
+ }
+ }
+ await MainActor.run { progressIndicator = false }
+ } catch let error {
+ logger.error("UserAddressView apiSetProfileAddress: \(responseError(error))")
+ await MainActor.run { progressIndicator = false }
+ }
+ }
+ }
+
+ private struct AutoAcceptState: Equatable {
+ var enable = false
+ var incognito = false
+ var welcomeText = ""
+
+ init(enable: Bool = false, incognito: Bool = false, welcomeText: String = "") {
+ self.enable = enable
+ self.incognito = incognito
+ self.welcomeText = welcomeText
+ }
+
+ init(userAddress: UserContactLink) {
+ if let aa = userAddress.autoAccept {
+ enable = true
+ incognito = aa.acceptIncognito
+ if let msg = aa.autoReply {
+ welcomeText = msg.text
+ } else {
+ welcomeText = ""
+ }
+ } else {
+ enable = false
+ incognito = false
+ welcomeText = ""
+ }
+ }
+
+ var autoAccept: AutoAccept? {
+ if enable {
+ var autoReply: MsgContent? = nil
+ let s = welcomeText.trimmingCharacters(in: .whitespacesAndNewlines)
+ if s != "" { autoReply = .text(s) }
+ return AutoAccept(acceptIncognito: incognito, autoReply: autoReply)
+ }
+ return nil
+ }
+ }
+
+ @ViewBuilder private func autoAcceptSection() -> some View {
+ Section {
+ acceptIncognitoToggle()
+ welcomeMessageEditor()
+ saveAASButton()
+ .disabled(aas == savedAAS)
+ } header: {
+ Text("Auto-accept")
+ }
+ }
+
+ private func acceptIncognitoToggle() -> some View {
+ settingsRow(
+ aas.incognito ? "theatermasks.fill" : "theatermasks",
+ color: aas.incognito ? .indigo : .secondary
+ ) {
+ Toggle("Accept incognito", isOn: $aas.incognito)
+ }
+ }
+
+ private func welcomeMessageEditor() -> some View {
+ ZStack {
+ Group {
+ if aas.welcomeText.isEmpty {
+ TextEditor(text: Binding.constant(NSLocalizedString("Enter welcome message… (optional)", comment: "placeholder")))
+ .foregroundColor(.secondary)
+ .disabled(true)
+ }
+ TextEditor(text: $aas.welcomeText)
+ .focused($keyboardVisible)
+ }
+ .padding(.horizontal, -5)
+ .padding(.top, -8)
+ .frame(height: 90, alignment: .topLeading)
+ .frame(maxWidth: .infinity, alignment: .leading)
+ }
+ }
+
+ private func saveAASButton() -> some View {
+ Button {
+ keyboardVisible = false
+ saveAAS()
+ } label: {
+ Text("Save")
+ }
+ }
+
+ private func saveAAS() {
+ Task {
+ do {
+ if let address = try await userAddressAutoAccept(aas.autoAccept) {
+ chatModel.userAddress = address
+ savedAAS = aas
+ }
+ } catch let error {
+ logger.error("userAddressAutoAccept error: \(responseError(error))")
+ }
+ }
+ }
+}
+
+struct UserAddressView_Previews: PreviewProvider {
+ static var previews: some View {
+ let chatModel = ChatModel()
+ chatModel.userAddress = UserContactLink(connReqContact: "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D")
+ return Group {
+ UserAddressView()
+ .environmentObject(chatModel)
+ UserAddressView()
+ .environmentObject(ChatModel())
+ }
+ }
+}
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 775e7c754d..0980517f78 100644
--- a/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff
+++ b/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff
@@ -361,6 +361,10 @@ Dostupné ve verzi 5.1
O SimpleX chat
No comment provided by engineer.
+
+ About SimpleX address
+ No comment provided by engineer.
+
Accent color
Zbarvení
@@ -387,9 +391,8 @@ Dostupné ve verzi 5.1
Přijmout inkognito
No comment provided by engineer.
-
- Accept requests
- Přijímat žádosti
+
+ Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -422,6 +425,10 @@ Dostupné ve verzi 5.1
Přidat uvítací zprávu
No comment provided by engineer.
+
+ Address
+ No comment provided by engineer.
+
Admins can create the links to join groups.
Správci mohou vytvářet odkazy pro připojení ke skupinám.
@@ -447,9 +454,12 @@ Dostupné ve verzi 5.1
Všechny zprávy budou smazány – tuto akci nelze vrátit zpět! Zprávy budou smazány POUZE pro vás.
No comment provided by engineer.
-
- All your contacts will remain connected
- Všechny vaše kontakty zůstanou připojeny
+
+ All your contacts will remain connected.
+ No comment provided by engineer.
+
+
+ All your contacts will remain connected. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -612,6 +622,10 @@ Dostupné ve verzi 5.1
Ověřování není k dispozici
No comment provided by engineer.
+
+ Auto-accept
+ No comment provided by engineer.
+
Auto-accept contact requests
Automatické přijímání žádostí o kontakt
@@ -622,11 +636,6 @@ Dostupné ve verzi 5.1
Automaticky přijímat obrázky
No comment provided by engineer.
-
- Automatically
- Automaticky
- No comment provided by engineer.
-
Back
Zpět
@@ -992,11 +1001,6 @@ Dostupné ve verzi 5.1
Předvolby kontaktů
No comment provided by engineer.
-
- Contact requests
- Žádosti o kontakt
- No comment provided by engineer.
-
Contacts can mark messages for deletion; you will be able to view them.
Kontakty mohou označit zprávy ke smazání; vy je budete moci zobrazit.
@@ -1017,9 +1021,12 @@ Dostupné ve verzi 5.1
Vytvořit
No comment provided by engineer.
-
- Create address
- Vytvořit adresu
+
+ Create SimpleX address
+ No comment provided by engineer.
+
+
+ Create an address to let people connect with you.
No comment provided by engineer.
@@ -1590,6 +1597,10 @@ Dostupné ve verzi 5.1
Zadejte server ručně
No comment provided by engineer.
+
+ Enter welcome message… (optional)
+ placeholder
+
Error
Chyba
@@ -2343,6 +2354,10 @@ 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).
+ No comment provided by engineer.
+
Leave
Opustit
@@ -2987,6 +3002,10 @@ Dostupné ve verzi 5.1
Heslo profilu
No comment provided by engineer.
+
+ Profile update will be sent to your contacts.
+ No comment provided by engineer.
+
Prohibit audio/video calls.
Zákaz audio/video hovorů.
@@ -3247,6 +3266,10 @@ Dostupné ve verzi 5.1
Uložit archiv
No comment provided by engineer.
+
+ Save auto-accept settings
+ No comment provided by engineer.
+
Save group profile
Uložení profilu skupiny
@@ -3282,6 +3305,10 @@ Dostupné ve verzi 5.1
Uložit servery?
No comment provided by engineer.
+
+ Save settings?
+ No comment provided by engineer.
+
Save welcome message?
Uložit uvítací zprávu?
@@ -3472,6 +3499,14 @@ Dostupné ve verzi 5.1
Sdílet
chat item action
+
+ Share address
+ No comment provided by engineer.
+
+
+ Share address with contacts?
+ No comment provided by engineer.
+
Share invitation link
Sdílet odkaz na pozvánku
@@ -3487,6 +3522,10 @@ Dostupné ve verzi 5.1
Jednorázový zvací odkaz
No comment provided by engineer.
+
+ Share with contacts
+ No comment provided by engineer.
+
Show QR code
Zobrazit QR kód
@@ -3537,6 +3576,10 @@ Dostupné ve verzi 5.1
Zapnutý zámek SimpleX Lock
No comment provided by engineer.
+
+ SimpleX address
+ No comment provided by engineer.
+
SimpleX contact address
SimpleX kontaktní adresa
@@ -3632,6 +3675,14 @@ Dostupné ve verzi 5.1
Zastavit odesílání souboru?
No comment provided by engineer.
+
+ Stop sharing
+ No comment provided by engineer.
+
+
+ Stop sharing address?
+ No comment provided by engineer.
+
Submit
Odeslat
@@ -4228,6 +4279,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
Když je k dispozici
No comment provided by engineer.
+
+ When people request to connect, you can accept or reject it.
+ No comment provided by engineer.
+
When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.
Pokud s někým sdílíte inkognito profil, bude tento profil použit pro skupiny, do kterých vás pozve.
@@ -4320,9 +4375,13 @@ SimpleX zámek musí být povolen.
Můžete sdílet odkaz nebo QR kód - ke skupině se bude moci připojit kdokoli. O členy skupiny nepřijdete, pokud ji později odstraníte.
No comment provided by engineer.
-
- 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.
- 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.
+
+ You can share this address with your contacts to let them connect with **%@**.
+ No comment provided by engineer.
+
+
+ You can share your address as a link or QR code - anybody can connect to you.
+ Můžete sdílet svou adresu jako odkaz nebo jako QR kód - kdokoli se k vám bude moci připojit.
No comment provided by engineer.
@@ -4435,6 +4494,11 @@ SimpleX zámek musí být povolen.
Přestanete dostávat zprávy z této skupiny. Historie chatu bude zachována.
No comment provided by engineer.
+
+ You won't lose your contacts if you later delete your address.
+ O své kontakty nepřijdete, pokud ji později smažete.
+ No comment provided by engineer.
+
You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile
Snažíte se pozvat kontakt, se kterým jste sdíleli inkognito profil, do skupiny, ve které používáte svůj hlavní profil
@@ -4462,7 +4526,7 @@ SimpleX zámek musí být povolen.
Your SimpleX contact address
- Vaše kontaktní adresa SimpleX
+ Vaše adresa SimpleX
No comment provided by engineer.
@@ -4532,6 +4596,10 @@ Toto připojení můžete zrušit a kontakt odebrat (a zkusit to později s nov
Vaše kontakty mohou povolit úplné mazání zpráv.
No comment provided by engineer.
+
+ Your contacts will remain connected.
+ No comment provided by engineer.
+
Your current chat database will be DELETED and REPLACED with the imported one.
Vaše aktuální chat databáze bude ODSTRANĚNA a NAHRAZENA importovanou.
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 14b40892cf..68ccbbb7a3 100644
--- a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff
+++ b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff
@@ -361,6 +361,10 @@ Verfügbar ab v5.1
Über SimpleX Chat
No comment provided by engineer.
+
+ About SimpleX address
+ No comment provided by engineer.
+
Accent color
Akzentfarbe
@@ -387,9 +391,8 @@ Verfügbar ab v5.1
Inkognito akzeptieren
No comment provided by engineer.
-
- Accept requests
- Anfragen annehmen
+
+ Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -422,6 +425,10 @@ Verfügbar ab v5.1
Begrüßungsmeldung hinzufügen
No comment provided by engineer.
+
+ Address
+ No comment provided by engineer.
+
Admins can create the links to join groups.
Administratoren können Links für den Beitritt zu Gruppen erzeugen.
@@ -447,9 +454,12 @@ Verfügbar ab v5.1
Alle Nachrichten werden gelöscht - dies kann nicht rückgängig gemacht werden! Die Nachrichten werden NUR bei Ihnen gelöscht.
No comment provided by engineer.
-
- All your contacts will remain connected
- Alle Ihre Kontakte bleiben verbunden
+
+ All your contacts will remain connected.
+ No comment provided by engineer.
+
+
+ All your contacts will remain connected. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -612,6 +622,10 @@ Verfügbar ab v5.1
Authentifizierung nicht verfügbar
No comment provided by engineer.
+
+ Auto-accept
+ No comment provided by engineer.
+
Auto-accept contact requests
Kontaktanfragen automatisch annehmen
@@ -622,11 +636,6 @@ Verfügbar ab v5.1
Bilder automatisch akzeptieren
No comment provided by engineer.
-
- Automatically
- Automatisch
- No comment provided by engineer.
-
Back
Zurück
@@ -992,11 +1001,6 @@ Verfügbar ab v5.1
Kontakt Präferenzen
No comment provided by engineer.
-
- Contact requests
- Kontaktanfragen
- No comment provided by engineer.
-
Contacts can mark messages for deletion; you will be able to view them.
Ihre Kontakte können Nachrichten zum Löschen markieren. Sie können diese Nachrichten trotzdem anschauen.
@@ -1017,9 +1021,12 @@ Verfügbar ab v5.1
Erstellen
No comment provided by engineer.
-
- Create address
- Adresse erstellen
+
+ Create SimpleX address
+ No comment provided by engineer.
+
+
+ Create an address to let people connect with you.
No comment provided by engineer.
@@ -1590,6 +1597,10 @@ Verfügbar ab v5.1
Geben Sie den Server manuell ein
No comment provided by engineer.
+
+ Enter welcome message… (optional)
+ placeholder
+
Error
Fehler
@@ -2343,6 +2354,10 @@ 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).
+ No comment provided by engineer.
+
Leave
Verlassen
@@ -2987,6 +3002,10 @@ Verfügbar ab v5.1
Passwort für Profil
No comment provided by engineer.
+
+ Profile update will be sent to your contacts.
+ No comment provided by engineer.
+
Prohibit audio/video calls.
Audio/Video Anrufe nicht erlauben.
@@ -3247,6 +3266,10 @@ Verfügbar ab v5.1
Archiv speichern
No comment provided by engineer.
+
+ Save auto-accept settings
+ No comment provided by engineer.
+
Save group profile
Gruppenprofil speichern
@@ -3282,6 +3305,10 @@ Verfügbar ab v5.1
Alle Server speichern?
No comment provided by engineer.
+
+ Save settings?
+ No comment provided by engineer.
+
Save welcome message?
Begrüßungsmeldung speichern?
@@ -3472,6 +3499,14 @@ Verfügbar ab v5.1
Teilen
chat item action
+
+ Share address
+ No comment provided by engineer.
+
+
+ Share address with contacts?
+ No comment provided by engineer.
+
Share invitation link
Einladungslink teilen
@@ -3487,6 +3522,10 @@ Verfügbar ab v5.1
Einmal-Einladungslink teilen
No comment provided by engineer.
+
+ Share with contacts
+ No comment provided by engineer.
+
Show QR code
QR-Code anzeigen
@@ -3537,6 +3576,10 @@ Verfügbar ab v5.1
SimpleX Sperre aktiviert
No comment provided by engineer.
+
+ SimpleX address
+ No comment provided by engineer.
+
SimpleX contact address
SimpleX Kontaktadressen-Link
@@ -3632,6 +3675,14 @@ Verfügbar ab v5.1
Das Senden der Datei beenden?
No comment provided by engineer.
+
+ Stop sharing
+ No comment provided by engineer.
+
+
+ Stop sharing address?
+ No comment provided by engineer.
+
Submit
Übermitteln
@@ -4228,6 +4279,10 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
Wenn verfügbar
No comment provided by engineer.
+
+ When people request to connect, you can accept or reject it.
+ No comment provided by engineer.
+
When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.
Wenn Sie ein Inkognito-Profil mit Jemandem teilen, wird dieses Profil auch für die Gruppen verwendet, für die Sie von diesem Kontakt eingeladen werden.
@@ -4320,9 +4375,13 @@ Dafür muss die SimpleX Sperre aktiviert sein.
Sie können diesen Link oder QR-Code teilen - Damit kann jede Person der Gruppe beitreten. Wenn Sie den Link später löschen, werden Sie keine Gruppenmitglieder verlieren, die der Gruppe darüber beigetreten sind.
No comment provided by engineer.
-
- 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.
- 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.
+
+ You can share this address with your contacts to let them connect with **%@**.
+ No comment provided by engineer.
+
+
+ You can share your address as a link or QR code - anybody can connect to you.
+ Sie können Ihre Adresse als Link oder als QR-Code teilen – Jede Person kann sich darüber mit Ihnen verbinden.
No comment provided by engineer.
@@ -4435,6 +4494,11 @@ Dafür muss die SimpleX Sperre aktiviert sein.
Sie werden von dieser Gruppe keine Nachrichten mehr erhalten. Der Chatverlauf wird beibehalten.
No comment provided by engineer.
+
+ You won't lose your contacts if you later delete your address.
+ Sie werden Ihre mit dieser Adresse verbundenen Kontakte nicht verlieren, wenn Sie diese Adresse später löschen.
+ No comment provided by engineer.
+
You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile
Sie versuchen, einen Kontakt, mit dem Sie ein Inkognito-Profil geteilt haben, in die Gruppe einzuladen, in der Sie Ihr Hauptprofil verwenden
@@ -4532,6 +4596,10 @@ Sie können diese Verbindung abbrechen und den Kontakt entfernen (und es später
Ihre Kontakte können die unwiederbringliche Löschung von Nachrichten erlauben.
No comment provided by engineer.
+
+ Your contacts will remain connected.
+ No comment provided by engineer.
+
Your current chat database will be DELETED and REPLACED with the imported one.
Ihre aktuelle Chat-Datenbank wird GELÖSCHT und durch die Importierte ERSETZT.
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 c0a0c7cfc1..d7c662591e 100644
--- a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff
+++ b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff
@@ -361,6 +361,11 @@ Available in v5.1
About SimpleX Chat
No comment provided by engineer.
+
+ About SimpleX address
+ About SimpleX address
+ No comment provided by engineer.
+
Accent color
Accent color
@@ -387,9 +392,9 @@ Available in v5.1
Accept incognito
No comment provided by engineer.
-
- Accept requests
- Accept requests
+
+ Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.
+ Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -422,6 +427,11 @@ Available in v5.1
Add welcome message
No comment provided by engineer.
+
+ Address
+ Address
+ No comment provided by engineer.
+
Admins can create the links to join groups.
Admins can create the links to join groups.
@@ -447,9 +457,14 @@ Available in v5.1
All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.
No comment provided by engineer.
-
- All your contacts will remain connected
- All your contacts will remain connected
+
+ All your contacts will remain connected.
+ All your contacts will remain connected.
+ No comment provided by engineer.
+
+
+ All your contacts will remain connected. Profile update will be sent to your contacts.
+ All your contacts will remain connected. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -612,6 +627,11 @@ Available in v5.1
Authentication unavailable
No comment provided by engineer.
+
+ Auto-accept
+ Auto-accept
+ No comment provided by engineer.
+
Auto-accept contact requests
Auto-accept contact requests
@@ -622,11 +642,6 @@ Available in v5.1
Auto-accept images
No comment provided by engineer.
-
- Automatically
- Automatically
- No comment provided by engineer.
-
Back
Back
@@ -992,11 +1007,6 @@ Available in v5.1
Contact preferences
No comment provided by engineer.
-
- Contact requests
- Contact requests
- No comment provided by engineer.
-
Contacts can mark messages for deletion; you will be able to view them.
Contacts can mark messages for deletion; you will be able to view them.
@@ -1017,9 +1027,14 @@ Available in v5.1
Create
No comment provided by engineer.
-
- Create address
- Create address
+
+ Create SimpleX address
+ Create SimpleX address
+ No comment provided by engineer.
+
+
+ Create an address to let people connect with you.
+ Create an address to let people connect with you.
No comment provided by engineer.
@@ -1590,6 +1605,11 @@ Available in v5.1
Enter server manually
No comment provided by engineer.
+
+ Enter welcome message… (optional)
+ Enter welcome message… (optional)
+ placeholder
+
Error
Error
@@ -2343,6 +2363,11 @@ 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).
+ No comment provided by engineer.
+
Leave
Leave
@@ -2987,6 +3012,11 @@ Available in v5.1
Profile password
No comment provided by engineer.
+
+ Profile update will be sent to your contacts.
+ Profile update will be sent to your contacts.
+ No comment provided by engineer.
+
Prohibit audio/video calls.
Prohibit audio/video calls.
@@ -3247,6 +3277,11 @@ Available in v5.1
Save archive
No comment provided by engineer.
+
+ Save auto-accept settings
+ Save auto-accept settings
+ No comment provided by engineer.
+
Save group profile
Save group profile
@@ -3282,6 +3317,11 @@ Available in v5.1
Save servers?
No comment provided by engineer.
+
+ Save settings?
+ Save settings?
+ No comment provided by engineer.
+
Save welcome message?
Save welcome message?
@@ -3472,6 +3512,16 @@ Available in v5.1
Share
chat item action
+
+ Share address
+ Share address
+ No comment provided by engineer.
+
+
+ Share address with contacts?
+ Share address with contacts?
+ No comment provided by engineer.
+
Share invitation link
Share invitation link
@@ -3487,6 +3537,11 @@ Available in v5.1
Share one-time invitation link
No comment provided by engineer.
+
+ Share with contacts
+ Share with contacts
+ No comment provided by engineer.
+
Show QR code
Show QR code
@@ -3537,6 +3592,11 @@ Available in v5.1
SimpleX Lock turned on
No comment provided by engineer.
+
+ SimpleX address
+ SimpleX address
+ No comment provided by engineer.
+
SimpleX contact address
SimpleX contact address
@@ -3632,6 +3692,16 @@ Available in v5.1
Stop sending file?
No comment provided by engineer.
+
+ Stop sharing
+ Stop sharing
+ No comment provided by engineer.
+
+
+ Stop sharing address?
+ Stop sharing address?
+ No comment provided by engineer.
+
Submit
Submit
@@ -4228,6 +4298,11 @@ To connect, please ask your contact to create another connection link and check
When available
No comment provided by engineer.
+
+ When people request to connect, you can accept or reject it.
+ When people request to connect, you can accept or reject it.
+ No comment provided by engineer.
+
When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.
When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.
@@ -4320,9 +4395,14 @@ SimpleX Lock must be enabled.
You can share a link or a QR code - anybody will be able to join the group. You won't lose members of the group if you later delete it.
No comment provided by engineer.
-
- 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.
- 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.
+
+ You can share this address with your contacts to let them connect with **%@**.
+ You can share this address with your contacts to let them connect with **%@**.
+ No comment provided by engineer.
+
+
+ You can share your address as a link or QR code - anybody can connect to you.
+ You can share your address as a link or QR code - anybody can connect to you.
No comment provided by engineer.
@@ -4435,6 +4515,11 @@ SimpleX Lock must be enabled.
You will stop receiving messages from this group. Chat history will be preserved.
No comment provided by engineer.
+
+ You won't lose your contacts if you later delete your address.
+ You won't lose your contacts if you later delete your address.
+ No comment provided by engineer.
+
You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile
You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile
@@ -4460,9 +4545,9 @@ SimpleX Lock must be enabled.
Your SMP servers
No comment provided by engineer.
-
- Your SimpleX contact address
- Your SimpleX contact address
+
+ Your SimpleX address
+ Your SimpleX address
No comment provided by engineer.
@@ -4532,6 +4617,11 @@ You can cancel this connection and remove the contact (and try later with a new
Your contacts can allow full message deletion.
No comment provided by engineer.
+
+ Your contacts will remain connected.
+ Your contacts will remain connected.
+ No comment provided by engineer.
+
Your current chat database will be DELETED and REPLACED with the imported one.
Your current chat database will be DELETED and REPLACED with the imported one.
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 b87a02742f..148a814c74 100644
--- a/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff
+++ b/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff
@@ -361,6 +361,10 @@ Disponible en v5.1
Acerca de SimpleX Chat
No comment provided by engineer.
+
+ About SimpleX address
+ No comment provided by engineer.
+
Accent color
Color
@@ -387,9 +391,8 @@ Disponible en v5.1
Aceptar incógnito
No comment provided by engineer.
-
- Accept requests
- Aceptar solicitudes
+
+ Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -422,6 +425,10 @@ Disponible en v5.1
Agregar mensaje de bienvenida
No comment provided by engineer.
+
+ Address
+ No comment provided by engineer.
+
Admins can create the links to join groups.
Los administradores pueden crear los enlaces para unirse a los grupos.
@@ -447,9 +454,12 @@ Disponible en v5.1
Se eliminarán todos los mensajes SOLO para tí. ¡No puede deshacerse!
No comment provided by engineer.
-
- All your contacts will remain connected
- Todos tus contactos permanecerán conectados
+
+ All your contacts will remain connected.
+ No comment provided by engineer.
+
+
+ All your contacts will remain connected. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -612,6 +622,10 @@ Disponible en v5.1
Autenticación no disponible
No comment provided by engineer.
+
+ Auto-accept
+ No comment provided by engineer.
+
Auto-accept contact requests
Aceptar automáticamente solicitudes del contacto
@@ -622,11 +636,6 @@ Disponible en v5.1
Aceptar automáticamente imágenes
No comment provided by engineer.
-
- Automatically
- Automáticamente
- No comment provided by engineer.
-
Back
Volver
@@ -992,11 +1001,6 @@ Disponible en v5.1
Preferencias de contacto
No comment provided by engineer.
-
- Contact requests
- Solicitud del contacto
- No comment provided by engineer.
-
Contacts can mark messages for deletion; you will be able to view them.
El contacto solo puede marcar los mensajes para eliminar. Tu podrás verlos.
@@ -1017,9 +1021,12 @@ Disponible en v5.1
Crear
No comment provided by engineer.
-
- Create address
- Crear dirección
+
+ Create SimpleX address
+ No comment provided by engineer.
+
+
+ Create an address to let people connect with you.
No comment provided by engineer.
@@ -1590,6 +1597,10 @@ Disponible en v5.1
Introduce el servidor manualmente
No comment provided by engineer.
+
+ Enter welcome message… (optional)
+ placeholder
+
Error
Error
@@ -2343,6 +2354,10 @@ 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).
+ No comment provided by engineer.
+
Leave
Salir
@@ -2987,6 +3002,10 @@ Disponible en v5.1
Contraseña del perfil
No comment provided by engineer.
+
+ Profile update will be sent to your contacts.
+ No comment provided by engineer.
+
Prohibit audio/video calls.
Prohibir las llamadas/videollamadas.
@@ -3247,6 +3266,10 @@ Disponible en v5.1
Guardar archivo
No comment provided by engineer.
+
+ Save auto-accept settings
+ No comment provided by engineer.
+
Save group profile
Guardar perfil de grupo
@@ -3282,6 +3305,10 @@ Disponible en v5.1
¿Guardar servidores?
No comment provided by engineer.
+
+ Save settings?
+ No comment provided by engineer.
+
Save welcome message?
¿Guardar mensaje de bienvenida?
@@ -3472,6 +3499,14 @@ Disponible en v5.1
Compartir
chat item action
+
+ Share address
+ No comment provided by engineer.
+
+
+ Share address with contacts?
+ No comment provided by engineer.
+
Share invitation link
Compartir enlace de invitación
@@ -3487,6 +3522,10 @@ Disponible en v5.1
Compartir enlace de invitación de un uso
No comment provided by engineer.
+
+ Share with contacts
+ No comment provided by engineer.
+
Show QR code
Mostrar código QR
@@ -3537,6 +3576,10 @@ Disponible en v5.1
Bloqueo SimpleX activado
No comment provided by engineer.
+
+ SimpleX address
+ No comment provided by engineer.
+
SimpleX contact address
Dirección de contacto SimpleX
@@ -3632,6 +3675,14 @@ Disponible en v5.1
¿Dejar de enviar el archivo?
No comment provided by engineer.
+
+ Stop sharing
+ No comment provided by engineer.
+
+
+ Stop sharing address?
+ No comment provided by engineer.
+
Submit
Enviar
@@ -4229,6 +4280,10 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb
Cuando esté disponible
No comment provided by engineer.
+
+ When people request to connect, you can accept or reject it.
+ No comment provided by engineer.
+
When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.
Cuando compartes un perfil incógnito con alguien, este perfil también se usará para los grupos a los que te inviten.
@@ -4321,9 +4376,13 @@ Bloqueo SimpleX debe estar activado.
Puedes compartir un enlace o un código QR: cualquiera podrá unirse al grupo. Si lo eliminas más tarde los miembros del grupo no se perderán.
No comment provided by engineer.
-
- 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.
- 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.
+
+ You can share this address with your contacts to let them connect with **%@**.
+ No comment provided by engineer.
+
+
+ You can share your address as a link or QR code - anybody can connect to you.
+ Puedes compartir tu dirección como enlace o como código QR: cualquiera podrá conectarse contigo.
No comment provided by engineer.
@@ -4436,6 +4495,11 @@ Bloqueo SimpleX debe estar activado.
Dejarás de recibir mensajes de este grupo. El historial del chat se conservará.
No comment provided by engineer.
+
+ You won't lose your contacts if you later delete your address.
+ Si lo eliminas más tarde tus contactos no se perderán.
+ No comment provided by engineer.
+
You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile
Estás intentando invitar a un contacto con el que compartes un perfil incógnito a un grupo en el que usas tu perfil principal
@@ -4463,7 +4527,7 @@ Bloqueo SimpleX debe estar activado.
Your SimpleX contact address
- Mi dirección de contacto SimpleX
+ Mi dirección SimpleX
No comment provided by engineer.
@@ -4533,6 +4597,10 @@ Puedes cancelar esta conexión y eliminar el contacto (e intentarlo más tarde c
Tus contactos pueden permitir la eliminación completa de mensajes.
No comment provided by engineer.
+
+ Your contacts will remain connected.
+ No comment provided by engineer.
+
Your current chat database will be DELETED and REPLACED with the imported one.
La base de datos actual será ELIMINADA y SUSTITUIDA por la importada.
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 88d5bca63d..a5c44c9ff4 100644
--- a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff
+++ b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff
@@ -361,6 +361,10 @@ Disponible dans la v5.1
À propos de SimpleX Chat
No comment provided by engineer.
+
+ About SimpleX address
+ No comment provided by engineer.
+
Accent color
Couleur principale
@@ -387,9 +391,8 @@ Disponible dans la v5.1
Accepter en incognito
No comment provided by engineer.
-
- Accept requests
- Accepter les demandes
+
+ Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -422,6 +425,10 @@ Disponible dans la v5.1
Ajouter un message d'accueil
No comment provided by engineer.
+
+ Address
+ No comment provided by engineer.
+
Admins can create the links to join groups.
Les admins peuvent créer les liens qui permettent de rejoindre les groupes.
@@ -447,9 +454,12 @@ Disponible dans la v5.1
Tous les messages seront supprimés - impossible de revenir en arrière ! Les messages seront supprimés UNIQUEMENT pour vous.
No comment provided by engineer.
-
- All your contacts will remain connected
- Tous vos contacts resteront connectés
+
+ All your contacts will remain connected.
+ No comment provided by engineer.
+
+
+ All your contacts will remain connected. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -612,6 +622,10 @@ Disponible dans la v5.1
Authentification indisponible
No comment provided by engineer.
+
+ Auto-accept
+ No comment provided by engineer.
+
Auto-accept contact requests
Demandes de contact auto-acceptées
@@ -622,11 +636,6 @@ Disponible dans la v5.1
Images auto-acceptées
No comment provided by engineer.
-
- Automatically
- Automatiquement
- No comment provided by engineer.
-
Back
Retour
@@ -992,11 +1001,6 @@ Disponible dans la v5.1
Préférences de contact
No comment provided by engineer.
-
- Contact requests
- Demandes de contact
- No comment provided by engineer.
-
Contacts can mark messages for deletion; you will be able to view them.
Vos contacts peuvent marquer les messages pour les supprimer ; vous pourrez les consulter.
@@ -1017,9 +1021,12 @@ Disponible dans la v5.1
Créer
No comment provided by engineer.
-
- Create address
- Créer une adresse
+
+ Create SimpleX address
+ No comment provided by engineer.
+
+
+ Create an address to let people connect with you.
No comment provided by engineer.
@@ -1590,6 +1597,10 @@ Disponible dans la v5.1
Entrer un serveur manuellement
No comment provided by engineer.
+
+ Enter welcome message… (optional)
+ placeholder
+
Error
Erreur
@@ -2343,6 +2354,10 @@ 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).
+ No comment provided by engineer.
+
Leave
Quitter
@@ -2987,6 +3002,10 @@ Disponible dans la v5.1
Mot de passe de profil
No comment provided by engineer.
+
+ Profile update will be sent to your contacts.
+ No comment provided by engineer.
+
Prohibit audio/video calls.
Interdire les appels audio/vidéo.
@@ -3247,6 +3266,10 @@ Disponible dans la v5.1
Sauvegarder l'archive
No comment provided by engineer.
+
+ Save auto-accept settings
+ No comment provided by engineer.
+
Save group profile
Sauvegarder le profil du groupe
@@ -3282,6 +3305,10 @@ Disponible dans la v5.1
Sauvegarder les serveurs ?
No comment provided by engineer.
+
+ Save settings?
+ No comment provided by engineer.
+
Save welcome message?
Sauvegarder le message d'accueil ?
@@ -3472,6 +3499,14 @@ Disponible dans la v5.1
Partager
chat item action
+
+ Share address
+ No comment provided by engineer.
+
+
+ Share address with contacts?
+ No comment provided by engineer.
+
Share invitation link
Partager le lien d'invitation
@@ -3487,6 +3522,10 @@ Disponible dans la v5.1
Partager un lien d'invitation unique
No comment provided by engineer.
+
+ Share with contacts
+ No comment provided by engineer.
+
Show QR code
Afficher le code QR
@@ -3537,6 +3576,10 @@ Disponible dans la v5.1
SimpleX Lock activé
No comment provided by engineer.
+
+ SimpleX address
+ No comment provided by engineer.
+
SimpleX contact address
Adresse de contact SimpleX
@@ -3632,6 +3675,14 @@ Disponible dans la v5.1
Arrêter l'envoi du fichier ?
No comment provided by engineer.
+
+ Stop sharing
+ No comment provided by engineer.
+
+
+ Stop sharing address?
+ No comment provided by engineer.
+
Submit
Soumettre
@@ -4228,6 +4279,10 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
Quand disponible
No comment provided by engineer.
+
+ When people request to connect, you can accept or reject it.
+ No comment provided by engineer.
+
When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.
Lorsque vous partagez un profil incognito avec quelqu'un, ce profil sera utilisé pour les groupes auxquels il vous invite.
@@ -4320,9 +4375,13 @@ SimpleX Lock doit être activé.
Vous pouvez partager un lien ou un code QR - n'importe qui pourra rejoindre le groupe. Vous ne perdrez pas les membres du groupe si vous le supprimez par la suite.
No comment provided by engineer.
-
- 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.
- 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.
+
+ You can share this address with your contacts to let them connect with **%@**.
+ No comment provided by engineer.
+
+
+ You can share your address as a link or QR code - anybody can connect to you.
+ Vous pouvez partager votre adresse sous forme de lien ou de code QR - n'importe qui pourra se connecter à vous.
No comment provided by engineer.
@@ -4435,6 +4494,11 @@ SimpleX Lock doit être activé.
Vous ne recevrez plus de messages de ce groupe. L'historique du chat sera conservé.
No comment provided by engineer.
+
+ You won't lose your contacts if you later delete your address.
+ Vous ne perdrez pas vos contacts si vous la supprimez par la suite.
+ No comment provided by engineer.
+
You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile
Vous essayez d'inviter un contact avec lequel vous avez partagé un profil incognito à rejoindre le groupe dans lequel vous utilisez votre profil principal
@@ -4462,7 +4526,7 @@ SimpleX Lock doit être activé.
Your SimpleX contact address
- Votre adresse de contact SimpleX
+ Votre adresse SimpleX
No comment provided by engineer.
@@ -4532,6 +4596,10 @@ Vous pouvez annuler la connexion et supprimer le contact (et réessayer plus tar
Vos contacts peuvent autoriser la suppression complète des messages.
No comment provided by engineer.
+
+ Your contacts will remain connected.
+ No comment provided by engineer.
+
Your current chat database will be DELETED and REPLACED with the imported one.
Votre base de données de chat actuelle va être SUPPRIMEE et REMPLACEE par celle importée.
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 6c0ee81008..bb549d4e9f 100644
--- a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff
+++ b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff
@@ -361,6 +361,10 @@ Disponibile nella v5.1
Riguardo SimpleX Chat
No comment provided by engineer.
+
+ About SimpleX address
+ No comment provided by engineer.
+
Accent color
Colore principale
@@ -387,9 +391,8 @@ Disponibile nella v5.1
Accetta in incognito
No comment provided by engineer.
-
- Accept requests
- Accetta le richieste
+
+ Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -422,6 +425,10 @@ Disponibile nella v5.1
Aggiungi messaggio di benvenuto
No comment provided by engineer.
+
+ Address
+ No comment provided by engineer.
+
Admins can create the links to join groups.
Gli amministratori possono creare i link per entrare nei gruppi.
@@ -447,9 +454,12 @@ Disponibile nella v5.1
Tutti i messaggi verranno eliminati, non è reversibile! I messaggi verranno eliminati SOLO per te.
No comment provided by engineer.
-
- All your contacts will remain connected
- Tutti i tuoi contatti resteranno connessi
+
+ All your contacts will remain connected.
+ No comment provided by engineer.
+
+
+ All your contacts will remain connected. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -612,6 +622,10 @@ Disponibile nella v5.1
Autenticazione non disponibile
No comment provided by engineer.
+
+ Auto-accept
+ No comment provided by engineer.
+
Auto-accept contact requests
Auto-accetta richieste di contatto
@@ -622,11 +636,6 @@ Disponibile nella v5.1
Auto-accetta immagini
No comment provided by engineer.
-
- Automatically
- Automaticamente
- No comment provided by engineer.
-
Back
Indietro
@@ -992,11 +1001,6 @@ Disponibile nella v5.1
Preferenze del contatto
No comment provided by engineer.
-
- Contact requests
- Richieste del contatto
- No comment provided by engineer.
-
Contacts can mark messages for deletion; you will be able to view them.
I contatti possono contrassegnare i messaggi per l'eliminazione; potrai vederli.
@@ -1017,9 +1021,12 @@ Disponibile nella v5.1
Crea
No comment provided by engineer.
-
- Create address
- Crea indirizzo
+
+ Create SimpleX address
+ No comment provided by engineer.
+
+
+ Create an address to let people connect with you.
No comment provided by engineer.
@@ -1590,6 +1597,10 @@ Disponibile nella v5.1
Inserisci il server a mano
No comment provided by engineer.
+
+ Enter welcome message… (optional)
+ placeholder
+
Error
Errore
@@ -2343,6 +2354,10 @@ 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).
+ No comment provided by engineer.
+
Leave
Esci
@@ -2987,6 +3002,10 @@ Disponibile nella v5.1
Password del profilo
No comment provided by engineer.
+
+ Profile update will be sent to your contacts.
+ No comment provided by engineer.
+
Prohibit audio/video calls.
Proibisci le chiamate audio/video.
@@ -3247,6 +3266,10 @@ Disponibile nella v5.1
Salva archivio
No comment provided by engineer.
+
+ Save auto-accept settings
+ No comment provided by engineer.
+
Save group profile
Salva il profilo del gruppo
@@ -3282,6 +3305,10 @@ Disponibile nella v5.1
Salvare i server?
No comment provided by engineer.
+
+ Save settings?
+ No comment provided by engineer.
+
Save welcome message?
Salvare il messaggio di benvenuto?
@@ -3472,6 +3499,14 @@ Disponibile nella v5.1
Condividi
chat item action
+
+ Share address
+ No comment provided by engineer.
+
+
+ Share address with contacts?
+ No comment provided by engineer.
+
Share invitation link
Condividi link di invito
@@ -3487,6 +3522,10 @@ Disponibile nella v5.1
Condividi link di invito una tantum
No comment provided by engineer.
+
+ Share with contacts
+ No comment provided by engineer.
+
Show QR code
Mostra codice QR
@@ -3537,6 +3576,10 @@ Disponibile nella v5.1
SimpleX Lock attivato
No comment provided by engineer.
+
+ SimpleX address
+ No comment provided by engineer.
+
SimpleX contact address
Indirizzo del contatto SimpleX
@@ -3632,6 +3675,14 @@ Disponibile nella v5.1
Fermare l'invio del file?
No comment provided by engineer.
+
+ Stop sharing
+ No comment provided by engineer.
+
+
+ Stop sharing address?
+ No comment provided by engineer.
+
Submit
Invia
@@ -4228,6 +4279,10 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
Quando disponibili
No comment provided by engineer.
+
+ When people request to connect, you can accept or reject it.
+ No comment provided by engineer.
+
When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.
Quando condividi un profilo in incognito con qualcuno, questo profilo verrà utilizzato per i gruppi a cui ti invitano.
@@ -4320,9 +4375,13 @@ SimpleX Lock deve essere attivato.
Puoi condividere un link o un codice QR: chiunque potrà unirsi al gruppo. Non perderai i membri del gruppo se in seguito lo elimini.
No comment provided by engineer.
-
- 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.
- 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.
+
+ You can share this address with your contacts to let them connect with **%@**.
+ No comment provided by engineer.
+
+
+ You can share your address as a link or QR code - anybody can connect to you.
+ Puoi condividere il tuo indirizzo come link o come codice QR: chiunque potrà connettersi a te.
No comment provided by engineer.
@@ -4435,6 +4494,11 @@ SimpleX Lock deve essere attivato.
Non riceverai più messaggi da questo gruppo. La cronologia della chat verrà conservata.
No comment provided by engineer.
+
+ You won't lose your contacts if you later delete your address.
+ Non perderai i tuoi contatti se in seguito lo elimini.
+ No comment provided by engineer.
+
You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile
Stai tentando di invitare un contatto con cui hai condiviso un profilo in incognito nel gruppo in cui stai usando il tuo profilo principale
@@ -4462,7 +4526,7 @@ SimpleX Lock deve essere attivato.
Your SimpleX contact address
- Il tuo indirizzo di contatto SimpleX
+ Il tuo indirizzo SimpleX
No comment provided by engineer.
@@ -4532,6 +4596,10 @@ Puoi annullare questa connessione e rimuovere il contatto (e riprovare più tard
I tuoi contatti possono consentire l'eliminazione completa dei messaggi.
No comment provided by engineer.
+
+ Your contacts will remain connected.
+ No comment provided by engineer.
+
Your current chat database will be DELETED and REPLACED with the imported one.
Il tuo attuale database della chat verrà ELIMINATO e SOSTITUITO con quello importato.
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 a144792be3..ff753124e3 100644
--- a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff
+++ b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff
@@ -361,6 +361,10 @@ Beschikbaar in v5.1
Over SimpleX Chat
No comment provided by engineer.
+
+ About SimpleX address
+ No comment provided by engineer.
+
Accent color
Accent kleur
@@ -387,9 +391,8 @@ Beschikbaar in v5.1
Accepteer incognito
No comment provided by engineer.
-
- Accept requests
- Verzoeken accepteren
+
+ Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -422,6 +425,10 @@ Beschikbaar in v5.1
Welkomst bericht toevoegen
No comment provided by engineer.
+
+ Address
+ No comment provided by engineer.
+
Admins can create the links to join groups.
Beheerders kunnen de uitnodiging links naar groepen aanmaken.
@@ -447,9 +454,12 @@ Beschikbaar in v5.1
Alle berichten worden verwijderd, dit kan niet ongedaan worden gemaakt! De berichten worden ALLEEN voor jou verwijderd.
No comment provided by engineer.
-
- All your contacts will remain connected
- Al uw contacten blijven verbonden
+
+ All your contacts will remain connected.
+ No comment provided by engineer.
+
+
+ All your contacts will remain connected. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -612,6 +622,10 @@ Beschikbaar in v5.1
Verificatie niet beschikbaar
No comment provided by engineer.
+
+ Auto-accept
+ No comment provided by engineer.
+
Auto-accept contact requests
Contact verzoeken automatisch accepteren
@@ -622,11 +636,6 @@ Beschikbaar in v5.1
Afbeeldingen automatisch accepteren
No comment provided by engineer.
-
- Automatically
- Automatisch
- No comment provided by engineer.
-
Back
Terug
@@ -992,11 +1001,6 @@ Beschikbaar in v5.1
Contact voorkeuren
No comment provided by engineer.
-
- Contact requests
- Contact verzoeken
- No comment provided by engineer.
-
Contacts can mark messages for deletion; you will be able to view them.
Contact personen kunnen berichten markeren voor verwijdering; u kunt ze wel bekijken.
@@ -1017,9 +1021,12 @@ Beschikbaar in v5.1
Maak
No comment provided by engineer.
-
- Create address
- Adres aanmaken
+
+ Create SimpleX address
+ No comment provided by engineer.
+
+
+ Create an address to let people connect with you.
No comment provided by engineer.
@@ -1590,6 +1597,10 @@ Beschikbaar in v5.1
Voer de server handmatig in
No comment provided by engineer.
+
+ Enter welcome message… (optional)
+ placeholder
+
Error
Fout
@@ -2343,6 +2354,10 @@ 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).
+ No comment provided by engineer.
+
Leave
Verlaten
@@ -2987,6 +3002,10 @@ Beschikbaar in v5.1
Profiel wachtwoord
No comment provided by engineer.
+
+ Profile update will be sent to your contacts.
+ No comment provided by engineer.
+
Prohibit audio/video calls.
Audio/video gesprekken verbieden.
@@ -3247,6 +3266,10 @@ Beschikbaar in v5.1
Bewaar archief
No comment provided by engineer.
+
+ Save auto-accept settings
+ No comment provided by engineer.
+
Save group profile
Groep profiel opslaan
@@ -3282,6 +3305,10 @@ Beschikbaar in v5.1
Servers opslaan?
No comment provided by engineer.
+
+ Save settings?
+ No comment provided by engineer.
+
Save welcome message?
Welkomst bericht opslaan?
@@ -3472,6 +3499,14 @@ Beschikbaar in v5.1
Deel
chat item action
+
+ Share address
+ No comment provided by engineer.
+
+
+ Share address with contacts?
+ No comment provided by engineer.
+
Share invitation link
Uitnodiging link delen
@@ -3487,6 +3522,10 @@ Beschikbaar in v5.1
Eenmalige uitnodiging link delen
No comment provided by engineer.
+
+ Share with contacts
+ No comment provided by engineer.
+
Show QR code
Toon QR-code
@@ -3537,6 +3576,10 @@ Beschikbaar in v5.1
SimpleX Vergrendelen ingeschakeld
No comment provided by engineer.
+
+ SimpleX address
+ No comment provided by engineer.
+
SimpleX contact address
SimpleX contact adres
@@ -3632,6 +3675,14 @@ Beschikbaar in v5.1
Bestand verzenden stoppen?
No comment provided by engineer.
+
+ Stop sharing
+ No comment provided by engineer.
+
+
+ Stop sharing address?
+ No comment provided by engineer.
+
Submit
Indienen
@@ -4228,6 +4279,10 @@ Om verbinding te maken, vraagt u uw contactpersoon om een andere verbinding link
Wanneer beschikbaar
No comment provided by engineer.
+
+ When people request to connect, you can accept or reject it.
+ No comment provided by engineer.
+
When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.
Wanneer je een incognito profiel met iemand deelt, wordt dit profiel gebruikt voor de groepen waarvoor ze je uitnodigen.
@@ -4320,9 +4375,13 @@ SimpleX Lock moet ingeschakeld zijn.
U kunt een link of een QR-code delen. Iedereen kan lid worden van de groep. U verliest geen leden van de groep als u deze later verwijdert.
No comment provided by engineer.
-
- 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.
- 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.
+
+ You can share this address with your contacts to let them connect with **%@**.
+ No comment provided by engineer.
+
+
+ You can share your address as a link or QR code - anybody can connect to you.
+ U kunt uw adres delen als een link of als een QR-code. Iedereen kan verbinding met u maken.
No comment provided by engineer.
@@ -4435,6 +4494,11 @@ SimpleX Lock moet ingeschakeld zijn.
Je ontvangt geen berichten meer van deze groep. Je gesprek geschiedenis blijft behouden.
No comment provided by engineer.
+
+ You won't lose your contacts if you later delete your address.
+ U verliest uw contacten niet als u deze later verwijdert.
+ No comment provided by engineer.
+
You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile
Je probeert een contact met wie je een incognito profiel hebt gedeeld, uit te nodigen voor de groep waarin je je hoofdprofiel gebruikt
@@ -4462,7 +4526,7 @@ SimpleX Lock moet ingeschakeld zijn.
Your SimpleX contact address
- Uw SimpleX contact adres
+ Uw SimpleX adres
No comment provided by engineer.
@@ -4532,6 +4596,10 @@ U kunt deze verbinding verbreken en het contact verwijderen (en later proberen m
Uw contacten kunnen volledige verwijdering van berichten toestaan.
No comment provided by engineer.
+
+ Your contacts will remain connected.
+ No comment provided by engineer.
+
Your current chat database will be DELETED and REPLACED with the imported one.
Uw huidige chat database wordt VERWIJDERD en VERVANGEN door de geïmporteerde.
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 78156e1239..3e71f25887 100644
--- a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff
+++ b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff
@@ -361,6 +361,10 @@ Dostępny w v5.1
O SimpleX Chat
No comment provided by engineer.
+
+ About SimpleX address
+ No comment provided by engineer.
+
Accent color
Kolor akcentu
@@ -387,9 +391,8 @@ Dostępny w v5.1
Akceptuj incognito
No comment provided by engineer.
-
- Accept requests
- Akceptuj prośby
+
+ Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -422,6 +425,10 @@ Dostępny w v5.1
Dodaj wiadomość powitalną
No comment provided by engineer.
+
+ Address
+ No comment provided by engineer.
+
Admins can create the links to join groups.
Administratorzy mogą tworzyć linki do dołączania do grup.
@@ -447,9 +454,12 @@ Dostępny w v5.1
Wszystkie wiadomości zostaną usunięte - nie można tego cofnąć! Wiadomości zostaną usunięte TYLKO dla Ciebie.
No comment provided by engineer.
-
- All your contacts will remain connected
- Wszystkie Twoje kontakty pozostaną połączone
+
+ All your contacts will remain connected.
+ No comment provided by engineer.
+
+
+ All your contacts will remain connected. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -612,6 +622,10 @@ Dostępny w v5.1
Uwierzytelnianie niedostępne
No comment provided by engineer.
+
+ Auto-accept
+ No comment provided by engineer.
+
Auto-accept contact requests
Automatyczne akceptowanie próśb o kontakt
@@ -622,11 +636,6 @@ Dostępny w v5.1
Automatyczne akceptowanie obrazów
No comment provided by engineer.
-
- Automatically
- Automatycznie
- No comment provided by engineer.
-
Back
Wstecz
@@ -992,11 +1001,6 @@ Dostępny w v5.1
Preferencje kontaktu
No comment provided by engineer.
-
- Contact requests
- Prośby kontaktu
- No comment provided by engineer.
-
Contacts can mark messages for deletion; you will be able to view them.
Kontakty mogą oznaczać wiadomości do usunięcia; będziesz mógł je zobaczyć.
@@ -1017,9 +1021,12 @@ Dostępny w v5.1
Utwórz
No comment provided by engineer.
-
- Create address
- Utwórz adres
+
+ Create SimpleX address
+ No comment provided by engineer.
+
+
+ Create an address to let people connect with you.
No comment provided by engineer.
@@ -1590,6 +1597,10 @@ Dostępny w v5.1
Wprowadź serwer ręcznie
No comment provided by engineer.
+
+ Enter welcome message… (optional)
+ placeholder
+
Error
Błąd
@@ -2343,6 +2354,10 @@ 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).
+ No comment provided by engineer.
+
Leave
Opuść
@@ -2987,6 +3002,10 @@ Dostępny w v5.1
Hasło profilu
No comment provided by engineer.
+
+ Profile update will be sent to your contacts.
+ No comment provided by engineer.
+
Prohibit audio/video calls.
Zabroń połączeń audio/wideo.
@@ -3247,6 +3266,10 @@ Dostępny w v5.1
Zapisz archiwum
No comment provided by engineer.
+
+ Save auto-accept settings
+ No comment provided by engineer.
+
Save group profile
Zapisz profil grupy
@@ -3282,6 +3305,10 @@ Dostępny w v5.1
Zapisać serwery?
No comment provided by engineer.
+
+ Save settings?
+ No comment provided by engineer.
+
Save welcome message?
Zapisać wiadomość powitalną?
@@ -3472,6 +3499,14 @@ Dostępny w v5.1
Udostępnij
chat item action
+
+ Share address
+ No comment provided by engineer.
+
+
+ Share address with contacts?
+ No comment provided by engineer.
+
Share invitation link
Udostępnij link zaproszenia
@@ -3487,6 +3522,10 @@ Dostępny w v5.1
Jednorazowy link zaproszenia
No comment provided by engineer.
+
+ Share with contacts
+ No comment provided by engineer.
+
Show QR code
Pokaż kod QR
@@ -3537,6 +3576,10 @@ Dostępny w v5.1
Blokada SimpleX włączona
No comment provided by engineer.
+
+ SimpleX address
+ No comment provided by engineer.
+
SimpleX contact address
Adres kontaktowy SimpleX
@@ -3632,6 +3675,14 @@ Dostępny w v5.1
Przestać wysyłać plik?
No comment provided by engineer.
+
+ Stop sharing
+ No comment provided by engineer.
+
+
+ Stop sharing address?
+ No comment provided by engineer.
+
Submit
Zatwierdź
@@ -4228,6 +4279,10 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
Gdy dostępny
No comment provided by engineer.
+
+ When people request to connect, you can accept or reject it.
+ No comment provided by engineer.
+
When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.
Gdy udostępnisz komuś profil incognito, będzie on używany w grupach, do których Cię zaprosi.
@@ -4320,9 +4375,13 @@ Funkcja blokady SimpleX musi być włączona.
Możesz udostępnić link lub kod QR - każdy będzie mógł dołączyć do grupy. Nie stracisz członków grupy, jeśli później ją usuniesz.
No comment provided by engineer.
-
- 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.
- 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.
+
+ You can share this address with your contacts to let them connect with **%@**.
+ No comment provided by engineer.
+
+
+ You can share your address as a link or QR code - anybody can connect to you.
+ Możesz udostępnić swój adres jako link lub jako kod QR - każdy będzie mógł się z Tobą połączyć.
No comment provided by engineer.
@@ -4435,6 +4494,11 @@ Funkcja blokady SimpleX musi być włączona.
Przestaniesz otrzymywać wiadomości od tej grupy. Historia czatu zostanie zachowana.
No comment provided by engineer.
+
+ You won't lose your contacts if you later delete your address.
+ Nie stracisz swoich kontaktów, jeśli później go usuniesz.
+ No comment provided by engineer.
+
You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile
Próbujesz zaprosić osobę, z którą masz wspólny profil incognito do grupy, w której używasz swojego głównego profilu
@@ -4462,7 +4526,7 @@ Funkcja blokady SimpleX musi być włączona.
Your SimpleX contact address
- Twój adres kontaktowy SimpleX
+ Twój adres SimpleX
No comment provided by engineer.
@@ -4532,6 +4596,10 @@ Możesz anulować to połączenie i usunąć kontakt (i spróbować później z
Twoje kontakty mogą zezwolić na pełne usunięcie wiadomości.
No comment provided by engineer.
+
+ Your contacts will remain connected.
+ No comment provided by engineer.
+
Your current chat database will be DELETED and REPLACED with the imported one.
Twoja obecna baza danych czatu zostanie usunięta i zastąpiona zaimportowaną.
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 6bb8229a32..a0e4c600b1 100644
--- a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff
+++ b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff
@@ -361,6 +361,10 @@ Available in v5.1
Информация о SimpleX Chat
No comment provided by engineer.
+
+ About SimpleX address
+ No comment provided by engineer.
+
Accent color
Основной цвет
@@ -387,9 +391,8 @@ Available in v5.1
Принять инкогнито
No comment provided by engineer.
-
- Accept requests
- Принимать запросы
+
+ Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -422,6 +425,10 @@ Available in v5.1
Добавить приветственное сообщение
No comment provided by engineer.
+
+ Address
+ No comment provided by engineer.
+
Admins can create the links to join groups.
Админы могут создать ссылки для вступления в группу.
@@ -447,9 +454,12 @@ Available in v5.1
Все сообщения будут удалены - это действие нельзя отменить! Сообщения будут удалены только для Вас.
No comment provided by engineer.
-
- All your contacts will remain connected
- Все контакты, которые соединились через этот адрес, сохранятся.
+
+ All your contacts will remain connected.
+ No comment provided by engineer.
+
+
+ All your contacts will remain connected. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -612,6 +622,10 @@ Available in v5.1
Аутентификация недоступна
No comment provided by engineer.
+
+ Auto-accept
+ No comment provided by engineer.
+
Auto-accept contact requests
Автоматически принимать запросы контактов
@@ -622,11 +636,6 @@ Available in v5.1
Автоприем изображений
No comment provided by engineer.
-
- Automatically
- Автоматически
- No comment provided by engineer.
-
Back
Назад
@@ -992,11 +1001,6 @@ Available in v5.1
Предпочтения контакта
No comment provided by engineer.
-
- Contact requests
- Запросы контактов
- No comment provided by engineer.
-
Contacts can mark messages for deletion; you will be able to view them.
Контакты могут помечать сообщения для удаления; Вы сможете просмотреть их.
@@ -1017,9 +1021,12 @@ Available in v5.1
Создать
No comment provided by engineer.
-
- Create address
- Создать адрес
+
+ Create SimpleX address
+ No comment provided by engineer.
+
+
+ Create an address to let people connect with you.
No comment provided by engineer.
@@ -1590,6 +1597,10 @@ Available in v5.1
Ввести сервер вручную
No comment provided by engineer.
+
+ Enter welcome message… (optional)
+ placeholder
+
Error
Ошибка
@@ -2343,6 +2354,10 @@ 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).
+ No comment provided by engineer.
+
Leave
Выйти
@@ -2987,6 +3002,10 @@ Available in v5.1
Пароль профиля
No comment provided by engineer.
+
+ Profile update will be sent to your contacts.
+ No comment provided by engineer.
+
Prohibit audio/video calls.
Запретить аудио/видео звонки.
@@ -3247,6 +3266,10 @@ Available in v5.1
Сохранить архив
No comment provided by engineer.
+
+ Save auto-accept settings
+ No comment provided by engineer.
+
Save group profile
Сохранить профиль группы
@@ -3282,6 +3305,10 @@ Available in v5.1
Сохранить серверы?
No comment provided by engineer.
+
+ Save settings?
+ No comment provided by engineer.
+
Save welcome message?
Сохранить приветственное сообщение?
@@ -3472,6 +3499,14 @@ Available in v5.1
Поделиться
chat item action
+
+ Share address
+ No comment provided by engineer.
+
+
+ Share address with contacts?
+ No comment provided by engineer.
+
Share invitation link
Поделиться ссылкой
@@ -3487,6 +3522,10 @@ Available in v5.1
Поделиться ссылкой-приглашением
No comment provided by engineer.
+
+ Share with contacts
+ No comment provided by engineer.
+
Show QR code
Показать QR код
@@ -3537,6 +3576,10 @@ Available in v5.1
Блокировка SimpleX включена
No comment provided by engineer.
+
+ SimpleX address
+ No comment provided by engineer.
+
SimpleX contact address
SimpleX ссылка-контакт
@@ -3632,6 +3675,14 @@ Available in v5.1
Остановить отправку файла?
No comment provided by engineer.
+
+ Stop sharing
+ No comment provided by engineer.
+
+
+ Stop sharing address?
+ No comment provided by engineer.
+
Submit
Продолжить
@@ -4228,6 +4279,10 @@ To connect, please ask your contact to create another connection link and check
Когда возможно
No comment provided by engineer.
+
+ When people request to connect, you can accept or reject it.
+ No comment provided by engineer.
+
When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.
Когда Вы соединены с контактом инкогнито, тот же самый инкогнито профиль будет использоваться для групп с этим контактом.
@@ -4320,9 +4375,13 @@ SimpleX Lock must be enabled.
Вы можете поделиться ссылкой или QR кодом - через них можно присоединиться к группе. Вы сможете удалить ссылку, сохранив членов группы, которые через нее соединились.
No comment provided by engineer.
-
- 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.
- Вы можете использовать Ваш адрес как ссылку или как QR код - кто угодно сможет соединиться с Вами. Вы сможете удалить адрес, сохранив контакты, которые через него соединились.
+
+ You can share this address with your contacts to let them connect with **%@**.
+ No comment provided by engineer.
+
+
+ You can share your address as a link or QR code - anybody can connect to you.
+ Вы можете использовать Ваш адрес как ссылку или как QR код - кто угодно сможет соединиться с Вами.
No comment provided by engineer.
@@ -4435,6 +4494,11 @@ SimpleX Lock must be enabled.
Вы перестанете получать сообщения от этой группы. История чата будет сохранена.
No comment provided by engineer.
+
+ You won't lose your contacts if you later delete your address.
+ Вы сможете удалить адрес, сохранив контакты, которые через него соединились.
+ No comment provided by engineer.
+
You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile
Вы пытаетесь пригласить инкогнито контакт в группу, где Вы используете свой основной профиль
@@ -4532,6 +4596,10 @@ You can cancel this connection and remove the contact (and try later with a new
Ваши контакты могут разрешить окончательное удаление сообщений.
No comment provided by engineer.
+
+ Your contacts will remain connected.
+ No comment provided by engineer.
+
Your current chat database will be DELETED and REPLACED with the imported one.
Текущие данные Вашего чата будет УДАЛЕНЫ и ЗАМЕНЕНЫ импортированными.
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 a518d5f499..1a525f62b6 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
@@ -361,6 +361,10 @@ Available in v5.1
关于SimpleX Chat
No comment provided by engineer.
+
+ About SimpleX address
+ No comment provided by engineer.
+
Accent color
色调
@@ -387,9 +391,8 @@ Available in v5.1
接受隐身聊天
No comment provided by engineer.
-
- Accept requests
- 接受请求
+
+ Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -422,6 +425,10 @@ Available in v5.1
添加欢迎信息
No comment provided by engineer.
+
+ Address
+ No comment provided by engineer.
+
Admins can create the links to join groups.
管理员可以创建链接以加入群组。
@@ -447,9 +454,12 @@ Available in v5.1
所有聊天记录和消息将被删除——这一行为无法撤销!只有您的消息会被删除。
No comment provided by engineer.
-
- All your contacts will remain connected
- 您的所有联系人将保持连接
+
+ All your contacts will remain connected.
+ No comment provided by engineer.
+
+
+ All your contacts will remain connected. Profile update will be sent to your contacts.
No comment provided by engineer.
@@ -612,6 +622,10 @@ Available in v5.1
身份验证不可用
No comment provided by engineer.
+
+ Auto-accept
+ No comment provided by engineer.
+
Auto-accept contact requests
自动接受联系人请求
@@ -622,11 +636,6 @@ Available in v5.1
自动接受图片
No comment provided by engineer.
-
- Automatically
- 自动
- No comment provided by engineer.
-
Back
返回
@@ -992,11 +1001,6 @@ Available in v5.1
联系人偏好设置
No comment provided by engineer.
-
- Contact requests
- 联系人请求
- No comment provided by engineer.
-
Contacts can mark messages for deletion; you will be able to view them.
联系人可以将信息标记为删除;您将可以查看这些信息。
@@ -1017,9 +1021,12 @@ Available in v5.1
创建
No comment provided by engineer.
-
- Create address
- 创建地址
+
+ Create SimpleX address
+ No comment provided by engineer.
+
+
+ Create an address to let people connect with you.
No comment provided by engineer.
@@ -1590,6 +1597,10 @@ Available in v5.1
手动输入服务器
No comment provided by engineer.
+
+ Enter welcome message… (optional)
+ placeholder
+
Error
错误
@@ -2343,6 +2354,10 @@ 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).
+ No comment provided by engineer.
+
Leave
离开
@@ -2987,6 +3002,10 @@ Available in v5.1
个人资料密码
No comment provided by engineer.
+
+ Profile update will be sent to your contacts.
+ No comment provided by engineer.
+
Prohibit audio/video calls.
禁止音频/视频通话。
@@ -3247,6 +3266,10 @@ Available in v5.1
保存存档
No comment provided by engineer.
+
+ Save auto-accept settings
+ No comment provided by engineer.
+
Save group profile
保存群组资料
@@ -3282,6 +3305,10 @@ Available in v5.1
保存服务器?
No comment provided by engineer.
+
+ Save settings?
+ No comment provided by engineer.
+
Save welcome message?
保存欢迎信息?
@@ -3472,6 +3499,14 @@ Available in v5.1
分享
chat item action
+
+ Share address
+ No comment provided by engineer.
+
+
+ Share address with contacts?
+ No comment provided by engineer.
+
Share invitation link
分享邀请链接
@@ -3487,6 +3522,10 @@ Available in v5.1
分享一次性邀请链接
No comment provided by engineer.
+
+ Share with contacts
+ No comment provided by engineer.
+
Show QR code
显示二维码
@@ -3537,6 +3576,10 @@ Available in v5.1
已开启 SimpleX 锁定
No comment provided by engineer.
+
+ SimpleX address
+ No comment provided by engineer.
+
SimpleX contact address
SimpleX 联系地址
@@ -3632,6 +3675,14 @@ Available in v5.1
停止发送文件?
No comment provided by engineer.
+
+ Stop sharing
+ No comment provided by engineer.
+
+
+ Stop sharing address?
+ No comment provided by engineer.
+
Submit
提交
@@ -4228,6 +4279,10 @@ To connect, please ask your contact to create another connection link and check
当可用时
No comment provided by engineer.
+
+ When people request to connect, you can accept or reject it.
+ No comment provided by engineer.
+
When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.
当您与某人共享隐身聊天资料时,该资料将用于他们邀请您加入的群组。
@@ -4320,9 +4375,13 @@ SimpleX Lock must be enabled.
您可以共享链接或二维码——任何人都可以加入该群组。如果您稍后将其删除,您不会失去该组的成员。
No comment provided by engineer.
-
- 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.
- 您可以将您的地址作为链接或二维码共享——任何人都可以连接到您。 如果您以后删除它,您不会丢失您的联系人。
+
+ You can share this address with your contacts to let them connect with **%@**.
+ No comment provided by engineer.
+
+
+ You can share your address as a link or QR code - anybody can connect to you.
+ 您可以将您的地址作为链接或二维码共享——任何人都可以连接到您。
No comment provided by engineer.
@@ -4435,6 +4494,11 @@ SimpleX Lock must be enabled.
您将停止接收来自该群组的消息。聊天记录将被保留。
No comment provided by engineer.
+
+ You won't lose your contacts if you later delete your address.
+ 如果您以后删除它,您不会丢失您的联系人。
+ No comment provided by engineer.
+
You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile
您正在尝试邀请与您共享隐身个人资料的联系人加入您使用主要个人资料的群组
@@ -4532,6 +4596,10 @@ You can cancel this connection and remove the contact (and try later with a new
您的联系人可以允许完全删除消息。
No comment provided by engineer.
+
+ Your contacts will remain connected.
+ No comment provided by engineer.
+
Your current chat database will be DELETED and REPLACED with the imported one.
您当前的聊天数据库将被删除并替换为导入的数据库。
diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj
index 8bed72bb71..3d666c7578 100644
--- a/apps/ios/SimpleX.xcodeproj/project.pbxproj
+++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj
@@ -104,7 +104,6 @@
5CB634B129E5EFEA0066AD6B /* PasscodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB634B029E5EFEA0066AD6B /* PasscodeView.swift */; };
5CB924D727A8563F00ACCCDD /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB924D627A8563F00ACCCDD /* SettingsView.swift */; };
5CB924E127A867BA00ACCCDD /* UserProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB924E027A867BA00ACCCDD /* UserProfile.swift */; };
- 5CB924E427A8683A00ACCCDD /* UserAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB924E327A8683A00ACCCDD /* UserAddress.swift */; };
5CB9250D27A9432000ACCCDD /* ChatListNavLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB9250C27A9432000ACCCDD /* ChatListNavLink.swift */; };
5CBD285A295711D700EC2CF4 /* ImageUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CBD2859295711D700EC2CF4 /* ImageUtils.swift */; };
5CBD285C29575B8E00EC2CF4 /* WhatsNewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CBD285B29575B8E00EC2CF4 /* WhatsNewView.swift */; };
@@ -116,7 +115,6 @@
5CC2C0FC2809BF11000C35E3 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CC2C0FA2809BF11000C35E3 /* Localizable.strings */; };
5CC2C0FF2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CC2C0FD2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings */; };
5CC868F329EB540C0017BBFD /* CIRcvDecryptionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC868F229EB540C0017BBFD /* CIRcvDecryptionError.swift */; };
- 5CCA7DF32905735700C8FEBA /* AcceptRequestsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCA7DF22905735700C8FEBA /* AcceptRequestsView.swift */; };
5CCB939C297EFCB100399E78 /* NavStackCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCB939B297EFCB100399E78 /* NavStackCompat.swift */; };
5CCD403427A5F6DF00368C90 /* AddContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403327A5F6DF00368C90 /* AddContactView.swift */; };
5CCD403727A5F9A200368C90 /* ScanToConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */; };
@@ -172,6 +170,9 @@
649BCDA22805D6EF00C3A862 /* CIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCDA12805D6EF00C3A862 /* CIImageView.swift */; };
64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */; };
64AA1C6C27F3537400AC7277 /* DeletedItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */; };
+ 64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; };
+ 64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */; };
+ 64D0C2C629FAC1EC00B38D5F /* AddContactLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C529FAC1EC00B38D5F /* AddContactLearnMore.swift */; };
64E972072881BB22008DBC02 /* CIGroupInvitationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E972062881BB22008DBC02 /* CIGroupInvitationView.swift */; };
64F1CC3B28B39D8600CD1FB1 /* IncognitoHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */; };
D7197A1829AE89660055C05A /* WebRTC in Frameworks */ = {isa = PBXBuildFile; productRef = D7197A1729AE89660055C05A /* WebRTC */; };
@@ -368,7 +369,6 @@
5CB634B029E5EFEA0066AD6B /* PasscodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasscodeView.swift; sourceTree = ""; };
5CB924D627A8563F00ACCCDD /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; };
5CB924E027A867BA00ACCCDD /* UserProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfile.swift; sourceTree = ""; };
- 5CB924E327A8683A00ACCCDD /* UserAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddress.swift; sourceTree = ""; };
5CB9250C27A9432000ACCCDD /* ChatListNavLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListNavLink.swift; sourceTree = ""; };
5CBD285529565CAE00EC2CF4 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; };
5CBD285629565CAE00EC2CF4 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; };
@@ -384,7 +384,6 @@
5CC2C0FB2809BF11000C35E3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; };
5CC2C0FE2809BF11000C35E3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = "ru.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = ""; };
5CC868F229EB540C0017BBFD /* CIRcvDecryptionError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIRcvDecryptionError.swift; sourceTree = ""; };
- 5CCA7DF22905735700C8FEBA /* AcceptRequestsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AcceptRequestsView.swift; sourceTree = ""; };
5CCB939B297EFCB100399E78 /* NavStackCompat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavStackCompat.swift; sourceTree = ""; };
5CCD403327A5F6DF00368C90 /* AddContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddContactView.swift; sourceTree = ""; };
5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanToConnectView.swift; sourceTree = ""; };
@@ -439,6 +438,9 @@
649BCDA12805D6EF00C3A862 /* CIImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIImageView.swift; sourceTree = ""; };
64AA1C6827EE10C800AC7277 /* ContextItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextItemView.swift; sourceTree = ""; };
64AA1C6B27F3537400AC7277 /* DeletedItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedItemView.swift; sourceTree = ""; };
+ 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = ""; };
+ 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressLearnMore.swift; sourceTree = ""; };
+ 64D0C2C529FAC1EC00B38D5F /* AddContactLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddContactLearnMore.swift; sourceTree = ""; };
64DAE1502809D9F5000DA960 /* FileUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = ""; };
64E972062881BB22008DBC02 /* CIGroupInvitationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIGroupInvitationView.swift; sourceTree = ""; };
64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncognitoHelp.swift; sourceTree = ""; };
@@ -694,6 +696,7 @@
6442E0B9287F169300CEC0F9 /* AddGroupView.swift */,
5CB2085028DB64CA00D024EC /* CreateLinkView.swift */,
5CB2085228DB7CAF00D024EC /* ConnectViaLinkView.swift */,
+ 64D0C2C529FAC1EC00B38D5F /* AddContactLearnMore.swift */,
);
path = NewChat;
sourceTree = "";
@@ -709,8 +712,6 @@
5C5DB70D289ABDD200730FFF /* AppearanceSettings.swift */,
5C05DF522840AA1D00C683F9 /* CallSettings.swift */,
5C3F1D57284363C400EC8A82 /* PrivacySettings.swift */,
- 5CB924E327A8683A00ACCCDD /* UserAddress.swift */,
- 5CCA7DF22905735700C8FEBA /* AcceptRequestsView.swift */,
5CB924E027A867BA00ACCCDD /* UserProfile.swift */,
5CC036DF29C488D500C0EF20 /* HiddenProfileView.swift */,
5C577F7C27C83AA10006112D /* MarkdownHelp.swift */,
@@ -722,6 +723,8 @@
18415845648CA4F5A8BCA272 /* UserProfilesView.swift */,
5C65F341297D3F3600B67AF3 /* VersionView.swift */,
5C65DAF829D0CC20003CEE45 /* DeveloperView.swift */,
+ 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */,
+ 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */,
);
path = UserSettings;
sourceTree = "";
@@ -1069,7 +1072,6 @@
5CE4407927ADB701007B033A /* EmojiItemView.swift in Sources */,
5C3F1D562842B68D00EC8A82 /* IntegrityErrorItemView.swift in Sources */,
5C029EAA283942EA004A9677 /* CallController.swift in Sources */,
- 5CCA7DF32905735700C8FEBA /* AcceptRequestsView.swift in Sources */,
5CBE6C142944CC12002D9531 /* ScanCodeView.swift in Sources */,
5CC036E029C488D500C0EF20 /* HiddenProfileView.swift in Sources */,
5C5346A827B59A6A004DF848 /* ChatHelp.swift in Sources */,
@@ -1088,8 +1090,8 @@
5C10D88A28F187F300E58BF0 /* FullScreenMediaView.swift in Sources */,
D72A9088294BD7A70047C86D /* NativeTextEditor.swift in Sources */,
5C00164428A26FBC0094D739 /* ContextMenu.swift in Sources */,
+ 64D0C2C629FAC1EC00B38D5F /* AddContactLearnMore.swift in Sources */,
5C3A88D127DF57800060F1C2 /* FramedItemView.swift in Sources */,
- 5CB924E427A8683A00ACCCDD /* UserAddress.swift in Sources */,
5C65F343297D45E100B67AF3 /* VersionView.swift in Sources */,
64F1CC3B28B39D8600CD1FB1 /* IncognitoHelp.swift in Sources */,
5CB0BA90282713D900B3292C /* SimpleXInfo.swift in Sources */,
@@ -1126,6 +1128,7 @@
5C2E260F27A30FDC00F70299 /* ChatView.swift in Sources */,
5C2E260B27A30CFA00F70299 /* ChatListView.swift in Sources */,
6442E0BA287F169300CEC0F9 /* AddGroupView.swift in Sources */,
+ 64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */,
5C971E2127AEBF8300C8A3CE /* ChatInfoImage.swift in Sources */,
5C55A921283CCCB700C4E99E /* IncomingCallView.swift in Sources */,
6454036F2822A9750090DDFF /* ComposeFileView.swift in Sources */,
@@ -1137,6 +1140,7 @@
6407BA83295DA85D0082BA18 /* CIInvalidJSONView.swift in Sources */,
644EFFDE292BCD9D00525D5B /* ComposeVoiceView.swift in Sources */,
5CA059EB279559F40002BEB4 /* SimpleXApp.swift in Sources */,
+ 64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */,
6448BBB628FA9D56000D2AB9 /* GroupLinkView.swift in Sources */,
5CB346E92869E8BA001FD2EF /* PushEnvironment.swift in Sources */,
5C55A91F283AD0E400C4E99E /* CallManager.swift in Sources */,
diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift
index b1021c5130..53ae7e8849 100644
--- a/apps/ios/SimpleXChat/APITypes.swift
+++ b/apps/ios/SimpleXChat/APITypes.swift
@@ -85,6 +85,7 @@ public enum ChatCommand {
case apiCreateMyAddress(userId: Int64)
case apiDeleteMyAddress(userId: Int64)
case apiShowMyAddress(userId: Int64)
+ case apiSetProfileAddress(userId: Int64, on: Bool)
case apiAddressAutoAccept(userId: Int64, autoAccept: AutoAccept?)
case apiAcceptContact(contactReqId: Int64)
case apiRejectContact(contactReqId: Int64)
@@ -189,6 +190,7 @@ public enum ChatCommand {
case let .apiCreateMyAddress(userId): return "/_address \(userId)"
case let .apiDeleteMyAddress(userId): return "/_delete_address \(userId)"
case let .apiShowMyAddress(userId): return "/_show_address \(userId)"
+ case let .apiSetProfileAddress(userId, on): return "/_profile_address \(userId) \(onOff(on))"
case let .apiAddressAutoAccept(userId, autoAccept): return "/_auto_accept \(userId) \(AutoAccept.cmdString(autoAccept))"
case let .apiAcceptContact(contactReqId): return "/_accept \(contactReqId)"
case let .apiRejectContact(contactReqId): return "/_reject \(contactReqId)"
@@ -290,6 +292,7 @@ public enum ChatCommand {
case .apiCreateMyAddress: return "apiCreateMyAddress"
case .apiDeleteMyAddress: return "apiDeleteMyAddress"
case .apiShowMyAddress: return "apiShowMyAddress"
+ case .apiSetProfileAddress: return "apiSetProfileAddress"
case .apiAddressAutoAccept: return "apiAddressAutoAccept"
case .apiAcceptContact: return "apiAcceptContact"
case .apiRejectContact: return "apiRejectContact"
diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift
index a449af1c3c..f82bb844bc 100644
--- a/apps/ios/SimpleXChat/ChatTypes.swift
+++ b/apps/ios/SimpleXChat/ChatTypes.swift
@@ -33,6 +33,10 @@ public struct User: Decodable, NamedChat, Identifiable {
activeUser || showNtfs
}
+ public var addressShared: Bool {
+ profile.contactLink != nil
+ }
+
public static let sampleData = User(
userId: 1,
userContactId: 1,
@@ -71,16 +75,24 @@ public typealias ContactName = String
public typealias GroupName = String
public struct Profile: Codable, NamedChat {
- public init(displayName: String, fullName: String, image: String? = nil, preferences: Preferences? = nil) {
+ public init(
+ displayName: String,
+ fullName: String,
+ image: String? = nil,
+ contactLink: String? = nil,
+ preferences: Preferences? = nil
+ ) {
self.displayName = displayName
self.fullName = fullName
self.image = image
+ self.contactLink = contactLink
self.preferences = preferences
}
public var displayName: String
public var fullName: String
public var image: String?
+ public var contactLink: String?
public var preferences: Preferences?
public var localAlias: String { get { "" } }
@@ -95,11 +107,20 @@ public struct Profile: Codable, NamedChat {
}
public struct LocalProfile: Codable, NamedChat {
- public init(profileId: Int64, displayName: String, fullName: String, image: String? = nil, preferences: Preferences? = nil, localAlias: String) {
+ public init(
+ profileId: Int64,
+ displayName: String,
+ fullName: String,
+ image: String? = nil,
+ contactLink: String? = nil,
+ preferences: Preferences? = nil,
+ localAlias: String
+ ) {
self.profileId = profileId
self.displayName = displayName
self.fullName = fullName
self.image = image
+ self.contactLink = contactLink
self.preferences = preferences
self.localAlias = localAlias
}
@@ -108,6 +129,7 @@ public struct LocalProfile: Codable, NamedChat {
public var displayName: String
public var fullName: String
public var image: String?
+ public var contactLink: String?
public var preferences: Preferences?
public var localAlias: String
@@ -127,11 +149,11 @@ public struct LocalProfile: Codable, NamedChat {
}
public func toLocalProfile (_ profileId: Int64, _ profile: Profile, _ localAlias: String) -> LocalProfile {
- LocalProfile(profileId: profileId, displayName: profile.displayName, fullName: profile.fullName, image: profile.image, preferences: profile.preferences, localAlias: localAlias)
+ LocalProfile(profileId: profileId, displayName: profile.displayName, fullName: profile.fullName, image: profile.image, contactLink: profile.contactLink, preferences: profile.preferences, localAlias: localAlias)
}
public func fromLocalProfile (_ profile: LocalProfile) -> Profile {
- Profile(displayName: profile.displayName, fullName: profile.fullName, image: profile.image, preferences: profile.preferences)
+ Profile(displayName: profile.displayName, fullName: profile.fullName, image: profile.image, contactLink: profile.contactLink, preferences: profile.preferences)
}
public enum ChatType: String {
@@ -1164,6 +1186,7 @@ public struct Contact: Identifiable, Decodable, NamedChat {
public var displayName: String { localAlias == "" ? profile.displayName : localAlias }
public var fullName: String { get { profile.fullName } }
public var image: String? { get { profile.image } }
+ public var contactLink: String? { get { profile.contactLink } }
public var localAlias: String { profile.localAlias }
public var verified: Bool { activeConn.connectionCode != nil }
@@ -1508,6 +1531,7 @@ public struct GroupMember: Identifiable, Decodable {
}
public var fullName: String { get { memberProfile.fullName } }
public var image: String? { get { memberProfile.image } }
+ public var contactLink: String? { get { memberProfile.contactLink } }
public var verified: Bool { activeConn?.connectionCode != nil }
var directChatId: ChatId? {
diff --git a/simplex-chat.cabal b/simplex-chat.cabal
index 7cfe9ead06..995f5c3cb6 100644
--- a/simplex-chat.cabal
+++ b/simplex-chat.cabal
@@ -92,6 +92,7 @@ library
Simplex.Chat.Migrations.M20230402_protocol_servers
Simplex.Chat.Migrations.M20230411_extra_xftp_file_descriptions
Simplex.Chat.Migrations.M20230420_rcv_files_to_receive
+ Simplex.Chat.Migrations.M20230422_profile_contact_links
Simplex.Chat.Mobile
Simplex.Chat.Mobile.WebRTC
Simplex.Chat.Options
diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs
index e241e0357f..2cf37abb54 100644
--- a/src/Simplex/Chat.hs
+++ b/src/Simplex/Chat.hs
@@ -1123,18 +1123,32 @@ processChatCommand = \case
pure $ CRUserContactLinkCreated user cReq
CreateMyAddress -> withUser $ \User {userId} ->
processChatCommand $ APICreateMyAddress userId
- APIDeleteMyAddress userId -> withUserId userId $ \user -> withChatLock "deleteMyAddress" $ do
+ APIDeleteMyAddress userId -> withUserId userId $ \user@User {profile = p} -> do
conns <- withStore (`getUserAddressConnections` user)
- procCmd $ do
+ withChatLock "deleteMyAddress" $ do
deleteAgentConnectionsAsync user $ map aConnId conns
withStore' (`deleteUserAddress` user)
- pure $ CRUserContactLinkDeleted user
+ let p' = (fromLocalProfile p :: Profile) {contactLink = Nothing}
+ r <- updateProfile_ user p' $ withStore' $ \db -> setUserProfileContactLink db user Nothing
+ let user' = case r of
+ CRUserProfileUpdated u' _ _ -> u'
+ _ -> user
+ pure $ CRUserContactLinkDeleted user'
DeleteMyAddress -> withUser $ \User {userId} ->
processChatCommand $ APIDeleteMyAddress userId
APIShowMyAddress userId -> withUserId userId $ \user ->
CRUserContactLink user <$> withStore (`getUserAddress` user)
ShowMyAddress -> withUser $ \User {userId} ->
processChatCommand $ APIShowMyAddress userId
+ APISetProfileAddress userId False -> withUserId userId $ \user@User {profile = p} -> do
+ let p' = (fromLocalProfile p :: Profile) {contactLink = Nothing}
+ updateProfile_ user p' $ withStore' $ \db -> setUserProfileContactLink db user Nothing
+ APISetProfileAddress userId True -> withUserId userId $ \user@User {profile = p} -> do
+ ucl@UserContactLink {connReqContact} <- withStore (`getUserAddress` user)
+ let p' = (fromLocalProfile p :: Profile) {contactLink = Just connReqContact}
+ updateProfile_ user p' $ withStore' $ \db -> setUserProfileContactLink db user $ Just ucl
+ SetProfileAddress onOff -> withUser $ \User {userId} ->
+ processChatCommand $ APISetProfileAddress userId onOff
APIAddressAutoAccept userId autoAccept_ -> withUserId userId $ \user -> do
contactLink <- withStore (\db -> updateUserAddressAutoAccept db user autoAccept_)
pure $ CRUserContactLinkUpdated user contactLink
@@ -1613,7 +1627,9 @@ processChatCommand = \case
| chunks <= sendChunks && chunks * n <= totalSendChunks && isVoice mc = Just IFMSent
| otherwise = Just IFMOffer
updateProfile :: User -> Profile -> m ChatResponse
- updateProfile user@User {profile = p} p'
+ updateProfile user p' = updateProfile_ user p' $ withStore $ \db -> updateUserProfile db user p'
+ updateProfile_ :: User -> Profile -> m User -> m ChatResponse
+ updateProfile_ user@User {profile = p} p' updateUser
| p' == fromLocalProfile p = pure $ CRUserProfileNoChange user
| otherwise = do
-- read contacts before user update to correctly merge preferences
@@ -1621,7 +1637,7 @@ processChatCommand = \case
contacts <-
filter (\ct -> isReady ct && not (contactConnIncognito ct))
<$> withStore' (`getUserContacts` user)
- user' <- withStore $ \db -> updateUserProfile db user p'
+ user' <- updateUser
asks currentUser >>= atomically . (`writeTVar` Just user')
withChatLock "updateProfile" . procCmd $ do
forM_ contacts $ \ct -> do
@@ -4407,7 +4423,7 @@ getCreateActiveUser st = do
loop = do
displayName <- getContactName
fullName <- T.pack <$> getWithPrompt "full name (optional)"
- withTransaction st (\db -> runExceptT $ createUserRecord db (AgentUserId 1) Profile {displayName, fullName, image = Nothing, preferences = Nothing} True) >>= \case
+ withTransaction st (\db -> runExceptT $ createUserRecord db (AgentUserId 1) Profile {displayName, fullName, image = Nothing, contactLink = Nothing, preferences = Nothing} True) >>= \case
Left SEDuplicateName -> do
putStrLn "chosen display name is already used by another profile on this device, choose another one"
loop
@@ -4713,6 +4729,8 @@ chatCommandP =
("/delete_address" <|> "/da") $> DeleteMyAddress,
"/_show_address " *> (APIShowMyAddress <$> A.decimal),
("/show_address" <|> "/sa") $> ShowMyAddress,
+ "/_profile_address " *> (APISetProfileAddress <$> A.decimal <* A.space <*> onOffP),
+ ("/profile_address " <|> "/pa ") *> (SetProfileAddress <$> onOffP),
"/_auto_accept " *> (APIAddressAutoAccept <$> A.decimal <* A.space <*> autoAcceptP),
"/auto_accept " *> (AddressAutoAccept <$> autoAcceptP),
("/accept " <|> "/ac ") *> char_ '@' *> (AcceptContact <$> displayName),
@@ -4766,7 +4784,7 @@ chatCommandP =
pure (cName, fullName)
userProfile = do
(cName, fullName) <- userNames
- pure Profile {displayName = cName, fullName, image = Nothing, preferences = Nothing}
+ pure Profile {displayName = cName, fullName, image = Nothing, contactLink = Nothing, preferences = Nothing}
jsonP :: J.FromJSON a => Parser a
jsonP = J.eitherDecodeStrict' <$?> A.takeByteString
groupProfile = do
diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs
index bd0299d78f..54a780384e 100644
--- a/src/Simplex/Chat/Controller.hs
+++ b/src/Simplex/Chat/Controller.hs
@@ -304,6 +304,8 @@ data ChatCommand
| DeleteMyAddress
| APIShowMyAddress UserId
| ShowMyAddress
+ | APISetProfileAddress UserId Bool
+ | SetProfileAddress Bool
| APIAddressAutoAccept UserId (Maybe AutoAccept)
| AddressAutoAccept (Maybe AutoAccept)
| AcceptContact ContactName
diff --git a/src/Simplex/Chat/Help.hs b/src/Simplex/Chat/Help.hs
index 37770d1bd1..1f77617af1 100644
--- a/src/Simplex/Chat/Help.hs
+++ b/src/Simplex/Chat/Help.hs
@@ -201,6 +201,7 @@ myAddressHelpInfo =
styleMarkdown
[ green "Your contact address commands:",
indent <> highlight "/address " <> " - create your address",
+ indent <> highlight "/profile_address on/off " <> " - share address with your contacts (it will be added to your profile)",
indent <> highlight "/delete_address " <> " - delete your address (accepted contacts will remain connected)",
indent <> highlight "/show_address " <> " - show your address",
indent <> highlight "/accept " <> " - accept contact request",
diff --git a/src/Simplex/Chat/Migrations/M20230422_profile_contact_links.hs b/src/Simplex/Chat/Migrations/M20230422_profile_contact_links.hs
new file mode 100644
index 0000000000..ee7ff053d5
--- /dev/null
+++ b/src/Simplex/Chat/Migrations/M20230422_profile_contact_links.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+module Simplex.Chat.Migrations.M20230422_profile_contact_links where
+
+import Database.SQLite.Simple (Query)
+import Database.SQLite.Simple.QQ (sql)
+
+m20230422_profile_contact_links :: Query
+m20230422_profile_contact_links =
+ [sql|
+ALTER TABLE contact_profiles ADD COLUMN contact_link BLOB;
+|]
+
+down_m20230422_profile_contact_links :: Query
+down_m20230422_profile_contact_links =
+ [sql|
+ALTER TABLE contact_profiles DROP COLUMN contact_link;
+|]
diff --git a/src/Simplex/Chat/Migrations/chat_schema.sql b/src/Simplex/Chat/Migrations/chat_schema.sql
index 5f24c8a3c3..c14ed3d211 100644
--- a/src/Simplex/Chat/Migrations/chat_schema.sql
+++ b/src/Simplex/Chat/Migrations/chat_schema.sql
@@ -17,7 +17,8 @@ CREATE TABLE contact_profiles(
user_id INTEGER DEFAULT NULL REFERENCES users ON DELETE CASCADE,
incognito INTEGER,
local_alias TEXT DEFAULT '' CHECK(local_alias NOT NULL),
- preferences TEXT
+ preferences TEXT,
+ contact_link BLOB
);
CREATE INDEX contact_profiles_index ON contact_profiles(
display_name,
diff --git a/src/Simplex/Chat/ProfileGenerator.hs b/src/Simplex/Chat/ProfileGenerator.hs
index 59c6b8a10c..55a051ad80 100644
--- a/src/Simplex/Chat/ProfileGenerator.hs
+++ b/src/Simplex/Chat/ProfileGenerator.hs
@@ -10,7 +10,7 @@ generateRandomProfile :: IO Profile
generateRandomProfile = do
adjective <- pick adjectives
noun <- pickNoun adjective 2
- pure $ Profile {displayName = adjective <> noun, fullName = "", image = Nothing, preferences = Nothing}
+ pure $ Profile {displayName = adjective <> noun, fullName = "", image = Nothing, contactLink = Nothing, preferences = Nothing}
where
pick :: [a] -> IO a
pick xs = (xs !!) <$> randomRIO (0, length xs - 1)
diff --git a/src/Simplex/Chat/Store.hs b/src/Simplex/Chat/Store.hs
index 44bab60132..489a7a266d 100644
--- a/src/Simplex/Chat/Store.hs
+++ b/src/Simplex/Chat/Store.hs
@@ -55,6 +55,7 @@ module Simplex.Chat.Store
getContact,
getContactIdByName,
updateUserProfile,
+ setUserProfileContactLink,
updateContactProfile,
updateContactUserPreferences,
updateContactAlias,
@@ -373,6 +374,7 @@ import Simplex.Chat.Migrations.M20230328_files_protocol
import Simplex.Chat.Migrations.M20230402_protocol_servers
import Simplex.Chat.Migrations.M20230411_extra_xftp_file_descriptions
import Simplex.Chat.Migrations.M20230420_rcv_files_to_receive
+import Simplex.Chat.Migrations.M20230422_profile_contact_links
import Simplex.Chat.Protocol
import Simplex.Chat.Types
import Simplex.Chat.Util (week)
@@ -447,7 +449,8 @@ schemaMigrations =
("20230328_files_protocol", m20230328_files_protocol, Just down_m20230328_files_protocol),
("20230402_protocol_servers", m20230402_protocol_servers, Just down_m20230402_protocol_servers),
("20230411_extra_xftp_file_descriptions", m20230411_extra_xftp_file_descriptions, Just down_m20230411_extra_xftp_file_descriptions),
- ("20230420_rcv_files_to_receive", m20230420_rcv_files_to_receive, Just down_m20230420_rcv_files_to_receive)
+ ("20230420_rcv_files_to_receive", m20230420_rcv_files_to_receive, Just down_m20230420_rcv_files_to_receive),
+ ("20230422_profile_contact_links", m20230422_profile_contact_links, Just down_m20230422_profile_contact_links)
]
-- | The list of migrations in ascending order by date
@@ -501,7 +504,7 @@ createUserRecord db (AgentUserId auId) Profile {displayName, fullName, image, pr
(profileId, displayName, userId, True, currentTs, currentTs)
contactId <- insertedRowId db
DB.execute db "UPDATE users SET contact_id = ? WHERE user_id = ?" (contactId, userId)
- pure $ toUser $ (userId, auId, contactId, profileId, activeUser, displayName, fullName, image, userPreferences, True) :. (Nothing, Nothing)
+ pure $ toUser $ (userId, auId, contactId, profileId, activeUser, displayName, fullName, image, Nothing, userPreferences, True) :. (Nothing, Nothing)
getUsersInfo :: DB.Connection -> IO [UserInfo]
getUsersInfo db = getUsers db >>= mapM getUserInfo
@@ -539,17 +542,17 @@ getUsers db =
userQuery :: Query
userQuery =
[sql|
- SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.local_display_name, ucp.full_name, ucp.image, ucp.preferences, u.show_ntfs, u.view_pwd_hash, u.view_pwd_salt
+ SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.local_display_name, ucp.full_name, ucp.image, ucp.contact_link, ucp.preferences, u.show_ntfs, u.view_pwd_hash, u.view_pwd_salt
FROM users u
JOIN contacts uct ON uct.contact_id = u.contact_id
JOIN contact_profiles ucp ON ucp.contact_profile_id = uct.contact_profile_id
|]
-toUser :: (UserId, UserId, ContactId, ProfileId, Bool, ContactName, Text, Maybe ImageData, Maybe Preferences, Bool) :. (Maybe B64UrlByteString, Maybe B64UrlByteString) -> User
-toUser ((userId, auId, userContactId, profileId, activeUser, displayName, fullName, image, userPreferences, showNtfs) :. (viewPwdHash_, viewPwdSalt_)) =
+toUser :: (UserId, UserId, ContactId, ProfileId, Bool, ContactName, Text, Maybe ImageData, Maybe ConnReqContact, Maybe Preferences, Bool) :. (Maybe B64UrlByteString, Maybe B64UrlByteString) -> User
+toUser ((userId, auId, userContactId, profileId, activeUser, displayName, fullName, image, contactLink, userPreferences, showNtfs) :. (viewPwdHash_, viewPwdSalt_)) =
User {userId, agentUserId = AgentUserId auId, userContactId, localDisplayName = displayName, profile, activeUser, fullPreferences, showNtfs, viewPwdHash}
where
- profile = LocalProfile {profileId, displayName, fullName, image, preferences = userPreferences, localAlias = ""}
+ profile = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences = userPreferences, localAlias = ""}
fullPreferences = mergePreferences Nothing userPreferences
viewPwdHash = UserPwdHash <$> viewPwdHash_ <*> viewPwdSalt_
@@ -672,7 +675,7 @@ getConnReqContactXContactId db user@User {userId} cReqHash = do
[sql|
SELECT
-- Contact
- ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.local_alias, ct.contact_used, ct.enable_ntfs,
+ ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.enable_ntfs,
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts,
-- Connection
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.local_alias,
@@ -724,15 +727,15 @@ getProfileById db userId profileId =
DB.query
db
[sql|
- SELECT cp.display_name, cp.full_name, cp.image, cp.local_alias, cp.preferences -- , ct.user_preferences
+ SELECT cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, cp.preferences -- , ct.user_preferences
FROM contact_profiles cp
-- JOIN contacts ct ON cp.contact_profile_id = ct.contact_profile_id
WHERE cp.user_id = ? AND cp.contact_profile_id = ?
|]
(userId, profileId)
where
- toProfile :: (ContactName, Text, Maybe ImageData, LocalAlias, Maybe Preferences) -> LocalProfile
- toProfile (displayName, fullName, image, localAlias, preferences) = LocalProfile {profileId, displayName, fullName, image, preferences, localAlias}
+ toProfile :: (ContactName, Text, Maybe ImageData, Maybe ConnReqContact, LocalAlias, Maybe Preferences) -> LocalProfile
+ toProfile (displayName, fullName, image, contactLink, localAlias, preferences) = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences, localAlias}
createConnection_ :: DB.Connection -> UserId -> ConnType -> Maybe Int64 -> ConnId -> Maybe ContactId -> Maybe Int64 -> Maybe ProfileId -> Int -> UTCTime -> IO Connection
createConnection_ db userId connType entityId acId viaContact viaUserContactLink customUserProfileId connLevel currentTs = do
@@ -765,12 +768,12 @@ createDirectContact db user@User {userId} activeConn@Connection {connId, localAl
pure $ Contact {contactId, localDisplayName, profile, activeConn, viaGroup = Nothing, contactUsed = False, chatSettings = defaultChatSettings, userPreferences, mergedPreferences, createdAt, updatedAt = createdAt, chatTs = Just createdAt}
createContact_ :: DB.Connection -> UserId -> Int64 -> Profile -> LocalAlias -> Maybe Int64 -> UTCTime -> Maybe UTCTime -> ExceptT StoreError IO (Text, ContactId, ProfileId)
-createContact_ db userId connId Profile {displayName, fullName, image, preferences} localAlias viaGroup currentTs chatTs =
+createContact_ db userId connId Profile {displayName, fullName, image, contactLink, preferences} localAlias viaGroup currentTs chatTs =
ExceptT . withLocalDisplayName db userId displayName $ \ldn -> do
DB.execute
db
- "INSERT INTO contact_profiles (display_name, full_name, image, user_id, local_alias, preferences, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?)"
- (displayName, fullName, image, userId, localAlias, preferences, currentTs, currentTs)
+ "INSERT INTO contact_profiles (display_name, full_name, image, contact_link, user_id, local_alias, preferences, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?)"
+ (displayName, fullName, image, contactLink, userId, localAlias, preferences, currentTs, currentTs)
profileId <- insertedRowId db
DB.execute
db
@@ -872,6 +875,23 @@ updateUserProfile db user p'
profile = toLocalProfile profileId p' localAlias
fullPreferences = mergePreferences Nothing preferences
+setUserProfileContactLink :: DB.Connection -> User -> Maybe UserContactLink -> IO User
+setUserProfileContactLink db user@User {userId, profile = p@LocalProfile {profileId}} ucl_ = do
+ ts <- getCurrentTime
+ DB.execute
+ db
+ [sql|
+ UPDATE contact_profiles
+ SET contact_link = ?, updated_at = ?
+ WHERE user_id = ? AND contact_profile_id = ?
+ |]
+ (connReqContact_, ts, userId, profileId)
+ pure (user :: User) {profile = p {contactLink = connReqContact_}}
+ where
+ connReqContact_ = case ucl_ of
+ Just UserContactLink {connReqContact} -> Just connReqContact
+ _ -> Nothing
+
updateContactProfile :: DB.Connection -> User -> Contact -> Profile -> ExceptT StoreError IO Contact
updateContactProfile db user@User {userId} c p'
| displayName == newName = do
@@ -964,15 +984,15 @@ updateContactProfile_ db userId profileId profile = do
updateContactProfile_' db userId profileId profile currentTs
updateContactProfile_' :: DB.Connection -> UserId -> ProfileId -> Profile -> UTCTime -> IO ()
-updateContactProfile_' db userId profileId Profile {displayName, fullName, image, preferences} updatedAt = do
+updateContactProfile_' db userId profileId Profile {displayName, fullName, image, contactLink, preferences} updatedAt = do
DB.execute
db
[sql|
UPDATE contact_profiles
- SET display_name = ?, full_name = ?, image = ?, preferences = ?, updated_at = ?
+ SET display_name = ?, full_name = ?, image = ?, contact_link = ?, preferences = ?, updated_at = ?
WHERE user_id = ? AND contact_profile_id = ?
|]
- (displayName, fullName, image, preferences, updatedAt, userId, profileId)
+ (displayName, fullName, image, contactLink, preferences, updatedAt, userId, profileId)
updateContact_ :: DB.Connection -> UserId -> Int64 -> ContactName -> ContactName -> UTCTime -> IO ()
updateContact_ db userId contactId displayName newName updatedAt = do
@@ -986,19 +1006,19 @@ updateContact_ db userId contactId displayName newName updatedAt = do
(newName, updatedAt, userId, contactId)
DB.execute db "DELETE FROM display_names WHERE local_display_name = ? AND user_id = ?" (displayName, userId)
-type ContactRow = (ContactId, ProfileId, ContactName, Maybe Int64, ContactName, Text, Maybe ImageData, LocalAlias, Bool, Maybe Bool) :. (Maybe Preferences, Preferences, UTCTime, UTCTime, Maybe UTCTime)
+type ContactRow = (ContactId, ProfileId, ContactName, Maybe Int64, ContactName, Text, Maybe ImageData, Maybe ConnReqContact, LocalAlias, Bool, Maybe Bool) :. (Maybe Preferences, Preferences, UTCTime, UTCTime, Maybe UTCTime)
toContact :: User -> ContactRow :. ConnectionRow -> Contact
-toContact user (((contactId, profileId, localDisplayName, viaGroup, displayName, fullName, image, localAlias, contactUsed, enableNtfs_) :. (preferences, userPreferences, createdAt, updatedAt, chatTs)) :. connRow) =
- let profile = LocalProfile {profileId, displayName, fullName, image, preferences, localAlias}
+toContact user (((contactId, profileId, localDisplayName, viaGroup, displayName, fullName, image, contactLink, localAlias, contactUsed, enableNtfs_) :. (preferences, userPreferences, createdAt, updatedAt, chatTs)) :. connRow) =
+ let profile = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences, localAlias}
activeConn = toConnection connRow
chatSettings = ChatSettings {enableNtfs = fromMaybe True enableNtfs_}
mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito activeConn
in Contact {contactId, localDisplayName, profile, activeConn, viaGroup, contactUsed, chatSettings, userPreferences, mergedPreferences, createdAt, updatedAt, chatTs}
toContactOrError :: User -> ContactRow :. MaybeConnectionRow -> Either StoreError Contact
-toContactOrError user (((contactId, profileId, localDisplayName, viaGroup, displayName, fullName, image, localAlias, contactUsed, enableNtfs_) :. (preferences, userPreferences, createdAt, updatedAt, chatTs)) :. connRow) =
- let profile = LocalProfile {profileId, displayName, fullName, image, preferences, localAlias}
+toContactOrError user (((contactId, profileId, localDisplayName, viaGroup, displayName, fullName, image, contactLink, localAlias, contactUsed, enableNtfs_) :. (preferences, userPreferences, createdAt, updatedAt, chatTs)) :. connRow) =
+ let profile = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences, localAlias}
chatSettings = ChatSettings {enableNtfs = fromMaybe True enableNtfs_}
in case toMaybeConnection connRow of
Just activeConn ->
@@ -1023,14 +1043,14 @@ getUserContactProfiles db User {userId} =
<$> DB.query
db
[sql|
- SELECT display_name, full_name, image, preferences
+ SELECT display_name, full_name, image, contact_link, preferences
FROM contact_profiles
WHERE user_id = ?
|]
(Only userId)
where
- toContactProfile :: (ContactName, Text, Maybe ImageData, Maybe Preferences) -> (Profile)
- toContactProfile (displayName, fullName, image, preferences) = Profile {displayName, fullName, image, preferences}
+ toContactProfile :: (ContactName, Text, Maybe ImageData, Maybe ConnReqContact, Maybe Preferences) -> (Profile)
+ toContactProfile (displayName, fullName, image, contactLink, preferences) = Profile {displayName, fullName, image, contactLink, preferences}
createUserContactLink :: DB.Connection -> User -> ConnId -> ConnReqContact -> ExceptT StoreError IO ()
createUserContactLink db User {userId} agentConnId cReq =
@@ -1081,7 +1101,7 @@ getUserContactLinks db User {userId} =
toUserContactConnection (connRow :. (userContactLinkId, connReqContact, groupId)) = (toConnection connRow, UserContact {userContactLinkId, connReqContact, groupId})
deleteUserAddress :: DB.Connection -> User -> IO ()
-deleteUserAddress db User {userId} = do
+deleteUserAddress db user@User {userId} = do
DB.execute
db
[sql|
@@ -1118,6 +1138,7 @@ deleteUserAddress db User {userId} = do
)
|]
[":user_id" := userId]
+ void $ setUserProfileContactLink db user Nothing
DB.execute db "DELETE FROM user_contact_links WHERE user_id = ? AND local_display_name = '' AND group_id IS NULL" (Only userId)
data UserContactLink = UserContactLink
@@ -1266,7 +1287,7 @@ setGroupLinkMemberRole db User {userId} userContactLinkId memberRole =
DB.execute db "UPDATE user_contact_links SET group_link_member_role = ? WHERE user_id = ? AND user_contact_link_id = ?" (memberRole, userId, userContactLinkId)
createOrUpdateContactRequest :: DB.Connection -> User -> Int64 -> InvitationId -> Profile -> Maybe XContactId -> ExceptT StoreError IO ContactOrRequest
-createOrUpdateContactRequest db user@User {userId} userContactLinkId invId Profile {displayName, fullName, image, preferences} xContactId_ =
+createOrUpdateContactRequest db user@User {userId} userContactLinkId invId Profile {displayName, fullName, image, contactLink, preferences} xContactId_ =
liftIO (maybeM getContact' xContactId_) >>= \case
Just contact -> pure $ CORContact contact
Nothing -> CORRequest <$> createOrUpdate_
@@ -1288,8 +1309,8 @@ createOrUpdateContactRequest db user@User {userId} userContactLinkId invId Profi
createContactRequest_ currentTs ldn = do
DB.execute
db
- "INSERT INTO contact_profiles (display_name, full_name, image, user_id, preferences, created_at, updated_at) VALUES (?,?,?,?,?,?,?)"
- (displayName, fullName, image, userId, preferences, currentTs, currentTs)
+ "INSERT INTO contact_profiles (display_name, full_name, image, contact_link, user_id, preferences, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?)"
+ (displayName, fullName, image, contactLink, userId, preferences, currentTs, currentTs)
profileId <- insertedRowId db
DB.execute
db
@@ -1308,7 +1329,7 @@ createOrUpdateContactRequest db user@User {userId} userContactLinkId invId Profi
[sql|
SELECT
-- Contact
- ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.local_alias, ct.contact_used, ct.enable_ntfs,
+ ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.enable_ntfs,
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts,
-- Connection
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.local_alias,
@@ -1329,7 +1350,7 @@ createOrUpdateContactRequest db user@User {userId} userContactLinkId invId Profi
[sql|
SELECT
cr.contact_request_id, cr.local_display_name, cr.agent_invitation_id, cr.user_contact_link_id,
- c.agent_conn_id, cr.contact_profile_id, p.display_name, p.full_name, p.image, cr.xcontact_id, p.preferences, cr.created_at, cr.updated_at
+ c.agent_conn_id, cr.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, cr.xcontact_id, p.preferences, cr.created_at, cr.updated_at
FROM contact_requests cr
JOIN connections c USING (user_contact_link_id)
JOIN contact_profiles p USING (contact_profile_id)
@@ -1357,6 +1378,7 @@ createOrUpdateContactRequest db user@User {userId} userContactLinkId invId Profi
SET display_name = ?,
full_name = ?,
image = ?,
+ contact_link = ?,
updated_at = ?
WHERE contact_profile_id IN (
SELECT contact_profile_id
@@ -1365,7 +1387,7 @@ createOrUpdateContactRequest db user@User {userId} userContactLinkId invId Profi
AND contact_request_id = ?
)
|]
- (displayName, fullName, image, currentTs, userId, cReqId)
+ (displayName, fullName, image, contactLink, currentTs, userId, cReqId)
getContactRequest' :: DB.Connection -> Int64 -> ExceptT StoreError IO (User, UserContactRequest)
getContactRequest' db contactRequestId = do
@@ -1380,7 +1402,7 @@ getContactRequest db User {userId} contactRequestId =
[sql|
SELECT
cr.contact_request_id, cr.local_display_name, cr.agent_invitation_id, cr.user_contact_link_id,
- c.agent_conn_id, cr.contact_profile_id, p.display_name, p.full_name, p.image, cr.xcontact_id, p.preferences, cr.created_at, cr.updated_at
+ c.agent_conn_id, cr.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, cr.xcontact_id, p.preferences, cr.created_at, cr.updated_at
FROM contact_requests cr
JOIN connections c USING (user_contact_link_id)
JOIN contact_profiles p USING (contact_profile_id)
@@ -1389,11 +1411,11 @@ getContactRequest db User {userId} contactRequestId =
|]
(userId, contactRequestId)
-type ContactRequestRow = (Int64, ContactName, AgentInvId, Int64, AgentConnId, Int64, ContactName, Text, Maybe ImageData) :. (Maybe XContactId, Maybe Preferences, UTCTime, UTCTime)
+type ContactRequestRow = (Int64, ContactName, AgentInvId, Int64, AgentConnId, Int64, ContactName, Text, Maybe ImageData, Maybe ConnReqContact) :. (Maybe XContactId, Maybe Preferences, UTCTime, UTCTime)
toContactRequest :: ContactRequestRow -> UserContactRequest
-toContactRequest ((contactRequestId, localDisplayName, agentInvitationId, userContactLinkId, agentContactConnId, profileId, displayName, fullName, image) :. (xContactId, preferences, createdAt, updatedAt)) = do
- let profile = Profile {displayName, fullName, image, preferences}
+toContactRequest ((contactRequestId, localDisplayName, agentInvitationId, userContactLinkId, agentContactConnId, profileId, displayName, fullName, image, contactLink) :. (xContactId, preferences, createdAt, updatedAt)) = do
+ let profile = Profile {displayName, fullName, image, contactLink, preferences}
in UserContactRequest {contactRequestId, agentInvitationId, userContactLinkId, agentContactConnId, localDisplayName, profileId, profile, xContactId, createdAt, updatedAt}
getContactRequestIdByName :: DB.Connection -> UserId -> ContactName -> ExceptT StoreError IO Int64
@@ -1754,16 +1776,16 @@ getConnectionEntity db user@User {userId, userContactId} agentConnId = do
db
[sql|
SELECT
- c.contact_profile_id, c.local_display_name, p.display_name, p.full_name, p.image, p.local_alias, c.via_group, c.contact_used, c.enable_ntfs,
+ c.contact_profile_id, c.local_display_name, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, c.via_group, c.contact_used, c.enable_ntfs,
p.preferences, c.user_preferences, c.created_at, c.updated_at, c.chat_ts
FROM contacts c
JOIN contact_profiles p ON c.contact_profile_id = p.contact_profile_id
WHERE c.user_id = ? AND c.contact_id = ?
|]
(userId, contactId)
- toContact' :: Int64 -> Connection -> [(ProfileId, ContactName, Text, Text, Maybe ImageData, LocalAlias, Maybe Int64, Bool, Maybe Bool) :. (Maybe Preferences, Preferences, UTCTime, UTCTime, Maybe UTCTime)] -> Either StoreError Contact
- toContact' contactId activeConn [(profileId, localDisplayName, displayName, fullName, image, localAlias, viaGroup, contactUsed, enableNtfs_) :. (preferences, userPreferences, createdAt, updatedAt, chatTs)] =
- let profile = LocalProfile {profileId, displayName, fullName, image, preferences, localAlias}
+ toContact' :: Int64 -> Connection -> [(ProfileId, ContactName, Text, Text, Maybe ImageData, Maybe ConnReqContact, LocalAlias, Maybe Int64, Bool, Maybe Bool) :. (Maybe Preferences, Preferences, UTCTime, UTCTime, Maybe UTCTime)] -> Either StoreError Contact
+ toContact' contactId activeConn [(profileId, localDisplayName, displayName, fullName, image, contactLink, localAlias, viaGroup, contactUsed, enableNtfs_) :. (preferences, userPreferences, createdAt, updatedAt, chatTs)] =
+ let profile = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences, localAlias}
chatSettings = ChatSettings {enableNtfs = fromMaybe True enableNtfs_}
mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito activeConn
in Right Contact {contactId, localDisplayName, profile, activeConn, viaGroup, contactUsed, chatSettings, userPreferences, mergedPreferences, createdAt, updatedAt, chatTs}
@@ -1781,10 +1803,10 @@ getConnectionEntity db user@User {userId, userContactId} agentConnId = do
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
mu.member_status, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
-- GroupInfo {membership = GroupMember {memberProfile}}
- pu.display_name, pu.full_name, pu.image, pu.local_alias, pu.preferences,
+ pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences,
-- from GroupMember
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category, m.member_status,
- m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.local_alias, p.preferences
+ m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences
FROM group_members m
JOIN contact_profiles p ON p.contact_profile_id = COALESCE(m.member_profile_id, m.contact_profile_id)
JOIN groups g ON g.group_id = m.group_id
@@ -1884,10 +1906,10 @@ getGroupAndMember db User {userId, userContactId} groupMemberId =
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
mu.member_status, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
-- GroupInfo {membership = GroupMember {memberProfile}}
- pu.display_name, pu.full_name, pu.image, pu.local_alias, pu.preferences,
+ pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences,
-- from GroupMember
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category, m.member_status,
- m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.local_alias, p.preferences,
+ m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.auth_err_counter
FROM group_members m
@@ -2120,7 +2142,7 @@ getUserGroupDetails db User {userId, userContactId} =
[sql|
SELECT g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, g.host_conn_custom_user_profile_id, g.enable_ntfs, gp.preferences, g.created_at, g.updated_at, g.chat_ts,
mu.group_member_id, g.group_id, mu.member_id, mu.member_role, mu.member_category, mu.member_status,
- mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, pu.display_name, pu.full_name, pu.image, pu.local_alias, pu.preferences
+ mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences
FROM groups g
JOIN group_profiles gp USING (group_profile_id)
JOIN group_members mu USING (group_id)
@@ -2167,7 +2189,7 @@ groupMemberQuery =
[sql|
SELECT
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category, m.member_status,
- m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.local_alias, p.preferences,
+ m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.auth_err_counter
FROM group_members m
@@ -2239,20 +2261,20 @@ getGroupInvitation db user groupId =
firstRow fromOnly (SEGroupNotFound groupId) $
DB.query db "SELECT g.inv_queue_info FROM groups g WHERE g.group_id = ? AND g.user_id = ?" (groupId, userId)
-type GroupMemberRow = ((Int64, Int64, MemberId, GroupMemberRole, GroupMemberCategory, GroupMemberStatus) :. (Maybe Int64, ContactName, Maybe ContactId, ProfileId, ProfileId, ContactName, Text, Maybe ImageData, LocalAlias, Maybe Preferences))
+type GroupMemberRow = ((Int64, Int64, MemberId, GroupMemberRole, GroupMemberCategory, GroupMemberStatus) :. (Maybe Int64, ContactName, Maybe ContactId, ProfileId, ProfileId, ContactName, Text, Maybe ImageData, Maybe ConnReqContact, LocalAlias, Maybe Preferences))
-type MaybeGroupMemberRow = ((Maybe Int64, Maybe Int64, Maybe MemberId, Maybe GroupMemberRole, Maybe GroupMemberCategory, Maybe GroupMemberStatus) :. (Maybe Int64, Maybe ContactName, Maybe ContactId, Maybe ProfileId, Maybe ProfileId, Maybe ContactName, Maybe Text, Maybe ImageData, Maybe LocalAlias, Maybe Preferences))
+type MaybeGroupMemberRow = ((Maybe Int64, Maybe Int64, Maybe MemberId, Maybe GroupMemberRole, Maybe GroupMemberCategory, Maybe GroupMemberStatus) :. (Maybe Int64, Maybe ContactName, Maybe ContactId, Maybe ProfileId, Maybe ProfileId, Maybe ContactName, Maybe Text, Maybe ImageData, Maybe ConnReqContact, Maybe LocalAlias, Maybe Preferences))
toGroupMember :: Int64 -> GroupMemberRow -> GroupMember
-toGroupMember userContactId ((groupMemberId, groupId, memberId, memberRole, memberCategory, memberStatus) :. (invitedById, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, localAlias, preferences)) =
- let memberProfile = LocalProfile {profileId, displayName, fullName, image, preferences, localAlias}
+toGroupMember userContactId ((groupMemberId, groupId, memberId, memberRole, memberCategory, memberStatus) :. (invitedById, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, preferences)) =
+ let memberProfile = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences, localAlias}
invitedBy = toInvitedBy userContactId invitedById
activeConn = Nothing
in GroupMember {..}
toMaybeGroupMember :: Int64 -> MaybeGroupMemberRow -> Maybe GroupMember
-toMaybeGroupMember userContactId ((Just groupMemberId, Just groupId, Just memberId, Just memberRole, Just memberCategory, Just memberStatus) :. (invitedById, Just localDisplayName, memberContactId, Just memberContactProfileId, Just profileId, Just displayName, Just fullName, image, Just localAlias, contactPreferences)) =
- Just $ toGroupMember userContactId ((groupMemberId, groupId, memberId, memberRole, memberCategory, memberStatus) :. (invitedById, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, localAlias, contactPreferences))
+toMaybeGroupMember userContactId ((Just groupMemberId, Just groupId, Just memberId, Just memberRole, Just memberCategory, Just memberStatus) :. (invitedById, Just localDisplayName, memberContactId, Just memberContactProfileId, Just profileId, Just displayName, Just fullName, image, contactLink, Just localAlias, contactPreferences)) =
+ Just $ toGroupMember userContactId ((groupMemberId, groupId, memberId, memberRole, memberCategory, memberStatus) :. (invitedById, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, contactPreferences))
toMaybeGroupMember _ _ = Nothing
createNewContactMember :: DB.Connection -> TVar ChaChaDRG -> User -> GroupId -> Contact -> GroupMemberRole -> ConnId -> ConnReqInvitation -> ExceptT StoreError IO GroupMember
@@ -2325,7 +2347,7 @@ getContactViaMember db user@User {userId} GroupMember {groupMemberId} =
[sql|
SELECT
-- Contact
- ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.local_alias, ct.contact_used, ct.enable_ntfs,
+ ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.enable_ntfs,
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts,
-- Connection
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.local_alias,
@@ -2380,13 +2402,13 @@ updateGroupMemberStatusById db userId groupMemberId memStatus = do
-- | add new member with profile
createNewGroupMember :: DB.Connection -> User -> GroupInfo -> MemberInfo -> GroupMemberCategory -> GroupMemberStatus -> ExceptT StoreError IO GroupMember
-createNewGroupMember db user@User {userId} gInfo memInfo@(MemberInfo _ _ Profile {displayName, fullName, image, preferences}) memCategory memStatus =
+createNewGroupMember db user@User {userId} gInfo memInfo@(MemberInfo _ _ Profile {displayName, fullName, image, contactLink, preferences}) memCategory memStatus =
ExceptT . withLocalDisplayName db userId displayName $ \localDisplayName -> do
currentTs <- getCurrentTime
DB.execute
db
- "INSERT INTO contact_profiles (display_name, full_name, image, user_id, preferences, created_at, updated_at) VALUES (?,?,?,?,?,?,?)"
- (displayName, fullName, image, userId, preferences, currentTs, currentTs)
+ "INSERT INTO contact_profiles (display_name, full_name, image, contact_link, user_id, preferences, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?)"
+ (displayName, fullName, image, contactLink, userId, preferences, currentTs, currentTs)
memProfileId <- insertedRowId db
let newMember =
NewGroupMember
@@ -2629,10 +2651,10 @@ getViaGroupMember db User {userId, userContactId} Contact {contactId} =
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
mu.member_status, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
-- GroupInfo {membership = GroupMember {memberProfile}}
- pu.display_name, pu.full_name, pu.image, pu.local_alias, pu.preferences,
+ pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences,
-- via GroupMember
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category, m.member_status,
- m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.local_alias, p.preferences,
+ m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.auth_err_counter
FROM group_members m
@@ -2664,7 +2686,7 @@ getViaGroupContact db user@User {userId} GroupMember {groupMemberId} =
db
[sql|
SELECT
- ct.contact_id, ct.contact_profile_id, ct.local_display_name, p.display_name, p.full_name, p.image, p.local_alias, ct.via_group, ct.contact_used, ct.enable_ntfs,
+ ct.contact_id, ct.contact_profile_id, ct.local_display_name, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, ct.via_group, ct.contact_used, ct.enable_ntfs,
p.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.auth_err_counter
@@ -2681,9 +2703,9 @@ getViaGroupContact db user@User {userId} GroupMember {groupMemberId} =
|]
(userId, groupMemberId)
where
- toContact' :: ((ContactId, ProfileId, ContactName, Text, Text, Maybe ImageData, LocalAlias, Maybe Int64, Bool, Maybe Bool) :. (Maybe Preferences, Preferences, UTCTime, UTCTime, Maybe UTCTime)) :. ConnectionRow -> Contact
- toContact' (((contactId, profileId, localDisplayName, displayName, fullName, image, localAlias, viaGroup, contactUsed, enableNtfs_) :. (preferences, userPreferences, createdAt, updatedAt, chatTs)) :. connRow) =
- let profile = LocalProfile {profileId, displayName, fullName, image, preferences, localAlias}
+ toContact' :: ((ContactId, ProfileId, ContactName, Text, Text, Maybe ImageData, Maybe ConnReqContact, LocalAlias, Maybe Int64, Bool, Maybe Bool) :. (Maybe Preferences, Preferences, UTCTime, UTCTime, Maybe UTCTime)) :. ConnectionRow -> Contact
+ toContact' (((contactId, profileId, localDisplayName, displayName, fullName, image, contactLink, localAlias, viaGroup, contactUsed, enableNtfs_) :. (preferences, userPreferences, createdAt, updatedAt, chatTs)) :. connRow) =
+ let profile = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences, localAlias}
chatSettings = ChatSettings {enableNtfs = fromMaybe True enableNtfs_}
activeConn = toConnection connRow
mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito activeConn
@@ -3698,7 +3720,7 @@ getChatItemQuote_ db User {userId, userContactId} chatDirection QuotedMsg {msgRe
-- GroupMember
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category,
m.member_status, m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id,
- p.display_name, p.full_name, p.image, p.local_alias, p.preferences
+ p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences
FROM group_members m
JOIN contact_profiles p ON p.contact_profile_id = COALESCE(m.member_profile_id, m.contact_profile_id)
LEFT JOIN contacts c ON m.contact_id = c.contact_id
@@ -3738,7 +3760,7 @@ getDirectChatPreviews_ db user@User {userId} = do
[sql|
SELECT
-- Contact
- ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.local_alias, ct.contact_used, ct.enable_ntfs,
+ ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.enable_ntfs,
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts,
-- Connection
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.local_alias,
@@ -3807,7 +3829,7 @@ getGroupChatPreviews_ db User {userId, userContactId} = do
-- GroupMember - membership
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
mu.member_status, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
- pu.display_name, pu.full_name, pu.image, pu.local_alias, pu.preferences,
+ pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences,
-- ChatStats
COALESCE(ChatStats.UnreadCount, 0), COALESCE(ChatStats.MinUnread, 0), g.unread_chat,
-- ChatItem
@@ -3817,17 +3839,17 @@ getGroupChatPreviews_ db User {userId, userContactId} = do
-- Maybe GroupMember - sender
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category,
m.member_status, m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id,
- p.display_name, p.full_name, p.image, p.local_alias, p.preferences,
+ p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
-- quoted ChatItem
ri.chat_item_id, i.quoted_shared_msg_id, i.quoted_sent_at, i.quoted_content, i.quoted_sent,
-- quoted GroupMember
rm.group_member_id, rm.group_id, rm.member_id, rm.member_role, rm.member_category,
rm.member_status, rm.invited_by, rm.local_display_name, rm.contact_id, rm.contact_profile_id, rp.contact_profile_id,
- rp.display_name, rp.full_name, rp.image, rp.local_alias, rp.preferences,
+ rp.display_name, rp.full_name, rp.image, rp.contact_link, rp.local_alias, rp.preferences,
-- deleted by GroupMember
dbm.group_member_id, dbm.group_id, dbm.member_id, dbm.member_role, dbm.member_category,
dbm.member_status, dbm.invited_by, dbm.local_display_name, dbm.contact_id, dbm.contact_profile_id, dbp.contact_profile_id,
- dbp.display_name, dbp.full_name, dbp.image, dbp.local_alias, dbp.preferences
+ dbp.display_name, dbp.full_name, dbp.image, dbp.contact_link, dbp.local_alias, dbp.preferences
FROM groups g
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id
JOIN group_members mu ON mu.group_id = g.group_id
@@ -3873,7 +3895,7 @@ getContactRequestChatPreviews_ db User {userId} =
[sql|
SELECT
cr.contact_request_id, cr.local_display_name, cr.agent_invitation_id, cr.user_contact_link_id,
- c.agent_conn_id, cr.contact_profile_id, p.display_name, p.full_name, p.image, cr.xcontact_id, p.preferences, cr.created_at, cr.updated_at
+ c.agent_conn_id, cr.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, cr.xcontact_id, p.preferences, cr.created_at, cr.updated_at
FROM contact_requests cr
JOIN connections c ON c.user_contact_link_id = cr.user_contact_link_id
JOIN contact_profiles p ON p.contact_profile_id = cr.contact_profile_id
@@ -4068,7 +4090,7 @@ getContact db user@User {userId} contactId =
[sql|
SELECT
-- Contact
- ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.local_alias, ct.contact_used, ct.enable_ntfs,
+ ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.enable_ntfs,
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts,
-- Connection
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.local_alias,
@@ -4197,7 +4219,7 @@ getGroupInfo db User {userId, userContactId} groupId =
-- GroupMember - membership
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
mu.member_status, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
- pu.display_name, pu.full_name, pu.image, pu.local_alias, pu.preferences
+ pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences
FROM groups g
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id
JOIN group_members mu ON mu.group_id = g.group_id
@@ -4595,17 +4617,17 @@ getGroupChatItem db User {userId, userContactId} groupId itemId = ExceptT $ do
-- GroupMember
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category,
m.member_status, m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id,
- p.display_name, p.full_name, p.image, p.local_alias, p.preferences,
+ p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
-- quoted ChatItem
ri.chat_item_id, i.quoted_shared_msg_id, i.quoted_sent_at, i.quoted_content, i.quoted_sent,
-- quoted GroupMember
rm.group_member_id, rm.group_id, rm.member_id, rm.member_role, rm.member_category,
rm.member_status, rm.invited_by, rm.local_display_name, rm.contact_id, rm.contact_profile_id, rp.contact_profile_id,
- rp.display_name, rp.full_name, rp.image, rp.local_alias, rp.preferences,
+ rp.display_name, rp.full_name, rp.image, rp.contact_link, rp.local_alias, rp.preferences,
-- deleted by GroupMember
dbm.group_member_id, dbm.group_id, dbm.member_id, dbm.member_role, dbm.member_category,
dbm.member_status, dbm.invited_by, dbm.local_display_name, dbm.contact_id, dbm.contact_profile_id, dbp.contact_profile_id,
- dbp.display_name, dbp.full_name, dbp.image, dbp.local_alias, dbp.preferences
+ dbp.display_name, dbp.full_name, dbp.image, dbp.contact_link, dbp.local_alias, dbp.preferences
FROM chat_items i
LEFT JOIN files f ON f.chat_item_id = i.chat_item_id
LEFT JOIN group_members m ON m.group_member_id = i.group_member_id
diff --git a/src/Simplex/Chat/Types.hs b/src/Simplex/Chat/Types.hs
index 22b0041281..de89599f2d 100644
--- a/src/Simplex/Chat/Types.hs
+++ b/src/Simplex/Chat/Types.hs
@@ -1071,6 +1071,7 @@ data Profile = Profile
{ displayName :: ContactName,
fullName :: Text,
image :: Maybe ImageData,
+ contactLink :: Maybe ConnReqContact,
preferences :: Maybe Preferences
-- fields that should not be read into this data type to prevent sending them as part of profile to contacts:
-- - contact_profile_id
@@ -1099,6 +1100,7 @@ data LocalProfile = LocalProfile
displayName :: ContactName,
fullName :: Text,
image :: Maybe ImageData,
+ contactLink :: Maybe ConnReqContact,
preferences :: Maybe Preferences,
localAlias :: LocalAlias
}
@@ -1112,12 +1114,12 @@ localProfileId :: LocalProfile -> ProfileId
localProfileId = profileId
toLocalProfile :: ProfileId -> Profile -> LocalAlias -> LocalProfile
-toLocalProfile profileId Profile {displayName, fullName, image, preferences} localAlias =
- LocalProfile {profileId, displayName, fullName, image, preferences, localAlias}
+toLocalProfile profileId Profile {displayName, fullName, image, contactLink, preferences} localAlias =
+ LocalProfile {profileId, displayName, fullName, image, contactLink, preferences, localAlias}
fromLocalProfile :: LocalProfile -> Profile
-fromLocalProfile LocalProfile {displayName, fullName, image, preferences} =
- Profile {displayName, fullName, image, preferences}
+fromLocalProfile LocalProfile {displayName, fullName, image, contactLink, preferences} =
+ Profile {displayName, fullName, image, contactLink, preferences}
data GroupProfile = GroupProfile
{ displayName :: GroupName,
diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs
index 5eedb8e638..f4ae01c863 100644
--- a/src/Simplex/Chat/View.hs
+++ b/src/Simplex/Chat/View.hs
@@ -811,8 +811,9 @@ viewNetworkConfig NetworkConfig {socksProxy, tcpTimeout} =
]
viewContactInfo :: Contact -> ConnectionStats -> Maybe Profile -> [StyledString]
-viewContactInfo ct@Contact {contactId, profile = LocalProfile {localAlias}} stats incognitoProfile =
+viewContactInfo ct@Contact {contactId, profile = LocalProfile {localAlias, contactLink}} stats incognitoProfile =
["contact ID: " <> sShow contactId] <> viewConnectionStats stats
+ <> maybe [] (\l -> ["contact address: " <> (plain . strEncode) l]) contactLink
<> maybe
["you've shared main profile with this contact"]
(\p -> ["you've shared incognito profile with this contact: " <> incognitoProfile' p])
@@ -872,11 +873,12 @@ viewSwitchPhase SPCompleted = "changed address"
viewSwitchPhase phase = plain (strEncode phase) <> " changing address"
viewUserProfileUpdated :: Profile -> Profile -> [StyledString]
-viewUserProfileUpdated Profile {displayName = n, fullName, image, preferences} Profile {displayName = n', fullName = fullName', image = image', preferences = prefs'} =
+viewUserProfileUpdated Profile {displayName = n, fullName, image, contactLink, preferences} Profile {displayName = n', fullName = fullName', image = image', contactLink = contactLink', preferences = prefs'} =
profileUpdated <> viewPrefsUpdated preferences prefs'
where
profileUpdated
- | n == n' && fullName == fullName' && image == image' = []
+ | n == n' && fullName == fullName' && image == image' && contactLink == contactLink' = []
+ | n == n' && fullName == fullName' && image == image' = [if isNothing contactLink' then "contact address removed" else "new contact address set"]
| n == n' && fullName == fullName' = [if isNothing image' then "profile image removed" else "profile image updated"]
| n == n' = ["user full name " <> (if T.null fullName' || fullName' == n' then "removed" else "changed to " <> plain fullName') <> notified]
| otherwise = ["user profile is changed to " <> ttyFullName n' fullName' <> notified]
@@ -980,9 +982,13 @@ viewConnectionAliasUpdated PendingContactConnection {pccConnId, localAlias}
viewContactUpdated :: Contact -> Contact -> [StyledString]
viewContactUpdated
- Contact {localDisplayName = n, profile = LocalProfile {fullName}}
- Contact {localDisplayName = n', profile = LocalProfile {fullName = fullName'}}
- | n == n' && fullName == fullName' = []
+ Contact {localDisplayName = n, profile = LocalProfile {fullName, contactLink}}
+ Contact {localDisplayName = n', profile = LocalProfile {fullName = fullName', contactLink = contactLink'}}
+ | n == n' && fullName == fullName' && contactLink == contactLink' = []
+ | n == n' && fullName == fullName' =
+ if isNothing contactLink'
+ then [ttyContact n <> " removed contact address"]
+ else [ttyContact n <> " set new contact address, use " <> highlight ("/info " <> n) <> " to view"]
| n == n' = ["contact " <> ttyContact n <> fullNameUpdate]
| otherwise =
[ "contact " <> ttyContact n <> " changed to " <> ttyFullName n' fullName',
diff --git a/tests/ChatTests/Profiles.hs b/tests/ChatTests/Profiles.hs
index cba818295f..a5dc083f71 100644
--- a/tests/ChatTests/Profiles.hs
+++ b/tests/ChatTests/Profiles.hs
@@ -19,6 +19,7 @@ chatProfileTests = do
it "update user profile with image" testUpdateProfileImage
describe "user contact link" $ do
describe "create and connect via contact link" testUserContactLink
+ it "add contact link to profile" testProfileLink
it "auto accept contact requests" testUserContactLinkAutoAccept
it "deduplicate contact requests" testDeduplicateContactRequests
it "deduplicate contact requests with profile change" testDeduplicateContactRequestsProfileChange
@@ -134,6 +135,83 @@ testUserContactLink = versionTestMatrix3 $ \alice bob cath -> do
alice @@@ [("@cath", lastChatFeature), ("@bob", "hey")]
alice <##> cath
+testProfileLink :: HasCallStack => FilePath -> IO ()
+testProfileLink =
+ testChat3 aliceProfile bobProfile cathProfile $
+ \alice bob cath -> do
+ alice ##> "/ad"
+ cLink <- getContactLink alice True
+
+ bob ##> ("/c " <> cLink)
+ alice <#? bob
+ alice ##> "/ac bob"
+ alice <## "bob (Bob): accepting contact request..."
+ concurrently_
+ (bob <## "alice (Alice): contact is connected")
+ (alice <## "bob (Bob): contact is connected")
+ alice <##> bob
+
+ alice ##> "/pa on"
+ alice <## "new contact address set"
+
+ bob <## "alice set new contact address, use /info alice to view"
+ checkAliceProfileLink bob cLink
+
+ cath ##> ("/c " <> cLink)
+ alice <#? cath
+ alice ##> "/ac cath"
+ alice <## "cath (Catherine): accepting contact request..."
+ concurrently_
+ (cath <## "alice (Alice): contact is connected")
+ (alice <## "cath (Catherine): contact is connected")
+ alice <##> cath
+
+ checkAliceProfileLink cath cLink
+
+ alice ##> "/pa off"
+ alice <## "contact address removed"
+
+ bob <## "alice removed contact address"
+ checkAliceNoProfileLink bob
+
+ cath <## "alice removed contact address"
+ checkAliceNoProfileLink cath
+
+ alice ##> "/pa on"
+ alice <## "new contact address set"
+
+ bob <## "alice set new contact address, use /info alice to view"
+ checkAliceProfileLink bob cLink
+
+ cath <## "alice set new contact address, use /info alice to view"
+ checkAliceProfileLink cath cLink
+
+ alice ##> "/da"
+ alice <## "Your chat address is deleted - accepted contacts will remain connected."
+ alice <## "To create a new chat address use /ad"
+
+ bob <## "alice removed contact address"
+ checkAliceNoProfileLink bob
+
+ cath <## "alice removed contact address"
+ checkAliceNoProfileLink cath
+ where
+ checkAliceProfileLink cc cLink = do
+ cc ##> "/info alice"
+ cc <## "contact ID: 2"
+ cc <##. "receiving messages via"
+ cc <##. "sending messages via"
+ cc <## ("contact address: " <> cLink)
+ cc <## "you've shared main profile with this contact"
+ cc <## "connection not verified, use /code command to see security code"
+ checkAliceNoProfileLink cc = do
+ cc ##> "/info alice"
+ cc <## "contact ID: 2"
+ cc <##. "receiving messages via"
+ cc <##. "sending messages via"
+ cc <## "you've shared main profile with this contact"
+ cc <## "connection not verified, use /code command to see security code"
+
testUserContactLinkAutoAccept :: HasCallStack => FilePath -> IO ()
testUserContactLinkAutoAccept =
testChat4 aliceProfile bobProfile cathProfile danProfile $
diff --git a/tests/ChatTests/Utils.hs b/tests/ChatTests/Utils.hs
index a373b7cea6..18866fe2d1 100644
--- a/tests/ChatTests/Utils.hs
+++ b/tests/ChatTests/Utils.hs
@@ -31,16 +31,16 @@ defaultPrefs :: Maybe Preferences
defaultPrefs = Just $ toChatPrefs defaultChatPrefs
aliceProfile :: Profile
-aliceProfile = Profile {displayName = "alice", fullName = "Alice", image = Nothing, preferences = defaultPrefs}
+aliceProfile = Profile {displayName = "alice", fullName = "Alice", image = Nothing, contactLink = Nothing, preferences = defaultPrefs}
bobProfile :: Profile
-bobProfile = Profile {displayName = "bob", fullName = "Bob", image = Just (ImageData "data:image/png;base64,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"), preferences = defaultPrefs}
+bobProfile = Profile {displayName = "bob", fullName = "Bob", image = Just (ImageData "data:image/png;base64,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"), contactLink = Nothing, preferences = defaultPrefs}
cathProfile :: Profile
-cathProfile = Profile {displayName = "cath", fullName = "Catherine", image = Nothing, preferences = defaultPrefs}
+cathProfile = Profile {displayName = "cath", fullName = "Catherine", image = Nothing, contactLink = Nothing, preferences = defaultPrefs}
danProfile :: Profile
-danProfile = Profile {displayName = "dan", fullName = "Daniel", image = Nothing, preferences = defaultPrefs}
+danProfile = Profile {displayName = "dan", fullName = "Daniel", image = Nothing, contactLink = Nothing, preferences = defaultPrefs}
xit' :: (HasCallStack, Example a) => String -> a -> SpecWith (Arg a)
xit' = if os == "linux" then xit else it
diff --git a/tests/ProtocolTests.hs b/tests/ProtocolTests.hs
index 4c1d056bf7..dcc7e88c9f 100644
--- a/tests/ProtocolTests.hs
+++ b/tests/ProtocolTests.hs
@@ -92,7 +92,7 @@ testGroupPreferences :: Maybe GroupPreferences
testGroupPreferences = Just GroupPreferences {timedMessages = Nothing, directMessages = Nothing, voice = Just VoiceGroupPreference {enable = FEOn}, fullDelete = Nothing}
testProfile :: Profile
-testProfile = Profile {displayName = "alice", fullName = "Alice", image = Just (ImageData "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII="), preferences = testChatPreferences}
+testProfile = Profile {displayName = "alice", fullName = "Alice", image = Just (ImageData "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII="), contactLink = Nothing, preferences = testChatPreferences}
testGroupProfile :: GroupProfile
testGroupProfile = GroupProfile {displayName = "team", fullName = "Team", description = Nothing, image = Nothing, groupPreferences = testGroupPreferences}
@@ -198,7 +198,7 @@ decodeChatMessageTest = describe "Chat message encoding/decoding" $ do
#==# XInfo testProfile
it "x.info with empty full name" $
"{\"event\":\"x.info\",\"params\":{\"profile\":{\"fullName\":\"\",\"displayName\":\"alice\",\"preferences\":{\"voice\":{\"allow\":\"yes\"}}}}}"
- #==# XInfo Profile {displayName = "alice", fullName = "", image = Nothing, preferences = testChatPreferences}
+ #==# XInfo Profile {displayName = "alice", fullName = "", image = Nothing, contactLink = Nothing, preferences = testChatPreferences}
it "x.contact with xContactId" $
"{\"event\":\"x.contact\",\"params\":{\"contactReqId\":\"AQIDBA==\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"voice\":{\"allow\":\"yes\"}}}}}"
#==# XContact testProfile (Just $ XContactId "\1\2\3\4")