Merge branch 'master' into f/directory-integration-plan

This commit is contained in:
spaced4ndy
2026-08-27 13:11:04 +04:00
333 changed files with 15675 additions and 2552 deletions
+6
View File
@@ -153,6 +153,8 @@ jobs:
- name: Checkout Code
if: matrix.should_run == true
uses: actions/checkout@v3
with:
submodules: recursive
- name: Setup swap
if: matrix.ghc == '8.10.7' && matrix.should_run == true
@@ -498,6 +500,8 @@ jobs:
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
submodules: recursive
- name: Prepare build
uses: ./.github/actions/prepare-build
@@ -607,6 +611,8 @@ jobs:
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
submodules: recursive
- name: Prepare build
uses: ./.github/actions/prepare-build
+3
View File
@@ -0,0 +1,3 @@
[submodule "apps/multiplatform/external/nanohttpd/upstream"]
path = apps/multiplatform/external/nanohttpd/upstream
url = https://github.com/NanoHttpd/nanohttpd
+3 -1
View File
@@ -8,7 +8,7 @@
<img src="images/github-banner.jpg" alt="SimpleX logo" width="100%">
Invest in SimpleX Chat. [Learn more on Wefunder](https://wefunder.com/simplexchat).
Invest in SimpleX Chat. [Learn more on Wefunder](https://wefunder.com/simplex.chat?utm_source=github).
# SimpleX - the first messaging platform that has no user identifiers of any kind - 100% private by design!
@@ -220,6 +220,8 @@ You can use SimpleX with your own servers and still communicate with people usin
Recent and important updates:
[Aug 20, 2026. Equity Crowdfunding Launched - You Can Get a Stake in SimpleX Chat](./blog/20260819-simplex-chat-crowdfunding.md)
[Jul 22, 2026. SimpleX Public Names — a Name Nobody Can Take From You](./blog/20260722-simplex-public-names.md)
[Apr 30, 2026. SimpleX Channels, SimpleX Network Consortium and Community Crowdfunding - to Preserve Freedom of Speech](./blog/20260430-simplex-channels-v6-5-consortium-crowdfunding-freedom-of-speech.md)
+4
View File
@@ -21,6 +21,7 @@ enum ChatCommand: ChatCmdProtocol {
case apiSetUserContactReceipts(userId: Int64, userMsgReceiptSettings: UserMsgReceiptSettings)
case apiSetUserGroupReceipts(userId: Int64, userMsgReceiptSettings: UserMsgReceiptSettings)
case apiSetUserAutoAcceptMemberContacts(userId: Int64, enable: Bool)
case apiSetUserAutoAcceptGroupInvitations(userId: Int64, enable: Bool)
case apiHideUser(userId: Int64, viewPwd: String)
case apiUnhideUser(userId: Int64, viewPwd: String)
case apiMuteUser(userId: Int64)
@@ -216,6 +217,8 @@ enum ChatCommand: ChatCmdProtocol {
return "/_set receipts groups \(userId) \(onOff(umrs.enable)) clear_overrides=\(onOff(umrs.clearOverrides))"
case let .apiSetUserAutoAcceptMemberContacts(userId, enable):
return "/_set accept member contacts \(userId) \(onOff(enable))"
case let .apiSetUserAutoAcceptGroupInvitations(userId, enable):
return "/_set accept group invitations \(userId) \(onOff(enable))"
case let .apiHideUser(userId, viewPwd): return "/_hide user \(userId) \(encodeJSON(viewPwd))"
case let .apiUnhideUser(userId, viewPwd): return "/_unhide user \(userId) \(encodeJSON(viewPwd))"
case let .apiMuteUser(userId): return "/_mute user \(userId)"
@@ -434,6 +437,7 @@ enum ChatCommand: ChatCmdProtocol {
case .apiSetUserContactReceipts: return "apiSetUserContactReceipts"
case .apiSetUserGroupReceipts: return "apiSetUserGroupReceipts"
case .apiSetUserAutoAcceptMemberContacts: return "apiSetUserAutoAcceptMemberContacts"
case .apiSetUserAutoAcceptGroupInvitations: return "apiSetUserAutoAcceptGroupInvitations"
case .apiHideUser: return "apiHideUser"
case .apiUnhideUser: return "apiUnhideUser"
case .apiMuteUser: return "apiMuteUser"
+4
View File
@@ -302,6 +302,10 @@ func apiSetUserAutoAcceptMemberContacts(_ userId: Int64, enable: Bool) async thr
try await sendCommandOkResp(.apiSetUserAutoAcceptMemberContacts(userId: userId, enable: enable))
}
func apiSetUserAutoAcceptGroupInvitations(_ userId: Int64, enable: Bool) async throws {
try await sendCommandOkResp(.apiSetUserAutoAcceptGroupInvitations(userId: userId, enable: enable))
}
func apiHideUser(_ userId: Int64, viewPwd: String) async throws -> User {
try await setUserPrivacy_(.apiHideUser(userId: userId, viewPwd: viewPwd))
}
@@ -75,7 +75,35 @@ struct FramedItemView: View {
}
})
} else if let itemForwarded = chatItem.meta.itemForwarded {
framedItemHeader(icon: "arrowshape.turn.up.forward", caption: Text(itemForwarded.text(chat.chatInfo.chatType)).italic(), pad: true)
let twoRowHeader: Bool = if chat.chatInfo.chatType == .local {
itemForwarded.chatTypeApiIdMsgId != nil || itemForwarded.sourceGroupLink != nil
} else {
switch itemForwarded {
case let .group(_, _, _, _, _, _, groupType): groupType != nil
case .groupLink: true
default: false
}
}
if twoRowHeader {
let caption: LocalizedStringKey = chat.chatInfo.chatType == .local ? "saved from" : "forwarded from"
headerFrame(pad: true) {
VStack(alignment: .leading, spacing: 4) {
headerRow(icon: "arrowshape.turn.up.forward", caption: Text(caption).italic())
Text(itemForwarded.chatName)
.font(.subheadline)
.lineLimit(1)
}
}
.simultaneousGesture(TapGesture().onEnded {
if let (chatType, apiId, msgId) = itemForwarded.chatTypeApiIdMsgId {
im.loadOpenChatNoWait("\(chatType.rawValue)\(apiId)", msgId)
} else if let link = itemForwarded.sourceGroupLink {
planAndConnect(link, theme: theme, dismiss: false)
}
})
} else {
framedItemHeader(icon: "arrowshape.turn.up.forward", caption: Text(itemForwarded.text(chat.chatInfo.chatType)).italic(), pad: true)
}
}
ChatItemContentView(chat: chat, im: im, chatItem: chatItem, msgContentView: framedMsgContentView)
@@ -191,8 +219,14 @@ struct FramedItemView: View {
}
}
@ViewBuilder func framedItemHeader(icon: String? = nil, iconColor: Color? = nil, caption: Text, pad: Bool = false) -> some View {
let v = HStack(spacing: 6) {
func framedItemHeader(icon: String? = nil, iconColor: Color? = nil, caption: Text, pad: Bool = false) -> some View {
headerFrame(pad: pad) {
headerRow(icon: icon, iconColor: iconColor, caption: caption)
}
}
private func headerRow(icon: String?, iconColor: Color? = nil, caption: Text) -> some View {
HStack(spacing: 6) {
if let icon = icon {
Image(systemName: icon)
.resizable()
@@ -204,13 +238,17 @@ struct FramedItemView: View {
.font(.caption)
.lineLimit(1)
}
.foregroundColor(theme.colors.secondary)
.padding(.horizontal, 12)
.padding(.top, 6)
.padding(.bottom, pad || (chatItem.quotedItem == nil && chatItem.meta.itemForwarded == nil) ? 6 : 0)
.overlay(DetermineWidth())
.frame(minWidth: msgWidth, alignment: .leading)
.background(chatItemFrameContextColor(chatItem, theme))
}
@ViewBuilder private func headerFrame(pad: Bool = false, @ViewBuilder _ content: () -> some View) -> some View {
let v = content()
.foregroundColor(theme.colors.secondary)
.padding(.horizontal, 12)
.padding(.top, 6)
.padding(.bottom, pad || (chatItem.quotedItem == nil && chatItem.meta.itemForwarded == nil) ? 6 : 0)
.overlay(DetermineWidth())
.frame(minWidth: msgWidth, alignment: .leading)
.background(chatItemFrameContextColor(chatItem, theme))
if let mediaWidth = maxMediaWidth(), mediaWidth < maxWidth {
v.frame(maxWidth: mediaWidth, alignment: .leading)
} else {
@@ -142,6 +142,7 @@ class OpenChatAlertViewController: UIViewController {
private let profileBadge: LocalBadge?
private let subtitle: String?
private let information: String?
private let secondaryInformation: Bool
private let cancelTitle: String
private let confirmTitle: String?
private let secondTitle: String?
@@ -156,6 +157,7 @@ class OpenChatAlertViewController: UIViewController {
profileBadge: LocalBadge? = nil,
subtitle: String? = nil,
information: String? = nil,
secondaryInformation: Bool = false,
cancelTitle: String = "Cancel",
confirmTitle: String? = "Open",
secondTitle: String? = nil,
@@ -169,6 +171,7 @@ class OpenChatAlertViewController: UIViewController {
self.profileBadge = profileBadge
self.subtitle = subtitle
self.information = information
self.secondaryInformation = secondaryInformation
self.cancelTitle = cancelTitle
self.confirmTitle = confirmTitle
self.secondTitle = secondTitle
@@ -248,7 +251,7 @@ class OpenChatAlertViewController: UIViewController {
let infoLabel = UILabel()
infoLabel.text = information
infoLabel.font = UIFont.preferredFont(forTextStyle: .footnote)
infoLabel.textColor = .label
infoLabel.textColor = secondaryInformation ? .secondaryLabel : .label
infoLabel.numberOfLines = 3
infoLabel.textAlignment = .center
infoLabel.translatesAutoresizingMaskIntoConstraints = false
@@ -426,6 +429,7 @@ func showOpenChatAlert<Content: View>(
theme: AppTheme,
subtitle: String? = nil,
information: String? = nil,
secondaryInformation: Bool = false,
cancelTitle: String = "Cancel",
confirmTitle: String? = "Open",
secondTitle: String? = nil,
@@ -446,6 +450,7 @@ func showOpenChatAlert<Content: View>(
profileBadge: profileBadge,
subtitle: subtitle,
information: information,
secondaryInformation: secondaryInformation,
cancelTitle: cancelTitle,
confirmTitle: confirmTitle,
secondTitle: secondTitle,
+24 -12
View File
@@ -859,8 +859,8 @@ enum ConnectTarget {
func strConnectTarget(_ str: String) -> ConnectTarget? {
let parsedMd = parseSimpleXMarkdown(str)
let links = parsedMd?.filter { $0.format?.isSimplexLink ?? false } ?? []
return if links.count == 1, case let .simplexLink(_, linkType, _, smpHosts) = links[0].format {
.link(text: links[0].text, linkType: linkType, linkText: simplexLinkText(linkType, smpHosts))
return if links.count == 1, case let .simplexLink(showText, linkType, simplexUri, smpHosts) = links[0].format {
.link(text: showText != nil ? simplexUri : links[0].text, linkType: linkType, linkText: simplexLinkText(linkType, smpHosts))
} else if links.isEmpty,
let nameFt = parsedMd?.first(where: { if case .simplexName = $0.format { true } else { false } }),
case let .simplexName(nameInfo) = nameFt.format {
@@ -1195,8 +1195,8 @@ private func showPrepareGroupAlert(
information: ownerVerificationMessage(ownerVerification),
cancelTitle: NSLocalizedString("Cancel", comment: "new chat action"),
confirmTitle: isChannel
? NSLocalizedString("Open new channel", comment: "new chat action")
: NSLocalizedString("Open new group", comment: "new chat action"),
? NSLocalizedString("Open channel", comment: "new chat action")
: NSLocalizedString("Open group", comment: "new chat action"),
secondTitle: connectOtherButton,
onCancel: { cleanup?() },
onConfirm: {
@@ -1259,6 +1259,20 @@ private func showOpenKnownContactAlert(
)
}
private func memberRoleInformation(_ role: GroupMemberRole, isChannel: Bool) -> String {
switch role {
case .observer: isChannel
? NSLocalizedString("You are a subscriber", comment: "new chat alert")
: NSLocalizedString("You are an observer", comment: "new chat alert")
case .moderator: NSLocalizedString("You are a moderator", comment: "new chat alert")
case .admin: NSLocalizedString("You are an admin", comment: "new chat alert")
case .owner: NSLocalizedString("You are an owner", comment: "new chat alert")
default: isChannel
? NSLocalizedString("You are a contributor", comment: "new chat alert")
: NSLocalizedString("You are a member", comment: "new chat alert")
}
}
private func showOpenKnownGroupAlert(
_ groupInfo: GroupInfo,
theme: AppTheme,
@@ -1278,18 +1292,16 @@ private func showOpenKnownGroupAlert(
),
theme: theme,
subtitle: groupInfo.useRelays ? subscriberCount : nil,
information: groupInfo.nextConnectPrepared || groupInfo.businessChat != nil
? nil
: memberRoleInformation(groupInfo.membership.memberRole, isChannel: groupInfo.useRelays),
secondaryInformation: true,
cancelTitle: NSLocalizedString("Cancel", comment: "new chat action"),
confirmTitle:
groupInfo.useRelays
? ( groupInfo.nextConnectPrepared
? NSLocalizedString("Open new channel", comment: "new chat action")
: NSLocalizedString("Open channel", comment: "new chat action")
)
? NSLocalizedString("Open channel", comment: "new chat action")
: groupInfo.businessChat == nil
? ( groupInfo.nextConnectPrepared
? NSLocalizedString("Open new group", comment: "new chat action")
: NSLocalizedString("Open group", comment: "new chat action")
)
? NSLocalizedString("Open group", comment: "new chat action")
: ( groupInfo.nextConnectPrepared
? NSLocalizedString("Open new chat", comment: "new chat action")
: NSLocalizedString("Open chat", comment: "new chat action")
@@ -8,6 +8,7 @@
// Spec: spec/client/navigation.md
import SwiftUI
import StoreKit
import SimpleXChat
private struct VersionDescription {
@@ -41,6 +42,11 @@ private struct FeatureView {
let view: () -> any View
}
let isInUS = {
let code = SKStorefront().countryCode
return code == "USA" || code == ""
}()
private let versionDescriptions: [VersionDescription] = [
VersionDescription(
version: "v4.2",
@@ -665,9 +671,15 @@ private let versionDescriptions: [VersionDescription] = [
]
),
VersionDescription(
version: "v7.0",
post: nil,
features: [
version: isInUS ? "v7.0.1" : "v7.0",
post: URL(string: "https://simplex.chat/blog/20260819-simplex-chat-crowdfunding.html"),
features: (isInUS ? [
.view(FeatureView(
icon: nil,
title: "You can now invest in SimpleX Chat",
view: { InvestInSimpleXChat() }
))
] : []) + [
.feature(Description(
icon: "at",
title: "SimpleX public names (BETA)",
@@ -762,6 +774,134 @@ fileprivate struct CreateUpdateAddressShortLink: View {
}
}
fileprivate struct InvestInSimpleXChat: View {
@EnvironmentObject var theme: AppTheme
@State private var showGetStakeSheet = false
var body: some View {
VStack(alignment: .leading, spacing: 4) {
Text("You can now invest in SimpleX Chat! 🚀").font(.title3).bold()
(Text("Crowdfunding on Wefunder.") + Text(verbatim: " ") + Text("Learn more").foregroundColor(theme.colors.primary))
.multilineTextAlignment(.leading)
.onTapGesture { showGetStakeSheet = true }
#if SIMPLEX_ASSETS
Image("crowdfunding_1")
.resizable()
.scaledToFit()
.cornerRadius(12)
.padding(.vertical, 4)
.onTapGesture { showGetStakeSheet = true }
#endif
}
.frame(maxWidth: .infinity, alignment: .leading)
.sheet(isPresented: $showGetStakeSheet) {
GetStakeView(fromSettings: false)
}
}
}
fileprivate let getStakeSlides: [(image: String, heading: String, info: String?, text: String)] = [
(
"crowdfunding_1",
"The first and the only messaging network without any user IDs",
nil,
"By investing, you can benefit from the company growth, and help us build the future of private and secure communications."
),
(
"crowdfunding_2",
"480,000+ users joined on their own",
nil,
"SimpleX users have been more than doubling every year without any paid marketing, and donated over $650,000."
),
(
"crowdfunding_3",
"Developers already bet on SimpleX success",
"Independent developers created moderation and AI bots, Telegram bridges, and a public server registry.",
"Every service developers build on SimpleX Network may increase its value, and bring new users to SimpleX Chat."
),
(
"crowdfunding_4",
"Revenue plan: free for users, channels & businesses pay",
"SimpleX Chat plans to earn from the infrastructure and services that creators, businesses and large communities need as they grow.",
"Read about how we plan to make SimpleX Chat and network profitable, and about all the investment terms on Wefunder."
),
]
private let wefunderURL = URL(string: "https://wefunder.com/simplex.chat?utm_source=app")!
private let simplexCrowdfundingURL = URL(string: "simplex:/a#JxGcOA1_QhlmVFzYYabloMbvMZk5Y9d9iS3ITDnhzYo?h=smp11.simplex.im")!
struct GetStakeView: View {
@Environment(\.dismiss) var dismiss: DismissAction
@EnvironmentObject var chatModel: ChatModel
var fromSettings: Bool
var body: some View {
ZoomablePageView {
VStack(alignment: .leading, spacing: 18) {
Text(verbatim: "Get a stake in\nSimpleX Chat")
.font(.largeTitle)
.bold()
.fixedSize(horizontal: false, vertical: true)
.if(!fromSettings) { $0.padding(.top) }
if fromSettings {
slideImage(getStakeSlides[0])
}
(Text(verbatim: getStakeSlides[0].text) + Text(verbatim: " Learn more and invest on Wefunder.").bold().foregroundColor(.accentColor))
.multilineTextAlignment(.leading)
.onTapGesture {
UIApplication.shared.open(wefunderURL)
}
.padding(.bottom)
ForEach(getStakeSlides[1...3], id: \.image) { slide in
VStack(alignment: .leading) {
slideImage(slide)
Text(slide.text)
}
.padding(.bottom)
}
Button {
UIApplication.shared.open(wefunderURL)
} label: {
Text(verbatim: "Learn more on Wefunder")
}
.buttonStyle(OnboardingButtonStyle())
Button {
dismiss()
DispatchQueue.main.async {
ChatModel.shared.appOpenUrl = simplexCrowdfundingURL
}
} label: {
Text(verbatim: "or ask SimpleX team")
.font(.callout)
}
.disabled(chatModel.chatRunning != true)
.frame(maxWidth: .infinity)
}
.padding()
}
.ignoresSafeArea(edges: .bottom)
.modifier(ThemedBackground(grouped: true))
}
@ViewBuilder
func slideImage(_ slide: (image: String, heading: String, info: String?, text: String?)) -> some View {
#if SIMPLEX_ASSETS
Image(slide.image)
.resizable()
.scaledToFit()
.cornerRadius(12)
#else
Text(slide.heading).font(.title3).bold()
if let info = slide.info {
Text(info)
}
#endif
}
}
private enum WhatsNewViewSheet: Identifiable {
case showConditions
@@ -37,6 +37,8 @@ struct PrivacySettings: View {
@State private var groupReceiptsDialogue = false
@State private var autoAcceptMemberContacts = false
@State private var autoAcceptMemberContactsReset = false
@State private var autoAcceptGroupInvitations = false
@State private var autoAcceptGroupInvitationsReset = false
@State private var alert: PrivacySettingsViewAlert?
enum PrivacySettingsViewAlert: Identifiable {
@@ -117,14 +119,17 @@ struct PrivacySettings: View {
}
Section {
settingsRow("checkmark", color: theme.colors.secondary) {
Toggle("Auto-accept", isOn: $autoAcceptMemberContacts)
settingsRow("person", color: theme.colors.secondary) {
Toggle("Contact requests in groups", isOn: $autoAcceptMemberContacts)
}
settingsRow("person.2", color: theme.colors.secondary) {
Toggle("Group invitations", isOn: $autoAcceptGroupInvitations)
}
} header: {
Text("Contact requests from groups")
Text("Auto-accept")
.foregroundColor(theme.colors.secondary)
} footer: {
Text("This setting is for your current profile **\(m.currentUser?.displayName ?? "")**.")
Text("These settings are for your current profile **\(m.currentUser?.displayName ?? "")**.")
.foregroundColor(theme.colors.secondary)
}
@@ -139,7 +144,14 @@ struct PrivacySettings: View {
if autoAcceptMemberContactsReset {
autoAcceptMemberContactsReset = false
} else {
setAutoAcceptGrpDirectInvs(autoAcceptMemberContacts)
setAutoAcceptMemberContacts(autoAcceptMemberContacts)
}
}
.onChange(of: autoAcceptGroupInvitations) { _ in
if autoAcceptGroupInvitationsReset {
autoAcceptGroupInvitationsReset = false
} else {
setAutoAcceptGroupInvitations(autoAcceptGroupInvitations)
}
}
.onAppear {
@@ -148,6 +160,10 @@ struct PrivacySettings: View {
autoAcceptMemberContactsReset = true
autoAcceptMemberContacts = u.autoAcceptMemberContacts
}
if autoAcceptGroupInvitations != u.autoAcceptGroupInvitations {
autoAcceptGroupInvitationsReset = true
autoAcceptGroupInvitations = u.autoAcceptGroupInvitations
}
}
}
.alert(item: $alert) { alert in
@@ -426,7 +442,7 @@ struct PrivacySettings: View {
}
}
private func setAutoAcceptGrpDirectInvs(_ enable: Bool) {
private func setAutoAcceptMemberContacts(_ enable: Bool) {
Task {
do {
if let currentUser = m.currentUser {
@@ -443,6 +459,23 @@ struct PrivacySettings: View {
}
}
private func setAutoAcceptGroupInvitations(_ enable: Bool) {
Task {
do {
if let currentUser = m.currentUser {
try await apiSetUserAutoAcceptGroupInvitations(currentUser.userId, enable: enable)
await MainActor.run {
var updatedUser = currentUser
updatedUser.autoAcceptGroupInvitations = enable
m.updateUser(updatedUser)
}
}
} catch let error {
alert = .error(title: "Error setting auto-accept", error: "Error: \(responseError(error))")
}
}
}
private func simplexLockRow(_ value: LocalizedStringKey) -> some View {
HStack {
Text("SimpleX Lock")
@@ -383,6 +383,17 @@ struct SettingsView: View {
Text(verbatim: "v\(appVersion ?? "?")")
}
}
if isInUS {
Section(header: Text("You can now invest in SimpleX Chat").foregroundColor(theme.colors.secondary)) {
NavigationLink {
GetStakeView(fromSettings: true)
.navigationBarTitle("", displayMode: .inline)
} label: {
settingsRow("dollarsign.circle", color: theme.colors.secondary) { Text("Crowdfunding on Wefunder") }
}
}
}
}
.navigationTitle("Your settings")
.modifier(ThemedBackground(grouped: true))
@@ -58,3 +58,54 @@ struct ZoomableScrollView<Content: View>: UIViewRepresentable {
}
}
}
struct ZoomablePageView<Content: View>: UIViewRepresentable {
private var content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
func makeUIView(context: Context) -> UIScrollView {
let scrollView = UIScrollView()
scrollView.delegate = context.coordinator
scrollView.maximumZoomScale = 5
scrollView.minimumZoomScale = 1
scrollView.bouncesZoom = true
scrollView.backgroundColor = .clear
let hostedView = context.coordinator.hostingController.view!
hostedView.backgroundColor = .clear
hostedView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(hostedView)
NSLayoutConstraint.activate([
hostedView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
hostedView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
hostedView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
hostedView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
hostedView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor)
])
return scrollView
}
func makeCoordinator() -> Coordinator {
Coordinator(hostingController: UIHostingController(rootView: self.content))
}
func updateUIView(_ uiView: UIScrollView, context: Context) {
context.coordinator.hostingController.rootView = self.content
}
class Coordinator: NSObject, UIScrollViewDelegate {
var hostingController: UIHostingController<Content>
init(hostingController: UIHostingController<Content>) {
self.hostingController = hostingController
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
hostingController.view
}
}
}
@@ -2429,8 +2429,8 @@ This is your own one-time link!</source>
<target>Настройки за контакт</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact will be deleted - this cannot be undone!" xml:space="preserve">
@@ -2603,6 +2603,14 @@ This is your own one-time link!</source>
<target>Линкът се създава…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>Текущ kод за достъп</target>
@@ -4500,6 +4508,10 @@ Error: %2$@</source>
<target>Груповата покана вече е невалидна, премахната е от подателя.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Групов линк</target>
@@ -8989,10 +9001,6 @@ alert subtitle</note>
<target>Тази настройка се прилага за съобщения в текущия ви профил **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<note>No comment provided by engineer.</note>
@@ -9938,6 +9946,14 @@ Repeat join request?</source>
<target>Вече можете да изпращате съобщения до %@</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<note>No comment provided by engineer.</note>
@@ -2333,8 +2333,8 @@ Toto je váš vlastní jednorázový odkaz!</target>
<target>Předvolby kontaktů</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact will be deleted - this cannot be undone!" xml:space="preserve">
@@ -2499,6 +2499,14 @@ Toto je váš vlastní jednorázový odkaz!</target>
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>Aktuální heslo</target>
@@ -4352,6 +4360,10 @@ Error: %2$@</source>
<target>Skupinová pozvánka již není platná, byla odstraněna odesílatelem.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Odkaz na skupinu</target>
@@ -8748,10 +8760,6 @@ alert subtitle</note>
<target>Toto nastavení platí pro zprávy ve vašem aktuálním profilu chatu **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<note>No comment provided by engineer.</note>
@@ -9655,6 +9663,14 @@ Repeat join request?</source>
<target>Nyní můžete posílat zprávy %@</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<note>No comment provided by engineer.</note>
@@ -2427,7 +2427,7 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit>
<trans-unit id="Connection link removed" xml:space="preserve">
<source>Connection link removed</source>
<target>Verbindungsfehler</target>
<target>Verbindungslink entfernt</target>
<note>conn error description</note>
</trans-unit>
<trans-unit id="Connection not ready." xml:space="preserve">
@@ -2525,8 +2525,8 @@ Das ist Ihr eigener Einmal-Link!</target>
<target>Kontakt-Präferenzen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<target>KONTAKTANFRAGEN VON GRUPPEN</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -2715,6 +2715,14 @@ Das ist Ihr eigener Einmal-Link!</target>
<target>Link wird erstellt…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>Aktueller Zugangscode</target>
@@ -4697,7 +4705,7 @@ Fehler: %2$@</target>
</trans-unit>
<trans-unit id="Get SimpleX name (BETA)" xml:space="preserve">
<source>Get SimpleX name (BETA)</source>
<target>SimpleX-Name erhalten (BETA)</target>
<target>Einen SimpleX-Namen erhalten (BETA)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Get link" xml:space="preserve">
@@ -4770,6 +4778,10 @@ Fehler: %2$@</target>
<target>Die Gruppeneinladung ist nicht mehr gültig, da sie vom Absender entfernt wurde.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Gruppen-Link</target>
@@ -6423,7 +6435,7 @@ Die sicherste Verschlüsselung.</target>
</trans-unit>
<trans-unit id="Nobody tracked your conversations. No one drew a map of where you'd been. Privacy was never a feature - it was the way of life." xml:space="preserve">
<source>Nobody tracked your conversations. No one drew a map of where you'd been. Privacy was never a feature - it was the way of life.</source>
<target>Niemand verfolgte Ihre Gespräche. Niemand erstellte eine Karte, wo Sie sich aufgehalten haben. Privatsphäre war nie ein Feature - sie war selbstverständlich.</target>
<target>Niemand verfolgte Ihre Gespräche. Niemand hat eine Karte erstellt, wo Sie überall waren. Privatsphäre war nie ein Feature sie war eine Selbstverständlichkeit.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Non-profit governance" xml:space="preserve">
@@ -7876,12 +7888,12 @@ swipe action</note>
</trans-unit>
<trans-unit id="Role will be changed to &quot;%@&quot;. All chat members will be notified." xml:space="preserve">
<source>Role will be changed to "%@". All chat members will be notified.</source>
<target>Die Rolle des Mitglieds wird auf "%@" geändert. Alle Chat-Mitglieder werden darüber informiert.</target>
<target>Die Rolle wird auf "%@" geändert. Alle Chat-Mitglieder werden darüber informiert.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Role will be changed to &quot;%@&quot;. All group members will be notified." xml:space="preserve">
<source>Role will be changed to "%@". All group members will be notified.</source>
<target>Die Mitgliederrolle wird auf "%@" geändert. Alle Gruppenmitglieder werden benachrichtigt.</target>
<target>Die Rolle wird auf "%@" geändert. Alle Gruppenmitglieder werden benachrichtigt.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Role will be changed to &quot;%@&quot;. All subscribers will be notified." xml:space="preserve">
@@ -7891,7 +7903,7 @@ swipe action</note>
</trans-unit>
<trans-unit id="Role will be changed to &quot;%@&quot;. The member will receive a new invitation." xml:space="preserve">
<source>Role will be changed to "%@". The member will receive a new invitation.</source>
<target>Die Mitgliederrolle wird auf "%@" geändert. Das Mitglied wird eine neue Einladung erhalten.</target>
<target>Die Rolle wird auf "%@" geändert. Das Mitglied wird eine neue Einladung erhalten.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Run chat" xml:space="preserve">
@@ -9428,7 +9440,7 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
</trans-unit>
<trans-unit id="The SimpleX name %@ is registered, but not added to profile. Please add it to your address or channel profile, if you are the owner." xml:space="preserve">
<source>The SimpleX name %@ is registered, but not added to profile. Please add it to your address or channel profile, if you are the owner.</source>
<target>Der SimpleXName %@ wurde registriert, jedoch nicht in Ihrem Profil hinterlegt. Bitte zu Ihrer Adresse oder zum Kanalprofil hinzufügen, sofern Sie der Besitzer sind.</target>
<target>Der SimpleXName %@ wurde registriert, jedoch nicht in Ihrem Profil hinterlegt. Bitte fügen Sie ihn zu Ihrer Adresse oder zum Kanalprofil hinzu, sofern Sie der Besitzer sind.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The SimpleX name @%@ is registered without SimpleX address. Add your SimpleX address to the name via the registration page." xml:space="preserve">
@@ -9575,7 +9587,7 @@ in dem Sie Ihre Kontakte und Gruppen besitzen.</target>
</trans-unit>
<trans-unit id="The sender deleted the connection request." xml:space="preserve">
<source>The sender deleted the connection request.</source>
<target>Der Absender hat möglicherweise die Verbindungsanfrage gelöscht.</target>
<target>Der Absender hat die Verbindungsanfrage gelöscht.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The sender will NOT be notified" xml:space="preserve">
@@ -9734,11 +9746,6 @@ alert subtitle</note>
<target>Diese Einstellung gilt für Nachrichten in Ihrem aktuellen Chat-Profil **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<target>Diese Einstellung gilt für Ihr aktuelles Profil **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<target>Die Zeit bis zum Verschwinden wird nur für neue Kontakte eingestellt.</target>
@@ -10769,6 +10776,14 @@ Verbindungsanfrage wiederholen?</target>
<target>Sie können nun Nachrichten an %@ versenden</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<target>Sie können aus den archivierten Kontakten heraus Nachrichten an %@ versenden.</target>
@@ -11058,8 +11073,8 @@ Verbindungsanfrage wiederholen?</target>
<trans-unit id="Your contact removed this link, or it was a one-time link that was already used.&#10;To connect, ask your contact to create a new link." xml:space="preserve">
<source>Your contact removed this link, or it was a one-time link that was already used.
To connect, ask your contact to create a new link.</source>
<target>Entweder hat Ihr Kontakt die Verbindung gelöscht, oder dieser Link wurde bereits verwendet, es könnte sich um einen Fehler handeln - Bitte melden Sie es uns.
Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um sich neu verbinden zu können und stellen Sie sicher, dass Sie eine stabile Netzwerk-Verbindung haben.</target>
<target>Ihr Kontakt hat diesen Link entfernt oder es war ein EinmalLink, welcher bereits verwendet wurde.
Um sich zu verbinden, bitten Sie Ihren Kontakt, einen neuen Link zu erstellen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contact sent a file that is larger than currently supported maximum size (%@)." xml:space="preserve">
@@ -2525,9 +2525,9 @@ This is your own one-time link!</target>
<target>Contact preferences</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<target>Contact requests from groups</target>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<target>Contact requests in groups</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact will be deleted - this cannot be undone!" xml:space="preserve">
@@ -2715,6 +2715,16 @@ This is your own one-time link!</target>
<target>Creating link…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<target>Crowdfunding on Wefunder</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<target>Crowdfunding on Wefunder.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>Current Passcode</target>
@@ -4770,6 +4780,11 @@ Error: %2$@</target>
<target>Group invitation is no longer valid, it was removed by sender.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<target>Group invitations</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Group link</target>
@@ -9734,11 +9749,6 @@ alert subtitle</note>
<target>This setting applies to messages in your current chat profile **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<target>This setting is for your current profile **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<target>Time to disappear is set only for new contacts.</target>
@@ -10769,6 +10779,16 @@ Repeat join request?</target>
<target>You can now chat with %@</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<target>You can now invest in SimpleX Chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<target>You can now invest in SimpleX Chat! 🚀</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<target>You can send messages to %@ from Archived contacts.</target>
@@ -2525,8 +2525,8 @@ This is your own one-time link!</source>
<target>Preferencias de contacto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<target>Solicitudes de contacto en grupo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -2715,6 +2715,14 @@ This is your own one-time link!</source>
<target>Creando enlace…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>Código de Acceso</target>
@@ -4770,6 +4778,10 @@ Error: %2$@</target>
<target>La invitación al grupo ya no es válida, ha sido eliminada por el remitente.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Enlace de grupo</target>
@@ -9734,11 +9746,6 @@ alert subtitle</note>
<target>Esta configuración se aplica a los mensajes del perfil actual **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<target>Esta configuración se aplica al perfil actual **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<target>Mensajes temporales activados sólo para los contactos nuevos.</target>
@@ -10769,6 +10776,14 @@ Repeat join request?</source>
<target>Ya puedes chatear con %@</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<target>Puedes enviar mensajes a %@ desde Contactos archivados.</target>
@@ -2220,8 +2220,8 @@ This is your own one-time link!</source>
<target>Kontaktin asetukset</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact will be deleted - this cannot be undone!" xml:space="preserve">
@@ -2386,6 +2386,14 @@ This is your own one-time link!</source>
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>Nykyinen pääsykoodi</target>
@@ -4236,6 +4244,10 @@ Error: %2$@</source>
<target>Ryhmäkutsu ei ole enää voimassa, lähettäjä poisti sen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Ryhmälinkki</target>
@@ -8623,10 +8635,6 @@ alert subtitle</note>
<target>Tämä asetus koskee nykyisen keskusteluprofiilisi viestejä *%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<note>No comment provided by engineer.</note>
@@ -9529,6 +9537,14 @@ Repeat join request?</source>
<target>Voit nyt lähettää viestejä %@:lle</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<note>No comment provided by engineer.</note>
File diff suppressed because it is too large Load Diff
@@ -2525,8 +2525,8 @@ Ez a saját egyszer használható meghívója!</target>
<target>Partnerbeállítások</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<target>Partneri kapcsolatkérések a csoportokból</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -2715,6 +2715,14 @@ Ez a saját egyszer használható meghívója!</target>
<target>Hivatkozás létrehozása…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>Jelenlegi jelkód</target>
@@ -4770,6 +4778,10 @@ Hiba: %2$@</target>
<target>A csoportmeghívó már nem érvényes, a küldője eltávolította.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Csoporthivatkozás</target>
@@ -9734,11 +9746,6 @@ alert subtitle</note>
<target>Ez a beállítás csak az Ön jelenlegi **%@** nevű csevegési profiljában lévő üzenetekre vonatkozik.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<target>Ez a beállítás csak a jelenlegi **%@** nevű csevegési profiljára vonatkozik.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<target>Az üzeneteltűnési idő csak az új partnerekre vonatkozik.</target>
@@ -10769,6 +10776,14 @@ Megismétli a csatlakozási kérést?</target>
<target>Mostantól küldhet üzeneteket %@ számára</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<target>Az „Archivált partnerekből” továbbra is küldhet üzeneteket neki: %@.</target>
@@ -2525,8 +2525,8 @@ Questo è il tuo link una tantum!</target>
<target>Preferenze del contatto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<target>Richieste di contatto dai gruppi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -2715,6 +2715,14 @@ Questo è il tuo link una tantum!</target>
<target>Creazione link…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>Codice di accesso attuale</target>
@@ -4770,6 +4778,10 @@ Errore: %2$@</target>
<target>L'invito al gruppo non è più valido, è stato rimosso dal mittente.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Link del gruppo</target>
@@ -9734,11 +9746,6 @@ alert subtitle</note>
<target>Questa impostazione si applica ai messaggi del profilo di chat attuale **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<target>Questa impostazione è per il tuo profilo attuale **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<target>Il tempo di scomparsa è impostato solo per i contatti nuovi.</target>
@@ -10769,6 +10776,14 @@ Ripetere la richiesta di ingresso?</target>
<target>Ora puoi inviare messaggi a %@</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<target>Puoi inviare messaggi a %@ dai contatti archiviati.</target>
@@ -2325,8 +2325,8 @@ This is your own one-time link!</source>
<target>連絡先の設定</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact will be deleted - this cannot be undone!" xml:space="preserve">
@@ -2491,6 +2491,14 @@ This is your own one-time link!</source>
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>現在のパスコード</target>
@@ -4353,6 +4361,10 @@ Error: %2$@</source>
<target>グループ招待が無効となり、送信元によって取り消されました。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>グループのリンク</target>
@@ -8736,10 +8748,6 @@ alert subtitle</note>
<target>この設定は現在のチャットプロフィール **%@** のメッセージに適用されます。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<note>No comment provided by engineer.</note>
@@ -9643,6 +9651,14 @@ Repeat join request?</source>
<target>%@ にメッセージを送信できるようになりました</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<note>No comment provided by engineer.</note>
@@ -2422,8 +2422,8 @@ Dit is uw eigen eenmalige link!</target>
<target>Contact voorkeuren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact will be deleted - this cannot be undone!" xml:space="preserve">
@@ -2603,6 +2603,14 @@ Dit is uw eigen eenmalige link!</target>
<target>Link maken…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>Huidige toegangscode</target>
@@ -4605,6 +4613,10 @@ Fout: %2$@</target>
<target>Groep uitnodiging is niet meer geldig, deze is verwijderd door de afzender.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Groep link</target>
@@ -9353,10 +9365,6 @@ alert subtitle</note>
<target>Deze instelling is van toepassing op berichten in je huidige chatprofiel **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<note>No comment provided by engineer.</note>
@@ -10349,6 +10357,14 @@ Deelnameverzoek herhalen?</target>
<target>Je kunt nu berichten sturen naar %@</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<target>U kunt berichten naar %@ sturen vanuit gearchiveerde contacten.</target>
@@ -2439,8 +2439,8 @@ To jest twój jednorazowy link!</target>
<target>Preferencje kontaktu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<target>Prośby o kontakt od grup</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -2622,6 +2622,14 @@ To jest twój jednorazowy link!</target>
<target>Tworzenie linku…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>Aktualny Pin</target>
@@ -4641,6 +4649,10 @@ Błąd: %2$@</target>
<target>Zaproszenie do grupy jest już nieważne, zostało usunięte przez nadawcę.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Link do grupy</target>
@@ -9449,11 +9461,6 @@ alert subtitle</note>
<target>To ustawienie dotyczy wiadomości Twojego bieżącego profilu czatu **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<target>To ustawienie jest dla Twojego obecnego profilu **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<target>Czas zniknięcia jest ustawiony tylko dla nowych kontaktów.</target>
@@ -10461,6 +10468,14 @@ Powtórzyć prośbę dołączenia?</target>
<target>Możesz teraz wysyłać wiadomości do %@</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<target>Możesz wysyłać wiadomości do %@ ze zarchiwizowanych kontaktów.</target>
@@ -2525,8 +2525,8 @@ This is your own one-time link!</source>
<target>Предпочтения контакта</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<target>Запросы на соединение из групп</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -2715,6 +2715,14 @@ This is your own one-time link!</source>
<target>Создаётся ссылка…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>Текущий Код</target>
@@ -4770,6 +4778,10 @@ Error: %2$@</source>
<target>Приглашение в группу больше не действительно, оно было удалено отправителем.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Ссылка группы</target>
@@ -9733,11 +9745,6 @@ alert subtitle</note>
<target>Эта настройка применяется к сообщениям в Вашем текущем профиле чата **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<target>Эта настройка применяется к Вашему текущему профилю чата **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<target>Время удаления устанавливается только для новых контактов.</target>
@@ -10768,6 +10775,14 @@ Repeat join request?</source>
<target>Вы теперь можете общаться с %@</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<target>Вы можете отправлять сообщения %@ из Архивированных контактов.</target>
@@ -2211,8 +2211,8 @@ This is your own one-time link!</source>
<target>การกําหนดลักษณะการติดต่อ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact will be deleted - this cannot be undone!" xml:space="preserve">
@@ -2375,6 +2375,14 @@ This is your own one-time link!</source>
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>รหัสผ่านปัจจุบัน</target>
@@ -4221,6 +4229,10 @@ Error: %2$@</source>
<target>คำเชิญเข้าร่วมกลุ่มใช้ไม่ถูกต้องอีกต่อไป คำเชิญถูกลบโดยผู้ส่ง</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>ลิงค์กลุ่ม</target>
@@ -8593,10 +8605,6 @@ alert subtitle</note>
<target>การตั้งค่านี้ใช้กับข้อความในโปรไฟล์แชทปัจจุบันของคุณ **%@**</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<note>No comment provided by engineer.</note>
@@ -9497,6 +9505,14 @@ Repeat join request?</source>
<target>ตอนนี้คุณสามารถส่งข้อความถึง %@</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<note>No comment provided by engineer.</note>
@@ -2450,8 +2450,8 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
<target>Kişi tercihleri</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<target>Gruplardan gelen iletişim talepleri</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -2633,6 +2633,14 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
<target>Link oluşturuluyor…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>Şu anki şifre</target>
@@ -4644,6 +4652,10 @@ Hata: %2$@</target>
<target>Grup davet artık geçerli değil, gönderici tarafından silindi.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Grup bağlantısı</target>
@@ -9436,11 +9448,6 @@ alert subtitle</note>
<target>Bu ayar, geçerli sohbet profiliniz **%@** deki mesajlara uygulanır.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<target>Bu ayar, mevcut profiliniz içindir.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<target>Kaybolma süresi yalnızca yeni kişiler için ayarlanır.</target>
@@ -10444,6 +10451,14 @@ Katılma isteği tekrarlansın mı?</target>
<target>Artık %@ adresine mesaj gönderebilirsin</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<target>Arşivlenen kişilerden %@'ya mesaj gönderebilirsiniz.</target>
@@ -2472,8 +2472,8 @@ This is your own one-time link!</source>
<target>Налаштування контактів</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact will be deleted - this cannot be undone!" xml:space="preserve">
@@ -2654,6 +2654,14 @@ This is your own one-time link!</source>
<target>Створення посилання…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>Поточний пароль</target>
@@ -4662,6 +4670,10 @@ Error: %2$@</source>
<target>Групове запрошення більше не дійсне, воно було видалено відправником.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>Посилання на групу</target>
@@ -9445,10 +9457,6 @@ alert subtitle</note>
<target>Це налаштування застосовується до повідомлень у вашому поточному профілі чату **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<target>Час зникнення встановлюється тільки для нових контактів.</target>
@@ -10451,6 +10459,14 @@ Repeat join request?</source>
<target>Тепер ви можете надсилати повідомлення на адресу %@</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<target>Ви можете надсилати повідомлення на %@ з архівних контактів.</target>
@@ -2521,8 +2521,8 @@ This is your own one-time link!</source>
<target>联系人偏好设置</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests from groups" xml:space="preserve">
<source>Contact requests from groups</source>
<trans-unit id="Contact requests in groups" xml:space="preserve">
<source>Contact requests in groups</source>
<target>来自群的联络请求</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -2710,6 +2710,14 @@ This is your own one-time link!</source>
<target>创建链接中…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder" xml:space="preserve">
<source>Crowdfunding on Wefunder</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Crowdfunding on Wefunder." xml:space="preserve">
<source>Crowdfunding on Wefunder.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source>
<target>当前密码</target>
@@ -4755,6 +4763,10 @@ Error: %2$@</source>
<target>群组邀请不再有效,已被发件人删除。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group invitations" xml:space="preserve">
<source>Group invitations</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve">
<source>Group link</source>
<target>群组链接</target>
@@ -9695,11 +9707,6 @@ alert subtitle</note>
<target>此设置适用于您当前聊天资料 **%@** 中的消息。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting is for your current profile **%@**." xml:space="preserve">
<source>This setting is for your current profile **%@**.</source>
<target>此设置用于当前个人资料 **%@**。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Time to disappear is set only for new contacts." xml:space="preserve">
<source>Time to disappear is set only for new contacts.</source>
<target>只为新联系人设置了消失时间。</target>
@@ -10725,6 +10732,14 @@ Repeat join request?</source>
<target>您现在可以给 %@ 发送消息</target>
<note>notification body</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat" xml:space="preserve">
<source>You can now invest in SimpleX Chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now invest in SimpleX Chat! 🚀" xml:space="preserve">
<source>You can now invest in SimpleX Chat! 🚀</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can send messages to %@ from Archived contacts." xml:space="preserve">
<source>You can send messages to %@ from Archived contacts.</source>
<target>您可以从存档的联系人向%@发送消息。</target>
@@ -2,7 +2,7 @@
"%d new events" = "%d nouveaux événements";
/* notification body */
"From %d chat(s)" = "De %d discussion(s)";
"From %d chat(s)" = "De %d conversation(s)";
/* notification body */
"From: %@" = "De : %@";
@@ -32,7 +32,7 @@
"Database passphrase is different from saved in the keychain." = "La phrase secrète de la base de données est différente de celle enregistrée dans la keychain.";
/* No comment provided by engineer. */
"Database passphrase is required to open chat." = "La phrase secrète de la base de données est nécessaire pour ouvrir le chat.";
"Database passphrase is required to open chat." = "La phrase secrète de la base de données est nécessaire pour ouvrir la messagerie.";
/* No comment provided by engineer. */
"Database upgrade required" = "Mise à niveau de la base de données nécessaire";
@@ -80,7 +80,7 @@
"Please create a profile in the SimpleX app" = "Veuillez créer un profil dans l'app SimpleX";
/* No comment provided by engineer. */
"Selected chat preferences prohibit this message." = "Les paramètres de chat sélectionnés ne permettent pas l'envoi de ce message.";
"Selected chat preferences prohibit this message." = "Les paramètres de conversation sélectionnés ne permettent pas l'envoi de ce message.";
/* No comment provided by engineer. */
"Sending a message takes longer than expected." = "L'envoi d'un message prend plus de temps que prévu.";
+28 -28
View File
@@ -183,8 +183,8 @@
64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */; };
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829982D54AEED006B9E89 /* libgmp.a */; };
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829992D54AEEE006B9E89 /* libffi.a */; };
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.11-SNj2VtVeH9ARktfFtATBo-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.11-SNj2VtVeH9ARktfFtATBo-ghc9.6.3.a */; };
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.11-SNj2VtVeH9ARktfFtATBo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.11-SNj2VtVeH9ARktfFtATBo.a */; };
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-7.1.0.3-9pyEF8uuax6HMofQg4cpqD-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-7.1.0.3-9pyEF8uuax6HMofQg4cpqD-ghc9.6.3.a */; };
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-7.1.0.3-9pyEF8uuax6HMofQg4cpqD.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-7.1.0.3-9pyEF8uuax6HMofQg4cpqD.a */; };
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */; };
64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; };
64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */; };
@@ -563,8 +563,8 @@
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>"; };
64C829992D54AEEE006B9E89 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.11-SNj2VtVeH9ARktfFtATBo-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-7.0.0.11-SNj2VtVeH9ARktfFtATBo-ghc9.6.3.a"; sourceTree = "<group>"; };
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.11-SNj2VtVeH9ARktfFtATBo.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-7.0.0.11-SNj2VtVeH9ARktfFtATBo.a"; sourceTree = "<group>"; };
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-7.1.0.3-9pyEF8uuax6HMofQg4cpqD-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-7.1.0.3-9pyEF8uuax6HMofQg4cpqD-ghc9.6.3.a"; sourceTree = "<group>"; };
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-7.1.0.3-9pyEF8uuax6HMofQg4cpqD.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-7.1.0.3-9pyEF8uuax6HMofQg4cpqD.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>"; };
64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressLearnMore.swift; sourceTree = "<group>"; };
@@ -735,8 +735,8 @@
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */,
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */,
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */,
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.11-SNj2VtVeH9ARktfFtATBo-ghc9.6.3.a in Frameworks */,
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.11-SNj2VtVeH9ARktfFtATBo.a in Frameworks */,
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-7.1.0.3-9pyEF8uuax6HMofQg4cpqD-ghc9.6.3.a in Frameworks */,
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-7.1.0.3-9pyEF8uuax6HMofQg4cpqD.a in Frameworks */,
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -822,8 +822,8 @@
64C829992D54AEEE006B9E89 /* libffi.a */,
64C829982D54AEED006B9E89 /* libgmp.a */,
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */,
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.11-SNj2VtVeH9ARktfFtATBo-ghc9.6.3.a */,
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.11-SNj2VtVeH9ARktfFtATBo.a */,
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-7.1.0.3-9pyEF8uuax6HMofQg4cpqD-ghc9.6.3.a */,
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-7.1.0.3-9pyEF8uuax6HMofQg4cpqD.a */,
);
path = Libraries;
sourceTree = "<group>";
@@ -2081,7 +2081,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 345;
CURRENT_PROJECT_VERSION = 350;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -2106,7 +2106,7 @@
"@executable_path/Frameworks",
);
LLVM_LTO = YES_THIN;
MARKETING_VERSION = 7.0;
MARKETING_VERSION = 7.1;
OTHER_LDFLAGS = "-Wl,-stack_size,0x1000000";
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
@@ -2131,7 +2131,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 345;
CURRENT_PROJECT_VERSION = 350;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -2156,7 +2156,7 @@
"@executable_path/Frameworks",
);
LLVM_LTO = YES;
MARKETING_VERSION = 7.0;
MARKETING_VERSION = 7.1;
OTHER_LDFLAGS = "-Wl,-stack_size,0x1000000";
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
@@ -2173,11 +2173,11 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 345;
CURRENT_PROJECT_VERSION = 350;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 7.0;
MARKETING_VERSION = 7.1;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2193,11 +2193,11 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 345;
CURRENT_PROJECT_VERSION = 350;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 7.0;
MARKETING_VERSION = 7.1;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2218,7 +2218,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 345;
CURRENT_PROJECT_VERSION = 350;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GCC_OPTIMIZATION_LEVEL = s;
@@ -2233,7 +2233,7 @@
"@executable_path/../../Frameworks",
);
LLVM_LTO = YES;
MARKETING_VERSION = 7.0;
MARKETING_VERSION = 7.1;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2255,7 +2255,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 345;
CURRENT_PROJECT_VERSION = 350;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_CODE_COVERAGE = NO;
@@ -2270,7 +2270,7 @@
"@executable_path/../../Frameworks",
);
LLVM_LTO = YES;
MARKETING_VERSION = 7.0;
MARKETING_VERSION = 7.1;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2292,7 +2292,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 345;
CURRENT_PROJECT_VERSION = 350;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2318,7 +2318,7 @@
"$(PROJECT_DIR)/Libraries/sim",
);
LLVM_LTO = YES;
MARKETING_VERSION = 7.0;
MARKETING_VERSION = 7.1;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
@@ -2343,7 +2343,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 345;
CURRENT_PROJECT_VERSION = 350;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2370,7 +2370,7 @@
"$(PROJECT_DIR)/Libraries/sim",
);
LLVM_LTO = YES;
MARKETING_VERSION = 7.0;
MARKETING_VERSION = 7.1;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
@@ -2397,7 +2397,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 345;
CURRENT_PROJECT_VERSION = 350;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -2412,7 +2412,7 @@
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 7.0;
MARKETING_VERSION = 7.1;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2431,7 +2431,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 345;
CURRENT_PROJECT_VERSION = 350;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -2446,7 +2446,7 @@
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 7.0;
MARKETING_VERSION = 7.1;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
+17 -7
View File
@@ -42,6 +42,7 @@ public struct User: Identifiable, Decodable, UserLike, NamedChat, Hashable {
public var sendRcptsContacts: Bool
public var sendRcptsSmallGroups: Bool
public var autoAcceptMemberContacts: Bool
public var autoAcceptGroupInvitations: Bool
public var viewPwdHash: UserPwdHash?
public var uiThemes: ThemeModeOverrides?
public var userChatRelay: Bool
@@ -71,6 +72,7 @@ public struct User: Identifiable, Decodable, UserLike, NamedChat, Hashable {
sendRcptsContacts: true,
sendRcptsSmallGroups: false,
autoAcceptMemberContacts: false,
autoAcceptGroupInvitations: false,
userChatRelay: false
)
}
@@ -4326,13 +4328,15 @@ public enum MsgDirection: String, Decodable, Hashable {
public enum CIForwardedFrom: Decodable, Hashable {
case unknown
case contact(chatName: String, msgDir: MsgDirection, contactId: Int64?, chatItemId: Int64?)
case group(chatName: String, msgDir: MsgDirection, groupId: Int64?, chatItemId: Int64?)
case group(chatName: String, msgDir: MsgDirection, groupId: Int64?, chatItemId: Int64?, memberId: String?, sharedMsgId_: String?, groupType: GroupType?)
case groupLink(chatName: String, msgDir: MsgDirection, groupLink: String, publicGroupId: String, memberId: String?, sharedMsgId: String, groupType: GroupType?)
var chatName: String {
public var chatName: String {
switch self {
case .unknown: ""
case let .contact(chatName, _, _, _): chatName
case let .group(chatName, _, _, _): chatName
case let .group(chatName, _, _, _, _, _, _): chatName
case let .groupLink(chatName, _, _, _, _, _, _): chatName
}
}
@@ -4343,17 +4347,23 @@ public enum CIForwardedFrom: Decodable, Hashable {
if let contactId {
(ChatType.direct, contactId, msgId)
} else { nil }
case let .group(_, _, groupId, msgId):
case let .group(_, _, groupId, msgId, _, _, _):
if let groupId {
(ChatType.group, groupId, msgId)
} else { nil }
case .groupLink: nil
}
}
public var sourceGroupLink: String? {
switch self {
case let .groupLink(_, _, groupLink, _, _, _, _): groupLink
default: nil
}
}
public func text(_ chatType: ChatType) -> LocalizedStringKey {
chatType == .local
? (chatName == "" ? "saved" : "saved from \(chatName)")
: "forwarded"
chatType == .local ? "saved" : "forwarded"
}
}
+13 -1
View File
@@ -3519,7 +3519,7 @@ chat item action */
"Saved from" = "Запазено от";
/* No comment provided by engineer. */
"saved from %@" = "запазено от %@";
"saved from" = "запазено от";
/* message info title */
"Saved message" = "Запазено съобщение";
@@ -4420,6 +4420,18 @@ server test failure */
/* No comment provided by engineer. */
"you are observer" = "вие сте наблюдател";
/* new chat alert */
"You are an observer" = "Вие сте наблюдател";
/* new chat alert */
"You are a member" = "Вие сте член";
/* new chat alert */
"You are an admin" = "Вие сте админ";
/* new chat alert */
"You are an owner" = "Вие сте собственик";
/* snd group event chat item */
"you blocked %@" = "вие блокирахте %@";
+12
View File
@@ -3514,6 +3514,18 @@ server test failure */
/* No comment provided by engineer. */
"you are observer" = "jste pozorovatel";
/* new chat alert */
"You are an observer" = "Jste pozorovatel";
/* new chat alert */
"You are a member" = "Jste člen";
/* new chat alert */
"You are an admin" = "Jste správce";
/* new chat alert */
"You are an owner" = "Jste vlastník";
/* No comment provided by engineer. */
"You can accept calls from lock screen, without device and app authentication." = "Můžete přijímat hovory z obrazovky zámku, bez ověření zařízení a aplikace.";
+32 -14
View File
@@ -1611,7 +1611,7 @@ server test step */
"Connection is blocked by server operator:\n%@" = "Die Verbindung wurde vom Serverbetreiber blockiert:\n%@";
/* conn error description */
"Connection link removed" = "Verbindungsfehler";
"Connection link removed" = "Verbindungslink entfernt";
/* No comment provided by engineer. */
"Connection not ready." = "Verbindung noch nicht bereit.";
@@ -1692,7 +1692,7 @@ server test step */
"Contact preferences" = "Kontakt-Präferenzen";
/* No comment provided by engineer. */
"Contact requests from groups" = "KONTAKTANFRAGEN VON GRUPPEN";
"Contact requests in groups" = "KONTAKTANFRAGEN VON GRUPPEN";
/* No comment provided by engineer. */
"contact should accept…" = "Kontakt sollte annehmen…";
@@ -3106,7 +3106,7 @@ servers warning */
"Get notified when mentioned." = "Bei Erwähnung benachrichtigt werden.";
/* No comment provided by engineer. */
"Get SimpleX name (BETA)" = "SimpleX-Name erhalten (BETA)";
"Get SimpleX name (BETA)" = "Einen SimpleX-Namen erhalten (BETA)";
/* No comment provided by engineer. */
"Get started" = "Jetzt starten";
@@ -4264,7 +4264,7 @@ servers warning */
"No valid link" = "Kein gültiger Link";
/* No comment provided by engineer. */
"Nobody tracked your conversations. No one drew a map of where you'd been. Privacy was never a feature - it was the way of life." = "Niemand verfolgte Ihre Gespräche. Niemand erstellte eine Karte, wo Sie sich aufgehalten haben. Privatsphäre war nie ein Feature - sie war selbstverständlich.";
"Nobody tracked your conversations. No one drew a map of where you'd been. Privacy was never a feature - it was the way of life." = "Niemand verfolgte Ihre Gespräche. Niemand hat eine Karte erstellt, wo Sie überall waren. Privatsphäre war nie ein Feature sie war eine Selbstverständlichkeit.";
/* No comment provided by engineer. */
"Non-profit governance" = "NonProfitGovernance";
@@ -5233,16 +5233,16 @@ swipe action */
"Role" = "Rolle";
/* No comment provided by engineer. */
"Role will be changed to \"%@\". All chat members will be notified." = "Die Rolle des Mitglieds wird auf \"%@\" geändert. Alle Chat-Mitglieder werden darüber informiert.";
"Role will be changed to \"%@\". All chat members will be notified." = "Die Rolle wird auf \"%@\" geändert. Alle Chat-Mitglieder werden darüber informiert.";
/* No comment provided by engineer. */
"Role will be changed to \"%@\". All group members will be notified." = "Die Mitgliederrolle wird auf \"%@\" geändert. Alle Gruppenmitglieder werden benachrichtigt.";
"Role will be changed to \"%@\". All group members will be notified." = "Die Rolle wird auf \"%@\" geändert. Alle Gruppenmitglieder werden benachrichtigt.";
/* No comment provided by engineer. */
"Role will be changed to \"%@\". All subscribers will be notified." = "Die Rolle wird auf \"%@\" geändert. Alle Abonnenten werden benachrichtigt.";
/* No comment provided by engineer. */
"Role will be changed to \"%@\". The member will receive a new invitation." = "Die Mitgliederrolle wird auf \"%@\" geändert. Das Mitglied wird eine neue Einladung erhalten.";
"Role will be changed to \"%@\". The member will receive a new invitation." = "Die Rolle wird auf \"%@\" geändert. Das Mitglied wird eine neue Einladung erhalten.";
/* No comment provided by engineer. */
"Run chat" = "Chat starten";
@@ -5346,7 +5346,7 @@ chat item action */
"Saved from" = "Abgespeichert von";
/* No comment provided by engineer. */
"saved from %@" = "abgespeichert von %@";
"saved from" = "abgespeichert von";
/* message info title */
"Saved message" = "Gespeicherte Nachricht";
@@ -6280,7 +6280,7 @@ server test failure */
"The second tick we missed! ✅" = "Wir haben das zweite Häkchen vermisst! ✅";
/* No comment provided by engineer. */
"The sender deleted the connection request." = "Der Absender hat möglicherweise die Verbindungsanfrage gelöscht.";
"The sender deleted the connection request." = "Der Absender hat die Verbindungsanfrage gelöscht.";
/* alert message */
"The sender will NOT be notified" = "Der Absender wird NICHT benachrichtigt";
@@ -6301,7 +6301,7 @@ server test failure */
"The SimpleX name %@ is registered, but it has no valid link." = "Der SimpleX-Name %@ wurde registriert, hat aber keinen gültigen Link.";
/* No comment provided by engineer. */
"The SimpleX name %@ is registered, but not added to profile. Please add it to your address or channel profile, if you are the owner." = "Der SimpleXName %@ wurde registriert, jedoch nicht in Ihrem Profil hinterlegt. Bitte zu Ihrer Adresse oder zum Kanalprofil hinzufügen, sofern Sie der Besitzer sind.";
"The SimpleX name %@ is registered, but not added to profile. Please add it to your address or channel profile, if you are the owner." = "Der SimpleXName %@ wurde registriert, jedoch nicht in Ihrem Profil hinterlegt. Bitte fügen Sie ihn zu Ihrer Adresse oder zum Kanalprofil hinzu, sofern Sie der Besitzer sind.";
/* No comment provided by engineer. */
"The text you pasted is not a SimpleX link." = "Der von Ihnen eingefügte Text ist kein SimpleX-Link.";
@@ -6388,9 +6388,6 @@ alert subtitle */
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "Diese Einstellung gilt für Nachrichten in Ihrem aktuellen Chat-Profil **%@**.";
/* No comment provided by engineer. */
"This setting is for your current profile **%@**." = "Diese Einstellung gilt für Ihr aktuelles Profil **%@**.";
/* No comment provided by engineer. */
"This SimpleX name is not registered. Please check the name." = "Dieser SimpleX-Name wurde nicht registriert. Bitte überprüfen Sie den Namen.";
@@ -7055,6 +7052,27 @@ alert title */
/* No comment provided by engineer. */
"you are observer" = "Sie sind Beobachter";
/* new chat alert */
"You are an observer" = "Sie sind Beobachter";
/* new chat alert */
"You are a member" = "Sie sind Mitglied";
/* new chat alert */
"You are a moderator" = "Sie sind Moderator";
/* new chat alert */
"You are an admin" = "Sie sind Admin";
/* new chat alert */
"You are an owner" = "Sie sind Eigentümer";
/* new chat alert */
"You are a subscriber" = "Sie sind Abonnent";
/* new chat alert */
"You are a contributor" = "Sie sind Mitwirkender";
/* No comment provided by engineer. */
"you are subscriber" = "Sie sind Abonnent";
@@ -7281,7 +7299,7 @@ alert title */
"Your contact" = "Ihr Kontakt";
/* No comment provided by engineer. */
"Your contact removed this link, or it was a one-time link that was already used.\nTo connect, ask your contact to create a new link." = "Entweder hat Ihr Kontakt die Verbindung gelöscht, oder dieser Link wurde bereits verwendet, es könnte sich um einen Fehler handeln - Bitte melden Sie es uns.\nBitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um sich neu verbinden zu können und stellen Sie sicher, dass Sie eine stabile Netzwerk-Verbindung haben.";
"Your contact removed this link, or it was a one-time link that was already used.\nTo connect, ask your contact to create a new link." = "Ihr Kontakt hat diesen Link entfernt oder es war ein EinmalLink, welcher bereits verwendet wurde.\nUm sich zu verbinden, bitten Sie Ihren Kontakt, einen neuen Link zu erstellen.";
/* No comment provided by engineer. */
"Your contact sent a file that is larger than currently supported maximum size (%@)." = "Ihr Kontakt hat eine Datei gesendet, die größer ist als die derzeit unterstützte maximale Größe (%@).";
+23 -5
View File
@@ -1692,7 +1692,7 @@ server test step */
"Contact preferences" = "Preferencias de contacto";
/* No comment provided by engineer. */
"Contact requests from groups" = "Solicitudes de contacto en grupo";
"Contact requests in groups" = "Solicitudes de contacto en grupo";
/* No comment provided by engineer. */
"contact should accept…" = "el contacto debe aceptarte…";
@@ -5346,7 +5346,7 @@ chat item action */
"Saved from" = "Guardado desde";
/* No comment provided by engineer. */
"saved from %@" = "Guardado desde %@";
"saved from" = "Guardado desde";
/* message info title */
"Saved message" = "Mensaje guardado";
@@ -6388,9 +6388,6 @@ alert subtitle */
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "Esta configuración se aplica a los mensajes del perfil actual **%@**.";
/* No comment provided by engineer. */
"This setting is for your current profile **%@**." = "Esta configuración se aplica al perfil actual **%@**.";
/* No comment provided by engineer. */
"This SimpleX name is not registered. Please check the name." = "El nombre SimpleX no está registrado. Por favor, comprueba el nombre.";
@@ -7055,6 +7052,27 @@ alert title */
/* No comment provided by engineer. */
"you are observer" = "Tu rol es observador";
/* new chat alert */
"You are an observer" = "Eres observador";
/* new chat alert */
"You are a member" = "Eres miembro";
/* new chat alert */
"You are a moderator" = "Eres moderador";
/* new chat alert */
"You are an admin" = "Eres administrador";
/* new chat alert */
"You are an owner" = "Eres propietario";
/* new chat alert */
"You are a subscriber" = "Eres suscriptor";
/* new chat alert */
"You are a contributor" = "Eres colaborador";
/* No comment provided by engineer. */
"you are subscriber" = "eres suscriptor";
+12
View File
@@ -3150,6 +3150,18 @@ server test failure */
/* No comment provided by engineer. */
"you are observer" = "olet tarkkailija";
/* new chat alert */
"You are an observer" = "Olet tarkkailija";
/* new chat alert */
"You are a member" = "Olet jäsen";
/* new chat alert */
"You are an admin" = "Olet ylläpitäjä";
/* new chat alert */
"You are an owner" = "Olet omistaja";
/* No comment provided by engineer. */
"You can accept calls from lock screen, without device and app authentication." = "Voit vastaanottaa puheluita lukitusnäytöltä ilman laitteen ja sovelluksen todennusta.";
File diff suppressed because it is too large Load Diff
@@ -8,7 +8,7 @@
"NSFaceIDUsageDescription" = "SimpleGroup not found!X utilise Face ID pour l'authentification locale";
/* Privacy - Local Network Usage Description */
"NSLocalNetworkUsageDescription" = "SimpleX utilise un accès au réseau local pour permettre l'utilisation du profil de chat de l'utilisateur via l'application de bureau au sein de ce même réseau.";
"NSLocalNetworkUsageDescription" = "SimpleX utilise laccès au réseau local pour permettre lutilisation du profil de messagerie sur lapp de bureau du même réseau.";
/* Privacy - Microphone Usage Description */
"NSMicrophoneUsageDescription" = "SimpleX a besoin d'un accès au microphone pour les appels audio et vidéo ainsi que pour enregistrer des messages vocaux.";
+23 -5
View File
@@ -1692,7 +1692,7 @@ server test step */
"Contact preferences" = "Partnerbeállítások";
/* No comment provided by engineer. */
"Contact requests from groups" = "Partneri kapcsolatkérések a csoportokból";
"Contact requests in groups" = "Partneri kapcsolatkérések a csoportokból";
/* No comment provided by engineer. */
"contact should accept…" = "a partnernek el kell fogadnia…";
@@ -5346,7 +5346,7 @@ chat item action */
"Saved from" = "Mentve innen";
/* No comment provided by engineer. */
"saved from %@" = "mentve innen: %@";
"saved from" = "mentve innen:";
/* message info title */
"Saved message" = "Mentett üzenet";
@@ -6388,9 +6388,6 @@ alert subtitle */
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "Ez a beállítás csak az Ön jelenlegi **%@** nevű csevegési profiljában lévő üzenetekre vonatkozik.";
/* No comment provided by engineer. */
"This setting is for your current profile **%@**." = "Ez a beállítás csak a jelenlegi **%@** nevű csevegési profiljára vonatkozik.";
/* No comment provided by engineer. */
"This SimpleX name is not registered. Please check the name." = "Ez a SimpleX-név nincs regisztrálva. Ellenőrizze a nevet.";
@@ -7055,6 +7052,27 @@ alert title */
/* No comment provided by engineer. */
"you are observer" = "Ön megfigyelő";
/* new chat alert */
"You are an observer" = "Ön megfigyelő";
/* new chat alert */
"You are a member" = "Ön tag";
/* new chat alert */
"You are a moderator" = "Ön moderátor";
/* new chat alert */
"You are an admin" = "Ön adminisztrátor";
/* new chat alert */
"You are an owner" = "Ön tulajdonos";
/* new chat alert */
"You are a subscriber" = "Ön feliratkozó";
/* new chat alert */
"You are a contributor" = "Ön közreműködő";
/* No comment provided by engineer. */
"you are subscriber" = "Ön feliratkozó";
+23 -5
View File
@@ -1692,7 +1692,7 @@ server test step */
"Contact preferences" = "Preferenze del contatto";
/* No comment provided by engineer. */
"Contact requests from groups" = "Richieste di contatto dai gruppi";
"Contact requests in groups" = "Richieste di contatto dai gruppi";
/* No comment provided by engineer. */
"contact should accept…" = "il contatto deve accettare…";
@@ -5346,7 +5346,7 @@ chat item action */
"Saved from" = "Salvato da";
/* No comment provided by engineer. */
"saved from %@" = "salvato da %@";
"saved from" = "salvato da";
/* message info title */
"Saved message" = "Messaggio salvato";
@@ -6388,9 +6388,6 @@ alert subtitle */
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "Questa impostazione si applica ai messaggi del profilo di chat attuale **%@**.";
/* No comment provided by engineer. */
"This setting is for your current profile **%@**." = "Questa impostazione è per il tuo profilo attuale **%@**.";
/* No comment provided by engineer. */
"This SimpleX name is not registered. Please check the name." = "Questo nome SimpleX non è registrato. Controlla il nome.";
@@ -7055,6 +7052,27 @@ alert title */
/* No comment provided by engineer. */
"you are observer" = "sei un osservatore";
/* new chat alert */
"You are an observer" = "Sei un osservatore";
/* new chat alert */
"You are a member" = "Sei un membro";
/* new chat alert */
"You are a moderator" = "Sei un moderatore";
/* new chat alert */
"You are an admin" = "Sei un amministratore";
/* new chat alert */
"You are an owner" = "Sei un proprietario";
/* new chat alert */
"You are a subscriber" = "Sei iscritto/a";
/* new chat alert */
"You are a contributor" = "Sei un collaboratore";
/* No comment provided by engineer. */
"you are subscriber" = "sei iscritto/a";
+12
View File
@@ -3484,6 +3484,18 @@ server test failure */
/* No comment provided by engineer. */
"you are observer" = "あなたはオブザーバーです";
/* new chat alert */
"You are an observer" = "あなたはオブザーバーです";
/* new chat alert */
"You are a member" = "あなたはメンバーです";
/* new chat alert */
"You are an admin" = "あなたは管理者です";
/* new chat alert */
"You are an owner" = "あなたはオーナーです";
/* No comment provided by engineer. */
"You can accept calls from lock screen, without device and app authentication." = "デバイスやアプリの認証を行わずに、ロック画面から通話を受けることができます。";
+16 -1
View File
@@ -4411,7 +4411,7 @@ chat item action */
"Saved from" = "Opgeslagen van";
/* No comment provided by engineer. */
"saved from %@" = "opgeslagen van %@";
"saved from" = "opgeslagen van";
/* message info title */
"Saved message" = "Opgeslagen bericht";
@@ -5739,6 +5739,21 @@ server test failure */
/* No comment provided by engineer. */
"you are observer" = "je bent waarnemer";
/* new chat alert */
"You are an observer" = "Je bent waarnemer";
/* new chat alert */
"You are a member" = "Je bent lid";
/* new chat alert */
"You are a moderator" = "Je bent moderator";
/* new chat alert */
"You are an admin" = "Je bent beheerder";
/* new chat alert */
"You are an owner" = "Je bent eigenaar";
/* snd group event chat item */
"you blocked %@" = "je hebt %@ geblokkeerd";
+17 -5
View File
@@ -1416,7 +1416,7 @@ server test step */
"Contact preferences" = "Preferencje kontaktu";
/* No comment provided by engineer. */
"Contact requests from groups" = "Prośby o kontakt od grup";
"Contact requests in groups" = "Prośby o kontakt od grup";
/* No comment provided by engineer. */
"contact should accept…" = "kontakt powinien zaakceptować…";
@@ -4646,7 +4646,7 @@ chat item action */
"Saved from" = "Zapisane od";
/* No comment provided by engineer. */
"saved from %@" = "zapisane od %@";
"saved from" = "zapisane od";
/* message info title */
"Saved message" = "Zachowano wiadomość";
@@ -5506,9 +5506,6 @@ server test failure */
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "To ustawienie dotyczy wiadomości Twojego bieżącego profilu czatu **%@**.";
/* No comment provided by engineer. */
"This setting is for your current profile **%@**." = "To ustawienie jest dla Twojego obecnego profilu **%@**.";
/* No comment provided by engineer. */
"Time to disappear is set only for new contacts." = "Czas zniknięcia jest ustawiony tylko dla nowych kontaktów.";
@@ -6098,6 +6095,21 @@ alert title */
/* No comment provided by engineer. */
"you are observer" = "jesteś obserwatorem";
/* new chat alert */
"You are an observer" = "Jesteś obserwatorem";
/* new chat alert */
"You are a member" = "Jesteś członkiem";
/* new chat alert */
"You are a moderator" = "Jesteś moderatorem";
/* new chat alert */
"You are an admin" = "Jesteś administratorem";
/* new chat alert */
"You are an owner" = "Jesteś właścicielem";
/* snd group event chat item */
"you blocked %@" = "zablokowałeś %@";
+1 -1
View File
@@ -113,7 +113,7 @@ Establishing contact between two SimpleX Chat users. SimpleX uses no user identi
1. When connecting to a channel link (`GroupShortLinkInfo.direct == false`):
2. `apiPrepareGroup(connLink:directLink:groupShortLinkData:)` is called with `directLink: false`, preparing the channel locally.
3. `groupShortLinkInfo.groupRelays` (hostnames) stored in `ChatModel.shared.channelRelayHostnames[groupId]`.
4. Pre-join UI shows channel icon and "Open new channel" (not "Open new group").
4. Pre-join UI shows channel icon and "Open channel" (not "Open group").
5. `apiConnectPreparedGroup(groupId:incognito:msg:)` returns `(GroupInfo, [RelayConnectionResult])`.
6. `RelayConnectionResult` contains `relayMember: GroupMember` and optional `relayError: ChatError?` per relay.
7. Relay members are upserted to `chatModel.groupMembers`; `channelRelayHostnames` entry is cleared.
+10 -2
View File
@@ -118,10 +118,18 @@ When `planAndConnect` encounters a `.simplexLink(_, .relay, _, _)`, it shows a "
| Context | Channel behavior | Group behavior |
|---|---|---|
| Prepare alert icon | `antenna.radiowaves.left.and.right.circle.fill` | `person.2.circle.fill` |
| Prepare alert title | "Open new channel" | "Open new group" |
| Prepare alert title | "Open channel" | "Open group" |
| Error text | "Error opening channel" | "Error opening group" |
| Own-link confirm | "This is your link for channel" with only "Open channel" + "Cancel" (no incognito/profile options) | Full incognito/profile selection |
| Known group alert | "Open channel" / "Open new channel" | "Open group" / "Open new group" |
| Known group alert | "Open channel", with the membership role line | "Open group", with the membership role line |
The known group alert shows an information line with the user's role, in the
secondary color (matching the subscriber count): "You are a subscriber" /
"You are a contributor" for channels, "You are an observer" / "You are a
member" for groups, and "You are a moderator" / "You are an admin" /
"You are an owner" for both. The line is omitted for prepared chats
(`nextConnectPrepared`) and business chats, so the prepare and known alerts
differ only by this line.
### Pre-Join Relay Info
+23 -5
View File
@@ -1692,7 +1692,7 @@ server test step */
"Contact preferences" = "Предпочтения контакта";
/* No comment provided by engineer. */
"Contact requests from groups" = "Запросы на соединение из групп";
"Contact requests in groups" = "Запросы на соединение из групп";
/* No comment provided by engineer. */
"contact should accept…" = "контакт должен принять…";
@@ -5346,7 +5346,7 @@ chat item action */
"Saved from" = "Сохранено из";
/* No comment provided by engineer. */
"saved from %@" = "сохранено из %@";
"saved from" = "сохранено из";
/* message info title */
"Saved message" = "Сохранённое сообщение";
@@ -6388,9 +6388,6 @@ alert subtitle */
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "Эта настройка применяется к сообщениям в Вашем текущем профиле чата **%@**.";
/* No comment provided by engineer. */
"This setting is for your current profile **%@**." = "Эта настройка применяется к Вашему текущему профилю чата **%@**.";
/* No comment provided by engineer. */
"This SimpleX name is not registered. Please check the name." = "Это SimpleX имя не зарегистрировано. Пожалуйста, проверьте имя.";
@@ -7058,6 +7055,27 @@ alert title */
/* No comment provided by engineer. */
"you are subscriber" = "Вы подписчик";
/* new chat alert */
"You are an observer" = "Вы читатель";
/* new chat alert */
"You are a member" = "Вы член группы";
/* new chat alert */
"You are a moderator" = "Вы модератор";
/* new chat alert */
"You are an admin" = "Вы админ";
/* new chat alert */
"You are an owner" = "Вы владелец";
/* new chat alert */
"You are a subscriber" = "Вы подписчик";
/* new chat alert */
"You are a contributor" = "Вы соавтор";
/* snd group event chat item */
"you blocked %@" = "Вы заблокировали %@";
+2 -2
View File
@@ -344,7 +344,7 @@ Similarly, in `planAndConnect()` (`NewChatView.swift`), `.simplexLink(_, .relay,
When `groupShortLinkInfo?.direct == false` (channel relay link), the prepare alert uses:
- Channel icon: `antenna.radiowaves.left.and.right.circle.fill`
- Title: "Open new channel"
- Title: "Open channel"
- Error: "Error opening channel"
- `apiPrepareGroup` call passes `directLink: false`
- Stores `groupShortLinkInfo.groupRelays` in `ChatModel.shared.channelRelayHostnames`
@@ -355,7 +355,7 @@ For channels: shows "This is your link for channel" with only "Open channel" + "
### Known Group Alert (`showOpenKnownGroupAlert`)
For channels (`groupInfo.useRelays`): titles become "Open channel" / "Open new channel".
For channels (`groupInfo.useRelays`): the title is "Open channel"; for groups, "Open group"; business chats keep "Open chat" / "Open new chat". Unless the chat is merely prepared (`nextConnectPrepared`) or a business chat, the alert shows an information line with the user's membership role (`memberRoleInformation`) in the secondary color: subscriber/contributor for channels, observer/member for groups, moderator/admin/owner for both.
---
+12
View File
@@ -3054,6 +3054,18 @@ server test failure */
/* No comment provided by engineer. */
"you are observer" = "คุณเป็นผู้สังเกตการณ์";
/* new chat alert */
"You are an observer" = "คุณเป็นผู้สังเกตการณ์";
/* new chat alert */
"You are a member" = "คุณเป็นสมาชิก";
/* new chat alert */
"You are an admin" = "คุณเป็นผู้ดูแลระบบ";
/* new chat alert */
"You are an owner" = "คุณเป็นเจ้าของ";
/* No comment provided by engineer. */
"You can accept calls from lock screen, without device and app authentication." = "คุณสามารถรับสายจากหน้าจอล็อกโดยไม่ต้องมีการตรวจสอบสิทธิ์อุปกรณ์และแอป";
+17 -5
View File
@@ -1454,7 +1454,7 @@ server test step */
"Contact preferences" = "Kişi tercihleri";
/* No comment provided by engineer. */
"Contact requests from groups" = "Gruplardan gelen iletişim talepleri";
"Contact requests in groups" = "Gruplardan gelen iletişim talepleri";
/* No comment provided by engineer. */
"contact should accept…" = "kişi kabul etmeli…";
@@ -4629,7 +4629,7 @@ chat item action */
"Saved from" = "Tarafından kaydedildi";
/* No comment provided by engineer. */
"saved from %@" = "%@ tarafından kaydedildi";
"saved from" = "kaydedildi:";
/* message info title */
"Saved message" = "Kaydedilmiş mesaj";
@@ -5465,9 +5465,6 @@ server test failure */
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "Bu ayar, geçerli sohbet profiliniz **%@** deki mesajlara uygulanır.";
/* No comment provided by engineer. */
"This setting is for your current profile **%@**." = "Bu ayar, mevcut profiliniz içindir.";
/* No comment provided by engineer. */
"Time to disappear is set only for new contacts." = "Kaybolma süresi yalnızca yeni kişiler için ayarlanır.";
@@ -6045,6 +6042,21 @@ alert title */
/* No comment provided by engineer. */
"you are observer" = "gözlemcisiniz";
/* new chat alert */
"You are an observer" = "Gözlemcisiniz";
/* new chat alert */
"You are a member" = "Üyesiniz";
/* new chat alert */
"You are a moderator" = "Moderatörsünüz";
/* new chat alert */
"You are an admin" = "Yöneticisiniz";
/* new chat alert */
"You are an owner" = "Sahipsiniz";
/* snd group event chat item */
"you blocked %@" = "engelledin %@";
+16 -1
View File
@@ -4650,7 +4650,7 @@ chat item action */
"Saved from" = "Збережено з";
/* No comment provided by engineer. */
"saved from %@" = "збережено з %@";
"saved from" = "збережено з";
/* message info title */
"Saved message" = "Збережене повідомлення";
@@ -6057,6 +6057,21 @@ alert title */
/* No comment provided by engineer. */
"you are observer" = "ви спостерігач";
/* new chat alert */
"You are an observer" = "Ви спостерігач";
/* new chat alert */
"You are a member" = "Ви учасник";
/* new chat alert */
"You are a moderator" = "Ви модератор";
/* new chat alert */
"You are an admin" = "Ви адмін";
/* new chat alert */
"You are an owner" = "Ви власник";
/* snd group event chat item */
"you blocked %@" = "ви заблокували %@";
+20 -5
View File
@@ -1680,7 +1680,7 @@ server test step */
"Contact preferences" = "联系人偏好设置";
/* No comment provided by engineer. */
"Contact requests from groups" = "来自群的联络请求";
"Contact requests in groups" = "来自群的联络请求";
/* No comment provided by engineer. */
"contact should accept…" = "联系人应当接受…";
@@ -5271,7 +5271,7 @@ chat item action */
"Saved from" = "保存自";
/* No comment provided by engineer. */
"saved from %@" = "保存自 %@";
"saved from" = "保存自";
/* message info title */
"Saved message" = "已保存的消息";
@@ -6267,9 +6267,6 @@ alert subtitle */
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "此设置适用于您当前聊天资料 **%@** 中的消息。";
/* No comment provided by engineer. */
"This setting is for your current profile **%@**." = "此设置用于当前个人资料 **%@**。";
/* No comment provided by engineer. */
"Time to disappear is set only for new contacts." = "只为新联系人设置了消失时间。";
@@ -6919,6 +6916,24 @@ alert title */
/* No comment provided by engineer. */
"you are subscriber" = "你是订阅者";
/* new chat alert */
"You are an observer" = "你是观察者";
/* new chat alert */
"You are a member" = "你是成员";
/* new chat alert */
"You are a moderator" = "你是协管";
/* new chat alert */
"You are an admin" = "你是管理员";
/* new chat alert */
"You are an owner" = "你是群主";
/* new chat alert */
"You are a subscriber" = "你是订阅者";
/* snd group event chat item */
"you blocked %@" = "你阻止了%@";
+1
View File
@@ -16,6 +16,7 @@ android/build
android/release
common/build
desktop/build
external/nanohttpd/build
release
# Generated SimpleX assets
+1
View File
@@ -289,6 +289,7 @@ desktop/src/jvmMain/kotlin/chat/simplex/desktop/ -- Desktop app (1 file)
| common/.../common/StoreWindowState.kt (desktopMain) | spec/architecture.md | product/views/settings.md |
| common/.../common/model/NtfManager.desktop.kt (desktopMain) | spec/services/notifications.md | product/flows/messaging.md |
| common/.../common/views/helpers/AppUpdater.kt (desktopMain) | spec/architecture.md | product/views/settings.md |
| common/.../common/platform/AnimatedImage.desktop.kt (desktopMain) | spec/client/chat-view.md | product/views/chat.md |
### Haskell Core Sources (at `../../src/Simplex/Chat/` relative to `apps/multiplatform/`)
+22 -5
View File
@@ -6,14 +6,31 @@ This is a guide to contributing to the develop of the SimpleX android and deskto
This is the **Kotlin Multiplatform (KMP)** mobile and desktop client for SimpleX Chat, sharing code between Android and Desktop (JVM) platforms using Compose Multiplatform for UI.
## Setup
The desktop app builds nanohttpd from a submodule, Android does not use it. Before building
the desktop app on a fresh checkout:
```bash
git submodule update --init --recursive
```
## Build Commands
```bash
# Android debug APK
./gradlew assembleDebug
# Android debug APK, assembleGoogleDebug builds the flavor with the Play Billing dependency
./gradlew assembleFossDebug
# Android release APK
./gradlew assembleRelease
# Android release APK, distributed via F-Droid and GitHub
./gradlew assembleFossRelease
# Android app bundle, distributed via Google Play, includes Play Billing
./gradlew bundleGoogleRelease
# Always name the flavor for releases. The aggregate tasks (build, assemble, assembleRelease,
# bundle, bundleRelease) fail on purpose: they would package a release APK with Play Billing,
# or an app bundle without it.
# The fdroiddata recipe defaults to assembleRelease and must be changed to assembleFossRelease.
# Desktop distribution (current OS)
./gradlew :desktop:packageDistributionForCurrentOS
@@ -22,7 +39,7 @@ This is the **Kotlin Multiplatform (KMP)** mobile and desktop client for SimpleX
./gradlew desktopTest
# Run Android instrumented tests (requires connected device/emulator)
./gradlew connectedAndroidTest
./gradlew connectedFossDebugAndroidTest
# Build native libraries for all platforms
./gradlew common:cmakeBuild -PcrossCompile
+87 -51
View File
@@ -35,6 +35,21 @@ android {
manifestPlaceholders["extract_native_libs"] = rootProject.extra["compression.level"] as Int != 0
}
// `google` is distributed via Google Play as an app bundle and includes Play Billing.
// `foss` is distributed via F-Droid and as APKs on GitHub, without Play dependencies.
flavorDimensions += "store"
productFlavors {
create("google") {
dimension = "store"
buildConfigField("boolean", "PLAY_STORE", "true")
}
create("foss") {
dimension = "store"
isDefault = true
buildConfigField("boolean", "PLAY_STORE", "false")
}
}
buildTypes {
debug {
applicationIdSuffix = rootProject.extra["application_id.suffix"] as String
@@ -128,8 +143,28 @@ android {
}
}
// The graph is checked rather than the requested task, because every aggregate task
// (assemble, assembleRelease, build, bundle, ...) packages these variants too.
val projectPath = project.path
val apkTasks = setOf("packageFossDebug", "packageGoogleDebug", "packageFossRelease", "packageGoogleRelease")
val apkTaskPaths = apkTasks.map { "$projectPath:$it" }.toSet()
val bundleTaskPaths = apkTaskPaths.map { it + "Bundle" }.toSet()
gradle.taskGraph.whenReady {
if (hasTask("$projectPath:packageGoogleRelease")) {
throw GradleException("A release apk must not include Play Billing, use assembleFossRelease or bundleGoogleRelease")
}
if (hasTask("$projectPath:packageFossReleaseBundle")) {
throw GradleException("An app bundle must include Play Billing, use bundleGoogleRelease or assembleFossRelease")
}
// `isBundle` above is derived from the whole invocation, so a bundle in it disables abi splits
if (apkTaskPaths.any { hasTask(it) } && bundleTaskPaths.any { hasTask(it) }) {
throw GradleException("Build the apks and the bundle in separate invocations, the bundle disables abi splits")
}
}
dependencies {
implementation(project(":common"))
"googleImplementation"("com.android.billingclient:billing:9.1.0")
implementation("androidx.core:core-ktx:1.13.1")
//implementation("androidx.compose.ui:ui:${rootProject.extra["compose.version"] as String}")
//implementation("androidx.compose.material:material:$compose_version")
@@ -160,58 +195,61 @@ dependencies {
tasks {
val compressApk by creating {
doLast {
val isRelease = gradle.startParameter.taskNames.find { it.lowercase().contains("release") } != null
val buildType: String = if (isRelease) "release" else "debug"
val javaHome = System.getProperties()["java.home"] ?: org.gradle.internal.jvm.Jvm.current().javaHome
val sdkDir = android.sdkDirectory.absolutePath
val keyAlias: String
val keyPassword: String
val storeFile: String
val storePassword: String
if (project.properties["android.injected.signing.key.alias"] != null) {
keyAlias = project.properties["android.injected.signing.key.alias"] as String
keyPassword = project.properties["android.injected.signing.key.password"] as String
storeFile = project.properties["android.injected.signing.store.file"] as String
storePassword = project.properties["android.injected.signing.store.password"] as String
} else {
try {
val gradleConfig = android.signingConfigs.getByName(buildType)
keyAlias = gradleConfig.keyAlias!!
keyPassword = gradleConfig.keyPassword!!
storeFile = gradleConfig.storeFile!!.absolutePath
storePassword = gradleConfig.storePassword!!
} catch (e: UnknownDomainObjectException) {
// There is no signing config for current build type, can"t sign the apk
println("No signing configs for this build type: $buildType")
return@doLast
// A single invocation can package more than one variant, for example assembleDebug
gradle.taskGraph.allTasks.filter { it.path in apkTaskPaths }.forEach { packageTask ->
val variant = packageTask.name.removePrefix("package")
val buildType: String = if (variant.endsWith("Release")) "release" else "debug"
val keyAlias: String
val keyPassword: String
val storeFile: String
val storePassword: String
if (project.properties["android.injected.signing.key.alias"] != null) {
keyAlias = project.properties["android.injected.signing.key.alias"] as String
keyPassword = project.properties["android.injected.signing.key.password"] as String
storeFile = project.properties["android.injected.signing.store.file"] as String
storePassword = project.properties["android.injected.signing.store.password"] as String
} else {
try {
val gradleConfig = android.signingConfigs.getByName(buildType)
keyAlias = gradleConfig.keyAlias!!
keyPassword = gradleConfig.keyPassword!!
storeFile = gradleConfig.storeFile!!.absolutePath
storePassword = gradleConfig.storePassword!!
} catch (e: UnknownDomainObjectException) {
// There is no signing config for current build type, can"t sign the apk
println("No signing configs for this build type: $buildType")
return@forEach
}
}
val outputDir = packageTask.outputs.files.files.last()
exec {
workingDir("../../scripts/android")
environment = mapOf(
"JAVA_HOME" to "$javaHome",
"PATH" to "${System.getenv("PATH")}:$javaHome/bin"
)
commandLine = listOf(
"./compress-and-sign-apk.sh",
"${rootProject.extra["compression.level"]}",
"$outputDir",
sdkDir,
storeFile,
storePassword,
keyAlias,
keyPassword
)
}
}
lateinit var outputDir: File
named(if (isRelease) "packageRelease" else "packageDebug") {
outputDir = outputs.files.files.last()
}
exec {
workingDir("../../scripts/android")
environment = mapOf(
"JAVA_HOME" to "$javaHome",
"PATH" to "${System.getenv("PATH")}:$javaHome/bin"
)
commandLine = listOf(
"./compress-and-sign-apk.sh",
"${rootProject.extra["compression.level"]}",
"$outputDir",
sdkDir,
storeFile,
storePassword,
keyAlias,
keyPassword
)
}
if (project.properties["android.injected.signing.key.alias"] != null && buildType == "release") {
File(outputDir, "android-release.apk").renameTo(File(outputDir, "simplex.apk"))
File(outputDir, "android-armeabi-v7a-release.apk").renameTo(File(outputDir, "simplex-armv7a.apk"))
File(outputDir, "android-arm64-v8a-release.apk").renameTo(File(outputDir, "simplex.apk"))
if (project.properties["android.injected.signing.key.alias"] != null && buildType == "release") {
val flavor = variant.removeSuffix("Release").lowercase()
mapOf("arm64-v8a" to "simplex.apk", "armeabi-v7a" to "simplex-armv7a.apk").forEach { (abi, name) ->
if (!File(outputDir, "android-$flavor-$abi-release.apk").renameTo(File(outputDir, name))) {
logger.warn("No $abi apk to rename to $name")
}
}
}
}
// View all gradle properties set
// project.properties.each { k, v -> println "$k -> $v" }
@@ -221,9 +259,7 @@ tasks {
// Don"t do anything if no compression is needed
if (rootProject.extra["compression.level"] as Int != 0) {
whenTaskAdded {
if (name == "packageDebug") {
finalizedBy(compressApk)
} else if (name == "packageRelease") {
if (name in apkTasks) {
finalizedBy(compressApk)
}
}
@@ -0,0 +1,4 @@
package chat.simplex.app
// Play Billing is only in the google flavor, so the Play country stays unknown here
fun loadPlayStoreCountry() {}
@@ -0,0 +1,31 @@
package chat.simplex.app
import chat.simplex.common.platform.androidAppContext
import chat.simplex.common.platform.androidPlayStoreCountry
import com.android.billingclient.api.*
// Requests the country of the Google Play account into [androidPlayStoreCountry].
// It stays null when Play is unavailable or the user is not signed in.
fun loadPlayStoreCountry() {
val client = BillingClient.newBuilder(androidAppContext)
.setListener { _, _ -> }
.enablePendingPurchases(PendingPurchasesParams.newBuilder().enableOneTimeProducts().build())
.build()
client.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(result: BillingResult) {
if (result.responseCode != BillingClient.BillingResponseCode.OK) {
client.endConnection()
return
}
client.getBillingConfigAsync(GetBillingConfigParams.newBuilder().build()) { configResult, config ->
if (configResult.responseCode == BillingClient.BillingResponseCode.OK) {
androidPlayStoreCountry.value = config?.countryCode
}
client.endConnection()
}
}
// The connection is only used for this one request, it is not retried
override fun onBillingServiceDisconnected() = client.endConnection()
})
}
@@ -341,6 +341,8 @@ class SimplexApp: Application(), LifecycleEventObserver {
override fun androidIsXiaomiDevice(): Boolean = setOf("xiaomi", "redmi", "poco").contains(Build.BRAND.lowercase())
override fun androidLoadPlayStoreCountry() = loadPlayStoreCountry()
@SuppressLint("SourceLockedOrientationActivity")
@Composable
override fun androidLockPortraitOrientation() {
@@ -370,6 +372,8 @@ class SimplexApp: Application(), LifecycleEventObserver {
override fun androidCreateActiveCallState(): Closeable = ActiveCallState()
override val androidApiLevel: Int get() = Build.VERSION.SDK_INT
override val androidIsPlayStoreBuild: Boolean get() = BuildConfig.PLAY_STORE
}
}
+1 -4
View File
@@ -72,7 +72,6 @@ kotlin {
api("org.jetbrains.compose.ui:ui-text:${rootProject.extra["compose.version"] as String}")
implementation("org.jetbrains.compose.material:material-icons-core:1.7.3")
implementation("org.jetbrains.compose.material:material-icons-extended:1.7.3")
implementation("org.jetbrains.compose.components:components-animatedimage:${rootProject.extra["compose.version"] as String}")
//Barcode
api("org.boofcv:boofcv-core:1.1.3")
implementation("com.godaddy.android.colorpicker:compose-color-picker-jvm:0.7.0")
@@ -148,8 +147,7 @@ kotlin {
implementation("org.slf4j:slf4j-simple:2.0.12")
implementation("uk.co.caprica:vlcj:4.8.3")
implementation("net.java.dev.jna:jna:5.14.0")
implementation("com.github.NanoHttpd.nanohttpd:nanohttpd:efb2ebf")
implementation("com.github.NanoHttpd.nanohttpd:nanohttpd-websocket:efb2ebf")
implementation(project(":external:nanohttpd"))
implementation("com.squareup.okhttp3:okhttp:4.12.0")
}
}
@@ -189,7 +187,6 @@ buildConfig {
buildConfigField("String", "DESKTOP_VERSION_NAME", "\"${extra["desktop.version_name"]}\"")
buildConfigField("int", "DESKTOP_VERSION_CODE", "${extra["desktop.version_code"]}")
buildConfigField("String", "DATABASE_BACKEND", "\"${extra["database.backend"]}\"")
buildConfigField("Boolean", "ANDROID_BUNDLE", "${extra["android.bundle"]}")
buildConfigField("Boolean", "SIMPLEX_ASSETS", "$hasSimplexAssets")
}
}
@@ -3,6 +3,7 @@ package chat.simplex.common.views.chat.item
import android.os.Build.VERSION.SDK_INT
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.State
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.painter.Painter
@@ -24,6 +25,7 @@ actual fun SimpleAndAnimatedImageView(
file: CIFile?,
imageProvider: () -> ImageGalleryProvider,
smallView: Boolean,
blurred: State<Boolean>, // coil drives the animation itself here, so there is nothing to pause
ImageView: @Composable (painter: Painter, onClick: () -> Unit) -> Unit
) {
val context = LocalContext.current
@@ -233,7 +233,8 @@ actual fun getFileName(uri: URI): String? {
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
cursor.moveToFirst()
// Can make an exception
cursor.getString(nameIndex)
// the provider controls this value, and callers use it as a bare file name
cursor.getString(nameIndex)?.let { File(it).name }
}
} catch (e: Exception) {
null
@@ -341,6 +342,19 @@ actual suspend fun getBitmapFromVideo(uri: URI, timestamp: Long?, random: Boolea
VideoPlayerInterface.PreviewAndDuration(null, 0, 0)
}
actual suspend fun hasVideoTrack(uri: URI): Boolean {
val mmr = MediaMetadataRetriever()
return try {
mmr.setDataSource(androidAppContext, uri.toUri())
mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO) == "yes"
} catch (e: Exception) {
Log.e(TAG, "Utils.android hasVideoTrack error: ${e.message}")
false
} finally {
mmr.release()
}
}
actual fun ByteArray.toBase64StringForPassphrase(): String = Base64.encodeToString(this, Base64.DEFAULT)
actual fun String.toByteArrayFromBase64ForPassphrase(): ByteArray = Base64.decode(this, Base64.DEFAULT)
@@ -1307,6 +1307,7 @@ data class User(
val sendRcptsContacts: Boolean,
val sendRcptsSmallGroups: Boolean,
val autoAcceptMemberContacts: Boolean,
val autoAcceptGroupInvitations: Boolean,
val viewPwdHash: UserPwdHash?,
val uiThemes: ThemeModeOverrides? = null,
val userChatRelay: Boolean,
@@ -1339,6 +1340,7 @@ data class User(
sendRcptsContacts = true,
sendRcptsSmallGroups = false,
autoAcceptMemberContacts = false,
autoAcceptGroupInvitations = false,
viewPwdHash = null,
uiThemes = null,
userChatRelay = false,
@@ -3937,13 +3939,15 @@ enum class MsgDirection {
sealed class CIForwardedFrom {
@Serializable @SerialName("unknown") object Unknown: CIForwardedFrom()
@Serializable @SerialName("contact") class Contact(override val chatName: String, val msgDir: MsgDirection, val contactId: Long? = null, val chatItemId: Long? = null): CIForwardedFrom()
@Serializable @SerialName("group") class Group(override val chatName: String, val msgDir: MsgDirection, val groupId: Long? = null, val chatItemId: Long? = null): CIForwardedFrom()
@Serializable @SerialName("group") class Group(override val chatName: String, val msgDir: MsgDirection, val groupId: Long? = null, val chatItemId: Long? = null, val memberId: String? = null, val sharedMsgId_: String? = null, val groupType: GroupType? = null): CIForwardedFrom()
@Serializable @SerialName("groupLink") class GroupLink(override val chatName: String, val msgDir: MsgDirection, val groupLink: String, val publicGroupId: String, val memberId: String? = null, val sharedMsgId: String, val groupType: GroupType? = null): CIForwardedFrom()
open val chatName: String
get() = when (this) {
Unknown -> ""
is Contact -> chatName
is Group -> chatName
is GroupLink -> chatName
}
val chatTypeApiIdMsgId: Triple<ChatType, Long, Long?>?
@@ -3951,18 +3955,15 @@ sealed class CIForwardedFrom {
Unknown -> null
is Contact -> if (contactId != null) Triple(ChatType.Direct, contactId, chatItemId) else null
is Group -> if (groupId != null) Triple(ChatType.Group, groupId, chatItemId) else null
is GroupLink -> null
}
val sourceGroupLink: String?
get() = if (this is GroupLink) groupLink else null
fun text(chatType: ChatType): String =
if (chatType == ChatType.Local) {
if (chatName.isEmpty()) {
generalGetString(MR.strings.saved_description)
} else {
generalGetString(MR.strings.saved_from_description).format(chatName)
}
} else {
generalGetString(MR.strings.forwarded_description)
}
if (chatType == ChatType.Local) generalGetString(MR.strings.saved_description)
else generalGetString(MR.strings.forwarded_description)
}
@Serializable
@@ -941,6 +941,12 @@ object ChatController {
throw Exception("failed to set auto-accept ${r.responseType} ${r.details}")
}
suspend fun apiSetUserAutoAcceptGroupInvitations(u: User, enable: Boolean) {
val r = sendCmd(u.remoteHostId, CC.ApiSetUserAutoAcceptGroupInvitations(u.userId, enable))
if (r.result is CR.CmdOk) return
throw Exception("failed to set auto-accept group invitations ${r.responseType} ${r.details}")
}
suspend fun apiHideUser(u: User, viewPwd: String): User =
setUserPrivacy(u.remoteHostId, CC.ApiHideUser(u.userId, viewPwd))
@@ -3786,6 +3792,7 @@ sealed class CC {
class ApiSetUserContactReceipts(val userId: Long, val userMsgReceiptSettings: UserMsgReceiptSettings): CC()
class ApiSetUserGroupReceipts(val userId: Long, val userMsgReceiptSettings: UserMsgReceiptSettings): CC()
class ApiSetUserAutoAcceptMemberContacts(val userId: Long, val enable: Boolean): CC()
class ApiSetUserAutoAcceptGroupInvitations(val userId: Long, val enable: Boolean): CC()
class ApiHideUser(val userId: Long, val viewPwd: String): CC()
class ApiUnhideUser(val userId: Long, val viewPwd: String): CC()
class ApiMuteUser(val userId: Long): CC()
@@ -3977,6 +3984,7 @@ sealed class CC {
"/_set receipts groups $userId ${onOff(mrs.enable)} clear_overrides=${onOff(mrs.clearOverrides)}"
}
is ApiSetUserAutoAcceptMemberContacts -> "/_set accept member contacts $userId ${onOff(enable)}"
is ApiSetUserAutoAcceptGroupInvitations -> "/_set accept group invitations $userId ${onOff(enable)}"
is ApiHideUser -> "/_hide user $userId ${json.encodeToString(viewPwd)}"
is ApiUnhideUser -> "/_unhide user $userId ${json.encodeToString(viewPwd)}"
is ApiMuteUser -> "/_mute user $userId"
@@ -4192,6 +4200,7 @@ sealed class CC {
is ApiSetUserContactReceipts -> "apiSetUserContactReceipts"
is ApiSetUserGroupReceipts -> "apiSetUserGroupReceipts"
is ApiSetUserAutoAcceptMemberContacts -> "apiSetUserAutoAcceptMemberContacts"
is ApiSetUserAutoAcceptGroupInvitations -> "apiSetUserAutoAcceptGroupInvitations"
is ApiHideUser -> "apiHideUser"
is ApiUnhideUser -> "apiUnhideUser"
is ApiMuteUser -> "apiMuteUser"
@@ -1,5 +1,7 @@
package chat.simplex.common.platform
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import chat.simplex.common.BuildConfigCommon
import chat.simplex.common.model.*
import chat.simplex.common.ui.theme.DefaultTheme
@@ -30,6 +32,9 @@ else
val databaseBackend: String = if (appPlatform == AppPlatform.ANDROID) "sqlite" else BuildConfigCommon.DATABASE_BACKEND
// Country of the Google Play account, only set in the google flavor of the Android app
val androidPlayStoreCountry: MutableState<String?> = mutableStateOf(null)
class FifoQueue<E>(private var capacity: Int) : LinkedList<E>() {
override fun add(element: E): Boolean {
if (size > capacity) removeFirstOrNull()
@@ -29,7 +29,11 @@ interface PlatformInterface {
fun androidRestartNetworkObserver() {}
fun androidCreateActiveCallState(): Closeable = Closeable { }
fun androidIsXiaomiDevice(): Boolean = false
// Requests the Google Play account country into [androidPlayStoreCountry]
fun androidLoadPlayStoreCountry() {}
val androidApiLevel: Int? get() = null
// The build distributed via Google Play, which has to follow its policies
val androidIsPlayStoreBuild: Boolean get() = false
@Composable fun androidLockPortraitOrientation() {}
suspend fun androidAskToAllowBackgroundCalls(): Boolean = true
@Composable fun desktopShowAppUpdateNotice() {}
@@ -502,14 +502,17 @@ fun ChatView(
groupMembersJob = scope.launch(Dispatchers.Default) {
val r = chatModel.controller.apiGroupMemberInfo(chatRh, groupInfo.groupId, member.groupMemberId)
val stats = r?.second
val (_, code) = if (member.memberActive) {
val (updatedMember, code) = if (member.memberActive) {
val memCode = chatModel.controller.apiGetGroupMemberCode(chatRh, groupInfo.apiId, member.groupMemberId)
member to memCode?.second
(memCode?.first ?: r?.first ?: member) to memCode?.second
} else {
member to null
(r?.first ?: member) to null
}
if (!isActive || chatModel.chatId.value != groupInfo.id) return@launch
// members are not loaded in large groups, so only the opened member is added to the model
withContext(Dispatchers.Main) {
chatModel.chatsContext.upsertGroupMember(chatRh, groupInfo, updatedMember)
}
setGroupMembers(chatRh, groupInfo, chatModel)
if (!isActive) return@launch
if (chatsCtx.secondaryContextFilter == null) {
ModalManager.end.closeModals()
@@ -285,7 +285,22 @@ expect fun AttachmentSelection(
)
fun MutableState<ComposeState>.onFilesAttached(uris: List<URI>) {
val groups = uris.groupBy { isImage(it) || isVideoUri(it) }
// The extension is enough to classify every format except .webm, which is just as commonly an
// audio-only container as a video one. An audio-only file has no frame to embed and is sent as a file,
// but that can only be told from the content, so reading it is deferred to a background thread.
// Only done here, where files arrive without the user saying how to send them (drag & drop, paste) -
// an explicitly picked video is still sent as one.
if (uris.none { isWebmUri(it) }) {
attachFiles(uris, emptySet())
} else {
CoroutineScope(Dispatchers.IO).launch {
attachFiles(uris, uris.filter { isWebmUri(it) && hasVideoTrack(it) }.toSet())
}
}
}
private fun MutableState<ComposeState>.attachFiles(uris: List<URI>, webmVideos: Set<URI>) {
val groups = uris.groupBy { isImage(it) || (isVideoUri(it) && (!isWebmUri(it) || it in webmVideos)) }
val media = groups[true] ?: emptyList()
val files = groups[false] ?: emptyList()
if (media.isNotEmpty()) {
@@ -298,9 +313,12 @@ fun MutableState<ComposeState>.onFilesAttached(uris: List<URI>) {
private fun isVideoUri(uri: URI): Boolean {
val name = getFileName(uri)?.lowercase() ?: return false
return name.endsWith(".mov") || name.endsWith(".avi") || name.endsWith(".mp4") ||
name.endsWith(".mpg") || name.endsWith(".mpeg") || name.endsWith(".mkv")
name.endsWith(".mpg") || name.endsWith(".mpeg") || name.endsWith(".mkv") ||
name.endsWith(".webm")
}
private fun isWebmUri(uri: URI): Boolean = getFileName(uri)?.lowercase()?.endsWith(".webm") == true
fun MutableState<ComposeState>.processPickedFile(uri: URI?, text: String?) {
if (uri != null) {
val maxFileSize = value.maxFileSize
@@ -210,7 +210,7 @@ fun CIImageView(
val loaded = res.value
if (loaded != null && file != null) {
val (imageBitmap, data, _) = loaded
SimpleAndAnimatedImageView(data, imageBitmap, file, imageProvider, smallView, @Composable { painter, onClick -> ImageView(painter, image, file.fileSource, onClick) })
SimpleAndAnimatedImageView(data, imageBitmap, file, imageProvider, smallView, blurred, @Composable { painter, onClick -> ImageView(painter, image, file.fileSource, onClick) })
} else {
imageView(previewBitmap, onClick = {
if (file != null) {
@@ -281,5 +281,6 @@ expect fun SimpleAndAnimatedImageView(
file: CIFile?,
imageProvider: () -> ImageGalleryProvider,
smallView: Boolean,
blurred: State<Boolean>,
ImageView: @Composable (painter: Painter, onClick: () -> Unit) -> Unit
)
@@ -23,6 +23,7 @@ import chat.simplex.common.platform.*
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.chat.*
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.chatlist.openChat
import chat.simplex.common.views.newchat.planAndConnect
import chat.simplex.res.MR
import kotlinx.coroutines.Dispatchers
@@ -101,14 +102,35 @@ fun FramedItemView(
}
@Composable
fun FramedItemHeader(caption: String, italic: Boolean, icon: Painter? = null, pad: Boolean = false, iconColor: Color? = null) {
fun HeaderText(caption: String, italic: Boolean, fontSize: TextUnit = 12.sp, modifier: Modifier = Modifier) {
Text(
modifier = modifier,
text = buildAnnotatedString {
withStyle(SpanStyle(fontSize = fontSize, fontStyle = if (italic) FontStyle.Italic else FontStyle.Normal, color = MaterialTheme.colors.secondary)) {
append(caption)
}
},
style = MaterialTheme.typography.body1.copy(lineHeight = 22.sp),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
@Composable
fun headerModifier(pad: Boolean, onClick: (() -> Unit)? = null): Modifier {
val sentColor = MaterialTheme.appColors.sentQuote
val receivedColor = MaterialTheme.appColors.receivedQuote
return Modifier
.background(if (sent) sentColor else receivedColor)
.fillMaxWidth()
.then(if (onClick != null) Modifier.clickable(onClick = onClick) else Modifier)
.padding(start = 8.dp, top = 6.dp, end = 12.dp, bottom = if (pad || (ci.quotedItem == null && ci.meta.itemForwarded == null)) 6.dp else 0.dp)
}
@Composable
fun HeaderRow(modifier: Modifier, caption: String, italic: Boolean, icon: Painter?, iconColor: Color?) {
Row(
Modifier
.background(if (sent) sentColor else receivedColor)
.fillMaxWidth()
.padding(start = 8.dp, top = 6.dp, end = 12.dp, bottom = if (pad || (ci.quotedItem == null && ci.meta.itemForwarded == null)) 6.dp else 0.dp),
modifier,
horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalAlignment = Alignment.CenterVertically
) {
@@ -120,19 +142,15 @@ fun FramedItemView(
tint = iconColor ?: if (isInDarkTheme()) FileDark else FileLight
)
}
Text(
buildAnnotatedString {
withStyle(SpanStyle(fontSize = 12.sp, fontStyle = if (italic) FontStyle.Italic else FontStyle.Normal, color = MaterialTheme.colors.secondary)) {
append(caption)
}
},
style = MaterialTheme.typography.body1.copy(lineHeight = 22.sp),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
HeaderText(caption, italic)
}
}
@Composable
fun FramedItemHeader(caption: String, italic: Boolean, icon: Painter? = null, pad: Boolean = false, iconColor: Color? = null) {
HeaderRow(headerModifier(pad), caption, italic, icon, iconColor)
}
@Composable
fun ciQuoteView(qi: CIQuote) {
val sentColor = MaterialTheme.appColors.sentQuote
@@ -293,8 +311,38 @@ fun FramedItemView(
}
} else {
Header()
if (ci.meta.itemForwarded != null) {
FramedItemHeader(ci.meta.itemForwarded.text(chatInfo.chatType), true, painterResource(MR.images.ic_forward), pad = true)
val forwarded = ci.meta.itemForwarded
if (forwarded != null) {
val twoRowHeader = if (chatInfo.chatType == ChatType.Local) {
forwarded.chatTypeApiIdMsgId != null || forwarded.sourceGroupLink != null
} else {
when (forwarded) {
is CIForwardedFrom.Group -> forwarded.groupType != null
is CIForwardedFrom.GroupLink -> true
else -> false
}
}
if (twoRowHeader) {
val caption = stringResource(if (chatInfo.chatType == ChatType.Local) MR.strings.saved_from else MR.strings.forwarded_from)
Column(
headerModifier(pad = true, onClick = {
val target = forwarded.chatTypeApiIdMsgId
val link = forwarded.sourceGroupLink
if (target != null) {
val (chatType, apiId, itemId) = target
withBGApi { openChat(secondaryChatsCtx = null, chat.remoteHostId, chatType, apiId, itemId) }
} else if (link != null) {
withBGApi { planAndConnect(chat.remoteHostId, link, close = null) }
}
}),
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
HeaderRow(Modifier, caption, true, painterResource(MR.images.ic_forward), null)
HeaderText(forwarded.chatName, italic = false, fontSize = 15.sp, modifier = Modifier.offset(y = (-2).dp))
}
} else {
FramedItemHeader(forwarded.text(chatInfo.chatType), true, painterResource(MR.images.ic_forward), pad = true)
}
}
}
if (ci.file == null && ci.formattedText == null && !ci.meta.isLive && isShortEmoji(ci.content.text)) {
@@ -148,8 +148,6 @@ fun ImageFullScreenView(imageProvider: () -> ImageGalleryProvider, close: () ->
)
}
.fillMaxSize()
// LALAL
// https://github.com/JetBrains/compose-multiplatform/pull/2015/files#diff-841b3825c504584012e1d1c834d731bae794cce6acad425d81847c8bbbf239e0R24
if (media is ProviderMedia.Image) {
val (data: ByteArray, imageBitmap: ImageBitmap) = media
FullScreenImageView(modifier, data, imageBitmap)
@@ -183,6 +183,8 @@ fun ChatListView(chatModel: ChatModel, userPickerState: MutableStateFlow<Animate
val showWhatsNew = shouldShowWhatsNew(chatModel)
val showUpdatedConditions = chatModel.conditions.value.conditionsAction?.shouldShowNotice ?: false
if (showWhatsNew || showUpdatedConditions) {
// Requested here, so that the country is known by the time the modal opens
platform.androidLoadPlayStoreCountry()
delay(1000L)
ModalManager.center.showCustomModal { close -> WhatsNewView(close = close, updatedConditions = showUpdatedConditions) }
}
@@ -753,6 +753,11 @@ private fun saveArchiveFromURI(importedArchiveURI: URI): String? {
if (inputStream != null && archiveName != null) {
val archivePath = "$databaseExportDir${File.separator}$archiveName"
val destFile = File(archivePath)
// resolves symlinks, so it also catches a final component linking outside the folder
if (destFile.canonicalFile.parentFile != databaseExportDir.canonicalFile) {
Log.e(TAG, "saveArchiveFromURI path outside of export folder")
return null
}
Files.copy(inputStream, destFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
archivePath
} else {
@@ -294,6 +294,7 @@ class AlertManager {
nameCaption: String? = null,
subtitle: String? = null,
information: String? = null,
secondaryInformation: Boolean = false,
confirmText: String? = generalGetString(MR.strings.connect_plan_open_chat),
onConfirm: (() -> Unit)? = null,
connectOtherButton: String? = null,
@@ -378,6 +379,7 @@ class AlertManager {
information,
textAlign = TextAlign.Center,
style = MaterialTheme.typography.body2,
color = if (secondaryInformation) MaterialTheme.colors.secondary else Color.Unspecified,
maxLines = 3,
modifier = Modifier.fillMaxWidth()
)
@@ -31,7 +31,8 @@ fun AppBarTitle(
val connection = if (enableAlphaChanges) handler?.connection else null
LaunchedEffect(title) {
if (enableAlphaChanges) {
handler?.title?.value = title
// the app bar shows a single line, so the line breaks of the large title are replaced with spaces
handler?.title?.value = title.replace("\n", " ")
} else {
handler?.connection?.scrollTrackingEnabled = false
}
@@ -495,6 +495,9 @@ fun ciSenderProfile(ci: ChatItem, chatInfo: ChatInfo): LocalProfile? = when (val
expect suspend fun getBitmapFromVideo(uri: URI, timestamp: Long? = null, random: Boolean = true, withAlertOnException: Boolean = true): VideoPlayerInterface.PreviewAndDuration
// Whether the file really contains a video track. Reads container metadata only, without decoding a frame.
expect suspend fun hasVideoTrack(uri: URI): Boolean
fun showWrongUriAlert() {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.non_content_uri_alert_title),
@@ -656,11 +656,24 @@ private fun showOpenKnownGroupAlert(chatModel: ChatModel, rhId: Long?, close: ((
},
nameCaption = planSimplexName?.shortStr,
subtitle = subscriberCount,
information = if (groupInfo.nextConnectPrepared || groupInfo.businessChat != null) {
null
} else {
val isChannel = groupInfo.useRelays
generalGetString(when (groupInfo.membership.memberRole) {
GroupMemberRole.Observer -> if (isChannel) MR.strings.connect_plan_you_are_subscriber else MR.strings.connect_plan_you_are_observer
GroupMemberRole.Moderator -> MR.strings.connect_plan_you_are_moderator
GroupMemberRole.Admin -> MR.strings.connect_plan_you_are_admin
GroupMemberRole.Owner -> MR.strings.connect_plan_you_are_owner
else -> if (isChannel) MR.strings.connect_plan_you_are_contributor else MR.strings.connect_plan_you_are_member
})
},
secondaryInformation = true,
confirmText = generalGetString(
if (groupInfo.useRelays) {
if (groupInfo.nextConnectPrepared) MR.strings.connect_plan_open_new_channel else MR.strings.connect_plan_open_channel
MR.strings.connect_plan_open_channel
} else if (groupInfo.businessChat == null) {
if (groupInfo.nextConnectPrepared) MR.strings.connect_plan_open_new_group else MR.strings.connect_plan_open_group
MR.strings.connect_plan_open_group
} else {
if (groupInfo.nextConnectPrepared) MR.strings.connect_plan_open_new_chat else MR.strings.connect_plan_open_chat
}
@@ -761,7 +774,7 @@ fun showPrepareGroupAlert(
nameCaption = planSimplexName?.shortStr,
subtitle = subscriberCount,
information = ownerVerificationMessage(ownerVerification),
confirmText = generalGetString(if (isChannel) MR.strings.connect_plan_open_new_channel else MR.strings.connect_plan_open_new_group),
confirmText = generalGetString(if (isChannel) MR.strings.connect_plan_open_channel else MR.strings.connect_plan_open_group),
onConfirm = {
AlertManager.privacySensitive.hideAlert()
withBGApi {
@@ -836,7 +836,8 @@ fun strConnectTarget(str: String): ConnectTarget? {
val links = parsedMd.filter { it.format?.isSimplexLink ?: false }
if (links.size == 1) {
val fmt = links[0].format as Format.SimplexLink
return ConnectTarget.Link(links[0].text, fmt.linkType, fmt.simplexLinkText)
val text = if (fmt.showText != null) fmt.simplexUri else links[0].text
return ConnectTarget.Link(text, fmt.linkType, fmt.simplexLinkText)
}
if (links.isEmpty()) {
val nameFt = parsedMd.firstOrNull { it.format is Format.SimplexName }
@@ -1,6 +1,10 @@
package chat.simplex.common.views.onboarding
import androidx.compose.foundation.*
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.calculatePan
import androidx.compose.foundation.gestures.calculateZoom
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
@@ -8,17 +12,41 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.RoundRect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.geometry.toRect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.PointerIcon
import androidx.compose.ui.input.pointer.pointerHoverIcon
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalUriHandler
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import androidx.compose.ui.text.LinkAnnotation
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.withLink
import androidx.compose.ui.text.withStyle
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.common.BuildConfigCommon
import chat.simplex.common.model.ChatController.appPrefs
import chat.simplex.common.model.ChatModel
import chat.simplex.common.model.*
@@ -34,6 +62,7 @@ import chat.simplex.common.views.usersettings.showAddShortLinkAlert
import chat.simplex.res.MR
import dev.icerock.moko.resources.ImageResource
import dev.icerock.moko.resources.StringResource
import kotlin.math.absoluteValue
@Composable
fun ModalData.WhatsNewView(updatedConditions: Boolean = false, viaSettings: Boolean = false, close: () -> Unit) {
@@ -913,9 +942,15 @@ private val versionDescriptions: List<VersionDescription> = listOf(
)
),
VersionDescription(
version = "v7.0",
post = null,
// the trailing space differs from the previously released "v7.0", so that What's new is shown again
version = if (isInUs()) "v7.0.1" else "v7.0",
post = "https://simplex.chat/blog/20260819-simplex-chat-crowdfunding.html",
features = listOf(
VersionFeature.FeatureView(
icon = null,
titleId = MR.strings.v7_0_invest,
view = { modalManager -> InvestInSimpleXChatView(modalManager) }
),
VersionFeature.FeatureDescription(
icon = MR.images.ic_alternate_email,
titleId = MR.strings.v7_0_simplex_names,
@@ -950,6 +985,295 @@ fun shouldShowWhatsNew(m: ChatModel): Boolean {
return v != lastVersion
}
private const val WEFUNDER_URL = "https://wefunder.com/simplex.chat"
private const val CROWDFUNDING_CONTACT_URI = "simplex:/a#JxGcOA1_QhlmVFzYYabloMbvMZk5Y9d9iS3ITDnhzYo?h=smp11.simplex.im"
// the center modal takes the remaining width of the window, so the image is limited to its design width
private val MAX_CROWDFUNDING_IMAGE_WIDTH = DEFAULT_MIN_CENTER_MODAL_WIDTH
// the width of the page images shipped with the desktop app, so that they are never upscaled
private val CROWDFUNDING_PAGE_IMAGE_WIDTH = DEFAULT_MIN_CENTER_MODAL_WIDTH
// the corner radius the images are designed with, and the same radius as a share of their design width
private val CROWDFUNDING_IMAGE_CORNER_RADIUS = 12.dp
private const val CROWDFUNDING_IMAGE_CORNER_RADIUS_RATIO = 0.03f
private class CrowdfundingLayout(
val maxImageWidth: Dp,
val imageShape: Shape,
// the modal manager that shows the page in the center of the window, or null when nothing does
private val centerOfWindow: ModalManager?
) {
fun inCenterOfWindow(modalManager: ModalManager) = modalManager === centerOfWindow
}
// the images are designed for the width of a phone screen, which Android always gives them. On desktop
// they are limited to their own width, and their radius is scaled with them, as they are still shown
// wider than designed: a fixed radius would not only look almost square, but would also leave the corners
// baked into the jpegs visible - they have black behind them, as jpegs have no transparency
private val crowdfundingLayout = if (appPlatform.isDesktop)
CrowdfundingLayout(CROWDFUNDING_PAGE_IMAGE_WIDTH, object : Shape {
override fun createOutline(size: Size, layoutDirection: LayoutDirection, density: Density): Outline =
Outline.Rounded(RoundRect(size.toRect(), CornerRadius(size.width * CROWDFUNDING_IMAGE_CORNER_RADIUS_RATIO)))
}, ModalManager.center)
else
CrowdfundingLayout(Dp.Unspecified, RoundedCornerShape(CROWDFUNDING_IMAGE_CORNER_RADIUS), null)
// Google Play policy restricts promoting investments, so Play builds only show it in the US
@Composable
fun crowdfundingAvailable(): Boolean {
if (!platform.androidIsPlayStoreBuild) return true
if (androidPlayStoreCountry.value == null) {
LaunchedEffect(Unit) {
if (androidPlayStoreCountry.value == null) platform.androidLoadPlayStoreCountry()
}
}
return isInUs()
}
fun isInUs(): Boolean =
androidPlayStoreCountry.value == "US"
|| androidPlayStoreCountry.value == ""
|| androidPlayStoreCountry.value == null
@Composable
private fun InvestInSimpleXChatView(modalManager: ModalManager) {
if (!crowdfundingAvailable()) return
val showGetStake = { modalManager.showModalCloseable(cardScreen = true) { close -> GetStakeView(fromSettings = false, inCenterOfWindow = crowdfundingLayout.inCenterOfWindow(modalManager), close = close) } }
Column(modifier = Modifier.padding(bottom = 12.dp)) {
Text(
generalGetString(MR.strings.v7_0_invest),
style = MaterialTheme.typography.h4,
fontWeight = FontWeight.Medium,
modifier = Modifier.padding(bottom = 6.dp)
)
Text(
buildAnnotatedString {
append(generalGetString(MR.strings.v7_0_invest_descr))
append(" ")
withStyle(SpanStyle(color = MaterialTheme.colors.primary)) {
append(generalGetString(MR.strings.learn_more))
}
},
fontSize = 15.sp,
modifier = Modifier
.pointerHoverIcon(PointerIcon.Hand)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = showGetStake
)
)
if (BuildConfigCommon.SIMPLEX_ASSETS) {
Image(
painterResource(MR.images.crowdfunding_1),
contentDescription = null,
contentScale = ContentScale.FillWidth,
modifier = Modifier
.padding(top = 8.dp)
.widthIn(max = MAX_CROWDFUNDING_IMAGE_WIDTH)
.fillMaxWidth()
.clip(crowdfundingLayout.imageShape)
.pointerHoverIcon(PointerIcon.Hand)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = showGetStake
)
)
}
}
}
private class CrowdfundingSlide(
val image: ImageResource,
val heading: String,
val info: String?,
val text: String,
)
// not localized: the page is only shown to US investors, and the text duplicates the images
private val getStakeSlides: List<CrowdfundingSlide> = listOf(
CrowdfundingSlide(
MR.images.crowdfunding_1,
"The first and the only messaging network without any user IDs",
null,
"By investing, you can benefit from the company growth, and help us build the future of private and secure communications."
),
CrowdfundingSlide(
MR.images.crowdfunding_2,
"480,000+ users joined on their own",
null,
"SimpleX users have been more than doubling every year without any paid marketing, and donated over \$650,000."
),
CrowdfundingSlide(
MR.images.crowdfunding_3,
"Developers already bet on SimpleX success",
"Independent developers created moderation and AI bots, Telegram bridges, and a public server registry.",
"Every service developers build on SimpleX Network may increase its value, and bring new users to SimpleX Chat."
),
CrowdfundingSlide(
MR.images.crowdfunding_4,
"Revenue plan: free for users, channels & businesses pay",
"SimpleX Chat plans to earn from the infrastructure and services that creators, businesses and large communities need as they grow.",
"Read about how we plan to make SimpleX Chat and network profitable, and about all the investment terms on Wefunder."
),
)
@Composable
fun GetStakeView(fromSettings: Boolean, inCenterOfWindow: Boolean = false, close: () -> Unit) {
val uriHandler = LocalUriHandler.current
val stopped = chatModel.chatRunning.value == false
@Composable
fun slideImage(slide: CrowdfundingSlide) {
if (BuildConfigCommon.SIMPLEX_ASSETS) {
Image(
painterResource(slide.image),
contentDescription = null,
contentScale = ContentScale.FillWidth,
modifier = Modifier
.widthIn(max = crowdfundingLayout.maxImageWidth)
.fillMaxWidth()
.clip(crowdfundingLayout.imageShape)
.fullScreenOnClick(slide.image)
)
} else {
Text(slide.heading, style = MaterialTheme.typography.h4, fontWeight = FontWeight.Medium)
if (slide.info != null) {
Text(slide.info, Modifier.padding(top = 4.dp), lineHeight = 24.sp)
}
}
}
ColumnWithScrollBar(Modifier.pinchZoom().padding(horizontal = DEFAULT_PADDING)) {
// in the center of the window the page is wide enough for the title to fit on one line
val title = "Get a stake in\nSimpleX Chat"
AppBarTitle(if (inCenterOfWindow) title.replace("\n", " ") else title, withPadding = false)
// What's new already shows the image of the first slide, above the link that opens this page
if (fromSettings) {
slideImage(getStakeSlides[0])
}
Text(
buildAnnotatedString {
append(getStakeSlides[0].text)
// only the link is clickable, the rest of the paragraph is not
withLink(LinkAnnotation.Url(WEFUNDER_URL) { uriHandler.openUriCatching(WEFUNDER_URL) }) {
withStyle(SpanStyle(color = MaterialTheme.colors.primary, fontWeight = FontWeight.Bold)) {
append(" Learn more and invest on Wefunder.")
}
}
},
Modifier.padding(top = if (fromSettings) 8.dp else 0.dp),
lineHeight = 24.sp
)
getStakeSlides.drop(1).forEach { slide ->
Column(Modifier.padding(top = DEFAULT_PADDING * 1.5f)) {
slideImage(slide)
Text(slide.text, Modifier.padding(top = 8.dp), lineHeight = 24.sp)
}
}
Column(
Modifier.fillMaxWidth().padding(top = DEFAULT_PADDING * 2),
horizontalAlignment = Alignment.CenterHorizontally
) {
OnboardingActionButton(
if (appPlatform.isAndroid) Modifier.fillMaxWidth() else Modifier.widthIn(min = 300.dp),
labelId = MR.strings.v7_0_invest_learn_more,
onboarding = null,
onclick = { uriHandler.openUriCatching(WEFUNDER_URL) }
)
if (!chatModel.desktopNoUserNoRemote) {
TextButtonBelowOnboardingButton(
"or ask SimpleX team",
onClick = if (stopped) null else ({
close()
uriHandler.openVerifiedSimplexUri(CROWDFUNDING_CONTACT_URI)
})
)
}
}
}
}
// there is no pinch gesture with a mouse, so on desktop a slide is opened full screen instead
@Composable
private fun Modifier.fullScreenOnClick(image: ImageResource): Modifier {
if (!appPlatform.isDesktop) return this
return pointerHoverIcon(PointerIcon.Hand).clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null
) {
ModalManager.fullscreen.showCustomModal { close ->
BackHandler(onBack = close)
Box(
Modifier
.fillMaxSize()
.background(Color.Black)
.clickable(interactionSource = remember { MutableInteractionSource() }, indication = null, onClick = close),
contentAlignment = Alignment.Center
) {
Image(painterResource(image), contentDescription = null, contentScale = ContentScale.Fit, modifier = Modifier.fillMaxSize())
}
}
}
}
private const val MAX_PAGE_ZOOM = 5f
/**
* The slide images contain small text that is unreadable at screen width, so the page can be pinch-zoomed.
* Android only: pinch is unavailable with a mouse.
*/
@Composable
private fun Modifier.pinchZoom(): Modifier {
if (!appPlatform.isAndroid) return this
var scale by remember { mutableStateOf(1f) }
var offsetX by remember { mutableStateOf(0f) }
var offsetY by remember { mutableStateOf(0f) }
var size by remember { mutableStateOf(IntSize.Zero) }
return this
.onGloballyPositioned { size = it.size }
.graphicsLayer {
scaleX = scale
scaleY = scale
translationX = offsetX
translationY = offsetY
}
.pointerInput(Unit) {
awaitEachGesture {
// the initial pass, as the scroll of the same column is applied after this modifier and would take the gesture first
awaitFirstDown(requireUnconsumed = false, pass = PointerEventPass.Initial)
var taken: Boolean? = null
do {
val event = awaitPointerEvent(PointerEventPass.Initial)
val multiTouch = event.changes.count { it.pressed } > 1
if (multiTouch || scale > 1f) {
scale = (scale * event.calculateZoom()).coerceIn(1f, MAX_PAGE_ZOOM)
val pan = event.calculatePan()
// the page is scaled around its center, so it can be panned by half of the overflow in each direction
val maxX = size.width * (scale - 1f) / 2
val maxY = size.height * (scale - 1f) / 2
val pannedY = offsetY + pan.y * scale
// the clamp is applied even when the gesture is not taken: at scale 1 both bounds
// are 0, which resets the offsets after zooming back out
offsetX = (offsetX + pan.x * scale).coerceIn(-maxX, maxX)
offsetY = pannedY.coerceIn(-maxY, maxY)
// two fingers always mean zoom, taken without a touch slop: waiting for one would let
// the scroll reach its own slop first and scroll the page. A one finger drag is left
// to the scroll at the edges, decided once so it cannot alternate mid drag
if (multiTouch) taken = true
else if (taken == null && pan.y != 0f) taken = pannedY.absoluteValue < maxY
if (taken == true) event.changes.forEach { if (it.pressed) it.consume() }
}
} while (event.changes.any { it.pressed })
}
}
}
@Composable
fun CreateUpdateAddressShortLinkView(modalManager: ModalManager) {
val clipboard = LocalClipboardManager.current
@@ -87,13 +87,19 @@ fun PrivacySettingsView(
val currentUser = chatModel.currentUser.value
if (currentUser != null && !chatModel.desktopNoUserNoRemote) {
SectionDividerSpaced()
ContacRequestsFromGroupsSection(
AutoAcceptSection(
currentUser = currentUser,
setAutoAcceptGrpDirectInvs = { enable ->
setAutoAcceptMemberContacts = { enable ->
withApi {
chatModel.controller.apiSetUserAutoAcceptMemberContacts(currentUser, enable)
chatModel.currentUser.value = currentUser.copy(autoAcceptMemberContacts = enable)
}
},
setAutoAcceptGroupInvitations = { enable ->
withApi {
chatModel.controller.apiSetUserAutoAcceptGroupInvitations(currentUser, enable)
chatModel.currentUser.value = currentUser.copy(autoAcceptGroupInvitations = enable)
}
}
)
}
@@ -333,16 +339,26 @@ expect fun PrivacyDeviceSection(
)
@Composable
private fun ContacRequestsFromGroupsSection(
private fun AutoAcceptSection(
currentUser: User,
setAutoAcceptGrpDirectInvs: (Boolean) -> Unit
setAutoAcceptMemberContacts: (Boolean) -> Unit,
setAutoAcceptGroupInvitations: (Boolean) -> Unit
) {
SectionView(stringResource(MR.strings.settings_section_title_contact_requests_from_groups)) {
SettingsActionItemWithContent(painterResource(MR.images.ic_check), stringResource(MR.strings.auto_accept_contact)) {
// legacy string key names, reused for their values so this section stays translated
SectionView(stringResource(MR.strings.auto_accept_contact)) {
SettingsActionItemWithContent(painterResource(MR.images.ic_person), stringResource(MR.strings.settings_section_title_contact_requests_from_groups)) {
DefaultSwitch(
checked = currentUser.autoAcceptMemberContacts,
onCheckedChange = { enable ->
setAutoAcceptGrpDirectInvs(enable)
setAutoAcceptMemberContacts(enable)
}
)
}
SettingsActionItemWithContent(painterResource(MR.images.ic_group), stringResource(MR.strings.group_invitations)) {
DefaultSwitch(
checked = currentUser.autoAcceptGroupInvitations,
onCheckedChange = { enable ->
setAutoAcceptGroupInvitations(enable)
}
)
}
@@ -350,7 +366,7 @@ private fun ContacRequestsFromGroupsSection(
SectionTextFooter(
remember(currentUser.displayName) {
buildAnnotatedString {
append(generalGetString(MR.strings.this_setting_is_for_your_current_profile) + " ")
append(generalGetString(MR.strings.these_settings_are_for_your_current_profile) + " ")
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
append(currentUser.displayName)
}
@@ -387,7 +403,7 @@ private fun DeliveryReceiptsSection(
SectionTextFooter(
remember(currentUser.displayName) {
buildAnnotatedString {
append(generalGetString(MR.strings.receipts_section_description) + " ")
append(generalGetString(MR.strings.these_settings_are_for_your_current_profile) + " ")
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
append(currentUser.displayName)
}
@@ -22,7 +22,6 @@ import dev.icerock.moko.resources.compose.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.*
import chat.simplex.common.BuildConfigCommon
import chat.simplex.common.model.*
import chat.simplex.common.model.ChatController.appPrefs
import chat.simplex.common.platform.*
@@ -30,8 +29,10 @@ import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.database.DatabaseView
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.migration.MigrateFromDeviceView
import chat.simplex.common.views.onboarding.GetStakeView
import chat.simplex.common.views.onboarding.SimpleXInfo
import chat.simplex.common.views.onboarding.WhatsNewView
import chat.simplex.common.views.onboarding.crowdfundingAvailable
import chat.simplex.common.views.usersettings.networkAndServers.NetworkAndServersView
import chat.simplex.res.MR
@@ -111,6 +112,17 @@ fun SettingsLayout(
AppShutdownItem()
AppVersionItem(showVersion)
}
if (crowdfundingAvailable()) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.v7_0_invest)) {
SettingsActionItem(
painterResource(MR.images.ic_redeem),
stringResource(MR.strings.v7_0_crowdfunding),
{ ModalManager.start.showModalCloseable(cardScreen = true) { close -> GetStakeView(fromSettings = true, close = close) } }
)
}
}
SectionBottomSpacer()
}
}
@@ -143,7 +155,7 @@ fun HelpAndSupportView(
SectionDividerSpaced()
SectionView(stringResource(MR.strings.settings_section_title_support_project)) {
if (!BuildConfigCommon.ANDROID_BUNDLE) {
if (!platform.androidIsPlayStoreBuild) {
ContributeItem(uriHandler)
}
if (appPlatform.isAndroid) {
@@ -29,7 +29,7 @@
<string name="allow_verb">اسمح</string>
<string name="smp_servers_preset_add">أضِف خوادم مُعدة مسبقًا</string>
<string name="smp_servers_add_to_another_device">أضِف إلى جهاز آخر</string>
<string name="users_delete_all_chats_deleted">سيتم حذف جميع الدردشات والرسائل - لا يمكن التراجع عن هذا!</string>
<string name="users_delete_all_chats_deleted">ستُحذف جميع الدردشات والرسائل - لا يمكن التراجع عن هذا!</string>
<string name="network_enable_socks_info">الوصول إلى الخوادم عبر وسيط SOCKS على المنفذ %d؟ يجب بدء تشغيل الوسيط قبل تفعيل هذا الخيار.</string>
<string name="smp_servers_add">أضف خادم</string>
<string name="network_settings">إعدادات الشبكة المتقدّمة</string>
@@ -44,7 +44,7 @@
<string name="v4_3_improved_server_configuration_desc">أضف الخوادم عن طريق مسح رموز QR.</string>
<string name="v4_2_group_links_desc">يمكن للمُدراء إنشاء روابط للانضمام إلى المجموعات.</string>
<string name="accept_connection_request__question">قبول طلب الاتصال؟</string>
<string name="clear_chat_warning">سيتم حذف جميع الرسائل - لا يمكن التراجع عن هذا! سيتم حذف الرسائل فقط من أجلك.</string>
<string name="clear_chat_warning">ستُحذف كل الرسائل - لا يمكن التراجع عن هذا! ستُحذف الرسائل فقط من أجلك.</string>
<string name="callstatus_accepted">قُبلت المكالمة</string>
<string name="allow_calls_only_if">اسمح بالمكالمات فقط إذا سمحت جهة اتصالك بذلك.</string>
<string name="allow_message_reactions_only_if">اسمح بردود الفعل على الرسائل فقط إذا سمحت جهة اتصالك بذلك.</string>
@@ -686,7 +686,7 @@
<string name="v5_2_favourites_filter_descr">تصفية الدردشات غير المقروءة والمفضلة.</string>
<string name="v5_2_favourites_filter">البحث عن الدردشات بشكل أسرع</string>
<string name="enable_receipts_all">فعّل</string>
<string name="v5_2_disappear_one_message_descr">حتى عندما يتم تعطيله في المحادثة.</string>
<string name="v5_2_disappear_one_message_descr">حتى عندما تُعطّل في المحادثة.</string>
<string name="v5_2_fix_encryption_descr">إصلاح التعمية بعد استعادة النُسخ الاحتياطية.</string>
<string name="v5_2_disappear_one_message">اجعل رسالة واحدة تختفي</string>
<string name="error_enabling_delivery_receipts">خطأ في تفعيل إيصالات التسليم!</string>
@@ -1106,7 +1106,7 @@
<string name="tap_to_activate_profile">انقر لتنشيط ملف التعريف.</string>
<string name="v4_5_transport_isolation">عزل النقل</string>
<string name="this_string_is_not_a_connection_link">هذه السلسلة ليست رابط اتصال!</string>
<string name="receipts_section_description">هذه الإعدادات لملف تعريفك الحالي</string>
<string name="these_settings_are_for_your_current_profile">هذه الإعدادات لملف تعريفك الحالي</string>
<string name="receipts_section_description_1">يمكن تجاوزها في إعدادات الاتصال والمجموعة.</string>
<string name="network_option_tcp_connection_timeout">انتهت مهلة اتصال TCP</string>
<string name="v4_5_private_filenames_descr">لحماية المنطقة الزمنية، تستخدم ملفات الصور / الصوت التوقيت العالمي المنسق (UTC).</string>
@@ -1219,6 +1219,13 @@
<string name="update_network_settings_question">تحديث إعدادات الشبكة؟</string>
<string name="updating_settings_will_reconnect_client_to_all_servers">سيؤدي تحديث الإعدادات إلى إعادة توصيل العميل بجميع الخوادم.</string>
<string name="you_are_observer">أنت المراقب</string>
<string name="connect_plan_you_are_observer">أنت المراقب</string>
<string name="connect_plan_you_are_member">أنت عضو</string>
<string name="connect_plan_you_are_moderator">أنت مُشرف</string>
<string name="connect_plan_you_are_admin">أنت المُدير</string>
<string name="connect_plan_you_are_owner">أنت المالك</string>
<string name="connect_plan_you_are_subscriber">أنت مشترك</string>
<string name="connect_plan_you_are_contributor">أنت مساهم</string>
<string name="you_are_invited_to_group">أنت مدعو إلى المجموعة</string>
<string name="callstate_waiting_for_confirmation">في انتظار التأكيد…</string>
<string name="unknown_database_error_with_info">خطأ غير معروف في قاعدة البيانات: %s</string>
@@ -1566,7 +1573,7 @@
<string name="v5_5_simpler_connect_ui_descr">يقبل شريط البحث روابط الدعوة.</string>
<string name="v5_5_message_delivery">تحسّن تسليم الرسائل</string>
<string name="v5_5_message_delivery_descr">مع انخفاض استخدام البطارية.</string>
<string name="clear_note_folder_warning">سيتم حذف كافة الرسائل - لا يمكن التراجع عن هذا!</string>
<string name="clear_note_folder_warning">ستُحذف كل الرسائل - لا يمكن التراجع عن هذا!</string>
<string name="info_row_created_at">أُنشئ في</string>
<string name="v5_5_new_interface_languages">واجهة المستخدم المجرية والتركية</string>
<string name="v5_5_simpler_connect_ui">الصق الرابط للاتصال!</string>
@@ -1710,7 +1717,7 @@
<string name="recipients_can_not_see_who_message_from">لا يستطيع المُستلم/ون معرفة مَن أرسل هذه الرسالة.</string>
<string name="saved_description">حُفظت</string>
<string name="saved_from_chat_item_info_title">حُفظت مِن</string>
<string name="saved_from_description">حُفظت مِن %s</string>
<string name="saved_from">حُفظت مِن</string>
<string name="audio_device_speaker">السماعة</string>
<string name="audio_device_earpiece">سماعة الأذن</string>
<string name="audio_device_wired_headphones">سماعات الرأس</string>
@@ -2184,7 +2191,7 @@
<string name="add_your_team_members_to_conversations">أضف أعضاء فريقك إلى المحادثات.</string>
<string name="direct_messages_are_prohibited_in_chat">يُمنع إرسال الرسائل المباشرة بين الأعضاء في هذه الدردشة.</string>
<string name="xiaomi_ignore_battery_optimization"><![CDATA[<b>أجهزة Xiaomi</b>: يُرجى تفعيل التشغيل التلقائي (Autostart) في إعدادات النظام لكي تعمل الإشعارات.]]></string>
<string name="all_message_and_files_e2e_encrypted"><![CDATA[يتم إرسال جميع الرسائل والملفات <b>مُعمَّاة بين الطرفين</b>، مع أمان ما بعد الكم في الرسائل المباشرة.]]></string>
<string name="all_message_and_files_e2e_encrypted"><![CDATA[تُرسل جميع الرسائل والملفات <b>مُعمَّاة بين الطرفين</b>، مع أمان ما بعد الكم في الرسائل المباشرة.]]></string>
<string name="onboarding_notifications_mode_periodic_desc_short">تحقق من الرسائل كل 10 دقائق</string>
<string name="direct_messages_are_prohibited">يُمنع إرسال الرسائل المباشرة بين الأعضاء.</string>
<string name="info_row_chat">الدردشة</string>
@@ -2247,7 +2254,7 @@
<string name="error_creating_chat_tags">خطأ في إنشاء قائمة الدردشة</string>
<string name="chat_list_businesses">الشركات</string>
<string name="error_loading_chat_tags">خطأ في تحميل قوائم الدردشة</string>
<string name="delete_chat_list_warning">سيتم إزالة جميع المحادثات من القائمة %s، وسيتم حذف القائمة</string>
<string name="delete_chat_list_warning">ستُزال جميع المحادثات من القائمة %s، وستُحذف القائمة</string>
<string name="create_list">أنشئ قائمة</string>
<string name="error_updating_chat_tags">خطأ في تحديث قائمة الدردشة</string>
<string name="chat_list_notes">الملحوظات</string>
@@ -2255,7 +2262,7 @@
<string name="change_order_chat_list_menu_action">تغيير الترتيب</string>
<string name="prefs_error_saving_settings">خطأ في حفظ الإعدادات</string>
<string name="error_creating_report">خطأ في إنشاء بلاغ</string>
<string name="report_item_visibility_submitter">أنت والمشرفون فقط هم من يرون ذلك</string>
<string name="report_item_visibility_submitter">أنت والمُشرفون فقط هم من يرون ذلك</string>
<string name="report_item_archived">بلاغ مؤرشف</string>
<string name="report_item_visibility_moderators">لا يراه إلا المُرسِل والمُشرفين</string>
<string name="archive_verb">أرشف</string>
@@ -2269,15 +2276,15 @@
<string name="group_reports_active_one">1 بلاغ</string>
<string name="group_reports_active">%d بلاغات</string>
<string name="group_reports_member_reports">بلاغات الأعضاء</string>
<string name="report_compose_reason_header_illegal">بلّغ عن المحتوى: سيراه مشرفو المجموعة فقط.</string>
<string name="report_compose_reason_header_other">بلّغ عن أُخرى: سيراه مشرفو المجموعة فقط.</string>
<string name="group_member_role_moderator">مشرف</string>
<string name="report_compose_reason_header_illegal">بلّغ عن المحتوى: سيراه مُشرفو المجموعة فقط.</string>
<string name="report_compose_reason_header_other">بلّغ عن أُخرى: سيراه مُشرفو المجموعة فقط.</string>
<string name="group_member_role_moderator">مُشرف</string>
<string name="report_item_archived_by">بلاغ مؤرشف بواسطة %s</string>
<string name="report_compose_reason_header_profile">بلّغ عن ملف تعريف العضو: سيراه مشرفو المجموعة فقط.</string>
<string name="report_compose_reason_header_profile">بلّغ عن ملف تعريف العضو: سيراه مُشرفو المجموعة فقط.</string>
<string name="report_reason_community">انتهاك إرشادات المجتمع</string>
<string name="report_reason_illegal">محتوى غير لائق</string>
<string name="report_compose_reason_header_community">بلّغ عن مخالفة: سيراه مشرفو المجموعة فقط.</string>
<string name="report_compose_reason_header_spam">بلّغ عن إزعاج (spam): سيراه مشرفو المجموعة فقط.</string>
<string name="report_compose_reason_header_community">بلّغ عن مخالفة: سيراه مُشرفو المجموعة فقط.</string>
<string name="report_compose_reason_header_spam">بلّغ عن إزعاج (spam): سيراه مُشرفو المجموعة فقط.</string>
<string name="report_archive_alert_title">أرشفة البلاغ؟</string>
<string name="report_reason_alert_title">سبب الإبلاغ؟</string>
<string name="report_archive_alert_desc">سيتم أرشفة البلاغ لك.</string>
@@ -2307,14 +2314,14 @@
<string name="mute_all_chat">اكتم الكل</string>
<string name="unread_mentions">ذّكورات غير مقروءة</string>
<string name="max_group_mentions_per_message_reached">يمكنك ذكر ما يصل إلى %1$s من الأعضاء في الرسالة الواحدة!</string>
<string name="enable_sending_member_reports">السماح بالإبلاغ عن الرسائل إلى المشرفين.</string>
<string name="disable_sending_member_reports">امنع الإبلاغ عن الرسائل للمشرفين.</string>
<string name="enable_sending_member_reports">السماح بالإبلاغ عن الرسائل إلى المُشرفين.</string>
<string name="disable_sending_member_reports">امنع الإبلاغ عن الرسائل للمُشرفين.</string>
<string name="report_archive_alert_title_all">أرشفة كافة البلاغات؟</string>
<string name="archive_reports">أرشف البلاغات</string>
<string name="report_archive_for_all_moderators">لكل المشرفين</string>
<string name="report_archive_for_all_moderators">لكل المُشرفين</string>
<string name="report_archive_for_me">لي</string>
<string name="notification_group_report">بلاغ: %s</string>
<string name="group_members_can_send_reports">يمكن للأعضاء الإبلاغ عن الرسائل إلى المشرفين.</string>
<string name="group_members_can_send_reports">يمكن للأعضاء الإبلاغ عن الرسائل إلى المُشرفين.</string>
<string name="report_archive_alert_desc_all">سيتم أرشفة كافة البلاغات لك.</string>
<string name="report_archive_alert_title_nth">أرشفة %d بلاغ؟</string>
<string name="member_reports_are_prohibited">يُمنع الإبلاغ عن الرسائل في هذه المجموعة.</string>
@@ -2343,7 +2350,7 @@
<string name="unblock_members_desc">سيتم عرض رسائل من هؤلاء الأعضاء!</string>
<string name="restore_passphrase_can_not_be_read_enter_manually_desc">لا يمكن قراءة عبارة المرور في Keystore، يُرجى إدخالها يدويًا. قد يكون هذا قد حدث بعد تحديث النظام غير متوافق مع التطبيق. إذا لم يكن الأمر كذلك، فيُرجى التواصل مع المطوِّرين.</string>
<string name="members_will_be_removed_from_group_cannot_be_undone">سيتم إزالة الأعضاء من المجموعة - لا يمكن التراجع عن هذا!</string>
<string name="feature_roles_moderators">المشرفين</string>
<string name="feature_roles_moderators">المُشرفين</string>
<string name="restore_passphrase_can_not_be_read_desc">لا يمكن قراءة عبارة المرور في Keystore. قد يكون هذا قد حدث بعد تحديث النظام غير متوافق مع التطبيق. إذا لم يكن الأمر كذلك، فيُرجى التواصل مع المطوِّرين.</string>
<string name="group_member_status_pending_approval">موافقة الانتظار</string>
<string name="onboarding_conditions_privacy_policy_and_conditions_of_use">سياسة الخصوصية وشروط الاستخدام.</string>
@@ -2364,7 +2371,7 @@
<string name="group_new_support_chats_short">%d دردشة/ات</string>
<string name="group_new_support_chats">%d دردشات مع الأعضاء</string>
<string name="group_new_support_messages">%d رسائل</string>
<string name="report_sent_alert_title">أُرسِل البلاغ للمشرفين</string>
<string name="report_sent_alert_title">أُرسِل البلاغ للمُشرفين</string>
<string name="report_sent_alert_msg_view_in_support_chat">يمكنك عرض تقاريرك في \"دردش مع المُدراء\".</string>
<string name="accept_pending_member_alert_confirmation_as_observer">اقبل كمراقب</string>
<string name="cant_send_message_contact_deleted">حُذفت جهة الاتصال</string>
@@ -2375,7 +2382,7 @@
<string name="rcv_group_event_member_accepted">قبلت %1$s</string>
<string name="rcv_group_event_user_accepted">قبِلك</string>
<string name="snd_group_event_member_accepted">لقد قبلت هذا العضو.</string>
<string name="snd_group_event_user_pending_review">الرجاء الانتظار ريثما يراجع مشرفو المجموعة طلبك للانضمام إليها.</string>
<string name="snd_group_event_user_pending_review">الرجاء الانتظار ريثما يراجع مُشرفو المجموعة طلبك للانضمام إليها.</string>
<string name="button_support_chat">دردش مع المُدراء</string>
<string name="admission_stage_review">راجع الأعضاء</string>
<string name="member_criteria_off">غير مفعّل</string>
@@ -2445,7 +2452,7 @@
<string name="v6_4_connect_faster">اتصل بشكل أسرع! 🚀</string>
<string name="v6_4_message_delivery_descr">تقليل حركة البيانات على شبكات الجوّال.</string>
<string name="v6_4_connect_faster_descr">راسل فورًا بمجرد النقر على \"اتصل\".</string>
<string name="v6_4_role_moderator">دور جديد للمجموعة: مشرف</string>
<string name="v6_4_role_moderator">دور جديد للمجموعة: مُشرف</string>
<string name="private_routing_no_session">لا توجد جلسة توجيه خاصة</string>
<string name="private_routing_timeout">انتهت مهلة التوجيه الخاص</string>
<string name="network_option_protocol_timeout_background">انتهت مهلة خلفية البروتوكول</string>
@@ -2746,7 +2753,7 @@
<string name="group_members_can_add_message_reactions_channel">يمكن للمشتركين إضافة ردود الفعل على الرسائل.</string>
<string name="members_can_chat_with_admins_channel">يمكن للمشتركين الدردشة مع المُدراء.</string>
<string name="group_members_can_delete_channel">يمكن للمشتركين حذف الرسائل المُرسلة نهائيًا. (24 ساعة)</string>
<string name="group_members_can_send_reports_channel">يمكن للمشتركين الإبلاغ عن الرسائل للمشرفين.</string>
<string name="group_members_can_send_reports_channel">يمكن للمشتركين الإبلاغ عن الرسائل للمُشرفين.</string>
<string name="group_members_can_send_dms_channel">يمكن للمشتركين إرسال رسائل مباشرة.</string>
<string name="group_members_can_send_disappearing_channel">يمكن للمشتركين إرسال رسائل تختفي.</string>
<string name="group_members_can_send_files_channel">يمكن للمشتركين إرسال الملفات والوسائط.</string>
@@ -2878,7 +2885,7 @@
<string name="connect_plan_join_name">انضم للقناة %s</string>
<string name="message_signatures_are_not_required">توقيع الرسالة ليس إلزاميًا.</string>
<string name="message_signatures_are_required">مطلوب توقيع الرسالة.</string>
<string name="register_test_name">سجِّل اسم اختبار</string>
<string name="register_test_name">كيفية تسجيل اسم اختبار</string>
<string name="remove_name">أزِل الاسم</string>
<string name="require_message_signatures">تطلب توقيع الرسائل.</string>
<string name="save_simplex_name_question">احفظ اسم SimpleX؟</string>
@@ -2902,8 +2909,8 @@
<string name="v7_0_channels_previews">أنشئ معاينة الويب.</string>
<string name="v7_0_channels_wider_messages">أسهل في القراءة.</string>
<string name="v7_0_channels_relays">أدِر مُرحلاتك.</string>
<string name="v7_0_simplex_names">أسماء SimpleX (تجريبي)</string>
<string name="v7_0_simplex_names_descr">أسماء لقناتك أو لشركتك.</string>
<string name="v7_0_simplex_names">أسماء SimpleX العامة (تجريبي)</string>
<string name="v7_0_simplex_names_descr">الأسماء العامة لقناتك أو لشركتك.</string>
<string name="info_row_file_servers">خوادم الملفات</string>
<string name="share_text_file_servers">خوادم الملفات: %s</string>
</resources>
@@ -20,6 +20,11 @@
<string name="connect_plan_open_new_chat">Open new chat</string>
<string name="connect_plan_open_group">Open group</string>
<string name="connect_plan_open_new_group">Open new group</string>
<string name="connect_plan_you_are_observer">You are an observer</string>
<string name="connect_plan_you_are_member">You are a member</string>
<string name="connect_plan_you_are_moderator">You are a moderator</string>
<string name="connect_plan_you_are_admin">You are an admin</string>
<string name="connect_plan_you_are_owner">You are an owner</string>
<string name="error_parsing_uri_title">Invalid link</string>
<string name="error_parsing_uri_desc">Please check that SimpleX link is correct.</string>
@@ -65,8 +70,9 @@
<string name="live">LIVE</string>
<string name="moderated_description">moderated</string>
<string name="forwarded_description">forwarded</string>
<string name="forwarded_from">forwarded from</string>
<string name="saved_description">saved</string>
<string name="saved_from_description">saved from %s</string>
<string name="saved_from">saved from</string>
<string name="invalid_chat">invalid chat</string>
<string name="invalid_data">invalid data</string>
<string name="error_showing_message">error showing message</string>
@@ -1206,6 +1212,7 @@
<string name="stop_sharing_address">Stop sharing address?</string>
<string name="stop_sharing">Stop sharing</string>
<string name="auto_accept_contact">Auto-accept</string>
<string name="group_invitations">Group invitations</string>
<string name="sent_to_your_contact_after_connection">Sent to your contact after connection.</string>
<string name="address_welcome_message">Welcome message</string>
<string name="enter_welcome_message_optional">Enter welcome message… (optional)</string>
@@ -1557,7 +1564,7 @@
<string name="if_you_enter_passcode_data_removed">If you enter this passcode when opening the app, all app data will be irreversibly removed!</string>
<string name="set_passcode">Set passcode</string>
<string name="this_setting_is_for_your_current_profile">This setting is for your current profile</string>
<string name="receipts_section_description">These settings are for your current profile</string>
<string name="these_settings_are_for_your_current_profile">These settings are for your current profile</string>
<string name="receipts_section_description_1">They can be overridden in contact and group settings.</string>
<string name="receipts_section_contacts">Contacts</string>
<string name="receipts_contacts_title_enable">Enable receipts?</string>
@@ -1602,7 +1609,7 @@
<string name="settings_section_title_chats">Chats</string>
<string name="settings_section_title_files">Files</string>
<string name="settings_section_title_delivery_receipts">Send delivery receipts to</string>
<string name="settings_section_title_contact_requests_from_groups">Contact requests from groups</string>
<string name="settings_section_title_contact_requests_from_groups">Contact requests in groups</string>
<string name="settings_section_title_about">About</string>
<string name="settings_section_title_contact">Contact</string>
<string name="settings_section_title_support_project">Support the project</string>
@@ -2736,6 +2743,10 @@
<string name="v6_5_safe_web_links_descr">- opt-in to send link previews.\n- use SOCKS proxy if enabled.\n- prevent hyperlink phishing.\n- remove link tracking.</string>
<string name="v6_5_non_profit_governance">Non-profit governance</string>
<string name="v6_5_non_profit_governance_descr">To make SimpleX Network last.</string>
<string name="v7_0_invest" translatable="false">You can now invest in SimpleX Chat! 🚀</string>
<string name="v7_0_invest_descr" translatable="false">Crowdfunding on Wefunder.</string>
<string name="v7_0_crowdfunding" translatable="false">Crowdfunding on Wefunder</string>
<string name="v7_0_invest_learn_more" translatable="false">Learn more on Wefunder</string>
<string name="v7_0_simplex_names">SimpleX public names (BETA)</string>
<string name="v7_0_simplex_names_descr">Public names for your channel or business.</string>
<string name="v7_0_channels">Better channels 📢</string>
@@ -3165,6 +3176,8 @@
<string name="relay_address_alert_message">This is a chat relay address, it cannot be used to connect.</string>
<string name="connect_plan_open_channel">Open channel</string>
<string name="connect_plan_open_new_channel">Open new channel</string>
<string name="connect_plan_you_are_subscriber">You are a subscriber</string>
<string name="connect_plan_you_are_contributor">You are a contributor</string>
<string name="connect_plan_this_is_your_link_for_channel">Your channel</string>
<string name="connect_plan_this_is_your_link_for_channel_vName"><![CDATA[This is your link for channel <b>%1$s</b>!]]></string>
<string name="error_opening_channel">Error opening channel</string>
@@ -481,7 +481,7 @@
<string name="enter_correct_passphrase">Въведи правилна парола.</string>
<string name="feature_enabled_for_you">активирано за вас</string>
<string name="enter_password_to_show">Въведи парола в търсенето</string>
<string name="receipts_section_description">Тези настройки са за текущия ви профил</string>
<string name="these_settings_are_for_your_current_profile">Тези настройки са за текущия ви профил</string>
<string name="receipts_section_description_1">Те могат да бъдат променени в настройките за всеки контакт и група.</string>
<string name="settings_developer_tools">Инструменти за разработчици</string>
<string name="receipts_contacts_disable_for_all">Деактивиране за всички</string>
@@ -1301,6 +1301,11 @@
<string name="auth_unlock">Отключи</string>
<string name="auth_you_will_be_required_to_authenticate_when_you_start_or_resume">Ще трябва да се идентифицирате, когато стартирате или възобновите приложението след 30 секунди във фонов режим.</string>
<string name="you_are_observer">вие сте наблюдател</string>
<string name="connect_plan_you_are_observer">Вие сте наблюдател</string>
<string name="connect_plan_you_are_member">Вие сте член</string>
<string name="connect_plan_you_are_moderator">Вие сте модератор</string>
<string name="connect_plan_you_are_admin">Вие сте админ</string>
<string name="connect_plan_you_are_owner">Вие сте собственик</string>
<string name="gallery_video_button">Видео</string>
<string name="you_can_connect_to_simplex_chat_founder"><![CDATA[Можете да <font color="#0088ff">се свържете с разработчиците на SimpleX Chat, за да задавате въпроси и да получавате актуализации</font>;.]]></string>
<string name="contact_wants_to_connect_with_you">иска да се свърже с вас!</string>
@@ -1723,7 +1728,7 @@
<string name="v5_7_forward">Препращане и запазване на съобщения</string>
<string name="v5_7_call_sounds">Звуци по време на разговор</string>
<string name="saved_description">запазено</string>
<string name="saved_from_description">запазено от %s</string>
<string name="saved_from">запазено от</string>
<string name="saved_chat_item_info_tab">Запазено</string>
<string name="saved_from_chat_item_info_title">Запазено от</string>
<string name="recipients_can_not_see_who_message_from">Получателят(ите) не могат да видят от кого е това съобщение.</string>
@@ -23,6 +23,7 @@
<string name="callstatus_accepted">কলটি গৃহীত হয়েছে</string>
<string name="smp_servers_preset_add">পূর্বনির্ধারিত সার্ভারগুলি যুক্ত করুন</string>
<string name="group_member_role_admin">অ্যাডমিন</string>
<string name="connect_plan_you_are_admin">আপনি একজন অ্যাডমিন</string>
<string name="button_add_welcome_message">স্বাগত বার্তা যুক্ত করুন</string>
<string name="users_add">প্রোফাইল যুক্ত করুন</string>
<string name="color_secondary_variant">আনুষঙ্গিক রং</string>
@@ -1573,7 +1573,7 @@
<string name="note_folder_local_display_name">Notes privades</string>
<string name="receiving_files_not_yet_supported">la recepció de fitxers encara no està suportada</string>
<string name="display_name_requested_to_connect">sol·licitada connexió</string>
<string name="saved_from_description">desat des de %s</string>
<string name="saved_from">desat des de</string>
<string name="simplex_link_contact">Adreça de contacte SimpleX</string>
<string name="simplex_link_group">Enllaç de grup SimpleX</string>
<string name="simplex_link_mode">Enllaços SimpleX</string>
@@ -1715,6 +1715,11 @@
<string name="image_decoding_exception_desc">La imatge no es pot descodificar. Si us plau, proveu amb una imatge diferent o contacteu amb els desenvolupadors.</string>
<string name="video_decoding_exception_desc">El vídeo no es pot descodificar. Si us plau, prova amb un vídeo diferent o contacta amb els desenvolupadors.</string>
<string name="you_are_observer">ets observador</string>
<string name="connect_plan_you_are_observer">Ets observador</string>
<string name="connect_plan_you_are_member">Ets membre</string>
<string name="connect_plan_you_are_moderator">Ets moderador</string>
<string name="connect_plan_you_are_admin">Ets administrador</string>
<string name="connect_plan_you_are_owner">Ets propietari</string>
<string name="observer_cant_send_message_title">ets observador(a)</string>
<string name="observer_cant_send_message_desc">Poseu-vos en contacte amb l\'administrador del grup.</string>
<string name="only_owners_can_enable_files_and_media">Només els propietaris del grup poden activar fitxers i mitjans.</string>
@@ -1946,7 +1951,7 @@
<string name="if_you_enter_passcode_data_removed">Si introduïu aquesta contrasenya en obrir l\'aplicació, totes les dades de l\'aplicació s\'eliminaran de manera irreversible.</string>
<string name="if_you_enter_self_destruct_code">Si introduïu el vostre codi d\'autodestrucció mentre obriu l\'aplicació:</string>
<string name="set_passcode">Estableix codi</string>
<string name="receipts_section_description">Aquesta configuració és per al vostre perfil actual</string>
<string name="these_settings_are_for_your_current_profile">Aquesta configuració és per al vostre perfil actual</string>
<string name="receipts_section_description_1">Es pot canviar a la configuració de contacte i grup.</string>
<string name="privacy_media_blur_radius_off">No</string>
<string name="settings_section_title_settings">Configuració</string>
@@ -931,6 +931,11 @@
<string name="moderate_verb">Moderovat</string>
<string name="observer_cant_send_message_desc">Kontaktujte prosím správce skupiny.</string>
<string name="you_are_observer">jste pozorovatel</string>
<string name="connect_plan_you_are_observer">Jste pozorovatel</string>
<string name="connect_plan_you_are_member">Jste člen</string>
<string name="connect_plan_you_are_moderator">Jste moderátor</string>
<string name="connect_plan_you_are_admin">Jste správce</string>
<string name="connect_plan_you_are_owner">Jste vlastník</string>
<string name="group_member_role_observer">pozorovatel</string>
<string name="moderate_message_will_be_deleted_warning">Zpráva bude smazána pro všechny členy.</string>
<string name="moderate_message_will_be_marked_warning">Zpráva bude pro všechny členy označena jako moderovaná.</string>
@@ -1246,7 +1251,7 @@
<string name="snd_conn_event_ratchet_sync_required">vyžadováno opětovné vyjednávání šifrování pro %s</string>
<string name="receipts_contacts_override_disabled">Odesílání potvrzení o doručení je vypnuto pro %d kontakty.</string>
<string name="sending_delivery_receipts_will_be_enabled_all_profiles">Odesílání potvrzení o doručení bude povoleno pro všechny kontakty ve všech viditelných profilech chatu.</string>
<string name="receipts_section_description">Toto nastavení je pro váš aktuální profil</string>
<string name="these_settings_are_for_your_current_profile">Toto nastavení je pro váš aktuální profil</string>
<string name="conn_event_ratchet_sync_allowed">opětovné vyjednávání šifrování povoleno</string>
<string name="snd_conn_event_ratchet_sync_allowed">opětovné vyjednávání šifrování povoleno pro %s</string>
<string name="conn_event_ratchet_sync_required">vyžadováno opětovné vyjednávání šifrování</string>
@@ -1693,7 +1698,7 @@
<string name="v5_7_network_descr">Spolehlivější síťové připojení.</string>
<string name="allow_to_send_simplex_links">Povolit odesílat SimpleX odkazy.</string>
<string name="saved_description">uloženo</string>
<string name="saved_from_description">Uloženo z %s</string>
<string name="saved_from">Uloženo z</string>
<string name="saved_chat_item_info_tab">Uloženo</string>
<string name="forwarded_chat_item_info_tab">Přeposláno</string>
<string name="saved_from_chat_item_info_title">Uloženo z</string>
@@ -168,7 +168,7 @@
<string name="connect_plan_open_group">Åben gruppe</string>
<string name="connect_plan_open_new_group">Åbn ny gruppe</string>
<string name="error_parsing_uri_title">Ugyldigt link</string>
<string name="error_parsing_uri_desc">Kontroller at SimpleX-linket er korrekt.</string>
<string name="error_parsing_uri_desc">Kontroller, at SimpleX-linket er korrekt.</string>
<string name="opening_database">Åbner databasen…</string>
<string name="database_migration_in_progress">Databasemigrering er i gang.\nDet kan tage et par minutter.</string>
<string name="non_content_uri_alert_title">Ugyldig filsti</string>
@@ -201,7 +201,7 @@
<string name="moderated_description">modereret</string>
<string name="forwarded_description">videresendt</string>
<string name="saved_description">gemt</string>
<string name="saved_from_description">gemt fra %s</string>
<string name="saved_from">gemt fra</string>
<string name="invalid_chat">ugyldig chat</string>
<string name="invalid_data">ugyldige data</string>
<string name="error_showing_message">fejl ved visning af besked</string>
@@ -635,6 +635,8 @@
<string name="cant_send_message_you_left">du forlod</string>
<string name="cant_send_message_generic">kan ikke sende beskeder</string>
<string name="you_are_observer">du er observatør</string>
<string name="connect_plan_you_are_observer">Du er observatør</string>
<string name="connect_plan_you_are_admin">Du er administrator</string>
<string name="reviewed_by_admins">gennemgået af administratorer</string>
<string name="cant_send_message_member_has_old_version">medlemmet har en gammel version</string>
<string name="image_descr">Billede</string>
@@ -882,4 +884,64 @@
<string name="another_instance_title">Appen kører allerede</string>
<string name="app_update_required">App\'en skal opdateres</string>
<string name="chat_link_business_address">Virksomhedsadresse</string>
<string name="connect_plan_join_name">Deltag i kanal %s</string>
<string name="connect_plan_connect_to_name">Forbind til %s</string>
<string name="another_instance_not_responding">En anden instans af appen kører eller blev ikke lukket korrekt. Start alligevel?</string>
<string name="channel_owners_contributors_count">%1$d ejere og bidragsydere</string>
<string name="relay_bar_relays_failed">%1$d relays fejlede</string>
<string name="relay_bar_relays_not_active">%1$d relays ikke aktive</string>
<string name="relay_bar_relays_removed">%1$d relays fjernet</string>
<string name="channel_subscriber_count_singular">%1$d abonnent</string>
<string name="channel_subscriber_count_plural">%1$d abonnenter</string>
<string name="badge_supported_simplex">%1$s støttede SimpleX Chat. Mærket udløb den %2$s.</string>
<string name="settings_section_title_about">Om</string>
<string name="relay_status_accepted">accepteret</string>
<string name="v7_0_channels_contributors">Tilføj bidragsydere.</string>
<string name="add_description">Tilføj beskrivelse</string>
<string name="a_link_for_one_person">Et link til at en enkelt person kan forbinde</string>
<string name="content_filter_all_messages">Alle beskeder</string>
<string name="messages_section_title">Beskeder</string>
<string name="settings_section_title_messages">Beskeder og filer</string>
<string name="allow_chat_with_admins">Tillad medlemmer at chatte med admins.</string>
<string name="allow_direct_messages_channel">Tillad at sende direkte beskeder til abonnenter.</string>
<string name="allow_chat_with_admins_channel">Tillad abonnenter at chatte med admins.</string>
<string name="relay_bar_all_relays_failed">Alle relays fejlede</string>
<string name="relay_bar_all_relays_removed">Alle relays fjernet</string>
<string name="embed_any_webpage_can_show">Enhver hjemmeside kan vise forhåndsvisningen.</string>
<string name="badge_unknown_key_title">Mærke kan ikke bekræftes</string>
<string name="onboarding_be_free">Vær fri\ni dit netværk</string>
<string name="why_built_tagline">Vær fri i dit netværk.</string>
<string name="v7_0_channels">Bedre kanaler 📢</string>
<string name="block_subscriber_for_all_question">Blokér abonnent for alle?</string>
<string name="one_hand_ui_bottom_bar">Værktøjslinje nederst</string>
<string name="server_no_sub">intet abonnement</string>
<string name="not_connected_to_server_to_receive_messages_no_sub">Du er ikke forbundet til den server, der bruges til at modtage meddelelser fra denne forbindelse (intet abonnement).</string>
<string name="voice_recording_not_supported">Stemmeoptagelse er ikke understøttet på din platform</string>
<string name="e2ee_info_no_e2ee"><![CDATA[Beskeder i denne kanal er <b>ikke ende-til-ende-krypteret</b>. Et chat-relay kan se disse beskeder.]]></string>
<string name="simplex_link_relay">SimpleX relay-adresse</string>
<string name="no_chat_relays_enabled">Ingen chat-relays aktiveret.</string>
<string name="no_names_servers_enabled">Ingen servere til at slå navne op.</string>
<string name="server_warning">Server-advarsel</string>
<string name="network_error_unknown_ca">Fingeraftrykket i serveradressen matcher ikke certifikatet: %1$s.</string>
<string name="proxy_destination_error_unknown_ca">Fingeraftrykket i destinations-serveradressen matcher ikke certifikatet: %1$s.</string>
<string name="error_marking_member_support_chat_read">Fejl ved markering som læst</string>
<string name="unsupported_channel_name">Ikke-understøttet navn på kanal</string>
<string name="unsupported_contact_name">Ikke-understøttet navn på kontakt</string>
<string name="channel_name_requires_newer_app_version">Forbindelse gennem kanal-navnet kræver en nyere version af appen.</string>
<string name="contact_name_requires_newer_app_version">Forbindelse gennem kontakt-navnet kræver en nyere version af appen.</string>
<string name="please_upgrade_the_app">Opgrader appen.</string>
<string name="simplex_name_error">Fejl i SimpleX-navn</string>
<string name="simplex_name_no_servers_desc">Ingen af dine servere er sat op til at slå SimpleX-navne op. Konfigurer serverne, eller anvend et forbindelseslink.</string>
<string name="simplex_name_not_found">Navn ikke fundet</string>
<string name="simplex_name_not_found_desc">Dette SimpleX-navn er ikke registreret. Kontrollér navnet.</string>
<string name="simplex_name_no_valid_link">Intet gyldigt link</string>
<string name="simplex_name_no_valid_link_desc">SimpleX-navnet %1$s er registreret, men det har ikke et gyldigt link.</string>
<string name="simplex_name_unconfirmed">Ubekræftet navn</string>
<string name="simplex_name_unconfirmed_desc">SimpleX-navnet %1$s er registreret, men ikke tilføjet til profil. Tilføj det til din adresse eller kanal-profil, hvis du er indehaveren.</string>
<string name="channel_temporarily_unavailable">Kanal midlertidigt utilgængelig</string>
<string name="channel_no_active_relays_try_later">Kanalen har ingen aktive relays. Vent og prøv igen senere.</string>
<string name="group_link_requires_newer_version">Denne gruppe kræver en nyere version af appen. Opdater appen for at kunne deltage.</string>
<string name="error_deleting_message">Fejl ved sletning af meddelelse</string>
<string name="save_simplex_name_question">Gem SimpleX-navn?</string>
<string name="get_simplex_name_beta">Anskaf SimpleX-navn (BETA)</string>
</resources>
@@ -1012,6 +1012,13 @@
<string name="moderate_verb">Moderieren</string>
<string name="moderate_message_will_be_marked_warning">Diese Nachricht wird für alle Mitglieder als moderiert gekennzeichnet.</string>
<string name="you_are_observer">Sie sind Beobachter</string>
<string name="connect_plan_you_are_observer">Sie sind Beobachter</string>
<string name="connect_plan_you_are_member">Sie sind Mitglied</string>
<string name="connect_plan_you_are_moderator">Sie sind Moderator</string>
<string name="connect_plan_you_are_admin">Sie sind Admin</string>
<string name="connect_plan_you_are_owner">Sie sind Eigentümer</string>
<string name="connect_plan_you_are_subscriber">Sie sind Abonnent</string>
<string name="connect_plan_you_are_contributor">Sie sind Mitwirkender</string>
<string name="observer_cant_send_message_title">Sie sind Beobachter</string>
<string name="group_member_role_observer">Beobachter</string>
<string name="initial_member_role">Anfängliche Rolle</string>
@@ -1364,7 +1371,7 @@
<string name="v5_2_favourites_filter_descr">Nach ungelesenen und favorisierten Chats filtern.</string>
<string name="sending_delivery_receipts_will_be_enabled_all_profiles">Das Senden von Empfangsbestätigungen an alle Kontakte in allen sichtbaren Chat-Profilen wird aktiviert.</string>
<string name="receipts_contacts_override_disabled">Das Senden von Bestätigungen an %d Kontakte ist deaktiviert</string>
<string name="receipts_section_description">Diese Einstellungen gelten für Ihr aktuelles Chat-Profil</string>
<string name="these_settings_are_for_your_current_profile">Diese Einstellungen gelten für Ihr aktuelles Chat-Profil</string>
<string name="receipts_section_description_1">Sie können in den Kontakt- und Gruppeneinstellungen überschrieben werden.</string>
<string name="receipts_section_contacts">Kontakte</string>
<string name="receipts_contacts_title_disable">Bestätigungen deaktivieren\?</string>
@@ -1805,7 +1812,7 @@
<string name="audio_device_wired_headphones">Kopfhörer</string>
<string name="network_option_rcv_concurrency">Gelijktijdige ontvangst</string>
<string name="recipients_can_not_see_who_message_from">Empfänger können nicht sehen, von wem die Nachricht stammt.</string>
<string name="saved_from_description">abgespeichert von %s</string>
<string name="saved_from">abgespeichert von</string>
<string name="saved_chat_item_info_tab">Abgespeichert</string>
<string name="saved_description">abgespeichert</string>
<string name="forwarded_chat_item_info_tab">Weitergeleitet</string>
@@ -2812,7 +2819,7 @@
<string name="v6_5_invite_friends_descr">Wir haben das Verbinden für neue Nutzer vereinfacht.</string>
<string name="your_public_address">Ihre öffentliche Adresse</string>
<string name="why_built_heading">Sie wurden ohne ein Benutzerkonto geboren.</string>
<string name="why_built_p1">Niemand verfolgte Ihre Gespräche. Niemand erstellte eine Karte, wo Sie sich aufgehalten haben. Privatsphäre war nie ein Feature - sie war selbstverständlich.</string>
<string name="why_built_p1">Niemand verfolgte Ihre Gespräche. Niemand hat eine Karte erstellt, wo Sie überall waren. Privatsphäre war nie ein Feature sie war eine Selbstverständlichkeit.</string>
<string name="why_built_p2">Dann sind wir online gegangen, und jede Plattform wollte Etwas von Ihnen - Ihren Namen, Ihre Nummer, Ihre Freunde. Wir akzeptierten, dass es der Preis mit Anderen zu kommunizieren ist, Jemandem preiszugeben, mit wem und wie wir miteinander kommunizieren. Jede Generation, Menschen und Technologien, kannten es nur so - Telefon, E-Mail, Messenger, soziale Medien. Es schien der einzig mögliche Weg zu sein.</string>
<string name="why_built_p3">Es gibt einen anderen Weg. Ein Netzwerk ohne Telefonnummern, ohne Benutzerkonten, ohne Benutzerkennungen und ohne jegliche Benutzeridentität. Ein Netzwerk, welches Menschen verbindet und verschlüsselte Nachrichten überträgt, ohne zu wissen, wer mit wem verbunden ist.</string>
<string name="why_built_p4">Nicht ein besseres Schloss an der Tür eines Anderen. Kein freundlicher Vermieter, der Ihre Privatsphäre respektiert, aber dennoch jeden Besucher registriert. Sie sind kein Gast. Sie sind zu Hause. Kein Vermieter, kein Fremder kann es betreten - Sie sind souverän.</string>
@@ -2959,7 +2966,7 @@
<string name="simplex_name_error">Fehler beim SimpleX-Namen</string>
<string name="simplex_name_not_verified">SimpleX-Name ist nicht verifiziert</string>
<string name="simplex_name_no_valid_link_desc">Der SimpleX-Name %1$s wurde registriert, aber er hat keinen gültigen Link.</string>
<string name="simplex_name_unconfirmed_desc">Der SimpleXName %1$s wurde registriert, jedoch nicht in Ihrem Profil hinterlegt. Bitte zu Ihrer Adresse oder zum Kanalprofil hinzufügen, sofern Sie der Besitzer sind.</string>
<string name="simplex_name_unconfirmed_desc">Der SimpleXName %1$s wurde registriert, jedoch nicht in Ihrem Profil hinterlegt. Bitte fügen Sie ihn zu Ihrer Adresse oder zum Kanalprofil hinzu, sofern Sie der Besitzer sind.</string>
<string name="simplex_name_owner_no_channel_link">Der SimpleXName %1$s wurde ohne KanalLink registriert. Fügen Sie den KanalLink über die Registrierungsseite hinzu.</string>
<string name="simplex_name_owner_no_address">Der SimpleXName %1$s wurde ohne SimpleX-Adresse registriert. Fügen Sie die SimpleX-Adresse über die Registrierungsseite hinzu.</string>
<string name="simplex_name_not_found_desc">Dieser SimpleX-Name wurde nicht registriert. Bitte überprüfen Sie den Namen.</string>
@@ -2984,7 +2991,7 @@
<string name="sign_messages">Nachrichten signieren</string>
<string name="signature_missing_alert_desc">Der Kanal verlangt für diese Nachricht eine Signatur, welche aber fehlt.</string>
<string name="channel_simplex_name">Im Kanal genutzter SimpleX-Name</string>
<string name="get_simplex_name_beta">SimpleX-Name erhalten (BETA)</string>
<string name="get_simplex_name_beta">Einen SimpleX-Namen erhalten (BETA)</string>
<string name="register_test_name">Wie man einen Test-Namen registriert</string>
<string name="remove_name">Name entfernen</string>
<string name="save_simplex_name_question">SimpleX-Name speichern?</string>
@@ -1350,7 +1350,7 @@
<string name="the_sender_will_not_be_notified">Ο αποστολέας ΔΕΝ θα ειδοποιηθεί.</string>
<string name="smp_servers_per_user">Οι διακομιστές για τις νέες συνδέσεις του τρέχοντος προφίλ συνομιλίας σου</string>
<string name="xftp_servers_per_user">Οι διακομιστές για τα νέα αρχεία του τρέχοντος προφίλ συνομιλίας σου</string>
<string name="receipts_section_description">Αυτές οι ρυθμίσεις ισχύουν για το τρέχον προφίλ σου</string>
<string name="these_settings_are_for_your_current_profile">Αυτές οι ρυθμίσεις ισχύουν για το τρέχον προφίλ σου</string>
<string name="the_text_you_pasted_is_not_a_link">Το κείμενο που επικόλλησες δεν είναι σύνδεσμος SimpleX.</string>
<string name="migrate_from_device_uploaded_archive_will_be_removed">Το αρχείο της βάσης δεδομένων που μεταφορτώθηκε, θα διαγραφεί οριστικά από τους διακομιστές.</string>
<string name="video_decoding_exception_desc">Το βίντεο δεν μπορεί να αποκωδικοποιηθεί. Δοκίμασε ένα άλλο βίντεο ή επικοινώνησε με τους προγραμματιστές.</string>
@@ -2051,7 +2051,7 @@
<string name="saved_description">αποθηκευμένο</string>
<string name="saved_chat_item_info_tab">Αποθηκευμένο</string>
<string name="saved_from_chat_item_info_title">Αποθηκευμένο από</string>
<string name="saved_from_description">αποθηκευμένο από %s</string>
<string name="saved_from">αποθηκευμένο από</string>
<string name="saved_message_title">Αποθηκευμένο μήνυμα</string>
<string name="saved_ICE_servers_will_be_removed">Οι αποθηκευμένοι διακομιστές WebRTC ICE θα αφαιρεθούν.</string>
<string name="save_group_profile">Αποθήκευση προφίλ ομάδας</string>
@@ -2429,6 +2429,11 @@
<string name="not_connected_to_server_to_receive_messages_no_sub">Δεν είσαι συνδεδεμένος στον διακομιστή που χρησιμοποιείται για τη λήψη μηνυμάτων από αυτή τη σύνδεση (δεν υπάρχει συνδρομή).</string>
<string name="servers_info_proxied_servers_section_footer">Δεν είσαι συνδεδεμένος σε αυτούς τους διακομιστές. Για την παράδοση μηνυμάτων σε αυτούς, χρησιμοποιείται ιδιωτική δρομολόγηση.</string>
<string name="you_are_observer">είσαι παρατηρητής</string>
<string name="connect_plan_you_are_observer">Είσαι παρατηρητής</string>
<string name="connect_plan_you_are_member">Είσαι μέλος</string>
<string name="connect_plan_you_are_moderator">Είσαι διαχειριστής</string>
<string name="connect_plan_you_are_admin">Είσαι διαχειριστής</string>
<string name="connect_plan_you_are_owner">Είσαι ιδιοκτήτης</string>
<string name="observer_cant_send_message_title">είσαι παρατηρητής</string>
<string name="snd_group_event_member_blocked">μπλόκαρες %s</string>
<string name="one_hand_ui_change_instruction">Μπορείς να το αλλάξεις στις ρυθμίσεις Εμφάνισης.</string>
@@ -1283,7 +1283,7 @@
<string name="receipts_contacts_override_disabled">El envío de confirmaciones está desactivado para %d contactos</string>
<string name="receipts_contacts_override_enabled">El envío de confirmaciones está activado para %d contactos</string>
<string name="send_receipts">Enviar confirmaciones</string>
<string name="receipts_section_description">Esta configuración afecta a tu perfil actual</string>
<string name="these_settings_are_for_your_current_profile">Esta configuración afecta a tu perfil actual</string>
<string name="enable_receipts_all">Activar</string>
<string name="receipts_contacts_title_disable">¿Desactivar confirmaciones\?</string>
<string name="receipts_contacts_title_enable">¿Activar confirmaciones\?</string>
@@ -1724,7 +1724,7 @@
<string name="feature_roles_all_members">todos los miembros</string>
<string name="allow_to_send_simplex_links">Se permite enviar enlaces SimpleX.</string>
<string name="saved_description">guardado</string>
<string name="saved_from_description">guardado desde %s</string>
<string name="saved_from">guardado desde</string>
<string name="saved_chat_item_info_tab">Guardado</string>
<string name="saved_from_chat_item_info_title">Guardado desde</string>
<string name="forwarded_from_chat_item_info_title">Reenviado por</string>
@@ -2665,6 +2665,13 @@
<string name="relay_test_step_wait_response">Espera respuesta</string>
<string name="channel_member_you"></string>
<string name="you_are_subscriber">eres suscriptor</string>
<string name="connect_plan_you_are_observer">Eres observador</string>
<string name="connect_plan_you_are_member">Eres miembro</string>
<string name="connect_plan_you_are_moderator">Eres moderador</string>
<string name="connect_plan_you_are_admin">Eres administrador</string>
<string name="connect_plan_you_are_owner">Eres propietario</string>
<string name="connect_plan_you_are_subscriber">Eres suscriptor</string>
<string name="connect_plan_you_are_contributor">Eres colaborador</string>
<string name="you_can_share_channel_link_anybody_will_be_able_to_connect">Puedes compartir el enlace o código QR. Cualquiera podrá unirse al canal.</string>
<string name="relay_section_footer_subscriber">Te conectaste al canal mediante este enlace de servidor.</string>
<string name="chat_banner_your_channel">Tu canal</string>
@@ -156,7 +156,7 @@
<string name="turn_off_battery_optimization"><![CDATA[در دیالوگ بعدی <b>اجازه دهید</b> تا اعلان‌ها را فوری دریافت کنید.]]></string>
<string name="to_preserve_privacy_simplex_has_background_service_instead_of_push_notifications_it_uses_a_few_pc_battery"><![CDATA[برای بهبود حریم خصوصی، <b>SimpleX در پس‌زمینه اجرا می‌شود</b> و به جای استفاده از پوش نوتیفیکیشن، کار می‌کند.]]></string>
<string name="saved_description">ذخیره شده</string>
<string name="saved_from_description">ذخیره شده از %s</string>
<string name="saved_from">ذخیره شده از</string>
<string name="saved_from_chat_item_info_title">ذخیره شده از</string>
<string name="forwarded_description">فرستاده شده</string>
<string name="e2ee_info_no_pq"><![CDATA[پیام‌ها، فایل‌ها و تماس‌ها به وسیله <b>رمزنگاری انتها به انتها</b> با محرمانگی پیشرو، مردودسازی و بازیابی ورود غیرمجاز محافظت شده‌اند.]]></string>
@@ -437,6 +437,11 @@
<string name="la_could_not_be_verified">تایید شما ممکن نیست؛ لطفا دوباره امتحان کنید.</string>
<string name="choose_file">فایل</string>
<string name="you_are_observer">شما ناظر هستید</string>
<string name="connect_plan_you_are_observer">شما ناظر هستید</string>
<string name="connect_plan_you_are_member">شما عضو هستید</string>
<string name="connect_plan_you_are_moderator">شما مدیر هستید</string>
<string name="connect_plan_you_are_admin">شما مدیر هستید</string>
<string name="connect_plan_you_are_owner">شما صاحب هستید</string>
<string name="clear_chat_question">چت پاک شود؟</string>
<string name="clear_note_folder_warning">تمام پیام‌ها حذف خواهند شد - این عمل قابل برگشت نیست!</string>
<string name="delete_contact_menu_action">حذف</string>
@@ -756,7 +761,7 @@
<string name="self_destruct_new_display_name">نام نمایشی جدید:</string>
<string name="if_you_enter_self_destruct_code">اگر کد عبور خودتخریبی خود را زمان باز کردن برنامه وارد کنید:</string>
<string name="all_app_data_will_be_cleared">تمام اطلاعات برنامه حذف می‌شود.</string>
<string name="receipts_section_description">این تنظیمات برای پروفایل فعلی شما هستند</string>
<string name="these_settings_are_for_your_current_profile">این تنظیمات برای پروفایل فعلی شما هستند</string>
<string name="receipts_contacts_override_enabled">ارسال رسید برای %d مخاطب فعال است</string>
<string name="receipts_contacts_disable_for_all">غیرفعال برای همه</string>
<string name="receipts_groups_enable_for_all">فعال برای همه گروه‌ها</string>
@@ -1169,6 +1169,10 @@
<string name="to_preserve_privacy_simplex_has_background_service_instead_of_push_notifications_it_uses_a_few_pc_battery"><![CDATA[Yksityisyytesi säilyttämiseksi sovelluksessa on push-ilmoitusten sijaan <b>SimpleX-taustapalvelu</b> se kuluttaa muutaman prosentin akusta päivässä.]]></string>
<string name="auth_unlock">Avaa</string>
<string name="you_are_observer">olet tarkkailija</string>
<string name="connect_plan_you_are_observer">Olet tarkkailija</string>
<string name="connect_plan_you_are_member">Olet jäsen</string>
<string name="connect_plan_you_are_admin">Olet ylläpitäjä</string>
<string name="connect_plan_you_are_owner">Olet omistaja</string>
<string name="videos_limit_title">Liikaa videoita!</string>
<string name="voice_message">Ääniviesti</string>
<string name="waiting_for_video">Odottaa videota</string>
@@ -1272,7 +1276,7 @@
<string name="sync_connection_force_confirm">Uudelleenneuvottele</string>
<string name="sync_connection_force_question">Uudelleenneuvottele salaus\?</string>
<string name="sync_connection_force_desc">Salaus toimii ja uutta salaussopimusta ei tarvita. Tämä voi johtaa yhteysvirheisiin!</string>
<string name="receipts_section_description">Nämä asetukset koskevat nykyistä profiiliasi</string>
<string name="these_settings_are_for_your_current_profile">Nämä asetukset koskevat nykyistä profiiliasi</string>
<string name="receipts_section_description_1">Ne voidaan ohittaa kontakti- ja ryhmäasetuksissa.</string>
<string name="conn_event_ratchet_sync_ok">salaus ok</string>
<string name="conn_event_ratchet_sync_allowed">salauksen uudelleenneuvottelu sallittu</string>
File diff suppressed because it is too large Load Diff
@@ -283,6 +283,9 @@
<string name="member_will_be_removed_from_group_cannot_be_undone">सदस्य को समूह से निकाल दिया जाएगा - इसे पूर्ववत नहीं किया जा सकता!</string>
<string name="member_info_section_title_member">सदस्य</string>
<string name="group_member_role_member">सदस्य</string>
<string name="connect_plan_you_are_member">आप सदस्य हैं</string>
<string name="connect_plan_you_are_admin">आप व्यवस्थापक हैं</string>
<string name="connect_plan_you_are_owner">आप स्वामी हैं</string>
<string name="search_verb">खोजें</string>
<string name="la_mode_off">बंद है</string>
<string name="connect_via_contact_link">संपर्क पते के माध्यम से कनेक्ट करें?</string>
@@ -590,7 +590,7 @@
<string name="incognito_info_protects">Anonimni režim štiti Vašu privatnost koristeći novi nasumični profil za svaki kontakt.</string>
<string name="custom_time_unit_weeks">nedelje</string>
<string name="agent_internal_error_title">Interna greška</string>
<string name="saved_from_description">Sačuvano od %s</string>
<string name="saved_from">Sačuvano od</string>
<string name="saved_description">sačuvano</string>
<string name="group_member_status_invited">pozvan</string>
<string name="saved_message_title">Sačuvana poruka</string>
@@ -1435,6 +1435,11 @@
<string name="unable_to_open_browser_desc">Za pozive je potreban podrazumevani veb pretraživač. Molimo vas da konfigurišete podrazumevani pretraživač u sistemu i podelite više informacija sa programerima.</string>
<string name="snd_group_event_member_unblocked">odblokirali ste %s</string>
<string name="you_are_observer">Vi ste posmatrač.</string>
<string name="connect_plan_you_are_observer">Vi ste posmatrač</string>
<string name="connect_plan_you_are_member">Vi ste član</string>
<string name="connect_plan_you_are_moderator">Vi ste moderator</string>
<string name="connect_plan_you_are_admin">Vi ste administrator</string>
<string name="connect_plan_you_are_owner">Vi ste vlasnik</string>
<string name="v4_3_improved_privacy_and_security">Unapređena privatnost i bezbednost</string>
<string name="v5_6_app_data_migration_descr">Migriraj na drugi uređaj pomoću QR koda.</string>
<string name="group_preview_rejected">odbijeno</string>
@@ -1127,6 +1127,13 @@
<string name="simplex_service_notification_text">Üzenetek fogadása…</string>
<string name="rcv_group_event_2_members_connected">%s és %s kapcsolódott</string>
<string name="you_are_observer">Ön megfigyelő</string>
<string name="connect_plan_you_are_observer">Ön megfigyelő</string>
<string name="connect_plan_you_are_member">Ön tag</string>
<string name="connect_plan_you_are_moderator">Ön moderátor</string>
<string name="connect_plan_you_are_admin">Ön adminisztrátor</string>
<string name="connect_plan_you_are_owner">Ön tulajdonos</string>
<string name="connect_plan_you_are_subscriber">Ön feliratkozó</string>
<string name="connect_plan_you_are_contributor">Ön közreműködő</string>
<string name="port_verb">Port</string>
<string name="set_passcode">Jelkód beállítása</string>
<string name="whats_new">Újdonságok</string>
@@ -1475,7 +1482,7 @@
<string name="settings_is_storing_in_clear_text">A jelmondat a beállításokban egyszerű szövegként van tárolva.</string>
<string name="terminal_always_visible">Konzol megjelenítése új ablakban</string>
<string name="alert_text_msg_bad_hash">Az előző üzenet kivonata különbözik.</string>
<string name="receipts_section_description">Ezek a beállítások csak a jelenlegi csevegési profiljára vonatkoznak</string>
<string name="these_settings_are_for_your_current_profile">Ezek a beállítások csak a jelenlegi csevegési profiljára vonatkoznak</string>
<string name="loading_remote_file_desc">Várjon, amíg a fájl betöltődik a társított hordozható eszközről</string>
<string name="read_more_in_github_with_link"><![CDATA[További információkat a <font color="#0088ff">GitHub-tárolónkban</font> talál.]]></string>
<string name="error_showing_content">Hiba történt a tartalom megjelenítésekor</string>
@@ -1694,7 +1701,7 @@
<string name="allow_to_send_simplex_links">A SimpleX-hivatkozások küldése engedélyezve van.</string>
<string name="feature_enabled_for">Számukra engedélyezve</string>
<string name="saved_description">mentett</string>
<string name="saved_from_description">mentve innen: %s</string>
<string name="saved_from">mentve innen:</string>
<string name="forwarded_from_chat_item_info_title">Továbbítva innen</string>
<string name="recipients_can_not_see_who_message_from">A címzett(ek) nem látja(k), hogy kitől származik ez az üzenet.</string>
<string name="saved_chat_item_info_tab">Mentett</string>
@@ -2881,7 +2888,7 @@
<string name="signature_missing_alert_desc">A csatorna megköveteli az üzenet aláírását, de az hiányzik.</string>
<string name="channel_simplex_name">Csatorna SimpleX-neve</string>
<string name="get_simplex_name_beta">SimpleX-név beszerzése (béta)</string>
<string name="register_test_name">Egy név regisztrálása tesztelési céllal</string>
<string name="register_test_name">Útmutató egy név regisztrálásához tesztelési céllal</string>
<string name="remove_name">Név eltávolítása</string>
<string name="save_simplex_name_question">Menti a SimpleX-nevet?</string>
<string name="to_verify_channel_member_key">A kulcsok ellenőrzéséhez ezzel a feliratkozóval hasonlítsa össze (vagy olvassa be) az eszközökön található kódot.</string>
@@ -755,7 +755,7 @@
<string name="moderated_description">dimoderasi</string>
<string name="invalid_chat">obrolan tidak valid</string>
<string name="forwarded_description">diteruskan</string>
<string name="saved_from_description">disimpan dari %s</string>
<string name="saved_from">disimpan dari</string>
<string name="receiving_files_not_yet_supported">terima berkas belum didukung</string>
<string name="sender_you_pronoun">anda</string>
<string name="unknown_message_format">format pesan tak diketahui</string>
@@ -1206,7 +1206,7 @@
<string name="receipts_groups_title_enable">Aktifkan tanda terima untuk grup?</string>
<string name="empty_chat_profile_is_created">Profil obrolan kosong dengan nama yang disediakan dibuat, dan aplikasi terbuka seperti biasa.</string>
<string name="if_you_enter_passcode_data_removed">Jika Anda memasukkan kode sandi saat membuka aplikasi, semua data aplikasi akan dihapus secara permanen!</string>
<string name="receipts_section_description">Pengaturan ini untuk profil Anda saat ini</string>
<string name="these_settings_are_for_your_current_profile">Pengaturan ini untuk profil Anda saat ini</string>
<string name="receipts_contacts_override_enabled">Kirim tanda terima diaktifkan untuk %d kontak</string>
<string name="receipts_contacts_override_disabled">Kirim tanda terima dimatikan untuk %d kontak</string>
<string name="error_loading_xftp_servers">Gagal memuat server XFTP</string>
@@ -2010,6 +2010,13 @@
<string name="file_error_auth">Kunci salah atau alamat potongan berkas tidak dikenal - kemungkinan berkas dihapus.</string>
<string name="srv_error_version">Versi server tidak kompatibel dengan pengaturan jaringan.</string>
<string name="you_are_observer">Anda adalah pengamat</string>
<string name="connect_plan_you_are_observer">Anda adalah pengamat</string>
<string name="connect_plan_you_are_member">Anda adalah anggota</string>
<string name="connect_plan_you_are_moderator">Anda adalah moderator</string>
<string name="connect_plan_you_are_admin">Anda adalah admin</string>
<string name="connect_plan_you_are_owner">Anda adalah pemilik</string>
<string name="connect_plan_you_are_subscriber">Anda adalah pelanggan</string>
<string name="connect_plan_you_are_contributor">Anda adalah kontributor</string>
<string name="to_start_a_new_chat_help_header">Untuk memulai obrolan baru</string>
<string name="gallery_video_button">Video</string>
<string name="connection_you_accepted_will_be_cancelled">Koneksi yang Anda terima akan dibatalkan!</string>
@@ -934,6 +934,13 @@
<string name="moderate_message_will_be_deleted_warning">Il messaggio verrà eliminato per tutti i membri.</string>
<string name="moderate_message_will_be_marked_warning">Il messaggio sarà segnato come moderato per tutti i membri.</string>
<string name="you_are_observer">sei un osservatore</string>
<string name="connect_plan_you_are_observer">Sei un osservatore</string>
<string name="connect_plan_you_are_member">Sei un membro</string>
<string name="connect_plan_you_are_moderator">Sei un moderatore</string>
<string name="connect_plan_you_are_admin">Sei un amministratore</string>
<string name="connect_plan_you_are_owner">Sei un proprietario</string>
<string name="connect_plan_you_are_subscriber">Sei iscritto/a</string>
<string name="connect_plan_you_are_contributor">Sei un collaboratore</string>
<string name="initial_member_role">Ruolo iniziale</string>
<string name="error_updating_link_for_group">Errore nell\'aggiornamento del link del gruppo</string>
<string name="group_member_role_observer">osservatore</string>
@@ -1290,7 +1297,7 @@
<string name="sending_delivery_receipts_will_be_enabled_all_profiles">L\'invio delle ricevute di consegna sarà attivo per tutti i contatti in tutti i profili di chat visibili.</string>
<string name="receipts_contacts_override_disabled">L\'invio di ricevute è disattivato per %d contatti</string>
<string name="sync_connection_force_desc">La crittografia funziona e il nuovo accordo sulla crittografia non è richiesto. Potrebbero verificarsi errori di connessione!</string>
<string name="receipts_section_description">Queste impostazioni sono per il tuo profilo attuale</string>
<string name="these_settings_are_for_your_current_profile">Queste impostazioni sono per il tuo profilo attuale</string>
<string name="receipts_section_description_1">Possono essere sovrascritte nelle impostazioni dei contatti e dei gruppi.</string>
<string name="receipts_contacts_enable_for_all">Attiva per tutti</string>
<string name="receipts_contacts_enable_keep_overrides">Attiva (mantieni sostituzioni)</string>
@@ -1732,7 +1739,7 @@
<string name="forward_chat_item">Inoltra</string>
<string name="recipients_can_not_see_who_message_from">I destinatari non possono vedere da chi proviene questo messaggio.</string>
<string name="saved_chat_item_info_tab">Salvato</string>
<string name="saved_from_description">salvato da %s</string>
<string name="saved_from">salvato da</string>
<string name="audio_device_bluetooth">Bluetooth</string>
<string name="audio_device_earpiece">Auricolari</string>
<string name="audio_device_wired_headphones">Cuffie</string>
@@ -2916,7 +2923,7 @@
<string name="signature_missing_alert_desc">Il canale ha richiesto di firmare questo messaggio, ma la firma non è presente.</string>
<string name="channel_simplex_name">Nome SimpleX per il canale</string>
<string name="get_simplex_name_beta">Ottieni nome SimpleX (BETA)</string>
<string name="register_test_name">Registra un nome di prova</string>
<string name="register_test_name">Come registrare un nome di prova</string>
<string name="remove_name">Rimuovi nome</string>
<string name="save_simplex_name_question">Salvare il nome SimpleX?</string>
<string name="to_verify_channel_member_key">Per verificare le chiavi con questo iscritto, confrontate (o scansionate) il codice sui vostri dispositivi.</string>

Some files were not shown because too many files have changed in this diff Show More