Compare commits

...

14 commits

Author SHA1 Message Date
spaced4ndy
3d22b738d8
core: fix change connection user (#5992)
* core: fix change connection user

* plans
2025-06-16 22:38:02 +01:00
Evgeny Poberezkin
c08189108e
6.3.6: ios 282, android 295, desktop 106 2025-06-14 20:12:19 +01:00
Evgeny Poberezkin
442d9afc4b
android: remove Contribute link from Android bundle 2025-06-14 19:26:46 +01:00
Evgeny Poberezkin
a593557c21
core: 6.3.6.0 (simplexmq 6.4.0.3.1) 2025-06-14 14:46:08 +01:00
Evgeny
07abe24e18
core: make decoding for short link data forward compatible (#5989)
* core: make decoding for short link data forward compatible

* simplexmq
2025-06-14 14:17:34 +01:00
Evgeny Poberezkin
5f6595dda9
6.3.5: ios 280, android 292, desktop 104 2025-06-09 09:32:32 +01:00
Evgeny Poberezkin
6fdd50efb9
core: 6.3.5.0 2025-06-08 18:28:26 +01:00
Evgeny
50dfda6c09
core: fix deletion queries for PostgreSQL client (#5969)
* core: fix deletion queries for PostgreSQL client

* disable test in posrgres

* plan
2025-06-08 18:27:42 +01:00
Evgeny Poberezkin
ea1a81fcac
core: 6.3.4.2 (simplexmq 6.4.0.3) 2025-06-06 12:26:46 +01:00
Evgeny
cf0639bf28
website: add Whonix to reviews (#5966) 2025-06-05 21:05:16 +01:00
Evgeny
7b362ff655
ui: label in compose when user cannot send messages (#5922)
* ui: label in compose when user cannot send messages

* gray buttons when user cannot send messages

* improve

* kotlin

* fix order

* fix alert

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2025-05-19 14:50:33 +00:00
Evgeny
26e5742354
ios: fix swipe in members list for iOS 15 (#5914)
* ios: fix swipe in members list for iOS 15

* refactor
2025-05-15 14:58:40 +01:00
Evgeny
5dd89fe127
ios: fix swipe on iOS 15, fix onboarding layout on iOS 15 and small screens (#5913)
* ios: fix onboarding layout issues on iOS 15 and small screens

* fix swipe on iOS 15
2025-05-15 14:25:46 +01:00
sh
a36a6d44db
flatpak: update metainfo (#5899)
* flatpak: update metainfo

* flatpak: rewrite metainfo
2025-05-14 10:55:03 +01:00
87 changed files with 529 additions and 496 deletions

View file

@ -10,7 +10,7 @@
# SimpleX - the first messaging platform that has no user identifiers of any kind - 100% private by design! # SimpleX - the first messaging platform that has no user identifiers of any kind - 100% private by design!
[<img src="./images/trail-of-bits.jpg" height="100">](http://simplex.chat/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html) &nbsp;&nbsp;&nbsp; [<img src="./images/privacy-guides.jpg" height="80">](https://www.privacyguides.org/en/real-time-communication/#simplex-chat) &nbsp;&nbsp;&nbsp; [<img src="./images/kuketz-blog.jpg" height="80">](https://www.kuketz-blog.de/simplex-eindruecke-vom-messenger-ohne-identifier/) [<img src="./images/trail-of-bits.jpg" height="80">](http://simplex.chat/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html) &nbsp;&nbsp;&nbsp; [<img src="./images/privacy-guides.jpg" height="64">](https://www.privacyguides.org/en/real-time-communication/#simplex-chat) &nbsp;&nbsp;&nbsp; [<img src="./images/whonix-logo.jpg" height="64">](https://www.whonix.org/wiki/Chat#Recommendation) &nbsp;&nbsp;&nbsp; [<img src="./images/kuketz-blog.jpg" height="64">](https://www.kuketz-blog.de/simplex-eindruecke-vom-messenger-ohne-identifier/)
## Welcome to SimpleX Chat! ## Welcome to SimpleX Chat!
@ -110,6 +110,15 @@ After you connect, you can [verify connection security code](./blog/20230103-sim
Read about the app features and settings in the new [User guide](./docs/guide/README.md). Read about the app features and settings in the new [User guide](./docs/guide/README.md).
## Contribute
We would love to have you join the development! You can help us with:
- [share the color theme](./docs/THEMES.md) you use in Android app!
- writing a tutorial or recipes about hosting servers, chat bot automations, etc.
- contributing to SimpleX Chat knowledge-base.
- developing features - please connect to us via chat so we can help you get started.
## Help translating SimpleX Chat ## Help translating SimpleX Chat
Thanks to our users and [Weblate](https://hosted.weblate.org/engage/simplex-chat/), SimpleX Chat apps, website and documents are translated to many other languages. Thanks to our users and [Weblate](https://hosted.weblate.org/engage/simplex-chat/), SimpleX Chat apps, website and documents are translated to many other languages.
@ -141,15 +150,6 @@ Join our translators to help SimpleX grow!
Languages in progress: Arabic, Japanese, Korean, Portuguese and [others](https://hosted.weblate.org/projects/simplex-chat/#languages). We will be adding more languages as some of the already added are completed please suggest new languages, review the [translation guide](./docs/TRANSLATIONS.md) and get in touch with us! Languages in progress: Arabic, Japanese, Korean, Portuguese and [others](https://hosted.weblate.org/projects/simplex-chat/#languages). We will be adding more languages as some of the already added are completed please suggest new languages, review the [translation guide](./docs/TRANSLATIONS.md) and get in touch with us!
## Contribute
We would love to have you join the development! You can help us with:
- [share the color theme](./docs/THEMES.md) you use in Android app!
- writing a tutorial or recipes about hosting servers, chat bot automations, etc.
- contributing to SimpleX Chat knowledge-base.
- developing features - please connect to us via chat so we can help you get started.
## Please support us with your donations ## Please support us with your donations
Huge thank you to everybody who donated to SimpleX Chat! Huge thank you to everybody who donated to SimpleX Chat!

View file

@ -1152,27 +1152,6 @@ final class Chat: ObservableObject, Identifiable, ChatLike {
) )
} }
var userCanSend: Bool {
switch chatInfo {
case .direct: return true
case let .group(groupInfo):
let m = groupInfo.membership
return m.memberActive && m.memberRole >= .member
case .local:
return true
default: return false
}
}
var userIsObserver: Bool {
switch chatInfo {
case let .group(groupInfo):
let m = groupInfo.membership
return m.memberActive && m.memberRole == .observer
default: return false
}
}
var unreadTag: Bool { var unreadTag: Bool {
switch chatInfo.chatSettings?.enableNtfs { switch chatInfo.chatSettings?.enableNtfs {
case .all: chatStats.unreadChat || chatStats.unreadCount > 0 case .all: chatStats.unreadChat || chatStats.unreadCount > 0

View file

@ -98,14 +98,24 @@ struct ChatView: View {
} }
connectingText() connectingText()
if selectedChatItems == nil { if selectedChatItems == nil {
let reason = chat.chatInfo.userCantSendReason
ComposeView( ComposeView(
chat: chat, chat: chat,
composeState: $composeState, composeState: $composeState,
keyboardVisible: $keyboardVisible, keyboardVisible: $keyboardVisible,
keyboardHiddenDate: $keyboardHiddenDate, keyboardHiddenDate: $keyboardHiddenDate,
selectedRange: $selectedRange selectedRange: $selectedRange,
disabledText: reason?.composeLabel
) )
.disabled(!cInfo.sendMsgEnabled) .disabled(!cInfo.sendMsgEnabled)
.if(!cInfo.sendMsgEnabled) { v in
v.disabled(true).onTapGesture {
AlertManager.shared.showAlertMsg(
title: "You can't send messages!",
message: reason?.alertMessage
)
}
}
} else { } else {
SelectedItemsBottomToolbar( SelectedItemsBottomToolbar(
chatItems: ItemsModel.shared.reversedChatItems, chatItems: ItemsModel.shared.reversedChatItems,

View file

@ -327,6 +327,7 @@ struct ComposeView: View {
@Binding var keyboardVisible: Bool @Binding var keyboardVisible: Bool
@Binding var keyboardHiddenDate: Date @Binding var keyboardHiddenDate: Date
@Binding var selectedRange: NSRange @Binding var selectedRange: NSRange
var disabledText: LocalizedStringKey? = nil
@State var linkUrl: URL? = nil @State var linkUrl: URL? = nil
@State var hasSimplexLink: Bool = false @State var hasSimplexLink: Bool = false
@ -391,7 +392,7 @@ struct ComposeView: View {
Image(systemName: "paperclip") Image(systemName: "paperclip")
.resizable() .resizable()
} }
.disabled(composeState.attachmentDisabled || !chat.userCanSend || (chat.chatInfo.contact?.nextSendGrpInv ?? false)) .disabled(composeState.attachmentDisabled || !chat.chatInfo.sendMsgEnabled || (chat.chatInfo.contact?.nextSendGrpInv ?? false))
.frame(width: 25, height: 25) .frame(width: 25, height: 25)
.padding(.bottom, 16) .padding(.bottom, 16)
.padding(.leading, 12) .padding(.leading, 12)
@ -441,19 +442,13 @@ struct ComposeView: View {
: theme.colors.primary : theme.colors.primary
) )
.padding(.trailing, 12) .padding(.trailing, 12)
.disabled(!chat.userCanSend) .disabled(!chat.chatInfo.sendMsgEnabled)
if chat.userIsObserver { if let disabledText {
Text("you are observer") Text(disabledText)
.italic() .italic()
.foregroundColor(theme.colors.secondary) .foregroundColor(theme.colors.secondary)
.padding(.horizontal, 12) .padding(.horizontal, 12)
.onTapGesture {
AlertManager.shared.showAlertMsg(
title: "You can't send messages!",
message: "Please contact group admin."
)
}
} }
} }
} }
@ -479,8 +474,8 @@ struct ComposeView: View {
hasSimplexLink = false hasSimplexLink = false
} }
} }
.onChange(of: chat.userCanSend) { canSend in .onChange(of: chat.chatInfo.sendMsgEnabled) { sendEnabled in
if !canSend { if !sendEnabled {
cancelCurrentVoiceRecording() cancelCurrentVoiceRecording()
clearCurrentDraft() clearCurrentDraft()
clearState() clearState()

View file

@ -15,6 +15,7 @@ struct SendMessageView: View {
@Binding var composeState: ComposeState @Binding var composeState: ComposeState
@Binding var selectedRange: NSRange @Binding var selectedRange: NSRange
@EnvironmentObject var theme: AppTheme @EnvironmentObject var theme: AppTheme
@Environment(\.isEnabled) var isEnabled
var sendMessage: (Int?) -> Void var sendMessage: (Int?) -> Void
var sendLiveMessage: (() async -> Void)? = nil var sendLiveMessage: (() async -> Void)? = nil
var updateLiveMessage: (() async -> Void)? = nil var updateLiveMessage: (() async -> Void)? = nil
@ -255,6 +256,7 @@ struct SendMessageView: View {
} }
private struct RecordVoiceMessageButton: View { private struct RecordVoiceMessageButton: View {
@Environment(\.isEnabled) var isEnabled
@EnvironmentObject var theme: AppTheme @EnvironmentObject var theme: AppTheme
var startVoiceMessageRecording: (() -> Void)? var startVoiceMessageRecording: (() -> Void)?
var finishVoiceMessageRecording: (() -> Void)? var finishVoiceMessageRecording: (() -> Void)?
@ -263,11 +265,11 @@ struct SendMessageView: View {
@State private var pressed: TimeInterval? = nil @State private var pressed: TimeInterval? = nil
var body: some View { var body: some View {
Image(systemName: "mic.fill") Image(systemName: isEnabled ? "mic.fill" : "mic")
.resizable() .resizable()
.scaledToFit() .scaledToFit()
.frame(width: 20, height: 20) .frame(width: 20, height: 20)
.foregroundColor(theme.colors.primary) .foregroundColor(isEnabled ? theme.colors.primary : theme.colors.secondary)
.opacity(holdingVMR ? 0.7 : 1) .opacity(holdingVMR ? 0.7 : 1)
.disabled(disabled) .disabled(disabled)
.frame(width: 31, height: 31) .frame(width: 31, height: 31)
@ -352,7 +354,7 @@ struct SendMessageView: View {
Image(systemName: "bolt.fill") Image(systemName: "bolt.fill")
.resizable() .resizable()
.scaledToFit() .scaledToFit()
.foregroundColor(theme.colors.primary) .foregroundColor(isEnabled ? theme.colors.primary : theme.colors.secondary)
.frame(width: 20, height: 20) .frame(width: 20, height: 20)
} }
.frame(width: 29, height: 29) .frame(width: 29, height: 29)

View file

@ -144,17 +144,9 @@ struct GroupChatInfoView: View {
let filteredMembers = s == "" let filteredMembers = s == ""
? members ? members
: members.filter { $0.wrapped.localAliasAndFullName.localizedLowercase.contains(s) } : members.filter { $0.wrapped.localAliasAndFullName.localizedLowercase.contains(s) }
MemberRowView(groupInfo: groupInfo, groupMember: GMember(groupInfo.membership), user: true, alert: $alert) MemberRowView(chat: chat, groupInfo: groupInfo, groupMember: GMember(groupInfo.membership), user: true, alert: $alert)
ForEach(filteredMembers) { member in ForEach(filteredMembers) { member in
ZStack { MemberRowView(chat: chat, groupInfo: groupInfo, groupMember: member, alert: $alert)
NavigationLink {
memberInfoView(member)
} label: {
EmptyView()
}
.opacity(0)
MemberRowView(groupInfo: groupInfo, groupMember: member, alert: $alert)
}
} }
} }
@ -358,6 +350,7 @@ struct GroupChatInfoView: View {
} }
private struct MemberRowView: View { private struct MemberRowView: View {
var chat: Chat
var groupInfo: GroupInfo var groupInfo: GroupInfo
@ObservedObject var groupMember: GMember @ObservedObject var groupMember: GMember
@EnvironmentObject var theme: AppTheme @EnvironmentObject var theme: AppTheme
@ -366,7 +359,7 @@ struct GroupChatInfoView: View {
var body: some View { var body: some View {
let member = groupMember.wrapped let member = groupMember.wrapped
let v = HStack{ let v1 = HStack{
MemberProfileImage(member, size: 38) MemberProfileImage(member, size: 38)
.padding(.trailing, 2) .padding(.trailing, 2)
// TODO server connection status // TODO server connection status
@ -383,6 +376,20 @@ struct GroupChatInfoView: View {
memberInfo(member) memberInfo(member)
} }
let v = ZStack {
if user {
v1
} else {
NavigationLink {
memberInfoView()
} label: {
EmptyView()
}
.opacity(0)
v1
}
}
if user { if user {
v v
} else if groupInfo.membership.memberRole >= .admin { } else if groupInfo.membership.memberRole >= .admin {
@ -407,6 +414,11 @@ struct GroupChatInfoView: View {
} }
} }
private func memberInfoView() -> some View {
GroupMemberInfoView(groupInfo: groupInfo, chat: chat, groupMember: groupMember)
.navigationBarHidden(false)
}
private func memberConnStatus(_ member: GroupMember) -> LocalizedStringKey { private func memberConnStatus(_ member: GroupMember) -> LocalizedStringKey {
if member.activeConn?.connDisabled ?? false { if member.activeConn?.connDisabled ?? false {
return "disabled" return "disabled"
@ -486,11 +498,6 @@ struct GroupChatInfoView: View {
} }
} }
private func memberInfoView(_ groupMember: GMember) -> some View {
GroupMemberInfoView(groupInfo: groupInfo, chat: chat, groupMember: groupMember)
.navigationBarHidden(false)
}
private func groupLinkButton() -> some View { private func groupLinkButton() -> some View {
NavigationLink { NavigationLink {
groupLinkDestinationView() groupLinkDestinationView()

View file

@ -94,7 +94,7 @@ struct ChatListNavLink: View {
Group { Group {
if contact.activeConn == nil && contact.profile.contactLink != nil && contact.active { if contact.activeConn == nil && contact.profile.contactLink != nil && contact.active {
ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false)) ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false))
.frame(height: dynamicRowHeight) .frameCompat(height: dynamicRowHeight)
.swipeActions(edge: .trailing, allowsFullSwipe: true) { .swipeActions(edge: .trailing, allowsFullSwipe: true) {
Button { Button {
deleteContactDialog( deleteContactDialog(
@ -121,6 +121,7 @@ struct ChatListNavLink: View {
selection: $chatModel.chatId, selection: $chatModel.chatId,
label: { ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false)) } label: { ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false)) }
) )
.frameCompat(height: dynamicRowHeight)
.swipeActions(edge: .leading, allowsFullSwipe: true) { .swipeActions(edge: .leading, allowsFullSwipe: true) {
markReadButton() markReadButton()
toggleFavoriteButton() toggleFavoriteButton()
@ -145,7 +146,6 @@ struct ChatListNavLink: View {
} }
.tint(.red) .tint(.red)
} }
.frame(height: dynamicRowHeight)
} }
} }
.alert(item: $alert) { $0.alert } .alert(item: $alert) { $0.alert }
@ -163,7 +163,7 @@ struct ChatListNavLink: View {
switch (groupInfo.membership.memberStatus) { switch (groupInfo.membership.memberStatus) {
case .memInvited: case .memInvited:
ChatPreviewView(chat: chat, progressByTimeout: $progressByTimeout) ChatPreviewView(chat: chat, progressByTimeout: $progressByTimeout)
.frame(height: dynamicRowHeight) .frameCompat(height: dynamicRowHeight)
.swipeActions(edge: .trailing, allowsFullSwipe: true) { .swipeActions(edge: .trailing, allowsFullSwipe: true) {
joinGroupButton() joinGroupButton()
if groupInfo.canDelete { if groupInfo.canDelete {
@ -183,7 +183,7 @@ struct ChatListNavLink: View {
.disabled(inProgress) .disabled(inProgress)
case .memAccepted: case .memAccepted:
ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false)) ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false))
.frame(height: dynamicRowHeight) .frameCompat(height: dynamicRowHeight)
.onTapGesture { .onTapGesture {
AlertManager.shared.showAlert(groupInvitationAcceptedAlert()) AlertManager.shared.showAlert(groupInvitationAcceptedAlert())
} }
@ -203,7 +203,7 @@ struct ChatListNavLink: View {
label: { ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false)) }, label: { ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false)) },
disabled: !groupInfo.ready disabled: !groupInfo.ready
) )
.frame(height: dynamicRowHeight) .frameCompat(height: dynamicRowHeight)
.swipeActions(edge: .leading, allowsFullSwipe: true) { .swipeActions(edge: .leading, allowsFullSwipe: true) {
markReadButton() markReadButton()
toggleFavoriteButton() toggleFavoriteButton()
@ -250,7 +250,7 @@ struct ChatListNavLink: View {
label: { ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false)) }, label: { ChatPreviewView(chat: chat, progressByTimeout: Binding.constant(false)) },
disabled: !noteFolder.ready disabled: !noteFolder.ready
) )
.frame(height: dynamicRowHeight) .frameCompat(height: dynamicRowHeight)
.swipeActions(edge: .leading, allowsFullSwipe: true) { .swipeActions(edge: .leading, allowsFullSwipe: true) {
markReadButton() markReadButton()
} }
@ -433,6 +433,7 @@ struct ChatListNavLink: View {
private func contactRequestNavLink(_ contactRequest: UserContactRequest) -> some View { private func contactRequestNavLink(_ contactRequest: UserContactRequest) -> some View {
ContactRequestView(contactRequest: contactRequest, chat: chat) ContactRequestView(contactRequest: contactRequest, chat: chat)
.frameCompat(height: dynamicRowHeight)
.swipeActions(edge: .trailing, allowsFullSwipe: true) { .swipeActions(edge: .trailing, allowsFullSwipe: true) {
Button { Button {
Task { await acceptContactRequest(incognito: false, contactRequest: contactRequest) } Task { await acceptContactRequest(incognito: false, contactRequest: contactRequest) }
@ -451,7 +452,6 @@ struct ChatListNavLink: View {
} }
.tint(.red) .tint(.red)
} }
.frame(height: dynamicRowHeight)
.contentShape(Rectangle()) .contentShape(Rectangle())
.onTapGesture { showContactRequestDialog = true } .onTapGesture { showContactRequestDialog = true }
.confirmationDialog("Accept connection request?", isPresented: $showContactRequestDialog, titleVisibility: .visible) { .confirmationDialog("Accept connection request?", isPresented: $showContactRequestDialog, titleVisibility: .visible) {
@ -463,6 +463,7 @@ struct ChatListNavLink: View {
private func contactConnectionNavLink(_ contactConnection: PendingContactConnection) -> some View { private func contactConnectionNavLink(_ contactConnection: PendingContactConnection) -> some View {
ContactConnectionView(chat: chat) ContactConnectionView(chat: chat)
.frameCompat(height: dynamicRowHeight)
.swipeActions(edge: .trailing, allowsFullSwipe: true) { .swipeActions(edge: .trailing, allowsFullSwipe: true) {
Button { Button {
AlertManager.shared.showAlert(deleteContactConnectionAlert(contactConnection) { a in AlertManager.shared.showAlert(deleteContactConnectionAlert(contactConnection) { a in
@ -480,7 +481,6 @@ struct ChatListNavLink: View {
} }
.tint(theme.colors.primary) .tint(theme.colors.primary)
} }
.frame(height: dynamicRowHeight)
.appSheet(isPresented: $showContactConnectionInfo) { .appSheet(isPresented: $showContactConnectionInfo) {
Group { Group {
if case let .contactConnection(contactConnection) = chat.chatInfo { if case let .contactConnection(contactConnection) = chat.chatInfo {
@ -583,7 +583,7 @@ struct ChatListNavLink: View {
Text("invalid chat data") Text("invalid chat data")
.foregroundColor(.red) .foregroundColor(.red)
.padding(4) .padding(4)
.frame(height: dynamicRowHeight) .frameCompat(height: dynamicRowHeight)
.onTapGesture { showInvalidJSON = true } .onTapGesture { showInvalidJSON = true }
.appSheet(isPresented: $showInvalidJSON) { .appSheet(isPresented: $showInvalidJSON) {
invalidJSONView(dataToString(json)) invalidJSONView(dataToString(json))
@ -603,6 +603,24 @@ struct ChatListNavLink: View {
} }
} }
extension View {
@inline(__always)
@ViewBuilder fileprivate func frameCompat(height: CGFloat) -> some View {
if #available(iOS 16, *) {
self.frame(height: height)
} else {
VStack(spacing: 0) {
Divider()
.padding(.leading, 16)
self
.frame(height: height)
.padding(.horizontal, 8)
.padding(.vertical, 8)
}
}
}
}
func rejectContactRequestAlert(_ contactRequest: UserContactRequest) -> Alert { func rejectContactRequestAlert(_ contactRequest: UserContactRequest) -> Alert {
Alert( Alert(
title: Text("Reject contact request"), title: Text("Reject contact request"),

View file

@ -367,13 +367,7 @@ struct ChatListView: View {
.offset(x: -8) .offset(x: -8)
} else { } else {
ForEach(cs, id: \.viewId) { chat in ForEach(cs, id: \.viewId) { chat in
VStack(spacing: .zero) {
Divider()
.padding(.leading, 16)
ChatListNavLink(chat: chat, parentSheet: $sheet) ChatListNavLink(chat: chat, parentSheet: $sheet)
.padding(.horizontal, 8)
.padding(.vertical, 6)
}
.scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center) .scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center)
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
.listRowInsets(EdgeInsets()) .listRowInsets(EdgeInsets())

View file

@ -67,7 +67,7 @@ struct OnboardingConditionsView: View {
var body: some View { var body: some View {
GeometryReader { g in GeometryReader { g in
ScrollView { let v = ScrollView {
VStack(alignment: .leading, spacing: 20) { VStack(alignment: .leading, spacing: 20) {
Text("Conditions of use") Text("Conditions of use")
.font(.largeTitle) .font(.largeTitle)
@ -107,6 +107,7 @@ struct OnboardingConditionsView: View {
.frame(minHeight: 40) .frame(minHeight: 40)
} }
} }
.padding(25)
.frame(minHeight: g.size.height) .frame(minHeight: g.size.height)
} }
.onAppear { .onAppear {
@ -127,9 +128,14 @@ struct OnboardingConditionsView: View {
} }
} }
.frame(maxHeight: .infinity, alignment: .top) .frame(maxHeight: .infinity, alignment: .top)
if #available(iOS 16.4, *) {
v.scrollBounceBehavior(.basedOnSize)
} else {
v
}
} }
.frame(maxHeight: .infinity, alignment: .top) .frame(maxHeight: .infinity, alignment: .top)
.padding(25) .navigationBarHidden(true) // necessary on iOS 15
} }
private func continueToNextStep() { private func continueToNextStep() {

View file

@ -62,8 +62,7 @@ struct CreateProfile: View {
.frame(height: 20) .frame(height: 20)
} footer: { } footer: {
VStack(alignment: .leading, spacing: 8) { VStack(alignment: .leading, spacing: 8) {
Text("Your profile, contacts and delivered messages are stored on your device.") Text("Your profile is stored on your device and only shared with your contacts.")
Text("The profile is only shared with your contacts.")
} }
.foregroundColor(theme.colors.secondary) .foregroundColor(theme.colors.secondary)
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
@ -118,25 +117,22 @@ struct CreateFirstProfile: View {
@State private var nextStepNavLinkActive = false @State private var nextStepNavLinkActive = false
var body: some View { var body: some View {
VStack(alignment: .leading, spacing: 20) { let v = VStack(alignment: .leading, spacing: 16) {
VStack(alignment: .center, spacing: 20) { VStack(alignment: .center, spacing: 16) {
Text("Create your profile") Text("Create profile")
.font(.largeTitle) .font(.largeTitle)
.bold() .bold()
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
Text("Your profile, contacts and delivered messages are stored on your device.") Text("Your profile is stored on your device and only shared with your contacts.")
.font(.callout)
.foregroundColor(theme.colors.secondary)
.multilineTextAlignment(.center)
Text("The profile is only shared with your contacts.")
.font(.callout) .font(.callout)
.foregroundColor(theme.colors.secondary) .foregroundColor(theme.colors.secondary)
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
} }
.fixedSize(horizontal: false, vertical: true)
.frame(maxWidth: .infinity) // Ensures it takes up the full width .frame(maxWidth: .infinity) // Ensures it takes up the full width
.padding(.horizontal, 10) .padding(.horizontal, 10)
.onTapGesture { focusDisplayName = false }
HStack { HStack {
let name = displayName.trimmingCharacters(in: .whitespaces) let name = displayName.trimmingCharacters(in: .whitespaces)
@ -174,12 +170,23 @@ struct CreateFirstProfile: View {
} }
} }
.onAppear() { .onAppear() {
if #available(iOS 16, *) {
focusDisplayName = true
} else {
// it does not work before animation completes on iOS 15
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
focusDisplayName = true focusDisplayName = true
} }
}
}
.padding(.horizontal, 25) .padding(.horizontal, 25)
.padding(.top, 10)
.padding(.bottom, 25) .padding(.bottom, 25)
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
if #available(iOS 16, *) {
return v.padding(.top, 10)
} else {
return v.padding(.top, 75).ignoresSafeArea(.all, edges: .top)
}
} }
func createProfileButton() -> some View { func createProfileButton() -> some View {

View file

@ -17,7 +17,7 @@ struct SetNotificationsMode: View {
var body: some View { var body: some View {
GeometryReader { g in GeometryReader { g in
ScrollView { let v = ScrollView {
VStack(alignment: .center, spacing: 20) { VStack(alignment: .center, spacing: 20) {
Text("Push notifications") Text("Push notifications")
.font(.largeTitle) .font(.largeTitle)
@ -57,11 +57,17 @@ struct SetNotificationsMode: View {
.padding(25) .padding(25)
.frame(minHeight: g.size.height) .frame(minHeight: g.size.height)
} }
if #available(iOS 16.4, *) {
v.scrollBounceBehavior(.basedOnSize)
} else {
v
}
} }
.frame(maxHeight: .infinity) .frame(maxHeight: .infinity)
.sheet(isPresented: $showInfo) { .sheet(isPresented: $showInfo) {
NotificationsInfoView() NotificationsInfoView()
} }
.navigationBarHidden(true) // necessary on iOS 15
} }
private func setNotificationsMode(_ token: DeviceToken, _ mode: NotificationsMode) { private func setNotificationsMode(_ token: DeviceToken, _ mode: NotificationsMode) {

View file

@ -18,7 +18,7 @@ struct SimpleXInfo: View {
var body: some View { var body: some View {
GeometryReader { g in GeometryReader { g in
ScrollView { let v = ScrollView {
VStack(alignment: .leading) { VStack(alignment: .leading) {
VStack(alignment: .center, spacing: 10) { VStack(alignment: .center, spacing: 10) {
Image(colorScheme == .light ? "logo" : "logo-light") Image(colorScheme == .light ? "logo" : "logo-light")
@ -66,6 +66,9 @@ struct SimpleXInfo: View {
} }
} }
} }
.padding(.horizontal, 25)
.padding(.top, 75)
.padding(.bottom, 25)
.frame(minHeight: g.size.height) .frame(minHeight: g.size.height)
} }
.sheet(isPresented: Binding( .sheet(isPresented: Binding(
@ -88,14 +91,17 @@ struct SimpleXInfo: View {
createProfileNavLinkActive: $createProfileNavLinkActive createProfileNavLinkActive: $createProfileNavLinkActive
) )
} }
if #available(iOS 16.4, *) {
v.scrollBounceBehavior(.basedOnSize)
} else {
v
}
} }
.onAppear() { .onAppear() {
setLastVersionDefault() setLastVersionDefault()
} }
.frame(maxHeight: .infinity) .frame(maxHeight: .infinity)
.padding(.horizontal, 25) .navigationBarHidden(true) // necessary on iOS 15
.padding(.top, 75)
.padding(.bottom, 25)
} }
private func onboardingInfoRow(_ image: String, _ title: LocalizedStringKey, _ text: LocalizedStringKey, width: CGFloat) -> some View { private func onboardingInfoRow(_ image: String, _ title: LocalizedStringKey, _ text: LocalizedStringKey, width: CGFloat) -> some View {

View file

@ -2826,8 +2826,8 @@ We will be adding server redundancy to prevent lost messages.</source>
<source>The old database was not removed during the migration, it can be deleted.</source> <source>The old database was not removed during the migration, it can be deleted.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source> <source>Your profile is stored on your device and only shared with your contacts.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The sender will NOT be notified" xml:space="preserve"> <trans-unit id="The sender will NOT be notified" xml:space="preserve">

View file

@ -7329,11 +7329,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Старата база данни не бе премахната по време на миграцията, тя може да бъде изтрита.</target> <target>Старата база данни не бе премахната по време на миграцията, тя може да бъде изтрита.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>Профилът се споделя само с вашите контакти.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@ -8577,6 +8572,11 @@ Repeat connection request?</source>
<target>Вашият профил **%@** ще бъде споделен.</target> <target>Вашият профил **%@** ще бъде споделен.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>Профилът се споделя само с вашите контакти.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Вашият профил се съхранява на вашето устройство и се споделя само с вашите контакти. SimpleX сървърите не могат да видят вашия профил.</target> <target>Вашият профил се съхранява на вашето устройство и се споделя само с вашите контакти. SimpleX сървърите не могат да видят вашия профил.</target>
@ -8586,11 +8586,6 @@ Repeat connection request?</source>
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source> <source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Вашият профил, контакти и доставени съобщения се съхраняват на вашето устройство.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Вашият автоматично генериран профил</target> <target>Вашият автоматично генериран профил</target>

View file

@ -3422,8 +3422,8 @@ It can happen because of some bug or when the connection is compromised.</source
<source>The old database was not removed during the migration, it can be deleted.</source> <source>The old database was not removed during the migration, it can be deleted.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source> <source>Your profile is stored on your device and only shared with your contacts.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The sender will NOT be notified" xml:space="preserve"> <trans-unit id="The sender will NOT be notified" xml:space="preserve">

View file

@ -1942,6 +1942,7 @@ This is your own one-time link!</source>
</trans-unit> </trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<target>Vytvořte si profil</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create queue" xml:space="preserve"> <trans-unit id="Create queue" xml:space="preserve">
@ -7080,11 +7081,6 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován
<target>Stará databáze nebyla během přenášení odstraněna, lze ji smazat.</target> <target>Stará databáze nebyla během přenášení odstraněna, lze ji smazat.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>Profil je sdílen pouze s vašimi kontakty.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@ -8271,6 +8267,11 @@ Repeat connection request?</source>
<target>Váš profil **%@** bude sdílen.</target> <target>Váš profil **%@** bude sdílen.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>Profil je sdílen pouze s vašimi kontakty.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Váš profil je uložen ve vašem zařízení a sdílen pouze s vašimi kontakty. Servery SimpleX nevidí váš profil.</target> <target>Váš profil je uložen ve vašem zařízení a sdílen pouze s vašimi kontakty. Servery SimpleX nevidí váš profil.</target>
@ -8280,11 +8281,6 @@ Repeat connection request?</source>
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source> <source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Váš profil, kontakty a doručené zprávy jsou uloženy ve vašem zařízení.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Váš náhodný profil</target> <target>Váš náhodný profil</target>

View file

@ -7763,11 +7763,6 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
<target>Die alte Datenbank wurde während der Migration nicht entfernt. Sie kann gelöscht werden.</target> <target>Die alte Datenbank wurde während der Migration nicht entfernt. Sie kann gelöscht werden.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>Das Profil wird nur mit Ihren Kontakten geteilt.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<target>Dieselben Nutzungsbedingungen gelten auch für den Betreiber **%@**.</target> <target>Dieselben Nutzungsbedingungen gelten auch für den Betreiber **%@**.</target>
@ -9081,6 +9076,11 @@ Verbindungsanfrage wiederholen?</target>
<target>Ihr Profil **%@** wird geteilt.</target> <target>Ihr Profil **%@** wird geteilt.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>Das Profil wird nur mit Ihren Kontakten geteilt.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Ihr Profil wird auf Ihrem Gerät gespeichert und nur mit Ihren Kontakten geteilt. SimpleX-Server können Ihr Profil nicht einsehen.</target> <target>Ihr Profil wird auf Ihrem Gerät gespeichert und nur mit Ihren Kontakten geteilt. SimpleX-Server können Ihr Profil nicht einsehen.</target>
@ -9091,11 +9091,6 @@ Verbindungsanfrage wiederholen?</target>
<target>Ihr Profil wurde geändert. Wenn Sie es speichern, wird das aktualisierte Profil an alle Ihre Kontakte gesendet.</target> <target>Ihr Profil wurde geändert. Wenn Sie es speichern, wird das aktualisierte Profil an alle Ihre Kontakte gesendet.</target>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Ihr Profil, Ihre Kontakte und zugestellten Nachrichten werden auf Ihrem Gerät gespeichert.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Ihr Zufallsprofil</target> <target>Ihr Zufallsprofil</target>

View file

@ -3043,8 +3043,8 @@ It can happen because of some bug or when the connection is compromised.</source
<source>The old database was not removed during the migration, it can be deleted.</source> <source>The old database was not removed during the migration, it can be deleted.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source> <source>Your profile is stored on your device and only shared with your contacts.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The sender will NOT be notified" xml:space="preserve"> <trans-unit id="The sender will NOT be notified" xml:space="preserve">

View file

@ -7764,11 +7764,6 @@ It can happen because of some bug or when the connection is compromised.</target
<target>The old database was not removed during the migration, it can be deleted.</target> <target>The old database was not removed during the migration, it can be deleted.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>The profile is only shared with your contacts.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<target>The same conditions will apply to operator **%@**.</target> <target>The same conditions will apply to operator **%@**.</target>
@ -9082,6 +9077,11 @@ Repeat connection request?</target>
<target>Your profile **%@** will be shared.</target> <target>Your profile **%@** will be shared.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>Your profile is stored on your device and only shared with your contacts.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</target> <target>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</target>
@ -9092,11 +9092,6 @@ Repeat connection request?</target>
<target>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</target> <target>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</target>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Your profile, contacts and delivered messages are stored on your device.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Your random profile</target> <target>Your random profile</target>

View file

@ -7763,11 +7763,6 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target>
<target>La base de datos antigua no se eliminó durante la migración, puede eliminarse.</target> <target>La base de datos antigua no se eliminó durante la migración, puede eliminarse.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>El perfil sólo se comparte con tus contactos.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<target>Las mismas condiciones se aplicarán al operador **%@**.</target> <target>Las mismas condiciones se aplicarán al operador **%@**.</target>
@ -9081,6 +9076,11 @@ Repeat connection request?</source>
<target>El perfil **%@** será compartido.</target> <target>El perfil **%@** será compartido.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>El perfil sólo se comparte con tus contactos.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos. Los servidores SimpleX no pueden ver tu perfil.</target> <target>Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos. Los servidores SimpleX no pueden ver tu perfil.</target>
@ -9091,11 +9091,6 @@ Repeat connection request?</source>
<target>Tu perfil ha sido modificado. Si lo guardas la actualización será enviada a todos tus contactos.</target> <target>Tu perfil ha sido modificado. Si lo guardas la actualización será enviada a todos tus contactos.</target>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Tu perfil, contactos y mensajes se almacenan en tu dispositivo.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Tu perfil aleatorio</target> <target>Tu perfil aleatorio</target>

View file

@ -1923,6 +1923,7 @@ This is your own one-time link!</source>
</trans-unit> </trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<target>Luo profiilisi</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create queue" xml:space="preserve"> <trans-unit id="Create queue" xml:space="preserve">
@ -7054,11 +7055,6 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.</t
<target>Vanhaa tietokantaa ei poistettu siirron aikana, se voidaan kuitenkin poistaa.</target> <target>Vanhaa tietokantaa ei poistettu siirron aikana, se voidaan kuitenkin poistaa.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>Profiili jaetaan vain kontaktiesi kanssa.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@ -8244,6 +8240,11 @@ Repeat connection request?</source>
<target>Profiilisi **%@** jaetaan.</target> <target>Profiilisi **%@** jaetaan.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>Profiili jaetaan vain kontaktiesi kanssa.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Profiilisi tallennetaan laitteeseesi ja jaetaan vain yhteystietojesi kanssa. SimpleX-palvelimet eivät näe profiiliasi.</target> <target>Profiilisi tallennetaan laitteeseesi ja jaetaan vain yhteystietojesi kanssa. SimpleX-palvelimet eivät näe profiiliasi.</target>
@ -8253,11 +8254,6 @@ Repeat connection request?</source>
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source> <source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Profiilisi, kontaktisi ja toimitetut viestit tallennetaan laitteellesi.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Satunnainen profiilisi</target> <target>Satunnainen profiilisi</target>

View file

@ -7696,11 +7696,6 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
<target>L'ancienne base de données n'a pas été supprimée lors de la migration, elle peut être supprimée.</target> <target>L'ancienne base de données n'a pas été supprimée lors de la migration, elle peut être supprimée.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>Le profil n'est partagé qu'avec vos contacts.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<target>Les mêmes conditions s'appliquent à l'opérateur **%@**.</target> <target>Les mêmes conditions s'appliquent à l'opérateur **%@**.</target>
@ -9003,6 +8998,11 @@ Répéter la demande de connexion ?</target>
<target>Votre profil **%@** sera partagé.</target> <target>Votre profil **%@** sera partagé.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>Le profil n'est partagé qu'avec vos contacts.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Votre profil est stocké sur votre appareil et est seulement partagé avec vos contacts. Les serveurs SimpleX ne peuvent pas voir votre profil.</target> <target>Votre profil est stocké sur votre appareil et est seulement partagé avec vos contacts. Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
@ -9013,11 +9013,6 @@ Répéter la demande de connexion ?</target>
<target>Votre profil a été modifié. Si vous l'enregistrez, le profil mis à jour sera envoyé à tous vos contacts.</target> <target>Votre profil a été modifié. Si vous l'enregistrez, le profil mis à jour sera envoyé à tous vos contacts.</target>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Votre profil, vos contacts et les messages reçus sont stockés sur votre appareil.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Votre profil aléatoire</target> <target>Votre profil aléatoire</target>

View file

@ -3569,8 +3569,8 @@ It can happen because of some bug or when the connection is compromised.</source
<source>The old database was not removed during the migration, it can be deleted.</source> <source>The old database was not removed during the migration, it can be deleted.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source> <source>Your profile is stored on your device and only shared with your contacts.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The sender will NOT be notified" xml:space="preserve"> <trans-unit id="The sender will NOT be notified" xml:space="preserve">

View file

@ -2619,8 +2619,8 @@ We will be adding server redundancy to prevent lost messages.</source>
<source>The old database was not removed during the migration, it can be deleted.</source> <source>The old database was not removed during the migration, it can be deleted.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source> <source>Your profile is stored on your device and only shared with your contacts.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The sender will NOT be notified" xml:space="preserve"> <trans-unit id="The sender will NOT be notified" xml:space="preserve">

View file

@ -7763,11 +7763,6 @@ Ez valamilyen hiba vagy sérült kapcsolat esetén fordulhat elő.</target>
<target>A régi adatbázis nem lett eltávolítva az átköltöztetéskor, ezért törölhető.</target> <target>A régi adatbázis nem lett eltávolítva az átköltöztetéskor, ezért törölhető.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>A profilja csak a partnereivel van megosztva.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<target>Ugyanezek a feltételek lesznek elfogadva a következő üzemeltető számára is: **%@**.</target> <target>Ugyanezek a feltételek lesznek elfogadva a következő üzemeltető számára is: **%@**.</target>
@ -9081,6 +9076,11 @@ Megismétli a meghívási kérést?</target>
<target>A(z) **%@** nevű profilja meg lesz osztva.</target> <target>A(z) **%@** nevű profilja meg lesz osztva.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>A profilja csak a partnereivel van megosztva.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>A profilja az eszközén van tárolva és csak a partnereivel van megosztva. A SimpleX-kiszolgálók nem láthatják a profilját.</target> <target>A profilja az eszközén van tárolva és csak a partnereivel van megosztva. A SimpleX-kiszolgálók nem láthatják a profilját.</target>
@ -9091,11 +9091,6 @@ Megismétli a meghívási kérést?</target>
<target>A profilja módosult. Ha elmenti, a profilfrissítés el lesz küldve a partnerei számára.</target> <target>A profilja módosult. Ha elmenti, a profilfrissítés el lesz küldve a partnerei számára.</target>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>A profilja, a partnerei és az elküldött üzenetei a saját eszközén vannak tárolva.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Véletlenszerű profil</target> <target>Véletlenszerű profil</target>

View file

@ -7763,11 +7763,6 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta
<target>Il database vecchio non è stato rimosso durante la migrazione, può essere eliminato.</target> <target>Il database vecchio non è stato rimosso durante la migrazione, può essere eliminato.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>Il profilo è condiviso solo con i tuoi contatti.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<target>Le stesse condizioni si applicheranno all'operatore **%@**.</target> <target>Le stesse condizioni si applicheranno all'operatore **%@**.</target>
@ -9081,6 +9076,11 @@ Ripetere la richiesta di connessione?</target>
<target>Verrà condiviso il tuo profilo **%@**.</target> <target>Verrà condiviso il tuo profilo **%@**.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>Il profilo è condiviso solo con i tuoi contatti.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Il tuo profilo è memorizzato sul tuo dispositivo e condiviso solo con i tuoi contatti. I server di SimpleX non possono vedere il tuo profilo.</target> <target>Il tuo profilo è memorizzato sul tuo dispositivo e condiviso solo con i tuoi contatti. I server di SimpleX non possono vedere il tuo profilo.</target>
@ -9091,11 +9091,6 @@ Ripetere la richiesta di connessione?</target>
<target>Il tuo profilo è stato cambiato. Se lo salvi, il profilo aggiornato verrà inviato a tutti i tuoi contatti.</target> <target>Il tuo profilo è stato cambiato. Se lo salvi, il profilo aggiornato verrà inviato a tutti i tuoi contatti.</target>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Il tuo profilo, i contatti e i messaggi recapitati sono memorizzati sul tuo dispositivo.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Il tuo profilo casuale</target> <target>Il tuo profilo casuale</target>

View file

@ -1990,6 +1990,7 @@ This is your own one-time link!</source>
</trans-unit> </trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<target>プロフィールを作成する</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create queue" xml:space="preserve"> <trans-unit id="Create queue" xml:space="preserve">
@ -7125,11 +7126,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>古いデータベースは移行時に削除されなかったので、削除することができます。</target> <target>古いデータベースは移行時に削除されなかったので、削除することができます。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>プロフィールは連絡先にしか共有されません。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@ -8315,6 +8311,11 @@ Repeat connection request?</source>
<target>あなたのプロファイル **%@** が共有されます。</target> <target>あなたのプロファイル **%@** が共有されます。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>プロフィールは連絡先にしか共有されません。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>プロフィールはデバイスに保存され、連絡先とのみ共有されます。 SimpleX サーバーはあなたのプロファイルを参照できません。</target> <target>プロフィールはデバイスに保存され、連絡先とのみ共有されます。 SimpleX サーバーはあなたのプロファイルを参照できません。</target>
@ -8324,11 +8325,6 @@ Repeat connection request?</source>
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source> <source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>あなたのプロフィール、連絡先、送信したメッセージがご自分の端末に保存されます。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>あなたのランダム・プロフィール</target> <target>あなたのランダム・プロフィール</target>

View file

@ -2867,8 +2867,8 @@ We will be adding server redundancy to prevent lost messages.</source>
<source>The old database was not removed during the migration, it can be deleted.</source> <source>The old database was not removed during the migration, it can be deleted.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source> <source>Your profile is stored on your device and only shared with your contacts.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The sender will NOT be notified" xml:space="preserve"> <trans-unit id="The sender will NOT be notified" xml:space="preserve">

View file

@ -2631,8 +2631,8 @@ We will be adding server redundancy to prevent lost messages.</source>
<source>The old database was not removed during the migration, it can be deleted.</source> <source>The old database was not removed during the migration, it can be deleted.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source> <source>Your profile is stored on your device and only shared with your contacts.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The sender will NOT be notified" xml:space="preserve"> <trans-unit id="The sender will NOT be notified" xml:space="preserve">

View file

@ -7760,11 +7760,6 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target>
<target>De oude database is niet verwijderd tijdens de migratie, deze kan worden verwijderd.</target> <target>De oude database is niet verwijderd tijdens de migratie, deze kan worden verwijderd.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>Het profiel wordt alleen gedeeld met uw contacten.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<target>Dezelfde voorwaarden gelden voor operator **%@**.</target> <target>Dezelfde voorwaarden gelden voor operator **%@**.</target>
@ -9074,6 +9069,11 @@ Verbindingsverzoek herhalen?</target>
<target>Uw profiel **%@** wordt gedeeld.</target> <target>Uw profiel **%@** wordt gedeeld.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>Het profiel wordt alleen gedeeld met uw contacten.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Uw profiel wordt op uw apparaat opgeslagen en alleen gedeeld met uw contacten. SimpleX servers kunnen uw profiel niet zien.</target> <target>Uw profiel wordt op uw apparaat opgeslagen en alleen gedeeld met uw contacten. SimpleX servers kunnen uw profiel niet zien.</target>
@ -9084,11 +9084,6 @@ Verbindingsverzoek herhalen?</target>
<target>Je profiel is gewijzigd. Als je het opslaat, wordt het bijgewerkte profiel naar al je contacten verzonden.</target> <target>Je profiel is gewijzigd. Als je het opslaat, wordt het bijgewerkte profiel naar al je contacten verzonden.</target>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Uw profiel, contacten en afgeleverde berichten worden op uw apparaat opgeslagen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Je willekeurige profiel</target> <target>Je willekeurige profiel</target>

View file

@ -7583,11 +7583,6 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
<target>Stara baza danych nie została usunięta podczas migracji, można ją usunąć.</target> <target>Stara baza danych nie została usunięta podczas migracji, można ją usunąć.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>Profil jest udostępniany tylko Twoim kontaktom.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@ -8870,6 +8865,11 @@ Powtórzyć prośbę połączenia?</target>
<target>Twój profil **%@** zostanie udostępniony.</target> <target>Twój profil **%@** zostanie udostępniony.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>Profil jest udostępniany tylko Twoim kontaktom.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Twój profil jest przechowywany na urządzeniu i udostępniany tylko Twoim kontaktom. Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target> <target>Twój profil jest przechowywany na urządzeniu i udostępniany tylko Twoim kontaktom. Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
@ -8880,11 +8880,6 @@ Powtórzyć prośbę połączenia?</target>
<target>Twój profil został zmieniony. Jeśli go zapiszesz, zaktualizowany profil zostanie wysłany do wszystkich kontaktów.</target> <target>Twój profil został zmieniony. Jeśli go zapiszesz, zaktualizowany profil zostanie wysłany do wszystkich kontaktów.</target>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Twój profil, kontakty i dostarczone wiadomości są przechowywane na Twoim urządzeniu.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Twój losowy profil</target> <target>Twój losowy profil</target>

View file

@ -3002,8 +3002,8 @@ We will be adding server redundancy to prevent lost messages.</source>
<source>The old database was not removed during the migration, it can be deleted.</source> <source>The old database was not removed during the migration, it can be deleted.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve" approved="no"> <trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve" approved="no">
<source>The profile is only shared with your contacts.</source> <source>Your profile is stored on your device and only shared with your contacts.</source>
<target state="translated">O perfil é compartilhado apenas com seus contatos.</target> <target state="translated">O perfil é compartilhado apenas com seus contatos.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>

View file

@ -3146,8 +3146,8 @@ It can happen because of some bug or when the connection is compromised.</source
<source>The old database was not removed during the migration, it can be deleted.</source> <source>The old database was not removed during the migration, it can be deleted.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source> <source>Your profile is stored on your device and only shared with your contacts.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The sender will NOT be notified" xml:space="preserve"> <trans-unit id="The sender will NOT be notified" xml:space="preserve">

View file

@ -7715,11 +7715,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Предыдущая версия данных чата не удалена при перемещении, её можно удалить.</target> <target>Предыдущая версия данных чата не удалена при перемещении, её можно удалить.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>Профиль отправляется только Вашим контактам.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<target>Те же самые условия будут приняты для оператора **%@**.</target> <target>Те же самые условия будут приняты для оператора **%@**.</target>
@ -9021,6 +9016,11 @@ Repeat connection request?</source>
<target>Будет отправлен Ваш профиль **%@**.</target> <target>Будет отправлен Ваш профиль **%@**.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>Ваш профиль храниться на Вашем устройстве и отправляется только контактам.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Ваш профиль хранится на Вашем устройстве и отправляется только Вашим контактам. SimpleX серверы не могут получить доступ к Вашему профилю.</target> <target>Ваш профиль хранится на Вашем устройстве и отправляется только Вашим контактам. SimpleX серверы не могут получить доступ к Вашему профилю.</target>
@ -9031,11 +9031,6 @@ Repeat connection request?</source>
<target>Ваш профиль был изменен. Если вы сохраните его, обновленный профиль будет отправлен всем вашим контактам.</target> <target>Ваш профиль был изменен. Если вы сохраните его, обновленный профиль будет отправлен всем вашим контактам.</target>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Ваш профиль, контакты и доставленные сообщения хранятся на Вашем устройстве.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Случайный профиль</target> <target>Случайный профиль</target>

View file

@ -7028,11 +7028,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>ฐานข้อมูลเก่าไม่ได้ถูกลบในระหว่างการย้ายข้อมูล แต่สามารถลบได้</target> <target>ฐานข้อมูลเก่าไม่ได้ถูกลบในระหว่างการย้ายข้อมูล แต่สามารถลบได้</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>โปรไฟล์นี้แชร์กับผู้ติดต่อของคุณเท่านั้น</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@ -8212,6 +8207,11 @@ Repeat connection request?</source>
<source>Your profile **%@** will be shared.</source> <source>Your profile **%@** will be shared.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>โปรไฟล์นี้แชร์กับผู้ติดต่อของคุณเท่านั้น</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>โปรไฟล์ของคุณจะถูกจัดเก็บไว้ในอุปกรณ์ของคุณและแชร์กับผู้ติดต่อของคุณเท่านั้น เซิร์ฟเวอร์ SimpleX ไม่สามารถดูโปรไฟล์ของคุณได้</target> <target>โปรไฟล์ของคุณจะถูกจัดเก็บไว้ในอุปกรณ์ของคุณและแชร์กับผู้ติดต่อของคุณเท่านั้น เซิร์ฟเวอร์ SimpleX ไม่สามารถดูโปรไฟล์ของคุณได้</target>
@ -8221,11 +8221,6 @@ Repeat connection request?</source>
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source> <source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>โปรไฟล์ รายชื่อผู้ติดต่อ และข้อความที่ส่งของคุณจะถูกจัดเก็บไว้ในอุปกรณ์ของคุณ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>โปรไฟล์แบบสุ่มของคุณ</target> <target>โปรไฟล์แบบสุ่มของคุณ</target>

View file

@ -7599,11 +7599,6 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir.
<target>Eski veritabanı geçiş sırasında kaldırılmadı, silinebilir.</target> <target>Eski veritabanı geçiş sırasında kaldırılmadı, silinebilir.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>Profil sadece kişilerinle paylaşılacak.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@ -8886,6 +8881,11 @@ Bağlantı isteği tekrarlansın mı?</target>
<target>Profiliniz **%@** paylaşılacaktır.</target> <target>Profiliniz **%@** paylaşılacaktır.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>Profil sadece kişilerinle paylaşılacak.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Profiliniz cihazınızda saklanır ve sadece kişilerinizle paylaşılır. SimpleX sunucuları profilinizi göremez.</target> <target>Profiliniz cihazınızda saklanır ve sadece kişilerinizle paylaşılır. SimpleX sunucuları profilinizi göremez.</target>
@ -8896,11 +8896,6 @@ Bağlantı isteği tekrarlansın mı?</target>
<target>Profiliniz değiştirildi. Kaydederseniz, güncellenmiş profil tüm kişilerinize gönderilecektir.</target> <target>Profiliniz değiştirildi. Kaydederseniz, güncellenmiş profil tüm kişilerinize gönderilecektir.</target>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Profiliniz, kişileriniz ve gönderilmiş mesajlar cihazınızda saklanır.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Rasgele profiliniz</target> <target>Rasgele profiliniz</target>

View file

@ -7638,11 +7638,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Стара база даних не була видалена під час міграції, її можна видалити.</target> <target>Стара база даних не була видалена під час міграції, її можна видалити.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>Профіль доступний лише вашим контактам.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<target>Такі ж умови діятимуть і для оператора **%@**.</target> <target>Такі ж умови діятимуть і для оператора **%@**.</target>
@ -8945,6 +8940,11 @@ Repeat connection request?</source>
<target>Ваш профіль **%@** буде опублікований.</target> <target>Ваш профіль **%@** буде опублікований.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>Профіль доступний лише вашим контактам.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>Ваш профіль зберігається на вашому пристрої і доступний лише вашим контактам. Сервери SimpleX не бачать ваш профіль.</target> <target>Ваш профіль зберігається на вашому пристрої і доступний лише вашим контактам. Сервери SimpleX не бачать ваш профіль.</target>
@ -8955,11 +8955,6 @@ Repeat connection request?</source>
<target>Ваш профіль було змінено. Якщо ви збережете його, оновлений профіль буде надіслано всім вашим контактам.</target> <target>Ваш профіль було змінено. Якщо ви збережете його, оновлений профіль буде надіслано всім вашим контактам.</target>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Ваш профіль, контакти та доставлені повідомлення зберігаються на вашому пристрої.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>Ваш випадковий профіль</target> <target>Ваш випадковий профіль</target>

View file

@ -7708,11 +7708,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>旧数据库在迁移过程中没有被移除,可以删除。</target> <target>旧数据库在迁移过程中没有被移除,可以删除。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve">
<source>The profile is only shared with your contacts.</source>
<target>该资料仅与您的联系人共享。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve"> <trans-unit id="The same conditions will apply to operator **%@**." xml:space="preserve">
<source>The same conditions will apply to operator **%@**.</source> <source>The same conditions will apply to operator **%@**.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@ -8987,6 +8982,11 @@ Repeat connection request?</source>
<target>您的个人资料 **%@** 将被共享。</target> <target>您的个人资料 **%@** 将被共享。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve">
<source>Your profile is stored on your device and only shared with your contacts.</source>
<target>该资料仅与您的联系人共享。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve"> <trans-unit id="Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source> <source>Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.</source>
<target>您的资料存储在您的设备上并仅与您的联系人共享。 SimpleX 服务器无法看到您的资料。</target> <target>您的资料存储在您的设备上并仅与您的联系人共享。 SimpleX 服务器无法看到您的资料。</target>
@ -8996,11 +8996,6 @@ Repeat connection request?</source>
<source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source> <source>Your profile was changed. If you save it, the updated profile will be sent to all your contacts.</source>
<note>alert message</note> <note>alert message</note>
</trans-unit> </trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>您的资料、联系人和发送的消息存储在您的设备上。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your random profile" xml:space="preserve"> <trans-unit id="Your random profile" xml:space="preserve">
<source>Your random profile</source> <source>Your random profile</source>
<target>您的随机资料</target> <target>您的随机资料</target>

View file

@ -3054,8 +3054,8 @@ We will be adding server redundancy to prevent lost messages.</source>
<target state="translated">舊的數據庫在遷移過程中沒有被移除,可以刪除。</target> <target state="translated">舊的數據庫在遷移過程中沒有被移除,可以刪除。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The profile is only shared with your contacts." xml:space="preserve" approved="no"> <trans-unit id="Your profile is stored on your device and only shared with your contacts." xml:space="preserve" approved="no">
<source>The profile is only shared with your contacts.</source> <source>Your profile is stored on your device and only shared with your contacts.</source>
<target state="translated">你的個人檔案只會和你的聯絡人分享。</target> <target state="translated">你的個人檔案只會和你的聯絡人分享。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>

View file

@ -174,8 +174,8 @@
64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */; }; 64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */; };
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829982D54AEED006B9E89 /* libgmp.a */; }; 64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829982D54AEED006B9E89 /* libgmp.a */; };
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829992D54AEEE006B9E89 /* libffi.a */; }; 64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829992D54AEEE006B9E89 /* libffi.a */; };
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.1-Cm6JGiMgJjo4088oWn41JO-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.1-Cm6JGiMgJjo4088oWn41JO-ghc9.6.3.a */; }; 64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.6.0-64eNxtIoLF9BaOhAoPagss-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.6.0-64eNxtIoLF9BaOhAoPagss-ghc9.6.3.a */; };
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.1-Cm6JGiMgJjo4088oWn41JO.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.1-Cm6JGiMgJjo4088oWn41JO.a */; }; 64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.3.6.0-64eNxtIoLF9BaOhAoPagss.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.6.0-64eNxtIoLF9BaOhAoPagss.a */; };
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */; }; 64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */; };
64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; }; 64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; };
64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */; }; 64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */; };
@ -533,8 +533,8 @@
64C3B0202A0D359700E19930 /* CustomTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTimePicker.swift; sourceTree = "<group>"; }; 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTimePicker.swift; sourceTree = "<group>"; };
64C829982D54AEED006B9E89 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; }; 64C829982D54AEED006B9E89 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
64C829992D54AEEE006B9E89 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; }; 64C829992D54AEEE006B9E89 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.1-Cm6JGiMgJjo4088oWn41JO-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.3.4.1-Cm6JGiMgJjo4088oWn41JO-ghc9.6.3.a"; sourceTree = "<group>"; }; 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.6.0-64eNxtIoLF9BaOhAoPagss-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.3.6.0-64eNxtIoLF9BaOhAoPagss-ghc9.6.3.a"; sourceTree = "<group>"; };
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.1-Cm6JGiMgJjo4088oWn41JO.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.3.4.1-Cm6JGiMgJjo4088oWn41JO.a"; sourceTree = "<group>"; }; 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.6.0-64eNxtIoLF9BaOhAoPagss.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.3.6.0-64eNxtIoLF9BaOhAoPagss.a"; sourceTree = "<group>"; };
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; }; 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = "<group>"; }; 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = "<group>"; };
64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressLearnMore.swift; sourceTree = "<group>"; }; 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressLearnMore.swift; sourceTree = "<group>"; };
@ -692,8 +692,8 @@
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */, 64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */,
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */, 64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */,
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */, 64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */,
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.1-Cm6JGiMgJjo4088oWn41JO-ghc9.6.3.a in Frameworks */, 64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.6.0-64eNxtIoLF9BaOhAoPagss-ghc9.6.3.a in Frameworks */,
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.1-Cm6JGiMgJjo4088oWn41JO.a in Frameworks */, 64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.3.6.0-64eNxtIoLF9BaOhAoPagss.a in Frameworks */,
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */, CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -778,8 +778,8 @@
64C829992D54AEEE006B9E89 /* libffi.a */, 64C829992D54AEEE006B9E89 /* libffi.a */,
64C829982D54AEED006B9E89 /* libgmp.a */, 64C829982D54AEED006B9E89 /* libgmp.a */,
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */, 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */,
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.1-Cm6JGiMgJjo4088oWn41JO-ghc9.6.3.a */, 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.6.0-64eNxtIoLF9BaOhAoPagss-ghc9.6.3.a */,
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.4.1-Cm6JGiMgJjo4088oWn41JO.a */, 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.3.6.0-64eNxtIoLF9BaOhAoPagss.a */,
); );
path = Libraries; path = Libraries;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1971,7 +1971,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 277; CURRENT_PROJECT_VERSION = 282;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@ -1996,7 +1996,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
LLVM_LTO = YES_THIN; LLVM_LTO = YES_THIN;
MARKETING_VERSION = 6.3.4; MARKETING_VERSION = 6.3.6;
OTHER_LDFLAGS = "-Wl,-stack_size,0x1000000"; OTHER_LDFLAGS = "-Wl,-stack_size,0x1000000";
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX; PRODUCT_NAME = SimpleX;
@ -2021,7 +2021,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 277; CURRENT_PROJECT_VERSION = 282;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@ -2046,7 +2046,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
LLVM_LTO = YES; LLVM_LTO = YES;
MARKETING_VERSION = 6.3.4; MARKETING_VERSION = 6.3.6;
OTHER_LDFLAGS = "-Wl,-stack_size,0x1000000"; OTHER_LDFLAGS = "-Wl,-stack_size,0x1000000";
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX; PRODUCT_NAME = SimpleX;
@ -2063,11 +2063,11 @@
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 277; CURRENT_PROJECT_VERSION = 282;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0; IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 6.3.4; MARKETING_VERSION = 6.3.6;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS"; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -2083,11 +2083,11 @@
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 277; CURRENT_PROJECT_VERSION = 282;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0; IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 6.3.4; MARKETING_VERSION = 6.3.6;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS"; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -2108,7 +2108,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 277; CURRENT_PROJECT_VERSION = 282;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
GCC_OPTIMIZATION_LEVEL = s; GCC_OPTIMIZATION_LEVEL = s;
@ -2123,7 +2123,7 @@
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
LLVM_LTO = YES; LLVM_LTO = YES;
MARKETING_VERSION = 6.3.4; MARKETING_VERSION = 6.3.6;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -2145,7 +2145,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 277; CURRENT_PROJECT_VERSION = 282;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
ENABLE_CODE_COVERAGE = NO; ENABLE_CODE_COVERAGE = NO;
@ -2160,7 +2160,7 @@
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
LLVM_LTO = YES; LLVM_LTO = YES;
MARKETING_VERSION = 6.3.4; MARKETING_VERSION = 6.3.6;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -2182,7 +2182,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 277; CURRENT_PROJECT_VERSION = 282;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
@ -2208,7 +2208,7 @@
"$(PROJECT_DIR)/Libraries/sim", "$(PROJECT_DIR)/Libraries/sim",
); );
LLVM_LTO = YES; LLVM_LTO = YES;
MARKETING_VERSION = 6.3.4; MARKETING_VERSION = 6.3.6;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -2233,7 +2233,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 277; CURRENT_PROJECT_VERSION = 282;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
@ -2259,7 +2259,7 @@
"$(PROJECT_DIR)/Libraries/sim", "$(PROJECT_DIR)/Libraries/sim",
); );
LLVM_LTO = YES; LLVM_LTO = YES;
MARKETING_VERSION = 6.3.4; MARKETING_VERSION = 6.3.6;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -2284,7 +2284,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements"; CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 277; CURRENT_PROJECT_VERSION = 282;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
@ -2299,7 +2299,7 @@
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 6.3.4; MARKETING_VERSION = 6.3.6;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE"; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -2318,7 +2318,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements"; CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 277; CURRENT_PROJECT_VERSION = 282;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
@ -2333,7 +2333,7 @@
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 6.3.4; MARKETING_VERSION = 6.3.6;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE"; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;

View file

@ -1333,6 +1333,19 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat, Hashable {
} }
} }
public var userCantSendReason: (composeLabel: LocalizedStringKey, alertMessage: LocalizedStringKey?)? {
get {
switch self {
case let .direct(contact): return contact.userCantSendReason
case let .group(groupInfo): return groupInfo.userCantSendReason
case let .local(noteFolder): return noteFolder.userCantSendReason
case let .contactRequest(contactRequest): return contactRequest.userCantSendReason
case let .contactConnection(contactConnection): return contactConnection.userCantSendReason
case .invalidJSON: return ("can't send messages", nil)
}
}
}
public var sendMsgEnabled: Bool { public var sendMsgEnabled: Bool {
get { get {
switch self { switch self {
@ -1642,15 +1655,16 @@ public struct Contact: Identifiable, Decodable, NamedChat, Hashable {
public var ready: Bool { get { activeConn?.connStatus == .ready } } public var ready: Bool { get { activeConn?.connStatus == .ready } }
public var sndReady: Bool { get { ready || activeConn?.connStatus == .sndReady } } public var sndReady: Bool { get { ready || activeConn?.connStatus == .sndReady } }
public var active: Bool { get { contactStatus == .active } } public var active: Bool { get { contactStatus == .active } }
public var sendMsgEnabled: Bool { get { public var userCantSendReason: (composeLabel: LocalizedStringKey, alertMessage: LocalizedStringKey?)? {
( // TODO [short links] this will have additional statuses for pending contact requests before they are accepted
sndReady if nextSendGrpInv { return nil }
&& active if !active { return ("contact deleted", nil) }
&& !(activeConn?.connectionStats?.ratchetSyncSendProhibited ?? false) if !sndReady { return ("contact not ready", nil) }
&& !(activeConn?.connDisabled ?? true) if activeConn?.connectionStats?.ratchetSyncSendProhibited ?? false { return ("not synchronized", nil) }
) if activeConn?.connDisabled ?? true { return ("contact disabled", nil) }
|| nextSendGrpInv return nil
} } }
public var sendMsgEnabled: Bool { userCantSendReason == nil }
public var nextSendGrpInv: Bool { get { contactGroupMemberId != nil && !contactGrpInvSent } } public var nextSendGrpInv: Bool { get { contactGroupMemberId != nil && !contactGrpInvSent } }
public var displayName: String { localAlias == "" ? profile.displayName : localAlias } public var displayName: String { localAlias == "" ? profile.displayName : localAlias }
public var fullName: String { get { profile.fullName } } public var fullName: String { get { profile.fullName } }
@ -1829,6 +1843,7 @@ public struct UserContactRequest: Decodable, NamedChat, Hashable {
public var id: ChatId { get { "<@\(contactRequestId)" } } public var id: ChatId { get { "<@\(contactRequestId)" } }
public var apiId: Int64 { get { contactRequestId } } public var apiId: Int64 { get { contactRequestId } }
var ready: Bool { get { true } } var ready: Bool { get { true } }
public var userCantSendReason: (composeLabel: LocalizedStringKey, alertMessage: LocalizedStringKey?)? { ("can't send messages", nil) }
public var sendMsgEnabled: Bool { get { false } } public var sendMsgEnabled: Bool { get { false } }
public var displayName: String { get { profile.displayName } } public var displayName: String { get { profile.displayName } }
public var fullName: String { get { profile.fullName } } public var fullName: String { get { profile.fullName } }
@ -1861,6 +1876,7 @@ public struct PendingContactConnection: Decodable, NamedChat, Hashable {
public var id: ChatId { get { ":\(pccConnId)" } } public var id: ChatId { get { ":\(pccConnId)" } }
public var apiId: Int64 { get { pccConnId } } public var apiId: Int64 { get { pccConnId } }
var ready: Bool { get { false } } var ready: Bool { get { false } }
public var userCantSendReason: (composeLabel: LocalizedStringKey, alertMessage: LocalizedStringKey?)? { ("can't send messages", nil) }
public var sendMsgEnabled: Bool { get { false } } public var sendMsgEnabled: Bool { get { false } }
var localDisplayName: String { var localDisplayName: String {
get { String.localizedStringWithFormat(NSLocalizedString("connection:%@", comment: "connection information"), pccConnId) } get { String.localizedStringWithFormat(NSLocalizedString("connection:%@", comment: "connection information"), pccConnId) }
@ -1990,7 +2006,20 @@ public struct GroupInfo: Identifiable, Decodable, NamedChat, Hashable {
public var id: ChatId { get { "#\(groupId)" } } public var id: ChatId { get { "#\(groupId)" } }
public var apiId: Int64 { get { groupId } } public var apiId: Int64 { get { groupId } }
public var ready: Bool { get { true } } public var ready: Bool { get { true } }
public var sendMsgEnabled: Bool { get { membership.memberActive } } public var userCantSendReason: (composeLabel: LocalizedStringKey, alertMessage: LocalizedStringKey?)? {
return if membership.memberActive {
membership.memberRole == .observer ? ("you are observer", "Please contact group admin.") : nil
} else {
switch membership.memberStatus {
case .memRejected: ("request to join rejected", nil)
case .memGroupDeleted: ("group is deleted", nil)
case .memRemoved: ("removed from group", nil)
case .memLeft: ("you left", nil)
default: ("can't send messages", nil)
}
}
}
public var sendMsgEnabled: Bool { userCantSendReason == nil }
public var displayName: String { localAlias == "" ? groupProfile.displayName : localAlias } public var displayName: String { localAlias == "" ? groupProfile.displayName : localAlias }
public var fullName: String { get { groupProfile.fullName } } public var fullName: String { get { groupProfile.fullName } }
public var image: String? { get { groupProfile.image } } public var image: String? { get { groupProfile.image } }
@ -2357,6 +2386,7 @@ public struct NoteFolder: Identifiable, Decodable, NamedChat, Hashable {
public var id: ChatId { get { "*\(noteFolderId)" } } public var id: ChatId { get { "*\(noteFolderId)" } }
public var apiId: Int64 { get { noteFolderId } } public var apiId: Int64 { get { noteFolderId } }
public var ready: Bool { get { true } } public var ready: Bool { get { true } }
public var userCantSendReason: (composeLabel: LocalizedStringKey, alertMessage: LocalizedStringKey?)? { nil }
public var sendMsgEnabled: Bool { get { true } } public var sendMsgEnabled: Bool { get { true } }
public var displayName: String { get { ChatInfo.privateNotesChatName } } public var displayName: String { get { ChatInfo.privateNotesChatName } }
public var fullName: String { get { "" } } public var fullName: String { get { "" } }

View file

@ -3777,7 +3777,7 @@ chat item action */
"The old database was not removed during the migration, it can be deleted." = "Старата база данни не бе премахната по време на миграцията, тя може да бъде изтрита."; "The old database was not removed during the migration, it can be deleted." = "Старата база данни не бе премахната по време на миграцията, тя може да бъде изтрита.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "Профилът се споделя само с вашите контакти."; "Your profile is stored on your device and only shared with your contacts." = "Профилът се споделя само с вашите контакти.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The second tick we missed! ✅" = "Втората отметка, която пропуснахме! ✅"; "The second tick we missed! ✅" = "Втората отметка, която пропуснахме! ✅";

View file

@ -822,6 +822,9 @@ set passcode view */
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Vytvořit nový profil v [desktop app](https://simplex.chat/downloads/). 💻"; "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Vytvořit nový profil v [desktop app](https://simplex.chat/downloads/). 💻";
/* No comment provided by engineer. */
"Create profile" = "Vytvořte si profil";
/* server test step */ /* server test step */
"Create queue" = "Vytvořit frontu"; "Create queue" = "Vytvořit frontu";
@ -2986,7 +2989,7 @@ chat item action */
"The old database was not removed during the migration, it can be deleted." = "Stará databáze nebyla během přenášení odstraněna, lze ji smazat."; "The old database was not removed during the migration, it can be deleted." = "Stará databáze nebyla během přenášení odstraněna, lze ji smazat.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "Profil je sdílen pouze s vašimi kontakty."; "Your profile is stored on your device and only shared with your contacts." = "Profil je sdílen pouze s vašimi kontakty.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The second tick we missed! ✅" = "Druhé zaškrtnutí jsme přehlédli! ✅"; "The second tick we missed! ✅" = "Druhé zaškrtnutí jsme přehlédli! ✅";

View file

@ -5101,7 +5101,7 @@ report reason */
"The old database was not removed during the migration, it can be deleted." = "Die alte Datenbank wurde während der Migration nicht entfernt. Sie kann gelöscht werden."; "The old database was not removed during the migration, it can be deleted." = "Die alte Datenbank wurde während der Migration nicht entfernt. Sie kann gelöscht werden.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "Das Profil wird nur mit Ihren Kontakten geteilt."; "Your profile is stored on your device and only shared with your contacts." = "Das Profil wird nur mit Ihren Kontakten geteilt.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The same conditions will apply to operator **%@**." = "Dieselben Nutzungsbedingungen gelten auch für den Betreiber **%@**."; "The same conditions will apply to operator **%@**." = "Dieselben Nutzungsbedingungen gelten auch für den Betreiber **%@**.";

View file

@ -5101,7 +5101,7 @@ report reason */
"The old database was not removed during the migration, it can be deleted." = "La base de datos antigua no se eliminó durante la migración, puede eliminarse."; "The old database was not removed during the migration, it can be deleted." = "La base de datos antigua no se eliminó durante la migración, puede eliminarse.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "El perfil sólo se comparte con tus contactos."; "Your profile is stored on your device and only shared with your contacts." = "El perfil sólo se comparte con tus contactos.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The same conditions will apply to operator **%@**." = "Las mismas condiciones se aplicarán al operador **%@**."; "The same conditions will apply to operator **%@**." = "Las mismas condiciones se aplicarán al operador **%@**.";

View file

@ -768,6 +768,9 @@ set passcode view */
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Luo uusi profiili [työpöytäsovelluksessa](https://simplex.chat/downloads/). 💻"; "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "Luo uusi profiili [työpöytäsovelluksessa](https://simplex.chat/downloads/). 💻";
/* No comment provided by engineer. */
"Create profile" = "Luo profiilisi";
/* server test step */ /* server test step */
"Create queue" = "Luo jono"; "Create queue" = "Luo jono";
@ -2908,7 +2911,7 @@ chat item action */
"The old database was not removed during the migration, it can be deleted." = "Vanhaa tietokantaa ei poistettu siirron aikana, se voidaan kuitenkin poistaa."; "The old database was not removed during the migration, it can be deleted." = "Vanhaa tietokantaa ei poistettu siirron aikana, se voidaan kuitenkin poistaa.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "Profiili jaetaan vain kontaktiesi kanssa."; "Your profile is stored on your device and only shared with your contacts." = "Profiili jaetaan vain kontaktiesi kanssa.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The second tick we missed! ✅" = "Toinen kuittaus, joka uupui! ✅"; "The second tick we missed! ✅" = "Toinen kuittaus, joka uupui! ✅";

View file

@ -4884,7 +4884,7 @@ chat item action */
"The old database was not removed during the migration, it can be deleted." = "L'ancienne base de données n'a pas été supprimée lors de la migration, elle peut être supprimée."; "The old database was not removed during the migration, it can be deleted." = "L'ancienne base de données n'a pas été supprimée lors de la migration, elle peut être supprimée.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "Le profil n'est partagé qu'avec vos contacts."; "Your profile is stored on your device and only shared with your contacts." = "Le profil n'est partagé qu'avec vos contacts.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The same conditions will apply to operator **%@**." = "Les mêmes conditions s'appliquent à l'opérateur **%@**."; "The same conditions will apply to operator **%@**." = "Les mêmes conditions s'appliquent à l'opérateur **%@**.";

View file

@ -5101,7 +5101,7 @@ report reason */
"The old database was not removed during the migration, it can be deleted." = "A régi adatbázis nem lett eltávolítva az átköltöztetéskor, ezért törölhető."; "The old database was not removed during the migration, it can be deleted." = "A régi adatbázis nem lett eltávolítva az átköltöztetéskor, ezért törölhető.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "A profilja csak a partnereivel van megosztva."; "Your profile is stored on your device and only shared with your contacts." = "A profilja csak a partnereivel van megosztva.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The same conditions will apply to operator **%@**." = "Ugyanezek a feltételek lesznek elfogadva a következő üzemeltető számára is: **%@**."; "The same conditions will apply to operator **%@**." = "Ugyanezek a feltételek lesznek elfogadva a következő üzemeltető számára is: **%@**.";

View file

@ -5101,7 +5101,7 @@ report reason */
"The old database was not removed during the migration, it can be deleted." = "Il database vecchio non è stato rimosso durante la migrazione, può essere eliminato."; "The old database was not removed during the migration, it can be deleted." = "Il database vecchio non è stato rimosso durante la migrazione, può essere eliminato.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "Il profilo è condiviso solo con i tuoi contatti."; "Your profile is stored on your device and only shared with your contacts." = "Il profilo è condiviso solo con i tuoi contatti.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The same conditions will apply to operator **%@**." = "Le stesse condizioni si applicheranno all'operatore **%@**."; "The same conditions will apply to operator **%@**." = "Le stesse condizioni si applicheranno all'operatore **%@**.";

View file

@ -957,6 +957,9 @@ set passcode view */
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "[デスクトップアプリ](https://simplex.chat/downloads/)で新しいプロファイルを作成します。 💻"; "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" = "[デスクトップアプリ](https://simplex.chat/downloads/)で新しいプロファイルを作成します。 💻";
/* No comment provided by engineer. */
"Create profile" = "プロフィールを作成する";
/* server test step */ /* server test step */
"Create queue" = "キューの作成"; "Create queue" = "キューの作成";
@ -3109,7 +3112,7 @@ chat item action */
"The old database was not removed during the migration, it can be deleted." = "古いデータベースは移行時に削除されなかったので、削除することができます。"; "The old database was not removed during the migration, it can be deleted." = "古いデータベースは移行時に削除されなかったので、削除することができます。";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "プロフィールは連絡先にしか共有されません。"; "Your profile is stored on your device and only shared with your contacts." = "プロフィールは連絡先にしか共有されません。";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The second tick we missed! ✅" = "長らくお待たせしました! ✅"; "The second tick we missed! ✅" = "長らくお待たせしました! ✅";

View file

@ -5092,7 +5092,7 @@ report reason */
"The old database was not removed during the migration, it can be deleted." = "De oude database is niet verwijderd tijdens de migratie, deze kan worden verwijderd."; "The old database was not removed during the migration, it can be deleted." = "De oude database is niet verwijderd tijdens de migratie, deze kan worden verwijderd.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "Het profiel wordt alleen gedeeld met uw contacten."; "Your profile is stored on your device and only shared with your contacts." = "Het profiel wordt alleen gedeeld met uw contacten.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The same conditions will apply to operator **%@**." = "Dezelfde voorwaarden gelden voor operator **%@**."; "The same conditions will apply to operator **%@**." = "Dezelfde voorwaarden gelden voor operator **%@**.";

View file

@ -4557,7 +4557,7 @@ chat item action */
"The old database was not removed during the migration, it can be deleted." = "Stara baza danych nie została usunięta podczas migracji, można ją usunąć."; "The old database was not removed during the migration, it can be deleted." = "Stara baza danych nie została usunięta podczas migracji, można ją usunąć.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "Profil jest udostępniany tylko Twoim kontaktom."; "Your profile is stored on your device and only shared with your contacts." = "Profil jest udostępniany tylko Twoim kontaktom.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The second tick we missed! ✅" = "Drugi tik, który przegapiliśmy! ✅"; "The second tick we missed! ✅" = "Drugi tik, który przegapiliśmy! ✅";

View file

@ -4957,7 +4957,7 @@ report reason */
"The old database was not removed during the migration, it can be deleted." = "Предыдущая версия данных чата не удалена при перемещении, её можно удалить."; "The old database was not removed during the migration, it can be deleted." = "Предыдущая версия данных чата не удалена при перемещении, её можно удалить.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "Профиль отправляется только Вашим контактам."; "Your profile is stored on your device and only shared with your contacts." = "Ваш профиль храниться на Вашем устройстве и отправляется только контактам.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The same conditions will apply to operator **%@**." = "Те же самые условия будут приняты для оператора **%@**."; "The same conditions will apply to operator **%@**." = "Те же самые условия будут приняты для оператора **%@**.";

View file

@ -2830,7 +2830,7 @@ chat item action */
"The old database was not removed during the migration, it can be deleted." = "ฐานข้อมูลเก่าไม่ได้ถูกลบในระหว่างการย้ายข้อมูล แต่สามารถลบได้"; "The old database was not removed during the migration, it can be deleted." = "ฐานข้อมูลเก่าไม่ได้ถูกลบในระหว่างการย้ายข้อมูล แต่สามารถลบได้";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "โปรไฟล์นี้แชร์กับผู้ติดต่อของคุณเท่านั้น"; "Your profile is stored on your device and only shared with your contacts." = "โปรไฟล์นี้แชร์กับผู้ติดต่อของคุณเท่านั้น";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The second tick we missed! ✅" = "ขีดที่สองที่เราพลาด! ✅"; "The second tick we missed! ✅" = "ขีดที่สองที่เราพลาด! ✅";

View file

@ -4602,7 +4602,7 @@ chat item action */
"The old database was not removed during the migration, it can be deleted." = "Eski veritabanı geçiş sırasında kaldırılmadı, silinebilir."; "The old database was not removed during the migration, it can be deleted." = "Eski veritabanı geçiş sırasında kaldırılmadı, silinebilir.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "Profil sadece kişilerinle paylaşılacak."; "Your profile is stored on your device and only shared with your contacts." = "Profil sadece kişilerinle paylaşılacak.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The second tick we missed! ✅" = "Özlediğimiz ikinci tik! ✅"; "The second tick we missed! ✅" = "Özlediğimiz ikinci tik! ✅";

View file

@ -4722,7 +4722,7 @@ chat item action */
"The old database was not removed during the migration, it can be deleted." = "Стара база даних не була видалена під час міграції, її можна видалити."; "The old database was not removed during the migration, it can be deleted." = "Стара база даних не була видалена під час міграції, її можна видалити.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "Профіль доступний лише вашим контактам."; "Your profile is stored on your device and only shared with your contacts." = "Профіль доступний лише вашим контактам.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The same conditions will apply to operator **%@**." = "Такі ж умови діятимуть і для оператора **%@**."; "The same conditions will apply to operator **%@**." = "Такі ж умови діятимуть і для оператора **%@**.";

View file

@ -4923,7 +4923,7 @@ chat item action */
"The old database was not removed during the migration, it can be deleted." = "旧数据库在迁移过程中没有被移除,可以删除。"; "The old database was not removed during the migration, it can be deleted." = "旧数据库在迁移过程中没有被移除,可以删除。";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The profile is only shared with your contacts." = "该资料仅与您的联系人共享。"; "Your profile is stored on your device and only shared with your contacts." = "该资料仅与您的联系人共享。";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"The second tick we missed! ✅" = "我们错过的第二个\"√\"!✅"; "The second tick we missed! ✅" = "我们错过的第二个\"√\"!✅";

View file

@ -155,6 +155,7 @@ buildConfig {
buildConfigField("String", "DESKTOP_VERSION_NAME", "\"${extra["desktop.version_name"]}\"") buildConfigField("String", "DESKTOP_VERSION_NAME", "\"${extra["desktop.version_name"]}\"")
buildConfigField("int", "DESKTOP_VERSION_CODE", "${extra["desktop.version_code"]}") buildConfigField("int", "DESKTOP_VERSION_CODE", "${extra["desktop.version_code"]}")
buildConfigField("String", "DATABASE_BACKEND", "\"${extra["database.backend"]}\"") buildConfigField("String", "DATABASE_BACKEND", "\"${extra["database.backend"]}\"")
buildConfigField("Boolean", "ANDROID_BUNDLE", "${extra["android.bundle"]}")
} }
} }

View file

@ -42,7 +42,6 @@ import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR import chat.simplex.res.MR
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
import java.lang.reflect.Field import java.lang.reflect.Field
import java.net.URI import java.net.URI
@ -51,10 +50,10 @@ import java.net.URI
actual fun PlatformTextField( actual fun PlatformTextField(
composeState: MutableState<ComposeState>, composeState: MutableState<ComposeState>,
sendMsgEnabled: Boolean, sendMsgEnabled: Boolean,
disabledText: String?,
sendMsgButtonDisabled: Boolean, sendMsgButtonDisabled: Boolean,
textStyle: MutableState<TextStyle>, textStyle: MutableState<TextStyle>,
showDeleteTextButton: MutableState<Boolean>, showDeleteTextButton: MutableState<Boolean>,
userIsObserver: Boolean,
placeholder: String, placeholder: String,
showVoiceButton: Boolean, showVoiceButton: Boolean,
onMessageChange: (ComposeMessage) -> Unit, onMessageChange: (ComposeMessage) -> Unit,
@ -197,16 +196,16 @@ actual fun PlatformTextField(
showDeleteTextButton.value = it.lineCount >= 4 && !cs.inProgress showDeleteTextButton.value = it.lineCount >= 4 && !cs.inProgress
} }
if (composeState.value.preview is ComposePreview.VoicePreview) { if (composeState.value.preview is ComposePreview.VoicePreview) {
ComposeOverlay(MR.strings.voice_message_send_text, textStyle, padding) ComposeOverlay(generalGetString(MR.strings.voice_message_send_text), textStyle, padding)
} else if (userIsObserver) { } else if (disabledText != null) {
ComposeOverlay(MR.strings.you_are_observer, textStyle, padding) ComposeOverlay(disabledText, textStyle, padding)
} }
} }
@Composable @Composable
private fun ComposeOverlay(textId: StringResource, textStyle: MutableState<TextStyle>, padding: PaddingValues) { private fun ComposeOverlay(text: String, textStyle: MutableState<TextStyle>, padding: PaddingValues) {
Text( Text(
generalGetString(textId), text,
Modifier.padding(padding), Modifier.padding(padding),
color = MaterialTheme.colors.secondary, color = MaterialTheme.colors.secondary,
style = textStyle.value.copy(fontStyle = FontStyle.Italic) style = textStyle.value.copy(fontStyle = FontStyle.Italic)

View file

@ -1204,6 +1204,7 @@ interface SomeChat {
val apiId: Long val apiId: Long
val ready: Boolean val ready: Boolean
val chatDeleted: Boolean val chatDeleted: Boolean
val userCantSendReason: Pair<String, String?>?
val sendMsgEnabled: Boolean val sendMsgEnabled: Boolean
val incognito: Boolean val incognito: Boolean
fun featureEnabled(feature: ChatFeature): Boolean fun featureEnabled(feature: ChatFeature): Boolean
@ -1228,14 +1229,6 @@ data class Chat(
else -> false else -> false
} }
val userIsObserver: Boolean get() = when(chatInfo) {
is ChatInfo.Group -> {
val m = chatInfo.groupInfo.membership
m.memberActive && m.memberRole == GroupMemberRole.Observer
}
else -> false
}
val unreadTag: Boolean get() = when (chatInfo.chatSettings?.enableNtfs) { val unreadTag: Boolean get() = when (chatInfo.chatSettings?.enableNtfs) {
All -> chatStats.unreadChat || chatStats.unreadCount > 0 All -> chatStats.unreadChat || chatStats.unreadCount > 0
Mentions -> chatStats.unreadChat || chatStats.unreadMentions > 0 Mentions -> chatStats.unreadChat || chatStats.unreadMentions > 0
@ -1282,6 +1275,7 @@ sealed class ChatInfo: SomeChat, NamedChat {
override val apiId get() = contact.apiId override val apiId get() = contact.apiId
override val ready get() = contact.ready override val ready get() = contact.ready
override val chatDeleted get() = contact.chatDeleted override val chatDeleted get() = contact.chatDeleted
override val userCantSendReason get() = contact.userCantSendReason
override val sendMsgEnabled get() = contact.sendMsgEnabled override val sendMsgEnabled get() = contact.sendMsgEnabled
override val incognito get() = contact.incognito override val incognito get() = contact.incognito
override fun featureEnabled(feature: ChatFeature) = contact.featureEnabled(feature) override fun featureEnabled(feature: ChatFeature) = contact.featureEnabled(feature)
@ -1307,6 +1301,7 @@ sealed class ChatInfo: SomeChat, NamedChat {
override val apiId get() = groupInfo.apiId override val apiId get() = groupInfo.apiId
override val ready get() = groupInfo.ready override val ready get() = groupInfo.ready
override val chatDeleted get() = groupInfo.chatDeleted override val chatDeleted get() = groupInfo.chatDeleted
override val userCantSendReason get() = groupInfo.userCantSendReason
override val sendMsgEnabled get() = groupInfo.sendMsgEnabled override val sendMsgEnabled get() = groupInfo.sendMsgEnabled
override val incognito get() = groupInfo.incognito override val incognito get() = groupInfo.incognito
override fun featureEnabled(feature: ChatFeature) = groupInfo.featureEnabled(feature) override fun featureEnabled(feature: ChatFeature) = groupInfo.featureEnabled(feature)
@ -1331,6 +1326,7 @@ sealed class ChatInfo: SomeChat, NamedChat {
override val apiId get() = noteFolder.apiId override val apiId get() = noteFolder.apiId
override val ready get() = noteFolder.ready override val ready get() = noteFolder.ready
override val chatDeleted get() = noteFolder.chatDeleted override val chatDeleted get() = noteFolder.chatDeleted
override val userCantSendReason get() = noteFolder.userCantSendReason
override val sendMsgEnabled get() = noteFolder.sendMsgEnabled override val sendMsgEnabled get() = noteFolder.sendMsgEnabled
override val incognito get() = noteFolder.incognito override val incognito get() = noteFolder.incognito
override fun featureEnabled(feature: ChatFeature) = noteFolder.featureEnabled(feature) override fun featureEnabled(feature: ChatFeature) = noteFolder.featureEnabled(feature)
@ -1355,6 +1351,7 @@ sealed class ChatInfo: SomeChat, NamedChat {
override val apiId get() = contactRequest.apiId override val apiId get() = contactRequest.apiId
override val ready get() = contactRequest.ready override val ready get() = contactRequest.ready
override val chatDeleted get() = contactRequest.chatDeleted override val chatDeleted get() = contactRequest.chatDeleted
override val userCantSendReason get() = contactRequest.userCantSendReason
override val sendMsgEnabled get() = contactRequest.sendMsgEnabled override val sendMsgEnabled get() = contactRequest.sendMsgEnabled
override val incognito get() = contactRequest.incognito override val incognito get() = contactRequest.incognito
override fun featureEnabled(feature: ChatFeature) = contactRequest.featureEnabled(feature) override fun featureEnabled(feature: ChatFeature) = contactRequest.featureEnabled(feature)
@ -1379,6 +1376,7 @@ sealed class ChatInfo: SomeChat, NamedChat {
override val apiId get() = contactConnection.apiId override val apiId get() = contactConnection.apiId
override val ready get() = contactConnection.ready override val ready get() = contactConnection.ready
override val chatDeleted get() = contactConnection.chatDeleted override val chatDeleted get() = contactConnection.chatDeleted
override val userCantSendReason get() = contactConnection.userCantSendReason
override val sendMsgEnabled get() = contactConnection.sendMsgEnabled override val sendMsgEnabled get() = contactConnection.sendMsgEnabled
override val incognito get() = contactConnection.incognito override val incognito get() = contactConnection.incognito
override fun featureEnabled(feature: ChatFeature) = contactConnection.featureEnabled(feature) override fun featureEnabled(feature: ChatFeature) = contactConnection.featureEnabled(feature)
@ -1408,6 +1406,7 @@ sealed class ChatInfo: SomeChat, NamedChat {
override val id get() = "?$apiId" override val id get() = "?$apiId"
override val ready get() = false override val ready get() = false
override val chatDeleted get() = false override val chatDeleted get() = false
override val userCantSendReason get() = generalGetString(MR.strings.cant_send_message_generic) to null
override val sendMsgEnabled get() = false override val sendMsgEnabled get() = false
override val incognito get() = false override val incognito get() = false
override fun featureEnabled(feature: ChatFeature) = false override fun featureEnabled(feature: ChatFeature) = false
@ -1450,14 +1449,6 @@ sealed class ChatInfo: SomeChat, NamedChat {
is InvalidJSON -> updatedAt is InvalidJSON -> updatedAt
} }
val userCanSend: Boolean
get() = when (this) {
is ChatInfo.Direct -> true
is ChatInfo.Group -> groupInfo.membership.memberRole >= GroupMemberRole.Member
is ChatInfo.Local -> true
else -> false
}
val chatTags: List<Long>? val chatTags: List<Long>?
get() = when (this) { get() = when (this) {
is Direct -> contact.chatTags is Direct -> contact.chatTags
@ -1528,13 +1519,17 @@ data class Contact(
override val ready get() = activeConn?.connStatus == ConnStatus.Ready override val ready get() = activeConn?.connStatus == ConnStatus.Ready
val sndReady get() = ready || activeConn?.connStatus == ConnStatus.SndReady val sndReady get() = ready || activeConn?.connStatus == ConnStatus.SndReady
val active get() = contactStatus == ContactStatus.Active val active get() = contactStatus == ContactStatus.Active
override val sendMsgEnabled get() = ( override val userCantSendReason: Pair<String, String?>?
sndReady get() {
&& active // TODO [short links] this will have additional statuses for pending contact requests before they are accepted
&& !(activeConn?.connectionStats?.ratchetSyncSendProhibited ?: false) if (nextSendGrpInv) return null
&& !(activeConn?.connDisabled ?: true) if (!active) return generalGetString(MR.strings.cant_send_message_contact_deleted) to null
) if (!sndReady) return generalGetString(MR.strings.cant_send_message_contact_not_ready) to null
|| nextSendGrpInv if (activeConn?.connectionStats?.ratchetSyncSendProhibited == true) return generalGetString(MR.strings.cant_send_message_contact_not_synchronized) to null
if (activeConn?.connDisabled == true) return generalGetString(MR.strings.cant_send_message_contact_disabled) to null
return null
}
override val sendMsgEnabled get() = userCantSendReason == null
val nextSendGrpInv get() = contactGroupMemberId != null && !contactGrpInvSent val nextSendGrpInv get() = contactGroupMemberId != null && !contactGrpInvSent
override val incognito get() = contactConnIncognito override val incognito get() = contactConnIncognito
override fun featureEnabled(feature: ChatFeature) = when (feature) { override fun featureEnabled(feature: ChatFeature) = when (feature) {
@ -1768,7 +1763,23 @@ data class GroupInfo (
override val apiId get() = groupId override val apiId get() = groupId
override val ready get() = membership.memberActive override val ready get() = membership.memberActive
override val chatDeleted get() = false override val chatDeleted get() = false
override val sendMsgEnabled get() = membership.memberActive override val userCantSendReason: Pair<String, String?>? get() =
if (membership.memberActive) {
if (membership.memberRole == GroupMemberRole.Observer) {
generalGetString(MR.strings.observer_cant_send_message_title) to generalGetString(MR.strings.observer_cant_send_message_desc)
} else {
null
}
} else {
when (membership.memberStatus) {
GroupMemberStatus.MemRejected -> generalGetString(MR.strings.cant_send_message_rejected) to null
GroupMemberStatus.MemGroupDeleted -> generalGetString(MR.strings.cant_send_message_group_deleted) to null
GroupMemberStatus.MemRemoved -> generalGetString(MR.strings.cant_send_message_mem_removed) to null
GroupMemberStatus.MemLeft -> generalGetString(MR.strings.cant_send_message_you_left) to null
else -> generalGetString(MR.strings.cant_send_message_generic) to null
}
}
override val sendMsgEnabled get() = userCantSendReason == null
override val incognito get() = membership.memberIncognito override val incognito get() = membership.memberIncognito
override fun featureEnabled(feature: ChatFeature) = when (feature) { override fun featureEnabled(feature: ChatFeature) = when (feature) {
ChatFeature.TimedMessages -> fullGroupPreferences.timedMessages.on ChatFeature.TimedMessages -> fullGroupPreferences.timedMessages.on
@ -2144,6 +2155,7 @@ class NoteFolder(
override val apiId get() = noteFolderId override val apiId get() = noteFolderId
override val chatDeleted get() = false override val chatDeleted get() = false
override val ready get() = true override val ready get() = true
override val userCantSendReason: Pair<String, String?>? = null
override val sendMsgEnabled get() = true override val sendMsgEnabled get() = true
override val incognito get() = false override val incognito get() = false
override fun featureEnabled(feature: ChatFeature) = feature == ChatFeature.Voice override fun featureEnabled(feature: ChatFeature) = feature == ChatFeature.Voice
@ -2180,6 +2192,7 @@ class UserContactRequest (
override val apiId get() = contactRequestId override val apiId get() = contactRequestId
override val chatDeleted get() = false override val chatDeleted get() = false
override val ready get() = true override val ready get() = true
override val userCantSendReason = generalGetString(MR.strings.cant_send_message_generic) to null
override val sendMsgEnabled get() = false override val sendMsgEnabled get() = false
override val incognito get() = false override val incognito get() = false
override fun featureEnabled(feature: ChatFeature) = false override fun featureEnabled(feature: ChatFeature) = false
@ -2219,6 +2232,7 @@ class PendingContactConnection(
override val apiId get() = pccConnId override val apiId get() = pccConnId
override val chatDeleted get() = false override val chatDeleted get() = false
override val ready get() = false override val ready get() = false
override val userCantSendReason = generalGetString(MR.strings.cant_send_message_generic) to null
override val sendMsgEnabled get() = false override val sendMsgEnabled get() = false
override val incognito get() = customUserProfileId != null override val incognito get() = customUserProfileId != null
override fun featureEnabled(feature: ChatFeature) = false override fun featureEnabled(feature: ChatFeature) = false

View file

@ -12,10 +12,10 @@ import java.net.URI
expect fun PlatformTextField( expect fun PlatformTextField(
composeState: MutableState<ComposeState>, composeState: MutableState<ComposeState>,
sendMsgEnabled: Boolean, sendMsgEnabled: Boolean,
disabledText: String?,
sendMsgButtonDisabled: Boolean, sendMsgButtonDisabled: Boolean,
textStyle: MutableState<TextStyle>, textStyle: MutableState<TextStyle>,
showDeleteTextButton: MutableState<Boolean>, showDeleteTextButton: MutableState<Boolean>,
userIsObserver: Boolean,
placeholder: String, placeholder: String,
showVoiceButton: Boolean, showVoiceButton: Boolean,
onMessageChange: (ComposeMessage) -> Unit, onMessageChange: (ComposeMessage) -> Unit,

View file

@ -99,12 +99,11 @@ fun TerminalLayout(
isDirectChat = false, isDirectChat = false,
liveMessageAlertShown = SharedPreference(get = { false }, set = {}), liveMessageAlertShown = SharedPreference(get = { false }, set = {}),
sendMsgEnabled = true, sendMsgEnabled = true,
userCantSendReason = null,
sendButtonEnabled = true, sendButtonEnabled = true,
nextSendGrpInv = false, nextSendGrpInv = false,
needToAllowVoiceToContact = false, needToAllowVoiceToContact = false,
allowedVoiceByPrefs = false, allowedVoiceByPrefs = false,
userIsObserver = false,
userCanSend = true,
allowVoiceToContact = {}, allowVoiceToContact = {},
placeholder = "", placeholder = "",
sendMessage = { sendCommand() }, sendMessage = { sendCommand() },

View file

@ -723,7 +723,7 @@ fun ChatLayout(
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.desktopOnExternalDrag( .desktopOnExternalDrag(
enabled = remember(attachmentDisabled.value, chatInfo.value?.userCanSend) { mutableStateOf(!attachmentDisabled.value && chatInfo.value?.userCanSend == true) }.value, enabled = remember(attachmentDisabled.value, chatInfo.value?.sendMsgEnabled) { mutableStateOf(!attachmentDisabled.value && chatInfo.value?.sendMsgEnabled == true) }.value,
onFiles = { paths -> composeState.onFilesAttached(paths.map { it.toURI() }) }, onFiles = { paths -> composeState.onFilesAttached(paths.map { it.toURI() }) },
onImage = { file -> CoroutineScope(Dispatchers.IO).launch { composeState.processPickedMedia(listOf(file.toURI()), null) } }, onImage = { file -> CoroutineScope(Dispatchers.IO).launch { composeState.processPickedMedia(listOf(file.toURI()), null) } },
onText = { onText = {

View file

@ -999,9 +999,8 @@ fun ComposeView(
chatModel.sharedContent.value = null chatModel.sharedContent.value = null
} }
val userCanSend = rememberUpdatedState(chat.chatInfo.userCanSend)
val sendMsgEnabled = rememberUpdatedState(chat.chatInfo.sendMsgEnabled) val sendMsgEnabled = rememberUpdatedState(chat.chatInfo.sendMsgEnabled)
val userIsObserver = rememberUpdatedState(chat.userIsObserver) val userCantSendReason = rememberUpdatedState(chat.chatInfo.userCantSendReason)
val nextSendGrpInv = rememberUpdatedState(chat.nextSendGrpInv) val nextSendGrpInv = rememberUpdatedState(chat.nextSendGrpInv)
Column { Column {
@ -1056,7 +1055,6 @@ fun ComposeView(
val attachmentEnabled = val attachmentEnabled =
!composeState.value.attachmentDisabled !composeState.value.attachmentDisabled
&& sendMsgEnabled.value && sendMsgEnabled.value
&& userCanSend.value
&& !isGroupAndProhibitedFiles && !isGroupAndProhibitedFiles
&& !nextSendGrpInv.value && !nextSendGrpInv.value
IconButton( IconButton(
@ -1102,8 +1100,8 @@ fun ComposeView(
} }
} }
LaunchedEffect(rememberUpdatedState(chat.chatInfo.userCanSend).value) { LaunchedEffect(rememberUpdatedState(chat.chatInfo.sendMsgEnabled).value) {
if (!chat.chatInfo.userCanSend) { if (!chat.chatInfo.sendMsgEnabled) {
clearCurrentDraft() clearCurrentDraft()
clearState() clearState()
} }
@ -1159,13 +1157,12 @@ fun ComposeView(
chat.chatInfo is ChatInfo.Direct, chat.chatInfo is ChatInfo.Direct,
liveMessageAlertShown = chatModel.controller.appPrefs.liveMessageAlertShown, liveMessageAlertShown = chatModel.controller.appPrefs.liveMessageAlertShown,
sendMsgEnabled = sendMsgEnabled.value, sendMsgEnabled = sendMsgEnabled.value,
userCantSendReason = userCantSendReason.value,
sendButtonEnabled = sendMsgEnabled.value && !(simplexLinkProhibited || fileProhibited || voiceProhibited), sendButtonEnabled = sendMsgEnabled.value && !(simplexLinkProhibited || fileProhibited || voiceProhibited),
nextSendGrpInv = nextSendGrpInv.value, nextSendGrpInv = nextSendGrpInv.value,
needToAllowVoiceToContact, needToAllowVoiceToContact,
allowedVoiceByPrefs, allowedVoiceByPrefs,
allowVoiceToContact = ::allowVoiceToContact, allowVoiceToContact = ::allowVoiceToContact,
userIsObserver = userIsObserver.value,
userCanSend = userCanSend.value,
sendButtonColor = sendButtonColor, sendButtonColor = sendButtonColor,
timedMessageAllowed = timedMessageAllowed, timedMessageAllowed = timedMessageAllowed,
customDisappearingMessageTimePref = chatModel.controller.appPrefs.customDisappearingMessageTime, customDisappearingMessageTimePref = chatModel.controller.appPrefs.customDisappearingMessageTime,

View file

@ -15,9 +15,7 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.graphics.* import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.* import androidx.compose.ui.unit.*
import chat.simplex.common.model.* import chat.simplex.common.model.*
@ -41,12 +39,11 @@ fun SendMsgView(
isDirectChat: Boolean, isDirectChat: Boolean,
liveMessageAlertShown: SharedPreference<Boolean>, liveMessageAlertShown: SharedPreference<Boolean>,
sendMsgEnabled: Boolean, sendMsgEnabled: Boolean,
userCantSendReason: Pair<String, String?>?,
sendButtonEnabled: Boolean, sendButtonEnabled: Boolean,
nextSendGrpInv: Boolean, nextSendGrpInv: Boolean,
needToAllowVoiceToContact: Boolean, needToAllowVoiceToContact: Boolean,
allowedVoiceByPrefs: Boolean, allowedVoiceByPrefs: Boolean,
userIsObserver: Boolean,
userCanSend: Boolean,
sendButtonColor: Color = MaterialTheme.colors.primary, sendButtonColor: Color = MaterialTheme.colors.primary,
allowVoiceToContact: () -> Unit, allowVoiceToContact: () -> Unit,
timedMessageAllowed: Boolean = false, timedMessageAllowed: Boolean = false,
@ -82,14 +79,14 @@ fun SendMsgView(
(!allowedVoiceByPrefs && cs.preview is ComposePreview.VoicePreview) || (!allowedVoiceByPrefs && cs.preview is ComposePreview.VoicePreview) ||
cs.endLiveDisabled || cs.endLiveDisabled ||
!sendButtonEnabled !sendButtonEnabled
val clicksOnTextFieldDisabled = !sendMsgEnabled || cs.preview is ComposePreview.VoicePreview || !userCanSend || cs.inProgress val clicksOnTextFieldDisabled = !sendMsgEnabled || cs.preview is ComposePreview.VoicePreview || cs.inProgress
PlatformTextField( PlatformTextField(
composeState, composeState,
sendMsgEnabled, sendMsgEnabled,
disabledText = userCantSendReason?.first,
sendMsgButtonDisabled, sendMsgButtonDisabled,
textStyle, textStyle,
showDeleteTextButton, showDeleteTextButton,
userIsObserver,
if (clicksOnTextFieldDisabled) "" else placeholder, if (clicksOnTextFieldDisabled) "" else placeholder,
showVoiceButton, showVoiceButton,
onMessageChange, onMessageChange,
@ -102,16 +99,23 @@ fun SendMsgView(
} }
} }
if (clicksOnTextFieldDisabled) { if (clicksOnTextFieldDisabled) {
if (userCantSendReason != null) {
Box( Box(
Modifier Modifier
.matchParentSize() .matchParentSize()
.clickable(enabled = !userCanSend, indication = null, interactionSource = remember { MutableInteractionSource() }, onClick = { .clickable(indication = null, interactionSource = remember { MutableInteractionSource() }, onClick = {
AlertManager.shared.showAlertMsg( AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.observer_cant_send_message_title), title = generalGetString(MR.strings.cant_send_message_alert_title),
text = generalGetString(MR.strings.observer_cant_send_message_desc) text = userCantSendReason.second
) )
}) })
) )
} else {
Box(
Modifier
.matchParentSize()
)
}
} }
if (showDeleteTextButton.value) { if (showDeleteTextButton.value) {
DeleteTextButton(composeState) DeleteTextButton(composeState)
@ -135,11 +139,11 @@ fun SendMsgView(
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
val stopRecOnNextClick = remember { mutableStateOf(false) } val stopRecOnNextClick = remember { mutableStateOf(false) }
when { when {
needToAllowVoiceToContact || !allowedVoiceByPrefs || !userCanSend -> { needToAllowVoiceToContact || !allowedVoiceByPrefs -> {
DisallowedVoiceButton(userCanSend) { DisallowedVoiceButton {
if (needToAllowVoiceToContact) { if (needToAllowVoiceToContact) {
showNeedToAllowVoiceAlert(allowVoiceToContact) showNeedToAllowVoiceAlert(allowVoiceToContact)
} else if (!allowedVoiceByPrefs) { } else {
showDisabledVoiceAlert(isDirectChat) showDisabledVoiceAlert(isDirectChat)
} }
} }
@ -155,7 +159,7 @@ fun SendMsgView(
&& cs.contextItem is ComposeContextItem.NoContextItem && cs.contextItem is ComposeContextItem.NoContextItem
) { ) {
Spacer(Modifier.width(12.dp)) Spacer(Modifier.width(12.dp))
StartLiveMessageButton(userCanSend) { StartLiveMessageButton {
if (composeState.value.preview is ComposePreview.NoPreview) { if (composeState.value.preview is ComposePreview.NoPreview) {
startLiveMessage(scope, sendLiveMessage, updateLiveMessage, sendButtonSize, sendButtonAlpha, composeState, liveMessageAlertShown) startLiveMessage(scope, sendLiveMessage, updateLiveMessage, sendButtonSize, sendButtonAlpha, composeState, liveMessageAlertShown)
} }
@ -343,8 +347,8 @@ private fun RecordVoiceView(recState: MutableState<RecordingState>, stopRecOnNex
} }
@Composable @Composable
private fun DisallowedVoiceButton(enabled: Boolean, onClick: () -> Unit) { private fun DisallowedVoiceButton(onClick: () -> Unit) {
IconButton(onClick, Modifier.size(36.dp), enabled = enabled) { IconButton(onClick, Modifier.size(36.dp)) {
Icon( Icon(
painterResource(MR.images.ic_keyboard_voice), painterResource(MR.images.ic_keyboard_voice),
stringResource(MR.strings.icon_descr_record_voice_message), stringResource(MR.strings.icon_descr_record_voice_message),
@ -460,14 +464,13 @@ private fun SendMsgButton(
} }
@Composable @Composable
private fun StartLiveMessageButton(enabled: Boolean, onClick: () -> Unit) { private fun StartLiveMessageButton(onClick: () -> Unit) {
val interactionSource = remember { MutableInteractionSource() } val interactionSource = remember { MutableInteractionSource() }
val ripple = remember { ripple(bounded = false, radius = 24.dp) } val ripple = remember { ripple(bounded = false, radius = 24.dp) }
Box( Box(
modifier = Modifier.requiredSize(36.dp) modifier = Modifier.requiredSize(36.dp)
.clickable( .clickable(
onClick = onClick, onClick = onClick,
enabled = enabled,
role = Role.Button, role = Role.Button,
interactionSource = interactionSource, interactionSource = interactionSource,
indication = ripple indication = ripple
@ -477,7 +480,7 @@ private fun StartLiveMessageButton(enabled: Boolean, onClick: () -> Unit) {
Icon( Icon(
BoltFilled, BoltFilled,
stringResource(MR.strings.icon_descr_send_message), stringResource(MR.strings.icon_descr_send_message),
tint = if (enabled) MaterialTheme.colors.primary else MaterialTheme.colors.secondary, tint = MaterialTheme.colors.primary,
modifier = Modifier modifier = Modifier
.size(36.dp) .size(36.dp)
.padding(4.dp) .padding(4.dp)
@ -576,12 +579,11 @@ fun PreviewSendMsgView() {
isDirectChat = true, isDirectChat = true,
liveMessageAlertShown = SharedPreference(get = { true }, set = { }), liveMessageAlertShown = SharedPreference(get = { true }, set = { }),
sendMsgEnabled = true, sendMsgEnabled = true,
userCantSendReason = null,
sendButtonEnabled = true, sendButtonEnabled = true,
nextSendGrpInv = false, nextSendGrpInv = false,
needToAllowVoiceToContact = false, needToAllowVoiceToContact = false,
allowedVoiceByPrefs = true, allowedVoiceByPrefs = true,
userIsObserver = false,
userCanSend = true,
allowVoiceToContact = {}, allowVoiceToContact = {},
timedMessageAllowed = false, timedMessageAllowed = false,
placeholder = "", placeholder = "",
@ -612,12 +614,11 @@ fun PreviewSendMsgViewEditing() {
isDirectChat = true, isDirectChat = true,
liveMessageAlertShown = SharedPreference(get = { true }, set = { }), liveMessageAlertShown = SharedPreference(get = { true }, set = { }),
sendMsgEnabled = true, sendMsgEnabled = true,
userCantSendReason = null,
sendButtonEnabled = true, sendButtonEnabled = true,
nextSendGrpInv = false, nextSendGrpInv = false,
needToAllowVoiceToContact = false, needToAllowVoiceToContact = false,
allowedVoiceByPrefs = true, allowedVoiceByPrefs = true,
userIsObserver = false,
userCanSend = true,
allowVoiceToContact = {}, allowVoiceToContact = {},
timedMessageAllowed = false, timedMessageAllowed = false,
placeholder = "", placeholder = "",
@ -648,12 +649,11 @@ fun PreviewSendMsgViewInProgress() {
isDirectChat = true, isDirectChat = true,
liveMessageAlertShown = SharedPreference(get = { true }, set = { }), liveMessageAlertShown = SharedPreference(get = { true }, set = { }),
sendMsgEnabled = true, sendMsgEnabled = true,
userCantSendReason = null,
sendButtonEnabled = true, sendButtonEnabled = true,
nextSendGrpInv = false, nextSendGrpInv = false,
needToAllowVoiceToContact = false, needToAllowVoiceToContact = false,
allowedVoiceByPrefs = true, allowedVoiceByPrefs = true,
userIsObserver = false,
userCanSend = true,
allowVoiceToContact = {}, allowVoiceToContact = {},
timedMessageAllowed = false, timedMessageAllowed = false,
placeholder = "", placeholder = "",

View file

@ -21,6 +21,7 @@ import dev.icerock.moko.resources.compose.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.* import androidx.compose.ui.unit.*
import chat.simplex.common.BuildConfigCommon
import chat.simplex.common.model.* import chat.simplex.common.model.*
import chat.simplex.common.model.ChatController.appPrefs import chat.simplex.common.model.ChatController.appPrefs
import chat.simplex.common.platform.* import chat.simplex.common.platform.*
@ -127,7 +128,9 @@ fun SettingsLayout(
SectionDividerSpaced() SectionDividerSpaced()
SectionView(stringResource(MR.strings.settings_section_title_support)) { SectionView(stringResource(MR.strings.settings_section_title_support)) {
if (!BuildConfigCommon.ANDROID_BUNDLE) {
ContributeItem(uriHandler) ContributeItem(uriHandler)
}
RateAppItem(uriHandler) RateAppItem(uriHandler)
StarOnGithubItem(uriHandler) StarOnGithubItem(uriHandler)
} }

View file

@ -487,8 +487,6 @@
<string name="image_decoding_exception_desc">The image cannot be decoded. Please, try a different image or contact developers.</string> <string name="image_decoding_exception_desc">The image cannot be decoded. Please, try a different image or contact developers.</string>
<string name="video_decoding_exception_desc">The video cannot be decoded. Please, try a different video or contact developers.</string> <string name="video_decoding_exception_desc">The video cannot be decoded. Please, try a different video or contact developers.</string>
<string name="you_are_observer">you are observer</string> <string name="you_are_observer">you are observer</string>
<string name="observer_cant_send_message_title">You can\'t send messages!</string>
<string name="observer_cant_send_message_desc">Please contact group admin.</string>
<string name="files_and_media_prohibited">Files and media prohibited!</string> <string name="files_and_media_prohibited">Files and media prohibited!</string>
<string name="only_owners_can_enable_files_and_media">Only group owners can enable files and media.</string> <string name="only_owners_can_enable_files_and_media">Only group owners can enable files and media.</string>
<string name="compose_send_direct_message_to_connect">Send direct message to connect</string> <string name="compose_send_direct_message_to_connect">Send direct message to connect</string>
@ -508,6 +506,19 @@
<string name="report_compose_reason_header_illegal">Report content: only group moderators will see it.</string> <string name="report_compose_reason_header_illegal">Report content: only group moderators will see it.</string>
<string name="report_compose_reason_header_other">Report other: only group moderators will see it.</string> <string name="report_compose_reason_header_other">Report other: only group moderators will see it.</string>
<string name="cant_send_message_alert_title">You can\'t send messages!</string>
<string name="cant_send_message_contact_not_ready">contact not ready</string>
<string name="cant_send_message_contact_deleted">contact deleted</string>
<string name="cant_send_message_contact_not_synchronized">not synchronized</string>
<string name="cant_send_message_contact_disabled">contact disabled</string>
<string name="observer_cant_send_message_title">you are observer</string>
<string name="observer_cant_send_message_desc">Please contact group admin.</string>
<string name="cant_send_message_rejected">request to join rejected</string>
<string name="cant_send_message_group_deleted">group is deleted</string>
<string name="cant_send_message_mem_removed">removed from group</string>
<string name="cant_send_message_you_left">you left</string>
<string name="cant_send_message_generic">can\'t send messages</string>
<!-- Images - chat.simplex.app.views.chat.item.CIImageView.kt --> <!-- Images - chat.simplex.app.views.chat.item.CIImageView.kt -->
<string name="image_descr">Image</string> <string name="image_descr">Image</string>
<string name="icon_descr_waiting_for_image">Waiting for image</string> <string name="icon_descr_waiting_for_image">Waiting for image</string>

View file

@ -44,10 +44,10 @@ import kotlin.text.substring
actual fun PlatformTextField( actual fun PlatformTextField(
composeState: MutableState<ComposeState>, composeState: MutableState<ComposeState>,
sendMsgEnabled: Boolean, sendMsgEnabled: Boolean,
disabledText: String?,
sendMsgButtonDisabled: Boolean, sendMsgButtonDisabled: Boolean,
textStyle: MutableState<TextStyle>, textStyle: MutableState<TextStyle>,
showDeleteTextButton: MutableState<Boolean>, showDeleteTextButton: MutableState<Boolean>,
userIsObserver: Boolean,
placeholder: String, placeholder: String,
showVoiceButton: Boolean, showVoiceButton: Boolean,
onMessageChange: (ComposeMessage) -> Unit, onMessageChange: (ComposeMessage) -> Unit,
@ -203,16 +203,16 @@ actual fun PlatformTextField(
) )
showDeleteTextButton.value = cs.message.text.split("\n").size >= 4 && !cs.inProgress showDeleteTextButton.value = cs.message.text.split("\n").size >= 4 && !cs.inProgress
if (composeState.value.preview is ComposePreview.VoicePreview) { if (composeState.value.preview is ComposePreview.VoicePreview) {
ComposeOverlay(MR.strings.voice_message_send_text, textStyle, padding) ComposeOverlay(generalGetString(MR.strings.voice_message_send_text), textStyle, padding)
} else if (userIsObserver) { } else if (disabledText != null) {
ComposeOverlay(MR.strings.you_are_observer, textStyle, padding) ComposeOverlay(disabledText, textStyle, padding)
} }
} }
@Composable @Composable
private fun ComposeOverlay(textId: StringResource, textStyle: MutableState<TextStyle>, padding: PaddingValues) { private fun ComposeOverlay(text: String, textStyle: MutableState<TextStyle>, padding: PaddingValues) {
Text( Text(
generalGetString(textId), text,
Modifier.padding(padding), Modifier.padding(padding),
color = MaterialTheme.colors.secondary, color = MaterialTheme.colors.secondary,
style = textStyle.value.copy(fontStyle = FontStyle.Italic) style = textStyle.value.copy(fontStyle = FontStyle.Italic)

View file

@ -24,11 +24,13 @@ android.nonTransitiveRClass=true
kotlin.mpp.androidSourceSetLayoutVersion=2 kotlin.mpp.androidSourceSetLayoutVersion=2
kotlin.jvm.target=11 kotlin.jvm.target=11
android.version_name=6.3.4 android.version_name=6.3.6
android.version_code=288 android.version_code=295
desktop.version_name=6.3.4 android.bundle=false
desktop.version_code=101
desktop.version_name=6.3.6
desktop.version_code=106
kotlin.version=1.9.23 kotlin.version=1.9.23
gradle.plugin.version=8.2.0 gradle.plugin.version=8.2.0

View file

@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd
source-repository-package source-repository-package
type: git type: git
location: https://github.com/simplex-chat/simplexmq.git location: https://github.com/simplex-chat/simplexmq.git
tag: deaec3cce286e959bd594b9620c307954b510a07 tag: 3d62a383d5dcae6529d6d866233857182bcb4d47
source-repository-package source-repository-package
type: git type: git

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before After
Before After

BIN
images/whonix-logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

View file

@ -38,6 +38,32 @@
</description> </description>
<releases> <releases>
<release version="6.3.4" date="2025-05-12">
<url type="details">https://simplex.chat/blog/20250308-simplex-chat-v6-3-new-user-experience-safety-in-public-groups.html</url>
<description>
<p>New in v6.3.1-4:</p>
<ul>
<li>fixes mentions with trailing punctuation (e.g., hello @name!).</li>
<li>recognizes domain names as links (e.g., simplex.chat).</li>
<li>forward compatibility with "knocking" (a feature for group admins to review and to chat with the new members prior to admitting them to groups, it will be released in 6.4)</li>
<li>support for connecting via short connection links.</li>
<li>fix related to backward/forward compatibility of the app in some rare cases.</li>
<li>scrolling/navigation improvements.</li>
<li>faster onboarding (conditions and operators are combined to one screen).</li>
</ul>
<p>New in v6.3.0:</p>
<ul>
<li>Mention members and get notified when mentioned.</li>
<li>Send private reports to moderators.</li>
<li>Delete, block and change role for multiple members at once</li>
<li>Faster sending messages and faster deletion.</li>
<li>Organize chats into lists to keep track of what's important.</li>
<li>Jump to found and forwarded messages.</li>
<li>Private media file names.</li>
<li>Message expiration in chats.</li>
</ul>
</description>
</release>
<release version="6.3.3" date="2025-04-24"> <release version="6.3.3" date="2025-04-24">
<url type="details">https://simplex.chat/blog/20250308-simplex-chat-v6-3-new-user-experience-safety-in-public-groups.html</url> <url type="details">https://simplex.chat/blog/20250308-simplex-chat-v6-3-new-user-experience-safety-in-public-groups.html</url>
<description> <description>

View file

@ -1,5 +1,5 @@
{ {
"https://github.com/simplex-chat/simplexmq.git"."deaec3cce286e959bd594b9620c307954b510a07" = "0b8m4czjiwsi9169plslyk2rjw0f370vv7ha6qm2hpx14bxzz7xm"; "https://github.com/simplex-chat/simplexmq.git"."3d62a383d5dcae6529d6d866233857182bcb4d47" = "133xm8jkim7agd6drwm3lbx1z7v8nf4l3asrm46ag3n2q201yfxc";
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";

View file

@ -5,7 +5,7 @@ cabal-version: 1.12
-- see: https://github.com/sol/hpack -- see: https://github.com/sol/hpack
name: simplex-chat name: simplex-chat
version: 6.3.4.1 version: 6.3.6.0
category: Web, System, Services, Cryptography category: Web, System, Services, Cryptography
homepage: https://github.com/simplex-chat/simplex-chat#readme homepage: https://github.com/simplex-chat/simplex-chat#readme
author: simplex.chat author: simplex.chat

View file

@ -1671,25 +1671,10 @@ processChatCommand' vr = \case
case (pccConnStatus, connLinkInv) of case (pccConnStatus, connLinkInv) of
(ConnNew, Just (CCLink cReqInv _)) -> do (ConnNew, Just (CCLink cReqInv _)) -> do
newUser <- privateGetUser newUserId newUser <- privateGetUser newUserId
conn' <- ifM (canKeepLink cReqInv newUser) (updateConnRecord user conn newUser) (recreateConn user conn newUser) conn' <- recreateConn user conn newUser
pure $ CRConnectionUserChanged user conn conn' newUser pure $ CRConnectionUserChanged user conn conn' newUser
_ -> throwChatError CEConnectionUserChangeProhibited _ -> throwChatError CEConnectionUserChangeProhibited
where where
canKeepLink :: ConnReqInvitation -> User -> CM Bool
canKeepLink (CRInvitationUri crData _) newUser = do
let ConnReqUriData {crSmpQueues = q :| _} = crData
SMPQueueUri {queueAddress = SMPQueueAddress {smpServer}} = q
newUserServers <-
map protoServer' . L.filter (\ServerCfg {enabled} -> enabled)
<$> getKnownAgentServers SPSMP newUser
pure $ smpServer `elem` newUserServers
updateConnRecord user@User {userId} conn@PendingContactConnection {customUserProfileId} newUser = do
withAgent $ \a -> changeConnectionUser a (aUserId user) (aConnId' conn) (aUserId newUser)
withFastStore' $ \db -> do
conn' <- updatePCCUser db userId conn newUserId
forM_ customUserProfileId $ \profileId ->
deletePCCIncognitoProfile db user profileId
pure conn'
recreateConn user conn@PendingContactConnection {customUserProfileId, connLinkInv} newUser = do recreateConn user conn@PendingContactConnection {customUserProfileId, connLinkInv} newUser = do
subMode <- chatReadVar subscriptionMode subMode <- chatReadVar subscriptionMode
let userData = shortLinkUserData $ isJust $ connShortLink =<< connLinkInv let userData = shortLinkUserData $ isJust $ connShortLink =<< connLinkInv

View file

@ -66,7 +66,6 @@ module Simplex.Chat.Store.Direct
updateContactAccepted, updateContactAccepted,
getUserByContactRequestId, getUserByContactRequestId,
getPendingContactConnections, getPendingContactConnections,
updatePCCUser,
getContactConnections, getContactConnections,
getConnectionById, getConnectionById,
getConnectionsContacts, getConnectionsContacts,
@ -440,19 +439,6 @@ updatePCCIncognito db User {userId} conn customUserProfileId = do
(customUserProfileId, updatedAt, userId, pccConnId conn) (customUserProfileId, updatedAt, userId, pccConnId conn)
pure (conn :: PendingContactConnection) {customUserProfileId, updatedAt} pure (conn :: PendingContactConnection) {customUserProfileId, updatedAt}
updatePCCUser :: DB.Connection -> UserId -> PendingContactConnection -> UserId -> IO PendingContactConnection
updatePCCUser db userId conn newUserId = do
updatedAt <- getCurrentTime
DB.execute
db
[sql|
UPDATE connections
SET user_id = ?, custom_user_profile_id = NULL, updated_at = ?
WHERE user_id = ? AND connection_id = ?
|]
(newUserId, updatedAt, userId, pccConnId conn)
pure (conn :: PendingContactConnection) {customUserProfileId = Nothing, updatedAt}
deletePCCIncognitoProfile :: DB.Connection -> User -> ProfileId -> IO () deletePCCIncognitoProfile :: DB.Connection -> User -> ProfileId -> IO ()
deletePCCIncognitoProfile db User {userId} profileId = deletePCCIncognitoProfile db User {userId} profileId =
DB.execute DB.execute

View file

@ -171,7 +171,7 @@ import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..))
import Simplex.Messaging.Util (eitherToMaybe) import Simplex.Messaging.Util (eitherToMaybe)
import UnliftIO.STM import UnliftIO.STM
#if defined(dbPostgres) #if defined(dbPostgres)
import Database.PostgreSQL.Simple (FromRow, Only (..), Query, ToRow, (:.) (..)) import Database.PostgreSQL.Simple (FromRow, In (..), Only (..), Query, ToRow, (:.) (..))
import Database.PostgreSQL.Simple.SqlQQ (sql) import Database.PostgreSQL.Simple.SqlQQ (sql)
#else #else
import Database.SQLite.Simple (FromRow, Only (..), Query, ToRow, (:.) (..)) import Database.SQLite.Simple (FromRow, Only (..), Query, ToRow, (:.) (..))
@ -2370,8 +2370,14 @@ updateGroupChatItemModerated db User {userId} GroupInfo {groupId} ci m@GroupMemb
updateMemberCIsModerated :: MsgDirectionI d => DB.Connection -> User -> GroupInfo -> GroupMember -> GroupMember -> SMsgDirection d -> UTCTime -> IO () updateMemberCIsModerated :: MsgDirectionI d => DB.Connection -> User -> GroupInfo -> GroupMember -> GroupMember -> SMsgDirection d -> UTCTime -> IO ()
updateMemberCIsModerated db User {userId} GroupInfo {groupId, membership} member byGroupMember md deletedTs = do updateMemberCIsModerated db User {userId} GroupInfo {groupId, membership} member byGroupMember md deletedTs = do
itemIds <- updateCIs =<< getCurrentTime itemIds <- updateCIs =<< getCurrentTime
#if defined(dbPostgres)
let inItemIds = Only $ In (map fromOnly itemIds)
DB.execute db "DELETE FROM messages WHERE message_id IN (SELECT message_id FROM chat_item_messages WHERE chat_item_id IN ?)" inItemIds
DB.execute db "DELETE FROM chat_item_versions WHERE chat_item_id IN ?" inItemIds
#else
DB.executeMany db deleteChatItemMessagesQuery itemIds DB.executeMany db deleteChatItemMessagesQuery itemIds
DB.executeMany db "DELETE FROM chat_item_versions WHERE chat_item_id = ?" itemIds DB.executeMany db "DELETE FROM chat_item_versions WHERE chat_item_id = ?" itemIds
#endif
where where
memId = groupMemberId' member memId = groupMemberId' member
updateQuery = updateQuery =

View file

@ -1071,10 +1071,6 @@ Query: UPDATE connections SET smp_agent_version = ? WHERE conn_id = ?
Plan: Plan:
SEARCH connections USING PRIMARY KEY (conn_id=?) SEARCH connections USING PRIMARY KEY (conn_id=?)
Query: UPDATE connections SET user_id = ? WHERE conn_id = ? and user_id = ?
Plan:
SEARCH connections USING PRIMARY KEY (conn_id=?)
Query: UPDATE messages SET msg_body = x'' WHERE conn_id = ? AND internal_id = ? Query: UPDATE messages SET msg_body = x'' WHERE conn_id = ? AND internal_id = ?
Plan: Plan:
SEARCH messages USING PRIMARY KEY (conn_id=? AND internal_id=?) SEARCH messages USING PRIMARY KEY (conn_id=? AND internal_id=?)

View file

@ -4215,14 +4215,6 @@ Query:
Plan: Plan:
SEARCH connections USING INTEGER PRIMARY KEY (rowid=?) SEARCH connections USING INTEGER PRIMARY KEY (rowid=?)
Query:
UPDATE connections
SET user_id = ?, custom_user_profile_id = NULL, updated_at = ?
WHERE user_id = ? AND connection_id = ?
Plan:
SEARCH connections USING INTEGER PRIMARY KEY (rowid=?)
Query: Query:
UPDATE contact_profiles UPDATE contact_profiles
SET contact_link = ?, updated_at = ? SET contact_link = ?, updated_at = ?

View file

@ -1747,10 +1747,9 @@ viewConnectionIncognitoUpdated PendingContactConnection {pccConnId, customUserPr
| otherwise = ["connection " <> sShow pccConnId <> " changed to non incognito"] | otherwise = ["connection " <> sShow pccConnId <> " changed to non incognito"]
viewConnectionUserChanged :: User -> PendingContactConnection -> User -> PendingContactConnection -> [StyledString] viewConnectionUserChanged :: User -> PendingContactConnection -> User -> PendingContactConnection -> [StyledString]
viewConnectionUserChanged User {localDisplayName = n} PendingContactConnection {pccConnId, connLinkInv} User {localDisplayName = n'} PendingContactConnection {connLinkInv = connLinkInv'} = viewConnectionUserChanged User {localDisplayName = n} PendingContactConnection {pccConnId} User {localDisplayName = n'} PendingContactConnection {connLinkInv = connLinkInv'} =
case (connLinkInv, connLinkInv') of case connLinkInv' of
(Just ccLink, Just ccLink') Just ccLink' -> [userChangedStr <> ", new link:"] <> newLink ccLink'
| ccLink /= ccLink' -> [userChangedStr <> ", new link:"] <> newLink ccLink'
_ -> [userChangedStr] _ -> [userChangedStr]
where where
userChangedStr = "connection " <> sShow pccConnId <> " changed from user " <> plain n <> " to user " <> plain n' userChangedStr = "connection " <> sShow pccConnId <> " changed from user " <> plain n <> " to user " <> plain n'

View file

@ -17,6 +17,7 @@ import Control.Concurrent (forkIOWithUnmask, killThread, threadDelay)
import Control.Concurrent.Async import Control.Concurrent.Async
import Control.Concurrent.STM import Control.Concurrent.STM
import Control.Exception (bracket, bracket_) import Control.Exception (bracket, bracket_)
import Control.Logger.Simple
import Control.Monad import Control.Monad
import Control.Monad.Except import Control.Monad.Except
import Control.Monad.Reader import Control.Monad.Reader
@ -519,7 +520,7 @@ smpServerCfg =
allowSMPProxy = True, allowSMPProxy = True,
serverClientConcurrency = 16, serverClientConcurrency = 16,
information = Nothing, information = Nothing,
startOptions = StartOptions {maintenance = False, compactLog = False, skipWarnings = False, confirmMigrations = MCYesUp} startOptions = StartOptions {maintenance = False, logLevel = LogError, compactLog = False, skipWarnings = False, confirmMigrations = MCYesUp}
} }
persistentServerStoreCfg :: FilePath -> AServerStoreCfg persistentServerStoreCfg :: FilePath -> AServerStoreCfg

View file

@ -84,7 +84,10 @@ chatGroupTests = do
describe "batch send messages" $ do describe "batch send messages" $ do
it "send multiple messages api" testSendMulti it "send multiple messages api" testSendMulti
it "send multiple timed messages" testSendMultiTimed it "send multiple timed messages" testSendMultiTimed
#if !defined(dbPostgres)
-- TODO [postgres] this test hangs with PostgreSQL
it "send multiple messages (many chat batches)" testSendMultiManyBatches it "send multiple messages (many chat batches)" testSendMultiManyBatches
#endif
xit'' "shared message body is reused" testSharedMessageBody xit'' "shared message body is reused" testSharedMessageBody
xit'' "shared batch body is reused" testSharedBatchBody xit'' "shared batch body is reused" testSharedBatchBody
describe "async group connections" $ do describe "async group connections" $ do

View file

@ -1827,7 +1827,7 @@ testChangePCCUser = testChat2 aliceProfile bobProfile $
\alice bob -> do \alice bob -> do
-- Create a new invite -- Create a new invite
alice ##> "/connect" alice ##> "/connect"
inv <- getInvitation alice _ <- getInvitation alice
-- Create new user and go back to original user -- Create new user and go back to original user
alice ##> "/create user alisa" alice ##> "/create user alisa"
showActiveUser alice "alisa" showActiveUser alice "alisa"
@ -1837,12 +1837,18 @@ testChangePCCUser = testChat2 aliceProfile bobProfile $
showActiveUser alice "alice (Alice)" showActiveUser alice "alice (Alice)"
-- Change connection to newly created user -- Change connection to newly created user
alice ##> "/_set conn user :1 2" alice ##> "/_set conn user :1 2"
alice <## "connection 1 changed from user alice to user alisa" alice <## "connection 1 changed from user alice to user alisa, new link:"
alice <## ""
_ <- getTermLine alice
alice <## ""
alice ##> "/user alisa" alice ##> "/user alisa"
showActiveUser alice "alisa" showActiveUser alice "alisa"
-- Change connection back to other user -- Change connection back to other user
alice ##> "/_set conn user :1 3" alice ##> "/_set conn user :1 3"
alice <## "connection 1 changed from user alisa to user alisa2" alice <## "connection 1 changed from user alisa to user alisa2, new link:"
alice <## ""
inv <- getTermLine alice
alice <## ""
alice ##> "/user alisa2" alice ##> "/user alisa2"
showActiveUser alice "alisa2" showActiveUser alice "alisa2"
-- Connect -- Connect
@ -1851,13 +1857,14 @@ testChangePCCUser = testChat2 aliceProfile bobProfile $
concurrently_ concurrently_
(alice <## "bob (Bob): contact is connected") (alice <## "bob (Bob): contact is connected")
(bob <## "alisa2: contact is connected") (bob <## "alisa2: contact is connected")
alice <##> bob
testChangePCCUserFromIncognito :: HasCallStack => TestParams -> IO () testChangePCCUserFromIncognito :: HasCallStack => TestParams -> IO ()
testChangePCCUserFromIncognito = testChat2 aliceProfile bobProfile $ testChangePCCUserFromIncognito = testChat2 aliceProfile bobProfile $
\alice bob -> do \alice bob -> do
-- Create a new invite and set as incognito -- Create a new invite and set as incognito
alice ##> "/connect" alice ##> "/connect"
inv <- getInvitation alice _ <- getInvitation alice
alice ##> "/_set incognito :1 on" alice ##> "/_set incognito :1 on"
alice <## "connection 1 changed to incognito" alice <## "connection 1 changed to incognito"
-- Create new user and go back to original user -- Create new user and go back to original user
@ -1867,13 +1874,19 @@ testChangePCCUserFromIncognito = testChat2 aliceProfile bobProfile $
showActiveUser alice "alice (Alice)" showActiveUser alice "alice (Alice)"
-- Change connection to newly created user -- Change connection to newly created user
alice ##> "/_set conn user :1 2" alice ##> "/_set conn user :1 2"
alice <## "connection 1 changed from user alice to user alisa" alice <## "connection 1 changed from user alice to user alisa, new link:"
alice <## ""
_ <- getTermLine alice
alice <## ""
alice `hasContactProfiles` ["alice"] alice `hasContactProfiles` ["alice"]
alice ##> "/user alisa" alice ##> "/user alisa"
showActiveUser alice "alisa" showActiveUser alice "alisa"
-- Change connection back to initial user -- Change connection back to initial user
alice ##> "/_set conn user :1 1" alice ##> "/_set conn user :1 1"
alice <## "connection 1 changed from user alisa to user alice" alice <## "connection 1 changed from user alisa to user alice, new link:"
alice <## ""
inv <- getTermLine alice
alice <## ""
alice ##> "/user alice" alice ##> "/user alice"
showActiveUser alice "alice (Alice)" showActiveUser alice "alice (Alice)"
-- Connect -- Connect
@ -1882,13 +1895,14 @@ testChangePCCUserFromIncognito = testChat2 aliceProfile bobProfile $
concurrently_ concurrently_
(alice <## "bob (Bob): contact is connected") (alice <## "bob (Bob): contact is connected")
(bob <## "alice (Alice): contact is connected") (bob <## "alice (Alice): contact is connected")
alice <##> bob
testChangePCCUserAndThenIncognito :: HasCallStack => TestParams -> IO () testChangePCCUserAndThenIncognito :: HasCallStack => TestParams -> IO ()
testChangePCCUserAndThenIncognito = testChat2 aliceProfile bobProfile $ testChangePCCUserAndThenIncognito = testChat2 aliceProfile bobProfile $
\alice bob -> do \alice bob -> do
-- Create a new invite and set as incognito -- Create a new invite and set as incognito
alice ##> "/connect" alice ##> "/connect"
inv <- getInvitation alice _ <- getInvitation alice
-- Create new user and go back to original user -- Create new user and go back to original user
alice ##> "/create user alisa" alice ##> "/create user alisa"
showActiveUser alice "alisa" showActiveUser alice "alisa"
@ -1896,7 +1910,10 @@ testChangePCCUserAndThenIncognito = testChat2 aliceProfile bobProfile $
showActiveUser alice "alice (Alice)" showActiveUser alice "alice (Alice)"
-- Change connection to newly created user -- Change connection to newly created user
alice ##> "/_set conn user :1 2" alice ##> "/_set conn user :1 2"
alice <## "connection 1 changed from user alice to user alisa" alice <## "connection 1 changed from user alice to user alisa, new link:"
alice <## ""
inv <- getTermLine alice
alice <## ""
alice ##> "/user alisa" alice ##> "/user alisa"
showActiveUser alice "alisa" showActiveUser alice "alisa"
-- Change connection to incognito and make sure it's attached to the newly created user profile -- Change connection to incognito and make sure it's attached to the newly created user profile
@ -1911,6 +1928,10 @@ testChangePCCUserAndThenIncognito = testChat2 aliceProfile bobProfile $
alice <## ("bob (Bob): contact is connected, your incognito profile for this contact is " <> alisaIncognito) alice <## ("bob (Bob): contact is connected, your incognito profile for this contact is " <> alisaIncognito)
alice <## ("use /i bob to print out this incognito profile again") alice <## ("use /i bob to print out this incognito profile again")
] ]
alice ?#> "@bob hi"
bob <# (alisaIncognito <> "> hi")
bob #> ("@" <> alisaIncognito <> " hey")
alice ?<# "bob> hey"
testChangePCCUserDiffSrv :: HasCallStack => TestParams -> IO () testChangePCCUserDiffSrv :: HasCallStack => TestParams -> IO ()
testChangePCCUserDiffSrv ps = do testChangePCCUserDiffSrv ps = do
@ -1951,6 +1972,7 @@ testChangePCCUserDiffSrv ps = do
concurrently_ concurrently_
(alice <## "bob (Bob): contact is connected") (alice <## "bob (Bob): contact is connected")
(bob <## "alisa: contact is connected") (bob <## "alisa: contact is connected")
alice <##> bob
where where
serverCfg' = serverCfg' =
smpServerCfg smpServerCfg

View file

@ -31,6 +31,10 @@
<img class="h-[40px] w-auto block dark:hidden" src="/img/privacy-guides-light.png" alt="Privacy Guides"> <img class="h-[40px] w-auto block dark:hidden" src="/img/privacy-guides-light.png" alt="Privacy Guides">
<img class="h-[40px] w-auto hidden dark:block" src="/img/privacy-guides-dark.png" alt="Privacy Guides"> <img class="h-[40px] w-auto hidden dark:block" src="/img/privacy-guides-dark.png" alt="Privacy Guides">
</a> </a>
<a class="block rounded overflow-hidden" title="Whonix messenger recommendations" href="https://www.whonix.org/wiki/Chat#Recommendation" target="_blank">
<img class="h-[24px] mb-[8px] w-auto block dark:hidden" src="/img/whonix-light.png" alt="Whonix">
<img class="h-[24px] mb-[8px] w-auto hidden dark:block" src="/img/whonix-dark.png" alt="Whonix">
</a>
<a class="block rounded overflow-hidden" title="publication" href="https://www.heise.de/suche/?q=simplex+chat&sort_by=date&rm=search" target="_blank"> <a class="block rounded overflow-hidden" title="publication" href="https://www.heise.de/suche/?q=simplex+chat&sort_by=date&rm=search" target="_blank">
<img class="h-[40px] w-auto block dark:hidden" src="/img/heise-light.png" alt="Heise Online"> <img class="h-[40px] w-auto block dark:hidden" src="/img/heise-light.png" alt="Heise Online">
<img class="h-[40px] w-auto hidden dark:block" src="/img/heise-dark.png" alt="Heise Online"> <img class="h-[40px] w-auto hidden dark:block" src="/img/heise-dark.png" alt="Heise Online">

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB