Compare commits

..

1 Commits

Author SHA1 Message Date
Avently
fa9f5b3250 android, desktop: move function to different thread 2024-01-22 20:26:14 +07:00
143 changed files with 2772 additions and 2833 deletions

View File

@@ -87,7 +87,7 @@ jobs:
uses: actions/checkout@v3
- name: Setup Haskell
uses: haskell/actions/setup@v2
uses: haskell-actions/setup@v2
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: "3.10.1.0"
@@ -197,7 +197,7 @@ jobs:
APPLE_SIMPLEX_NOTARIZATION_APPLE_ID: ${{ secrets.APPLE_SIMPLEX_NOTARIZATION_APPLE_ID }}
APPLE_SIMPLEX_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_SIMPLEX_NOTARIZATION_PASSWORD }}
run: |
scripts/build-desktop-mac.sh
scripts/ci/build-desktop-mac.sh
path=$(echo $PWD/apps/multiplatform/release/main/dmg/SimpleX-*.dmg)
echo "package_path=$path" >> $GITHUB_OUTPUT
echo "package_hash=$(echo SHA2-512\(${{ matrix.desktop_asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
@@ -277,9 +277,7 @@ jobs:
# Unix /
# / Windows
# * In powershell multiline commands do not fail if individual commands fail - https://github.community/t/multiline-commands-on-windows-do-not-fail-if-individual-commands-fail/16753
# * And GitHub Actions does not support parameterizing shell in a matrix job - https://github.community/t/using-matrix-to-specify-shell-is-it-possible/17065
# rm -rf dist-newstyle/src/direct-sq* is here because of the bug in cabal's dependency which prevents second build from finishing
- name: 'Setup MSYS2'
if: matrix.os == 'windows-latest'

View File

@@ -234,8 +234,6 @@ You can use SimpleX with your own servers and still communicate with people usin
Recent and important updates:
[Jan 24, 2024. SimpleX Chat: free infrastructure from Linode, v5.5 released with private notes, group history and a simpler UX to connect.](./blog/20240124-simplex-chat-infrastructure-costs-v5-5-simplex-ux-private-notes-group-history.md)
[Nov 25, 2023. SimpleX Chat v5.4 released: link mobile and desktop apps via quantum resistant protocol, and much better groups](./blog/20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.md).
[Sep 25, 2023. SimpleX Chat v5.3 released: desktop app, local file encryption, improved groups and directory service](./blog/20230925-simplex-chat-v5-3-desktop-app-local-file-encryption-directory-service.md).
@@ -301,7 +299,7 @@ What is already implemented:
11. Transport isolation - different TCP connections and Tor circuits are used for traffic of different user profiles, optionally - for different contacts and group member connections.
12. Manual messaging queue rotations to move conversation to another SMP relay.
13. Sending end-to-end encrypted files using [XFTP protocol](https://simplex.chat/blog/20230301-simplex-file-transfer-protocol.html).
14. Local files encryption.
14. Local files encryption, except videos (to be added later).
We plan to add:
@@ -373,13 +371,12 @@ Please also join [#simplex-devs](https://simplex.chat/contact#/?v=1-2&smp=smp%3A
- ✅ Desktop client.
- ✅ Encryption of local files stored in the app.
- ✅ Using mobile profiles from the desktop app.
- ✅ Private notes.
- ✅ Improve sending videos (including encryption of locally stored videos).
- 🏗 Improve experience for the new users.
- 🏗 Post-quantum resistant key exchange in double ratchet protocol.
- 🏗 Large groups, communities and public channels.
- 🏗 Message delivery relay for senders (to conceal IP address from the recipients' servers and to reduce the traffic).
- Message delivery relay for senders (to conceal IP address from the recipients' servers and to reduce the traffic).
- Privacy & security slider - a simple way to set all settings at once.
- Improve sending videos (including encryption of locally stored videos).
- SMP queue redundancy and rotation (manual is supported).
- Include optional message into connection request sent via contact address.
- Improved navigation and search in the conversation (expand and scroll to quoted message, scroll to search results, etc.).

View File

@@ -252,6 +252,12 @@ func apiSetFilesFolder(filesFolder: String) throws {
throw r
}
func setXFTPConfig(_ cfg: XFTPFileConfig?) throws {
let r = chatSendCmdSync(.apiSetXFTPConfig(config: cfg))
if case .cmdOk = r { return }
throw r
}
func apiSetEncryptLocalFiles(_ enable: Bool) throws {
let r = chatSendCmdSync(.apiSetEncryptLocalFiles(enable: enable))
if case .cmdOk = r { return }
@@ -1166,7 +1172,7 @@ func filterMembersToAdd(_ ms: [GMember]) -> [Contact] {
let memberContactIds = ms.compactMap{ m in m.wrapped.memberCurrent ? m.wrapped.memberContactId : nil }
return ChatModel.shared.chats
.compactMap{ $0.chatInfo.contact }
.filter{ c in c.ready && c.active && !memberContactIds.contains(c.apiId) }
.filter{ !memberContactIds.contains($0.apiId) }
.sorted{ $0.displayName.lowercased() < $1.displayName.lowercased() }
}
@@ -1243,6 +1249,7 @@ func initializeChat(start: Bool, confirmStart: Bool = false, dbKey: String? = ni
}
try apiSetTempFolder(tempFolder: getTempFilesDirectory().path)
try apiSetFilesFolder(filesFolder: getAppFilesDirectory().path)
try setXFTPConfig(getXFTPCfg())
try apiSetEncryptLocalFiles(privacyEncryptLocalFilesGroupDefault.get())
m.chatInitialized = true
m.currentUser = try apiGetActiveUser()
@@ -1854,9 +1861,7 @@ func chatItemSimpleUpdate(_ user: any UserLike, _ aChatItem: AChatItem) async {
let cItem = aChatItem.chatItem
if active(user) {
if await MainActor.run(body: { m.upsertChatItem(cInfo, cItem) }) {
if cItem.showNotification {
NtfManager.shared.notifyMessageReceived(user, cInfo, cItem)
}
NtfManager.shared.notifyMessageReceived(user, cInfo, cItem)
}
}
}

View File

@@ -65,8 +65,6 @@ struct MarkedDeletedItemView: View {
}
}
// same texts are in markedDeletedText in ChatPreviewView, but it returns String;
// can be refactored into a single function if functions calling these are changed to return same type
var markedDeletedText: LocalizedStringKey {
switch chatItem.meta.itemDeleted {
case let .moderated(_, byGroupMember): "moderated by \(byGroupMember.displayName)"

View File

@@ -159,13 +159,12 @@ struct ChatView: View {
switch cInfo {
case let .direct(contact):
HStack {
let callsPrefEnabled = contact.mergedPreferences.calls.enabled.forUser
if callsPrefEnabled {
if contact.allowsFeature(.calls) {
callButton(contact, .audio, imageName: "phone")
.disabled(!contact.ready || !contact.active)
}
Menu {
if callsPrefEnabled {
if contact.allowsFeature(.calls) {
Button {
CallController.shared.startCall(contact, .video)
} label: {
@@ -749,9 +748,7 @@ struct ChatView: View {
if ci.meta.editable && !mc.isVoice && !live {
menu.append(editAction(ci))
}
if !ci.isLiveDummy {
menu.append(viewInfoUIAction(ci))
}
menu.append(viewInfoUIAction(ci))
if revealed {
menu.append(hideUIAction())
}

View File

@@ -978,9 +978,6 @@ struct ComposeView: View {
}
private func cancelLinkPreview() {
if let pendingLink = pendingLinkUrl?.absoluteString {
cancelledLinks.insert(pendingLink)
}
if let uri = composeState.linkPreview?.uri.absoluteString {
cancelledLinks.insert(uri)
}

View File

@@ -370,11 +370,7 @@ struct GroupChatInfoView: View {
private func addOrEditWelcomeMessage() -> some View {
NavigationLink {
GroupWelcomeView(
groupInfo: $groupInfo,
groupProfile: groupInfo.groupProfile,
welcomeText: groupInfo.groupProfile.description ?? ""
)
GroupWelcomeView(groupId: groupInfo.groupId, groupInfo: $groupInfo)
.navigationTitle("Welcome message")
.navigationBarTitleDisplayMode(.large)
} label: {

View File

@@ -11,32 +11,29 @@ import SimpleXChat
struct GroupWelcomeView: View {
@Environment(\.dismiss) var dismiss: DismissAction
@EnvironmentObject private var m: ChatModel
var groupId: Int64
@Binding var groupInfo: GroupInfo
@State var groupProfile: GroupProfile
@State var welcomeText: String
@State private var welcomeText: String = ""
@State private var editMode = true
@FocusState private var keyboardVisible: Bool
@State private var showSaveDialog = false
let maxByteCount = 1200
var body: some View {
VStack {
if groupInfo.canEdit {
editorView()
.modifier(BackButton {
if welcomeTextUnchanged() {
if welcomeText == groupInfo.groupProfile.description || (welcomeText == "" && groupInfo.groupProfile.description == nil) {
dismiss()
} else {
showSaveDialog = true
}
})
.confirmationDialog(
welcomeTextFitsLimit() ? "Save welcome message?" : "Welcome message is too long",
isPresented: $showSaveDialog
) {
if welcomeTextFitsLimit() {
Button("Save and update group profile") { save() }
.confirmationDialog("Save welcome message?", isPresented: $showSaveDialog) {
Button("Save and update group profile") {
save()
dismiss()
}
Button("Exit without saving") { dismiss() }
}
@@ -50,15 +47,14 @@ struct GroupWelcomeView: View {
}
}
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
keyboardVisible = true
}
welcomeText = groupInfo.groupProfile.description ?? ""
keyboardVisible = true
}
}
private func textPreview() -> some View {
messageText(welcomeText, parseSimpleXMarkdown(welcomeText), nil, showSecrets: false)
.frame(minHeight: 130, alignment: .topLeading)
.frame(minHeight: 140, alignment: .topLeading)
.frame(maxWidth: .infinity, alignment: .leading)
}
@@ -78,7 +74,7 @@ struct GroupWelcomeView: View {
}
.padding(.horizontal, -5)
.padding(.top, -8)
.frame(height: 130, alignment: .topLeading)
.frame(height: 140, alignment: .topLeading)
.frame(maxWidth: .infinity, alignment: .leading)
}
} else {
@@ -97,9 +93,6 @@ struct GroupWelcomeView: View {
}
.disabled(welcomeText.isEmpty)
copyButton()
} footer: {
Text(!welcomeTextFitsLimit() ? "Message too large" : "")
.foregroundColor(.red)
}
Section {
@@ -120,15 +113,7 @@ struct GroupWelcomeView: View {
Button("Save and update group profile") {
save()
}
.disabled(welcomeTextUnchanged() || !welcomeTextFitsLimit())
}
private func welcomeTextUnchanged() -> Bool {
welcomeText == groupInfo.groupProfile.description || (welcomeText == "" && groupInfo.groupProfile.description == nil)
}
private func welcomeTextFitsLimit() -> Bool {
chatJsonLength(welcomeText) <= maxByteCount
.disabled(welcomeText == groupInfo.groupProfile.description || (welcomeText == "" && groupInfo.groupProfile.description == nil))
}
private func save() {
@@ -138,13 +123,11 @@ struct GroupWelcomeView: View {
if welcome?.count == 0 {
welcome = nil
}
groupProfile.description = welcome
let gInfo = try await apiUpdateGroup(groupInfo.groupId, groupProfile)
await MainActor.run {
groupInfo = gInfo
ChatModel.shared.updateGroup(gInfo)
dismiss()
}
var groupProfileUpdated = groupInfo.groupProfile
groupProfileUpdated.description = welcome
groupInfo = try await apiUpdateGroup(groupId, groupProfileUpdated)
m.updateGroup(groupInfo)
welcomeText = welcome ?? ""
} catch let error {
logger.error("apiUpdateGroup error: \(responseError(error))")
}
@@ -154,6 +137,6 @@ struct GroupWelcomeView: View {
struct GroupWelcomeView_Previews: PreviewProvider {
static var previews: some View {
GroupProfileView(groupInfo: Binding.constant(GroupInfo.sampleData), groupProfile: GroupProfile.sampleData)
GroupWelcomeView(groupId: 1, groupInfo: Binding.constant(GroupInfo.sampleData))
}
}

View File

@@ -34,7 +34,7 @@ struct ChatPreviewView: View {
HStack(alignment: .top) {
chatPreviewTitle()
Spacer()
(cItem?.timestampText ?? formatTimestampText(chat.chatInfo.chatTs))
(cItem?.timestampText ?? formatTimestampText(chat.chatInfo.updatedAt))
.font(.subheadline)
.frame(minWidth: 60, alignment: .trailing)
.foregroundColor(.secondary)
@@ -171,21 +171,10 @@ struct ChatPreviewView: View {
}
func chatItemPreview(_ cItem: ChatItem) -> Text {
let itemText = cItem.meta.itemDeleted == nil ? cItem.text : markedDeletedText()
let itemText = cItem.meta.itemDeleted == nil ? cItem.text : NSLocalizedString("marked deleted", comment: "marked deleted chat item preview text")
let itemFormattedText = cItem.meta.itemDeleted == nil ? cItem.formattedText : nil
return messageText(itemText, itemFormattedText, cItem.memberDisplayName, icon: attachment(), preview: true, showSecrets: false)
// same texts are in markedDeletedText in MarkedDeletedItemView, but it returns LocalizedStringKey;
// can be refactored into a single function if functions calling these are changed to return same type
func markedDeletedText() -> String {
switch cItem.meta.itemDeleted {
case let .moderated(_, byGroupMember): String.localizedStringWithFormat(NSLocalizedString("moderated by %@", comment: "marked deleted chat item preview text"), byGroupMember.displayName)
case .blocked: NSLocalizedString("blocked", comment: "marked deleted chat item preview text")
case .blockedByAdmin: NSLocalizedString("blocked by admin", comment: "marked deleted chat item preview text")
case .deleted, nil: NSLocalizedString("marked deleted", comment: "marked deleted chat item preview text")
}
}
func attachment() -> String? {
switch cItem.content.msgContent {
case .file: return "doc.fill"

View File

@@ -42,6 +42,25 @@ struct DeveloperView: View {
} footer: {
(developerTools ? Text("Show:") : Text("Hide:")) + Text(" ") + Text("Database IDs and Transport isolation option.")
}
// Section {
// settingsRow("arrow.up.doc") {
// Toggle("Send videos and files via XFTP", isOn: $xftpSendEnabled)
// .onChange(of: xftpSendEnabled) { _ in
// do {
// try setXFTPConfig(getXFTPCfg())
// } catch {
// logger.error("setXFTPConfig: cannot set XFTP config \(responseError(error))")
// }
// }
// }
// } header: {
// Text("Experimental")
// } footer: {
// if xftpSendEnabled {
// Text("v4.6.1+ is required to receive via XFTP.")
// }
// }
}
}
}

View File

@@ -219,7 +219,6 @@
</trans-unit>
<trans-unit id="%lld messages blocked by admin" xml:space="preserve">
<source>%lld messages blocked by admin</source>
<target>%lld Nachrichten wurden vom Administrator blockiert</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve">
@@ -645,7 +644,6 @@
</trans-unit>
<trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve">
<source>All messages will be deleted - this cannot be undone!</source>
<target>Es werden alle Nachrichten gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve">
@@ -655,7 +653,7 @@
</trans-unit>
<trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve">
<source>All new messages from %@ will be hidden!</source>
<target>Von %@ werden alle neuen Nachrichten ausgeblendet!</target>
<target>Alle neuen Nachrichten von %@ werden verborgen!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
@@ -925,7 +923,6 @@
</trans-unit>
<trans-unit id="Block for all" xml:space="preserve">
<source>Block for all</source>
<target>Für Alle blockieren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
@@ -940,7 +937,6 @@
</trans-unit>
<trans-unit id="Block member for all?" xml:space="preserve">
<source>Block member for all?</source>
<target>Mitglied für Alle blockieren?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member?" xml:space="preserve">
@@ -950,7 +946,6 @@
</trans-unit>
<trans-unit id="Blocked by admin" xml:space="preserve">
<source>Blocked by admin</source>
<target>wurde vom Administrator blockiert</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@@ -1166,7 +1161,6 @@
</trans-unit>
<trans-unit id="Clear private notes?" xml:space="preserve">
<source>Clear private notes?</source>
<target>Private Notizen löschen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Clear verification" xml:space="preserve">
@@ -1465,12 +1459,10 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit>
<trans-unit id="Created at" xml:space="preserve">
<source>Created at</source>
<target>Erstellt um</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Created at: %@" xml:space="preserve">
<source>Created at: %@</source>
<target>Erstellt um: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Created on %@" xml:space="preserve">
@@ -2260,7 +2252,6 @@ Das kann nicht rückgängig gemacht werden!</target>
</trans-unit>
<trans-unit id="Error creating message" xml:space="preserve">
<source>Error creating message</source>
<target>Fehler beim Erstellen der Nachricht</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error creating profile!" xml:space="preserve">
@@ -2935,7 +2926,6 @@ Das kann nicht rückgängig gemacht werden!</target>
</trans-unit>
<trans-unit id="Improved message delivery" xml:space="preserve">
<source>Improved message delivery</source>
<target>Verbesserte Zustellung von Nachrichten</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Improved privacy and security" xml:space="preserve">
@@ -3163,7 +3153,6 @@ Das kann nicht rückgängig gemacht werden!</target>
</trans-unit>
<trans-unit id="Join group conversations" xml:space="preserve">
<source>Join group conversations</source>
<target>Gruppenunterhaltungen beitreten</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join group?" xml:space="preserve">
@@ -3874,7 +3863,6 @@ Das ist Ihr Link für die Gruppe %@!</target>
</trans-unit>
<trans-unit id="Past member %@" xml:space="preserve">
<source>Past member %@</source>
<target>Ehemaliges Mitglied %@</target>
<note>past/unknown group member</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve">
@@ -3889,7 +3877,6 @@ Das ist Ihr Link für die Gruppe %@!</target>
</trans-unit>
<trans-unit id="Paste link to connect!" xml:space="preserve">
<source>Paste link to connect!</source>
<target>Zum Verbinden den Link einfügen!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve">
@@ -4026,7 +4013,6 @@ Fehler: %@</target>
</trans-unit>
<trans-unit id="Private notes" xml:space="preserve">
<source>Private notes</source>
<target>Private Notizen</target>
<note>name of notes to self</note>
</trans-unit>
<trans-unit id="Profile and server connections" xml:space="preserve">
@@ -4211,7 +4197,6 @@ Fehler: %@</target>
</trans-unit>
<trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve">
<source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source>
<target>Aktueller Nachrichtenverlauf und verbesserter [Gruppenverzeichnis-Bot](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Recipients see updates as you type them." xml:space="preserve">
@@ -4501,7 +4486,6 @@ Fehler: %@</target>
</trans-unit>
<trans-unit id="Saved message" xml:space="preserve">
<source>Saved message</source>
<target>Gespeicherte Nachricht</target>
<note>message info title</note>
</trans-unit>
<trans-unit id="Scan QR code" xml:space="preserve">
@@ -4536,7 +4520,6 @@ Fehler: %@</target>
</trans-unit>
<trans-unit id="Search bar accepts invitation links." xml:space="preserve">
<source>Search bar accepts invitation links.</source>
<target>Von der Suchleiste werden Einladungslinks akzeptiert.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
@@ -5375,7 +5358,6 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt
</trans-unit>
<trans-unit id="Turkish interface" xml:space="preserve">
<source>Turkish interface</source>
<target>Türkische Bedienoberfläche</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn off" xml:space="preserve">
@@ -5400,7 +5382,6 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt
</trans-unit>
<trans-unit id="Unblock for all" xml:space="preserve">
<source>Unblock for all</source>
<target>Für Alle freigeben</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member" xml:space="preserve">
@@ -5410,7 +5391,6 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt
</trans-unit>
<trans-unit id="Unblock member for all?" xml:space="preserve">
<source>Unblock member for all?</source>
<target>Mitglied für Alle freigeben?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
@@ -5777,7 +5757,6 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit>
<trans-unit id="With encrypted files and media." xml:space="preserve">
<source>With encrypted files and media.</source>
<target>Mit verschlüsselten Dateien und Medien.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="With optional welcome message." xml:space="preserve">
@@ -5787,7 +5766,6 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit>
<trans-unit id="With reduced battery usage." xml:space="preserve">
<source>With reduced battery usage.</source>
<target>Mit reduziertem Akkuverbrauch.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Wrong database passphrase" xml:space="preserve">
@@ -6290,17 +6268,15 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="blocked" xml:space="preserve">
<source>blocked</source>
<target>Blockiert</target>
<target>blockiert</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="blocked %@" xml:space="preserve">
<source>blocked %@</source>
<target>%@ wurde blockiert</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="blocked by admin" xml:space="preserve">
<source>blocked by admin</source>
<target>wurde vom Administrator blockiert</target>
<note>blocked chat item</note>
</trans-unit>
<trans-unit id="bold" xml:space="preserve">
@@ -6425,7 +6401,6 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="contact %@ changed to %@" xml:space="preserve">
<source>contact %1$@ changed to %2$@</source>
<target>Der Kontaktname %1$@ wurde auf %2$@ geändert</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="contact has e2e encryption" xml:space="preserve">
@@ -6700,7 +6675,6 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="member %@ changed to %@" xml:space="preserve">
<source>member %1$@ changed to %2$@</source>
<target>Der Mitgliedsname %1$@ wurde auf %2$@ geändert</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="member connected" xml:space="preserve">
@@ -6827,12 +6801,10 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="removed contact address" xml:space="preserve">
<source>removed contact address</source>
<target>Kontaktadresse wurde entfernt</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="removed profile picture" xml:space="preserve">
<source>removed profile picture</source>
<target>Profil-Bild wurde entfernt</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="removed you" xml:space="preserve">
@@ -6867,12 +6839,10 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="set new contact address" xml:space="preserve">
<source>set new contact address</source>
<target>Neue Kontaktadresse wurde festgelegt</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="set new profile picture" xml:space="preserve">
<source>set new profile picture</source>
<target>Neues Profil-Bild wurde festgelegt</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="starting…" xml:space="preserve">
@@ -6892,7 +6862,6 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="unblocked %@" xml:space="preserve">
<source>unblocked %@</source>
<target>%@ wurde freigegeben</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="unknown" xml:space="preserve">
@@ -6902,7 +6871,6 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="unknown status" xml:space="preserve">
<source>unknown status</source>
<target>unbekannter Gruppenmitglieds-Status</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="updated group profile" xml:space="preserve">
@@ -6912,7 +6880,6 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="updated profile" xml:space="preserve">
<source>updated profile</source>
<target>Das Profil wurde aktualisiert</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="v%@" xml:space="preserve">
@@ -6987,7 +6954,6 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="you blocked %@" xml:space="preserve">
<source>you blocked %@</source>
<target>Sie haben %@ blockiert</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you changed address" xml:space="preserve">
@@ -7032,7 +6998,6 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="you unblocked %@" xml:space="preserve">
<source>you unblocked %@</source>
<target>Sie haben %@ freigegeben</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you: " xml:space="preserve">

View File

@@ -219,7 +219,6 @@
</trans-unit>
<trans-unit id="%lld messages blocked by admin" xml:space="preserve">
<source>%lld messages blocked by admin</source>
<target>%lld messaggi bloccati dall'amministratore</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve">
@@ -925,7 +924,6 @@
</trans-unit>
<trans-unit id="Block for all" xml:space="preserve">
<source>Block for all</source>
<target>Blocca per tutti</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
@@ -940,7 +938,6 @@
</trans-unit>
<trans-unit id="Block member for all?" xml:space="preserve">
<source>Block member for all?</source>
<target>Bloccare il membro per tutti?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member?" xml:space="preserve">
@@ -950,7 +947,6 @@
</trans-unit>
<trans-unit id="Blocked by admin" xml:space="preserve">
<source>Blocked by admin</source>
<target>Bloccato dall'amministratore</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@@ -5400,7 +5396,6 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio
</trans-unit>
<trans-unit id="Unblock for all" xml:space="preserve">
<source>Unblock for all</source>
<target>Sblocca per tutti</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member" xml:space="preserve">
@@ -5410,7 +5405,6 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio
</trans-unit>
<trans-unit id="Unblock member for all?" xml:space="preserve">
<source>Unblock member for all?</source>
<target>Sbloccare il membro per tutti?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
@@ -6295,12 +6289,10 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
</trans-unit>
<trans-unit id="blocked %@" xml:space="preserve">
<source>blocked %@</source>
<target>ha bloccato %@</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="blocked by admin" xml:space="preserve">
<source>blocked by admin</source>
<target>bloccato dall'amministratore</target>
<note>blocked chat item</note>
</trans-unit>
<trans-unit id="bold" xml:space="preserve">
@@ -6892,7 +6884,6 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
</trans-unit>
<trans-unit id="unblocked %@" xml:space="preserve">
<source>unblocked %@</source>
<target>ha sbloccato %@</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="unknown" xml:space="preserve">
@@ -6987,7 +6978,6 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
</trans-unit>
<trans-unit id="you blocked %@" xml:space="preserve">
<source>you blocked %@</source>
<target>hai bloccato %@</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you changed address" xml:space="preserve">
@@ -7032,7 +7022,6 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
</trans-unit>
<trans-unit id="you unblocked %@" xml:space="preserve">
<source>you unblocked %@</source>
<target>hai sbloccato %@</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you: " xml:space="preserve">

View File

@@ -219,7 +219,6 @@
</trans-unit>
<trans-unit id="%lld messages blocked by admin" xml:space="preserve">
<source>%lld messages blocked by admin</source>
<target>%lld berichten geblokkeerd door beheerder</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve">
@@ -925,7 +924,6 @@
</trans-unit>
<trans-unit id="Block for all" xml:space="preserve">
<source>Block for all</source>
<target>Blokkeren voor iedereen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
@@ -940,7 +938,6 @@
</trans-unit>
<trans-unit id="Block member for all?" xml:space="preserve">
<source>Block member for all?</source>
<target>Lid voor iedereen blokkeren?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member?" xml:space="preserve">
@@ -950,7 +947,6 @@
</trans-unit>
<trans-unit id="Blocked by admin" xml:space="preserve">
<source>Blocked by admin</source>
<target>Geblokkeerd door beheerder</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@@ -3163,7 +3159,7 @@ Dit kan niet ongedaan gemaakt worden!</target>
</trans-unit>
<trans-unit id="Join group conversations" xml:space="preserve">
<source>Join group conversations</source>
<target>Neem deel aan groepsgesprekken</target>
<target>Neem deel aan groep gesprekken</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join group?" xml:space="preserve">
@@ -3889,7 +3885,7 @@ Dit is jouw link voor groep %@!</target>
</trans-unit>
<trans-unit id="Paste link to connect!" xml:space="preserve">
<source>Paste link to connect!</source>
<target>Plak een link om te verbinden!</target>
<target>Plak link om te verbinden!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve">
@@ -4541,7 +4537,7 @@ Fout: %@</target>
</trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<target>Zoek of plak een SimpleX link</target>
<target>Zoek of plak de SimpleX link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve">
@@ -5400,7 +5396,6 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc
</trans-unit>
<trans-unit id="Unblock for all" xml:space="preserve">
<source>Unblock for all</source>
<target>Deblokkeer voor iedereen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member" xml:space="preserve">
@@ -5410,7 +5405,6 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc
</trans-unit>
<trans-unit id="Unblock member for all?" xml:space="preserve">
<source>Unblock member for all?</source>
<target>Lid voor iedereen deblokkeren?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
@@ -6295,12 +6289,10 @@ SimpleX servers kunnen uw profiel niet zien.</target>
</trans-unit>
<trans-unit id="blocked %@" xml:space="preserve">
<source>blocked %@</source>
<target>geblokkeerd %@</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="blocked by admin" xml:space="preserve">
<source>blocked by admin</source>
<target>geblokkeerd door beheerder</target>
<note>blocked chat item</note>
</trans-unit>
<trans-unit id="bold" xml:space="preserve">
@@ -6892,7 +6884,6 @@ SimpleX servers kunnen uw profiel niet zien.</target>
</trans-unit>
<trans-unit id="unblocked %@" xml:space="preserve">
<source>unblocked %@</source>
<target>gedeblokkeerd %@</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="unknown" xml:space="preserve">
@@ -6987,7 +6978,6 @@ SimpleX servers kunnen uw profiel niet zien.</target>
</trans-unit>
<trans-unit id="you blocked %@" xml:space="preserve">
<source>you blocked %@</source>
<target>je hebt %@ geblokkeerd</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you changed address" xml:space="preserve">
@@ -7032,7 +7022,6 @@ SimpleX servers kunnen uw profiel niet zien.</target>
</trans-unit>
<trans-unit id="you unblocked %@" xml:space="preserve">
<source>you unblocked %@</source>
<target>je hebt %@ gedeblokkeerd</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you: " xml:space="preserve">

View File

@@ -219,7 +219,6 @@
</trans-unit>
<trans-unit id="%lld messages blocked by admin" xml:space="preserve">
<source>%lld messages blocked by admin</source>
<target>%lld wiadomości zablokowanych przez admina</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve">
@@ -645,7 +644,6 @@
</trans-unit>
<trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve">
<source>All messages will be deleted - this cannot be undone!</source>
<target>Wszystkie wiadomości zostaną usunięte nie można tego cofnąć!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve">
@@ -925,7 +923,6 @@
</trans-unit>
<trans-unit id="Block for all" xml:space="preserve">
<source>Block for all</source>
<target>Zablokuj dla wszystkich</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
@@ -940,7 +937,6 @@
</trans-unit>
<trans-unit id="Block member for all?" xml:space="preserve">
<source>Block member for all?</source>
<target>Zablokować członka dla wszystkich?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member?" xml:space="preserve">
@@ -950,7 +946,6 @@
</trans-unit>
<trans-unit id="Blocked by admin" xml:space="preserve">
<source>Blocked by admin</source>
<target>Zablokowany przez admina</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@@ -1166,7 +1161,6 @@
</trans-unit>
<trans-unit id="Clear private notes?" xml:space="preserve">
<source>Clear private notes?</source>
<target>Wyczyścić prywatne notatki?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Clear verification" xml:space="preserve">
@@ -1465,12 +1459,10 @@ To jest twój jednorazowy link!</target>
</trans-unit>
<trans-unit id="Created at" xml:space="preserve">
<source>Created at</source>
<target>Utworzony o</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Created at: %@" xml:space="preserve">
<source>Created at: %@</source>
<target>Utworzony o: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Created on %@" xml:space="preserve">
@@ -1965,7 +1957,6 @@ To nie może być cofnięte!</target>
</trans-unit>
<trans-unit id="Do not send history to new members." xml:space="preserve">
<source>Do not send history to new members.</source>
<target>Nie wysyłaj historii do nowych członków.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Don't create address" xml:space="preserve">
@@ -2260,7 +2251,6 @@ To nie może być cofnięte!</target>
</trans-unit>
<trans-unit id="Error creating message" xml:space="preserve">
<source>Error creating message</source>
<target>Błąd tworzenia wiadomości</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error creating profile!" xml:space="preserve">
@@ -2840,7 +2830,6 @@ To nie może być cofnięte!</target>
</trans-unit>
<trans-unit id="History is not sent to new members." xml:space="preserve">
<source>History is not sent to new members.</source>
<target>Historia nie jest wysyłana do nowych członków.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="How SimpleX works" xml:space="preserve">
@@ -2935,7 +2924,6 @@ To nie może być cofnięte!</target>
</trans-unit>
<trans-unit id="Improved message delivery" xml:space="preserve">
<source>Improved message delivery</source>
<target>Ulepszona dostawa wiadomości</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Improved privacy and security" xml:space="preserve">
@@ -3052,7 +3040,6 @@ To nie może być cofnięte!</target>
</trans-unit>
<trans-unit id="Invalid display name!" xml:space="preserve">
<source>Invalid display name!</source>
<target>Nieprawidłowa nazwa wyświetlana!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
@@ -3163,7 +3150,6 @@ To nie może być cofnięte!</target>
</trans-unit>
<trans-unit id="Join group conversations" xml:space="preserve">
<source>Join group conversations</source>
<target>Dołącz do grupowej rozmowy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join group?" xml:space="preserve">
@@ -3874,7 +3860,6 @@ To jest twój link do grupy %@!</target>
</trans-unit>
<trans-unit id="Past member %@" xml:space="preserve">
<source>Past member %@</source>
<target>Były członek %@</target>
<note>past/unknown group member</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve">
@@ -3889,7 +3874,6 @@ To jest twój link do grupy %@!</target>
</trans-unit>
<trans-unit id="Paste link to connect!" xml:space="preserve">
<source>Paste link to connect!</source>
<target>Wklej link, aby połączyć!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve">
@@ -4026,7 +4010,6 @@ Błąd: %@</target>
</trans-unit>
<trans-unit id="Private notes" xml:space="preserve">
<source>Private notes</source>
<target>Prywatne notatki</target>
<note>name of notes to self</note>
</trans-unit>
<trans-unit id="Profile and server connections" xml:space="preserve">
@@ -4211,7 +4194,6 @@ Błąd: %@</target>
</trans-unit>
<trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve">
<source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source>
<target>Ostania historia i ulepszony [bot adresowy](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Recipients see updates as you type them." xml:space="preserve">
@@ -4501,7 +4483,6 @@ Błąd: %@</target>
</trans-unit>
<trans-unit id="Saved message" xml:space="preserve">
<source>Saved message</source>
<target>Zachowano wiadomość</target>
<note>message info title</note>
</trans-unit>
<trans-unit id="Scan QR code" xml:space="preserve">
@@ -4536,7 +4517,6 @@ Błąd: %@</target>
</trans-unit>
<trans-unit id="Search bar accepts invitation links." xml:space="preserve">
<source>Search bar accepts invitation links.</source>
<target>Pasek wyszukiwania akceptuje linki zaproszenia.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
@@ -4651,7 +4631,6 @@ Błąd: %@</target>
</trans-unit>
<trans-unit id="Send up to 100 last messages to new members." xml:space="preserve">
<source>Send up to 100 last messages to new members.</source>
<target>Wysyłaj do 100 ostatnich wiadomości do nowych członków.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sender cancelled file transfer." xml:space="preserve">
@@ -5268,7 +5247,6 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
</trans-unit>
<trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve">
<source>This display name is invalid. Please choose another name.</source>
<target>Nazwa wyświetlana jest nieprawidłowa. Proszę wybrać inną nazwę.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
@@ -5375,7 +5353,6 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.</ta
</trans-unit>
<trans-unit id="Turkish interface" xml:space="preserve">
<source>Turkish interface</source>
<target>Turecki interfejs</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn off" xml:space="preserve">
@@ -5400,7 +5377,6 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.</ta
</trans-unit>
<trans-unit id="Unblock for all" xml:space="preserve">
<source>Unblock for all</source>
<target>Odblokuj dla wszystkich</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member" xml:space="preserve">
@@ -5410,7 +5386,6 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.</ta
</trans-unit>
<trans-unit id="Unblock member for all?" xml:space="preserve">
<source>Unblock member for all?</source>
<target>Odblokować członka dla wszystkich?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
@@ -5512,7 +5487,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
</trans-unit>
<trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve">
<source>Up to 100 last messages are sent to new members.</source>
<target>Do nowych członków wysyłanych jest do 100 ostatnich wiadomości.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Update" xml:space="preserve">
@@ -5687,7 +5661,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
</trans-unit>
<trans-unit id="Visible history" xml:space="preserve">
<source>Visible history</source>
<target>Widoczna historia</target>
<note>chat feature</note>
</trans-unit>
<trans-unit id="Voice messages" xml:space="preserve">
@@ -5777,7 +5750,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
</trans-unit>
<trans-unit id="With encrypted files and media." xml:space="preserve">
<source>With encrypted files and media.</source>
<target>Z zaszyfrowanymi plikami i multimediami.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="With optional welcome message." xml:space="preserve">
@@ -5787,7 +5759,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
</trans-unit>
<trans-unit id="With reduced battery usage." xml:space="preserve">
<source>With reduced battery usage.</source>
<target>Ze zmniejszonym zużyciem baterii.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Wrong database passphrase" xml:space="preserve">
@@ -6295,12 +6266,10 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit>
<trans-unit id="blocked %@" xml:space="preserve">
<source>blocked %@</source>
<target>zablokowany %@</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="blocked by admin" xml:space="preserve">
<source>blocked by admin</source>
<target>zablokowany przez admina</target>
<note>blocked chat item</note>
</trans-unit>
<trans-unit id="bold" xml:space="preserve">
@@ -6425,7 +6394,6 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit>
<trans-unit id="contact %@ changed to %@" xml:space="preserve">
<source>contact %1$@ changed to %2$@</source>
<target>kontakt %1$@ zmieniony na %2$@</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="contact has e2e encryption" xml:space="preserve">
@@ -6700,7 +6668,6 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit>
<trans-unit id="member %@ changed to %@" xml:space="preserve">
<source>member %1$@ changed to %2$@</source>
<target>członek %1$@ zmieniony na %2$@</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="member connected" xml:space="preserve">
@@ -6827,12 +6794,10 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit>
<trans-unit id="removed contact address" xml:space="preserve">
<source>removed contact address</source>
<target>usunięto adres kontaktu</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="removed profile picture" xml:space="preserve">
<source>removed profile picture</source>
<target>usunięto zdjęcie profilu</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="removed you" xml:space="preserve">
@@ -6867,12 +6832,10 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit>
<trans-unit id="set new contact address" xml:space="preserve">
<source>set new contact address</source>
<target>ustaw nowy adres kontaktu</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="set new profile picture" xml:space="preserve">
<source>set new profile picture</source>
<target>ustaw nowe zdjęcie profilu</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="starting…" xml:space="preserve">
@@ -6892,7 +6855,6 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit>
<trans-unit id="unblocked %@" xml:space="preserve">
<source>unblocked %@</source>
<target>odblokowano %@</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="unknown" xml:space="preserve">
@@ -6902,7 +6864,6 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit>
<trans-unit id="unknown status" xml:space="preserve">
<source>unknown status</source>
<target>nieznany status</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="updated group profile" xml:space="preserve">
@@ -6912,7 +6873,6 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit>
<trans-unit id="updated profile" xml:space="preserve">
<source>updated profile</source>
<target>zaktualizowano profil</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="v%@" xml:space="preserve">
@@ -6987,7 +6947,6 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit>
<trans-unit id="you blocked %@" xml:space="preserve">
<source>you blocked %@</source>
<target>zablokowałeś %@</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you changed address" xml:space="preserve">
@@ -7032,7 +6991,6 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit>
<trans-unit id="you unblocked %@" xml:space="preserve">
<source>you unblocked %@</source>
<target>odblokowałeś %@</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you: " xml:space="preserve">

View File

@@ -219,7 +219,6 @@
</trans-unit>
<trans-unit id="%lld messages blocked by admin" xml:space="preserve">
<source>%lld messages blocked by admin</source>
<target>%lld сообщений заблокировано администратором</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve">
@@ -925,7 +924,6 @@
</trans-unit>
<trans-unit id="Block for all" xml:space="preserve">
<source>Block for all</source>
<target>Заблокировать для всех</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
@@ -940,7 +938,6 @@
</trans-unit>
<trans-unit id="Block member for all?" xml:space="preserve">
<source>Block member for all?</source>
<target>Заблокировать члена для всех?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member?" xml:space="preserve">
@@ -950,7 +947,6 @@
</trans-unit>
<trans-unit id="Blocked by admin" xml:space="preserve">
<source>Blocked by admin</source>
<target>Заблокирован администратором</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@@ -5400,7 +5396,6 @@ You will be prompted to complete authentication before this feature is enabled.<
</trans-unit>
<trans-unit id="Unblock for all" xml:space="preserve">
<source>Unblock for all</source>
<target>Разблокировать для всех</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member" xml:space="preserve">
@@ -5410,7 +5405,6 @@ You will be prompted to complete authentication before this feature is enabled.<
</trans-unit>
<trans-unit id="Unblock member for all?" xml:space="preserve">
<source>Unblock member for all?</source>
<target>Разблокировать члена для всех?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
@@ -6295,12 +6289,10 @@ SimpleX серверы не могут получить доступ к Ваше
</trans-unit>
<trans-unit id="blocked %@" xml:space="preserve">
<source>blocked %@</source>
<target>%@ заблокирован</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="blocked by admin" xml:space="preserve">
<source>blocked by admin</source>
<target>заблокировано администратором</target>
<note>blocked chat item</note>
</trans-unit>
<trans-unit id="bold" xml:space="preserve">
@@ -6892,7 +6884,6 @@ SimpleX серверы не могут получить доступ к Ваше
</trans-unit>
<trans-unit id="unblocked %@" xml:space="preserve">
<source>unblocked %@</source>
<target>%@ разблокирован</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="unknown" xml:space="preserve">
@@ -6987,7 +6978,6 @@ SimpleX серверы не могут получить доступ к Ваше
</trans-unit>
<trans-unit id="you blocked %@" xml:space="preserve">
<source>you blocked %@</source>
<target>Вы заблокировали %@</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you changed address" xml:space="preserve">
@@ -7032,7 +7022,6 @@ SimpleX серверы не могут получить доступ к Ваше
</trans-unit>
<trans-unit id="you unblocked %@" xml:space="preserve">
<source>you unblocked %@</source>
<target>Вы разблокировали %@</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you: " xml:space="preserve">

View File

@@ -14,17 +14,17 @@
</trans-unit>
<trans-unit id=" " xml:space="preserve">
<source> </source>
<target> </target>
<target> . </target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=" " xml:space="preserve">
<source> </source>
<target> </target>
<target> </target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=" " xml:space="preserve">
<source> </source>
<target> </target>
<target> . </target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=" (" xml:space="preserve">

View File

@@ -453,6 +453,7 @@ var receiverStarted = false
let startLock = DispatchSemaphore(value: 1)
let suspendLock = DispatchSemaphore(value: 1)
var networkConfig: NetCfg = getNetCfg()
let xftpConfig: XFTPFileConfig? = getXFTPCfg()
// startChat uses semaphore startLock to ensure that only one didReceive thread can start chat controller
// Subsequent calls to didReceive will be waiting on semaphore and won't start chat again, as it will be .active
@@ -498,6 +499,7 @@ func doStartChat() -> DBMigrationResult? {
try setNetworkConfig(networkConfig)
try apiSetTempFolder(tempFolder: getTempFilesDirectory().path)
try apiSetFilesFolder(filesFolder: getAppFilesDirectory().path)
try setXFTPConfig(xftpConfig)
try apiSetEncryptLocalFiles(privacyEncryptLocalFilesGroupDefault.get())
// prevent suspension while starting chat
suspendLock.wait()
@@ -731,6 +733,12 @@ func apiSetFilesFolder(filesFolder: String) throws {
throw r
}
func setXFTPConfig(_ cfg: XFTPFileConfig?) throws {
let r = sendSimpleXCmd(.apiSetXFTPConfig(config: cfg))
if case .cmdOk = r { return }
throw r
}
func apiSetEncryptLocalFiles(_ enable: Bool) throws {
let r = sendSimpleXCmd(.apiSetEncryptLocalFiles(enable: enable))
if case .cmdOk = r { return }

View File

@@ -90,11 +90,6 @@
5CB0BA90282713D900B3292C /* SimpleXInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB0BA8F282713D900B3292C /* SimpleXInfo.swift */; };
5CB0BA92282713FD00B3292C /* CreateProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB0BA91282713FD00B3292C /* CreateProfile.swift */; };
5CB0BA9A2827FD8800B3292C /* HowItWorks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB0BA992827FD8800B3292C /* HowItWorks.swift */; };
5CB1CE922B86660100963938 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CB1CE8D2B86660100963938 /* libgmp.a */; };
5CB1CE932B86660100963938 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CB1CE8E2B86660100963938 /* libgmpxx.a */; };
5CB1CE942B86660100963938 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CB1CE8F2B86660100963938 /* libffi.a */; };
5CB1CE952B86660100963938 /* libHSsimplex-chat-5.5.5.0-7lQXtpK7ThcLvpQEItJUcV-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CB1CE902B86660100963938 /* libHSsimplex-chat-5.5.5.0-7lQXtpK7ThcLvpQEItJUcV-ghc9.6.3.a */; };
5CB1CE962B86660100963938 /* libHSsimplex-chat-5.5.5.0-7lQXtpK7ThcLvpQEItJUcV.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CB1CE912B86660100963938 /* libHSsimplex-chat-5.5.5.0-7lQXtpK7ThcLvpQEItJUcV.a */; };
5CB2084F28DA4B4800D024EC /* RTCServers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB2084E28DA4B4800D024EC /* RTCServers.swift */; };
5CB346E52868AA7F001FD2EF /* SuspendChat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB346E42868AA7F001FD2EF /* SuspendChat.swift */; };
5CB346E72868D76D001FD2EF /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB346E62868D76D001FD2EF /* NotificationsView.swift */; };
@@ -117,6 +112,11 @@
5CC2C0FF2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CC2C0FD2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings */; };
5CC868F329EB540C0017BBFD /* CIRcvDecryptionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC868F229EB540C0017BBFD /* CIRcvDecryptionError.swift */; };
5CCB939C297EFCB100399E78 /* NavStackCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCB939B297EFCB100399E78 /* NavStackCompat.swift */; };
5CCD2C462B5C800E00F76440 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCD2C412B5C800E00F76440 /* libgmpxx.a */; };
5CCD2C472B5C800E00F76440 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCD2C422B5C800E00F76440 /* libgmp.a */; };
5CCD2C482B5C800E00F76440 /* libHSsimplex-chat-5.5.0.3-3tzCJyUgrnK8CcHdWjtxcl-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCD2C432B5C800E00F76440 /* libHSsimplex-chat-5.5.0.3-3tzCJyUgrnK8CcHdWjtxcl-ghc9.6.3.a */; };
5CCD2C492B5C800E00F76440 /* libHSsimplex-chat-5.5.0.3-3tzCJyUgrnK8CcHdWjtxcl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCD2C442B5C800E00F76440 /* libHSsimplex-chat-5.5.0.3-3tzCJyUgrnK8CcHdWjtxcl.a */; };
5CCD2C4A2B5C800E00F76440 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CCD2C452B5C800E00F76440 /* libffi.a */; };
5CD67B8F2B0E858A00C510B1 /* hs_init.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CD67B8D2B0E858A00C510B1 /* hs_init.h */; settings = {ATTRIBUTES = (Public, ); }; };
5CD67B902B0E858A00C510B1 /* hs_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 5CD67B8E2B0E858A00C510B1 /* hs_init.c */; };
5CDCAD482818589900503DA2 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CDCAD472818589900503DA2 /* NotificationService.swift */; };
@@ -372,11 +372,6 @@
5CB0BA8F282713D900B3292C /* SimpleXInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleXInfo.swift; sourceTree = "<group>"; };
5CB0BA91282713FD00B3292C /* CreateProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateProfile.swift; sourceTree = "<group>"; };
5CB0BA992827FD8800B3292C /* HowItWorks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HowItWorks.swift; sourceTree = "<group>"; };
5CB1CE8D2B86660100963938 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
5CB1CE8E2B86660100963938 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
5CB1CE8F2B86660100963938 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
5CB1CE902B86660100963938 /* libHSsimplex-chat-5.5.5.0-7lQXtpK7ThcLvpQEItJUcV-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.5.0-7lQXtpK7ThcLvpQEItJUcV-ghc9.6.3.a"; sourceTree = "<group>"; };
5CB1CE912B86660100963938 /* libHSsimplex-chat-5.5.5.0-7lQXtpK7ThcLvpQEItJUcV.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.5.0-7lQXtpK7ThcLvpQEItJUcV.a"; sourceTree = "<group>"; };
5CB2084E28DA4B4800D024EC /* RTCServers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RTCServers.swift; sourceTree = "<group>"; };
5CB2085428DE647400D024EC /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
5CB346E42868AA7F001FD2EF /* SuspendChat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuspendChat.swift; sourceTree = "<group>"; };
@@ -403,6 +398,11 @@
5CC2C0FE2809BF11000C35E3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = "ru.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = "<group>"; };
5CC868F229EB540C0017BBFD /* CIRcvDecryptionError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIRcvDecryptionError.swift; sourceTree = "<group>"; };
5CCB939B297EFCB100399E78 /* NavStackCompat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavStackCompat.swift; sourceTree = "<group>"; };
5CCD2C412B5C800E00F76440 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
5CCD2C422B5C800E00F76440 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
5CCD2C432B5C800E00F76440 /* libHSsimplex-chat-5.5.0.3-3tzCJyUgrnK8CcHdWjtxcl-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.0.3-3tzCJyUgrnK8CcHdWjtxcl-ghc9.6.3.a"; sourceTree = "<group>"; };
5CCD2C442B5C800E00F76440 /* libHSsimplex-chat-5.5.0.3-3tzCJyUgrnK8CcHdWjtxcl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.0.3-3tzCJyUgrnK8CcHdWjtxcl.a"; sourceTree = "<group>"; };
5CCD2C452B5C800E00F76440 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
5CD67B8D2B0E858A00C510B1 /* hs_init.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hs_init.h; sourceTree = "<group>"; };
5CD67B8E2B0E858A00C510B1 /* hs_init.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hs_init.c; sourceTree = "<group>"; };
5CDCAD452818589900503DA2 /* SimpleX NSE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "SimpleX NSE.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -514,12 +514,12 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5CB1CE932B86660100963938 /* libgmpxx.a in Frameworks */,
5CCD2C462B5C800E00F76440 /* libgmpxx.a in Frameworks */,
5CCD2C492B5C800E00F76440 /* libHSsimplex-chat-5.5.0.3-3tzCJyUgrnK8CcHdWjtxcl.a in Frameworks */,
5CCD2C482B5C800E00F76440 /* libHSsimplex-chat-5.5.0.3-3tzCJyUgrnK8CcHdWjtxcl-ghc9.6.3.a in Frameworks */,
5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */,
5CB1CE962B86660100963938 /* libHSsimplex-chat-5.5.5.0-7lQXtpK7ThcLvpQEItJUcV.a in Frameworks */,
5CB1CE922B86660100963938 /* libgmp.a in Frameworks */,
5CB1CE952B86660100963938 /* libHSsimplex-chat-5.5.5.0-7lQXtpK7ThcLvpQEItJUcV-ghc9.6.3.a in Frameworks */,
5CB1CE942B86660100963938 /* libffi.a in Frameworks */,
5CCD2C4A2B5C800E00F76440 /* libffi.a in Frameworks */,
5CCD2C472B5C800E00F76440 /* libgmp.a in Frameworks */,
5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -582,11 +582,11 @@
5C764E5C279C70B7000C6508 /* Libraries */ = {
isa = PBXGroup;
children = (
5CB1CE8F2B86660100963938 /* libffi.a */,
5CB1CE8D2B86660100963938 /* libgmp.a */,
5CB1CE8E2B86660100963938 /* libgmpxx.a */,
5CB1CE902B86660100963938 /* libHSsimplex-chat-5.5.5.0-7lQXtpK7ThcLvpQEItJUcV-ghc9.6.3.a */,
5CB1CE912B86660100963938 /* libHSsimplex-chat-5.5.5.0-7lQXtpK7ThcLvpQEItJUcV.a */,
5CCD2C452B5C800E00F76440 /* libffi.a */,
5CCD2C422B5C800E00F76440 /* libgmp.a */,
5CCD2C412B5C800E00F76440 /* libgmpxx.a */,
5CCD2C432B5C800E00F76440 /* libHSsimplex-chat-5.5.0.3-3tzCJyUgrnK8CcHdWjtxcl-ghc9.6.3.a */,
5CCD2C442B5C800E00F76440 /* libHSsimplex-chat-5.5.0.3-3tzCJyUgrnK8CcHdWjtxcl.a */,
);
path = Libraries;
sourceTree = "<group>";
@@ -1509,7 +1509,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 200;
CURRENT_PROJECT_VERSION = 191;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
@@ -1531,7 +1531,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 5.5.5;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1552,7 +1552,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 200;
CURRENT_PROJECT_VERSION = 191;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
@@ -1574,7 +1574,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 5.5.5;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1633,7 +1633,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 200;
CURRENT_PROJECT_VERSION = 191;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GENERATE_INFOPLIST_FILE = YES;
@@ -1646,7 +1646,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.5.5;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1665,7 +1665,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 200;
CURRENT_PROJECT_VERSION = 191;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GENERATE_INFOPLIST_FILE = YES;
@@ -1678,7 +1678,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.5.5;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1697,7 +1697,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 200;
CURRENT_PROJECT_VERSION = 191;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1721,7 +1721,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Libraries/sim",
);
MARKETING_VERSION = 5.5.5;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
@@ -1743,7 +1743,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 200;
CURRENT_PROJECT_VERSION = 191;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1767,7 +1767,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Libraries/sim",
);
MARKETING_VERSION = 5.5.5;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;

View File

@@ -105,11 +105,6 @@ public func parseSimpleXMarkdown(_ s: String) -> [FormattedText]? {
return nil
}
public func chatJsonLength(_ s: String) -> Int {
var c = s.cString(using: .utf8)!
return Int(chat_json_length(&c))
}
struct ParsedMarkdown: Decodable {
var formattedText: [FormattedText]?
}

View File

@@ -31,6 +31,7 @@ public enum ChatCommand {
case apiSuspendChat(timeoutMicroseconds: Int)
case setTempFolder(tempFolder: String)
case setFilesFolder(filesFolder: String)
case apiSetXFTPConfig(config: XFTPFileConfig?)
case apiSetEncryptLocalFiles(enable: Bool)
case apiExportArchive(config: ArchiveConfig)
case apiImportArchive(config: ArchiveConfig)
@@ -161,6 +162,11 @@ public enum ChatCommand {
case let .apiSuspendChat(timeoutMicroseconds): return "/_app suspend \(timeoutMicroseconds)"
case let .setTempFolder(tempFolder): return "/_temp_folder \(tempFolder)"
case let .setFilesFolder(filesFolder): return "/_files_folder \(filesFolder)"
case let .apiSetXFTPConfig(cfg): if let cfg = cfg {
return "/_xftp on \(encodeJSON(cfg))"
} else {
return "/_xftp off"
}
case let .apiSetEncryptLocalFiles(enable): return "/_files_encrypt \(onOff(enable))"
case let .apiExportArchive(cfg): return "/_db export \(encodeJSON(cfg))"
case let .apiImportArchive(cfg): return "/_db import \(encodeJSON(cfg))"
@@ -305,6 +311,7 @@ public enum ChatCommand {
case .apiSuspendChat: return "apiSuspendChat"
case .setTempFolder: return "setTempFolder"
case .setFilesFolder: return "setFilesFolder"
case .apiSetXFTPConfig: return "apiSetXFTPConfig"
case .apiSetEncryptLocalFiles: return "apiSetEncryptLocalFiles"
case .apiExportArchive: return "apiExportArchive"
case .apiImportArchive: return "apiImportArchive"
@@ -998,6 +1005,10 @@ struct ComposedMessage: Encodable {
var msgContent: MsgContent
}
public struct XFTPFileConfig: Encodable {
var minFileSize: Int64
}
public struct ArchiveConfig: Encodable {
var archivePath: String
var disableCompression: Bool?

View File

@@ -265,6 +265,10 @@ public class Default<T> {
}
}
public func getXFTPCfg() -> XFTPFileConfig {
return XFTPFileConfig(minFileSize: 0)
}
public func getNetCfg() -> NetCfg {
let onionHosts = networkUseOnionHostsGroupDefault.get()
let (hostMode, requiredHostMode) = onionHosts.hostMode

View File

@@ -1367,17 +1367,6 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat {
}
}
public var chatTs: Date {
switch self {
case let .direct(contact): return contact.chatTs ?? contact.updatedAt
case let .group(groupInfo): return groupInfo.chatTs ?? groupInfo.updatedAt
case let .local(noteFolder): return noteFolder.chatTs
case let .contactRequest(contactRequest): return contactRequest.updatedAt
case let .contactConnection(contactConnection): return contactConnection.updatedAt
case .invalidJSON: return .now
}
}
public struct SampleData {
public var direct: ChatInfo
public var group: ChatInfo
@@ -1436,7 +1425,6 @@ public struct Contact: Identifiable, Decodable, NamedChat {
public var mergedPreferences: ContactUserPreferences
var createdAt: Date
var updatedAt: Date
var chatTs: Date?
var contactGroupMemberId: Int64?
var contactGrpInvSent: Bool
@@ -1756,7 +1744,6 @@ public struct GroupInfo: Identifiable, Decodable, NamedChat {
public var chatSettings: ChatSettings
var createdAt: Date
var updatedAt: Date
var chatTs: Date?
public var id: ChatId { get { "#\(groupId)" } }
public var apiId: Int64 { get { groupId } }
@@ -2062,7 +2049,6 @@ public struct NoteFolder: Identifiable, Decodable, NamedChat {
public var unread: Bool
var createdAt: Date
public var updatedAt: Date
var chatTs: Date
public var id: ChatId { get { "*\(noteFolderId)" } }
public var apiId: Int64 { get { noteFolderId } }
@@ -2084,8 +2070,7 @@ public struct NoteFolder: Identifiable, Decodable, NamedChat {
favorite: false,
unread: false,
createdAt: .now,
updatedAt: .now,
chatTs: .now
updatedAt: .now
)
}

View File

@@ -25,7 +25,6 @@ extern char *chat_parse_markdown(char *str);
extern char *chat_parse_server(char *str);
extern char *chat_password_hash(char *pwd, char *salt);
extern char *chat_valid_name(char *name);
extern int chat_json_length(char *str);
extern char *chat_encrypt_media(chat_ctrl ctl, char *key, char *frame, int len);
extern char *chat_decrypt_media(char *key, char *frame, int len);

View File

@@ -202,9 +202,6 @@
/* No comment provided by engineer. */
"%lld messages blocked" = "%lld Nachrichten blockiert";
/* No comment provided by engineer. */
"%lld messages blocked by admin" = "%lld Nachrichten wurden vom Administrator blockiert";
/* No comment provided by engineer. */
"%lld messages marked deleted" = "%lld Nachrichten als gelöscht markiert";
@@ -401,14 +398,11 @@
/* No comment provided by engineer. */
"All group members will remain connected." = "Alle Gruppenmitglieder bleiben verbunden.";
/* No comment provided by engineer. */
"All messages will be deleted - this cannot be undone!" = "Es werden alle Nachrichten gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden!";
/* No comment provided by engineer. */
"All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Alle Nachrichten werden gelöscht - dies kann nicht rückgängig gemacht werden! Die Nachrichten werden NUR bei Ihnen gelöscht.";
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Von %@ werden alle neuen Nachrichten ausgeblendet!";
"All new messages from %@ will be hidden!" = "Alle neuen Nachrichten von %@ werden verborgen!";
/* No comment provided by engineer. */
"All your contacts will remain connected." = "Alle Ihre Kontakte bleiben verbunden.";
@@ -587,32 +581,17 @@
/* No comment provided by engineer. */
"Block" = "Blockieren";
/* No comment provided by engineer. */
"Block for all" = "Für Alle blockieren";
/* No comment provided by engineer. */
"Block group members" = "Gruppenmitglieder blockieren";
/* No comment provided by engineer. */
"Block member" = "Mitglied blockieren";
/* No comment provided by engineer. */
"Block member for all?" = "Mitglied für Alle blockieren?";
/* No comment provided by engineer. */
"Block member?" = "Mitglied blockieren?";
/* No comment provided by engineer. */
"blocked" = "Blockiert";
/* rcv group event chat item */
"blocked %@" = "%@ wurde blockiert";
/* blocked chat item */
"blocked by admin" = "wurde vom Administrator blockiert";
/* No comment provided by engineer. */
"Blocked by admin" = "wurde vom Administrator blockiert";
"blocked" = "blockiert";
/* No comment provided by engineer. */
"bold" = "fett";
@@ -771,9 +750,6 @@
/* No comment provided by engineer. */
"Clear conversation?" = "Unterhaltung löschen?";
/* No comment provided by engineer. */
"Clear private notes?" = "Private Notizen löschen?";
/* No comment provided by engineer. */
"Clear verification" = "Überprüfung zurücknehmen";
@@ -912,9 +888,6 @@
/* connection information */
"connection:%@" = "Verbindung:%@";
/* profile update event chat item */
"contact %@ changed to %@" = "Der Kontaktname %1$@ wurde auf %2$@ geändert";
/* No comment provided by engineer. */
"Contact allows" = "Der Kontakt erlaubt";
@@ -999,12 +972,6 @@
/* No comment provided by engineer. */
"Create your profile" = "Erstellen Sie Ihr Profil";
/* No comment provided by engineer. */
"Created at" = "Erstellt um";
/* copied message info */
"Created at: %@" = "Erstellt um: %@";
/* No comment provided by engineer. */
"Created on %@" = "Erstellt am %@";
@@ -1557,9 +1524,6 @@
/* No comment provided by engineer. */
"Error creating member contact" = "Fehler beim Anlegen eines Mitglied-Kontaktes";
/* No comment provided by engineer. */
"Error creating message" = "Fehler beim Erstellen der Nachricht";
/* No comment provided by engineer. */
"Error creating profile!" = "Fehler beim Erstellen des Profils!";
@@ -1974,9 +1938,6 @@
/* No comment provided by engineer. */
"Import database" = "Datenbank importieren";
/* No comment provided by engineer. */
"Improved message delivery" = "Verbesserte Zustellung von Nachrichten";
/* No comment provided by engineer. */
"Improved privacy and security" = "Verbesserte Privatsphäre und Sicherheit";
@@ -2154,9 +2115,6 @@
/* No comment provided by engineer. */
"Join group" = "Treten Sie der Gruppe bei";
/* No comment provided by engineer. */
"Join group conversations" = "Gruppenunterhaltungen beitreten";
/* No comment provided by engineer. */
"Join group?" = "Der Gruppe beitreten?";
@@ -2292,9 +2250,6 @@
/* No comment provided by engineer. */
"Member" = "Mitglied";
/* profile update event chat item */
"member %@ changed to %@" = "Der Mitgliedsname %1$@ wurde auf %2$@ geändert";
/* rcv group event chat item */
"member connected" = "ist der Gruppe beigetreten";
@@ -2639,18 +2594,12 @@
/* No comment provided by engineer. */
"Password to show" = "Passwort anzeigen";
/* past/unknown group member */
"Past member %@" = "Ehemaliges Mitglied %@";
/* No comment provided by engineer. */
"Paste desktop address" = "Desktop-Adresse einfügen";
/* No comment provided by engineer. */
"Paste image" = "Bild einfügen";
/* No comment provided by engineer. */
"Paste link to connect!" = "Zum Verbinden den Link einfügen!";
/* No comment provided by engineer. */
"Paste the link you received" = "Fügen Sie den erhaltenen Link ein";
@@ -2738,9 +2687,6 @@
/* No comment provided by engineer. */
"Private filenames" = "Neutrale Dateinamen";
/* name of notes to self */
"Private notes" = "Private Notizen";
/* No comment provided by engineer. */
"Profile and server connections" = "Profil und Serververbindungen";
@@ -2855,9 +2801,6 @@
/* No comment provided by engineer. */
"Receiving via" = "Empfangen über";
/* No comment provided by engineer. */
"Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." = "Aktueller Nachrichtenverlauf und verbesserter [Gruppenverzeichnis-Bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).";
/* No comment provided by engineer. */
"Recipients see updates as you type them." = "Die Empfänger sehen Nachrichtenaktualisierungen, während Sie sie eingeben.";
@@ -2912,12 +2855,6 @@
/* rcv group event chat item */
"removed %@" = "hat %@ aus der Gruppe entfernt";
/* profile update event chat item */
"removed contact address" = "Kontaktadresse wurde entfernt";
/* profile update event chat item */
"removed profile picture" = "Profil-Bild wurde entfernt";
/* rcv group event chat item */
"removed you" = "hat Sie aus der Gruppe entfernt";
@@ -3041,9 +2978,6 @@
/* No comment provided by engineer. */
"Save welcome message?" = "Begrüßungsmeldung speichern?";
/* message info title */
"Saved message" = "Gespeicherte Nachricht";
/* No comment provided by engineer. */
"Saved WebRTC ICE servers will be removed" = "Gespeicherte WebRTC ICE-Server werden entfernt";
@@ -3065,9 +2999,6 @@
/* No comment provided by engineer. */
"Search" = "Suche";
/* No comment provided by engineer. */
"Search bar accepts invitation links." = "Von der Suchleiste werden Einladungslinks akzeptiert.";
/* No comment provided by engineer. */
"Search or paste SimpleX link" = "Suchen oder fügen Sie den SimpleX-Link ein";
@@ -3224,12 +3155,6 @@
/* No comment provided by engineer. */
"Set it instead of system authentication." = "Anstelle der System-Authentifizierung festlegen.";
/* profile update event chat item */
"set new contact address" = "Neue Kontaktadresse wurde festgelegt";
/* profile update event chat item */
"set new profile picture" = "Neues Profil-Bild wurde festgelegt";
/* No comment provided by engineer. */
"Set passcode" = "Zugangscode einstellen";
@@ -3599,9 +3524,6 @@
/* No comment provided by engineer. */
"Trying to connect to the server used to receive messages from this contact." = "Versuche die Verbindung mit dem Server aufzunehmen, der für den Empfang von Nachrichten mit diesem Kontakt genutzt wird.";
/* No comment provided by engineer. */
"Turkish interface" = "Türkische Bedienoberfläche";
/* No comment provided by engineer. */
"Turn off" = "Abschalten";
@@ -3614,21 +3536,12 @@
/* No comment provided by engineer. */
"Unblock" = "Freigeben";
/* No comment provided by engineer. */
"Unblock for all" = "Für Alle freigeben";
/* No comment provided by engineer. */
"Unblock member" = "Mitglied freigeben";
/* No comment provided by engineer. */
"Unblock member for all?" = "Mitglied für Alle freigeben?";
/* No comment provided by engineer. */
"Unblock member?" = "Mitglied freigeben?";
/* rcv group event chat item */
"unblocked %@" = "%@ wurde freigegeben";
/* item status description */
"Unexpected error: %@" = "Unerwarteter Fehler: %@";
@@ -3662,9 +3575,6 @@
/* No comment provided by engineer. */
"Unknown error" = "Unbekannter Fehler";
/* No comment provided by engineer. */
"unknown status" = "unbekannter Gruppenmitglieds-Status";
/* No comment provided by engineer. */
"Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions." = "Aktivieren Sie den Modus \"Bitte nicht stören\", um Unterbrechungen zu vermeiden, es sei denn, Sie verwenden die iOS Anrufschnittstelle.";
@@ -3710,9 +3620,6 @@
/* rcv group event chat item */
"updated group profile" = "Aktualisiertes Gruppenprofil";
/* profile update event chat item */
"updated profile" = "Das Profil wurde aktualisiert";
/* No comment provided by engineer. */
"Updating settings will re-connect the client to all servers." = "Die Aktualisierung der Einstellungen wird den Client wieder mit allen Servern verbinden.";
@@ -3887,15 +3794,9 @@
/* No comment provided by engineer. */
"When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." = "Wenn Sie ein Inkognito-Profil mit Jemandem teilen, wird dieses Profil auch für die Gruppen verwendet, für die Sie von diesem Kontakt eingeladen werden.";
/* No comment provided by engineer. */
"With encrypted files and media." = "Mit verschlüsselten Dateien und Medien.";
/* No comment provided by engineer. */
"With optional welcome message." = "Mit optionaler Begrüßungsmeldung.";
/* No comment provided by engineer. */
"With reduced battery usage." = "Mit reduziertem Akkuverbrauch.";
/* No comment provided by engineer. */
"Wrong database passphrase" = "Falsches Datenbank-Passwort";
@@ -3956,9 +3857,6 @@
/* No comment provided by engineer. */
"you are observer" = "Sie sind Beobachter";
/* snd group event chat item */
"you blocked %@" = "Sie haben %@ blockiert";
/* No comment provided by engineer. */
"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.";
@@ -4070,9 +3968,6 @@
/* chat list item description */
"you shared one-time link incognito" = "Sie haben Inkognito einen Einmal-Link geteilt";
/* snd group event chat item */
"you unblocked %@" = "Sie haben %@ freigegeben";
/* No comment provided by engineer. */
"You will be connected to group when the group host's device is online, please wait or check later!" = "Sie werden mit der Gruppe verbunden, sobald das Endgerät des Gruppen-Hosts online ist. Bitte warten oder schauen Sie später nochmal nach!";

View File

@@ -202,9 +202,6 @@
/* No comment provided by engineer. */
"%lld messages blocked" = "%lld messaggi bloccati";
/* No comment provided by engineer. */
"%lld messages blocked by admin" = "%lld messaggi bloccati dall'amministratore";
/* No comment provided by engineer. */
"%lld messages marked deleted" = "%lld messaggi contrassegnati eliminati";
@@ -587,33 +584,18 @@
/* No comment provided by engineer. */
"Block" = "Blocca";
/* No comment provided by engineer. */
"Block for all" = "Blocca per tutti";
/* No comment provided by engineer. */
"Block group members" = "Blocca i membri dei gruppi";
/* No comment provided by engineer. */
"Block member" = "Blocca membro";
/* No comment provided by engineer. */
"Block member for all?" = "Bloccare il membro per tutti?";
/* No comment provided by engineer. */
"Block member?" = "Bloccare il membro?";
/* No comment provided by engineer. */
"blocked" = "bloccato";
/* rcv group event chat item */
"blocked %@" = "ha bloccato %@";
/* blocked chat item */
"blocked by admin" = "bloccato dall'amministratore";
/* No comment provided by engineer. */
"Blocked by admin" = "Bloccato dall'amministratore";
/* No comment provided by engineer. */
"bold" = "grassetto";
@@ -3614,21 +3596,12 @@
/* No comment provided by engineer. */
"Unblock" = "Sblocca";
/* No comment provided by engineer. */
"Unblock for all" = "Sblocca per tutti";
/* No comment provided by engineer. */
"Unblock member" = "Sblocca membro";
/* No comment provided by engineer. */
"Unblock member for all?" = "Sbloccare il membro per tutti?";
/* No comment provided by engineer. */
"Unblock member?" = "Sbloccare il membro?";
/* rcv group event chat item */
"unblocked %@" = "ha sbloccato %@";
/* item status description */
"Unexpected error: %@" = "Errore imprevisto: % @";
@@ -3956,9 +3929,6 @@
/* No comment provided by engineer. */
"you are observer" = "sei un osservatore";
/* snd group event chat item */
"you blocked %@" = "hai bloccato %@";
/* No comment provided by engineer. */
"You can accept calls from lock screen, without device and app authentication." = "Puoi accettare chiamate dalla schermata di blocco, senza l'autenticazione del dispositivo e dell'app.";
@@ -4070,9 +4040,6 @@
/* chat list item description */
"you shared one-time link incognito" = "hai condiviso un link incognito una tantum";
/* snd group event chat item */
"you unblocked %@" = "hai sbloccato %@";
/* No comment provided by engineer. */
"You will be connected to group when the group host's device is online, please wait or check later!" = "Verrai connesso/a al gruppo quando il dispositivo dell'host del gruppo sarà in linea, attendi o controlla più tardi!";

View File

@@ -202,9 +202,6 @@
/* No comment provided by engineer. */
"%lld messages blocked" = "%lld berichten geblokkeerd";
/* No comment provided by engineer. */
"%lld messages blocked by admin" = "%lld berichten geblokkeerd door beheerder";
/* No comment provided by engineer. */
"%lld messages marked deleted" = "%lld berichten gemarkeerd als verwijderd";
@@ -587,33 +584,18 @@
/* No comment provided by engineer. */
"Block" = "Blokkeren";
/* No comment provided by engineer. */
"Block for all" = "Blokkeren voor iedereen";
/* No comment provided by engineer. */
"Block group members" = "Groepsleden blokkeren";
/* No comment provided by engineer. */
"Block member" = "Lid blokkeren";
/* No comment provided by engineer. */
"Block member for all?" = "Lid voor iedereen blokkeren?";
/* No comment provided by engineer. */
"Block member?" = "Lid blokkeren?";
/* No comment provided by engineer. */
"blocked" = "geblokkeerd";
/* rcv group event chat item */
"blocked %@" = "geblokkeerd %@";
/* blocked chat item */
"blocked by admin" = "geblokkeerd door beheerder";
/* No comment provided by engineer. */
"Blocked by admin" = "Geblokkeerd door beheerder";
/* No comment provided by engineer. */
"bold" = "vetgedrukt";
@@ -2155,7 +2137,7 @@
"Join group" = "Word lid van groep";
/* No comment provided by engineer. */
"Join group conversations" = "Neem deel aan groepsgesprekken";
"Join group conversations" = "Neem deel aan groep gesprekken";
/* No comment provided by engineer. */
"Join group?" = "Deelnemen aan groep?";
@@ -2649,7 +2631,7 @@
"Paste image" = "Afbeelding plakken";
/* No comment provided by engineer. */
"Paste link to connect!" = "Plak een link om te verbinden!";
"Paste link to connect!" = "Plak link om te verbinden!";
/* No comment provided by engineer. */
"Paste the link you received" = "Plak de link die je hebt ontvangen";
@@ -3069,7 +3051,7 @@
"Search bar accepts invitation links." = "Zoekbalk accepteert uitnodigingslinks.";
/* No comment provided by engineer. */
"Search or paste SimpleX link" = "Zoek of plak een SimpleX link";
"Search or paste SimpleX link" = "Zoek of plak de SimpleX link";
/* network option */
"sec" = "sec";
@@ -3614,21 +3596,12 @@
/* No comment provided by engineer. */
"Unblock" = "Deblokkeren";
/* No comment provided by engineer. */
"Unblock for all" = "Deblokkeer voor iedereen";
/* No comment provided by engineer. */
"Unblock member" = "Lid deblokkeren";
/* No comment provided by engineer. */
"Unblock member for all?" = "Lid voor iedereen deblokkeren?";
/* No comment provided by engineer. */
"Unblock member?" = "Lid deblokkeren?";
/* rcv group event chat item */
"unblocked %@" = "gedeblokkeerd %@";
/* item status description */
"Unexpected error: %@" = "Onverwachte fout: %@";
@@ -3956,9 +3929,6 @@
/* No comment provided by engineer. */
"you are observer" = "jij bent waarnemer";
/* snd group event chat item */
"you blocked %@" = "je hebt %@ geblokkeerd";
/* No comment provided by engineer. */
"You can accept calls from lock screen, without device and app authentication." = "U kunt oproepen van het vergrendelingsscherm accepteren, zonder apparaat- en app-verificatie.";
@@ -4070,9 +4040,6 @@
/* chat list item description */
"you shared one-time link incognito" = "je hebt een eenmalige link incognito gedeeld";
/* snd group event chat item */
"you unblocked %@" = "je hebt %@ gedeblokkeerd";
/* No comment provided by engineer. */
"You will be connected to group when the group host's device is online, please wait or check later!" = "Je wordt verbonden met de groep wanneer het apparaat van de groep host online is, even geduld a.u.b. of controleer het later!";

View File

@@ -202,9 +202,6 @@
/* No comment provided by engineer. */
"%lld messages blocked" = "%lld wiadomości zablokowanych";
/* No comment provided by engineer. */
"%lld messages blocked by admin" = "%lld wiadomości zablokowanych przez admina";
/* No comment provided by engineer. */
"%lld messages marked deleted" = "%lld wiadomości oznaczonych do usunięcia";
@@ -401,9 +398,6 @@
/* No comment provided by engineer. */
"All group members will remain connected." = "Wszyscy członkowie grupy pozostaną połączeni.";
/* No comment provided by engineer. */
"All messages will be deleted - this cannot be undone!" = "Wszystkie wiadomości zostaną usunięte nie można tego cofnąć!";
/* No comment provided by engineer. */
"All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Wszystkie wiadomości zostaną usunięte - nie można tego cofnąć! Wiadomości zostaną usunięte TYLKO dla Ciebie.";
@@ -587,33 +581,18 @@
/* No comment provided by engineer. */
"Block" = "Zablokuj";
/* No comment provided by engineer. */
"Block for all" = "Zablokuj dla wszystkich";
/* No comment provided by engineer. */
"Block group members" = "Blokuj członków grupy";
/* No comment provided by engineer. */
"Block member" = "Zablokuj członka";
/* No comment provided by engineer. */
"Block member for all?" = "Zablokować członka dla wszystkich?";
/* No comment provided by engineer. */
"Block member?" = "Zablokować członka?";
/* No comment provided by engineer. */
"blocked" = "zablokowany";
/* rcv group event chat item */
"blocked %@" = "zablokowany %@";
/* blocked chat item */
"blocked by admin" = "zablokowany przez admina";
/* No comment provided by engineer. */
"Blocked by admin" = "Zablokowany przez admina";
/* No comment provided by engineer. */
"bold" = "pogrubiona";
@@ -771,9 +750,6 @@
/* No comment provided by engineer. */
"Clear conversation?" = "Wyczyścić rozmowę?";
/* No comment provided by engineer. */
"Clear private notes?" = "Wyczyścić prywatne notatki?";
/* No comment provided by engineer. */
"Clear verification" = "Wyczyść weryfikację";
@@ -912,9 +888,6 @@
/* connection information */
"connection:%@" = "połączenie: %@";
/* profile update event chat item */
"contact %@ changed to %@" = "kontakt %1$@ zmieniony na %2$@";
/* No comment provided by engineer. */
"Contact allows" = "Kontakt pozwala";
@@ -999,12 +972,6 @@
/* No comment provided by engineer. */
"Create your profile" = "Utwórz swój profil";
/* No comment provided by engineer. */
"Created at" = "Utworzony o";
/* copied message info */
"Created at: %@" = "Utworzony o: %@";
/* No comment provided by engineer. */
"Created on %@" = "Utworzony w dniu %@";
@@ -1329,9 +1296,6 @@
/* No comment provided by engineer. */
"Do it later" = "Zrób to później";
/* No comment provided by engineer. */
"Do not send history to new members." = "Nie wysyłaj historii do nowych członków.";
/* No comment provided by engineer. */
"Do NOT use SimpleX for emergency calls." = "NIE używaj SimpleX do połączeń alarmowych.";
@@ -1557,9 +1521,6 @@
/* No comment provided by engineer. */
"Error creating member contact" = "Błąd tworzenia kontaktu członka";
/* No comment provided by engineer. */
"Error creating message" = "Błąd tworzenia wiadomości";
/* No comment provided by engineer. */
"Error creating profile!" = "Błąd tworzenia profilu!";
@@ -1914,9 +1875,6 @@
/* No comment provided by engineer. */
"History" = "Historia";
/* No comment provided by engineer. */
"History is not sent to new members." = "Historia nie jest wysyłana do nowych członków.";
/* time unit */
"hours" = "godziny";
@@ -1974,9 +1932,6 @@
/* No comment provided by engineer. */
"Import database" = "Importuj bazę danych";
/* No comment provided by engineer. */
"Improved message delivery" = "Ulepszona dostawa wiadomości";
/* No comment provided by engineer. */
"Improved privacy and security" = "Zwiększona prywatność i bezpieczeństwo";
@@ -2061,9 +2016,6 @@
/* invalid chat item */
"invalid data" = "nieprawidłowe dane";
/* No comment provided by engineer. */
"Invalid display name!" = "Nieprawidłowa nazwa wyświetlana!";
/* No comment provided by engineer. */
"Invalid link" = "Nieprawidłowy link";
@@ -2154,9 +2106,6 @@
/* No comment provided by engineer. */
"Join group" = "Dołącz do grupy";
/* No comment provided by engineer. */
"Join group conversations" = "Dołącz do grupowej rozmowy";
/* No comment provided by engineer. */
"Join group?" = "Dołączyć do grupy?";
@@ -2292,9 +2241,6 @@
/* No comment provided by engineer. */
"Member" = "Członek";
/* profile update event chat item */
"member %@ changed to %@" = "członek %1$@ zmieniony na %2$@";
/* rcv group event chat item */
"member connected" = "połączony";
@@ -2639,18 +2585,12 @@
/* No comment provided by engineer. */
"Password to show" = "Hasło do wyświetlenia";
/* past/unknown group member */
"Past member %@" = "Były członek %@";
/* No comment provided by engineer. */
"Paste desktop address" = "Wklej adres komputera";
/* No comment provided by engineer. */
"Paste image" = "Wklej obraz";
/* No comment provided by engineer. */
"Paste link to connect!" = "Wklej link, aby połączyć!";
/* No comment provided by engineer. */
"Paste the link you received" = "Wklej link, który otrzymałeś";
@@ -2738,9 +2678,6 @@
/* No comment provided by engineer. */
"Private filenames" = "Prywatne nazwy plików";
/* name of notes to self */
"Private notes" = "Prywatne notatki";
/* No comment provided by engineer. */
"Profile and server connections" = "Profil i połączenia z serwerem";
@@ -2855,9 +2792,6 @@
/* No comment provided by engineer. */
"Receiving via" = "Odbieranie przez";
/* No comment provided by engineer. */
"Recent history and improved [directory bot](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." = "Ostania historia i ulepszony [bot adresowy](simplex:/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).";
/* No comment provided by engineer. */
"Recipients see updates as you type them." = "Odbiorcy widzą aktualizacje podczas ich wpisywania.";
@@ -2912,12 +2846,6 @@
/* rcv group event chat item */
"removed %@" = "usunięto %@";
/* profile update event chat item */
"removed contact address" = "usunięto adres kontaktu";
/* profile update event chat item */
"removed profile picture" = "usunięto zdjęcie profilu";
/* rcv group event chat item */
"removed you" = "usunął cię";
@@ -3041,9 +2969,6 @@
/* No comment provided by engineer. */
"Save welcome message?" = "Zapisać wiadomość powitalną?";
/* message info title */
"Saved message" = "Zachowano wiadomość";
/* No comment provided by engineer. */
"Saved WebRTC ICE servers will be removed" = "Zapisane serwery WebRTC ICE zostaną usunięte";
@@ -3065,9 +2990,6 @@
/* No comment provided by engineer. */
"Search" = "Szukaj";
/* No comment provided by engineer. */
"Search bar accepts invitation links." = "Pasek wyszukiwania akceptuje linki zaproszenia.";
/* No comment provided by engineer. */
"Search or paste SimpleX link" = "Wyszukaj lub wklej link SimpleX";
@@ -3149,9 +3071,6 @@
/* No comment provided by engineer. */
"Send them from gallery or custom keyboards." = "Wyślij je z galerii lub niestandardowych klawiatur.";
/* No comment provided by engineer. */
"Send up to 100 last messages to new members." = "Wysyłaj do 100 ostatnich wiadomości do nowych członków.";
/* No comment provided by engineer. */
"Sender cancelled file transfer." = "Nadawca anulował transfer pliku.";
@@ -3224,12 +3143,6 @@
/* No comment provided by engineer. */
"Set it instead of system authentication." = "Ustaw go zamiast uwierzytelniania systemowego.";
/* profile update event chat item */
"set new contact address" = "ustaw nowy adres kontaktu";
/* profile update event chat item */
"set new profile picture" = "ustaw nowe zdjęcie profilu";
/* No comment provided by engineer. */
"Set passcode" = "Ustaw pin";
@@ -3536,9 +3449,6 @@
/* No comment provided by engineer. */
"This device name" = "Nazwa tego urządzenia";
/* No comment provided by engineer. */
"This display name is invalid. Please choose another name." = "Nazwa wyświetlana jest nieprawidłowa. Proszę wybrać inną nazwę.";
/* No comment provided by engineer. */
"This group has over %lld members, delivery receipts are not sent." = "Ta grupa ma ponad %lld członków, potwierdzenia dostawy nie są wysyłane.";
@@ -3599,9 +3509,6 @@
/* No comment provided by engineer. */
"Trying to connect to the server used to receive messages from this contact." = "Próbowanie połączenia z serwerem używanym do odbierania wiadomości od tego kontaktu.";
/* No comment provided by engineer. */
"Turkish interface" = "Turecki interfejs";
/* No comment provided by engineer. */
"Turn off" = "Wyłącz";
@@ -3614,21 +3521,12 @@
/* No comment provided by engineer. */
"Unblock" = "Odblokuj";
/* No comment provided by engineer. */
"Unblock for all" = "Odblokuj dla wszystkich";
/* No comment provided by engineer. */
"Unblock member" = "Odblokuj członka";
/* No comment provided by engineer. */
"Unblock member for all?" = "Odblokować członka dla wszystkich?";
/* No comment provided by engineer. */
"Unblock member?" = "Odblokować członka?";
/* rcv group event chat item */
"unblocked %@" = "odblokowano %@";
/* item status description */
"Unexpected error: %@" = "Nieoczekiwany błąd: %@";
@@ -3662,9 +3560,6 @@
/* No comment provided by engineer. */
"Unknown error" = "Nieznany błąd";
/* No comment provided by engineer. */
"unknown status" = "nieznany status";
/* No comment provided by engineer. */
"Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions." = "O ile nie korzystasz z interfejsu połączeń systemu iOS, włącz tryb Nie przeszkadzać, aby uniknąć przerywania.";
@@ -3689,9 +3584,6 @@
/* No comment provided by engineer. */
"Unread" = "Nieprzeczytane";
/* No comment provided by engineer. */
"Up to 100 last messages are sent to new members." = "Do nowych członków wysyłanych jest do 100 ostatnich wiadomości.";
/* No comment provided by engineer. */
"Update" = "Aktualizuj";
@@ -3710,9 +3602,6 @@
/* rcv group event chat item */
"updated group profile" = "zaktualizowano profil grupy";
/* profile update event chat item */
"updated profile" = "zaktualizowano profil";
/* No comment provided by engineer. */
"Updating settings will re-connect the client to all servers." = "Aktualizacja ustawień spowoduje ponowne połączenie klienta ze wszystkimi serwerami.";
@@ -3821,9 +3710,6 @@
/* No comment provided by engineer. */
"View security code" = "Pokaż kod bezpieczeństwa";
/* chat feature */
"Visible history" = "Widoczna historia";
/* No comment provided by engineer. */
"Voice message…" = "Wiadomość głosowa…";
@@ -3887,15 +3773,9 @@
/* No comment provided by engineer. */
"When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." = "Gdy udostępnisz komuś profil incognito, będzie on używany w grupach, do których Cię zaprosi.";
/* No comment provided by engineer. */
"With encrypted files and media." = "Z zaszyfrowanymi plikami i multimediami.";
/* No comment provided by engineer. */
"With optional welcome message." = "Z opcjonalną wiadomością powitalną.";
/* No comment provided by engineer. */
"With reduced battery usage." = "Ze zmniejszonym zużyciem baterii.";
/* No comment provided by engineer. */
"Wrong database passphrase" = "Nieprawidłowe hasło bazy danych";
@@ -3956,9 +3836,6 @@
/* No comment provided by engineer. */
"you are observer" = "jesteś obserwatorem";
/* snd group event chat item */
"you blocked %@" = "zablokowałeś %@";
/* No comment provided by engineer. */
"You can accept calls from lock screen, without device and app authentication." = "Możesz przyjmować połączenia z ekranu blokady, bez uwierzytelniania urządzenia i aplikacji.";
@@ -4070,9 +3947,6 @@
/* chat list item description */
"you shared one-time link incognito" = "udostępniłeś jednorazowy link incognito";
/* snd group event chat item */
"you unblocked %@" = "odblokowałeś %@";
/* No comment provided by engineer. */
"You will be connected to group when the group host's device is online, please wait or check later!" = "Zostaniesz połączony do grupy, gdy urządzenie gospodarza grupy będzie online, proszę czekać lub sprawdzić później!";

View File

@@ -202,9 +202,6 @@
/* No comment provided by engineer. */
"%lld messages blocked" = "%lld сообщений заблокировано";
/* No comment provided by engineer. */
"%lld messages blocked by admin" = "%lld сообщений заблокировано администратором";
/* No comment provided by engineer. */
"%lld messages marked deleted" = "%lld сообщений помечено удалёнными";
@@ -587,33 +584,18 @@
/* No comment provided by engineer. */
"Block" = "Заблокировать";
/* No comment provided by engineer. */
"Block for all" = "Заблокировать для всех";
/* No comment provided by engineer. */
"Block group members" = "Блокируйте членов группы";
/* No comment provided by engineer. */
"Block member" = "Заблокировать члена группы";
/* No comment provided by engineer. */
"Block member for all?" = "Заблокировать члена для всех?";
/* No comment provided by engineer. */
"Block member?" = "Заблокировать члена группы?";
/* No comment provided by engineer. */
"blocked" = "заблокировано";
/* rcv group event chat item */
"blocked %@" = "%@ заблокирован";
/* blocked chat item */
"blocked by admin" = "заблокировано администратором";
/* No comment provided by engineer. */
"Blocked by admin" = "Заблокирован администратором";
/* No comment provided by engineer. */
"bold" = "жирный";
@@ -3614,21 +3596,12 @@
/* No comment provided by engineer. */
"Unblock" = "Разблокировать";
/* No comment provided by engineer. */
"Unblock for all" = "Разблокировать для всех";
/* No comment provided by engineer. */
"Unblock member" = "Разблокировать члена группы";
/* No comment provided by engineer. */
"Unblock member for all?" = "Разблокировать члена для всех?";
/* No comment provided by engineer. */
"Unblock member?" = "Разблокировать члена группы?";
/* rcv group event chat item */
"unblocked %@" = "%@ разблокирован";
/* item status description */
"Unexpected error: %@" = "Неожиданная ошибка: %@";
@@ -3956,9 +3929,6 @@
/* No comment provided by engineer. */
"you are observer" = "только чтение сообщений";
/* snd group event chat item */
"you blocked %@" = "Вы заблокировали %@";
/* No comment provided by engineer. */
"You can accept calls from lock screen, without device and app authentication." = "Вы можете принимать звонки на экране блокировки, без аутентификации.";
@@ -4070,9 +4040,6 @@
/* chat list item description */
"you shared one-time link incognito" = "Вы создали ссылку инкогнито";
/* snd group event chat item */
"you unblocked %@" = "Вы разблокировали %@";
/* No comment provided by engineer. */
"You will be connected to group when the group host's device is online, please wait or check later!" = "Соединение с группой будет установлено, когда хост группы будет онлайн. Пожалуйста, подождите или проверьте позже!";

View File

@@ -2,13 +2,13 @@
"\n" = "\n";
/* No comment provided by engineer. */
" " = " ";
" " = " . ";
/* No comment provided by engineer. */
" " = " ";
" " = " ";
/* No comment provided by engineer. */
" " = " ";
" " = " . ";
/* No comment provided by engineer. */
" (" = " (";

View File

@@ -1,12 +1,11 @@
package chat.simplex.app
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.*
import android.view.WindowManager
import androidx.activity.compose.setContent
import androidx.compose.ui.platform.ClipboardManager
import androidx.appcompat.app.AppCompatDelegate
import androidx.fragment.app.FragmentActivity
import chat.simplex.app.model.NtfManager
import chat.simplex.app.model.NtfManager.getUserIdFromIntent
@@ -59,17 +58,6 @@ class MainActivity: FragmentActivity() {
override fun onResume() {
super.onResume()
AppLock.recheckAuthState()
withApi {
delay(1000)
if (!isAppOnForeground) return@withApi
/**
* When the app calls [ClipboardManager.shareText] and a user copies text in clipboard, Android denies
* access to clipboard because the app considered in background.
* This will ensure that the app will get the event on resume
* */
val service = getSystemService(Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager
chatModel.clipboardHasText.value = service.hasPrimaryClip()
}
}
override fun onPause() {

View File

@@ -71,7 +71,7 @@ class SimplexApp: Application(), LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
Log.d(TAG, "onStateChanged: $event")
withLongRunningApi {
withBGApi {
when (event) {
Lifecycle.Event.ON_START -> {
isAppOnForeground = true
@@ -97,6 +97,13 @@ class SimplexApp: Application(), LifecycleEventObserver {
}
Lifecycle.Event.ON_RESUME -> {
isAppOnForeground = true
/**
* When the app calls [ClipboardManager.shareText] and a user copies text in clipboard, Android denies
* access to clipboard because the app considered in background.
* This will ensure that the app will get the event on resume
* */
val service = androidAppContext.getSystemService(Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager
chatModel.clipboardHasText.value = service.hasPrimaryClip()
if (chatModel.controller.appPrefs.onboardingStage.get() == OnboardingStage.OnboardingComplete && chatModel.currentUser.value != null) {
SimplexService.showBackgroundServiceNoticeIfNeeded()
}
@@ -190,18 +197,10 @@ class SimplexApp: Application(), LifecycleEventObserver {
}
SimplexService.StartReceiver.toggleReceiver(mode == NotificationsMode.SERVICE)
CoroutineScope(Dispatchers.Default).launch {
if (mode == NotificationsMode.SERVICE) {
if (mode == NotificationsMode.SERVICE)
SimplexService.start()
// Sometimes, when we change modes fast from one to another, system destroys the service after start.
// We can wait a little and restart the service, and it will work in 100% of cases
delay(2000)
if (!SimplexService.isServiceStarted && appPrefs.notificationsMode.get() == NotificationsMode.SERVICE) {
Log.i(TAG, "Service tried to start but destroyed by system, repeating once more")
SimplexService.start()
}
} else {
else
SimplexService.safeStopService()
}
}
if (mode != NotificationsMode.PERIODIC) {

View File

@@ -104,7 +104,7 @@ class SimplexService: Service() {
if (wakeLock != null || isStartingService) return
val self = this
isStartingService = true
withLongRunningApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
val chatController = ChatController
waitDbMigrationEnds(chatController)
try {
@@ -262,7 +262,7 @@ class SimplexService: Service() {
private const val SHARED_PREFS_SERVICE_STATE = "SIMPLEX_SERVICE_STATE"
private const val WORK_NAME_ONCE = "ServiceStartWorkerOnce"
var isServiceStarted = false
private var isServiceStarted = false
private var stopAfterStart = false
fun scheduleStart(context: Context) {

View File

@@ -14,27 +14,17 @@ import chat.simplex.common.views.helpers.*
import java.io.BufferedOutputStream
import java.io.File
import chat.simplex.res.MR
import kotlin.math.min
actual fun ClipboardManager.shareText(text: String) {
var text = text
for (i in 10 downTo 1) {
try {
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, text)
type = "text/plain"
flags = FLAG_ACTIVITY_NEW_TASK
}
val shareIntent = Intent.createChooser(sendIntent, null)
shareIntent.addFlags(FLAG_ACTIVITY_NEW_TASK)
androidAppContext.startActivity(shareIntent)
break
} catch (e: Exception) {
Log.e(TAG, "Failed to share text: ${e.stackTraceToString()}")
text = text.substring(0, min(i * 1000, text.length))
}
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, text)
type = "text/plain"
flags = FLAG_ACTIVITY_NEW_TASK
}
val shareIntent = Intent.createChooser(sendIntent, null)
shareIntent.addFlags(FLAG_ACTIVITY_NEW_TASK)
androidAppContext.startActivity(shareIntent)
}
actual fun shareFile(text: String, fileSource: CryptoFile) {

View File

@@ -12,8 +12,6 @@ import androidx.activity.compose.setContent
import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalView
import chat.simplex.common.AppScreen
import chat.simplex.common.model.clear
import chat.simplex.common.ui.theme.SimpleXTheme
import chat.simplex.common.views.helpers.*
import androidx.compose.ui.platform.LocalContext as LocalContext1
import chat.simplex.res.MR
@@ -114,8 +112,7 @@ actual class GlobalExceptionsHandler: Thread.UncaughtExceptionHandler {
Handler(Looper.getMainLooper()).post {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.app_was_crashed),
text = e.stackTraceToString(),
shareText = true
text = e.stackTraceToString()
)
}
}

View File

@@ -1,106 +0,0 @@
package chat.simplex.common.views.helpers
import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.common.model.CustomTimeUnit
import chat.simplex.common.ui.theme.DEFAULT_PADDING
import com.sd.lib.compose.wheel_picker.*
@Composable
actual fun CustomTimePicker(
selection: MutableState<Int>,
timeUnitsLimits: List<TimeUnitLimits>
) {
fun getUnitValues(unit: CustomTimeUnit, selectedValue: Int): List<Int> {
val unitLimits = timeUnitsLimits.firstOrNull { it.timeUnit == unit } ?: TimeUnitLimits.defaultUnitLimits(unit)
val regularUnitValues = (unitLimits.minValue..unitLimits.maxValue).toList()
return regularUnitValues + if (regularUnitValues.contains(selectedValue)) emptyList() else listOf(selectedValue)
}
val (unit, duration) = CustomTimeUnit.toTimeUnit(selection.value)
val selectedUnit: MutableState<CustomTimeUnit> = remember { mutableStateOf(unit) }
val selectedDuration = remember { mutableStateOf(duration) }
val selectedUnitValues = remember { mutableStateOf(getUnitValues(selectedUnit.value, selectedDuration.value)) }
val isTriggered = remember { mutableStateOf(false) }
LaunchedEffect(selectedUnit.value) {
// on initial composition, if passed selection doesn't fit into picker bounds, so that selectedDuration is bigger than selectedUnit maxValue
// (e.g., for selection = 121 seconds: selectedUnit would be Second, selectedDuration would be 121 > selectedUnit maxValue of 120),
// selectedDuration would've been replaced by maxValue - isTriggered check prevents this by skipping LaunchedEffect on initial composition
if (isTriggered.value) {
val maxValue = timeUnitsLimits.firstOrNull { it.timeUnit == selectedUnit.value }?.maxValue
if (maxValue != null && selectedDuration.value > maxValue) {
selectedDuration.value = maxValue
selectedUnitValues.value = getUnitValues(selectedUnit.value, selectedDuration.value)
} else {
selectedUnitValues.value = getUnitValues(selectedUnit.value, selectedDuration.value)
selection.value = selectedUnit.value.toSeconds * selectedDuration.value
}
} else {
isTriggered.value = true
}
}
LaunchedEffect(selectedDuration.value) {
selection.value = selectedUnit.value.toSeconds * selectedDuration.value
}
Row(
Modifier
.fillMaxWidth()
.padding(horizontal = DEFAULT_PADDING),
horizontalArrangement = Arrangement.spacedBy(0.dp)
) {
Column(Modifier.weight(1f)) {
val durationPickerState = rememberFWheelPickerState(selectedUnitValues.value.indexOf(selectedDuration.value))
FVerticalWheelPicker(
count = selectedUnitValues.value.count(),
state = durationPickerState,
unfocusedCount = 2,
focus = {
FWheelPickerFocusVertical(dividerColor = MaterialTheme.colors.primary)
}
) { index ->
Text(
selectedUnitValues.value[index].toString(),
fontSize = 18.sp,
color = MaterialTheme.colors.primary
)
}
LaunchedEffect(durationPickerState) {
snapshotFlow { durationPickerState.currentIndex }
.collect {
selectedDuration.value = selectedUnitValues.value[it]
}
}
}
Column(Modifier.weight(1f)) {
val unitPickerState = rememberFWheelPickerState(timeUnitsLimits.indexOfFirst { it.timeUnit == selectedUnit.value })
FVerticalWheelPicker(
count = timeUnitsLimits.count(),
state = unitPickerState,
unfocusedCount = 2,
focus = {
FWheelPickerFocusVertical(dividerColor = MaterialTheme.colors.primary)
}
) { index ->
Text(
timeUnitsLimits[index].timeUnit.text,
fontSize = 18.sp,
color = MaterialTheme.colors.primary
)
}
LaunchedEffect(unitPickerState) {
snapshotFlow { unitPickerState.currentIndex }
.collect {
selectedUnit.value = timeUnitsLimits[it].timeUnit
}
}
}
}
}

View File

@@ -66,7 +66,6 @@ extern char *chat_parse_markdown(const char *str);
extern char *chat_parse_server(const char *str);
extern char *chat_password_hash(const char *pwd, const char *salt);
extern char *chat_valid_name(const char *name);
extern int chat_json_length(const char *str);
extern char *chat_write_file(chat_ctrl ctrl, const char *path, char *ptr, int length);
extern char *chat_read_file(const char *path, const char *key, const char *nonce);
extern char *chat_encrypt_file(chat_ctrl ctrl, const char *from_path, const char *to_path);
@@ -164,14 +163,6 @@ Java_chat_simplex_common_platform_CoreKt_chatValidName(JNIEnv *env, jclass clazz
return res;
}
JNIEXPORT int JNICALL
Java_chat_simplex_common_platform_CoreKt_chatJsonLength(JNIEnv *env, jclass clazz, jstring str) {
const char *_str = (*env)->GetStringUTFChars(env, str, JNI_FALSE);
int res = chat_json_length(_str);
(*env)->ReleaseStringUTFChars(env, str, _str);
return res;
}
JNIEXPORT jstring JNICALL
Java_chat_simplex_common_platform_CoreKt_chatWriteFile(JNIEnv *env, jclass clazz, jlong controller, jstring path, jobject buffer) {
const char *_path = (*env)->GetStringUTFChars(env, path, JNI_FALSE);

View File

@@ -71,7 +71,7 @@ if(NOT APPLE)
else()
# Without direct linking it can't find hs_init in linking step
add_library( rts SHARED IMPORTED )
FILE(GLOB RTSLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/deps/libHSrts*_thr-*.${OS_LIB_EXT})
FILE(GLOB RTSLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/libHSrts*_thr-*.${OS_LIB_EXT})
set_target_properties( rts PROPERTIES IMPORTED_LOCATION ${RTSLIB})
target_link_libraries(app-lib rts simplex)

View File

@@ -39,7 +39,6 @@ extern char *chat_parse_markdown(const char *str);
extern char *chat_parse_server(const char *str);
extern char *chat_password_hash(const char *pwd, const char *salt);
extern char *chat_valid_name(const char *name);
extern int chat_json_length(const char *str);
extern char *chat_write_file(chat_ctrl ctrl, const char *path, char *ptr, int length);
extern char *chat_read_file(const char *path, const char *key, const char *nonce);
extern char *chat_encrypt_file(chat_ctrl ctrl, const char *from_path, const char *to_path);
@@ -174,14 +173,6 @@ Java_chat_simplex_common_platform_CoreKt_chatValidName(JNIEnv *env, jclass clazz
return res;
}
JNIEXPORT int JNICALL
Java_chat_simplex_common_platform_CoreKt_chatJsonLength(JNIEnv *env, jclass clazz, jstring str) {
const char *_str = encode_to_utf8_chars(env, str);
int res = chat_json_length(_str);
(*env)->ReleaseStringUTFChars(env, str, _str);
return res;
}
JNIEXPORT jstring JNICALL
Java_chat_simplex_common_platform_CoreKt_chatWriteFile(JNIEnv *env, jclass clazz, jlong controller, jstring path, jobject buffer) {
const char *_path = encode_to_utf8_chars(env, path);

View File

@@ -108,7 +108,6 @@ fun MainScreen() {
val localUserCreated = chatModel.localUserCreated.value
var showInitializationView by remember { mutableStateOf(false) }
when {
chatModel.dbMigrationInProgress.value -> DefaultProgressView(stringResource(MR.strings.database_migration_in_progress))
chatModel.chatDbStatus.value == null && showInitializationView -> DefaultProgressView(stringResource(MR.strings.opening_database))
showChatDatabaseError -> {
// Prevent showing keyboard on Android when: passcode enabled and database password not saved

View File

@@ -2,7 +2,6 @@ package chat.simplex.common.model
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.runtime.snapshots.SnapshotStateMap
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.SpanStyle
@@ -49,7 +48,6 @@ object ChatModel {
val chatDbEncrypted = mutableStateOf<Boolean?>(false)
val chatDbStatus = mutableStateOf<DBMigrationResult?>(null)
val ctrlInitInProgress = mutableStateOf(false)
val dbMigrationInProgress = mutableStateOf(false)
val chats = mutableStateListOf<Chat>()
// map of connections network statuses, key is agent connection id
val networkStatuses = mutableStateMapOf<String, NetworkStatus>()
@@ -57,7 +55,7 @@ object ChatModel {
// current chat
val chatId = mutableStateOf<String?>(null)
val chatItems = mutableStateOf(SnapshotStateList<ChatItem>())
val chatItems = mutableStateListOf<ChatItem>()
// rhId, chatId
val deletedChats = mutableStateOf<List<Pair<Long?, String>>>(emptyList())
val chatItemStatuses = mutableMapOf<Long, CIStatus>()
@@ -65,6 +63,8 @@ object ChatModel {
val terminalItems = mutableStateOf<List<TerminalItem>>(listOf())
val userAddress = mutableStateOf<UserContactLinkRec?>(null)
// Allows to temporary save servers that are being edited on multiple screens
val userSMPServersUnsaved = mutableStateOf<(List<ServerCfg>)?>(null)
val chatItemTTL = mutableStateOf<ChatItemTTL>(ChatItemTTL.None)
// set when app opened from external intent
@@ -269,15 +269,18 @@ object ChatModel {
} else {
addChat(Chat(remoteHostId = rhId, chatInfo = cInfo, chatItems = arrayListOf(cItem)))
}
Log.d(TAG, "TODOCHAT: addChatItem: adding to chat ${chatId.value} from ${cInfo.id} ${cItem.id}, size ${chatItems.size}")
withContext(Dispatchers.Main) {
// add to current chat
if (chatId.value == cInfo.id) {
Log.d(TAG, "TODOCHAT: addChatItem: chatIds are equal, size ${chatItems.size}")
// Prevent situation when chat item already in the list received from backend
if (chatItems.value.none { it.id == cItem.id }) {
if (chatItems.value.lastOrNull()?.id == ChatItem.TEMP_LIVE_CHAT_ITEM_ID) {
chatItems.add(kotlin.math.max(0, chatItems.value.lastIndex), cItem)
if (chatItems.none { it.id == cItem.id }) {
if (chatItems.lastOrNull()?.id == ChatItem.TEMP_LIVE_CHAT_ITEM_ID) {
chatItems.add(kotlin.math.max(0, chatItems.lastIndex), cItem)
} else {
chatItems.add(cItem)
Log.d(TAG, "TODOCHAT: addChatItem: added to chat ${chatId.value} from ${cInfo.id} ${cItem.id}, size ${chatItems.size}")
}
}
}
@@ -304,13 +307,14 @@ object ChatModel {
addChat(Chat(remoteHostId = rhId, chatInfo = cInfo, chatItems = arrayListOf(cItem)))
res = true
}
Log.d(TAG, "TODOCHAT: upsertChatItem: upserting to chat ${chatId.value} from ${cInfo.id} ${cItem.id}, size ${chatItems.size}")
return withContext(Dispatchers.Main) {
// update current chat
if (chatId.value == cInfo.id) {
val items = chatItems.value
val itemIndex = items.indexOfFirst { it.id == cItem.id }
val itemIndex = chatItems.indexOfFirst { it.id == cItem.id }
if (itemIndex >= 0) {
items[itemIndex] = cItem
chatItems[itemIndex] = cItem
Log.d(TAG, "TODOCHAT: upsertChatItem: updated in chat $chatId from ${cInfo.id} ${cItem.id}, size ${chatItems.size}")
false
} else {
val status = chatItemStatuses.remove(cItem.id)
@@ -320,6 +324,7 @@ object ChatModel {
cItem
}
chatItems.add(ci)
Log.d(TAG, "TODOCHAT: upsertChatItem: added to chat $chatId from ${cInfo.id} ${cItem.id}, size ${chatItems.size}")
true
}
} else {
@@ -331,10 +336,9 @@ object ChatModel {
suspend fun updateChatItem(cInfo: ChatInfo, cItem: ChatItem, status: CIStatus? = null) {
withContext(Dispatchers.Main) {
if (chatId.value == cInfo.id) {
val items = chatItems.value
val itemIndex = items.indexOfFirst { it.id == cItem.id }
val itemIndex = chatItems.indexOfFirst { it.id == cItem.id }
if (itemIndex >= 0) {
items[itemIndex] = cItem
chatItems[itemIndex] = cItem
}
} else if (status != null) {
chatItemStatuses[cItem.id] = status
@@ -358,10 +362,10 @@ object ChatModel {
}
// remove from current chat
if (chatId.value == cInfo.id) {
chatItems.removeAll {
val remove = it.id == cItem.id
if (remove) { AudioPlayer.stop(it) }
remove
val itemIndex = chatItems.indexOfFirst { it.id == cItem.id }
if (itemIndex >= 0) {
AudioPlayer.stop(chatItems[itemIndex])
chatItems.removeAt(itemIndex)
}
}
}
@@ -402,7 +406,7 @@ object ChatModel {
}
fun removeLiveDummy() {
if (chatItems.value.lastOrNull()?.id == ChatItem.TEMP_LIVE_CHAT_ITEM_ID) {
if (chatItems.lastOrNull()?.id == ChatItem.TEMP_LIVE_CHAT_ITEM_ID) {
chatItems.removeLast()
}
}
@@ -434,14 +438,14 @@ object ChatModel {
var markedRead = 0
if (chatId.value == cInfo.id) {
var i = 0
val items = chatItems.value
while (i < items.size) {
val item = items[i]
Log.d(TAG, "TODOCHAT: markItemsReadInCurrentChat: marking read ${cInfo.id}, current chatId ${chatId.value}, size was ${chatItems.size}")
while (i < chatItems.count()) {
val item = chatItems[i]
if (item.meta.itemStatus is CIStatus.RcvNew && (range == null || (range.from <= item.id && item.id <= range.to))) {
val newItem = item.withStatus(CIStatus.RcvRead())
items[i] = newItem
chatItems[i] = newItem
if (newItem.meta.itemLive != true && newItem.meta.itemTimed?.ttl != null) {
items[i] = newItem.copy(meta = newItem.meta.copy(itemTimed = newItem.meta.itemTimed.copy(
chatItems[i] = newItem.copy(meta = newItem.meta.copy(itemTimed = newItem.meta.itemTimed.copy(
deleteAt = Clock.System.now() + newItem.meta.itemTimed.ttl.toDuration(DurationUnit.SECONDS)))
)
}
@@ -449,6 +453,7 @@ object ChatModel {
}
i += 1
}
Log.d(TAG, "TODOCHAT: markItemsReadInCurrentChat: marked read ${cInfo.id}, current chatId ${chatId.value}, size now ${chatItems.size}")
}
return markedRead
}
@@ -639,8 +644,7 @@ object ChatModel {
}
fun addTerminalItem(item: TerminalItem) {
val maxItems = if (appPreferences.developerTools.get()) 500 else 200
if (terminalItems.value.size >= maxItems) {
if (terminalItems.value.size >= 500) {
terminalItems.value = terminalItems.value.subList(1, terminalItems.value.size)
}
terminalItems.value += item
@@ -965,16 +969,6 @@ sealed class ChatInfo: SomeChat, NamedChat {
is Group -> groupInfo.chatSettings
else -> null
}
val chatTs: Instant
get() = when(this) {
is Direct -> contact.chatTs ?: contact.updatedAt
is Group -> groupInfo.chatTs ?: groupInfo.updatedAt
is Local -> noteFolder.chatTs
is ContactRequest -> contactRequest.updatedAt
is ContactConnection -> contactConnection.updatedAt
is InvalidJSON -> updatedAt
}
}
@Serializable
@@ -1015,7 +1009,6 @@ data class Contact(
val mergedPreferences: ContactUserPreferences,
override val createdAt: Instant,
override val updatedAt: Instant,
val chatTs: Instant?,
val contactGroupMemberId: Long? = null,
val contactGrpInvSent: Boolean
): SomeChat, NamedChat {
@@ -1084,7 +1077,6 @@ data class Contact(
mergedPreferences = ContactUserPreferences.sampleData,
createdAt = Clock.System.now(),
updatedAt = Clock.System.now(),
chatTs = Clock.System.now(),
contactGrpInvSent = false
)
}
@@ -1212,8 +1204,7 @@ data class GroupInfo (
val hostConnCustomUserProfileId: Long? = null,
val chatSettings: ChatSettings,
override val createdAt: Instant,
override val updatedAt: Instant,
val chatTs: Instant?
override val updatedAt: Instant
): SomeChat, NamedChat {
override val chatType get() = ChatType.Group
override val id get() = "#$groupId"
@@ -1254,8 +1245,7 @@ data class GroupInfo (
hostConnCustomUserProfileId = null,
chatSettings = ChatSettings(enableNtfs = MsgFilter.All, sendRcpts = null, favorite = false),
createdAt = Clock.System.now(),
updatedAt = Clock.System.now(),
chatTs = Clock.System.now()
updatedAt = Clock.System.now()
)
}
}
@@ -1517,8 +1507,7 @@ class NoteFolder(
val favorite: Boolean,
val unread: Boolean,
override val createdAt: Instant,
override val updatedAt: Instant,
val chatTs: Instant
override val updatedAt: Instant
): SomeChat, NamedChat {
override val chatType get() = ChatType.Local
override val id get() = "*$noteFolderId"
@@ -1541,8 +1530,7 @@ class NoteFolder(
favorite = false,
unread = false,
createdAt = Clock.System.now(),
updatedAt = Clock.System.now(),
chatTs = Clock.System.now()
updatedAt = Clock.System.now()
)
}
}
@@ -2002,46 +1990,6 @@ data class ChatItem (
}
}
fun MutableState<SnapshotStateList<ChatItem>>.add(index: Int, chatItem: ChatItem) {
value = SnapshotStateList<ChatItem>().apply { addAll(value); add(index, chatItem) }
}
fun MutableState<SnapshotStateList<ChatItem>>.add(chatItem: ChatItem) {
value = SnapshotStateList<ChatItem>().apply { addAll(value); add(chatItem) }
}
fun MutableState<SnapshotStateList<ChatItem>>.addAll(index: Int, chatItems: List<ChatItem>) {
value = SnapshotStateList<ChatItem>().apply { addAll(value); addAll(index, chatItems) }
}
fun MutableState<SnapshotStateList<ChatItem>>.addAll(chatItems: List<ChatItem>) {
value = SnapshotStateList<ChatItem>().apply { addAll(value); addAll(chatItems) }
}
fun MutableState<SnapshotStateList<ChatItem>>.removeAll(block: (ChatItem) -> Boolean) {
value = SnapshotStateList<ChatItem>().apply { addAll(value); removeAll(block) }
}
fun MutableState<SnapshotStateList<ChatItem>>.removeAt(index: Int) {
value = SnapshotStateList<ChatItem>().apply { addAll(value); removeAt(index) }
}
fun MutableState<SnapshotStateList<ChatItem>>.removeLast() {
value = SnapshotStateList<ChatItem>().apply { addAll(value); removeLast() }
}
fun MutableState<SnapshotStateList<ChatItem>>.replaceAll(chatItems: List<ChatItem>) {
value = SnapshotStateList<ChatItem>().apply { addAll(chatItems) }
}
fun MutableState<SnapshotStateList<ChatItem>>.clear() {
value = SnapshotStateList<ChatItem>()
}
fun State<SnapshotStateList<ChatItem>>.asReversed(): MutableList<ChatItem> = value.asReversed()
val State<List<ChatItem>>.size: Int get() = value.size
enum class CIMergeCategory {
MemberConnected,
RcvGroupEvent,

View File

@@ -451,21 +451,7 @@ object ChatController {
}
try {
val msg = recvMsg(ctrl)
if (msg != null) {
val finishedWithoutTimeout = withTimeoutOrNull(60_000L) {
processReceivedMsg(msg)
}
if (finishedWithoutTimeout == null) {
Log.e(TAG, "Timeout reached while processing received message: " + msg.resp.responseType)
if (appPreferences.developerTools.get() && appPreferences.showSlowApiCalls.get()) {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.possible_slow_function_title),
text = generalGetString(MR.strings.possible_slow_function_desc).format(60, msg.resp.responseType + "\n" + Exception().stackTraceToString()),
shareText = true
)
}
}
}
if (msg != null) withSingleThreadContext { processReceivedMsg(msg) }
} catch (e: Exception) {
Log.e(TAG, "ChatController recvMsg/processReceivedMsg exception: " + e.stackTraceToString());
} catch (e: Throwable) {
@@ -631,6 +617,12 @@ object ChatController {
throw Error("failed to set remote hosts folder: ${r.responseType} ${r.details}")
}
suspend fun apiSetXFTPConfig(cfg: XFTPFileConfig?) {
val r = sendCmd(null, CC.ApiSetXFTPConfig(cfg))
if (r is CR.CmdOk) return
throw Error("apiSetXFTPConfig bad response: ${r.responseType} ${r.details}")
}
suspend fun apiSetEncryptLocalFiles(enable: Boolean) = sendCommandOkResp(null, CC.ApiSetEncryptLocalFiles(enable))
suspend fun apiExportArchive(config: ArchiveConfig) {
@@ -1693,7 +1685,7 @@ object ChatController {
chatModel.networkStatuses[s.agentConnId] = s.networkStatus
}
}
is CR.NewChatItem -> withBGApi {
is CR.NewChatItem -> {
val cInfo = r.chatItem.chatInfo
val cItem = r.chatItem.chatItem
if (active(r.user)) {
@@ -1708,7 +1700,7 @@ object ChatController {
((mc is MsgContent.MCImage && file.fileSize <= MAX_IMAGE_SIZE_AUTO_RCV)
|| (mc is MsgContent.MCVideo && file.fileSize <= MAX_VIDEO_SIZE_AUTO_RCV)
|| (mc is MsgContent.MCVoice && file.fileSize <= MAX_VOICE_SIZE_AUTO_RCV && file.fileStatus !is CIFileStatus.RcvAccepted))) {
receiveFile(rhId, r.user, file.fileId, auto = true)
withBGApi { receiveFile(rhId, r.user, file.fileId, auto = true) }
}
if (cItem.showNotification && (allowedToShowNotification() || chatModel.chatId.value != cInfo.id || chatModel.remoteHostId() != rhId)) {
ntfManager.notifyMessageReceived(r.user, cInfo, cItem)
@@ -2167,6 +2159,10 @@ object ChatController {
}
}
fun getXFTPCfg(): XFTPFileConfig {
return XFTPFileConfig(minFileSize = 0)
}
fun getNetCfg(): NetCfg {
val useSocksProxy = appPrefs.networkUseSocksProxy.get()
val proxyHostPort = appPrefs.networkProxyHostPort.get()
@@ -2275,6 +2271,7 @@ sealed class CC {
class SetTempFolder(val tempFolder: String): CC()
class SetFilesFolder(val filesFolder: String): CC()
class SetRemoteHostsFolder(val remoteHostsFolder: String): CC()
class ApiSetXFTPConfig(val config: XFTPFileConfig?): CC()
class ApiSetEncryptLocalFiles(val enable: Boolean): CC()
class ApiExportArchive(val config: ArchiveConfig): CC()
class ApiImportArchive(val config: ArchiveConfig): CC()
@@ -2404,6 +2401,7 @@ sealed class CC {
is SetTempFolder -> "/_temp_folder $tempFolder"
is SetFilesFolder -> "/_files_folder $filesFolder"
is SetRemoteHostsFolder -> "/remote_hosts_folder $remoteHostsFolder"
is ApiSetXFTPConfig -> if (config != null) "/_xftp on ${json.encodeToString(config)}" else "/_xftp off"
is ApiSetEncryptLocalFiles -> "/_files_encrypt ${onOff(enable)}"
is ApiExportArchive -> "/_db export ${json.encodeToString(config)}"
is ApiImportArchive -> "/_db import ${json.encodeToString(config)}"
@@ -2538,6 +2536,7 @@ sealed class CC {
is SetTempFolder -> "setTempFolder"
is SetFilesFolder -> "setFilesFolder"
is SetRemoteHostsFolder -> "setRemoteHostsFolder"
is ApiSetXFTPConfig -> "apiSetXFTPConfig"
is ApiSetEncryptLocalFiles -> "apiSetEncryptLocalFiles"
is ApiExportArchive -> "apiExportArchive"
is ApiImportArchive -> "apiImportArchive"
@@ -2703,6 +2702,9 @@ sealed class ChatPagination {
@Serializable
class ComposedMessage(val fileSource: CryptoFile?, val quotedItemId: Long?, val msgContent: MsgContent)
@Serializable
class XFTPFileConfig(val minFileSize: Long)
@Serializable
class ArchiveConfig(val archivePath: String, val disableCompression: Boolean? = null, val parentTempDirectory: String? = null)

View File

@@ -28,7 +28,6 @@ external fun chatParseMarkdown(str: String): String
external fun chatParseServer(str: String): String
external fun chatPasswordHash(pwd: String, salt: String): String
external fun chatValidName(name: String): String
external fun chatJsonLength(str: String): Int
external fun chatWriteFile(ctrl: ChatCtrl, path: String, buffer: ByteBuffer): String
external fun chatReadFile(path: String, key: String, nonce: String): Array<Any>
external fun chatEncryptFile(ctrl: ChatCtrl, fromPath: String, toPath: String): String
@@ -43,7 +42,7 @@ val appPreferences: AppPreferences
val chatController: ChatController = ChatController
fun initChatControllerAndRunMigrations() {
withLongRunningApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
if (appPreferences.chatStopped.get() && appPreferences.storeDBPassphrase.get() && ksDatabasePassword.get() != null) {
initChatController(startChat = ::showStartChatAfterRestartAlert)
} else {
@@ -59,23 +58,10 @@ suspend fun initChatController(useKey: String? = null, confirmMigrations: Migrat
chatModel.ctrlInitInProgress.value = true
val dbKey = useKey ?: DatabaseUtils.useDatabaseKey()
val confirm = confirmMigrations ?: if (appPreferences.developerTools.get() && appPreferences.confirmDBUpgrades.get()) MigrationConfirmation.Error else MigrationConfirmation.YesUp
var migrated: Array<Any> = chatMigrateInit(dbAbsolutePrefixPath, dbKey, MigrationConfirmation.Error.value)
var res: DBMigrationResult = runCatching {
val migrated: Array<Any> = chatMigrateInit(dbAbsolutePrefixPath, dbKey, confirm.value)
val res: DBMigrationResult = kotlin.runCatching {
json.decodeFromString<DBMigrationResult>(migrated[0] as String)
}.getOrElse { DBMigrationResult.Unknown(migrated[0] as String) }
val rerunMigration = res is DBMigrationResult.ErrorMigration && when (res.migrationError) {
// we don't allow to run down migrations without confirmation in UI, so currently it won't be YesUpDown
is MigrationError.Upgrade -> confirm == MigrationConfirmation.YesUp || confirm == MigrationConfirmation.YesUpDown
is MigrationError.Downgrade -> confirm == MigrationConfirmation.YesUpDown
is MigrationError.Error -> false
}
if (rerunMigration) {
chatModel.dbMigrationInProgress.value = true
migrated = chatMigrateInit(dbAbsolutePrefixPath, dbKey, confirm.value)
res = runCatching {
json.decodeFromString<DBMigrationResult>(migrated[0] as String)
}.getOrElse { DBMigrationResult.Unknown(migrated[0] as String) }
}
val ctrl = if (res is DBMigrationResult.OK) {
migrated[1] as Long
} else null
@@ -91,6 +77,7 @@ suspend fun initChatController(useKey: String? = null, confirmMigrations: Migrat
if (appPlatform.isDesktop) {
controller.apiSetRemoteHostsFolder(remoteHostsDir.absolutePath)
}
controller.apiSetXFTPConfig(controller.getXFTPCfg())
controller.apiSetEncryptLocalFiles(controller.appPrefs.privacyEncryptLocalFiles.get())
// If we migrated successfully means previous re-encryption process on database level finished successfully too
if (appPreferences.encryptionStartedAt.get() != null) appPreferences.encryptionStartedAt.set(null)
@@ -132,7 +119,6 @@ suspend fun initChatController(useKey: String? = null, confirmMigrations: Migrat
}
} finally {
chatModel.ctrlInitInProgress.value = false
chatModel.dbMigrationInProgress.value = false
}
}

View File

@@ -55,7 +55,7 @@ abstract class NtfManager {
}
fun openChatAction(userId: Long?, chatId: ChatId) {
withLongRunningApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
awaitChatStartedIfNeeded(chatModel)
if (userId != null && userId != chatModel.currentUser.value?.userId && chatModel.currentUser.value != null) {
// TODO include remote host ID in desktop notifications?
@@ -70,7 +70,7 @@ abstract class NtfManager {
}
fun showChatsAction(userId: Long?) {
withLongRunningApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
awaitChatStartedIfNeeded(chatModel)
if (userId != null && userId != chatModel.currentUser.value?.userId && chatModel.currentUser.value != null) {
// TODO include remote host ID in desktop notifications?

View File

@@ -324,7 +324,7 @@ fun ChatItemInfoView(chatModel: ChatModel, ci: ChatItem, ciInfo: ChatItemInfo, d
.fillMaxHeight(),
verticalArrangement = Arrangement.SpaceBetween
) {
LaunchedEffect(ciInfo) {
LaunchedEffect(Unit) {
if (ciInfo.memberDeliveryStatuses != null) {
selection.value = CIInfoTab.Delivery(ciInfo.memberDeliveryStatuses)
}

View File

@@ -67,13 +67,13 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId:
launch {
snapshotFlow { chatModel.chatId.value }
.distinctUntilChanged()
.filterNotNull()
.onEach { Log.d(TAG, "TODOCHAT: chatId: activeChatId ${activeChat.value?.id} == new chatId $it ${activeChat.value?.id == it} ") }
.filter { it != null && activeChat.value?.id != it }
.collect { chatId ->
if (activeChat.value?.id != chatId) {
// Redisplay the whole hierarchy if the chat is different to make going from groups to direct chat working correctly
// Also for situation when chatId changes after clicking in notification, etc
activeChat.value = chatModel.getChat(chatId)
}
// Redisplay the whole hierarchy if the chat is different to make going from groups to direct chat working correctly
// Also for situation when chatId changes after clicking in notification, etc
activeChat.value = chatModel.getChat(chatId!!)
Log.d(TAG, "TODOCHAT: chatId: activeChatId became ${activeChat.value?.id}")
markUnreadChatAsRead(activeChat, chatModel)
}
}
@@ -92,10 +92,12 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId:
}
}
.distinctUntilChanged()
.onEach { Log.d(TAG, "TODOCHAT: chats: activeChatId ${activeChat.value?.id} == new chatId ${it?.id} ${activeChat.value?.id == it?.id} ") }
// Only changed chatInfo is important thing. Other properties can be skipped for reducing recompositions
.filter { it != null && it.chatInfo != activeChat.value?.chatInfo }
.filter { it != null && it?.chatInfo != activeChat.value?.chatInfo }
.collect {
activeChat.value = it
Log.d(TAG, "TODOCHAT: chats: activeChatId became ${activeChat.value?.id}")
}
}
}
@@ -146,6 +148,7 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId:
},
attachmentOption,
attachmentBottomSheetState,
chatModel.chatItems,
searchText,
useLinkPreviews = useLinkPreviews,
linkMode = chatModel.simplexLinkMode.value,
@@ -223,17 +226,19 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId:
loadPrevMessages = {
if (chatModel.chatId.value != activeChat.value?.id) return@ChatLayout
val c = chatModel.getChat(chatModel.chatId.value ?: return@ChatLayout)
val firstId = chatModel.chatItems.value.firstOrNull()?.id
val firstId = chatModel.chatItems.firstOrNull()?.id
if (c != null && firstId != null) {
withBGApi {
Log.d(TAG, "TODOCHAT: loadPrevMessages: loading for ${c.id}, current chatId ${ChatModel.chatId.value}, size was ${ChatModel.chatItems.size}")
apiLoadPrevMessages(c, chatModel, firstId, searchText.value)
Log.d(TAG, "TODOCHAT: loadPrevMessages: loaded for ${c.id}, current chatId ${ChatModel.chatId.value}, size now ${ChatModel.chatItems.size}")
}
}
},
deleteMessage = { itemId, mode ->
withBGApi {
val cInfo = chat.chatInfo
val toDeleteItem = chatModel.chatItems.value.firstOrNull { it.id == itemId }
val toDeleteItem = chatModel.chatItems.firstOrNull { it.id == itemId }
val toModerate = toDeleteItem?.memberToModerate(chat.chatInfo)
val groupInfo = toModerate?.first
val groupMember = toModerate?.second
@@ -399,15 +404,12 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId:
setGroupMembers(chatRh, chat.chatInfo.groupInfo, chatModel)
}
ModalManager.end.closeModals()
ModalManager.end.showModalCloseable(endButtons = {
ModalManager.end.showModal(endButtons = {
ShareButton {
clipboard.shareText(itemInfoShareText(chatModel, cItem, ciInfo, chatModel.controller.appPrefs.developerTools.get()))
}
}) { close ->
}) {
ChatItemInfoView(chatModel, cItem, ciInfo, devTools = chatModel.controller.appPrefs.developerTools.get())
KeyChangeEffect(chatModel.chatId.value) {
close()
}
}
}
}
@@ -493,6 +495,7 @@ fun ChatLayout(
composeView: (@Composable () -> Unit),
attachmentOption: MutableState<AttachmentOption?>,
attachmentBottomSheetState: ModalBottomSheetState,
chatItems: List<ChatItem>,
searchValue: State<String>,
useLinkPreviews: Boolean,
linkMode: SimplexLinkMode,
@@ -579,7 +582,7 @@ fun ChatLayout(
.padding(contentPadding)
) {
ChatItemsList(
chat, unreadCount, composeState, searchValue,
chat, unreadCount, composeState, chatItems, searchValue,
useLinkPreviews, linkMode, showMemberInfo, loadPrevMessages, deleteMessage, deleteMessages,
receiveFile, cancelFile, joinGroup, acceptCall, acceptFeature, openDirectChat,
updateContactStats, updateMemberStats, syncContactConnection, syncMemberConnection, findModelChat, findModelMember,
@@ -644,7 +647,7 @@ fun ChatInfoToolbar(
}
}
if (chat.chatInfo is ChatInfo.Direct && chat.chatInfo.contact.mergedPreferences.calls.enabled.forUser) {
if (chat.chatInfo is ChatInfo.Direct && chat.chatInfo.contact.allowsFeature(ChatFeature.Calls)) {
if (activeCall == null) {
barButtons.add {
if (appPlatform.isAndroid) {
@@ -837,6 +840,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
chat: Chat,
unreadCount: State<Int>,
composeState: MutableState<ComposeState>,
chatItems: List<ChatItem>,
searchValue: State<String>,
useLinkPreviews: Boolean,
linkMode: SimplexLinkMode,
@@ -865,7 +869,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
) {
val listState = rememberLazyListState()
val scope = rememberCoroutineScope()
ScrollToBottom(chat.id, listState, chatModel.chatItems)
ScrollToBottom(chat.id, listState, chatItems)
var prevSearchEmptiness by rememberSaveable { mutableStateOf(searchValue.value.isEmpty()) }
// Scroll to bottom when search value changes from something to nothing and back
LaunchedEffect(searchValue.value.isEmpty()) {
@@ -882,7 +886,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
PreloadItems(listState, ChatPagination.UNTIL_PRELOAD_COUNT, loadPrevMessages)
Spacer(Modifier.size(8.dp))
val reversedChatItems by remember { derivedStateOf { chatModel.chatItems.asReversed() } }
val reversedChatItems by remember { derivedStateOf { chatItems.reversed().toList() } }
val maxHeightRounded = with(LocalDensity.current) { maxHeight.roundToPx() }
val scrollToItem: (Long) -> Unit = { itemId: Long ->
val index = reversedChatItems.indexOfFirst { it.id == itemId }
@@ -935,7 +939,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
}
}
val provider = {
providerForGallery(i, chatModel.chatItems.value, cItem.id) { indexInReversed ->
providerForGallery(i, chatItems, cItem.id) { indexInReversed ->
scope.launch {
listState.scrollToItem(
kotlin.math.min(reversedChatItems.lastIndex, indexInReversed + 1),
@@ -1058,11 +1062,11 @@ fun BoxWithConstraintsScope.ChatItemsList(
}
}
}
FloatingButtons(chatModel.chatItems, unreadCount, chat.chatStats.minUnreadItemId, searchValue, markRead, setFloatingButton, listState)
FloatingButtons(chatItems, unreadCount, chat.chatStats.minUnreadItemId, searchValue, markRead, setFloatingButton, listState)
}
@Composable
private fun ScrollToBottom(chatId: ChatId, listState: LazyListState, chatItems: State<List<ChatItem>>) {
private fun ScrollToBottom(chatId: ChatId, listState: LazyListState, chatItems: List<ChatItem>) {
val scope = rememberCoroutineScope()
// Helps to scroll to bottom after moving from Group to Direct chat
// and prevents scrolling to bottom on orientation change
@@ -1080,7 +1084,7 @@ private fun ScrollToBottom(chatId: ChatId, listState: LazyListState, chatItems:
* When the first visible item (from bottom) is visible (even partially) we can autoscroll to 0 item. Or just scrollBy small distance otherwise
* */
LaunchedEffect(Unit) {
snapshotFlow { chatItems.value.lastOrNull()?.id }
snapshotFlow { chatItems.lastOrNull()?.id }
.distinctUntilChanged()
.filter { listState.layoutInfo.visibleItemsInfo.firstOrNull()?.key != it }
.collect {
@@ -1103,7 +1107,7 @@ private fun ScrollToBottom(chatId: ChatId, listState: LazyListState, chatItems:
@Composable
fun BoxWithConstraintsScope.FloatingButtons(
chatItems: State<List<ChatItem>>,
chatItems: List<ChatItem>,
unreadCount: State<Int>,
minUnreadItemId: Long,
searchValue: State<String>,
@@ -1137,11 +1141,10 @@ fun BoxWithConstraintsScope.FloatingButtons(
val bottomUnreadCount by remember {
derivedStateOf {
if (unreadCount.value == 0) return@derivedStateOf 0
val items = chatItems.value
val from = items.lastIndex - firstVisibleIndex - lastIndexOfVisibleItems
if (items.size <= from || from < 0) return@derivedStateOf 0
val from = chatItems.lastIndex - firstVisibleIndex - lastIndexOfVisibleItems
if (chatItems.size <= from || from < 0) return@derivedStateOf 0
items.subList(from, items.size).count { it.isRcvNew }
chatItems.subList(from, chatItems.size).count { it.isRcvNew }
}
}
val firstVisibleOffset = (-with(LocalDensity.current) { maxHeight.roundToPx() } * 0.8).toInt()
@@ -1187,7 +1190,7 @@ fun BoxWithConstraintsScope.FloatingButtons(
painterResource(MR.images.ic_check),
onClick = {
markRead(
CC.ItemRange(minUnreadItemId, chatItems.value[chatItems.size - listState.layoutInfo.visibleItemsInfo.lastIndex - 1].id - 1),
CC.ItemRange(minUnreadItemId, chatItems[chatItems.size - listState.layoutInfo.visibleItemsInfo.lastIndex - 1].id - 1),
bottomUnreadCount
)
showDropDown.value = false
@@ -1492,6 +1495,7 @@ fun PreviewChatLayout() {
composeView = {},
attachmentOption = remember { mutableStateOf<AttachmentOption?>(null) },
attachmentBottomSheetState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden),
chatItems = chatItems,
searchValue,
useLinkPreviews = true,
linkMode = SimplexLinkMode.DESCRIPTION,
@@ -1564,6 +1568,7 @@ fun PreviewGroupChatLayout() {
composeView = {},
attachmentOption = remember { mutableStateOf<AttachmentOption?>(null) },
attachmentBottomSheetState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden),
chatItems = chatItems,
searchValue,
useLinkPreviews = true,
linkMode = SimplexLinkMode.DESCRIPTION,

View File

@@ -267,7 +267,7 @@ fun ComposeView(
fun loadLinkPreview(url: String, wait: Long? = null) {
if (pendingLinkUrl.value == url) {
composeState.value = composeState.value.copy(preview = ComposePreview.CLinkPreview(null))
withLongRunningApi(slow = 60_000) {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
if (wait != null) delay(wait)
val lp = getLinkPreview(url)
if (lp != null && pendingLinkUrl.value == url) {
@@ -551,7 +551,7 @@ fun ComposeView(
}
fun sendMessage(ttl: Int?) {
withLongRunningApi(slow = 120_000) {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
sendMessageAsync(null, false, ttl)
}
}
@@ -583,10 +583,6 @@ fun ComposeView(
}
fun cancelLinkPreview() {
val pendingLink = pendingLinkUrl.value
if (pendingLink != null) {
cancelledLinks.add(pendingLink)
}
val uri = composeState.value.linkPreview?.uri
if (uri != null) {
cancelledLinks.add(uri)
@@ -665,7 +661,7 @@ fun ComposeView(
fun editPrevMessage() {
if (composeState.value.contextItem != ComposeContextItem.NoContextItem || composeState.value.preview != ComposePreview.NoPreview) return
val lastEditable = chatModel.chatItems.value.findLast { it.meta.editable }
val lastEditable = chatModel.chatItems.findLast { it.meta.editable }
if (lastEditable != null) {
composeState.value = ComposeState(editingItem = lastEditable, useLinkPreviews = useLinkPreviews)
}

View File

@@ -59,6 +59,14 @@ fun SendMsgView(
) {
val showCustomDisappearingMessageDialog = remember { mutableStateOf(false) }
if (showCustomDisappearingMessageDialog.value) {
CustomDisappearingMessageDialog(
sendMessage = sendMessage,
setShowDialog = { showCustomDisappearingMessageDialog.value = it },
customDisappearingMessageTimePref = customDisappearingMessageTimePref
)
}
Box(Modifier.padding(vertical = 8.dp)) {
val cs = composeState.value
var progressByTimeout by rememberSaveable { mutableStateOf(false) }
@@ -195,11 +203,6 @@ fun SendMsgView(
DefaultDropdownMenu(showDropdown) {
menuItems.forEach { composable -> composable() }
}
CustomDisappearingMessageDialog(
showCustomDisappearingMessageDialog,
sendMessage = sendMessage,
customDisappearingMessageTimePref = customDisappearingMessageTimePref
)
} else {
SendMsgButton(icon, sendButtonSize, sendButtonAlpha, sendButtonColor, !sendMsgButtonDisabled, sendMessage)
}
@@ -217,43 +220,93 @@ expect fun VoiceButtonWithoutPermissionByPlatform()
@Composable
private fun CustomDisappearingMessageDialog(
showMenu: MutableState<Boolean>,
sendMessage: (Int?) -> Unit,
setShowDialog: (Boolean) -> Unit,
customDisappearingMessageTimePref: SharedPreference<Int>?
) {
DefaultDropdownMenu(showMenu) {
Text(
generalGetString(MR.strings.send_disappearing_message),
Modifier.padding(vertical = DEFAULT_PADDING_HALF, horizontal = DEFAULT_PADDING * 1.5f),
fontSize = 16.sp,
color = MaterialTheme.colors.secondary
)
val showCustomTimePicker = remember { mutableStateOf(false) }
ItemAction(generalGetString(MR.strings.send_disappearing_message_30_seconds)) {
sendMessage(30)
showMenu.value = false
if (showCustomTimePicker.value) {
val selectedDisappearingMessageTime = remember {
mutableStateOf(customDisappearingMessageTimePref?.get?.invoke() ?: 300)
}
ItemAction(generalGetString(MR.strings.send_disappearing_message_1_minute)) {
sendMessage(60)
showMenu.value = false
CustomTimePickerDialog(
selectedDisappearingMessageTime,
title = generalGetString(MR.strings.delete_after),
confirmButtonText = generalGetString(MR.strings.send_disappearing_message_send),
confirmButtonAction = { ttl ->
sendMessage(ttl)
customDisappearingMessageTimePref?.set?.invoke(ttl)
setShowDialog(false)
},
cancel = { setShowDialog(false) }
)
} else {
@Composable
fun ChoiceButton(
text: String,
onClick: () -> Unit
) {
TextButton(onClick) {
Text(
text,
fontSize = 18.sp,
color = MaterialTheme.colors.primary
)
}
}
ItemAction(generalGetString(MR.strings.send_disappearing_message_5_minutes)) {
sendMessage(300)
showMenu.value = false
}
ItemAction(generalGetString(MR.strings.send_disappearing_message_custom_time)) {
showMenu.value = false
val selectedDisappearingMessageTime = mutableStateOf(customDisappearingMessageTimePref?.get?.invoke() ?: 300)
showCustomTimePickerDialog(
selectedDisappearingMessageTime,
title = generalGetString(MR.strings.delete_after),
confirmButtonText = generalGetString(MR.strings.send_disappearing_message_send),
confirmButtonAction = { ttl ->
sendMessage(ttl)
customDisappearingMessageTimePref?.set?.invoke(ttl)
},
cancel = { showMenu.value = false }
)
DefaultDialog(onDismissRequest = { setShowDialog(false) }) {
Surface(
shape = RoundedCornerShape(corner = CornerSize(25.dp)),
contentColor = LocalContentColor.current
) {
Box(
contentAlignment = Alignment.Center
) {
Column(
modifier = Modifier.padding(DEFAULT_PADDING),
verticalArrangement = Arrangement.spacedBy(6.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(" ") // centers title
Text(
generalGetString(MR.strings.send_disappearing_message),
fontSize = 16.sp,
color = MaterialTheme.colors.secondary
)
Icon(
painterResource(MR.images.ic_close),
generalGetString(MR.strings.icon_descr_close_button),
tint = MaterialTheme.colors.secondary,
modifier = Modifier
.size(25.dp)
.clickable { setShowDialog(false) }
)
}
ChoiceButton(generalGetString(MR.strings.send_disappearing_message_30_seconds)) {
sendMessage(30)
setShowDialog(false)
}
ChoiceButton(generalGetString(MR.strings.send_disappearing_message_1_minute)) {
sendMessage(60)
setShowDialog(false)
}
ChoiceButton(generalGetString(MR.strings.send_disappearing_message_5_minutes)) {
sendMessage(300)
setShowDialog(false)
}
ChoiceButton(generalGetString(MR.strings.send_disappearing_message_custom_time)) {
showCustomTimePicker.value = true
}
}
}
}
}
}
}

View File

@@ -54,7 +54,7 @@ fun AddGroupMembersView(rhId: Long?, groupInfo: GroupInfo, creatingGroup: Boolea
},
inviteMembers = {
allowModifyMembers = false
withLongRunningApi(slow = 120_000) {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
for (contactId in selectedContacts) {
val member = chatModel.controller.apiAddMember(rhId, groupInfo.groupId, contactId, selectedRole.value)
if (member != null) {
@@ -86,7 +86,7 @@ fun getContactsToAdd(chatModel: ChatModel, search: String): List<Contact> {
.map { it.chatInfo }
.filterIsInstance<ChatInfo.Direct>()
.map { it.contact }
.filter { c -> c.ready && c.active && c.contactId !in memberContactIds && c.chatViewName.lowercase().contains(s) }
.filter { it.contactId !in memberContactIds && it.chatViewName.lowercase().contains(s) }
.sortedBy { it.displayName.lowercase() }
.toList()
}

View File

@@ -152,7 +152,7 @@ fun leaveGroupDialog(rhId: Long?, groupInfo: GroupInfo, chatModel: ChatModel, cl
text = generalGetString(MR.strings.you_will_stop_receiving_messages_from_this_group_chat_history_will_be_preserved),
confirmText = generalGetString(MR.strings.leave_group_button),
onConfirm = {
withLongRunningApi(60_000) {
withBGApi {
chatModel.controller.leaveGroup(rhId, groupInfo.groupId)
close?.invoke()
}

View File

@@ -3,9 +3,11 @@ package chat.simplex.common.views.chat.group
import InfoRow
import SectionBottomSpacer
import SectionDividerSpaced
import SectionItemView
import SectionSpacer
import SectionTextFooter
import SectionView
import TextIconSpaced
import androidx.compose.desktop.ui.tooling.preview.Preview
import java.net.URI
import androidx.compose.foundation.*
@@ -72,8 +74,9 @@ fun GroupMemberInfoView(
if (chatModel.getContactChat(it) == null) {
chatModel.addChat(c)
}
chatModel.chatItems.clear()
chatModel.chatItemStatuses.clear()
chatModel.chatItems.replaceAll(c.chatItems)
chatModel.chatItems.addAll(c.chatItems)
chatModel.chatId.value = c.id
closeAll()
}

View File

@@ -3,7 +3,6 @@ package chat.simplex.common.views.chat.group
import SectionBottomSpacer
import SectionDividerSpaced
import SectionItemView
import SectionTextFooter
import SectionView
import TextIconSpaced
import androidx.compose.foundation.layout.*
@@ -15,7 +14,6 @@ import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.text.AnnotatedString
@@ -29,13 +27,9 @@ import chat.simplex.common.views.chat.item.MarkdownText
import chat.simplex.common.views.helpers.*
import chat.simplex.common.model.ChatModel
import chat.simplex.common.model.GroupInfo
import chat.simplex.common.platform.chatJsonLength
import chat.simplex.common.ui.theme.DEFAULT_PADDING_HALF
import chat.simplex.res.MR
import kotlinx.coroutines.delay
private const val maxByteCount = 1200
@Composable
fun GroupWelcomeView(m: ChatModel, rhId: Long?, groupInfo: GroupInfo, close: () -> Unit) {
var gInfo by remember { mutableStateOf(groupInfo) }
@@ -60,11 +54,8 @@ fun GroupWelcomeView(m: ChatModel, rhId: Long?, groupInfo: GroupInfo, close: ()
ModalView(
close = {
when {
welcomeTextUnchanged(welcomeText, gInfo) -> close()
!welcomeTextFitsLimit(welcomeText) -> showUnsavedChangesTooLongAlert(close)
else -> showUnsavedChangesAlert({ save(close) }, close)
}
if (welcomeText.value == gInfo.groupProfile.description || (welcomeText.value == "" && gInfo.groupProfile.description == null)) close()
else showUnsavedChangesAlert({ save(close) }, close)
},
) {
GroupWelcomeLayout(
@@ -76,14 +67,6 @@ fun GroupWelcomeView(m: ChatModel, rhId: Long?, groupInfo: GroupInfo, close: ()
}
}
private fun welcomeTextUnchanged(welcomeText: MutableState<String>, groupInfo: GroupInfo): Boolean {
return welcomeText.value == groupInfo.groupProfile.description || (welcomeText.value == "" && groupInfo.groupProfile.description == null)
}
private fun welcomeTextFitsLimit(welcomeText: MutableState<String>): Boolean {
return chatJsonLength(welcomeText.value) <= maxByteCount
}
@Composable
private fun GroupWelcomeLayout(
welcomeText: MutableState<String>,
@@ -112,13 +95,6 @@ private fun GroupWelcomeLayout(
} else {
TextPreview(wt.value, linkMode)
}
SectionTextFooter(
if (!welcomeTextFitsLimit(wt)) { generalGetString(MR.strings.message_too_large) } else "",
color = if (welcomeTextFitsLimit(wt)) MaterialTheme.colors.secondary else Color.Red
)
Spacer(Modifier.size(8.dp))
ChangeModeButton(
editMode.value,
click = {
@@ -128,18 +104,10 @@ private fun GroupWelcomeLayout(
)
val clipboard = LocalClipboardManager.current
CopyTextButton { clipboard.setText(AnnotatedString(wt.value)) }
Divider(
Modifier.padding(
start = DEFAULT_PADDING_HALF,
top = 8.dp,
end = DEFAULT_PADDING_HALF,
bottom = 8.dp)
)
SectionDividerSpaced(maxBottomPadding = false)
SaveButton(
save = save,
disabled = welcomeTextUnchanged(wt, groupInfo) || !welcomeTextFitsLimit(wt)
disabled = wt.value == groupInfo.groupProfile.description || (wt.value == "" && groupInfo.groupProfile.description == null)
)
} else {
val clipboard = LocalClipboardManager.current
@@ -214,11 +182,3 @@ private fun showUnsavedChangesAlert(save: () -> Unit, revert: () -> Unit) {
onDismiss = revert,
)
}
private fun showUnsavedChangesTooLongAlert(revert: () -> Unit) {
AlertManager.shared.showAlertDialogStacked(
title = generalGetString(MR.strings.welcome_message_is_too_long),
confirmText = generalGetString(MR.strings.exit_without_saving),
onConfirm = revert,
)
}

View File

@@ -94,7 +94,7 @@ fun CIFileView(
FileProtocol.LOCAL -> {}
}
file.fileStatus is CIFileStatus.RcvComplete || (file.fileStatus is CIFileStatus.SndStored && file.fileProtocol == FileProtocol.LOCAL) -> {
withLongRunningApi(slow = 600_000) {
withLongRunningApi(slow = 60_000, deadlock = 600_000) {
var filePath = getLoadedFilePath(file)
if (chatModel.connectedToRemote() && filePath == null) {
file.loadRemoteFile(true)

View File

@@ -41,7 +41,7 @@ fun CIVideoView(
val filePath = remember(file, CIFile.cachedRemoteFileRequests.toList()) { mutableStateOf(getLoadedFilePath(file)) }
if (chatModel.connectedToRemote()) {
LaunchedEffect(file) {
withLongRunningApi(slow = 600_000) {
withLongRunningApi(slow = 60_000, deadlock = 600_000) {
if (file != null && file.loaded && getLoadedFilePath(file) == null) {
file.loadRemoteFile(false)
filePath.value = getLoadedFilePath(file)

View File

@@ -103,7 +103,7 @@ fun ChatItemView(
setReaction(cInfo, cItem, !r.userReacted, r.reaction)
}
}
Row(modifier.padding(2.dp), verticalAlignment = Alignment.CenterVertically) {
Row(modifier.padding(2.dp)) {
ReactionIcon(r.reaction.text, fontSize = 12.sp)
if (r.totalReacted > 1) {
Spacer(Modifier.width(4.dp))
@@ -112,6 +112,7 @@ fun ChatItemView(
fontSize = 11.5.sp,
fontWeight = if (r.userReacted) FontWeight.Bold else FontWeight.Normal,
color = if (r.userReacted) MaterialTheme.colors.primary else MaterialTheme.colors.secondary,
modifier = if (appPlatform.isAndroid) Modifier else Modifier.padding(top = 4.dp)
)
}
}
@@ -177,8 +178,7 @@ fun ChatItemView(
fun MsgContentItemDropdownMenu() {
val saveFileLauncher = rememberSaveFileLauncher(ciFile = cItem.file)
when {
// cItem.id check is a special case for live message chat item which has negative ID while not sent yet
cItem.content.msgContent != null && cItem.id >= 0 -> {
cItem.content.msgContent != null -> {
DefaultDropdownMenu(showMenu) {
if (cInfo.featureEnabled(ChatFeature.Reactions) && cItem.allowAddReaction) {
MsgReactionsMenu()
@@ -213,7 +213,7 @@ fun ChatItemView(
showMenu.value = false
}
if (chatModel.connectedToRemote() && fileSource == null) {
withLongRunningApi(slow = 600_000) {
withLongRunningApi(slow = 60_000, deadlock = 600_000) {
cItem.file?.loadRemoteFile(true)
fileSource = getLoadedFileSource(cItem.file)
shareIfExists()
@@ -527,9 +527,8 @@ fun DeleteItemAction(
val range = chatViewItemsRange(currIndex, prevHidden)
if (range != null) {
val itemIds: ArrayList<Long> = arrayListOf()
val reversedChatItems = chatModel.chatItems.asReversed()
for (i in range) {
itemIds.add(reversedChatItems[i].id)
itemIds.add(chatModel.chatItems.asReversed()[i].id)
}
deleteMessagesAlertDialog(itemIds, generalGetString(MR.strings.delete_message_mark_deleted_warning), deleteMessages = deleteMessages)
} else {
@@ -652,23 +651,6 @@ fun ItemAction(text: String, icon: ImageVector, onClick: () -> Unit, color: Colo
}
}
@Composable
fun ItemAction(text: String, color: Color = Color.Unspecified, onClick: () -> Unit) {
val finalColor = if (color == Color.Unspecified) {
MenuTextColor
} else color
DropdownMenuItem(onClick, contentPadding = PaddingValues(horizontal = DEFAULT_PADDING * 1.5f)) {
Text(
text,
modifier = Modifier
.fillMaxWidth()
.weight(1F)
.padding(end = 15.dp),
color = finalColor
)
}
}
fun cancelFileAlertDialog(fileId: Long, cancelFile: (Long) -> Unit, cancelAction: CancelAction) {
AlertManager.shared.showAlertDialog(
title = generalGetString(cancelAction.alert.titleId),

View File

@@ -91,7 +91,7 @@ private fun MergedMarkedDeletedText(chatItem: ChatItem, revealed: MutableState<B
)
}
fun markedDeletedText(meta: CIMeta): String =
private fun markedDeletedText(meta: CIMeta): String =
when (meta.itemDeleted) {
is CIDeleted.Moderated ->
String.format(generalGetString(MR.strings.moderated_item_description), meta.itemDeleted.byGroupMember.displayName)

View File

@@ -212,15 +212,18 @@ suspend fun openGroupChat(rhId: Long?, groupId: Long, chatModel: ChatModel) {
}
suspend fun openChat(rhId: Long?, chatInfo: ChatInfo, chatModel: ChatModel) {
Log.d(TAG, "TODOCHAT: openChat: opening ${chatInfo.id}, current chatId ${ChatModel.chatId.value}, size ${ChatModel.chatItems.size}")
val chat = chatModel.controller.apiGetChat(rhId, chatInfo.chatType, chatInfo.apiId)
if (chat != null) {
openLoadedChat(chat, chatModel)
Log.d(TAG, "TODOCHAT: openChat: opened ${chatInfo.id}, current chatId ${ChatModel.chatId.value}, size ${ChatModel.chatItems.size}")
}
}
fun openLoadedChat(chat: Chat, chatModel: ChatModel) {
chatModel.chatItems.clear()
chatModel.chatItemStatuses.clear()
chatModel.chatItems.replaceAll(chat.chatItems)
chatModel.chatItems.addAll(chat.chatItems)
chatModel.chatId.value = chat.chatInfo.id
}
@@ -236,7 +239,8 @@ suspend fun apiFindMessages(ch: Chat, chatModel: ChatModel, search: String) {
val chatInfo = ch.chatInfo
val chat = chatModel.controller.apiGetChat(ch.remoteHostId, chatInfo.chatType, chatInfo.apiId, search = search) ?: return
if (chatModel.chatId.value != chat.id) return
chatModel.chatItems.replaceAll(chat.chatItems)
chatModel.chatItems.clear()
chatModel.chatItems.addAll(0, chat.chatItems)
}
suspend fun setGroupMembers(rhId: Long?, groupInfo: GroupInfo, chatModel: ChatModel) {

View File

@@ -26,7 +26,6 @@ import chat.simplex.common.views.helpers.*
import chat.simplex.common.model.*
import chat.simplex.common.model.GroupInfo
import chat.simplex.common.platform.chatModel
import chat.simplex.common.views.chat.item.markedDeletedText
import chat.simplex.res.MR
import dev.icerock.moko.resources.ImageResource
@@ -171,7 +170,7 @@ fun ChatPreviewView(
val (text: CharSequence, inlineTextContent) = when {
chatModelDraftChatId == chat.id && chatModelDraft != null -> remember(chatModelDraft) { messageDraft(chatModelDraft) }
ci.meta.itemDeleted == null -> ci.text to null
else -> markedDeletedText(ci.meta) to null
else -> generalGetString(MR.strings.marked_deleted_description) to null
}
val formattedText = when {
chatModelDraftChatId == chat.id && chatModelDraft != null -> null
@@ -287,7 +286,7 @@ fun ChatPreviewView(
Box(
contentAlignment = Alignment.TopEnd
) {
val ts = chat.chatItems.lastOrNull()?.timestampText ?: getTimestampText(chat.chatInfo.chatTs)
val ts = chat.chatItems.lastOrNull()?.timestampText ?: getTimestampText(chat.chatInfo.updatedAt)
Text(
ts,
color = MaterialTheme.colors.secondary,

View File

@@ -62,7 +62,7 @@ fun DatabaseEncryptionView(m: ChatModel) {
initialRandomDBPassphrase,
progressIndicator,
onConfirmEncrypt = {
withLongRunningApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
encryptDatabase(currentKey, newKey, confirmNewKey, initialRandomDBPassphrase, useKeychain, storedKey, progressIndicator)
}
}
@@ -233,13 +233,13 @@ fun resetFormAfterEncryption(
storedKey: MutableState<Boolean>,
stored: Boolean = false,
) {
m.chatDbEncrypted.value = true
initialRandomDBPassphrase.value = false
m.controller.appPrefs.initialRandomDBPassphrase.set(false)
currentKey.value = ""
newKey.value = ""
confirmNewKey.value = ""
storedKey.value = stored
m.chatDbEncrypted.value = true
initialRandomDBPassphrase.value = false
m.controller.appPrefs.initialRandomDBPassphrase.set(false)
}
fun setUseKeychain(value: Boolean, useKeychain: MutableState<Boolean>, prefs: AppPreferences) {
@@ -392,11 +392,12 @@ suspend fun encryptDatabase(
false
}
else -> {
val new = newKey.value
resetFormAfterEncryption(m, initialRandomDBPassphrase, currentKey, newKey, confirmNewKey, storedKey, useKeychain.value)
prefs.initialRandomDBPassphrase.set(false)
initialRandomDBPassphrase.value = false
if (useKeychain.value) {
DatabaseUtils.ksDatabasePassword.set(new)
DatabaseUtils.ksDatabasePassword.set(newKey.value)
}
resetFormAfterEncryption(m, initialRandomDBPassphrase, currentKey, newKey, confirmNewKey, storedKey, useKeychain.value)
operationEnded(m, progressIndicator) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.database_encrypted))
}

View File

@@ -368,7 +368,7 @@ fun chatArchiveTitle(chatArchiveTime: Instant, chatLastStart: Instant): String {
}
fun startChat(m: ChatModel, chatLastStart: MutableState<Instant?>, chatDbChanged: MutableState<Boolean>, progressIndicator: MutableState<Boolean>? = null) {
withLongRunningApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
try {
progressIndicator?.value = true
if (chatDbChanged.value) {
@@ -581,7 +581,7 @@ private fun importArchive(
progressIndicator.value = true
val archivePath = saveArchiveFromURI(importedArchiveURI)
if (archivePath != null) {
withLongRunningApi {
withLongRunningApi(slow = 60_000, deadlock = 180_000) {
try {
m.controller.apiDeleteStorage()
try {

View File

@@ -12,7 +12,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.style.TextAlign
@@ -23,8 +22,6 @@ import chat.simplex.common.ui.theme.*
import chat.simplex.res.MR
import dev.icerock.moko.resources.StringResource
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
class AlertManager {
@@ -131,8 +128,6 @@ class AlertManager {
) {
val focusRequester = remember { FocusRequester() }
LaunchedEffect(Unit) {
// Wait before focusing to prevent auto-confirming if a user used Enter key on hardware keyboard
delay(200)
focusRequester.requestFocus()
}
TextButton(onClick = {
@@ -191,7 +186,6 @@ class AlertManager {
title: String, text: String? = null,
confirmText: String = generalGetString(MR.strings.ok),
hostDevice: Pair<Long?, String>? = null,
shareText: Boolean? = null
) {
showAlert {
AlertDialog(
@@ -201,23 +195,12 @@ class AlertManager {
AlertContent(text, hostDevice, extraPadding = true) {
val focusRequester = remember { FocusRequester() }
LaunchedEffect(Unit) {
// Wait before focusing to prevent auto-confirming if a user used Enter key on hardware keyboard
delay(200)
focusRequester.requestFocus()
}
// Can pass shareText = false to prevent showing Share button if it's needed in a specific case
val showShareButton = text != null && (shareText == true || (shareText == null && text.length > 500))
Row(
Modifier.fillMaxWidth().padding(horizontal = DEFAULT_PADDING),
horizontalArrangement = if (showShareButton) Arrangement.SpaceBetween else Arrangement.Center
horizontalArrangement = Arrangement.Center
) {
val clipboard = LocalClipboardManager.current
if (showShareButton && text != null) {
TextButton(onClick = {
clipboard.shareText(text)
hideAlert()
}) { Text(stringResource(MR.strings.share_verb)) }
}
TextButton(
onClick = {
hideAlert()

View File

@@ -27,8 +27,8 @@ fun ChatInfoImage(chatInfo: ChatInfo, size: Dp, iconColor: Color = MaterialTheme
val icon =
when (chatInfo) {
is ChatInfo.Group -> MR.images.ic_supervised_user_circle_filled
is ChatInfo.Local -> MR.images.ic_folder_filled
else -> MR.images.ic_account_circle_filled
is ChatInfo.Direct -> MR.images.ic_account_circle_filled
else -> MR.images.ic_folder_filled
}
ProfileImage(size, chatInfo.image, icon, if (chatInfo is ChatInfo.Local) NoteFolderIconColor else iconColor)
}

View File

@@ -1,21 +1,116 @@
package chat.simplex.common.views.helpers
import SectionItemView
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import dev.icerock.moko.resources.compose.painterResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import chat.simplex.common.ui.theme.DEFAULT_PADDING
import chat.simplex.common.model.CustomTimeUnit
import chat.simplex.common.model.timeText
import chat.simplex.res.MR
import com.sd.lib.compose.wheel_picker.*
@Composable
expect fun CustomTimePicker(
fun CustomTimePicker(
selection: MutableState<Int>,
timeUnitsLimits: List<TimeUnitLimits> = TimeUnitLimits.defaultUnitsLimits
)
) {
fun getUnitValues(unit: CustomTimeUnit, selectedValue: Int): List<Int> {
val unitLimits = timeUnitsLimits.firstOrNull { it.timeUnit == unit } ?: TimeUnitLimits.defaultUnitLimits(unit)
val regularUnitValues = (unitLimits.minValue..unitLimits.maxValue).toList()
return regularUnitValues + if (regularUnitValues.contains(selectedValue)) emptyList() else listOf(selectedValue)
}
val (unit, duration) = CustomTimeUnit.toTimeUnit(selection.value)
val selectedUnit: MutableState<CustomTimeUnit> = remember { mutableStateOf(unit) }
val selectedDuration = remember { mutableStateOf(duration) }
val selectedUnitValues = remember { mutableStateOf(getUnitValues(selectedUnit.value, selectedDuration.value)) }
val isTriggered = remember { mutableStateOf(false) }
LaunchedEffect(selectedUnit.value) {
// on initial composition, if passed selection doesn't fit into picker bounds, so that selectedDuration is bigger than selectedUnit maxValue
// (e.g., for selection = 121 seconds: selectedUnit would be Second, selectedDuration would be 121 > selectedUnit maxValue of 120),
// selectedDuration would've been replaced by maxValue - isTriggered check prevents this by skipping LaunchedEffect on initial composition
if (isTriggered.value) {
val maxValue = timeUnitsLimits.firstOrNull { it.timeUnit == selectedUnit.value }?.maxValue
if (maxValue != null && selectedDuration.value > maxValue) {
selectedDuration.value = maxValue
selectedUnitValues.value = getUnitValues(selectedUnit.value, selectedDuration.value)
} else {
selectedUnitValues.value = getUnitValues(selectedUnit.value, selectedDuration.value)
selection.value = selectedUnit.value.toSeconds * selectedDuration.value
}
} else {
isTriggered.value = true
}
}
LaunchedEffect(selectedDuration.value) {
selection.value = selectedUnit.value.toSeconds * selectedDuration.value
}
Row(
Modifier
.fillMaxWidth()
.padding(horizontal = DEFAULT_PADDING),
horizontalArrangement = Arrangement.spacedBy(0.dp)
) {
Column(Modifier.weight(1f)) {
val durationPickerState = rememberFWheelPickerState(selectedUnitValues.value.indexOf(selectedDuration.value))
FVerticalWheelPicker(
count = selectedUnitValues.value.count(),
state = durationPickerState,
unfocusedCount = 2,
focus = {
FWheelPickerFocusVertical(dividerColor = MaterialTheme.colors.primary)
}
) { index ->
Text(
selectedUnitValues.value[index].toString(),
fontSize = 18.sp,
color = MaterialTheme.colors.primary
)
}
LaunchedEffect(durationPickerState) {
snapshotFlow { durationPickerState.currentIndex }
.collect {
selectedDuration.value = selectedUnitValues.value[it]
}
}
}
Column(Modifier.weight(1f)) {
val unitPickerState = rememberFWheelPickerState(timeUnitsLimits.indexOfFirst { it.timeUnit == selectedUnit.value })
FVerticalWheelPicker(
count = timeUnitsLimits.count(),
state = unitPickerState,
unfocusedCount = 2,
focus = {
FWheelPickerFocusVertical(dividerColor = MaterialTheme.colors.primary)
}
) { index ->
Text(
timeUnitsLimits[index].timeUnit.text,
fontSize = 18.sp,
color = MaterialTheme.colors.primary
)
}
LaunchedEffect(unitPickerState) {
snapshotFlow { unitPickerState.currentIndex }
.collect {
selectedUnit.value = timeUnitsLimits[it].timeUnit
}
}
}
}
}
data class TimeUnitLimits(
val timeUnit: CustomTimeUnit,
@@ -46,7 +141,8 @@ data class TimeUnitLimits(
}
}
fun showCustomTimePickerDialog(
@Composable
fun CustomTimePickerDialog(
selection: MutableState<Int>,
timeUnitsLimits: List<TimeUnitLimits> = TimeUnitLimits.defaultUnitsLimits,
title: String,
@@ -54,26 +150,53 @@ fun showCustomTimePickerDialog(
confirmButtonAction: (Int) -> Unit,
cancel: () -> Unit
) {
AlertManager.shared.showAlertDialogButtonsColumn(
title = title,
onDismissRequest = cancel
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
CustomTimePicker(
selection,
timeUnitsLimits
)
SectionItemView({
AlertManager.shared.hideAlert()
confirmButtonAction(selection.value)
}
DefaultDialog(onDismissRequest = cancel) {
Surface(
shape = RoundedCornerShape(corner = CornerSize(25.dp)),
contentColor = LocalContentColor.current
) {
Box(
contentAlignment = Alignment.Center
) {
Text(
confirmButtonText,
Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
color = MaterialTheme.colors.primary
)
Column(
modifier = Modifier.padding(DEFAULT_PADDING),
verticalArrangement = Arrangement.spacedBy(6.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(" ") // centers title
Text(
title,
fontSize = 16.sp,
color = MaterialTheme.colors.secondary
)
Icon(
painterResource(MR.images.ic_close),
generalGetString(MR.strings.icon_descr_close_button),
tint = MaterialTheme.colors.secondary,
modifier = Modifier
.size(25.dp)
.clickable { cancel() }
)
}
CustomTimePicker(
selection,
timeUnitsLimits
)
TextButton(onClick = { confirmButtonAction(selection.value) }) {
Text(
confirmButtonText,
fontSize = 18.sp,
color = MaterialTheme.colors.primary
)
}
}
}
}
}
@@ -97,6 +220,7 @@ fun DropdownCustomTimePickerSettingRow(
val dropdownSelection: MutableState<DropdownSelection> = remember { mutableStateOf(DropdownSelection.DropdownValue(selection.value)) }
val values: MutableState<List<DropdownSelection>> = remember { mutableStateOf(getValues(selection.value)) }
val showCustomTimePicker = remember { mutableStateOf(false) }
fun updateValue(selectedValue: Int?) {
values.value = getValues(selectedValue)
@@ -123,22 +247,28 @@ fun DropdownCustomTimePickerSettingRow(
onSelected = { sel: DropdownSelection ->
when (sel) {
is DropdownSelection.DropdownValue -> updateValue(sel.value)
DropdownSelection.Custom -> {
val selectedCustomTime = mutableStateOf(selection.value ?: 86400)
showCustomTimePickerDialog(
selectedCustomTime,
timeUnitsLimits = customPickerTimeUnitsLimits,
title = customPickerTitle,
confirmButtonText = customPickerConfirmButtonText,
confirmButtonAction = ::updateValue,
cancel = {
dropdownSelection.value = DropdownSelection.DropdownValue(selection.value)
}
)
}
DropdownSelection.Custom -> showCustomTimePicker.value = true
}
}
)
if (showCustomTimePicker.value) {
val selectedCustomTime = remember { mutableStateOf(selection.value ?: 86400) }
CustomTimePickerDialog(
selectedCustomTime,
timeUnitsLimits = customPickerTimeUnitsLimits,
title = customPickerTitle,
confirmButtonText = customPickerConfirmButtonText,
confirmButtonAction = { time ->
updateValue(time)
showCustomTimePicker.value = false
},
cancel = {
dropdownSelection.value = DropdownSelection.DropdownValue(selection.value)
showCustomTimePicker.value = false
}
)
}
}
private sealed class DropdownSelection {

View File

@@ -5,7 +5,6 @@ import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import chat.simplex.common.ui.theme.DEFAULT_PADDING
@@ -21,7 +20,7 @@ fun DefaultProgressView(description: String?) {
strokeWidth = 2.5.dp
)
if (description != null) {
Text(description, textAlign = TextAlign.Center)
Text(description)
}
}
}

View File

@@ -61,10 +61,10 @@ class ModalManager(private val placement: ModalPlacement? = null) {
}
}
fun showModalCloseable(settings: Boolean = false, showClose: Boolean = true, endButtons: @Composable RowScope.() -> Unit = {}, content: @Composable ModalData.(close: () -> Unit) -> Unit) {
fun showModalCloseable(settings: Boolean = false, showClose: Boolean = true, content: @Composable ModalData.(close: () -> Unit) -> Unit) {
val data = ModalData()
showCustomModal { close ->
ModalView(close, showClose = showClose, endButtons = endButtons, content = { data.content(close) })
ModalView(close, showClose = showClose, content = { data.content(close) })
}
}

View File

@@ -16,7 +16,7 @@ class ProcessedErrors <T: AgentErrorType>(val interval: Long) {
fun newError(error: T, offerRestart: Boolean) {
timer.cancel()
timer = withLongRunningApi(slow = 130_000) {
timer = withLongRunningApi(slow = 70_000, deadlock = 130_000) {
val delayBeforeNext = (lastShownTimestamp + interval) - System.currentTimeMillis()
if ((lastShownOfferRestart || !offerRestart) && delayBeforeNext >= 0) {
delay(delayBeforeNext)

View File

@@ -22,7 +22,6 @@ import dev.icerock.moko.resources.compose.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.*
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.res.MR
@@ -96,7 +95,7 @@ fun SearchTextField(
value = searchText.value.text,
innerTextField = innerTextField,
placeholder = {
Text(placeholder, maxLines = 1, overflow = TextOverflow.Ellipsis)
Text(placeholder)
},
trailingIcon = if (searchText.value.text.isNotEmpty()) {{
IconButton({

View File

@@ -198,16 +198,16 @@ fun <T> SectionItemWithValue(
}
@Composable
fun SectionTextFooter(text: String, color: Color = MaterialTheme.colors.secondary) {
SectionTextFooter(AnnotatedString(text), color = color)
fun SectionTextFooter(text: String) {
SectionTextFooter(AnnotatedString(text))
}
@Composable
fun SectionTextFooter(text: AnnotatedString, textAlign: TextAlign = TextAlign.Start, color: Color = MaterialTheme.colors.secondary) {
fun SectionTextFooter(text: AnnotatedString, textAlign: TextAlign = TextAlign.Start) {
Text(
text,
Modifier.padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING, top = DEFAULT_PADDING_HALF).fillMaxWidth(0.9F),
color = color,
color = MaterialTheme.colors.secondary,
lineHeight = 18.sp,
fontSize = 14.sp,
textAlign = textAlign

View File

@@ -37,22 +37,32 @@ fun withBGApi(action: suspend CoroutineScope.() -> Unit): Job =
CoroutineScope(singleThreadDispatcher).launch(block = { wrapWithLogging(action, it) })
}
fun withLongRunningApi(slow: Long = Long.MAX_VALUE, action: suspend CoroutineScope.() -> Unit): Job =
fun withLongRunningApi(slow: Long = Long.MAX_VALUE, deadlock: Long = Long.MAX_VALUE, action: suspend CoroutineScope.() -> Unit): Job =
Exception().let {
CoroutineScope(Dispatchers.Default).launch(block = { wrapWithLogging(action, it, slow = slow) })
CoroutineScope(Dispatchers.Default).launch(block = { wrapWithLogging(action, it, slow = slow, deadlock = deadlock) })
}
private suspend fun wrapWithLogging(action: suspend CoroutineScope.() -> Unit, exception: java.lang.Exception, slow: Long = 20_000) = coroutineScope {
suspend fun withSingleThreadContext(action: suspend CoroutineScope.() -> Unit) = withContext(singleThreadDispatcher, action)
private suspend fun wrapWithLogging(action: suspend CoroutineScope.() -> Unit, exception: java.lang.Exception, slow: Long = 10_000, deadlock: Long = 60_000) = coroutineScope {
val start = System.currentTimeMillis()
val job = launch {
delay(deadlock)
Log.e(TAG, "Possible deadlock of the thread, not finished after ${deadlock / 1000}s:\n${exception.stackTraceToString()}")
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.possible_deadlock_title),
text = generalGetString(MR.strings.possible_deadlock_desc).format(deadlock / 1000, exception.stackTraceToString()),
)
}
action()
val end = System.currentTimeMillis()
if (end - start > slow) {
Log.e(TAG, "Possible problem with execution of the thread, took ${(end - start) / 1000}s:\n${exception.stackTraceToString()}")
if (appPreferences.developerTools.get() && appPreferences.showSlowApiCalls.get()) {
job.cancel()
if (appPreferences.developerTools.get() && appPreferences.showSlowApiCalls.get()) {
val end = System.currentTimeMillis()
if (end - start > slow) {
Log.e(TAG, "Possible problem with execution of the thread, took ${(end - start) / 1000}s:\n${exception.stackTraceToString()}")
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.possible_slow_function_title),
text = generalGetString(MR.strings.possible_slow_function_desc).format((end - start) / 1000, exception.stackTraceToString()),
shareText = true
)
}
}

View File

@@ -49,7 +49,7 @@ fun LocalAuthView(m: ChatModel, authRequest: LocalAuthRequest) {
}
private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: (LAResult) -> Unit) {
withLongRunningApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
try {
/** Waiting until [initChatController] finishes */
while (m.ctrlInitInProgress.value) {

View File

@@ -50,7 +50,7 @@ fun SetupDatabasePassphrase(m: ChatModel) {
confirmNewKey,
progressIndicator,
onConfirmEncrypt = {
withLongRunningApi {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
if (m.chatRunning.value == true) {
// Stop chat if it's started before doing anything
stopChatAsync(m)

View File

@@ -36,7 +36,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) {
Icon(
painterResource(MR.images.ic_open_in_new), stringResource(titleId), tint = MaterialTheme.colors.primary,
modifier = Modifier
.clickable { if (link.startsWith("simplex:")) uriHandler.openVerifiedSimplexUri(link) else uriHandler.openUriCatching(link) }
.clickable { uriHandler.openUriCatching(link) }
)
}

View File

@@ -47,6 +47,10 @@ fun NetworkAndServersView(
val onionHosts = remember { mutableStateOf(netCfg.onionHosts) }
val sessionMode = remember { mutableStateOf(netCfg.sessionMode) }
LaunchedEffect(Unit) {
chatModel.userSMPServersUnsaved.value = null
}
val proxyPort = remember { derivedStateOf { chatModel.controller.appPrefs.networkProxyHostPort.state.value?.split(":")?.lastOrNull()?.toIntOrNull() ?: 9050 } }
NetworkAndServersLayout(
currentRemoteHost = currentRemoteHost,

View File

@@ -96,7 +96,7 @@ fun PrivacySettingsView(
val currentUser = chatModel.currentUser.value
if (currentUser != null) {
fun setSendReceiptsContacts(enable: Boolean, clearOverrides: Boolean) {
withLongRunningApi(slow = 60_000) {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
val mrs = UserMsgReceiptSettings(enable, clearOverrides)
chatModel.controller.apiSetUserContactReceipts(currentUser, mrs)
chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.set(true)
@@ -119,7 +119,7 @@ fun PrivacySettingsView(
}
fun setSendReceiptsGroups(enable: Boolean, clearOverrides: Boolean) {
withLongRunningApi(slow = 60_000) {
withLongRunningApi(slow = 30_000, deadlock = 60_000) {
val mrs = UserMsgReceiptSettings(enable, clearOverrides)
chatModel.controller.apiSetUserGroupReceipts(currentUser, mrs)
chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.set(true)

View File

@@ -28,18 +28,19 @@ import chat.simplex.res.MR
@Composable
fun ModalData.ProtocolServersView(m: ChatModel, rhId: Long?, serverProtocol: ServerProtocol, close: () -> Unit) {
var presetServers by remember(rhId) { mutableStateOf(emptyList<String>()) }
var servers by remember { stateGetOrPut("servers") { emptyList<ServerCfg>() } }
var serversAlreadyLoaded by remember { stateGetOrPut("serversAlreadyLoaded") { false } }
var servers by remember(rhId) {
mutableStateOf(m.userSMPServersUnsaved.value ?: emptyList())
}
val currServers = remember(rhId) { mutableStateOf(servers) }
val testing = rememberSaveable(rhId) { mutableStateOf(false) }
val serversUnchanged = remember(servers) { derivedStateOf { servers == currServers.value || testing.value } }
val allServersDisabled = remember { derivedStateOf { servers.none { it.enabled } } }
val saveDisabled = remember(servers) {
val serversUnchanged = remember { derivedStateOf { servers == currServers.value || testing.value } }
val allServersDisabled = remember { derivedStateOf { servers.all { !it.enabled } } }
val saveDisabled = remember {
derivedStateOf {
servers.isEmpty() ||
servers == currServers.value ||
testing.value ||
servers.none { srv ->
!servers.all { srv ->
val address = parseServerAddress(srv.server)
address != null && uniqueAddress(srv, address, servers)
} ||
@@ -48,8 +49,8 @@ fun ModalData.ProtocolServersView(m: ChatModel, rhId: Long?, serverProtocol: Ser
}
KeyChangeEffect(rhId) {
m.userSMPServersUnsaved.value = null
servers = emptyList()
serversAlreadyLoaded = false
}
LaunchedEffect(rhId) {
@@ -58,9 +59,8 @@ fun ModalData.ProtocolServersView(m: ChatModel, rhId: Long?, serverProtocol: Ser
if (res != null) {
currServers.value = res.protoServers
presetServers = res.presetServers
if (servers.isEmpty() && !serversAlreadyLoaded) {
if (servers.isEmpty()) {
servers = currServers.value
serversAlreadyLoaded = true
}
}
}
@@ -80,11 +80,13 @@ fun ModalData.ProtocolServersView(m: ChatModel, rhId: Long?, serverProtocol: Ser
newServers.add(index, updated)
old = updated
servers = newServers
m.userSMPServersUnsaved.value = servers
},
onDelete = {
val newServers = ArrayList(servers)
newServers.removeAt(index)
servers = newServers
m.userSMPServersUnsaved.value = servers
close()
})
}
@@ -123,6 +125,7 @@ fun ModalData.ProtocolServersView(m: ChatModel, rhId: Long?, serverProtocol: Ser
ScanProtocolServer(rhId) {
close()
servers = servers + it
m.userSMPServersUnsaved.value = servers
}
}
}
@@ -147,11 +150,13 @@ fun ModalData.ProtocolServersView(m: ChatModel, rhId: Long?, serverProtocol: Ser
testServersJob.value = withLongRunningApi {
testServers(testing, servers, m) {
servers = it
m.userSMPServersUnsaved.value = servers
}
}
},
resetServers = {
servers = currServers.value
servers = currServers.value ?: emptyList()
m.userSMPServersUnsaved.value = null
},
saveSMPServers = {
saveServers(rhId, serverProtocol, currServers, servers, m)
@@ -350,6 +355,7 @@ private fun saveServers(rhId: Long?, protocol: ServerProtocol, currServers: Muta
withBGApi {
if (m.controller.setUserProtoServers(rhId, protocol, servers)) {
currServers.value = servers
m.userSMPServersUnsaved.value = null
}
afterSave()
}

View File

@@ -22,10 +22,10 @@
<string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">منصة الرسائل والتطبيقات تحمي خصوصيتك وأمنك.</string>
<string name="profile_is_only_shared_with_your_contacts">يتم مشاركة ملف التعريف مع جهات اتصالك فقط.</string>
<string name="member_role_will_be_changed_with_notification">سيتم تغيير الدور إلى \"%s\". سيتم إبلاغ كل فرد في المجموعة.</string>
<string name="member_role_will_be_changed_with_invitation">سيتم تغيير الدور إلى \"%s\". سيستلم العضو دعوة جديدة.</string>
<string name="member_role_will_be_changed_with_invitation">سيتم تغيير الدور إلى \"%s\". سيتلقى العضو دعوة جديدة.</string>
<string name="smp_servers_per_user">خوادم الاتصالات الجديدة لملف تعريف الدردشة الحالي الخاص بك</string>
<string name="switch_receiving_address_desc">سيتم تغيير عنوان الاستلام إلى خادم مختلف. سيتم إكمال تغيير العنوان بعد اتصال المرسل بالإنترنت.</string>
<string name="this_link_is_not_a_valid_connection_link">هذا الرابط ليس رابط اتصال صالح!</string>
<string name="this_link_is_not_a_valid_connection_link">هذا الارتباط ليس ارتباط اتصال صالح!</string>
<string name="allow_verb">يسمح</string>
<string name="smp_servers_preset_add">أضِف خوادم محدّدة مسبقًا</string>
<string name="smp_servers_add_to_another_device">أضِف إلى جهاز آخر</string>
@@ -36,13 +36,13 @@
<string name="all_group_members_will_remain_connected">سيبقى جميع أعضاء المجموعة على اتصال.</string>
<string name="allow_disappearing_messages_only_if">السماح باختفاء الرسائل فقط إذا سمحت جهة اتصالك بذلك.</string>
<string name="allow_irreversible_message_deletion_only_if">السماح بحذف الرسائل بشكل لا رجوع فيه فقط إذا سمحت لك جهة الاتصال بذلك. (24 ساعة)</string>
<string name="group_member_role_admin">المشرف</string>
<string name="group_member_role_admin">مسؤل</string>
<string name="users_add">أضِف ملف التعريف</string>
<string name="allow_direct_messages">السماح بإرسال رسائل مباشرة إلى الأعضاء.</string>
<string name="accept_contact_incognito_button">قبول التخفي</string>
<string name="button_add_welcome_message">أضِف رسالة ترحيب</string>
<string name="v4_3_improved_server_configuration_desc">أضف الخوادم عن طريق مسح رموز QR.</string>
<string name="v4_2_group_links_desc">يمكّن للمشرفين إنشاء روابط للانضمام إلى المجموعات.</string>
<string name="v4_2_group_links_desc">يمكن للمسؤولين إنشاء روابط للانضمام إلى المجموعات.</string>
<string name="accept_connection_request__question">قبول طلب الاتصال؟</string>
<string name="clear_chat_warning">سيتم حذف جميع الرسائل - لا يمكن التراجع عن هذا! سيتم حذف الرسائل فقط من أجلك.</string>
<string name="callstatus_accepted">مكالمة مقبولة</string>
@@ -65,7 +65,7 @@
<string name="allow_voice_messages_only_if">اسمح بالرسائل الصوتية فقط إذا سمحت جهة اتصالك بذلك.</string>
<string name="v5_0_app_passcode">رمز مرور التطبيق</string>
<string name="notifications_mode_service">دائِماً مُتاح</string>
<string name="notifications_mode_off_desc">يمكن للتطبيق استلام الإشعارات فقط عند تشغيله، ولن يتم بدء تشغيل أي خدمة في الخلفية</string>
<string name="notifications_mode_off_desc">يمكن للتطبيق تلقي الإشعارات فقط عند تشغيله ، ولن يتم بدء تشغيل أي خدمة في الخلفية</string>
<string name="allow_voice_messages_question">السماح بالرسائل الصوتية؟</string>
<string name="all_your_contacts_will_remain_connected">ستبقى جميع جهات الاتصال الخاصة بك متصلة.</string>
<string name="always_use_relay">استخدم التتابع دائمًا</string>
@@ -86,7 +86,7 @@
<string name="invite_prohibited">لا يمكن دعوة جهة اتصال!</string>
<string name="icon_descr_cancel_image_preview">إلغاء معاينة الصورة</string>
<string name="use_camera_button">الكاميرا</string>
<string name="icon_descr_cancel_link_preview">إلغاء معاينة الروابط</string>
<string name="icon_descr_cancel_link_preview">إلغاء معاينة الارتباط</string>
<string name="network_session_mode_user_description"><![CDATA[سيتم استخدام اتصال TCP منفصل (وبيانات اعتماد SOCKS) <b> لكل ملف تعريف دردشة لديك في التطبيق </b>.]]></string>
<string name="feature_cancelled_item">ألغيت %s</string>
<string name="one_time_link_short">رابط لمرة واحدة</string>
@@ -96,11 +96,11 @@
<string name="both_you_and_your_contact_can_add_message_reactions">يمكنك أنت وجهة اتصالك إضافة ردود فعل الرسائل.</string>
<string name="both_you_and_your_contact_can_send_disappearing">يمكنك أنت وجهة اتصالك إرسال رسائل تختفي.</string>
<string name="icon_descr_call_progress">مكالمتك تحت الإجراء</string>
<string name="cannot_receive_file">لا يمكّن استلام الملف</string>
<string name="cannot_receive_file">لا يمكن استقبال الملف</string>
<string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b> جيد للبطارية </b>. خدمة الخلفية تتحقق من الرسائل كل 10 دقائق. قد تفوتك مكالمات أو رسائل عاجلة.]]></string>
<string name="bold_text">عريض</string>
<string name="audio_call_no_encryption">مكالمات الصوت (ليست مُعمّاة بين الطرفين)</string>
<string name="onboarding_notifications_mode_off_desc"><![CDATA[<b> الأفضل للبطارية </b>. ستستلم إشعارات فقط عندما يكون التطبيق قيد التشغيل (لا توجد خدمة في الخلفية).]]></string>
<string name="onboarding_notifications_mode_off_desc"><![CDATA[<b> الأفضل للبطارية </b>. ستتلقى إشعارات فقط عندما يكون التطبيق قيد التشغيل (لا توجد خدمة في الخلفية).]]></string>
<string name="onboarding_notifications_mode_service_desc"><![CDATA[<b> تستهلك المزيد من البطارية </b>! تعمل خدمة الخلفية دائمًا - تظهر الإشعارات بمجرد توفر الرسائل.]]></string>
<string name="call_already_ended">انتهت المكالمة بالفعل!</string>
<string name="alert_title_msg_bad_hash">تجزئة رسالة سيئة</string>
@@ -244,7 +244,7 @@
<string name="chat_archive_header">أرشيف الدردشة</string>
<string name="group_member_status_intro_invitation">الاتصال (دعوة مقدمة)</string>
<string name="clear_contacts_selection_button">مسح</string>
<string name="error_creating_link_for_group">خطأ في إنشاء رابط المجموعة</string>
<string name="error_creating_link_for_group">خطأ في إنشاء ارتباط المجموعة</string>
<string name="item_info_current">(حاضِر)</string>
<string name="network_option_enable_tcp_keep_alive">تفعيل أبقِ TCP على قيد الحياة</string>
<string name="contact_connection_pending">جار الاتصال…</string>
@@ -332,7 +332,7 @@
<string name="snd_conn_event_ratchet_sync_required">مطلوب إعادة التفاوض على التعمية ل%s</string>
<string name="error_changing_message_deletion">خطأ في تغيير الإعداد</string>
<string name="error_changing_role">خطأ في تغيير الدور</string>
<string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d فشل فك تعمية الرسائل.</string>
<string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d فشل فك تشفير الرسائل.</string>
<string name="dark_theme">سمة داكنة</string>
<string name="deleted_description">حُذِفت</string>
<string name="database_passphrase_and_export">عبارة مرور قاعدة البيانات وتصديرها</string>
@@ -385,7 +385,7 @@
<string name="chat_preferences_default">الافتراضي %s</string>
<string name="delete_pending_connection__question">حذف الاتصال قيد الانتظار؟</string>
<string name="delete_chat_profile">حذف ملف تعريف الدردشة</string>
<string name="decryption_error">خطأ في فك التعمية</string>
<string name="decryption_error">خطأ في فك التشفير</string>
<string name="delete_message__question">حذف الرسالة؟</string>
<string name="developer_options">معرفات قاعدة البيانات وخيار عزل النقل.</string>
<string name="delete_address__question">حذف العنوان؟</string>
@@ -410,7 +410,7 @@
<string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 سطح المكتب: امسح رمز الاستجابة السريعة (QR) المعروض من التطبيق، عبر <b>مسح رمز QR</b>.]]></string>
<string name="delete_profile">حذف ملف التعريف</string>
<string name="smp_servers_delete_server">حذف الخادم</string>
<string name="error_updating_link_for_group">خطأ في تحديث رابط المجموعة</string>
<string name="error_updating_link_for_group">خطأ في تحديث ارتباط المجموعة</string>
<string name="simplex_link_mode_description">الوصف</string>
<string name="icon_descr_expand_role">توسيع اختيار الدور</string>
<string name="group_invitation_expired">انتهت صلاحية دعوة المجموعة</string>
@@ -507,7 +507,7 @@
<string name="conn_level_desc_indirect">غير مباشر (%1$s)</string>
<string name="how_it_works">آلية العمل</string>
<string name="incoming_video_call">مكالمة فيديو واردة</string>
<string name="if_you_received_simplex_invitation_link_you_can_open_in_browser">إذا استلمت رابط دعوة SimpleX Chat، فيمكنك فتحه في متصفحك:</string>
<string name="if_you_received_simplex_invitation_link_you_can_open_in_browser">إذا تلقيت رابط دعوة SimpleX Chat، فيمكنك فتحه في متصفحك:</string>
<string name="incognito_info_protects">يحمي وضع التخفي خصوصيتك بأستخدام ملف تعريف عشوائي جديد لكل جهة اتصال جديدة.</string>
<string name="info_menu">معلومات</string>
<string name="v4_3_improved_privacy_and_security_desc">إخفاء شاشة التطبيق في التطبيقات الحديثة.</string>
@@ -549,7 +549,7 @@
<string name="icon_descr_add_members">دعوة الأعضاء</string>
<string name="alert_text_skipped_messages_it_can_happen_when">يمكن أن يحدث عندما:
\n1. انتهت صلاحية الرسائل في العميل المرسل بعد يومين أو على الخادم بعد 30 يومًا.
\n2. فشل فك تعمية الرسالة، لأنك أو جهة اتصالك استخدمت نسخة احتياطية قديمة من قاعدة البيانات.
\n2. فشل فك تشفير الرسالة، لأنك أو جهة اتصالك استخدمت نسخة احتياطية قديمة من قاعدة البيانات.
\n3. اُخترق الاتصال.</string>
<string name="v5_1_japanese_portuguese_interface">واجهة أستخدام يابانية وبرتغالية</string>
<string name="alert_text_fragment_encryption_out_of_sync_old_database">يمكن أن يحدث ذلك عندما تستخدم أنت أو اتصالك النُسخة الاحتياطية القديمة لقاعدة البيانات.</string>
@@ -756,7 +756,7 @@
<string name="feature_offered_item_with_param">متوفرة %s: %2s</string>
<string name="notifications_will_be_hidden">سيتم تسليم الإشعارات فقط حتى يتوقف التطبيق!</string>
<string name="no_filtered_chats">لا توجد محادثات مُصفاة</string>
<string name="no_received_app_files">لا توجد ملفات مُستلمة أو مُرسلة</string>
<string name="no_received_app_files">لا توجد ملفات مستلمة أو مرسلة</string>
<string name="shutdown_alert_desc">ستتوقف الإشعارات عن العمل حتى تعيد تشغيل التطبيق</string>
<string name="new_passcode">رمز مرور جديد</string>
<string name="new_database_archive">أرشيف قاعدة بيانات جديدة</string>
@@ -764,7 +764,7 @@
<string name="network_use_onion_hosts_prefer_desc">سيتم استخدام مضيفات البصل عند توفرها.</string>
<string name="network_use_onion_hosts_no_desc">لن يتم استخدام مضيفات البصل.</string>
<string name="no_contacts_selected">لم تٌحدد جهات اتصال</string>
<string name="v4_6_group_moderation_descr">يمكّن للمشرف الآن:
<string name="v4_6_group_moderation_descr">يمكن للمسؤولين الآن:
\n- حذف رسائل الأعضاء.
\n- تعطيل الأعضاء (دور \"المراقب\")</string>
<string name="settings_notifications_mode_title">خدمة الإشعار</string>
@@ -795,7 +795,7 @@
<string name="new_passphrase">عبارة مرور جديدة…</string>
<string name="icon_descr_server_status_pending">يرجى الانتظار</string>
<string name="enter_passphrase_notification_title">كلمة المرور مطلوبة</string>
<string name="paste_the_link_you_received">ألصِق الرابط الذي استلمته</string>
<string name="paste_the_link_you_received">ألصِق الرابط الذي تلقيته</string>
<string name="only_owners_can_enable_files_and_media">فقط مالكي المجموعة يمكنهم تفعيل الملفات والوسائط.</string>
<string name="only_group_owners_can_enable_voice">فقط مالكي المجموعة يمكنهم تفعيل الرسائل الصوتية.</string>
<string name="only_stored_on_members_devices">(يخزن فقط بواسطة أعضاء المجموعة)</string>
@@ -930,7 +930,7 @@
<string name="group_welcome_preview">معاينة</string>
<string name="error_smp_test_certificate">من المحتمل أن الملف المرجعي للشهادة في عنوان الخادم غير صحيح</string>
<string name="simplex_service_notification_text">يتم استلام الرسائل…</string>
<string name="observer_cant_send_message_desc">يُرجى الاتصال بمشرف المجموعة.</string>
<string name="observer_cant_send_message_desc">يرجى الاتصال بمسؤول المجموعة.</string>
<string name="sync_connection_force_confirm">أعد التفاوض</string>
<string name="sync_connection_force_question">إعادة تفاوض التعمية</string>
<string name="revoke_file__action">سحب وصول الملف</string>
@@ -1039,7 +1039,7 @@
<string name="show_QR_code">عرض رمز QR</string>
<string name="is_verified">تم التحقق %s</string>
<string name="smp_servers_test_some_failed">فشلت بعض الخوادم في الاختبار:</string>
<string name="send_link_previews">إرسال معاينات الرابط</string>
<string name="send_link_previews">إرسال معاينات الارتباط</string>
<string name="skip_inviting_button">تخطي دعوة الأعضاء</string>
<string name="stop_chat_question">إيقاف الدردشة؟</string>
<string name="show_call_on_lock_screen">عرض</string>
@@ -1062,7 +1062,7 @@
<string name="star_on_github">اضع نجمة على GitHub</string>
<string name="stop_sharing_address">إيقاف مشاركة العنوان؟</string>
<string name="stop_sharing">إيقاف المشاركة</string>
<string name="stop_chat_to_export_import_or_delete_chat_database">أوقف الدردشة لتصدير أو استيراد أو حذف قاعدة بيانات الدردشة. لن تتمكّن من استلام الرسائل وإرسالها أثناء إيقاف الدردشة.</string>
<string name="stop_chat_to_export_import_or_delete_chat_database">أوقف الدردشة لتصدير أو استيراد أو حذف قاعدة بيانات الدردشة. لن تتمكن من تلقي الرسائل وإرسالها أثناء إيقاف الدردشة.</string>
<string name="stop_chat_to_enable_database_actions">أوقف الدردشة لتمكين إجراءات قاعدة البيانات.</string>
<string name="chat_item_ttl_seconds">%s ثانية/ثواني</string>
<string name="callstate_starting">يبدأ…</string>
@@ -1135,7 +1135,7 @@
<string name="v5_2_message_delivery_receipts_descr">فقدنا القراد الثاني! ✅</string>
<string name="whats_new_thanks_to_users_contribute_weblate">بفضل المستخدمين - المساهمة عبر Weblate!</string>
<string name="database_backup_can_be_restored">لم تكتمل محاولة تغيير عبارة مرور قاعدة البيانات.</string>
<string name="enter_passphrase_notification_desc">لاستلام الإشعارات، يُرجى إدخال عبارة مرور قاعدة البيانات</string>
<string name="enter_passphrase_notification_desc">لتلقي الإشعارات، يرجى إدخال عبارة مرور قاعدة البيانات</string>
<string name="la_lock_mode_system">مصادقة النظام</string>
<string name="sync_connection_force_desc">يعمل التعمية واتفاقية التعمية الجديدة غير مطلوبة. قد ينتج عن ذلك أخطاء في الاتصال!</string>
<string name="image_decoding_exception_desc">لا يمكن فك ترميز الصورة. من فضلك، جرب صورة مختلفة أو تواصل مع المطورين.</string>
@@ -1149,19 +1149,19 @@
<string name="alert_text_msg_bad_id">معرف الرسالة التالية غير صحيح (أقل أو يساوي السابق).
\nيمكن أن يحدث ذلك بسبب بعض العلل أو عندما يُخترق الاتصال.</string>
<string name="unfavorite_chat">إزالة من المفضلة</string>
<string name="trying_to_connect_to_server_to_receive_messages">محاولة الاتصال بالخادم المستخدم لاستلام الرسائل من جهة الاتصال هذه.</string>
<string name="trying_to_connect_to_server_to_receive_messages">محاولة الاتصال بالخادم المستخدم لتلقي الرسائل من جهة الاتصال هذه.</string>
<string name="choose_file_title">اختيار ملف</string>
<string name="icon_descr_sent_msg_status_unauthorized_send">إرسال غير مصرح به</string>
<string name="trying_to_connect_to_server_to_receive_messages_with_error">محاولة الاتصال بالخادم المستخدم لاستلام الرسائل من جهة الاتصال هذه (خطأ: %1$s).</string>
<string name="trying_to_connect_to_server_to_receive_messages_with_error">محاولة الاتصال بالخادم المستخدم لتلقي الرسائل من جهة الاتصال هذه (خطأ: %1$s).</string>
<string name="la_notice_turn_on">تشغيل</string>
<string name="webrtc_ice_servers">خوادم WebRTC ICE</string>
<string name="alert_title_cant_invite_contacts_descr">أنت تستخدم ملفًا شخصيًا متخفيًا لهذه المجموعة - لمنع مشاركة ملفك الشخصي الرئيسي الذي يدعو جهات الاتصال غير مسموح به</string>
<string name="snd_group_event_changed_member_role">غيّرتَ دور %s إلى %s</string>
<string name="chat_preferences_yes">نعم</string>
<string name="connected_to_server_to_receive_messages_from_contact">أنت متصل بالخادم المستخدم لاستلام الرسائل من جهة الاتصال هذه.</string>
<string name="connected_to_server_to_receive_messages_from_contact">أنت متصل بالخادم المستخدم لتلقي الرسائل من جهة الاتصال هذه.</string>
<string name="sender_you_pronoun">أنت</string>
<string name="description_you_shared_one_time_link">لقد شاركت رابط لمرة واحدة</string>
<string name="profile_will_be_sent_to_contact_sending_link">سيتم إرسال ملف التعريفك إلى جهة الاتصال التي استلمت منها هذا الرابط.</string>
<string name="profile_will_be_sent_to_contact_sending_link">سيتم إرسال ملف التعريفك إلى جهة الاتصال التي تلقيت منها هذا الارتباط.</string>
<string name="you_will_join_group">سوف تتصل بجميع أعضاء المجموعة.</string>
<string name="your_chat_profiles">ملفات تعريف الدردشة الخاصة بك</string>
<string name="your_simplex_contact_address">عنوان SimpleX الخاص بك</string>
@@ -1226,7 +1226,7 @@
<string name="snd_group_event_user_left">غادرت</string>
<string name="you_must_use_the_most_recent_version_of_database">يجب عليك استخدام أحدث إصدار من قاعدة بيانات الدردشة الخاصة بك على جهاز واحد فقط، وإلا فقد تتوقف عن تلقي الرسائل من بعض جهات الاتصال.</string>
<string name="video_will_be_received_when_contact_is_online">سيتم استلام الفيديو عندما تكون جهة اتصالك متصلة بالإنترنت، يرجى الانتظار أو التحقق لاحقًا!</string>
<string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[يمكنك التحكم من خلال الخادم (الخوادم) <b>لاستلام</b> الرسائل وجهات اتصالك - الخوادم التي تستخدمها لمراسلتهم.]]></string>
<string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[يمكنك التحكم من خلال الخادم (الخوادم) <b>لتلقي</b> الرسائل وجهات اتصالك - الخوادم التي تستخدمها لمراسلتهم.]]></string>
<string name="you_can_share_this_address_with_your_contacts">يمكنك مشاركة هذا العنوان مع جهات اتصالك للسماح لهم بالاتصال بـ%s.</string>
<string name="snd_group_event_member_deleted">أُزيلت %1$s</string>
<string name="update_database">تحديث</string>
@@ -1299,13 +1299,13 @@
<string name="upgrade_and_open_chat">قم بالترقية وفتح الدردشة</string>
<string name="button_welcome_message">رسالة الترحيب</string>
<string name="description_via_contact_address_link">عبر رابط عنوان الاتصال</string>
<string name="connection_error_auth_desc">ما لم يحذف جهة الاتصال الاتصال أو استُخدم هذا الرابط بالفعل، فقد يكون خطأ - الرجاء الإبلاغ عنه.
\nللاتصال، يُرجى مطالبة جهة اتصالك بإنشاء رابط اتصال آخر والتحقق من أن لديك اتصال شبكة ثابت.</string>
<string name="connection_error_auth_desc">ما لم يحذف جهة الاتصال الاتصال أو تم استخدام هذا الرابط بالفعل، فقد يكون خطأ - الرجاء الإبلاغ عنه.
\nللاتصال، يُرجى مطالبة جهة اتصالك بإنشاء ارتباط اتصال آخر والتحقق من أن لديك اتصال شبكة ثابت.</string>
<string name="your_chat_profile_will_be_sent_to_your_contact">سيتم إرسال ملف تعريف الدردشة الخاص بك
\nإلى جهة اتصالك</string>
<string name="user_unhide">إلغاء الإخفاء</string>
<string name="incognito_random_profile">ملفك الشخصي العشوائي</string>
<string name="you_will_still_receive_calls_and_ntfs">ستستمر في استلام المكالمات والإشعارات من الملفات الشخصية المكتومة عندما تكون نشطة.</string>
<string name="you_will_still_receive_calls_and_ntfs">ستستمر في تلقي المكالمات والإشعارات من الملفات الشخصية المكتومة عندما تكون نشطة.</string>
<string name="chat_preferences_you_allow">انت تسمح بها</string>
<string name="icon_descr_video_call">مكالمة فيديو</string>
<string name="voice_messages_are_prohibited">الرسائل الصوتية ممنوعة في هذه الدردشة.</string>
@@ -1348,7 +1348,7 @@
<string name="connect_use_current_profile">استخدم ملف التعريف الحالي</string>
<string name="disable_notifications_button">تعطيل الإشعارات</string>
<string name="turn_off_system_restriction_button">افتح إعدادات التطبيق</string>
<string name="system_restricted_background_desc">لا يمكن تشغيل SimpleX في الخلفية. ستستلم الإشعارات فقط عندما يكون التطبيق قيد التشغيل.</string>
<string name="system_restricted_background_desc">لا يمكن تشغيل SimpleX في الخلفية. ستتلقى الإشعارات فقط عندما يكون التطبيق قيد التشغيل.</string>
<string name="connect__a_new_random_profile_will_be_shared">سيتم مشاركة ملف تعريف عشوائي جديد.</string>
<string name="paste_the_link_you_received_to_connect_with_your_contact">ألصق الرابط المُستلَم للتواصل مع جهة اتصالك…</string>
<string name="connect__your_profile_will_be_shared">ستتم مشاركة ملفك الشخصي %1$s.</string>
@@ -1376,7 +1376,7 @@
<string name="open_database_folder">افتح مجلد قاعدة البيانات</string>
<string name="passphrase_will_be_saved_in_settings">سيتم تخزين عبارة المرور في الإعدادات كنص عادي بعد تغييرها أو إعادة تشغيل التطبيق.</string>
<string name="settings_is_storing_in_clear_text">يُخزين عبارة المرور في الإعدادات كنص عادي.</string>
<string name="socks_proxy_setting_limitations"><![CDATA[<b>يُرجى الملاحظة</b>: يتم توصيل مرحلات الرسائل والملفات عبر وكيل SOCKS. تستخدم المكالمات وإرسال معاينات الروابط الاتصال المباشر.]]></string>
<string name="socks_proxy_setting_limitations"><![CDATA[<b>يُرجى الملاحظة</b>: يتم توصيل مرحلات الرسائل والملفات عبر وكيل SOCKS. تستخدم المكالمات وإرسال معاينات الارتباط الاتصال المباشر.]]></string>
<string name="encrypt_local_files">عَمِّ الملفات المحلية</string>
<string name="v5_3_encrypt_local_files">عَمِّ الملفات والوسائط المخزنة</string>
<string name="v5_3_new_desktop_app">تطبيق سطح المكتب الجديد!</string>
@@ -1529,7 +1529,7 @@
<string name="retry_verb">حاول مجددًا</string>
<string name="camera_not_available">الكاميرا غير متوفرة</string>
<string name="enable_sending_recent_history">أرسل ما يصل إلى 100 رسالة أخيرة للأعضاء الجدد.</string>
<string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>إضافة جهة اتصال</b>: لإنشاء رابط دعوة جديد، أو الاتصال عبر رابط استلمته.]]></string>
<string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>إضافة جهة اتصال</b>: لإنشاء رابط دعوة جديد، أو الاتصال عبر رابط تلقيته.]]></string>
<string name="disable_sending_recent_history">لا ترسل التاريخ للأعضاء الجدد.</string>
<string name="or_show_this_qr_code">أو أظهر هذا الرمز</string>
<string name="recent_history_is_sent_to_new_members">يتم إرسال ما يصل إلى 100 رسالة أخيرة إلى الأعضاء الجدد.</string>
@@ -1588,6 +1588,8 @@
<string name="remote_ctrl_error_busy">سطح المكتب مشغول</string>
<string name="remote_ctrl_error_bad_version">يحتوي سطح المكتب على إصدار غير مدعوم. يُرجى التأكد من استخدام نفس الإصدار على كلا الجهازين</string>
<string name="past_member_vName">العضو السابق %1$s</string>
<string name="possible_deadlock_title">مأزق</string>
<string name="possible_deadlock_desc">يستغرق تنفيذ التعليمات البرمجية وقتًا طويلاً جدًا: %1$d ثانية. من المحتمل أن التطبيق مجمّد: %2$s</string>
<string name="possible_slow_function_title">وظيفة بطيئة</string>
<string name="developer_options_section">خيارات المطور</string>
<string name="profile_update_event_member_name_changed">تغيّر العضو %1$s إلى %2$s</string>
@@ -1615,17 +1617,4 @@
<string name="clear_note_folder_question">مسح الملاحظات الخاصة؟</string>
<string name="share_text_created_at">أُنشئ في: %s</string>
<string name="saved_message_title">رسالة محفوظة</string>
<string name="unblock_for_all_question">إلغاء حظر العضو للجميع؟</string>
<string name="unblock_for_all">إلغاء الحظر للجميع</string>
<string name="error_blocking_member_for_all">حدث خطأ أثناء حظر العضو للجميع</string>
<string name="blocked_by_admin_items_description">حُظر %d رسالة من قبل المشرف</string>
<string name="rcv_group_event_member_blocked">محظور %s</string>
<string name="rcv_group_event_member_unblocked">أُلغيت حظر %s</string>
<string name="snd_group_event_member_blocked">حظرت %s</string>
<string name="snd_group_event_member_unblocked">أُلغيت حظر %s</string>
<string name="member_info_member_blocked">محظور</string>
<string name="block_for_all">حظر للجميع</string>
<string name="block_for_all_question">حظر العضو للجميع؟</string>
<string name="blocked_by_admin_item_description">محظور من قبل المشرف</string>
<string name="member_blocked_by_admin">محظور من قبل المشرف</string>
</resources>

View File

@@ -16,7 +16,6 @@
<!-- MainActivity.kt -->
<string name="opening_database">Opening database…</string>
<string name="database_migration_in_progress">Database migration is in progress.\nIt may take a few minutes.</string>
<string name="non_content_uri_alert_title">Invalid file path</string>
<string name="non_content_uri_alert_text">You shared an invalid file path. Report the issue to the app developers.</string>
<string name="app_was_crashed">View crashed</string>
@@ -147,6 +146,8 @@
<string name="smp_server_test_delete_file">Delete file</string>
<string name="error_deleting_user">Error deleting user profile</string>
<string name="error_updating_user_privacy">Error updating user privacy</string>
<string name="possible_deadlock_title">Deadlock</string>
<string name="possible_deadlock_desc">Execution of code takes too long time: %1$d seconds. Probably, the app is frozen: %2$s</string>
<string name="possible_slow_function_title">Slow function</string>
<string name="possible_slow_function_desc">Execution of function takes too long time: %1$d seconds: %2$s</string>
@@ -1376,11 +1377,9 @@
<!-- GroupWelcomeView.kt -->
<string name="group_welcome_title">Welcome message</string>
<string name="save_welcome_message_question">Save welcome message?</string>
<string name="welcome_message_is_too_long">Welcome message is too long</string>
<string name="save_and_update_group_profile">Save and update group profile</string>
<string name="group_welcome_preview">Preview</string>
<string name="enter_welcome_message">Enter welcome message…</string>
<string name="message_too_large">Message too large</string>
<!-- ConnectionStats -->
<string name="conn_stats_section_title_servers">SERVERS</string>

View File

@@ -1555,6 +1555,7 @@
<string name="chat_is_stopped_you_should_transfer_database">Чатът е спрян. Ако вече сте използвали тази база данни на друго устройство, трябва да я прехвърлите обратно, преди да стартирате чата отново.</string>
<string name="remote_ctrl_error_bad_invitation">Настолното устройство има грешен код за връзка</string>
<string name="remote_ctrl_error_bad_version">Настолното устройство е с неподдържана версия. Моля, уверете се, че използвате една и съща версия и на двете устройства</string>
<string name="possible_deadlock_desc">Изпълнението на кода отнема твърде много време: %1$d секунди. Вероятно приложението е замразено: %2$s</string>
<string name="possible_slow_function_title">Бавна функция</string>
<string name="possible_slow_function_desc">Изпълнението на функцията отнема твърде много време: %1$d секунди: %2$s</string>
<string name="show_internal_errors">Покажи вътрешните грешки</string>
@@ -1590,4 +1591,5 @@
\nПрепоръчително е да рестартирате приложението.</string>
<string name="developer_options_section">Опции за разработчици</string>
<string name="show_slow_api_calls">Показване на бавни API заявки</string>
<string name="possible_deadlock_title">Грешка в заключено положение</string>
</resources>

View File

@@ -3,8 +3,8 @@
<string name="app_name">SimpleX</string>
<string name="thousand_abbreviation">k</string>
<!-- Connect via Link - MainActivity.kt -->
<string name="connect_via_contact_link">Über den Kontaktadressen-Link verbinden?</string>
<string name="connect_via_invitation_link">Über den Einmal-Einladungslink verbinden?</string>
<string name="connect_via_contact_link">Über die Kontakt-Adresse verbinden?</string>
<string name="connect_via_invitation_link">Über den Einmal-Link verbinden?</string>
<string name="connect_via_group_link">Der Gruppe beitreten?</string>
<string name="profile_will_be_sent_to_contact_sending_link">Ihr Profil wird an den Kontakt gesendet, von dem Sie diesen Link erhalten haben.</string>
<string name="you_will_join_group">Sie werden mit allen Gruppenmitgliedern verbunden.</string>
@@ -39,7 +39,7 @@
<string name="description_via_one_time_link_incognito">Inkognito über einen Einmal-Link</string>
<!-- FormattedText, SimpleX links - ChatModel.kt -->
<string name="simplex_link_contact">SimpleX-Kontaktadressen-Link</string>
<string name="simplex_link_invitation">SimpleX-Einmal-Einladungslink</string>
<string name="simplex_link_invitation">SimpleX-Einmal-Einladung</string>
<string name="simplex_link_group">SimpleX-Gruppen-Link</string>
<string name="simplex_link_connection">über %1$s</string>
<string name="simplex_link_mode">SimpleX-Links</string>
@@ -331,7 +331,7 @@
<string name="your_chat_profile_will_be_sent_to_your_contact">Ihr Chat-Profil wird
\nan Ihren Kontakt gesendet</string>
<string name="if_you_cannot_meet_in_person_scan_QR_in_video_call_or_ask_for_invitation_link"><![CDATA[Wenn Sie sich nicht persönlich treffen können, können Sie <b>den QR-Code während eines Videoanrufs scannen</b> oder Ihr Kontakt kann einen Einladungslink über einen anderen Kanal mit Ihnen teilen.]]></string>
<string name="share_invitation_link">Einmal-Einladungslink teilen</string>
<string name="share_invitation_link">Einmal-Link teilen</string>
<!-- PasteToConnect.kt -->
<string name="connect_via_link">Über einen Link verbinden</string>
<string name="connect_button">Verbinden</string>
@@ -1512,7 +1512,7 @@
<string name="remove_member_button">Mitglied entfernen</string>
<string name="block_member_confirmation">Blockieren</string>
<string name="unblock_member_question">Mitglied freigeben?</string>
<string name="blocked_items_description">%d Nachrichten wurden blockiert</string>
<string name="blocked_items_description">%d Nachrichten blockiert</string>
<string name="block_member_button">Mitglied blockieren</string>
<string name="connect_plan_repeat_join_request">Verbindungsanfrage wiederholen?</string>
<string name="button_remove_member_question">Mitglied entfernen?</string>
@@ -1530,8 +1530,8 @@
<string name="non_content_uri_alert_title">Ungültiger Datei-Pfad</string>
<string name="connect_plan_you_have_already_requested_connection_via_this_address">Sie haben über diese Adresse bereits eine Verbindung beantragt!</string>
<string name="terminal_always_visible">Die Konsole in einem neuen Fenster anzeigen</string>
<string name="block_member_desc">Von %s werden alle neuen Nachrichten ausgeblendet!</string>
<string name="blocked_item_description">Blockiert</string>
<string name="block_member_desc">Alle neuen Nachrichten von %s werden ausgeblendet!</string>
<string name="blocked_item_description">blockiert</string>
<string name="encryption_renegotiation_error">Fehler bei der Neuverhandlung der Verschlüsselung</string>
<string name="alert_text_encryption_renegotiation_failed">Neuverhandlung der Verschlüsselung fehlgeschlagen</string>
<string name="v5_4_block_group_members">Gruppenmitglieder blockieren</string>
@@ -1672,43 +1672,8 @@
<string name="possible_slow_function_title">Langsame Funktion</string>
<string name="show_slow_api_calls">Zeige langsame API-Aufrufe an</string>
<string name="group_member_status_unknown_short">unbekannt</string>
<string name="possible_deadlock_title">Blockade</string>
<string name="developer_options_section">Optionen für Entwickler</string>
<string name="possible_deadlock_desc">Die Code-Ausführung dauert zu lange: %1$d Sekunden. Wahrscheinlich ist die App eingefroren: %2$s</string>
<string name="group_member_status_unknown">unbekannter Gruppenmitglieds-Status</string>
<string name="v5_5_private_notes_descr">Mit verschlüsselten Dateien und Medien.</string>
<string name="v5_5_private_notes">Private Notizen</string>
<string name="clear_note_folder_warning">Es werden alle Nachrichten gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden!</string>
<string name="clear_note_folder_question">Private Notizen löschen?</string>
<string name="rcv_group_event_member_blocked">%s wurde blockiert</string>
<string name="rcv_group_event_member_unblocked">%s wurde freigegeben</string>
<string name="snd_group_event_member_blocked">Sie haben %s blockiert</string>
<string name="snd_group_event_member_unblocked">Sie haben %s freigegeben</string>
<string name="block_for_all_question">Mitglied für Alle blockieren?</string>
<string name="saved_message_title">Gespeicherte Nachricht</string>
<string name="v5_5_simpler_connect_ui">Zum Verbinden den Link einfügen!</string>
<string name="v5_5_message_delivery_descr">Mit reduziertem Akkuverbrauch.</string>
<string name="v5_5_join_group_conversation_descr">Aktueller Nachrichtenverlauf und verbesserter Gruppenverzeichnis-Bot.</string>
<string name="v5_5_simpler_connect_ui_descr">Von der Suchleiste werden Einladungslinks akzeptiert.</string>
<string name="unblock_for_all">Für Alle freigeben</string>
<string name="unblock_for_all_question">Mitglied für Alle freigeben?</string>
<string name="member_info_member_blocked">wurde blockiert</string>
<string name="blocked_by_admin_item_description">ist vom Administrator blockiert worden</string>
<string name="member_blocked_by_admin">wurde vom Administrator blockiert</string>
<string name="block_for_all">Für Alle blockiert</string>
<string name="info_row_created_at">Erstellt um</string>
<string name="share_text_created_at">Erstellt um: %s</string>
<string name="blocked_by_admin_items_description">%d Nachrichten wurden vom Administrator blockiert</string>
<string name="error_blocking_member_for_all">Fehler beim Blockieren des Mitglieds für Alle</string>
<string name="error_creating_message">Fehler beim Erstellen der Nachricht</string>
<string name="error_deleting_note_folder">Fehler beim Löschen der privaten Notizen</string>
<string name="v5_5_message_delivery">Verbesserte Zustellung von Nachrichten</string>
<string name="v5_5_join_group_conversation">Gruppenunterhaltungen beitreten</string>
<string name="v5_5_new_interface_languages">Ungarische und türkische Bedienoberfläche</string>
<string name="profile_update_event_contact_name_changed">Kontaktname %1$s wurde auf %2$s geändert</string>
<string name="profile_update_event_member_name_changed">Mitgliedsname %1$s wurde auf %2$s geändert</string>
<string name="profile_update_event_set_new_address">Neue Kontaktadresse wurde festgelegt</string>
<string name="profile_update_event_set_new_picture">Neues Profil-Bild wurde festgelegt</string>
<string name="profile_update_event_updated_profile">Das Profil wurde aktualisiert</string>
<string name="profile_update_event_removed_picture">Profil-Bild wurde entfernt</string>
<string name="profile_update_event_removed_address">Kontaktadresse wurde entfernt</string>
<string name="note_folder_local_display_name">Private Notizen</string>
</resources>

View File

@@ -82,35 +82,4 @@
<string name="simplex_link_invitation">دعوت یک بار مصرف SimpleX</string>
<string name="display_name_connecting">در حال اتصال…</string>
<string name="simplex_link_mode_browser_warning">باز کردن لینک در مرورگر ممکن است حریم خصوصی و امنیت اتصال را کاهش دهد. لینک‌های SimpleX ناموثق قرمز خواهند بود.</string>
<string name="error_loading_xftp_servers">خطا در بارگیری سرورهای XFTP</string>
<string name="failed_to_create_user_title">خطا در ایجاد نمایه!</string>
<string name="failed_to_active_user_title">خطا در تعویض نمایه!</string>
<string name="connection_timeout">توقف اتصال</string>
<string name="connection_error">خطا در اتصال</string>
<string name="error_sending_message">خطا در ارسال پیام</string>
<string name="error_creating_message">خطا در ایجاد پیام</string>
<string name="error_loading_details">خطا در بارگیری جزئیات</string>
<string name="error_joining_group">خطا در پیوستن به گروه</string>
<string name="sender_cancelled_file_transfer">فرستنده انتقال پرونده را لغو کرد.</string>
<string name="you_are_already_connected_to_vName_via_this_link">شما از قبل به %1$s متصل هستید.</string>
<string name="connection_error_auth">خطا در اتصال (تصدیق)</string>
<string name="error_loading_smp_servers">خطا در بارگیری سرورهای SMP</string>
<string name="failed_to_parse_chats_title">عدم موفقیت در بارگیری گپ‌ها</string>
<string name="contact_developers">لطفا برنامه را به‌روزرسانی کنید و با توسعه‌دهندگان تماس بگیرید.</string>
<string name="failed_to_create_user_duplicate_title">نام نمایشی همسان!</string>
<string name="failed_to_create_user_invalid_desc">نام نمایشی نامعتبر است. لطفا نام دیگری انتخاب کنید.</string>
<string name="error_adding_members">خطا در افزودن اعضا</string>
<string name="cannot_receive_file">امکان دریافت پرونده وجود ندارد</string>
<string name="network_error_desc">لطفا اتصال خود را با %1$s بررسی کنید و دوباره امتحان کنید.</string>
<string name="error_receiving_file">خطا در دریافت پرونده</string>
<string name="contact_already_exists">مخاطب از قبل وجود دارد</string>
<string name="invalid_connection_link">لینک اتصال نامعتبر</string>
<string name="please_check_correct_link_and_maybe_ask_for_a_new_one">لطفا بررسی کنید که از لینک صحیح استفاده کردید یا از مخاطبتان بخواهید لینک دیگری برایتان بفرستد.</string>
<string name="ensure_smp_server_address_are_correct_format_and_unique">مطمئن شوید قالب آدرس‌های سرور SMP صحیح است، در خط‌های جدا نوشته شده و تکرار نشده‌اند.</string>
<string name="error_setting_network_config">خطا در به‌روزرسانی پیکربندی شبکه</string>
<string name="failed_to_parse_chat_title">عدم موفقیت در بارگیری گپ</string>
<string name="failed_to_create_user_invalid_title">نام نمایشی نامعتبر!</string>
<string name="failed_to_create_user_duplicate_desc">شما یک نمایه گپ با نام نمایشی یکسان دارید، لطفا نام دیگری انتخاب کنید.</string>
<string name="error_creating_address">خطا در ایجاد نشانی</string>
<string name="ensure_xftp_server_address_are_correct_format_and_unique">مطمئن شوید قالب آدرس‌های سرور XFTP صحیح است، در خط‌های جدا نوشته شده و تکرار نشده‌اند.</string>
</resources>

View File

@@ -1559,9 +1559,11 @@
<string name="remote_host_error_bad_state"><![CDATA[État médiocre de la connexion au mobile <b>%s</b>.]]></string>
<string name="remote_ctrl_was_disconnected_title">Connexion interrompue</string>
<string name="remote_ctrl_error_bad_state">État médiocre de la connexion avec le bureau</string>
<string name="possible_deadlock_title">Impasse</string>
<string name="remote_ctrl_error_bad_version">La version de l\'ordinateur de bureau n\'est pas prise en charge. Veillez à utiliser la même version sur les deux appareils.</string>
<string name="remote_ctrl_error_disconnected">Le bureau a été déconnecté</string>
<string name="developer_options_section">Options pour les développeurs</string>
<string name="possible_deadlock_desc">Le code prend trop de temps à s\'exécuter: %1$d secondes. Il est probable que l\'application soit figée: %2$s</string>
<string name="agent_internal_error_title">Erreur interne</string>
<string name="remote_host_error_bad_version"><![CDATA[La version du mobile <b>%s</b> n\'est pas prise en charge. Veillez à utiliser la même version sur les deux appareils.]]></string>
<string name="show_internal_errors">Afficher les erreurs internes</string>

View File

@@ -37,7 +37,7 @@
<string name="empty_chat_profile_is_created">Egy üres chat profil létre lett hozva a megadott névvel és az app normál módon megnyílik.</string>
<string name="feature_cancelled_item">megszakítva %s</string>
<string name="smp_servers_preset_add">Adj hozzá egyedi szervereket</string>
<string name="calls_prohibited_with_this_contact">A hang- és videóhívások le vannak tiltva.</string>
<string name="calls_prohibited_with_this_contact">Hang-/videóhívások megtiltva.</string>
<string name="network_session_mode_entity_description">Külön TCP kapcsolat (és SOCKS bejelentkezési adatok) lesznek használva <b>minden ismerősre és csoport tagra</b>
\n<b>Tudnivaló</b>: ha sok ismerősöd van, az akkumulátor- és adat használatod jelentősen megnőhet és néhány kapcsolódási kísérlet sikertelen lehet.</string>
<string name="icon_descr_cancel_link_preview">URL link előnézet megszakítása</string>
@@ -65,7 +65,7 @@
<string name="cannot_receive_file">Nem tud fájlt fogadni</string>
<string name="auth_unavailable">Hitelesítés elérhetetlen</string>
<string name="app_version_title">Alkalmazás verzió</string>
<string name="button_add_welcome_message">Üdvözlő üzenet hozzáadása</string>
<string name="button_add_welcome_message">Üdvözlőszöveg hozzáadása</string>
<string name="snd_conn_event_ratchet_sync_started">a(z) %s titkosításának elfogadása…</string>
<string name="available_in_v51">"
\nElérhető a v5.1-ben"</string>
@@ -83,14 +83,14 @@
<string name="both_you_and_your_contact_can_send_voice">Mindketten, te is és az ismerősöd is küldhet hangüzeneteket.</string>
<string name="alert_title_msg_bad_id">Téves üzenet ID</string>
<string name="allow_your_contacts_adding_message_reactions">Ismerőseid küldhetnek reakciókat az üzenetekre.</string>
<string name="allow_to_send_voice">Hangüzenetek küldése engedélyezve.</string>
<string name="allow_to_send_voice">Hangüzenetek küldésének engedélyezése.</string>
<string name="allow_message_reactions_only_if">Üzenet reakciók engedélyezése kizárólag abban az esetben, ha a másik fél is engedélyezi.</string>
<string name="back">Vissza</string>
<string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b>Kikapcsolható a beállításokban</b> az értesítések továbbra is megjelenítésre kerülnek amíg az alkalmazás fut.]]></string>
<string name="v4_2_group_links_desc">Az adminok létrehozhatnak linkeket a csoporthoz való csatlakozáshoz.</string>
<string name="call_on_lock_screen">Hívások a lezárási képernyőn:</string>
<string name="conn_event_ratchet_sync_started">titkosítás elfogadása…</string>
<string name="invite_prohibited">Az ismerősök meghívása le van tiltva!</string>
<string name="invite_prohibited">Ismerős meghívása tiltott!</string>
<string name="integrity_msg_bad_id">téves üzenet ID</string>
<string name="v4_2_auto_accept_contact_requests">Ismerősnek jelölések automatikus elfogadása</string>
<string name="impossible_to_recover_passphrase"><![CDATA[<b>Tudnivaló</b>: NEM fogod tudni helyreállítani vagy megváltoztatni a jelmondatot az esetben ha elveszíted.]]></string>
@@ -109,13 +109,13 @@
<string name="block_member_button">Tag blokkolása</string>
<string name="v5_2_more_things">Néhány további dolog</string>
<string name="authentication_cancelled">Hitelesítés megszakítva</string>
<string name="allow_to_send_files">A fájlok- és a médiatartalom küldése engedélyezve.</string>
<string name="allow_to_send_files">Fájlok és fotók/videók küldésének engedélyezése.</string>
<string name="users_delete_all_chats_deleted">Minden beszélgetés, illetve az összes üzenet törlésre kerül - ezt nem lehet visszavonni!</string>
<string name="icon_descr_audio_call">hanghívás</string>
<string name="bold_text">félkövér</string>
<string name="app_passcode_replaced_with_self_destruct">Az alkalmazás jelkód helyettesítésre kerül egy önmegsemmisítő jelkóddal.</string>
<string name="v5_3_new_interface_languages_descr">Arab, bulgár, finn, héber, thai és ukrán - köszönet a felhasználóknak és a Weblate-nek!</string>
<string name="allow_voice_messages_question">Engedélyezed a hangüzenetek küldését?</string>
<string name="allow_voice_messages_question">Hangüzenetek engedélyezése?</string>
<string name="always_use_relay">Mindig használjon relay szervert</string>
<string name="chat_preferences_always">mindig</string>
<string name="call_already_ended">A hívás már befejeződött!</string>
@@ -135,7 +135,7 @@
<string name="callstatus_ended">a(z) %1$s hívás befejeződött</string>
<string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b>Jó akkumulátoridő</b>. A háttérszolgáltatás ellenőrzi az új üzeneteket 10 percenként. Hívásokról és fontos üzenetekről maradhatsz le.]]></string>
<string name="group_member_role_author">szerző</string>
<string name="allow_your_contacts_irreversibly_delete">Engedélyezed az ismerőseidnek, hogy visszafordíthatatlanul törölhessék az elküldött üzeneteket. (24 óra)</string>
<string name="allow_your_contacts_irreversibly_delete">Ismerőseid véglegesen törölhetnek elküldött üzeneteket engedélyezése. (24 óra)</string>
<string name="cancel_verb">Megszakítás</string>
<string name="notifications_mode_off_desc">Az alkalmazás csak akkor tud értesítéseket fogadni amikor fut, a héttérszolgáltatás nem kerül elindításra.</string>
<string name="v5_1_better_messages">Jobb üzenetek</string>
@@ -149,14 +149,14 @@
<string name="use_camera_button">Fényképező</string>
<string name="cannot_access_keychain">A Keystore-hoz nem sikerül hozzáférni az adatbázis jelszó elmentése végett</string>
<string name="callstatus_in_progress">hívás folyamatban</string>
<string name="auto_accept_images">Fotók automatikus elfogadása</string>
<string name="auto_accept_images">Fényképek automatikus elfogadása</string>
<string name="allow_your_contacts_to_call">Hang- és videóhívás engedélyezése az ismerőseid számára.</string>
<string name="settings_section_title_icon">ALKALMAZÁS IKON</string>
<string name="v4_3_improved_server_configuration_desc">Szerver hozzáadása QR kód befotózásával.</string>
<string name="allow_to_send_disappearing">Eltűnő üzenetek küldése engedélyezve.</string>
<string name="allow_to_send_disappearing">Eltünő üzenetek küldésének engedélyezése.</string>
<string name="allow_disappearing_messages_only_if">Eltűnő üzenetek engedélyezése kizárólag abban az esetben, ha a másik fél is engedélyezi.</string>
<string name="icon_descr_audio_off">Hang kikapcsolva</string>
<string name="allow_direct_messages">A közvetlen üzenetküldés csak a tagok számára engedélyezett.</string>
<string name="allow_direct_messages">A közvetlen üzenetküldés csak tagok számára engedélyezett.</string>
<string name="settings_section_title_app">Alkalmazás</string>
<string name="icon_descr_call_progress">Hívás folyamatban</string>
<string name="both_you_and_your_contact_can_add_message_reactions">Mindketten, te is és az ismerősöd is használhat üzenet reakciókat (emojik).</string>
@@ -216,7 +216,7 @@
<string name="connect_plan_connect_to_yourself">Kapcsolódás saját magához?</string>
<string name="copied">Kimásolva a vágólapra</string>
<string name="connection_request_sent">Kapcsolódási kérés elküldve!</string>
<string name="connecting_to_desktop">Kapcsolódás az asztali klienshez</string>
<string name="connecting_to_desktop">Kapcsolódás az asztalhoz</string>
<string name="network_session_mode_entity">Kapcsolat</string>
<string name="correct_name_to">Név helyesbítése erre: %s?</string>
<string name="connection_timeout">Kapcsolat időtúllépés</string>
@@ -227,9 +227,9 @@
<string name="desktop_connection_terminated">Kapcsolat megszakítva</string>
<string name="display_name_connection_established">Kapcsolat létrehozva</string>
<string name="status_contact_has_no_e2e_encryption">az ismerősnél az e2e titkosítás nem elérhető</string>
<string name="chat_preferences_contact_allows">Ez az ismerősöd engedélyezi</string>
<string name="chat_preferences_contact_allows">Az ismerős engedélyezi</string>
<string name="notification_preview_somebody">Ismerős elrejtve:</string>
<string name="connect_to_desktop">Kapcsolódás az asztali klienshez</string>
<string name="connect_to_desktop">Kapcsolódás az asztalhoz</string>
<string name="icon_descr_context">Kontextus ikon</string>
<string name="connect_via_link">Kapcsolódás egy linken keresztül</string>
<string name="receipts_section_contacts">Ismerősök</string>
@@ -260,7 +260,7 @@
<string name="theme_dark">Sötét</string>
<string name="create_profile">Profil létrehozása</string>
<string name="rcv_group_event_group_deleted">törölt csoport</string>
<string name="full_deletion">Törlés mindenkinél</string>
<string name="full_deletion">Törlés mindenkinek</string>
<string name="button_create_group_link">Link létrehozása</string>
<string name="chat_preferences">Chat beállítások</string>
<string name="chat_archive_header">Chat archívum</string>
@@ -304,7 +304,7 @@
<string name="snd_conn_event_switch_queue_phase_changing">azonosító megváltoztatása…</string>
<string name="display_name_connecting">kapcsolódás…</string>
<string name="icon_descr_call_connecting">Hívás kapcsolása</string>
<string name="delete_files_and_media_question">Biztosan törlöd a fájlokat és a médiatartalmakat?</string>
<string name="delete_files_and_media_question">Fájlok illetve fotók/videók törlése?</string>
<string name="group_member_status_complete">befejezett</string>
<string name="chat_database_section">CHAT ADATBÁZIS</string>
<string name="change_self_destruct_passcode">Önmegsemmisító jelkód megváltoztatása</string>
@@ -363,10 +363,10 @@
<string name="smp_servers_delete_server">Szerver törlése</string>
<string name="auth_device_authentication_is_disabled_turning_off">Eszközhitelesítés kikapcsolva. SimpleX zár kikapcsolása.</string>
<string name="no_call_on_lock_screen">Letiltás</string>
<string name="receipts_groups_disable_for_all">Letiltás minden csoport számára</string>
<string name="receipts_groups_enable_for_all">Minden csoportnak engedélyezve</string>
<string name="receipts_groups_disable_for_all">Letiltás minden csoportnak</string>
<string name="receipts_groups_enable_for_all">Engedélyezve minden csoportnak</string>
<string name="feature_enabled_for_contact">engedélyezve az ismerősnek</string>
<string name="disappearing_messages_are_prohibited">Az eltűnő üzenetek küldése le van tiltva ebben a csoportban.</string>
<string name="disappearing_messages_are_prohibited">Eltűnő üzenetek tiltottak ebben a csoportban.</string>
<string name="delete_address">Azonosító törlése</string>
<string name="ttl_week">%d hét</string>
<string name="desktop_address">Számítógép azonosítója</string>
@@ -380,11 +380,11 @@
<string name="ttl_hours">%d óra</string>
<string name="ttl_months">%d hónap</string>
<string name="delete_address__question">Azonosító törlése?</string>
<string name="receipts_contacts_title_disable">Letiltod az üzenet kézbesítési jelentéseket?</string>
<string name="receipts_contacts_title_disable">Igazolások letiltása?</string>
<string name="passphrase_is_different">Az adatbázis jelmondat eltérő a Keystore-ba elmentettől.</string>
<string name="direct_messages">Közvetlen üzenetek</string>
<string name="icon_descr_email">E-mail</string>
<string name="receipts_contacts_disable_for_all">Letiltás mindenki számára</string>
<string name="receipts_contacts_disable_for_all">Letiltás mindenkinek</string>
<string name="settings_developer_tools">Fejlesztői eszközök</string>
<string name="database_passphrase">Adatbázis jelmondat</string>
<string name="ttl_days">%d napok</string>
@@ -411,7 +411,7 @@
<string name="direct_messages_are_prohibited_in_chat">A közvetlen üzenetek tagok között titltottak ebben a csoportban.</string>
<string name="ttl_min">%d perc</string>
<string name="set_password_to_export_desc">Az adatbázis egy véletlenszerű jelmondattal van titkosítva. Kérlek cseréld le exportálás előtt!</string>
<string name="receipts_groups_title_disable">Letiltod az üzenet kézbesítés jelentéseket a csoportok számára?</string>
<string name="receipts_groups_title_disable">Igazolások letiltása csoportoknak?</string>
<string name="custom_time_unit_days">nap</string>
<string name="ttl_day">%d nap</string>
<string name="delete_chat_archive_question">Chat archív törlése?</string>
@@ -431,7 +431,7 @@
<string name="database_will_be_encrypted">Az adatbázis titkosításra kerül.</string>
<string name="database_passphrase_and_export">Adatbázis jelmondat és exportálás</string>
<string name="database_will_be_encrypted_and_passphrase_stored">Az adatbázis titkosításra kerül és a jelmondat eltárolásra a Keystore-ban.</string>
<string name="enable_automatic_deletion_question">Engedélyezed az automatikus üzenet törlést?</string>
<string name="enable_automatic_deletion_question">Automatikus üzenet törlés engedélyezve?</string>
<string name="delete_contact_menu_action">Törlés</string>
<string name="mtr_error_no_down_migration">az adatbázis verzió újabb, mint az alkalmazás, de nincs lefelé migráció eddig: %s</string>
<string name="simplex_link_mode_description">Leírás</string>
@@ -448,12 +448,12 @@
<string name="decentralized">Decentralizált</string>
<string name="image_decoding_exception_title">Dekódolási hiba</string>
<string name="edit_image">Kép szerkesztése</string>
<string name="disable_notifications_button">Értesítések letiltása</string>
<string name="disable_notifications_button">Értesítéásek letiltása</string>
<string name="devices">Eszközök</string>
<string name="multicast_discoverable_via_local_network">Látható helyi hálózaton</string>
<string name="dont_enable_receipts">Ne engedélyezd</string>
<string name="delete_archive">Archívum törlése</string>
<string name="disappearing_prohibited_in_this_chat">Az eltűnő üzenetek le vannak tiltva ebben a csevegésben.</string>
<string name="disappearing_prohibited_in_this_chat">Eltűnő üzenetek tiltottak ebben a chatben.</string>
<string name="chat_preferences_default">alap (%s)</string>
<string name="integrity_msg_duplicate">duplikálódott üzenet</string>
<string name="disconnect_desktop_question">Számítógép leválasztása?</string>
@@ -462,7 +462,7 @@
<string name="total_files_count_and_size">%d fájl %s összméretben</string>
<string name="database_passphrase_is_required">Adatbázis jelmondat szükséges chat megnyitásához.</string>
<string name="ttl_d">%dnap</string>
<string name="receipts_contacts_enable_for_all">Mindenki számára engedélyezve</string>
<string name="receipts_contacts_enable_for_all">Engedélyeve mindenki számára</string>
<string name="delivery_receipts_are_disabled">Kézbesítési izagolások kikapcsolva!</string>
<string name="expand_verb">Lenyit</string>
<string name="error_sending_message">Hiba az üzenet küldésekor</string>
@@ -472,7 +472,7 @@
<string name="error_encrypting_database">Hiba az adatbázis titkosításakor</string>
<string name="error_deleting_group">Hiba a csoport törlésekor</string>
<string name="exit_without_saving">Kilépés mentés nélkül</string>
<string name="v5_3_encrypt_local_files">Tárolt fájlok és médiatartalmak titkosítása</string>
<string name="v5_3_encrypt_local_files">Tárolt fájlok, képek és videók titkosítása</string>
<string name="error_setting_address">Hiba az azonosító beállításakor</string>
<string name="group_invitation_expired">A csoport meghívó lejárt</string>
<string name="error_saving_ICE_servers">Hiba az ICE szerverek elmentésekor</string>
@@ -487,7 +487,7 @@
\nCsatlakozz hozzám SimpleX Chaten: %s</string>
<string name="display_name_cannot_contain_whitespace">A megjelenített név nem tartalmazhat szóközöket.</string>
<string name="info_row_group">Csoport</string>
<string name="enter_welcome_message_optional">Írd be az üdvözlő üzenetet… (opcionális)</string>
<string name="enter_welcome_message_optional">Add meg az üdvözlőszöveget… (opcionális)</string>
<string name="error_exporting_chat_database">Hiba a chat adatbázis exportálásakor</string>
<string name="error_saving_file">Hiba a fájl elmentésekor</string>
<string name="encrypt_local_files">Helyi fájlok titkosítása</string>
@@ -523,9 +523,9 @@
<string name="enter_correct_passphrase">Helyes jelmondat bevitele.</string>
<string name="delete_group_for_self_cannot_undo_warning">A csoport törlésre kerül számodra -ez visszafordíthatatlan!</string>
<string name="encrypt_database_question">Adatbázis titkosítása?</string>
<string name="allow_accepting_calls_from_lock_screen">A zárolási képernyőn megjelenő hívások engedélyezése a Beállításokban.</string>
<string name="allow_accepting_calls_from_lock_screen">Lezárási képernyőn a hívások engedélyezése a beállításokban.</string>
<string name="conn_event_ratchet_sync_agreed">titkosítás egyeztetve</string>
<string name="receipts_contacts_title_enable">Engedélyezed az üzenet kézbesítési jelentéseket?</string>
<string name="receipts_contacts_title_enable">Kézbesítési igazolások engedélyezése?</string>
<string name="error_saving_group_profile">Hiba a csoport profil elmentésekor</string>
<string name="server_error">hiba</string>
<string name="revoke_file__message">A fájl törölve lesz a szerverekről.</string>
@@ -544,7 +544,7 @@
<string name="alert_text_encryption_renegotiation_failed">Titkosítás újra egyeztetés sikertelen.</string>
<string name="error_deleting_user">Hiba a felhasználói profil törlésekor</string>
<string name="fix_connection_not_supported_by_group_member">A javítás nem támogatott a csoporttag által</string>
<string name="enter_welcome_message">Írd be az üdvözlő üzenetet…</string>
<string name="enter_welcome_message">Add meg az üdvözlőszöveget…</string>
<string name="encrypted_database">Titkosított adatbázis</string>
<string name="enter_password_to_show">Add meg a jelszót a keresőben</string>
<string name="file_will_be_received_when_contact_completes_uploading">A fájl megérkezik amint az ismerősöd befejezi a feltöltését.</string>
@@ -559,12 +559,12 @@
<string name="group_members_can_delete">A csoporttagok visszafordíthatatlanul törölhetnek elküldött üzeneteket. (24 óra)</string>
<string name="error_changing_role">Hiba a szerepkör megváltoztatásakor</string>
<string name="fix_connection_confirm">Javítás</string>
<string name="group_members_can_send_disappearing">A csoporttagok küldhetnek eltűnő üzeneteket.</string>
<string name="group_members_can_send_disappearing">A csoporttagok küldhetnek eltünő üzeneteket.</string>
<string name="fix_connection">Kapcsolat javítása</string>
<string name="failed_to_create_user_title">Hiba a profil létrehozásakor!</string>
<string name="error_adding_members">Hiba a tag(-ok) hozzáadásakor</string>
<string name="icon_descr_file">Fájl</string>
<string name="group_members_can_send_files">A csoporttagok küldhetnek fájlokat és médiatartalmakat.</string>
<string name="group_members_can_send_files">A csoporttagok küldhetbnek fájlokat és képeket/hangfájlokat.</string>
<string name="delete_after">Törlés miután</string>
<string name="error_changing_message_deletion">Hiba a beállítás megváltoztatásakor</string>
<string name="error_updating_link_for_group">Hiba a csoport link frissítésekor</string>
@@ -572,12 +572,12 @@
<string name="snd_group_event_group_profile_updated">csoport profil frissítve</string>
<string name="error_deleting_pending_contact_connection">Hiba a függőben lévő parner kapcsolatának törlésekor</string>
<string name="error_importing_database">Hiba a chat adatbázis importálásakor</string>
<string name="error_enabling_delivery_receipts">Hiba a kézbesítési jelentések engedélyezésekor!</string>
<string name="error_enabling_delivery_receipts">Hiba a kézbesítési igazolások engedélyezésekor!</string>
<string name="error_saving_xftp_servers">Hiba az XFTP szerverek mentésekor</string>
<string name="group_members_can_send_dms">A csoporttagok küldhetnek közvetlen üzeneteket.</string>
<string name="error_removing_member">Hiba a tag eltávolításakor</string>
<string name="callstate_ended">befejeződött</string>
<string name="v4_6_group_welcome_message">A csoport üdvözlő üzenete</string>
<string name="v4_6_group_welcome_message">Csoport üdvözlő szöveg</string>
<string name="group_display_name_field">Csoport neve:</string>
<string name="error_sending_message_contact_invitation">Hiba a meghívó küldésekor</string>
<string name="display_name">Add meg a nevedet:</string>
@@ -594,7 +594,7 @@
<string name="error_receiving_file">Hiba a fájl fogadásakor</string>
<string name="conn_event_ratchet_sync_ok">titkosítás rendben</string>
<string name="error_deleting_contact_request">Hiba az ismerős kérés törlésekor</string>
<string name="receipts_groups_title_enable">Engedélyezed a csoportok számára az üzenet kézbesítési jelentéseket?</string>
<string name="receipts_groups_title_enable">Kézbesítési igazolások engedélyezése csoportok számára?</string>
<string name="fix_connection_not_supported_by_contact">A javítás nem támogatott az ismerős által</string>
<string name="file_not_found">Fájl nem található</string>
<string name="smp_server_test_disconnect">Kapcsolat bontása</string>
@@ -619,14 +619,14 @@
<string name="feature_enabled">engedélyezve</string>
<string name="error_loading_details">Hiba a részletek betöltésekor</string>
<string name="error_accepting_contact_request">Hiba az ismerős kérés elfogadása</string>
<string name="snd_conn_event_ratchet_sync_allowed">%s ismerősöddel való titkosítás újra egyeztetése engedélyezve</string>
<string name="snd_conn_event_ratchet_sync_allowed">titkosítás újra egyeztetése engedélyezve %s számára</string>
<string name="conn_event_ratchet_sync_required">titkosítás újra egyeztetés szükséges</string>
<string name="v4_6_hidden_chat_profiles">Rejtett chat profilok</string>
<string name="files_and_media_section">Fájlok és média</string>
<string name="image_saved">Fotók elmentve a fotóalbumba</string>
<string name="files_and_media_section">Fájlok és képek/videók</string>
<string name="image_saved">Képek elmentve a fotóalbumba</string>
<string name="hide_notification">Elrejt</string>
<string name="la_immediately">Azonnal</string>
<string name="files_and_media_prohibited">A fájlok- és a médiatartalom küldése le van tiltva!</string>
<string name="files_and_media_prohibited">Fájlok és képek/videók tiltottak!</string>
<string name="hide_profile">Profil elrejtése</string>
<string name="how_to_use_your_servers">Hogyan használd a szervereidet</string>
<string name="v5_2_favourites_filter">Találd meg a chat üzeneteket gyorsabban</string>
@@ -666,7 +666,7 @@
<string name="service_notifications_disabled">Azonnali értesítések kikapcsolva!</string>
<string name="service_notifications">Azonnali értesítések!</string>
<string name="image_descr">Kép</string>
<string name="files_are_prohibited_in_group">A fájlok- és a médiatartalom küldése le van tiltva ebben a csoportban.</string>
<string name="files_are_prohibited_in_group">Fájlok és képek/videók tiltottak ebben a csoportban.</string>
<string name="how_it_works">Hogyan működik</string>
<string name="hide_dev_options">Elrejt:</string>
<string name="error_creating_member_contact">Hiba az ismerősöddel való kapcsolat létrehozásában</string>
@@ -790,7 +790,7 @@
<string name="no_filtered_chats">Nincsenek szűrt csevegések</string>
<string name="invalid_data">Érvénytelen adat</string>
<string name="ensure_ICE_server_address_are_correct_format_and_unique">Győződj meg róla, hogy a WebRTC ICE-kiszolgáló címei megfelelő formátumúak, sorszeparáltak és nem duplikáltak.</string>
<string name="only_owners_can_enable_files_and_media">Csak a csoporttulajdonosok engedélyezhetik a fájlok- és a médiatartalmak küldését.</string>
<string name="only_owners_can_enable_files_and_media">Csak a csoporttulajdonosok engedélyezhetik a fájlokat és a médiát.</string>
<string name="loading_remote_file_title">A fájl betöltése</string>
<string name="no_contacts_to_add">Nincs hozzáadandó ismerős</string>
<string name="v4_5_message_draft">Üzenet vázlat</string>
@@ -807,7 +807,7 @@
<string name="user_mute">Elnémít</string>
<string name="link_a_mobile">Egy mobil összekapcsolása</string>
<string name="settings_notifications_mode_title">Értesítési szolgáltatás</string>
<string name="only_group_owners_can_enable_voice">Csak a csoporttulajdonosok engedélyezhetik a hangüzenetek küldését.</string>
<string name="only_group_owners_can_enable_voice">Csak a csoporttulajdonosok engedélyezhetik a hangüzeneteket.</string>
<string name="only_client_devices_store_contacts_groups_e2e_encrypted_messages"><![CDATA[Csak a te eszközeid tárolják a felhasználói profilodat, névjegyeidet, csoportjaidat és a <b>2 rétegű végponttól-végpontig titkosítással</b> küldött üzeneteidet.]]></string>
<string name="invalid_migration_confirmation">Érvénytelen migrációs visszaigazolás</string>
<string name="only_group_owners_can_change_prefs">Csak a csoporttulajdonosok módosíthatják a csoportbeállításokat.</string>
@@ -905,7 +905,7 @@
<string name="network_option_protocol_timeout">Protokoll időtúllépés</string>
<string name="secret_text">titok</string>
<string name="settings_notification_preview_mode_title">Előnézet mutatása</string>
<string name="callstate_waiting_for_confirmation">várakozás a visszaigazolásra…</string>
<string name="callstate_waiting_for_confirmation">várakozás visszaigazolásra…</string>
<string name="stop_file__action">Fájl megállítása</string>
<string name="description_via_group_link">csoport linken keresztül</string>
<string name="network_option_ping_interval">PING időköze</string>
@@ -916,7 +916,7 @@
<string name="your_simplex_contact_address">A te SimpleX azonosítód</string>
<string name="alert_text_fragment_please_report_to_developers">Kérlek jelentsd a fejlesztőknek!</string>
<string name="people_can_connect_only_via_links_you_share">Az emberek kizárólag az általad megosztott link alapján kapcsolódhatnak hozzád.</string>
<string name="prohibit_sending_disappearing">Az eltűnő üzenetek küldése le van tiltva.</string>
<string name="prohibit_sending_disappearing">Eltűnő üzenetek küldésének tiltása.</string>
<string name="only_you_can_send_voice">Kizárólag te tudsz hangüzeneteket küldeni.</string>
<string name="update_network_settings_confirmation">Frissítés</string>
<string name="icon_descr_video_snd_complete">Videó elküldve</string>
@@ -938,7 +938,7 @@
<string name="use_chat">Használd a chatet</string>
<string name="share_verb">Megosztás</string>
<string name="received_message">Fogadott üzenet</string>
<string name="button_welcome_message">Üdvözlő üzenet</string>
<string name="button_welcome_message">Üdvözlő szöveg</string>
<string name="rcv_group_event_n_members_connected">%s, %s és %d további tag csatlakozott</string>
<string name="only_your_contact_can_make_calls">Kizárólag az ismerősöd tud hívást indítani.</string>
<string name="settings_section_title_themes">SZÍNSÉMÁK</string>
@@ -963,7 +963,7 @@
<string name="only_your_contact_can_send_voice">Kizárólag az ismerősöd tud hangüzeneteket küldeni.</string>
<string name="icon_descr_settings">Beállítások</string>
<string name="scan_qr_to_connect_to_contact">Kapcsolat létrehozásához az ismerősöd beolvassa a QR-kódodat vagy a linket használja az appban.</string>
<string name="callstate_received_confirmation">visszaigazolás fogadása</string>
<string name="callstate_received_confirmation">fogadott visszaigazolás…</string>
<string name="scan_code_from_contacts_app">A biztonsági kód beolvasása az ismerősöd appjából.</string>
<string name="observer_cant_send_message_desc">Kérlek vedd fel a kapcsolatot a csoport adminnal!</string>
<string name="icon_descr_video_on">Videó bekapcsolva</string>
@@ -1039,8 +1039,8 @@
<string name="submit_passcode">Elküld</string>
<string name="security_code">Biztonsági kód</string>
<string name="enter_correct_current_passphrase">Kérlek írd be a helyes jelmondatot!</string>
<string name="prohibit_message_deletion">Az üzenetek véglegesen való törlése le van tiltva.</string>
<string name="prohibit_message_reactions">Az üzenetekre adott emoji reakciók le vannak tiltva.</string>
<string name="prohibit_message_deletion">Végleges üzenet törlés tiltása.</string>
<string name="prohibit_message_reactions">Üzenetekre adott emoji reakciók tiltása.</string>
<string name="use_random_passphrase">Véletlenszerű jelmondat használata</string>
<string name="call_connection_peer_to_peer">ponttól-pontig</string>
<string name="run_chat_section">CHAT SZOLGÁLTATÁS INDÍTÁSA</string>
@@ -1124,14 +1124,14 @@
<string name="sender_may_have_deleted_the_connection_request">A küldő törölhette a kapcsolódási kérelmet.</string>
<string name="wrong_passphrase">Téves adatbázis jelmondat</string>
<string name="your_SMP_servers">A te Simplex chat (SMP) szervereid</string>
<string name="send_receipts_disabled_alert_title">Üzenet kézbesítési jelentés letiltva</string>
<string name="send_receipts_disabled_alert_title">Visszaigazolások letiltva</string>
<string name="open_database_folder">Adatbázis mappa megnyitása</string>
<string name="description_via_one_time_link">egyszer használatos linken keresztül</string>
<string name="set_group_preferences">Csoportbeállítások megadása</string>
<string name="simplex_link_connection">%1$s keresztül</string>
<string name="chat_preferences_yes">igen</string>
<string name="voice_message">Hangüzenet</string>
<string name="settings_section_title_use_from_desktop">Használat asztali kliensről</string>
<string name="settings_section_title_use_from_desktop">Számítógépről használat</string>
<string name="settings_section_title_you">TE</string>
<string name="network_proxy_port">port %d</string>
<string name="to_connect_via_link_title">Kapcsolódás link által</string>
@@ -1158,7 +1158,7 @@
<string name="whats_new">Milyen újdonságok vannak</string>
<string name="connect_plan_open_group">Csoport megnyitása</string>
<string name="info_row_sent_at">Elküldve ekkor</string>
<string name="prohibit_sending_voice">A hangüzenetek küldése le van tiltva.</string>
<string name="prohibit_sending_voice">Hangüzenetek küldésének tiltása.</string>
<string name="privacy_show_last_messages">Utolsó üzenetek megjelenítése</string>
<string name="smp_servers_preset_address">Előre beállított szerver címe</string>
<string name="periodic_notifications_disabled">Rendszeres értesítések letiltva!</string>
@@ -1170,20 +1170,20 @@
<string name="unlink_desktop">Szétkapcsolás</string>
<string name="incognito_random_profile">A te véletlenszerű profilod</string>
<string name="wrong_passphrase_title">Téves jelmondat!</string>
<string name="prohibit_message_reactions_group">Az üzenetekre adott emoji reakciók le vannak tiltva.</string>
<string name="prohibit_message_reactions_group">Üzenetekre adott emoji reakciók tiltása.</string>
<string name="language_system">Rendszer</string>
<string name="icon_descr_received_msg_status_unread">olvasatlan</string>
<string name="icon_descr_server_status_pending">Függő</string>
<string name="personal_welcome">Üdvözöllek %1$s!</string>
<string name="remove_passphrase_from_keychain">Jelmondat eltávolítása a Keystrore-ból?</string>
<string name="auth_unlock">Feloldás</string>
<string name="prohibit_sending_disappearing_messages">Az eltűnő üzenetek küldése le van tiltva.</string>
<string name="prohibit_sending_disappearing_messages">Eltűnő üzenetek küldésének tiltása.</string>
<string name="gallery_video_button">Videó</string>
<string name="update_database">Frissítés</string>
<string name="open_verb">Megnyitás</string>
<string name="periodic_notifications">Rendszeres értesítések</string>
<string name="alert_title_skipped_messages">Kihagyott üzenetek</string>
<string name="prohibit_sending_voice_messages">A hangüzenetek küldése le van tiltva.</string>
<string name="prohibit_sending_voice_messages">Hangüzenetek küldésének tiltása.</string>
<string name="set_contact_name">Ismerős nevének beállítása...</string>
<string name="only_you_can_send_disappearing">Kizárólag te tudsz eltűnő üzeneteket küldeni.</string>
<string name="share_image">Kép/videó megoszása…</string>
@@ -1207,7 +1207,7 @@
<string name="show_QR_code">QR-kód mutatása</string>
<string name="icon_descr_video_call">videóhívás</string>
<string name="unfavorite_chat">Nem kedvenc</string>
<string name="send_receipts">Üzenet kézbesítési jelentések</string>
<string name="send_receipts">Küldési visszaigazolások</string>
<string name="icon_descr_address">SimpleX cím</string>
<string name="chat_help_tap_button">Érintsd meg a gombot</string>
<string name="save_and_notify_contact">Mentés és az ismerős értesítése</string>
@@ -1221,7 +1221,7 @@
<string name="la_lock_mode">SimpleX Zár mód</string>
<string name="revoke_file__action">Fájl visszavonása</string>
<string name="xftp_servers">Fájl küldő/fogadó (XFTP) SimpleX szerverek</string>
<string name="prohibit_sending_files">A fájlok- és a médiatartalom küldése le van tiltva.</string>
<string name="prohibit_sending_files">Fájlok, képek és videók küldésének tiltása.</string>
<string name="share_file">Fájl megosztása…</string>
<string name="save_verb">Mentés</string>
<string name="call_connection_via_relay">közvetítő szerveren keresztül</string>
@@ -1230,7 +1230,7 @@
<string name="save_passphrase_and_open_chat">Jelmondat elmentése és chat megnyitása</string>
<string name="save_preferences_question">Beállítások elmentése?</string>
<string name="first_platform_without_user_ids">Az első chat rendszer bármiféle felhasználó azonosító nélkül - privátra lett tervezre.</string>
<string name="prohibit_direct_messages">A tagoknak való közvetlen üzenetküldés le van tiltva.</string>
<string name="prohibit_direct_messages">Tagoknak való közvetlen üzenetküldés tiltása.</string>
<string name="network_enable_socks">SOCKS proxy használata?</string>
<string name="icon_descr_speaker_off">Hangszóró kikapcsolva</string>
<string name="custom_time_unit_weeks">hét</string>
@@ -1362,7 +1362,7 @@
<string name="unhide_profile">Profil felfedése</string>
<string name="this_link_is_not_a_valid_connection_link">Ez a link nem érvényes meghívó link!</string>
<string name="to_verify_compare">A felek közötti titkosítás (e2e) ellenőrzéséhez hasonlítsd össze (vagy olvasd be) a kódot az ismerősöddel együtt az eszközeiteken!</string>
<string name="you_must_use_the_most_recent_version_of_database">A csevegési adatbázis legfrissebb verzióját CSAK egy eszközön kell használnod, ellenkező esetben előfordulhat, hogy az üzeneteket nem fogod megkapni valamennyi kapcsolatodtól.</string>
<string name="you_must_use_the_most_recent_version_of_database">A legfrissebb chat adatbázis verziódat kell használd, kizárólag egyetlen eszközön, máskülönben leállhat az üzenetek fogadása néhény ismerőstől!</string>
<string name="messages_section_description">Ez a beállítás a jelenlegi chat profilodban lévő üzenetekre érvényes</string>
<string name="you_are_invited_to_group_join_to_connect_with_group_members">Meg vagy hívva a csoportba. Csatlakozz és lépj kapcsolatba a csoporttagokkal!</string>
<string name="alert_message_no_group">Ez a csoport többé nem létezik.</string>
@@ -1380,7 +1380,7 @@
<string name="alert_title_cant_invite_contacts_descr">Inkognító profilt használsz ehhez a csoporthoz - a fő profilod megosztásának elkerülése érdekében meghívók küldése tiltott</string>
<string name="v4_5_transport_isolation">Kapcsolat izolációs mód</string>
<string name="you_will_be_connected_when_your_connection_request_is_accepted">Csatlakoztok amikor a meghívód elfogadásra kerül. Kérlek várj vagy nézz vissza később!</string>
<string name="voice_messages_are_prohibited">A hangüzenetek küldése le van tiltva ebben a csoportban.</string>
<string name="voice_messages_are_prohibited">A hangüzenetek tiltottak ebben a csoportban.</string>
<string name="system_restricted_background_in_call_warn"><![CDATA[A háttérben való hívásokhoz kérlek válaszd az <b>App akkumulátor használat</b> / <b>Korlátlan</b> módot az app beállításaiban.]]></string>
<string name="v5_4_link_mobile_desktop_descr">Biztonságos kvantum ellenálló protokoll által.</string>
<string name="v5_1_better_messages_descr">- hangüzenetek 5 percig.
@@ -1406,7 +1406,7 @@
<string name="network_disable_socks">Közvetlen internet kapcsolat használata?</string>
<string name="you_will_still_receive_calls_and_ntfs">Továbbra is kapsz hívásokat és értesítéseket az elnémított profilokból amikor azok aktívak.</string>
<string name="group_main_profile_sent">A saját fő chat profilod megküldésre kerül a csoporttagok számára.</string>
<string name="you_can_enable_delivery_receipts_later_alert">Később engedélyezheted az alkalmazás Adatvédelmi és Biztonsági beállításaiban.</string>
<string name="you_can_enable_delivery_receipts_later_alert">Később engedélyezheted az app Adatvédelmi és Biztonsági beállításaiban.</string>
<string name="to_reveal_profile_enter_password">A rejtett profilod felfedéséhez gépeld be a jelszót a kereső mezőbe a Chat profiljaid oldalon!</string>
<string name="upgrade_and_open_chat">A chat frissítése és megnyitása</string>
<string name="you_need_to_allow_to_send_voice">Ahhoz, hogy hangüzeneteket küldhess, engedélyezned kell az ismerőseidnek is azok küldését.</string>
@@ -1429,7 +1429,7 @@
<string name="verify_code_on_mobile">Ellenőrizd a kódot a mobilon!</string>
<string name="youve_accepted_group_invitation_connecting_to_inviting_group_member">Csatlakoztál ehhez a csoporthoz. Kapcsolódás a meghívó csoporttaghoz.</string>
<string name="you_can_connect_to_simplex_chat_founder"><![CDATA[Kapcsolatba léphetsz <font color="#0088ff">a SimpleX Chat fejlesztőivel és kérdezhetsz bármit és értesülhetsz az újdonságokról</font>.]]></string>
<string name="v4_2_auto_accept_contact_requests_desc">Opcionális üdvözlő üzenettel.</string>
<string name="v4_2_auto_accept_contact_requests_desc">Opcionális üdvözlő szöveggel.</string>
<string name="unknown_database_error_with_info">Ismeretlen adatbázis hiba: %s</string>
<string name="you_can_hide_or_mute_user_profile">Elrejtheted vagy némíthatod egy felhasználó profilját - tartsd lenyomva a menühöz!</string>
<string name="v5_3_simpler_incognito_mode_descr">Inkognító mód csatlakozáskor</string>
@@ -1437,7 +1437,7 @@
<string name="you_can_share_group_link_anybody_will_be_able_to_connect">Megoszthatsz egy linket vagy QR-kódot - így bárki csatlakozhat a csoporthoz. Csoporttagokat nem fogsz elveszíteni, az esetben sem ha kásőbb törlöd a csoportot.</string>
<string name="you_joined_this_group">Csatlakoztál ehhez a csoporthoz</string>
<string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[Ez a linked a(z) <b>%1$s</b> csoporthoz!]]></string>
<string name="voice_prohibited_in_this_chat">A hangüzenetek le vannak tiltva ebben a csevegésben.</string>
<string name="voice_prohibited_in_this_chat">A hangüzenetek tiltottak ebben a chatben.</string>
<string name="you_control_your_chat">Te tartod kézben chatedet!</string>
<string name="verify_code_with_desktop">Kód ellenőrzése a számítógépen</string>
<string name="v4_5_private_filenames_descr">Az időzóna, kép/hang fájlok megvédése érdekében használd az UTC-t!</string>
@@ -1455,7 +1455,7 @@
<string name="profile_is_only_shared_with_your_contacts">A profilod csak az ismerőseid számára kerül megosztásra.</string>
<string name="smp_servers_test_some_failed">Néhány szerver megbukott a teszten:</string>
<string name="group_invitation_tap_to_join">Érintsd meg a csatlakozáshoz</string>
<string name="delete_files_and_media_desc">Ez a művelet nem vonható vissza - az összes fogadott és küldött fájl a médiatartalommal együtt törlésre kerülnek. Az alacsony felbontású fotók viszont megmaradnak.</string>
<string name="delete_files_and_media_desc">Ez a művelet nem vonható vissza - az összes fogadott és küldött fájl a médiatartalommal együtt törlésre kerülnek. Az alacsony felbontású képek viszont megmaradnak.</string>
<string name="receipts_contacts_override_enabled">A kézbesítési jelentés engedélyezve van %d ismerősödnél</string>
<string name="sending_via">Küldés ezen keresztül:</string>
<string name="v5_0_polish_interface_descr">Köszönet a felhasználóknak - hozzájárulás a Weblaten!</string>
@@ -1470,7 +1470,7 @@
\nKésőbb megváltoztathatod.</string>
<string name="group_invitation_tap_to_join_incognito">Érintsd meg az inkognitóban való csatlakozáshoz</string>
<string name="set_password_to_export">Jelmondat beállítása az exportáláshoz</string>
<string name="receipts_groups_override_disabled">Az üzenet kézbesítési jelentés le van tiltva %d csoportnál</string>
<string name="receipts_groups_override_disabled">A kézbesítési jelentés le van tiltva %d csoportnál</string>
<string name="non_fatal_errors_occured_during_import">Néhány nem végzetes hiba történt az importálás során - további részletekért lásd a Chat-konzolt.</string>
<string name="v4_5_italian_interface_descr">Köszönet a felhasználóknak - hozzájárulás a Weblaten!</string>
<string name="relay_server_if_necessary">A relé szerver csak végszükség esetén használatos. Egy másik fél megfigyelheti az IP-címedet.</string>
@@ -1491,7 +1491,7 @@
<string name="users_delete_with_connections">Profil és szerverkapcsolatok</string>
<string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">A Te adatvédelmedet és biztonságodat védő üzenetküldő és alkalmazásplatform.</string>
<string name="tap_to_activate_profile">Érintsd meg a profil aktiválásához.</string>
<string name="receipts_contacts_override_disabled">Az üzenet kézbesítési jelentés le van tiltva %d ismerősödnél</string>
<string name="receipts_contacts_override_disabled">A kézbesítési jelentés le van tiltva %d ismerősödnél</string>
<string name="session_code">Munkamenet kód</string>
<string name="v4_4_french_interface_descr">Köszönet a felhasználóknak - hozzájárulás a Weblaten!</string>
<string name="receipts_section_groups">Kis csoportok (max. 20 tag)</string>
@@ -1541,7 +1541,7 @@
<string name="enable_sending_recent_history">Utolsó 100 üzenet küldése új tagoknak.</string>
<string name="disable_sending_recent_history">Ne küldjön előzményeket új tagoknak.</string>
<string name="or_show_this_qr_code">Vagy mutassa meg ezt a kódot</string>
<string name="enable_camera_access">Kamera hozzáférés engedélyezése</string>
<string name="enable_camera_access">Kamera-hozzáférés engedélyezése</string>
<string name="keep_unused_invitation_question">Megtartod a fel nem használt meghívót?</string>
<string name="share_this_1_time_link">Egyszer használatos link megosztása</string>
<string name="new_chat">Új beszélgetés</string>
@@ -1583,7 +1583,9 @@
<string name="possible_slow_function_title">Lassú funkció</string>
<string name="show_slow_api_calls">Lassú API-hívások megjelenítése</string>
<string name="remote_host_error_inactive"><![CDATA[A(z) <b>%s</b> mobil eszköz inaktív]]></string>
<string name="possible_deadlock_title">Elakadt</string>
<string name="developer_options_section">Fejlesztői beállítások</string>
<string name="possible_deadlock_desc">A kód végrehajtása túl sokáig tart: %1$d másodperc. Valószínűleg az alkalmazás lefagyott: %2$s</string>
<string name="possible_slow_function_desc">A funkció végrehajtása túl sokáig tart: %1$d másodperc: %2$s</string>
<string name="remote_host_error_busy"><![CDATA[A(z) <b>%s</b> mobil eszköz elfoglalt]]></string>
<string name="past_member_vName">Legutóbbi tag %1$s</string>
@@ -1608,21 +1610,8 @@
<string name="v5_5_simpler_connect_ui">A link beillesztése a csatlakozáshoz!</string>
<string name="v5_5_private_notes">Privát jegyzetek</string>
<string name="v5_5_simpler_connect_ui_descr">A keresősáv fogadja a meghívó hivatkozásokat.</string>
<string name="v5_5_private_notes_descr">Titkosított fájlokkal és médiatartalommal.</string>
<string name="v5_5_private_notes_descr">Titkosított fájlokkal és média állományokkal.</string>
<string name="v5_5_message_delivery_descr">Csökkentett akkumulátorhasználattal.</string>
<string name="v5_5_new_interface_languages">Magyar és török felhasználói felület</string>
<string name="v5_5_join_group_conversation_descr">A közelmúlt eseményei és továbbfejlesztett Jegyzék Bot.</string>
<string name="rcv_group_event_member_unblocked">%s letiltása feloldva</string>
<string name="snd_group_event_member_unblocked">feloldottad %s letiltását</string>
<string name="member_info_member_blocked">letiltva</string>
<string name="blocked_by_admin_item_description">letiltva az admin által</string>
<string name="member_blocked_by_admin">Letiltva az admin által</string>
<string name="rcv_group_event_member_blocked">%s letiltva</string>
<string name="block_for_all">Mindenki számára letiltva</string>
<string name="block_for_all_question">Mindenki számára letiltod ezt a tagot?</string>
<string name="blocked_by_admin_items_description">%d üzenet letiltva az admin által</string>
<string name="unblock_for_all">Letiltás feloldása mindenki számára</string>
<string name="unblock_for_all_question">Mindenki számára feloldod ennek a tagnak a letiltását?</string>
<string name="snd_group_event_member_blocked">letiltottad %s-t</string>
<string name="error_blocking_member_for_all">Hiba a tag mindenki számára való letiltása során</string>
</resources>

View File

@@ -1591,7 +1591,9 @@
<string name="possible_slow_function_title">Funzione lenta</string>
<string name="show_slow_api_calls">Mostra chiamate API lente</string>
<string name="group_member_status_unknown_short">sconosciuto</string>
<string name="possible_deadlock_desc">L\'esecuzione del codice impiega troppo tempo: %1$d secondi. Probabilmente l\'app è congelata: %2$s</string>
<string name="group_member_status_unknown">stato sconosciuto</string>
<string name="possible_deadlock_title">Stallo</string>
<string name="developer_options_section">Opzioni sviluppatore</string>
<string name="v5_5_private_notes">Note private</string>
<string name="v5_5_new_interface_languages">Interfaccia in ungherese e turco</string>
@@ -1617,17 +1619,4 @@
<string name="profile_update_event_updated_profile">profilo aggiornato</string>
<string name="saved_message_title">Messaggio salvato</string>
<string name="v5_5_message_delivery_descr">Con consumo di batteria ridotto.</string>
<string name="blocked_by_admin_items_description">%d messaggi bloccati dall\'amministratore</string>
<string name="rcv_group_event_member_blocked">ha bloccato %s</string>
<string name="rcv_group_event_member_unblocked">ha sbloccato %s</string>
<string name="snd_group_event_member_unblocked">hai sbloccato %s</string>
<string name="unblock_for_all">Sblocca per tutti</string>
<string name="unblock_for_all_question">Sbloccare il membro per tutti?</string>
<string name="block_for_all">Blocca per tutti</string>
<string name="member_info_member_blocked">bloccato</string>
<string name="blocked_by_admin_item_description">bloccato dall\'amministratore</string>
<string name="member_blocked_by_admin">Bloccato dall\'amministratore</string>
<string name="block_for_all_question">Bloccare il membro per tutti?</string>
<string name="error_blocking_member_for_all">Errore nel blocco del membro per tutti</string>
<string name="snd_group_event_member_blocked">hai bloccato %s</string>
</resources>

View File

@@ -1571,7 +1571,9 @@
<string name="remote_ctrl_error_busy">PC版が処理中</string>
<string name="remote_ctrl_error_disconnected">PC版が切断されました</string>
<string name="remote_ctrl_error_bad_version">ご利用のPC版のバージョンがサポートされてません。両端末が同じバージョンかどうか、ご確認ください。</string>
<string name="possible_deadlock_title">デッドロック状態</string>
<string name="developer_options_section">開発者向けの設定</string>
<string name="possible_deadlock_desc">処理時間が異常にかかるようです: %1$d 秒。アプリが固まった恐れがあります: %2$s</string>
<string name="remote_host_error_busy"><![CDATA[携帯版 <b>%s</b> がただいま処理中]]></string>
<string name="possible_slow_function_desc">機能の処理時間が以上にかかってます: %1$d 秒: %2$s</string>
<string name="show_internal_errors">内部エラーを表示</string>

View File

@@ -363,7 +363,7 @@
<string name="disappearing_prohibited_in_this_chat">Išnykstančios žinutės šiame pokalbyje yra uždraustos.</string>
<string name="voice_messages_are_prohibited">Balso žinutės šioje grupėje yra uždraustos.</string>
<string name="connect_via_group_link">Prisijungti per grupės nuorodą\?</string>
<string name="connect_via_contact_link">Prisijungti per adresato adresą?</string>
<string name="connect_via_contact_link">Prisijungti per adresato nuorodą\?</string>
<string name="sending_files_not_yet_supported">failų siuntimas kol kas nepalaikomas</string>
<string name="invalid_message_format">neteisingas žinutės formatas</string>
<string name="receiving_files_not_yet_supported">failų gavimas kol kas nepalaikomas</string>
@@ -610,60 +610,4 @@
<string name="cannot_access_keychain">Negalima pasiekti \"Keystore\", kad išsaugotumėte duomenų bazės slaptažodį</string>
<string name="icon_descr_cancel_file_preview">Atšaukti failo peržiūrą</string>
<string name="icon_descr_cancel_image_preview">Atšaukti vaizdo peržiūrą</string>
<string name="share_text_database_id">Duomenų bazės ID: %d</string>
<string name="delete_and_notify_contact">Ištrinti ir pranešti adresatui</string>
<string name="send_disappearing_message_custom_time">Tinkintas laikas</string>
<string name="v5_3_new_interface_languages_descr">Arabų, bulgarų, suomių, hebrajų, tajų ir ukrainiečių dėkojame naudotojams ir Weblate.</string>
<string name="v5_3_new_interface_languages">6 naujos naudotojo sąsajos kalbos</string>
<string name="v5_1_custom_themes">Tinkinti apipavidalinimai</string>
<string name="multicast_connect_automatically">Prisijungti automatiškai</string>
<string name="chat_database_imported">Pokalbio duomenų bazė importuota</string>
<string name="connect_via_invitation_link">Prisijungti per vienkartinę nuorodą?</string>
<string name="icon_descr_close_button">Užvėrimo mygtukas</string>
<string name="devices">Įrenginiai</string>
<string name="connection_error_auth">Ryšio klaida (AUTH)</string>
<string name="disable_notifications_button">Išjungti pranešimus</string>
<string name="continue_to_next_step">Tęsti</string>
<string name="chat_database_deleted">Pokalbio duomenų bazė ištrinta</string>
<string name="choose_file_title">Pasirinkti failą</string>
<string name="contribute">Talkinti</string>
<string name="receipts_section_contacts">Adresatai</string>
<string name="settings_developer_tools">Plėtotojo įrankiai</string>
<string name="clear_note_folder_warning">Visos žinutės bus ištrintos to neįmanoma bus atšaukti!</string>
<string name="add_contact_button_to_create_link_or_connect_via_link"><![CDATA[<b>Pridėti adresatą</b>: sukurti naują pakvietimo nuorodą arba prisijungti per gautą nuorodą.]]></string>
<string name="camera_not_available">Kamera neprieinama</string>
<string name="contacts_can_mark_messages_for_deletion">Adresatai gali žymėti žinutes ištrynimui; jūs galėsite jas peržiūrėti.</string>
<string name="create_another_profile_button">Sukurti profilį</string>
<string name="creating_link">Kuriama nuoroda…</string>
<string name="deleted_description">ištrinta</string>
<string name="delivery_receipts_are_disabled">Pranešimai apie pristatymą yra išjungti!</string>
<string name="turn_off_battery_optimization_button">Leisti</string>
<string name="in_developing_title">Jau greitai!</string>
<string name="developer_options_section">Plėtotojo parinktys</string>
<string name="colored_text">spalvotas</string>
<string name="connect_plan_already_joining_the_group">Jau prisijungiama prie grupės!</string>
<string name="connect_plan_connect_via_link">Prisijungti per nuorodą?</string>
<string name="create_simplex_address">Sukurti SimpleX adresą</string>
<string name="ttl_h">%dval.</string>
<string name="agent_critical_error_title">Kritinė klaida</string>
<string name="create_group_button_to_create_new_group"><![CDATA[<b>Sukurti grupę</b>: sukurti naują grupę.]]></string>
<string name="add_contact_tab">Pridėti adresatą</string>
<string name="customize_theme_title">Tinkinti apipavidalinimą</string>
<string name="chat_database_section">POKALBIO DUOMENŲ BAZĖ</string>
<string name="v4_6_chinese_spanish_interface">Naudotojo sąsaja kinų ir ispanų kalbomis</string>
<string name="delivery_receipts_title">Pranešimai apie pristatymą!</string>
<string name="auth_disable_simplex_lock">Išjungti SimpleX užraktą</string>
<string name="delivery">Pristatymas</string>
<string name="change_lock_mode">Keisti užrakto veikseną</string>
<string name="ttl_d">%dd.</string>
<string name="disappearing_message">Išnykstanti žinutė</string>
<string name="receipts_contacts_title_disable">Išjungti pranešimus apie pristatymą?</string>
<string name="send_receipts_disabled">išjungta</string>
<string name="v5_4_better_groups">Geresnės grupės</string>
<string name="v5_4_incognito_groups_descr">Sukurti grupę naudojant atsitiktinį profilį.</string>
<string name="v5_3_encrypt_local_files_descr">Programėlė šifruoja naujus vietinius failus (išskyrus vaizdo įrašus).</string>
<string name="connect_plan_already_connecting">Jau jungiamasi!</string>
<string name="connect_via_member_address_alert_title">Prisijungti tiesiogiai?</string>
<string name="create_group_button">Sukurti grupę</string>
<string name="dark_theme">Tamsus apipavidalinimas</string>
</resources>

View File

@@ -1551,7 +1551,7 @@
<string name="tap_to_scan">Tik om te scannen</string>
<string name="keep_invitation_link">Bewaar</string>
<string name="tap_to_paste_link">Tik om de link te plakken</string>
<string name="search_or_paste_simplex_link">Zoek of plak een SimpleX link</string>
<string name="search_or_paste_simplex_link">Zoek of plak de SimpleX link</string>
<string name="chat_is_stopped_you_should_transfer_database">De chat is gestopt. Als u deze database al op een ander apparaat heeft gebruikt, moet u deze terugzetten voordat u met chatten begint.</string>
<string name="start_chat_question">Begin chat?</string>
<string name="show_internal_errors">Toon interne fouten</string>
@@ -1574,6 +1574,7 @@
<string name="remote_host_error_missing"><![CDATA[Mobiel <b>%s</b> ontbreekt]]></string>
<string name="remote_host_error_bad_state"><![CDATA[De verbinding met de mobiel <b>%s</b> is in slechte staat]]></string>
<string name="remote_ctrl_error_disconnected">De verbinding met desktop is verbroken</string>
<string name="possible_deadlock_title">Impasse</string>
<string name="possible_slow_function_desc">Uitvoering van functie duurt te lang: %1$d seconden: %2$s</string>
<string name="possible_slow_function_title">Langzame functie</string>
<string name="developer_options_section">Ontwikkelaars opties</string>
@@ -1587,13 +1588,14 @@
<string name="restart_chat_button">Chat opnieuw starten</string>
<string name="remote_host_error_timeout"><![CDATA[Time-out bereikt tijdens het verbinden met de mobiel <b>%s</b>]]></string>
<string name="remote_ctrl_error_bad_state">De verbinding met de desktop is in slechte staat</string>
<string name="possible_deadlock_desc">Het uitvoeren van de code duurt te lang: %1$d seconden. Waarschijnlijk is de app vastgelopen: %2$s</string>
<string name="remote_ctrl_error_bad_invitation">Desktop heeft verkeerde uitnodigingscode</string>
<string name="remote_host_error_bad_version"><![CDATA[Mobiel <b>%s</b> heeft een niet-ondersteunde versie. Zorg ervoor dat u op beide apparaten dezelfde versie gebruikt]]></string>
<string name="remote_ctrl_error_timeout">Time-out bereikt tijdens het verbinden met de desktop</string>
<string name="group_member_status_unknown">onbekende status</string>
<string name="v5_5_message_delivery">Verbeterde berichtbezorging</string>
<string name="v5_5_join_group_conversation">Neem deel aan groepsgesprekken</string>
<string name="v5_5_simpler_connect_ui">Plak een link om te verbinden!</string>
<string name="v5_5_join_group_conversation">Neem deel aan groep gesprekken</string>
<string name="v5_5_simpler_connect_ui">Plak link om te verbinden!</string>
<string name="v5_5_private_notes">Privé notities</string>
<string name="clear_note_folder_warning">Alle berichten worden verwijderd. Dit kan niet ongedaan worden gemaakt!</string>
<string name="info_row_created_at">Gemaakt op</string>
@@ -1615,17 +1617,4 @@
<string name="profile_update_event_removed_picture">profielfoto verwijderd</string>
<string name="profile_update_event_set_new_address">nieuw contactadres instellen</string>
<string name="profile_update_event_set_new_picture">nieuwe profielfoto instellen</string>
<string name="member_blocked_by_admin">Geblokkeerd door beheerder</string>
<string name="block_for_all">Blokkeren voor iedereen</string>
<string name="block_for_all_question">Lid voor iedereen blokkeren?</string>
<string name="unblock_for_all">Deblokkeer voor iedereen</string>
<string name="member_info_member_blocked">geblokkeerd</string>
<string name="blocked_by_admin_item_description">geblokkeerd door beheerder</string>
<string name="rcv_group_event_member_blocked">%s geblokkeerd</string>
<string name="blocked_by_admin_items_description">%d berichten geblokkeerd door beheerder</string>
<string name="rcv_group_event_member_unblocked">%s gedeblokkeerd</string>
<string name="error_blocking_member_for_all">Fout bij blokkeren van lid voor iedereen</string>
<string name="unblock_for_all_question">Lid voor iedereen deblokkeren?</string>
<string name="snd_group_event_member_blocked">je hebt %s geblokkeerd</string>
<string name="snd_group_event_member_unblocked">je hebt %s gedeblokkeerd</string>
</resources>

View File

@@ -1554,80 +1554,4 @@
<string name="keep_invitation_link">Zachowaj</string>
<string name="tap_to_paste_link">Dotknij, aby wkleić link</string>
<string name="search_or_paste_simplex_link">Wyszukaj lub wklej link SimpleX</string>
<string name="v5_5_private_notes">Prywatne notatki</string>
<string name="v5_5_message_delivery">Ulepszona dostawa wiadomości</string>
<string name="v5_5_new_interface_languages">Węgierski i turecki interfejs</string>
<string name="v5_5_message_delivery_descr">Ze zmniejszonym zużyciem baterii.</string>
<string name="remote_ctrl_error_bad_state">Połączenie z komputerem jest w złym stanie</string>
<string name="remote_ctrl_error_bad_invitation">Komputer ma zły kod zaproszenia</string>
<string name="remote_ctrl_error_busy">Komputer jest zajęty</string>
<string name="remote_ctrl_error_disconnected">Komputer został odłączony</string>
<string name="error_deleting_note_folder">Błąd usuwania prywatnych notatek</string>
<string name="possible_slow_function_title">Wolne funkcje</string>
<string name="clear_note_folder_question">Wyczyścić prywatne notatki?</string>
<string name="developer_options_section">Opcje deweloperskie</string>
<string name="show_slow_api_calls">Pokaż wolne zapytania API</string>
<string name="rcv_group_event_member_blocked">zablokowany %s</string>
<string name="start_chat_question">Uruchomić czat?</string>
<string name="rcv_group_event_member_unblocked">odblokuj %s</string>
<string name="snd_group_event_member_blocked">zablokowałeś %s</string>
<string name="snd_group_event_member_unblocked">odblokowałeś %s</string>
<string name="profile_update_event_member_name_changed">członek %1$s zmienił na %2$s</string>
<string name="profile_update_event_set_new_address">ustaw nowy adres kontaktu</string>
<string name="profile_update_event_updated_profile">zaktualizowano profil</string>
<string name="past_member_vName">Były członek %1$s</string>
<string name="block_for_all_question">Zablokować członka dla wszystkich?</string>
<string name="info_row_created_at">Utworzony o</string>
<string name="saved_message_title">Zachowano wiadomość</string>
<string name="unblock_for_all">Odblokuj dla wszystkich</string>
<string name="unblock_for_all_question">Odblokować członka dla wszystkich?</string>
<string name="error_blocking_member_for_all">Błąd blokowania członka dla wszystkich</string>
<string name="v5_5_simpler_connect_ui">Wklej link, aby połączyć!</string>
<string name="v5_5_private_notes_descr">Z zaszyfrowanymi plikami i multimediami.</string>
<string name="v5_5_simpler_connect_ui_descr">Pasek wyszukiwania akceptuje linki zaproszenia.</string>
<string name="v5_5_join_group_conversation_descr">Ostatnia historia i ulepszony bot adresowy.</string>
<string name="agent_critical_error_title">Krytyczny błąd</string>
<string name="agent_critical_error_desc">Proszę zgłosić to do deweloperów:
\n%s
\n
\nZalecane jest zrestartowanie aplikacji.</string>
<string name="agent_internal_error_desc">Proszę zgłosić to do deweloperów:
\n%s</string>
<string name="restart_chat_button">Zrestartuj czat</string>
<string name="clear_note_folder_warning">Wszystkie wiadomości zostaną usunięte nie można tego cofnąć!</string>
<string name="member_info_member_blocked">zablokowany</string>
<string name="blocked_by_admin_item_description">zablokowany przez administratora</string>
<string name="member_blocked_by_admin">Zablokowany przez admina</string>
<string name="block_for_all">Zablokuj dla wszystkich</string>
<string name="chat_is_stopped_you_should_transfer_database">Czat został zatrzymany. Jeśli korzystałeś już z tej bazy danych na innym urządzeniu, powinieneś przenieść ją z powrotem przed rozpoczęciem czatu.</string>
<string name="agent_internal_error_title">Wewnętrzny błąd</string>
<string name="v5_5_join_group_conversation">Dołącz do grupowej rozmowy</string>
<string name="share_text_created_at">Utworzony o: %s</string>
<string name="remote_ctrl_error_bad_version">Komputer ma niewspieraną wersję. Proszę upewnić się, że używasz tych samych wersji na obu urządzeniach</string>
<string name="blocked_by_admin_items_description">%d wiadomości zablokowanych przez admina</string>
<string name="error_creating_message">Błąd tworzenia wiadomości</string>
<string name="possible_slow_function_desc">Wykonanie kodu zajmuje za dużo czasu: %1$d sekund: %2$s</string>
<string name="note_folder_local_display_name">Prywatne notatki</string>
<string name="group_member_status_unknown">nieznany status</string>
<string name="show_internal_errors">Pokaż błędy wewnętrzne</string>
<string name="remote_ctrl_error_timeout">Osiągnięto limit czasu podczas łączenia z komputerem</string>
<string name="failed_to_create_user_invalid_title">Nieprawidłowa nazwa wyświetlana!</string>
<string name="failed_to_create_user_invalid_desc">Nazwa wyświetlana jest nieprawidłowa. Proszę wybrać inną nazwę.</string>
<string name="remote_host_was_disconnected_title">Połączenie zatrzymane</string>
<string name="remote_ctrl_was_disconnected_title">Połączenie zatrzymane</string>
<string name="remote_host_disconnected_from"><![CDATA[Odłączono od telefonu <b>%s</b> z powodu: %s]]></string>
<string name="remote_host_error_missing"><![CDATA[Brakuje telefonu <b>%s</b>]]></string>
<string name="remote_host_error_inactive"><![CDATA[Telefon <b>%s</b> jest nieaktywny]]></string>
<string name="remote_host_error_bad_version"><![CDATA[Telefon <b>%s</b> ma niewspieraną wersję. Proszę, upewnij się, że używasz tej samej wersji na obydwu urządzeniach]]></string>
<string name="group_member_status_unknown_short">nieznany</string>
<string name="profile_update_event_contact_name_changed">kontakt %1$s zmieniony na %2$s</string>
<string name="profile_update_event_removed_address">usunięto adres kontaktu</string>
<string name="profile_update_event_removed_picture">usunięto zdjęcie profilu</string>
<string name="profile_update_event_set_new_picture">ustaw nowe zdjęcie profilu</string>
<string name="remote_host_error_bad_state"><![CDATA[Połączenie z telefonem <b>%s</b> jest w złym stanie]]></string>
<string name="remote_ctrl_disconnected_with_reason">Odłączono z powodu: %s</string>
<string name="remote_host_error_busy"><![CDATA[Telefon <b>%s</b> jest zajęty]]></string>
<string name="remote_host_error_timeout"><![CDATA[Osiągnięto limit czasu podczas łączenia z telefonem <b>%s</b>]]></string>
<string name="remote_ctrl_error_inactive">Komputer jest nieaktywny</string>
<string name="remote_host_error_disconnected"><![CDATA[Telefon <b>%s</b> został rozłączony]]></string>
</resources>

View File

@@ -1,72 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="moderated_items_description">%1$d mesaje moderate de %2$s</string>
<string name="abort_switch_receiving_address_question">Întrerupi schimbarea adresei?</string>
<string name="send_disappearing_message_30_seconds">30 secunde</string>
<string name="accept_contact_button">Acceptă</string>
<string name="accept_contact_incognito_button">Acceptă incognito</string>
<string name="smp_servers_add">Adaugă server…</string>
<string name="network_settings">Setări de rețea avansate</string>
<string name="contact_wants_to_connect_via_call">%1$s dorește să se conecteze cu tine prin</string>
<string name="accept_call_on_lock_screen">Acceptă</string>
<string name="alert_text_decryption_error_too_many_skipped">%1$d mesaje omise.</string>
<string name="chat_item_ttl_month">1 lună</string>
<string name="chat_item_ttl_week">1 săptămână</string>
<string name="group_member_role_admin">administrator</string>
<string name="color_primary_variant">Accent adițional</string>
<string name="color_secondary_variant">Adițional secundar</string>
<string name="accept_feature">Acceptă</string>
<string name="v5_3_new_interface_languages">6 limbi noi pentru interfață</string>
<string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d mesaje nu au putut fi decriptate.</string>
<string name="integrity_msg_skipped">%1$d mesaj(e) omis(e)</string>
<string name="group_info_section_title_num_members">%1$s MEMBRI</string>
<string name="chat_item_ttl_day">1 zi</string>
<string name="send_disappearing_message_1_minute">1 minut</string>
<string name="one_time_link_short">link de unică folosință</string>
<string name="send_disappearing_message_5_minutes">5 minute</string>
<string name="about_simplex">Despre SimpleX</string>
<string name="learn_more_about_address">Despre adresa SimpleX</string>
<string name="about_simplex_chat">Despre SimpleX Chat</string>
<string name="above_then_preposition_continuation">deasupra, apoi:</string>
<string name="color_primary">Accent</string>
<string name="accept">Acceptă</string>
<string name="accept_connection_request__question">Accepți cererea de conexiune?</string>
<string name="add_contact_tab">Adaugă contact</string>
<string name="callstatus_accepted">apel acceptat</string>
<string name="smp_servers_preset_add">Adaugă servere prestabilite</string>
<string name="users_add">Adaugă profil</string>
<string name="address_section_title">Adresă</string>
<string name="v4_3_improved_server_configuration_desc">Adaugă servere prin scanare de coduri QR.</string>
<string name="smp_servers_add_to_another_device">Adaugă la un alt dispozitiv</string>
<string name="button_add_welcome_message">Adaugă mesaj de întâmpinare</string>
<string name="conn_event_ratchet_sync_started">acceptând criptarea…</string>
<string name="snd_conn_event_ratchet_sync_started">acceptând criptarea pentru %s…</string>
<string name="v4_2_group_links_desc">Administratorii pot crea linkuri de participare la grupuri.</string>
<string name="v5_2_more_things">Câteva lucruri în plus</string>
<string name="all_app_data_will_be_cleared">Toate datele aplicației sunt șterse.</string>
<string name="abort_switch_receiving_address_desc">Schimbarea de adresă va fi întreruptă. Se va folosi vechea adresa de primire.</string>
<string name="add_address_to_your_profile">Adaugă adresa la profil, astfel încât contactele să o poată partaja cu alte persoane. Profilul reînoit va fi comunicat contactelor.</string>
<string name="network_enable_socks_info">Accesezi serverele prin proxy SOCKS cu portul %d? Proxyul trebuie pornit înaintea activării acestei opțiuni.</string>
<string name="abort_switch_receiving_address">Întrerupe schimbarea adresei</string>
<string name="abort_switch_receiving_address_confirm">Întrerupe</string>
<string name="users_delete_all_chats_deleted">Toate conversațiile și mesajele vor fi șterse - operațiunea este definitivă!</string>
<string name="clear_note_folder_warning">Toate mesajele vor fi șterse - operațiunea este definitivă!</string>
<string name="allow_message_reactions_only_if">Permite reacții la mesaje doar dacă și contactul tău le permite.</string>
<string name="allow_to_delete_messages">Permite ștergerea ireversibila a mesajelor trimise. (24 ore)</string>
<string name="allow_to_send_files">Permite trimiterea de fișiere și media.</string>
<string name="v5_1_self_destruct_passcode_descr">Toate datele sunt șterse când este introdusă.</string>
<string name="all_group_members_will_remain_connected">Toți membrii grupului vor rămâne conectați.</string>
<string name="clear_chat_warning">Toate mesajele vor fi șterse - operațiunea este definitivă! Mesajele vor fi șterse DOAR pentru tine.</string>
<string name="block_member_desc">Toate mesajele noi de la %s vor fi ascunse!</string>
<string name="turn_off_battery_optimization_button">Permite</string>
<string name="allow_verb">Permite</string>
<string name="allow_calls_only_if">Permite apeluri doar dacă le permite contactul tău.</string>
<string name="allow_voice_messages_question">Permiți mesaje vocale?</string>
<string name="allow_voice_messages_only_if">Permite mesajele vocale numai dacă le permite și contactul tău.</string>
<string name="allow_irreversible_message_deletion_only_if">Permite ștergerea mesajelor ireversibile doar dacă și contactul tău îți permite ție. (24 ore)</string>
<string name="allow_message_reactions">Permite reacții la mesaje.</string>
<string name="allow_direct_messages">Permite trimiterea de mesaje directe membrilor.</string>
<string name="allow_to_send_disappearing">Permite trimiterea de mesaje efemere.</string>
<string name="allow_to_send_voice">Permite trimiterea de mesaje vocale.</string>
<string name="allow_disappearing_messages_only_if">Permite mesaje efemere doar dacă le permite contactul tău.</string>
</resources>

View File

@@ -1680,6 +1680,8 @@
<string name="error_showing_message">ошибка отображения сообщения</string>
<string name="error_showing_content">ошибка отображения содержания</string>
<string name="remote_ctrl_disconnected_with_reason">Отсоединён по причине: %s</string>
<string name="possible_deadlock_title">Взаимная блокировка</string>
<string name="possible_deadlock_desc">Выполнение задачи занимает долгое время: %1$d секунд. Возможно, приложение заблокировано: %2$s</string>
<string name="possible_slow_function_desc">Выполнение задачи занимает долгое время: %1$d секунд: %2$s</string>
<string name="possible_slow_function_title">Медленный вызов</string>
<string name="profile_update_event_contact_name_changed">контакт %1$s изменён на %2$s</string>
@@ -1700,17 +1702,4 @@
<string name="saved_message_title">Сохраненное сообщение</string>
<string name="group_member_status_unknown_short">неизвестно</string>
<string name="group_member_status_unknown">неизвестный статус</string>
<string name="blocked_by_admin_items_description">%d сообщений заблокировано администратором</string>
<string name="rcv_group_event_member_blocked">%s заблокирован</string>
<string name="rcv_group_event_member_unblocked">%s разблокирован</string>
<string name="snd_group_event_member_unblocked">Вы разблокировали %s</string>
<string name="unblock_for_all">Разблокировать для всех</string>
<string name="block_for_all_question">Заблокировать члена для всех?</string>
<string name="member_info_member_blocked">заблокирован</string>
<string name="blocked_by_admin_item_description">заблокировано администратором</string>
<string name="member_blocked_by_admin">Заблокирован администратором</string>
<string name="block_for_all">Заблокировать для всех</string>
<string name="error_blocking_member_for_all">Ошибка при блокировании члена для всех</string>
<string name="unblock_for_all_question">Разблокировать члена для всех?</string>
<string name="snd_group_event_member_blocked">Вы заблокировали %s</string>
</resources>

View File

@@ -1586,6 +1586,8 @@
<string name="remote_host_error_bad_state"><![CDATA[到移动主机 <b>%s</b>的连接状态不佳]]></string>
<string name="remote_host_error_timeout"><![CDATA[连接到移动主机<b>%s</b>时超时]]></string>
<string name="failed_to_create_user_invalid_desc">显示名无效。请另选一个名称。</string>
<string name="possible_deadlock_title">死锁</string>
<string name="possible_deadlock_desc">代码执行花费的时间过久:%1$d秒。应用可能卡住了%2$s</string>
<string name="possible_slow_function_title">慢函数</string>
<string name="show_slow_api_calls">显示缓慢的 API 调用</string>
<string name="past_member_vName">过往成员 %1$s</string>
@@ -1617,17 +1619,4 @@
<string name="note_folder_local_display_name">私密笔记</string>
<string name="clear_note_folder_question">清除私密笔记?</string>
<string name="saved_message_title">已保存的消息</string>
<string name="blocked_by_admin_items_description">管理员封禁了 %d 条消息</string>
<string name="rcv_group_event_member_unblocked">已解封 %s</string>
<string name="block_for_all">为所有人封禁</string>
<string name="unblock_for_all">为所有人解封</string>
<string name="unblock_for_all_question">为所有其他成员解封该成员?</string>
<string name="member_blocked_by_admin">由管理员封禁</string>
<string name="blocked_by_admin_item_description">由管理员封禁</string>
<string name="rcv_group_event_member_blocked">已封禁 %s</string>
<string name="block_for_all_question">为所有其他成员封禁该成员?</string>
<string name="error_blocking_member_for_all">执行为所有人封禁时出错</string>
<string name="member_info_member_blocked">已封禁</string>
<string name="snd_group_event_member_blocked">你封禁了 %s</string>
<string name="snd_group_event_member_unblocked">你解封了 %s</string>
</resources>

View File

@@ -14,7 +14,8 @@ import androidx.compose.ui.input.key.*
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.*
import chat.simplex.common.model.*
import chat.simplex.common.model.ChatController
import chat.simplex.common.model.ChatModel
import chat.simplex.common.platform.*
import chat.simplex.common.ui.theme.DEFAULT_START_MODAL_WIDTH
import chat.simplex.common.ui.theme.SimpleXTheme
@@ -39,8 +40,7 @@ fun showApp() {
WindowExceptionHandler { e ->
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.app_was_crashed),
text = e.stackTraceToString(),
shareText = true
text = e.stackTraceToString()
)
Log.e(TAG, "App crashed, thread name: " + Thread.currentThread().name + ", exception: " + e.stackTraceToString())
window.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))

View File

@@ -42,7 +42,7 @@ actual fun SaveContentItemAction(cItem: ChatItem, saveFileLauncher: FileChooserL
}
var fileSource = getLoadedFileSource(cItem.file)
if (chatModel.connectedToRemote() && fileSource == null) {
withLongRunningApi(slow = 600_000) {
withLongRunningApi(slow = 60_000, deadlock = 600_000) {
cItem.file?.loadRemoteFile(true)
fileSource = getLoadedFileSource(cItem.file)
saveIfExists()
@@ -51,7 +51,7 @@ actual fun SaveContentItemAction(cItem: ChatItem, saveFileLauncher: FileChooserL
})
}
actual fun copyItemToClipboard(cItem: ChatItem, clipboard: ClipboardManager) = withLongRunningApi(slow = 600_000) {
actual fun copyItemToClipboard(cItem: ChatItem, clipboard: ClipboardManager) = withLongRunningApi(slow = 60_000, deadlock = 600_000) {
var fileSource = getLoadedFileSource(cItem.file)
if (chatModel.connectedToRemote() && fileSource == null) {
cItem.file?.loadRemoteFile(true)

View File

@@ -1,80 +0,0 @@
package chat.simplex.common.views.helpers
import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import chat.simplex.common.model.CustomTimeUnit
import chat.simplex.common.ui.theme.DEFAULT_PADDING
@Composable
actual fun CustomTimePicker(
selection: MutableState<Int>,
timeUnitsLimits: List<TimeUnitLimits>
) {
val unit = remember {
var res: CustomTimeUnit = CustomTimeUnit.Second
val found = timeUnitsLimits.asReversed().any {
if (selection.value >= it.minValue * it.timeUnit.toSeconds && selection.value <= it.maxValue * it.timeUnit.toSeconds) {
res = it.timeUnit
selection.value = (selection.value / it.timeUnit.toSeconds).coerceIn(it.minValue, it.maxValue) * it.timeUnit.toSeconds
true
} else {
false
}
}
if (!found) {
// If custom interval doesn't fit in any category, set it to 1 second interval
selection.value = 1
}
mutableStateOf(res)
}
val values = remember(unit.value) {
val limit = timeUnitsLimits.first { it.timeUnit == unit.value }
val res = ArrayList<Pair<Int, String>>()
for (i in limit.minValue..limit.maxValue) {
val seconds = i * limit.timeUnit.toSeconds
val desc = i.toString()
res.add(seconds to desc)
}
if (res.none { it.first == selection.value }) {
// Doesn't fit into min..max, put it equal to the closest value
selection.value = selection.value.coerceIn(res.first().first, res.last().first)
//selection.value = res.last { it.first <= selection.value }.first
}
res
}
val units = remember {
val res = ArrayList<Pair<CustomTimeUnit, String>>()
for (unit in timeUnitsLimits) {
res.add(unit.timeUnit to unit.timeUnit.text)
}
res
}
Row(
Modifier.padding(bottom = DEFAULT_PADDING),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly
) {
ExposedDropDownSetting(
values,
selection,
textColor = MaterialTheme.colors.onBackground,
enabled = remember { mutableStateOf(true) },
onSelected = { selection.value = it }
)
Spacer(Modifier.width(DEFAULT_PADDING))
ExposedDropDownSetting(
units,
unit,
textColor = MaterialTheme.colors.onBackground,
enabled = remember { mutableStateOf(true) },
onSelected = {
selection.value = selection.value / unit.value.toSeconds * it.toSeconds
unit.value = it
}
)
}
}

View File

@@ -25,11 +25,11 @@ android.nonTransitiveRClass=true
android.enableJetifier=true
kotlin.mpp.androidSourceSetLayoutVersion=2
android.version_name=5.5.5
android.version_code=185
android.version_name=5.5-beta.2
android.version_code=174
desktop.version_name=5.5.5
desktop.version_code=31
desktop.version_name=5.5-beta.2
desktop.version_code=25
kotlin.version=1.8.20
gradle.plugin.version=7.4.2

View File

@@ -1,119 +0,0 @@
---
layout: layouts/article.html
title: "SimpleX Chat: free infrastructure from Linode, v5.5 released with private notes, group history and a simpler UX to connect."
date: 2024-01-24
previewBody: blog_previews/20240124.html
image: images/20240124-connect1.png
permalink: "/blog/20240124-simplex-chat-infrastructure-costs-v5-5-simplex-ux-private-notes-group-history.html"
---
# SimpleX Chat: free infrastructure from Linode, v5.5 released with private notes, group history and a simpler UX to connect.
**Published:** Jan 24, 2024
[SimpleX Chat infrastructure on Linode](#simplex-chat-infrastructure-on-linode):
- Free infrastructure.
- SimpleX servers in Linode Marketplace.
- High capacity messaging servers.
What's new in v5.5:
- [private notes](#private-notes)
- [group history](#group-history)
- [simpler UX to connect to other users](#simpler-ux-to-connect-to-other-users)
- [message delivery stability and other improvements](#message-delivery-stability-and-other-improvements)
Also, we added Hungarian (only Android) and Turkish interface languages, thanks to [our users and Weblate](https://github.com/simplex-chat/simplex-chat#help-translating-simplex-chat).
SimpleX Chat Android app is now available in 20 languages!
## SimpleX Chat infrastructure on Linode
We chose Linode as our hosting provider as and they have been consistently reliable, cheaper than alternatives, with excellent support and great documentation.
When Linode was acquired by Akamai, we were a bit nervous about how it may affect service quality. So far it's been working out quite well.
As the usage of SimpleX network was growing, so did our hosting costs, and from being really small they started to become significant, particularly as we didn't yet manage to optimize the servers last year.
Linode helped - we're really excited to announce that Akamai decided to support SimpleX Chat growth by accepting it into their [Linode Rise startup program](https://www.linode.com/linode-for-startups/).
Thanks to this program:
- we received free infrastructure for the first year up to $10,000 per month, no strings attached. It already saved us some money, and gave us enough time to optimize the servers - the latest version of the servers are much less costly to operate with the current traffic, and can support a much larger traffic within this limit. In the year 2 of the program we will receive 50% discount with unlimited traffic, and in year 3 - 25% discount.
- Linode Marketplace now includes [SimpleX Chat messages and file servers](https://www.linode.com/marketplace/apps/simplex-chat/simplex-chat/) - you can get free $100 credits for the first 2 months and run your own servers in just a few clicks, and use them in SimpleX Chat apps. Anybody can submit their application to Linode marketplace, but dedicated support we have from Linode team via this program made it simpler.
- Akamai solution engineers are helping us to design high capacity server solution, free of charge, so that a single host can provide horizontally scalable capacity for messaging, allowing for a much larger number of concurrent users on a single server address. Initially we considered using HAProxy, and the latest proof of concept uses OpenResty - a fork of Nginx with Lua script engine - to route requests from a single host to multiple SMP relays, reducing an overhead for the clients that would be configured with a smaller number of higher capacity servers. This project is still in progress, there will be more details as we roll it out.
## What's new in v5.5
### Private notes
<img src="./images/20240124-notes1.png" width="220" class="float-to-left"> <img src="./images/20240124-notes2.png" width="220" class="float-to-left">
*"Where do I put notes for myself?"* was a very common support question. There was a workaround - you could create an empty group, just with yourself, and use it to save notes, but it was not very convenient, and you could accidentally add members there.
This version has a more convenient and private alternative - the Private notes. It looks like an ordinary conversation where you can put text messages, links with previews, and any media and files, but they are not sent anywhere - they are stored locally, only on your device, with encrypted files.
You can access the Private notes created in mobile app from desktop app too, by linking a mobile and desktop apps - the feature [added in the previous version](./20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.md). It allows to conveniently share files between the devices without sending them over the Internet.
### Group history
<img src="./images/20240124-history1.png" width="220" class="float-to-left"> <img src="./images/20240124-history2.png" width="220" class="float-to-left">
In the previous version, when users joined groups, they only saw an empty conversation, and the notifications of being connected to other members. This version allows group admins sending recent group history to the new members - this option is enabled by default for new groups, and can be enabled for the existing groups in the preferences. So now new members can join the conversation as soon as they join.
This does not mean that these messages are stored on any servers - the admin member that adds a new member to the group sends these messages directly when a new member joins. Groups are still fully decentralized, do not have any identity on the network, and fully private - only their members know they exist.
That is, unless a group owner decides to make it public. Groups can be registered in [SimpleX groups directory](https://simplex.chat/contact#/?v=1-4&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion) to be discovered by the new members - group directory is also improved.
### Simpler UX to connect to other users
<img src="./images/20240124-connect1.png" width="220" class="float-to-left"> <img src="./images/20240124-connect2.png" width="220" class="float-to-left">
SimpleX platform has no user accounts or identities, and while it improves metadata privacy, it also makes it harder to understand how to connect to other people, particularly for the new users who are not invited by the existing users.
This version simplifies this interface by allowing to connect via the received link just by pasting the address into the search bar, as is common in many wallet apps and some other decentralized messengers. We also improved the interface of creating invitation links.
We will continue working on improving and simplifying user interface throughout the year. Please send us any feedback and suggestions to the team's address available in the app.
### Message delivery stability and other improvements
One of the long standing issues was that message reception could get stuck in some rare occasions, and only get resumed once the app is fully restarted. As Android app includes an always-on notification service that runs in background, full restart should be done via the app settings.
This version fixed many issues with message delivery stability and also added some diagnostics to identify any other cases when message delivery may stop. These fixes should also reduce battery usage, particularly on slow internet connections.
Other improvements in this version:
- you can now reveal secret messages by tapping. To send a secret message wrap in "#" characters, e.g. "\#password\#".
- you can delete the last user profile, simplifying account deletion. If you have [hidden user profiles](./20230328-simplex-chat-v4-6-hidden-profiles.md), they won't be deleted in this case, and will be accessible again once you create a new profile.
## SimpleX platform
Some links to answer the most common questions:
[How can SimpleX deliver messages without user identifiers](./20220511-simplex-chat-v2-images-files.md#the-first-messaging-platform-without-user-identifiers).
[What are the risks to have identifiers assigned to the users](./20220711-simplex-chat-v3-released-ios-notifications-audio-video-calls-database-export-import-protocol-improvements.md#why-having-users-identifiers-is-bad-for-the-users).
[Technical details and limitations](https://github.com/simplex-chat/simplex-chat#privacy-technical-details-and-limitations).
[How SimpleX is different from Session, Matrix, Signal, etc.](https://github.com/simplex-chat/simplex-chat/blob/stable/README.md#frequently-asked-questions).
Please also see our [website](https://simplex.chat).
## Help us with donations
Huge thank you to everybody who donated to SimpleX Chat!
We are prioritizing users privacy and security - it would be impossible without your support.
Our pledge to our users is that SimpleX protocols are and will remain open, and in public domain, - so anybody can build the future implementations of the clients and the servers. We are building SimpleX platform based on the same principles as email and web, but much more private and secure.
Your donations help us raise more funds any amount, even the price of the cup of coffee, makes a big difference for us.
See [this section](https://github.com/simplex-chat/simplex-chat/tree/master#help-us-with-donations) for the ways to donate.
Thank you,
Evgeny
SimpleX Chat founder

View File

@@ -1,20 +1,5 @@
# Blog
Jan 24, 2024 [SimpleX Chat: free infrastructure from Linode, v5.5 released](./20240124-simplex-chat-infrastructure-costs-v5-5-simplex-ux-private-notes-group-history.md)
SimpleX Chat infrastructure on Linode:
- Free infrastructure.
- SimpleX servers in Linode Marketplace.
- High capacity messaging servers.
What's new in v5.5:
- private notes.
- group history.
- simpler UX to connect to other users.
- message delivery stability and other improvements.
---
Nov 25, 2023 [SimpleX Chat v5.4 released](./20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.md)
- Link mobile and desktop apps via secure quantum-resistant protocol. 🔗

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 303 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 363 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 KiB

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