diff --git a/apps/ios/Shared/Model/AppAPITypes.swift b/apps/ios/Shared/Model/AppAPITypes.swift
index b459f36c9d..a5a56174b1 100644
--- a/apps/ios/Shared/Model/AppAPITypes.swift
+++ b/apps/ios/Shared/Model/AppAPITypes.swift
@@ -1404,6 +1404,7 @@ enum GroupLinkPlan: Decodable, Hashable {
case connectingProhibit(groupInfo_: GroupInfo?)
case known(groupInfo: GroupInfo)
case noRelays(groupSLinkData_: GroupShortLinkData?)
+ case updateRequired(groupSLinkData_: GroupShortLinkData?)
}
struct ChatTagData: Encodable {
diff --git a/apps/ios/Shared/Views/Chat/ChatItem/MsgContentView.swift b/apps/ios/Shared/Views/Chat/ChatItem/MsgContentView.swift
index 2f4338c0af..9aaff57cc5 100644
--- a/apps/ios/Shared/Views/Chat/ChatItem/MsgContentView.swift
+++ b/apps/ios/Shared/Views/Chat/ChatItem/MsgContentView.swift
@@ -208,7 +208,9 @@ private func handleTextTaps(
var browser: Bool = false
s.enumerateAttributes(in: NSRange(location: 0, length: s.length)) { attrs, range, stop in
if index >= range.location && index < range.location + range.length {
- if let url = attrs[linkAttrKey] as? String {
+ if let nameInfo = attrs[nameAttrKey] as? SimplexNameInfo {
+ showUnsupportedNameAlert(nameInfo)
+ } else if let url = attrs[linkAttrKey] as? String {
linkURL = url
browser = attrs[webLinkAttrKey] != nil
} else if let showSecrets, let i = attrs[secretAttrKey] as? Int {
@@ -251,6 +253,7 @@ private let webLinkAttrKey = NSAttributedString.Key("chat.simplex.app.webLink")
private let secretAttrKey = NSAttributedString.Key("chat.simplex.app.secret")
private let commandAttrKey = NSAttributedString.Key("chat.simplex.app.command")
+private let nameAttrKey = NSAttributedString.Key("chat.simplex.app.name")
typealias MsgTextResult = (string: NSMutableAttributedString, hasSecrets: Bool, handleTaps: Bool)
@@ -424,6 +427,12 @@ func messageText(
t = mentionText(memberName)
}
}
+ case let .simplexName(nameInfo):
+ attrs = linkAttrs()
+ if !preview {
+ attrs[nameAttrKey] = nameInfo
+ handleTaps = true
+ }
case .email:
attrs = linkAttrs()
if !preview {
diff --git a/apps/ios/Shared/Views/ChatList/ChatListView.swift b/apps/ios/Shared/Views/ChatList/ChatListView.swift
index dc4971aafa..d90149c7dd 100644
--- a/apps/ios/Shared/Views/ChatList/ChatListView.swift
+++ b/apps/ios/Shared/Views/ChatList/ChatListView.swift
@@ -675,17 +675,18 @@ struct ChatListSearchBar: View {
if ignoreSearchTextChange {
ignoreSearchTextChange = false
} else {
- if let link = strHasSingleSimplexLink(t.trimmingCharacters(in: .whitespaces)) { // if SimpleX link is pasted, show connection dialogue
+ switch strConnectTarget(t.trimmingCharacters(in: .whitespaces)) {
+ case let .link(text, _, linkText):
searchFocussed = false
- if case let .simplexLink(_, linkType, _, smpHosts) = link.format {
- ignoreSearchTextChange = true
- searchText = simplexLinkText(linkType, smpHosts)
- }
+ ignoreSearchTextChange = true
+ searchText = linkText
searchShowingSimplexLink = true
searchChatFilteredBySimplexLink = nil
- connect(link.text)
- } else {
- if t != "" { // if some other text is pasted, enter search mode
+ connect(text)
+ case let .name(nameInfo):
+ showUnsupportedNameAlert(nameInfo)
+ case .none:
+ if t != "" {
searchFocussed = true
} else {
ConnectProgressManager.shared.cancelConnectProgress()
diff --git a/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift b/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift
index 177f8761f4..f99b03086e 100644
--- a/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift
+++ b/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift
@@ -381,17 +381,18 @@ struct ContactsListSearchBar: View {
if ignoreSearchTextChange {
ignoreSearchTextChange = false
} else {
- if let link = strHasSingleSimplexLink(t.trimmingCharacters(in: .whitespaces)) { // if SimpleX link is pasted, show connection dialogue
+ switch strConnectTarget(t.trimmingCharacters(in: .whitespaces)) {
+ case let .link(text, _, linkText):
searchFocussed = false
- if case let .simplexLink(_, linkType, _, smpHosts) = link.format {
- ignoreSearchTextChange = true
- searchText = simplexLinkText(linkType, smpHosts)
- }
+ ignoreSearchTextChange = true
+ searchText = linkText
searchShowingSimplexLink = true
searchChatFilteredBySimplexLink = nil
- connect(link.text)
- } else {
- if t != "" { // if some other text is pasted, enter search mode
+ connect(text)
+ case let .name(nameInfo):
+ showUnsupportedNameAlert(nameInfo)
+ case .none:
+ if t != "" {
searchFocussed = true
} else {
connectProgressManager.cancelConnectProgress()
diff --git a/apps/ios/Shared/Views/NewChat/NewChatView.swift b/apps/ios/Shared/Views/NewChat/NewChatView.swift
index 9bcc326a66..4a7e50d7d2 100644
--- a/apps/ios/Shared/Views/NewChat/NewChatView.swift
+++ b/apps/ios/Shared/Views/NewChat/NewChatView.swift
@@ -663,14 +663,13 @@ private struct ConnectView: View {
ZStack(alignment: .trailing) {
Button {
if let str = UIPasteboard.general.string {
- if let link = strHasSingleSimplexLink(str.trimmingCharacters(in: .whitespaces)) {
- pastedLink = link.text
- // It would be good to hide it, but right now it is not clear how to release camera in CodeScanner
- // https://github.com/twostraws/CodeScanner/issues/121
- // No known tricks worked (changing view ID, wrapping it in another view, etc.)
- // showQRCodeScanner = false
+ switch strConnectTarget(str.trimmingCharacters(in: .whitespaces)) {
+ case let .link(text, _, _):
+ pastedLink = text
connect(pastedLink)
- } else {
+ case let .name(nameInfo):
+ showUnsupportedNameAlert(nameInfo)
+ case .none:
alert = .newChatSomeAlert(alert: SomeAlert(
alert: mkAlert(title: "Invalid link", message: "The text you pasted is not a SimpleX link."),
id: "pasteLinkView: code is not a SimpleX link"
@@ -866,16 +865,36 @@ func strIsSimplexLink(_ str: String) -> Bool {
}
}
-func strHasSingleSimplexLink(_ str: String) -> FormattedText? {
- if let parsedMd = parseSimpleXMarkdown(str) {
- let parsedLinks = parsedMd.filter({ $0.format?.isSimplexLink ?? false })
- if parsedLinks.count == 1 {
- return parsedLinks[0]
- } else {
- return nil
- }
+enum ConnectTarget {
+ case link(text: String, linkType: SimplexLinkType, linkText: String)
+ case name(SimplexNameInfo)
+}
+
+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))
+ } else if links.isEmpty,
+ case let .simplexName(nameInfo) = parsedMd?.first(where: { if case .simplexName = $0.format { true } else { false } })?.format {
+ .name(nameInfo)
} else {
- return nil
+ nil
+ }
+}
+
+func showUnsupportedNameAlert(_ nameInfo: SimplexNameInfo) {
+ let upgrade = " " + NSLocalizedString("Please upgrade the app.", comment: "alert message")
+ if nameInfo.nameType == .contact {
+ showAlert(
+ NSLocalizedString("Unsupported contact name", comment: "alert title"),
+ message: NSLocalizedString("Connecting via contact name requires a newer app version.", comment: "alert message") + upgrade
+ )
+ } else {
+ showAlert(
+ NSLocalizedString("Unsupported channel name", comment: "alert title"),
+ message: NSLocalizedString("Connecting via channel name requires a newer app version.", comment: "alert message") + upgrade
+ )
}
}
@@ -1295,13 +1314,21 @@ func planAndConnect(
filterKnownContact: ((Contact) -> Void)? = nil,
filterKnownGroup: ((GroupInfo) -> Void)? = nil
) {
- if case .simplexLink(_, .relay, _, _) = strHasSingleSimplexLink(shortOrFullLink)?.format {
- showAlert(
- NSLocalizedString("Relay address", comment: "alert title"),
- message: NSLocalizedString("This is a chat relay address, it cannot be used to connect.", comment: "alert message")
- )
+ switch strConnectTarget(shortOrFullLink) {
+ case let .name(nameInfo):
+ showUnsupportedNameAlert(nameInfo)
cleanup?()
return
+ case let .link(_, linkType, _):
+ if linkType == .relay {
+ showAlert(
+ NSLocalizedString("Relay address", comment: "alert title"),
+ message: NSLocalizedString("This is a chat relay address, it cannot be used to connect.", comment: "alert message")
+ )
+ cleanup?()
+ return
+ }
+ case .none: break
}
ConnectProgressManager.shared.cancelConnectProgress()
let inProgress = BoxedValue(true)
@@ -1559,6 +1586,33 @@ func planAndConnect(
cleanup?()
}
}
+ case let .updateRequired(groupSLinkData_):
+ logger.debug("planAndConnect, .groupLink, .updateRequired")
+ await MainActor.run {
+ if let groupSLinkData = groupSLinkData_ {
+ showOpenChatAlert(
+ profileName: groupSLinkData.groupProfile.displayName,
+ profileFullName: groupSLinkData.groupProfile.fullName,
+ profileImage:
+ ProfileImage(
+ imageStr: groupSLinkData.groupProfile.image,
+ iconName: "person.2.circle.fill",
+ size: alertProfileImageSize
+ ),
+ theme: theme,
+ subtitle: NSLocalizedString("This group requires a newer version of the app. Please update the app to join.", comment: "alert subtitle"),
+ cancelTitle: NSLocalizedString("OK", comment: "alert button"),
+ confirmTitle: nil,
+ onCancel: { cleanup?() }
+ )
+ } else {
+ showAlert(
+ NSLocalizedString("App update required", comment: "alert title"),
+ message: NSLocalizedString("This group requires a newer version of the app. Please update the app to join.", comment: "alert message")
+ )
+ cleanup?()
+ }
+ }
}
case let .error(chatError):
logger.debug("planAndConnect, .error \(chatErrorString(chatError))")
diff --git a/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff b/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff
index 71a7a427be..364cee97e5 100644
--- a/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff
+++ b/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff
@@ -715,6 +715,10 @@ swipe action
Активни връзкиNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.No comment provided by engineer.
@@ -739,6 +743,14 @@ swipe action
Добави профилNo comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverДобави сървър
@@ -784,10 +796,6 @@ swipe action
Добавени сървъри за съобщенияNo comment provided by engineer.
-
- Adding relays will be supported later.
- No comment provided by engineer.
- Additional accentДопълнителен акцент
@@ -1157,6 +1165,10 @@ swipe action
Сесия на приложениетоNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionВерсия на приложението
@@ -1578,6 +1590,14 @@ in your network
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationОтмени миграцията
@@ -1722,8 +1742,8 @@ alert subtitle
Channel will be deleted for you - this cannot be undone!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2215,6 +2235,14 @@ This is your own one-time link!
Свързване с настолно устройствоNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionВръзка
@@ -2360,7 +2388,7 @@ This is your own one-time link!
ContinueПродължи
- No comment provided by engineer.
+ alert actionContribute
@@ -2780,6 +2808,10 @@ swipe action
Изтрий за менNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupИзтрий група
@@ -3514,6 +3546,10 @@ chat item action
Error adding relayalert title
+
+ Error adding relays
+ alert title
+ Error adding serveralert title
@@ -3632,6 +3668,10 @@ chat item action
Грешка при изтриване на базата данниalert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseГрешка при изтриване на старата база данни
@@ -5677,6 +5717,10 @@ The most secure encryption.
Приложението няма kод за достъпAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNo comment provided by engineer.
@@ -5788,6 +5832,10 @@ The most secure encryption.
Няма получени или изпратени файловеNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.servers error
@@ -6373,6 +6421,10 @@ Error: %@
Please try to disable and re-enable notfications.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.snd group event chat item
@@ -6480,10 +6532,6 @@ Error: %@
Private routing timeoutalert title
-
- Proceed
- alert action
- Profile and server connectionsПрофилни и сървърни връзки
@@ -6845,6 +6893,14 @@ swipe action
Relay test failed!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.No comment provided by engineer.
@@ -6885,9 +6941,9 @@ swipe action
Премахване на паролата от keychain?No comment provided by engineer.
-
- Remove subscriber
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -8078,6 +8134,10 @@ report reason
StatisticsNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ StopСпри
@@ -8608,10 +8668,19 @@ your contacts and groups.
Тази група вече не съществува.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!new chat action
@@ -8920,10 +8989,18 @@ To connect, please ask your contact to create another connection link and check
Непрочетеноswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.На новите членове се изпращат до последните 100 съобщения.
@@ -9852,6 +9929,11 @@ Repeat connection request?
Your networkNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesВашите настройки
diff --git a/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff b/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff
index 1cc44dd7cb..5ba29ec846 100644
--- a/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff
+++ b/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff
@@ -710,6 +710,10 @@ swipe action
Aktivní spojeníNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.No comment provided by engineer.
@@ -732,6 +736,14 @@ swipe action
Přidat profilNo comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverPřidat server
@@ -776,10 +788,6 @@ swipe action
Přidané servery zprávNo comment provided by engineer.
-
- Adding relays will be supported later.
- No comment provided by engineer.
- Additional accentDalší zbarvení
@@ -1140,6 +1148,10 @@ swipe action
App sessionNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionVerze aplikace
@@ -1542,6 +1554,14 @@ in your network
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationZrušit přesun
@@ -1686,8 +1706,8 @@ alert subtitle
Channel will be deleted for you - this cannot be undone!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2127,6 +2147,14 @@ Toto je váš vlastní jednorázový odkaz!
Connecting to desktopNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionPřipojení
@@ -2264,7 +2292,7 @@ Toto je váš vlastní jednorázový odkaz!
ContinuePokračovat
- No comment provided by engineer.
+ alert actionContribute
@@ -2673,6 +2701,10 @@ swipe action
Smazat pro měNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupSmazat skupinu
@@ -3387,6 +3419,10 @@ chat item action
Error adding relayalert title
+
+ Error adding relays
+ alert title
+ Error adding serveralert title
@@ -3504,6 +3540,10 @@ chat item action
Chyba při mazání databázealert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseChyba při mazání staré databáze
@@ -5489,6 +5529,10 @@ The most secure encryption.
Žádné heslo aplikaceAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNo comment provided by engineer.
@@ -5599,6 +5643,10 @@ The most secure encryption.
Žádné přijaté ani odeslané souboryNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.servers error
@@ -6169,6 +6217,10 @@ Error: %@
Please try to disable and re-enable notfications.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.snd group event chat item
@@ -6275,10 +6327,6 @@ Error: %@
Private routing timeoutalert title
-
- Proceed
- alert action
- Profile and server connectionsProfil a připojení k serveru
@@ -6634,6 +6682,14 @@ swipe action
Relay test failed!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.No comment provided by engineer.
@@ -6674,9 +6730,9 @@ swipe action
Odstranit přístupovou frázi z klíčenek?No comment provided by engineer.
-
- Remove subscriber
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -7845,6 +7901,10 @@ report reason
StatisticsNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ StopZastavit
@@ -8367,10 +8427,19 @@ your contacts and groups.
Tato skupina již neexistuje.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!new chat action
@@ -8670,10 +8739,18 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
Nepřečtenýswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.No comment provided by engineer.
@@ -9567,6 +9644,11 @@ Repeat connection request?
Your networkNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesVaše preference
diff --git a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff
index 872fafddd7..797a489c92 100644
--- a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff
+++ b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff
@@ -622,7 +622,7 @@ time interval
A separate TCP connection will be used **for each chat profile you have in the app**.
- **Für jedes von Ihnen in der App genutzte Chat-Profil** wird eine separate TCP-Verbindung genutzt.
+ **Für jedes von Ihnen in der App genutzte Chat-Profil** wird eine separate TCP-Verbindung (und SOCKS-Berechtigung) genutzt.No comment provided by engineer.
@@ -736,6 +736,10 @@ swipe action
Aktive VerbindungenNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.Fügen Sie die Adresse Ihrem Profil hinzu, damit Ihre SimpleX-Kontakte sie mit anderen Personen teilen können. Es wird eine Profilaktualisierung an Ihre SimpleX-Kontakte gesendet.
@@ -761,6 +765,14 @@ swipe action
Profil hinzufügenNo comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverServer hinzufügen
@@ -806,11 +818,6 @@ swipe action
Nachrichtenserver hinzugefügtNo comment provided by engineer.
-
- Adding relays will be supported later.
- Das Hinzufügen von Relais wird zu einem späteren Zeitpunkt unterstützt.
- No comment provided by engineer.
- Additional accentErste Akzentfarbe
@@ -963,7 +970,7 @@ swipe action
All your contacts, conversations and files will be securely encrypted and uploaded in chunks to configured XFTP relays.
- Alle Ihre Kontakte, Unterhaltungen und Dateien werden sicher verschlüsselt und in Daten-Paketen auf die konfigurierten XTFP-Relais hochgeladen.
+ Alle Ihre Kontakte, Unterhaltungen und Dateien werden sicher verschlüsselt und in Daten-Paketen auf die konfigurierten XTFP-Router hochgeladen.No comment provided by engineer.
@@ -1123,12 +1130,12 @@ swipe action
Always use private routing.
- Sie nutzen immer privates Routing.
+ Immer privates Routing nutzen.No comment provided by engineer.Always use relay
- Über ein Relais verbinden
+ Immer über einen Router verbindenNo comment provided by engineer.
@@ -1186,6 +1193,10 @@ swipe action
App-SitzungNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionApp Version
@@ -1198,7 +1209,7 @@ swipe action
Appearance
- Erscheinungsbild
+ DarstellungNo comment provided by engineer.
@@ -1615,6 +1626,14 @@ in Ihrem Netzwerk
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationMigration abbrechen
@@ -1772,9 +1791,8 @@ alert subtitle
Der Kanal wird für Sie gelöscht. Dies kann nicht rückgängig gemacht werden!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
- Der Kanal wird mit %1$d von %2$d Relais gestartet. Fortfahren?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -1864,7 +1882,7 @@ alert subtitle
Chat profile
- Benutzerprofil
+ Chat-ProfilNo comment provided by engineer.
@@ -2070,7 +2088,7 @@ chat toolbar
Conditions accepted on: %@.
- Die Nutzungsbedingungen wurden akzeptiert am: %@.
+ Die Nutzungsbedingungen wurden am %@ akzeptiert.No comment provided by engineer.
@@ -2095,12 +2113,12 @@ chat toolbar
Conditions will be accepted on: %@.
- Die Nutzungsbedingungen werden akzeptiert am: %@.
+ Die Nutzungsbedingungen werden am %@ akzeptiert.No comment provided by engineer.Conditions will be automatically accepted for enabled operators on: %@.
- Die Nutzungsbedingungen der aktivierten Betreiber werden automatisch akzeptiert am: %@.
+ Die Nutzungsbedingungen der aktivierten Betreiber werden am %@ automatisch akzeptiert.No comment provided by engineer.
@@ -2278,6 +2296,14 @@ Das ist Ihr eigener Einmal-Link!
Mit dem Desktop verbindenNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionVerbindung
@@ -2433,7 +2459,7 @@ Das ist Ihr eigener Einmal-Link!
ContinueWeiter
- No comment provided by engineer.
+ alert actionContribute
@@ -2879,6 +2905,10 @@ swipe action
Nur bei mir löschenNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupGruppe löschen
@@ -3242,7 +3272,7 @@ alert button
Do NOT use private routing.
- Sie nutzen KEIN privates Routing.
+ KEIN privates Routing nutzen.No comment provided by engineer.
@@ -3262,7 +3292,7 @@ alert button
Do not use credentials with proxy.
- Verwenden Sie keine Anmeldeinformationen mit einem Proxy.
+ Keine Anmeldeinformationen mit einem Proxy verwenden.No comment provided by engineer.
@@ -3666,6 +3696,10 @@ chat item action
Fehler beim Hinzufügen des Relaisalert title
+
+ Error adding relays
+ alert title
+ Error adding serverFehler beim Hinzufügen des Servers
@@ -3796,6 +3830,10 @@ chat item action
Fehler beim Löschen der Datenbankalert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseFehler beim Löschen der alten Datenbank
@@ -5895,12 +5933,12 @@ wer mit wem kommuniziert
New SOCKS credentials will be used every time you start the app.
- Jedes Mal wenn Sie die App starten, werden neue SOCKS-Anmeldeinformationen genutzt
+ Bei jedem Neustart der App, werden neue SOCKS-Anmeldeinformationen genutzt.No comment provided by engineer.New SOCKS credentials will be used for each server.
- Für jeden Server werden neue SOCKS-Anmeldeinformationen genutzt
+ Für jeden Server werden neue SOCKS-Anmeldeinformationen genutzt.No comment provided by engineer.
@@ -6005,6 +6043,10 @@ Die sicherste Verschlüsselung.
Kein App-PasswortAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysKeine Chat-Relais
@@ -6130,9 +6172,13 @@ Die sicherste Verschlüsselung.
Keine herunter- oder hochgeladenen DateienNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.
- Keine Server für privates Nachrichten-Routing.
+ Keine Router für privates Nachrichten-Routing.servers error
@@ -6778,6 +6824,10 @@ Fehler: %@
Bitte versuchen Sie, die Benachrichtigungen zu deaktivieren und wieder zu aktivieren.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.Bitte warten Sie auf die Überprüfung Ihrer Anfrage durch die Gruppen-Moderatoren, um der Gruppe beitreten zu können.
@@ -6855,7 +6905,7 @@ Fehler: %@
Privacy: for owners and subscribers.
- Privatsphäre: für Besitzer und Abonnenten.
+ Privatsphäre: Für Eigentümer und Abonnenten.No comment provided by engineer.
@@ -6903,11 +6953,6 @@ Fehler: %@
Zeitüberschreitung der privaten Routing-Sitzungalert title
-
- Proceed
- Fortfahren
- alert action
- Profile and server connectionsProfil und Serververbindungen
@@ -7011,7 +7056,7 @@ Fehler: %@
Protect your IP address from the messaging relays chosen by your contacts.
Enable in *Network & servers* settings.
- Schützen Sie Ihre IP-Adresse vor den Nachrichten-Relais, die Ihre Kontakte ausgewählt haben.
+ Schützen Sie Ihre IP-Adresse vor den Nachrichten-Routern, die Ihre Kontakte ausgewählt haben.
Aktivieren Sie es in den *Netzwerk & Server* Einstellungen.No comment provided by engineer.
@@ -7294,7 +7339,7 @@ swipe action
Relay server protects your IP address, but it can observe the duration of the call.
- Relais-Server schützen Ihre IP-Adresse, aber sie können die Anrufdauer erfassen.
+ Relais-Server schützen Ihre IP-Adresse, können aber die Anrufdauer erfassen.No comment provided by engineer.
@@ -7302,9 +7347,17 @@ swipe action
Relais-Test fehlgeschlagen!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.
- Zuverlässigkeit: mehrere Relais pro Kanal.
+ Zuverlässigkeit: Mehrere Relais pro Kanal.No comment provided by engineer.
@@ -7347,10 +7400,9 @@ swipe action
Passwort aus dem Schlüsselbund entfernen?No comment provided by engineer.
-
- Remove subscriber
- Abonnent entfernen
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -7850,7 +7902,7 @@ chat item action
Security: owners hold channel keys.
- Sicherheit: Eigentümer besitzen die Kanalschlüssel.
+ Sicherheit: Nur die Eigentümer des Kanals besitzen die Schlüssel.No comment provided by engineer.
@@ -7945,12 +7997,12 @@ chat item action
Send messages directly when IP address is protected and your or destination server does not support private routing.
- Nachrichten werden direkt versendet, wenn die IP-Adresse geschützt ist, und Ihr oder der Zielserver kein privates Routing unterstützt.
+ Nachrichten werden direkt versendet, wenn die IP-Adresse geschützt ist, und Ihr oder der Ziel-Server kein privates Routing unterstützt.No comment provided by engineer.Send messages directly when your or destination server does not support private routing.
- Nachrichten werden direkt versendet, wenn Ihr oder der Zielserver kein privates Routing unterstützt.
+ Nachrichten werden direkt versendet, wenn Ihr oder der Ziel-Server kein privates Routing unterstützt.No comment provided by engineer.
@@ -8150,7 +8202,7 @@ chat item action
Server requires authorization to connect to relay, check password.
- Der Server erfordert eine Autorisierung, um eine Verbindung zum Relais herzustellen. Bitte Passwort überprüfen.
+ Der Server erfordert eine Autorisierung, um eine Verbindung zum Router herzustellen. Bitte Passwort überprüfen.relay test error
@@ -8366,7 +8418,7 @@ chat item action
Share relay address
- Relais-Adresse teilen
+ Router-Adresse teilenNo comment provided by engineer.
@@ -8667,6 +8719,10 @@ report reason
StatistikenNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ StopBeenden
@@ -9254,11 +9310,20 @@ in dem Sie Ihre Kontakte und Gruppen besitzen.
Diese Gruppe existiert nicht mehr.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.Dies ist eine Chat‑Relais-Adresse, welche nicht zum Verbinden verwendet werden kann.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!Dies ist Ihr Link für den Kanal %@!
@@ -9336,7 +9401,7 @@ in dem Sie Ihre Kontakte und Gruppen besitzen.
To protect your IP address, private routing uses your SMP servers to deliver messages.
- Zum Schutz Ihrer IP-Adresse, wird für die Nachrichten-Auslieferung privates Routing über Ihre konfigurierten SMP-Server genutzt.
+ Zum Schutz Ihrer IP-Adresse, wird für die Nachrichten-Auslieferung privates Routing über Ihre konfigurierten SMP-Router genutzt.No comment provided by engineer.
@@ -9593,11 +9658,19 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
Ungelesenswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkVerbindungs-Link wird nicht unterstütztconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.Bis zu 100 der letzten Nachrichten werden an neue Mitglieder gesendet.
@@ -9785,12 +9858,12 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
Use private routing with unknown servers when IP address is not protected.
- Sie nutzen privates Routing mit unbekannten Servern, wenn Ihre IP-Adresse nicht geschützt ist.
+ Bei unbekannten Servern privates Routing nutzen, wenn Ihre IP-Adresse nicht geschützt ist.No comment provided by engineer.Use private routing with unknown servers.
- Sie nutzen privates Routing mit unbekannten Servern.
+ Bei unbekannten Servern privates Routing nutzen.No comment provided by engineer.
@@ -10120,7 +10193,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
Without Tor or VPN, your IP address will be visible to these XFTP relays: %@.
- Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für diese XFTP-Relais sichtbar sein: %@.
+ Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für diese XFTP-Router sichtbar sein: %@.alert message
@@ -10237,7 +10310,7 @@ Verbindungsanfrage wiederholen?
You can change it in Appearance settings.
- Kann von Ihnen in den Erscheinungsbild-Einstellungen geändert werden.
+ Sie können dies in den Einstellungen unter „Darstellung“ ändern.No comment provided by engineer.
@@ -10606,6 +10679,11 @@ Verbindungsanfrage wiederholen?
Ihr NetzwerkNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesIhre Präferenzen
@@ -11659,7 +11737,7 @@ Zuletzt empfangene Nachricht: %2$@
unknown servers
- Unbekannte Relais
+ Unbekannte ServerNo comment provided by engineer.
diff --git a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff
index 5e95cf39cc..c108dcc904 100644
--- a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff
+++ b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff
@@ -736,6 +736,11 @@ swipe action
Active connectionsNo comment provided by engineer.
+
+ Add
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.
@@ -761,6 +766,16 @@ swipe action
Add profileNo comment provided by engineer.
+
+ Add relays
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverAdd server
@@ -806,11 +821,6 @@ swipe action
Added message serversNo comment provided by engineer.
-
- Adding relays will be supported later.
- Adding relays will be supported later.
- No comment provided by engineer.
- Additional accentAdditional accent
@@ -1186,6 +1196,11 @@ swipe action
App sessionNo comment provided by engineer.
+
+ App update required
+ App update required
+ alert title
+ App versionApp version
@@ -1615,6 +1630,16 @@ in your network
alert button
new chat action
+
+ Cancel and delete channel
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ Cancel creating channel?
+ alert title
+ Cancel migrationCancel migration
@@ -1772,9 +1797,9 @@ alert subtitle
Channel will be deleted for you - this cannot be undone!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
- Channel will start working with %1$d of %2$d relays. Proceed?
+
+ Channel will start working with %1$d of %2$d relays. Continue?
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2278,6 +2303,16 @@ This is your own one-time link!
Connecting to desktopNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionConnection
@@ -2433,7 +2468,7 @@ This is your own one-time link!
ContinueContinue
- No comment provided by engineer.
+ alert actionContribute
@@ -2879,6 +2914,11 @@ swipe action
Delete for meNo comment provided by engineer.
+
+ Delete from history
+ Delete from history
+ No comment provided by engineer.
+ Delete groupDelete group
@@ -3666,6 +3706,11 @@ chat item action
Error adding relayalert title
+
+ Error adding relays
+ Error adding relays
+ alert title
+ Error adding serverError adding server
@@ -3796,6 +3841,11 @@ chat item action
Error deleting databasealert title
+
+ Error deleting message
+ Error deleting message
+ alert title
+ Error deleting old databaseError deleting old database
@@ -6005,6 +6055,11 @@ The most secure encryption.
No app passwordAuthentication unavailable
+
+ No available relays
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNo chat relays
@@ -6130,6 +6185,11 @@ The most secure encryption.
No received or sent filesNo comment provided by engineer.
+
+ No relays
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.No servers for private message routing.
@@ -6778,6 +6838,11 @@ Error: %@
Please try to disable and re-enable notfications.token info
+
+ Please upgrade the app.
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.Please wait for group moderators to review your request to join the group.
@@ -6903,11 +6968,6 @@ Error: %@
Private routing timeoutalert title
-
- Proceed
- Proceed
- alert action
- Profile and server connectionsProfile and server connections
@@ -7302,6 +7362,16 @@ swipe action
Relay test failed!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.Reliability: many relays per channel.
@@ -7347,10 +7417,10 @@ swipe action
Remove passphrase from keychain?No comment provided by engineer.
-
- Remove subscriber
- Remove subscriber
- No comment provided by engineer.
+
+ Remove relay?
+ Remove relay?
+ alert titleRemove subscriber?
@@ -8667,6 +8737,11 @@ report reason
StatisticsNo comment provided by engineer.
+
+ Status
+ Status
+ No comment provided by engineer.
+ StopStop
@@ -9254,11 +9329,22 @@ your contacts and groups.
This group no longer exists.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.This is a chat relay address, it cannot be used to connect.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!This is your link for channel %@!
@@ -9593,11 +9679,21 @@ To connect, please ask your contact to create another connection link and check
Unreadswipe action
+
+ Unsupported channel name
+ Unsupported channel name
+ alert title
+ Unsupported connection linkUnsupported connection linkconn error description
+
+ Unsupported contact name
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.Up to 100 last messages are sent to new members.
@@ -10606,6 +10702,13 @@ Repeat connection request?
Your networkNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesYour preferences
diff --git a/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff b/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff
index 43d3895cc4..d93e692a63 100644
--- a/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff
+++ b/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff
@@ -7,7 +7,7 @@
(can be copied)
- (puede copiarse)
+ (puede ser copiado)No comment provided by engineer.
@@ -736,6 +736,10 @@ swipe action
Conexiones activasNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.Añade la dirección a tu perfil para que tus contactos SimpleX puedan compartirla con otros. La actualización del perfil se enviará a tus contactos SimpleX.
@@ -761,6 +765,14 @@ swipe action
Añadir perfilNo comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverAñadir servidor
@@ -806,11 +818,6 @@ swipe action
Servidores de mensajes añadidosNo comment provided by engineer.
-
- Adding relays will be supported later.
- Añadir servidores estará disponible en una versión posterior.
- No comment provided by engineer.
- Additional accentAcento adicional
@@ -1186,6 +1193,10 @@ swipe action
por sesiónNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionVersión de la aplicación
@@ -1615,6 +1626,14 @@ en tu red
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationCancelar migración
@@ -1772,9 +1791,8 @@ alert subtitle
El canal será eliminado para tí. ¡No puede deshacerse!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
- El canal comenzará a funcionar con %1$d de %2$d servidores. ¿Continuar?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2278,6 +2296,14 @@ This is your own one-time link!
Conectando con ordenadorNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionConexión
@@ -2433,7 +2459,7 @@ This is your own one-time link!
ContinueContinuar
- No comment provided by engineer.
+ alert actionContribute
@@ -2879,6 +2905,10 @@ swipe action
Eliminar para míNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupEliminar grupo
@@ -3666,6 +3696,10 @@ chat item action
Error al añadir el servidoralert title
+
+ Error adding relays
+ alert title
+ Error adding serverError al añadir servidor
@@ -3796,6 +3830,10 @@ chat item action
Error al eliminar base de datosalert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseError al eliminar base de datos antigua
@@ -6005,6 +6043,10 @@ El cifrado más seguro.
Sin contraseña de la aplicaciónAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysSin servidores de chat
@@ -6130,6 +6172,10 @@ El cifrado más seguro.
Sin archivos recibidos o enviadosNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.Sin servidores para enrutamiento privado.
@@ -6778,6 +6824,10 @@ Error: %@
Por favor, intenta desactivar y reactivar las notificaciones.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.Por favor, espera a que tu solicitud sea revisada por los moderadores del grupo.
@@ -6903,11 +6953,6 @@ Error: %@
Timeout enrutamiento privadoalert title
-
- Proceed
- Continuar
- alert action
- Profile and server connectionsEliminar perfil y conexiones
@@ -7302,6 +7347,14 @@ swipe action
¡El test del servidor ha fallado!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.Fiabilidad: muchos servidores por canal.
@@ -7347,10 +7400,9 @@ swipe action
¿Eliminar contraseña de Keychain?No comment provided by engineer.
-
- Remove subscriber
- Eliminar suscriptor
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -8667,6 +8719,10 @@ report reason
EstadísticasNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ StopParar
@@ -9254,11 +9310,20 @@ y los contactos son tuyos.
Este grupo ya no existe.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.Esto es una dirección de servidor, no puede usarse para conectar.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!Este es tu enlace para el canal %@!
@@ -9593,11 +9658,19 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión
No leídoswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkEnlace de conexión no compatibleconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.Hasta 100 últimos mensajes son enviados a los miembros nuevos.
@@ -10606,6 +10679,11 @@ Repeat connection request?
Tu redNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesMis preferencias
diff --git a/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff b/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff
index 892f686bd2..5656516b7d 100644
--- a/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff
+++ b/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff
@@ -667,6 +667,10 @@ swipe action
Active connectionsNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.No comment provided by engineer.
@@ -688,6 +692,14 @@ swipe action
Lisää profiiliNo comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverLisää palvelin
@@ -728,10 +740,6 @@ swipe action
Added message serversNo comment provided by engineer.
-
- Adding relays will be supported later.
- No comment provided by engineer.
- Additional accentNo comment provided by engineer.
@@ -1069,6 +1077,10 @@ swipe action
App sessionNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionSovellusversio
@@ -1442,6 +1454,14 @@ in your network
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationNo comment provided by engineer.
@@ -1580,8 +1600,8 @@ alert subtitle
Channel will be deleted for you - this cannot be undone!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2014,6 +2034,14 @@ This is your own one-time link!
Connecting to desktopNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionYhteys
@@ -2151,7 +2179,7 @@ This is your own one-time link!
ContinueJatka
- No comment provided by engineer.
+ alert actionContribute
@@ -2560,6 +2588,10 @@ swipe action
Poista minultaNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupPoista ryhmä
@@ -3273,6 +3305,10 @@ chat item action
Error adding relayalert title
+
+ Error adding relays
+ alert title
+ Error adding serveralert title
@@ -3389,6 +3425,10 @@ chat item action
Virhe tietokannan poistamisessaalert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseVirhe vanhan tietokannan poistamisessa
@@ -5372,6 +5412,10 @@ The most secure encryption.
Ei sovelluksen salasanaaAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNo comment provided by engineer.
@@ -5482,6 +5526,10 @@ The most secure encryption.
Ei vastaanotettuja tai lähetettyjä tiedostojaNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.servers error
@@ -6049,6 +6097,10 @@ Error: %@
Please try to disable and re-enable notfications.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.snd group event chat item
@@ -6155,10 +6207,6 @@ Error: %@
Private routing timeoutalert title
-
- Proceed
- alert action
- Profile and server connectionsProfiili- ja palvelinyhteydet
@@ -6514,6 +6562,14 @@ swipe action
Relay test failed!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.No comment provided by engineer.
@@ -6554,9 +6610,9 @@ swipe action
Poista tunnuslause avainnipusta?No comment provided by engineer.
-
- Remove subscriber
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -7723,6 +7779,10 @@ report reason
StatisticsNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ StopLopeta
@@ -8242,10 +8302,19 @@ your contacts and groups.
Tätä ryhmää ei enää ole olemassa.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!new chat action
@@ -8544,10 +8613,18 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
Lukematonswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.No comment provided by engineer.
@@ -9439,6 +9516,11 @@ Repeat connection request?
Your networkNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesAsetuksesi
diff --git a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff
index be6a766ca1..3ea0859d76 100644
--- a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff
+++ b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff
@@ -715,6 +715,10 @@ swipe action
Connections activesNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.No comment provided by engineer.
@@ -739,6 +743,14 @@ swipe action
Ajouter un profilNo comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverAjouter un serveur
@@ -784,10 +796,6 @@ swipe action
Ajout de serveurs de messagesNo comment provided by engineer.
-
- Adding relays will be supported later.
- No comment provided by engineer.
- Additional accentAccent additionnel
@@ -1156,6 +1164,10 @@ swipe action
Session de l'appNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionVersion de l'app
@@ -1571,6 +1583,14 @@ in your network
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationAnnuler le transfert
@@ -1715,8 +1735,8 @@ alert subtitle
Channel will be deleted for you - this cannot be undone!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2203,6 +2223,14 @@ Il s'agit de votre propre lien unique !
Connexion au bureauNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionConnexion
@@ -2355,7 +2383,7 @@ Il s'agit de votre propre lien unique !
ContinueContinuer
- No comment provided by engineer.
+ alert actionContribute
@@ -2791,6 +2819,10 @@ swipe action
Supprimer pour moiNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupSupprimer le groupe
@@ -3558,6 +3590,10 @@ chat item action
Error adding relayalert title
+
+ Error adding relays
+ alert title
+ Error adding serverErreur lors de l'ajout du serveur
@@ -3683,6 +3719,10 @@ chat item action
Erreur lors de la suppression de la base de donnéesalert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseErreur lors de la suppression de l'ancienne base de données
@@ -5816,6 +5856,10 @@ The most secure encryption.
Pas de mot de passe pour l'appAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNo comment provided by engineer.
@@ -5933,6 +5977,10 @@ The most secure encryption.
Aucun fichier reçu ou envoyéNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.Pas de serveurs pour le routage privé des messages.
@@ -6541,6 +6589,10 @@ Erreur : %@
Please try to disable and re-enable notfications.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.snd group event chat item
@@ -6656,10 +6708,6 @@ Erreur : %@
Private routing timeoutalert title
-
- Proceed
- alert action
- Profile and server connectionsProfil et connexions au serveur
@@ -7038,6 +7086,14 @@ swipe action
Relay test failed!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.No comment provided by engineer.
@@ -7080,9 +7136,9 @@ swipe action
Supprimer la phrase secrète de la keychain ?No comment provided by engineer.
-
- Remove subscriber
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -8339,6 +8395,10 @@ report reason
StatistiquesNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ StopArrêter
@@ -8889,10 +8949,19 @@ your contacts and groups.
Ce groupe n'existe plus.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!new chat action
@@ -9215,10 +9284,18 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
Non luswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.Les 100 derniers messages sont envoyés aux nouveaux membres.
@@ -10185,6 +10262,11 @@ Répéter la demande de connexion ?
Your networkNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesVos préférences
diff --git a/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff b/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff
index 7723cabdcb..129436ecb0 100644
--- a/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff
+++ b/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff
@@ -257,12 +257,12 @@ channel relay bar
%1$d/%2$d relays connected
- %1$d/%2$d átjátszó kapcsolódva
+ %1$d/%2$d átjátszó kapcsolódottchannel subscriber relay bar progress%1$d/%2$d relays connected, %3$d errors
- %1$d/%2$d átjátszó kapcsolódva, %3$d hiba
+ %1$d/%2$d átjátszó kapcsolódott, %3$d hibachannel subscriber relay bar
@@ -412,17 +412,17 @@ channel relay bar
**Create 1-time link**: to create and share a new invitation link.
- **Partner hozzáadása:** új meghívási hivatkozás létrehozásához, vagy egy kapott hivatkozáson keresztül történő kapcsolódáshoz.
+ **Partner hozzáadása**: új meghívási hivatkozás létrehozásához, vagy egy kapott hivatkozáson keresztül történő kapcsolódáshoz.No comment provided by engineer.**Create group**: to create a new group.
- **Csoport létrehozása:** új csoport létrehozásához.
+ **Csoport létrehozása**: új csoport létrehozásához.No comment provided by engineer.**More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata.
- **Privátabb:** 20 percenként ellenőrzi az új üzeneteket. Az eszköztoken meg lesz osztva a SimpleX Chat kiszolgálóval, de az nem, hogy hány partnere vagy üzenete van.
+ **Privátabb**: 20 percenként ellenőrzi az új üzeneteket. Az eszköztoken meg lesz osztva a SimpleX Chat kiszolgálóval, de az nem, hogy hány partnere vagy üzenete van.No comment provided by engineer.
@@ -432,17 +432,17 @@ channel relay bar
**Please note**: using the same database on two devices will break the decryption of messages from your connections, as a security protection.
- **Megjegyzés:** ha két eszközön is ugyanazt az adatbázist használja, akkor biztonsági védelemként megszakítja a partnereitől érkező üzenetek visszafejtését.
+ **Megjegyzés**: ha két eszközön is ugyanazt az adatbázist használja, akkor biztonsági védelemként megszakítja a partnereitől érkező üzenetek visszafejtését.No comment provided by engineer.**Please note**: you will NOT be able to recover or change passphrase if you lose it.
- **Megjegyzés:** NEM fogja tudni helyreállítani vagy módosítani a jelmondatot abban az esetben, ha elveszíti.
+ **Megjegyzés**: NEM fogja tudni helyreállítani vagy módosítani a jelmondatot abban az esetben, ha elveszíti.No comment provided by engineer.**Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from.
- **Megjegyzés:** az eszköztoken és az értesítések el lesznek küldve a SimpleX Chat értesítési kiszolgálóra, kivéve az üzenet tartalma, mérete vagy az, hogy kitől származik.
+ **Megjegyzés**: az eszköztoken és az értesítések el lesznek küldve a SimpleX Chat értesítési kiszolgálóra, kivéve az üzenet tartalma, mérete vagy az, hogy kitől származik.No comment provided by engineer.
@@ -457,12 +457,12 @@ channel relay bar
**Warning**: Instant push notifications require passphrase saved in Keychain.
- **Figyelmeztetés:** Az azonnali leküldéses értesítésekhez a kulcstartóban tárolt jelmondat megadása szükséges.
+ **Figyelmeztetés**: Az azonnali leküldéses értesítésekhez a kulcstartóban tárolt jelmondat megadása szükséges.No comment provided by engineer.**Warning**: the archive will be removed.
- **Figyelmeztetés:** az archívum el lesz távolítva.
+ **Figyelmeztetés**: az archívum el lesz távolítva.No comment provided by engineer.
@@ -629,7 +629,7 @@ time interval
A separate TCP connection will be used **for each contact and group member**.
**Please note**: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail.**Az összes partneréhez és csoporttaghoz** külön TCP-kapcsolat lesz használva.
-**Megjegyzés:** ha sok kapcsolata van, akkor az akkumulátor-használat és az adatforgalom jelentősen megnövekedhet, és néhány kapcsolódási kísérlet sikertelen lehet.
+**Megjegyzés**: ha sok kapcsolata van, akkor az akkumulátor-használat és az adatforgalom jelentősen megnövekedhet, és néhány kapcsolódási kísérlet sikertelen lehet.
No comment provided by engineer.
@@ -718,7 +718,7 @@ swipe action
Acknowledged
- Visszaigazolt
+ VisszaigazolvaNo comment provided by engineer.
@@ -736,6 +736,10 @@ swipe action
Aktív kapcsolatok számaNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.Cím hozzáadása a profilhoz, hogy a SimpleX partnerei megoszthassák másokkal. A profilfrissítés el lesz küldve a SimpleX partnerei számára.
@@ -761,6 +765,14 @@ swipe action
Profil hozzáadásaNo comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverKiszolgáló hozzáadása
@@ -806,11 +818,6 @@ swipe action
Hozzáadott üzenetkiszolgálókNo comment provided by engineer.
-
- Adding relays will be supported later.
- Az átjátszók hozzáadása később lesz támogatott.
- No comment provided by engineer.
- Additional accentTovábbi kiemelőszín
@@ -1123,12 +1130,12 @@ swipe action
Always use private routing.
- Mindig legyen használva privát útválasztás.
+ Privát útválasztás használata minden esetben.No comment provided by engineer.Always use relay
- Mindig legyen használva átjátszó
+ Átjátszó használata minden esetbenNo comment provided by engineer.
@@ -1186,6 +1193,10 @@ swipe action
Alkalmazás munkameneteNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionAlkalmazás verziója
@@ -1360,7 +1371,7 @@ a saját hálózatában
Be free in your network.
- Legyen szabad a saját hálózatában.
+ Váljon szabaddá a saját hálózatában.No comment provided by engineer.
@@ -1470,7 +1481,7 @@ a saját hálózatában
Blocked by admin
- Letiltva az adminisztrátor által
+ Az adminisztrátor letiltottaNo comment provided by engineer.
@@ -1615,6 +1626,14 @@ a saját hálózatában
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationÁtköltöztetés visszavonása
@@ -1754,7 +1773,7 @@ alert subtitle
Channel profile was changed. If you save it, the updated profile will be sent to channel subscribers.
- A csatornaprofil módosult. Ha menti, akkor a frissített profil el lesz küldve a csatorna feliratkozóinak.
+ Csatornaprofil módosítva. Ha menti, akkor a frissített profil el lesz küldve a csatorna feliratkozóinak.alert message
@@ -1772,9 +1791,8 @@ alert subtitle
A csatorna törölve lesz az Ön számára – ez a művelet nem vonható vissza!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
- A csatorna %2$d átjátszóból %1$d használatával kezd el működni. Folytatja?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2278,6 +2296,14 @@ Ez a saját egyszer használható meghívója!
Társítás számítógéppelNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionKapcsolat
@@ -2433,7 +2459,7 @@ Ez a saját egyszer használható meghívója!
ContinueFolytatás
- No comment provided by engineer.
+ alert actionContribute
@@ -2701,7 +2727,7 @@ Ez a saját egyszer használható meghívója!
Database passphrase is different from saved in the keychain.
- Az adatbázis jelmondata nem egyezik a kulcstartóba mentettől.
+ Az adatbázis jelmondata eltér a kulcstartóban tárolttól.No comment provided by engineer.
@@ -2879,6 +2905,10 @@ swipe action
Csak nálamNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupCsoport törlése
@@ -3242,7 +3272,7 @@ alert button
Do NOT use private routing.
- NE legyen használva privát útválasztás.
+ Privát útválasztás használatának elkerülése.No comment provided by engineer.
@@ -3533,7 +3563,7 @@ chat item action
Encrypted message: keychain error
- Titkosított üzenet: kulcstartó hiba
+ Titkosított üzenet: kulcstartóhibanotification
@@ -3653,7 +3683,7 @@ chat item action
Error accepting member
- Hiba a tag befogadásakor
+ Hiba történt a tag befogadásakoralert title
@@ -3663,7 +3693,11 @@ chat item action
Error adding relay
- Hiba az átjátszó hozzáadásakor
+ Hiba történt az átjátszó hozzáadásakor
+ alert title
+
+
+ Error adding relaysalert title
@@ -3683,7 +3717,7 @@ chat item action
Error changing chat profile
- Hiba a csevegési profil módosításakor
+ Hiba történt a csevegési profil módosításakoralert title
@@ -3728,7 +3762,7 @@ chat item action
Error creating channel
- Hiba a csatorna létrehozásakor
+ Hiba történt a csatorna létrehozásakoralert title
@@ -3773,7 +3807,7 @@ chat item action
Error deleting chat
- Hiba a csevegés törlésekor
+ Hiba történt a csevegés törlésekoralert title
@@ -3796,6 +3830,10 @@ chat item action
Hiba történt az adatbázis törlésekoralert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseHiba történt a régi adatbázis törlésekor
@@ -3913,7 +3951,7 @@ chat item action
Error saving channel profile
- Hiba a csatornaprofil mentésekor
+ Hiba történt a csatornaprofil mentésekorNo comment provided by engineer.
@@ -3973,7 +4011,7 @@ chat item action
Error setting auto-accept
- Hiba az automatikus elfogadás beállításakor
+ Hiba történt az automatikus elfogadás beállításakorNo comment provided by engineer.
@@ -3983,7 +4021,7 @@ chat item action
Error sharing channel
- Hiba a csatorna megosztásakor
+ Hiba történt a csatorna megosztásakoralert title
@@ -4611,7 +4649,7 @@ Hiba: %2$@
Group profile was changed. If you save it, the updated profile will be sent to group members.
- Csoportprofil módosítva. Ha menti, akkor a frissített profil el lesz küldve a csoporttagoknak.
+ Csoportprofil módosítva. Ha menti, akkor a frissített profil el lesz küldve a csoport tagjainak.alert message
@@ -4726,7 +4764,7 @@ Hiba: %2$@
How to use your servers
- Hogyan használja a saját kiszolgálóit
+ Útmutató a saját kiszolgálók használatáhozNo comment provided by engineer.
@@ -4938,7 +4976,7 @@ További fejlesztések hamarosan!
Install SimpleX Chat for terminal
- A SimpleX Chat terminálhoz telepítése
+ SimpleX Chat telepítése a terminálhozNo comment provided by engineer.
@@ -5273,7 +5311,7 @@ Ez a saját hivatkozása a(z) %@ nevű csoporthoz!
Let someone connect to you
- Hagyja, hogy valaki elérje Önt
+ Legyen elérhető mások számáraNo comment provided by engineer.
@@ -6005,6 +6043,10 @@ A legbiztonságosabb titkosítás.
Nincs alkalmazás jelszóAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNincsenek csevegési átjátszók
@@ -6130,6 +6172,10 @@ A legbiztonságosabb titkosítás.
Nincsenek fogadott vagy küldött fájlokNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.Nincsenek kiszolgálók a privát üzenet-útválasztáshoz.
@@ -6778,6 +6824,10 @@ Hiba: %@
Próbálja meg letiltani és újra engedélyezni az értesítéseket.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.Várja meg, amíg a csoport moderátorai áttekintik a csoporthoz való csatlakozási kérését.
@@ -6855,7 +6905,7 @@ Hiba: %@
Privacy: for owners and subscribers.
- Adatvédelem: tulajdonosok és előfizetők számára.
+ Adatvédelem: tulajdonosok és feliratkozók számára.No comment provided by engineer.
@@ -6903,11 +6953,6 @@ Hiba: %@
Privát útválasztás időtúllépésealert title
-
- Proceed
- Folytatás
- alert action
- Profile and server connectionsProfil és kiszolgálókapcsolatok
@@ -7289,12 +7334,12 @@ swipe action
Relay server is only used if necessary. Another party can observe your IP address.
- Az átjátszó csak szükség esetén lesz használva. Egy másik fél megfigyelheti az IP-címét.
+ Az átjátszó kiszolgáló csak szükség esetén lesz használva. Egy másik fél megfigyelheti az IP-címét.No comment provided by engineer.Relay server protects your IP address, but it can observe the duration of the call.
- Az átjátszó megvédi az IP-címét, de megfigyelheti a hívás időtartamát.
+ Az átjátszó kiszolgáló megvédi az IP-címét, de megfigyelheti a hívás időtartamát.No comment provided by engineer.
@@ -7302,6 +7347,14 @@ swipe action
Nem sikerült tesztelni az átjátszót!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.Megbízhatóság: több átjátszó is használható csatornánként.
@@ -7347,10 +7400,9 @@ swipe action
Eltávolítja a jelmondatot a kulcstartóból?No comment provided by engineer.
-
- Remove subscriber
- Feliratkozó eltávolítása
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -8667,6 +8719,10 @@ report reason
StatisztikákNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ StopMegállítás
@@ -8971,7 +9027,7 @@ Az átjátszó címe ennek az átjátszónak a beállítására szolgált a csat
Test failed at step %@.
- A teszt a(z) %@ lépésnél sikertelen volt.
+ A teszt a(z) %@. lépésnél sikertelen volt.relay test failure
server test failure
@@ -9254,11 +9310,20 @@ a saját kapcsolatait és csoportjait.
Ez a csoport már nem létezik.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.Ez egy csevegési átjátszó címe, nem használható kapcsolódásra.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!Ez a saját hivatkozása a(z) %@ nevű csatornához!
@@ -9593,11 +9658,19 @@ A kapcsolódáshoz kérje meg a partnerét, hogy hozzon létre egy másik kapcso
Olvasatlanswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkNem támogatott kapcsolattartási hivatkozásconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.Legfeljebb az utolsó 100 üzenet lesz elküldve az új tagok számára.
@@ -10175,7 +10248,7 @@ A kapcsolódáshoz kérje meg a partnerét, hogy hozzon létre egy másik kapcso
You are already connected with %@.
- Ön már kapcsolódva van vele: %@.
+ Ön már kapcsolatban van vele: %@.No comment provided by engineer.
@@ -10606,6 +10679,11 @@ Megismétli a kapcsolódási kérést?
Saját hálózatNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesBeállítások
@@ -10815,7 +10893,7 @@ Az átjátszók hozzáférhetnek a csatornaüzenetekhez.
blocked by admin
- letiltva az adminisztrátor által
+ az adminisztrátor letiltottablocked chat item
marked deleted chat item preview text
@@ -11570,7 +11648,7 @@ time to disappear
reviewed by admins
- áttekintve a moderátorok által
+ a moderátorok áttekintettékNo comment provided by engineer.
@@ -11674,12 +11752,12 @@ utoljára fogadott üzenet: %2$@
updated channel profile
- frissített csatornaprofil
+ frissítette a csatorna profiljátrcv group event chat itemupdated group profile
- frissítette a csoportprofilt
+ frissítette a csoport profiljátrcv group event chat item
@@ -12019,7 +12097,7 @@ utoljára fogadott üzenet: %2$@
Database passphrase is different from saved in the keychain.
- Az adatbázis jelmondata nem egyezik a kulcstartóba mentettől.
+ Az adatbázis jelmondata eltér a kulcstartóban tárolttól.No comment provided by engineer.
@@ -12139,7 +12217,7 @@ utoljára fogadott üzenet: %2$@
Wait
- Várjon
+ VárakozásNo comment provided by engineer.
diff --git a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff
index 4d9fce7b4f..469da88ce2 100644
--- a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff
+++ b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff
@@ -736,6 +736,10 @@ swipe action
Connessioni attiveNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.Aggiungi l'indirizzo al tuo profilo, in modo che i tuoi contatti di SimpleX possano condividerlo con altre persone. L'aggiornamento del profilo verrà inviato ai tuoi contatti di SimpleX.
@@ -761,6 +765,14 @@ swipe action
Aggiungi profiloNo comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverAggiungi server
@@ -806,11 +818,6 @@ swipe action
Server dei messaggi aggiuntiNo comment provided by engineer.
-
- Adding relays will be supported later.
- L'aggiunta di relay verrà supportata prossimamente.
- No comment provided by engineer.
- Additional accentPrincipale aggiuntivo
@@ -1186,6 +1193,10 @@ swipe action
Sessione dell'appNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionVersione dell'app
@@ -1615,6 +1626,14 @@ nella tua rete
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationAnnulla migrazione
@@ -1772,9 +1791,8 @@ alert subtitle
Il canale verrà eliminato per te, non è reversibile!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
- Il canale sarà operativo con %1$d di %2$d relay. Procedere?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2278,6 +2296,14 @@ Questo è il tuo link una tantum!
Connessione al desktopNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionConnessione
@@ -2433,7 +2459,7 @@ Questo è il tuo link una tantum!
ContinueContinua
- No comment provided by engineer.
+ alert actionContribute
@@ -2879,6 +2905,10 @@ swipe action
Elimina per meNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupElimina gruppo
@@ -3666,6 +3696,10 @@ chat item action
Errore di aggiunta del relayalert title
+
+ Error adding relays
+ alert title
+ Error adding serverErrore di aggiunta del server
@@ -3796,6 +3830,10 @@ chat item action
Errore nell'eliminazione del databasealert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseErrore nell'eliminazione del database vecchio
@@ -6005,6 +6043,10 @@ La crittografia più sicura.
Nessuna password dell'appAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNessun relay di chat
@@ -6130,6 +6172,10 @@ La crittografia più sicura.
Nessun file ricevuto o inviatoNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.Nessun server per l'instradamento dei messaggi privati.
@@ -6463,12 +6509,12 @@ alert button
Open new channel
- Apri un canale nuovo
+ Apri il nuovo canalenew chat actionOpen new chat
- Apri una chat nuova
+ Apri la nuova chatnew chat action
@@ -6778,6 +6824,10 @@ Errore: %@
Prova a disattivare e riattivare le notifiche.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.Attendi che i moderatori del gruppo revisionino la tua richiesta di entrare nel gruppo.
@@ -6903,11 +6953,6 @@ Errore: %@
Scadenza dell'instradamento privatoalert title
-
- Proceed
- Procedi
- alert action
- Profile and server connectionsProfilo e connessioni al server
@@ -7302,6 +7347,14 @@ swipe action
Prova del relay fallita!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.Affidabilità: relay multipli per canale.
@@ -7347,10 +7400,9 @@ swipe action
Rimuovere la password dal portachiavi?No comment provided by engineer.
-
- Remove subscriber
- Rimuovi iscritto
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -8667,6 +8719,10 @@ report reason
StatisticheNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ StopFerma
@@ -9254,11 +9310,20 @@ i tuoi contatti e i tuoi gruppi.
Questo gruppo non esiste più.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.Questo è un indirizzo di relay di chat, non può essere usato per connettersi.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!Questo è il tuo link per il canale %@!
@@ -9593,11 +9658,19 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
Non lettoswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkLink di connessione non supportatoconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.Vengono inviati ai nuovi membri fino a 100 ultimi messaggi.
@@ -10606,6 +10679,11 @@ Ripetere la richiesta di connessione?
La tua reteNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesLe tue preferenze
diff --git a/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff b/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff
index 0d3a7a9088..13396b13a4 100644
--- a/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff
+++ b/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff
@@ -711,6 +711,10 @@ swipe action
アクティブな接続No comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.No comment provided by engineer.
@@ -734,6 +738,14 @@ swipe action
プロフィールを追加No comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverサーバを追加
@@ -778,10 +790,6 @@ swipe action
追加されたメッセージサーバーNo comment provided by engineer.
-
- Adding relays will be supported later.
- No comment provided by engineer.
- Additional accentNo comment provided by engineer.
@@ -1135,6 +1143,10 @@ swipe action
App sessionNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionアプリのバージョン
@@ -1515,6 +1527,14 @@ in your network
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migration移行を中止する
@@ -1655,8 +1675,8 @@ alert subtitle
Channel will be deleted for you - this cannot be undone!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2107,6 +2127,14 @@ This is your own one-time link!
デスクトップに接続中No comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ Connection接続
@@ -2246,7 +2274,7 @@ This is your own one-time link!
Continue続ける
- No comment provided by engineer.
+ alert actionContribute
@@ -2658,6 +2686,10 @@ swipe action
自分側で削除No comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupグループを削除
@@ -3374,6 +3406,10 @@ chat item action
Error adding relayalert title
+
+ Error adding relays
+ alert title
+ Error adding serveralert title
@@ -3491,6 +3527,10 @@ chat item action
データベースの削除にエラー発生alert title
+
+ Error deleting message
+ alert title
+ Error deleting old database古いデータベースを削除にエラー発生
@@ -5475,6 +5515,10 @@ The most secure encryption.
アプリのパスワードはありませんAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNo comment provided by engineer.
@@ -5585,6 +5629,10 @@ The most secure encryption.
送受信済みのファイルがありませんNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.servers error
@@ -6153,6 +6201,10 @@ Error: %@
Please try to disable and re-enable notfications.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.snd group event chat item
@@ -6260,10 +6312,6 @@ Error: %@
Private routing timeoutalert title
-
- Proceed
- alert action
- Profile and server connectionsプロフィールとサーバ接続
@@ -6618,6 +6666,14 @@ swipe action
Relay test failed!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.No comment provided by engineer.
@@ -6658,9 +6714,9 @@ swipe action
キーチェーンからパスフレーズを削除しますか?No comment provided by engineer.
-
- Remove subscriber
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -7821,6 +7877,10 @@ report reason
StatisticsNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ Stop停止
@@ -8339,10 +8399,19 @@ your contacts and groups.
このグループはもう存在しません。No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!new chat action
@@ -8641,10 +8710,18 @@ To connect, please ask your contact to create another connection link and check
未読swipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.No comment provided by engineer.
@@ -9537,6 +9614,11 @@ Repeat connection request?
Your networkNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesあなたの設定
diff --git a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff
index 3bf4a6f197..9f1818fba9 100644
--- a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff
+++ b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff
@@ -714,6 +714,10 @@ swipe action
Actieve verbindingenNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.No comment provided by engineer.
@@ -737,6 +741,14 @@ swipe action
Profiel toevoegenNo comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverServer toevoegen
@@ -782,10 +794,6 @@ swipe action
Berichtservers toegevoegdNo comment provided by engineer.
-
- Adding relays will be supported later.
- No comment provided by engineer.
- Additional accentExtra accent
@@ -1153,6 +1161,10 @@ swipe action
AppsessieNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionApp versie
@@ -1568,6 +1580,14 @@ in your network
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationMigratie annuleren
@@ -1712,8 +1732,8 @@ alert subtitle
Channel will be deleted for you - this cannot be undone!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2203,6 +2223,14 @@ Dit is uw eigen eenmalige link!
Verbinding maken met desktopNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionVerbinding
@@ -2355,7 +2383,7 @@ Dit is uw eigen eenmalige link!
ContinueDoorgaan
- No comment provided by engineer.
+ alert actionContribute
@@ -2792,6 +2820,10 @@ swipe action
Verwijder voor mijNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupGroep verwijderen
@@ -3560,6 +3592,10 @@ chat item action
Error adding relayalert title
+
+ Error adding relays
+ alert title
+ Error adding serverFout bij toevoegen server
@@ -3686,6 +3722,10 @@ chat item action
Fout bij het verwijderen van de databasealert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseFout bij het verwijderen van de oude database
@@ -5845,6 +5885,10 @@ The most secure encryption.
Geen app wachtwoordAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNo comment provided by engineer.
@@ -5967,6 +6011,10 @@ The most secure encryption.
Geen ontvangen of verzonden bestandenNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.Geen servers voor het routeren van privéberichten.
@@ -6585,6 +6633,10 @@ Fout: %@
Probeer meldingen uit en weer in te schakelen.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.Wacht totdat de moderators van de groep uw verzoek tot lidmaatschap van de groep hebben beoordeeld.
@@ -6705,10 +6757,6 @@ Fout: %@
Private routing timeoutalert title
-
- Proceed
- alert action
- Profile and server connectionsProfiel- en serververbindingen
@@ -7092,6 +7140,14 @@ swipe action
Relay test failed!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.No comment provided by engineer.
@@ -7134,9 +7190,9 @@ swipe action
Wachtwoord van de keychain verwijderen?No comment provided by engineer.
-
- Remove subscriber
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -8415,6 +8471,10 @@ report reason
StatistiekenNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ StopStop
@@ -8969,10 +9029,19 @@ your contacts and groups.
Deze groep bestaat niet meer.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!new chat action
@@ -9298,11 +9367,19 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
Ongelezenswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkNiet-ondersteunde verbindingslinkconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.Er worden maximaal 100 laatste berichten naar nieuwe leden verzonden.
@@ -10275,6 +10352,11 @@ Verbindingsverzoek herhalen?
Your networkNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesJouw voorkeuren
diff --git a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff
index b232aa84af..2644708927 100644
--- a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff
+++ b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff
@@ -715,6 +715,10 @@ swipe action
Aktywne połączeniaNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.No comment provided by engineer.
@@ -739,6 +743,14 @@ swipe action
Dodaj profilNo comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverDodaj serwer
@@ -784,10 +796,6 @@ swipe action
Dodano serwery wiadomościNo comment provided by engineer.
-
- Adding relays will be supported later.
- No comment provided by engineer.
- Additional accentDodatkowy akcent
@@ -1158,6 +1166,10 @@ swipe action
Sesja aplikacjiNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionWersja aplikacji
@@ -1582,6 +1594,14 @@ in your network
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationAnuluj migrację
@@ -1726,8 +1746,8 @@ alert subtitle
Channel will be deleted for you - this cannot be undone!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2219,6 +2239,14 @@ To jest twój jednorazowy link!
Łączenie z komputeremNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionPołączenie
@@ -2373,7 +2401,7 @@ To jest twój jednorazowy link!
ContinueKontynuuj
- No comment provided by engineer.
+ alert actionContribute
@@ -2811,6 +2839,10 @@ swipe action
Usuń dla mnieNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupUsuń grupę
@@ -3585,6 +3617,10 @@ chat item action
Error adding relayalert title
+
+ Error adding relays
+ alert title
+ Error adding serverBłąd podczas dodawania serwera
@@ -3714,6 +3750,10 @@ chat item action
Błąd usuwania bazy danychalert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseBłąd usuwania starej bazy danych
@@ -5895,6 +5935,10 @@ The most secure encryption.
Brak hasła aplikacjiAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNo comment provided by engineer.
@@ -6018,6 +6062,10 @@ The most secure encryption.
Brak odebranych lub wysłanych plikówNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.Brak serwerów prywatnej sesji routingu.
@@ -6648,6 +6696,10 @@ Błąd: %@
Spróbuj wyłączyć, a następnie ponownie włączyć powiadomienia.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.Poczekaj, aż moderatorzy grupy rozpatrzą Twoją prośbę o dołączenie do grupy.
@@ -6769,10 +6821,6 @@ Błąd: %@
Limit czasu routingu prywatnegoalert title
-
- Proceed
- alert action
- Profile and server connectionsProfil i połączenia z serwerem
@@ -7157,6 +7205,14 @@ swipe action
Relay test failed!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.No comment provided by engineer.
@@ -7201,9 +7257,9 @@ swipe action
Usunąć hasło z pęku kluczy?No comment provided by engineer.
-
- Remove subscriber
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -8501,6 +8557,10 @@ report reason
StatystykiNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ StopZatrzymaj
@@ -9065,10 +9125,19 @@ your contacts and groups.
Ta grupa już nie istnieje.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!new chat action
@@ -9399,11 +9468,19 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
Nieprzeczytaneswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkNieobsługiwane łącze połączeniaconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.Do nowych członków wysyłanych jest do 100 ostatnich wiadomości.
@@ -10394,6 +10471,11 @@ Powtórzyć prośbę połączenia?
Your networkNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesTwoje preferencje
diff --git a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff
index a438327ba1..a3971c0325 100644
--- a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff
+++ b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff
@@ -736,6 +736,10 @@ swipe action
Активные соединенияNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.Добавьте адрес в свой профиль, чтобы Ваши SimpleX контакты могли поделиться им. Профиль будет отправлен Вашим SimpleX контактам.
@@ -761,6 +765,14 @@ swipe action
Добавить профильNo comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverДобавить сервер
@@ -806,11 +818,6 @@ swipe action
Дополнительные серверы сообщенийNo comment provided by engineer.
-
- Adding relays will be supported later.
- Добавление релеев будет поддерживаться позже.
- No comment provided by engineer.
- Additional accentДополнительный акцент
@@ -1186,6 +1193,10 @@ swipe action
Сессия приложенияNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionВерсия приложения
@@ -1615,6 +1626,14 @@ in your network
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationОтменить миграцию
@@ -1772,9 +1791,8 @@ alert subtitle
Канал будет удалён для Вас - это нельзя отменить!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
- Канал начнёт работу с %1$d из %2$d релеев. Продолжить?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2278,6 +2296,14 @@ This is your own one-time link!
Подключение к компьютеруNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionСоединение
@@ -2433,7 +2459,7 @@ This is your own one-time link!
ContinueПродолжить
- No comment provided by engineer.
+ alert actionContribute
@@ -2879,6 +2905,10 @@ swipe action
Удалить для меняNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupУдалить группу
@@ -3666,6 +3696,10 @@ chat item action
Ошибка добавления релеяalert title
+
+ Error adding relays
+ alert title
+ Error adding serverОшибка добавления сервера
@@ -3796,6 +3830,10 @@ chat item action
Ошибка при удалении данных чатаalert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseОшибка при удалении предыдущей версии данных чата
@@ -6004,6 +6042,10 @@ The most secure encryption.
Нет кода доступаAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysНет чат-релеев
@@ -6129,6 +6171,10 @@ The most secure encryption.
Нет полученных или отправленных файловNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.Нет серверов для доставки сообщений.
@@ -6777,6 +6823,10 @@ Error: %@
Попробуйте выключить и снова включить уведомления.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.Пожалуйста, подождите, пока модераторы группы рассмотрят ваш запрос на вступление.
@@ -6902,11 +6952,6 @@ Error: %@
Таймаут конфиденциальной доставкиalert title
-
- Proceed
- Продолжить
- alert action
- Profile and server connectionsПрофиль и соединения на сервере
@@ -7301,6 +7346,14 @@ swipe action
Тест релея не пройден!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.Надёжность: несколько релеев на каждый канал.
@@ -7346,10 +7399,9 @@ swipe action
Удалить пароль из Keychain?No comment provided by engineer.
-
- Remove subscriber
- Удалить подписчика
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -8666,6 +8718,10 @@ report reason
СтатистикаNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ StopОстановить
@@ -9253,11 +9309,20 @@ your contacts and groups.
Эта группа больше не существует.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.Это адрес чат-релея, с ним нельзя соединиться.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!Это ваша ссылка на канал %@!
@@ -9592,11 +9657,19 @@ To connect, please ask your contact to create another connection link and check
Не прочитаноswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkСсылка не поддерживаетсяconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.До 100 последних сообщений отправляются новым членам.
@@ -10605,6 +10678,11 @@ Repeat connection request?
Ваша сетьNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesВаши предпочтения
@@ -11673,7 +11751,7 @@ last received msg: %2$@
updated channel profile
- обновлён профиль канала
+ обновил профиль каналаrcv group event chat item
diff --git a/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff b/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff
index 04c51bbf43..cd2e30977d 100644
--- a/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff
+++ b/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff
@@ -659,6 +659,10 @@ swipe action
Active connectionsNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.No comment provided by engineer.
@@ -680,6 +684,14 @@ swipe action
เพิ่มโปรไฟล์No comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverเพิ่มเซิร์ฟเวอร์
@@ -720,10 +732,6 @@ swipe action
Added message serversNo comment provided by engineer.
-
- Adding relays will be supported later.
- No comment provided by engineer.
- Additional accentNo comment provided by engineer.
@@ -1061,6 +1069,10 @@ swipe action
App sessionNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionเวอร์ชันแอป
@@ -1434,6 +1446,14 @@ in your network
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationNo comment provided by engineer.
@@ -1572,8 +1592,8 @@ alert subtitle
Channel will be deleted for you - this cannot be undone!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2005,6 +2025,14 @@ This is your own one-time link!
Connecting to desktopNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ Connectionการเชื่อมต่อ
@@ -2142,7 +2170,7 @@ This is your own one-time link!
Continueดำเนินการต่อ
- No comment provided by engineer.
+ alert actionContribute
@@ -2549,6 +2577,10 @@ swipe action
ลบให้ฉันNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupลบกลุ่ม
@@ -3259,6 +3291,10 @@ chat item action
Error adding relayalert title
+
+ Error adding relays
+ alert title
+ Error adding serveralert title
@@ -3374,6 +3410,10 @@ chat item action
เกิดข้อผิดพลาดในการลบฐานข้อมูลalert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseเกิดข้อผิดพลาดในการลบฐานข้อมูลเก่า
@@ -5354,6 +5394,10 @@ The most secure encryption.
ไม่มีรหัสผ่านสำหรับแอปAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNo comment provided by engineer.
@@ -5463,6 +5507,10 @@ The most secure encryption.
ไม่มีไฟล์ที่ได้รับหรือส่งNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.servers error
@@ -6028,6 +6076,10 @@ Error: %@
Please try to disable and re-enable notfications.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.snd group event chat item
@@ -6134,10 +6186,6 @@ Error: %@
Private routing timeoutalert title
-
- Proceed
- alert action
- Profile and server connectionsการเชื่อมต่อโปรไฟล์และเซิร์ฟเวอร์
@@ -6491,6 +6539,14 @@ swipe action
Relay test failed!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.No comment provided by engineer.
@@ -6531,9 +6587,9 @@ swipe action
ลบรหัสผ่านออกจาก keychain หรือไม่?No comment provided by engineer.
-
- Remove subscriber
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -7696,6 +7752,10 @@ report reason
StatisticsNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ Stopหยุด
@@ -8214,10 +8274,19 @@ your contacts and groups.
ไม่มีกลุ่มนี้แล้วNo comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!new chat action
@@ -8516,10 +8585,18 @@ To connect, please ask your contact to create another connection link and check
เปลี่ยนเป็นยังไม่ได้อ่านswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.No comment provided by engineer.
@@ -9408,6 +9485,11 @@ Repeat connection request?
Your networkNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesการตั้งค่าของคุณ
diff --git a/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff
index 90d537d06c..1189b53e3c 100644
--- a/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff
+++ b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff
@@ -187,16 +187,19 @@
%d relays failed
+ %d aktarıcı başarısız olduchannel relay bar
channel subscriber relay bar%d relays not active
+ %d aktarıcı etkin değilchannel relay bar
channel subscriber relay bar%d relays removed
+ %d aktarıcı kaldırıldıchannel relay bar
channel subscriber relay bar
@@ -217,10 +220,12 @@ channel subscriber relay bar
%d subscriber
+ %d abonechannel subscriber count%d subscribers
+ %d abonechannel subscriber count
@@ -230,24 +235,29 @@ channel subscriber relay bar
%1$d/%2$d relays active
+ %1$d/%2$d aktarıcı etkinchannel creation progress
channel relay bar progress%1$d/%2$d relays active, %3$d errors
+ %1$d/%2$d aktarıcı etkin, %3$d hatachannel relay bar%1$d/%2$d relays active, %3$d failed
+ %1$d/%2$d aktarıcı etkin, %3$d başarısızchannel creation progress with errors
channel relay bar%1$d/%2$d relays active, %3$d removed
+ %1$d/%2$d aktarıcı etkin, %3$d kaldırıldıchannel relay bar%1$d/%2$d relays connected
+ %1$d/%2$d aktarıcı bağlıchannel subscriber relay bar progress
@@ -715,6 +725,10 @@ swipe action
Aktif bağlantılarNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.No comment provided by engineer.
@@ -739,6 +753,14 @@ swipe action
Profil ekleNo comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverSunucu ekle
@@ -784,10 +806,6 @@ swipe action
Mesaj sunucuları eklendiNo comment provided by engineer.
-
- Adding relays will be supported later.
- No comment provided by engineer.
- Additional accentEk ana renk
@@ -1157,6 +1175,10 @@ swipe action
Uygulama oturumuNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionUygulama sürümü
@@ -1578,6 +1600,14 @@ in your network
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationTaşımayı iptal et
@@ -1722,8 +1752,8 @@ alert subtitle
Channel will be deleted for you - this cannot be undone!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2215,6 +2245,14 @@ Bu senin kendi tek kullanımlık bağlantın!
Bilgisayara bağlanıyorNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionBağlantı
@@ -2368,7 +2406,7 @@ Bu senin kendi tek kullanımlık bağlantın!
ContinueDevam et
- No comment provided by engineer.
+ alert actionContribute
@@ -2806,6 +2844,10 @@ swipe action
Benden silNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupGrubu sil
@@ -3578,6 +3620,10 @@ chat item action
Error adding relayalert title
+
+ Error adding relays
+ alert title
+ Error adding serverSunucu eklenirken hata oluştu
@@ -3706,6 +3752,10 @@ chat item action
Veritabanı silinirken hata oluştualert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseEski veritabanı silinirken hata oluştu
@@ -5877,6 +5927,10 @@ The most secure encryption.
Uygulama şifresi yokAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNo comment provided by engineer.
@@ -6000,6 +6054,10 @@ The most secure encryption.
Hiç alınmış veya gönderilmiş dosya yokNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.Özel mesaj yönlendirmesi için hiç sunucu yok.
@@ -6628,6 +6686,10 @@ Hata: %@
Lütfen bildirimleri devre dışı bırakmayı ve yeniden etkinleştirmeyi deneyin.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.Lütfen grup moderatörlerinin gruba katılma isteğinizi incelemesini bekleyin.
@@ -6749,10 +6811,6 @@ Hata: %@
Özel yönlendirme zaman aşımıalert title
-
- Proceed
- alert action
- Profile and server connectionsProfil ve sunucu bağlantıları
@@ -7137,6 +7195,14 @@ swipe action
Relay test failed!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.No comment provided by engineer.
@@ -7180,9 +7246,9 @@ swipe action
Anahtar Zinciri'ndeki parola silinsin mi?No comment provided by engineer.
-
- Remove subscriber
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -8475,6 +8541,10 @@ report reason
İstatistiklerNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ StopDur
@@ -9036,10 +9106,19 @@ your contacts and groups.
Bu grup artık mevcut değildir.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!new chat action
@@ -9369,11 +9448,19 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste
Okunmamışswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkDesteklenmeyen bağlantı bağlantısıconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.Yeni üyelere 100e kadar en son mesajlar gönderildi.
@@ -10359,6 +10446,11 @@ Bağlantı isteği tekrarlansın mı?
Your networkNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesTercihleriniz
diff --git a/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff b/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff
index c20b26e029..49f9e21eda 100644
--- a/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff
+++ b/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff
@@ -715,6 +715,10 @@ swipe action
Активні з'єднанняNo comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.No comment provided by engineer.
@@ -739,6 +743,14 @@ swipe action
Додати профільNo comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add serverДодати сервер
@@ -784,10 +796,6 @@ swipe action
Додано сервери повідомленьNo comment provided by engineer.
-
- Adding relays will be supported later.
- No comment provided by engineer.
- Additional accentДодатковий акцент
@@ -1155,6 +1163,10 @@ swipe action
Сесія програмиNo comment provided by engineer.
+
+ App update required
+ alert title
+ App versionВерсія програми
@@ -1574,6 +1586,14 @@ in your network
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migrationСкасувати міграцію
@@ -1718,8 +1738,8 @@ alert subtitle
Channel will be deleted for you - this cannot be undone!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2211,6 +2231,14 @@ This is your own one-time link!
Підключення до ПКNo comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ ConnectionПідключення
@@ -2363,7 +2391,7 @@ This is your own one-time link!
ContinueПродовжуйте
- No comment provided by engineer.
+ alert actionContribute
@@ -2801,6 +2829,10 @@ swipe action
Видалити для менеNo comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete groupВидалити групу
@@ -3572,6 +3604,10 @@ chat item action
Error adding relayalert title
+
+ Error adding relays
+ alert title
+ Error adding serverПомилка додавання сервера
@@ -3700,6 +3736,10 @@ chat item action
Помилка видалення бази данихalert title
+
+ Error deleting message
+ alert title
+ Error deleting old databaseПомилка видалення старої бази даних
@@ -5867,6 +5907,10 @@ The most secure encryption.
Немає пароля програмиAuthentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNo comment provided by engineer.
@@ -5990,6 +6034,10 @@ The most secure encryption.
Немає отриманих або відправлених файлівNo comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.Немає серверів для маршрутизації приватних повідомлень.
@@ -6613,6 +6661,10 @@ Error: %@
Будь ласка, спробуйте вимкнути та знову увімкнути сповіщення.token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.Будь ласка, зачекайте, поки модератори групи розглянуть ваш запит на приєднання до групи.
@@ -6734,10 +6786,6 @@ Error: %@
Тайм-аут приватної маршрутизаціїalert title
-
- Proceed
- alert action
- Profile and server connectionsЗ'єднання профілю та сервера
@@ -7122,6 +7170,14 @@ swipe action
Relay test failed!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.No comment provided by engineer.
@@ -7164,9 +7220,9 @@ swipe action
Видалити парольну фразу з брелока?No comment provided by engineer.
-
- Remove subscriber
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -8459,6 +8515,10 @@ report reason
СтатистикаNo comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ StopЗупинити
@@ -9019,10 +9079,19 @@ your contacts and groups.
Цієї групи більше не існує.No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!new chat action
@@ -9350,11 +9419,19 @@ To connect, please ask your contact to create another connection link and check
Непрочитанеswipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection linkНесумісне посилання для підключенняconn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.Новим користувачам надсилається до 100 останніх повідомлень.
@@ -10340,6 +10417,11 @@ Repeat connection request?
Your networkNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferencesВаші уподобання
diff --git a/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff b/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff
index 51cbb94bda..8823f17204 100644
--- a/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff
+++ b/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff
@@ -715,6 +715,10 @@ swipe action
活动连接No comment provided by engineer.
+
+ Add
+ No comment provided by engineer.
+ Add address to your profile, so that your SimpleX contacts can share it with other people. Profile update will be sent to your SimpleX contacts.No comment provided by engineer.
@@ -739,6 +743,14 @@ swipe action
添加个人资料No comment provided by engineer.
+
+ Add relays
+ No comment provided by engineer.
+
+
+ Add relays to restore message delivery.
+ No comment provided by engineer.
+ Add server添加服务器
@@ -784,10 +796,6 @@ swipe action
已添加消息服务器No comment provided by engineer.
-
- Adding relays will be supported later.
- No comment provided by engineer.
- Additional accent附加重音
@@ -1158,6 +1166,10 @@ swipe action
应用会话No comment provided by engineer.
+
+ App update required
+ alert title
+ App version应用程序版本
@@ -1582,6 +1594,14 @@ in your network
alert button
new chat action
+
+ Cancel and delete channel
+ No comment provided by engineer.
+
+
+ Cancel creating channel?
+ alert title
+ Cancel migration取消迁移
@@ -1726,8 +1746,8 @@ alert subtitle
Channel will be deleted for you - this cannot be undone!No comment provided by engineer.
-
- Channel will start working with %1$d of %2$d relays. Proceed?
+
+ Channel will start working with %1$d of %2$d relays. Continue?alert message
@@ -2219,6 +2239,14 @@ This is your own one-time link!
正连接到桌面No comment provided by engineer.
+
+ Connecting via channel name requires a newer app version.
+ alert message
+
+
+ Connecting via contact name requires a newer app version.
+ alert message
+ Connection连接
@@ -2371,7 +2399,7 @@ This is your own one-time link!
Continue继续
- No comment provided by engineer.
+ alert actionContribute
@@ -2809,6 +2837,10 @@ swipe action
为我删除No comment provided by engineer.
+
+ Delete from history
+ No comment provided by engineer.
+ Delete group删除群组
@@ -3582,6 +3614,10 @@ chat item action
Error adding relayalert title
+
+ Error adding relays
+ alert title
+ Error adding server添加服务器出错
@@ -3710,6 +3746,10 @@ chat item action
删除数据库错误alert title
+
+ Error deleting message
+ alert title
+ Error deleting old database删除旧数据库错误
@@ -5889,6 +5929,10 @@ The most secure encryption.
没有应用程序密码Authentication unavailable
+
+ No available relays
+ No comment provided by engineer.
+ No chat relaysNo comment provided by engineer.
@@ -6012,6 +6056,10 @@ The most secure encryption.
未收到或发送文件No comment provided by engineer.
+
+ No relays
+ No comment provided by engineer.
+ No servers for private message routing.无私密消息路由服务器。
@@ -6642,6 +6690,10 @@ Error: %@
请尝试禁用并重新启用通知。token info
+
+ Please upgrade the app.
+ alert message
+ Please wait for group moderators to review your request to join the group.请等待群的协管审核你加入该群的请求。
@@ -6763,10 +6815,6 @@ Error: %@
私密路由超时alert title
-
- Proceed
- alert action
- Profile and server connections资料和服务器连接
@@ -7150,6 +7198,14 @@ swipe action
Relay test failed!No comment provided by engineer.
+
+ Relay will be removed from channel - this cannot be undone!
+ alert message
+
+
+ Relays added: %@.
+ alert message
+ Reliability: many relays per channel.No comment provided by engineer.
@@ -7194,9 +7250,9 @@ swipe action
从钥匙串中删除密码?No comment provided by engineer.
-
- Remove subscriber
- No comment provided by engineer.
+
+ Remove relay?
+ alert titleRemove subscriber?
@@ -8493,6 +8549,10 @@ report reason
统计No comment provided by engineer.
+
+ Status
+ No comment provided by engineer.
+ Stop停止
@@ -9054,10 +9114,19 @@ your contacts and groups.
该群组已不存在。No comment provided by engineer.
+
+ This group requires a newer version of the app. Please update the app to join.
+ alert message
+alert subtitle
+ This is a chat relay address, it cannot be used to connect.alert message
+
+ This is the last active relay. Removing it will prevent message delivery to subscribers.
+ alert message
+ This is your link for channel %@!new chat action
@@ -9387,11 +9456,19 @@ To connect, please ask your contact to create another connection link and check
未读swipe action
+
+ Unsupported channel name
+ alert title
+ Unsupported connection link不支持的连接链接conn error description
+
+ Unsupported contact name
+ alert title
+ Up to 100 last messages are sent to new members.给新成员发送了最多 100 条历史消息。
@@ -10379,6 +10456,11 @@ Repeat connection request?
Your networkNo comment provided by engineer.
+
+ Your new channel %1$@ is connected to %2$d of %3$d relays.
+If you cancel, the channel will be deleted - you can create it again.
+ alert message
+ Your preferences您的偏好设置
diff --git a/apps/ios/SimpleX SE/hu.lproj/Localizable.strings b/apps/ios/SimpleX SE/hu.lproj/Localizable.strings
index dfb7a302b9..3aad39c5d1 100644
--- a/apps/ios/SimpleX SE/hu.lproj/Localizable.strings
+++ b/apps/ios/SimpleX SE/hu.lproj/Localizable.strings
@@ -29,7 +29,7 @@
"Database error" = "Adatbázishiba";
/* No comment provided by engineer. */
-"Database passphrase is different from saved in the keychain." = "Az adatbázis jelmondata nem egyezik a kulcstartóba mentettől.";
+"Database passphrase is different from saved in the keychain." = "Az adatbázis jelmondata eltér a kulcstartóban tárolttól.";
/* No comment provided by engineer. */
"Database passphrase is required to open chat." = "A csevegés megnyitásához adja meg az adatbázis jelmondatát.";
@@ -101,7 +101,7 @@
"Unsupported format" = "Nem támogatott formátum";
/* No comment provided by engineer. */
-"Wait" = "Várjon";
+"Wait" = "Várakozás";
/* No comment provided by engineer. */
"Wrong database passphrase" = "Érvénytelen adatbázis-jelmondat";
diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj
index f0bd6d9118..5bc1de821c 100644
--- a/apps/ios/SimpleX.xcodeproj/project.pbxproj
+++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj
@@ -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-6.5.2.0-8CNxlktzYRPIWqOtKFvRIa-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.2.0-8CNxlktzYRPIWqOtKFvRIa-ghc9.6.3.a */; };
- 64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.5.2.0-8CNxlktzYRPIWqOtKFvRIa.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.2.0-8CNxlktzYRPIWqOtKFvRIa.a */; };
+ 64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.4.1-4Ybrr1jdwOoLdJnIO0aOG7-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.4.1-4Ybrr1jdwOoLdJnIO0aOG7-ghc9.6.3.a */; };
+ 64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.5.4.1-4Ybrr1jdwOoLdJnIO0aOG7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.4.1-4Ybrr1jdwOoLdJnIO0aOG7.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 */; };
@@ -561,8 +561,8 @@
64C3B0202A0D359700E19930 /* CustomTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTimePicker.swift; sourceTree = ""; };
64C829982D54AEED006B9E89 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; };
64C829992D54AEEE006B9E89 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; };
- 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.2.0-8CNxlktzYRPIWqOtKFvRIa-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.5.2.0-8CNxlktzYRPIWqOtKFvRIa-ghc9.6.3.a"; sourceTree = ""; };
- 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.2.0-8CNxlktzYRPIWqOtKFvRIa.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.5.2.0-8CNxlktzYRPIWqOtKFvRIa.a"; sourceTree = ""; };
+ 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.4.1-4Ybrr1jdwOoLdJnIO0aOG7-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.5.4.1-4Ybrr1jdwOoLdJnIO0aOG7-ghc9.6.3.a"; sourceTree = ""; };
+ 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.4.1-4Ybrr1jdwOoLdJnIO0aOG7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.5.4.1-4Ybrr1jdwOoLdJnIO0aOG7.a"; sourceTree = ""; };
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; };
64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = ""; };
64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressLearnMore.swift; sourceTree = ""; };
@@ -731,8 +731,8 @@
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */,
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */,
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */,
- 64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.2.0-8CNxlktzYRPIWqOtKFvRIa-ghc9.6.3.a in Frameworks */,
- 64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.5.2.0-8CNxlktzYRPIWqOtKFvRIa.a in Frameworks */,
+ 64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.4.1-4Ybrr1jdwOoLdJnIO0aOG7-ghc9.6.3.a in Frameworks */,
+ 64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.5.4.1-4Ybrr1jdwOoLdJnIO0aOG7.a in Frameworks */,
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -818,8 +818,8 @@
64C829992D54AEEE006B9E89 /* libffi.a */,
64C829982D54AEED006B9E89 /* libgmp.a */,
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */,
- 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.2.0-8CNxlktzYRPIWqOtKFvRIa-ghc9.6.3.a */,
- 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.2.0-8CNxlktzYRPIWqOtKFvRIa.a */,
+ 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.4.1-4Ybrr1jdwOoLdJnIO0aOG7-ghc9.6.3.a */,
+ 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.4.1-4Ybrr1jdwOoLdJnIO0aOG7.a */,
);
path = Libraries;
sourceTree = "";
@@ -2073,7 +2073,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 332;
+ CURRENT_PROJECT_VERSION = 333;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -2098,7 +2098,7 @@
"@executable_path/Frameworks",
);
LLVM_LTO = YES_THIN;
- MARKETING_VERSION = 6.5.2;
+ MARKETING_VERSION = 6.5.3;
OTHER_LDFLAGS = "-Wl,-stack_size,0x1000000";
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
@@ -2123,7 +2123,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 332;
+ CURRENT_PROJECT_VERSION = 333;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -2148,7 +2148,7 @@
"@executable_path/Frameworks",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.5.2;
+ MARKETING_VERSION = 6.5.3;
OTHER_LDFLAGS = "-Wl,-stack_size,0x1000000";
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
@@ -2165,11 +2165,11 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 332;
+ CURRENT_PROJECT_VERSION = 333;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
- MARKETING_VERSION = 6.5.2;
+ MARKETING_VERSION = 6.5.3;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2185,11 +2185,11 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 332;
+ CURRENT_PROJECT_VERSION = 333;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
- MARKETING_VERSION = 6.5.2;
+ MARKETING_VERSION = 6.5.3;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2210,7 +2210,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 332;
+ CURRENT_PROJECT_VERSION = 333;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GCC_OPTIMIZATION_LEVEL = s;
@@ -2225,7 +2225,7 @@
"@executable_path/../../Frameworks",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.5.2;
+ MARKETING_VERSION = 6.5.3;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2247,7 +2247,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 332;
+ CURRENT_PROJECT_VERSION = 333;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_CODE_COVERAGE = NO;
@@ -2262,7 +2262,7 @@
"@executable_path/../../Frameworks",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.5.2;
+ MARKETING_VERSION = 6.5.3;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2284,7 +2284,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 332;
+ CURRENT_PROJECT_VERSION = 333;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2310,7 +2310,7 @@
"$(PROJECT_DIR)/Libraries/sim",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.5.2;
+ MARKETING_VERSION = 6.5.3;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
@@ -2335,7 +2335,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 332;
+ CURRENT_PROJECT_VERSION = 333;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2362,7 +2362,7 @@
"$(PROJECT_DIR)/Libraries/sim",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.5.2;
+ MARKETING_VERSION = 6.5.3;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
@@ -2389,7 +2389,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 332;
+ CURRENT_PROJECT_VERSION = 333;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -2404,7 +2404,7 @@
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
- MARKETING_VERSION = 6.5.2;
+ MARKETING_VERSION = 6.5.3;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@@ -2423,7 +2423,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 332;
+ CURRENT_PROJECT_VERSION = 333;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -2438,7 +2438,7 @@
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
- MARKETING_VERSION = 6.5.2;
+ MARKETING_VERSION = 6.5.3;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift
index b7372bf6b7..3302850b64 100644
--- a/apps/ios/SimpleXChat/ChatTypes.swift
+++ b/apps/ios/SimpleXChat/ChatTypes.swift
@@ -2533,10 +2533,22 @@ public enum GroupType: Codable, Hashable {
}
}
+public struct PublicGroupAccess: Codable, Hashable {
+ public var groupWebPage: String?
+ public var groupDomain: String?
+ public var domainWebPage: Bool = false
+ public var allowEmbedding: Bool = false
+}
+
+public struct RelayCapabilities: Codable, Hashable {
+ public var webDomain: String?
+}
+
public struct PublicGroupProfile: Codable, Hashable {
public var groupType: GroupType
public var groupLink: String
public var publicGroupId: String
+ public var publicGroupAccess: PublicGroupAccess?
}
public struct GroupProfile: Codable, NamedChat, Hashable {
@@ -2705,6 +2717,7 @@ public struct GroupRelay: Identifiable, Decodable, Equatable, Hashable {
public var userChatRelay: UserChatRelay
public var relayStatus: RelayStatus
public var relayLink: String?
+ public var relayCap: RelayCapabilities
public var id: Int64 { groupRelayId }
}
@@ -5106,6 +5119,7 @@ public enum Format: Decodable, Equatable, Hashable {
case uri
case hyperLink(showText: String?, linkUri: String)
case simplexLink(showText: String?, linkType: SimplexLinkType, simplexUri: String, smpHosts: [String])
+ case simplexName(nameInfo: SimplexNameInfo)
case command(commandStr: String)
case mention(memberName: String)
case email
@@ -5140,6 +5154,28 @@ public enum SimplexLinkType: String, Decodable, Hashable {
}
}
+public struct SimplexNameInfo: Decodable, Equatable, Hashable {
+ public var nameType: SimplexNameType
+ public var nameDomain: SimplexNameDomain
+}
+
+public struct SimplexNameDomain: Decodable, Equatable, Hashable {
+ public var nameTLD: SimplexTLD
+ public var domain: String
+ public var subDomain: [String]
+}
+
+public enum SimplexTLD: String, Decodable, Hashable {
+ case simplex
+ case testing
+ case web
+}
+
+public enum SimplexNameType: String, Decodable, Hashable {
+ case publicGroup
+ case contact
+}
+
public enum FormatColor: String, Decodable, Hashable {
case red = "red"
case green = "green"
diff --git a/apps/ios/bg.lproj/Localizable.strings b/apps/ios/bg.lproj/Localizable.strings
index 17e11d1020..ec869e05b4 100644
--- a/apps/ios/bg.lproj/Localizable.strings
+++ b/apps/ios/bg.lproj/Localizable.strings
@@ -1364,7 +1364,7 @@ server test step */
/* No comment provided by engineer. */
"Contacts can mark messages for deletion; you will be able to view them." = "Контактите могат да маркират съобщения за изтриване; ще можете да ги разглеждате.";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "Продължи";
/* No comment provided by engineer. */
diff --git a/apps/ios/cs.lproj/Localizable.strings b/apps/ios/cs.lproj/Localizable.strings
index f7e90e0c88..fc4b3f0fc6 100644
--- a/apps/ios/cs.lproj/Localizable.strings
+++ b/apps/ios/cs.lproj/Localizable.strings
@@ -1056,7 +1056,7 @@ server test step */
/* No comment provided by engineer. */
"Contacts can mark messages for deletion; you will be able to view them." = "Kontakty mohou označit zprávy ke smazání; vy je budete moci zobrazit.";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "Pokračovat";
/* No comment provided by engineer. */
diff --git a/apps/ios/de.lproj/Localizable.strings b/apps/ios/de.lproj/Localizable.strings
index d5978b48dc..2c4e37791b 100644
--- a/apps/ios/de.lproj/Localizable.strings
+++ b/apps/ios/de.lproj/Localizable.strings
@@ -373,7 +373,7 @@ time interval */
"A new random profile will be shared." = "Es wird ein neues Zufallsprofil geteilt.";
/* No comment provided by engineer. */
-"A separate TCP connection will be used **for each chat profile you have in the app**." = "**Für jedes von Ihnen in der App genutzte Chat-Profil** wird eine separate TCP-Verbindung genutzt.";
+"A separate TCP connection will be used **for each chat profile you have in the app**." = "**Für jedes von Ihnen in der App genutzte Chat-Profil** wird eine separate TCP-Verbindung (und SOCKS-Berechtigung) genutzt.";
/* No comment provided by engineer. */
"A separate TCP connection will be used **for each contact and group member**.\n**Please note**: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail." = "**Für jeden Kontakt und jedes Gruppenmitglied** wird eine separate TCP-Verbindung genutzt.\n**Bitte beachten Sie**: Wenn Sie viele Verbindungen haben, kann der Batterieverbrauch und die Datennutzung wesentlich höher sein und einige Verbindungen können scheitern.";
@@ -505,9 +505,6 @@ swipe action */
/* No comment provided by engineer. */
"Added message servers" = "Nachrichtenserver hinzugefügt";
-/* No comment provided by engineer. */
-"Adding relays will be supported later." = "Das Hinzufügen von Relais wird zu einem späteren Zeitpunkt unterstützt.";
-
/* No comment provided by engineer. */
"Additional accent" = "Erste Akzentfarbe";
@@ -617,7 +614,7 @@ swipe action */
"All your contacts will remain connected. Profile update will be sent to your contacts." = "Alle Ihre Kontakte bleiben verbunden. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet.";
/* No comment provided by engineer. */
-"All your contacts, conversations and files will be securely encrypted and uploaded in chunks to configured XFTP relays." = "Alle Ihre Kontakte, Unterhaltungen und Dateien werden sicher verschlüsselt und in Daten-Paketen auf die konfigurierten XTFP-Relais hochgeladen.";
+"All your contacts, conversations and files will be securely encrypted and uploaded in chunks to configured XFTP relays." = "Alle Ihre Kontakte, Unterhaltungen und Dateien werden sicher verschlüsselt und in Daten-Paketen auf die konfigurierten XTFP-Router hochgeladen.";
/* No comment provided by engineer. */
"Allow" = "Erlauben";
@@ -716,10 +713,10 @@ swipe action */
"always" = "Immer";
/* No comment provided by engineer. */
-"Always use private routing." = "Sie nutzen immer privates Routing.";
+"Always use private routing." = "Immer privates Routing nutzen.";
/* No comment provided by engineer. */
-"Always use relay" = "Über ein Relais verbinden";
+"Always use relay" = "Immer über einen Router verbinden";
/* No comment provided by engineer. */
"An empty chat profile with the provided name is created, and the app opens as usual." = "Es wurde ein leeres Chat-Profil mit dem eingegebenen Namen erstellt und die App öffnet wie gewohnt.";
@@ -764,7 +761,7 @@ swipe action */
"App version: v%@" = "App Version: v%@";
/* No comment provided by engineer. */
-"Appearance" = "Erscheinungsbild";
+"Appearance" = "Darstellung";
/* No comment provided by engineer. */
"Apply" = "Anwenden";
@@ -1182,9 +1179,6 @@ alert subtitle */
/* No comment provided by engineer. */
"Channel will be deleted for you - this cannot be undone!" = "Der Kanal wird für Sie gelöscht. Dies kann nicht rückgängig gemacht werden!";
-/* alert message */
-"Channel will start working with %d of %d relays. Proceed?" = "Der Kanal wird mit %1$d von %2$d Relais gestartet. Fortfahren?";
-
/* No comment provided by engineer. */
"Channels" = "Kanäle";
@@ -1237,7 +1231,7 @@ alert subtitle */
"Chat preferences were changed." = "Die Chat-Präferenzen wurden geändert.";
/* No comment provided by engineer. */
-"Chat profile" = "Benutzerprofil";
+"Chat profile" = "Chat-Profil";
/* No comment provided by engineer. */
"Chat relay" = "Chat-Relais";
@@ -1367,7 +1361,7 @@ chat toolbar */
"Completed" = "Abgeschlossen";
/* No comment provided by engineer. */
-"Conditions accepted on: %@." = "Die Nutzungsbedingungen wurden akzeptiert am: %@.";
+"Conditions accepted on: %@." = "Die Nutzungsbedingungen wurden am %@ akzeptiert.";
/* No comment provided by engineer. */
"Conditions are accepted for the operator(s): **%@**." = "Die Nutzungsbedingungen der/des Betreiber(s) werden akzeptiert: **%@**.";
@@ -1382,10 +1376,10 @@ chat toolbar */
"Conditions will be accepted for the operator(s): **%@**." = "Die Nutzungsbedingungen der/des Betreiber(s) werden akzeptiert: **%@**.";
/* No comment provided by engineer. */
-"Conditions will be accepted on: %@." = "Die Nutzungsbedingungen werden akzeptiert am: %@.";
+"Conditions will be accepted on: %@." = "Die Nutzungsbedingungen werden am %@ akzeptiert.";
/* No comment provided by engineer. */
-"Conditions will be automatically accepted for enabled operators on: %@." = "Die Nutzungsbedingungen der aktivierten Betreiber werden automatisch akzeptiert am: %@.";
+"Conditions will be automatically accepted for enabled operators on: %@." = "Die Nutzungsbedingungen der aktivierten Betreiber werden am %@ automatisch akzeptiert.";
/* No comment provided by engineer. */
"Configure ICE servers" = "ICE-Server konfigurieren";
@@ -1634,7 +1628,7 @@ server test step */
/* blocking reason */
"Content violates conditions of use" = "Inhalt verletzt Nutzungsbedingungen";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "Weiter";
/* No comment provided by engineer. */
@@ -2169,10 +2163,10 @@ alert button */
"Do NOT send messages directly, even if your or destination server does not support private routing." = "Nachrichten werden nicht direkt versendet, selbst wenn Ihr oder der Zielserver kein privates Routing unterstützt.";
/* No comment provided by engineer. */
-"Do not use credentials with proxy." = "Verwenden Sie keine Anmeldeinformationen mit einem Proxy.";
+"Do not use credentials with proxy." = "Keine Anmeldeinformationen mit einem Proxy verwenden.";
/* No comment provided by engineer. */
-"Do NOT use private routing." = "Sie nutzen KEIN privates Routing.";
+"Do NOT use private routing." = "KEIN privates Routing nutzen.";
/* No comment provided by engineer. */
"Do NOT use SimpleX for emergency calls." = "SimpleX NICHT für Notrufe nutzen.";
@@ -3975,10 +3969,10 @@ servers warning */
"New server" = "Neuer Server";
/* No comment provided by engineer. */
-"New SOCKS credentials will be used every time you start the app." = "Jedes Mal wenn Sie die App starten, werden neue SOCKS-Anmeldeinformationen genutzt";
+"New SOCKS credentials will be used every time you start the app." = "Bei jedem Neustart der App, werden neue SOCKS-Anmeldeinformationen genutzt.";
/* No comment provided by engineer. */
-"New SOCKS credentials will be used for each server." = "Für jeden Server werden neue SOCKS-Anmeldeinformationen genutzt";
+"New SOCKS credentials will be used for each server." = "Für jeden Server werden neue SOCKS-Anmeldeinformationen genutzt.";
/* pref value */
"no" = "Nein";
@@ -4074,7 +4068,7 @@ servers warning */
"No received or sent files" = "Keine herunter- oder hochgeladenen Dateien";
/* servers error */
-"No servers for private message routing." = "Keine Server für privates Nachrichten-Routing.";
+"No servers for private message routing." = "Keine Router für privates Nachrichten-Routing.";
/* servers error */
"No servers to receive files." = "Keine Server für das Herunterladen von Dateien.";
@@ -4548,7 +4542,7 @@ alert button */
"Privacy policy and conditions of use." = "Datenschutz- und Nutzungsbedingungen.";
/* No comment provided by engineer. */
-"Privacy: for owners and subscribers." = "Privatsphäre: für Besitzer und Abonnenten.";
+"Privacy: for owners and subscribers." = "Privatsphäre: Für Eigentümer und Abonnenten.";
/* No comment provided by engineer. */
"Private and secure messaging." = "Private und sichere Kommunikation.";
@@ -4577,9 +4571,6 @@ alert button */
/* alert title */
"Private routing timeout" = "Zeitüberschreitung der privaten Routing-Sitzung";
-/* alert action */
-"Proceed" = "Fortfahren";
-
/* No comment provided by engineer. */
"Profile and server connections" = "Profil und Serververbindungen";
@@ -4644,7 +4635,7 @@ alert button */
"Protect your chat profiles with a password!" = "Ihre Chat-Profile mit einem Passwort schützen!";
/* No comment provided by engineer. */
-"Protect your IP address from the messaging relays chosen by your contacts.\nEnable in *Network & servers* settings." = "Schützen Sie Ihre IP-Adresse vor den Nachrichten-Relais, die Ihre Kontakte ausgewählt haben.\nAktivieren Sie es in den *Netzwerk & Server* Einstellungen.";
+"Protect your IP address from the messaging relays chosen by your contacts.\nEnable in *Network & servers* settings." = "Schützen Sie Ihre IP-Adresse vor den Nachrichten-Routern, die Ihre Kontakte ausgewählt haben.\nAktivieren Sie es in den *Netzwerk & Server* Einstellungen.";
/* No comment provided by engineer. */
"Protocol background timeout" = "Protokoll Hintergrund-Zeitüberschreitung";
@@ -4829,13 +4820,13 @@ swipe action */
"Relay server is only used if necessary. Another party can observe your IP address." = "Relais-Server werden nur genutzt, wenn sie benötigt werden. Ihre IP-Adresse kann von Anderen erfasst werden.";
/* No comment provided by engineer. */
-"Relay server protects your IP address, but it can observe the duration of the call." = "Relais-Server schützen Ihre IP-Adresse, aber sie können die Anrufdauer erfassen.";
+"Relay server protects your IP address, but it can observe the duration of the call." = "Relais-Server schützen Ihre IP-Adresse, können aber die Anrufdauer erfassen.";
/* No comment provided by engineer. */
"Relay test failed!" = "Relais-Test fehlgeschlagen!";
/* No comment provided by engineer. */
-"Reliability: many relays per channel." = "Zuverlässigkeit: mehrere Relais pro Kanal.";
+"Reliability: many relays per channel." = "Zuverlässigkeit: Mehrere Relais pro Kanal.";
/* alert action */
"Remove" = "Entfernen";
@@ -4861,9 +4852,6 @@ swipe action */
/* No comment provided by engineer. */
"Remove passphrase from keychain?" = "Passwort aus dem Schlüsselbund entfernen?";
-/* No comment provided by engineer. */
-"Remove subscriber" = "Abonnent entfernen";
-
/* alert title */
"Remove subscriber?" = "Abonnent entfernen?";
@@ -5223,7 +5211,7 @@ chat item action */
"security code changed" = "Sicherheitscode wurde geändert";
/* No comment provided by engineer. */
-"Security: owners hold channel keys." = "Sicherheit: Eigentümer besitzen die Kanalschlüssel.";
+"Security: owners hold channel keys." = "Sicherheit: Nur die Eigentümer des Kanals besitzen die Schlüssel.";
/* chat item action */
"Select" = "Auswählen";
@@ -5280,10 +5268,10 @@ chat item action */
"Send message to enable calls." = "Nachricht senden, um Anrufe zu aktivieren.";
/* No comment provided by engineer. */
-"Send messages directly when IP address is protected and your or destination server does not support private routing." = "Nachrichten werden direkt versendet, wenn die IP-Adresse geschützt ist, und Ihr oder der Zielserver kein privates Routing unterstützt.";
+"Send messages directly when IP address is protected and your or destination server does not support private routing." = "Nachrichten werden direkt versendet, wenn die IP-Adresse geschützt ist, und Ihr oder der Ziel-Server kein privates Routing unterstützt.";
/* No comment provided by engineer. */
-"Send messages directly when your or destination server does not support private routing." = "Nachrichten werden direkt versendet, wenn Ihr oder der Zielserver kein privates Routing unterstützt.";
+"Send messages directly when your or destination server does not support private routing." = "Nachrichten werden direkt versendet, wenn Ihr oder der Ziel-Server kein privates Routing unterstützt.";
/* No comment provided by engineer. */
"Send notifications" = "Benachrichtigungen senden";
@@ -5406,7 +5394,7 @@ chat item action */
"server queue info: %@\n\nlast received msg: %@" = "Server-Warteschlangen-Information: %1$@\n\nZuletzt empfangene Nachricht: %2$@";
/* relay test error */
-"Server requires authorization to connect to relay, check password." = "Der Server erfordert eine Autorisierung, um eine Verbindung zum Relais herzustellen. Bitte Passwort überprüfen.";
+"Server requires authorization to connect to relay, check password." = "Der Server erfordert eine Autorisierung, um eine Verbindung zum Router herzustellen. Bitte Passwort überprüfen.";
/* server test error */
"Server requires authorization to create queues, check password." = "Der Server erfordert zum Erstellen von Warteschlangen eine Autorisierung. Bitte überprüfen Sie das Passwort.";
@@ -5539,7 +5527,7 @@ chat item action */
"Share profile" = "Profil teilen";
/* No comment provided by engineer. */
-"Share relay address" = "Relais-Adresse teilen";
+"Share relay address" = "Router-Adresse teilen";
/* No comment provided by engineer. */
"Share SimpleX address on social media." = "Die SimpleX-Adresse auf sozialen Medien teilen.";
@@ -6141,7 +6129,7 @@ server test failure */
"To protect your information, turn on SimpleX Lock.\nYou will be prompted to complete authentication before this feature is enabled." = "Um Ihre Informationen zu schützen, schalten Sie die SimpleX-Sperre ein.\nSie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funktion aktiviert wird.";
/* No comment provided by engineer. */
-"To protect your IP address, private routing uses your SMP servers to deliver messages." = "Zum Schutz Ihrer IP-Adresse, wird für die Nachrichten-Auslieferung privates Routing über Ihre konfigurierten SMP-Server genutzt.";
+"To protect your IP address, private routing uses your SMP servers to deliver messages." = "Zum Schutz Ihrer IP-Adresse, wird für die Nachrichten-Auslieferung privates Routing über Ihre konfigurierten SMP-Router genutzt.";
/* No comment provided by engineer. */
"To protect your privacy, SimpleX uses separate IDs for each of your contacts." = "Zum Schutz Ihrer Privatsphäre verwendet SimpleX an Stelle von Benutzerkennungen, die von allen anderen Plattformen verwendet werden, Kennungen für Nachrichtenwarteschlangen, die für jeden Ihrer Kontakte individuell sind.";
@@ -6270,7 +6258,7 @@ server test failure */
"Unknown error" = "Unbekannter Fehler";
/* No comment provided by engineer. */
-"unknown servers" = "Unbekannte Relais";
+"unknown servers" = "Unbekannte Server";
/* alert title */
"Unknown servers!" = "Unbekannte Server!";
@@ -6417,10 +6405,10 @@ server test failure */
"Use only local notifications?" = "Nur lokale Benachrichtigungen nutzen?";
/* No comment provided by engineer. */
-"Use private routing with unknown servers when IP address is not protected." = "Sie nutzen privates Routing mit unbekannten Servern, wenn Ihre IP-Adresse nicht geschützt ist.";
+"Use private routing with unknown servers when IP address is not protected." = "Bei unbekannten Servern privates Routing nutzen, wenn Ihre IP-Adresse nicht geschützt ist.";
/* No comment provided by engineer. */
-"Use private routing with unknown servers." = "Sie nutzen privates Routing mit unbekannten Servern.";
+"Use private routing with unknown servers." = "Bei unbekannten Servern privates Routing nutzen.";
/* No comment provided by engineer. */
"Use relay" = "Relais verwenden";
@@ -6672,7 +6660,7 @@ server test failure */
"Without Tor or VPN, your IP address will be visible to file servers." = "Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für Datei-Server sichtbar sein.";
/* alert message */
-"Without Tor or VPN, your IP address will be visible to these XFTP relays: %@." = "Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für diese XFTP-Relais sichtbar sein: %@.";
+"Without Tor or VPN, your IP address will be visible to these XFTP relays: %@." = "Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für diese XFTP-Router sichtbar sein: %@.";
/* No comment provided by engineer. */
"Wrong database passphrase" = "Falsches Datenbank-Passwort";
@@ -6759,7 +6747,7 @@ server test failure */
"You can accept calls from lock screen, without device and app authentication." = "Sie können Anrufe ohne Geräte- und App-Authentifizierung vom Sperrbildschirm aus annehmen.";
/* No comment provided by engineer. */
-"You can change it in Appearance settings." = "Kann von Ihnen in den Erscheinungsbild-Einstellungen geändert werden.";
+"You can change it in Appearance settings." = "Sie können dies in den Einstellungen unter „Darstellung“ ändern.";
/* No comment provided by engineer. */
"You can configure servers via settings." = "Sie können die Server über die Einstellungen konfigurieren.";
diff --git a/apps/ios/es.lproj/Localizable.strings b/apps/ios/es.lproj/Localizable.strings
index 49826ff7f6..cf03ae6dbf 100644
--- a/apps/ios/es.lproj/Localizable.strings
+++ b/apps/ios/es.lproj/Localizable.strings
@@ -1,5 +1,5 @@
/* No comment provided by engineer. */
-" (can be copied)" = " (puede copiarse)";
+" (can be copied)" = " (puede ser copiado)";
/* No comment provided by engineer. */
"_italic_" = "\\_italic_";
@@ -505,9 +505,6 @@ swipe action */
/* No comment provided by engineer. */
"Added message servers" = "Servidores de mensajes añadidos";
-/* No comment provided by engineer. */
-"Adding relays will be supported later." = "Añadir servidores estará disponible en una versión posterior.";
-
/* No comment provided by engineer. */
"Additional accent" = "Acento adicional";
@@ -1182,9 +1179,6 @@ alert subtitle */
/* No comment provided by engineer. */
"Channel will be deleted for you - this cannot be undone!" = "El canal será eliminado para tí. ¡No puede deshacerse!";
-/* alert message */
-"Channel will start working with %d of %d relays. Proceed?" = "El canal comenzará a funcionar con %1$d de %2$d servidores. ¿Continuar?";
-
/* No comment provided by engineer. */
"Channels" = "Canales";
@@ -1634,7 +1628,7 @@ server test step */
/* blocking reason */
"Content violates conditions of use" = "El contenido viola las condiciones de uso";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "Continuar";
/* No comment provided by engineer. */
@@ -4577,9 +4571,6 @@ alert button */
/* alert title */
"Private routing timeout" = "Timeout enrutamiento privado";
-/* alert action */
-"Proceed" = "Continuar";
-
/* No comment provided by engineer. */
"Profile and server connections" = "Eliminar perfil y conexiones";
@@ -4861,9 +4852,6 @@ swipe action */
/* No comment provided by engineer. */
"Remove passphrase from keychain?" = "¿Eliminar contraseña de Keychain?";
-/* No comment provided by engineer. */
-"Remove subscriber" = "Eliminar suscriptor";
-
/* alert title */
"Remove subscriber?" = "¿Eliminar suscriptor?";
diff --git a/apps/ios/fi.lproj/Localizable.strings b/apps/ios/fi.lproj/Localizable.strings
index b75323054a..3b1bd6523c 100644
--- a/apps/ios/fi.lproj/Localizable.strings
+++ b/apps/ios/fi.lproj/Localizable.strings
@@ -732,7 +732,7 @@ server test step */
/* No comment provided by engineer. */
"Contacts can mark messages for deletion; you will be able to view them." = "Kontaktit voivat merkitä viestit poistettaviksi; voit katsella niitä.";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "Jatka";
/* No comment provided by engineer. */
diff --git a/apps/ios/fr.lproj/Localizable.strings b/apps/ios/fr.lproj/Localizable.strings
index 329490f34b..91cd6f3078 100644
--- a/apps/ios/fr.lproj/Localizable.strings
+++ b/apps/ios/fr.lproj/Localizable.strings
@@ -1357,7 +1357,7 @@ server test step */
/* blocking reason */
"Content violates conditions of use" = "Le contenu enfreint les conditions d'utilisation";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "Continuer";
/* No comment provided by engineer. */
diff --git a/apps/ios/hu.lproj/Localizable.strings b/apps/ios/hu.lproj/Localizable.strings
index 623d79433c..029fb9edd5 100644
--- a/apps/ios/hu.lproj/Localizable.strings
+++ b/apps/ios/hu.lproj/Localizable.strings
@@ -38,10 +38,10 @@
"[Send us email](mailto:chat@simplex.chat)" = "[Küldjön nekünk e-mailt](mailto:chat@simplex.chat)";
/* No comment provided by engineer. */
-"**Create 1-time link**: to create and share a new invitation link." = "**Partner hozzáadása:** új meghívási hivatkozás létrehozásához, vagy egy kapott hivatkozáson keresztül történő kapcsolódáshoz.";
+"**Create 1-time link**: to create and share a new invitation link." = "**Partner hozzáadása**: új meghívási hivatkozás létrehozásához, vagy egy kapott hivatkozáson keresztül történő kapcsolódáshoz.";
/* No comment provided by engineer. */
-"**Create group**: to create a new group." = "**Csoport létrehozása:** új csoport létrehozásához.";
+"**Create group**: to create a new group." = "**Csoport létrehozása**: új csoport létrehozásához.";
/* No comment provided by engineer. */
"**e2e encrypted** audio call" = "**végpontok között titkosított** hanghívás";
@@ -50,19 +50,19 @@
"**e2e encrypted** video call" = "**végpontok között titkosított** videóhívás";
/* No comment provided by engineer. */
-"**More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata." = "**Privátabb:** 20 percenként ellenőrzi az új üzeneteket. Az eszköztoken meg lesz osztva a SimpleX Chat kiszolgálóval, de az nem, hogy hány partnere vagy üzenete van.";
+"**More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata." = "**Privátabb**: 20 percenként ellenőrzi az új üzeneteket. Az eszköztoken meg lesz osztva a SimpleX Chat kiszolgálóval, de az nem, hogy hány partnere vagy üzenete van.";
/* No comment provided by engineer. */
"**Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app." = "**A legprivátabb**: Az alkalmazás nem használja a SimpleX Chat push-kiszolgálóját. Az alkalmazás a háttérben ellenőrzi az üzeneteket, amikor a rendszer ezt lehetővé teszi, attól függően, hogy Ön milyen gyakran használja az alkalmazást.";
/* No comment provided by engineer. */
-"**Please note**: using the same database on two devices will break the decryption of messages from your connections, as a security protection." = "**Megjegyzés:** ha két eszközön is ugyanazt az adatbázist használja, akkor biztonsági védelemként megszakítja a partnereitől érkező üzenetek visszafejtését.";
+"**Please note**: using the same database on two devices will break the decryption of messages from your connections, as a security protection." = "**Megjegyzés**: ha két eszközön is ugyanazt az adatbázist használja, akkor biztonsági védelemként megszakítja a partnereitől érkező üzenetek visszafejtését.";
/* No comment provided by engineer. */
-"**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Megjegyzés:** NEM fogja tudni helyreállítani vagy módosítani a jelmondatot abban az esetben, ha elveszíti.";
+"**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Megjegyzés**: NEM fogja tudni helyreállítani vagy módosítani a jelmondatot abban az esetben, ha elveszíti.";
/* No comment provided by engineer. */
-"**Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from." = "**Megjegyzés:** az eszköztoken és az értesítések el lesznek küldve a SimpleX Chat értesítési kiszolgálóra, kivéve az üzenet tartalma, mérete vagy az, hogy kitől származik.";
+"**Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from." = "**Megjegyzés**: az eszköztoken és az értesítések el lesznek küldve a SimpleX Chat értesítési kiszolgálóra, kivéve az üzenet tartalma, mérete vagy az, hogy kitől származik.";
/* No comment provided by engineer. */
"**Scan / Paste link**: to connect via a link you received." = "**Hivatkozás beolvasása / beillesztése**: egy kapott hivatkozáson keresztüli kapcsolódáshoz.";
@@ -71,10 +71,10 @@
"**Test relay** to retrieve its name." = "**Átjátszó tesztelése** a nevének lekéréséhez.";
/* No comment provided by engineer. */
-"**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Figyelmeztetés:** Az azonnali leküldéses értesítésekhez a kulcstartóban tárolt jelmondat megadása szükséges.";
+"**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Figyelmeztetés**: Az azonnali leküldéses értesítésekhez a kulcstartóban tárolt jelmondat megadása szükséges.";
/* No comment provided by engineer. */
-"**Warning**: the archive will be removed." = "**Figyelmeztetés:** az archívum el lesz távolítva.";
+"**Warning**: the archive will be removed." = "**Figyelmeztetés**: az archívum el lesz távolítva.";
/* No comment provided by engineer. */
"*bold*" = "\\*félkövér*";
@@ -226,10 +226,10 @@ channel relay bar */
"%d/%d relays active, %d removed" = "%1$d/%2$d átjátszó aktív, %3$d eltávolítva";
/* channel subscriber relay bar progress */
-"%d/%d relays connected" = "%1$d/%2$d átjátszó kapcsolódva";
+"%d/%d relays connected" = "%1$d/%2$d átjátszó kapcsolódott";
/* channel subscriber relay bar */
-"%d/%d relays connected, %d errors" = "%1$d/%2$d átjátszó kapcsolódva, %3$d hiba";
+"%d/%d relays connected, %d errors" = "%1$d/%2$d átjátszó kapcsolódott, %3$d hiba";
/* channel subscriber relay bar */
"%d/%d relays connected, %d failed" = "%1$d/%2$d átjátszó kapcsolódott, %3$d átjátszóhoz nem sikerült kapcsolódni";
@@ -376,7 +376,7 @@ time interval */
"A separate TCP connection will be used **for each chat profile you have in the app**." = "**Az összes csevegési profiljához az alkalmazásban** külön TCP-kapcsolat lesz használva.";
/* No comment provided by engineer. */
-"A separate TCP connection will be used **for each contact and group member**.\n**Please note**: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail." = "**Az összes partneréhez és csoporttaghoz** külön TCP-kapcsolat lesz használva.\n**Megjegyzés:** ha sok kapcsolata van, akkor az akkumulátor-használat és az adatforgalom jelentősen megnövekedhet, és néhány kapcsolódási kísérlet sikertelen lehet.";
+"A separate TCP connection will be used **for each contact and group member**.\n**Please note**: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail." = "**Az összes partneréhez és csoporttaghoz** külön TCP-kapcsolat lesz használva.\n**Megjegyzés**: ha sok kapcsolata van, akkor az akkumulátor-használat és az adatforgalom jelentősen megnövekedhet, és néhány kapcsolódási kísérlet sikertelen lehet.";
/* No comment provided by engineer. */
"Abort" = "Megszakítás";
@@ -449,7 +449,7 @@ swipe action */
"accepted you" = "befogadta Önt";
/* No comment provided by engineer. */
-"Acknowledged" = "Visszaigazolt";
+"Acknowledged" = "Visszaigazolva";
/* No comment provided by engineer. */
"Acknowledgement errors" = "Visszaigazolási hibák";
@@ -505,9 +505,6 @@ swipe action */
/* No comment provided by engineer. */
"Added message servers" = "Hozzáadott üzenetkiszolgálók";
-/* No comment provided by engineer. */
-"Adding relays will be supported later." = "Az átjátszók hozzáadása később lesz támogatott.";
-
/* No comment provided by engineer. */
"Additional accent" = "További kiemelőszín";
@@ -716,10 +713,10 @@ swipe action */
"always" = "mindig";
/* No comment provided by engineer. */
-"Always use private routing." = "Mindig legyen használva privát útválasztás.";
+"Always use private routing." = "Privát útválasztás használata minden esetben.";
/* No comment provided by engineer. */
-"Always use relay" = "Mindig legyen használva átjátszó";
+"Always use relay" = "Átjátszó használata minden esetben";
/* No comment provided by engineer. */
"An empty chat profile with the provided name is created, and the app opens as usual." = "Egy üres csevegési profil lesz létrehozva a megadott névvel, és az alkalmazás a szokásos módon megnyílik.";
@@ -878,7 +875,7 @@ swipe action */
"Be free\nin your network" = "Váljon szabaddá\na saját hálózatában";
/* No comment provided by engineer. */
-"Be free in your network." = "Legyen szabad a saját hálózatában.";
+"Be free in your network." = "Váljon szabaddá a saját hálózatában.";
/* No comment provided by engineer. */
"Because we destroyed the power to know who you are. So that your power can never be taken." = "Mert felszámoltuk a lehetőségét is annak, hogy megtudjuk, Ön kicsoda. Így az önrendelkezése soha nem kerülhet idegen kezekbe.";
@@ -951,10 +948,10 @@ swipe action */
/* blocked chat item
marked deleted chat item preview text */
-"blocked by admin" = "letiltva az adminisztrátor által";
+"blocked by admin" = "az adminisztrátor letiltotta";
/* No comment provided by engineer. */
-"Blocked by admin" = "Letiltva az adminisztrátor által";
+"Blocked by admin" = "Az adminisztrátor letiltotta";
/* No comment provided by engineer. */
"Blur for better privacy." = "Elhomályosítás a jobb adatvédelemért.";
@@ -1171,7 +1168,7 @@ alert subtitle */
"channel profile updated" = "csatornaprofil frissítve";
/* alert message */
-"Channel profile was changed. If you save it, the updated profile will be sent to channel subscribers." = "A csatornaprofil módosult. Ha menti, akkor a frissített profil el lesz küldve a csatorna feliratkozóinak.";
+"Channel profile was changed. If you save it, the updated profile will be sent to channel subscribers." = "Csatornaprofil módosítva. Ha menti, akkor a frissített profil el lesz küldve a csatorna feliratkozóinak.";
/* alert title */
"Channel temporarily unavailable" = "A csatorna ideiglenesen nem érhető el";
@@ -1182,9 +1179,6 @@ alert subtitle */
/* No comment provided by engineer. */
"Channel will be deleted for you - this cannot be undone!" = "A csatorna törölve lesz az Ön számára – ez a művelet nem vonható vissza!";
-/* alert message */
-"Channel will start working with %d of %d relays. Proceed?" = "A csatorna %2$d átjátszóból %1$d használatával kezd el működni. Folytatja?";
-
/* No comment provided by engineer. */
"Channels" = "Csatornák";
@@ -1634,7 +1628,7 @@ server test step */
/* blocking reason */
"Content violates conditions of use" = "A tartalom sérti a használati feltételeket";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "Folytatás";
/* No comment provided by engineer. */
@@ -1800,7 +1794,7 @@ server test step */
"Database passphrase & export" = "Adatbázis-jelmondat és -exportálás";
/* No comment provided by engineer. */
-"Database passphrase is different from saved in the keychain." = "Az adatbázis jelmondata nem egyezik a kulcstartóba mentettől.";
+"Database passphrase is different from saved in the keychain." = "Az adatbázis jelmondata eltér a kulcstartóban tárolttól.";
/* No comment provided by engineer. */
"Database passphrase is required to open chat." = "A csevegés megnyitásához adja meg az adatbázis jelmondatát.";
@@ -2172,7 +2166,7 @@ alert button */
"Do not use credentials with proxy." = "Ne használja a hitelesítési adatokat proxyval.";
/* No comment provided by engineer. */
-"Do NOT use private routing." = "NE legyen használva privát útválasztás.";
+"Do NOT use private routing." = "Privát útválasztás használatának elkerülése.";
/* No comment provided by engineer. */
"Do NOT use SimpleX for emergency calls." = "NE használja a SimpleXet segélyhívásokhoz.";
@@ -2356,7 +2350,7 @@ chat item action */
"Encrypted message: database migration error" = "Titkosított üzenet: adatbázis-átköltöztetési hiba";
/* notification */
-"Encrypted message: keychain error" = "Titkosított üzenet: kulcstartó hiba";
+"Encrypted message: keychain error" = "Titkosított üzenet: kulcstartóhiba";
/* notification */
"Encrypted message: no passphrase" = "Titkosított üzenet: nincs jelmondat";
@@ -2461,13 +2455,13 @@ chat item action */
"Error accepting contact request" = "Hiba történt a partneri kapcsolatkérés elfogadásakor";
/* alert title */
-"Error accepting member" = "Hiba a tag befogadásakor";
+"Error accepting member" = "Hiba történt a tag befogadásakor";
/* No comment provided by engineer. */
"Error adding member(s)" = "Hiba történt a tag(ok) hozzáadásakor";
/* alert title */
-"Error adding relay" = "Hiba az átjátszó hozzáadásakor";
+"Error adding relay" = "Hiba történt az átjátszó hozzáadásakor";
/* alert title */
"Error adding server" = "Hiba történt a kiszolgáló hozzáadásakor";
@@ -2479,7 +2473,7 @@ chat item action */
"Error changing address" = "Hiba történt a cím módosításakor";
/* alert title */
-"Error changing chat profile" = "Hiba a csevegési profil módosításakor";
+"Error changing chat profile" = "Hiba történt a csevegési profil módosításakor";
/* No comment provided by engineer. */
"Error changing connection profile" = "Hiba történt a kapcsolati profilra való váltáskor";
@@ -2506,7 +2500,7 @@ chat item action */
"Error creating address" = "Hiba történt a cím létrehozásakor";
/* alert title */
-"Error creating channel" = "Hiba a csatorna létrehozásakor";
+"Error creating channel" = "Hiba történt a csatorna létrehozásakor";
/* No comment provided by engineer. */
"Error creating group" = "Hiba történt a csoport létrehozásakor";
@@ -2533,7 +2527,7 @@ chat item action */
"Error decrypting file" = "Hiba történt a fájl visszafejtésekor";
/* alert title */
-"Error deleting chat" = "Hiba a csevegés törlésekor";
+"Error deleting chat" = "Hiba történt a csevegés törlésekor";
/* alert title */
"Error deleting chat database" = "Hiba történt a csevegési adatbázis törlésekor";
@@ -2614,7 +2608,7 @@ chat item action */
"Error resetting statistics" = "Hiba történt a statisztikák visszaállításakor";
/* No comment provided by engineer. */
-"Error saving channel profile" = "Hiba a csatornaprofil mentésekor";
+"Error saving channel profile" = "Hiba történt a csatornaprofil mentésekor";
/* alert title */
"Error saving chat list" = "Hiba történt a csevegési lista mentésekor";
@@ -2653,13 +2647,13 @@ chat item action */
"Error sending message" = "Hiba történt az üzenet elküldésekor";
/* No comment provided by engineer. */
-"Error setting auto-accept" = "Hiba az automatikus elfogadás beállításakor";
+"Error setting auto-accept" = "Hiba történt az automatikus elfogadás beállításakor";
/* No comment provided by engineer. */
"Error setting delivery receipts!" = "Hiba történt a kézbesítési jelentések beállításakor!";
/* alert title */
-"Error sharing channel" = "Hiba a csatorna megosztásakor";
+"Error sharing channel" = "Hiba történt a csatorna megosztásakor";
/* No comment provided by engineer. */
"Error starting chat" = "Hiba történt a csevegés elindításakor";
@@ -3057,7 +3051,7 @@ servers warning */
"group profile updated" = "csoportprofil frissítve";
/* alert message */
-"Group profile was changed. If you save it, the updated profile will be sent to group members." = "Csoportprofil módosítva. Ha menti, akkor a frissített profil el lesz küldve a csoporttagoknak.";
+"Group profile was changed. If you save it, the updated profile will be sent to group members." = "Csoportprofil módosítva. Ha menti, akkor a frissített profil el lesz küldve a csoport tagjainak.";
/* No comment provided by engineer. */
"Group welcome message" = "A csoport üdvözlőüzenete";
@@ -3129,7 +3123,7 @@ servers warning */
"How to use it" = "Használati útmutató";
/* No comment provided by engineer. */
-"How to use your servers" = "Hogyan használja a saját kiszolgálóit";
+"How to use your servers" = "Útmutató a saját kiszolgálók használatához";
/* No comment provided by engineer. */
"Hungarian interface" = "Magyar kezelőfelület";
@@ -3267,7 +3261,7 @@ servers warning */
"Initial role" = "Kezdeti szerepkör";
/* No comment provided by engineer. */
-"Install SimpleX Chat for terminal" = "A SimpleX Chat terminálhoz telepítése";
+"Install SimpleX Chat for terminal" = "SimpleX Chat telepítése a terminálhoz";
/* No comment provided by engineer. */
"Instant" = "Azonnali";
@@ -3501,7 +3495,7 @@ servers warning */
"Less traffic on mobile networks." = "Kevesebb adatforgalom a mobilhálózatokon.";
/* No comment provided by engineer. */
-"Let someone connect to you" = "Hagyja, hogy valaki elérje Önt";
+"Let someone connect to you" = "Legyen elérhető mások számára";
/* email subject */
"Let's talk in SimpleX Chat" = "Beszélgessünk a SimpleX Chatben";
@@ -4548,7 +4542,7 @@ alert button */
"Privacy policy and conditions of use." = "Adatvédelmi szabályzat és felhasználási feltételek.";
/* No comment provided by engineer. */
-"Privacy: for owners and subscribers." = "Adatvédelem: tulajdonosok és előfizetők számára.";
+"Privacy: for owners and subscribers." = "Adatvédelem: tulajdonosok és feliratkozók számára.";
/* No comment provided by engineer. */
"Private and secure messaging." = "Privát és biztonságos üzenetváltás.";
@@ -4577,9 +4571,6 @@ alert button */
/* alert title */
"Private routing timeout" = "Privát útválasztás időtúllépése";
-/* alert action */
-"Proceed" = "Folytatás";
-
/* No comment provided by engineer. */
"Profile and server connections" = "Profil és kiszolgálókapcsolatok";
@@ -4826,10 +4817,10 @@ swipe action */
"Relay results:" = "Átjátszóeredmények:";
/* No comment provided by engineer. */
-"Relay server is only used if necessary. Another party can observe your IP address." = "Az átjátszó csak szükség esetén lesz használva. Egy másik fél megfigyelheti az IP-címét.";
+"Relay server is only used if necessary. Another party can observe your IP address." = "Az átjátszó kiszolgáló csak szükség esetén lesz használva. Egy másik fél megfigyelheti az IP-címét.";
/* No comment provided by engineer. */
-"Relay server protects your IP address, but it can observe the duration of the call." = "Az átjátszó megvédi az IP-címét, de megfigyelheti a hívás időtartamát.";
+"Relay server protects your IP address, but it can observe the duration of the call." = "Az átjátszó kiszolgáló megvédi az IP-címét, de megfigyelheti a hívás időtartamát.";
/* No comment provided by engineer. */
"Relay test failed!" = "Nem sikerült tesztelni az átjátszót!";
@@ -4861,9 +4852,6 @@ swipe action */
/* No comment provided by engineer. */
"Remove passphrase from keychain?" = "Eltávolítja a jelmondatot a kulcstartóból?";
-/* No comment provided by engineer. */
-"Remove subscriber" = "Feliratkozó eltávolítása";
-
/* alert title */
"Remove subscriber?" = "Eltávolítja a feliratkozót?";
@@ -5030,7 +5018,7 @@ swipe action */
"Review members before admitting (\"knocking\")." = "Tagok áttekintése a befogadás előtt (kopogtatás).";
/* No comment provided by engineer. */
-"reviewed by admins" = "áttekintve a moderátorok által";
+"reviewed by admins" = "a moderátorok áttekintették";
/* No comment provided by engineer. */
"Revoke" = "Visszavonás";
@@ -5919,7 +5907,7 @@ report reason */
/* relay test failure
server test failure */
-"Test failed at step %@." = "A teszt a(z) %@ lépésnél sikertelen volt.";
+"Test failed at step %@." = "A teszt a(z) %@. lépésnél sikertelen volt.";
/* No comment provided by engineer. */
"Test notifications" = "Értesítések tesztelése";
@@ -6327,13 +6315,13 @@ server test failure */
"Update settings?" = "Frissíti a beállításokat?";
/* rcv group event chat item */
-"updated channel profile" = "frissített csatornaprofil";
+"updated channel profile" = "frissítette a csatorna profilját";
/* No comment provided by engineer. */
"Updated conditions" = "Frissített feltételek";
/* rcv group event chat item */
-"updated group profile" = "frissítette a csoportprofilt";
+"updated group profile" = "frissítette a csoport profilját";
/* profile update event chat item */
"updated profile" = "frissítette a profilját";
@@ -6714,7 +6702,7 @@ server test failure */
"You are already connected to %@." = "Ön már kapcsolódott a következőhöz: %@.";
/* No comment provided by engineer. */
-"You are already connected with %@." = "Ön már kapcsolódva van vele: %@.";
+"You are already connected with %@." = "Ön már kapcsolatban van vele: %@.";
/* new chat sheet message */
"You are already connecting to %@." = "A kapcsolódás már folyamatban van a következőhöz: %@.";
diff --git a/apps/ios/it.lproj/Localizable.strings b/apps/ios/it.lproj/Localizable.strings
index 96b117eeca..c882eb662c 100644
--- a/apps/ios/it.lproj/Localizable.strings
+++ b/apps/ios/it.lproj/Localizable.strings
@@ -505,9 +505,6 @@ swipe action */
/* No comment provided by engineer. */
"Added message servers" = "Server dei messaggi aggiunti";
-/* No comment provided by engineer. */
-"Adding relays will be supported later." = "L'aggiunta di relay verrà supportata prossimamente.";
-
/* No comment provided by engineer. */
"Additional accent" = "Principale aggiuntivo";
@@ -1182,9 +1179,6 @@ alert subtitle */
/* No comment provided by engineer. */
"Channel will be deleted for you - this cannot be undone!" = "Il canale verrà eliminato per te, non è reversibile!";
-/* alert message */
-"Channel will start working with %d of %d relays. Proceed?" = "Il canale sarà operativo con %1$d di %2$d relay. Procedere?";
-
/* No comment provided by engineer. */
"Channels" = "Canali";
@@ -1634,7 +1628,7 @@ server test step */
/* blocking reason */
"Content violates conditions of use" = "Il contenuto viola le condizioni di utilizzo";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "Continua";
/* No comment provided by engineer. */
@@ -4293,10 +4287,10 @@ alert button */
"Open migration to another device" = "Apri migrazione ad un altro dispositivo";
/* new chat action */
-"Open new channel" = "Apri un canale nuovo";
+"Open new channel" = "Apri il nuovo canale";
/* new chat action */
-"Open new chat" = "Apri una chat nuova";
+"Open new chat" = "Apri la nuova chat";
/* new chat action */
"Open new group" = "Apri il nuovo gruppo";
@@ -4577,9 +4571,6 @@ alert button */
/* alert title */
"Private routing timeout" = "Scadenza dell'instradamento privato";
-/* alert action */
-"Proceed" = "Procedi";
-
/* No comment provided by engineer. */
"Profile and server connections" = "Profilo e connessioni al server";
@@ -4861,9 +4852,6 @@ swipe action */
/* No comment provided by engineer. */
"Remove passphrase from keychain?" = "Rimuovere la password dal portachiavi?";
-/* No comment provided by engineer. */
-"Remove subscriber" = "Rimuovi iscritto";
-
/* alert title */
"Remove subscriber?" = "Rimuovere l'iscritto?";
diff --git a/apps/ios/ja.lproj/Localizable.strings b/apps/ios/ja.lproj/Localizable.strings
index b14777244f..35d8732e3f 100644
--- a/apps/ios/ja.lproj/Localizable.strings
+++ b/apps/ios/ja.lproj/Localizable.strings
@@ -1005,7 +1005,7 @@ server test step */
/* No comment provided by engineer. */
"Contacts can mark messages for deletion; you will be able to view them." = "連絡先はメッセージを削除対象とすることができます。あなたには閲覧可能です。";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "続ける";
/* No comment provided by engineer. */
diff --git a/apps/ios/nl.lproj/Localizable.strings b/apps/ios/nl.lproj/Localizable.strings
index e12e255488..407665bbec 100644
--- a/apps/ios/nl.lproj/Localizable.strings
+++ b/apps/ios/nl.lproj/Localizable.strings
@@ -1382,7 +1382,7 @@ server test step */
/* blocking reason */
"Content violates conditions of use" = "Inhoud schendt de gebruiksvoorwaarden";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "Doorgaan";
/* No comment provided by engineer. */
diff --git a/apps/ios/pl.lproj/Localizable.strings b/apps/ios/pl.lproj/Localizable.strings
index e2e46590c9..8905300160 100644
--- a/apps/ios/pl.lproj/Localizable.strings
+++ b/apps/ios/pl.lproj/Localizable.strings
@@ -1439,7 +1439,7 @@ server test step */
/* blocking reason */
"Content violates conditions of use" = "Treść narusza warunki użytkowania";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "Kontynuuj";
/* No comment provided by engineer. */
diff --git a/apps/ios/ru.lproj/Localizable.strings b/apps/ios/ru.lproj/Localizable.strings
index c2b01228a2..9f79b5dea0 100644
--- a/apps/ios/ru.lproj/Localizable.strings
+++ b/apps/ios/ru.lproj/Localizable.strings
@@ -505,9 +505,6 @@ swipe action */
/* No comment provided by engineer. */
"Added message servers" = "Дополнительные серверы сообщений";
-/* No comment provided by engineer. */
-"Adding relays will be supported later." = "Добавление релеев будет поддерживаться позже.";
-
/* No comment provided by engineer. */
"Additional accent" = "Дополнительный акцент";
@@ -1182,9 +1179,6 @@ alert subtitle */
/* No comment provided by engineer. */
"Channel will be deleted for you - this cannot be undone!" = "Канал будет удалён для Вас - это нельзя отменить!";
-/* alert message */
-"Channel will start working with %d of %d relays. Proceed?" = "Канал начнёт работу с %1$d из %2$d релеев. Продолжить?";
-
/* No comment provided by engineer. */
"Channels" = "Каналы";
@@ -1634,7 +1628,7 @@ server test step */
/* blocking reason */
"Content violates conditions of use" = "Содержание нарушает условия использования";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "Продолжить";
/* No comment provided by engineer. */
@@ -4577,9 +4571,6 @@ alert button */
/* alert title */
"Private routing timeout" = "Таймаут конфиденциальной доставки";
-/* alert action */
-"Proceed" = "Продолжить";
-
/* No comment provided by engineer. */
"Profile and server connections" = "Профиль и соединения на сервере";
@@ -4861,9 +4852,6 @@ swipe action */
/* No comment provided by engineer. */
"Remove passphrase from keychain?" = "Удалить пароль из Keychain?";
-/* No comment provided by engineer. */
-"Remove subscriber" = "Удалить подписчика";
-
/* alert title */
"Remove subscriber?" = "Удалить подписчика?";
@@ -6327,7 +6315,7 @@ server test failure */
"Update settings?" = "Обновить настройки?";
/* rcv group event chat item */
-"updated channel profile" = "обновлён профиль канала";
+"updated channel profile" = "обновил профиль канала";
/* No comment provided by engineer. */
"Updated conditions" = "Обновлённые условия";
diff --git a/apps/ios/th.lproj/Localizable.strings b/apps/ios/th.lproj/Localizable.strings
index 652737b4ca..cc3abea189 100644
--- a/apps/ios/th.lproj/Localizable.strings
+++ b/apps/ios/th.lproj/Localizable.strings
@@ -705,7 +705,7 @@ server test step */
/* No comment provided by engineer. */
"Contacts can mark messages for deletion; you will be able to view them." = "ผู้ติดต่อสามารถทําเครื่องหมายข้อความเพื่อลบได้ คุณจะสามารถดูได้";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "ดำเนินการต่อ";
/* No comment provided by engineer. */
diff --git a/apps/ios/tr.lproj/Localizable.strings b/apps/ios/tr.lproj/Localizable.strings
index fb3bf39168..e06989afee 100644
--- a/apps/ios/tr.lproj/Localizable.strings
+++ b/apps/ios/tr.lproj/Localizable.strings
@@ -169,6 +169,18 @@
/* time interval */
"%d months" = "%d ay";
+/* channel relay bar
+channel subscriber relay bar */
+"%d relays failed" = "%d aktarıcı başarısız oldu";
+
+/* channel relay bar
+channel subscriber relay bar */
+"%d relays not active" = "%d aktarıcı etkin değil";
+
+/* channel relay bar
+channel subscriber relay bar */
+"%d relays removed" = "%d aktarıcı kaldırıldı";
+
/* time interval */
"%d sec" = "%d saniye";
@@ -178,9 +190,32 @@
/* integrity error chat item */
"%d skipped message(s)" = "%d okunmamış mesaj(lar)";
+/* channel subscriber count */
+"%d subscriber" = "%d abone";
+
+/* channel subscriber count */
+"%d subscribers" = "%d abone";
+
/* time interval */
"%d weeks" = "%d hafta";
+/* channel creation progress
+channel relay bar progress */
+"%d/%d relays active" = "%1$d/%2$d aktarıcı etkin";
+
+/* channel relay bar */
+"%d/%d relays active, %d errors" = "%1$d/%2$d aktarıcı etkin, %3$d hata";
+
+/* channel creation progress with errors
+channel relay bar */
+"%d/%d relays active, %d failed" = "%1$d/%2$d aktarıcı etkin, %3$d başarısız";
+
+/* channel relay bar */
+"%d/%d relays active, %d removed" = "%1$d/%2$d aktarıcı etkin, %3$d kaldırıldı";
+
+/* channel subscriber relay bar progress */
+"%d/%d relays connected" = "%1$d/%2$d aktarıcı bağlı";
+
/* No comment provided by engineer. */
"%lld" = "%lld";
@@ -1424,7 +1459,7 @@ server test step */
/* blocking reason */
"Content violates conditions of use" = "İçerik kullanım koşullarını ihlal ediyor";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "Devam et";
/* No comment provided by engineer. */
diff --git a/apps/ios/uk.lproj/Localizable.strings b/apps/ios/uk.lproj/Localizable.strings
index a0d9490b00..4a21eb4ae8 100644
--- a/apps/ios/uk.lproj/Localizable.strings
+++ b/apps/ios/uk.lproj/Localizable.strings
@@ -1409,7 +1409,7 @@ server test step */
/* blocking reason */
"Content violates conditions of use" = "Вміст порушує умови використання";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "Продовжуйте";
/* No comment provided by engineer. */
diff --git a/apps/ios/zh-Hans.lproj/Localizable.strings b/apps/ios/zh-Hans.lproj/Localizable.strings
index 3893351fdd..13be5125ea 100644
--- a/apps/ios/zh-Hans.lproj/Localizable.strings
+++ b/apps/ios/zh-Hans.lproj/Localizable.strings
@@ -1433,7 +1433,7 @@ server test step */
/* blocking reason */
"Content violates conditions of use" = "内容违反使用条款";
-/* No comment provided by engineer. */
+/* alert action */
"Continue" = "继续";
/* No comment provided by engineer. */
diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt
index 09142d2cc7..f3024d7ca1 100644
--- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt
+++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt
@@ -2240,11 +2240,25 @@ object GroupTypeSerializer : KSerializer {
}
}
+@Serializable
+data class PublicGroupAccess(
+ val groupWebPage: String? = null,
+ val groupDomain: String? = null,
+ val domainWebPage: Boolean = false,
+ val allowEmbedding: Boolean = false
+)
+
+@Serializable
+data class RelayCapabilities(
+ val webDomain: String? = null
+)
+
@Serializable
data class PublicGroupProfile(
val groupType: GroupType,
val groupLink: String,
- val publicGroupId: String
+ val publicGroupId: String,
+ val publicGroupAccess: PublicGroupAccess? = null
)
@Serializable
@@ -2368,7 +2382,8 @@ data class GroupRelay(
val groupMemberId: Long,
val userChatRelay: UserChatRelay,
val relayStatus: RelayStatus,
- val relayLink: String? = null
+ val relayLink: String? = null,
+ val relayCap: RelayCapabilities
) {
val id: Long get() = groupRelayId
}
@@ -4711,6 +4726,7 @@ sealed class Format {
val viaHosts: String get() =
"(${String.format(generalGetString(MR.strings.simplex_link_connection), smpHosts.firstOrNull() ?: "?")})"
}
+ @Serializable @SerialName("simplexName") class SimplexName(val nameInfo: SimplexNameInfo): Format()
@Serializable @SerialName("command") class Command(val commandStr: String): Format()
@Serializable @SerialName("mention") class Mention(val memberName: String): Format()
@Serializable @SerialName("email") class Email: Format()
@@ -4728,6 +4744,7 @@ sealed class Format {
is Uri -> linkStyle
is HyperLink -> linkStyle
is SimplexLink -> linkStyle
+ is SimplexName -> linkStyle
is Command -> SpanStyle(color = MaterialTheme.colors.primary, fontFamily = FontFamily.Monospace)
is Mention -> SpanStyle(fontWeight = FontWeight.Medium)
is Email -> linkStyle
@@ -4759,6 +4776,32 @@ enum class SimplexLinkType(val linkType: String) {
})
}
+@Serializable
+data class SimplexNameInfo(
+ val nameType: SimplexNameType,
+ val nameDomain: SimplexNameDomain
+)
+
+@Serializable
+data class SimplexNameDomain(
+ val nameTLD: SimplexTLD,
+ val domain: String,
+ val subDomain: List
+)
+
+@Serializable
+enum class SimplexTLD {
+ @SerialName("simplex") simplex,
+ @SerialName("testing") testing,
+ @SerialName("web") web
+}
+
+@Serializable
+enum class SimplexNameType {
+ @SerialName("publicGroup") publicGroup,
+ @SerialName("contact") contact
+}
+
@Serializable
enum class FormatColor(val color: String) {
red("red"),
diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt
index ec75c1a359..35e92e2cd2 100644
--- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt
+++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt
@@ -6994,6 +6994,7 @@ sealed class GroupLinkPlan {
@Serializable @SerialName("connectingProhibit") class ConnectingProhibit(val groupInfo_: GroupInfo? = null): GroupLinkPlan()
@Serializable @SerialName("known") class Known(val groupInfo: GroupInfo): GroupLinkPlan()
@Serializable @SerialName("noRelays") class NoRelays(val groupSLinkData_: GroupShortLinkData? = null): GroupLinkPlan()
+ @Serializable @SerialName("updateRequired") class UpdateRequired(val groupSLinkData_: GroupShortLinkData? = null): GroupLinkPlan()
}
abstract class TerminalItem {
diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/TextSelection.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/TextSelection.kt
index d85488cefc..db31c05dce 100644
--- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/TextSelection.kt
+++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/TextSelection.kt
@@ -217,6 +217,9 @@ class SelectionManager {
val hi = maxOf(r.startIndex, r.endIndex)
return (lo..hi).mapNotNull { idx ->
val ci = items.getOrNull(idx)?.newest()?.item ?: return@mapNotNull null
+ // Only real messages are copyable. Event/info items (e.g. "connected", calls, e2ee info)
+ // have no msgContent and are never highlighted as selected, so they must never be copied.
+ if (ci.content.msgContent == null) return@mapNotNull null
if (ci.meta.itemDeleted != null && (!revealedItems.contains(ci.id) || ci.isDeletedContent)) return@mapNotNull null
val sel = selectedRange(range, idx) ?: return@mapNotNull null
selectedItemCopiedText(ci, sel, linkMode)
diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/TextItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/TextItemView.kt
index 3358a23e1e..c9f7d96f39 100644
--- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/TextItemView.kt
+++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/TextItemView.kt
@@ -281,6 +281,13 @@ fun MarkdownText (
}
}
}
+ is Format.SimplexName -> {
+ hasLinks = true
+ val ftStyle = Format.linkStyle
+ withAnnotation(tag = "SIMPLEX_NAME", annotation = i.toString()) {
+ withStyle(ftStyle) { append(ft.text) }
+ }
+ }
is Format.Email -> {
hasLinks = true
val ftStyle = Format.linkStyle
@@ -329,6 +336,16 @@ fun MarkdownText (
withAnnotation("WEB_URL") { a -> openBrowserAlert(a.item, uriHandler) }
withAnnotation("OTHER_URL") { a -> safeOpenUri(a.item, uriHandler) }
withAnnotation("SIMPLEX_URL") { a -> uriHandler.openVerifiedSimplexUri(a.item) }
+ withAnnotation("SIMPLEX_NAME") { a ->
+ val idx = a.item.toIntOrNull()
+ val nameInfo = (idx?.let { formattedText.getOrNull(it) }?.format as? Format.SimplexName)?.nameInfo
+ val (title, msg) = if (nameInfo?.nameType == SimplexNameType.contact) {
+ generalGetString(MR.strings.unsupported_contact_name) to generalGetString(MR.strings.contact_name_requires_newer_app_version)
+ } else {
+ generalGetString(MR.strings.unsupported_channel_name) to generalGetString(MR.strings.channel_name_requires_newer_app_version)
+ }
+ AlertManager.shared.showAlertMsg(title, "$msg ${generalGetString(MR.strings.please_upgrade_the_app)}")
+ }
}
if (hasSecrets) {
withAnnotation("SECRET") { a ->
@@ -343,7 +360,7 @@ fun MarkdownText (
onHover = { offset ->
val hasAnnotation: (String) -> Boolean = { tag -> annotatedText.hasStringAnnotations(tag, start = offset, end = offset) }
icon.value =
- if (hasAnnotation("WEB_URL") || hasAnnotation("SIMPLEX_URL") || hasAnnotation("OTHER_URL") || hasAnnotation("SECRET") || hasAnnotation("COMMAND")) {
+ if (hasAnnotation("WEB_URL") || hasAnnotation("SIMPLEX_URL") || hasAnnotation("OTHER_URL") || hasAnnotation("SIMPLEX_NAME") || hasAnnotation("SECRET") || hasAnnotation("COMMAND")) {
PointerIcon.Hand
} else {
PointerIcon.Text
diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt
index 94b13a8270..3012525f9b 100644
--- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt
+++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt
@@ -792,31 +792,29 @@ private fun ChatListSearchBar(listState: LazyListState, searchText: MutableState
snapshotFlow { searchText.value.text }
.distinctUntilChanged()
.collect {
- val link = strHasSingleSimplexLink(it.trim())
- if (link != null) {
- // if SimpleX link is pasted, show connection dialogue
- hideKeyboard(view)
- if (link.format is Format.SimplexLink) {
- val linkText = link.format.simplexLinkText
- searchText.value = searchText.value.copy(linkText, selection = TextRange.Zero)
+ when (val target = strConnectTarget(it.trim())) {
+ is ConnectTarget.Link -> {
+ hideKeyboard(view)
+ searchText.value = searchText.value.copy(target.linkText, selection = TextRange.Zero)
+ searchShowingSimplexLink.value = true
+ searchChatFilteredBySimplexLink.value = null
+ connect(target.text, searchChatFilteredBySimplexLink) { searchText.value = TextFieldValue() }
}
- searchShowingSimplexLink.value = true
- searchChatFilteredBySimplexLink.value = null
- connect(link.text, searchChatFilteredBySimplexLink) { searchText.value = TextFieldValue() }
- } else if (!searchShowingSimplexLink.value || it.isEmpty()) {
- if (it.isNotEmpty()) {
- // if some other text is pasted, enter search mode
- focusRequester.requestFocus()
- } else {
- if (!chatModel.appOpenUrlConnecting.value) {
- connectProgressManager.cancelConnectProgress()
- }
- if (listState.layoutInfo.totalItemsCount > 0) {
- listState.scrollToItem(0)
+ is ConnectTarget.Name -> showUnsupportedNameAlert(target.nameInfo)
+ null -> if (!searchShowingSimplexLink.value || it.isEmpty()) {
+ if (it.isNotEmpty()) {
+ focusRequester.requestFocus()
+ } else {
+ if (!chatModel.appOpenUrlConnecting.value) {
+ connectProgressManager.cancelConnectProgress()
+ }
+ if (listState.layoutInfo.totalItemsCount > 0) {
+ listState.scrollToItem(0)
+ }
}
+ searchShowingSimplexLink.value = false
+ searchChatFilteredBySimplexLink.value = null
}
- searchShowingSimplexLink.value = false
- searchChatFilteredBySimplexLink.value = null
}
}
}
diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ConnectPlan.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ConnectPlan.kt
index cafad97574..9fd5dd5b4a 100644
--- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ConnectPlan.kt
+++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ConnectPlan.kt
@@ -30,14 +30,23 @@ suspend fun planAndConnect(
filterKnownContact: ((Contact) -> Unit)? = null,
filterKnownGroup: ((GroupInfo) -> Unit)? = null,
): CompletableDeferred {
- val link = strHasSingleSimplexLink(shortOrFullLink.trim())
- if (link?.format is Format.SimplexLink && (link.format as Format.SimplexLink).linkType == SimplexLinkType.relay) {
- AlertManager.privacySensitive.showAlertMsg(
- generalGetString(MR.strings.relay_address_alert_title),
- generalGetString(MR.strings.relay_address_alert_message),
- )
- cleanup?.invoke()
- return CompletableDeferred(false)
+ when (val target = strConnectTarget(shortOrFullLink.trim())) {
+ is ConnectTarget.Name -> {
+ showUnsupportedNameAlert(target.nameInfo)
+ cleanup?.invoke()
+ return CompletableDeferred(false)
+ }
+ is ConnectTarget.Link -> {
+ if (target.linkType == SimplexLinkType.relay) {
+ AlertManager.privacySensitive.showAlertMsg(
+ generalGetString(MR.strings.relay_address_alert_title),
+ generalGetString(MR.strings.relay_address_alert_message),
+ )
+ cleanup?.invoke()
+ return CompletableDeferred(false)
+ }
+ }
+ null -> {}
}
connectProgressManager.cancelConnectProgress()
val inProgress = mutableStateOf(true)
@@ -73,11 +82,8 @@ private suspend fun planAndConnectTask(
if (!inProgress.value) { return completable }
if (result != null) {
val (connectionLink, connectionPlan) = result
- val link = strHasSingleSimplexLink(shortOrFullLink.trim())
- val linkText = if (link?.format is Format.SimplexLink)
- "
${link.format.simplexLinkText}"
- else
- ""
+ val target = strConnectTarget(shortOrFullLink.trim())
+ val linkText = if (target is ConnectTarget.Link) "
${target.linkText}" else ""
when (connectionPlan) {
is ConnectionPlan.InvitationLink -> when (connectionPlan.invitationLinkPlan) {
is InvitationLinkPlan.Ok ->
@@ -316,6 +322,33 @@ private suspend fun planAndConnectTask(
cleanup()
}
}
+ is GroupLinkPlan.UpdateRequired -> {
+ Log.d(TAG, "planAndConnect, .GroupLink, .UpdateRequired")
+ val groupSLinkData = connectionPlan.groupLinkPlan.groupSLinkData_
+ if (groupSLinkData != null) {
+ AlertManager.privacySensitive.showOpenChatAlert(
+ profileName = groupSLinkData.groupProfile.displayName,
+ profileFullName = groupSLinkData.groupProfile.fullName,
+ profileImage = {
+ ProfileImage(
+ size = alertProfileImageSize,
+ image = groupSLinkData.groupProfile.image,
+ icon = MR.images.ic_supervised_user_circle_filled
+ )
+ },
+ subtitle = generalGetString(MR.strings.group_link_requires_newer_version),
+ confirmText = null,
+ dismissText = generalGetString(MR.strings.ok),
+ onDismiss = { cleanup() }
+ )
+ } else {
+ AlertManager.privacySensitive.showAlertMsg(
+ generalGetString(MR.strings.app_update_required),
+ generalGetString(MR.strings.group_link_requires_newer_version)
+ )
+ cleanup()
+ }
+ }
}
is ConnectionPlan.Error -> {
Log.d(TAG, "planAndConnect, error ${connectionPlan.chatError}")
diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt
index 993e1fca01..af7f59496b 100644
--- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt
+++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt
@@ -523,34 +523,32 @@ private fun ContactsSearchBar(
snapshotFlow { searchText.value.text }
.distinctUntilChanged()
.collect {
- val link = strHasSingleSimplexLink(it.trim())
- if (link != null) {
- // if SimpleX link is pasted, show connection dialogue
- hideKeyboard(view)
- if (link.format is Format.SimplexLink) {
- val linkText = link.format.simplexLinkText
- searchText.value = searchText.value.copy(linkText, selection = TextRange.Zero)
+ when (val target = strConnectTarget(it.trim())) {
+ is ConnectTarget.Link -> {
+ hideKeyboard(view)
+ searchText.value = searchText.value.copy(target.linkText, selection = TextRange.Zero)
+ searchShowingSimplexLink.value = true
+ searchChatFilteredBySimplexLink.value = null
+ connect(
+ link = target.text,
+ searchChatFilteredBySimplexLink = searchChatFilteredBySimplexLink,
+ close = close,
+ cleanup = { searchText.value = TextFieldValue() }
+ )
}
- searchShowingSimplexLink.value = true
- searchChatFilteredBySimplexLink.value = null
- connect(
- link = link.text,
- searchChatFilteredBySimplexLink = searchChatFilteredBySimplexLink,
- close = close,
- cleanup = { searchText.value = TextFieldValue() }
- )
- } else if (!searchShowingSimplexLink.value || it.isEmpty()) {
- if (it.isNotEmpty()) {
- // if some other text is pasted, enter search mode
- focusRequester.requestFocus()
- } else {
- connectProgressManager.cancelConnectProgress()
- if (listState.layoutInfo.totalItemsCount > 0) {
- listState.scrollToItem(0)
+ is ConnectTarget.Name -> showUnsupportedNameAlert(target.nameInfo)
+ null -> if (!searchShowingSimplexLink.value || it.isEmpty()) {
+ if (it.isNotEmpty()) {
+ focusRequester.requestFocus()
+ } else {
+ connectProgressManager.cancelConnectProgress()
+ if (listState.layoutInfo.totalItemsCount > 0) {
+ listState.scrollToItem(0)
+ }
}
+ searchShowingSimplexLink.value = false
+ searchChatFilteredBySimplexLink.value = null
}
- searchShowingSimplexLink.value = false
- searchChatFilteredBySimplexLink.value = null
}
}
}
diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt
index 5b3fd34c22..a7aa1f400b 100644
--- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt
+++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt
@@ -671,13 +671,14 @@ private fun PasteLinkView(rhId: Long?, pastedLink: MutableState, showQRC
val clipboard = LocalClipboardManager.current
SectionItemView({
val str = clipboard.getText()?.text ?: return@SectionItemView
- val link = strHasSingleSimplexLink(str.trim())
- if (link != null) {
- pastedLink.value = link.text
- showQRCodeScanner.value = false
- withBGApi { connect(rhId, link.text, close) { pastedLink.value = "" } }
- } else {
- AlertManager.shared.showAlertMsg(
+ when (val target = strConnectTarget(str.trim())) {
+ is ConnectTarget.Link -> {
+ pastedLink.value = target.text
+ showQRCodeScanner.value = false
+ withBGApi { connect(rhId, target.text, close) { pastedLink.value = "" } }
+ }
+ is ConnectTarget.Name -> showUnsupportedNameAlert(target.nameInfo)
+ null -> AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.invalid_contact_link),
text = generalGetString(MR.strings.the_text_you_pasted_is_not_a_link)
)
@@ -819,12 +820,32 @@ fun strIsSimplexLink(str: String): Boolean {
return parsedMd != null && parsedMd.size == 1 && parsedMd[0].format is Format.SimplexLink
}
-fun strHasSingleSimplexLink(str: String): FormattedText? {
- val parsedMd = parseToMarkdown(str) ?: return null
- val parsedLinks = parsedMd.filter { it.format?.isSimplexLink ?: false }
- if (parsedLinks.size != 1) return null
+sealed class ConnectTarget {
+ class Link(val text: String, val linkType: SimplexLinkType, val linkText: String) : ConnectTarget()
+ class Name(val nameInfo: SimplexNameInfo) : ConnectTarget()
+}
- return parsedLinks[0]
+fun strConnectTarget(str: String): ConnectTarget? {
+ val parsedMd = parseToMarkdown(str) ?: return null
+ 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)
+ }
+ if (links.isEmpty()) {
+ val nameInfo = parsedMd.firstNotNullOfOrNull { (it.format as? Format.SimplexName)?.nameInfo }
+ if (nameInfo != null) return ConnectTarget.Name(nameInfo)
+ }
+ return null
+}
+
+fun showUnsupportedNameAlert(nameInfo: SimplexNameInfo) {
+ val (title, msg) = if (nameInfo.nameType == SimplexNameType.contact) {
+ generalGetString(MR.strings.unsupported_contact_name) to generalGetString(MR.strings.contact_name_requires_newer_app_version)
+ } else {
+ generalGetString(MR.strings.unsupported_channel_name) to generalGetString(MR.strings.channel_name_requires_newer_app_version)
+ }
+ AlertManager.shared.showAlertMsg(title, "$msg ${generalGetString(MR.strings.please_upgrade_the_app)}")
}
@Composable
diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml
index 36744ad503..d5af88c18b 100644
--- a/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml
+++ b/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml
@@ -60,7 +60,7 @@
السماح لجهات اتصالك بالاتصال بك.السماح بردود الفعل على الرسائل.يتم مسح جميع البيانات عند إدخالها.
- سيتم استخدام Android Keystore لتخزين عبارة المرور بشكل آمن بعد إعادة تشغيل التطبيق أو تغيير عبارة المرور - سيسمح بتلقي الإشعارات.
+ سيتم استخدام Android Keystore لتخزين عبارة المرور بشكل آمن بعد إعادة تشغيل التطبيق أو تغيير عبارة المرور - سيسمح بإستلام الإشعارات.السماح لجهات اتصالك بإرسال رسائل تختفي.اسمح بالرسائل الصوتية فقط إذا سمحت جهة اتصالك بذلك.رمز مرور التطبيق
@@ -76,7 +76,7 @@
عن عنوان SimpleXبناء التطبيق: %sالمظهر
- أضف عنوانًا إلى ملف تعريفك، حتى تتمكن جهات اتصالك من مشاركته مع أشخاص آخرين. سيتم إرسال تحديث ملف التعريف إلى جهات اتصالك.
+ أضف عنوانًا إلى ملف تعريفك، حتى تتمكن جهات اتصالك على SimpleX من مشاركته مع أشخاص آخرين. سيتم إرسال تحديث ملف التعريف إلى جهات اتصالك على SimpleX.ستبقى جميع جهات اتصالك متصلة. سيتم إرسال تحديث ملف التعريف إلى جهات اتصالك.رمز التطبيقعنوان
@@ -525,7 +525,7 @@
فوريالمضيفإخفاء
- السماح بذلك في مربع الحوار التالي لتلقي الإشعارات على الفور.]]>
+ السماح بذلك في مربع الحوار التالي لاستلام الإشعارات على الفور.]]>ردًا علىإشعارات فوريةخوادم ICE (واحد لكل سطر)
@@ -728,7 +728,7 @@
إيصالات تسليم الرسائل!دقائقشهور
- - توصيل رسائل أكثر استقرارًا.\n- مجموعات أفضل قليلاً.\n- و اكثر!
+ - تسليم رسائل أكثر استقرارًا.\n- مجموعات أفضل قليلاً.\n- و اكثر!حالة الشبكةكتمردود الفعل الرسائل ممنوعة.
@@ -878,7 +878,7 @@
يرى المُستلمون التحديثات أثناء كتابتها.استلمت، ممنوعحفظ
- سيتم إرسال تحديث ملف التعريف إلى جهات اتصالك.
+ سيتم إرسال تحديث ملف التعريف إلى جهات اتصالك على SimpleX.حفظ وإشعار جهات الاتصالحفظ وتحديث ملف تعريف المجموعةعدد البينج
@@ -971,7 +971,7 @@
تدمير ذاتيمسح الرمزأرسل أسئلة وأفكار
- مشاركة العنوان مع جهات الاتصال؟
+ مشاركة العنوان مع جهات اتصال SimpleX؟شارك العنوانحفظ رسالة الترحيب؟احفظ الخوادم
@@ -1060,7 +1060,7 @@
التوقف عن إرسال الملف؟عنوان SimpleXاستخدم مضيفي .onion إلى "لا" إذا كان وسيط SOCKS لا يدعمها.]]>
- مشاركة مع جهات الاتصال
+ شارك مع جهات اتصال SimpleXإيقاف التشغيل؟إعدادات وسيط SOCKSإيقاف التشغيل
@@ -1306,7 +1306,7 @@
الإيصالات مُعطَّلة%s: %sتضم هذه المجموعة أكثر من %1$d عضو، ولا يتم إرسال إيصالات التسليم.
- التوصيل
+ التسليممُعطَّلتعطيل الإيصالات للمجموعات؟فعّل (الاحتفاظ بتجاوزات المجموعة)
@@ -1323,7 +1323,7 @@
افتح إعدادات التطبيقلا يمكن تشغيل SimpleX في الخلفية. ستستلم الإشعارات فقط عندما يكون التطبيق قيد التشغيل.سيتم مشاركة ملف تعريف عشوائي جديد.
- ألصق الرابط المُستلَم للتواصل مع جهة اتصالك…
+ ألصِق الرابط المُستلَم للتواصل مع جهة اتصالك…ستتم مشاركة ملفك التعريفي %1$s.قد يغلق التطبيق بعد دقيقة واحدة في الخلفية.سماح
@@ -1348,7 +1348,7 @@
افتح مجلد قاعدة البياناتسيتم تخزين عبارة المرور في الإعدادات كنص عادي بعد تغييرها أو إعادة تشغيل التطبيق.عبارة المرور مخزنة في الإعدادات كنص عادي.
- يُرجى الملاحظة: يتم توصيل مُرحلات الرسائل والملفات عبر وسيط SOCKS. تستخدم المكالمات وإرسال معاينات الروابط الاتصال المباشر.]]>
+ يُرجى الملاحظة: يتم تسليم مُرحلات الرسائل والملفات عبر وسيط SOCKS. تستخدم المكالمات الاتصال المباشر.]]>عَمِّ الملفات المحليةعمِّ الملفات والوسائط المخزنةتطبيق سطح المكتب الجديد!
@@ -1843,7 +1843,7 @@
العضو غير نشطرسالة مُحوّلةلا يوجد اتصال مباشر حتى الآن، الرسالة مُحوّلة بواسطة المُدير.
- امسح / ألصِق الرابط
+ ألصِق رابط / امسحخوادم SMP المهيأةخوادم SMP أخرىخوادم XFTP المهيأة
@@ -1936,7 +1936,7 @@
أعِد توصيل كافة الخوادم المتصلة لفرض تسليم الرسالة. يستخدم حركة مرور إضافية.خوادم موّكلةتلقي الأخطاء
- تلقى الإجمالي
+ استلام الإجماليأعِد توصيل جميع الخوادمأعِد توصيل الخوادم؟عنوان الخادم
@@ -2125,7 +2125,7 @@
%s.]]>شروط الاستخدامللتوجيه الخاص
- لتلقي
+ لاستلاماستخدم للملفاتاعرض الشروط%s.]]>
@@ -2159,12 +2159,12 @@
لا يمكن تحميل نص الشروط الحالية، يمكنك مراجعة الشروط عبر هذا الرابط:خطأ في قبول الشروطخطأ في حفظ الخوادم
- على سبيل المثال، إذا تلقى أحد جهات اتصالك رسائل عبر خادم SimpleX Chat، فسيقوم تطبيقك بتسليمها عبر خادم Flux.
+ على سبيل المثال، إذا استلم أحد جهات اتصالك رسائل عبر خادم SimpleX Chat، فسيقوم تطبيقك بتسليمها عبر خادم Flux.لا يوجد خوادم لتوجيه الرسائل الخاصة.لا يوجد خوادم رسائل.
- لا يوجد خوادم لاستقبال الملفات.
+ لا يوجد خوادم لاستلام الملفات.لا توجد رسالة
- لا يوجد خوادم لاستقبال الرسائل.
+ لا يوجد خوادم لاستلام الرسائل.- فتح الدردشة عند أول رسالة غير مقروءة.\n- الانتقال إلى الرسائل المقتبسة.يمكنك تعيين اسم الاتصال، لتذكر الأشخاص الذين تمت مشاركة الرابط معهم.راجع لاحقًا
@@ -2197,7 +2197,7 @@
احذف الدردشةالدردشة موجودة بالفعل!حذف الدردشة؟
- %1$s.]]>
+ %1$s.]]>أو استورد ملف الأرشيفلا توجد خدمة خلفيةالإشعارات والبطارية
@@ -2350,8 +2350,8 @@
لا يمكن قراءة عبارة المرور في Keystore. قد يكون هذا قد حدث بعد تحديث النظام غير متوافق مع التطبيق. إذا لم يكن الأمر كذلك، فيُرجى التواصل مع المطوِّرين.موافقة الانتظارسياسة الخصوصية وشروط الاستخدام.
- لا يمكن الوصول إلى الدردشات الخاصة والمجموعات وجهات اتصالك لمشغلي الخادم.
- باستخدام SimpleX Chat، توافق على:\n- إرسال المحتوى القانوني فقط في المجموعات العامة.\n- احترام المستخدمين الآخرين – لا سبام.
+ يلتزم المشغلون بما يلي:\n- الاستقلالية\n- تقليل استخدام البيانات الوصفية\n- تشغيل برمجيات مفتوحة المصدر وموثقة
+ أنت تلتزم بـ:\n- المحتوى القانوني فقط في المجموعات العامة\n- احترام المستخدمين الآخرين — لا للرسائل المزعجةاقبليتطلب هذا الرابط إصدار تطبيق أحدث. يُرجى ترقية التطبيق أو اطلب من جهة اتصالك إرسال رابط متوافق.رابط كامل
@@ -2564,7 +2564,7 @@
حُدِّث ملف تعريف القناةستُحذف القناة لجميع المشتركين - لا يمكن التراجع عن هذا الإجراء!ستُحذف القناة من عِندك - لا يمكن التراجع عن هذا الإجراء!
- ستبدأ القناة بالعمل مع %1$d من أصل %2$d من المُرحلات. أتود المتابعة؟
+ ستبدأ القناة بالعمل مع %1$d من أصل %2$d مُرحلات. أتود الاستمرار؟مُرحل الدردشةمُرحلات الدردشةمُرحلات الدردشة توجّه الرسائل في القنوات التي تنشئها.
@@ -2654,4 +2654,160 @@
عنوان مُرحلكاسم مُرحلكستتوقف عن تلقي الرسائل من هذه القناة، وسيتم الاحتفاظ بسجل الدردشة.
+ %1$d/%2$d مِن المُرحلات نشطة، و%3$d أخطاء
+ %1$d/%2$d مِن المُرحلات نشطة، وأُزيل %3$d
+ %1$d/%2$d مِن المُرحلات متصلة، وفشل %3$d
+ %1$d/%2$d مِن المُرحلات متصلة، وأُزيل %3$d
+ فشل %1$d مُرحلات
+ %1$d مُرحلات غير نشطة
+ %1$d مُرحلات أُزيلت
+ أضف مُرحلات لاستعادة تسليم الرسائل.
+ رابط اتصال لشخص واحد
+ اسمح للأعضاء بالدردشة مع المُدراء.
+ اسمح بإرسال رسائل مباشرة للمشتركين.
+ اسمح للمشتركين بالدردشة مع المُدراء.
+ فشلت كل المُرحلات
+ أُزيلت كل المُرحلات
+ لأننا دمرنا القدرة على معرفة من أنت. لكي لا تُسلب قوتك أبدًا.
+ كن حُرًا\nفي شبكتك
+ كن حُرًا في شبكتك.
+ الشريط السفلي
+ عنوان العمل التجاري
+ تعذّر الإذاعة
+ القناة لا تحتوي على محطات تقوية نشطة. يُرجى محاولة الانضمام لاحقًا.
+ رابط القناة
+ تفضلات القناة
+ القنوات
+ القناة غير متوفرة مؤقتًا
+ الدردشة مع المُدراء محظورة.
+ الدردشة مع المُدراء في القنوات العامة لا تتوفر فيها ميزة التعمية بين الطرفين (E2E) - لا تستخدمها إلا مع مُرحلات دردشة موثوقة.
+ عُطّل الدردشة مع الأعضاء
+ الدردشة مع المُدراء
+ اتصل عبر رابط أو رمز QR
+ عنوان التواصل
+ أنشئ رابطك
+ أنشئ رابطك العام
+ تُمنع الرسائل المباشرة بين المشتركين.
+ عطّل
+ لا ترسل السجل للمشتركين الجدد.
+ أصبح أسهل أن تدعي أصحابك 👋
+ فعّل
+ فعّل
+ فعّل الدردشة مع المُدراء؟
+ فعّل معاينة الروابط؟
+ أدخل اسم ملف التعريف…
+ خطأ
+ خطأ في مشاركة القناة
+ لكي يتمكن أي شخص من الوصول إليك
+ (مِن المالك)
+ ابدأ
+ رابط المجموعة
+ لا يُرسل السجل للمشتركين الجدد.
+ غير نشط
+ ادعُ شخصٍ ما بشكل خاص
+ اجعل شخصًا ما يتواصل معك
+ سيتم طلب معاينة الرابط عبر وسيط SOCKS. قد لا يزال البحث عن نظام أسماء النطاقات (DNS) يتم محليًا من خلال محلّل DNS الخاص بك.
+ تحققَ من توقيع الرابط.
+ يمكن للأعضاء الدردشة مع المُدراء.
+ ليست مُعمّاة تمامًا بين الطرفين. يمكن لمُرحلات الدردشة رؤية هذه الرسائل.]]>
+ رحّل
+ التزامات الشبكة
+ خطأ في الشبكة
+ لا يمكن لموجّهات الشبكة معرفة مَن يتحدث مع مَن
+ رابط جديد لمرة واحدة
+ لا حساب. لا هاتف. لا بريد إلكتروني. لا هوية. التعمية الأكثر أمانًا.
+ لا مُرحلات نشطة
+ لم يتتبع أحد محادثاتك. ولم يرسم أحد خريطة للأماكن التي زرتها. لم تكن الخصوصية مجرد ميزة، بل كانت أسلوب حياة.
+ تنظيم غير ربحي
+ ليس مجرد قفل أفضل على باب شخص آخر. ولا صاحب عقار ألطف يحترم خصوصيتك، لكنه لا يزال يحتفظ بسجل لجميع الزوار. أنت لست ضيفًا. أنت في بيتك. لا يمكن لأي ملك أن يدخله — فأنت صاحب السيادة.
+ رابط لمرة واحدة
+ يمكن لمالكي القنوات فقط تغيير تفضيلات القناة.
+ على جوّالك، وليس على الخوادم.
+ افتح رابط خارجي؟
+ - الموافقة على إرسال معاينات الروابط.\n- استخدام وسيط SOCKS في حال تفعيله.\n- منع التصيد الاحتيالي عبر الروابط التشعبية.\n- إزالة تتبُع الروابط.
+ أو أظهر رمز QR شخصيًا أو عبر مكالمة فيديو.
+ أو استخدم رمز QR هذا - اطبعه أو اعرضه عبر الإنترنت.
+ الملكية: يمكنك تشغيل المُرحلات الخاصة بك.
+ الخصوصية: للمالكين والمشتركين.
+ مُراسلة خاصة وآمنة.
+ منع الدردشات مع المُدراء.
+ منع إرسال رسائل مباشرة للمشتركين.
+ قنوات عامة - تحدث بحرية 🚀
+ نتائج المُرحل:
+ الموثوقية: عِدّة مُرحلات لكل قناة.
+ أُزيل بواسطة المُشغل
+ روابط ويب آمنة
+ الأمن: المالكون يمتلكون مفاتيح القنوات.
+ قد يؤدي إرسال معاينة للرابط إلى كشف عنوان IP الخاص بك للموقع الإلكتروني. يمكنك تغيير هذا الإعداد لاحقًا من إعدادات الخصوصية.
+ أرسل الرابط عبر أي تطبيق مُراسلة - فهو آمن. واطلب منه لصقه في SimpleX.
+ أرسل ما يصل إلى آخر 100 رسالة للمشتركين الجدد.
+ أعِدّ الإشعارات
+ أعِدّ أجهزة التوجيه
+ شارك القناة…
+ شارك عبر الدردشة
+ ⚠️ فشل التحقق من التوقيع: %s.
+ (موقّع)
+ بلاغات المشترك
+ يمكن للمشتركين إضافة ردود الفعل على الرسائل.
+ يمكن للمشتركين الدردشة مع المُدراء.
+ يمكن للمشتركين حذف الرسائل المُرسلة نهائيًا. (24 ساعة)
+ يمكن للمشتركين الإبلاغ عن الرسائل للمشرفين.
+ يمكن للمشتركين إرسال رسائل مباشرة.
+ يمكن للمشتركين إرسال رسائل تختفي.
+ يمكن للمشتركين إرسال الملفات والوسائط.
+ يمكن للمشتركين إرسال روابط SimpleX.
+ يمكن للمشتركين إرسال رسائل صوتية.
+ تحدث مع شخصٍ ما
+ انقر للفتح
+ وصل الاتصال إلى الحد الأقصى للرسائل غير المُسلَّمة
+ أول شبكة تمتلك\nفيها جهات اتصالك ومجموعاتك.
+ ’ثم انتقلنا إلى الإنترنت، وطلبت كل منصة جزءًا منك؛ اسمك، ورقمك، وأصدقاءك. وقبلنا بأن ثمن التحدث مع الآخرين هو السماح لشخص ما بمعرفة مَن نتحدث إليهم. وكل جيل، سواء من الناس أو التقنية، عاش الأمر على هذا النحو؛ الهاتف، والبريد الإلكتروني، وتطبيقات المراسلة، ووسائل التواصل الاجتماعي. وبدا أن هذه هي الطريقة الوحيدة الممكنة.
+ أقدم حرية إنسانية — وهي التحدث إلى شخص آخر دون مراقبة — مبنية على بنية تحتية لا يمكنها خيانتها.
+ هناك طريقة أخرى. شبكة بلا أرقام هواتف، ولا أسماء مستخدمين، ولا حسابات، ولا هويات مستخدمين من أي نوع. شبكة تربط الناس وتنقل الرسائل المُعمّاة دون معرفة مَن المتصل.
+ لضمان استمرارية شبكة SimpleX.
+ الشريط العلوي
+ يُرسل ما يصل إلى آخر 100 رسالة للمشتركين الجدد.
+ استخدم هذا العنوان في ملف تعريفك على مواقع التواصل الاجتماعي أو موقعك الإلكتروني أو في توقيع بريدك الإلكتروني.
+ في انتظار قيام مالك القناة بإضافة المُرحلات.
+ جعلنا عملية الاتصال أكثر بساطة للمستخدمين الجدد.
+ لماذا بُنيا SimpleX.
+ محادثاتك ملك لك، تمامًا كما كان الحال دائمًا قبل ظهور الإنترنت. الشبكة ليست مكانًا تزوره، بل هي مكان تصنعه وتمتلكه؛ ولا يمكن لأحد أن يسلبه منك، سواء جعلته خاصًا أو عامًا.
+ شبكتك
+ ملف تعريفك
+ عنوانك العام
+ لقد وُلدت دون حساب تعريفي.
+ قناتك الجديدة %1$s متصلة بـ %2$d من أصل %3$d مُرحلات. إذا ألغيت، ستُحذف القناة - يمكنك إنشاؤها مرة أخرى.
+ أضف
+ أضف مُرحل
+ أضف مُرحلات
+ ألغِ واحذف القناة
+ %d مُرحل/ات مُحدّدة
+ خطأ في إضافة المُرحلات
+ لا مُرحلات متاحة
+ لا مُرحلات
+ لا مُرحلات مُحدّدة
+ المُرحلات المُضافة: %1$s.
+ سيُزيل المُرحل من القناة - لا يمكن التراجع عن هذا الإجراء!
+ أُزيل
+ أزِل المُرحل
+ إزالة المُرحل؟
+ حدّد المُرحلات
+ هذا هو آخر مُرحل نشط. إزالته ستمنع تسليم الرسائل للمشتركين.
+ أغلِق التطبيق
+ خطأ في حذف الرسالة
+ من السجل
+ إذا اخترت أغلِق، فلن تُستلم الرسائل.\nيمكنك تغيير ذلك لاحقًا من إعدادات المظهر.
+ أبقِ SimpleX يعمل في الخلفية لاستلام الرسائل.
+ صغّر إلى اللوحة
+ تصغير إلى اللوحة؟
+ صغّر إلى اللوحة عند إغلاق النافذة
+ أنهِ SimpleX
+ أظهر SimpleX
+ SimpleX
+ SimpleX — %d غير مقروءة
+ قد تكون هناك نُسخة أخرى من التطبيق قيد التشغيل أو لم تُغلق بشكل صحيح. أتريد البدء على أي حال؟
+ التطبيق يعمل بالفعل
+ رُفض
+ رُفض بواسطة مُشغل المُرحل
+ الحالة
diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml
index e5d313e9ed..ee79fc0af0 100644
--- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml
+++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml
@@ -194,8 +194,15 @@
Please check that you used the correct link or ask your contact to send you another one.Unsupported connection linkThis link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link.
+ Unsupported channel name
+ Unsupported contact name
+ Connecting via channel name requires a newer app version.
+ Connecting via contact name requires a newer app version.
+ Please upgrade the app.Channel temporarily unavailableChannel has no active relays. Please try to join later.
+ App update required
+ This group requires a newer version of the app. Please update the app to join.Connection error (AUTH)Unless your contact deleted the connection or this link was already used, it might be a bug - please report it.\nTo connect, please ask your contact to create another connection link and check that you have a stable network connection.Connection blocked
diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml
index 3a97c594b1..71c6db7b99 100644
--- a/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml
+++ b/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml
@@ -1537,7 +1537,7 @@
Chyba vytváření zprávyChyba odstranění soukromých poznámekSmazat soukromé poznámky?
- Všechny zprávy budou smazány - nemůže být zvráceno!
+ Všechny zprávy budou smazány - nelze zvrátit!Možnosti vývojářeblokováno %skontakt %1$s změnen na %2$s
@@ -1556,8 +1556,7 @@
PC má nepodporovanou verzi. Ujistěte se, že používáte stejnou verzi na obou zařízeníchPC má chybný kód pozvánkyNeplatné jméno!
- Databáze migrace běží.
-\nMůže to trvat několik minut.
+ Probíhá migrace databáze. \nMůže to trvat několik minut.člen %1$s změněn na %2$sblokovánoBlokováno adminem
@@ -1589,7 +1588,7 @@
%s byl odpojen]]>Chyba otevření prohlížečeodstraněn profilový obrázek
- nastavit novou kontaktní adresu
+ nastavil novou kontaktní adresunastavil nový profilový obrázekUložené zprávyPomalá funkce
@@ -2247,9 +2246,9 @@
NahránoAnoTuto akci nelze zrušit - zprávy odeslané a přijaté v tomto chatu dříve než vybraná, budou smazány.
- Statistiky serverů budou obnoveny - nemůže být vráceno!
+ Statistiky serverů budou obnoveny - nelze vrátit!Odešlete soukromý report
- Pomozte administrátorům moderovat své skupiny.
+ Pomozte správcům moderovat jejich skupiny.Rychlejší mazání skupin.Od %s.Můžete zmínit až %1$s členů ve zprávě!
@@ -2532,7 +2531,7 @@
FiltrObrázkyOdkazy
- Zprávy člena budou smazány - nemůže být zrušeno!
+ Zprávy člena budou smazány - nelze zrušit!bez předplatnéhoOdebrat a smazat zprávyHledat soubory
@@ -2556,4 +2555,219 @@
Nejstarší lidská svoboda - mluvit s druhým člověkem, aniž by byl sledován - postavena na infrastruktuře, která ji nemůže zradit.Protože jsme zničili sílu vědět, kdo jste. Aby vám vaši moc nikdo nemohl vzít.Buďte svobodní ve své síti.
+ %1$d/%2$d relé aktivních
+ %1$d/%2$d relé aktivních, %3$d chyb
+ %1$d/%2$d relé aktivních, %3$d selhalo
+ %1$d/%2$d relé aktivních, %3$d odstraněno
+ %1$d/%2$d relé připojeno
+ %1$d/%2$d relé připojeno, %3$d chyb
+ %1$d/%2$d relé připojeno, %3$d selhalo
+ %1$d/%2$d relé připojeno, %3$d odstraněno
+ %1$d relé selhalo
+ %1$d relé neaktivních
+ %1$d relé odstraněno
+ %1$d odběratel
+ %1$d odběratelů
+ přijaté
+ Přidávání relé bude podporováno později.
+ Odkaz pro připojení jedné osoby
+ Povolit členům chat se správci.
+ Kanál
+ Kanál
+ Celý název kanálu:
+ Kanál nemá aktivní relé.\nProsím, zkuste se připojit později.
+ Odkaz kanálu
+ Odkaz kanálu
+ Členové kanálu
+ Název kanálu
+ Vlastnosti kanálu
+ kanál
+ Profil Kanálu je uložen na zařízeních odběratelů a na chat relé.
+ profil kanálu aktualizován
+ Kanály
+ Kanál dočasně nedostupný
+ Kanál bude smazán pro všechny odběratele - nelze zrušit!
+ Kanál bude pro vás odstraněn - nelze zvrátit!
+ Kanál začne pracovat s %1$d z %2$d relé. Pokračovat?
+ Chat relé
+ Chat relé
+ Chat relé
+ Chat relé
+ Chat relé předávají zprávy v kanálech, které vytvoříte.
+ Chat relé předávají zprávy na kanál odběratelů.
+ Chat se správci zakázán.
+ Chat se správci ve veřejných kanálech nemají šifrování E2E - používejte pouze s důvěryhodnými chat relé.
+ Chat se členy je zakázán
+ Chat se správci
+ Zkontrolujte relé adresu a zkuste to znovu.
+ Zkontrolujte jméno relé a zkuste to znovu.
+ Nastavit relé
+ Připojit
+ připojeno
+ připojuji
+ Připojení přes odkaz nebo QR kód
+ Vytvořit veřejný kanál
+ Vytvořit veřejný kanál
+ Vytvořit veřejný kanál (BETA)
+ Vytvořte odkaz
+ Vytvořte si veřejnou adresu
+ Vytvářím kanál
+ %d událostí kanálu
+ Dekódovací odkaz
+ Smazat kanál
+ Smazat kanál?
+ smazán
+ smazaný kanál
+ Smazat relé
+ Přímé zprávy mezi odběrateli jsou zakázány.
+ Zakázat
+ Neposílat historii novým odběratelům.
+ Snadněji pozvěte své přátele 👋
+ Upravit profil kanálu
+ Povolit
+ Povolit
+ Povolte alespoň jedno chat relé pro vytvoření kanálu.
+ Povolit chat se správci?
+ Povolit náhledy odkazů?
+ Zadejte název profilu…
+ Zadejte jméno relé…
+ Chyba
+ Chyba přidávání relé
+ Chyba vytváření kanálu
+ Chyba otevírání kanálu
+ chyba: %s
+ Chyba ukládání profilu kanálu
+ Chyba sdílení kanálu
+ selhalo
+ selhalo
+ Pro spojení s kýmkoli
+ (od majitele)
+ Získat odkaz
+ Začít
+ Odkaz skupiny
+ Historie není odesílána novým odběratelům.
+ neaktivní
+ Špatná relé adresa!
+ Neplatné jméno relé!
+ pozván
+ Pozvat soukromě
+ Připojit ke kanálu
+ Opustit kanál
+ Opustit kanál?
+ Přidat
+ Přidat relé
+ Přidat relé
+ Povolit odběratelům odesílání přímých zpráv.
+ Povolit odběratelům chat se správci.
+ Všechna relé selhala
+ Všechny relé odebrány
+ Buďte volní\nve vaší síti
+ Blokovat uživatele všem?
+ Spodní lišta
+ Vysílání
+ Test relé pro načtení jeho jména.]]>
+ Obchodní adresa
+ Zrušit a odstranit kanál
+ Zrušit vytvoření kanálu?
+ nemůže vysílat
+ Zavřít aplikaci
+ Adresa kontaktu
+ %d relé vybráno
+ zahozeno (%1$d pokusů)
+ Chyba přidávání relé
+ Chyba odstranění zprávy
+ Z historie
+ Pokud vyberete Zavřít, zprávy nebudou přijímány.\nMůžete to změnit později v nastavení Vzhledu.
+ Nechat SimpleX běžet na pozadí pro přijímání zpráv.
+ Umožněte ostatním se s vámi spojit
+ Odkaz
+ Náhled odkazu bude vyžádán prostřednictvím SOCKS proxy. DNS vyhledávání se stále může uskutečnit lokálně pomocí vašeho DNS resolveru.
+ Podpis odkazu ověřen.
+ Členové mohou chatovat se správci.
+ Chyba zprávy
+ end-to-end nešifrované. Chat relé může vidět tyto zprávy.]]>
+ Přenést
+ Skrýt do oznamovací oblasti
+ Skrýt do oznamovací oblasti?
+ Skrýt do oznamovací oblasti při zavření okna
+ Chyba sítě
+ nové
+ Nový jednorázový odkaz
+ Nové chat relé
+ Žádné aktivní relé
+ Žádné dostupné relé
+ Žádné chat relé
+ Není povoleno žádné relé.
+ Žádné relé
+ Relé nevybráno
+ Ne všechny relé připojeny
+ Jednorázový odkaz
+ Pouze majitelé kanálu mohou měnit nastavení.
+ Na vašem telefonu, ne na serverech.
+ Otevřít kanál
+ Otevřít externí odkaz?
+ Otevřít nový kanál
+ Nebo ukažte QR osobně nebo prostřednictvím videohovoru.
+ Nebo použijte tento QR kód - tisk nebo zobrazit online.
+ MAJITEL
+ Majitelé
+ Vlastnictví: můžete provozovat vlastní relé.
+ Soukromí: pro majitele a odběratele.
+ Soukromé a bezpečné zasílání zpráv.
+ Zakázat chat se správci.
+ Zakázat odesílání přímých zpráv odběratelům.
+ Veřejné kanály - mluvte volně 🚀
+ Opustit SimpleX
+ relé
+ RELÉ
+ Relé adresa
+ Relé adresa
+ Připojení relé selhalo
+ Relé odkaz
+ Relé výsledky:
+ Relé přidáno: %1$s.
+ Relé test selhal!
+ odstraněno
+ odstraněno operátorem
+ Odstranit relé
+ Odstranit relé?
+ Odstranit odběratele
+ Odstranit odběratele?
+ Bezpečné odkazy
+ Uložit a informovat odběratele kanálu
+ Uložit profil kanálu
+ Vybrat relé
+ Varování serveru
+ Nastavit oznamování
+ Nastavit routery
+ Sdílet kanál…
+ Sdílet adresu relé
+ Sdílet pomocí chatu
+ Zobrazit SimpleX
+ ⚠️ Ověření podpisu selhalo: %s.
+ (podepsán)
+ SimpleX
+ SimpleX - %d nepřečteno
+ ODBĚRATEL
+ Hlášení odběratelů
+ Odběratelé
+ Odběratelé mohou přidávat reakce na zprávy.
+ Odběratelé mohou psát správcům.
+ Odběratelé mohou nevratně mazat odeslané zprávy. (24 hodin)
+ Odběratelé mohou nahlásit zprávy moderátorům.
+ Odběratelé mohou posílat přímé zprávy.
+ Odběratelé mohou odesílat mizející zprávy.
+ Odběratelé mohou posílat soubory a média.
+ Odběratelé mohou odesílat SimpleX odkazy.
+ Odběratelé mohou posílat hlasové zprávy.
+ Odběratelé použijí relé odkaz pro připojení ke kanálu.\nRelé adresa byla použita pro nastavení tohoto kanálu.
+ Odběratelé budou odebráni z kanálu - Nelze zvrátit!
+ Promluvte si s někým
+ Klepněte na Přidat kanál
+ Klepněte pro otevření
+ Test selhal v kroku %s.
+ Test relé
+ Aplikace odstranila tuto zprávu po %1$d pokusech o přijetí.
+ Připojení dosáhlo limitu nedoručených zpráv
+ První síť, kde vy vlastníte\nvaše kontakty a skupiny.
diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml
index ebe38b2dc7..c8bb00bfa9 100644
--- a/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml
+++ b/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml
@@ -404,7 +404,7 @@
Onion-Hosts werden nicht verwendet.Für die Verbindung werden Onion-Hosts benötigt.
\nBitte beachten Sie: Ohne .onion-Adresse können Sie keine Verbindung mit den Servern herstellen.
- Erscheinungsbild
+ DarstellungAdresse erstellenAdresse löschen?
@@ -495,14 +495,14 @@
Audio- & VideoanrufeIhre Anrufe
- Immer über ein Relais verbinden
+ Immer über einen Router verbindenAnrufe auf Sperrbildschirm:AkzeptierenAnzeigenDeaktivierenIhre ICE-ServerWebRTC-ICE-Server
- Relais-Server schützen Ihre IP-Adresse, aber sie können die Anrufdauer erfassen.
+ Relais-Server schützen Ihre IP-Adresse, können aber die Anrufdauer erfassen.Relais-Server werden nur genutzt, wenn sie benötigt werden. Ihre IP-Adresse kann von Anderen erfasst werden.Öffnen Sie SimpleX Chat, um den Anruf anzunehmen.
@@ -1437,7 +1437,7 @@
Datenbank-Ordner öffnenDas Passwort wird in Klartext in den Einstellungen gespeichert, nachdem Sie es geändert oder die App neu gestartet haben.Das Passwort wurde in Klartext in den Einstellungen gespeichert.
- Bitte beachten Sie: Die Nachrichten- und Datei-Relais sind per SOCKS-Proxy verbunden. Anrufe nutzen eine direkte Verbindung.]]>
+ Bitte beachten Sie: Die Nachrichten- und Datei-Router sind per SOCKS-Proxy verbunden. Anrufe nutzen eine direkte Verbindung.]]>Lokale Dateien verschlüsselnÖffnenGespeicherte Dateien & Medien verschlüsseln
@@ -1702,7 +1702,7 @@
Link-Details werden heruntergeladenArchiv wird heruntergeladenAnwenden
- Alle Ihre Kontakte, Unterhaltungen und Dateien werden sicher verschlüsselt und in Daten-Paketen auf die konfigurierten XTFP-Relais hochgeladen.
+ Alle Ihre Kontakte, Unterhaltungen und Dateien werden sicher verschlüsselt und in Daten-Paketen auf die konfigurierten XTFP-Router hochgeladen.Archivieren und HochladenWarnung: Das Archiv wird gelöscht.]]>Überprüfen Sie Ihre Internetverbindung und probieren Sie es nochmals
@@ -1840,8 +1840,8 @@
NieUnbekannte ServerUngeschützt
- Sie nutzen privates Routing mit unbekannten Servern.
- Sie nutzen KEIN privates Routing.
+ Bei unbekannten Servern privates Routing nutzen.
+ KEIN privates Routing nutzen.Modus für das Nachrichten-RoutingJaNein
@@ -1849,20 +1849,19 @@
Fallback für das Nachrichten-RoutingNachrichtenstatus anzeigenHerabstufung erlauben
- Sie nutzen immer privates Routing.
+ Immer privates Routing nutzen.Nachrichten werden nicht direkt versendet, selbst wenn Ihr oder der Ziel-Server kein privates Routing unterstützt.Privates Nachrichten-RoutingNachrichten werden direkt versendet, wenn die IP-Adresse geschützt ist, und Ihr oder der Ziel-Server kein privates Routing unterstützt.Nachrichten werden direkt versendet, wenn Ihr oder der Ziel-Server kein privates Routing unterstützt.
- Zum Schutz Ihrer IP-Adresse, wird für die Nachrichten-Auslieferung privates Routing über Ihre konfigurierten SMP-Server genutzt.
- Sie nutzen privates Routing mit unbekannten Servern, wenn Ihre IP-Adresse nicht geschützt ist.
+ Zum Schutz Ihrer IP-Adresse, wird für die Nachrichten-Auslieferung privates Routing über Ihre konfigurierten SMP-Router genutzt.
+ Bei unbekannten Servern privates Routing nutzen, wenn Ihre IP-Adresse nicht geschützt ist.IP-Adresse schützenDateienDie App wird bei unbekannten Datei-Servern nach einer Download-Bestätigung fragen (außer bei .onion oder wenn ein SOCKS-Proxy aktiviert ist).Unbekannte Server!Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für Datei-Server sichtbar sein.
- Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für diese XFTP-Relais sichtbar sein:
-\n%1$s.
+ Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für diese XFTP-Router sichtbar sein: \n%1$s.Profil-DesignSchwarzFarbvariante
@@ -1903,8 +1902,7 @@
Gestalten Sie Ihre Chats unterschiedlich!Neue Chat-DesignsPrivates Nachrichten-Routing 🚀
- Schützen Sie Ihre IP-Adresse vor den Nachrichten-Relais , die Ihr Kontakt ausgewählt hat.
-\nAktivieren Sie es in den *Netzwerk & Server* Einstellungen.
+ Schützen Sie Ihre IP-Adresse vor den Nachrichten-Routern, die Ihre Kontakte ausgewählt haben.\nAktivieren Sie es in den *Netzwerk & Server* Einstellungen.Dateien sicher herunterladenMit reduziertem Akkuverbrauch.Keine Information
@@ -2107,7 +2105,7 @@
ErstellenLaden Sie neue Versionen von GitHub herunter.Direkt aus der Chat-Liste abspielen.
- Kann von Ihnen in den Erscheinungsbild-Einstellungen geändert werden.
+ Sie können dies in den Einstellungen unter „Darstellung“ ändern.Kontakte für spätere Chats archivieren.Ihre IP-Adresse und Verbindungen werden geschützt.Löschen Sie bis zu 20 Nachrichten auf einmal.
@@ -2135,15 +2133,15 @@
Chat-Profil auswählenArchiv entfernen?Ihre Anmeldeinformationen können unverschlüsselt versendet werden.
- Verwenden Sie keine Anmeldeinformationen mit einem Proxy.
+ Keine Anmeldeinformationen mit einem Proxy verwenden.Ihre Verbindung wurde auf %s verschoben, aber während des Profil-Wechsels trat ein Fehler auf.Stellen Sie sicher, dass die Proxy-Konfiguration richtig ist.Fehler beim Speichern des ProxysPasswortProxy-Authentifizierung
- Verwenden Sie für jede Verbindung unterschiedliche Proxy-Anmeldeinformationen.
- Verwenden Sie für jedes Profil unterschiedliche Proxy-Anmeldeinformationen.
- Verwenden Sie zufällige Anmeldeinformationen
+ Für jede Verbindung unterschiedliche Proxy-Anmeldeinformationen verwenden.
+ Für jedes Profil unterschiedliche Proxy-Anmeldeinformationen verwenden.
+ Zufällige Anmeldeinformationen verwendenBenutzername%1$d Datei-Fehler:\n%2$s%1$d Datei(en) wird/werden immer noch heruntergeladen.
@@ -2179,7 +2177,7 @@
Die SimpleX-Protokolle wurden von Trail of Bits überprüft.Während des Anrufs zwischen Audio und Video wechselnDas Chat-Profil für Einmal-Einladungen wechseln
- Jedes Mal wenn Sie die App starten, werden neue SOCKS-Anmeldeinformationen genutzt
+ Bei jedem Neustart der App, werden neue SOCKS-Anmeldeinformationen genutztVerbesserte Sicherheit ✅Verbesserte Nachrichten-DatumsinformationVerbesserte Nutzer-Erfahrung
@@ -2215,7 +2213,7 @@
AktualisierenVoreingestellte ServerNutzungsbedingungen einsehen
- Die Nutzungsbedingungen der aktivierten Betreiber werden automatisch akzeptiert am: %s.
+ Die Nutzungsbedingungen der aktivierten Betreiber werden am %s automatisch akzeptiert.Ihre ServerBetreiber%s Server
@@ -2258,7 +2256,7 @@
nur mit einem Kontakt genutzt werden - teilen Sie ihn nur persönlich oder über einen beliebigen Messenger.]]>%s.]]>%s.]]>
- Die Nutzungsbedingungen wurden akzeptiert am: %s
+ Die Nutzungsbedingungen wurden am %s akzeptiert.%s.]]>%s zu nutzen, müssen Sie dessen Nutzungsbedingungen akzeptieren.]]>Fehler beim Akzeptieren der Nutzungsbedingungen
@@ -2274,7 +2272,7 @@
Zum Schutz vor dem Austausch Ihres Links können Sie die Sicherheitscodes Ihrer Kontakte vergleichen.%s.]]>%s.]]>
- Die Nutzungsbedingungen wurden akzeptiert am: %s.
+ Die Nutzungsbedingungen wurden am %s akzeptiert.Der Text der aktuellen Nutzungsbedingungen konnte nicht geladen werden. Sie können die Nutzungsbedingungen unter diesem Link einsehen:Ferngesteuerte MobiltelefoneOder importieren Sie eine Archiv-Datei
@@ -2380,7 +2378,7 @@
%d MeldungenMitglieder-MeldungenMeldungen
- Inhalt verletzt Nutzungsbedingungen
+ Inhalt verletzt die NutzungsbedingungenSpamVerbindung blockiertDie Datei wird vom Serverbetreiber blockiert:\n%1$s.
@@ -2708,7 +2706,7 @@
Relais-Test fehlgeschlagen!Abonnent entfernenAbonnent entfernen?
- Der Server erfordert eine Autorisierung, um eine Verbindung zum Relais herzustellen. Bitte Passwort überprüfen.
+ Der Server erfordert eine Autorisierung, um eine Verbindung zum Router herzustellen. Bitte Passwort überprüfen.ServerwarnungRelais-Adresse teilenAbonnent
@@ -2757,7 +2755,7 @@
%1$d Relais fehlgeschlagen%1$d Relais nicht aktiv%1$d Relais entfernt
- Das Hinzufügen von Relais wird zu einem späteren Zeitpunkt unterstützt.
+ Relais hinzufügen, um die Nachrichtenübermittlung wiederherzustellen.Alle Relais fehlgeschlagenAlle Relais entferntBroadcast nicht möglich
@@ -2805,11 +2803,11 @@
Oder den QR‑Code persönlich oder per Videoanruf zeigen.Oder diesen QR‑Code verwenden – ausgedruckt oder online.Volle Kontrolle: Sie können Ihre eigenen Relais betreiben.
- Privatsphäre: für Besitzer und Abonnenten.
+ Privatsphäre: Für Eigentümer und Abonnenten.Öffentliche Kanäle – frei sprechen 🚀
- Zuverlässigkeit: mehrere Relais pro Kanal.
+ Zuverlässigkeit: Mehrere Relais pro Kanal.Sichere Web-Links
- Sicherheit: Eigentümer besitzen die Kanalschlüssel.
+ Sicherheit: Nur die Eigentümer des Kanals besitzen die Schlüssel.Den Link über einen beliebigen Messenger versenden – es ist sicher. Bitte in SimpleX einfügen.Mit Jemandem sprechenFür ein dauerhaftes SimpleX-Netzwerk.
@@ -2873,4 +2871,38 @@
Untere LeisteDie Linkvorschau wird über einen SOCKS-Proxy angefordert. DNS-Abfragen können dennoch lokal über Ihren DNS-Resolver erfolgen.Obere Leiste
+ Ihr neuer Kanal %1$s ist mit %2$d von %3$d Relais verbunden.\nBei Abbruch, wird der Kanal gelöscht. Sie können ihn später neu erstellen.
+ Hinzufügen
+ Relais hinzufügen
+ Relais hinzufügen
+ Kanal abbrechen und löschen
+ %d Relais ausgewählt
+ Fehler beim Hinzufügen von Relais
+ Keine verfügbaren Relais
+ Keine Relais
+ Keine Relais ausgewählt
+ %1$s Relais hinzugefügt.
+ Relais wird aus dem Kanal entfernt. Dies kann nicht rückgängig gemacht werden!
+ Entfernt
+ Relais entfernen
+ Relais entfernen?
+ Relais auswählen
+ Dies ist das letzte aktive Relais. Wenn Sie es entfernen, können keine Nachrichten mehr an Abonnenten zugestellt werden.
+ App schließen
+ Wenn Sie \"Schließen\" auswählen, werden keine Nachrichten mehr empfangen.\nSie können dies später in den Einstellungen unter \"Darstellung\" ändern.
+ SimpleX im Hintergrund weiter ausführen, um Nachrichten zu empfangen.
+ In den Infobereich minimieren
+ In den Infobereich minimieren?
+ Beim Schließen des Fensters in den Infobereich minimieren
+ SimpleX beenden
+ SimpleX anzeigen
+ SimpleX
+ SimpleX — %d ungelesen
+ Fehler beim Löschen der Nachricht
+ Aus dem Nachrichtenverlauf
+ App ist bereits gestartet
+ App ist eventuell schon gestartet oder wurde nicht richtig beendet. Trotzdem starten?
+ Abgelehnt
+ Status
+ Vom Relais-Betreiber abgelehnt
diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml
index 6b02074b7d..cdb8a71d7b 100644
--- a/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml
+++ b/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml
@@ -2708,7 +2708,7 @@
%1$d servidores han fallado%1$d servidores inactivos%1$d servidores eliminados
- Añadir servidores estará disponible en una versión posterior.
+ Añadir servidores pare retomar el envío.Enlace para un solo contactoPermitir que los miembros chateen con administradores.Permitir que los suscriptores chateen con administradores.
@@ -2798,4 +2798,33 @@
Menú inferiorLas previsualizaciones de enlaces se solicitan a través del proxy SOCKS. Las peticiónes DNS aún pueden usar el DNS local del sistema.Menú superior
+ Tu nuevo canal %1$s está conectado a %2$d de %3$d servidores.\nSi cancelas, el canal será eliminado. Puedes crearlo de nuevo.
+ Añadir
+ Añadir servidor
+ Añadir servidores
+ Cancelar y eliminar el canal
+ Cerrar aplicación
+ %d servidor(es) seleccionados
+ Error al añaidr servidores
+ Error al eliminar mensaje
+ Del historial
+ Si eliges Cerrar, los mensajes no serán recibidos.\nPuedes cambiarlo más tarde desde el menú Apariencia.
+ Mantener Simplex en segundo plano para recibir mensajes.
+ Minimizar
+ Minimizar?
+ Minimizar al cerrar la ventana
+ Sin servidores disponibles
+ Sin servidores
+ Sin servidores seleccionados
+ Salir de SimpleX
+ Servidores añadidos %1$s.
+ El servidor será eliminado del canal. ¡No puede deshacerse!
+ eliminado
+ Eliminar servidor
+ ¿Eliminar el servidor?
+ Seleccionar servidores
+ Ver SimpleX
+ SimpleX
+ SimpleX — %d no leído
+ Este es el último servidor activo. Si lo eliminas los mensajes no llegarán a los suscriptores.
diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml
index e1730a54aa..b90d79fb3b 100644
--- a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml
+++ b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml
@@ -38,14 +38,14 @@
%s visszavonvaElőre beállított kiszolgálók hozzáadásaA hívások kezdeményezése le van tiltva.
- Az összes partneréhez és csoporttaghoz külön TCP-kapcsolat (és SOCKS-hitelesítési adat) lesz használva.\nMegjegyzés: ha sok kapcsolata van, akkor az akkumulátor-használat és az adatforgalom jelentősen megnövekedhet, és néhány kapcsolódási kísérlet sikertelen lehet.]]>
+ Az összes partneréhez és csoporttaghoz külön TCP-kapcsolat (és SOCKS-hitelesítési adat) lesz használva.\nMegjegyzés: ha sok kapcsolata van, akkor az akkumulátor-használat és az adatforgalom jelentősen megnövekedhet, és néhány kapcsolódási kísérlet sikertelen lehet.]]>hivatkozáselőnézet visszavonásaAz összes csevegési profiljához az alkalmazásban külön TCP-kapcsolat (és SOCKS-hitelesítési adat) lesz használva.]]>Mindkét fél küldhet eltűnő üzeneteket.Az Android Keystore-t a jelmondat biztonságos tárolására használják – lehetővé teszi az értesítési szolgáltatás működését.Hibás az üzenet kivonataHáttér
- Megjegyzés: az üzenet- és a fájlátjátszók SOCKS proxyn keresztül kapcsolódnak. A hívások pedig közvetlen kapcsolatot használnak.]]>
+ Megjegyzés: az üzenet- és a fájlátjátszók SOCKS proxyn keresztül kapcsolódnak. A hívások pedig közvetlen kapcsolatot használnak.]]>Alkalmazásadatok biztonsági mentéseAz adatbázis előkészítése sikertelenAz összes partnerével továbbra is kapcsolatban marad. A profilfrissítés el lesz küldve a partnerei számára.
@@ -91,7 +91,7 @@
Nem lehet meghívni a partnert!hibás az üzenet azonosítójaPartneri kapcsolatkérések automatikus elfogadása
- Megjegyzés: NEM fogja tudni helyreállítani vagy módosítani a jelmondatot abban az esetben, ha elveszíti.]]>
+ Megjegyzés: NEM fogja tudni helyreállítani vagy módosítani a jelmondatot abban az esetben, ha elveszíti.]]>hívás…További másodlagos színHozzáadás egy másik eszközhöz
@@ -114,7 +114,7 @@
Az alkalmazásjelkód helyettesítve lesz egy önmegsemmisítő jelkóddal.Arab, bolgár, finn, héber, thai és ukrán – köszönet a felhasználóknak és a Weblate-nek.Engedélyezi a hangüzeneteket?
- Mindig legyen használva átjátszó
+ Átjátszó használata minden esetbenmindigA hívás már véget ért!Engedélyezés
@@ -168,7 +168,7 @@
hanghívás (végpontok között NEM titkosított)letiltvaMódosítja az adatbázis jelmondatát?
- kapcsolódva
+ kapcsolódottJelkód módosításaa következőre módosította %s szerepkörét: „%s”Fogadási cím módosítása
@@ -182,9 +182,9 @@
KapcsolódáskapcsolódottTársított hordozható eszköz
- kapcsolódva
+ kapcsolódottSzerepkör módosítása
- Kapcsolódva
+ KapcsolódottHitelesítési adat megerősítéseMódosítja a fogadási címet?módosította a címet az Ön számára
@@ -1022,7 +1022,7 @@
Kapott hivatkozás beillesztéseMenti a kiszolgálókat?A SimpleX Chat biztonsága a Trail of Bits által lett auditálva.
- frissítette a csoportprofilt
+ frissítette a csoport profiljátSimpleX Chat támogatásaSimpleX Chat szolgáltatásÖn megfigyelő
@@ -1295,7 +1295,7 @@
Nem sikerült ellenőrizni; próbálja meg újra.Az üzenet az összes tag számára moderáltként lesz megjelölve.Értesítések fogadásához adja meg az adatbázis jelmondatát
- A teszt a(z) %s lépésnél sikertelen volt.
+ A teszt a(z) %s. lépésnél sikertelen volt.Az alkalmazás elindításához vagy 30 másodpercnyi háttérben töltött idő után, az alkalmazáshoz való visszatéréshez hitelesítésre lesz szükség.Az üzenet az összes tag számára törölve lesz.A videó nem dekódolható. Próbálja ki egy másik videóval, vagy lépjen kapcsolatba a fejlesztőkkel.
@@ -1571,8 +1571,8 @@
feloldotta %s letiltásátÖn feloldotta %s letiltásátletiltva
- letiltva az adminisztrátor által
- Letiltva az adminisztrátor által
+ az adminisztrátor letiltotta
+ Az adminisztrátor letiltottaletiltotta őt: %sLetiltásAz összes tag számára letiltja a tagot?
@@ -1649,14 +1649,14 @@
Átköltöztetés ideEszköz átköltöztetéseÁtköltöztetés egy másik eszközre
- Figyelmeztetés: az archívum törölve lesz.]]>
+ Figyelmeztetés: az archívum törölve lesz.]]>Átköltöztetés egy másik eszközrőlKvantumbiztos titkosításMegpróbálhatja még egyszer.Átköltöztetés készÁtköltöztetés egy másik eszközre QR-kód használatával.Átköltöztetés
- Megjegyzés: ha két eszközön is ugyanazt az adatbázist használja, akkor biztonsági védelemként megszakítja a partnereitől érkező üzenetek visszafejtését.]]>
+ Megjegyzés: ha két eszközön is ugyanazt az adatbázist használja, akkor biztonsági védelemként megszakítja a partnereitől érkező üzenetek visszafejtését.]]>Megpróbálhatja még egyszer.Érvénytelen hivatkozásvégpontok közötti kvantumbiztos titkosítás
@@ -1720,11 +1720,11 @@
Profilkép alakzataNégyzet, kör vagy bármi a kettő között.Célkiszolgáló-hiba: %1$s
- Továbbítókiszolgáló: %1$s\nHiba: %2$s
+ Továbbító kiszolgáló: %1$s\nHiba: %2$sHálózati problémák – az üzenet többszöri elküldési kísérlet után lejárt.A kiszolgáló verziója nem kompatibilis a hálózati beállításokkal.Érvénytelen kulcs vagy ismeretlen kapcsolat – valószínűleg ez a kapcsolat törlődött.
- Továbbítókiszolgáló: %1$s\nCélkiszolgáló-hiba: %2$s
+ Továbbító kiszolgáló: %1$s\nCélkiszolgáló-hiba: %2$sHiba: %1$sKapacitás túllépés – a címzett nem kapta meg a korábban elküldött üzeneteket.Üzenetkézbesítési figyelmeztetés
@@ -1738,10 +1738,10 @@
NemNem védettIgen
- NE legyen használva privát útválasztás.
+ Privát útválasztás használatának elkerülése.Privát útválasztásPrivát útválasztás használata az ismeretlen kiszolgálókhoz.
- Mindig legyen használva privát útválasztás.
+ Privát útválasztás használata minden esetben.Üzenet-útválasztási módKözvetlen üzenetküldés, ha az IP-cím védett és a saját kiszolgálója vagy a célkiszolgáló nem támogatja a privát útválasztást.Közvetlen üzenetküldés, ha a saját kiszolgálója vagy a célkiszolgáló nem támogatja a privát útválasztást.
@@ -1874,7 +1874,7 @@
Kiszolgáló-beállítások megnyitásaKiszolgáló címeFeltöltési hibák
- Visszaigazolt
+ VisszaigazolvaVisszaigazolási hibákkísérletekTörölt töredékek
@@ -1926,7 +1926,7 @@
Ezen verzió kihagyásaHa értesítést szeretne kapni az új kiadásokról, kapcsolja be a stabil vagy béta verziók időszakos ellenőrzését.Új verzió érhető el: %s
- A frissítés letöltése megszakítva
+ Frissítésletöltés visszavonvaBétaLetiltásLetiltva
@@ -2194,7 +2194,7 @@
A tagok közötti közvetlen üzenetek le vannak tiltva.Üzleti csevegésekSaját ügyfeleinek adatvédelme.
- %1$s.]]>
+ %1$s.]]>A csevegés már létezik!Csökkentse az üzenet méretét, és küldje el újra.Üzenetek ellenőrzése 10 percenként
@@ -2270,7 +2270,7 @@
Tagok jelentései1 jelentésJelentések
- %s által archivált jelentés
+ %s archiválta a jelentést%d jelentésKéretlen tartalomA tartalom sérti a használati feltételeket
@@ -2350,7 +2350,7 @@
KikapcsolvaElőre beállított kiszolgálókA 443-as TCP-port használata kizárólag az előre beállított kiszolgálókhoz.
- Hiba a tag befogadásakor
+ Hiba történt a tag befogadásakor%d csevegés a tagokkal%d üzenet1 csevegés egy taggal
@@ -2382,7 +2382,7 @@
Ön befogadta ezt a tagotBefogadás tagkéntbefogadta őt: %1$s
- áttekintve a moderátorok által
+ a moderátorok áttekintettéknem lehet üzeneteket küldenipartner letiltvacsoport törölve
@@ -2407,7 +2407,7 @@
Hiba történt a partneri kapcsolatkérés elutasításakorHiba történt a csevegés megnyitásakorHiba történt a csoport megnyitásakor
- Hiba a profil módosításakor
+ Hiba történt a profil módosításakorMegnyitás a csatlakozáshozMegnyitás a kapcsolódáshozMegnyitás az elfogadáshoz
@@ -2496,7 +2496,7 @@
Teljes hivatkozás megnyitásaNyomonkövetési paraméterek eltávolítása a hivatkozásokbólSimpleX-átjátszó címe
- Hiba a csevegés olvasottként való megjelölésekor
+ Hiba történt a csevegés olvasottként való megjelölésekorA célkiszolgáló címében szereplő ujjlenyomat nem egyezik a tanúsítvánnyal: %1$s.A továbbító kiszolgáló címében szereplő ujjlenyomat nem egyezik a tanúsítvánnyal: %1$s.A kiszolgáló címében szereplő ujjlenyomat nem egyezik a tanúsítvánnyal: %1$s.
@@ -2597,7 +2597,7 @@
Ellenőrizze az átjátszó nevét, és próbálja újra.Érvénytelen az átjátszó címe!Ellenőrizze az átjátszó címét, és próbálja újra.
- Hiba az átjátszó hozzáadásakor
+ Hiba történt az átjátszó hozzáadásakorCsevegési átjátszókA csevegési átjátszók továbbítják az üzeneteket az Ön által létrehozott csatornákban.Csevegési átjátszók
@@ -2605,8 +2605,8 @@
A csevegési átjátszók továbbítják az üzeneteket a csatorna feliratkozóinak.%1$d/%2$d átjátszó aktív, %3$d sikertelen%1$d/%2$d átjátszó aktív
- %1$d/%2$d átjátszó kapcsolódva, %3$d hiba
- %1$d/%2$d átjátszó kapcsolódva
+ %1$d/%2$d átjátszó kapcsolódott, %3$d hiba
+ %1$d/%2$d átjátszó kapcsolódottÁtjátszóÁtjátszóhivatkozásÁtjátszó címe
@@ -2616,7 +2616,7 @@
Ön ezen az átjátszóhivatkozáson keresztül kapcsolódott a csatornához.Feliratkozó eltávolításaAz összes feliratkozó számára letiltja a feliratkozót?
- Hiba a csatorna létrehozásakor
+ Hiba történt a csatorna létrehozásakorVisszavonja a csatorna létrehozását?Engedélyezzen legalább egy csevegési átjátszót a csatorna létrehozásához.A(z) %1$s nevű profilja meg lesz osztva a csatorna átjátszóival és feliratkozóival.\nAz átjátszók hozzáférhetnek a csatornaüzenetekhez.
@@ -2627,7 +2627,7 @@
Átjátszó címeEz egy csevegési átjátszó címe, nem használható kapcsolódásra.%1$s nevű csatornához!]]>
- Hiba a csatorna megnyitásakor
+ Hiba történt a csatorna megnyitásakorAz összes feliratkozó számára feloldja a feliratkozó letiltását?Átjátszó tesztelése a nevének lekéréséhez.]]>Csatorna teljes neve:
@@ -2636,11 +2636,11 @@
%d csatornaeseménytörölt csatornahiba: %s
- Hiba a csatornaprofil mentésekor
+ Hiba történt a csatornaprofil mentésekorÜzenethibaMentés és a csatorna feliratkozóinak értesítéseCsatornaprofil mentése
- frissített csatornaprofil
+ frissítette a csatorna profiljátAz alkalmazás %1$d sikertelen letöltési kísérlet után eltávolította ezt az üzenetet.eltávolítva (%1$d kísérlet)A csatorna ideiglenesen nem érhető el
@@ -2658,12 +2658,12 @@
%1$d/%2$d átjátszó aktív, %3$d hiba%1$d/%2$d átjátszó kapcsolódott, %3$d átjátszóhoz nem sikerült kapcsolódni%1$d/%2$d átjátszó kapcsolódott, %3$d eltávolítva
- Az átjátszók hozzáadása később lesz támogatott.
+ Átjátszók hozzáadása az üzenetküldés helyreállításához.Várakozás a csatorna tulajdonosára az átjátszók hozzáadásához.Üzleti címCsatornahivatkozásKapcsolattartási cím
- Hiba a csatorna megosztásakor
+ Hiba történt a csatorna megosztásakor(a tulajdonostól)CsoporthivatkozásHivatkozás aláírása ellenőrizve.
@@ -2692,7 +2692,7 @@
Saját hivatkozás létrehozásaBárki számára, aki el szeretné érni ÖntPartner meghívása privátban
- Hagyja, hogy valaki elérje Önt
+ Legyen elérhető mások számáraVagy mutassa meg a QR-kódot személyesen vagy videóhíváson keresztül.Vagy használja ezt a QR-kódot – nyomtassa ki vagy mutassa meg online.Küldje el a hivatkozást bármilyen üzenetváltó alkalmazáson keresztül – ez egy biztonságos módszer – és kérje meg a partnerét, hogy illessze be a SimpleX alkalmazásba.
@@ -2702,7 +2702,7 @@
Nonprofit irányítás- Hivatkozások előnézetének küldése.\n- SOCKS proxy használata, ha engedélyezve van.\n- Hiperhivatkozásokon keresztüli adathalászat megakadályozása.\n- Hivatkozások nyomonkövetési paramétereinek eltávolítása.Tulajdonjog: saját átjátszókat üzemeltethet.
- Adatvédelem: tulajdonosok és előfizetők számára.
+ Adatvédelem: tulajdonosok és feliratkozók számára.Nyilvános csatornák – mondja el szabadon a véleményét 🚀Megbízhatóság: több átjátszó is használható csatornánként.Biztonságos webhivatkozások
@@ -2711,13 +2711,13 @@
Az új felhasználók számára egyszerűbbé tettük a kapcsolatok létrehozását.Fiók nélkül születtünk.Senki sem követte nyomon a beszélgetéseinket. Senki sem készített térképet arról, hogy merre jártunk. A magánéletünk nem csak egy funkció volt, hanem az életmódunk.
- Aztán felléptünk az internetre, és minden platform kért belőlünk egy darabot - nevet, telefonszámot, baráti kapcsolatokat. Elfogadtuk, hogy a kommunikáció ára az, hogy mások megtudják, hogy kivel beszélünk. Minden generáció, az emberek és a technológia is eddig így működött - telefon, e-mail, üzenetküldő programok, közösségi média. Úgy tűnt, ez az egyetlen lehetséges mód.
+ Aztán felléptünk az internetre, és minden platform kért belőlünk egy darabot– nevet, telefonszámot, baráti kapcsolatokat. Elfogadtuk, hogy a kommunikáció ára az, hogy mások megtudják, hogy kivel beszélünk. Minden generáció, az emberek és a technológia is eddig így működött – telefon, e-mail, üzenetküldő programok, közösségi média. Úgy tűnt, ez az egyetlen lehetséges mód.De van egy másik lehetőség is. Egy hálózat, amelyben nincsenek telefonszámok. Nincsenek felhasználónevek. Nincsenek fiókok. Nincsenek semmiféle felhasználói azonosítók. Egy hálózat, amely összeköti az embereket és titkosított üzeneteket továbbít, anélkül, hogy tudná, ki csatlakozik hozzá.
- Nem egy jobb zár mások ajtaján. Nem egy kedvesebb házmester, aki tiszteletben tartja az Ön magánéletét, de mégis nyilvántartást vezet minden látogatójáról. Ön itt nem csak egy vendég. Ön itt otthon van. Nincs az a hatalom, amely beléphetne ide - Ön itt szuverén.
+ Nem egy jobb zár mások ajtaján. Nem egy kedvesebb házmester, aki tiszteletben tartja az Ön magánéletét, de mégis nyilvántartást vezet minden látogatójáról. Ön itt nem csak egy vendég. Ön itt otthon van. Nincs az a hatalom, amely beléphetne ide – Ön itt szuverén.A beszélgetései Önhöz tartoznak, ahogy az internet megjelenése előtt is mindig így volt. A hálózat nem egy hely, amelyet meglátogat. Ez egy olyan hely, amelyet Ön hoz létre saját magának. És senki sem veheti el Öntől, függetlenül attól, hogy privát vagy nyilvános.
- A legrégebbi emberi szabadság - beszélgetni az emberekkel, anélkül, hogy mások megfigyelnének - olyan infrastruktúrán alapul, amely nem tudja elárulni.
+ A legrégebbi emberi szabadság – beszélgetni az emberekkel, anélkül, hogy mások megfigyelnének – olyan infrastruktúrán alapul, amely nem tudja elárulni.Mert felszámoltuk a lehetőségét is annak, hogy megtudjuk, Ön kicsoda. Így az önrendelkezése soha nem kerülhet idegen kezekbe.
- Legyen szabad a saját hálózatában.
+ Váljon szabaddá a saját hálózatában.Feliratkozók jelentéseiA közvetlen üzenetek küldése a feliratkozók között engedélyezve van.
@@ -2737,7 +2737,7 @@
Az előzmények nem lesznek elküldve az új feliratkozók számára.A csevegés az adminisztrátorokkal engedélyezve van a tagok számára.A csevegés az adminisztrátorokkal engedélyezve van a feliratkozók számára.
- Váljon szabaddá\na saját hálózatában.
+ Váljon szabaddá\na saját hálózatábanA csevegés az adminisztrátorokkal le van tiltva.A nyilvános csatornákban az adminisztrátorokkal való csevegések nem rendelkeznek végpontok közötti titkosítással – csak megbízható csevegési átjátszókkal használja őket.A csevegés a tagokkal le van tiltva
@@ -2758,12 +2758,46 @@
A csevegés az adminisztrátorokkal le van tiltva.Értesítések beállításaÚtválasztók beállítása
- A feliratkozók cseveghetnek az adminisztrátorokkal
+ A feliratkozók cseveghetnek az adminisztrátorokkal.Miért jött létre a SimpleX?Saját hálózat
- Profil létrehozása
+ Saját profil létrehozásaAz első hálózat, ahol Ön birtokolja\na saját kapcsolatait és csoportjait.Alsó sávA hivatkozások előnézetét SOCKS proxyn keresztül kéri le a kliens. A DNS-lekérdezés viszont továbbra is történhet helyi szinten, a saját DNS-kiszolgálón keresztül.Felső sáv
+ Az új %1$s nevű csatornája %3$d átjátszóból %2$d átjátszóhoz kapcsolódik.\nHa visszavonja, akkor a csatorna törlődni fog – de később újra létrehozhatja.
+ Visszavonás és a csatorna törlése
+ Hozzáadás
+ Átjátszó hozzáadása
+ Átjátszók hozzáadása
+ %d átjátszó kiválasztva
+ Hiba történt az átjátszók hozzáadásakor
+ Nincsenek elérhető átjátszók
+ Nincsenek átjátszók
+ Nincsenek átjátszók kiválasztva
+ Átjátszók hozzáadva: %1$s.
+ Az átjátszó el lesz távolítva a csatornából – ez a művelet nem vonható vissza!
+ eltávolítva
+ Átjátszó eltávolítása
+ Eltávolítja az átjátszót?
+ Átjátszók kiválasztása
+ Ez az utolsó aktív átjátszó. Ha eltávolítja, akkor azzal megakadályozza az üzenetek eljuttatását a feliratkozóknak.
+ Alkalmazás bezárása
+ Ha a bezárás mellett dönt, az üzenetek nem fognak megérkezni.\nEzt később a „Megjelenés” beállításaiban módosíthatja.
+ Hagyja a SimpleX-et a háttérben futni az üzenetek fogadásához.
+ Kilépés a SimpleXből
+ SimpleX megjelenítése
+ SimpleX
+ SimpleX – %d olvasatlan üzenet
+ Kicsinyítés az értesítési területre
+ Biztosan kicsinyíteni szeretné az értesítési területre?
+ Kicsinyítés az értesítési területre az ablak bezárásakor
+ Hiba történt az üzenet törlésekor
+ Az előzményekből
+ Állapot
+ elutasítva
+ az átjátszó üzemeltetője elutasította
+ Az alkalmazás már fut
+ Lehet, hogy egy másik alkalmazáspéldány fut, vagy nem zárult be megfelelően. Így is elindítja?
diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml
index 9db5b3a58f..c3f3461c48 100644
--- a/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml
+++ b/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml
@@ -2448,7 +2448,7 @@
Errore nel rifiuto della richiesta di contattoEntra nel gruppoApri la chat
- Apri una chat nuova
+ Apri la nuova chatApri il nuovo gruppoApri per accettareApri per connettere
@@ -2578,7 +2578,7 @@
Nome del canaleIl canale verrà eliminato per tutti gli iscritti, non è reversibile!Il canale verrà eliminato per te, non è reversibile!
- Il canale sarà operativo con %1$d di %2$d relay. Procedere?
+ Il canale sarà operativo con %1$d di %2$d relay. Continuare?Relay di chatRelay di chatRelay di chat
@@ -2619,7 +2619,7 @@
Nessun relay di chat attivato.Non tutti i relay sono connessiApri canale
- Apri un canale nuovo
+ Apri il nuovo canaleProprietarioProprietariIndirizzo relay preimpostato
@@ -2686,7 +2686,7 @@
%1$d relay falliti%1$d relay non attivi%1$d relay rimossi
- L\'aggiunta di relay verrà supportata prossimamente.
+ Aggiungi relay per ripristinare la consegna dei messaggi.Tutti i relay fallitiTutti i relay rimossiimpossibile trasmettere
@@ -2802,4 +2802,38 @@
Barra inferioreL\'anteprima del link verrà richiesta via proxy SOCKS. La ricerca DNS può ancora accadere localmente tramite il tuo risolutore DNS.Barra superiore
+ Il tuo nuovo canale %1$s è connesso a %2$d di %3$d relay.\nSe annulli, il canale verrà eliminato. Potrai crearlo di nuovo.
+ Aggiungi
+ Aggiungi relay
+ Aggiungi relay
+ Annulla ed elimina il canale
+ %d relay selezionato/i
+ Errore di aggiunta dei relay
+ Nessun relay disponibile
+ Nessun relay
+ Nessun relay selezionato
+ Relay aggiunti: %1$s.
+ Il relay verrà rimosso dal canale, non è reversibile!
+ rimosso
+ Rimuovi relay
+ Rimuovere il relay?
+ Seleziona i relay
+ Questo è l\'ultimo relay attivo. La sua rimozione impedirà la consegna dei messaggi agli iscritti.
+ Chiudi l\'app
+ Errore di eliminazione del messaggio
+ Dalla cronologia
+ Se scegli Chiudi, i messaggi non verranno ricevuti.\nPuoi cambiarlo più tardi nelle impostazioni di Aspetto.
+ Tieni SimpleX attivo in secondo piano per ricevere i messaggi.
+ Riduci nell\'area delle notifiche
+ Ridurre nell\'area delle notifiche?
+ Riduci nell\'area delle notifiche alla chiusura della finestra
+ Esci da SimpleX
+ Mostra SimpleX
+ SimpleX
+ SimpleX — %d non letto/i
+ Un\'altra istanza dell\'app potrebbe essere in esecuzione o non si è chiusa correttamente. Avviare comunque?
+ L\'app è già in esecuzione
+ rifiutato
+ rifiutato dall\'operatore del relay
+ Stato
diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml
index 18f9118d3d..5804679dbd 100644
--- a/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml
+++ b/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml
@@ -2207,7 +2207,7 @@
Посмотреть условия%s.]]>Условия будут автоматически приняты для включенных операторов: %s.
- Условия приняты: %s.
+ Условия приняты: %sВебсайт%s.]]>%s.]]>
@@ -2799,7 +2799,7 @@
Приложение удалило это сообщение после %1$d попыток его получить.Если Вы присоединились к каналам или создали их, они перестанут работать навсегда.Вы перестанете получать сообщения из этого канала. История чата сохранится.
- обновлён профиль канала
+ обновил профиль каналаошибкаОшибка соединенияЧат с админами
@@ -2858,7 +2858,7 @@
ошибкановыйВсе релеи недоступны
- Добавление релеев будет поддерживаться позже.
+ Добавить релеи чтобы восстановить доставку сообщений.Ожидает, когда владелец канала добавит релеи.через %1$sПодписчики используют ссылку релея для подключения к каналу.\nАдрес релея был использован для настройки этого релея для канала.
@@ -2874,4 +2874,9 @@
Нижнее менюКартинка ссылки будет загружена через SOCKS-прокси. DNS-запрос может быть локальным через Ваш резолвер.Верхнее меню
+ Добавить
+ Добавить релей
+ Добавить релеи
+ Отменить и удалить канал
+ Закрыть приложение
diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml
index ff69251bc6..3b767b97b4 100644
--- a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml
+++ b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml
@@ -2670,7 +2670,7 @@
%1$d 个中继失灵%1$d 个中继不活跃删除了 %1$d 个中继
- 目前不支持添加中继。
+ 添加恢复消息传输的中继。所有中继均失灵删除了所有中继无法广播
@@ -2785,4 +2785,38 @@
底部栏将通过 SOCKS5 代理请求链接预览。DNS 查询仍可能通过你的 DNS 解析器在本地发生。顶部栏
+ 你的新频道 %1$s 已连接到 %3$d 个中继中的 %2$d 个中继。\n如果取消,频道将被删除 —— 你可以再次创建它。
+ 这是上次活跃的中继。删除它会阻止给订阅者传送消息。
+ 添加
+ 添加中继
+ 添加中继
+ 取消并删除频道
+ 选中了 %d 个中继
+ 添加中继出错
+ 无可用中继
+ 无中继
+ 未选中中继
+ 已添加的中继:%1$s。
+ 将从频道删除中继 — 这无法撤销!
+ 已删除
+ 删除中继
+ 删除中继?
+ 选择中继
+ 如果选择关闭将不会接收消息。\n可以之后在外观设置中更改。
+ 保持 SimpleX 在后台运行以接收消息。
+ 最小化到托盘
+ 最小化到托盘?
+ 关闭窗口时最小化到托盘
+ 退出 SimpleX
+ 显示 SimpleX
+ SimpleX
+ SimpleX — %d 则未读
+ 关闭应用
+ 删除消息出错
+ 来自历史记录
+ 另一个应用实例可能正在运行或没有正确退出。仍要启动?
+ 应用正在运行
+ 被拒绝
+ 被中继运营方拒绝
+ 状态
diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Platform.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Platform.desktop.kt
index 97de08b07e..7ea41d3593 100644
--- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Platform.desktop.kt
+++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Platform.desktop.kt
@@ -10,7 +10,7 @@ val desktopPlatform = detectDesktopPlatform()
enum class DesktopPlatform(val libExtension: String, val configPath: String, val dataPath: String, val githubAssetName: String) {
LINUX_X86_64("so", unixConfigPath, unixDataPath, "simplex-desktop-x86_64.AppImage"),
- LINUX_AARCH64("so", unixConfigPath, unixDataPath, " simplex-desktop-aarch64.AppImage"),
+ LINUX_AARCH64("so", unixConfigPath, unixDataPath, "simplex-desktop-aarch64.AppImage"),
WINDOWS_X86_64("dll", System.getenv("AppData") + File.separator + "SimpleX", System.getenv("AppData") + File.separator + "SimpleX", "simplex-desktop-windows-x86_64.msi"),
MAC_X86_64("dylib", unixConfigPath, unixDataPath, "simplex-desktop-macos-x86_64.dmg"),
MAC_AARCH64("dylib", unixConfigPath, unixDataPath, "simplex-desktop-macos-aarch64.dmg");
diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/VideoPlayer.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/VideoPlayer.desktop.kt
index 90c80d3b2a..c3b6dc3a4c 100644
--- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/VideoPlayer.desktop.kt
+++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/VideoPlayer.desktop.kt
@@ -6,6 +6,7 @@ import androidx.compose.ui.graphics.*
import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR
import kotlinx.coroutines.*
+import org.jetbrains.compose.videoplayer.SkiaBitmapVideoSurface
import uk.co.caprica.vlcj.media.VideoOrientation
import uk.co.caprica.vlcj.player.base.*
import uk.co.caprica.vlcj.player.component.CallbackMediaPlayerComponent
@@ -214,7 +215,7 @@ actual class VideoPlayer actual constructor(
}
}
- suspend fun getBitmapFromVideo(defaultPreview: ImageBitmap?, uri: URI?, withAlertOnException: Boolean = true): VideoPlayerInterface.PreviewAndDuration = withContext(playerThread.asCoroutineDispatcher()) {
+ suspend fun getBitmapFromVideo(defaultPreview: ImageBitmap?, uri: URI?, withAlertOnException: Boolean = true): VideoPlayerInterface.PreviewAndDuration = withContext(previewThread.asCoroutineDispatcher()) {
val mediaComponent = getOrCreateHelperPlayer()
val player = mediaComponent.mediaPlayer()
if (uri == null || !uri.toFile().exists()) {
@@ -222,12 +223,12 @@ actual class VideoPlayer actual constructor(
return@withContext VideoPlayerInterface.PreviewAndDuration(preview = defaultPreview, timestamp = 0L, duration = 0L)
}
+ val surface = SkiaBitmapVideoSurface()
+ player.videoSurface().set(surface)
player.media().startPaused(uri.toFile().absolutePath)
- val start = System.currentTimeMillis()
- var snap: BufferedImage? = null
- while (snap == null && start + 1500 > System.currentTimeMillis()) {
- snap = player.snapshots()?.get()
- delay(50)
+ val snap = withTimeoutOrNull(1500L) {
+ while (surface.bitmap.value == null) delay(50)
+ surface.bitmap.value!!.toAwtImage()
}
val orientation = player.media().info().videoTracks().firstOrNull()?.orientation()
if (orientation == null) {
@@ -255,6 +256,7 @@ actual class VideoPlayer actual constructor(
}
val playerThread = Executors.newSingleThreadExecutor()
+ private val previewThread = Executors.newSingleThreadExecutor()
private val playersPool: ArrayList = ArrayList()
private val helperPlayersPool: ArrayList = ArrayList()
diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/AppUpdater.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/AppUpdater.kt
index 974578882d..f6a6023d47 100644
--- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/AppUpdater.kt
+++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/AppUpdater.kt
@@ -26,6 +26,8 @@ import java.io.Closeable
import java.io.File
import java.net.InetSocketAddress
import java.net.Proxy
+import java.nio.file.Files
+import java.nio.file.StandardCopyOption
import kotlin.math.min
data class SemVer(
@@ -376,7 +378,7 @@ private fun chooseGitHubReleaseAssets(release: GitHubRelease): List
val res = if (isRunningFromFlatpak()) {
// No need to show download options for Flatpak users
emptyList()
- } else if (!isRunningFromAppImage() && Runtime.getRuntime().exec("which dpkg").onExit().join().exitValue() == 0) {
+ } else if (desktopPlatform.isLinux() && !isRunningFromAppImage() && Runtime.getRuntime().exec("which dpkg").onExit().join().exitValue() == 0) {
// Show all available .deb packages and user will choose the one that works on his system (for Debian derivatives)
release.assets.filter { it.name.lowercase().endsWith(".deb") }
} else {
@@ -388,18 +390,42 @@ private fun chooseGitHubReleaseAssets(release: GitHubRelease): List
private suspend fun installAppUpdate(file: File) = withContext(Dispatchers.IO) {
when {
desktopPlatform.isLinux() -> {
- val process = Runtime.getRuntime().exec("xdg-open ${file.absolutePath}").onExit().join()
- val startedInstallation = process.exitValue() == 0 && process.children().count() > 0
- if (!startedInstallation) {
- Log.e(TAG, "Error starting installation: ${process.inputReader().use { it.readLines().joinToString("\n") }}${process.errorStream.use { String(it.readAllBytes()) }}")
- // Failed to start installation. show directory with the file for manual installation
- desktopOpenDir(file.parentFile)
+ val appImagePath = System.getenv("APPIMAGE")
+ if (appImagePath != null) {
+ // Replace the running AppImage crash-safely: copy onto the target's own
+ // filesystem first (an atomic rename only works within one filesystem, and
+ // the download lives in the temp dir which is usually a different one),
+ // then atomically move the staged file onto $APPIMAGE.
+ val target = File(appImagePath)
+ val staging = File(target.parentFile, ".${target.name}.update")
+ try {
+ Files.copy(file.toPath(), staging.toPath(), StandardCopyOption.REPLACE_EXISTING)
+ staging.setExecutable(true, false)
+ Files.move(staging.toPath(), target.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING)
+ file.delete()
+ AlertManager.shared.showAlertMsg(
+ title = generalGetString(MR.strings.app_check_for_updates_installed_successfully_title),
+ text = generalGetString(MR.strings.app_check_for_updates_installed_successfully_desc)
+ )
+ } catch (e: Exception) {
+ Log.e(TAG, "Failed to replace AppImage: ${e.stackTraceToString()}")
+ staging.delete()
+ desktopOpenDir(file.parentFile)
+ }
} else {
- AlertManager.shared.showAlertMsg(
- title = generalGetString(MR.strings.app_check_for_updates_installed_successfully_title),
- text = generalGetString(MR.strings.app_check_for_updates_installed_successfully_desc)
- )
- file.delete()
+ val process = Runtime.getRuntime().exec("xdg-open ${file.absolutePath}").onExit().join()
+ val startedInstallation = process.exitValue() == 0 && process.children().count() > 0
+ if (!startedInstallation) {
+ Log.e(TAG, "Error starting installation: ${process.inputReader().use { it.readLines().joinToString("\n") }}${process.errorStream.use { String(it.readAllBytes()) }}")
+ // Failed to start installation. show directory with the file for manual installation
+ desktopOpenDir(file.parentFile)
+ } else {
+ AlertManager.shared.showAlertMsg(
+ title = generalGetString(MR.strings.app_check_for_updates_installed_successfully_title),
+ text = generalGetString(MR.strings.app_check_for_updates_installed_successfully_desc)
+ )
+ file.delete()
+ }
}
}
desktopPlatform.isWindows() -> {
diff --git a/apps/multiplatform/gradle.properties b/apps/multiplatform/gradle.properties
index 4d504e069e..3d4bf66913 100644
--- a/apps/multiplatform/gradle.properties
+++ b/apps/multiplatform/gradle.properties
@@ -24,13 +24,13 @@ android.nonTransitiveRClass=true
kotlin.mpp.androidSourceSetLayoutVersion=2
kotlin.jvm.target=11
-android.version_name=6.5.2
-android.version_code=349
+android.version_name=6.5.3
+android.version_code=351
android.bundle=false
-desktop.version_name=6.5.2
-desktop.version_code=143
+desktop.version_name=6.5.3
+desktop.version_code=144
kotlin.version=2.1.20
gradle.plugin.version=8.7.0
diff --git a/apps/simplex-directory-service/src/Directory/Service.hs b/apps/simplex-directory-service/src/Directory/Service.hs
index 6e414ef011..577cc99752 100644
--- a/apps/simplex-directory-service/src/Directory/Service.hs
+++ b/apps/simplex-directory-service/src/Directory/Service.hs
@@ -970,6 +970,7 @@ directoryServiceEvent st opts@DirectoryOpts {adminUsers, superUsers, serviceName
GLPConnectingProhibit _ -> sendMessage cc ct $ "Already connecting to this " <> gt <> "."
GLPConnectingConfirmReconnect -> sendMessage cc ct $ "Already connecting to this " <> gt <> "."
GLPNoRelays _ -> sendMessage cc ct $ T.toTitle gt <> " has no active relays. Please try again later."
+ GLPUpdateRequired _ -> sendMessage cc ct $ T.toTitle gt <> " requires a newer version."
GLPOwnLink _ -> sendMessage cc ct "Unexpected error. Please report it to directory admins."
_ -> sendMessage cc ct "Unexpected error. Please report it to directory admins."
diff --git a/bots/api/TYPES.md b/bots/api/TYPES.md
index d3fa4aeb47..d648de8e36 100644
--- a/bots/api/TYPES.md
+++ b/bots/api/TYPES.md
@@ -146,6 +146,7 @@ This file is generated automatically.
- [Profile](#profile)
- [ProxyClientError](#proxyclienterror)
- [ProxyError](#proxyerror)
+- [PublicGroupAccess](#publicgroupaccess)
- [PublicGroupData](#publicgroupdata)
- [PublicGroupProfile](#publicgroupprofile)
- [RCErrorType](#rcerrortype)
@@ -157,6 +158,7 @@ This file is generated automatically.
- [RcvFileTransfer](#rcvfiletransfer)
- [RcvGroupEvent](#rcvgroupevent)
- [RcvMsgError](#rcvmsgerror)
+- [RelayCapabilities](#relaycapabilities)
- [RelayProfile](#relayprofile)
- [RelayStatus](#relaystatus)
- [ReportReason](#reportreason)
@@ -165,6 +167,10 @@ This file is generated automatically.
- [SecurityCode](#securitycode)
- [SimplePreference](#simplepreference)
- [SimplexLinkType](#simplexlinktype)
+- [SimplexNameDomain](#simplexnamedomain)
+- [SimplexNameInfo](#simplexnameinfo)
+- [SimplexNameType](#simplexnametype)
+- [SimplexTLD](#simplextld)
- [SndCIStatusProgress](#sndcistatusprogress)
- [SndConnEvent](#sndconnevent)
- [SndError](#snderror)
@@ -2088,6 +2094,10 @@ SimplexLink:
- simplexUri: string
- smpHosts: [string]
+SimplexName:
+- type: "simplexName"
+- nameInfo: [SimplexNameInfo](#simplexnameinfo)
+
Command:
- type: "command"
- commandStr: string
@@ -2329,6 +2339,10 @@ NoRelays:
- type: "noRelays"
- groupSLinkData_: [GroupShortLinkData](#groupshortlinkdata)?
+UpdateRequired:
+- type: "updateRequired"
+- groupSLinkData_: [GroupShortLinkData](#groupshortlinkdata)?
+
---
@@ -2485,6 +2499,7 @@ NoRelays:
- userChatRelay: [UserChatRelay](#userchatrelay)
- relayStatus: [RelayStatus](#relaystatus)
- relayLink: string?
+- relayCap: [RelayCapabilities](#relaycapabilities)
---
@@ -3055,6 +3070,17 @@ NO_SESSION:
- type: "NO_SESSION"
+---
+
+## PublicGroupAccess
+
+**Record type**:
+- groupWebPage: string?
+- groupDomain: string?
+- domainWebPage: bool
+- allowEmbedding: bool
+
+
---
## PublicGroupData
@@ -3071,6 +3097,7 @@ NO_SESSION:
- groupType: [GroupType](#grouptype)
- groupLink: string
- publicGroupId: string
+- publicGroupAccess: [PublicGroupAccess](#publicgroupaccess)?
---
@@ -3328,6 +3355,14 @@ ParseError:
- parseError: string
+---
+
+## RelayCapabilities
+
+**Record type**:
+- webDomain: string?
+
+
---
## RelayProfile
@@ -3435,6 +3470,44 @@ A_QUEUE:
- "relay"
+---
+
+## SimplexNameDomain
+
+**Record type**:
+- nameTLD: [SimplexTLD](#simplextld)
+- domain: string
+- subDomain: [string]
+
+
+---
+
+## SimplexNameInfo
+
+**Record type**:
+- nameType: [SimplexNameType](#simplexnametype)
+- nameDomain: [SimplexNameDomain](#simplexnamedomain)
+
+
+---
+
+## SimplexNameType
+
+**Enum type**:
+- "publicGroup"
+- "contact"
+
+
+---
+
+## SimplexTLD
+
+**Enum type**:
+- "simplex"
+- "testing"
+- "web"
+
+
---
## SndCIStatusProgress
diff --git a/bots/src/API/Docs/Types.hs b/bots/src/API/Docs/Types.hs
index be4a55835a..8397503bbe 100644
--- a/bots/src/API/Docs/Types.hs
+++ b/bots/src/API/Docs/Types.hs
@@ -327,6 +327,7 @@ chatTypesDocsData =
(sti @Profile, STRecord, "", [], "", ""),
(sti @ProxyClientError, STUnion, "Proxy", [], "", ""),
(sti @ProxyError, STUnion, "", [], "", ""),
+ (sti @PublicGroupAccess, STRecord, "", [], "", ""),
(sti @PublicGroupData, STRecord, "", [], "", ""),
(sti @PublicGroupProfile, STRecord, "", [], "", ""),
(sti @RatchetSyncState, STEnum, "RS", [], "", ""),
@@ -338,6 +339,7 @@ chatTypesDocsData =
(sti @RcvFileTransfer, STRecord, "", [], "", ""),
(sti @RcvGroupEvent, STUnion, "RGE", [], "", ""),
(sti @RcvMsgError, STUnion, "RME", [], "", ""),
+ (sti @RelayCapabilities, STRecord, "", [], "", ""),
(sti @RelayProfile, STRecord, "", [], "", ""),
(sti @RelayStatus, STEnum, "RS", [], "", ""),
(sti @ReportReason, STEnum' (dropPfxSfx "RR" ""), "", ["RRUnknown"], "", ""),
@@ -345,6 +347,10 @@ chatTypesDocsData =
(sti @SecurityCode, STRecord, "", [], "", ""),
(sti @SimplePreference, STRecord, "", [], "", ""),
(sti @SimplexLinkType, STEnum, "XL", [], "", ""),
+ (sti @SimplexNameDomain, STRecord, "", [], "", ""),
+ (sti @SimplexNameInfo, STRecord, "", [], "", ""),
+ (sti @SimplexNameType, STEnum, "NT", [], "", ""),
+ (sti @SimplexTLD, STEnum, "TLD", [], "", ""),
(sti @SMPAgentError, STUnion, "", [], "", ""),
(sti @SndCIStatusProgress, STEnum, "SSP", [], "", ""),
(sti @SndConnEvent, STUnion, "SCE", [], "", ""),
@@ -542,6 +548,7 @@ deriving instance Generic PreparedGroup
deriving instance Generic Profile
deriving instance Generic ProxyClientError
deriving instance Generic ProxyError
+deriving instance Generic PublicGroupAccess
deriving instance Generic PublicGroupData
deriving instance Generic PublicGroupProfile
deriving instance Generic RatchetSyncState
@@ -553,11 +560,16 @@ deriving instance Generic RcvFileStatus
deriving instance Generic RcvFileTransfer
deriving instance Generic RcvGroupEvent
deriving instance Generic RcvMsgError
+deriving instance Generic RelayCapabilities
deriving instance Generic RelayProfile
deriving instance Generic RelayStatus
deriving instance Generic ReportReason
deriving instance Generic SecurityCode
deriving instance Generic SimplexLinkType
+deriving instance Generic SimplexNameDomain
+deriving instance Generic SimplexNameInfo
+deriving instance Generic SimplexNameType
+deriving instance Generic SimplexTLD
deriving instance Generic SMPAgentError
deriving instance Generic SndCIStatusProgress
deriving instance Generic SndConnEvent
diff --git a/cabal.project b/cabal.project
index 22eeebe714..27f82d85bd 100644
--- a/cabal.project
+++ b/cabal.project
@@ -21,7 +21,7 @@ constraints: zip +disable-bzip2 +disable-zstd
source-repository-package
type: git
location: https://github.com/simplex-chat/simplexmq.git
- tag: f0b7a4be7325cb787297a881076299c5ffbe26e7
+ tag: 61ee188ee0839c34de16bc17934f04ebc7fd4873
source-repository-package
type: git
diff --git a/docs/rfcs/2026-05-21-public-namespaces.md b/docs/rfcs/2026-05-21-public-namespaces.md
new file mode 100644
index 0000000000..9f968945f3
--- /dev/null
+++ b/docs/rfcs/2026-05-21-public-namespaces.md
@@ -0,0 +1,246 @@
+# Public Namespaces for SimpleX Network
+
+## Motivation
+
+SimpleX has no user identifiers - users exchange invitation links out-of-band to connect. Short links help but are unmemorable. Public namespaces map human-readable names to SimpleX addresses.
+
+Names also solve censorship at two levels. A short link is controlled by one SMP router - that router can delete it. An on-chain name can't be deleted by any router. If the link is removed, the owner points the name to a new link on a different router. At the network level, links can be URL-filtered, but names resolve through SMP proxy chains - censoring a name requires controlling all resolvers the user can reach.
+
+DNS-based naming is vulnerable to domain seizure and requires WHOIS entries. Blockchains provide censorship-resistant globally unique names.
+
+## Product requirements
+
+### MVP
+
+- **Names**: TLD `.simplex` (e.g., `privacy.simplex`, `my-channel.simplex`). Subdomains: `support.acme.simplex`. In markdown, `.simplex` can be omitted: `#privacy` = `privacy.simplex`.
+- **Name rules**: see [Name rules](#name-rules).
+- **Two address types**: each name stores channel links (set) and contact links (set). Client uses the first; set provides forward-compatible redundancy. Either can be empty.
+- **Optional metadata**: admin SimpleX address, admin email.
+- **Registration**: commit-reveal to prevent frontrunning. Length-based ETH pricing. Annual renewal. Dutch auction on expiry.
+- **Launch gating**: requires SimpleX test NFT. Up to 5 paid + 5 test names per holder. Test names free, auto-removed after 3 months, use `testing` namespace.
+- **Reserved names**: common verticals (books, games, music, movies, news, etc.) reserved for community-operated channels managed by SimpleX Network Consortium.
+- Only 7+ character names can be registered during "launch phase".
+- **Resolution**: client queries two independent name servers (Ethereum light clients) via two SMP proxies. Agreement = trusted. Disagreement = warning.
+- **Double resolution**: name -> short link (on-chain), short link -> connection data (existing protocol).
+- **Verification**: if on-chain link matches profile address, name is verified. Manual "verify" button + optional auto-verify on profile open.
+- **Markdown**: `#name` (`.simplex` implied), `#name.simplex` (explicit), `#name.testing` for test namespace. In CLI, `#` is local in group commands, global in `/c` and message bodies.
+- **Search**: `#name.simplex` auto-resolves. Disable in "More privacy" settings.
+- **Router role**: `names` added to `ServerRoles`. Not all routers support it.
+- **Contract**: ENS fork on Ethereum mainnet. ETH payment. Upgradeable.
+
+### Post-MVP
+
+- **Multiple links**: redundant entries per name. Forward-compatible schema in MVP where practical.
+- **Contact syntax**: `:name.simplex`, `:my-name.simplex`. Same namespace, different link type. MVP parser supports this syntax; resolution works; UI support is post-MVP.
+- **Community Credits**: replace ETH for private registration.
+- **Unicode expansion**: add scripts as user base grows.
+
+## Part 1: Blockchain contract
+
+### Overview
+
+ENS fork on Ethereum mainnet. Retains commit-reveal, pricing, expiry, Dutch auction. Compatible with ENS dApp. Upgradeable.
+
+ENS source:
+- Contracts: https://github.com/ensdomains/ens-contracts
+- dApp: https://github.com/ensdomains/ens-app-v3
+- JS library: https://github.com/ensdomains/ensjs
+
+### Contract state
+
+```
+Name record (ENS structure + SimpleX resolver fields):
+ owner : address
+ channelLinks : string[]
+ contactLinks : string[]
+ adminAddress : string -- optional
+ adminEmail : string -- optional
+ expiry : uint256
+ isTest : bool
+
+Global state:
+ reservedNames : mapping(string => bool)
+ testNFT : address
+ registrationLimit : uint8 -- 5
+ testLimit : uint8 -- 5
+```
+
+There must be maps to track names by owner, but specific contract design should be based on ENS.
+
+### Name rules
+
+ENS normalization (ENSIP-15) with additional restrictions enforced in dApp (registration) and resolvers (resolution). Contract follows ENS as-is.
+
+Additional restrictions beyond ENSIP-15:
+- No consecutive hyphens.
+- No accented characters. Latin is `a-z` only (same as DNS LDH rule).
+- Allowed scripts: Latin, Cyrillic, Arabic, Hebrew, Devanagari, Bengali, Thai, Greek, CJK, Hangul, Kana. Expandable as user base grows.
+
+### Registration flow
+
+1. NFT check
+2. Limit check (5 paid / 5 test)
+3. `commit(hash(name, owner, secret))`
+4. Wait (min 1 minute)
+5. `reveal(name, owner, secret)` + ETH (zero for test)
+6. Validate: well-formed, not taken, not reserved, fee covered
+7. Store record
+
+### Pricing
+
+Annual fees by name length:
+
+| Length | Fee |
+|---|---|
+| 7+ | base |
+| 6 | 4x |
+| 5 | 16x |
+| 4 | 64x |
+| 3 | 256x |
+
+Test names: free, expire after 3 months.
+
+### Renewal and expiry
+
+Annual renewal. Grace period, then Dutch auction decaying to base price.
+
+### Updates
+
+Owner can update links, admin address, admin email. Transfer follows ENS mechanics.
+
+### Reserved names
+
+List for community channels (e.g., `books`, `games`, `music`, `news`):
+- Not registrable by users
+- Revenue shared with network
+
+### Retained ENS features
+
+- **Resolver pattern**: registry maps name -> (owner, resolver). A SimpleX Resolver contract stores channel links, contact links, admin fields. Allows future extensibility without registry changes.
+- **Multicoin address records**: BTC/ETH/XMR donation addresses per name. Subscribers see donation options from name resolution.
+- **Text records**: generic key-value store for future metadata without contract upgrades.
+- **Reverse resolution**: name lookup by address. Enables verification and discovery.
+- **Subdomain registrar**: owner of `acme.simplex` can create `support.acme.simplex`, `sales.acme.simplex` without additional on-chain registration.
+
+### Removed ENS features
+
+- Avatar/image records.
+- `.eth` TLD and ENS name imports.
+- DNS name registration (DNSSEC imports).
+
+### Governance
+
+SimpleX Chat during testing and launch phases, migration to SimpleX Network Consortium.
+
+## Part 2: SMP protocol extension
+
+### New router role
+
+```haskell
+data ServerRoles = ServerRoles
+ { storage :: Bool,
+ proxy :: Bool,
+ names :: Bool
+ }
+```
+
+Name-capable routers run an Ethereum light client.
+
+### Resolution protocol
+
+Uses existing SMP proxy infrastructure. Client sends queries through a proxy, not directly to name servers.
+
+#### Commands
+
+```
+Client -> Proxy -> Name Server:
+ RSLV
+
+Name Server -> Proxy -> Client:
+ NAME
+ ERR AUTH
+```
+
+Forwarded via `PRXY`/`PFWD`/`RRES` mechanism.
+
+#### Two-operator resolution
+
+```
+Client -> Proxy A (Op 1) -> Name Server X (Op 1)
+Client -> Proxy B (Op 2) -> Name Server Y (Op 2)
+```
+
+Both read same Ethereum state.
+
+- Agree: trusted
+- Disagree: warn, don't use
+- One fails: retry with another server or show single result with reduced trust
+
+Proxy sees client IP and session, but not query. Name server sees query, not client IP or session.
+
+#### Name server implementation
+
+1. Runs Ethereum light client (e.g., Helios) tracking SNRC
+2. Receives `RSLV` via SMP proxy
+3. Returns record from local state
+
+State proofs can be added post-MVP.
+
+#### Configuration
+
+```haskell
+data NamesConfig = NamesConfig
+ { ethereumEndpoint :: String,
+ snrcAddress :: EthAddress,
+ cacheSeconds :: Int
+ }
+```
+
+#### Versioning
+
+New SMP protocol version. Older routers/clients don't advertise the capability.
+
+### Default routers
+
+Default router list updated to include name-capable routers.
+
+## Part 3: UI integration
+
+### Markdown
+
+- `#name` or `#name.simplex` - native names (no dot = `.simplex` implied)
+- `#my-name` or `#my-name.simplex` - hyphenated names
+- `#sub.name.simplex` - subdomains (explicit TLD)
+- `#name.testing` - test namespace
+- Rendered as clickable resolve-and-connect links
+
+CLI: `#` = local in group commands, global in `/c` and messages.
+
+`:name.simplex`, `:my-name.simplex` - contact addresses (same namespace, different link type). MVP parser supports this syntax; resolution works; UI support is post-MVP.
+
+### Resolution flow
+
+1. Normalize per ENSIP-15, compute namehash
+2. `RSLV` to two name servers via two proxies
+3. Compare results
+4. First channel link -> short link resolution -> connection data
+5. Present for joining
+
+### Search
+
+`#...simplex` triggers resolution. Disable in "More privacy" settings.
+
+### Verification
+
+On-chain link matches profile address = verified. Only name owner can set on-chain links.
+
+- Manual: "Verify" button resolves and compares
+- Auto: optional setting, resolves on profile open
+
+### Display
+
+Show name and verification status. `#` is syntax, not part of the name.
+
+## Open questions
+
+1. **Contract upgrade mechanism**: proxy pattern with timelock? Migration path for future Community Credits payment and domain name support.
diff --git a/packages/simplex-chat-client/types/typescript/src/types.ts b/packages/simplex-chat-client/types/typescript/src/types.ts
index b4ee5a19d2..f364bebd9b 100644
--- a/packages/simplex-chat-client/types/typescript/src/types.ts
+++ b/packages/simplex-chat-client/types/typescript/src/types.ts
@@ -2352,6 +2352,7 @@ export type Format =
| Format.Uri
| Format.HyperLink
| Format.SimplexLink
+ | Format.SimplexName
| Format.Command
| Format.Mention
| Format.Email
@@ -2369,6 +2370,7 @@ export namespace Format {
| "uri"
| "hyperLink"
| "simplexLink"
+ | "simplexName"
| "command"
| "mention"
| "email"
@@ -2425,6 +2427,11 @@ export namespace Format {
smpHosts: string[] // non-empty
}
+ export interface SimplexName extends Interface {
+ type: "simplexName"
+ nameInfo: SimplexNameInfo
+ }
+
export interface Command extends Interface {
type: "command"
commandStr: string
@@ -2597,6 +2604,7 @@ export type GroupLinkPlan =
| GroupLinkPlan.ConnectingProhibit
| GroupLinkPlan.Known
| GroupLinkPlan.NoRelays
+ | GroupLinkPlan.UpdateRequired
export namespace GroupLinkPlan {
export type Tag =
@@ -2606,6 +2614,7 @@ export namespace GroupLinkPlan {
| "connectingProhibit"
| "known"
| "noRelays"
+ | "updateRequired"
interface Interface {
type: Tag
@@ -2644,6 +2653,11 @@ export namespace GroupLinkPlan {
type: "noRelays"
groupSLinkData_?: GroupShortLinkData
}
+
+ export interface UpdateRequired extends Interface {
+ type: "updateRequired"
+ groupSLinkData_?: GroupShortLinkData
+ }
}
export interface GroupMember {
@@ -2757,6 +2771,7 @@ export interface GroupRelay {
userChatRelay: UserChatRelay
relayStatus: RelayStatus
relayLink?: string
+ relayCap: RelayCapabilities
}
export type GroupRootKey = GroupRootKey.Private | GroupRootKey.Public
@@ -3338,6 +3353,13 @@ export namespace ProxyError {
}
}
+export interface PublicGroupAccess {
+ groupWebPage?: string
+ groupDomain?: string
+ domainWebPage: boolean
+ allowEmbedding: boolean
+}
+
export interface PublicGroupData {
publicMemberCount: number // int64
}
@@ -3346,6 +3368,7 @@ export interface PublicGroupProfile {
groupType: GroupType
groupLink: string
publicGroupId: string
+ publicGroupAccess?: PublicGroupAccess
}
export type RCErrorType =
@@ -3734,6 +3757,10 @@ export namespace RcvMsgError {
}
}
+export interface RelayCapabilities {
+ webDomain?: string
+}
+
export interface RelayProfile {
displayName: string
fullName: string
@@ -3837,6 +3864,28 @@ export enum SimplexLinkType {
Relay = "relay",
}
+export interface SimplexNameDomain {
+ nameTLD: SimplexTLD
+ domain: string
+ subDomain: string[]
+}
+
+export interface SimplexNameInfo {
+ nameType: SimplexNameType
+ nameDomain: SimplexNameDomain
+}
+
+export enum SimplexNameType {
+ PublicGroup = "publicGroup",
+ Contact = "contact",
+}
+
+export enum SimplexTLD {
+ Simplex = "simplex",
+ Testing = "testing",
+ Web = "web",
+}
+
export enum SndCIStatusProgress {
Partial = "partial",
Complete = "complete",
diff --git a/packages/simplex-chat-python/examples/squaring_bot.py b/packages/simplex-chat-python/examples/squaring_bot.py
index 296b51347e..4d062ad718 100644
--- a/packages/simplex-chat-python/examples/squaring_bot.py
+++ b/packages/simplex-chat-python/examples/squaring_bot.py
@@ -26,7 +26,15 @@ bot = Bot(
profile=BotProfile(display_name="Squaring bot"),
db=SqliteDb(file_prefix="./squaring_bot"),
welcome="Send me a number, I'll square it.",
- commands=[BotCommand(keyword="help", label="Show help")],
+ commands=[
+ # `params=None` (default): the client SENDS `/help` immediately
+ # when the user taps it in the commands menu.
+ BotCommand(keyword="help", label="Show help"),
+ # `params=""`: the client PASTES `/square `
+ # into the input box and positions the cursor at the end. The
+ # user replaces `` with the actual number and sends.
+ BotCommand(keyword="square", label="Square a number", params=""),
+ ],
)
NUMBER_RE = re.compile(r"^-?\d+(\.\d+)?$")
@@ -48,5 +56,19 @@ async def help_cmd(msg: Message, _cmd: ParsedCommand) -> None:
await msg.reply("Send a number, I'll square it.")
+@bot.on_command("square")
+async def square_cmd(msg: Message, cmd: ParsedCommand) -> None:
+ """Demonstrates the `params` flow: `cmd.args` is the trimmed text
+ AFTER `/square`. When the user tapped the menu entry above, the
+ client pasted `/square ` and the user replaced
+ `` with the actual value before sending."""
+ try:
+ n = float(cmd.args)
+ except ValueError:
+ await msg.reply(f"Usage: /square (got {cmd.args!r})")
+ return
+ await msg.reply(f"{n} * {n} = {n * n}")
+
+
if __name__ == "__main__":
bot.run()
diff --git a/packages/simplex-chat-python/src/simplex_chat/bot.py b/packages/simplex-chat-python/src/simplex_chat/bot.py
index fb511e2818..4e385493b2 100644
--- a/packages/simplex-chat-python/src/simplex_chat/bot.py
+++ b/packages/simplex-chat-python/src/simplex_chat/bot.py
@@ -33,8 +33,38 @@ from .types import T
@dataclass(slots=True)
class BotCommand:
+ """One entry in the bot's advertised slash-command list (wire-side
+ `groupPreferences.commands` or profile `preferences.commands`).
+
+ `keyword` and `label` are required: `keyword` is what the user
+ types after `/`; `label` is the human-readable description shown
+ next to the keyword in the SimpleX client's commands menu.
+
+ `params` is an optional placeholder string that controls how the
+ client behaves when the user taps the command in the menu:
+
+ * `params=None` (default) — the client SENDS `/`
+ immediately on tap; no input-box detour. Use this for
+ zero-argument commands (`/help`, `/ping`) where the action is
+ unambiguous.
+
+ * `params=""` — the client PASTES `/`
+ into the input box and positions the cursor at the end. The
+ user edits the placeholder and sends. Use this for commands
+ that take a required argument (`/review `,
+ `/order `) so the user sees the expected shape
+ without having to remember it.
+
+ Mirrors `CBCCommand` in the Haskell core
+ (`Simplex.Chat.Types.Preferences`) and the wire TypedDict
+ `ChatBotCommand_command`. Both SimpleX clients (Android/Kotlin
+ and iOS/Swift) implement the paste-vs-send branch on the
+ `params` field; see `CommandsMenuView.{kt,swift}` for the
+ reference UI behaviour.
+ """
keyword: str
label: str
+ params: str | None = None
class Bot(Client):
@@ -145,10 +175,24 @@ class Bot(Client):
"files": {"allow": "yes" if self._allow_files else "no"},
}
if self._commands:
- prefs["commands"] = [
- {"type": "command", "keyword": c.keyword, "label": c.label}
- for c in self._commands
- ]
+ cmds: list[T.ChatBotCommand] = []
+ for c in self._commands:
+ entry: T.ChatBotCommand_command = {
+ "type": "command",
+ "keyword": c.keyword,
+ "label": c.label,
+ }
+ # `params` is `NotRequired[str]` on the wire; omit the
+ # key entirely when None so the Haskell parser sees
+ # `Nothing` rather than `Just ""`. The two have
+ # different client semantics: `Nothing` (`params=None`)
+ # triggers an immediate send on tap; `Just ""` would
+ # paste `/ ` (with a trailing space) into the
+ # input box, which is rarely what the operator wants.
+ if c.params is not None:
+ entry["params"] = c.params
+ cmds.append(entry)
+ prefs["commands"] = cmds
p["preferences"] = prefs
p["peerType"] = "bot"
return p
diff --git a/packages/simplex-chat-python/src/simplex_chat/types/_types.py b/packages/simplex-chat-python/src/simplex_chat/types/_types.py
index 55641345a6..c8445443b1 100644
--- a/packages/simplex-chat-python/src/simplex_chat/types/_types.py
+++ b/packages/simplex-chat-python/src/simplex_chat/types/_types.py
@@ -1683,6 +1683,10 @@ class Format_simplexLink(TypedDict):
simplexUri: str
smpHosts: list[str] # non-empty
+class Format_simplexName(TypedDict):
+ type: Literal["simplexName"]
+ nameInfo: "SimplexNameInfo"
+
class Format_command(TypedDict):
type: Literal["command"]
commandStr: str
@@ -1708,13 +1712,14 @@ Format = (
| Format_uri
| Format_hyperLink
| Format_simplexLink
+ | Format_simplexName
| Format_command
| Format_mention
| Format_email
| Format_phone
)
-Format_Tag = Literal["bold", "italic", "strikeThrough", "snippet", "secret", "small", "colored", "uri", "hyperLink", "simplexLink", "command", "mention", "email", "phone"]
+Format_Tag = Literal["bold", "italic", "strikeThrough", "snippet", "secret", "small", "colored", "uri", "hyperLink", "simplexLink", "simplexName", "command", "mention", "email", "phone"]
class FormattedText(TypedDict):
format: NotRequired["Format"]
@@ -1851,6 +1856,10 @@ class GroupLinkPlan_noRelays(TypedDict):
type: Literal["noRelays"]
groupSLinkData_: NotRequired["GroupShortLinkData"]
+class GroupLinkPlan_updateRequired(TypedDict):
+ type: Literal["updateRequired"]
+ groupSLinkData_: NotRequired["GroupShortLinkData"]
+
GroupLinkPlan = (
GroupLinkPlan_ok
| GroupLinkPlan_ownLink
@@ -1858,9 +1867,10 @@ GroupLinkPlan = (
| GroupLinkPlan_connectingProhibit
| GroupLinkPlan_known
| GroupLinkPlan_noRelays
+ | GroupLinkPlan_updateRequired
)
-GroupLinkPlan_Tag = Literal["ok", "ownLink", "connectingConfirmReconnect", "connectingProhibit", "known", "noRelays"]
+GroupLinkPlan_Tag = Literal["ok", "ownLink", "connectingConfirmReconnect", "connectingProhibit", "known", "noRelays", "updateRequired"]
class GroupMember(TypedDict):
groupMemberId: int # int64
@@ -1936,6 +1946,7 @@ class GroupRelay(TypedDict):
userChatRelay: "UserChatRelay"
relayStatus: "RelayStatus"
relayLink: NotRequired[str]
+ relayCap: "RelayCapabilities"
class GroupRootKey_private(TypedDict):
type: Literal["private"]
@@ -2344,6 +2355,12 @@ ProxyError = ProxyError_PROTOCOL | ProxyError_BROKER | ProxyError_BASIC_AUTH | P
ProxyError_Tag = Literal["PROTOCOL", "BROKER", "BASIC_AUTH", "NO_SESSION"]
+class PublicGroupAccess(TypedDict):
+ groupWebPage: NotRequired[str]
+ groupDomain: NotRequired[str]
+ domainWebPage: bool
+ allowEmbedding: bool
+
class PublicGroupData(TypedDict):
publicMemberCount: int # int64
@@ -2351,6 +2368,7 @@ class PublicGroupProfile(TypedDict):
groupType: "GroupType"
groupLink: str
publicGroupId: str
+ publicGroupAccess: NotRequired["PublicGroupAccess"]
class RCErrorType_internal(TypedDict):
type: Literal["internal"]
@@ -2619,6 +2637,9 @@ RcvMsgError = RcvMsgError_dropped | RcvMsgError_parseError
RcvMsgError_Tag = Literal["dropped", "parseError"]
+class RelayCapabilities(TypedDict):
+ webDomain: NotRequired[str]
+
class RelayProfile(TypedDict):
displayName: str
fullName: str
@@ -2680,6 +2701,19 @@ class SimplePreference(TypedDict):
SimplexLinkType = Literal["contact", "invitation", "group", "channel", "relay"]
+class SimplexNameDomain(TypedDict):
+ nameTLD: "SimplexTLD"
+ domain: str
+ subDomain: list[str]
+
+class SimplexNameInfo(TypedDict):
+ nameType: "SimplexNameType"
+ nameDomain: "SimplexNameDomain"
+
+SimplexNameType = Literal["publicGroup", "contact"]
+
+SimplexTLD = Literal["simplex", "testing", "web"]
+
SndCIStatusProgress = Literal["partial", "complete"]
class SndConnEvent_switchQueue(TypedDict):
diff --git a/packages/simplex-chat-python/tests/test_bot_registration.py b/packages/simplex-chat-python/tests/test_bot_registration.py
index f6f245c344..06837bdc07 100644
--- a/packages/simplex-chat-python/tests/test_bot_registration.py
+++ b/packages/simplex-chat-python/tests/test_bot_registration.py
@@ -86,8 +86,63 @@ def test_bot_profile_to_wire_with_commands():
)
cmds = bot._profile_to_wire().get("preferences", {}).get("commands") or []
assert len(cmds) == 2
+ # `params` defaults to None and must be ABSENT from the wire dict
+ # (not present as `null`/`""`) so the Haskell parser sees
+ # `Nothing` and the SimpleX client sends the bare `/keyword` on
+ # tap rather than pasting a trailing-space placeholder.
assert cmds[0] == {"type": "command", "keyword": "ping", "label": "Ping bot"}
assert cmds[1] == {"type": "command", "keyword": "help", "label": "Show help"}
+ assert "params" not in cmds[0]
+ assert "params" not in cmds[1]
+
+
+def test_bot_command_params_emits_on_wire():
+ """When `BotCommand.params` is set, the wire dict carries it as
+ `params: `. The SimpleX client (verified against
+ `CommandsMenuView.kt:153-161` and `CommandsMenuView.swift:117-128`
+ in simplex-chat 6.5) then pastes `/` into the
+ input box on tap, positions the cursor at the end, and lets the
+ user edit before sending. Use this for commands that take a
+ required argument (`/review `)."""
+ bot = Bot(
+ profile=BotProfile(display_name="x"),
+ db=SqliteDb(file_prefix="/tmp/test"),
+ commands=[
+ BotCommand(keyword="review", label="Review PR", params=""),
+ BotCommand(keyword="order", label="Place order", params=""),
+ ],
+ )
+ cmds = bot._profile_to_wire().get("preferences", {}).get("commands") or []
+ assert cmds[0] == {
+ "type": "command",
+ "keyword": "review",
+ "label": "Review PR",
+ "params": "",
+ }
+ assert cmds[1] == {
+ "type": "command",
+ "keyword": "order",
+ "label": "Place order",
+ "params": "",
+ }
+
+
+def test_bot_command_distinguishes_none_from_empty_params():
+ """`params=None` (immediate send) and `params=""` (paste with
+ trailing space) are semantically different on the client side.
+ Verify the wire form preserves the distinction: None → key
+ absent; empty string → key present with empty value."""
+ bot = Bot(
+ profile=BotProfile(display_name="x"),
+ db=SqliteDb(file_prefix="/tmp/test"),
+ commands=[
+ BotCommand(keyword="send", label="Send", params=None),
+ BotCommand(keyword="paste", label="Paste", params=""),
+ ],
+ )
+ cmds = bot._profile_to_wire().get("preferences", {}).get("commands") or []
+ assert "params" not in cmds[0]
+ assert cmds[1].get("params") == ""
def test_client_profile_to_wire_has_no_bot_extras():
diff --git a/plans/2026-05-15-fix-video-preview-snapshot-hang.md b/plans/2026-05-15-fix-video-preview-snapshot-hang.md
new file mode 100644
index 0000000000..4a64d0ca43
--- /dev/null
+++ b/plans/2026-05-15-fix-video-preview-snapshot-hang.md
@@ -0,0 +1,57 @@
+# Desktop: video playback hangs after a preview snapshot stalls
+
+Branch: `nd/fix-video` · final code commit `4c7073bdc` · PR [#6983](https://github.com/simplex-chat/simplex-chat/pull/6983).
+
+## 1. Problem statement
+
+On Desktop with several videos in a chat, clicking the play button on the second (or any subsequent) video does nothing. The first video plays normally; later ones present a play button that responds to the click but never starts playback. No error dialog appears in the UI. `stderr` shows libvlc and libavcodec noise:
+
+```
+[h264 @ 0x...] get_buffer() failed
+[h264 @ 0x...] thread_get_buffer() failed
+[h264 @ 0x...] decode_slice_header error
+[h264 @ 0x...] no frame!
+... main video output error: Failed to grab a snapshot
+```
+
+The bug appeared after PR [#6924](https://github.com/simplex-chat/simplex-chat/pull/6924) (`ab2d03630`), which switched the preview helper player from the shared `vlcFactory` to a dedicated `vlcPreviewFactory` with `--avcodec-hw=none`. Hardware-accelerated decoding had previously masked the underlying fragility. Scope: Desktop only.
+
+## 2. Root cause
+
+Two compounding defects in `VideoPlayer.desktop.kt`, surfaced by `#6924`:
+
+### 2a. Synchronous `snapshots().get()` blocks the shared `playerThread` indefinitely
+
+`getBitmapFromVideo` ran inside `withContext(playerThread.asCoroutineDispatcher())` — the same single-thread executor used by `play()`/`stop()` for playback. Its loop polls vlcj's snapshot API:
+
+```kotlin
+while (snap == null && start + 1500 > System.currentTimeMillis()) {
+ snap = player.snapshots()?.get()
+ delay(50)
+}
+```
+
+The 1500 ms wall-clock guard only fires *between* calls. `player.snapshots()?.get()` is a synchronous JNI call that, when libvlc cannot produce a frame, waits indefinitely. While it blocks, `playerThread` is held: every queued `playerThread.execute { videoPlaying.value = start(...) }` from a subsequent `play()` click sits in the queue and never runs.
+
+This was confirmed by instrumented printlns: after the first video's preview entered the snapshot loop, the second video's `play()` body executed (UI thread println fires), but its lambda submitted to `playerThread.execute` produced no `lambda started` print — because `playerThread` was stuck inside the JNI call.
+
+### 2b. Helper-player pool reuse exhausts the software h264 buffer pool
+
+`getOrCreateHelperPlayer()` returns a `CallbackMediaPlayerComponent` from `helperPlayersPool`, recycling it across preview generations. With `vlcFactory` (hardware-accelerated by default), this was harmless — the GPU buffer pool was large with different lifecycle semantics. After `#6924` switched the helper to `vlcPreviewFactory` (`--avcodec-hw=none`), libavcodec frames from the previous run were not released cleanly across `stop` + `startPaused`, and the second decoder ran out of buffers (`get_buffer() failed`). The vout never produced a frame, which is the trigger for the hang in 2a.
+
+## 3. Solution summary
+
+`apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/VideoPlayer.desktop.kt` — single file, +8 / −6 lines. Helper-player pool is preserved as-is.
+
+1. **Replace the polling `snapshots().get()` loop with a `CallbackVideoSurface` capture wrapped in `withTimeoutOrNull`.** The existing `SkiaBitmapVideoSurface` (already used for full-screen playback rendering) is attached to the helper player before `media().startPaused(...)`. Its `RenderCallback.display()` runs as soon as libvlc decodes the first frame, populating `surface.bitmap`. `getBitmapFromVideo` polls `surface.bitmap.value` from inside `withTimeoutOrNull(1500L) { ... }`; the wait is now structurally bounded — the synchronous JNI call is gone. Frame is converted to `BufferedImage` via `ImageBitmap.toAwtImage()` for the existing orientation-correction code path. This addresses 2a directly: a helper that fails to decode (2b) no longer holds the dispatcher.
+
+2. **Move preview generation to a dedicated executor.** A new `previewThread = Executors.newSingleThreadExecutor()` runs `getBitmapFromVideo`. Defense in depth: even if 1500 ms of preview work overlaps with a play click, playback's `playerThread` is free to service it.
+
+The pool is intentionally not touched. Removing it loses the factory-warmup amortization across distinct video URIs without addressing the actual hang (which is in the synchronous snapshot API, not in player reuse).
+
+## 4. Alternatives considered (and rejected)
+
+- **Drop the helper-player pool (initial attempt, commit `4a964c661`).** Replaces every preview's helper with a fresh `CallbackMediaPlayerComponent`. Fixes the symptom by sidestepping pool reuse, but costs the factory-warmup benefit and does not address the underlying blocking JNI call — a single corrupt video could still hang preview generation indefinitely (just on a fresh helper). Superseded by the surface-capture approach.
+- **Keep the pool, reset the helper between uses.** vlcj has no clean reset API; would require `media().release()` + manual re-attach. More code, fragile, doesn't address 2a.
+- **Wrap `snapshots().get()` in a coroutine timeout on a separate IO thread.** `withTimeoutOrNull` cannot cancel a blocked JNI call; the IO thread leaks until libvlc returns (which may be never).
+- **Revert PR #6924.** Restores the masking effect of hardware-accelerated decoding but reintroduces whatever the PR was guarding against, and leaves both 2a and 2b in place.
diff --git a/plans/2026-05-16-desktop-updater-fixes.md b/plans/2026-05-16-desktop-updater-fixes.md
new file mode 100644
index 0000000000..40dbefd11d
--- /dev/null
+++ b/plans/2026-05-16-desktop-updater-fixes.md
@@ -0,0 +1,100 @@
+# Desktop In-App Updater Fixes
+
+## Problem Statement
+
+The desktop in-app updater (`apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/helpers/AppUpdater.kt`) silently or visibly fails on three of the four supported desktop platforms:
+
+1. **Windows**: no update dialog ever appears for any Windows user, regardless of how out-of-date the running version is.
+2. **AppImage (x86_64)**: the update dialog appears and the download succeeds, but clicking "Install update" opens the new AppImage in an archive viewer ("Archive format not recognized") instead of installing it. The running AppImage is never replaced.
+3. **AppImage (aarch64)**: no update dialog ever appears for any aarch64 AppImage user.
+
+The desktop installer flow on macOS and the `.deb` flow on Debian-derivative Linux are not affected and remain unchanged.
+
+## Root Causes
+
+### 1. Windows — `which dpkg` IOException swallowed
+
+`chooseGitHubReleaseAssets` (AppUpdater.kt) invokes `Runtime.getRuntime().exec("which dpkg")` unconditionally to detect Debian-derivative systems. On Windows there is no `which.exe`; `CreateProcess` returns error 2 and the JVM throws `IOException: Cannot run program "which"` synchronously from `Runtime.exec`. The exception propagates up through `chooseGitHubReleaseAssets` into `checkForUpdate`'s outer `try { ... } catch (e: Exception) { Log.e(...) }`, which logs to stderr and returns. The user-facing alert is never built.
+
+The `.deb` probe was correct in intent but executed too eagerly: it has no business running on a non-Linux platform.
+
+### 2. AppImage — `xdg-open` is the wrong operation
+
+The Linux branch of `installAppUpdate` calls `xdg-open `. An AppImage is not "installable" in the package-manager sense — it is a self-contained executable that lives at the path stored in the `$APPIMAGE` environment variable (set by the AppImage runtime). On most desktop environments, `xdg-open` resolves the `.AppImage` MIME type to an archive handler (file-roller, ark, engrampa). The handler attempts to read the AppImage as a `.iso`/squashfs archive and fails with "Archive format not recognized". Even when it succeeds, it does not replace the running AppImage — the next launch still runs the old binary.
+
+The existing code had no awareness of `$APPIMAGE` at install time. The `GitHubAsset.isAppImage` field hints at an earlier abandoned attempt at AppImage-specific handling.
+
+### 3. aarch64 AppImage — leading space in asset name
+
+`Platform.desktop.kt` declares:
+
+```kotlin
+LINUX_AARCH64("so", unixConfigPath, unixDataPath, " simplex-desktop-aarch64.AppImage"),
+```
+
+The `githubAssetName` literal has a leading space character. The actual release asset published by `.github/workflows/build.yml` is `simplex-desktop-aarch64.AppImage` (no space — verified against the live GitHub releases API). The exact-name filter in `chooseGitHubReleaseAssets` (`release.assets.filter { it.name == desktopPlatform.githubAssetName }`) never matches, the asset list is empty, and `checkForUpdate` returns at the "No assets to download for current system" branch without ever showing a dialog. Same silent-failure pattern as the Windows bug, single arch in blast radius.
+
+## Solution Summary
+
+Three small, independent commits — one per root cause. None of them changes shared logic; each touches one line (Windows, aarch64) or one branch of the install dispatch (AppImage).
+
+### Fix 1 — Gate the `dpkg` probe on Linux
+
+```kotlin
+// AppUpdater.kt: chooseGitHubReleaseAssets
+} else if (desktopPlatform.isLinux() && !isRunningFromAppImage()
+ && Runtime.getRuntime().exec("which dpkg").onExit().join().exitValue() == 0) {
+```
+
+Single conjunct (`desktopPlatform.isLinux() &&`) added at the start of the `else if`. Boolean short-circuit ensures `Runtime.exec` is never reached on non-Linux. The added gate matches the actual semantic intent: `.deb` is a Linux-only package format. Both the Windows IOException and the (theoretical) macOS misbehavior of the `which` probe are eliminated.
+
+### Fix 2 — AppImage-aware install path
+
+In `installAppUpdate`'s Linux branch, read `System.getenv("APPIMAGE")`:
+
+- If non-null, the running app is an AppImage at that path. Replacing it crash-safely takes two steps, because an atomic file replacement is only possible *within a single filesystem* (POSIX `rename(2)`), and the download lives in the temp dir — usually a different filesystem (tmpfs) from where `$APPIMAGE` lives:
+ 1. `Files.copy` the downloaded file to a staging file (`..update`) in the target's *own* directory. This is the unavoidable cross-filesystem transfer; it is not atomic, but it writes only a sidecar, never the live `$APPIMAGE`.
+ 2. Mark the staging file executable, then `Files.move` it onto `$APPIMAGE` with `ATOMIC_MOVE`. Because staging now shares the target's filesystem, this is a real atomic `rename(2)`: the live file flips from old to new in one indivisible step, never partially written.
+
+ A direct `Files.move(downloaded, target, REPLACE_EXISTING)` is **not** sufficient — across filesystems it copies bytes straight onto the live `$APPIMAGE`, which is neither atomic nor crash-safe (an interrupted copy destroys the user's installed app). `ATOMIC_MOVE` on a cross-filesystem move throws `AtomicMoveNotSupportedException`. Staging on the target's filesystem first is what makes the atomic move possible. On Linux the kernel keeps the running process's open file descriptors valid across the rename: the running app continues to function until the user restarts, at which point the new binary is used.
+- If null, fall back to the existing `xdg-open` path (used for `.deb` install on Debian, which is the only remaining caller of this path after Fix 2).
+
+On any exception (permission denied if the AppImage lives in `/opt/`, target read-only, etc.) the catch deletes the staging file and falls back to `desktopOpenDir(file.parentFile)` — the same fallback the original `xdg-open` path used.
+
+### Fix 3 — Remove leading space from `LINUX_AARCH64` asset name
+
+```kotlin
+LINUX_AARCH64("so", unixConfigPath, unixDataPath, "simplex-desktop-aarch64.AppImage"),
+```
+
+Single character removed. The asset name now matches what `make-appimage-linux.sh` produces and what GitHub releases publish.
+
+## Why three commits, not one
+
+Each fix has a different blast radius, a different fix size, and (potentially) a different review path. Three focused commits let a reviewer judge each one in isolation:
+
+- Windows fix: 1 line, gates a side-effecting `Runtime.exec` on a platform check that the surrounding code already establishes.
+- AppImage install: ~35 lines, introduces new file-system operations (`Files.copy` to a staging file, then `Files.move` with `ATOMIC_MOVE`).
+- aarch64 fix: 1 character, fixes a typo in a string literal.
+
+Bundling them as a single commit would force a reviewer to verify all three at once and would obscure `git blame` on the AppImage install logic, which is the only one of the three that introduces meaningful new behavior.
+
+## Out of scope
+
+The following were identified during the audit (`apps/multiplatform/app-updater-audit.md`) but deliberately deferred to keep this PR focused:
+
+- `msiexec /i ${file.absolutePath}` uses the single-string `Runtime.exec` overload that tokenizes on whitespace; paths containing spaces (uncommon on Windows but possible) break the install.
+- Download failures (network, TLS, disk-full, GitHub error) are caught but only logged; the user sees nothing.
+- `process.children().count() > 0` in the Linux `xdg-open` path is racy and arguably wrong.
+- No SHA256 / signature verification on the downloaded artifact — the updater installs whatever GitHub serves.
+- 24h delay with no retry / backoff on transient network errors.
+- macOS install hardcodes `/Applications/SimpleX.app`.
+
+Each is documented with `file:line` references in the audit; none affects the three platforms this PR fixes.
+
+## Test plan
+
+- **Windows**: built x86_64 MSI via the fork CI workflow [`build-windows-msi.yml`](https://github.com/Narasimha-sc/simplex-chat/actions/runs/25958413517), installed in a Windows VM as version 6.5.1 (intentionally lowered to trigger the check against current stable 6.5.2). Settings → Check for updates → Stable: dialog appeared as expected.
+- **AppImage x86_64**: built locally (host build, GHC 9.6.3, gradle createDistributable, appimagetool), installed and ran on Linux. Settings → Check for updates → Stable: dialog appeared, Download landed file at `/tmp/simplex/simplex-desktop-x86_64.AppImage`, Install replaced `$APPIMAGE` in place. Verified by hashing `$APPIMAGE` before and after.
+- **aarch64 AppImage**: not separately tested. Fix is a 1-character literal change verified against the live GitHub releases API (`simplex-desktop-aarch64.AppImage`, no leading space).
+- **macOS**: no changes to the macOS install branch.
diff --git a/plans/2026-05-20-fix-copy-non-msg-items.md b/plans/2026-05-20-fix-copy-non-msg-items.md
new file mode 100644
index 0000000000..4f0c554357
--- /dev/null
+++ b/plans/2026-05-20-fix-copy-non-msg-items.md
@@ -0,0 +1,50 @@
+# Desktop: text selection copies non-message event items
+
+Branch: `nd/fix-copy-non-msg-items` · code commit `a536452ca` · PR [#6993](https://github.com/simplex-chat/simplex-chat/pull/6993).
+
+## 1. Problem statement
+
+The Desktop "select text in messages" feature (PR [#6725](https://github.com/simplex-chat/simplex-chat/pull/6725)) lets the user drag a selection across several message bubbles and copy it. When the selection spans a chat event/info item — a "connected" event, a member "joined"/"left" event, a call event, an e2ee-info line, a feature-change line — the copied text includes that item's text, even though the item is never shown highlighted as part of the selection.
+
+Expected: only real message text is copied. Observed: event/info text such as "connected" is appended into the clipboard between the selected messages.
+
+### Privacy note
+
+Event/info item text is produced from localized string resources (`generalGetString`, `RcvConnEvent.text`, etc.) — it is rendered in the language the user has chosen for the app, whereas real message text is not. A user who selects and copies a long span of messages carelessly, then pastes it into another chat or app, can therefore leak their chosen interface language through the event lines mixed into the paste. For a privacy-focused messenger this is a metadata leak, not only a cosmetic bug.
+
+## 2. Root cause
+
+`SelectionManager.getSelectedCopiedText` (`TextSelection.kt`) builds the copied string by iterating every merged-item index between the selection bounds and emitting each item's text:
+
+```kotlin
+return (lo..hi).mapNotNull { idx ->
+ val ci = items.getOrNull(idx)?.newest()?.item ?: return@mapNotNull null
+ if (ci.meta.itemDeleted != null && ...) return@mapNotNull null
+ val sel = selectedRange(range, idx) ?: return@mapNotNull null
+ selectedItemCopiedText(ci, sel, linkMode)
+}
+```
+
+For an *interior* item in a multi-item selection, `selectedRange` returns `0 until Int.MAX_VALUE` — the whole item is treated as selected — so its text is emitted unconditionally. The only items previously skipped were deleted ones.
+
+Anchor/focus character tracking (`setupItemSelection`) is wired up only for real message views (`FramedItemView`, `EmojiItemView`); event/info items never register offsets and never compute a highlight range. So an event item caught between two selected messages is invisible to the highlight but fully visible to `getSelectedCopiedText`. The copy logic and the on-screen selection disagreed.
+
+The distinguishing property: a real message has `ci.content.msgContent != null`; every event/info `CIContent` variant returns `msgContent == null`.
+
+## 3. Solution summary
+
+`apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/TextSelection.kt` — one guard, +3 lines.
+
+In `getSelectedCopiedText`, skip any item whose `content.msgContent` is null, alongside the existing deleted-item filter:
+
+```kotlin
+if (ci.content.msgContent == null) return@mapNotNull null
+```
+
+Only real messages now contribute copied text — which is exactly the set of items that are selectable and highlighted, so the clipboard matches the visible selection. `content.msgContent` is the existing model property used elsewhere to tell a real message apart from an event/info item.
+
+## 4. Alternatives considered (and rejected)
+
+- **Special-case only "connected" events.** Matches the literal report but leaves the identical bug for every other event/info item (joined/left, calls, e2ee info, feature changes) — same class, same language leak.
+- **Make event items non-selectable / consume the drag.** Larger change to the selection gesture; event items are already non-anchorable, and the bug is purely in the copy aggregation, not in the gesture.
+- **Filter at the call site (`onCopySelection`).** Duplicates the message/non-message distinction outside the one function that owns copied-text assembly; `getSelectedCopiedText` is the correct single source.
diff --git a/plans/2026-05-25-channel-web-preview.md b/plans/2026-05-25-channel-web-preview.md
new file mode 100644
index 0000000000..561d3948e7
--- /dev/null
+++ b/plans/2026-05-25-channel-web-preview.md
@@ -0,0 +1,596 @@
+# Channel Web Preview
+
+## Context
+
+SimpleX channels are public - anybody with the link to join and chat relays rebroadcasting the messages can see content. To grow channels, owners need a public web preview (like Telegram's `t.me/s/channelname`) showing the last 50 messages. This lets potential subscribers browse before joining.
+
+The relay already stores all messages in its database. The web preview is a periodic read-and-render loop that writes JSON files served by Caddy, with CORS controlling which domains can embed the preview.
+
+This feature integrates with the `.simplex` namespace (ENS-based names resolving to channel links). A channel's registered domain (`groupDomain`) lives in `PublicGroupAccess` inside `PublicGroupProfile` and is disseminated with the profile. On-chain verification of the domain is deferred until RSLV resolution protocol ships.
+
+## Architecture
+
+```
+simplex-chat CLI (--relay --web-json-dir=... --web-base-url=...)
+ ├── Main chat loop (existing)
+ ├── Relay logic (existing, gated by --relay)
+ └── Web preview thread (new, gated by relayWebOptions)
+ ├── Periodic: load publishable groups → render JSON → write files
+ └── Regenerate Caddy CORS config → caddy reload
+
+Caddy (operator-configured)
+ ├── Serves JSON at https:///group/.json
+ └── Imports generated CORS config file
+
+Channel page (static HTML+JS, hosted by owner or on GitHub)
+ ├── Fetches JSON from relay(s) with fallback
+ └── Renders messages, shows join button
+```
+
+## Data Model Changes
+
+### 1. Extend `PublicGroupProfile` with domain and web access settings
+
+**File:** `src/Simplex/Chat/Types.hs` (line 796)
+
+Current:
+```haskell
+data PublicGroupProfile = PublicGroupProfile
+ { groupType :: GroupType,
+ groupLink :: ShortLinkContact,
+ publicGroupId :: B64UrlByteString
+ }
+```
+
+New:
+```haskell
+data PublicGroupAccess = PublicGroupAccess
+ { groupWebPage :: Maybe Text, -- channel's web page URL (adds CORS origin)
+ groupDomain :: Maybe Text, -- domain for this channel (must have link set in domain record in the contract)
+ domainWebPage :: Bool, -- show on the domain's page (e.g. simplexnetwork.org site for simplex TLD domains, or domain site for web domains)
+ allowEmbeding :: Bool -- allow embedding from any origin (CORS: *)
+ }
+
+data PublicGroupProfile = PublicGroupProfile
+ { groupType :: GroupType,
+ groupLink :: ShortLinkContact,
+ publicGroupId :: B64UrlByteString,
+ publicGroupAccess :: Maybe PublicGroupAccess -- NEW: web preview settings
+ }
+```
+
+`groupDomain` stores the channel's registered `.simplex` domain name or another supported TLD. It is:
+- Set by the owner after registering a name on-chain
+- Disseminated to all members via `GroupProfile` (nested in `publicGroup`)
+- Used by `simplexnetwork.org/c/` to route to the channel's web preview (for .simplex domain)
+
+JSON instances: TH-derived `$(JQ.deriveJSON defaultJSON ''PublicGroupAccess)`. Existing `$(JQ.deriveJSON defaultJSON ''PublicGroupProfile)` covers the new optional field.
+
+**Migration (SQLite/Postgres):** separate columns, same pattern as `group_type`/`group_link`/`public_group_id`:
+```sql
+ALTER TABLE group_profiles ADD COLUMN group_web_page TEXT;
+ALTER TABLE group_profiles ADD COLUMN group_domain TEXT;
+ALTER TABLE group_profiles ADD COLUMN domain_web_page INTEGER;
+ALTER TABLE group_profiles ADD COLUMN allow_embedding INTEGER;
+ALTER TABLE group_profiles ADD COLUMN group_domain_verified_at TEXT;
+```
+
+`group_domain_verified_at` is relay-local verification state (nullable timestamp, NULL = unverified).
+
+**Store changes:**
+
+`src/Simplex/Chat/Store/Shared.hs` line 693 - new constructor alongside `toPublicGroupProfile`:
+```haskell
+toPublicGroupAccess :: Maybe Text -> Maybe Text -> Maybe BoolInt -> Maybe BoolInt -> Maybe PublicGroupAccess
+toPublicGroupAccess groupWebPage groupDomain domainWebPage_ allowEmbeding_
+ | isJust groupWebPage || isJust groupDomain || fromBI domainWebPage_ || fromBI allowEmbeding_ =
+ Just PublicGroupAccess {groupWebPage, groupDomain, domainWebPage = fromBI domainWebPage_, allowEmbeding = fromBI allowEmbeding_}
+ | otherwise = Nothing
+ where fromBI = maybe False unBI
+```
+
+Extend `toPublicGroupProfile` to accept and pass through `Maybe PublicGroupAccess`.
+
+`GroupInfoRow` type (line 668) gains columns for: `group_web_page`, `group_domain`, `domain_web_page`, `allow_embedding`, `group_domain_verified_at`.
+
+`src/Simplex/Chat/Store/Groups.hs`:
+- INSERT (line 367): add all new columns
+- SELECT (line 2375): add `gp.group_web_page`, `gp.group_domain`, `gp.domain_web_page`, `gp.allow_embedding`, `gp.group_domain_verified_at`
+- UPDATE (line 1922): include new columns in `updateGroupProfile_`
+
+### 2. `RelayCapabilities` record, extend `XGrpRelayAcpt`, new `XGrpRelayCap`
+
+**File:** `src/Simplex/Chat/Protocol.hs`
+
+New record for relay capabilities (extensible for future fields):
+```haskell
+data RelayCapabilities = RelayCapabilities
+ { webDomain :: Maybe Text
+ }
+```
+
+TH-derived JSON. All fields optional so old relays produce `{}` and new fields are backward compatible.
+
+**`XGrpRelayAcpt`** - carries capabilities at acceptance time:
+
+Current (line 444): `XGrpRelayAcpt :: ShortLinkContact -> ChatMsgEvent 'Json`
+New: `XGrpRelayAcpt :: ShortLinkContact -> RelayCapabilities -> ChatMsgEvent 'Json`
+
+Parsing: `XGrpRelayAcpt_ -> XGrpRelayAcpt <$> p "relayLink" <*> (p "relayCap" <|> pure defaultRelayCap)`
+Encoding: `XGrpRelayAcpt relayLink cap -> o ["relayLink" .= relayLink, "relayCap" .= cap]`
+Backward compatible: old relays omit `relayCap`, parsed as default (all `Nothing`).
+
+**`XGrpRelayCap`** - new message for ongoing capability updates:
+
+```haskell
+XGrpRelayCap :: RelayCapabilities -> ChatMsgEvent 'Json
+```
+
+Tag: `"x.grp.relay.cap"`
+Parsing: `XGrpRelayCap_ -> XGrpRelayCap <$> p "relayCap"`
+Encoding: `XGrpRelayCap cap -> o ["relayCap" .= cap]`
+
+Sent by relay to owner only when capabilities change (not periodic). Relay detects change by comparing current config against persisted state on startup.
+
+### 3. Store `webDomain` per relay
+
+**File:** `src/Simplex/Chat/Operators.hs` (line 278)
+
+Current:
+```haskell
+data GroupRelay = GroupRelay
+ { groupRelayId :: Int64,
+ groupMemberId :: Int64,
+ userChatRelay :: UserChatRelay,
+ relayStatus :: RelayStatus,
+ relayLink :: Maybe ShortLinkContact
+ }
+```
+
+Add: `relayCap :: Maybe RelayCapabilities`
+
+Stored as separate columns (same pattern as `PublicGroupAccess`):
+**Migration:** `ALTER TABLE group_relays ADD COLUMN base_web_url TEXT`
+
+`relayCap` constructed from columns: `Just RelayCapabilities {webDomain}` when any capability column is non-NULL, `Nothing` otherwise.
+
+**Handlers in `src/Simplex/Chat/Library/Subscriber.hs`:**
+- `XGrpRelayAcpt` (line 770): store `RelayCapabilities` in relay record on acceptance
+- `XGrpRelayCap` (new handler): update `RelayCapabilities` in relay record; only accepted from relay members (`isRelay m`), owner receives
+
+**Relay-side persistence:** relay persists its current `RelayCapabilities` (derived from `RelayWebOptions`) so it can detect config changes on restart. On startup, if persisted capabilities differ from config, relay sends `XGrpRelayCap` to all group owners it serves.
+
+### 4. CLI options for web preview
+
+**File:** `src/Simplex/Chat/Options.hs`
+
+New record bundling all web preview options:
+```haskell
+data RelayWebOptions = RelayWebOptions
+ { webJsonDir :: FilePath, -- --web-json-dir: where to write JSON files
+ webDomain :: Text, -- --web-base-url: public URL prefix (sent in XGrpRelayAcpt)
+ webCorsFile :: FilePath, -- --web-cors-file: generated Caddy CORS config path
+ webUpdateInterval :: Int -- --web-update-interval: seconds (default 300)
+ }
+```
+
+Add as a proper field in `CoreChatOpts`:
+```haskell
+data CoreChatOpts = CoreChatOpts
+ { ...existing...,
+ relayWebOptions :: Maybe RelayWebOptions
+ }
+```
+
+Parsed from CLI: when `--web-json-dir` is provided, all other `--web-*` flags are required. `Nothing` when no web preview flags are set. Only meaningful when `--relay` is also set.
+
+### 5. Web preview thread startup
+
+**File:** `src/Simplex/Chat/Core.hs` (line 74)
+
+Current:
+```haskell
+runSimplexChat ... = do
+ a1 <- runReaderT (startChatController True True) cc
+ when (chatRelay && not testView) $ askCreateRelayAddress cc u
+ forM_ (postStartHook chatHooks) ($ cc)
+ a2 <- async $ chat u cc
+ waitEither_ a1 a2
+```
+
+Add web preview thread as a third async when config is present:
+```haskell
+runSimplexChat ... = do
+ a1 <- runReaderT (startChatController True True) cc
+ when (chatRelay && not testView) $ askCreateRelayAddress cc u
+ forM_ (postStartHook chatHooks) ($ cc)
+ a2 <- async $ chat u cc
+ case relayWebOptions coreOptions of
+ Nothing -> waitEither_ a1 a2
+ Just webOpts -> do
+ a3 <- async $ webPreviewThread webOpts cc
+ void $ waitAnyCancel [a1, a2, a3]
+```
+
+## New Types for JSON Serialization
+
+**File:** new module `src/Simplex/Chat/Web/Preview.hs`
+
+### Reuse as-is (existing ToJSON instances)
+
+- `GroupProfile` (Types.hs:803) - channel metadata (displayName, fullName, shortDescr, description, image, publicGroup incl. groupDomain)
+- `MsgContent` (Protocol.hs:689) - tagged union: MCText, MCLink, MCImage, MCVideo, etc.
+- `LinkPreview` (Protocol.hs:256) - `{uri, title, description, image, content}`
+- `FormattedText` / `MarkdownList` (Markdown.hs:133/139) - parsed markdown
+- `QuotedMsg` / `MsgRef` (Protocol.hs:589) - quoted message context
+- `MsgMentions` = `Map MemberName CIMention` (Messages.hs:264)
+- `CIMention` (Messages.hs:272) - `{memberId, memberRef}`
+- `CIReactionCount` (Messages.hs:338) - `{reaction, userReacted, totalReacted}`
+
+### New types
+
+```haskell
+data WebFileInfo = WebFileInfo
+ { fileName :: String,
+ fileSize :: Integer
+ }
+
+data WebMemberProfile = WebMemberProfile
+ { memberId :: MemberId,
+ displayName :: Text,
+ image :: Maybe ImageData
+ }
+
+data WebMessage = WebMessage
+ { sender :: Maybe MemberId, -- Nothing for CIChannelRcv (forwarded-from-channel)
+ ts :: UTCTime,
+ content :: MsgContent,
+ formattedText :: Maybe MarkdownList,
+ file :: Maybe WebFileInfo,
+ quote :: Maybe QuotedMsg,
+ mentions :: Map MemberName CIMention,
+ reactions :: [CIReactionCount],
+ forwarded :: Maybe CIForwardedFrom,
+ edited :: Bool
+ }
+
+data WebChannelPreview = WebChannelPreview
+ { channel :: GroupProfile, -- NOTE: render loop strips groupDomain until verified
+ subscriberCount :: Maybe Int,
+ members :: [WebMemberProfile],
+ messages :: [WebMessage],
+ updatedAt :: UTCTime
+ }
+```
+
+TH-derived JSON for `WebFileInfo`, `WebMemberProfile`, `WebMessage`, `WebChannelPreview`.
+
+## Render Loop
+
+**File:** new module `src/Simplex/Chat/Web.hs`
+
+Pattern from directory service's `updateListingsThread_` (Service.hs:185-194).
+
+```haskell
+webPreviewThread :: RelayWebOptions -> ChatController -> IO ()
+webPreviewThread opts cc = forever $ do
+ u_ <- readTVarIO $ currentUser cc
+ forM_ u_ $ \user -> do
+ groups <- getWebPublishGroups cc user
+ corsEntries <- forM groups $ \gInfo -> do
+ renderGroupPreview opts cc user gInfo
+ pure (corsEntry gInfo)
+ writeCorsConfig opts corsEntries
+ threadDelay (webUpdateInterval opts * 1_000_000)
+```
+
+### Loading groups
+
+New store function `getWebPublishGroups`:
+```sql
+SELECT ... FROM groups g
+JOIN group_profiles gp ON g.group_profile_id = gp.group_profile_id
+WHERE gp.group_web_page IS NOT NULL
+ AND g.user_id = ?
+```
+
+Returns `[GroupInfo]`. For each, call `getGroupChat` with `CPLast 50` (Store/Messages.hs:1436) to get chat items.
+
+### Converting CChatItem to WebMessage
+
+For each `CChatItem SMDRcv (ChatItem {chatDir, meta, content, mentions, formattedText, quotedItem, reactions, file})`:
+
+1. **Skip if:**
+ - `itemDeleted meta` is `Just _`
+ - `itemTimed meta` is `Just _`
+ - `content` is not `CIRcvMsgContent mc` (skip `CIRcvGroupEvent`, `CIRcvIntegrityError`, etc.)
+ - `mc` is `MCReport` or `MCUnknown`
+
+2. **Extract sender:**
+ - `CIGroupRcv member` -> `Just (memberId member)`, collect member into profiles array
+ - `CIChannelRcv` -> `Nothing` (channel-forwarded message, no individual sender)
+
+3. **Extract file info:**
+ - `file :: Maybe (CIFile 'MDRcv)` has `fileName :: String`, `fileSize :: Integer`
+ - Strip `fileSource`, `fileStatus`, `fileProtocol` (download metadata irrelevant for web)
+
+4. **Build WebMessage:**
+ ```haskell
+ WebMessage
+ { sender = senderMemberId
+ , ts = itemTs meta
+ , content = mc
+ , formattedText = formattedText
+ , file = (\f -> WebFileInfo (fileName f) (fileSize f)) <$> file
+ , quote = quotedItem -- QuotedMsg reused directly
+ , mentions = mentions
+ , reactions = reactions
+ , forwarded = itemForwarded meta
+ , edited = itemEdited meta
+ }
+ ```
+
+5. **Collect unique senders** into `[WebMemberProfile]` from `GroupMember` records in `CIGroupRcv`.
+
+Also include `CIGroupSnd` items (relay's own sent messages, if any - unlikely but possible for admin announcements).
+
+### Filtering unverified domains
+
+Before serializing, the render loop strips `groupDomain` from the `PublicGroupAccess` included in the profile when not verified:
+
+```haskell
+stripUnverifiedDomain :: Maybe UTCTime -> GroupProfile -> GroupProfile
+stripUnverifiedDomain verifiedAt gp = case verifiedAt of
+ Just _ -> gp -- domain verified, include as-is
+ Nothing -> gp {publicGroup = clearDomain <$> publicGroup gp}
+ where
+ clearDomain pgp = pgp {publicGroupAccess = clearAccess <$> publicGroupAccess pgp}
+ clearAccess acc = acc {groupDomain = ""} -- or strip the access record entirely
+```
+
+The `group_domain_verified_at` timestamp is loaded alongside the group info. Until RSLV ships, this column is always NULL, so all domains are stripped from web export.
+
+`domainWebPage` in CORS config is also gated on verified domain - unverified means no domain-site origin in CORS.
+
+### Writing JSON
+
+- Serialize `WebChannelPreview` to JSON via `Data.Aeson.encode`
+- Write atomically (write to temp, rename) to `/.json`
+- `publicGroupId` from `PublicGroupProfile` (base64url-encoded, existing field)
+
+### Generating Caddy CORS config
+
+Write a single file with Caddy `map` directive:
+
+```caddy
+map {path} {cors_origin} {
+ /.json "https://owner-domain.com"
+ /.json "*"
+ default ""
+}
+header /*.json Access-Control-Allow-Origin {cors_origin}
+header /*.json Access-Control-Allow-Methods "GET, OPTIONS"
+```
+
+CORS origin derivation from `PublicGroupAccess`:
+- `allowEmbeding = True` -> `*`
+- `groupWebPage = Just url` -> extract origin from URL (+ domain site origin if `domainWebPage` and domain verified)
+- `groupWebPage = Nothing, domainWebPage = True` -> domain site origin only (when domain is verified)
+- No web page, no embedding, no domain page -> omit from config
+
+After writing, run `caddy reload` if file content changed (compare hash before/after).
+
+## Namespace Integration
+
+`groupDomain` ships now in the profile (inside `PublicGroupAccess`). What's deferred is on-chain verification (RSLV protocol).
+
+### What ships now
+
+1. **`groupDomain :: Text` in `PublicGroupAccess`** - owner sets the registered domain, disseminated to all members
+2. **`domainWebPage :: Bool` in `PublicGroupAccess`** - flag stored but has no effect until domain is verified
+3. **Relay strips `groupDomain` from web export** - no verification means domain is cleared in JSON, no domain-site CORS origin
+
+### What ships with RSLV
+
+1. **RSLV protocol** - relay queries name servers via SMP proxy to verify domain ownership
+2. **`domainWebPage` becomes functional** - enables domain-site hosting (e.g. `simplexnetwork.org/c/`) for verified domains
+3. **In-app resolution** - `#name` markdown (already parsed by namespace branch) resolves and connects
+
+### Verification flow (relay-side)
+
+When owner updates profile with `groupDomain`:
+
+1. **Trigger:** Relay receives profile update on owner's connection containing `groupDomain` field
+2. **Initiate:** Relay sends `RSLV ` through SMP proxy (async, on the same owner connection context)
+3. **Pending state:** `group_domain_verified_at = NULL` in DB. Web export excludes domain while pending.
+4. **Resolution arrives:** `NAME ` agent event arrives on the owner's connection (continuation bound to the connection that sent the profile update)
+5. **Verify:** Check if `channelLinks` in the NAME response includes this group's `groupLink`
+6. **Store result:** Set `group_domain_verified_at = ` on success, leave NULL on failure
+7. **Effect:** Web render loop includes domain in JSON and enables domain-site CORS only when `group_domain_verified_at IS NOT NULL`
+
+Re-verification: periodic (e.g. daily or on each web update cycle) to catch expired/transferred domains. Clear `group_domain_verified_at` when re-verification fails.
+
+### What the namespace branch already provides
+
+- `SimplexNameInfo {nameType, namespace, domain, subDomain}` in Markdown.hs
+- `SimplexName` variant in `Format` ADT
+- Parser for `#name` / `#name.simplex` / `:name.simplex` syntax
+- Forward-compatibility alerts in Kotlin/Swift UI (shows "requires newer app" until resolution is implemented)
+
+## UI Changes (Kotlin/Swift)
+
+### Kotlin types
+
+**File:** `apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt`
+
+```kotlin
+@Serializable
+data class PublicGroupAccess(
+ val groupWebPage: String? = null,
+ val groupDomain: String? = null,
+ val domainWebPage: Boolean = false,
+ val allowEmbeding: Boolean = false
+)
+
+// Extend existing PublicGroupProfile (currently at line 2213):
+@Serializable
+data class PublicGroupProfile(
+ val groupType: GroupType,
+ val groupLink: String,
+ val publicGroupId: String,
+ val publicGroupAccess: PublicGroupAccess? = null // NEW
+)
+
+@Serializable
+data class RelayCapabilities(
+ val webDomain: String? = null
+)
+
+// Extend existing GroupRelay:
+@Serializable
+data class GroupRelay(
+ ...existing fields...,
+ val relayCap: RelayCapabilities? = null // NEW
+)
+```
+
+### Owner: Channel info page
+
+**File:** `GroupChatInfoView.kt` (around line 604-606)
+
+After existing `ChannelLinkButton(manageGroupLink)`:
+```kotlin
+ChannelWebPageButton(openChannelWebPage) // owner only
+```
+
+New nav destination opens `ChannelWebPageView`.
+
+### Owner: Channel web page screen
+
+**File:** new `apps/multiplatform/.../views/chat/group/ChannelWebPageView.kt`
+
+- Text field: web page URL (`groupWebPage`)
+- Text field: domain (`groupDomain`)
+- Toggle: allow embedding (`allowEmbeding`)
+- Toggle: show on domain's page (`domainWebPage`) - stored but inert until RSLV ships
+- Section: embed snippet (read-only, auto-generated from relay `webDomain` values + `publicGroupId`)
+- Save button -> `apiUpdateGroup` with updated `GroupProfile`
+
+### Subscriber: Channel info page
+
+In the top section (around line 607-614), after channel link QR:
+```kotlin
+val webPageUrl = groupInfo.groupProfile.publicGroup?.publicGroupAccess?.groupWebPage
+if (webPageUrl != null) {
+ WebPageLinkRow(webPageUrl) // clickable, opens browser
+}
+```
+
+## Build Configuration
+
+Web preview code compiles into the main `simplex-chat` library (not conditional). The thread only starts when `relayWebOptions` is set in `CoreChatOpts`. Mobile apps never set this.
+
+No cabal flag needed - the thread startup is gated by `Maybe RelayWebOptions` at runtime (same pattern as `chatRelay` gating relay behavior).
+
+## Caddy Setup (operator documentation)
+
+Main Caddyfile (operator writes once):
+```caddy
+relay.example.com {
+ import /etc/caddy/simplex-cors.conf
+ handle /preview/* {
+ root * /var/lib/simplex/web/preview
+ file_server
+ }
+}
+```
+
+Relay CLI invocation:
+```
+simplex-chat --relay \
+ --web-json-dir /var/lib/simplex/web/preview \
+ --web-base-url https://relay.example.com/preview \
+ --web-cors-file /etc/caddy/simplex-cors.conf \
+ --web-update-interval 300
+```
+
+## Channel Page and Embed Code
+
+### Embed snippet (shown to owner)
+
+The "Channel web page" screen auto-generates this from the channel's relay `webDomain` values and `publicGroupId`. Owner copies it into their page:
+
+```html
+
+
+
+```
+
+Example with real values:
+```html
+
+
+
+```
+
+The script fetches `/a1b2c3d4.json`, renders the preview into the `div`. Tries relays in order, falls back on failure. The owner's domain must match the CORS origin configured by the relay (derived from `groupWebPage`), or `allowEmbeding` must be `True` for `*`.
+
+For iframe embedding (when allowed), the snippet is simpler - just an iframe pointing to the owner's hosted channel page.
+
+### Channel page (static JS)
+
+Separate repo or folder. `channel-preview.js` + minimal CSS:
+- Reads config from `data-` attributes on the container div
+- Fetches JSON from relays with fallback (try first, fall back to second)
+- Renders: channel header (name, avatar, description, subscriber count), message list (text with FormattedText markdown, link previews, file indicators, reactions, quotes)
+- Join button: `simplex://` deep link on mobile, QR code on desktop
+- Reuses directory page's markdown rendering approach
+
+## Files to Create/Modify
+
+### New files
+- `src/Simplex/Chat/Web/Preview.hs` - types: `WebChannelPreview`, `WebMessage`, `WebFileInfo`, `WebMemberProfile`
+- `src/Simplex/Chat/Web.hs` - render loop, JSON writing, Caddy config generation
+- `apps/multiplatform/.../views/chat/group/ChannelWebPageView.kt`
+- `apps/ios/Shared/Views/Chat/Group/ChannelWebPageView.swift`
+- Migration files (SQLite + Postgres): `group_web_page`, `group_domain`, `domain_web_page`, `allow_embedding`, `group_domain_verified_at` in group_profiles; `base_web_url` in group_relays
+- Channel page static site (separate repo/folder)
+
+### Modified files
+- `src/Simplex/Chat/Types.hs` - `PublicGroupAccess` type, extend `PublicGroupProfile` with `publicGroupAccess`
+- `src/Simplex/Chat/Protocol.hs` - `RelayCapabilities` record, extend `XGrpRelayAcpt`, add `XGrpRelayCap`
+- `src/Simplex/Chat/Options.hs` - `RelayWebOptions` record, `relayWebOptions :: Maybe RelayWebOptions` in `CoreChatOpts`
+- `src/Simplex/Chat/Core.hs` - start web preview thread in `runSimplexChat`
+- `src/Simplex/Chat/Operators.hs` - `webDomain` in `GroupRelay`
+- `src/Simplex/Chat/Store/Groups.hs` - read/write `PublicGroupAccess` columns; `getWebPublishGroups`
+- `src/Simplex/Chat/Store/Shared.hs` - `toPublicGroupAccess`, extend `toPublicGroupProfile` and `GroupInfoRow`
+- `src/Simplex/Chat/Library/Subscriber.hs` - handle `RelayCapabilities` in `XGrpRelayAcpt` and `XGrpRelayCap`
+- `apps/multiplatform/.../model/ChatModel.kt` - `PublicGroupAccess`, `RelayCapabilities`, `PublicGroupProfile.publicGroupAccess`, `GroupRelay.relayCap`
+- `apps/multiplatform/.../views/chat/group/GroupChatInfoView.kt` - nav link for web page
+- `simplex-chat.cabal` - add `Simplex.Chat.Web.Preview`, `Simplex.Chat.Web` to exposed-modules
+
+## Implementation Order
+
+1. **Data model** - `PublicGroupAccess` in `PublicGroupProfile`, migrations (separate columns), store functions
+2. **Protocol** - `RelayCapabilities`, extend `XGrpRelayAcpt`, add `XGrpRelayCap`, handlers in Subscriber.hs
+3. **CLI options** - `RelayWebOptions` record, `relayWebOptions` field in `CoreChatOpts`
+4. **Web types** - `WebChannelPreview`, `WebMessage`, etc. in new module
+5. **Render loop** - thread startup in Core.hs, periodic JSON generation, Caddy config
+6. **UI (owner)** - "Channel web page" settings screen
+7. **UI (subscriber)** - web page link in channel info
+8. **Channel page** - static HTML+JS template
+9. **Documentation** - operator setup guide
+
+## Verification
+
+1. **Build**: `cabal build simplex-chat` with new modules compiles
+2. **Unit test**: serialize `WebChannelPreview` with sample data, verify JSON matches expected structure
+3. **Integration test**: create channel with `publicGroupAccess` set, run relay with `--web-json-dir`, verify JSON file appears at correct path with correct content
+4. **CORS test**: verify generated config produces correct `Access-Control-Allow-Origin` for configured domains
+5. **UI test**: owner can set web page URL and domain, see embed snippet; subscriber sees clickable link
+6. **Channel page test**: serve static page locally against relay's JSON, verify rendering
+7. **Domain stripping test**: set `groupDomain` on a channel, verify it is stripped from web export JSON (unverified, `group_domain_verified_at IS NULL`)
diff --git a/plans/2026-05-29-fix-space-in-interface.md b/plans/2026-05-29-fix-space-in-interface.md
new file mode 100644
index 0000000000..e3d8ba7cc4
--- /dev/null
+++ b/plans/2026-05-29-fix-space-in-interface.md
@@ -0,0 +1,13 @@
+# Fix `/start remote host` parser when iface name contains a space
+
+## Problem
+
+Picking a non-default interface (e.g. Windows `Ethernet 2`) on the "Link a mobile" screen and refreshing the QR code returns `error chat: error chat commandError Failed reading: empty`. The desktop UI sends `/start remote host new addr=… iface="Ethernet 2" port=…`; the chat backend rejects it as an unparseable command. Without a workaround the user can't pin a specific local interface for the mobile-link controller.
+
+## Cause
+
+`rcCtrlAddressP` parses the iface value with `jsonP <|> text1P` (`src/Simplex/Chat/Library/Commands.hs:5549`). `jsonP` calls `A.takeByteString`, consuming *all* remaining input, then runs `eitherDecodeStrict'`. When `port=…` follows `iface=…` the strict decode fails because the JSON value `"Ethernet 2"` has trailing junk after it, so attoparsec backtracks to `text1P` (`takeTill (== ' ')`). `text1P` stops at the first space — inside the JSON quotes — leaving `2" port=12345` which nothing downstream can consume, `A.endOfInput` fails, the whole `A.choice` exhausts and surfaces attoparsec's `empty` message. With an iface name that has no space (`"lo"`) the bug is invisible: text1P swallows the full quoted token and the rest parses, but the interface name is stored with literal quotes so the iface preference silently never matches a real adapter anyway.
+
+## Fix
+
+Replace `jsonP` with a bounded `quotedP` that consumes only the bytes between `"…"` and leaves trailing fields for the next parser. `text1P` is kept as the unquoted fallback. Two-line change in `Commands.hs` plus a pure regression test in `tests/RemoteTests.hs` that asserts `parseChatCommand` of `/start remote host new addr=192.168.1.5 iface="Ethernet 2" port=12345` produces `RCCtrlAddress _ "Ethernet 2"` with port `12345`.
diff --git a/plans/cli-paste-slowness.md b/plans/cli-paste-slowness.md
deleted file mode 100644
index 33255996be..0000000000
--- a/plans/cli-paste-slowness.md
+++ /dev/null
@@ -1,111 +0,0 @@
-# CLI terminal: event loss root cause analysis
-
-## Two distinct problems
-
-### Problem 1: Paste — TMVar capacity-1 bottleneck
-
-When copy-pasting text, the capacity-1 `TMVar` event channel between the keyboard input reader and the consumer loop throttles stdin reading to terminal redraw speed.
-
-**Root cause:** `events <- liftIO newEmptyTMVarIO` (`Platform.hsc:64`). Producer blocks on `putTMVar` after each event until consumer finishes redrawing. Consumer does a full terminal redraw per event (`Input.hs:161`).
-
-**Fix:** Replace `TMVar` with `TQueue` in `Platform.hsc` (6 line changes on POSIX, matching changes on Windows). Decouples producer from consumer — stdin is drained at full speed regardless of redraw speed.
-
-See previous analysis in git history for full details on this issue.
-
----
-
-### Problem 2: Heavy load — `outputQ` backpressure blocks `agentSubscriber`
-
-When the CLI is used as a heavy client (e.g., 1M connections), incoming chat events overwhelm the terminal display, causing cascading backpressure that blocks message acknowledgments and stalls the entire event processing pipeline.
-
-**This is the more severe problem.** It causes actual message loss at the protocol level, not just UI slowness.
-
-## Root cause: bounded `outputQ` + single-threaded `agentSubscriber`
-
-### The queue chain
-
-```
-Network (SMP/XFTP connections)
- → agent internal queues
- → subQ (TBQueue, capacity 1024) ← agent → chat boundary
- → agentSubscriber (single-threaded) ← Commands.hs:4167
- → processAgentMessage ← Subscriber.hs:109
- → toView_ → writeTBQueue outputQ ← Controller.hs:1528, BLOCKS when full
- → outputQ (TBQueue, capacity 1024) ← Chat.hs:152
- → runTerminalOutput ← Output.hs:146
- → printToTerminal (acquires termLock) ← Output.hs:298-303
- → terminal I/O (slow)
-```
-
-All queues are bounded `TBQueue` with default capacity 1024 (`Options.hs:226`). All writes use `writeTBQueue` which **blocks when full** — no events are dropped within the application, but backpressure cascades upstream.
-
-### The blocking chain under heavy load
-
-1. **Terminal I/O is the bottleneck.** `runTerminalOutput` (`Output.hs:146`) reads one event at a time from `outputQ`, acquires `termLock`, prints the message + redraws input, releases lock. Each iteration involves ANSI escape sequences, cursor manipulation, and `flush` syscalls. Throughput: ~hundreds of events/sec at best.
-
-2. **`outputQ` fills up.** With 1M connections generating events, the arrival rate far exceeds terminal display speed. The 1024-element TBQueue fills in seconds.
-
-3. **`toView_` blocks.** `Controller.hs:1528`: `writeTBQueue localQ (Nothing, event)` blocks when the queue is full. This call happens inside `processAgentMessage` → `processAgentMessageConn`, which runs within the `agentSubscriber` loop.
-
-4. **`agentSubscriber` blocks — head-of-line blocking.** `Commands.hs:4164-4167`:
- ```haskell
- agentSubscriber = do
- q <- asks $ subQ . smpAgent
- forever (atomically (readTBQueue q) >>= process)
- ```
- Single-threaded. When `process` blocks on `toView_`, ALL events for ALL connections queue up behind it. Events for 1M other connections — including time-critical ACKs, keepalives, and handshakes — are stuck.
-
-5. **ACKs are never sent.** The message receive path (`Subscriber.hs:1537-1540`) calls `toView` BEFORE `ackMsg`:
- ```haskell
- -- Inside withAckMessage's action:
- saveRcvChatItem' ... -- save to DB (succeeds)
- toView $ CEvtNewChatItems ... -- BLOCKS here (outputQ full)
- -- returns (withRcpt, shouldDelConns)
-
- -- After action returns (Subscriber.hs:1396-1397):
- ackMsg msgMeta ... -- NEVER REACHED while toView blocks
- ```
- The developers explicitly acknowledge this at `Subscriber.hs:122-123`:
- > *without ACK the message delivery will be stuck*
-
-6. **`subQ` fills up.** The agent can't deliver events to `subQ` (also capacity 1024) because `agentSubscriber` isn't reading. Agent-level processing stalls.
-
-7. **Network-level failure.** Connections time out due to unprocessed keepalives and unacknowledged messages. Messages are lost at the protocol level.
-
-### `termLock` contention worsens the bottleneck
-
-`termLock` (`Output.hs:55`) is a `TMVar ()` mutex shared between:
-- **Output thread** (`runTerminalOutput` → `printToTerminal`): acquires lock for each displayed message
-- **Input thread** (`receiveFromTTY` → `updateInput`): acquires lock after each keystroke
-- **Live prompt thread** (`blinkLivePrompt` → `updateInputView`): acquires lock every 1 second
-
-Under heavy load, the output thread dominates the lock (constant stream of messages). The input thread is starved — user keystrokes are delayed. This also slows the output thread itself (lock contention overhead).
-
-Note: `withTermLock` (`Output.hs:138-142`) is not exception-safe — no `bracket`/`finally`. If the action throws, the lock leaks and all threads deadlock.
-
-### Error reporting also blocks
-
-When `processAgentMessage` encounters an error, the error handler (`Commands.hs:4179`) calls `eToView'` → `toView_` → `writeTBQueue outputQ`. If `outputQ` is already full, even error reporting blocks. There is no escape path.
-
-## Impact summary
-
-| Load level | `outputQ` state | Effect |
-|---|---|---|
-| Light (few connections) | Nearly empty | No issues |
-| Moderate (hundreds) | Partially filled | Occasional display lag |
-| Heavy (thousands+) | Full (1024) | `toView_` blocks → `agentSubscriber` blocks → head-of-line blocking for ALL connections → ACKs delayed → message delivery stuck |
-| Extreme (1M connections) | Permanently full | Cascading failure: all event processing stops, connections time out, messages lost at protocol level |
-
-## Fix
-
-The core fix: **`toView_` must never block the event processing pipeline on terminal display.**
-
-Options (in order of simplicity):
-
-1. **Make `outputQ` unbounded** — replace `TBQueue` with `TQueue` in `Chat.hs:152`. `writeTQueue` never blocks. Events accumulate in memory under heavy load but the event processing pipeline (including ACKs) is never stalled. Tradeoff: unbounded memory growth under sustained heavy load.
-
-2. **Non-blocking write with drop** — use `tryWriteTBQueue` in `toView_`. When `outputQ` is full, drop the display event (or a coalesced summary). ACKs and network processing proceed unblocked. Tradeoff: some events not displayed, but none lost at protocol level.
-
-3. **Separate ACK from display** — restructure `withAckMessage` to send ACK immediately after DB save, before `toView`. This decouples protocol correctness from display. `toView` can still block, but ACKs are always timely. Tradeoff: requires careful restructuring of the message processing path.
-
-4. **Increase queue capacity** — increase `tbqSize` from 1024 to a larger value. Delays the problem but doesn't fix it. Under sustained heavy load, any finite queue eventually fills.
diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix
index e4532c49b5..5ce5bca19a 100644
--- a/scripts/nix/sha256map.nix
+++ b/scripts/nix/sha256map.nix
@@ -1,5 +1,5 @@
{
- "https://github.com/simplex-chat/simplexmq.git"."f0b7a4be7325cb787297a881076299c5ffbe26e7" = "0a8a9l31l4a9nilcqg8h60mrxpqxpzzqxi58i60nw8h4vxqqlzcz";
+ "https://github.com/simplex-chat/simplexmq.git"."61ee188ee0839c34de16bc17934f04ebc7fd4873" = "0ap5khdfwzi9gzc96y916hngmbl3c4ivkbf33anmv2r8n15bkkp0";
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
diff --git a/simplex-chat.cabal b/simplex-chat.cabal
index 4c0b8e4452..13a331d638 100644
--- a/simplex-chat.cabal
+++ b/simplex-chat.cabal
@@ -5,7 +5,7 @@ cabal-version: 1.12
-- see: https://github.com/sol/hpack
name: simplex-chat
-version: 6.5.3.0
+version: 6.5.4.1
category: Web, System, Services, Cryptography
homepage: https://github.com/simplex-chat/simplex-chat#readme
author: simplex.chat
@@ -133,10 +133,11 @@ library
Simplex.Chat.Store.Postgres.Migrations.M20260429_relay_request_retries
Simplex.Chat.Store.Postgres.Migrations.M20260507_relay_inactive_at
Simplex.Chat.Store.Postgres.Migrations.M20260514_relay_request_group_link_index
- Simplex.Chat.Store.Postgres.Migrations.M20260515_delivery_job_senders
- Simplex.Chat.Store.Postgres.Migrations.M20260520_client_services
- Simplex.Chat.Store.Postgres.Migrations.M20260525_member_removed_at
- Simplex.Chat.Store.Postgres.Migrations.M20260526_group_roster
+ Simplex.Chat.Store.Postgres.Migrations.M20260515_public_group_access
+ Simplex.Chat.Store.Postgres.Migrations.M20260529_delivery_job_senders
+ Simplex.Chat.Store.Postgres.Migrations.M20260530_client_services
+ Simplex.Chat.Store.Postgres.Migrations.M20260531_member_removed_at
+ Simplex.Chat.Store.Postgres.Migrations.M20260601_group_roster
else
exposed-modules:
Simplex.Chat.Archive
@@ -292,10 +293,11 @@ library
Simplex.Chat.Store.SQLite.Migrations.M20260429_relay_request_retries
Simplex.Chat.Store.SQLite.Migrations.M20260507_relay_inactive_at
Simplex.Chat.Store.SQLite.Migrations.M20260514_relay_request_group_link_index
- Simplex.Chat.Store.SQLite.Migrations.M20260515_delivery_job_senders
- Simplex.Chat.Store.SQLite.Migrations.M20260520_client_services
- Simplex.Chat.Store.SQLite.Migrations.M20260525_member_removed_at
- Simplex.Chat.Store.SQLite.Migrations.M20260526_group_roster
+ Simplex.Chat.Store.SQLite.Migrations.M20260515_public_group_access
+ Simplex.Chat.Store.SQLite.Migrations.M20260529_delivery_job_senders
+ Simplex.Chat.Store.SQLite.Migrations.M20260530_client_services
+ Simplex.Chat.Store.SQLite.Migrations.M20260531_member_removed_at
+ Simplex.Chat.Store.SQLite.Migrations.M20260601_group_roster
other-modules:
Paths_simplex_chat
hs-source-dirs:
@@ -502,7 +504,7 @@ executable simplex-directory-service
Directory.Store.Migrate
Directory.Util
Paths_simplex_chat
- ghc-options: -O2 -Weverything -Wno-missing-exported-signatures -Wno-missing-import-lists -Wno-missed-specialisations -Wno-all-missed-specialisations -Wno-unsafe -Wno-safe -Wno-missing-local-signatures -Wno-missing-kind-signatures -Wno-missing-deriving-strategies -Wno-monomorphism-restriction -Wno-prepositive-qualified-module -Wno-unused-packages -Wno-implicit-prelude -Wno-missing-safe-haskell-mode -Wno-missing-export-lists -Wno-partial-fields -Wcompat -Werror=incomplete-record-updates -Werror=incomplete-patterns -Werror=missing-methods -Werror=incomplete-uni-patterns -Werror=tabs -Wredundant-constraints -Wincomplete-record-updates -Wunused-type-patterns -threaded
+ ghc-options: -O2 -Weverything -Wno-missing-exported-signatures -Wno-missing-import-lists -Wno-missed-specialisations -Wno-all-missed-specialisations -Wno-unsafe -Wno-safe -Wno-missing-local-signatures -Wno-missing-kind-signatures -Wno-missing-deriving-strategies -Wno-monomorphism-restriction -Wno-prepositive-qualified-module -Wno-unused-packages -Wno-implicit-prelude -Wno-missing-safe-haskell-mode -Wno-missing-export-lists -Wno-partial-fields -Wcompat -Werror=incomplete-record-updates -Werror=incomplete-patterns -Werror=missing-methods -Werror=incomplete-uni-patterns -Werror=tabs -Wredundant-constraints -Wincomplete-record-updates -Wunused-type-patterns -threaded -rtsopts
build-depends:
aeson ==2.2.*
, async ==2.2.*
diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs
index 402bfa6b10..27b3fedae6 100644
--- a/src/Simplex/Chat/Controller.hs
+++ b/src/Simplex/Chat/Controller.hs
@@ -1053,6 +1053,7 @@ data GroupLinkPlan
| GLPConnectingProhibit {groupInfo_ :: Maybe GroupInfo}
| GLPKnown {groupInfo :: GroupInfo, groupUpdated :: BoolDef, ownerVerification :: Maybe OwnerVerification, linkOwners :: ListDef GroupLinkOwner}
| GLPNoRelays {groupSLinkData_ :: Maybe GroupShortLinkData}
+ | GLPUpdateRequired {groupSLinkData_ :: Maybe GroupShortLinkData}
deriving (Show)
data GroupLinkOwner = GroupLinkOwner
@@ -1098,6 +1099,7 @@ connectionPlanProceed = \case
GLPOwnLink _ -> True
GLPConnectingConfirmReconnect -> True
GLPNoRelays _ -> False
+ GLPUpdateRequired _ -> False
_ -> False
CPError _ -> True
diff --git a/src/Simplex/Chat/Library/Commands.hs b/src/Simplex/Chat/Library/Commands.hs
index 5eba2db802..b1183127a5 100644
--- a/src/Simplex/Chat/Library/Commands.hs
+++ b/src/Simplex/Chat/Library/Commands.hs
@@ -2535,7 +2535,8 @@ processChatCommand vr nm = \case
-- generate owner key, OwnerAuth signed by root key
memberId <- MemberId <$> liftIO (encodedRandomBytes gVar 12)
(memberPrivKey, ownerAuth) <- liftIO $ SL.newOwnerAuth gVar (unMemberId memberId) rootPrivKey
- let groupProfile' = (groupProfile :: GroupProfile) {publicGroup = Just PublicGroupProfile {groupType = GTChannel, groupLink = sLnk, publicGroupId = B64UrlByteString entityId}}
+ -- TODO [channel web] pass publicGroupAccess from owner's profile
+ let groupProfile' = (groupProfile :: GroupProfile) {publicGroup = Just PublicGroupProfile {groupType = GTChannel, groupLink = sLnk, publicGroupId = B64UrlByteString entityId, publicGroupAccess = Nothing}}
userData = encodeShortLinkData $ GroupShortLinkData {groupProfile = groupProfile', publicGroupData = Just (PublicGroupData 1)}
userLinkData = UserContactLinkData UserContactData {direct = False, owners = [ownerAuth], relays = [], userData}
-- create connection with prepared link (single network call)
@@ -2653,8 +2654,7 @@ processChatCommand vr nm = \case
Nothing -> throwChatError $ CEContactNotActive ct
APIAcceptMember groupId gmId role -> withUser $ \user@User {userId} -> do
(gInfo, m) <- withFastStore $ \db -> (,) <$> getGroupInfo db vr user groupId <*> getGroupMemberById db vr user gmId
- -- TODO check that user's role is > role, possibly restrict role to only observer and member
- assertUserGroupRole gInfo GRModerator
+ assertUserGroupRole gInfo $ max GRModerator role
case memberStatus m of
GSMemPendingApproval | memberCategory m == GCInviteeMember -> do -- only host can approve
let GroupInfo {groupProfile = GroupProfile {memberAdmission}} = gInfo
@@ -4149,21 +4149,25 @@ processChatCommand vr nm = \case
Nothing -> do
(fd, cData@(ContactLinkData _ UserContactData {direct, owners, relays})) <- getShortLinkConnReq' nm user l'
groupSLinkData_ <- liftIO $ decodeLinkUserData cData
- if not direct && null relays
- then pure (con (linkConnReq fd), CPGroupLink (GLPNoRelays groupSLinkData_))
- else do
- let FixedLinkData {linkConnReq = cReq, linkEntityId, rootKey} = fd
- linkInfo = GroupShortLinkInfo {direct, groupRelays = relays, publicGroupId = B64UrlByteString <$> linkEntityId}
- let profilePGId = groupSLinkData_ >>= \GroupShortLinkData {groupProfile = GroupProfile {publicGroup}} ->
- fmap (\PublicGroupProfile {publicGroupId} -> publicGroupId) publicGroup
- case (B64UrlByteString <$> linkEntityId, profilePGId) of
- (Just entityId, Just publicGroupId) | entityId == publicGroupId -> pure ()
- (Nothing, Nothing) -> pure ()
- _ -> throwChatError CEInvalidConnReq
- let ov = verifyLinkOwner rootKey owners l' sig_
- plan <- groupJoinRequestPlan user cReq (Just linkInfo) groupSLinkData_ ov
- pure (con cReq, plan)
+ if
+ | not direct && unsupportedGroupType groupSLinkData_ -> pure (con (linkConnReq fd), CPGroupLink (GLPUpdateRequired groupSLinkData_))
+ | not direct && null relays -> pure (con (linkConnReq fd), CPGroupLink (GLPNoRelays groupSLinkData_))
+ | otherwise -> do
+ let FixedLinkData {linkConnReq = cReq, linkEntityId, rootKey} = fd
+ linkInfo = GroupShortLinkInfo {direct, groupRelays = relays, publicGroupId = B64UrlByteString <$> linkEntityId}
+ let profilePGId = groupSLinkData_ >>= \GroupShortLinkData {groupProfile = GroupProfile {publicGroup}} ->
+ fmap (\PublicGroupProfile {publicGroupId} -> publicGroupId) publicGroup
+ case (B64UrlByteString <$> linkEntityId, profilePGId) of
+ (Just entityId, Just publicGroupId) | entityId == publicGroupId -> pure ()
+ (Nothing, Nothing) -> pure ()
+ _ -> throwChatError CEInvalidConnReq
+ let ov = verifyLinkOwner rootKey owners l' sig_
+ plan <- groupJoinRequestPlan user cReq (Just linkInfo) groupSLinkData_ ov
+ pure (con cReq, plan)
where
+ unsupportedGroupType = \case
+ Just GroupShortLinkData {groupProfile = GroupProfile {publicGroup = Just PublicGroupProfile {groupType}}} -> groupType /= GTChannel
+ _ -> False
knownLinkPlans = withFastStore $ \db ->
liftIO (getGroupInfoViaUserShortLink db vr user l') >>= \case
Just (cReq, g) -> pure $ Just (con cReq, CPGroupLink (GLPOwnLink g))
@@ -5563,7 +5567,8 @@ chatCommandP =
addressAA = AddressSettings False <$> (Just . AutoAccept <$> (" incognito=" *> onOffP <|> pure False)) <*> autoReply
businessAA = " business" *> (AddressSettings True (Just $ AutoAccept False) <$> autoReply)
autoReply = optional (A.space *> msgContentP)
- rcCtrlAddressP = RCCtrlAddress <$> ("addr=" *> strP) <*> (" iface=" *> (jsonP <|> text1P))
+ rcCtrlAddressP = RCCtrlAddress <$> ("addr=" *> strP) <*> (" iface=" *> (quotedP <|> text1P))
+ quotedP = safeDecodeUtf8 <$> (A.char '"' *> A.takeTill (== '"') <* A.char '"')
text1P = safeDecodeUtf8 <$> A.takeTill (== ' ')
char_ = optional . A.char
@@ -5584,17 +5589,25 @@ mkValidName :: String -> String
mkValidName = dropWhileEnd isSpace . take 50 . reverse . fst3 . foldl' addChar ("", '\NUL', 0 :: Int)
where
fst3 (x, _, _) = x
- addChar (r, prev, punct) c = if validChar then (c' : r, c', punct') else (r, prev, punct)
+ addChar (r, prev, punct) c' = if validChar then (c : r, c, punct') else (r, prev, punct)
where
- c' = if isSpace c then ' ' else c
+ c = if isSpace c' then ' ' else c'
+ cat = generalCategory c
+ isPunct = case cat of
+ ConnectorPunctuation -> True
+ DashPunctuation -> True
+ OtherPunctuation -> True
+ _ -> False
punct'
- | isPunctuation c = punct + 1
- | isSpace c = punct
+ | isPunct = punct + 1
+ | c == ' ' = punct
| otherwise = 0
validChar
- | c == '\'' = False
- | prev == '\NUL' = c > ' ' && c /= '#' && c /= '@' && validFirstChar
- | isSpace prev = validFirstChar || (punct == 0 && isPunctuation c)
- | isPunctuation prev = validFirstChar || isSpace c || (punct < 3 && isPunctuation c)
- | otherwise = validFirstChar || isSpace c || isMark c || isPunctuation c
- validFirstChar = isLetter c || isNumber c || isSymbol c
+ | c `elem` prohibited = False
+ | prev == '\NUL' = c > ' ' && validFirstNameChar
+ | prev == ' ' = validFirstChar || (punct == 0 && isPunct)
+ | punct > 0 = validFirstChar || c == ' '
+ | otherwise = validFirstChar || c == ' ' || isMark c || isPunct
+ validFirstNameChar = isLetter c || cat == DecimalNumber || cat == OtherSymbol
+ validFirstChar = validFirstNameChar || cat == CurrencySymbol || cat == MathSymbol
+ prohibited = ".,;/\\#@'\"`~" :: String
diff --git a/src/Simplex/Chat/Library/Internal.hs b/src/Simplex/Chat/Library/Internal.hs
index 96727f7d3a..548c7b230b 100644
--- a/src/Simplex/Chat/Library/Internal.hs
+++ b/src/Simplex/Chat/Library/Internal.hs
@@ -1045,7 +1045,8 @@ acceptRelayJoinRequestAsync
cReqInvId
cReqChatVRange
relayLink = do
- let msg = XGrpRelayAcpt relayLink
+ -- TODO [channel web] derive RelayCapabilities from relay config (RelayWebOptions)
+ let msg = XGrpRelayAcpt relayLink defaultRelayCapabilities
subMode <- chatReadVar subscriptionMode
vr <- chatVersionRange
let chatV = vr `peerConnChatVersion` cReqChatVRange
diff --git a/src/Simplex/Chat/Library/Subscriber.hs b/src/Simplex/Chat/Library/Subscriber.hs
index 0df684d006..d65ab7bf39 100644
--- a/src/Simplex/Chat/Library/Subscriber.hs
+++ b/src/Simplex/Chat/Library/Subscriber.hs
@@ -774,9 +774,11 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
-- [async agent commands] no continuation needed, but command should be asynchronous for stability
allowAgentConnectionAsync user conn' confId XOk
| otherwise -> messageError "x.grp.acpt: memberId is different from expected"
- XGrpRelayAcpt relayLink
+ XGrpRelayAcpt relayLink relayCap
| memberRole' membership == GROwner && isRelay m -> do
- withStore' $ \db -> setRelayLinkConfId db m confId relayLink
+ withStore' $ \db -> do
+ setRelayLinkConfId db m confId relayLink
+ updateRelayCapabilities db m relayCap
void $ getAgentConnShortLinkAsync user CFGetRelayDataAccept (Just conn') relayLink
| otherwise -> messageError "x.grp.relay.acpt: only owner can add relay"
XGrpRelayReject reason
@@ -1045,6 +1047,10 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
XGrpLinkMem p -> Nothing <$ xGrpLinkMem gInfo' m'' conn' p
XGrpLinkAcpt acceptance role memberId -> Nothing <$ xGrpLinkAcpt gInfo' m'' acceptance role memberId msg brokerTs
XGrpRelayNew rl -> fmap ctx <$> xGrpRelayNew gInfo' m'' rl
+ XGrpRelayCap relayCap
+ | memberRole' membership == GROwner && isRelay m'' ->
+ Nothing <$ withStore' (\db -> updateRelayCapabilities db m'' relayCap)
+ | otherwise -> Nothing <$ messageWarning "x.grp.relay.cap: only owner should receive relay capabilities"
XGrpMemNew memInfo msgScope -> fmap ctx <$> xGrpMemNew gInfo' m'' memInfo msgScope msg brokerTs
XGrpMemIntro memInfo memRestrictions_ -> Nothing <$ xGrpMemIntro gInfo' m'' memInfo memRestrictions_
XGrpMemInv memId introInv -> Nothing <$ xGrpMemInv gInfo' m'' memId introInv
@@ -2617,6 +2623,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
xGrpLinkAcpt :: GroupInfo -> GroupMember -> GroupAcceptance -> GroupMemberRole -> MemberId -> RcvMessage -> UTCTime -> CM ()
xGrpLinkAcpt gInfo@GroupInfo {membership} m acceptance role memberId msg brokerTs
+ | memberRole' m < GRModerator || memberRole' m < role =
+ messageError "x.grp.link.acpt with insufficient member permissions"
| sameMemberId memberId membership = processUserAccepted
| otherwise =
withStore' (\db -> runExceptT $ getGroupMemberByMemberId db vr user gInfo memberId) >>= \case
diff --git a/src/Simplex/Chat/Markdown.hs b/src/Simplex/Chat/Markdown.hs
index 9325de41eb..9507375527 100644
--- a/src/Simplex/Chat/Markdown.hs
+++ b/src/Simplex/Chat/Markdown.hs
@@ -35,11 +35,11 @@ import Data.Text (Text)
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8)
import Simplex.Chat.Types
-import Simplex.Messaging.Agent.Protocol (AConnectionLink (..), ConnReqUriData (..), ConnShortLink (..), ConnectionLink (..), ConnectionRequestUri (..), ContactConnType (..), SMPQueue (..), simplexConnReqUri, simplexShortLink)
+import Simplex.Messaging.Agent.Protocol (AConnectionLink (..), ConnReqUriData (..), ConnShortLink (..), ConnectionLink (..), ConnectionRequestUri (..), ContactConnType (..), SMPQueue (..), SimplexNameInfo (..), simplexConnReqUri, simplexShortLink)
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, enumJSON, fstToLower, sumTypeJSON)
import Simplex.Messaging.Protocol (ProtocolServer (..))
-import Simplex.Messaging.Util (decodeJSON, safeDecodeUtf8, tshow)
+import Simplex.Messaging.Util (decodeJSON, safeDecodeUtf8, tshow, (<$?>))
import System.Console.ANSI.Types
import qualified Text.Email.Validate as Email
import qualified URI.ByteString as U
@@ -59,6 +59,7 @@ data Format
-- showText is Nothing for the usual Uri without text
| HyperLink {showText :: Maybe Text, linkUri :: Text}
| SimplexLink {showText :: Maybe Text, linkType :: SimplexLinkType, simplexUri :: AConnectionLink, smpHosts :: NonEmpty Text}
+ | SimplexName {nameInfo :: SimplexNameInfo}
| Command {commandStr :: Text}
| Mention {memberName :: Text}
| Email
@@ -184,6 +185,7 @@ isLink = \case
Uri -> True
HyperLink {} -> True
SimplexLink {} -> True
+ SimplexName {} -> True
_ -> False
hasLinks :: MarkdownList -> Bool
@@ -202,9 +204,9 @@ markdownP = mconcat <$> A.many' fragmentP
'_' -> formattedP '_' Italic
'~' -> formattedP '~' StrikeThrough
'`' -> formattedP '`' Snippet
- '#' -> A.char '#' *> secretP
+ '#' -> A.char '#' *> (secretP <|> nameRefP '#' <|> secretFallback)
'!' -> styledP <|> wordP
- '@' -> mentionP <|> wordP
+ '@' -> (A.char '@' *> nameRefP '@') <|> mentionP <|> wordP
'/' -> commandP <|> wordP
'[' -> sowLinkP <|> wordP
_
@@ -221,14 +223,29 @@ markdownP = mconcat <$> A.many' fragmentP
unmarked $ c `T.cons` s `T.snoc` c
| otherwise = markdown f s
secretP :: Parser Markdown
- secretP = secret <$> A.takeWhile (== '#') <*> A.takeTill (== '#') <*> A.takeWhile (== '#')
- secret :: Text -> Text -> Text -> Markdown
- secret b s a
- | T.null a || T.null s || T.head s == ' ' || T.last s == ' ' =
- unmarked $ '#' `T.cons` ss
- | otherwise = markdown Secret $ T.init ss
+ secretP = secret <$?> ((,,) <$> A.takeWhile (== '#') <*> A.takeTill (== '#') <*> A.takeWhile1 (== '#'))
+ secret :: (Text, Text, Text) -> Either String Markdown
+ secret (b, s, a)
+ | T.null s || T.head s == ' ' || T.last s == ' ' = Left "not secret"
+ | otherwise = Right $ markdown Secret $ T.init ss
where
ss = b <> s <> a
+ secretFallback :: Parser Markdown
+ secretFallback = unmarked . ('#' `T.cons`) <$> A.takeTill (== ' ')
+ nameRefP :: Char -> Parser Markdown
+ nameRefP pfx = nameRef <$?> A.takeTill (== ' ')
+ where
+ nameRef word
+ | pfx == '@' && T.all (/= '.') name = Left "not a name"
+ | otherwise = mkMd <$> strDecode (encodeUtf8 full)
+ where
+ (name, punct) = splitPunctuation word
+ full = pfx `T.cons` name
+ mkMd ni
+ | T.null punct = md'
+ | otherwise = md' :|: unmarked punct
+ where
+ md' = markdown (SimplexName ni) full
styledP :: Parser Markdown
styledP = do
f <- A.char '!' *> ((A.char '-' $> Small) <|> (colored <$> colorP)) <* A.space
@@ -449,6 +466,7 @@ markdownText (FormattedText f_ t) = case f_ of
Uri -> t
HyperLink {} -> t
SimplexLink {} -> t
+ SimplexName {} -> t
Mention _ -> t
Command _ -> t
Email -> t
@@ -479,7 +497,6 @@ displayNameTextP_ = (,"") <$> quoted '\'' <|> splitPunctuation <$> takeNameTill
takeNameTill p =
A.peekChar' >>= \c ->
if refChar c then A.takeTill p else fail "invalid first character in display name"
- splitPunctuation s = (T.dropWhileEnd isPunctuation s, T.takeWhileEnd isPunctuation s)
quoted c = A.char c *> takeNameTill (== c) <* A.char c
refChar c = c > ' ' && c /= '#' && c /= '@' && c /= '\''
@@ -490,6 +507,9 @@ commandTextP = do
(keyword : _) | T.all (\c -> isAlpha c || isDigit c || c == '_') keyword -> pure (cmd, punct)
_ -> fail "invalid command keyword"
+splitPunctuation :: Text -> (Text, Text)
+splitPunctuation s = (T.dropWhileEnd isPunctuation s, T.takeWhileEnd isPunctuation s)
+
-- quotes names that contain spaces or end on punctuation
viewName :: Text -> Text
viewName s = if T.any isSpace s || maybe False (isPunctuation . snd) (T.unsnoc s) then "'" <> s <> "'" else s
diff --git a/src/Simplex/Chat/Operators.hs b/src/Simplex/Chat/Operators.hs
index 03cc38e12a..6816a5f692 100644
--- a/src/Simplex/Chat/Operators.hs
+++ b/src/Simplex/Chat/Operators.hs
@@ -46,7 +46,7 @@ import Data.Time (addUTCTime)
import Data.Time.Clock (UTCTime, nominalDay)
import Language.Haskell.TH.Syntax (lift)
import Simplex.Chat.Operators.Conditions
-import Simplex.Chat.Protocol (RelayProfile (..))
+import Simplex.Chat.Protocol (RelayCapabilities (..), RelayProfile (..))
import Simplex.Chat.Types (ShortLinkContact, User)
import Simplex.Chat.Types.Shared (RelayStatus)
import Simplex.Messaging.Agent.Env.SQLite (ServerCfg (..), ServerRoles (..), allRoles)
@@ -280,7 +280,8 @@ data GroupRelay = GroupRelay
groupMemberId :: Int64,
userChatRelay :: UserChatRelay,
relayStatus :: RelayStatus,
- relayLink :: Maybe ShortLinkContact
+ relayLink :: Maybe ShortLinkContact,
+ relayCap :: RelayCapabilities
}
deriving (Eq, Show)
diff --git a/src/Simplex/Chat/Protocol.hs b/src/Simplex/Chat/Protocol.hs
index 4bc7b70eb5..3f885281c1 100644
--- a/src/Simplex/Chat/Protocol.hs
+++ b/src/Simplex/Chat/Protocol.hs
@@ -262,6 +262,14 @@ data LinkContent = LCPage | LCImage | LCVideo {duration :: Maybe Int} | LCUnknow
data ReportReason = RRSpam | RRContent | RRCommunity | RRProfile | RROther | RRUnknown Text
deriving (Eq, Show)
+data RelayCapabilities = RelayCapabilities
+ { webDomain :: Maybe Text
+ }
+ deriving (Eq, Show)
+
+defaultRelayCapabilities :: RelayCapabilities
+defaultRelayCapabilities = RelayCapabilities {webDomain = Nothing}
+
$(pure [])
instance FromJSON LinkContent where
@@ -281,6 +289,12 @@ instance ToJSON LinkContent where
$(JQ.deriveJSON defaultJSON ''LinkPreview)
+$(JQ.deriveToJSON defaultJSON ''RelayCapabilities)
+
+instance FromJSON RelayCapabilities where
+ parseJSON = $(JQ.mkParseJSON defaultJSON ''RelayCapabilities)
+ omittedField = Just defaultRelayCapabilities
+
instance StrEncoding ReportReason where
strEncode = \case
RRSpam -> "spam"
@@ -456,10 +470,11 @@ data ChatMsgEvent (e :: MsgEncoding) where
XGrpLinkMem :: Profile -> ChatMsgEvent 'Json
XGrpLinkAcpt :: GroupAcceptance -> GroupMemberRole -> MemberId -> ChatMsgEvent 'Json
XGrpRelayInv :: GroupRelayInvitation -> ChatMsgEvent 'Json
- XGrpRelayAcpt :: ShortLinkContact -> ChatMsgEvent 'Json
+ XGrpRelayAcpt :: ShortLinkContact -> RelayCapabilities -> ChatMsgEvent 'Json
XGrpRelayTest :: ByteString -> Maybe ByteString -> ChatMsgEvent 'Json
XGrpRelayNew :: ShortLinkContact -> ChatMsgEvent 'Json
XGrpRelayReject :: RelayRejectionReason -> ChatMsgEvent 'Json
+ XGrpRelayCap :: RelayCapabilities -> ChatMsgEvent 'Json
XGrpMemNew :: MemberInfo -> Maybe MsgScope -> ChatMsgEvent 'Json
XGrpMemIntro :: MemberInfo -> Maybe MemberRestrictions -> ChatMsgEvent 'Json
XGrpMemInv :: MemberId -> IntroInvitation -> ChatMsgEvent 'Json
@@ -1016,6 +1031,7 @@ data CMEventTag (e :: MsgEncoding) where
XGrpRelayTest_ :: CMEventTag 'Json
XGrpRelayNew_ :: CMEventTag 'Json
XGrpRelayReject_ :: CMEventTag 'Json
+ XGrpRelayCap_ :: CMEventTag 'Json
XGrpMemNew_ :: CMEventTag 'Json
XGrpMemIntro_ :: CMEventTag 'Json
XGrpMemInv_ :: CMEventTag 'Json
@@ -1076,6 +1092,7 @@ instance MsgEncodingI e => StrEncoding (CMEventTag e) where
XGrpRelayTest_ -> "x.grp.relay.test"
XGrpRelayNew_ -> "x.grp.relay.new"
XGrpRelayReject_ -> "x.grp.relay.reject"
+ XGrpRelayCap_ -> "x.grp.relay.cap"
XGrpMemNew_ -> "x.grp.mem.new"
XGrpMemIntro_ -> "x.grp.mem.intro"
XGrpMemInv_ -> "x.grp.mem.inv"
@@ -1137,6 +1154,7 @@ instance StrEncoding ACMEventTag where
"x.grp.relay.test" -> XGrpRelayTest_
"x.grp.relay.new" -> XGrpRelayNew_
"x.grp.relay.reject" -> XGrpRelayReject_
+ "x.grp.relay.cap" -> XGrpRelayCap_
"x.grp.mem.new" -> XGrpMemNew_
"x.grp.mem.intro" -> XGrpMemIntro_
"x.grp.mem.inv" -> XGrpMemInv_
@@ -1190,10 +1208,11 @@ toCMEventTag msg = case msg of
XGrpLinkMem _ -> XGrpLinkMem_
XGrpLinkAcpt {} -> XGrpLinkAcpt_
XGrpRelayInv _ -> XGrpRelayInv_
- XGrpRelayAcpt _ -> XGrpRelayAcpt_
+ XGrpRelayAcpt {} -> XGrpRelayAcpt_
XGrpRelayTest {} -> XGrpRelayTest_
XGrpRelayNew _ -> XGrpRelayNew_
XGrpRelayReject _ -> XGrpRelayReject_
+ XGrpRelayCap _ -> XGrpRelayCap_
XGrpMemNew {} -> XGrpMemNew_
XGrpMemIntro _ _ -> XGrpMemIntro_
XGrpMemInv _ _ -> XGrpMemInv_
@@ -1346,7 +1365,8 @@ appJsonToCM AppMessageJson {v, msgId, event, params} = do
XGrpLinkMem_ -> XGrpLinkMem <$> p "profile"
XGrpLinkAcpt_ -> XGrpLinkAcpt <$> p "acceptance" <*> p "role" <*> p "memberId"
XGrpRelayInv_ -> XGrpRelayInv <$> p "groupRelayInvitation"
- XGrpRelayAcpt_ -> XGrpRelayAcpt <$> p "relayLink"
+ XGrpRelayAcpt_ -> XGrpRelayAcpt <$> p "relayLink" <*> (fromMaybe defaultRelayCapabilities <$> opt "relayCap")
+ XGrpRelayCap_ -> XGrpRelayCap <$> p "relayCap"
XGrpRelayTest_ -> do
B64UrlByteString challenge <- p "challenge"
sig_ <- fmap (\(B64UrlByteString s) -> s) <$> opt "signature"
@@ -1419,7 +1439,8 @@ chatToAppMessage chatMsg@ChatMessage {chatVRange, msgId, chatMsgEvent} = case en
XGrpLinkMem profile -> o ["profile" .= profile]
XGrpLinkAcpt acceptance role memberId -> o ["acceptance" .= acceptance, "role" .= role, "memberId" .= memberId]
XGrpRelayInv groupRelayInv -> o ["groupRelayInvitation" .= groupRelayInv]
- XGrpRelayAcpt relayLink -> o ["relayLink" .= relayLink]
+ XGrpRelayAcpt relayLink relayCap -> o ["relayLink" .= relayLink, "relayCap" .= relayCap]
+ XGrpRelayCap relayCap -> o ["relayCap" .= relayCap]
XGrpRelayTest challenge sig_ -> o $
("signature" .=? (B64UrlByteString <$> sig_))
["challenge" .= B64UrlByteString challenge]
diff --git a/src/Simplex/Chat/Store/Connections.hs b/src/Simplex/Chat/Store/Connections.hs
index 2cbbad30e2..ac4583b9b9 100644
--- a/src/Simplex/Chat/Store/Connections.hs
+++ b/src/Simplex/Chat/Store/Connections.hs
@@ -139,6 +139,7 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do
SELECT
-- GroupInfo
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.short_descr, g.local_alias, gp.description, gp.image, gp.group_type, gp.group_link, gp.public_group_id,
+ gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding,
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
diff --git a/src/Simplex/Chat/Store/Groups.hs b/src/Simplex/Chat/Store/Groups.hs
index 11c4fd0798..b8af85ffe9 100644
--- a/src/Simplex/Chat/Store/Groups.hs
+++ b/src/Simplex/Chat/Store/Groups.hs
@@ -97,6 +97,7 @@ module Simplex.Chat.Store.Groups
updateRelayStatusFromTo,
setRelayLinkAccepted,
setRelayLinkConfId,
+ updateRelayCapabilities,
getRelayConfId,
updateRelayMemberData,
setGroupInProgressDone,
@@ -378,10 +379,11 @@ createNewGroup db vr user@User {userId} groupProfile incognitoProfile useRelays
INSERT INTO group_profiles
(display_name, full_name, short_descr, description, image,
group_type, group_link, public_group_id,
+ group_web_page, group_domain, domain_web_page, allow_embedding,
user_id, preferences, member_admission, created_at, updated_at)
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
+ VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|]
- ((displayName, fullName, shortDescr, description, image, groupType_, groupLink_, publicGroupId_)
+ ((displayName, fullName, shortDescr, description, image, groupType_, groupLink_, publicGroupId_) :. publicGroupAccessRow publicGroup
:. (userId, groupPreferences, memberAdmission, currentTs, currentTs))
profileId <- insertedRowId db
DB.execute
@@ -881,10 +883,11 @@ createGroup_ db userId groupProfile prepared business useRelays relayOwnStatus p
INSERT INTO group_profiles
(display_name, full_name, short_descr, description, image,
group_type, group_link, public_group_id,
+ group_web_page, group_domain, domain_web_page, allow_embedding,
user_id, preferences, member_admission, created_at, updated_at)
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
+ VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|]
- ((displayName, fullName, shortDescr, description, image, groupType_, groupLink_, publicGroupId_)
+ ((displayName, fullName, shortDescr, description, image, groupType_, groupLink_, publicGroupId_) :. publicGroupAccessRow publicGroup
:. (userId, groupPreferences, memberAdmission, currentTs, currentTs))
profileId <- insertedRowId db
DB.execute
@@ -1391,15 +1394,16 @@ groupRelayQuery =
[sql|
SELECT gr.group_relay_id, gr.group_member_id,
cr.chat_relay_id, cr.address, cr.display_name, cr.full_name, cr.short_descr, cr.image, cr.domains, cr.preset, cr.tested, cr.enabled, cr.deleted,
- gr.relay_status, gr.relay_link
+ gr.relay_status, gr.relay_link, gr.base_web_url
FROM group_relays gr
JOIN chat_relays cr ON cr.chat_relay_id = gr.chat_relay_id
|]
-toGroupRelay :: (Int64, GroupMemberId, DBEntityId, ShortLinkContact, Text, Text, Maybe Text, Maybe ImageData, Text, BoolInt) :. (Maybe BoolInt, BoolInt, BoolInt, RelayStatus, Maybe ShortLinkContact) -> GroupRelay
-toGroupRelay ((groupRelayId, groupMemberId, chatRelayId, address, displayName, fullName, shortDescr, image, domains, BI preset) :. (tested, BI enabled, BI deleted, relayStatus, relayLink)) =
+toGroupRelay :: (Int64, GroupMemberId, DBEntityId, ShortLinkContact, Text, Text, Maybe Text, Maybe ImageData, Text, BoolInt) :. (Maybe BoolInt, BoolInt, BoolInt, RelayStatus, Maybe ShortLinkContact, Maybe Text) -> GroupRelay
+toGroupRelay ((groupRelayId, groupMemberId, chatRelayId, address, displayName, fullName, shortDescr, image, domains, BI preset) :. (tested, BI enabled, BI deleted, relayStatus, relayLink, webDomain)) =
let userChatRelay = UserChatRelay {chatRelayId, address, relayProfile = toRelayProfile (displayName, fullName, shortDescr, image), domains = T.splitOn "," domains, preset, tested = unBI <$> tested, enabled, deleted}
- in GroupRelay {groupRelayId, groupMemberId, userChatRelay, relayStatus, relayLink}
+ relayCap = RelayCapabilities {webDomain}
+ in GroupRelay {groupRelayId, groupMemberId, userChatRelay, relayStatus, relayLink, relayCap}
setGroupRosterVersion :: DB.Connection -> GroupInfo -> VersionRoster -> IO ()
setGroupRosterVersion db GroupInfo {groupId} v = do
@@ -1578,6 +1582,18 @@ setRelayLinkConfId db m confId relayLink = do
|]
(relayLink, currentTs, groupMemberId' m)
+updateRelayCapabilities :: DB.Connection -> GroupMember -> RelayCapabilities -> IO ()
+updateRelayCapabilities db m RelayCapabilities {webDomain} = do
+ currentTs <- getCurrentTime
+ DB.execute
+ db
+ [sql|
+ UPDATE group_relays
+ SET base_web_url = ?, updated_at = ?
+ WHERE group_member_id = ?
+ |]
+ (webDomain, currentTs, groupMemberId' m)
+
getRelayConfId :: DB.Connection -> GroupMember -> ExceptT StoreError IO ConfirmationId
getRelayConfId db m =
ExceptT . firstRow fromOnly (SEGroupRelayNotFoundByMemberId $ groupMemberId' m) $
@@ -2426,6 +2442,7 @@ updateGroupProfile db user@User {userId} g@GroupInfo {groupId, localDisplayName,
UPDATE group_profiles
SET display_name = ?, full_name = ?, short_descr = ?, description = ?, image = ?,
group_type = ?, group_link = ?,
+ group_web_page = ?, group_domain = ?, domain_web_page = ?, allow_embedding = ?,
preferences = ?, member_admission = ?, updated_at = ?
WHERE group_profile_id IN (
SELECT group_profile_id
@@ -2433,7 +2450,7 @@ updateGroupProfile db user@User {userId} g@GroupInfo {groupId, localDisplayName,
WHERE user_id = ? AND group_id = ?
)
|]
- ((newName, fullName, shortDescr, description, image, groupType_, groupLink_) :. (groupPreferences, memberAdmission, currentTs, userId, groupId))
+ ((newName, fullName, shortDescr, description, image, groupType_, groupLink_) :. publicGroupAccessRow publicGroup :. (groupPreferences, memberAdmission, currentTs, userId, groupId))
updateGroup_ ldn currentTs = do
DB.execute
db
@@ -2473,14 +2490,16 @@ updateGroupProfileFromMember db user g@GroupInfo {groupId} Profile {displayName
[sql|
SELECT gp.display_name, gp.full_name, gp.short_descr, gp.description, gp.image,
gp.group_type, gp.group_link, gp.public_group_id,
+ gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding,
gp.preferences, gp.member_admission
FROM group_profiles gp
JOIN groups g ON gp.group_profile_id = g.group_profile_id
WHERE g.group_id = ?
|]
(Only groupId)
- toGroupProfile (displayName, fullName, shortDescr, description, image, groupType_, groupLink_, publicGroupId_, groupPreferences, memberAdmission) =
- GroupProfile {displayName, fullName, shortDescr, description, image, publicGroup = toPublicGroupProfile groupType_ groupLink_ publicGroupId_, groupPreferences, memberAdmission}
+ toGroupProfile ((displayName, fullName, shortDescr, description, image, groupType_, groupLink_, publicGroupId_) :. accessRow :. (groupPreferences, memberAdmission)) =
+ let publicGroupAccess = toPublicGroupAccess accessRow
+ in GroupProfile {displayName, fullName, shortDescr, description, image, publicGroup = toPublicGroupProfile groupType_ groupLink_ publicGroupId_ publicGroupAccess, groupPreferences, memberAdmission}
getGroupInfoByUserContactLinkConnReq :: DB.Connection -> VersionRangeChat -> User -> (ConnReqContact, ConnReqContact) -> IO (Maybe GroupInfo)
getGroupInfoByUserContactLinkConnReq db vr user@User {userId} (cReqSchema1, cReqSchema2) = do
diff --git a/src/Simplex/Chat/Store/Postgres/Migrations.hs b/src/Simplex/Chat/Store/Postgres/Migrations.hs
index 051af834da..470e2726d6 100644
--- a/src/Simplex/Chat/Store/Postgres/Migrations.hs
+++ b/src/Simplex/Chat/Store/Postgres/Migrations.hs
@@ -31,10 +31,11 @@ import Simplex.Chat.Store.Postgres.Migrations.M20260403_item_viewed
import Simplex.Chat.Store.Postgres.Migrations.M20260429_relay_request_retries
import Simplex.Chat.Store.Postgres.Migrations.M20260507_relay_inactive_at
import Simplex.Chat.Store.Postgres.Migrations.M20260514_relay_request_group_link_index
-import Simplex.Chat.Store.Postgres.Migrations.M20260515_delivery_job_senders
-import Simplex.Chat.Store.Postgres.Migrations.M20260520_client_services
-import Simplex.Chat.Store.Postgres.Migrations.M20260525_member_removed_at
-import Simplex.Chat.Store.Postgres.Migrations.M20260526_group_roster
+import Simplex.Chat.Store.Postgres.Migrations.M20260515_public_group_access
+import Simplex.Chat.Store.Postgres.Migrations.M20260529_delivery_job_senders
+import Simplex.Chat.Store.Postgres.Migrations.M20260530_client_services
+import Simplex.Chat.Store.Postgres.Migrations.M20260531_member_removed_at
+import Simplex.Chat.Store.Postgres.Migrations.M20260601_group_roster
import Simplex.Messaging.Agent.Store.Shared (Migration (..))
schemaMigrations :: [(String, Text, Maybe Text)]
@@ -66,10 +67,11 @@ schemaMigrations =
("20260429_relay_request_retries", m20260429_relay_request_retries, Just down_m20260429_relay_request_retries),
("20260507_relay_inactive_at", m20260507_relay_inactive_at, Just down_m20260507_relay_inactive_at),
("20260514_relay_request_group_link_index", m20260514_relay_request_group_link_index, Just down_m20260514_relay_request_group_link_index),
- ("20260515_delivery_job_senders", m20260515_delivery_job_senders, Just down_m20260515_delivery_job_senders),
- ("20260520_client_services", m20260520_client_services, Just down_m20260520_client_services),
- ("20260525_member_removed_at", m20260525_member_removed_at, Just down_m20260525_member_removed_at),
- ("20260526_group_roster", m20260526_group_roster, Just down_m20260526_group_roster)
+ ("20260515_public_group_access", m20260515_public_group_access, Just down_m20260515_public_group_access),
+ ("20260529_delivery_job_senders", m20260529_delivery_job_senders, Just down_m20260529_delivery_job_senders),
+ ("20260530_client_services", m20260530_client_services, Just down_m20260530_client_services),
+ ("20260531_member_removed_at", m20260531_member_removed_at, Just down_m20260531_member_removed_at),
+ ("20260601_group_roster", m20260601_group_roster, Just down_m20260601_group_roster)
]
-- | The list of migrations in ascending order by date
diff --git a/src/Simplex/Chat/Store/Postgres/Migrations/M20260515_public_group_access.hs b/src/Simplex/Chat/Store/Postgres/Migrations/M20260515_public_group_access.hs
new file mode 100644
index 0000000000..1fbb731626
--- /dev/null
+++ b/src/Simplex/Chat/Store/Postgres/Migrations/M20260515_public_group_access.hs
@@ -0,0 +1,29 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE QuasiQuotes #-}
+
+module Simplex.Chat.Store.Postgres.Migrations.M20260515_public_group_access where
+
+import Data.Text (Text)
+import Text.RawString.QQ (r)
+
+m20260515_public_group_access :: Text
+m20260515_public_group_access =
+ [r|
+ALTER TABLE group_profiles ADD COLUMN group_web_page TEXT;
+ALTER TABLE group_profiles ADD COLUMN group_domain TEXT;
+ALTER TABLE group_profiles ADD COLUMN domain_web_page BIGINT;
+ALTER TABLE group_profiles ADD COLUMN allow_embedding BIGINT;
+
+ALTER TABLE group_relays ADD COLUMN base_web_url TEXT;
+|]
+
+down_m20260515_public_group_access :: Text
+down_m20260515_public_group_access =
+ [r|
+ALTER TABLE group_relays DROP COLUMN base_web_url;
+
+ALTER TABLE group_profiles DROP COLUMN allow_embedding;
+ALTER TABLE group_profiles DROP COLUMN domain_web_page;
+ALTER TABLE group_profiles DROP COLUMN group_domain;
+ALTER TABLE group_profiles DROP COLUMN group_web_page;
+|]
diff --git a/src/Simplex/Chat/Store/Postgres/Migrations/M20260515_delivery_job_senders.hs b/src/Simplex/Chat/Store/Postgres/Migrations/M20260529_delivery_job_senders.hs
similarity index 89%
rename from src/Simplex/Chat/Store/Postgres/Migrations/M20260515_delivery_job_senders.hs
rename to src/Simplex/Chat/Store/Postgres/Migrations/M20260529_delivery_job_senders.hs
index d082587391..660e33561f 100644
--- a/src/Simplex/Chat/Store/Postgres/Migrations/M20260515_delivery_job_senders.hs
+++ b/src/Simplex/Chat/Store/Postgres/Migrations/M20260529_delivery_job_senders.hs
@@ -5,13 +5,13 @@
-- NULL means [] (sender-less jobs, e.g. DJRelayRemoved). One column carries
-- single- and multi-sender jobs uniformly; the per-job introduction bits live
-- in group_members.member_relations_vector (MRIntroduced).
-module Simplex.Chat.Store.Postgres.Migrations.M20260515_delivery_job_senders where
+module Simplex.Chat.Store.Postgres.Migrations.M20260529_delivery_job_senders where
import Data.Text (Text)
import Text.RawString.QQ (r)
-m20260515_delivery_job_senders :: Text
-m20260515_delivery_job_senders =
+m20260529_delivery_job_senders :: Text
+m20260529_delivery_job_senders =
[r|
DROP INDEX idx_delivery_jobs_single_sender_group_member_id;
@@ -24,8 +24,8 @@ WHERE single_sender_group_member_id IS NOT NULL;
ALTER TABLE delivery_jobs DROP COLUMN single_sender_group_member_id;
|]
-down_m20260515_delivery_job_senders :: Text
-down_m20260515_delivery_job_senders =
+down_m20260529_delivery_job_senders :: Text
+down_m20260529_delivery_job_senders =
[r|
-- Pre-up the FK was ON DELETE CASCADE, so orphan delivery_jobs cannot
-- exist. After up the FK was dropped and orphans may accumulate. Drop
diff --git a/src/Simplex/Chat/Store/Postgres/Migrations/M20260520_client_services.hs b/src/Simplex/Chat/Store/Postgres/Migrations/M20260530_client_services.hs
similarity index 57%
rename from src/Simplex/Chat/Store/Postgres/Migrations/M20260520_client_services.hs
rename to src/Simplex/Chat/Store/Postgres/Migrations/M20260530_client_services.hs
index af567130eb..2a37f8f4e3 100644
--- a/src/Simplex/Chat/Store/Postgres/Migrations/M20260520_client_services.hs
+++ b/src/Simplex/Chat/Store/Postgres/Migrations/M20260530_client_services.hs
@@ -1,19 +1,19 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
-module Simplex.Chat.Store.Postgres.Migrations.M20260520_client_services where
+module Simplex.Chat.Store.Postgres.Migrations.M20260530_client_services where
import Data.Text (Text)
import Text.RawString.QQ (r)
-m20260520_client_services :: Text
-m20260520_client_services =
+m20260530_client_services :: Text
+m20260530_client_services =
[r|
ALTER TABLE users ADD COLUMN client_service SMALLINT NOT NULL DEFAULT 0;
|]
-down_m20260520_client_services :: Text
-down_m20260520_client_services =
+down_m20260530_client_services :: Text
+down_m20260530_client_services =
[r|
ALTER TABLE users DROP COLUMN client_service;
|]
diff --git a/src/Simplex/Chat/Store/Postgres/Migrations/M20260525_member_removed_at.hs b/src/Simplex/Chat/Store/Postgres/Migrations/M20260531_member_removed_at.hs
similarity index 56%
rename from src/Simplex/Chat/Store/Postgres/Migrations/M20260525_member_removed_at.hs
rename to src/Simplex/Chat/Store/Postgres/Migrations/M20260531_member_removed_at.hs
index 6099751702..9dde712f0b 100644
--- a/src/Simplex/Chat/Store/Postgres/Migrations/M20260525_member_removed_at.hs
+++ b/src/Simplex/Chat/Store/Postgres/Migrations/M20260531_member_removed_at.hs
@@ -1,19 +1,19 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
-module Simplex.Chat.Store.Postgres.Migrations.M20260525_member_removed_at where
+module Simplex.Chat.Store.Postgres.Migrations.M20260531_member_removed_at where
import Data.Text (Text)
import Text.RawString.QQ (r)
-m20260525_member_removed_at :: Text
-m20260525_member_removed_at =
+m20260531_member_removed_at :: Text
+m20260531_member_removed_at =
[r|
ALTER TABLE group_members ADD COLUMN removed_at TIMESTAMPTZ;
|]
-down_m20260525_member_removed_at :: Text
-down_m20260525_member_removed_at =
+down_m20260531_member_removed_at :: Text
+down_m20260531_member_removed_at =
[r|
ALTER TABLE group_members DROP COLUMN removed_at;
|]
diff --git a/src/Simplex/Chat/Store/Postgres/Migrations/M20260526_group_roster.hs b/src/Simplex/Chat/Store/Postgres/Migrations/M20260601_group_roster.hs
similarity index 81%
rename from src/Simplex/Chat/Store/Postgres/Migrations/M20260526_group_roster.hs
rename to src/Simplex/Chat/Store/Postgres/Migrations/M20260601_group_roster.hs
index 014d392c97..21858f73e8 100644
--- a/src/Simplex/Chat/Store/Postgres/Migrations/M20260526_group_roster.hs
+++ b/src/Simplex/Chat/Store/Postgres/Migrations/M20260601_group_roster.hs
@@ -1,13 +1,13 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
-module Simplex.Chat.Store.Postgres.Migrations.M20260526_group_roster where
+module Simplex.Chat.Store.Postgres.Migrations.M20260601_group_roster where
import Data.Text (Text)
import Text.RawString.QQ (r)
-m20260526_group_roster :: Text
-m20260526_group_roster =
+m20260601_group_roster :: Text
+m20260601_group_roster =
[r|
ALTER TABLE groups ADD COLUMN roster_version INTEGER;
ALTER TABLE groups ADD COLUMN roster_msg_body BYTEA;
@@ -17,8 +17,8 @@ ALTER TABLE groups ADD COLUMN roster_sending_owner_gm_id BIGINT;
ALTER TABLE groups ADD COLUMN roster_broker_ts TIMESTAMPTZ;
|]
-down_m20260526_group_roster :: Text
-down_m20260526_group_roster =
+down_m20260601_group_roster :: Text
+down_m20260601_group_roster =
[r|
ALTER TABLE groups DROP COLUMN roster_broker_ts;
ALTER TABLE groups DROP COLUMN roster_sending_owner_gm_id;
diff --git a/src/Simplex/Chat/Store/Postgres/Migrations/chat_schema.sql b/src/Simplex/Chat/Store/Postgres/Migrations/chat_schema.sql
index 667317ab4a..6012625cca 100644
--- a/src/Simplex/Chat/Store/Postgres/Migrations/chat_schema.sql
+++ b/src/Simplex/Chat/Store/Postgres/Migrations/chat_schema.sql
@@ -850,7 +850,11 @@ CREATE TABLE test_chat_schema.group_profiles (
short_descr text,
group_type text,
group_link bytea,
- public_group_id bytea
+ public_group_id bytea,
+ group_web_page text,
+ group_domain text,
+ domain_web_page bigint,
+ allow_embedding bigint
);
@@ -875,7 +879,8 @@ CREATE TABLE test_chat_schema.group_relays (
relay_link bytea,
conf_id bytea,
created_at text DEFAULT now() NOT NULL,
- updated_at text DEFAULT now() NOT NULL
+ updated_at text DEFAULT now() NOT NULL,
+ base_web_url text
);
@@ -963,7 +968,7 @@ CREATE TABLE test_chat_schema.groups (
public_member_count bigint,
relay_request_retries bigint DEFAULT 0 NOT NULL,
relay_request_delay bigint DEFAULT 0 NOT NULL,
- relay_request_execute_at timestamp with time zone DEFAULT '1970-01-01 04:00:00+04'::timestamp with time zone NOT NULL,
+ relay_request_execute_at timestamp with time zone DEFAULT '1970-01-01 01:00:00+01'::timestamp with time zone NOT NULL,
relay_inactive_at timestamp with time zone,
roster_version integer,
roster_msg_body bytea,
diff --git a/src/Simplex/Chat/Store/SQLite/Migrations.hs b/src/Simplex/Chat/Store/SQLite/Migrations.hs
index 1758c148eb..75a759d661 100644
--- a/src/Simplex/Chat/Store/SQLite/Migrations.hs
+++ b/src/Simplex/Chat/Store/SQLite/Migrations.hs
@@ -154,10 +154,11 @@ import Simplex.Chat.Store.SQLite.Migrations.M20260403_item_viewed
import Simplex.Chat.Store.SQLite.Migrations.M20260429_relay_request_retries
import Simplex.Chat.Store.SQLite.Migrations.M20260507_relay_inactive_at
import Simplex.Chat.Store.SQLite.Migrations.M20260514_relay_request_group_link_index
-import Simplex.Chat.Store.SQLite.Migrations.M20260515_delivery_job_senders
-import Simplex.Chat.Store.SQLite.Migrations.M20260520_client_services
-import Simplex.Chat.Store.SQLite.Migrations.M20260525_member_removed_at
-import Simplex.Chat.Store.SQLite.Migrations.M20260526_group_roster
+import Simplex.Chat.Store.SQLite.Migrations.M20260515_public_group_access
+import Simplex.Chat.Store.SQLite.Migrations.M20260529_delivery_job_senders
+import Simplex.Chat.Store.SQLite.Migrations.M20260530_client_services
+import Simplex.Chat.Store.SQLite.Migrations.M20260531_member_removed_at
+import Simplex.Chat.Store.SQLite.Migrations.M20260601_group_roster
import Simplex.Messaging.Agent.Store.Shared (Migration (..))
schemaMigrations :: [(String, Query, Maybe Query)]
@@ -312,10 +313,11 @@ schemaMigrations =
("20260429_relay_request_retries", m20260429_relay_request_retries, Just down_m20260429_relay_request_retries),
("20260507_relay_inactive_at", m20260507_relay_inactive_at, Just down_m20260507_relay_inactive_at),
("20260514_relay_request_group_link_index", m20260514_relay_request_group_link_index, Just down_m20260514_relay_request_group_link_index),
- ("20260515_delivery_job_senders", m20260515_delivery_job_senders, Just down_m20260515_delivery_job_senders),
- ("20260520_client_services", m20260520_client_services, Just down_m20260520_client_services),
- ("20260525_member_removed_at", m20260525_member_removed_at, Just down_m20260525_member_removed_at),
- ("20260526_group_roster", m20260526_group_roster, Just down_m20260526_group_roster)
+ ("20260515_public_group_access", m20260515_public_group_access, Just down_m20260515_public_group_access),
+ ("20260529_delivery_job_senders", m20260529_delivery_job_senders, Just down_m20260529_delivery_job_senders),
+ ("20260530_client_services", m20260530_client_services, Just down_m20260530_client_services),
+ ("20260531_member_removed_at", m20260531_member_removed_at, Just down_m20260531_member_removed_at),
+ ("20260601_group_roster", m20260601_group_roster, Just down_m20260601_group_roster)
]
-- | The list of migrations in ascending order by date
diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/M20260515_public_group_access.hs b/src/Simplex/Chat/Store/SQLite/Migrations/M20260515_public_group_access.hs
new file mode 100644
index 0000000000..69f1793d3b
--- /dev/null
+++ b/src/Simplex/Chat/Store/SQLite/Migrations/M20260515_public_group_access.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+module Simplex.Chat.Store.SQLite.Migrations.M20260515_public_group_access where
+
+import Database.SQLite.Simple (Query)
+import Database.SQLite.Simple.QQ (sql)
+
+m20260515_public_group_access :: Query
+m20260515_public_group_access =
+ [sql|
+ALTER TABLE group_profiles ADD COLUMN group_web_page TEXT;
+ALTER TABLE group_profiles ADD COLUMN group_domain TEXT;
+ALTER TABLE group_profiles ADD COLUMN domain_web_page INTEGER;
+ALTER TABLE group_profiles ADD COLUMN allow_embedding INTEGER;
+
+ALTER TABLE group_relays ADD COLUMN base_web_url TEXT;
+|]
+
+down_m20260515_public_group_access :: Query
+down_m20260515_public_group_access =
+ [sql|
+ALTER TABLE group_relays DROP COLUMN base_web_url;
+
+ALTER TABLE group_profiles DROP COLUMN allow_embedding;
+ALTER TABLE group_profiles DROP COLUMN domain_web_page;
+ALTER TABLE group_profiles DROP COLUMN group_domain;
+ALTER TABLE group_profiles DROP COLUMN group_web_page;
+|]
diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/M20260515_delivery_job_senders.hs b/src/Simplex/Chat/Store/SQLite/Migrations/M20260529_delivery_job_senders.hs
similarity index 89%
rename from src/Simplex/Chat/Store/SQLite/Migrations/M20260515_delivery_job_senders.hs
rename to src/Simplex/Chat/Store/SQLite/Migrations/M20260529_delivery_job_senders.hs
index 67a9ae31e8..9346b16128 100644
--- a/src/Simplex/Chat/Store/SQLite/Migrations/M20260515_delivery_job_senders.hs
+++ b/src/Simplex/Chat/Store/SQLite/Migrations/M20260529_delivery_job_senders.hs
@@ -4,13 +4,13 @@
-- NULL means [] (sender-less jobs, e.g. DJRelayRemoved). One column carries
-- single- and multi-sender jobs uniformly; the per-job introduction bits live
-- in group_members.member_relations_vector (MRIntroduced).
-module Simplex.Chat.Store.SQLite.Migrations.M20260515_delivery_job_senders where
+module Simplex.Chat.Store.SQLite.Migrations.M20260529_delivery_job_senders where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
-m20260515_delivery_job_senders :: Query
-m20260515_delivery_job_senders =
+m20260529_delivery_job_senders :: Query
+m20260529_delivery_job_senders =
[sql|
DROP INDEX idx_delivery_jobs_single_sender_group_member_id;
@@ -23,8 +23,8 @@ WHERE single_sender_group_member_id IS NOT NULL;
ALTER TABLE delivery_jobs DROP COLUMN single_sender_group_member_id;
|]
-down_m20260515_delivery_job_senders :: Query
-down_m20260515_delivery_job_senders =
+down_m20260529_delivery_job_senders :: Query
+down_m20260529_delivery_job_senders =
[sql|
-- Pre-up the FK was ON DELETE CASCADE, so orphan delivery_jobs cannot
-- exist. After up the FK was dropped and orphans may accumulate. Drop
diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/M20260520_client_services.hs b/src/Simplex/Chat/Store/SQLite/Migrations/M20260530_client_services.hs
similarity index 56%
rename from src/Simplex/Chat/Store/SQLite/Migrations/M20260520_client_services.hs
rename to src/Simplex/Chat/Store/SQLite/Migrations/M20260530_client_services.hs
index db141d6c03..d65f8f1c67 100644
--- a/src/Simplex/Chat/Store/SQLite/Migrations/M20260520_client_services.hs
+++ b/src/Simplex/Chat/Store/SQLite/Migrations/M20260530_client_services.hs
@@ -1,18 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
-module Simplex.Chat.Store.SQLite.Migrations.M20260520_client_services where
+module Simplex.Chat.Store.SQLite.Migrations.M20260530_client_services where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
-m20260520_client_services :: Query
-m20260520_client_services =
+m20260530_client_services :: Query
+m20260530_client_services =
[sql|
ALTER TABLE users ADD COLUMN client_service INTEGER NOT NULL DEFAULT 0;
|]
-down_m20260520_client_services :: Query
-down_m20260520_client_services =
+down_m20260530_client_services :: Query
+down_m20260530_client_services =
[sql|
ALTER TABLE users DROP COLUMN client_service;
|]
diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/M20260525_member_removed_at.hs b/src/Simplex/Chat/Store/SQLite/Migrations/M20260531_member_removed_at.hs
similarity index 54%
rename from src/Simplex/Chat/Store/SQLite/Migrations/M20260525_member_removed_at.hs
rename to src/Simplex/Chat/Store/SQLite/Migrations/M20260531_member_removed_at.hs
index 704950b3fb..c63e6a37f9 100644
--- a/src/Simplex/Chat/Store/SQLite/Migrations/M20260525_member_removed_at.hs
+++ b/src/Simplex/Chat/Store/SQLite/Migrations/M20260531_member_removed_at.hs
@@ -1,18 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
-module Simplex.Chat.Store.SQLite.Migrations.M20260525_member_removed_at where
+module Simplex.Chat.Store.SQLite.Migrations.M20260531_member_removed_at where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
-m20260525_member_removed_at :: Query
-m20260525_member_removed_at =
+m20260531_member_removed_at :: Query
+m20260531_member_removed_at =
[sql|
ALTER TABLE group_members ADD COLUMN removed_at TEXT;
|]
-down_m20260525_member_removed_at :: Query
-down_m20260525_member_removed_at =
+down_m20260531_member_removed_at :: Query
+down_m20260531_member_removed_at =
[sql|
ALTER TABLE group_members DROP COLUMN removed_at;
|]
diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/M20260526_group_roster.hs b/src/Simplex/Chat/Store/SQLite/Migrations/M20260601_group_roster.hs
similarity index 80%
rename from src/Simplex/Chat/Store/SQLite/Migrations/M20260526_group_roster.hs
rename to src/Simplex/Chat/Store/SQLite/Migrations/M20260601_group_roster.hs
index 03aba429a8..f23e41ce54 100644
--- a/src/Simplex/Chat/Store/SQLite/Migrations/M20260526_group_roster.hs
+++ b/src/Simplex/Chat/Store/SQLite/Migrations/M20260601_group_roster.hs
@@ -1,12 +1,12 @@
{-# LANGUAGE QuasiQuotes #-}
-module Simplex.Chat.Store.SQLite.Migrations.M20260526_group_roster where
+module Simplex.Chat.Store.SQLite.Migrations.M20260601_group_roster where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
-m20260526_group_roster :: Query
-m20260526_group_roster =
+m20260601_group_roster :: Query
+m20260601_group_roster =
[sql|
ALTER TABLE groups ADD COLUMN roster_version INTEGER;
ALTER TABLE groups ADD COLUMN roster_msg_body BLOB;
@@ -16,8 +16,8 @@ ALTER TABLE groups ADD COLUMN roster_sending_owner_gm_id INTEGER;
ALTER TABLE groups ADD COLUMN roster_broker_ts TEXT;
|]
-down_m20260526_group_roster :: Query
-down_m20260526_group_roster =
+down_m20260601_group_roster :: Query
+down_m20260601_group_roster =
[sql|
ALTER TABLE groups DROP COLUMN roster_broker_ts;
ALTER TABLE groups DROP COLUMN roster_sending_owner_gm_id;
diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt b/src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt
index 12f9d2e878..6a6d147b5c 100644
--- a/src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt
+++ b/src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt
@@ -141,6 +141,7 @@ Query:
SELECT
-- GroupInfo
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.short_descr, g.local_alias, gp.description, gp.image, gp.group_type, gp.group_link, gp.public_group_id,
+ gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding,
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
@@ -970,6 +971,7 @@ SEARCH delivery_tasks USING COVERING INDEX idx_delivery_tasks_next (group_id=? A
Query:
SELECT gp.display_name, gp.full_name, gp.short_descr, gp.description, gp.image,
gp.group_type, gp.group_link, gp.public_group_id,
+ gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding,
gp.preferences, gp.member_admission
FROM group_profiles gp
JOIN groups g ON gp.group_profile_id = g.group_profile_id
@@ -1217,8 +1219,9 @@ Query:
INSERT INTO group_profiles
(display_name, full_name, short_descr, description, image,
group_type, group_link, public_group_id,
+ group_web_page, group_domain, domain_web_page, allow_embedding,
user_id, preferences, member_admission, created_at, updated_at)
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
+ VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
Plan:
@@ -1741,6 +1744,7 @@ Query:
UPDATE group_profiles
SET display_name = ?, full_name = ?, short_descr = ?, description = ?, image = ?,
group_type = ?, group_link = ?,
+ group_web_page = ?, group_domain = ?, domain_web_page = ?, allow_embedding = ?,
preferences = ?, member_admission = ?, updated_at = ?
WHERE group_profile_id IN (
SELECT group_profile_id
@@ -5120,6 +5124,14 @@ SEARCH group_profiles USING INTEGER PRIMARY KEY (rowid=?)
LIST SUBQUERY 1
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
+Query:
+ UPDATE group_relays
+ SET base_web_url = ?, updated_at = ?
+ WHERE group_member_id = ?
+
+Plan:
+SEARCH group_relays USING INDEX idx_group_relays_group_member_id (group_member_id=?)
+
Query:
UPDATE group_relays
SET conf_id = ?, relay_link = ?, updated_at = ?
@@ -5313,6 +5325,7 @@ Query:
SELECT
-- GroupInfo
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.short_descr, g.local_alias, gp.description, gp.image, gp.group_type, gp.group_link, gp.public_group_id,
+ gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding,
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
@@ -5349,6 +5362,7 @@ Query:
SELECT
-- GroupInfo
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.short_descr, g.local_alias, gp.description, gp.image, gp.group_type, gp.group_link, gp.public_group_id,
+ gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding,
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
@@ -5378,6 +5392,7 @@ Query:
SELECT
-- GroupInfo
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.short_descr, g.local_alias, gp.description, gp.image, gp.group_type, gp.group_link, gp.public_group_id,
+ gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding,
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
@@ -5793,7 +5808,7 @@ SEARCH f USING INDEX idx_files_chat_item_id (chat_item_id=?)
Query:
SELECT gr.group_relay_id, gr.group_member_id,
cr.chat_relay_id, cr.address, cr.display_name, cr.full_name, cr.short_descr, cr.image, cr.domains, cr.preset, cr.tested, cr.enabled, cr.deleted,
- gr.relay_status, gr.relay_link
+ gr.relay_status, gr.relay_link, gr.base_web_url
FROM group_relays gr
JOIN chat_relays cr ON cr.chat_relay_id = gr.chat_relay_id
@@ -5810,7 +5825,7 @@ SEARCH m USING INTEGER PRIMARY KEY (rowid=?)
Query:
SELECT gr.group_relay_id, gr.group_member_id,
cr.chat_relay_id, cr.address, cr.display_name, cr.full_name, cr.short_descr, cr.image, cr.domains, cr.preset, cr.tested, cr.enabled, cr.deleted,
- gr.relay_status, gr.relay_link
+ gr.relay_status, gr.relay_link, gr.base_web_url
FROM group_relays gr
JOIN chat_relays cr ON cr.chat_relay_id = gr.chat_relay_id
WHERE gr.group_id = ?
@@ -5821,7 +5836,7 @@ SEARCH cr USING INTEGER PRIMARY KEY (rowid=?)
Query:
SELECT gr.group_relay_id, gr.group_member_id,
cr.chat_relay_id, cr.address, cr.display_name, cr.full_name, cr.short_descr, cr.image, cr.domains, cr.preset, cr.tested, cr.enabled, cr.deleted,
- gr.relay_status, gr.relay_link
+ gr.relay_status, gr.relay_link, gr.base_web_url
FROM group_relays gr
JOIN chat_relays cr ON cr.chat_relay_id = gr.chat_relay_id
WHERE gr.group_member_id = ?
@@ -5832,7 +5847,7 @@ SEARCH cr USING INTEGER PRIMARY KEY (rowid=?)
Query:
SELECT gr.group_relay_id, gr.group_member_id,
cr.chat_relay_id, cr.address, cr.display_name, cr.full_name, cr.short_descr, cr.image, cr.domains, cr.preset, cr.tested, cr.enabled, cr.deleted,
- gr.relay_status, gr.relay_link
+ gr.relay_status, gr.relay_link, gr.base_web_url
FROM group_relays gr
JOIN chat_relays cr ON cr.chat_relay_id = gr.chat_relay_id
WHERE gr.group_relay_id = ?
diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql b/src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql
index f6cbf20f72..ed31f10880 100644
--- a/src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql
+++ b/src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql
@@ -126,7 +126,11 @@ CREATE TABLE group_profiles(
short_descr TEXT,
group_type TEXT,
group_link BLOB,
- public_group_id BLOB
+ public_group_id BLOB,
+ group_web_page TEXT,
+ group_domain TEXT,
+ domain_web_page INTEGER,
+ allow_embedding INTEGER
) STRICT;
CREATE TABLE groups(
group_id INTEGER PRIMARY KEY, -- local group ID
@@ -787,6 +791,8 @@ CREATE TABLE group_relays(
conf_id BLOB,
created_at TEXT NOT NULL DEFAULT(datetime('now')),
updated_at TEXT NOT NULL DEFAULT(datetime('now'))
+ ,
+ base_web_url TEXT
) STRICT;
CREATE INDEX contact_profiles_index ON contact_profiles(
display_name,
diff --git a/src/Simplex/Chat/Store/Shared.hs b/src/Simplex/Chat/Store/Shared.hs
index 1e2ae342c6..ae33960ab9 100644
--- a/src/Simplex/Chat/Store/Shared.hs
+++ b/src/Simplex/Chat/Store/Shared.hs
@@ -665,18 +665,20 @@ type BusinessChatInfoRow = (Maybe BusinessChatType, Maybe MemberId, Maybe Member
type GroupKeysRow = (Maybe C.PrivateKeyEd25519, Maybe C.PublicKeyEd25519, Maybe C.PrivateKeyEd25519)
-type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe Text, Text, Maybe Text, Maybe ImageData, Maybe GroupType, Maybe ShortLinkContact, Maybe B64UrlByteString) :. (Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe GroupPreferences, Maybe GroupMemberAdmission) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime) :. PreparedGroupRow :. BusinessChatInfoRow :. (BoolInt, Maybe RelayStatus, Maybe UIThemeEntityOverrides, Int64, Maybe Int64, Maybe VersionRoster, Maybe CustomData, Maybe Int64, Int, Maybe ConnReqContact) :. GroupKeysRow :. GroupMemberRow
+type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe Text, Text, Maybe Text, Maybe ImageData, Maybe GroupType, Maybe ShortLinkContact, Maybe B64UrlByteString) :. PublicGroupAccessRow :. (Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe GroupPreferences, Maybe GroupMemberAdmission) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime) :. PreparedGroupRow :. BusinessChatInfoRow :. (BoolInt, Maybe RelayStatus, Maybe UIThemeEntityOverrides, Int64, Maybe Int64, Maybe VersionRoster, Maybe CustomData, Maybe Int64, Int, Maybe ConnReqContact) :. GroupKeysRow :. GroupMemberRow
+
+type PublicGroupAccessRow = (Maybe Text, Maybe Text, Maybe BoolInt, Maybe BoolInt)
type GroupMemberRow = (GroupMemberId, GroupId, Int64, MemberId, VersionChat, VersionChat, GroupMemberRole, GroupMemberCategory, GroupMemberStatus, BoolInt, Maybe MemberRestrictionStatus) :. (Maybe Int64, Maybe GroupMemberId, ContactName, Maybe ContactId, ProfileId) :. ProfileRow :. (UTCTime, UTCTime) :. (Maybe UTCTime, Int64, Int64, Int64, Maybe UTCTime, Maybe C.PublicKeyEd25519, Maybe ShortLinkContact)
type ProfileRow = (ProfileId, ContactName, Text, Maybe Text, Maybe ImageData, Maybe ConnLinkContact, Maybe ChatPeerType, LocalAlias, Maybe Preferences)
toGroupInfo :: VersionRangeChat -> Int64 -> [ChatTagId] -> GroupInfoRow -> GroupInfo
-toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName, fullName, shortDescr, localAlias, description, image, groupType_, groupLink_, publicGroupId_) :. (enableNtfs_, sendRcpts, BI favorite, groupPreferences, memberAdmission) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. preparedGroupRow :. businessRow :. (BI useRelays, relayOwnStatus, uiThemes, currentMembers, publicMemberCount, rosterVersion, customData, chatItemTTL, membersRequireAttention, viaGroupLinkUri) :. groupKeysRow :. userMemberRow) =
+toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName, fullName, shortDescr, localAlias, description, image, groupType_, groupLink_, publicGroupId_) :. accessRow :. (enableNtfs_, sendRcpts, BI favorite, groupPreferences, memberAdmission) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. preparedGroupRow :. businessRow :. (BI useRelays, relayOwnStatus, uiThemes, currentMembers, publicMemberCount, rosterVersion, customData, chatItemTTL, membersRequireAttention, viaGroupLinkUri) :. groupKeysRow :. userMemberRow) =
let membership = (toGroupMember userContactId userMemberRow) {memberChatVRange = vr}
chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts = unBI <$> sendRcpts, favorite}
fullGroupPreferences = mergeGroupPreferences groupPreferences
- publicGroup = toPublicGroupProfile groupType_ groupLink_ publicGroupId_
+ publicGroup = toPublicGroupProfile groupType_ groupLink_ publicGroupId_ (toPublicGroupAccess accessRow)
groupKeys = toGroupKeys publicGroupId_ groupKeysRow
groupProfile = GroupProfile {displayName, fullName, shortDescr, description, image, publicGroup, groupPreferences, memberAdmission}
businessChat = toBusinessChatInfo businessRow
@@ -690,10 +692,25 @@ toPreparedGroup = \case
Just PreparedGroup {connLinkToConnect = CCLink fullLink shortLink_, connLinkPreparedConnection, connLinkStartedConnection, welcomeSharedMsgId, requestSharedMsgId}
_ -> Nothing
-toPublicGroupProfile :: Maybe GroupType -> Maybe ShortLinkContact -> Maybe B64UrlByteString -> Maybe PublicGroupProfile
-toPublicGroupProfile (Just groupType) (Just groupLink) (Just publicGroupId) =
- Just PublicGroupProfile {groupType, groupLink, publicGroupId}
-toPublicGroupProfile _ _ _ = Nothing
+toPublicGroupProfile :: Maybe GroupType -> Maybe ShortLinkContact -> Maybe B64UrlByteString -> Maybe PublicGroupAccess -> Maybe PublicGroupProfile
+toPublicGroupProfile (Just groupType) (Just groupLink) (Just publicGroupId) publicGroupAccess =
+ Just PublicGroupProfile {groupType, groupLink, publicGroupId, publicGroupAccess}
+toPublicGroupProfile _ _ _ _ = Nothing
+
+publicGroupAccessRow :: Maybe PublicGroupProfile -> PublicGroupAccessRow
+publicGroupAccessRow pgp = case pgp >>= publicGroupAccess of
+ Just PublicGroupAccess {groupWebPage, groupDomain, domainWebPage, allowEmbedding} ->
+ (groupWebPage, groupDomain, Just (BI domainWebPage), Just (BI allowEmbedding))
+ Nothing -> (Nothing, Nothing, Nothing, Nothing)
+
+toPublicGroupAccess :: PublicGroupAccessRow -> Maybe PublicGroupAccess
+toPublicGroupAccess (groupWebPage, groupDomain, domainWebPage_, allowEmbedding_)
+ | isJust groupWebPage || isJust groupDomain || domainWebPage || allowEmbedding =
+ Just PublicGroupAccess {groupWebPage, groupDomain, domainWebPage, allowEmbedding}
+ | otherwise = Nothing
+ where
+ domainWebPage = maybe False unBI domainWebPage_
+ allowEmbedding = maybe False unBI allowEmbedding_
toGroupKeys :: Maybe B64UrlByteString -> GroupKeysRow -> Maybe GroupKeys
toGroupKeys (Just publicGroupId) (rootPrivKey_, rootPubKey_, Just memberPrivKey) =
@@ -760,6 +777,7 @@ groupInfoQueryFields =
SELECT
-- GroupInfo
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.short_descr, g.local_alias, gp.description, gp.image, gp.group_type, gp.group_link, gp.public_group_id,
+ gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding,
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
diff --git a/src/Simplex/Chat/Terminal.hs b/src/Simplex/Chat/Terminal.hs
index 29299cfeae..21781229e4 100644
--- a/src/Simplex/Chat/Terminal.hs
+++ b/src/Simplex/Chat/Terminal.hs
@@ -8,7 +8,6 @@
module Simplex.Chat.Terminal where
import Control.Monad
-import Control.Monad.IO.Class (liftIO)
import qualified Data.List.NonEmpty as L
import Simplex.Chat (defaultChatConfig)
import Simplex.Chat.Controller
@@ -23,8 +22,6 @@ import Simplex.Chat.Terminal.Output
import Simplex.FileTransfer.Client.Presets (defaultXFTPServers)
import Simplex.Messaging.Client (NetworkConfig (..), SMPProxyFallback (..), SMPProxyMode (..), defaultNetworkConfig)
import Simplex.Messaging.Util (raceAny_)
-import System.Terminal (Key, Modifiers)
-import UnliftIO.STM
#if !defined(dbPostgres)
import Control.Exception (handle, throwIO)
import qualified Data.ByteArray as BA
@@ -102,9 +99,4 @@ simplexChatTerminal cfg options t = run options
#endif
runChatTerminal :: ChatTerminal -> ChatController -> ChatOpts -> IO ()
-runChatTerminal ct cc opts = do
- keyQ <- newTQueueIO
- raceAny_ [runKeyReader ct keyQ, runTerminalInput ct cc keyQ, runTerminalOutput ct cc opts, runInputLoop ct cc]
-
-runKeyReader :: ChatTerminal -> TQueue (Key, Modifiers) -> IO ()
-runKeyReader ct q = withChatTerm ct $ forever $ getKey >>= liftIO . atomically . writeTQueue q
+runChatTerminal ct cc opts = raceAny_ [runTerminalInput ct cc, runTerminalOutput ct cc opts, runInputLoop ct cc]
diff --git a/src/Simplex/Chat/Terminal/Input.hs b/src/Simplex/Chat/Terminal/Input.hs
index effcb7a71c..e0ee10aff9 100644
--- a/src/Simplex/Chat/Terminal/Input.hs
+++ b/src/Simplex/Chat/Terminal/Input.hs
@@ -152,14 +152,14 @@ sendUpdatedLiveMessage cc sentMsg LiveMessage {chatName, chatItemId} live = do
let cmd = UpdateLiveMessage chatName chatItemId live $ T.pack sentMsg
execChatCommand' cmd 0 `runReaderT` cc
-runTerminalInput :: ChatTerminal -> ChatController -> TQueue (Key, Modifiers) -> IO ()
-runTerminalInput ct cc keyQ = do
- updateInputView ct
- receiveFromTTY keyQ cc ct
+runTerminalInput :: ChatTerminal -> ChatController -> IO ()
+runTerminalInput ct cc = withChatTerm ct $ do
+ updateInput ct
+ receiveFromTTY cc ct
-receiveFromTTY :: TQueue (Key, Modifiers) -> ChatController -> ChatTerminal -> IO ()
-receiveFromTTY keyQ cc@ChatController {inputQ, currentUser, currentRemoteHost, chatStore} ct@ChatTerminal {termSize, termState, liveMessageState, activeTo} =
- forever $ atomically (readTQueue keyQ) >>= processKey >> updateInputView ct
+receiveFromTTY :: forall m. MonadTerminal m => ChatController -> ChatTerminal -> m ()
+receiveFromTTY cc@ChatController {inputQ, currentUser, currentRemoteHost, chatStore} ct@ChatTerminal {termSize, termState, liveMessageState, activeTo} =
+ forever $ getKey >>= liftIO . processKey >> withTermLock ct (updateInput ct)
where
processKey :: (Key, Modifiers) -> IO ()
processKey key = case key of
diff --git a/src/Simplex/Chat/Types.hs b/src/Simplex/Chat/Types.hs
index 1d4189173c..141dceaad1 100644
--- a/src/Simplex/Chat/Types.hs
+++ b/src/Simplex/Chat/Types.hs
@@ -796,10 +796,19 @@ instance FromField GroupType where fromField = fromTextField_ textDecode
instance ToField GroupType where toField = toField . textEncode
+data PublicGroupAccess = PublicGroupAccess
+ { groupWebPage :: Maybe Text,
+ groupDomain :: Maybe Text,
+ domainWebPage :: Bool,
+ allowEmbedding :: Bool
+ }
+ deriving (Eq, Show)
+
data PublicGroupProfile = PublicGroupProfile
{ groupType :: GroupType,
groupLink :: ShortLinkContact,
- publicGroupId :: B64UrlByteString -- group identity = sha256(genesis root key), immutable
+ publicGroupId :: B64UrlByteString, -- group identity = sha256(genesis root key), immutable
+ publicGroupAccess :: Maybe PublicGroupAccess
}
deriving (Eq, Show)
@@ -2098,6 +2107,8 @@ instance ToJSON GroupType where
toJSON = textToJSON
toEncoding = textToEncoding
+$(JQ.deriveJSON defaultJSON ''PublicGroupAccess)
+
$(JQ.deriveJSON defaultJSON ''PublicGroupProfile)
$(JQ.deriveJSON defaultJSON ''GroupProfile)
diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs
index 725642b6e3..600e952a3e 100644
--- a/src/Simplex/Chat/View.hs
+++ b/src/Simplex/Chat/View.hs
@@ -2150,6 +2150,7 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
]
knownGroup prepared = grpOrBizLink g <> ": known " <> prepared <> grpOrBiz g <> " " <> ttyGroup' g
GLPNoRelays _ -> [grpLink "channel has no active relays, please try to join later"]
+ GLPUpdateRequired _ -> [grpLink "this group requires a newer version of the app, please upgrade"]
where
connecting g = [grpOrBizLink g <> ": connecting to " <> grpOrBiz g <> " " <> ttyGroup' g]
grpLink = ("group link: " <>)
diff --git a/tests/ChatTests/Groups.hs b/tests/ChatTests/Groups.hs
index daf094fed6..86386b7cb6 100644
--- a/tests/ChatTests/Groups.hs
+++ b/tests/ChatTests/Groups.hs
@@ -3304,6 +3304,12 @@ testGLinkReviewMember =
alice ##> "/_delete member chat #1 5"
alice <## "bad chat command: member is pending"
+ -- moderator can't accept member with a role higher than their own
+ dan ##> "/_accept member #1 5 admin"
+ dan <## "#team: you have insufficient permissions for this action, the required role is admin"
+ dan ##> "/_accept member #1 5 owner"
+ dan <## "#team: you have insufficient permissions for this action, the required role is owner"
+
-- accept member
dan ##> "/_accept member #1 5 member"
concurrentlyN_
diff --git a/tests/MarkdownTests.hs b/tests/MarkdownTests.hs
index a82e18f988..efa010ceb1 100644
--- a/tests/MarkdownTests.hs
+++ b/tests/MarkdownTests.hs
@@ -10,6 +10,7 @@ import Data.Text (Text)
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8)
import Simplex.Chat.Markdown
+import Simplex.Messaging.Agent.Protocol (SimplexNameDomain (..), SimplexNameInfo (..), SimplexNameType (..), SimplexTLD (..))
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Util ((<$$>))
import System.Console.ANSI.Types
@@ -28,6 +29,7 @@ markdownTests = do
textWithPhone
textWithMentions
textWithCommands
+ textWithSimplexNames
multilineMarkdownList
testSanitizeUri
@@ -117,7 +119,7 @@ secretText = describe "secret text" do
"this is # unformatted # text"
<==> "this is # unformatted # text"
"this is #unformatted # text"
- <==> "this is #unformatted # text"
+ <==> "this is " <> sname NTPublicGroup TLDSimplex "unformatted" [] "unformatted" <> " # text"
"this is # unformatted# text"
<==> "this is # unformatted# text"
"this is ## unformatted ## text"
@@ -125,9 +127,9 @@ secretText = describe "secret text" do
"this is#unformatted# text"
<==> "this is#unformatted# text"
"this is #unformatted text"
- <==> "this is #unformatted text"
+ <==> "this is " <> sname NTPublicGroup TLDSimplex "unformatted" [] "unformatted" <> " text"
"*this* is #unformatted text"
- <==> bold "this" <> " is #unformatted text"
+ <==> bold "this" <> " is " <> sname NTPublicGroup TLDSimplex "unformatted" [] "unformatted" <> " text"
it "ignored internal markdown" do
"snippet: `this is #secret_text#`"
<==> "snippet: " <> markdown Snippet "this is #secret_text#"
@@ -297,8 +299,8 @@ textWithEmail = describe "text with Email" do
"test chat@simplex.chat." <==> "test " <> email "chat@simplex.chat" <> "."
"test chat@simplex.chat..." <==> "test " <> email "chat@simplex.chat" <> "..."
it "ignored as email markdown" do
- "chat @simplex.chat" <==> "chat " <> mention "simplex.chat" "@simplex.chat"
- "this is chat @simplex.chat" <==> "this is chat " <> mention "simplex.chat" "@simplex.chat"
+ "chat @simplex.chat" <==> "chat " <> sname NTContact TLDWeb "simplex.chat" [] "simplex.chat"
+ "this is chat @simplex.chat" <==> "this is chat " <> sname NTContact TLDWeb "simplex.chat" [] "simplex.chat"
"this is chat@ simplex.chat" <==> "this is chat@ " <> uri "simplex.chat"
"this is chat @ simplex.chat" <==> "this is chat @ " <> uri "simplex.chat"
"*this* is chat @ simplex.chat" <==> bold "this" <> " is chat @ " <> uri "simplex.chat"
@@ -378,6 +380,39 @@ uri' = FormattedText $ Just Uri
command' :: Text -> Text -> FormattedText
command' = FormattedText . Just . Command
+sname :: SimplexNameType -> SimplexTLD -> Text -> [Text] -> Text -> Markdown
+sname nt ns dom sub txt = markdown (SimplexName $ SimplexNameInfo nt (SimplexNameDomain ns dom sub)) (pfx <> txt)
+ where
+ pfx = case nt of NTPublicGroup -> "#"; NTContact -> "@"
+
+textWithSimplexNames :: Spec
+textWithSimplexNames = describe "text with SimpleX names" do
+ it "channel names - simplex namespace" do
+ "#privacy" <==> sname NTPublicGroup TLDSimplex "privacy" [] "privacy"
+ "#privacy.simplex" <==> sname NTPublicGroup TLDSimplex "privacy" [] "privacy.simplex"
+ "#my-channel.simplex" <==> sname NTPublicGroup TLDSimplex "my-channel" [] "my-channel.simplex"
+ "hello #privacy!" <==> "hello " <> sname NTPublicGroup TLDSimplex "privacy" [] "privacy" <> "!"
+ "see #privacy.simplex now" <==> "see " <> sname NTPublicGroup TLDSimplex "privacy" [] "privacy.simplex" <> " now"
+ "#123" <==> sname NTPublicGroup TLDSimplex "123" [] "123"
+ it "channel names - subdomains" do
+ "#support.acme.simplex" <==> sname NTPublicGroup TLDSimplex "acme" ["support"] "support.acme.simplex"
+ "#a.b.acme.simplex" <==> sname NTPublicGroup TLDSimplex "acme" ["b", "a"] "a.b.acme.simplex"
+ it "channel names - testing namespace" do
+ "#test.testing" <==> sname NTPublicGroup TLDTesting "test" [] "test.testing"
+ "#sub.test.testing" <==> sname NTPublicGroup TLDTesting "test" ["sub"] "sub.test.testing"
+ it "channel names - web domains" do
+ "#example.com" <==> sname NTPublicGroup TLDWeb "example.com" [] "example.com"
+ "#news.bbc.co.uk" <==> sname NTPublicGroup TLDWeb "news.bbc.co.uk" [] "news.bbc.co.uk"
+ "#123.com" <==> sname NTPublicGroup TLDWeb "123.com" [] "123.com"
+ it "contact names" do
+ "@privacy.simplex" <==> sname NTContact TLDSimplex "privacy" [] "privacy.simplex"
+ "@my-name.simplex" <==> sname NTContact TLDSimplex "my-name" [] "my-name.simplex"
+ "@alice.example.com" <==> sname NTContact TLDWeb "alice.example.com" [] "alice.example.com"
+ it "not parsed as names" do
+ "#secret#" <==> markdown Secret "secret"
+ "##double secret##" <==> markdown Secret "#double secret#"
+ "#" <==> "#"
+
multilineMarkdownList :: Spec
multilineMarkdownList = describe "multiline markdown" do
it "correct markdown" do
diff --git a/tests/PostgresSchemaDump.hs b/tests/PostgresSchemaDump.hs
index 197e9a9b89..0cd79ac513 100644
--- a/tests/PostgresSchemaDump.hs
+++ b/tests/PostgresSchemaDump.hs
@@ -80,5 +80,5 @@ skipComparisonForDownMigrations =
-- group_member_intro_id field moves
"20251128_migrate_member_relations",
-- on down migration single_sender_group_member_id column is re-added at the end of the table
- "20260515_delivery_job_senders"
+ "20260529_delivery_job_senders"
]
diff --git a/tests/RemoteTests.hs b/tests/RemoteTests.hs
index 51f4324bf0..e96d531805 100644
--- a/tests/RemoteTests.hs
+++ b/tests/RemoteTests.hs
@@ -16,7 +16,8 @@ import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy.Char8 as LB
import Data.List (find, isPrefixOf)
import qualified Data.Map.Strict as M
-import Simplex.Chat.Controller (ChatConfig (..), versionNumber)
+import Simplex.Chat.Controller (ChatCommand (..), ChatConfig (..), versionNumber)
+import Simplex.Chat.Library.Commands (parseChatCommand)
import qualified Simplex.Chat.Controller as Controller
import Simplex.Chat.Mobile.File
import Simplex.Chat.Remote (remoteFilesFolder)
@@ -24,6 +25,7 @@ import Simplex.Chat.Remote.Types
import Simplex.Messaging.Crypto.File (CryptoFileArgs (..))
import Simplex.Messaging.Encoding.String (strEncode)
import Simplex.Messaging.Util
+import Simplex.RemoteControl.Types (RCCtrlAddress (..))
import System.FilePath ((>))
import Test.Hspec hiding (it)
import UnliftIO
@@ -32,6 +34,12 @@ import UnliftIO.Directory
remoteTests :: SpecWith TestParams
remoteTests = describe "Remote" $ do
+ describe "/start remote host parser" $ do
+ it "parses iface name with a space followed by port=" $ \_ ->
+ parseChatCommand "/start remote host new addr=192.168.1.5 iface=\"Ethernet 2\" port=12345"
+ `shouldSatisfy` \case
+ Right (StartRemoteHost Nothing (Just (RCCtrlAddress _ "Ethernet 2")) (Just 12345)) -> True
+ _ -> False
xdescribe "No compression" $ aroundWith (. ((False, False),)) runRemoteTests
xdescribe "Mobile offers compression" $ aroundWith (. ((True, False),)) runRemoteTests
xdescribe "Desktop offers compression" $ aroundWith (. ((False, True),)) runRemoteTests
diff --git a/tests/SchemaDump.hs b/tests/SchemaDump.hs
index bc74f3ec33..2336fd56dd 100644
--- a/tests/SchemaDump.hs
+++ b/tests/SchemaDump.hs
@@ -145,7 +145,7 @@ skipComparisonForDownMigrations =
-- on down migration single_sender_group_member_id column and its index
-- are re-added at the end of the table / file (ALTER TABLE ADD COLUMN
-- appends; CREATE INDEX appends).
- "20260515_delivery_job_senders"
+ "20260529_delivery_job_senders"
]
getSchema :: FilePath -> FilePath -> IO String
diff --git a/tests/ValidNames.hs b/tests/ValidNames.hs
index 22ac4a695d..dd8433d231 100644
--- a/tests/ValidNames.hs
+++ b/tests/ValidNames.hs
@@ -10,15 +10,17 @@ validNameTests = describe "valid chat names" $ do
testMkValidName :: IO ()
testMkValidName = do
mkValidName "alice" `shouldBe` "alice"
+ mkValidName " alice" `shouldBe` "alice"
+ mkValidName "?alice" `shouldBe` "alice"
mkValidName "алиса" `shouldBe` "алиса"
mkValidName "John Doe" `shouldBe` "John Doe"
- mkValidName "J.Doe" `shouldBe` "J.Doe"
- mkValidName "J. Doe" `shouldBe` "J. Doe"
- mkValidName "J..Doe" `shouldBe` "J..Doe"
- mkValidName "J ..Doe" `shouldBe` "J ..Doe"
- mkValidName "J ... Doe" `shouldBe` "J ... Doe"
- mkValidName "J .... Doe" `shouldBe` "J ... Doe"
- mkValidName "J . . Doe" `shouldBe` "J . Doe"
+ mkValidName "J.Doe" `shouldBe` "JDoe"
+ mkValidName "J. Doe" `shouldBe` "J Doe"
+ mkValidName "J..Doe" `shouldBe` "JDoe"
+ mkValidName "J ..Doe" `shouldBe` "J Doe"
+ mkValidName "J ... Doe" `shouldBe` "J Doe"
+ mkValidName "J .... Doe" `shouldBe` "J Doe"
+ mkValidName "J . . Doe" `shouldBe` "J Doe"
mkValidName "@alice" `shouldBe` "alice"
mkValidName "#alice" `shouldBe` "alice"
mkValidName "'alice" `shouldBe` "alice"
@@ -26,17 +28,32 @@ testMkValidName = do
mkValidName "alice " `shouldBe` "alice"
mkValidName "John Doe" `shouldBe` "John Doe"
mkValidName "'John Doe'" `shouldBe` "John Doe"
- mkValidName "\"John Doe\"" `shouldBe` "John Doe\""
- mkValidName "`John Doe`" `shouldBe` "`John Doe`"
- mkValidName "John \"Doe\"" `shouldBe` "John \"Doe\""
- mkValidName "John `Doe`" `shouldBe` "John `Doe`"
- mkValidName "alice/bob" `shouldBe` "alice/bob"
- mkValidName "alice / bob" `shouldBe` "alice / bob"
- mkValidName "alice /// bob" `shouldBe` "alice /// bob"
- mkValidName "alice //// bob" `shouldBe` "alice /// bob"
+ mkValidName "\"John Doe\"" `shouldBe` "John Doe"
+ mkValidName "`John Doe`" `shouldBe` "John Doe"
+ mkValidName "John \"Doe\"" `shouldBe` "John Doe"
+ mkValidName "John `Doe`" `shouldBe` "John Doe"
+ mkValidName "alice/bob" `shouldBe` "alicebob"
+ mkValidName "alice / bob" `shouldBe` "alice bob"
+ mkValidName "alice /// bob" `shouldBe` "alice bob"
+ mkValidName "alice //// bob" `shouldBe` "alice bob"
mkValidName "alice >>= bob" `shouldBe` "alice >>= bob"
- mkValidName "alice@example.com" `shouldBe` "alice@example.com"
+ mkValidName "alice@example.com" `shouldBe` "aliceexamplecom"
mkValidName "alice <> bob" `shouldBe` "alice <> bob"
mkValidName "alice -> bob" `shouldBe` "alice -> bob"
+ mkValidName "alice & bob" `shouldBe` "alice & bob"
+ mkValidName "alice && bob" `shouldBe` "alice & bob"
+ mkValidName "alice & & bob" `shouldBe` "alice & bob"
+ mkValidName "alice-bob" `shouldBe` "alice-bob"
+ mkValidName "alice--bob" `shouldBe` "alice-bob"
+ mkValidName "alice -- bob" `shouldBe` "alice - bob"
+ mkValidName "alice \\ bob" `shouldBe` "alice bob"
+ mkValidName "alice (bob)" `shouldBe` "alice bob"
+ mkValidName "alice: bob" `shouldBe` "alice: bob"
+ mkValidName "alice 👍" `shouldBe` "alice 👍"
+ mkValidName "👍" `shouldBe` "👍"
+ mkValidName "alice >" `shouldBe` "alice >"
+ mkValidName "> alice" `shouldBe` "alice"
+ mkValidName "123" `shouldBe` "123"
+ mkValidName "123 alice" `shouldBe` "123 alice"
mkValidName "01234567890123456789012345678901234567890123456789extra" `shouldBe` "01234567890123456789012345678901234567890123456789"
mkValidName "0123456789012345678901234567890123456789012345678 extra" `shouldBe` "0123456789012345678901234567890123456789012345678"