Compare commits

..

1 Commits

Author SHA1 Message Date
Avently 29857e33e2 multiplatform: init haskell in different thread 2023-11-21 18:47:01 +07:00
436 changed files with 10185 additions and 23906 deletions
+18 -44
View File
@@ -42,7 +42,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
build: build:
name: build-${{ matrix.os }}-${{ matrix.ghc }} name: build-${{ matrix.os }}
if: always() if: always()
needs: prepare-release needs: prepare-release
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -51,25 +51,18 @@ jobs:
matrix: matrix:
include: include:
- os: ubuntu-20.04 - os: ubuntu-20.04
ghc: "8.10.7"
cache_path: ~/.cabal/store
- os: ubuntu-20.04
ghc: "9.6.3"
cache_path: ~/.cabal/store cache_path: ~/.cabal/store
asset_name: simplex-chat-ubuntu-20_04-x86-64 asset_name: simplex-chat-ubuntu-20_04-x86-64
desktop_asset_name: simplex-desktop-ubuntu-20_04-x86_64.deb desktop_asset_name: simplex-desktop-ubuntu-20_04-x86_64.deb
- os: ubuntu-22.04 - os: ubuntu-22.04
ghc: "9.6.3"
cache_path: ~/.cabal/store cache_path: ~/.cabal/store
asset_name: simplex-chat-ubuntu-22_04-x86-64 asset_name: simplex-chat-ubuntu-22_04-x86-64
desktop_asset_name: simplex-desktop-ubuntu-22_04-x86_64.deb desktop_asset_name: simplex-desktop-ubuntu-22_04-x86_64.deb
- os: macos-latest - os: macos-latest
ghc: "9.6.3"
cache_path: ~/.cabal/store cache_path: ~/.cabal/store
asset_name: simplex-chat-macos-x86-64 asset_name: simplex-chat-macos-x86-64
desktop_asset_name: simplex-desktop-macos-x86_64.dmg desktop_asset_name: simplex-desktop-macos-x86_64.dmg
- os: windows-latest - os: windows-latest
ghc: "9.6.3"
cache_path: C:/cabal cache_path: C:/cabal
asset_name: simplex-chat-windows-x86-64 asset_name: simplex-chat-windows-x86-64
desktop_asset_name: simplex-desktop-windows-x86_64.msi desktop_asset_name: simplex-desktop-windows-x86_64.msi
@@ -88,17 +81,16 @@ jobs:
- name: Setup Haskell - name: Setup Haskell
uses: haskell-actions/setup@v2 uses: haskell-actions/setup@v2
with: with:
ghc-version: ${{ matrix.ghc }} ghc-version: "9.6.3"
cabal-version: "3.10.1.0" cabal-version: "3.10.1.0"
- name: Restore cached build - name: Cache dependencies
id: restore_cache uses: actions/cache@v3
uses: actions/cache/restore@v3
with: with:
path: | path: |
${{ matrix.cache_path }} ${{ matrix.cache_path }}
dist-newstyle dist-newstyle
key: ${{ matrix.os }}-ghc${{ matrix.ghc }}-${{ hashFiles('cabal.project', 'simplex-chat.cabal') }} key: ${{ matrix.os }}-${{ hashFiles('cabal.project', 'simplex-chat.cabal') }}
# / Unix # / Unix
@@ -113,7 +105,7 @@ jobs:
echo " flags: +openssl" >> cabal.project.local echo " flags: +openssl" >> cabal.project.local
- name: Install AppImage dependencies - name: Install AppImage dependencies
if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os == 'ubuntu-20.04' if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04'
run: sudo apt install -y desktop-file-utils run: sudo apt install -y desktop-file-utils
- name: Install pkg-config for Mac - name: Install pkg-config for Mac
@@ -139,7 +131,7 @@ jobs:
echo "bin_hash=$(echo SHA2-512\(${{ matrix.asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT echo "bin_hash=$(echo SHA2-512\(${{ matrix.asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
- name: Unix upload CLI binary to release - name: Unix upload CLI binary to release
if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os != 'windows-latest' if: startsWith(github.ref, 'refs/tags/v') && matrix.os != 'windows-latest'
uses: svenstaro/upload-release-action@v2 uses: svenstaro/upload-release-action@v2
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
@@ -148,7 +140,7 @@ jobs:
tag: ${{ github.ref }} tag: ${{ github.ref }}
- name: Unix update CLI binary hash - name: Unix update CLI binary hash
if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os != 'windows-latest' if: startsWith(github.ref, 'refs/tags/v') && matrix.os != 'windows-latest'
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -158,7 +150,7 @@ jobs:
${{ steps.unix_cli_build.outputs.bin_hash }} ${{ steps.unix_cli_build.outputs.bin_hash }}
- name: Setup Java - name: Setup Java
if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name if: startsWith(github.ref, 'refs/tags/v')
uses: actions/setup-java@v3 uses: actions/setup-java@v3
with: with:
distribution: 'corretto' distribution: 'corretto'
@@ -167,7 +159,7 @@ jobs:
- name: Linux build desktop - name: Linux build desktop
id: linux_desktop_build id: linux_desktop_build
if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04') if: startsWith(github.ref, 'refs/tags/v') && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04')
shell: bash shell: bash
run: | run: |
scripts/desktop/build-lib-linux.sh scripts/desktop/build-lib-linux.sh
@@ -176,10 +168,10 @@ jobs:
path=$(echo $PWD/release/main/deb/simplex_*_amd64.deb) path=$(echo $PWD/release/main/deb/simplex_*_amd64.deb)
echo "package_path=$path" >> $GITHUB_OUTPUT 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 echo "package_hash=$(echo SHA2-512\(${{ matrix.desktop_asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
- name: Linux make AppImage - name: Linux make AppImage
id: linux_appimage_build id: linux_appimage_build
if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os == 'ubuntu-20.04' if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04'
shell: bash shell: bash
run: | run: |
scripts/desktop/make-appimage-linux.sh scripts/desktop/make-appimage-linux.sh
@@ -202,7 +194,7 @@ jobs:
echo "package_hash=$(echo SHA2-512\(${{ matrix.desktop_asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT echo "package_hash=$(echo SHA2-512\(${{ matrix.desktop_asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
- name: Linux upload desktop package to release - name: Linux upload desktop package to release
if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04') if: startsWith(github.ref, 'refs/tags/v') && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04')
uses: svenstaro/upload-release-action@v2 uses: svenstaro/upload-release-action@v2
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
@@ -211,7 +203,7 @@ jobs:
tag: ${{ github.ref }} tag: ${{ github.ref }}
- name: Linux update desktop package hash - name: Linux update desktop package hash
if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04') if: startsWith(github.ref, 'refs/tags/v') && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04')
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -221,7 +213,7 @@ jobs:
${{ steps.linux_desktop_build.outputs.package_hash }} ${{ steps.linux_desktop_build.outputs.package_hash }}
- name: Linux upload AppImage to release - name: Linux upload AppImage to release
if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os == 'ubuntu-20.04' if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04'
uses: svenstaro/upload-release-action@v2 uses: svenstaro/upload-release-action@v2
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
@@ -230,7 +222,7 @@ jobs:
tag: ${{ github.ref }} tag: ${{ github.ref }}
- name: Linux update AppImage hash - name: Linux update AppImage hash
if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os == 'ubuntu-20.04' if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04'
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -258,15 +250,6 @@ jobs:
body: | body: |
${{ steps.mac_desktop_build.outputs.package_hash }} ${{ steps.mac_desktop_build.outputs.package_hash }}
- name: Cache unix build
uses: actions/cache/save@v3
if: matrix.os != 'windows-latest'
with:
path: |
${{ matrix.cache_path }}
dist-newstyle
key: ${{ steps.restore_cache.outputs.cache-primary-key }}
- name: Unix test - name: Unix test
if: matrix.os != 'windows-latest' if: matrix.os != 'windows-latest'
timeout-minutes: 30 timeout-minutes: 30
@@ -279,7 +262,7 @@ jobs:
# rm -rf dist-newstyle/src/direct-sq* is here because of the bug in cabal's dependency which prevents second build from finishing # 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' - name: 'Setup MSYS2'
if: matrix.os == 'windows-latest' if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'windows-latest'
uses: msys2/setup-msys2@v2 uses: msys2/setup-msys2@v2
with: with:
msystem: ucrt64 msystem: ucrt64
@@ -347,7 +330,7 @@ jobs:
path=$(echo $PWD/release/main/msi/*imple*.msi | sed 's#/\([a-z]\)#\1:#' | sed 's#/#\\#g') path=$(echo $PWD/release/main/msi/*imple*.msi | sed 's#/\([a-z]\)#\1:#' | sed 's#/#\\#g')
echo "package_path=$path" >> $GITHUB_OUTPUT 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 echo "package_hash=$(echo SHA2-512\(${{ matrix.desktop_asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT
- name: Windows upload desktop package to release - name: Windows upload desktop package to release
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'windows-latest' if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'windows-latest'
uses: svenstaro/upload-release-action@v2 uses: svenstaro/upload-release-action@v2
@@ -367,13 +350,4 @@ jobs:
body: | body: |
${{ steps.windows_desktop_build.outputs.package_hash }} ${{ steps.windows_desktop_build.outputs.package_hash }}
- name: Cache windows build
uses: actions/cache/save@v3
if: matrix.os == 'windows-latest'
with:
path: |
${{ matrix.cache_path }}
dist-newstyle
key: ${{ steps.restore_cache.outputs.cache-primary-key }}
# Windows / # Windows /
+4 -6
View File
@@ -232,8 +232,6 @@ You can use SimpleX with your own servers and still communicate with people usin
Recent and important updates: Recent and important updates:
[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). [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).
[Jul 22, 2023. SimpleX Chat: v5.2 released with message delivery receipts](./blog/20230722-simplex-chat-v5-2-message-delivery-receipts.md). [Jul 22, 2023. SimpleX Chat: v5.2 released with message delivery receipts](./blog/20230722-simplex-chat-v5-2-message-delivery-receipts.md).
@@ -368,13 +366,13 @@ Please also join [#simplex-devs](https://simplex.chat/contact#/?v=1-2&smp=smp%3A
- ✅ Message delivery confirmation (with sender opt-out per contact). - ✅ Message delivery confirmation (with sender opt-out per contact).
- ✅ Desktop client. - ✅ Desktop client.
- ✅ Encryption of local files stored in the app. - ✅ Encryption of local files stored in the app.
- Using mobile profiles from the desktop app. - 🏗 Using mobile profiles from the desktop app.
- 🏗 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).
- Post-quantum resistant key exchange in double ratchet protocol.
- Large groups, communities and public channels.
- Privacy & security slider - a simple way to set all settings at once. - Privacy & security slider - a simple way to set all settings at once.
- Improve sending videos (including encryption of locally stored videos). - Improve sending videos (including encryption of locally stored videos).
- Improve experience for the new users.
- SMP queue redundancy and rotation (manual is supported). - SMP queue redundancy and rotation (manual is supported).
- Include optional message into connection request sent via contact address. - 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.). - Improved navigation and search in the conversation (expand and scroll to quoted message, scroll to search results, etc.).
+1 -7
View File
@@ -15,7 +15,6 @@ class AppDelegate: NSObject, UIApplicationDelegate {
logger.debug("AppDelegate: didFinishLaunchingWithOptions") logger.debug("AppDelegate: didFinishLaunchingWithOptions")
application.registerForRemoteNotifications() application.registerForRemoteNotifications()
if #available(iOS 17.0, *) { trackKeyboard() } if #available(iOS 17.0, *) { trackKeyboard() }
NotificationCenter.default.addObserver(self, selector: #selector(pasteboardChanged), name: UIPasteboard.changedNotification, object: nil)
return true return true
} }
@@ -37,17 +36,12 @@ class AppDelegate: NSObject, UIApplicationDelegate {
ChatModel.shared.keyboardHeight = 0 ChatModel.shared.keyboardHeight = 0
} }
@objc func pasteboardChanged() {
ChatModel.shared.pasteboardHasStrings = UIPasteboard.general.hasStrings
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%02hhx", $0) }.joined() let token = deviceToken.map { String(format: "%02hhx", $0) }.joined()
logger.debug("AppDelegate: didRegisterForRemoteNotificationsWithDeviceToken \(token)") logger.debug("AppDelegate: didRegisterForRemoteNotificationsWithDeviceToken \(token)")
let m = ChatModel.shared let m = ChatModel.shared
let deviceToken = DeviceToken(pushProvider: PushProvider(env: pushEnvironment), token: token) let deviceToken = DeviceToken(pushProvider: PushProvider(env: pushEnvironment), token: token)
m.deviceToken = deviceToken m.deviceToken = deviceToken
// savedToken is set in startChat, when it is started before this method is called
if m.savedToken != nil { if m.savedToken != nil {
registerToken(token: deviceToken) registerToken(token: deviceToken)
} }
@@ -86,7 +80,7 @@ class AppDelegate: NSObject, UIApplicationDelegate {
} }
} else if let checkMessages = ntfData["checkMessages"] as? Bool, checkMessages { } else if let checkMessages = ntfData["checkMessages"] as? Bool, checkMessages {
logger.debug("AppDelegate: didReceiveRemoteNotification: checkMessages") logger.debug("AppDelegate: didReceiveRemoteNotification: checkMessages")
if m.ntfEnablePeriodic && allowBackgroundRefresh() && BGManager.shared.lastRanLongAgo { if appStateGroupDefault.get().inactive && m.ntfEnablePeriodic {
receiveMessages(completionHandler) receiveMessages(completionHandler)
} else { } else {
completionHandler(.noData) completionHandler(.noData)
+61 -100
View File
@@ -14,14 +14,11 @@ struct ContentView: View {
@ObservedObject var alertManager = AlertManager.shared @ObservedObject var alertManager = AlertManager.shared
@ObservedObject var callController = CallController.shared @ObservedObject var callController = CallController.shared
@Environment(\.colorScheme) var colorScheme @Environment(\.colorScheme) var colorScheme
@Binding var doAuthenticate: Bool
var contentAccessAuthenticationExtended: Bool @Binding var userAuthorized: Bool?
@Binding var canConnectCall: Bool
@Environment(\.scenePhase) var scenePhase @Binding var lastSuccessfulUnlock: TimeInterval?
@State private var automaticAuthenticationAttempted = false @Binding var showInitializationView: Bool
@State private var canConnectViewCall = false
@State private var lastSuccessfulUnlock: TimeInterval? = nil
@AppStorage(DEFAULT_SHOW_LA_NOTICE) private var prefShowLANotice = false @AppStorage(DEFAULT_SHOW_LA_NOTICE) private var prefShowLANotice = false
@AppStorage(DEFAULT_LA_NOTICE_SHOWN) private var prefLANoticeShown = false @AppStorage(DEFAULT_LA_NOTICE_SHOWN) private var prefLANoticeShown = false
@AppStorage(DEFAULT_PERFORM_LA) private var prefPerformLA = false @AppStorage(DEFAULT_PERFORM_LA) private var prefPerformLA = false
@@ -31,7 +28,6 @@ struct ContentView: View {
@State private var showWhatsNew = false @State private var showWhatsNew = false
@State private var showChooseLAMode = false @State private var showChooseLAMode = false
@State private var showSetPasscode = false @State private var showSetPasscode = false
@State private var waitingForOrPassedAuth = true
@State private var chatListActionSheet: ChatListActionSheet? = nil @State private var chatListActionSheet: ChatListActionSheet? = nil
private enum ChatListActionSheet: Identifiable { private enum ChatListActionSheet: Identifiable {
@@ -44,31 +40,16 @@ struct ContentView: View {
} }
} }
private var accessAuthenticated: Bool {
chatModel.contentViewAccessAuthenticated || contentAccessAuthenticationExtended
}
var body: some View { var body: some View {
ZStack { ZStack {
// contentView() has to be in a single branch, so that enabling authentication doesn't trigger re-rendering and close settings. contentView()
// i.e. with separate branches like this settings are closed: `if prefPerformLA { ... contentView() ... } else { contentView() }
if !prefPerformLA || accessAuthenticated {
contentView()
} else {
lockButton()
}
if chatModel.showCallView, let call = chatModel.activeCall { if chatModel.showCallView, let call = chatModel.activeCall {
callView(call) callView(call)
} }
if !showSettings, let la = chatModel.laRequest { if !showSettings, let la = chatModel.laRequest {
LocalAuthView(authRequest: la) LocalAuthView(authRequest: la)
.onDisappear {
// this flag is separate from accessAuthenticated to show initializationView while we wait for authentication
waitingForOrPassedAuth = accessAuthenticated
}
} else if showSetPasscode { } else if showSetPasscode {
SetAppPasscodeView { SetAppPasscodeView {
chatModel.contentViewAccessAuthenticated = true
prefPerformLA = true prefPerformLA = true
showSetPasscode = false showSetPasscode = false
privacyLocalAuthModeDefault.set(.passcode) privacyLocalAuthModeDefault.set(.passcode)
@@ -78,10 +59,15 @@ struct ContentView: View {
showSetPasscode = false showSetPasscode = false
alertManager.showAlert(laPasscodeNotSetAlert()) alertManager.showAlert(laPasscodeNotSetAlert())
} }
} else if chatModel.chatDbStatus == nil && AppChatState.shared.value != .stopped && waitingForOrPassedAuth {
initializationView()
} }
} }
.onAppear {
if prefPerformLA { requestNtfAuthorization() }
initAuthenticate()
}
.onChange(of: doAuthenticate) { _ in
initAuthenticate()
}
.alert(isPresented: $alertManager.presentAlert) { alertManager.alertView! } .alert(isPresented: $alertManager.presentAlert) { alertManager.alertView! }
.sheet(isPresented: $showSettings) { .sheet(isPresented: $showSettings) {
SettingsView(showSettings: $showSettings) SettingsView(showSettings: $showSettings)
@@ -90,44 +76,14 @@ struct ContentView: View {
Button("System authentication") { initialEnableLA() } Button("System authentication") { initialEnableLA() }
Button("Passcode entry") { showSetPasscode = true } Button("Passcode entry") { showSetPasscode = true }
} }
.onChange(of: scenePhase) { phase in
logger.debug("scenePhase was \(String(describing: scenePhase)), now \(String(describing: phase))")
switch (phase) {
case .background:
// also see .onChange(of: scenePhase) in SimpleXApp: on entering background
// it remembers enteredBackgroundAuthenticated and sets chatModel.contentViewAccessAuthenticated to false
automaticAuthenticationAttempted = false
canConnectViewCall = false
case .active:
canConnectViewCall = !prefPerformLA || contentAccessAuthenticationExtended || unlockedRecently()
// condition `!chatModel.contentViewAccessAuthenticated` is required for when authentication is enabled in settings or on initial notice
if prefPerformLA && !chatModel.contentViewAccessAuthenticated {
if AppChatState.shared.value != .stopped {
if contentAccessAuthenticationExtended {
chatModel.contentViewAccessAuthenticated = true
} else {
if !automaticAuthenticationAttempted {
automaticAuthenticationAttempted = true
// authenticate if call kit call is not in progress
if !(CallController.useCallKit() && chatModel.showCallView && chatModel.activeCall != nil) {
authenticateContentViewAccess()
}
}
}
} else {
// when app is stopped automatic authentication is not attempted
chatModel.contentViewAccessAuthenticated = contentAccessAuthenticationExtended
}
}
default:
break
}
}
} }
@ViewBuilder private func contentView() -> some View { @ViewBuilder private func contentView() -> some View {
if let status = chatModel.chatDbStatus, status != .ok { if prefPerformLA && userAuthorized != true {
lockButton()
} else if chatModel.chatDbStatus == nil && showInitializationView {
initializationView()
} else if let status = chatModel.chatDbStatus, status != .ok {
DatabaseErrorView(status: status) DatabaseErrorView(status: status)
} else if !chatModel.v3DBMigration.startChat { } else if !chatModel.v3DBMigration.startChat {
MigrateToAppGroupView() MigrateToAppGroupView()
@@ -150,11 +106,11 @@ struct ContentView: View {
if CallController.useCallKit() { if CallController.useCallKit() {
ActiveCallView(call: call, canConnectCall: Binding.constant(true)) ActiveCallView(call: call, canConnectCall: Binding.constant(true))
.onDisappear { .onDisappear {
if prefPerformLA && !accessAuthenticated { authenticateContentViewAccess() } if userAuthorized == false && doAuthenticate { runAuthenticate() }
} }
} else { } else {
ActiveCallView(call: call, canConnectCall: $canConnectViewCall) ActiveCallView(call: call, canConnectCall: $canConnectCall)
if prefPerformLA && !accessAuthenticated { if prefPerformLA && userAuthorized != true {
Rectangle() Rectangle()
.fill(colorScheme == .dark ? .black : .white) .fill(colorScheme == .dark ? .black : .white)
.frame(maxWidth: .infinity, maxHeight: .infinity) .frame(maxWidth: .infinity, maxHeight: .infinity)
@@ -164,27 +120,22 @@ struct ContentView: View {
} }
private func lockButton() -> some View { private func lockButton() -> some View {
Button(action: authenticateContentViewAccess) { Label("Unlock", systemImage: "lock") } Button(action: runAuthenticate) { Label("Unlock", systemImage: "lock") }
} }
private func initializationView() -> some View { private func initializationView() -> some View {
VStack { VStack {
ProgressView().scaleEffect(2) ProgressView().scaleEffect(2)
Text("Opening app") Text("Opening database")
.padding() .padding()
} }
.frame(maxWidth: .infinity, maxHeight: .infinity )
.background(
Rectangle()
.fill(.background)
)
} }
private func mainView() -> some View { private func mainView() -> some View {
ZStack(alignment: .top) { ZStack(alignment: .top) {
ChatListView(showSettings: $showSettings).privacySensitive(protectScreen) ChatListView(showSettings: $showSettings).privacySensitive(protectScreen)
.onAppear { .onAppear {
requestNtfAuthorization() if !prefPerformLA { requestNtfAuthorization() }
// Local Authentication notice is to be shown on next start after onboarding is complete // Local Authentication notice is to be shown on next start after onboarding is complete
if (!prefLANoticeShown && prefShowLANotice && !chatModel.chats.isEmpty) { if (!prefLANoticeShown && prefShowLANotice && !chatModel.chats.isEmpty) {
prefLANoticeShown = true prefLANoticeShown = true
@@ -236,37 +187,48 @@ struct ContentView: View {
} }
} }
private func unlockedRecently() -> Bool { private func initAuthenticate() {
if let lastSuccessfulUnlock = lastSuccessfulUnlock { logger.debug("initAuthenticate")
return ProcessInfo.processInfo.systemUptime - lastSuccessfulUnlock < 2 if CallController.useCallKit() && chatModel.showCallView && chatModel.activeCall != nil {
} else { userAuthorized = false
return false } else if doAuthenticate {
runAuthenticate()
} }
} }
private func authenticateContentViewAccess() { private func runAuthenticate() {
logger.debug("DEBUGGING: authenticateContentViewAccess") logger.debug("DEBUGGING: runAuthenticate")
dismissAllSheets(animated: false) { if !prefPerformLA {
logger.debug("DEBUGGING: authenticateContentViewAccess, in dismissAllSheets callback") userAuthorized = true
chatModel.chatId = nil } else {
logger.debug("DEBUGGING: before dismissAllSheets")
dismissAllSheets(animated: false) {
logger.debug("DEBUGGING: in dismissAllSheets callback")
chatModel.chatId = nil
justAuthenticate()
}
}
}
authenticate(reason: NSLocalizedString("Unlock app", comment: "authentication reason"), selfDestruct: true) { laResult in private func justAuthenticate() {
logger.debug("DEBUGGING: authenticate callback: \(String(describing: laResult))") userAuthorized = false
switch (laResult) { let laMode = privacyLocalAuthModeDefault.get()
case .success: authenticate(reason: NSLocalizedString("Unlock app", comment: "authentication reason"), selfDestruct: true) { laResult in
chatModel.contentViewAccessAuthenticated = true logger.debug("DEBUGGING: authenticate callback: \(String(describing: laResult))")
canConnectViewCall = true switch (laResult) {
lastSuccessfulUnlock = ProcessInfo.processInfo.systemUptime case .success:
case .failed: userAuthorized = true
chatModel.contentViewAccessAuthenticated = false canConnectCall = true
if privacyLocalAuthModeDefault.get() == .passcode { lastSuccessfulUnlock = ProcessInfo.processInfo.systemUptime
AlertManager.shared.showAlert(laFailedAlert()) case .failed:
} if laMode == .passcode {
case .unavailable: AlertManager.shared.showAlert(laFailedAlert())
prefPerformLA = false
canConnectViewCall = true
AlertManager.shared.showAlert(laUnavailableTurningOffAlert())
} }
case .unavailable:
userAuthorized = true
prefPerformLA = false
canConnectCall = true
AlertManager.shared.showAlert(laUnavailableTurningOffAlert())
} }
} }
} }
@@ -297,7 +259,6 @@ struct ContentView: View {
authenticate(reason: NSLocalizedString("Enable SimpleX Lock", comment: "authentication reason")) { laResult in authenticate(reason: NSLocalizedString("Enable SimpleX Lock", comment: "authentication reason")) { laResult in
switch laResult { switch laResult {
case .success: case .success:
chatModel.contentViewAccessAuthenticated = true
prefPerformLA = true prefPerformLA = true
alertManager.showAlert(laTurnedOnAlert()) alertManager.showAlert(laTurnedOnAlert())
case .failed: case .failed:
+6 -28
View File
@@ -15,13 +15,7 @@ private let receiveTaskId = "chat.simplex.app.receive"
// TCP timeout + 2 sec // TCP timeout + 2 sec
private let waitForMessages: TimeInterval = 6 private let waitForMessages: TimeInterval = 6
// This is the smallest interval between refreshes, and also target interval in "off" mode private let bgRefreshInterval: TimeInterval = 450
private let bgRefreshInterval: TimeInterval = 600 // 10 minutes
// This intervals are used for background refresh in instant and periodic modes
private let periodicBgRefreshInterval: TimeInterval = 1200 // 20 minutes
private let maxBgRefreshInterval: TimeInterval = 2400 // 40 minutes
private let maxTimerCount = 9 private let maxTimerCount = 9
@@ -39,14 +33,14 @@ class BGManager {
} }
} }
func schedule(interval: TimeInterval? = nil) { func schedule() {
if !ChatModel.shared.ntfEnableLocal { if !ChatModel.shared.ntfEnableLocal {
logger.debug("BGManager.schedule: disabled") logger.debug("BGManager.schedule: disabled")
return return
} }
logger.debug("BGManager.schedule") logger.debug("BGManager.schedule")
let request = BGAppRefreshTaskRequest(identifier: receiveTaskId) let request = BGAppRefreshTaskRequest(identifier: receiveTaskId)
request.earliestBeginDate = Date(timeIntervalSinceNow: interval ?? runInterval) request.earliestBeginDate = Date(timeIntervalSinceNow: bgRefreshInterval)
do { do {
try BGTaskScheduler.shared.submit(request) try BGTaskScheduler.shared.submit(request)
} catch { } catch {
@@ -54,34 +48,20 @@ class BGManager {
} }
} }
var runInterval: TimeInterval {
switch ChatModel.shared.notificationMode {
case .instant: maxBgRefreshInterval
case .periodic: periodicBgRefreshInterval
case .off: bgRefreshInterval
}
}
var lastRanLongAgo: Bool {
Date.now.timeIntervalSince(chatLastBackgroundRunGroupDefault.get()) > runInterval
}
private func handleRefresh(_ task: BGAppRefreshTask) { private func handleRefresh(_ task: BGAppRefreshTask) {
if !ChatModel.shared.ntfEnableLocal { if !ChatModel.shared.ntfEnableLocal {
logger.debug("BGManager.handleRefresh: disabled") logger.debug("BGManager.handleRefresh: disabled")
return return
} }
logger.debug("BGManager.handleRefresh") logger.debug("BGManager.handleRefresh")
let shouldRun_ = lastRanLongAgo schedule()
if allowBackgroundRefresh() && shouldRun_ { if appStateGroupDefault.get().inactive {
schedule()
let completeRefresh = completionHandler { let completeRefresh = completionHandler {
task.setTaskCompleted(success: true) task.setTaskCompleted(success: true)
} }
task.expirationHandler = { completeRefresh("expirationHandler") } task.expirationHandler = { completeRefresh("expirationHandler") }
receiveMessages(completeRefresh) receiveMessages(completeRefresh)
} else { } else {
schedule(interval: shouldRun_ ? bgRefreshInterval : runInterval)
logger.debug("BGManager.completionHandler: already active, not started") logger.debug("BGManager.completionHandler: already active, not started")
task.setTaskCompleted(success: true) task.setTaskCompleted(success: true)
} }
@@ -110,22 +90,20 @@ class BGManager {
} }
self.completed = false self.completed = false
DispatchQueue.main.async { DispatchQueue.main.async {
chatLastBackgroundRunGroupDefault.set(Date.now)
let m = ChatModel.shared let m = ChatModel.shared
if (!m.chatInitialized) { if (!m.chatInitialized) {
setAppState(.bgRefresh)
do { do {
try initializeChat(start: true) try initializeChat(start: true)
} catch let error { } catch let error {
fatalError("Failed to start or load chats: \(responseError(error))") fatalError("Failed to start or load chats: \(responseError(error))")
} }
} }
activateChat(appState: .bgRefresh)
if m.currentUser == nil { if m.currentUser == nil {
completeReceiving("no current user") completeReceiving("no current user")
return return
} }
logger.debug("BGManager.receiveMessages: starting chat") logger.debug("BGManager.receiveMessages: starting chat")
activateChat(appState: .bgRefresh)
let cr = ChatReceiver() let cr = ChatReceiver()
self.chatReceiver = cr self.chatReceiver = cr
cr.start() cr.start()
+13 -41
View File
@@ -54,9 +54,6 @@ final class ChatModel: ObservableObject {
@Published var chatDbChanged = false @Published var chatDbChanged = false
@Published var chatDbEncrypted: Bool? @Published var chatDbEncrypted: Bool?
@Published var chatDbStatus: DBMigrationResult? @Published var chatDbStatus: DBMigrationResult?
@Published var ctrlInitInProgress: Bool = false
// local authentication
@Published var contentViewAccessAuthenticated: Bool = false
@Published var laRequest: LocalAuthRequest? @Published var laRequest: LocalAuthRequest?
// list of chat "previews" // list of chat "previews"
@Published var chats: [Chat] = [] @Published var chats: [Chat] = []
@@ -86,19 +83,18 @@ final class ChatModel: ObservableObject {
// current WebRTC call // current WebRTC call
@Published var callInvitations: Dictionary<ChatId, RcvCallInvitation> = [:] @Published var callInvitations: Dictionary<ChatId, RcvCallInvitation> = [:]
@Published var activeCall: Call? @Published var activeCall: Call?
let callCommand: WebRTCCommandProcessor = WebRTCCommandProcessor() @Published var callCommand: WCallCommand?
@Published var showCallView = false @Published var showCallView = false
// remote desktop // remote desktop
@Published var remoteCtrlSession: RemoteCtrlSession? @Published var remoteCtrlSession: RemoteCtrlSession?
// currently showing invitation // currently showing QR code
@Published var showingInvitation: ShowingInvitation? @Published var connReqInv: String?
// audio recording and playback // audio recording and playback
@Published var stopPreviousRecPlay: URL? = nil // coordinates currently playing source @Published var stopPreviousRecPlay: URL? = nil // coordinates currently playing source
@Published var draft: ComposeState? @Published var draft: ComposeState?
@Published var draftChatId: String? @Published var draftChatId: String?
// tracks keyboard height via subscription in AppDelegate // tracks keyboard height via subscription in AppDelegate
@Published var keyboardHeight: CGFloat = 0 @Published var keyboardHeight: CGFloat = 0
@Published var pasteboardHasStrings: Bool = UIPasteboard.general.hasStrings
var messageDelivery: Dictionary<Int64, () -> Void> = [:] var messageDelivery: Dictionary<Int64, () -> Void> = [:]
@@ -108,10 +104,12 @@ final class ChatModel: ObservableObject {
static var ok: Bool { ChatModel.shared.chatDbStatus == .ok } static var ok: Bool { ChatModel.shared.chatDbStatus == .ok }
let ntfEnableLocal = true var ntfEnableLocal: Bool {
notificationMode == .off || ntfEnableLocalGroupDefault.get()
}
var ntfEnablePeriodic: Bool { var ntfEnablePeriodic: Bool {
notificationMode != .off notificationMode == .periodic || ntfEnablePeriodicGroupDefault.get()
} }
var activeRemoteCtrl: Bool { var activeRemoteCtrl: Bool {
@@ -269,20 +267,7 @@ final class ChatModel: ObservableObject {
func addChatItem(_ cInfo: ChatInfo, _ cItem: ChatItem) { func addChatItem(_ cInfo: ChatInfo, _ cItem: ChatItem) {
// update previews // update previews
if let i = getChatIndex(cInfo.id) { if let i = getChatIndex(cInfo.id) {
chats[i].chatItems = switch cInfo { chats[i].chatItems = [cItem]
case .group:
if let currentPreviewItem = chats[i].chatItems.first {
if cItem.meta.itemTs >= currentPreviewItem.meta.itemTs {
[cItem]
} else {
[currentPreviewItem]
}
} else {
[cItem]
}
default:
[cItem]
}
if case .rcvNew = cItem.meta.itemStatus { if case .rcvNew = cItem.meta.itemStatus {
chats[i].chatStats.unreadCount = chats[i].chatStats.unreadCount + 1 chats[i].chatStats.unreadCount = chats[i].chatStats.unreadCount + 1
increaseUnreadCounter(user: currentUser!) increaseUnreadCounter(user: currentUser!)
@@ -622,16 +607,14 @@ final class ChatModel: ObservableObject {
} }
func dismissConnReqView(_ id: String) { func dismissConnReqView(_ id: String) {
if id == showingInvitation?.connId { if let connReqInv = connReqInv,
markShowingInvitationUsed() let c = getChat(id),
case let .contactConnection(contactConnection) = c.chatInfo,
connReqInv == contactConnection.connReqInv {
dismissAllSheets() dismissAllSheets()
} }
} }
func markShowingInvitationUsed() {
showingInvitation?.connChatUsed = true
}
func removeChat(_ id: String) { func removeChat(_ id: String) {
withAnimation { withAnimation {
chats.removeAll(where: { $0.id == id }) chats.removeAll(where: { $0.id == id })
@@ -708,11 +691,6 @@ final class ChatModel: ObservableObject {
} }
} }
struct ShowingInvitation {
var connId: String
var connChatUsed: Bool
}
struct NTFContactRequest { struct NTFContactRequest {
var incognito: Bool var incognito: Bool
var chatId: String var chatId: String
@@ -792,7 +770,7 @@ final class GMember: ObservableObject, Identifiable {
} }
struct RemoteCtrlSession { struct RemoteCtrlSession {
var ctrlAppInfo: CtrlAppInfo? var ctrlAppInfo: CtrlAppInfo
var appVersion: String var appVersion: String
var sessionState: UIRemoteCtrlSessionState var sessionState: UIRemoteCtrlSessionState
@@ -804,10 +782,6 @@ struct RemoteCtrlSession {
if case .connected = sessionState { true } else { false } if case .connected = sessionState { true } else { false }
} }
var discovery: Bool {
if case .searching = sessionState { true } else { false }
}
var sessionCode: String? { var sessionCode: String? {
switch sessionState { switch sessionState {
case let .pendingConfirmation(_, sessionCode): sessionCode case let .pendingConfirmation(_, sessionCode): sessionCode
@@ -819,8 +793,6 @@ struct RemoteCtrlSession {
enum UIRemoteCtrlSessionState { enum UIRemoteCtrlSessionState {
case starting case starting
case searching
case found(remoteCtrl: RemoteCtrlInfo, compatible: Bool)
case connecting(remoteCtrl_: RemoteCtrlInfo?) case connecting(remoteCtrl_: RemoteCtrlInfo?)
case pendingConfirmation(remoteCtrl_: RemoteCtrlInfo?, sessionCode: String) case pendingConfirmation(remoteCtrl_: RemoteCtrlInfo?, sessionCode: String)
case connected(remoteCtrl: RemoteCtrlInfo, sessionCode: String) case connected(remoteCtrl: RemoteCtrlInfo, sessionCode: String)
+4 -4
View File
@@ -195,18 +195,18 @@ func moveTempFileFromURL(_ url: URL) -> CryptoFile? {
} }
} }
func generateNewFileName(_ prefix: String, _ ext: String, fullPath: Bool = false) -> String { func generateNewFileName(_ prefix: String, _ ext: String) -> String {
uniqueCombine("\(prefix)_\(getTimestamp()).\(ext)", fullPath: fullPath) uniqueCombine("\(prefix)_\(getTimestamp()).\(ext)")
} }
private func uniqueCombine(_ fileName: String, fullPath: Bool = false) -> String { private func uniqueCombine(_ fileName: String) -> String {
func tryCombine(_ fileName: String, _ n: Int) -> String { func tryCombine(_ fileName: String, _ n: Int) -> String {
let ns = fileName as NSString let ns = fileName as NSString
let name = ns.deletingPathExtension let name = ns.deletingPathExtension
let ext = ns.pathExtension let ext = ns.pathExtension
let suffix = (n == 0) ? "" : "_\(n)" let suffix = (n == 0) ? "" : "_\(n)"
let f = "\(name)\(suffix).\(ext)" let f = "\(name)\(suffix).\(ext)"
return (FileManager.default.fileExists(atPath: fullPath ? f : getAppFilePath(f).path)) ? tryCombine(fileName, n + 1) : f return (FileManager.default.fileExists(atPath: getAppFilePath(f).path)) ? tryCombine(fileName, n + 1) : f
} }
return tryCombine(fileName, 0) return tryCombine(fileName, 0)
} }
-83
View File
@@ -1,83 +0,0 @@
//
// NSESubscriber.swift
// SimpleXChat
//
// Created by Evgeny on 09/12/2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import Foundation
import SimpleXChat
private var nseSubscribers: [UUID:NSESubscriber] = [:]
// timeout for active notification service extension going into "suspending" state.
// If in two seconds the state does not change, we assume that it was not running and proceed with app activation/answering call.
private let SUSPENDING_TIMEOUT: TimeInterval = 2
// timeout should be larger than SUSPENDING_TIMEOUT
func waitNSESuspended(timeout: TimeInterval, suspended: @escaping (Bool) -> Void) {
if timeout <= SUSPENDING_TIMEOUT {
logger.warning("waitNSESuspended: small timeout \(timeout), using \(SUSPENDING_TIMEOUT + 1)")
}
var state = nseStateGroupDefault.get()
if case .suspended = state {
DispatchQueue.main.async { suspended(true) }
return
}
let id = UUID()
var suspendedCalled = false
checkTimeout()
nseSubscribers[id] = nseMessageSubscriber { msg in
if case let .state(newState) = msg {
state = newState
logger.debug("waitNSESuspended state: \(state.rawValue)")
if case .suspended = newState {
notifySuspended(true)
}
}
}
return
func notifySuspended(_ ok: Bool) {
logger.debug("waitNSESuspended notifySuspended: \(ok)")
if !suspendedCalled {
logger.debug("waitNSESuspended notifySuspended: calling suspended(\(ok))")
suspendedCalled = true
nseSubscribers.removeValue(forKey: id)
DispatchQueue.main.async { suspended(ok) }
}
}
func checkTimeout() {
if !suspending() {
checkSuspendingTimeout()
} else if state == .suspending {
checkSuspendedTimeout()
}
}
func suspending() -> Bool {
suspendedCalled || state == .suspended || state == .suspending
}
func checkSuspendingTimeout() {
DispatchQueue.global().asyncAfter(deadline: .now() + SUSPENDING_TIMEOUT) {
logger.debug("waitNSESuspended check suspending timeout")
if !suspending() {
notifySuspended(false)
} else if state != .suspended {
checkSuspendedTimeout()
}
}
}
func checkSuspendedTimeout() {
DispatchQueue.global().asyncAfter(deadline: .now() + min(timeout - SUSPENDING_TIMEOUT, 1)) {
logger.debug("waitNSESuspended check suspended timeout")
if state != .suspended {
notifySuspended(false)
}
}
}
}
+47 -96
View File
@@ -211,7 +211,7 @@ func apiDeleteUser(_ userId: Int64, _ delSMPQueues: Bool, viewPwd: String?) asyn
} }
func apiStartChat() throws -> Bool { func apiStartChat() throws -> Bool {
let r = chatSendCmdSync(.startChat(mainApp: true)) let r = chatSendCmdSync(.startChat(subscribe: true, expire: true, xftp: true))
switch r { switch r {
case .chatStarted: return true case .chatStarted: return true
case .chatRunning: return false case .chatRunning: return false
@@ -228,8 +228,7 @@ func apiStopChat() async throws {
} }
func apiActivateChat() { func apiActivateChat() {
chatReopenStore() let r = chatSendCmdSync(.apiActivateChat)
let r = chatSendCmdSync(.apiActivateChat(restoreChat: true))
if case .cmdOk = r { return } if case .cmdOk = r { return }
logger.error("apiActivateChat error: \(String(describing: r))") logger.error("apiActivateChat error: \(String(describing: r))")
} }
@@ -403,7 +402,7 @@ func apiGetNtfToken() -> (DeviceToken?, NtfTknStatus?, NotificationsMode) {
case let .ntfToken(token, status, ntfMode): return (token, status, ntfMode) case let .ntfToken(token, status, ntfMode): return (token, status, ntfMode)
case .chatCmdError(_, .errorAgent(.CMD(.PROHIBITED))): return (nil, nil, .off) case .chatCmdError(_, .errorAgent(.CMD(.PROHIBITED))): return (nil, nil, .off)
default: default:
logger.debug("apiGetNtfToken response: \(String(describing: r))") logger.debug("apiGetNtfToken response: \(String(describing: r), privacy: .public)")
return (nil, nil, .off) return (nil, nil, .off)
} }
} }
@@ -581,15 +580,15 @@ func apiVerifyGroupMember(_ groupId: Int64, _ groupMemberId: Int64, connectionCo
return nil return nil
} }
func apiAddContact(incognito: Bool) async -> ((String, PendingContactConnection)?, Alert?) { func apiAddContact(incognito: Bool) async -> (String, PendingContactConnection)? {
guard let userId = ChatModel.shared.currentUser?.userId else { guard let userId = ChatModel.shared.currentUser?.userId else {
logger.error("apiAddContact: no current user") logger.error("apiAddContact: no current user")
return (nil, nil) return nil
} }
let r = await chatSendCmd(.apiAddContact(userId: userId, incognito: incognito), bgTask: false) let r = await chatSendCmd(.apiAddContact(userId: userId, incognito: incognito), bgTask: false)
if case let .invitation(_, connReqInvitation, connection) = r { return ((connReqInvitation, connection), nil) } if case let .invitation(_, connReqInvitation, connection) = r { return (connReqInvitation, connection) }
let alert = connectionErrorAlert(r) AlertManager.shared.showAlert(connectionErrorAlert(r))
return (nil, alert) return nil
} }
func apiSetConnectionIncognito(connId: Int64, incognito: Bool) async throws -> PendingContactConnection? { func apiSetConnectionIncognito(connId: Int64, incognito: Bool) async throws -> PendingContactConnection? {
@@ -606,29 +605,27 @@ func apiConnectPlan(connReq: String) async throws -> ConnectionPlan {
throw r throw r
} }
func apiConnect(incognito: Bool, connReq: String) async -> (ConnReqType, PendingContactConnection)? { func apiConnect(incognito: Bool, connReq: String) async -> ConnReqType? {
let (r, alert) = await apiConnect_(incognito: incognito, connReq: connReq) let (connReqType, alert) = await apiConnect_(incognito: incognito, connReq: connReq)
if let alert = alert { if let alert = alert {
AlertManager.shared.showAlert(alert) AlertManager.shared.showAlert(alert)
return nil return nil
} else { } else {
return r return connReqType
} }
} }
func apiConnect_(incognito: Bool, connReq: String) async -> ((ConnReqType, PendingContactConnection)?, Alert?) { func apiConnect_(incognito: Bool, connReq: String) async -> (ConnReqType?, Alert?) {
guard let userId = ChatModel.shared.currentUser?.userId else { guard let userId = ChatModel.shared.currentUser?.userId else {
logger.error("apiConnect: no current user") logger.error("apiConnect: no current user")
return (nil, nil) return (nil, nil)
} }
let r = await chatSendCmd(.apiConnect(userId: userId, incognito: incognito, connReq: connReq)) let r = await chatSendCmd(.apiConnect(userId: userId, incognito: incognito, connReq: connReq))
let m = ChatModel.shared
switch r { switch r {
case let .sentConfirmation(_, connection): case .sentConfirmation: return (.invitation, nil)
return ((.invitation, connection), nil) case .sentInvitation: return (.contact, nil)
case let .sentInvitation(_, connection):
return ((.contact, connection), nil)
case let .contactAlreadyExists(_, contact): case let .contactAlreadyExists(_, contact):
let m = ChatModel.shared
if let c = m.getContactChat(contact.contactId) { if let c = m.getContactChat(contact.contactId) {
await MainActor.run { m.chatId = c.id } await MainActor.run { m.chatId = c.id }
} }
@@ -922,10 +919,8 @@ func findKnownRemoteCtrl() async throws {
try await sendCommandOkResp(.findKnownRemoteCtrl) try await sendCommandOkResp(.findKnownRemoteCtrl)
} }
func confirmRemoteCtrl(_ rcId: Int64) async throws -> (RemoteCtrlInfo?, CtrlAppInfo, String) { func confirmRemoteCtrl(_ rcId: Int64) async throws {
let r = await chatSendCmd(.confirmRemoteCtrl(remoteCtrlId: rcId)) try await sendCommandOkResp(.confirmRemoteCtrl(remoteCtrlId: rcId))
if case let .remoteCtrlConnecting(rc_, ctrlAppInfo, v) = r { return (rc_, ctrlAppInfo, v) }
throw r
} }
func verifyRemoteCtrlSession(_ sessCode: String) async throws -> RemoteCtrlInfo { func verifyRemoteCtrlSession(_ sessCode: String) async throws -> RemoteCtrlInfo {
@@ -1212,11 +1207,9 @@ private func currentUserId(_ funcName: String) throws -> Int64 {
throw RuntimeError("\(funcName): no current user") throw RuntimeError("\(funcName): no current user")
} }
func initializeChat(start: Bool, confirmStart: Bool = false, dbKey: String? = nil, refreshInvitations: Bool = true, confirmMigrations: MigrationConfirmation? = nil) throws { func initializeChat(start: Bool, dbKey: String? = nil, refreshInvitations: Bool = true, confirmMigrations: MigrationConfirmation? = nil) throws {
logger.debug("initializeChat") logger.debug("initializeChat")
let m = ChatModel.shared let m = ChatModel.shared
m.ctrlInitInProgress = true
defer { m.ctrlInitInProgress = false }
(m.chatDbEncrypted, m.chatDbStatus) = chatMigrateInit(dbKey, confirmMigrations: confirmMigrations) (m.chatDbEncrypted, m.chatDbStatus) = chatMigrateInit(dbKey, confirmMigrations: confirmMigrations)
if m.chatDbStatus != .ok { return } if m.chatDbStatus != .ok { return }
// If we migrated successfully means previous re-encryption process on database level finished successfully too // If we migrated successfully means previous re-encryption process on database level finished successfully too
@@ -1233,43 +1226,10 @@ func initializeChat(start: Bool, confirmStart: Bool = false, dbKey: String? = ni
onboardingStageDefault.set(.step1_SimpleXInfo) onboardingStageDefault.set(.step1_SimpleXInfo)
privacyDeliveryReceiptsSet.set(true) privacyDeliveryReceiptsSet.set(true)
m.onboardingStage = .step1_SimpleXInfo m.onboardingStage = .step1_SimpleXInfo
} else if confirmStart { } else if start {
showStartChatAfterRestartAlert { start in
do {
if start { AppChatState.shared.set(.active) }
try chatInitialized(start: start, refreshInvitations: refreshInvitations)
} catch let error {
logger.error("ChatInitialized error: \(error)")
}
}
} else {
try chatInitialized(start: start, refreshInvitations: refreshInvitations)
}
}
func showStartChatAfterRestartAlert(result: @escaping (_ start: Bool) -> Void) {
AlertManager.shared.showAlert(Alert(
title: Text("Start chat?"),
message: Text("Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat."),
primaryButton: .default(Text("Ok")) {
result(true)
},
secondaryButton: .cancel {
result(false)
}
))
}
private func chatInitialized(start: Bool, refreshInvitations: Bool) throws {
let m = ChatModel.shared
if m.currentUser == nil { return }
if start {
try startChat(refreshInvitations: refreshInvitations) try startChat(refreshInvitations: refreshInvitations)
} else { } else {
m.chatRunning = false m.chatRunning = false
try getUserChatData()
NtfManager.shared.setNtfBadgeCount(m.totalUnreadCountForAllUsers())
m.onboardingStage = onboardingStageDefault.get()
} }
} }
@@ -1286,8 +1246,6 @@ func startChat(refreshInvitations: Bool = true) throws {
try refreshCallInvitations() try refreshCallInvitations()
} }
(m.savedToken, m.tokenStatus, m.notificationMode) = apiGetNtfToken() (m.savedToken, m.tokenStatus, m.notificationMode) = apiGetNtfToken()
// deviceToken is set when AppDelegate.application(didRegisterForRemoteNotificationsWithDeviceToken:) is called,
// when it is called before startChat
if let token = m.deviceToken { if let token = m.deviceToken {
registerToken(token: token) registerToken(token: token)
} }
@@ -1402,6 +1360,18 @@ func processReceivedMsg(_ res: ChatResponse) async {
let m = ChatModel.shared let m = ChatModel.shared
logger.debug("processReceivedMsg: \(res.responseType)") logger.debug("processReceivedMsg: \(res.responseType)")
switch res { switch res {
case let .newContactConnection(user, connection):
if active(user) {
await MainActor.run {
m.updateContactConnection(connection)
}
}
case let .contactConnectionDeleted(user, connection):
if active(user) {
await MainActor.run {
m.removeChat(connection.id)
}
}
case let .contactDeletedByContact(user, contact): case let .contactDeletedByContact(user, contact):
if active(user) && contact.directOrUsed { if active(user) && contact.directOrUsed {
await MainActor.run { await MainActor.run {
@@ -1694,40 +1664,36 @@ func processReceivedMsg(_ res: ChatResponse) async {
activateCall(invitation) activateCall(invitation)
case let .callOffer(_, contact, callType, offer, sharedKey, _): case let .callOffer(_, contact, callType, offer, sharedKey, _):
await withCall(contact) { call in await withCall(contact) { call in
await MainActor.run { call.callState = .offerReceived
call.callState = .offerReceived call.peerMedia = callType.media
call.peerMedia = callType.media call.sharedKey = sharedKey
call.sharedKey = sharedKey
}
let useRelay = UserDefaults.standard.bool(forKey: DEFAULT_WEBRTC_POLICY_RELAY) let useRelay = UserDefaults.standard.bool(forKey: DEFAULT_WEBRTC_POLICY_RELAY)
let iceServers = getIceServers() let iceServers = getIceServers()
logger.debug(".callOffer useRelay \(useRelay)") logger.debug(".callOffer useRelay \(useRelay)")
logger.debug(".callOffer iceServers \(String(describing: iceServers))") logger.debug(".callOffer iceServers \(String(describing: iceServers))")
await m.callCommand.processCommand(.offer( m.callCommand = .offer(
offer: offer.rtcSession, offer: offer.rtcSession,
iceCandidates: offer.rtcIceCandidates, iceCandidates: offer.rtcIceCandidates,
media: callType.media, aesKey: sharedKey, media: callType.media, aesKey: sharedKey,
iceServers: iceServers, iceServers: iceServers,
relay: useRelay relay: useRelay
)) )
} }
case let .callAnswer(_, contact, answer): case let .callAnswer(_, contact, answer):
await withCall(contact) { call in await withCall(contact) { call in
await MainActor.run { call.callState = .answerReceived
call.callState = .answerReceived m.callCommand = .answer(answer: answer.rtcSession, iceCandidates: answer.rtcIceCandidates)
}
await m.callCommand.processCommand(.answer(answer: answer.rtcSession, iceCandidates: answer.rtcIceCandidates))
} }
case let .callExtraInfo(_, contact, extraInfo): case let .callExtraInfo(_, contact, extraInfo):
await withCall(contact) { _ in await withCall(contact) { _ in
await m.callCommand.processCommand(.ice(iceCandidates: extraInfo.rtcIceCandidates)) m.callCommand = .ice(iceCandidates: extraInfo.rtcIceCandidates)
} }
case let .callEnded(_, contact): case let .callEnded(_, contact):
if let invitation = await MainActor.run(body: { m.callInvitations.removeValue(forKey: contact.id) }) { if let invitation = await MainActor.run(body: { m.callInvitations.removeValue(forKey: contact.id) }) {
CallController.shared.reportCallRemoteEnded(invitation: invitation) CallController.shared.reportCallRemoteEnded(invitation: invitation)
} }
await withCall(contact) { call in await withCall(contact) { call in
await m.callCommand.processCommand(.end) m.callCommand = .end
CallController.shared.reportCallRemoteEnded(call: call) CallController.shared.reportCallRemoteEnded(call: call)
} }
case .chatSuspended: case .chatSuspended:
@@ -1748,17 +1714,9 @@ func processReceivedMsg(_ res: ChatResponse) async {
await MainActor.run { await MainActor.run {
m.updateGroupMemberConnectionStats(groupInfo, member, ratchetSyncProgress.connectionStats) m.updateGroupMemberConnectionStats(groupInfo, member, ratchetSyncProgress.connectionStats)
} }
case let .remoteCtrlFound(remoteCtrl, ctrlAppInfo_, appVersion, compatible): case let .remoteCtrlFound(remoteCtrl):
await MainActor.run { // TODO multicast
if let sess = m.remoteCtrlSession, case .searching = sess.sessionState { logger.debug("\(String(describing: remoteCtrl))")
let state = UIRemoteCtrlSessionState.found(remoteCtrl: remoteCtrl, compatible: compatible)
m.remoteCtrlSession = RemoteCtrlSession(
ctrlAppInfo: ctrlAppInfo_,
appVersion: appVersion,
sessionState: state
)
}
}
case let .remoteCtrlSessionCode(remoteCtrl_, sessionCode): case let .remoteCtrlSessionCode(remoteCtrl_, sessionCode):
await MainActor.run { await MainActor.run {
let state = UIRemoteCtrlSessionState.pendingConfirmation(remoteCtrl_: remoteCtrl_, sessionCode: sessionCode) let state = UIRemoteCtrlSessionState.pendingConfirmation(remoteCtrl_: remoteCtrl_, sessionCode: sessionCode)
@@ -1773,23 +1731,16 @@ func processReceivedMsg(_ res: ChatResponse) async {
case .remoteCtrlStopped: case .remoteCtrlStopped:
// This delay is needed to cancel the session that fails on network failure, // This delay is needed to cancel the session that fails on network failure,
// e.g. when user did not grant permission to access local network yet. // e.g. when user did not grant permission to access local network yet.
if let sess = m.remoteCtrlSession { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
await MainActor.run { switchToLocalSession()
m.remoteCtrlSession = nil
}
if case .connected = sess.sessionState {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
switchToLocalSession()
}
}
} }
default: default:
logger.debug("unsupported event: \(res.responseType)") logger.debug("unsupported event: \(res.responseType)")
} }
func withCall(_ contact: Contact, _ perform: (Call) async -> Void) async { func withCall(_ contact: Contact, _ perform: (Call) -> Void) async {
if let call = m.activeCall, call.contact.apiId == contact.apiId { if let call = m.activeCall, call.contact.apiId == contact.apiId {
await perform(call) await MainActor.run { perform(call) }
} else { } else {
logger.debug("processReceivedMsg: ignoring \(res.responseType), not in call with the contact \(contact.id)") logger.debug("processReceivedMsg: ignoring \(res.responseType), not in call with the contact \(contact.id)")
} }
+24 -87
View File
@@ -9,30 +9,27 @@
import Foundation import Foundation
import UIKit import UIKit
import SimpleXChat import SimpleXChat
import SwiftUI
private let suspendLockQueue = DispatchQueue(label: "chat.simplex.app.suspend.lock") private let suspendLockQueue = DispatchQueue(label: "chat.simplex.app.suspend.lock")
let appSuspendTimeout: Int = 15 // seconds
let bgSuspendTimeout: Int = 5 // seconds let bgSuspendTimeout: Int = 5 // seconds
let terminationTimeout: Int = 3 // seconds let terminationTimeout: Int = 3 // seconds
let activationDelay: TimeInterval = 1.5
let nseSuspendTimeout: TimeInterval = 5
private func _suspendChat(timeout: Int) { private func _suspendChat(timeout: Int) {
// this is a redundant check to prevent logical errors, like the one fixed in this PR // this is a redundant check to prevent logical errors, like the one fixed in this PR
let state = AppChatState.shared.value let state = appStateGroupDefault.get()
if !state.canSuspend { if !state.canSuspend {
logger.error("_suspendChat called, current state: \(state.rawValue)") logger.error("_suspendChat called, current state: \(state.rawValue, privacy: .public)")
} else if ChatModel.ok { } else if ChatModel.ok {
AppChatState.shared.set(.suspending) appStateGroupDefault.set(.suspending)
apiSuspendChat(timeoutMicroseconds: timeout * 1000000) apiSuspendChat(timeoutMicroseconds: timeout * 1000000)
let endTask = beginBGTask(chatSuspended) let endTask = beginBGTask(chatSuspended)
DispatchQueue.global().asyncAfter(deadline: .now() + Double(timeout) + 1, execute: endTask) DispatchQueue.global().asyncAfter(deadline: .now() + Double(timeout) + 1, execute: endTask)
} else { } else {
AppChatState.shared.set(.suspended) appStateGroupDefault.set(.suspended)
} }
} }
@@ -44,16 +41,18 @@ func suspendChat() {
func suspendBgRefresh() { func suspendBgRefresh() {
suspendLockQueue.sync { suspendLockQueue.sync {
if case .bgRefresh = AppChatState.shared.value { if case .bgRefresh = appStateGroupDefault.get() {
_suspendChat(timeout: bgSuspendTimeout) _suspendChat(timeout: bgSuspendTimeout)
} }
} }
} }
private var terminating = false
func terminateChat() { func terminateChat() {
logger.debug("terminateChat") logger.debug("terminateChat")
suspendLockQueue.sync { suspendLockQueue.sync {
switch AppChatState.shared.value { switch appStateGroupDefault.get() {
case .suspending: case .suspending:
// suspend instantly if already suspending // suspend instantly if already suspending
_chatSuspended() _chatSuspended()
@@ -65,6 +64,7 @@ func terminateChat() {
case .stopped: case .stopped:
chatCloseStore() chatCloseStore()
default: default:
terminating = true
// the store will be closed in _chatSuspended when event is received // the store will be closed in _chatSuspended when event is received
_suspendChat(timeout: terminationTimeout) _suspendChat(timeout: terminationTimeout)
} }
@@ -73,7 +73,7 @@ func terminateChat() {
func chatSuspended() { func chatSuspended() {
suspendLockQueue.sync { suspendLockQueue.sync {
if case .suspending = AppChatState.shared.value { if case .suspending = appStateGroupDefault.get() {
_chatSuspended() _chatSuspended()
} }
} }
@@ -81,111 +81,48 @@ func chatSuspended() {
private func _chatSuspended() { private func _chatSuspended() {
logger.debug("_chatSuspended") logger.debug("_chatSuspended")
AppChatState.shared.set(.suspended) appStateGroupDefault.set(.suspended)
if ChatModel.shared.chatRunning == true { if ChatModel.shared.chatRunning == true {
ChatReceiver.shared.stop() ChatReceiver.shared.stop()
} }
chatCloseStore() if terminating {
} chatCloseStore()
func setAppState(_ appState: AppState) {
suspendLockQueue.sync {
AppChatState.shared.set(appState)
} }
} }
func activateChat(appState: AppState = .active) { func activateChat(appState: AppState = .active) {
logger.debug("DEBUGGING: activateChat") logger.debug("DEBUGGING: activateChat")
terminating = false
suspendLockQueue.sync { suspendLockQueue.sync {
AppChatState.shared.set(appState) appStateGroupDefault.set(appState)
if ChatModel.ok { apiActivateChat() } if ChatModel.ok { apiActivateChat() }
logger.debug("DEBUGGING: activateChat: after apiActivateChat") logger.debug("DEBUGGING: activateChat: after apiActivateChat")
} }
} }
func initChatAndMigrate(refreshInvitations: Bool = true) { func initChatAndMigrate(refreshInvitations: Bool = true) {
terminating = false
let m = ChatModel.shared let m = ChatModel.shared
if (!m.chatInitialized) { if (!m.chatInitialized) {
m.v3DBMigration = v3DBMigrationDefault.get()
if AppChatState.shared.value == .stopped && storeDBPassphraseGroupDefault.get() && kcDatabasePassword.get() != nil {
initialize(start: true, confirmStart: true)
} else {
initialize(start: true)
}
}
func initialize(start: Bool, confirmStart: Bool = false) {
do { do {
try initializeChat(start: m.v3DBMigration.startChat && start, confirmStart: m.v3DBMigration.startChat && confirmStart, refreshInvitations: refreshInvitations) m.v3DBMigration = v3DBMigrationDefault.get()
try initializeChat(start: m.v3DBMigration.startChat, refreshInvitations: refreshInvitations)
} catch let error { } catch let error {
AlertManager.shared.showAlertMsg( fatalError("Failed to start or load chats: \(responseError(error))")
title: start ? "Error starting chat" : "Error opening chat",
message: "Please contact developers.\nError: \(responseError(error))"
)
} }
} }
} }
func startChatForCall() { func startChatAndActivate() {
logger.debug("DEBUGGING: startChatForCall") terminating = false
if ChatModel.shared.chatRunning == true {
ChatReceiver.shared.start()
logger.debug("DEBUGGING: startChatForCall: after ChatReceiver.shared.start")
}
if .active != AppChatState.shared.value {
logger.debug("DEBUGGING: startChatForCall: before activateChat")
activateChat()
logger.debug("DEBUGGING: startChatForCall: after activateChat")
}
}
func startChatAndActivate(_ completion: @escaping () -> Void) {
logger.debug("DEBUGGING: startChatAndActivate") logger.debug("DEBUGGING: startChatAndActivate")
if ChatModel.shared.chatRunning == true { if ChatModel.shared.chatRunning == true {
ChatReceiver.shared.start() ChatReceiver.shared.start()
logger.debug("DEBUGGING: startChatAndActivate: after ChatReceiver.shared.start") logger.debug("DEBUGGING: startChatAndActivate: after ChatReceiver.shared.start")
} }
if case .active = AppChatState.shared.value { if .active != appStateGroupDefault.get() {
completion()
} else if nseStateGroupDefault.get().inactive {
activate()
} else {
// setting app state to "activating" to notify NSE that it should suspend
setAppState(.activating)
waitNSESuspended(timeout: nseSuspendTimeout) { ok in
if !ok {
// if for some reason NSE failed to suspend,
// e.g., it crashed previously without setting its state to "suspended",
// set it to "suspended" state anyway, so that next time app
// does not have to wait when activating.
nseStateGroupDefault.set(.suspended)
}
if AppChatState.shared.value == .activating {
activate()
}
}
}
func activate() {
logger.debug("DEBUGGING: startChatAndActivate: before activateChat") logger.debug("DEBUGGING: startChatAndActivate: before activateChat")
activateChat() activateChat()
completion()
logger.debug("DEBUGGING: startChatAndActivate: after activateChat") logger.debug("DEBUGGING: startChatAndActivate: after activateChat")
} }
} }
// appStateGroupDefault must not be used in the app directly, only via this singleton
class AppChatState {
static let shared = AppChatState()
private var value_ = appStateGroupDefault.get()
var value: AppState {
value_
}
func set(_ state: AppState) {
appStateGroupDefault.set(state)
sendAppState(state)
value_ = state
}
}
+45 -37
View File
@@ -16,15 +16,17 @@ struct SimpleXApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@StateObject private var chatModel = ChatModel.shared @StateObject private var chatModel = ChatModel.shared
@ObservedObject var alertManager = AlertManager.shared @ObservedObject var alertManager = AlertManager.shared
@Environment(\.scenePhase) var scenePhase @Environment(\.scenePhase) var scenePhase
@State private var enteredBackgroundAuthenticated: TimeInterval? = nil @AppStorage(DEFAULT_PERFORM_LA) private var prefPerformLA = false
@State private var userAuthorized: Bool?
@State private var doAuthenticate = false
@State private var enteredBackground: TimeInterval? = nil
@State private var canConnectCall = false
@State private var lastSuccessfulUnlock: TimeInterval? = nil
@State private var showInitializationView = false
init() { init() {
DispatchQueue.global(qos: .background).sync { hs_init(0, nil)
haskell_init()
// hs_init(0, nil)
}
UserDefaults.standard.register(defaults: appDefaults) UserDefaults.standard.register(defaults: appDefaults)
setGroupDefaults() setGroupDefaults()
registerGroupDefaults() registerGroupDefaults()
@@ -34,55 +36,53 @@ struct SimpleXApp: App {
} }
var body: some Scene { var body: some Scene {
WindowGroup { return WindowGroup {
// contentAccessAuthenticationExtended has to be passed to ContentView on view initialization, ContentView(
// so that it's computed by the time view renders, and not on event after rendering doAuthenticate: $doAuthenticate,
ContentView(contentAccessAuthenticationExtended: !authenticationExpired()) userAuthorized: $userAuthorized,
canConnectCall: $canConnectCall,
lastSuccessfulUnlock: $lastSuccessfulUnlock,
showInitializationView: $showInitializationView
)
.environmentObject(chatModel) .environmentObject(chatModel)
.onOpenURL { url in .onOpenURL { url in
logger.debug("ContentView.onOpenURL: \(url)") logger.debug("ContentView.onOpenURL: \(url)")
chatModel.appOpenUrl = url chatModel.appOpenUrl = url
} }
.onAppear() { .onAppear() {
if kcAppPassword.get() == nil || kcSelfDestructPassword.get() == nil { showInitializationView = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
initChatAndMigrate() initChatAndMigrate()
}
} }
} }
.onChange(of: scenePhase) { phase in .onChange(of: scenePhase) { phase in
logger.debug("scenePhase was \(String(describing: scenePhase)), now \(String(describing: phase))") logger.debug("scenePhase was \(String(describing: scenePhase)), now \(String(describing: phase))")
switch (phase) { switch (phase) {
case .background: case .background:
// --- authentication
// see ContentView .onChange(of: scenePhase) for remaining authentication logic
if chatModel.contentViewAccessAuthenticated {
enteredBackgroundAuthenticated = ProcessInfo.processInfo.systemUptime
}
chatModel.contentViewAccessAuthenticated = false
// authentication ---
if CallController.useCallKit() && chatModel.activeCall != nil { if CallController.useCallKit() && chatModel.activeCall != nil {
CallController.shared.shouldSuspendChat = true CallController.shared.shouldSuspendChat = true
} else { } else {
suspendChat() suspendChat()
BGManager.shared.schedule() BGManager.shared.schedule()
} }
if userAuthorized == true {
enteredBackground = ProcessInfo.processInfo.systemUptime
}
doAuthenticate = false
canConnectCall = false
NtfManager.shared.setNtfBadgeCount(chatModel.totalUnreadCountForAllUsers()) NtfManager.shared.setNtfBadgeCount(chatModel.totalUnreadCountForAllUsers())
case .active: case .active:
CallController.shared.shouldSuspendChat = false CallController.shared.shouldSuspendChat = false
let appState = AppChatState.shared.value let appState = appStateGroupDefault.get()
startChatAndActivate()
if appState != .stopped { if appState.inactive && chatModel.chatRunning == true {
startChatAndActivate { updateChats()
if appState.inactive && chatModel.chatRunning == true { if !chatModel.showCallView && !CallController.shared.hasActiveCalls() {
updateChats() updateCallInvitations()
if !chatModel.showCallView && !CallController.shared.hasActiveCalls() {
updateCallInvitations()
}
}
} }
} }
doAuthenticate = authenticationExpired()
canConnectCall = !(doAuthenticate && prefPerformLA) || unlockedRecently()
default: default:
break break
} }
@@ -100,12 +100,12 @@ struct SimpleXApp: App {
if legacyDatabase, case .documents = dbContainerGroupDefault.get() { if legacyDatabase, case .documents = dbContainerGroupDefault.get() {
dbContainerGroupDefault.set(.documents) dbContainerGroupDefault.set(.documents)
setMigrationState(.offer) setMigrationState(.offer)
logger.debug("SimpleXApp init: using legacy DB in documents folder: \(getAppDatabasePath())*.db") logger.debug("SimpleXApp init: using legacy DB in documents folder: \(getAppDatabasePath(), privacy: .public)*.db")
} else { } else {
dbContainerGroupDefault.set(.group) dbContainerGroupDefault.set(.group)
setMigrationState(.ready) setMigrationState(.ready)
logger.debug("SimpleXApp init: using DB in app group container: \(getAppDatabasePath())*.db") logger.debug("SimpleXApp init: using DB in app group container: \(getAppDatabasePath(), privacy: .public)*.db")
logger.debug("SimpleXApp init: legacy DB\(legacyDatabase ? "" : " not") present") logger.debug("SimpleXApp init: legacy DB\(legacyDatabase ? "" : " not", privacy: .public) present")
} }
} }
@@ -115,14 +115,22 @@ struct SimpleXApp: App {
} }
private func authenticationExpired() -> Bool { private func authenticationExpired() -> Bool {
if let enteredBackgroundAuthenticated = enteredBackgroundAuthenticated { if let enteredBackground = enteredBackground {
let delay = Double(UserDefaults.standard.integer(forKey: DEFAULT_LA_LOCK_DELAY)) let delay = Double(UserDefaults.standard.integer(forKey: DEFAULT_LA_LOCK_DELAY))
return ProcessInfo.processInfo.systemUptime - enteredBackgroundAuthenticated >= delay return ProcessInfo.processInfo.systemUptime - enteredBackground >= delay
} else { } else {
return true return true
} }
} }
private func unlockedRecently() -> Bool {
if let lastSuccessfulUnlock = lastSuccessfulUnlock {
return ProcessInfo.processInfo.systemUptime - lastSuccessfulUnlock < 2
} else {
return false
}
}
private func updateChats() { private func updateChats() {
do { do {
let chats = try apiGetChats() let chats = try apiGetChats()
@@ -38,21 +38,21 @@ struct ActiveCallView: View {
} }
} }
.onAppear { .onAppear {
logger.debug("ActiveCallView: appear client is nil \(client == nil), scenePhase \(String(describing: scenePhase)), canConnectCall \(canConnectCall)") logger.debug("ActiveCallView: appear client is nil \(client == nil), scenePhase \(String(describing: scenePhase), privacy: .public), canConnectCall \(canConnectCall)")
AppDelegate.keepScreenOn(true) AppDelegate.keepScreenOn(true)
createWebRTCClient() createWebRTCClient()
dismissAllSheets() dismissAllSheets()
} }
.onChange(of: canConnectCall) { _ in .onChange(of: canConnectCall) { _ in
logger.debug("ActiveCallView: canConnectCall changed to \(canConnectCall)") logger.debug("ActiveCallView: canConnectCall changed to \(canConnectCall, privacy: .public)")
createWebRTCClient() createWebRTCClient()
} }
.onDisappear { .onDisappear {
logger.debug("ActiveCallView: disappear") logger.debug("ActiveCallView: disappear")
Task { await m.callCommand.setClient(nil) }
AppDelegate.keepScreenOn(false) AppDelegate.keepScreenOn(false)
client?.endCall() client?.endCall()
} }
.onChange(of: m.callCommand) { _ in sendCommandToClient()}
.background(.black) .background(.black)
.preferredColorScheme(.dark) .preferredColorScheme(.dark)
} }
@@ -60,8 +60,19 @@ struct ActiveCallView: View {
private func createWebRTCClient() { private func createWebRTCClient() {
if client == nil && canConnectCall { if client == nil && canConnectCall {
client = WebRTCClient($activeCall, { msg in await MainActor.run { processRtcMessage(msg: msg) } }, $localRendererAspectRatio) client = WebRTCClient($activeCall, { msg in await MainActor.run { processRtcMessage(msg: msg) } }, $localRendererAspectRatio)
sendCommandToClient()
}
}
private func sendCommandToClient() {
if call == m.activeCall,
m.activeCall != nil,
let client = client,
let cmd = m.callCommand {
m.callCommand = nil
logger.debug("sendCallCommand: \(cmd.cmdType)")
Task { Task {
await m.callCommand.setClient(client) await client.sendCallCommand(command: cmd)
} }
} }
} }
@@ -157,10 +168,8 @@ struct ActiveCallView: View {
} }
case let .error(message): case let .error(message):
logger.debug("ActiveCallView: command error: \(message)") logger.debug("ActiveCallView: command error: \(message)")
AlertManager.shared.showAlert(Alert(title: Text("Error"), message: Text(message)))
case let .invalid(type): case let .invalid(type):
logger.debug("ActiveCallView: invalid response: \(type)") logger.debug("ActiveCallView: invalid response: \(type)")
AlertManager.shared.showAlert(Alert(title: Text("Invalid response"), message: Text(type)))
} }
} }
} }
@@ -246,6 +255,7 @@ struct ActiveCallOverlay: View {
HStack { HStack {
Text(call.encryptionStatus) Text(call.encryptionStatus)
if let connInfo = call.connectionInfo { if let connInfo = call.connectionInfo {
// Text("(") + Text(connInfo.text) + Text(", \(connInfo.protocolText))")
Text("(") + Text(connInfo.text) + Text(")") Text("(") + Text(connInfo.text) + Text(")")
} }
} }
+14 -27
View File
@@ -130,7 +130,7 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
// The delay allows to accept the second call before suspending a chat // The delay allows to accept the second call before suspending a chat
// see `.onChange(of: scenePhase)` in SimpleXApp // see `.onChange(of: scenePhase)` in SimpleXApp
DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
logger.debug("CallController: shouldSuspendChat \(String(describing: self?.shouldSuspendChat))") logger.debug("CallController: shouldSuspendChat \(String(describing: self?.shouldSuspendChat), privacy: .public)")
if ChatModel.shared.activeCall == nil && self?.shouldSuspendChat == true { if ChatModel.shared.activeCall == nil && self?.shouldSuspendChat == true {
self?.shouldSuspendChat = false self?.shouldSuspendChat = false
suspendChat() suspendChat()
@@ -142,46 +142,33 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
@objc(pushRegistry:didUpdatePushCredentials:forType:) @objc(pushRegistry:didUpdatePushCredentials:forType:)
func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) { func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
logger.debug("CallController: didUpdate push credentials for type \(type.rawValue)") logger.debug("CallController: didUpdate push credentials for type \(type.rawValue, privacy: .public)")
} }
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
logger.debug("CallController: did receive push with type \(type.rawValue)") logger.debug("CallController: did receive push with type \(type.rawValue, privacy: .public)")
if type != .voIP { if type != .voIP {
completion() completion()
return return
} }
if AppChatState.shared.value == .stopped { logger.debug("CallController: initializing chat")
self.reportExpiredCall(payload: payload, completion)
return
}
if (!ChatModel.shared.chatInitialized) { if (!ChatModel.shared.chatInitialized) {
logger.debug("CallController: initializing chat") initChatAndMigrate(refreshInvitations: false)
do {
try initializeChat(start: true, refreshInvitations: false)
} catch let error {
logger.error("CallController: initializing chat error: \(error)")
self.reportExpiredCall(payload: payload, completion)
return
}
} }
logger.debug("CallController: initialized chat") startChatAndActivate()
startChatForCall() shouldSuspendChat = true
logger.debug("CallController: started chat")
self.shouldSuspendChat = true
// There are no invitations in the model, as it was processed by NSE // There are no invitations in the model, as it was processed by NSE
_ = try? justRefreshCallInvitations() _ = try? justRefreshCallInvitations()
logger.debug("CallController: updated call invitations chat")
// logger.debug("CallController justRefreshCallInvitations: \(String(describing: m.callInvitations))") // logger.debug("CallController justRefreshCallInvitations: \(String(describing: m.callInvitations))")
// Extract the call information from the push notification payload // Extract the call information from the push notification payload
let m = ChatModel.shared let m = ChatModel.shared
if let contactId = payload.dictionaryPayload["contactId"] as? String, if let contactId = payload.dictionaryPayload["contactId"] as? String,
let invitation = m.callInvitations[contactId] { let invitation = m.callInvitations[contactId] {
let update = self.cxCallUpdate(invitation: invitation) let update = cxCallUpdate(invitation: invitation)
if let uuid = invitation.callkitUUID { if let uuid = invitation.callkitUUID {
logger.debug("CallController: report pushkit call via CallKit") logger.debug("CallController: report pushkit call via CallKit")
let update = self.cxCallUpdate(invitation: invitation) let update = cxCallUpdate(invitation: invitation)
self.provider.reportNewIncomingCall(with: uuid, update: update) { error in provider.reportNewIncomingCall(with: uuid, update: update) { error in
if error != nil { if error != nil {
m.callInvitations.removeValue(forKey: contactId) m.callInvitations.removeValue(forKey: contactId)
} }
@@ -189,10 +176,10 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
completion() completion()
} }
} else { } else {
self.reportExpiredCall(update: update, completion) reportExpiredCall(update: update, completion)
} }
} else { } else {
self.reportExpiredCall(payload: payload, completion) reportExpiredCall(payload: payload, completion)
} }
} }
@@ -223,7 +210,7 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
} }
func reportNewIncomingCall(invitation: RcvCallInvitation, completion: @escaping (Error?) -> Void) { func reportNewIncomingCall(invitation: RcvCallInvitation, completion: @escaping (Error?) -> Void) {
logger.debug("CallController.reportNewIncomingCall, UUID=\(String(describing: invitation.callkitUUID))") logger.debug("CallController.reportNewIncomingCall, UUID=\(String(describing: invitation.callkitUUID), privacy: .public)")
if CallController.useCallKit(), let uuid = invitation.callkitUUID { if CallController.useCallKit(), let uuid = invitation.callkitUUID {
if invitation.callTs.timeIntervalSinceNow >= -180 { if invitation.callTs.timeIntervalSinceNow >= -180 {
let update = cxCallUpdate(invitation: invitation) let update = cxCallUpdate(invitation: invitation)
@@ -363,7 +350,7 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
private func requestTransaction(with action: CXAction, onSuccess: @escaping () -> Void = {}) { private func requestTransaction(with action: CXAction, onSuccess: @escaping () -> Void = {}) {
controller.request(CXTransaction(action: action)) { error in controller.request(CXTransaction(action: action)) { error in
if let error = error { if let error = error {
logger.error("CallController.requestTransaction error requesting transaction: \(error.localizedDescription)") logger.error("CallController.requestTransaction error requesting transaction: \(error.localizedDescription, privacy: .public)")
} else { } else {
logger.debug("CallController.requestTransaction requested transaction successfully") logger.debug("CallController.requestTransaction requested transaction successfully")
onSuccess() onSuccess()
+8 -12
View File
@@ -22,7 +22,7 @@ class CallManager {
let m = ChatModel.shared let m = ChatModel.shared
if let call = m.activeCall, call.callkitUUID == callUUID { if let call = m.activeCall, call.callkitUUID == callUUID {
m.showCallView = true m.showCallView = true
Task { await m.callCommand.processCommand(.capabilities(media: call.localMedia)) } m.callCommand = .capabilities(media: call.localMedia)
return true return true
} }
return false return false
@@ -57,21 +57,19 @@ class CallManager {
m.activeCall = call m.activeCall = call
m.showCallView = true m.showCallView = true
Task { m.callCommand = .start(
await m.callCommand.processCommand(.start(
media: invitation.callType.media, media: invitation.callType.media,
aesKey: invitation.sharedKey, aesKey: invitation.sharedKey,
iceServers: iceServers, iceServers: iceServers,
relay: useRelay relay: useRelay
)) )
}
} }
} }
func enableMedia(media: CallMediaType, enable: Bool, callUUID: UUID) -> Bool { func enableMedia(media: CallMediaType, enable: Bool, callUUID: UUID) -> Bool {
if let call = ChatModel.shared.activeCall, call.callkitUUID == callUUID { if let call = ChatModel.shared.activeCall, call.callkitUUID == callUUID {
let m = ChatModel.shared let m = ChatModel.shared
Task { await m.callCommand.processCommand(.media(media: media, enable: enable)) } m.callCommand = .media(media: media, enable: enable)
return true return true
} }
return false return false
@@ -96,13 +94,11 @@ class CallManager {
completed() completed()
} else { } else {
logger.debug("CallManager.endCall: ending call...") logger.debug("CallManager.endCall: ending call...")
m.callCommand = .end
m.activeCall = nil
m.showCallView = false
completed()
Task { Task {
await m.callCommand.processCommand(.end)
await MainActor.run {
m.activeCall = nil
m.showCallView = false
completed()
}
do { do {
try await apiEndCall(call.contact) try await apiEndCall(call.contact)
} catch { } catch {
+14 -44
View File
@@ -335,50 +335,6 @@ extension WCallResponse: Encodable {
} }
} }
actor WebRTCCommandProcessor {
private var client: WebRTCClient? = nil
private var commands: [WCallCommand] = []
private var running: Bool = false
func setClient(_ client: WebRTCClient?) async {
logger.debug("WebRTC: setClient, commands count \(self.commands.count)")
self.client = client
if client != nil {
await processAllCommands()
} else {
commands.removeAll()
}
}
func processCommand(_ c: WCallCommand) async {
// logger.debug("WebRTC: process command \(c.cmdType)")
commands.append(c)
if !running && client != nil {
await processAllCommands()
}
}
func processAllCommands() async {
logger.debug("WebRTC: process all commands, commands count \(self.commands.count), client == nil \(self.client == nil)")
if let client = client {
running = true
while let c = commands.first, shouldRunCommand(client, c) {
commands.remove(at: 0)
await client.sendCallCommand(command: c)
logger.debug("WebRTC: processed cmd \(c.cmdType)")
}
running = false
}
}
func shouldRunCommand(_ client: WebRTCClient, _ c: WCallCommand) -> Bool {
switch c {
case .capabilities, .start, .offer, .end: true
default: client.activeCall.wrappedValue != nil
}
}
}
struct ConnectionState: Codable, Equatable { struct ConnectionState: Codable, Equatable {
var connectionState: String var connectionState: String
var iceConnectionState: String var iceConnectionState: String
@@ -402,12 +358,26 @@ struct ConnectionInfo: Codable, Equatable {
return "\(local?.rawValue ?? unknown) / \(remote?.rawValue ?? unknown)" return "\(local?.rawValue ?? unknown) / \(remote?.rawValue ?? unknown)"
} }
} }
var protocolText: String {
let unknown = NSLocalizedString("unknown", comment: "connection info")
let local = localCandidate?.protocol?.uppercased() ?? unknown
let localRelay = localCandidate?.relayProtocol?.uppercased() ?? unknown
let remote = remoteCandidate?.protocol?.uppercased() ?? unknown
let localText = localRelay == local || localCandidate?.relayProtocol == nil
? local
: "\(local) (\(localRelay))"
return local == remote
? localText
: "\(localText) / \(remote)"
}
} }
// https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidate // https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidate
struct RTCIceCandidate: Codable, Equatable { struct RTCIceCandidate: Codable, Equatable {
var candidateType: RTCIceCandidateType? var candidateType: RTCIceCandidateType?
var `protocol`: String? var `protocol`: String?
var relayProtocol: String?
var sdpMid: String? var sdpMid: String?
var sdpMLineIndex: Int? var sdpMLineIndex: Int?
var candidate: String var candidate: String
+78 -119
View File
@@ -18,11 +18,10 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
}() }()
private static let ivTagBytes: Int = 28 private static let ivTagBytes: Int = 28
private static let enableEncryption: Bool = true private static let enableEncryption: Bool = true
private var chat_ctrl = getChatCtrl()
struct Call { struct Call {
var connection: RTCPeerConnection var connection: RTCPeerConnection
var iceCandidates: IceCandidates var iceCandidates: [RTCIceCandidate]
var localMedia: CallMediaType var localMedia: CallMediaType
var localCamera: RTCVideoCapturer? var localCamera: RTCVideoCapturer?
var localVideoSource: RTCVideoSource? var localVideoSource: RTCVideoSource?
@@ -34,24 +33,10 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
var frameDecryptor: RTCFrameDecryptor? var frameDecryptor: RTCFrameDecryptor?
} }
actor IceCandidates {
private var candidates: [RTCIceCandidate] = []
func getAndClear() async -> [RTCIceCandidate] {
let cs = candidates
candidates = []
return cs
}
func append(_ c: RTCIceCandidate) async {
candidates.append(c)
}
}
private let rtcAudioSession = RTCAudioSession.sharedInstance() private let rtcAudioSession = RTCAudioSession.sharedInstance()
private let audioQueue = DispatchQueue(label: "audio") private let audioQueue = DispatchQueue(label: "audio")
private var sendCallResponse: (WVAPIMessage) async -> Void private var sendCallResponse: (WVAPIMessage) async -> Void
var activeCall: Binding<Call?> private var activeCall: Binding<Call?>
private var localRendererAspectRatio: Binding<CGFloat?> private var localRendererAspectRatio: Binding<CGFloat?>
@available(*, unavailable) @available(*, unavailable)
@@ -75,7 +60,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
WebRTC.RTCIceServer(urlStrings: ["turn:turn.simplex.im:443?transport=tcp"], username: "private", credential: "yleob6AVkiNI87hpR94Z"), WebRTC.RTCIceServer(urlStrings: ["turn:turn.simplex.im:443?transport=tcp"], username: "private", credential: "yleob6AVkiNI87hpR94Z"),
] ]
func initializeCall(_ iceServers: [WebRTC.RTCIceServer]?, _ mediaType: CallMediaType, _ aesKey: String?, _ relay: Bool?) -> Call { func initializeCall(_ iceServers: [WebRTC.RTCIceServer]?, _ remoteIceCandidates: [RTCIceCandidate], _ mediaType: CallMediaType, _ aesKey: String?, _ relay: Bool?) -> Call {
let connection = createPeerConnection(iceServers ?? getWebRTCIceServers() ?? defaultIceServers, relay) let connection = createPeerConnection(iceServers ?? getWebRTCIceServers() ?? defaultIceServers, relay)
connection.delegate = self connection.delegate = self
createAudioSender(connection) createAudioSender(connection)
@@ -102,7 +87,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
} }
return Call( return Call(
connection: connection, connection: connection,
iceCandidates: IceCandidates(), iceCandidates: remoteIceCandidates,
localMedia: mediaType, localMedia: mediaType,
localCamera: localCamera, localCamera: localCamera,
localVideoSource: localVideoSource, localVideoSource: localVideoSource,
@@ -159,18 +144,26 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
logger.debug("starting incoming call - create webrtc session") logger.debug("starting incoming call - create webrtc session")
if activeCall.wrappedValue != nil { endCall() } if activeCall.wrappedValue != nil { endCall() }
let encryption = WebRTCClient.enableEncryption let encryption = WebRTCClient.enableEncryption
let call = initializeCall(iceServers?.toWebRTCIceServers(), media, encryption ? aesKey : nil, relay) let call = initializeCall(iceServers?.toWebRTCIceServers(), [], media, encryption ? aesKey : nil, relay)
activeCall.wrappedValue = call activeCall.wrappedValue = call
let (offer, error) = await call.connection.offer() call.connection.offer { answer in
if let offer = offer { Task {
resp = .offer( let gotCandidates = await self.waitWithTimeout(10_000, stepMs: 1000, until: { self.activeCall.wrappedValue?.iceCandidates.count ?? 0 > 0 })
offer: compressToBase64(input: encodeJSON(CustomRTCSessionDescription(type: offer.type.toSdpType(), sdp: offer.sdp))), if gotCandidates {
iceCandidates: compressToBase64(input: encodeJSON(await self.getInitialIceCandidates())), await self.sendCallResponse(.init(
capabilities: CallCapabilities(encryption: encryption) corrId: nil,
) resp: .offer(
self.waitForMoreIceCandidates() offer: compressToBase64(input: encodeJSON(CustomRTCSessionDescription(type: answer.type.toSdpType(), sdp: answer.sdp))),
} else { iceCandidates: compressToBase64(input: encodeJSON(self.activeCall.wrappedValue?.iceCandidates ?? [])),
resp = .error(message: "offer error: \(error?.localizedDescription ?? "unknown error")") capabilities: CallCapabilities(encryption: encryption)
),
command: command)
)
} else {
self.endCall()
}
}
} }
case let .offer(offer, iceCandidates, media, aesKey, iceServers, relay): case let .offer(offer, iceCandidates, media, aesKey, iceServers, relay):
if activeCall.wrappedValue != nil { if activeCall.wrappedValue != nil {
@@ -179,21 +172,26 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
resp = .error(message: "accept: encryption is not supported") resp = .error(message: "accept: encryption is not supported")
} else if let offer: CustomRTCSessionDescription = decodeJSON(decompressFromBase64(input: offer)), } else if let offer: CustomRTCSessionDescription = decodeJSON(decompressFromBase64(input: offer)),
let remoteIceCandidates: [RTCIceCandidate] = decodeJSON(decompressFromBase64(input: iceCandidates)) { let remoteIceCandidates: [RTCIceCandidate] = decodeJSON(decompressFromBase64(input: iceCandidates)) {
let call = initializeCall(iceServers?.toWebRTCIceServers(), media, WebRTCClient.enableEncryption ? aesKey : nil, relay) let call = initializeCall(iceServers?.toWebRTCIceServers(), remoteIceCandidates, media, WebRTCClient.enableEncryption ? aesKey : nil, relay)
activeCall.wrappedValue = call activeCall.wrappedValue = call
let pc = call.connection let pc = call.connection
if let type = offer.type, let sdp = offer.sdp { if let type = offer.type, let sdp = offer.sdp {
if (try? await pc.setRemoteDescription(RTCSessionDescription(type: type.toWebRTCSdpType(), sdp: sdp))) != nil { if (try? await pc.setRemoteDescription(RTCSessionDescription(type: type.toWebRTCSdpType(), sdp: sdp))) != nil {
let (answer, error) = await pc.answer() pc.answer { answer in
if let answer = answer {
self.addIceCandidates(pc, remoteIceCandidates) self.addIceCandidates(pc, remoteIceCandidates)
resp = .answer( // Task {
answer: compressToBase64(input: encodeJSON(CustomRTCSessionDescription(type: answer.type.toSdpType(), sdp: answer.sdp))), // try? await Task.sleep(nanoseconds: 32_000 * 1000000)
iceCandidates: compressToBase64(input: encodeJSON(await self.getInitialIceCandidates())) Task {
) await self.sendCallResponse(.init(
self.waitForMoreIceCandidates() corrId: nil,
} else { resp: .answer(
resp = .error(message: "answer error: \(error?.localizedDescription ?? "unknown error")") answer: compressToBase64(input: encodeJSON(CustomRTCSessionDescription(type: answer.type.toSdpType(), sdp: answer.sdp))),
iceCandidates: compressToBase64(input: encodeJSON(call.iceCandidates))
),
command: command)
)
}
// }
} }
} else { } else {
resp = .error(message: "accept: remote description is not set") resp = .error(message: "accept: remote description is not set")
@@ -236,7 +234,6 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
resp = .ok resp = .ok
} }
case .end: case .end:
// TODO possibly, endCall should be called before returning .ok
await sendCallResponse(.init(corrId: nil, resp: .ok, command: command)) await sendCallResponse(.init(corrId: nil, resp: .ok, command: command))
endCall() endCall()
} }
@@ -245,33 +242,6 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
} }
} }
func getInitialIceCandidates() async -> [RTCIceCandidate] {
await untilIceComplete(timeoutMs: 750, stepMs: 150) {}
let candidates = await activeCall.wrappedValue?.iceCandidates.getAndClear() ?? []
logger.debug("WebRTCClient: sending initial ice candidates: \(candidates.count)")
return candidates
}
func waitForMoreIceCandidates() {
Task {
await untilIceComplete(timeoutMs: 12000, stepMs: 1500) {
let candidates = await self.activeCall.wrappedValue?.iceCandidates.getAndClear() ?? []
if candidates.count > 0 {
logger.debug("WebRTCClient: sending more ice candidates: \(candidates.count)")
await self.sendIceCandidates(candidates)
}
}
}
}
func sendIceCandidates(_ candidates: [RTCIceCandidate]) async {
await self.sendCallResponse(.init(
corrId: nil,
resp: .ice(iceCandidates: compressToBase64(input: encodeJSON(candidates))),
command: nil)
)
}
func enableMedia(_ media: CallMediaType, _ enable: Bool) { func enableMedia(_ media: CallMediaType, _ enable: Bool) {
logger.debug("WebRTCClient: enabling media \(media.rawValue) \(enable)") logger.debug("WebRTCClient: enabling media \(media.rawValue) \(enable)")
media == .video ? setVideoEnabled(enable) : setAudioEnabled(enable) media == .video ? setVideoEnabled(enable) : setAudioEnabled(enable)
@@ -309,7 +279,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
memcpy(pointer, (unencrypted as NSData).bytes, unencrypted.count) memcpy(pointer, (unencrypted as NSData).bytes, unencrypted.count)
let isKeyFrame = unencrypted[0] & 1 == 0 let isKeyFrame = unencrypted[0] & 1 == 0
let clearTextBytesSize = mediaType.rawValue == 0 ? 1 : isKeyFrame ? 10 : 3 let clearTextBytesSize = mediaType.rawValue == 0 ? 1 : isKeyFrame ? 10 : 3
logCrypto("encrypt", chat_encrypt_media(chat_ctrl, &key, pointer.advanced(by: clearTextBytesSize), Int32(unencrypted.count + WebRTCClient.ivTagBytes - clearTextBytesSize))) logCrypto("encrypt", chat_encrypt_media(&key, pointer.advanced(by: clearTextBytesSize), Int32(unencrypted.count + WebRTCClient.ivTagBytes - clearTextBytesSize)))
return Data(bytes: pointer, count: unencrypted.count + WebRTCClient.ivTagBytes) return Data(bytes: pointer, count: unencrypted.count + WebRTCClient.ivTagBytes)
} else { } else {
return nil return nil
@@ -417,13 +387,12 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg
audioSessionToDefaults() audioSessionToDefaults()
} }
func untilIceComplete(timeoutMs: UInt64, stepMs: UInt64, action: @escaping () async -> Void) async { func waitWithTimeout(_ timeoutMs: UInt64, stepMs: UInt64, until success: () -> Bool) async -> Bool {
var t: UInt64 = 0 let startedAt = DispatchTime.now()
repeat { while !success() && startedAt.uptimeNanoseconds + timeoutMs * 1000000 > DispatchTime.now().uptimeNanoseconds {
_ = try? await Task.sleep(nanoseconds: stepMs * 1000000) guard let _ = try? await Task.sleep(nanoseconds: stepMs * 1000000) else { break }
t += stepMs }
await action() return success()
} while t < timeoutMs && activeCall.wrappedValue?.connection.iceGatheringState != .complete
} }
} }
@@ -436,33 +405,25 @@ extension WebRTC.RTCPeerConnection {
optionalConstraints: nil) optionalConstraints: nil)
} }
func offer() async -> (RTCSessionDescription?, Error?) { func offer(_ completion: @escaping (_ sdp: RTCSessionDescription) -> Void) {
await withCheckedContinuation { cont in offer(for: mediaConstraints()) { (sdp, error) in
offer(for: mediaConstraints()) { (sdp, error) in guard let sdp = sdp else {
self.processSDP(cont, sdp, error) return
} }
}
}
func answer() async -> (RTCSessionDescription?, Error?) {
await withCheckedContinuation { cont in
answer(for: mediaConstraints()) { (sdp, error) in
self.processSDP(cont, sdp, error)
}
}
}
private func processSDP(_ cont: CheckedContinuation<(RTCSessionDescription?, Error?), Never>, _ sdp: RTCSessionDescription?, _ error: Error?) {
if let sdp = sdp {
self.setLocalDescription(sdp, completionHandler: { (error) in self.setLocalDescription(sdp, completionHandler: { (error) in
if let error = error { completion(sdp)
cont.resume(returning: (nil, error)) })
} else { }
cont.resume(returning: (sdp, nil)) }
}
func answer(_ completion: @escaping (_ sdp: RTCSessionDescription) -> Void) {
answer(for: mediaConstraints()) { (sdp, error) in
guard let sdp = sdp else {
return
}
self.setLocalDescription(sdp, completionHandler: { (error) in
completion(sdp)
}) })
} else {
cont.resume(returning: (nil, error))
} }
} }
} }
@@ -518,7 +479,6 @@ extension WebRTCClient: RTCPeerConnectionDelegate {
default: enableSpeaker = false default: enableSpeaker = false
} }
setSpeakerEnabledAndConfigureSession(enableSpeaker) setSpeakerEnabledAndConfigureSession(enableSpeaker)
case .connected: sendConnectedEvent(connection)
case .disconnected, .failed: endCall() case .disconnected, .failed: endCall()
default: do {} default: do {}
} }
@@ -531,9 +491,7 @@ extension WebRTCClient: RTCPeerConnectionDelegate {
func peerConnection(_ connection: RTCPeerConnection, didGenerate candidate: WebRTC.RTCIceCandidate) { func peerConnection(_ connection: RTCPeerConnection, didGenerate candidate: WebRTC.RTCIceCandidate) {
// logger.debug("Connection generated candidate \(candidate.debugDescription)") // logger.debug("Connection generated candidate \(candidate.debugDescription)")
Task { activeCall.wrappedValue?.iceCandidates.append(candidate.toCandidate(nil, nil, nil))
await self.activeCall.wrappedValue?.iceCandidates.append(candidate.toCandidate(nil, nil))
}
} }
func peerConnection(_ connection: RTCPeerConnection, didRemove candidates: [WebRTC.RTCIceCandidate]) { func peerConnection(_ connection: RTCPeerConnection, didRemove candidates: [WebRTC.RTCIceCandidate]) {
@@ -548,9 +506,10 @@ extension WebRTCClient: RTCPeerConnectionDelegate {
lastReceivedMs lastDataReceivedMs: Int32, lastReceivedMs lastDataReceivedMs: Int32,
changeReason reason: String) { changeReason reason: String) {
// logger.debug("Connection changed candidate \(reason) \(remote.debugDescription) \(remote.description)") // logger.debug("Connection changed candidate \(reason) \(remote.debugDescription) \(remote.description)")
sendConnectedEvent(connection, local: local, remote: remote)
} }
func sendConnectedEvent(_ connection: WebRTC.RTCPeerConnection) { func sendConnectedEvent(_ connection: WebRTC.RTCPeerConnection, local: WebRTC.RTCIceCandidate, remote: WebRTC.RTCIceCandidate) {
connection.statistics { (stats: RTCStatisticsReport) in connection.statistics { (stats: RTCStatisticsReport) in
stats.statistics.values.forEach { stat in stats.statistics.values.forEach { stat in
// logger.debug("Stat \(stat.debugDescription)") // logger.debug("Stat \(stat.debugDescription)")
@@ -558,25 +517,24 @@ extension WebRTCClient: RTCPeerConnectionDelegate {
let localId = stat.values["localCandidateId"] as? String, let localId = stat.values["localCandidateId"] as? String,
let remoteId = stat.values["remoteCandidateId"] as? String, let remoteId = stat.values["remoteCandidateId"] as? String,
let localStats = stats.statistics[localId], let localStats = stats.statistics[localId],
let remoteStats = stats.statistics[remoteId] let remoteStats = stats.statistics[remoteId],
local.sdp.contains("\((localStats.values["ip"] as? String ?? "--")) \((localStats.values["port"] as? String ?? "--"))") &&
remote.sdp.contains("\((remoteStats.values["ip"] as? String ?? "--")) \((remoteStats.values["port"] as? String ?? "--"))")
{ {
Task { Task {
await self.sendCallResponse(.init( await self.sendCallResponse(.init(
corrId: nil, corrId: nil,
resp: .connected(connectionInfo: ConnectionInfo( resp: .connected(connectionInfo: ConnectionInfo(
localCandidate: RTCIceCandidate( localCandidate: local.toCandidate(
candidateType: RTCIceCandidateType.init(rawValue: localStats.values["candidateType"] as! String), RTCIceCandidateType.init(rawValue: localStats.values["candidateType"] as! String),
protocol: localStats.values["protocol"] as? String, localStats.values["protocol"] as? String,
sdpMid: nil, localStats.values["relayProtocol"] as? String
sdpMLineIndex: nil,
candidate: ""
), ),
remoteCandidate: RTCIceCandidate( remoteCandidate: remote.toCandidate(
candidateType: RTCIceCandidateType.init(rawValue: remoteStats.values["candidateType"] as! String), RTCIceCandidateType.init(rawValue: remoteStats.values["candidateType"] as! String),
protocol: remoteStats.values["protocol"] as? String, remoteStats.values["protocol"] as? String,
sdpMid: nil, remoteStats.values["relayProtocol"] as? String
sdpMLineIndex: nil, ))),
candidate: ""))),
command: nil) command: nil)
) )
} }
@@ -676,10 +634,11 @@ extension RTCIceCandidate {
} }
extension WebRTC.RTCIceCandidate { extension WebRTC.RTCIceCandidate {
func toCandidate(_ candidateType: RTCIceCandidateType?, _ protocol: String?) -> RTCIceCandidate { func toCandidate(_ candidateType: RTCIceCandidateType?, _ protocol: String?, _ relayProtocol: String?) -> RTCIceCandidate {
RTCIceCandidate( RTCIceCandidate(
candidateType: candidateType, candidateType: candidateType,
protocol: `protocol`, protocol: `protocol`,
relayProtocol: relayProtocol,
sdpMid: sdpMid, sdpMid: sdpMid,
sdpMLineIndex: Int(sdpMLineIndex), sdpMLineIndex: Int(sdpMLineIndex),
candidate: sdp candidate: sdp
@@ -28,9 +28,7 @@ struct FramedItemView: View {
@State var metaColor = Color.secondary @State var metaColor = Color.secondary
@State var showFullScreenImage = false @State var showFullScreenImage = false
@Binding var allowMenu: Bool @Binding var allowMenu: Bool
@State private var showSecrets = false
@State private var showQuoteSecrets = false
@Binding var audioPlayer: AudioPlayer? @Binding var audioPlayer: AudioPlayer?
@Binding var playbackState: VoiceMessagePlaybackState @Binding var playbackState: VoiceMessagePlaybackState
@Binding var playbackTime: TimeInterval? @Binding var playbackTime: TimeInterval?
@@ -254,12 +252,10 @@ struct FramedItemView: View {
} }
private func ciQuotedMsgTextView(_ qi: CIQuote, lines: Int) -> some View { private func ciQuotedMsgTextView(_ qi: CIQuote, lines: Int) -> some View {
toggleSecrets(qi.formattedText, $showQuoteSecrets, MsgContentView(chat: chat, text: qi.text, formattedText: qi.formattedText)
MsgContentView(chat: chat, text: qi.text, formattedText: qi.formattedText, showSecrets: showQuoteSecrets) .lineLimit(lines)
.lineLimit(lines) .font(.subheadline)
.font(.subheadline) .padding(.bottom, 6)
.padding(.bottom, 6)
)
} }
private func ciQuoteIconView(_ image: String) -> some View { private func ciQuoteIconView(_ image: String) -> some View {
@@ -282,15 +278,13 @@ struct FramedItemView: View {
@ViewBuilder private func ciMsgContentView(_ ci: ChatItem) -> some View { @ViewBuilder private func ciMsgContentView(_ ci: ChatItem) -> some View {
let text = ci.meta.isLive ? ci.content.msgContent?.text ?? ci.text : ci.text let text = ci.meta.isLive ? ci.content.msgContent?.text ?? ci.text : ci.text
let rtl = isRightToLeft(text) let rtl = isRightToLeft(text)
let ft = text == "" ? [] : ci.formattedText let v = MsgContentView(
let v = toggleSecrets(ft, $showSecrets, MsgContentView(
chat: chat, chat: chat,
text: text, text: text,
formattedText: ft, formattedText: text == "" ? [] : ci.formattedText,
meta: ci.meta, meta: ci.meta,
rightToLeft: rtl, rightToLeft: rtl
showSecrets: showSecrets )
))
.multilineTextAlignment(rtl ? .trailing : .leading) .multilineTextAlignment(rtl ? .trailing : .leading)
.padding(.vertical, 6) .padding(.vertical, 6)
.padding(.horizontal, 12) .padding(.horizontal, 12)
@@ -304,7 +298,7 @@ struct FramedItemView: View {
v v
} }
} }
@ViewBuilder private func ciFileView(_ ci: ChatItem, _ text: String) -> some View { @ViewBuilder private func ciFileView(_ ci: ChatItem, _ text: String) -> some View {
CIFileView(file: chatItem.file, edited: chatItem.meta.itemEdited) CIFileView(file: chatItem.file, edited: chatItem.meta.itemEdited)
.overlay(DetermineWidth()) .overlay(DetermineWidth())
@@ -324,14 +318,6 @@ struct FramedItemView: View {
} }
} }
@ViewBuilder func toggleSecrets<V: View>(_ ft: [FormattedText]?, _ showSecrets: Binding<Bool>, _ v: V) -> some View {
if let ft = ft, ft.contains(where: { $0.isSecret }) {
v.onTapGesture { showSecrets.wrappedValue.toggle() }
} else {
v
}
}
func isRightToLeft(_ s: String) -> Bool { func isRightToLeft(_ s: String) -> Bool {
if let lang = CFStringTokenizerCopyBestStringLanguage(s as CFString, CFRange(location: 0, length: min(s.count, 80))) { if let lang = CFStringTokenizerCopyBestStringLanguage(s as CFString, CFRange(location: 0, length: min(s.count, 80))) {
return NSLocale.characterDirection(forLanguage: lang as String) == .rightToLeft return NSLocale.characterDirection(forLanguage: lang as String) == .rightToLeft
@@ -9,7 +9,7 @@
import SwiftUI import SwiftUI
import SimpleXChat import SimpleXChat
let uiLinkColor = UIColor(red: 0, green: 0.533, blue: 1, alpha: 1) private let uiLinkColor = UIColor(red: 0, green: 0.533, blue: 1, alpha: 1)
private let noTyping = Text(" ") private let noTyping = Text(" ")
@@ -31,7 +31,6 @@ struct MsgContentView: View {
var sender: String? = nil var sender: String? = nil
var meta: CIMeta? = nil var meta: CIMeta? = nil
var rightToLeft = false var rightToLeft = false
var showSecrets: Bool
@State private var typingIdx = 0 @State private var typingIdx = 0
@State private var timer: Timer? @State private var timer: Timer?
@@ -63,7 +62,7 @@ struct MsgContentView: View {
} }
private func msgContentView() -> Text { private func msgContentView() -> Text {
var v = messageText(text, formattedText, sender, showSecrets: showSecrets) var v = messageText(text, formattedText, sender)
if let mt = meta { if let mt = meta {
if mt.isLive { if mt.isLive {
v = v + typingIndicator(mt.recent) v = v + typingIndicator(mt.recent)
@@ -85,14 +84,14 @@ struct MsgContentView: View {
} }
} }
func messageText(_ text: String, _ formattedText: [FormattedText]?, _ sender: String?, icon: String? = nil, preview: Bool = false, showSecrets: Bool) -> Text { func messageText(_ text: String, _ formattedText: [FormattedText]?, _ sender: String?, icon: String? = nil, preview: Bool = false) -> Text {
let s = text let s = text
var res: Text var res: Text
if let ft = formattedText, ft.count > 0 && ft.count <= 200 { if let ft = formattedText, ft.count > 0 && ft.count <= 200 {
res = formatText(ft[0], preview, showSecret: showSecrets) res = formatText(ft[0], preview)
var i = 1 var i = 1
while i < ft.count { while i < ft.count {
res = res + formatText(ft[i], preview, showSecret: showSecrets) res = res + formatText(ft[i], preview)
i = i + 1 i = i + 1
} }
} else { } else {
@@ -111,7 +110,7 @@ func messageText(_ text: String, _ formattedText: [FormattedText]?, _ sender: St
} }
} }
private func formatText(_ ft: FormattedText, _ preview: Bool, showSecret: Bool) -> Text { private func formatText(_ ft: FormattedText, _ preview: Bool) -> Text {
let t = ft.text let t = ft.text
if let f = ft.format { if let f = ft.format {
switch (f) { switch (f) {
@@ -119,13 +118,7 @@ private func formatText(_ ft: FormattedText, _ preview: Bool, showSecret: Bool)
case .italic: return Text(t).italic() case .italic: return Text(t).italic()
case .strikeThrough: return Text(t).strikethrough() case .strikeThrough: return Text(t).strikethrough()
case .snippet: return Text(t).font(.body.monospaced()) case .snippet: return Text(t).font(.body.monospaced())
case .secret: return case .secret: return Text(t).foregroundColor(.clear).underline(color: .primary)
showSecret
? Text(t)
: Text(AttributedString(t, attributes: AttributeContainer([
.foregroundColor: UIColor.clear as Any,
.backgroundColor: UIColor.secondarySystemFill as Any
])))
case let .colored(color): return Text(t).foregroundColor(color.uiColor) case let .colored(color): return Text(t).foregroundColor(color.uiColor)
case .uri: return linkText(t, t, preview, prefix: "") case .uri: return linkText(t, t, preview, prefix: "")
case let .simplexLink(linkType, simplexUri, smpHosts): case let .simplexLink(linkType, simplexUri, smpHosts):
@@ -151,7 +144,7 @@ private func linkText(_ s: String, _ link: String, _ preview: Bool, prefix: Stri
]))).underline() ]))).underline()
} }
func simplexLinkText(_ linkType: SimplexLinkType, _ smpHosts: [String]) -> String { private func simplexLinkText(_ linkType: SimplexLinkType, _ smpHosts: [String]) -> String {
linkType.description + " " + "(via \(smpHosts.first ?? "?"))" linkType.description + " " + "(via \(smpHosts.first ?? "?"))"
} }
@@ -163,8 +156,7 @@ struct MsgContentView_Previews: PreviewProvider {
text: chatItem.text, text: chatItem.text,
formattedText: chatItem.formattedText, formattedText: chatItem.formattedText,
sender: chatItem.memberDisplayName, sender: chatItem.memberDisplayName,
meta: chatItem.meta, meta: chatItem.meta
showSecrets: false
) )
.environmentObject(Chat.sampleData) .environmentObject(Chat.sampleData)
} }
@@ -168,6 +168,7 @@ struct ChatItemInfoView: View {
@ViewBuilder private func itemVersionView(_ itemVersion: ChatItemVersion, _ maxWidth: CGFloat, current: Bool) -> some View { @ViewBuilder private func itemVersionView(_ itemVersion: ChatItemVersion, _ maxWidth: CGFloat, current: Bool) -> some View {
VStack(alignment: .leading, spacing: 4) { VStack(alignment: .leading, spacing: 4) {
textBubble(itemVersion.msgContent.text, itemVersion.formattedText, nil) textBubble(itemVersion.msgContent.text, itemVersion.formattedText, nil)
.allowsHitTesting(false)
.padding(.horizontal, 12) .padding(.horizontal, 12)
.padding(.vertical, 6) .padding(.vertical, 6)
.background(chatItemFrameColor(ci, colorScheme)) .background(chatItemFrameColor(ci, colorScheme))
@@ -197,7 +198,7 @@ struct ChatItemInfoView: View {
@ViewBuilder private func textBubble(_ text: String, _ formattedText: [FormattedText]?, _ sender: String? = nil) -> some View { @ViewBuilder private func textBubble(_ text: String, _ formattedText: [FormattedText]?, _ sender: String? = nil) -> some View {
if text != "" { if text != "" {
TextBubble(text: text, formattedText: formattedText, sender: sender) messageText(text, formattedText, sender)
} else { } else {
Text("no text") Text("no text")
.italic() .italic()
@@ -205,17 +206,6 @@ struct ChatItemInfoView: View {
} }
} }
private struct TextBubble: View {
var text: String
var formattedText: [FormattedText]?
var sender: String? = nil
@State private var showSecrets = false
var body: some View {
toggleSecrets(formattedText, $showSecrets, messageText(text, formattedText, sender, showSecrets: showSecrets))
}
}
@ViewBuilder private func quoteTab(_ qi: CIQuote) -> some View { @ViewBuilder private func quoteTab(_ qi: CIQuote) -> some View {
GeometryReader { g in GeometryReader { g in
let maxWidth = (g.size.width - 32) * 0.84 let maxWidth = (g.size.width - 32) * 0.84
@@ -237,6 +227,7 @@ struct ChatItemInfoView: View {
@ViewBuilder private func quotedMsgView(_ qi: CIQuote, _ maxWidth: CGFloat) -> some View { @ViewBuilder private func quotedMsgView(_ qi: CIQuote, _ maxWidth: CGFloat) -> some View {
VStack(alignment: .leading, spacing: 4) { VStack(alignment: .leading, spacing: 4) {
textBubble(qi.text, qi.formattedText, qi.getSender(nil)) textBubble(qi.text, qi.formattedText, qi.getSender(nil))
.allowsHitTesting(false)
.padding(.horizontal, 12) .padding(.horizontal, 12)
.padding(.vertical, 6) .padding(.vertical, 6)
.background(quotedMsgFrameColor(qi, colorScheme)) .background(quotedMsgFrameColor(qi, colorScheme))
+7 -12
View File
@@ -250,8 +250,8 @@ struct ChatView: View {
} }
private func searchToolbar() -> some View { private func searchToolbar() -> some View {
HStack(spacing: 12) { HStack {
HStack(spacing: 4) { HStack {
Image(systemName: "magnifyingglass") Image(systemName: "magnifyingglass")
TextField("Search", text: $searchText) TextField("Search", text: $searchText)
.focused($searchFocussed) .focused($searchFocussed)
@@ -264,9 +264,9 @@ struct ChatView: View {
Image(systemName: "xmark.circle.fill").opacity(searchText == "" ? 0 : 1) Image(systemName: "xmark.circle.fill").opacity(searchText == "" ? 0 : 1)
} }
} }
.padding(EdgeInsets(top: 7, leading: 7, bottom: 7, trailing: 7)) .padding(EdgeInsets(top: 8, leading: 6, bottom: 8, trailing: 6))
.foregroundColor(.secondary) .foregroundColor(.secondary)
.background(Color(.tertiarySystemFill)) .background(Color(.secondarySystemBackground))
.cornerRadius(10.0) .cornerRadius(10.0)
Button ("Cancel") { Button ("Cancel") {
@@ -723,14 +723,9 @@ struct ChatView: View {
if ci.meta.itemDeleted == nil && !ci.isLiveDummy && !live { if ci.meta.itemDeleted == nil && !ci.isLiveDummy && !live {
menu.append(replyUIAction(ci)) menu.append(replyUIAction(ci))
} }
let fileSource = getLoadedFileSource(ci.file) menu.append(shareUIAction(ci))
let fileExists = if let fs = fileSource, FileManager.default.fileExists(atPath: getAppFilePath(fs.filePath).path) { true } else { false } menu.append(copyUIAction(ci))
let copyAndShareAllowed = !ci.content.text.isEmpty || (ci.content.msgContent?.isImage == true && fileExists) if let fileSource = getLoadedFileSource(ci.file) {
if copyAndShareAllowed {
menu.append(shareUIAction(ci))
menu.append(copyUIAction(ci))
}
if let fileSource = fileSource, fileExists {
if case .image = ci.content.msgContent, let image = getLoadedImage(ci.file) { if case .image = ci.content.msgContent, let image = getLoadedImage(ci.file) {
if image.imageData != nil { if image.imageData != nil {
menu.append(saveFileAction(fileSource)) menu.append(saveFileAction(fileSource))
@@ -104,7 +104,7 @@ struct ComposeState {
var sendEnabled: Bool { var sendEnabled: Bool {
switch preview { switch preview {
case let .mediaPreviews(media): return !media.isEmpty case .mediaPreviews: return true
case .voicePreview: return voiceMessageRecordingState == .finished case .voicePreview: return voiceMessageRecordingState == .finished
case .filePreview: return true case .filePreview: return true
default: return !message.isEmpty || liveMessage != nil default: return !message.isEmpty || liveMessage != nil
@@ -384,10 +384,10 @@ struct ComposeView: View {
} }
} }
.sheet(isPresented: $showMediaPicker) { .sheet(isPresented: $showMediaPicker) {
LibraryMediaListPicker(addMedia: addMediaContent, selectionLimit: 10, finishedPreprocessing: finishedPreprocessingMediaContent) { itemsSelected in LibraryMediaListPicker(media: $chosenMedia, selectionLimit: 10) { itemsSelected in
await MainActor.run { showMediaPicker = false
showMediaPicker = false if itemsSelected {
if itemsSelected { DispatchQueue.main.async {
composeState = composeState.copy(preview: .mediaPreviews(mediaPreviews: [])) composeState = composeState.copy(preview: .mediaPreviews(mediaPreviews: []))
} }
} }
@@ -488,30 +488,6 @@ struct ComposeView: View {
} }
} }
private func addMediaContent(_ content: UploadContent) async {
if let img = resizeImageToStrSize(content.uiImage, maxDataSize: 14000) {
var newMedia: [(String, UploadContent?)] = []
if case var .mediaPreviews(media) = composeState.preview {
media.append((img, content))
newMedia = media
} else {
newMedia = [(img, content)]
}
await MainActor.run {
composeState = composeState.copy(preview: .mediaPreviews(mediaPreviews: newMedia))
}
}
}
// When error occurs while converting video, remove media preview
private func finishedPreprocessingMediaContent() {
if case let .mediaPreviews(media) = composeState.preview, media.isEmpty {
DispatchQueue.main.async {
composeState = composeState.copy(preview: .noPreview)
}
}
}
private var maxFileSize: Int64 { private var maxFileSize: Int64 {
getMaxFileSize(.xftp) getMaxFileSize(.xftp)
} }
@@ -51,8 +51,7 @@ struct ContextItemView: View {
MsgContentView( MsgContentView(
chat: chat, chat: chat,
text: contextItem.text, text: contextItem.text,
formattedText: contextItem.formattedText, formattedText: contextItem.formattedText
showSecrets: false
) )
.multilineTextAlignment(isRightToLeft(contextItem.text) ? .trailing : .leading) .multilineTextAlignment(isRightToLeft(contextItem.text) ? .trailing : .leading)
.lineLimit(lines) .lineLimit(lines)
@@ -116,6 +116,7 @@ struct ContactPreferencesView: View {
private func featureFooter(_ feature: ChatFeature, _ enabled: FeatureEnabled) -> some View { private func featureFooter(_ feature: ChatFeature, _ enabled: FeatureEnabled) -> some View {
Text(feature.enabledDescription(enabled)) Text(feature.enabledDescription(enabled))
.frame(height: 36, alignment: .topLeading)
} }
private func savePreferences() { private func savePreferences() {
@@ -157,7 +157,7 @@ struct AddGroupMembersViewCommon: View {
private func rolePicker() -> some View { private func rolePicker() -> some View {
Picker("New member role", selection: $selectedRole) { Picker("New member role", selection: $selectedRole) {
ForEach(GroupMemberRole.allCases) { role in ForEach(GroupMemberRole.allCases) { role in
if role <= groupInfo.membership.memberRole && role != .author { if role <= groupInfo.membership.memberRole {
Text(role.text) Text(role.text)
} }
} }
@@ -16,6 +16,7 @@ struct GroupChatInfoView: View {
@Environment(\.dismiss) var dismiss: DismissAction @Environment(\.dismiss) var dismiss: DismissAction
@ObservedObject var chat: Chat @ObservedObject var chat: Chat
@Binding var groupInfo: GroupInfo @Binding var groupInfo: GroupInfo
@ObservedObject private var alertManager = AlertManager.shared
@State private var alert: GroupChatInfoViewAlert? = nil @State private var alert: GroupChatInfoViewAlert? = nil
@State private var groupLink: String? @State private var groupLink: String?
@State private var groupLinkMemberRole: GroupMemberRole = .member @State private var groupLinkMemberRole: GroupMemberRole = .member
@@ -188,19 +188,17 @@ struct GroupMemberInfoView: View {
// this condition prevents re-setting picker // this condition prevents re-setting picker
if !justOpened { return } if !justOpened { return }
} }
justOpened = false newRole = member.memberRole
DispatchQueue.main.async { do {
newRole = member.memberRole let (_, stats) = try apiGroupMemberInfo(groupInfo.apiId, member.groupMemberId)
do { let (mem, code) = member.memberActive ? try apiGetGroupMemberCode(groupInfo.apiId, member.groupMemberId) : (member, nil)
let (_, stats) = try apiGroupMemberInfo(groupInfo.apiId, member.groupMemberId) _ = chatModel.upsertGroupMember(groupInfo, mem)
let (mem, code) = member.memberActive ? try apiGetGroupMemberCode(groupInfo.apiId, member.groupMemberId) : (member, nil) connectionStats = stats
_ = chatModel.upsertGroupMember(groupInfo, mem) connectionCode = code
connectionStats = stats } catch let error {
connectionCode = code logger.error("apiGroupMemberInfo or apiGetGroupMemberCode error: \(responseError(error))")
} catch let error {
logger.error("apiGroupMemberInfo or apiGetGroupMemberCode error: \(responseError(error))")
}
} }
justOpened = false
} }
.onChange(of: newRole) { newRole in .onChange(of: newRole) { newRole in
if newRole != member.memberRole { if newRole != member.memberRole {
@@ -28,7 +28,6 @@ struct GroupPreferencesView: View {
featureSection(.reactions, $preferences.reactions.enable) featureSection(.reactions, $preferences.reactions.enable)
featureSection(.voice, $preferences.voice.enable) featureSection(.voice, $preferences.voice.enable)
featureSection(.files, $preferences.files.enable) featureSection(.files, $preferences.files.enable)
featureSection(.history, $preferences.history.enable)
if groupInfo.canEdit { if groupInfo.canEdit {
Section { Section {
@@ -97,6 +96,7 @@ struct GroupPreferencesView: View {
} }
} footer: { } footer: {
Text(feature.enableDescription(enableFeature.wrappedValue, groupInfo.canEdit)) Text(feature.enableDescription(enableFeature.wrappedValue, groupInfo.canEdit))
.frame(height: 36, alignment: .topLeading)
} }
} }
@@ -103,10 +103,8 @@ struct GroupProfileView: View {
} }
} }
.sheet(isPresented: $showImagePicker) { .sheet(isPresented: $showImagePicker) {
LibraryImagePicker(image: $chosenImage) { _ in LibraryImagePicker(image: $chosenImage) {
await MainActor.run { didSelectItem in showImagePicker = false
showImagePicker = false
}
} }
} }
.onChange(of: chosenImage) { image in .onChange(of: chosenImage) { image in
@@ -53,7 +53,8 @@ struct GroupWelcomeView: View {
} }
private func textPreview() -> some View { private func textPreview() -> some View {
messageText(welcomeText, parseSimpleXMarkdown(welcomeText), nil, showSecrets: false) messageText(welcomeText, parseSimpleXMarkdown(welcomeText), nil)
.allowsHitTesting(false)
.frame(minHeight: 140, alignment: .topLeading) .frame(minHeight: 140, alignment: .topLeading)
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
} }
@@ -17,7 +17,7 @@ struct ScanCodeView: View {
var body: some View { var body: some View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
CodeScannerView(codeTypes: [.qr], scanMode: .oncePerCode, completion: processQRCode) CodeScannerView(codeTypes: [.qr], completion: processQRCode)
.aspectRatio(1, contentMode: .fit) .aspectRatio(1, contentMode: .fit)
.cornerRadius(12) .cornerRadius(12)
Text("Scan security code from your contact's app.") Text("Scan security code from your contact's app.")
@@ -11,7 +11,7 @@ import SwiftUI
struct ChatHelp: View { struct ChatHelp: View {
@EnvironmentObject var chatModel: ChatModel @EnvironmentObject var chatModel: ChatModel
@Binding var showSettings: Bool @Binding var showSettings: Bool
@State private var newChatMenuOption: NewChatMenuOption? = nil @State private var showAddChat = false
var body: some View { var body: some View {
ScrollView { chatHelp() } ScrollView { chatHelp() }
@@ -39,12 +39,13 @@ struct ChatHelp: View {
HStack(spacing: 8) { HStack(spacing: 8) {
Text("Tap button ") Text("Tap button ")
NewChatMenuButton(newChatMenuOption: $newChatMenuOption) NewChatButton(showAddChat: $showAddChat)
Text("above, then choose:") Text("above, then choose:")
} }
Text("**Add contact**: to create a new invitation link, or connect via a link you received.") Text("**Create link / QR code** for your contact to use.")
Text("**Create group**: to create a new group.") Text("**Paste received link** or open it in the browser and tap **Open in mobile app**.")
Text("**Scan QR code**: to connect to your contact in person or via video call.")
} }
.padding(.top, 24) .padding(.top, 24)
+22 -159
View File
@@ -12,12 +12,8 @@ import SimpleXChat
struct ChatListView: View { struct ChatListView: View {
@EnvironmentObject var chatModel: ChatModel @EnvironmentObject var chatModel: ChatModel
@Binding var showSettings: Bool @Binding var showSettings: Bool
@State private var searchMode = false
@FocusState private var searchFocussed
@State private var searchText = "" @State private var searchText = ""
@State private var searchShowingSimplexLink = false @State private var showAddChat = false
@State private var searchChatFilteredBySimplexLink: String? = nil
@State private var newChatMenuOption: NewChatMenuOption? = nil
@State private var userPickerVisible = false @State private var userPickerVisible = false
@State private var showConnectDesktop = false @State private var showConnectDesktop = false
@AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false @AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false
@@ -66,7 +62,11 @@ struct ChatListView: View {
private var chatListView: some View { private var chatListView: some View {
VStack { VStack {
chatList if chatModel.chats.count > 0 {
chatList.searchable(text: $searchText)
} else {
chatList
}
} }
.onDisappear() { withAnimation { userPickerVisible = false } } .onDisappear() { withAnimation { userPickerVisible = false } }
.refreshable { .refreshable {
@@ -85,9 +85,9 @@ struct ChatListView: View {
secondaryButton: .cancel() secondaryButton: .cancel()
)) ))
} }
.offset(x: -8)
.listStyle(.plain) .listStyle(.plain)
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.navigationBarHidden(searchMode)
.toolbar { .toolbar {
ToolbarItem(placement: .navigationBarLeading) { ToolbarItem(placement: .navigationBarLeading) {
let user = chatModel.currentUser ?? User.sampleData let user = chatModel.currentUser ?? User.sampleData
@@ -124,7 +124,7 @@ struct ChatListView: View {
} }
ToolbarItem(placement: .navigationBarTrailing) { ToolbarItem(placement: .navigationBarTrailing) {
switch chatModel.chatRunning { switch chatModel.chatRunning {
case .some(true): NewChatMenuButton(newChatMenuOption: $newChatMenuOption) case .some(true): NewChatButton(showAddChat: $showAddChat)
case .some(false): chatStoppedIcon() case .some(false): chatStoppedIcon()
case .none: EmptyView() case .none: EmptyView()
} }
@@ -144,25 +144,11 @@ struct ChatListView: View {
@ViewBuilder private var chatList: some View { @ViewBuilder private var chatList: some View {
let cs = filteredChats() let cs = filteredChats()
ZStack { ZStack {
VStack { List {
List { ForEach(cs, id: \.viewId) { chat in
if !chatModel.chats.isEmpty { ChatListNavLink(chat: chat)
ChatListSearchBar( .padding(.trailing, -16)
searchMode: $searchMode, .disabled(chatModel.chatRunning != true)
searchFocussed: $searchFocussed,
searchText: $searchText,
searchShowingSimplexLink: $searchShowingSimplexLink,
searchChatFilteredBySimplexLink: $searchChatFilteredBySimplexLink
)
.listRowSeparator(.hidden)
.frame(maxWidth: .infinity)
}
ForEach(cs, id: \.viewId) { chat in
ChatListNavLink(chat: chat)
.padding(.trailing, -16)
.disabled(chatModel.chatRunning != true)
}
.offset(x: -8)
} }
} }
.onChange(of: chatModel.chatId) { _ in .onChange(of: chatModel.chatId) { _ in
@@ -196,7 +182,7 @@ struct ChatListView: View {
.padding(.trailing, 12) .padding(.trailing, 12)
connectButton("Tap to start a new chat") { connectButton("Tap to start a new chat") {
newChatMenuOption = .newContact showAddChat = true
} }
Spacer() Spacer()
@@ -228,25 +214,22 @@ struct ChatListView: View {
} }
private func filteredChats() -> [Chat] { private func filteredChats() -> [Chat] {
if let linkChatId = searchChatFilteredBySimplexLink { let s = searchText.trimmingCharacters(in: .whitespaces).localizedLowercase
return chatModel.chats.filter { $0.id == linkChatId } return s == "" && !showUnreadAndFavorites
} else {
let s = searchString()
return s == "" && !showUnreadAndFavorites
? chatModel.chats ? chatModel.chats
: chatModel.chats.filter { chat in : chatModel.chats.filter { chat in
let cInfo = chat.chatInfo let cInfo = chat.chatInfo
switch cInfo { switch cInfo {
case let .direct(contact): case let .direct(contact):
return s == "" return s == ""
? filtered(chat) ? filtered(chat)
: (viewNameContains(cInfo, s) || : (viewNameContains(cInfo, s) ||
contact.profile.displayName.localizedLowercase.contains(s) || contact.profile.displayName.localizedLowercase.contains(s) ||
contact.fullName.localizedLowercase.contains(s)) contact.fullName.localizedLowercase.contains(s))
case let .group(gInfo): case let .group(gInfo):
return s == "" return s == ""
? (filtered(chat) || gInfo.membership.memberStatus == .memInvited) ? (filtered(chat) || gInfo.membership.memberStatus == .memInvited)
: viewNameContains(cInfo, s) : viewNameContains(cInfo, s)
case .contactRequest: case .contactRequest:
return s == "" || viewNameContains(cInfo, s) return s == "" || viewNameContains(cInfo, s)
case let .contactConnection(conn): case let .contactConnection(conn):
@@ -255,11 +238,6 @@ struct ChatListView: View {
return false return false
} }
} }
}
func searchString() -> String {
searchShowingSimplexLink ? "" : searchText.trimmingCharacters(in: .whitespaces).localizedLowercase
}
func filtered(_ chat: Chat) -> Bool { func filtered(_ chat: Chat) -> Bool {
(chat.chatInfo.chatSettings?.favorite ?? false) || chat.chatStats.unreadCount > 0 || chat.chatStats.unreadChat (chat.chatInfo.chatSettings?.favorite ?? false) || chat.chatStats.unreadCount > 0 || chat.chatStats.unreadChat
@@ -271,121 +249,6 @@ struct ChatListView: View {
} }
} }
struct ChatListSearchBar: View {
@EnvironmentObject var m: ChatModel
@Binding var searchMode: Bool
@FocusState.Binding var searchFocussed: Bool
@Binding var searchText: String
@Binding var searchShowingSimplexLink: Bool
@Binding var searchChatFilteredBySimplexLink: String?
@State private var ignoreSearchTextChange = false
@State private var showScanCodeSheet = false
@State private var alert: PlanAndConnectAlert?
@State private var sheet: PlanAndConnectActionSheet?
var body: some View {
VStack(spacing: 12) {
HStack(spacing: 12) {
HStack(spacing: 4) {
Image(systemName: "magnifyingglass")
TextField("Search or paste SimpleX link", text: $searchText)
.foregroundColor(searchShowingSimplexLink ? .secondary : .primary)
.disabled(searchShowingSimplexLink)
.focused($searchFocussed)
.frame(maxWidth: .infinity)
if !searchText.isEmpty {
Image(systemName: "xmark.circle.fill")
.onTapGesture {
searchText = ""
}
} else if !searchFocussed {
HStack(spacing: 24) {
if m.pasteboardHasStrings {
Image(systemName: "doc")
.onTapGesture {
if let str = UIPasteboard.general.string {
searchText = str
}
}
}
Image(systemName: "qrcode")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
.onTapGesture {
showScanCodeSheet = true
}
}
.padding(.trailing, 2)
}
}
.padding(EdgeInsets(top: 7, leading: 7, bottom: 7, trailing: 7))
.foregroundColor(.secondary)
.background(Color(.tertiarySystemFill))
.cornerRadius(10.0)
if searchFocussed {
Text("Cancel")
.foregroundColor(.accentColor)
.onTapGesture {
searchText = ""
searchFocussed = false
}
}
}
Divider()
}
.sheet(isPresented: $showScanCodeSheet) {
NewChatView(selection: .connect, showQRCodeScanner: true)
.environment(\EnvironmentValues.refresh as! WritableKeyPath<EnvironmentValues, RefreshAction?>, nil) // fixes .refreshable in ChatListView affecting nested view
}
.onChange(of: searchFocussed) { sf in
withAnimation { searchMode = sf }
}
.onChange(of: searchText) { t in
if ignoreSearchTextChange {
ignoreSearchTextChange = false
} else {
if let link = strHasSingleSimplexLink(t.trimmingCharacters(in: .whitespaces)) { // if SimpleX link is pasted, show connection dialogue
searchFocussed = false
if case let .simplexLink(linkType, _, smpHosts) = link.format {
ignoreSearchTextChange = true
searchText = simplexLinkText(linkType, smpHosts)
}
searchShowingSimplexLink = true
searchChatFilteredBySimplexLink = nil
connect(link.text)
} else {
if t != "" { // if some other text is pasted, enter search mode
searchFocussed = true
}
searchShowingSimplexLink = false
searchChatFilteredBySimplexLink = nil
}
}
}
.alert(item: $alert) { a in
planAndConnectAlert(a, dismiss: true, cleanup: { searchText = "" })
}
.actionSheet(item: $sheet) { s in
planAndConnectActionSheet(s, dismiss: true, cleanup: { searchText = "" })
}
}
private func connect(_ link: String) {
planAndConnect(
link,
showAlert: { alert = $0 },
showActionSheet: { sheet = $0 },
dismiss: false,
incognito: nil,
filterKnownContact: { searchChatFilteredBySimplexLink = $0.id },
filterKnownGroup: { searchChatFilteredBySimplexLink = $0.id }
)
}
}
func chatStoppedIcon() -> some View { func chatStoppedIcon() -> some View {
Button { Button {
AlertManager.shared.showAlertMsg( AlertManager.shared.showAlertMsg(
@@ -150,7 +150,7 @@ struct ChatPreviewView: View {
let msg = draft.message let msg = draft.message
return image("rectangle.and.pencil.and.ellipsis", color: .accentColor) return image("rectangle.and.pencil.and.ellipsis", color: .accentColor)
+ attachment() + attachment()
+ messageText(msg, parseSimpleXMarkdown(msg), nil, preview: true, showSecrets: false) + messageText(msg, parseSimpleXMarkdown(msg), nil, preview: true)
func image(_ s: String, color: Color = Color(uiColor: .tertiaryLabel)) -> Text { func image(_ s: String, color: Color = Color(uiColor: .tertiaryLabel)) -> Text {
Text(Image(systemName: s)).foregroundColor(color) + Text(" ") Text(Image(systemName: s)).foregroundColor(color) + Text(" ")
@@ -169,7 +169,7 @@ struct ChatPreviewView: View {
func chatItemPreview(_ cItem: ChatItem) -> Text { func chatItemPreview(_ cItem: ChatItem) -> Text {
let itemText = cItem.meta.itemDeleted == nil ? cItem.text : NSLocalizedString("marked deleted", comment: "marked deleted chat item preview text") 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 let itemFormattedText = cItem.meta.itemDeleted == nil ? cItem.formattedText : nil
return messageText(itemText, itemFormattedText, cItem.memberDisplayName, icon: attachment(), preview: true, showSecrets: false) return messageText(itemText, itemFormattedText, cItem.memberDisplayName, icon: attachment(), preview: true)
func attachment() -> String? { func attachment() -> String? {
switch cItem.content.msgContent { switch cItem.content.msgContent {
@@ -164,28 +164,6 @@ struct ContactConnectionInfo: View {
} }
} }
private func shareLinkButton(_ connReqInvitation: String) -> some View {
Button {
showShareSheet(items: [simplexChatLink(connReqInvitation)])
} label: {
settingsRow("square.and.arrow.up") {
Text("Share 1-time link")
}
}
}
private func oneTimeLinkLearnMoreButton() -> some View {
NavigationLink {
AddContactLearnMore(showTitle: false)
.navigationTitle("One-time invitation link")
.navigationBarTitleDisplayMode(.large)
} label: {
settingsRow("info.circle") {
Text("Learn more")
}
}
}
struct ContactConnectionInfo_Previews: PreviewProvider { struct ContactConnectionInfo_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
ContactConnectionInfo(contactConnection: PendingContactConnection.getSampleData()) ContactConnectionInfo(contactConnection: PendingContactConnection.getSampleData())
@@ -149,7 +149,7 @@ struct DatabaseErrorView: View {
private func runChatSync(confirmMigrations: MigrationConfirmation? = nil) { private func runChatSync(confirmMigrations: MigrationConfirmation? = nil) {
do { do {
resetChatCtrl() resetChatCtrl()
try initializeChat(start: m.v3DBMigration.startChat, confirmStart: m.v3DBMigration.startChat && AppChatState.shared.value == .stopped, dbKey: useKeychain ? nil : dbKey, confirmMigrations: confirmMigrations) try initializeChat(start: m.v3DBMigration.startChat, dbKey: useKeychain ? nil : dbKey, confirmMigrations: confirmMigrations)
if let s = m.chatDbStatus { if let s = m.chatDbStatus {
status = s status = s
let am = AlertManager.shared let am = AlertManager.shared
@@ -415,7 +415,7 @@ struct DatabaseView: View {
do { do {
try initializeChat(start: true) try initializeChat(start: true)
m.chatDbChanged = false m.chatDbChanged = false
AppChatState.shared.set(.active) appStateGroupDefault.set(.active)
} catch let error { } catch let error {
fatalError("Error starting chat \(responseError(error))") fatalError("Error starting chat \(responseError(error))")
} }
@@ -427,7 +427,7 @@ struct DatabaseView: View {
m.chatRunning = true m.chatRunning = true
ChatReceiver.shared.start() ChatReceiver.shared.start()
chatLastStartGroupDefault.set(Date.now) chatLastStartGroupDefault.set(Date.now)
AppChatState.shared.set(.active) appStateGroupDefault.set(.active)
} catch let error { } catch let error {
runChat = false runChat = false
alert = .error(title: "Error starting chat", error: responseError(error)) alert = .error(title: "Error starting chat", error: responseError(error))
@@ -477,14 +477,13 @@ func stopChatAsync() async throws {
try await apiStopChat() try await apiStopChat()
ChatReceiver.shared.stop() ChatReceiver.shared.stop()
await MainActor.run { ChatModel.shared.chatRunning = false } await MainActor.run { ChatModel.shared.chatRunning = false }
AppChatState.shared.set(.stopped) appStateGroupDefault.set(.stopped)
} }
func deleteChatAsync() async throws { func deleteChatAsync() async throws {
try await apiDeleteStorage() try await apiDeleteStorage()
_ = kcDatabasePassword.remove() _ = kcDatabasePassword.remove()
storeDBPassphraseGroupDefault.set(true) storeDBPassphraseGroupDefault.set(true)
deleteAppDatabaseAndFiles()
} }
struct DatabaseView_Previews: PreviewProvider { struct DatabaseView_Previews: PreviewProvider {
+79 -97
View File
@@ -13,130 +13,112 @@ import SimpleXChat
struct LibraryImagePicker: View { struct LibraryImagePicker: View {
@Binding var image: UIImage? @Binding var image: UIImage?
var didFinishPicking: (_ didSelectImage: Bool) async -> Void var didFinishPicking: (_ didSelectItems: Bool) -> Void
@State var mediaAdded = false @State var images: [UploadContent] = []
var body: some View { var body: some View {
LibraryMediaListPicker(addMedia: addMedia, selectionLimit: 1, didFinishPicking: didFinishPicking) LibraryMediaListPicker(media: $images, selectionLimit: 1, didFinishPicking: didFinishPicking)
} .onChange(of: images) { _ in
if let img = images.first {
private func addMedia(_ content: UploadContent) async { image = img.uiImage
if mediaAdded { return } }
await MainActor.run { }
mediaAdded = true
image = content.uiImage
}
} }
} }
struct LibraryMediaListPicker: UIViewControllerRepresentable { struct LibraryMediaListPicker: UIViewControllerRepresentable {
typealias UIViewControllerType = PHPickerViewController typealias UIViewControllerType = PHPickerViewController
var addMedia: (_ content: UploadContent) async -> Void @Binding var media: [UploadContent]
var selectionLimit: Int var selectionLimit: Int
var finishedPreprocessing: () -> Void = {} var didFinishPicking: (_ didSelectItems: Bool) -> Void
var didFinishPicking: (_ didSelectItems: Bool) async -> Void
class Coordinator: PHPickerViewControllerDelegate { class Coordinator: PHPickerViewControllerDelegate {
let parent: LibraryMediaListPicker let parent: LibraryMediaListPicker
let dispatchQueue = DispatchQueue(label: "chat.simplex.app.LibraryMediaListPicker") let dispatchQueue = DispatchQueue(label: "chat.simplex.app.LibraryMediaListPicker")
var media: [UploadContent] = []
var mediaCount: Int = 0
init(_ parent: LibraryMediaListPicker) { init(_ parent: LibraryMediaListPicker) {
self.parent = parent self.parent = parent
} }
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
Task { parent.didFinishPicking(!results.isEmpty)
await parent.didFinishPicking(!results.isEmpty) guard !results.isEmpty else {
if results.isEmpty { return } return
for r in results {
await loadItem(r.itemProvider)
}
parent.finishedPreprocessing()
} }
}
private func loadItem(_ p: NSItemProvider) async { parent.media = []
logger.debug("LibraryMediaListPicker result") media = []
if p.hasItemConformingToTypeIdentifier(UTType.movie.identifier) { mediaCount = results.count
if let video = await loadVideo(p) { for result in results {
await self.parent.addMedia(video) logger.log("LibraryMediaListPicker result")
logger.debug("LibraryMediaListPicker: added video") let p = result.itemProvider
} if p.hasItemConformingToTypeIdentifier(UTType.movie.identifier) {
} else if p.hasItemConformingToTypeIdentifier(UTType.data.identifier) { p.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { url, error in
if let img = await loadImageData(p) { if let url = url {
await self.parent.addMedia(img) let tempUrl = URL(fileURLWithPath: getTempFilesDirectory().path + "/" + generateNewFileName("video", url.pathExtension))
logger.debug("LibraryMediaListPicker: added image") if ((try? FileManager.default.copyItem(at: url, to: tempUrl)) != nil) {
} ChatModel.shared.filesToDelete.insert(tempUrl)
} else if p.canLoadObject(ofClass: UIImage.self) { self.loadVideo(url: tempUrl, error: error)
if let img = await loadImage(p) {
await self.parent.addMedia(.simpleImage(image: img))
logger.debug("LibraryMediaListPicker: added image")
}
}
}
private func loadImageData(_ p: NSItemProvider) async -> UploadContent? {
await withCheckedContinuation { cont in
loadFileURL(p, type: UTType.data) { url in
if let url = url {
let img = UploadContent.loadFromURL(url: url)
cont.resume(returning: img)
} else {
cont.resume(returning: nil)
}
}
}
}
private func loadImage(_ p: NSItemProvider) async -> UIImage? {
await withCheckedContinuation { cont in
p.loadObject(ofClass: UIImage.self) { obj, err in
if let err = err {
logger.error("LibraryMediaListPicker result image error: \(err.localizedDescription)")
cont.resume(returning: nil)
} else {
cont.resume(returning: obj as? UIImage)
}
}
}
}
private func loadVideo(_ p: NSItemProvider) async -> UploadContent? {
await withCheckedContinuation { cont in
loadFileURL(p, type: UTType.movie) { url in
if let url = url {
let tempUrl = URL(fileURLWithPath: generateNewFileName(getTempFilesDirectory().path + "/" + "rawvideo", url.pathExtension, fullPath: true))
let convertedVideoUrl = URL(fileURLWithPath: generateNewFileName(getTempFilesDirectory().path + "/" + "video", "mp4", fullPath: true))
do {
// logger.debug("LibraryMediaListPicker copyItem \(url) to \(tempUrl)")
try FileManager.default.copyItem(at: url, to: tempUrl)
} catch let err {
logger.error("LibraryMediaListPicker copyItem error: \(err.localizedDescription)")
return cont.resume(returning: nil)
}
Task {
let success = await makeVideoQualityLower(tempUrl, outputUrl: convertedVideoUrl)
try? FileManager.default.removeItem(at: tempUrl)
if success {
_ = ChatModel.shared.filesToDelete.insert(convertedVideoUrl)
let video = UploadContent.loadVideoFromURL(url: convertedVideoUrl)
return cont.resume(returning: video)
} }
try? FileManager.default.removeItem(at: convertedVideoUrl)
cont.resume(returning: nil)
} }
} }
} else if p.hasItemConformingToTypeIdentifier(UTType.data.identifier) {
p.loadFileRepresentation(forTypeIdentifier: UTType.data.identifier) { url, error in
self.loadImage(object: url, error: error)
}
} else if p.canLoadObject(ofClass: UIImage.self) {
p.loadObject(ofClass: UIImage.self) { image, error in
DispatchQueue.main.async {
self.loadImage(object: image, error: error)
}
}
} else {
dispatchQueue.sync { self.mediaCount -= 1}
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
self.dispatchQueue.sync {
if self.parent.media.count == 0 {
logger.log("LibraryMediaListPicker: added \(self.media.count) images out of \(results.count)")
self.parent.media = self.media
}
} }
} }
} }
private func loadFileURL(_ p: NSItemProvider, type: UTType, completion: @escaping (URL?) -> Void) { func loadImage(object: Any?, error: Error? = nil) {
p.loadFileRepresentation(forTypeIdentifier: type.identifier) { url, err in if let error = error {
if let err = err { logger.error("LibraryMediaListPicker: couldn't load image with error: \(error.localizedDescription)")
logger.error("LibraryMediaListPicker loadFileURL error: \(err.localizedDescription)") } else if let image = object as? UIImage {
completion(nil) media.append(.simpleImage(image: image))
} else { logger.log("LibraryMediaListPicker: added image")
completion(url) } else if let url = object as? URL, let image = UploadContent.loadFromURL(url: url) {
media.append(image)
}
dispatchQueue.sync {
self.mediaCount -= 1
if self.mediaCount == 0 && self.parent.media.count == 0 {
logger.log("LibraryMediaListPicker: added all media")
self.parent.media = self.media
self.media = []
}
}
}
func loadVideo(url: URL?, error: Error? = nil) {
if let error = error {
logger.error("LibraryMediaListPicker: couldn't load video with error: \(error.localizedDescription)")
} else if let url = url as URL?, let video = UploadContent.loadVideoFromURL(url: url) {
media.append(video)
}
dispatchQueue.sync {
self.mediaCount -= 1
if self.mediaCount == 0 && self.parent.media.count == 0 {
logger.log("LibraryMediaListPicker: added all media")
self.parent.media = self.media
self.media = []
} }
} }
} }
@@ -1,26 +0,0 @@
//
// VideoUtils.swift
// SimpleX (iOS)
//
// Created by Avently on 25.12.2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import AVFoundation
import Foundation
import SimpleXChat
func makeVideoQualityLower(_ input: URL, outputUrl: URL) async -> Bool {
let asset: AVURLAsset = AVURLAsset(url: input, options: nil)
if let s = AVAssetExportSession(asset: asset, presetName: AVAssetExportPreset640x480) {
s.outputURL = outputUrl
s.outputFileType = .mp4
s.metadataItemFilter = AVMetadataItemFilter.forSharing()
await s.export()
if let err = s.error {
logger.error("Failed to export video with error: \(err)")
}
return s.status == .completed
}
return false
}
@@ -13,28 +13,19 @@ struct LocalAuthView: View {
@EnvironmentObject var m: ChatModel @EnvironmentObject var m: ChatModel
var authRequest: LocalAuthRequest var authRequest: LocalAuthRequest
@State private var password = "" @State private var password = ""
@State private var allowToReact = true
var body: some View { var body: some View {
PasscodeView(passcode: $password, title: authRequest.title ?? "Enter Passcode", reason: authRequest.reason, submitLabel: "Submit", PasscodeView(passcode: $password, title: authRequest.title ?? "Enter Passcode", reason: authRequest.reason, submitLabel: "Submit") {
buttonsEnabled: $allowToReact) {
if let sdPassword = kcSelfDestructPassword.get(), authRequest.selfDestruct && password == sdPassword { if let sdPassword = kcSelfDestructPassword.get(), authRequest.selfDestruct && password == sdPassword {
allowToReact = false
deleteStorageAndRestart(sdPassword) { r in deleteStorageAndRestart(sdPassword) { r in
m.laRequest = nil m.laRequest = nil
authRequest.completed(r) authRequest.completed(r)
} }
return return
} }
let r: LAResult let r: LAResult = password == authRequest.password
if password == authRequest.password { ? .success
if authRequest.selfDestruct && kcSelfDestructPassword.get() != nil && !m.chatInitialized { : .failed(authError: NSLocalizedString("Incorrect passcode", comment: "PIN entry"))
initChatAndMigrate()
}
r = .success
} else {
r = .failed(authError: NSLocalizedString("Incorrect passcode", comment: "PIN entry"))
}
m.laRequest = nil m.laRequest = nil
authRequest.completed(r) authRequest.completed(r)
} cancel: { } cancel: {
@@ -46,27 +37,8 @@ struct LocalAuthView: View {
private func deleteStorageAndRestart(_ password: String, completed: @escaping (LAResult) -> Void) { private func deleteStorageAndRestart(_ password: String, completed: @escaping (LAResult) -> Void) {
Task { Task {
do { do {
/** Waiting until [initializeChat] finishes */ try await stopChatAsync()
while (m.ctrlInitInProgress) { try await deleteChatAsync()
try await Task.sleep(nanoseconds: 50_000000)
}
if m.chatRunning == true {
try await stopChatAsync()
}
if m.chatInitialized {
/**
* The following sequence can bring a user here:
* the user opened the app, entered app passcode, went to background, returned back, entered self-destruct code.
* In this case database should be closed to prevent possible situation when OS can deny database removal command
* */
chatCloseStore()
}
deleteAppDatabaseAndFiles()
// Clear sensitive data on screen just in case app fails to hide its views while new database is created
m.chatId = nil
m.reversedChatItems = []
m.chats = []
m.users = []
_ = kcAppPassword.set(password) _ = kcAppPassword.set(password)
_ = kcSelfDestructPassword.remove() _ = kcSelfDestructPassword.remove()
await NtfManager.shared.removeAllNotifications() await NtfManager.shared.removeAllNotifications()
@@ -80,8 +52,8 @@ struct LocalAuthView: View {
resetChatCtrl() resetChatCtrl()
try initializeChat(start: true) try initializeChat(start: true)
m.chatDbChanged = false m.chatDbChanged = false
AppChatState.shared.set(.active) appStateGroupDefault.set(.active)
if m.currentUser != nil || !m.chatInitialized { return } if m.currentUser != nil { return }
var profile: Profile? = nil var profile: Profile? = nil
if let displayName = displayName, displayName != "" { if let displayName = displayName, displayName != "" {
profile = Profile(displayName: displayName, fullName: "") profile = Profile(displayName: displayName, fullName: "")
@@ -14,8 +14,6 @@ struct PasscodeView: View {
var reason: String? = nil var reason: String? = nil
var submitLabel: LocalizedStringKey var submitLabel: LocalizedStringKey
var submitEnabled: ((String) -> Bool)? var submitEnabled: ((String) -> Bool)?
@Binding var buttonsEnabled: Bool
var submit: () -> Void var submit: () -> Void
var cancel: () -> Void var cancel: () -> Void
@@ -72,11 +70,11 @@ struct PasscodeView: View {
@ViewBuilder private func buttonsView() -> some View { @ViewBuilder private func buttonsView() -> some View {
Button(action: cancel) { Button(action: cancel) {
Label("Cancel", systemImage: "multiply") Label("Cancel", systemImage: "multiply")
}.disabled(!buttonsEnabled) }
Button(action: submit) { Button(action: submit) {
Label(submitLabel, systemImage: "checkmark") Label(submitLabel, systemImage: "checkmark")
} }
.disabled(submitEnabled?(passcode) == false || passcode.count < 4 || !buttonsEnabled) .disabled(submitEnabled?(passcode) == false || passcode.count < 4)
} }
} }
@@ -87,7 +85,6 @@ struct PasscodeViewView_Previews: PreviewProvider {
title: "Enter Passcode", title: "Enter Passcode",
reason: "Unlock app", reason: "Unlock app",
submitLabel: "Submit", submitLabel: "Submit",
buttonsEnabled: Binding.constant(true),
submit: {}, submit: {},
cancel: {} cancel: {}
) )
@@ -11,7 +11,6 @@ import SimpleXChat
struct SetAppPasscodeView: View { struct SetAppPasscodeView: View {
var passcodeKeychain: KeyChainItem = kcAppPassword var passcodeKeychain: KeyChainItem = kcAppPassword
var prohibitedPasscodeKeychain: KeyChainItem = kcSelfDestructPassword
var title: LocalizedStringKey = "New Passcode" var title: LocalizedStringKey = "New Passcode"
var reason: String? var reason: String?
var submit: () -> Void var submit: () -> Void
@@ -42,10 +41,7 @@ struct SetAppPasscodeView: View {
} }
} }
} else { } else {
setPasswordView(title: title, setPasswordView(title: title, submitLabel: "Save") {
submitLabel: "Save",
// Do not allow to set app passcode == selfDestruct passcode
submitEnabled: { pwd in pwd != prohibitedPasscodeKeychain.get() }) {
enteredPassword = passcode enteredPassword = passcode
passcode = "" passcode = ""
confirming = true confirming = true
@@ -58,7 +54,7 @@ struct SetAppPasscodeView: View {
} }
private func setPasswordView(title: LocalizedStringKey, submitLabel: LocalizedStringKey, submitEnabled: (((String) -> Bool))? = nil, submit: @escaping () -> Void) -> some View { private func setPasswordView(title: LocalizedStringKey, submitLabel: LocalizedStringKey, submitEnabled: (((String) -> Bool))? = nil, submit: @escaping () -> Void) -> some View {
PasscodeView(passcode: $passcode, title: title, reason: reason, submitLabel: submitLabel, submitEnabled: submitEnabled, buttonsEnabled: Binding.constant(true), submit: submit) { PasscodeView(passcode: $passcode, title: title, reason: reason, submitLabel: submitLabel, submitEnabled: submitEnabled, submit: submit) {
dismiss() dismiss()
cancel() cancel()
} }
@@ -9,20 +9,8 @@
import SwiftUI import SwiftUI
struct AddContactLearnMore: View { struct AddContactLearnMore: View {
var showTitle: Bool
var body: some View { var body: some View {
List { List {
if showTitle {
Text("One-time invitation link")
.font(.largeTitle)
.bold()
.fixedSize(horizontal: false, vertical: true)
.padding(.vertical)
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
}
VStack(alignment: .leading, spacing: 18) { VStack(alignment: .leading, spacing: 18) {
Text("To connect, your contact can scan QR code or use the link in the app.") Text("To connect, your contact can scan QR code or use the link in the app.")
Text("If you can't meet in person, show QR code in a video call, or share the link.") Text("If you can't meet in person, show QR code in a video call, or share the link.")
@@ -35,6 +23,6 @@ struct AddContactLearnMore: View {
struct AddContactLearnMore_Previews: PreviewProvider { struct AddContactLearnMore_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
AddContactLearnMore(showTitle: true) AddContactLearnMore()
} }
} }
@@ -0,0 +1,129 @@
//
// AddContactView.swift
// SimpleX
//
// Created by Evgeny Poberezkin on 29/01/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import SwiftUI
import CoreImage.CIFilterBuiltins
import SimpleXChat
struct AddContactView: View {
@EnvironmentObject private var chatModel: ChatModel
@Binding var contactConnection: PendingContactConnection?
var connReqInvitation: String
@AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false
var body: some View {
VStack {
List {
Section {
if connReqInvitation != "" {
SimpleXLinkQRCode(uri: connReqInvitation)
} else {
ProgressView()
.progressViewStyle(.circular)
.scaleEffect(2)
.frame(maxWidth: .infinity)
.padding(.vertical)
}
IncognitoToggle(incognitoEnabled: $incognitoDefault)
.disabled(contactConnection == nil)
shareLinkButton(connReqInvitation)
oneTimeLinkLearnMoreButton()
} header: {
Text("1-time link")
} footer: {
sharedProfileInfo(incognitoDefault)
}
}
}
.onAppear { chatModel.connReqInv = connReqInvitation }
.onChange(of: incognitoDefault) { incognito in
Task {
do {
if let contactConn = contactConnection,
let conn = try await apiSetConnectionIncognito(connId: contactConn.pccConnId, incognito: incognito) {
await MainActor.run {
contactConnection = conn
chatModel.updateContactConnection(conn)
}
}
} catch {
logger.error("apiSetConnectionIncognito error: \(responseError(error))")
}
}
}
}
}
struct IncognitoToggle: View {
@Binding var incognitoEnabled: Bool
@State private var showIncognitoSheet = false
var body: some View {
ZStack(alignment: .leading) {
Image(systemName: incognitoEnabled ? "theatermasks.fill" : "theatermasks")
.frame(maxWidth: 24, maxHeight: 24, alignment: .center)
.foregroundColor(incognitoEnabled ? Color.indigo : .secondary)
.font(.system(size: 14))
Toggle(isOn: $incognitoEnabled) {
HStack(spacing: 6) {
Text("Incognito")
Image(systemName: "info.circle")
.foregroundColor(.accentColor)
.font(.system(size: 14))
}
.onTapGesture {
showIncognitoSheet = true
}
}
.padding(.leading, 36)
}
.sheet(isPresented: $showIncognitoSheet) {
IncognitoHelp()
}
}
}
func sharedProfileInfo(_ incognito: Bool) -> Text {
let name = ChatModel.shared.currentUser?.displayName ?? ""
return Text(
incognito
? "A new random profile will be shared."
: "Your profile **\(name)** will be shared."
)
}
func shareLinkButton(_ connReqInvitation: String) -> some View {
Button {
showShareSheet(items: [simplexChatLink(connReqInvitation)])
} label: {
settingsRow("square.and.arrow.up") {
Text("Share 1-time link")
}
}
}
func oneTimeLinkLearnMoreButton() -> some View {
NavigationLink {
AddContactLearnMore()
.navigationTitle("One-time invitation link")
.navigationBarTitleDisplayMode(.large)
} label: {
settingsRow("info.circle") {
Text("Learn more")
}
}
}
struct AddContactView_Previews: PreviewProvider {
static var previews: some View {
AddContactView(
contactConnection: Binding.constant(PendingContactConnection.getSampleData()),
connReqInvitation: "https://simplex.chat/invitation#/?v=1&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FFe5ICmvrm4wkrr6X1LTMii-lhBqLeB76%23MCowBQYDK2VuAyEAdhZZsHpuaAk3Hh1q0uNb_6hGTpuwBIrsp2z9U2T0oC0%3D&e2e=v%3D1%26x3dh%3DMEIwBQYDK2VvAzkAcz6jJk71InuxA0bOX7OUhddfB8Ov7xwQIlIDeXBRZaOntUU4brU5Y3rBzroZBdQJi0FKdtt_D7I%3D%2CMEIwBQYDK2VvAzkA-hDvk1duBi1hlOr08VWSI-Ou4JNNSQjseY69QyKm7Kgg1zZjbpGfyBqSZ2eqys6xtoV4ZtoQUXQ%3D"
)
}
}
@@ -130,10 +130,8 @@ struct AddGroupView: View {
} }
} }
.sheet(isPresented: $showImagePicker) { .sheet(isPresented: $showImagePicker) {
LibraryImagePicker(image: $chosenImage) { _ in LibraryImagePicker(image: $chosenImage) {
await MainActor.run { didSelectItem in showImagePicker = false
showImagePicker = false
}
} }
} }
.alert(isPresented: $showInvalidNameAlert) { .alert(isPresented: $showInvalidNameAlert) {
@@ -187,7 +185,6 @@ struct AddGroupView: View {
hideKeyboard() hideKeyboard()
do { do {
profile.displayName = profile.displayName.trimmingCharacters(in: .whitespaces) profile.displayName = profile.displayName.trimmingCharacters(in: .whitespaces)
profile.groupPreferences = GroupPreferences(history: GroupPreference(enable: .on))
let gInfo = try apiNewGroup(incognito: incognitoDefault, groupProfile: profile) let gInfo = try apiNewGroup(incognito: incognitoDefault, groupProfile: profile)
Task { Task {
let groupMembers = await apiListMembers(gInfo.groupId) let groupMembers = await apiListMembers(gInfo.groupId)
@@ -0,0 +1,42 @@
//
// ConnectViaLinkView.swift
// SimpleX (iOS)
//
// Created by Evgeny on 21/09/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import SwiftUI
enum ConnectViaLinkTab: String {
case scan
case paste
}
struct ConnectViaLinkView: View {
@State private var selection: ConnectViaLinkTab = connectViaLinkTabDefault.get()
var body: some View {
TabView(selection: $selection) {
ScanToConnectView()
.tabItem {
Label("Scan QR code", systemImage: "qrcode")
}
.tag(ConnectViaLinkTab.scan)
PasteToConnectView()
.tabItem {
Label("Paste received link", systemImage: "doc.plaintext")
}
.tag(ConnectViaLinkTab.paste)
}
.onChange(of: selection) { _ in
connectViaLinkTabDefault.set(selection)
}
}
}
struct ConnectViaLinkView_Previews: PreviewProvider {
static var previews: some View {
ConnectViaLinkView()
}
}
@@ -0,0 +1,93 @@
//
// CreateLinkView.swift
// SimpleX (iOS)
//
// Created by Evgeny on 21/09/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
enum CreateLinkTab {
case oneTime
case longTerm
var title: LocalizedStringKey {
switch self {
case .oneTime: return "One-time invitation link"
case .longTerm: return "Your SimpleX address"
}
}
}
struct CreateLinkView: View {
@EnvironmentObject var m: ChatModel
@State var selection: CreateLinkTab
@State var connReqInvitation: String = ""
@State var contactConnection: PendingContactConnection? = nil
@State private var creatingConnReq = false
var viaNavLink = false
var body: some View {
if viaNavLink {
createLinkView()
} else {
NavigationView {
createLinkView()
}
}
}
private func createLinkView() -> some View {
TabView(selection: $selection) {
AddContactView(contactConnection: $contactConnection, connReqInvitation: connReqInvitation)
.tabItem {
Label(
connReqInvitation == ""
? "Create one-time invitation link"
: "One-time invitation link",
systemImage: "1.circle"
)
}
.tag(CreateLinkTab.oneTime)
UserAddressView(viaCreateLinkView: true)
.tabItem {
Label("Your SimpleX address", systemImage: "infinity.circle")
}
.tag(CreateLinkTab.longTerm)
}
.onChange(of: selection) { _ in
if case .oneTime = selection, connReqInvitation == "", contactConnection == nil && !creatingConnReq {
createInvitation()
}
}
.onAppear { m.connReqInv = connReqInvitation }
.onDisappear { m.connReqInv = nil }
.navigationTitle(selection.title)
.navigationBarTitleDisplayMode(.large)
}
private func createInvitation() {
creatingConnReq = true
Task {
if let (connReq, pcc) = await apiAddContact(incognito: incognitoGroupDefault.get()) {
await MainActor.run {
connReqInvitation = connReq
contactConnection = pcc
m.connReqInv = connReq
}
} else {
await MainActor.run {
creatingConnReq = false
}
}
}
}
}
struct CreateLinkView_Previews: PreviewProvider {
static var previews: some View {
CreateLinkView(selection: CreateLinkTab.oneTime)
}
}
@@ -0,0 +1,460 @@
//
// NewChatButton.swift
// SimpleX
//
// Created by Evgeny Poberezkin on 31/01/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
enum NewChatAction: Identifiable {
case createLink(link: String, connection: PendingContactConnection)
case connectViaLink
case createGroup
var id: String {
switch self {
case let .createLink(link, _): return "createLink \(link)"
case .connectViaLink: return "connectViaLink"
case .createGroup: return "createGroup"
}
}
}
struct NewChatButton: View {
@Binding var showAddChat: Bool
@State private var actionSheet: NewChatAction?
var body: some View {
Button { showAddChat = true } label: {
Image(systemName: "square.and.pencil")
.resizable()
.scaledToFit()
.frame(width: 24, height: 24)
}
.confirmationDialog("Start a new chat", isPresented: $showAddChat, titleVisibility: .visible) {
Button("Share one-time invitation link") { addContactAction() }
Button("Connect via link / QR code") { actionSheet = .connectViaLink }
Button("Create secret group") { actionSheet = .createGroup }
}
.sheet(item: $actionSheet) { sheet in
switch sheet {
case let .createLink(link, pcc):
CreateLinkView(selection: .oneTime, connReqInvitation: link, contactConnection: pcc)
case .connectViaLink: ConnectViaLinkView()
case .createGroup: AddGroupView()
}
}
}
func addContactAction() {
Task {
if let (connReq, pcc) = await apiAddContact(incognito: incognitoGroupDefault.get()) {
actionSheet = .createLink(link: connReq, connection: pcc)
}
}
}
}
enum PlanAndConnectAlert: Identifiable {
case ownInvitationLinkConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool)
case invitationLinkConnecting(connectionLink: String)
case ownContactAddressConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool)
case contactAddressConnectingConfirmReconnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool)
case groupLinkConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool)
case groupLinkConnectingConfirmReconnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool)
case groupLinkConnecting(connectionLink: String, groupInfo: GroupInfo?)
var id: String {
switch self {
case let .ownInvitationLinkConfirmConnect(connectionLink, _, _): return "ownInvitationLinkConfirmConnect \(connectionLink)"
case let .invitationLinkConnecting(connectionLink): return "invitationLinkConnecting \(connectionLink)"
case let .ownContactAddressConfirmConnect(connectionLink, _, _): return "ownContactAddressConfirmConnect \(connectionLink)"
case let .contactAddressConnectingConfirmReconnect(connectionLink, _, _): return "contactAddressConnectingConfirmReconnect \(connectionLink)"
case let .groupLinkConfirmConnect(connectionLink, _, _): return "groupLinkConfirmConnect \(connectionLink)"
case let .groupLinkConnectingConfirmReconnect(connectionLink, _, _): return "groupLinkConnectingConfirmReconnect \(connectionLink)"
case let .groupLinkConnecting(connectionLink, _): return "groupLinkConnecting \(connectionLink)"
}
}
}
func planAndConnectAlert(_ alert: PlanAndConnectAlert, dismiss: Bool) -> Alert {
switch alert {
case let .ownInvitationLinkConfirmConnect(connectionLink, connectionPlan, incognito):
return Alert(
title: Text("Connect to yourself?"),
message: Text("This is your own one-time link!"),
primaryButton: .destructive(
Text(incognito ? "Connect incognito" : "Connect"),
action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) }
),
secondaryButton: .cancel()
)
case .invitationLinkConnecting:
return Alert(
title: Text("Already connecting!"),
message: Text("You are already connecting via this one-time link!")
)
case let .ownContactAddressConfirmConnect(connectionLink, connectionPlan, incognito):
return Alert(
title: Text("Connect to yourself?"),
message: Text("This is your own SimpleX address!"),
primaryButton: .destructive(
Text(incognito ? "Connect incognito" : "Connect"),
action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) }
),
secondaryButton: .cancel()
)
case let .contactAddressConnectingConfirmReconnect(connectionLink, connectionPlan, incognito):
return Alert(
title: Text("Repeat connection request?"),
message: Text("You have already requested connection via this address!"),
primaryButton: .destructive(
Text(incognito ? "Connect incognito" : "Connect"),
action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) }
),
secondaryButton: .cancel()
)
case let .groupLinkConfirmConnect(connectionLink, connectionPlan, incognito):
return Alert(
title: Text("Join group?"),
message: Text("You will connect to all group members."),
primaryButton: .default(
Text(incognito ? "Join incognito" : "Join"),
action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) }
),
secondaryButton: .cancel()
)
case let .groupLinkConnectingConfirmReconnect(connectionLink, connectionPlan, incognito):
return Alert(
title: Text("Repeat join request?"),
message: Text("You are already joining the group via this link!"),
primaryButton: .destructive(
Text(incognito ? "Join incognito" : "Join"),
action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) }
),
secondaryButton: .cancel()
)
case let .groupLinkConnecting(_, groupInfo):
if let groupInfo = groupInfo {
return Alert(
title: Text("Group already exists!"),
message: Text("You are already joining the group \(groupInfo.displayName).")
)
} else {
return Alert(
title: Text("Already joining the group!"),
message: Text("You are already joining the group via this link.")
)
}
}
}
enum PlanAndConnectActionSheet: Identifiable {
case askCurrentOrIncognitoProfile(connectionLink: String, connectionPlan: ConnectionPlan?, title: LocalizedStringKey)
case askCurrentOrIncognitoProfileDestructive(connectionLink: String, connectionPlan: ConnectionPlan, title: LocalizedStringKey)
case askCurrentOrIncognitoProfileConnectContactViaAddress(contact: Contact)
case ownGroupLinkConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool?, groupInfo: GroupInfo)
var id: String {
switch self {
case let .askCurrentOrIncognitoProfile(connectionLink, _, _): return "askCurrentOrIncognitoProfile \(connectionLink)"
case let .askCurrentOrIncognitoProfileDestructive(connectionLink, _, _): return "askCurrentOrIncognitoProfileDestructive \(connectionLink)"
case let .askCurrentOrIncognitoProfileConnectContactViaAddress(contact): return "askCurrentOrIncognitoProfileConnectContactViaAddress \(contact.contactId)"
case let .ownGroupLinkConfirmConnect(connectionLink, _, _, _): return "ownGroupLinkConfirmConnect \(connectionLink)"
}
}
}
func planAndConnectActionSheet(_ sheet: PlanAndConnectActionSheet, dismiss: Bool) -> ActionSheet {
switch sheet {
case let .askCurrentOrIncognitoProfile(connectionLink, connectionPlan, title):
return ActionSheet(
title: Text(title),
buttons: [
.default(Text("Use current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: false) },
.default(Text("Use new incognito profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: true) },
.cancel()
]
)
case let .askCurrentOrIncognitoProfileDestructive(connectionLink, connectionPlan, title):
return ActionSheet(
title: Text(title),
buttons: [
.destructive(Text("Use current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: false) },
.destructive(Text("Use new incognito profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: true) },
.cancel()
]
)
case let .askCurrentOrIncognitoProfileConnectContactViaAddress(contact):
return ActionSheet(
title: Text("Connect with \(contact.chatViewName)"),
buttons: [
.default(Text("Use current profile")) { connectContactViaAddress_(contact, dismiss: dismiss, incognito: false) },
.default(Text("Use new incognito profile")) { connectContactViaAddress_(contact, dismiss: dismiss, incognito: true) },
.cancel()
]
)
case let .ownGroupLinkConfirmConnect(connectionLink, connectionPlan, incognito, groupInfo):
if let incognito = incognito {
return ActionSheet(
title: Text("Join your group?\nThis is your link for group \(groupInfo.displayName)!"),
buttons: [
.default(Text("Open group")) { openKnownGroup(groupInfo, dismiss: dismiss, showAlreadyExistsAlert: nil) },
.destructive(Text(incognito ? "Join incognito" : "Join with current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito) },
.cancel()
]
)
} else {
return ActionSheet(
title: Text("Join your group?\nThis is your link for group \(groupInfo.displayName)!"),
buttons: [
.default(Text("Open group")) { openKnownGroup(groupInfo, dismiss: dismiss, showAlreadyExistsAlert: nil) },
.destructive(Text("Use current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: false) },
.destructive(Text("Use new incognito profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: true) },
.cancel()
]
)
}
}
}
func planAndConnect(
_ connectionLink: String,
showAlert: @escaping (PlanAndConnectAlert) -> Void,
showActionSheet: @escaping (PlanAndConnectActionSheet) -> Void,
dismiss: Bool,
incognito: Bool?
) {
Task {
do {
let connectionPlan = try await apiConnectPlan(connReq: connectionLink)
switch connectionPlan {
case let .invitationLink(ilp):
switch ilp {
case .ok:
logger.debug("planAndConnect, .invitationLink, .ok, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito)
} else {
showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect via one-time link"))
}
case .ownLink:
logger.debug("planAndConnect, .invitationLink, .ownLink, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
showAlert(.ownInvitationLinkConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito))
} else {
showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect to yourself?\nThis is your own one-time link!"))
}
case let .connecting(contact_):
logger.debug("planAndConnect, .invitationLink, .connecting, incognito=\(incognito?.description ?? "nil")")
if let contact = contact_ {
openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyConnectingAlert(contact)) }
} else {
showAlert(.invitationLinkConnecting(connectionLink: connectionLink))
}
case let .known(contact):
logger.debug("planAndConnect, .invitationLink, .known, incognito=\(incognito?.description ?? "nil")")
openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyExistsAlert(contact)) }
}
case let .contactAddress(cap):
switch cap {
case .ok:
logger.debug("planAndConnect, .contactAddress, .ok, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito)
} else {
showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect via contact address"))
}
case .ownLink:
logger.debug("planAndConnect, .contactAddress, .ownLink, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
showAlert(.ownContactAddressConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito))
} else {
showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect to yourself?\nThis is your own SimpleX address!"))
}
case .connectingConfirmReconnect:
logger.debug("planAndConnect, .contactAddress, .connectingConfirmReconnect, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
showAlert(.contactAddressConnectingConfirmReconnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito))
} else {
showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "You have already requested connection!\nRepeat connection request?"))
}
case let .connectingProhibit(contact):
logger.debug("planAndConnect, .contactAddress, .connectingProhibit, incognito=\(incognito?.description ?? "nil")")
openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyConnectingAlert(contact)) }
case let .known(contact):
logger.debug("planAndConnect, .contactAddress, .known, incognito=\(incognito?.description ?? "nil")")
openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyExistsAlert(contact)) }
case let .contactViaAddress(contact):
logger.debug("planAndConnect, .contactAddress, .contactViaAddress, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
connectContactViaAddress_(contact, dismiss: dismiss, incognito: incognito)
} else {
showActionSheet(.askCurrentOrIncognitoProfileConnectContactViaAddress(contact: contact))
}
}
case let .groupLink(glp):
switch glp {
case .ok:
if let incognito = incognito {
showAlert(.groupLinkConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito))
} else {
showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Join group"))
}
case let .ownLink(groupInfo):
logger.debug("planAndConnect, .groupLink, .ownLink, incognito=\(incognito?.description ?? "nil")")
showActionSheet(.ownGroupLinkConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito, groupInfo: groupInfo))
case .connectingConfirmReconnect:
logger.debug("planAndConnect, .groupLink, .connectingConfirmReconnect, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
showAlert(.groupLinkConnectingConfirmReconnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito))
} else {
showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "You are already joining the group!\nRepeat join request?"))
}
case let .connectingProhibit(groupInfo_):
logger.debug("planAndConnect, .groupLink, .connectingProhibit, incognito=\(incognito?.description ?? "nil")")
showAlert(.groupLinkConnecting(connectionLink: connectionLink, groupInfo: groupInfo_))
case let .known(groupInfo):
logger.debug("planAndConnect, .groupLink, .known, incognito=\(incognito?.description ?? "nil")")
openKnownGroup(groupInfo, dismiss: dismiss) { AlertManager.shared.showAlert(groupAlreadyExistsAlert(groupInfo)) }
}
}
} catch {
logger.debug("planAndConnect, plan error")
if let incognito = incognito {
connectViaLink(connectionLink, connectionPlan: nil, dismiss: dismiss, incognito: incognito)
} else {
showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: nil, title: "Connect via link"))
}
}
}
}
private func connectContactViaAddress_(_ contact: Contact, dismiss: Bool, incognito: Bool) {
Task {
if dismiss {
DispatchQueue.main.async {
dismissAllSheets(animated: true)
}
}
_ = await connectContactViaAddress(contact.contactId, incognito)
}
}
private func connectViaLink(_ connectionLink: String, connectionPlan: ConnectionPlan?, dismiss: Bool, incognito: Bool) {
Task {
if let connReqType = await apiConnect(incognito: incognito, connReq: connectionLink) {
let crt: ConnReqType
if let plan = connectionPlan {
crt = planToConnReqType(plan)
} else {
crt = connReqType
}
DispatchQueue.main.async {
if dismiss {
dismissAllSheets(animated: true) {
AlertManager.shared.showAlert(connReqSentAlert(crt))
}
} else {
AlertManager.shared.showAlert(connReqSentAlert(crt))
}
}
} else {
if dismiss {
DispatchQueue.main.async {
dismissAllSheets(animated: true)
}
}
}
}
}
func openKnownContact(_ contact: Contact, dismiss: Bool, showAlreadyExistsAlert: (() -> Void)?) {
Task {
let m = ChatModel.shared
if let c = m.getContactChat(contact.contactId) {
DispatchQueue.main.async {
if dismiss {
dismissAllSheets(animated: true) {
m.chatId = c.id
showAlreadyExistsAlert?()
}
} else {
m.chatId = c.id
showAlreadyExistsAlert?()
}
}
}
}
}
func openKnownGroup(_ groupInfo: GroupInfo, dismiss: Bool, showAlreadyExistsAlert: (() -> Void)?) {
Task {
let m = ChatModel.shared
if let g = m.getGroupChat(groupInfo.groupId) {
DispatchQueue.main.async {
if dismiss {
dismissAllSheets(animated: true) {
m.chatId = g.id
showAlreadyExistsAlert?()
}
} else {
m.chatId = g.id
showAlreadyExistsAlert?()
}
}
}
}
}
func contactAlreadyConnectingAlert(_ contact: Contact) -> Alert {
mkAlert(
title: "Contact already exists",
message: "You are already connecting to \(contact.displayName)."
)
}
func groupAlreadyExistsAlert(_ groupInfo: GroupInfo) -> Alert {
mkAlert(
title: "Group already exists",
message: "You are already in group \(groupInfo.displayName)."
)
}
enum ConnReqType: Equatable {
case invitation
case contact
case groupLink
var connReqSentText: LocalizedStringKey {
switch self {
case .invitation: return "You will be connected when your contact's device is online, please wait or check later!"
case .contact: return "You will be connected when your connection request is accepted, please wait or check later!"
case .groupLink: return "You will be connected when group link host's device is online, please wait or check later!"
}
}
}
private func planToConnReqType(_ connectionPlan: ConnectionPlan) -> ConnReqType {
switch connectionPlan {
case .invitationLink: return .invitation
case .contactAddress: return .contact
case .groupLink: return .groupLink
}
}
func connReqSentAlert(_ type: ConnReqType) -> Alert {
return mkAlert(
title: "Connection request sent!",
message: type.connReqSentText
)
}
struct NewChatButton_Previews: PreviewProvider {
static var previews: some View {
NewChatButton(showAddChat: Binding.constant(false))
}
}
@@ -1,52 +0,0 @@
//
// NewChatMenuButton.swift
// SimpleX (iOS)
//
// Created by spaced4ndy on 28.11.2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import SwiftUI
enum NewChatMenuOption: Identifiable {
case newContact
case newGroup
var id: Self { self }
}
struct NewChatMenuButton: View {
@Binding var newChatMenuOption: NewChatMenuOption?
var body: some View {
Menu {
Button {
newChatMenuOption = .newContact
} label: {
Text("Add contact")
}
Button {
newChatMenuOption = .newGroup
} label: {
Text("Create group")
}
} label: {
Image(systemName: "square.and.pencil")
.resizable()
.scaledToFit()
.frame(width: 24, height: 24)
}
.sheet(item: $newChatMenuOption) { opt in
switch opt {
case .newContact: NewChatView(selection: .invite)
case .newGroup: AddGroupView()
}
}
}
}
#Preview {
NewChatMenuButton(
newChatMenuOption: Binding.constant(nil)
)
}
@@ -1,959 +0,0 @@
//
// NewChatView.swift
// SimpleX (iOS)
//
// Created by spaced4ndy on 28.11.2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
import CodeScanner
import AVFoundation
enum SomeAlert: Identifiable {
case someAlert(alert: Alert, id: String)
var id: String {
switch self {
case let .someAlert(_, id): return id
}
}
}
private enum NewChatViewAlert: Identifiable {
case planAndConnectAlert(alert: PlanAndConnectAlert)
case newChatSomeAlert(alert: SomeAlert)
var id: String {
switch self {
case let .planAndConnectAlert(alert): return "planAndConnectAlert \(alert.id)"
case let .newChatSomeAlert(alert): return "newChatSomeAlert \(alert.id)"
}
}
}
enum NewChatOption: Identifiable {
case invite
case connect
var id: Self { self }
}
struct NewChatView: View {
@EnvironmentObject var m: ChatModel
@State var selection: NewChatOption
@State var showQRCodeScanner = false
@State private var invitationUsed: Bool = false
@State private var contactConnection: PendingContactConnection? = nil
@State private var connReqInvitation: String = ""
@State private var creatingConnReq = false
@State private var pastedLink: String = ""
@State private var alert: NewChatViewAlert?
var body: some View {
VStack(alignment: .leading) {
HStack {
Text("New chat")
.font(.largeTitle)
.bold()
.fixedSize(horizontal: false, vertical: true)
Spacer()
InfoSheetButton {
AddContactLearnMore(showTitle: true)
}
}
.padding()
.padding(.top)
Picker("New chat", selection: $selection) {
Label("Add contact", systemImage: "link")
.tag(NewChatOption.invite)
Label("Connect via link", systemImage: "qrcode")
.tag(NewChatOption.connect)
}
.pickerStyle(.segmented)
.padding()
VStack {
// it seems there's a bug in iOS 15 if several views in switch (or if-else) statement have different transitions
// https://developer.apple.com/forums/thread/714977?answerId=731615022#731615022
if case .invite = selection {
prepareAndInviteView()
.transition(.move(edge: .leading))
.onAppear {
createInvitation()
}
}
if case .connect = selection {
ConnectView(showQRCodeScanner: showQRCodeScanner, pastedLink: $pastedLink, alert: $alert)
.transition(.move(edge: .trailing))
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(
// Rectangle is needed for swipe gesture to work on mostly empty views (creatingLinkProgressView and retryButton)
Rectangle()
.fill(Color(uiColor: .systemGroupedBackground))
)
.animation(.easeInOut(duration: 0.3333), value: selection)
.gesture(DragGesture(minimumDistance: 20.0, coordinateSpace: .local)
.onChanged { value in
switch(value.translation.width, value.translation.height) {
case (...0, -30...30): // left swipe
if selection == .invite {
selection = .connect
}
case (0..., -30...30): // right swipe
if selection == .connect {
selection = .invite
}
default: ()
}
}
)
}
.background(Color(.systemGroupedBackground))
.onChange(of: invitationUsed) { used in
if used && !(m.showingInvitation?.connChatUsed ?? true) {
m.markShowingInvitationUsed()
}
}
.onDisappear {
if !(m.showingInvitation?.connChatUsed ?? true),
let conn = contactConnection {
AlertManager.shared.showAlert(Alert(
title: Text("Keep unused invitation?"),
message: Text("You can view invitation link again in connection details."),
primaryButton: .default(Text("Keep")) {},
secondaryButton: .destructive(Text("Delete")) {
Task {
await deleteChat(Chat(
chatInfo: .contactConnection(contactConnection: conn),
chatItems: []
))
}
}
))
}
m.showingInvitation = nil
}
.alert(item: $alert) { a in
switch(a) {
case let .planAndConnectAlert(alert):
return planAndConnectAlert(alert, dismiss: true, cleanup: { pastedLink = "" })
case let .newChatSomeAlert(.someAlert(alert, _)):
return alert
}
}
}
private func prepareAndInviteView() -> some View {
ZStack { // ZStack is needed for views to not make transitions between each other
if connReqInvitation != "" {
InviteView(
invitationUsed: $invitationUsed,
contactConnection: $contactConnection,
connReqInvitation: connReqInvitation
)
} else if creatingConnReq {
creatingLinkProgressView()
} else {
retryButton()
}
}
}
private func createInvitation() {
if connReqInvitation == "" && contactConnection == nil && !creatingConnReq {
creatingConnReq = true
Task {
_ = try? await Task.sleep(nanoseconds: 250_000000)
let (r, apiAlert) = await apiAddContact(incognito: incognitoGroupDefault.get())
if let (connReq, pcc) = r {
await MainActor.run {
m.updateContactConnection(pcc)
m.showingInvitation = ShowingInvitation(connId: pcc.id, connChatUsed: false)
connReqInvitation = connReq
contactConnection = pcc
}
} else {
await MainActor.run {
creatingConnReq = false
if let apiAlert = apiAlert {
alert = .newChatSomeAlert(alert: .someAlert(alert: apiAlert, id: "createInvitation error"))
}
}
}
}
}
}
// Rectangle here and in retryButton are needed for gesture to work
private func creatingLinkProgressView() -> some View {
ProgressView("Creating link…")
.progressViewStyle(.circular)
}
private func retryButton() -> some View {
Button(action: createInvitation) {
VStack(spacing: 6) {
Image(systemName: "arrow.counterclockwise")
Text("Retry")
}
}
}
}
private struct InviteView: View {
@EnvironmentObject var chatModel: ChatModel
@Binding var invitationUsed: Bool
@Binding var contactConnection: PendingContactConnection?
var connReqInvitation: String
@AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false
var body: some View {
List {
Section("Share this 1-time invite link") {
shareLinkView()
}
.listRowInsets(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 10))
qrCodeView()
Section {
IncognitoToggle(incognitoEnabled: $incognitoDefault)
} footer: {
sharedProfileInfo(incognitoDefault)
}
}
.onChange(of: incognitoDefault) { incognito in
Task {
do {
if let contactConn = contactConnection,
let conn = try await apiSetConnectionIncognito(connId: contactConn.pccConnId, incognito: incognito) {
await MainActor.run {
contactConnection = conn
chatModel.updateContactConnection(conn)
}
}
} catch {
logger.error("apiSetConnectionIncognito error: \(responseError(error))")
}
}
setInvitationUsed()
}
}
private func shareLinkView() -> some View {
HStack {
let link = simplexChatLink(connReqInvitation)
linkTextView(link)
Button {
showShareSheet(items: [link])
setInvitationUsed()
} label: {
Image(systemName: "square.and.arrow.up")
.padding(.top, -7)
}
}
.frame(maxWidth: .infinity)
}
private func qrCodeView() -> some View {
Section("Or show this code") {
SimpleXLinkQRCode(uri: connReqInvitation, onShare: setInvitationUsed)
.padding()
.background(
RoundedRectangle(cornerRadius: 12, style: .continuous)
.fill(Color(uiColor: .secondarySystemGroupedBackground))
)
.padding(.horizontal)
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
}
}
private func setInvitationUsed() {
if !invitationUsed {
invitationUsed = true
}
}
}
private struct ConnectView: View {
@Environment(\.dismiss) var dismiss: DismissAction
@State var showQRCodeScanner = false
@State private var cameraAuthorizationStatus: AVAuthorizationStatus?
@Binding var pastedLink: String
@Binding var alert: NewChatViewAlert?
@State private var sheet: PlanAndConnectActionSheet?
var body: some View {
List {
Section("Paste the link you received") {
pasteLinkView()
}
scanCodeView()
}
.actionSheet(item: $sheet) { s in
planAndConnectActionSheet(s, dismiss: true, cleanup: { pastedLink = "" })
}
.onAppear {
let status = AVCaptureDevice.authorizationStatus(for: .video)
cameraAuthorizationStatus = status
if showQRCodeScanner {
switch status {
case .notDetermined: askCameraAuthorization()
case .restricted: showQRCodeScanner = false
case .denied: showQRCodeScanner = false
case .authorized: ()
@unknown default: askCameraAuthorization()
}
}
}
}
func askCameraAuthorization(_ cb: (() -> Void)? = nil) {
AVCaptureDevice.requestAccess(for: .video) { allowed in
cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
if allowed { cb?() }
}
}
@ViewBuilder private func pasteLinkView() -> some View {
if pastedLink == "" {
Button {
if let str = UIPasteboard.general.string {
if let link = strHasSingleSimplexLink(str.trimmingCharacters(in: .whitespaces)) {
pastedLink = link.text
// It would be good to hide it, but right now it is not clear how to release camera in CodeScanner
// https://github.com/twostraws/CodeScanner/issues/121
// No known tricks worked (changing view ID, wrapping it in another view, etc.)
// showQRCodeScanner = false
connect(pastedLink)
} else {
alert = .newChatSomeAlert(alert: .someAlert(
alert: mkAlert(title: "Invalid link", message: "The text you pasted is not a SimpleX link."),
id: "pasteLinkView: code is not a SimpleX link"
))
}
}
} label: {
Text("Tap to paste link")
}
.disabled(!ChatModel.shared.pasteboardHasStrings)
.frame(maxWidth: .infinity, alignment: .center)
} else {
linkTextView(pastedLink)
}
}
private func scanCodeView() -> some View {
Section("Or scan QR code") {
if showQRCodeScanner, case .authorized = cameraAuthorizationStatus {
CodeScannerView(codeTypes: [.qr], scanMode: .continuous, completion: processQRCode)
.aspectRatio(1, contentMode: .fit)
.cornerRadius(12)
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
.padding(.horizontal)
} else {
Button {
switch cameraAuthorizationStatus {
case .notDetermined: askCameraAuthorization { showQRCodeScanner = true }
case .restricted: ()
case .denied: UIApplication.shared.open(appSettingsURL)
case .authorized: showQRCodeScanner = true
default: askCameraAuthorization { showQRCodeScanner = true }
}
} label: {
ZStack {
Rectangle()
.aspectRatio(contentMode: .fill)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.foregroundColor(Color.clear)
switch cameraAuthorizationStatus {
case .restricted: Text("Camera not available")
case .denied: Label("Enable camera access", systemImage: "camera")
default: Label("Tap to scan", systemImage: "qrcode")
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
.padding()
.background(
RoundedRectangle(cornerRadius: 12, style: .continuous)
.fill(Color(uiColor: .secondarySystemGroupedBackground))
)
.padding(.horizontal)
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
.disabled(cameraAuthorizationStatus == .restricted)
}
}
}
private func processQRCode(_ resp: Result<ScanResult, ScanError>) {
switch resp {
case let .success(r):
let link = r.string
if strIsSimplexLink(r.string) {
connect(link)
} else {
alert = .newChatSomeAlert(alert: .someAlert(
alert: mkAlert(title: "Invalid QR code", message: "The code you scanned is not a SimpleX link QR code."),
id: "processQRCode: code is not a SimpleX link"
))
}
case let .failure(e):
logger.error("processQRCode QR code error: \(e.localizedDescription)")
alert = .newChatSomeAlert(alert: .someAlert(
alert: mkAlert(title: "Invalid QR code", message: "Error scanning code: \(e.localizedDescription)"),
id: "processQRCode: failure"
))
}
}
private func connect(_ link: String) {
planAndConnect(
link,
showAlert: { alert = .planAndConnectAlert(alert: $0) },
showActionSheet: { sheet = $0 },
dismiss: true,
incognito: nil
)
}
}
private func linkTextView(_ link: String) -> some View {
Text(link)
.lineLimit(1)
.font(.caption)
.truncationMode(.middle)
}
struct InfoSheetButton<Content: View>: View {
@ViewBuilder let content: Content
@State private var showInfoSheet = false
var body: some View {
Button {
showInfoSheet = true
} label: {
Image(systemName: "info.circle")
.resizable()
.scaledToFit()
.frame(width: 24, height: 24)
}
.sheet(isPresented: $showInfoSheet) {
content
}
}
}
func strIsSimplexLink(_ str: String) -> Bool {
if let parsedMd = parseSimpleXMarkdown(str),
parsedMd.count == 1,
case .simplexLink = parsedMd[0].format {
return true
} else {
return false
}
}
func strHasSingleSimplexLink(_ str: String) -> FormattedText? {
if let parsedMd = parseSimpleXMarkdown(str) {
let parsedLinks = parsedMd.filter({ $0.format?.isSimplexLink ?? false })
if parsedLinks.count == 1 {
return parsedLinks[0]
} else {
return nil
}
} else {
return nil
}
}
struct IncognitoToggle: View {
@Binding var incognitoEnabled: Bool
@State private var showIncognitoSheet = false
var body: some View {
ZStack(alignment: .leading) {
Image(systemName: incognitoEnabled ? "theatermasks.fill" : "theatermasks")
.frame(maxWidth: 24, maxHeight: 24, alignment: .center)
.foregroundColor(incognitoEnabled ? Color.indigo : .secondary)
.font(.system(size: 14))
Toggle(isOn: $incognitoEnabled) {
HStack(spacing: 6) {
Text("Incognito")
Image(systemName: "info.circle")
.foregroundColor(.accentColor)
.font(.system(size: 14))
}
.onTapGesture {
showIncognitoSheet = true
}
}
.padding(.leading, 36)
}
.sheet(isPresented: $showIncognitoSheet) {
IncognitoHelp()
}
}
}
func sharedProfileInfo(_ incognito: Bool) -> Text {
let name = ChatModel.shared.currentUser?.displayName ?? ""
return Text(
incognito
? "A new random profile will be shared."
: "Your profile **\(name)** will be shared."
)
}
enum PlanAndConnectAlert: Identifiable {
case ownInvitationLinkConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool)
case invitationLinkConnecting(connectionLink: String)
case ownContactAddressConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool)
case contactAddressConnectingConfirmReconnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool)
case groupLinkConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool)
case groupLinkConnectingConfirmReconnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool)
case groupLinkConnecting(connectionLink: String, groupInfo: GroupInfo?)
var id: String {
switch self {
case let .ownInvitationLinkConfirmConnect(connectionLink, _, _): return "ownInvitationLinkConfirmConnect \(connectionLink)"
case let .invitationLinkConnecting(connectionLink): return "invitationLinkConnecting \(connectionLink)"
case let .ownContactAddressConfirmConnect(connectionLink, _, _): return "ownContactAddressConfirmConnect \(connectionLink)"
case let .contactAddressConnectingConfirmReconnect(connectionLink, _, _): return "contactAddressConnectingConfirmReconnect \(connectionLink)"
case let .groupLinkConfirmConnect(connectionLink, _, _): return "groupLinkConfirmConnect \(connectionLink)"
case let .groupLinkConnectingConfirmReconnect(connectionLink, _, _): return "groupLinkConnectingConfirmReconnect \(connectionLink)"
case let .groupLinkConnecting(connectionLink, _): return "groupLinkConnecting \(connectionLink)"
}
}
}
func planAndConnectAlert(_ alert: PlanAndConnectAlert, dismiss: Bool, cleanup: (() -> Void)? = nil) -> Alert {
switch alert {
case let .ownInvitationLinkConfirmConnect(connectionLink, connectionPlan, incognito):
return Alert(
title: Text("Connect to yourself?"),
message: Text("This is your own one-time link!"),
primaryButton: .destructive(
Text(incognito ? "Connect incognito" : "Connect"),
action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) }
),
secondaryButton: .cancel() { cleanup?() }
)
case .invitationLinkConnecting:
return Alert(
title: Text("Already connecting!"),
message: Text("You are already connecting via this one-time link!"),
dismissButton: .default(Text("OK")) { cleanup?() }
)
case let .ownContactAddressConfirmConnect(connectionLink, connectionPlan, incognito):
return Alert(
title: Text("Connect to yourself?"),
message: Text("This is your own SimpleX address!"),
primaryButton: .destructive(
Text(incognito ? "Connect incognito" : "Connect"),
action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) }
),
secondaryButton: .cancel() { cleanup?() }
)
case let .contactAddressConnectingConfirmReconnect(connectionLink, connectionPlan, incognito):
return Alert(
title: Text("Repeat connection request?"),
message: Text("You have already requested connection via this address!"),
primaryButton: .destructive(
Text(incognito ? "Connect incognito" : "Connect"),
action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) }
),
secondaryButton: .cancel() { cleanup?() }
)
case let .groupLinkConfirmConnect(connectionLink, connectionPlan, incognito):
return Alert(
title: Text("Join group?"),
message: Text("You will connect to all group members."),
primaryButton: .default(
Text(incognito ? "Join incognito" : "Join"),
action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) }
),
secondaryButton: .cancel() { cleanup?() }
)
case let .groupLinkConnectingConfirmReconnect(connectionLink, connectionPlan, incognito):
return Alert(
title: Text("Repeat join request?"),
message: Text("You are already joining the group via this link!"),
primaryButton: .destructive(
Text(incognito ? "Join incognito" : "Join"),
action: { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) }
),
secondaryButton: .cancel() { cleanup?() }
)
case let .groupLinkConnecting(_, groupInfo):
if let groupInfo = groupInfo {
return Alert(
title: Text("Group already exists!"),
message: Text("You are already joining the group \(groupInfo.displayName)."),
dismissButton: .default(Text("OK")) { cleanup?() }
)
} else {
return Alert(
title: Text("Already joining the group!"),
message: Text("You are already joining the group via this link."),
dismissButton: .default(Text("OK")) { cleanup?() }
)
}
}
}
enum PlanAndConnectActionSheet: Identifiable {
case askCurrentOrIncognitoProfile(connectionLink: String, connectionPlan: ConnectionPlan?, title: LocalizedStringKey)
case askCurrentOrIncognitoProfileDestructive(connectionLink: String, connectionPlan: ConnectionPlan, title: LocalizedStringKey)
case askCurrentOrIncognitoProfileConnectContactViaAddress(contact: Contact)
case ownGroupLinkConfirmConnect(connectionLink: String, connectionPlan: ConnectionPlan, incognito: Bool?, groupInfo: GroupInfo)
var id: String {
switch self {
case let .askCurrentOrIncognitoProfile(connectionLink, _, _): return "askCurrentOrIncognitoProfile \(connectionLink)"
case let .askCurrentOrIncognitoProfileDestructive(connectionLink, _, _): return "askCurrentOrIncognitoProfileDestructive \(connectionLink)"
case let .askCurrentOrIncognitoProfileConnectContactViaAddress(contact): return "askCurrentOrIncognitoProfileConnectContactViaAddress \(contact.contactId)"
case let .ownGroupLinkConfirmConnect(connectionLink, _, _, _): return "ownGroupLinkConfirmConnect \(connectionLink)"
}
}
}
func planAndConnectActionSheet(_ sheet: PlanAndConnectActionSheet, dismiss: Bool, cleanup: (() -> Void)? = nil) -> ActionSheet {
switch sheet {
case let .askCurrentOrIncognitoProfile(connectionLink, connectionPlan, title):
return ActionSheet(
title: Text(title),
buttons: [
.default(Text("Use current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: false, cleanup: cleanup) },
.default(Text("Use new incognito profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: true, cleanup: cleanup) },
.cancel() { cleanup?() }
]
)
case let .askCurrentOrIncognitoProfileDestructive(connectionLink, connectionPlan, title):
return ActionSheet(
title: Text(title),
buttons: [
.destructive(Text("Use current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: false, cleanup: cleanup) },
.destructive(Text("Use new incognito profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: true, cleanup: cleanup) },
.cancel() { cleanup?() }
]
)
case let .askCurrentOrIncognitoProfileConnectContactViaAddress(contact):
return ActionSheet(
title: Text("Connect with \(contact.chatViewName)"),
buttons: [
.default(Text("Use current profile")) { connectContactViaAddress_(contact, dismiss: dismiss, incognito: false, cleanup: cleanup) },
.default(Text("Use new incognito profile")) { connectContactViaAddress_(contact, dismiss: dismiss, incognito: true, cleanup: cleanup) },
.cancel() { cleanup?() }
]
)
case let .ownGroupLinkConfirmConnect(connectionLink, connectionPlan, incognito, groupInfo):
if let incognito = incognito {
return ActionSheet(
title: Text("Join your group?\nThis is your link for group \(groupInfo.displayName)!"),
buttons: [
.default(Text("Open group")) { openKnownGroup(groupInfo, dismiss: dismiss, showAlreadyExistsAlert: nil) },
.destructive(Text(incognito ? "Join incognito" : "Join with current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup) },
.cancel() { cleanup?() }
]
)
} else {
return ActionSheet(
title: Text("Join your group?\nThis is your link for group \(groupInfo.displayName)!"),
buttons: [
.default(Text("Open group")) { openKnownGroup(groupInfo, dismiss: dismiss, showAlreadyExistsAlert: nil) },
.destructive(Text("Use current profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: false, cleanup: cleanup) },
.destructive(Text("Use new incognito profile")) { connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: true, cleanup: cleanup) },
.cancel() { cleanup?() }
]
)
}
}
}
func planAndConnect(
_ connectionLink: String,
showAlert: @escaping (PlanAndConnectAlert) -> Void,
showActionSheet: @escaping (PlanAndConnectActionSheet) -> Void,
dismiss: Bool,
incognito: Bool?,
cleanup: (() -> Void)? = nil,
filterKnownContact: ((Contact) -> Void)? = nil,
filterKnownGroup: ((GroupInfo) -> Void)? = nil
) {
Task {
do {
let connectionPlan = try await apiConnectPlan(connReq: connectionLink)
switch connectionPlan {
case let .invitationLink(ilp):
switch ilp {
case .ok:
logger.debug("planAndConnect, .invitationLink, .ok, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup)
} else {
showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect via one-time link"))
}
case .ownLink:
logger.debug("planAndConnect, .invitationLink, .ownLink, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
showAlert(.ownInvitationLinkConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito))
} else {
showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect to yourself?\nThis is your own one-time link!"))
}
case let .connecting(contact_):
logger.debug("planAndConnect, .invitationLink, .connecting, incognito=\(incognito?.description ?? "nil")")
if let contact = contact_ {
if let f = filterKnownContact {
f(contact)
} else {
openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyConnectingAlert(contact)) }
}
} else {
showAlert(.invitationLinkConnecting(connectionLink: connectionLink))
}
case let .known(contact):
logger.debug("planAndConnect, .invitationLink, .known, incognito=\(incognito?.description ?? "nil")")
if let f = filterKnownContact {
f(contact)
} else {
openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyExistsAlert(contact)) }
}
}
case let .contactAddress(cap):
switch cap {
case .ok:
logger.debug("planAndConnect, .contactAddress, .ok, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
connectViaLink(connectionLink, connectionPlan: connectionPlan, dismiss: dismiss, incognito: incognito, cleanup: cleanup)
} else {
showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect via contact address"))
}
case .ownLink:
logger.debug("planAndConnect, .contactAddress, .ownLink, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
showAlert(.ownContactAddressConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito))
} else {
showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Connect to yourself?\nThis is your own SimpleX address!"))
}
case .connectingConfirmReconnect:
logger.debug("planAndConnect, .contactAddress, .connectingConfirmReconnect, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
showAlert(.contactAddressConnectingConfirmReconnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito))
} else {
showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "You have already requested connection!\nRepeat connection request?"))
}
case let .connectingProhibit(contact):
logger.debug("planAndConnect, .contactAddress, .connectingProhibit, incognito=\(incognito?.description ?? "nil")")
if let f = filterKnownContact {
f(contact)
} else {
openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyConnectingAlert(contact)) }
}
case let .known(contact):
logger.debug("planAndConnect, .contactAddress, .known, incognito=\(incognito?.description ?? "nil")")
if let f = filterKnownContact {
f(contact)
} else {
openKnownContact(contact, dismiss: dismiss) { AlertManager.shared.showAlert(contactAlreadyExistsAlert(contact)) }
}
case let .contactViaAddress(contact):
logger.debug("planAndConnect, .contactAddress, .contactViaAddress, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
connectContactViaAddress_(contact, dismiss: dismiss, incognito: incognito, cleanup: cleanup)
} else {
showActionSheet(.askCurrentOrIncognitoProfileConnectContactViaAddress(contact: contact))
}
}
case let .groupLink(glp):
switch glp {
case .ok:
if let incognito = incognito {
showAlert(.groupLinkConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito))
} else {
showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "Join group"))
}
case let .ownLink(groupInfo):
logger.debug("planAndConnect, .groupLink, .ownLink, incognito=\(incognito?.description ?? "nil")")
if let f = filterKnownGroup {
f(groupInfo)
}
showActionSheet(.ownGroupLinkConfirmConnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito, groupInfo: groupInfo))
case .connectingConfirmReconnect:
logger.debug("planAndConnect, .groupLink, .connectingConfirmReconnect, incognito=\(incognito?.description ?? "nil")")
if let incognito = incognito {
showAlert(.groupLinkConnectingConfirmReconnect(connectionLink: connectionLink, connectionPlan: connectionPlan, incognito: incognito))
} else {
showActionSheet(.askCurrentOrIncognitoProfileDestructive(connectionLink: connectionLink, connectionPlan: connectionPlan, title: "You are already joining the group!\nRepeat join request?"))
}
case let .connectingProhibit(groupInfo_):
logger.debug("planAndConnect, .groupLink, .connectingProhibit, incognito=\(incognito?.description ?? "nil")")
showAlert(.groupLinkConnecting(connectionLink: connectionLink, groupInfo: groupInfo_))
case let .known(groupInfo):
logger.debug("planAndConnect, .groupLink, .known, incognito=\(incognito?.description ?? "nil")")
if let f = filterKnownGroup {
f(groupInfo)
} else {
openKnownGroup(groupInfo, dismiss: dismiss) { AlertManager.shared.showAlert(groupAlreadyExistsAlert(groupInfo)) }
}
}
}
} catch {
logger.debug("planAndConnect, plan error")
if let incognito = incognito {
connectViaLink(connectionLink, connectionPlan: nil, dismiss: dismiss, incognito: incognito, cleanup: cleanup)
} else {
showActionSheet(.askCurrentOrIncognitoProfile(connectionLink: connectionLink, connectionPlan: nil, title: "Connect via link"))
}
}
}
}
private func connectContactViaAddress_(_ contact: Contact, dismiss: Bool, incognito: Bool, cleanup: (() -> Void)? = nil) {
Task {
if dismiss {
DispatchQueue.main.async {
dismissAllSheets(animated: true)
}
}
_ = await connectContactViaAddress(contact.contactId, incognito)
cleanup?()
}
}
private func connectViaLink(
_ connectionLink: String,
connectionPlan: ConnectionPlan?,
dismiss: Bool,
incognito: Bool,
cleanup: (() -> Void)?
) {
Task {
if let (connReqType, pcc) = await apiConnect(incognito: incognito, connReq: connectionLink) {
await MainActor.run {
ChatModel.shared.updateContactConnection(pcc)
}
let crt: ConnReqType
if let plan = connectionPlan {
crt = planToConnReqType(plan)
} else {
crt = connReqType
}
DispatchQueue.main.async {
if dismiss {
dismissAllSheets(animated: true) {
AlertManager.shared.showAlert(connReqSentAlert(crt))
}
} else {
AlertManager.shared.showAlert(connReqSentAlert(crt))
}
}
} else {
if dismiss {
DispatchQueue.main.async {
dismissAllSheets(animated: true)
}
}
}
cleanup?()
}
}
func openKnownContact(_ contact: Contact, dismiss: Bool, showAlreadyExistsAlert: (() -> Void)?) {
Task {
let m = ChatModel.shared
if let c = m.getContactChat(contact.contactId) {
DispatchQueue.main.async {
if dismiss {
dismissAllSheets(animated: true) {
m.chatId = c.id
showAlreadyExistsAlert?()
}
} else {
m.chatId = c.id
showAlreadyExistsAlert?()
}
}
}
}
}
func openKnownGroup(_ groupInfo: GroupInfo, dismiss: Bool, showAlreadyExistsAlert: (() -> Void)?) {
Task {
let m = ChatModel.shared
if let g = m.getGroupChat(groupInfo.groupId) {
DispatchQueue.main.async {
if dismiss {
dismissAllSheets(animated: true) {
m.chatId = g.id
showAlreadyExistsAlert?()
}
} else {
m.chatId = g.id
showAlreadyExistsAlert?()
}
}
}
}
}
func contactAlreadyConnectingAlert(_ contact: Contact) -> Alert {
mkAlert(
title: "Contact already exists",
message: "You are already connecting to \(contact.displayName)."
)
}
func groupAlreadyExistsAlert(_ groupInfo: GroupInfo) -> Alert {
mkAlert(
title: "Group already exists",
message: "You are already in group \(groupInfo.displayName)."
)
}
enum ConnReqType: Equatable {
case invitation
case contact
case groupLink
var connReqSentText: LocalizedStringKey {
switch self {
case .invitation: return "You will be connected when your contact's device is online, please wait or check later!"
case .contact: return "You will be connected when your connection request is accepted, please wait or check later!"
case .groupLink: return "You will be connected when group link host's device is online, please wait or check later!"
}
}
}
private func planToConnReqType(_ connectionPlan: ConnectionPlan) -> ConnReqType {
switch connectionPlan {
case .invitationLink: return .invitation
case .contactAddress: return .contact
case .groupLink: return .groupLink
}
}
func connReqSentAlert(_ type: ConnReqType) -> Alert {
return mkAlert(
title: "Connection request sent!",
message: type.connReqSentText
)
}
#Preview {
NewChatView(
selection: .invite
)
}
@@ -0,0 +1,106 @@
//
// PasteToConnectView.swift
// SimpleX (iOS)
//
// Created by Ian Davies on 22/04/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
struct PasteToConnectView: View {
@Environment(\.dismiss) var dismiss: DismissAction
@State private var connectionLink: String = ""
@AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false
@FocusState private var linkEditorFocused: Bool
@State private var alert: PlanAndConnectAlert?
@State private var sheet: PlanAndConnectActionSheet?
var body: some View {
List {
Text("Connect via link")
.font(.largeTitle)
.bold()
.fixedSize(horizontal: false, vertical: true)
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
.onTapGesture { linkEditorFocused = false }
Section {
linkEditor()
Button {
if connectionLink == "" {
connectionLink = UIPasteboard.general.string ?? ""
} else {
connectionLink = ""
}
} label: {
if connectionLink == "" {
settingsRow("doc.plaintext") { Text("Paste") }
} else {
settingsRow("multiply") { Text("Clear") }
}
}
Button {
connect()
} label: {
settingsRow("link") { Text("Connect") }
}
.disabled(connectionLink == "" || connectionLink.trimmingCharacters(in: .whitespaces).firstIndex(of: " ") != nil)
IncognitoToggle(incognitoEnabled: $incognitoDefault)
} footer: {
VStack(alignment: .leading, spacing: 4) {
sharedProfileInfo(incognitoDefault)
Text("You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.")
}
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.alert(item: $alert) { a in planAndConnectAlert(a, dismiss: true) }
.actionSheet(item: $sheet) { s in planAndConnectActionSheet(s, dismiss: true) }
}
private func linkEditor() -> some View {
ZStack {
Group {
if connectionLink.isEmpty {
TextEditor(text: Binding.constant(NSLocalizedString("Paste the link you received to connect with your contact.", comment: "placeholder")))
.foregroundColor(.secondary)
.disabled(true)
}
TextEditor(text: $connectionLink)
.onSubmit(connect)
.textInputAutocapitalization(.never)
.disableAutocorrection(true)
.focused($linkEditorFocused)
}
.allowsTightening(false)
.padding(.horizontal, -5)
.padding(.top, -8)
.frame(height: 180, alignment: .topLeading)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
private func connect() {
let link = connectionLink.trimmingCharacters(in: .whitespaces)
planAndConnect(
link,
showAlert: { alert = $0 },
showActionSheet: { sheet = $0 },
dismiss: true,
incognito: incognitoDefault
)
}
}
struct PasteToConnectView_Previews: PreviewProvider {
static var previews: some View {
PasteToConnectView()
}
}
+21 -17
View File
@@ -11,12 +11,20 @@ import CoreImage.CIFilterBuiltins
struct MutableQRCode: View { struct MutableQRCode: View {
@Binding var uri: String @Binding var uri: String
var withLogo: Bool = true @State private var image: UIImage?
var tintColor = UIColor(red: 0.023, green: 0.176, blue: 0.337, alpha: 1)
var body: some View { var body: some View {
QRCode(uri: uri, withLogo: withLogo, tintColor: tintColor) ZStack {
.id("simplex-qrcode-view-for-\(uri)") if let image = image {
qrCodeImage(image)
}
}
.onAppear {
image = generateImage(uri)
}
.onChange(of: uri) { _ in
image = generateImage(uri)
}
} }
} }
@@ -24,10 +32,9 @@ struct SimpleXLinkQRCode: View {
let uri: String let uri: String
var withLogo: Bool = true var withLogo: Bool = true
var tintColor = UIColor(red: 0.023, green: 0.176, blue: 0.337, alpha: 1) var tintColor = UIColor(red: 0.023, green: 0.176, blue: 0.337, alpha: 1)
var onShare: (() -> Void)? = nil
var body: some View { var body: some View {
QRCode(uri: simplexChatLink(uri), withLogo: withLogo, tintColor: tintColor, onShare: onShare) QRCode(uri: simplexChatLink(uri), withLogo: withLogo, tintColor: tintColor)
} }
} }
@@ -41,9 +48,8 @@ struct QRCode: View {
let uri: String let uri: String
var withLogo: Bool = true var withLogo: Bool = true
var tintColor = UIColor(red: 0.023, green: 0.176, blue: 0.337, alpha: 1) var tintColor = UIColor(red: 0.023, green: 0.176, blue: 0.337, alpha: 1)
var onShare: (() -> Void)? = nil
@State private var image: UIImage? = nil @State private var image: UIImage? = nil
@State private var makeScreenshotFunc: () -> Void = {} @State private var makeScreenshotBinding: () -> Void = {}
var body: some View { var body: some View {
ZStack { ZStack {
@@ -64,20 +70,18 @@ struct QRCode: View {
} }
} }
.onAppear { .onAppear {
makeScreenshotFunc = { makeScreenshotBinding = {
let size = CGSizeMake(1024 / UIScreen.main.scale, 1024 / UIScreen.main.scale) let size = CGSizeMake(1024 / UIScreen.main.scale, 1024 / UIScreen.main.scale)
showShareSheet(items: [makeScreenshot(geo.frame(in: .local).origin, size)]) showShareSheet(items: [makeScreenshot(geo.frame(in: .local).origin, size)])}
onShare?()
}
} }
.frame(width: geo.size.width, height: geo.size.height) .frame(width: geo.size.width, height: geo.size.height)
} }
} }
.onTapGesture(perform: makeScreenshotFunc) .onTapGesture(perform: makeScreenshotBinding)
.onAppear { .onAppear {
image = image ?? generateImage(uri, tintColor: tintColor) image = image ?? generateImage(uri)?.replaceColor(UIColor.black, tintColor)
} }
.frame(maxWidth: .infinity, maxHeight: .infinity)
} }
} }
@@ -89,13 +93,13 @@ private func qrCodeImage(_ image: UIImage) -> some View {
.textSelection(.enabled) .textSelection(.enabled)
} }
private func generateImage(_ uri: String, tintColor: UIColor) -> UIImage? { private func generateImage(_ uri: String) -> UIImage? {
let context = CIContext() let context = CIContext()
let filter = CIFilter.qrCodeGenerator() let filter = CIFilter.qrCodeGenerator()
filter.message = Data(uri.utf8) filter.message = Data(uri.utf8)
if let outputImage = filter.outputImage, if let outputImage = filter.outputImage,
let cgImage = context.createCGImage(outputImage, from: outputImage.extent) { let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
return UIImage(cgImage: cgImage).replaceColor(UIColor.black, tintColor) return UIImage(cgImage: cgImage)
} }
return nil return nil
} }
@@ -0,0 +1,79 @@
//
// ConnectContactView.swift
// SimpleX
//
// Created by Evgeny Poberezkin on 29/01/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
import CodeScanner
struct ScanToConnectView: View {
@Environment(\.dismiss) var dismiss: DismissAction
@AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false
@State private var alert: PlanAndConnectAlert?
@State private var sheet: PlanAndConnectActionSheet?
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Text("Scan QR code")
.font(.largeTitle)
.bold()
.fixedSize(horizontal: false, vertical: true)
.padding(.vertical)
CodeScannerView(codeTypes: [.qr], completion: processQRCode)
.aspectRatio(1, contentMode: .fit)
.cornerRadius(12)
IncognitoToggle(incognitoEnabled: $incognitoDefault)
.padding(.horizontal)
.padding(.vertical, 6)
.background(
RoundedRectangle(cornerRadius: 12, style: .continuous)
.fill(Color(uiColor: .systemBackground))
)
.padding(.top)
VStack(alignment: .leading, spacing: 4) {
sharedProfileInfo(incognitoDefault)
Text("If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.")
}
.frame(maxWidth: .infinity, alignment: .leading)
.font(.footnote)
.foregroundColor(.secondary)
.padding(.horizontal)
}
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
}
.background(Color(.systemGroupedBackground))
.alert(item: $alert) { a in planAndConnectAlert(a, dismiss: true) }
.actionSheet(item: $sheet) { s in planAndConnectActionSheet(s, dismiss: true) }
}
func processQRCode(_ resp: Result<ScanResult, ScanError>) {
switch resp {
case let .success(r):
planAndConnect(
r.string,
showAlert: { alert = $0 },
showActionSheet: { sheet = $0 },
dismiss: true,
incognito: incognitoDefault
)
case let .failure(e):
logger.error("ConnectContactView.processQRCode QR code error: \(e.localizedDescription)")
dismiss()
}
}
}
struct ConnectContactView_Previews: PreviewProvider {
static var previews: some View {
ScanToConnectView()
}
}
@@ -11,14 +11,12 @@ import SimpleXChat
enum UserProfileAlert: Identifiable { enum UserProfileAlert: Identifiable {
case duplicateUserError case duplicateUserError
case invalidDisplayNameError
case createUserError(error: LocalizedStringKey) case createUserError(error: LocalizedStringKey)
case invalidNameError(validName: String) case invalidNameError(validName: String)
var id: String { var id: String {
switch self { switch self {
case .duplicateUserError: return "duplicateUserError" case .duplicateUserError: return "duplicateUserError"
case .invalidDisplayNameError: return "invalidDisplayNameError"
case .createUserError: return "createUserError" case .createUserError: return "createUserError"
case let .invalidNameError(validName): return "invalidNameError \(validName)" case let .invalidNameError(validName): return "invalidNameError \(validName)"
} }
@@ -189,12 +187,6 @@ private func createProfile(_ displayName: String, showAlert: (UserProfileAlert)
} else { } else {
showAlert(.duplicateUserError) showAlert(.duplicateUserError)
} }
case .chatCmdError(_, .error(.invalidDisplayName)):
if m.currentUser == nil {
AlertManager.shared.showAlert(invalidDisplayNameAlert)
} else {
showAlert(.invalidDisplayNameError)
}
default: default:
let err: LocalizedStringKey = "Error: \(responseError(error))" let err: LocalizedStringKey = "Error: \(responseError(error))"
if m.currentUser == nil { if m.currentUser == nil {
@@ -215,7 +207,6 @@ private func canCreateProfile(_ displayName: String) -> Bool {
func userProfileAlert(_ alert: UserProfileAlert, _ displayName: Binding<String>) -> Alert { func userProfileAlert(_ alert: UserProfileAlert, _ displayName: Binding<String>) -> Alert {
switch alert { switch alert {
case .duplicateUserError: return duplicateUserAlert case .duplicateUserError: return duplicateUserAlert
case .invalidDisplayNameError: return invalidDisplayNameAlert
case let .createUserError(err): return creatUserErrorAlert(err) case let .createUserError(err): return creatUserErrorAlert(err)
case let .invalidNameError(name): return createInvalidNameAlert(name, displayName) case let .invalidNameError(name): return createInvalidNameAlert(name, displayName)
} }
@@ -228,13 +219,6 @@ private var duplicateUserAlert: Alert {
) )
} }
private var invalidDisplayNameAlert: Alert {
Alert(
title: Text("Invalid display name!"),
message: Text("This display name is invalid. Please choose another name.")
)
}
private func creatUserErrorAlert(_ err: LocalizedStringKey) -> Alert { private func creatUserErrorAlert(_ err: LocalizedStringKey) -> Alert {
Alert( Alert(
title: Text("Error creating profile!"), title: Text("Error creating profile!"),
@@ -81,6 +81,11 @@ struct CreateSimpleXAddress: View {
DispatchQueue.main.async { DispatchQueue.main.async {
m.userAddress = UserContactLink(connReqContact: connReqContact) m.userAddress = UserContactLink(connReqContact: connReqContact)
} }
if let u = try await apiSetProfileAddress(on: true) {
DispatchQueue.main.async {
m.updateUser(u)
}
}
await MainActor.run { progressIndicator = false } await MainActor.run { progressIndicator = false }
} catch let error { } catch let error {
logger.error("CreateSimpleXAddress create address: \(responseError(error))") logger.error("CreateSimpleXAddress create address: \(responseError(error))")
@@ -95,7 +100,7 @@ struct CreateSimpleXAddress: View {
} label: { } label: {
Text("Create SimpleX address").font(.title) Text("Create SimpleX address").font(.title)
} }
Text("You can make it visible to your SimpleX contacts via Settings.") Text("Your contacts in SimpleX will see it.\nYou can change it in Settings.")
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
.font(.footnote) .font(.footnote)
.padding(.horizontal, 32) .padding(.horizontal, 32)
@@ -283,37 +283,6 @@ private let versionDescriptions: [VersionDescription] = [
), ),
] ]
), ),
VersionDescription(
version: "v5.4",
post: URL(string: "https://simplex.chat/blog/20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.html"),
features: [
FeatureDescription(
icon: "desktopcomputer",
title: "Link mobile and desktop apps! 🔗",
description: "Via secure quantum resistant protocol."
),
FeatureDescription(
icon: "person.2",
title: "Better groups",
description: "Faster joining and more reliable messages."
),
FeatureDescription(
icon: "theatermasks",
title: "Incognito groups",
description: "Create a group using a random profile."
),
FeatureDescription(
icon: "hand.raised",
title: "Block group members",
description: "To hide unwanted messages."
),
FeatureDescription(
icon: "gift",
title: "A few more things",
description: "- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!"
),
]
),
] ]
private let lastVersion = versionDescriptions.last!.version private let lastVersion = versionDescriptions.last!.version
@@ -16,19 +16,12 @@ struct ConnectDesktopView: View {
var viaSettings = false var viaSettings = false
@AppStorage(DEFAULT_DEVICE_NAME_FOR_REMOTE_ACCESS) private var deviceName = UIDevice.current.name @AppStorage(DEFAULT_DEVICE_NAME_FOR_REMOTE_ACCESS) private var deviceName = UIDevice.current.name
@AppStorage(DEFAULT_CONFIRM_REMOTE_SESSIONS) private var confirmRemoteSessions = false @AppStorage(DEFAULT_CONFIRM_REMOTE_SESSIONS) private var confirmRemoteSessions = false
@AppStorage(DEFAULT_CONNECT_REMOTE_VIA_MULTICAST) private var connectRemoteViaMulticast = true @AppStorage(DEFAULT_CONNECT_REMOTE_VIA_MULTICAST) private var connectRemoteViaMulticast = false
@AppStorage(DEFAULT_CONNECT_REMOTE_VIA_MULTICAST_AUTO) private var connectRemoteViaMulticastAuto = true @AppStorage(DEFAULT_OFFER_REMOTE_MULTICAST) private var offerRemoteMulticast = true
@AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false @AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false
@State private var sessionAddress: String = "" @State private var sessionAddress: String = ""
@State private var remoteCtrls: [RemoteCtrlInfo] = [] @State private var remoteCtrls: [RemoteCtrlInfo] = []
@State private var alert: ConnectDesktopAlert? @State private var alert: ConnectDesktopAlert?
@State private var showConnectScreen = true
@State private var showQRCodeScanner = true
@State private var firstAppearance = true
private var useMulticast: Bool {
connectRemoteViaMulticast && !remoteCtrls.isEmpty
}
private enum ConnectDesktopAlert: Identifiable { private enum ConnectDesktopAlert: Identifiable {
case unlinkDesktop(rc: RemoteCtrlInfo) case unlinkDesktop(rc: RemoteCtrlInfo)
@@ -74,14 +67,9 @@ struct ConnectDesktopView: View {
var viewBody: some View { var viewBody: some View {
Group { Group {
let discovery = m.remoteCtrlSession?.discovery if let session = m.remoteCtrlSession {
if discovery == true || (discovery == nil && !showConnectScreen) {
searchingDesktopView()
} else if let session = m.remoteCtrlSession {
switch session.sessionState { switch session.sessionState {
case .starting: connectingDesktopView(session, nil) case .starting: connectingDesktopView(session, nil)
case .searching: searchingDesktopView()
case let .found(rc, compatible): foundDesktopView(session, rc, compatible)
case let .connecting(rc_): connectingDesktopView(session, rc_) case let .connecting(rc_): connectingDesktopView(session, rc_)
case let .pendingConfirmation(rc_, sessCode): case let .pendingConfirmation(rc_, sessCode):
if confirmRemoteSessions || rc_ == nil { if confirmRemoteSessions || rc_ == nil {
@@ -93,35 +81,16 @@ struct ConnectDesktopView: View {
} }
case let .connected(rc, _): activeSessionView(session, rc) case let .connected(rc, _): activeSessionView(session, rc)
} }
// The hack below prevents camera freezing when exiting linked devices view.
// Using showQRCodeScanner inside connectDesktopView or passing it as parameter still results in freezing.
} else if showQRCodeScanner || firstAppearance {
connectDesktopView()
} else { } else {
connectDesktopView(showScanner: false) connectDesktopView()
} }
} }
.onAppear { .onAppear {
setDeviceName(deviceName) setDeviceName(deviceName)
updateRemoteCtrls() updateRemoteCtrls()
showConnectScreen = !useMulticast
if m.remoteCtrlSession != nil {
disconnectDesktop()
} else if useMulticast {
findKnownDesktop()
}
// The hack below prevents camera freezing when exiting linked devices view.
// `firstAppearance` prevents camera flicker when the view first opens.
// moving `showQRCodeScanner = false` to `onDisappear` (to avoid `firstAppearance`) does not prevent freeze.
showQRCodeScanner = false
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
firstAppearance = false
showQRCodeScanner = true
}
} }
.onDisappear { .onDisappear {
if m.remoteCtrlSession != nil { if m.remoteCtrlSession != nil {
showConnectScreen = false
disconnectDesktop() disconnectDesktop()
} }
} }
@@ -165,14 +134,12 @@ struct ConnectDesktopView: View {
.interactiveDismissDisabled(m.activeRemoteCtrl) .interactiveDismissDisabled(m.activeRemoteCtrl)
} }
private func connectDesktopView(showScanner: Bool = true) -> some View { private func connectDesktopView() -> some View {
List { List {
Section("This device name") { Section("This device name") {
devicesView() devicesView()
} }
if showScanner { scanDesctopAddressView()
scanDesctopAddressView()
}
if developerTools { if developerTools {
desktopAddressView() desktopAddressView()
} }
@@ -200,56 +167,6 @@ struct ConnectDesktopView: View {
.navigationTitle("Connecting to desktop") .navigationTitle("Connecting to desktop")
} }
private func searchingDesktopView() -> some View {
List {
Section("This device name") {
devicesView()
}
Section("Found desktop") {
Text("Waiting for desktop...").italic()
Button {
disconnectDesktop()
} label: {
Label("Scan QR code", systemImage: "qrcode")
}
}
}
.navigationTitle("Connecting to desktop")
}
@ViewBuilder private func foundDesktopView(_ session: RemoteCtrlSession, _ rc: RemoteCtrlInfo, _ compatible: Bool) -> some View {
let v = List {
Section("This device name") {
devicesView()
}
Section("Found desktop") {
ctrlDeviceNameText(session, rc)
ctrlDeviceVersionText(session)
if !compatible {
Text("Not compatible!").foregroundColor(.red)
} else if !connectRemoteViaMulticastAuto {
Button {
confirmKnownDesktop(rc)
} label: {
Label("Connect", systemImage: "checkmark")
}
}
}
if !compatible && !connectRemoteViaMulticastAuto {
Section {
disconnectButton("Cancel")
}
}
}
.navigationTitle("Found desktop")
if compatible && connectRemoteViaMulticastAuto {
v.onAppear { confirmKnownDesktop(rc) }
} else {
v
}
}
private func verifySessionView(_ session: RemoteCtrlSession, _ rc: RemoteCtrlInfo?, _ sessCode: String) -> some View { private func verifySessionView(_ session: RemoteCtrlSession, _ rc: RemoteCtrlInfo?, _ sessCode: String) -> some View {
List { List {
Section("Connected to desktop") { Section("Connected to desktop") {
@@ -274,7 +191,7 @@ struct ConnectDesktopView: View {
} }
private func ctrlDeviceNameText(_ session: RemoteCtrlSession, _ rc: RemoteCtrlInfo?) -> Text { private func ctrlDeviceNameText(_ session: RemoteCtrlSession, _ rc: RemoteCtrlInfo?) -> Text {
var t = Text(rc?.deviceViewName ?? session.ctrlAppInfo?.deviceName ?? "") var t = Text(rc?.deviceViewName ?? session.ctrlAppInfo.deviceName)
if (rc == nil) { if (rc == nil) {
t = t + Text(" ") + Text("(new)").italic() t = t + Text(" ") + Text("(new)").italic()
} }
@@ -282,8 +199,8 @@ struct ConnectDesktopView: View {
} }
private func ctrlDeviceVersionText(_ session: RemoteCtrlSession) -> Text { private func ctrlDeviceVersionText(_ session: RemoteCtrlSession) -> Text {
let v = session.ctrlAppInfo?.appVersionRange.maxVersion let v = session.ctrlAppInfo.appVersionRange.maxVersion
var t = Text("v\(v ?? "")") var t = Text("v\(v)")
if v != session.appVersion { if v != session.appVersion {
t = t + Text(" ") + Text("(this device v\(session.appVersion))").italic() t = t + Text(" ") + Text("(this device v\(session.appVersion))").italic()
} }
@@ -332,7 +249,7 @@ struct ConnectDesktopView: View {
private func scanDesctopAddressView() -> some View { private func scanDesctopAddressView() -> some View {
Section("Scan QR code from desktop") { Section("Scan QR code from desktop") {
CodeScannerView(codeTypes: [.qr], scanMode: .oncePerCode, completion: processDesktopQRCode) CodeScannerView(codeTypes: [.qr], completion: processDesktopQRCode)
.aspectRatio(1, contentMode: .fit) .aspectRatio(1, contentMode: .fit)
.cornerRadius(12) .cornerRadius(12)
.listRowBackground(Color.clear) .listRowBackground(Color.clear)
@@ -384,10 +301,7 @@ struct ConnectDesktopView: View {
Section("Linked desktop options") { Section("Linked desktop options") {
Toggle("Verify connections", isOn: $confirmRemoteSessions) Toggle("Verify connections", isOn: $confirmRemoteSessions)
Toggle("Discover via local network", isOn: $connectRemoteViaMulticast) Toggle("Discover on network", isOn: $connectRemoteViaMulticast).disabled(true)
if connectRemoteViaMulticast {
Toggle("Connect automatically", isOn: $connectRemoteViaMulticastAuto)
}
} }
} }
.navigationTitle("Linked desktops") .navigationTitle("Linked desktops")
@@ -421,42 +335,10 @@ struct ConnectDesktopView: View {
} }
} }
private func findKnownDesktop() {
Task {
do {
try await findKnownRemoteCtrl()
await MainActor.run {
m.remoteCtrlSession = RemoteCtrlSession(
ctrlAppInfo: nil,
appVersion: "",
sessionState: .searching
)
showConnectScreen = true
}
} catch let e {
await MainActor.run {
errorAlert(e)
}
}
}
}
private func confirmKnownDesktop(_ rc: RemoteCtrlInfo) {
connectDesktop_ {
try await confirmRemoteCtrl(rc.remoteCtrlId)
}
}
private func connectDesktopAddress(_ addr: String) { private func connectDesktopAddress(_ addr: String) {
connectDesktop_ {
try await connectRemoteCtrl(desktopAddress: addr)
}
}
private func connectDesktop_(_ connect: @escaping () async throws -> (RemoteCtrlInfo?, CtrlAppInfo, String)) {
Task { Task {
do { do {
let (rc_, ctrlAppInfo, v) = try await connect() let (rc_, ctrlAppInfo, v) = try await connectRemoteCtrl(desktopAddress: addr)
await MainActor.run { await MainActor.run {
sessionAddress = "" sessionAddress = ""
m.remoteCtrlSession = RemoteCtrlSession( m.remoteCtrlSession = RemoteCtrlSession(
@@ -498,11 +380,11 @@ struct ConnectDesktopView: View {
} }
} }
private func disconnectButton(_ label: LocalizedStringKey = "Disconnect") -> some View { private func disconnectButton() -> some View {
Button { Button {
disconnectDesktop(.dismiss) disconnectDesktop()
} label: { } label: {
Label(label, systemImage: "multiply") Label("Disconnect", systemImage: "multiply")
} }
} }
@@ -511,11 +393,7 @@ struct ConnectDesktopView: View {
do { do {
try await stopRemoteCtrl() try await stopRemoteCtrl()
await MainActor.run { await MainActor.run {
if case .connected = m.remoteCtrlSession?.sessionState { switchToLocalSession()
switchToLocalSession()
} else {
m.remoteCtrlSession = nil
}
switch action { switch action {
case .back: dismiss() case .back: dismiss()
case .dismiss: dismiss() case .dismiss: dismiss()
@@ -51,9 +51,9 @@ struct AdvancedNetworkSettings: View {
} }
.disabled(currentNetCfg == NetCfg.proxyDefaults) .disabled(currentNetCfg == NetCfg.proxyDefaults)
timeoutSettingPicker("TCP connection timeout", selection: $netCfg.tcpConnectTimeout, values: [7_500000, 10_000000, 15_000000, 20_000000, 30_000000, 45_000000], label: secondsLabel) timeoutSettingPicker("TCP connection timeout", selection: $netCfg.tcpConnectTimeout, values: [5_000000, 7_500000, 10_000000, 15_000000, 20_000000, 30_000000, 45_000000], label: secondsLabel)
timeoutSettingPicker("Protocol timeout", selection: $netCfg.tcpTimeout, values: [5_000000, 7_000000, 10_000000, 15_000000, 20_000000, 30_000000], label: secondsLabel) timeoutSettingPicker("Protocol timeout", selection: $netCfg.tcpTimeout, values: [3_000000, 5_000000, 7_000000, 10_000000, 15_000000, 20_000000, 30_000000], label: secondsLabel)
timeoutSettingPicker("Protocol timeout per KB", selection: $netCfg.tcpTimeoutPerKb, values: [15_000, 30_000, 45_000, 60_000, 90_000, 120_000], label: secondsLabel) timeoutSettingPicker("Protocol timeout per KB", selection: $netCfg.tcpTimeoutPerKb, values: [15_000, 30_000, 60_000, 90_000, 120_000], label: secondsLabel)
timeoutSettingPicker("PING interval", selection: $netCfg.smpPingInterval, values: [120_000000, 300_000000, 600_000000, 1200_000000, 2400_000000, 3600_000000], label: secondsLabel) timeoutSettingPicker("PING interval", selection: $netCfg.smpPingInterval, values: [120_000000, 300_000000, 600_000000, 1200_000000, 2400_000000, 3600_000000], label: secondsLabel)
intSettingPicker("PING count", selection: $netCfg.smpPingCount, values: [1, 2, 3, 5, 8], label: "") intSettingPicker("PING count", selection: $netCfg.smpPingCount, values: [1, 2, 3, 5, 8], label: "")
Toggle("Enable TCP keep-alive", isOn: $enableKeepAlive) Toggle("Enable TCP keep-alive", isOn: $enableKeepAlive)
@@ -10,23 +10,24 @@ import SwiftUI
struct IncognitoHelp: View { struct IncognitoHelp: View {
var body: some View { var body: some View {
List { VStack(alignment: .leading) {
Text("Incognito mode") Text("Incognito mode")
.font(.largeTitle) .font(.largeTitle)
.bold() .bold()
.fixedSize(horizontal: false, vertical: true)
.padding(.vertical) .padding(.vertical)
.listRowBackground(Color.clear) ScrollView {
.listRowSeparator(.hidden) VStack(alignment: .leading) {
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) Group {
VStack(alignment: .leading, spacing: 18) { Text("Incognito mode protects your privacy by using a new random profile for each contact.")
Text("Incognito mode protects your privacy by using a new random profile for each contact.") Text("It allows having many anonymous connections without any shared data between them in a single chat profile.")
Text("It allows having many anonymous connections without any shared data between them in a single chat profile.") Text("When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.")
Text("When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.") }
Text("Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).") .padding(.bottom)
}
} }
.listRowBackground(Color.clear)
} }
.frame(maxWidth: .infinity)
.padding()
} }
} }
@@ -14,6 +14,9 @@ struct NotificationsView: View {
@State private var notificationMode: NotificationsMode = ChatModel.shared.notificationMode @State private var notificationMode: NotificationsMode = ChatModel.shared.notificationMode
@State private var showAlert: NotificationAlert? @State private var showAlert: NotificationAlert?
@State private var legacyDatabase = dbContainerGroupDefault.get() == .documents @State private var legacyDatabase = dbContainerGroupDefault.get() == .documents
// @AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false
// @AppStorage(GROUP_DEFAULT_NTF_ENABLE_LOCAL, store: groupDefaults) private var ntfEnableLocal = false
// @AppStorage(GROUP_DEFAULT_NTF_ENABLE_PERIODIC, store: groupDefaults) private var ntfEnablePeriodic = false
var body: some View { var body: some View {
List { List {
@@ -85,6 +88,13 @@ struct NotificationsView: View {
.padding(.top, 1) .padding(.top, 1)
} }
} }
// if developerTools {
// Section(String("Experimental")) {
// Toggle(String("Always enable local"), isOn: $ntfEnableLocal)
// Toggle(String("Always enable periodic"), isOn: $ntfEnablePeriodic)
// }
// }
} }
.disabled(legacyDatabase) .disabled(legacyDatabase)
} }
@@ -109,7 +119,7 @@ struct NotificationsView: View {
private func ntfModeAlertTitle(_ mode: NotificationsMode) -> LocalizedStringKey { private func ntfModeAlertTitle(_ mode: NotificationsMode) -> LocalizedStringKey {
switch mode { switch mode {
case .off: return "Use only local notifications?" case .off: return "Turn off notifications?"
case .periodic: return "Enable periodic notifications?" case .periodic: return "Enable periodic notifications?"
case .instant: return "Enable instant notifications?" case .instant: return "Enable instant notifications?"
} }
@@ -63,6 +63,7 @@ struct PreferencesView: View {
private func featureFooter(_ feature: ChatFeature, _ allowFeature: Binding<FeatureAllowed>) -> some View { private func featureFooter(_ feature: ChatFeature, _ allowFeature: Binding<FeatureAllowed>) -> some View {
Text(feature.allowDescription(allowFeature.wrappedValue)) Text(feature.allowDescription(allowFeature.wrappedValue))
.frame(height: 36, alignment: .topLeading)
} }
private func savePreferences() { private func savePreferences() {
@@ -467,7 +467,6 @@ struct SimplexLockView: View {
switch a { switch a {
case .enableAuth: case .enableAuth:
SetAppPasscodeView { SetAppPasscodeView {
m.contentViewAccessAuthenticated = true
laLockDelay = 30 laLockDelay = 30
prefPerformLA = true prefPerformLA = true
showChangePassword = true showChangePassword = true
@@ -491,23 +490,14 @@ struct SimplexLockView: View {
showLAAlert(.laPasscodeNotChangedAlert) showLAAlert(.laPasscodeNotChangedAlert)
} }
case .enableSelfDestruct: case .enableSelfDestruct:
SetAppPasscodeView( SetAppPasscodeView(passcodeKeychain: kcSelfDestructPassword, title: "Set passcode", reason: NSLocalizedString("Enable self-destruct passcode", comment: "set passcode view")) {
passcodeKeychain: kcSelfDestructPassword,
prohibitedPasscodeKeychain: kcAppPassword,
title: "Set passcode",
reason: NSLocalizedString("Enable self-destruct passcode", comment: "set passcode view")
) {
updateSelfDestruct() updateSelfDestruct()
showLAAlert(.laSelfDestructPasscodeSetAlert) showLAAlert(.laSelfDestructPasscodeSetAlert)
} cancel: { } cancel: {
revertSelfDestruct() revertSelfDestruct()
} }
case .changeSelfDestructPasscode: case .changeSelfDestructPasscode:
SetAppPasscodeView( SetAppPasscodeView(passcodeKeychain: kcSelfDestructPassword, reason: NSLocalizedString("Change self-destruct passcode", comment: "set passcode view")) {
passcodeKeychain: kcSelfDestructPassword,
prohibitedPasscodeKeychain: kcAppPassword,
reason: NSLocalizedString("Change self-destruct passcode", comment: "set passcode view")
) {
showLAAlert(.laSelfDestructPasscodeChangedAlert) showLAAlert(.laSelfDestructPasscodeChangedAlert)
} cancel: { } cancel: {
showLAAlert(.laPasscodeNotChangedAlert) showLAAlert(.laPasscodeNotChangedAlert)
@@ -629,7 +619,6 @@ struct SimplexLockView: View {
authenticate(reason: NSLocalizedString("Enable SimpleX Lock", comment: "authentication reason")) { laResult in authenticate(reason: NSLocalizedString("Enable SimpleX Lock", comment: "authentication reason")) { laResult in
switch laResult { switch laResult {
case .success: case .success:
m.contentViewAccessAuthenticated = true
prefPerformLA = true prefPerformLA = true
laAlert = .laTurnedOnAlert laAlert = .laTurnedOnAlert
case .failed: case .failed:
@@ -21,7 +21,7 @@ struct ScanProtocolServer: View {
.font(.largeTitle) .font(.largeTitle)
.bold() .bold()
.padding(.vertical) .padding(.vertical)
CodeScannerView(codeTypes: [.qr], scanMode: .oncePerCode, completion: processQRCode) CodeScannerView(codeTypes: [.qr], completion: processQRCode)
.aspectRatio(1, contentMode: .fit) .aspectRatio(1, contentMode: .fit)
.cornerRadius(12) .cornerRadius(12)
.padding(.top) .padding(.top)
@@ -56,7 +56,7 @@ let DEFAULT_SHOW_UNREAD_AND_FAVORITES = "showUnreadAndFavorites"
let DEFAULT_DEVICE_NAME_FOR_REMOTE_ACCESS = "deviceNameForRemoteAccess" let DEFAULT_DEVICE_NAME_FOR_REMOTE_ACCESS = "deviceNameForRemoteAccess"
let DEFAULT_CONFIRM_REMOTE_SESSIONS = "confirmRemoteSessions" let DEFAULT_CONFIRM_REMOTE_SESSIONS = "confirmRemoteSessions"
let DEFAULT_CONNECT_REMOTE_VIA_MULTICAST = "connectRemoteViaMulticast" let DEFAULT_CONNECT_REMOTE_VIA_MULTICAST = "connectRemoteViaMulticast"
let DEFAULT_CONNECT_REMOTE_VIA_MULTICAST_AUTO = "connectRemoteViaMulticastAuto" let DEFAULT_OFFER_REMOTE_MULTICAST = "offerRemoteMulticast"
let appDefaults: [String: Any] = [ let appDefaults: [String: Any] = [
DEFAULT_SHOW_LA_NOTICE: false, DEFAULT_SHOW_LA_NOTICE: false,
@@ -91,16 +91,10 @@ let appDefaults: [String: Any] = [
DEFAULT_CUSTOM_DISAPPEARING_MESSAGE_TIME: 300, DEFAULT_CUSTOM_DISAPPEARING_MESSAGE_TIME: 300,
DEFAULT_SHOW_UNREAD_AND_FAVORITES: false, DEFAULT_SHOW_UNREAD_AND_FAVORITES: false,
DEFAULT_CONFIRM_REMOTE_SESSIONS: false, DEFAULT_CONFIRM_REMOTE_SESSIONS: false,
DEFAULT_CONNECT_REMOTE_VIA_MULTICAST: true, DEFAULT_CONNECT_REMOTE_VIA_MULTICAST: false,
DEFAULT_CONNECT_REMOTE_VIA_MULTICAST_AUTO: true, DEFAULT_OFFER_REMOTE_MULTICAST: true
] ]
// not used anymore
enum ConnectViaLinkTab: String {
case scan
case paste
}
enum SimpleXLinkMode: String, Identifiable { enum SimpleXLinkMode: String, Identifiable {
case description case description
case full case full
@@ -190,8 +190,7 @@ struct UserAddressView: View {
@ViewBuilder private func existingAddressView(_ userAddress: UserContactLink) -> some View { @ViewBuilder private func existingAddressView(_ userAddress: UserContactLink) -> some View {
Section { Section {
SimpleXLinkQRCode(uri: userAddress.connReqContact) MutableQRCode(uri: Binding.constant(simplexChatLink(userAddress.connReqContact)))
.id("simplex-contact-address-qrcode-\(userAddress.connReqContact)")
shareQRCodeButton(userAddress) shareQRCodeButton(userAddress)
if MFMailComposeViewController.canSendMail() { if MFMailComposeViewController.canSendMail() {
shareViaEmailButton(userAddress) shareViaEmailButton(userAddress)
@@ -120,10 +120,8 @@ struct UserProfile: View {
} }
} }
.sheet(isPresented: $showImagePicker) { .sheet(isPresented: $showImagePicker) {
LibraryImagePicker(image: $chosenImage) { _ in LibraryImagePicker(image: $chosenImage) {
await MainActor.run { didSelectItem in showImagePicker = false
showImagePicker = false
}
} }
} }
.onChange(of: chosenImage) { image in .onChange(of: chosenImage) { image in
@@ -303,17 +303,14 @@
<target>)</target> <target>)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve">
<source>**Add contact**: to create a new invitation link, or connect via a link you received.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target>**Добави нов контакт**: за да създадете своя еднократен QR код или линк за вашия контакт.</target> <target>**Добави нов контакт**: за да създадете своя еднократен QR код или линк за вашия контакт.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Create group**: to create a new group." xml:space="preserve"> <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<source>**Create group**: to create a new group.</source> <source>**Create link / QR code** for your contact to use.</source>
<target>**Създай линк / QR код**, който вашият контакт да използва.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -326,6 +323,11 @@
<target>**Най-поверително**: не използвайте сървъра за известия SimpleX Chat, периодично проверявайте съобщенията във фонов режим (зависи от това колко често използвате приложението).</target> <target>**Най-поверително**: не използвайте сървъра за известия SimpleX Chat, периодично проверявайте съобщенията във фонов режим (зависи от това колко често използвате приложението).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve">
<source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source>
<target>**Поставете получения линк** или го отворете в браузъра и докоснете **Отваряне в мобилно приложение**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve">
<source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source>
<target>**Моля, обърнете внимание**: НЯМА да можете да възстановите или промените паролата, ако я загубите.</target> <target>**Моля, обърнете внимание**: НЯМА да можете да възстановите или промените паролата, ако я загубите.</target>
@@ -336,6 +338,11 @@
<target>**Препоръчително**: токенът на устройството и известията се изпращат до сървъра за уведомяване на SimpleX Chat, но не и съдържанието, размерът на съобщението или от кого е.</target> <target>**Препоръчително**: токенът на устройството и известията се изпращат до сървъра за уведомяване на SimpleX Chat, но не и съдържанието, размерът на съобщението или от кого е.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve">
<source>**Scan QR code**: to connect to your contact in person or via video call.</source>
<target>**Сканирай QR код**: за да се свържете с вашия контакт лично или чрез видеообаждане.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target>**Внимание**: Незабавните push известия изискват парола, запазена в Keychain.</target> <target>**Внимание**: Незабавните push известия изискват парола, запазена в Keychain.</target>
@@ -379,12 +386,6 @@
- и още!</target> - и още!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="- optionally notify deleted contacts.&#10;- profile names with spaces.&#10;- and more!" xml:space="preserve">
<source>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve"> <trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve">
<source>- voice messages up to 5 minutes. <source>- voice messages up to 5 minutes.
- custom time to disappear. - custom time to disappear.
@@ -433,6 +434,11 @@
<target>1 седмица</target> <target>1 седмица</target>
<note>time interval</note> <note>time interval</note>
</trans-unit> </trans-unit>
<trans-unit id="1-time link" xml:space="preserve">
<source>1-time link</source>
<target>Еднократен линк</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="5 minutes" xml:space="preserve"> <trans-unit id="5 minutes" xml:space="preserve">
<source>5 minutes</source> <source>5 minutes</source>
<target>5 минути</target> <target>5 минути</target>
@@ -548,10 +554,6 @@
<target>Добавете адрес към вашия профил, така че вашите контакти да могат да го споделят с други хора. Актуализацията на профила ще бъде изпратена до вашите контакти.</target> <target>Добавете адрес към вашия профил, така че вашите контакти да могат да го споделят с други хора. Актуализацията на профила ще бъде изпратена до вашите контакти.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add contact" xml:space="preserve">
<source>Add contact</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve"> <trans-unit id="Add preset servers" xml:space="preserve">
<source>Add preset servers</source> <source>Add preset servers</source>
<target>Добави предварително зададени сървъри</target> <target>Добави предварително зададени сървъри</target>
@@ -878,10 +880,6 @@
<target>Лош хеш на съобщението</target> <target>Лош хеш на съобщението</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
<source>Better groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better messages" xml:space="preserve"> <trans-unit id="Better messages" xml:space="preserve">
<source>Better messages</source> <source>Better messages</source>
<target>По-добри съобщения</target> <target>По-добри съобщения</target>
@@ -891,10 +889,6 @@
<source>Block</source> <source>Block</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
<source>Block group members</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve"> <trans-unit id="Block member" xml:space="preserve">
<source>Block member</source> <source>Block member</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -948,10 +942,6 @@
<target>Обаждания</target> <target>Обаждания</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Camera not available" xml:space="preserve">
<source>Camera not available</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Can't delete user profile!" xml:space="preserve"> <trans-unit id="Can't delete user profile!" xml:space="preserve">
<source>Can't delete user profile!</source> <source>Can't delete user profile!</source>
<target>Потребителският профил не може да се изтрие!</target> <target>Потребителският профил не може да се изтрие!</target>
@@ -1068,10 +1058,6 @@
<target>Чатът е спрян</target> <target>Чатът е спрян</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve">
<source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve"> <trans-unit id="Chat preferences" xml:space="preserve">
<source>Chat preferences</source> <source>Chat preferences</source>
<target>Чат настройки</target> <target>Чат настройки</target>
@@ -1172,10 +1158,6 @@
<target>Свързване</target> <target>Свързване</target>
<note>server test step</note> <note>server test step</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect automatically" xml:space="preserve">
<source>Connect automatically</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve"> <trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source> <source>Connect incognito</source>
<target>Свързване инкогнито</target> <target>Свързване инкогнито</target>
@@ -1208,6 +1190,11 @@ This is your own one-time link!</source>
<target>Свърване чрез линк</target> <target>Свърване чрез линк</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link / QR code" xml:space="preserve">
<source>Connect via link / QR code</source>
<target>Свърване чрез линк/QR код</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link" xml:space="preserve"> <trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source> <source>Connect via one-time link</source>
<target>Свързване чрез еднократен линк за връзка</target> <target>Свързване чрез еднократен линк за връзка</target>
@@ -1342,10 +1329,6 @@ This is your own one-time link!</source>
<target>Създай SimpleX адрес</target> <target>Създай SimpleX адрес</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create a group using a random profile." xml:space="preserve">
<source>Create a group using a random profile.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source> <source>Create an address to let people connect with you.</source>
<target>Създайте адрес, за да позволите на хората да се свързват с вас.</target> <target>Създайте адрес, за да позволите на хората да се свързват с вас.</target>
@@ -1375,6 +1358,11 @@ This is your own one-time link!</source>
<target>Създайте нов профил в [настолното приложение](https://simplex.chat/downloads/). 💻</target> <target>Създайте нов профил в [настолното приложение](https://simplex.chat/downloads/). 💻</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create one-time invitation link" xml:space="preserve">
<source>Create one-time invitation link</source>
<target>Създай линк за еднократна покана</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -1399,10 +1387,6 @@ This is your own one-time link!</source>
<target>Създаден на %@</target> <target>Създаден на %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve"> <trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source> <source>Current Passcode</source>
<target>Текущ kод за достъп</target> <target>Текущ kод за достъп</target>
@@ -1860,8 +1844,8 @@ This cannot be undone!</source>
<target>Открийте и се присъединете към групи</target> <target>Открийте и се присъединете към групи</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve"> <trans-unit id="Discover on network" xml:space="preserve">
<source>Discover via local network</source> <source>Discover on network</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -1944,10 +1928,6 @@ This cannot be undone!</source>
<target>Активиране на автоматично изтриване на съобщения?</target> <target>Активиране на автоматично изтриване на съобщения?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enable camera access" xml:space="preserve">
<source>Enable camera access</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve"> <trans-unit id="Enable for all" xml:space="preserve">
<source>Enable for all</source> <source>Enable for all</source>
<target>Активиране за всички</target> <target>Активиране за всички</target>
@@ -2013,10 +1993,6 @@ This cannot be undone!</source>
<target>Криптирано съобщение или друго събитие</target> <target>Криптирано съобщение или друго събитие</target>
<note>notification</note> <note>notification</note>
</trans-unit> </trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve">
<source>Encrypted message: app is stopped</source>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve"> <trans-unit id="Encrypted message: database error" xml:space="preserve">
<source>Encrypted message: database error</source> <source>Encrypted message: database error</source>
<target>Криптирано съобщение: грешка в базата данни</target> <target>Криптирано съобщение: грешка в базата данни</target>
@@ -2242,10 +2218,6 @@ This cannot be undone!</source>
<target>Грешка при зареждане на %@ сървъри</target> <target>Грешка при зареждане на %@ сървъри</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error receiving file" xml:space="preserve"> <trans-unit id="Error receiving file" xml:space="preserve">
<source>Error receiving file</source> <source>Error receiving file</source>
<target>Грешка при получаване на файл</target> <target>Грешка при получаване на файл</target>
@@ -2286,10 +2258,6 @@ This cannot be undone!</source>
<target>Грешка при запазване на потребителска парола</target> <target>Грешка при запазване на потребителска парола</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error scanning code: %@" xml:space="preserve">
<source>Error scanning code: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve"> <trans-unit id="Error sending email" xml:space="preserve">
<source>Error sending email</source> <source>Error sending email</source>
<target>Грешка при изпращане на имейл</target> <target>Грешка при изпращане на имейл</target>
@@ -2414,10 +2382,6 @@ This cannot be undone!</source>
<target>Бързо и без чакане, докато подателят е онлайн!</target> <target>Бързо и без чакане, докато подателят е онлайн!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve"> <trans-unit id="Favorite" xml:space="preserve">
<source>Favorite</source> <source>Favorite</source>
<target>Любим</target> <target>Любим</target>
@@ -2513,10 +2477,6 @@ This cannot be undone!</source>
<target>За конзолата</target> <target>За конзолата</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Found desktop" xml:space="preserve">
<source>Found desktop</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="French interface" xml:space="preserve"> <trans-unit id="French interface" xml:space="preserve">
<source>French interface</source> <source>French interface</source>
<target>Френски интерфейс</target> <target>Френски интерфейс</target>
@@ -2759,6 +2719,11 @@ This cannot be undone!</source>
<target>Ако не можете да се срещнете лично, покажете QR код във видеоразговора или споделете линка.</target> <target>Ако не можете да се срещнете лично, покажете QR код във видеоразговора или споделете линка.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve">
<source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source>
<target>Ако не можете да се срещнете на живо, можете да **сканирате QR код във видеообаждането** или вашият контакт може да сподели линк за покана.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve">
<source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source>
<target>Ако въведете този kод за достъп, когато отваряте приложението, всички данни от приложението ще бъдат необратимо изтрити!</target> <target>Ако въведете този kод за достъп, когато отваряте приложението, всички данни от приложението ще бъдат необратимо изтрити!</target>
@@ -2834,10 +2799,6 @@ This cannot be undone!</source>
<target>Инкогнито</target> <target>Инкогнито</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve"> <trans-unit id="Incognito mode" xml:space="preserve">
<source>Incognito mode</source> <source>Incognito mode</source>
<target>Режим инкогнито</target> <target>Режим инкогнито</target>
@@ -2914,27 +2875,15 @@ This cannot be undone!</source>
<target>Интерфейс</target> <target>Интерфейс</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid QR code" xml:space="preserve">
<source>Invalid QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve"> <trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source> <source>Invalid connection link</source>
<target>Невалиден линк за връзка</target> <target>Невалиден линк за връзка</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
<source>Invalid link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve"> <trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source> <source>Invalid name!</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid response" xml:space="preserve">
<source>Invalid response</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve"> <trans-unit id="Invalid server address!" xml:space="preserve">
<source>Invalid server address!</source> <source>Invalid server address!</source>
<target>Невалиден адрес на сървъра!</target> <target>Невалиден адрес на сървъра!</target>
@@ -3049,18 +2998,10 @@ This is your link for group %@!</source>
<target>Присъединяване към групата</target> <target>Присъединяване към групата</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep" xml:space="preserve">
<source>Keep</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
<source>Keep the app open to use it from desktop</source> <source>Keep the app open to use it from desktop</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep unused invitation?" xml:space="preserve">
<source>Keep unused invitation?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve"> <trans-unit id="Keep your connections" xml:space="preserve">
<source>Keep your connections</source> <source>Keep your connections</source>
<target>Запазете връзките си</target> <target>Запазете връзките си</target>
@@ -3121,10 +3062,6 @@ This is your link for group %@!</source>
<target>Ограничения</target> <target>Ограничения</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve"> <trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source> <source>Linked desktop options</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3143,11 +3080,6 @@ This is your link for group %@!</source>
<target>Съобщения на живо</target> <target>Съобщения на живо</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Local" xml:space="preserve">
<source>Local</source>
<target>Локално</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Local name" xml:space="preserve"> <trans-unit id="Local name" xml:space="preserve">
<source>Local name</source> <source>Local name</source>
<target>Локално име</target> <target>Локално име</target>
@@ -3387,10 +3319,6 @@ This is your link for group %@!</source>
<target>Нов kод за достъп</target> <target>Нов kод за достъп</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="New chat" xml:space="preserve">
<source>New chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve"> <trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source> <source>New contact request</source>
<target>Нова заявка за контакт</target> <target>Нова заявка за контакт</target>
@@ -3491,10 +3419,6 @@ This is your link for group %@!</source>
<target>Няма получени или изпратени файлове</target> <target>Няма получени или изпратени файлове</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Not compatible!" xml:space="preserve">
<source>Not compatible!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve"> <trans-unit id="Notifications" xml:space="preserve">
<source>Notifications</source> <source>Notifications</source>
<target>Известия</target> <target>Известия</target>
@@ -3514,15 +3438,16 @@ This is your link for group %@!</source>
- да деактивират членове (роля "наблюдател")</target> - да деактивират членове (роля "наблюдател")</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="OK" xml:space="preserve">
<source>OK</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Off" xml:space="preserve"> <trans-unit id="Off" xml:space="preserve">
<source>Off</source> <source>Off</source>
<target>Изключено</target> <target>Изключено</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Off (Local)" xml:space="preserve">
<source>Off (Local)</source>
<target>Изключено (Локално)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ok" xml:space="preserve"> <trans-unit id="Ok" xml:space="preserve">
<source>Ok</source> <source>Ok</source>
<target>Ок</target> <target>Ок</target>
@@ -3662,16 +3587,9 @@ This is your link for group %@!</source>
<target>Протокол и код с отворен код – всеки може да оперира собствени сървъри.</target> <target>Протокол и код с отворен код – всеки може да оперира собствени сървъри.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Opening app…" xml:space="preserve"> <trans-unit id="Opening database…" xml:space="preserve">
<source>Opening app…</source> <source>Opening database…</source>
<note>No comment provided by engineer.</note> <target>Отваряне на база данни…</target>
</trans-unit>
<trans-unit id="Or scan QR code" xml:space="preserve">
<source>Or scan QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
<source>Or show this code</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="PING count" xml:space="preserve"> <trans-unit id="PING count" xml:space="preserve">
@@ -3714,6 +3632,11 @@ This is your link for group %@!</source>
<target>Парола за показване</target> <target>Парола за показване</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste" xml:space="preserve">
<source>Paste</source>
<target>Постави</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve"> <trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source> <source>Paste desktop address</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3723,10 +3646,16 @@ This is your link for group %@!</source>
<target>Постави изображение</target> <target>Постави изображение</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve"> <trans-unit id="Paste received link" xml:space="preserve">
<source>Paste the link you received</source> <source>Paste received link</source>
<target>Постави получения линк</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Поставете линка, който сте получили, за да се свържете с вашия контакт.</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source> <source>People can connect to you only via the links you share.</source>
<target>Хората могат да се свържат с вас само чрез ликовете, които споделяте.</target> <target>Хората могат да се свържат с вас само чрез ликовете, които споделяте.</target>
@@ -3762,11 +3691,6 @@ This is your link for group %@!</source>
<target>Моля, проверете вашите настройки и тези вашия за контакт.</target> <target>Моля, проверете вашите настройки и тези вашия за контакт.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Please contact developers.&#10;Error: %@" xml:space="preserve">
<source>Please contact developers.
Error: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please contact group admin." xml:space="preserve"> <trans-unit id="Please contact group admin." xml:space="preserve">
<source>Please contact group admin.</source> <source>Please contact group admin.</source>
<target>Моля, свържете се с груповия администартор.</target> <target>Моля, свържете се с груповия администартор.</target>
@@ -3970,10 +3894,6 @@ Error: %@</source>
<target>Прочетете повече в [Ръководство за потребителя](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <target>Прочетете повече в [Ръководство за потребителя](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source>
<target>Прочетете повече в [Ръководство на потребителя](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> <target>Прочетете повече в [Ръководство на потребителя](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target>
@@ -4182,10 +4102,6 @@ Error: %@</source>
<target>Грешка при възстановяване на базата данни</target> <target>Грешка при възстановяване на базата данни</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Retry" xml:space="preserve">
<source>Retry</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reveal" xml:space="preserve"> <trans-unit id="Reveal" xml:space="preserve">
<source>Reveal</source> <source>Reveal</source>
<target>Покажи</target> <target>Покажи</target>
@@ -4340,10 +4256,6 @@ Error: %@</source>
<target>Търсене</target> <target>Търсене</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve"> <trans-unit id="Secure queue" xml:space="preserve">
<source>Secure queue</source> <source>Secure queue</source>
<target>Сигурна опашка</target> <target>Сигурна опашка</target>
@@ -4618,8 +4530,9 @@ Error: %@</source>
<target>Сподели линк</target> <target>Сподели линк</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve"> <trans-unit id="Share one-time invitation link" xml:space="preserve">
<source>Share this 1-time invite link</source> <source>Share one-time invitation link</source>
<target>Сподели линк за еднократна покана</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve"> <trans-unit id="Share with contacts" xml:space="preserve">
@@ -4742,15 +4655,16 @@ Error: %@</source>
<target>Някой</target> <target>Някой</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="Start a new chat" xml:space="preserve">
<source>Start a new chat</source>
<target>Започни нов чат</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start chat" xml:space="preserve"> <trans-unit id="Start chat" xml:space="preserve">
<source>Start chat</source> <source>Start chat</source>
<target>Започни чат</target> <target>Започни чат</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Start chat?" xml:space="preserve">
<source>Start chat?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start migration" xml:space="preserve"> <trans-unit id="Start migration" xml:space="preserve">
<source>Start migration</source> <source>Start migration</source>
<target>Започни миграция</target> <target>Започни миграция</target>
@@ -4875,14 +4789,6 @@ Error: %@</source>
<target>Докосни за инкогнито вход</target> <target>Докосни за инкогнито вход</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Tap to paste link" xml:space="preserve">
<source>Tap to paste link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to scan" xml:space="preserve">
<source>Tap to scan</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve"> <trans-unit id="Tap to start a new chat" xml:space="preserve">
<source>Tap to start a new chat</source> <source>Tap to start a new chat</source>
<target>Докосни за започване на нов чат</target> <target>Докосни за започване на нов чат</target>
@@ -4945,10 +4851,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Опитът за промяна на паролата на базата данни не беше завършен.</target> <target>Опитът за промяна на паролата на базата данни не беше завършен.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source> <source>The connection you accepted will be cancelled!</source>
<target>Връзката, която приехте, ще бъде отказана!</target> <target>Връзката, която приехте, ще бъде отказана!</target>
@@ -5014,10 +4916,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Сървърите за нови връзки на текущия ви чат профил **%@**.</target> <target>Сървърите за нови връзки на текущия ви чат профил **%@**.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve">
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve"> <trans-unit id="Theme" xml:space="preserve">
<source>Theme</source> <source>Theme</source>
<target>Тема</target> <target>Тема</target>
@@ -5095,10 +4993,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>За да се свърже, вашият контакт може да сканира QR код или да използва линка в приложението.</target> <target>За да се свърже, вашият контакт може да сканира QR код или да използва линка в приложението.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve"> <trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source> <source>To make a new connection</source>
<target>За да направите нова връзка</target> <target>За да направите нова връзка</target>
@@ -5166,6 +5060,11 @@ You will be prompted to complete authentication before this feature is enabled.<
<target>Изключи</target> <target>Изключи</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Turn off notifications?" xml:space="preserve">
<source>Turn off notifications?</source>
<target>Изключи известията?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn on" xml:space="preserve"> <trans-unit id="Turn on" xml:space="preserve">
<source>Turn on</source> <source>Turn on</source>
<target>Включи</target> <target>Включи</target>
@@ -5362,10 +5261,6 @@ To connect, please ask your contact to create another connection link and check
<target>Използвай нов инкогнито профил</target> <target>Използвай нов инкогнито профил</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use only local notifications?" xml:space="preserve">
<source>Use only local notifications?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve"> <trans-unit id="Use server" xml:space="preserve">
<source>Use server</source> <source>Use server</source>
<target>Използвай сървър</target> <target>Използвай сървър</target>
@@ -5413,10 +5308,6 @@ To connect, please ask your contact to create another connection link and check
<target>Чрез браузър</target> <target>Чрез браузър</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve"> <trans-unit id="Video call" xml:space="preserve">
<source>Video call</source> <source>Video call</source>
<target>Видео разговор</target> <target>Видео разговор</target>
@@ -5467,10 +5358,6 @@ To connect, please ask your contact to create another connection link and check
<target>Гласово съобщение…</target> <target>Гласово съобщение…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Waiting for desktop..." xml:space="preserve">
<source>Waiting for desktop...</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Waiting for file" xml:space="preserve"> <trans-unit id="Waiting for file" xml:space="preserve">
<source>Waiting for file</source> <source>Waiting for file</source>
<target>Изчаква се получаването на файла</target> <target>Изчаква се получаването на файла</target>
@@ -5615,6 +5502,11 @@ Repeat join request?</source>
<target>Можете да приемате обаждания от заключен екран, без идентификация на устройство и приложението.</target> <target>Можете да приемате обаждания от заключен екран, без идентификация на устройство и приложението.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve">
<source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source>
<target>Можете също да се свържете, като натиснете върху линка. Ако се отвори в браузъра, натиснете върху бутона **Отваряне в мобилно приложение**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can create it later" xml:space="preserve"> <trans-unit id="You can create it later" xml:space="preserve">
<source>You can create it later</source> <source>You can create it later</source>
<target>Можете да го създадете по-късно</target> <target>Можете да го създадете по-късно</target>
@@ -5635,10 +5527,6 @@ Repeat join request?</source>
<target>Можете да скриете или заглушите известията за потребителски профил - плъзнете надясно.</target> <target>Можете да скриете или заглушите известията за потребителски профил - плъзнете надясно.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now send messages to %@" xml:space="preserve"> <trans-unit id="You can now send messages to %@" xml:space="preserve">
<source>You can now send messages to %@</source> <source>You can now send messages to %@</source>
<target>Вече можете да изпращате съобщения до %@</target> <target>Вече можете да изпращате съобщения до %@</target>
@@ -5679,10 +5567,6 @@ Repeat join request?</source>
<target>Можете да използвате markdown за форматиране на съобщенията:</target> <target>Можете да използвате markdown за форматиране на съобщенията:</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can view invitation link again in connection details." xml:space="preserve">
<source>You can view invitation link again in connection details.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can't send messages!" xml:space="preserve"> <trans-unit id="You can't send messages!" xml:space="preserve">
<source>You can't send messages!</source> <source>You can't send messages!</source>
<target>Не може да изпращате съобщения!</target> <target>Не може да изпращате съобщения!</target>
@@ -5867,6 +5751,13 @@ You can cancel this connection and remove the contact (and try later with a new
<target>Вашите контакти могат да позволят пълното изтриване на съобщението.</target> <target>Вашите контакти могат да позволят пълното изтриване на съобщението.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your contacts in SimpleX will see it.&#10;You can change it in Settings." xml:space="preserve">
<source>Your contacts in SimpleX will see it.
You can change it in Settings.</source>
<target>Вашите контакти в SimpleX ще го видят.
Можете да го промените в Настройки.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve"> <trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source> <source>Your contacts will remain connected.</source>
<target>Вашите контакти ще останат свързани.</target> <target>Вашите контакти ще останат свързани.</target>
@@ -5997,10 +5888,6 @@ SimpleX сървърите не могат да видят вашия профи
<target>аудио разговор (не е e2e криптиран)</target> <target>аудио разговор (не е e2e криптиран)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="author" xml:space="preserve">
<source>author</source>
<note>member role</note>
</trans-unit>
<trans-unit id="bad message ID" xml:space="preserve"> <trans-unit id="bad message ID" xml:space="preserve">
<source>bad message ID</source> <source>bad message ID</source>
<target>лошо ID на съобщението</target> <target>лошо ID на съобщението</target>
@@ -303,17 +303,14 @@
<target>)</target> <target>)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve">
<source>**Add contact**: to create a new invitation link, or connect via a link you received.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target>**Přidat nový kontakt**: pro vytvoření jednorázového QR kódu nebo odkazu pro váš kontakt.</target> <target>**Přidat nový kontakt**: pro vytvoření jednorázového QR kódu nebo odkazu pro váš kontakt.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Create group**: to create a new group." xml:space="preserve"> <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<source>**Create group**: to create a new group.</source> <source>**Create link / QR code** for your contact to use.</source>
<target>**Vytvořte odkaz / QR kód** pro váš kontakt.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -326,6 +323,11 @@
<target>**Nejsoukromější**: nepoužívejte server oznámení SimpleX Chat, pravidelně kontrolujte zprávy na pozadí (závisí na tom, jak často aplikaci používáte).</target> <target>**Nejsoukromější**: nepoužívejte server oznámení SimpleX Chat, pravidelně kontrolujte zprávy na pozadí (závisí na tom, jak často aplikaci používáte).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve">
<source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source>
<target>**Vložte přijatý odkaz** nebo jej otevřete v prohlížeči a klepněte na **Otevřít v mobilní aplikaci**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve">
<source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source>
<target>**Upozornění**: Pokud heslo ztratíte, NEBUDETE jej moci obnovit ani změnit.</target> <target>**Upozornění**: Pokud heslo ztratíte, NEBUDETE jej moci obnovit ani změnit.</target>
@@ -336,6 +338,11 @@
<target>**Doporučeno**: Token zařízení a oznámení se odesílají na oznamovací server SimpleX Chat, ale nikoli obsah, velikost nebo od koho jsou zprávy.</target> <target>**Doporučeno**: Token zařízení a oznámení se odesílají na oznamovací server SimpleX Chat, ale nikoli obsah, velikost nebo od koho jsou zprávy.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve">
<source>**Scan QR code**: to connect to your contact in person or via video call.</source>
<target>** Naskenujte QR kód**: pro připojení ke kontaktu osobně nebo prostřednictvím videohovoru.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target>**Upozornění**: Okamžitě doručovaná oznámení vyžadují přístupové heslo uložené v Klíčence.</target> <target>**Upozornění**: Okamžitě doručovaná oznámení vyžadují přístupové heslo uložené v Klíčence.</target>
@@ -379,12 +386,6 @@
- a více!</target> - a více!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="- optionally notify deleted contacts.&#10;- profile names with spaces.&#10;- and more!" xml:space="preserve">
<source>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve"> <trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve">
<source>- voice messages up to 5 minutes. <source>- voice messages up to 5 minutes.
- custom time to disappear. - custom time to disappear.
@@ -433,6 +434,11 @@
<target>1 týden</target> <target>1 týden</target>
<note>time interval</note> <note>time interval</note>
</trans-unit> </trans-unit>
<trans-unit id="1-time link" xml:space="preserve">
<source>1-time link</source>
<target>Jednorázový odkaz</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="5 minutes" xml:space="preserve"> <trans-unit id="5 minutes" xml:space="preserve">
<source>5 minutes</source> <source>5 minutes</source>
<target>5 minut</target> <target>5 minut</target>
@@ -548,10 +554,6 @@
<target>Přidejte adresu do svého profilu, aby ji vaše kontakty mohly sdílet s dalšími lidmi. Aktualizace profilu bude zaslána vašim kontaktům.</target> <target>Přidejte adresu do svého profilu, aby ji vaše kontakty mohly sdílet s dalšími lidmi. Aktualizace profilu bude zaslána vašim kontaktům.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add contact" xml:space="preserve">
<source>Add contact</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve"> <trans-unit id="Add preset servers" xml:space="preserve">
<source>Add preset servers</source> <source>Add preset servers</source>
<target>Přidejte přednastavené servery</target> <target>Přidejte přednastavené servery</target>
@@ -878,10 +880,6 @@
<target>Špatný hash zprávy</target> <target>Špatný hash zprávy</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
<source>Better groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better messages" xml:space="preserve"> <trans-unit id="Better messages" xml:space="preserve">
<source>Better messages</source> <source>Better messages</source>
<target>Lepší zprávy</target> <target>Lepší zprávy</target>
@@ -891,10 +889,6 @@
<source>Block</source> <source>Block</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
<source>Block group members</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve"> <trans-unit id="Block member" xml:space="preserve">
<source>Block member</source> <source>Block member</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -948,10 +942,6 @@
<target>Hovory</target> <target>Hovory</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Camera not available" xml:space="preserve">
<source>Camera not available</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Can't delete user profile!" xml:space="preserve"> <trans-unit id="Can't delete user profile!" xml:space="preserve">
<source>Can't delete user profile!</source> <source>Can't delete user profile!</source>
<target>Nemohu smazat uživatelský profil!</target> <target>Nemohu smazat uživatelský profil!</target>
@@ -1068,10 +1058,6 @@
<target>Chat je zastaven</target> <target>Chat je zastaven</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve">
<source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve"> <trans-unit id="Chat preferences" xml:space="preserve">
<source>Chat preferences</source> <source>Chat preferences</source>
<target>Předvolby chatu</target> <target>Předvolby chatu</target>
@@ -1172,10 +1158,6 @@
<target>Připojit</target> <target>Připojit</target>
<note>server test step</note> <note>server test step</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect automatically" xml:space="preserve">
<source>Connect automatically</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve"> <trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source> <source>Connect incognito</source>
<target>Spojit se inkognito</target> <target>Spojit se inkognito</target>
@@ -1208,6 +1190,11 @@ This is your own one-time link!</source>
<target>Připojte se prostřednictvím odkazu</target> <target>Připojte se prostřednictvím odkazu</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link / QR code" xml:space="preserve">
<source>Connect via link / QR code</source>
<target>Připojit se prostřednictvím odkazu / QR kódu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link" xml:space="preserve"> <trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source> <source>Connect via one-time link</source>
<target>Připojit se jednorázovým odkazem</target> <target>Připojit se jednorázovým odkazem</target>
@@ -1342,10 +1329,6 @@ This is your own one-time link!</source>
<target>Vytvořit SimpleX adresu</target> <target>Vytvořit SimpleX adresu</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create a group using a random profile." xml:space="preserve">
<source>Create a group using a random profile.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source> <source>Create an address to let people connect with you.</source>
<target>Vytvořit adresu, aby se s vámi lidé mohli spojit.</target> <target>Vytvořit adresu, aby se s vámi lidé mohli spojit.</target>
@@ -1375,6 +1358,11 @@ This is your own one-time link!</source>
<target>Vytvořit nový profil v [desktop app](https://simplex.chat/downloads/). 💻</target> <target>Vytvořit nový profil v [desktop app](https://simplex.chat/downloads/). 💻</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create one-time invitation link" xml:space="preserve">
<source>Create one-time invitation link</source>
<target>Vytvořit jednorázovou pozvánku</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -1399,10 +1387,6 @@ This is your own one-time link!</source>
<target>Vytvořeno na %@</target> <target>Vytvořeno na %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve"> <trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source> <source>Current Passcode</source>
<target>Aktuální heslo</target> <target>Aktuální heslo</target>
@@ -1860,8 +1844,8 @@ This cannot be undone!</source>
<target>Objevte a připojte skupiny</target> <target>Objevte a připojte skupiny</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve"> <trans-unit id="Discover on network" xml:space="preserve">
<source>Discover via local network</source> <source>Discover on network</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -1944,10 +1928,6 @@ This cannot be undone!</source>
<target>Povolit automatické mazání zpráv?</target> <target>Povolit automatické mazání zpráv?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enable camera access" xml:space="preserve">
<source>Enable camera access</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve"> <trans-unit id="Enable for all" xml:space="preserve">
<source>Enable for all</source> <source>Enable for all</source>
<target>Povolit pro všechny</target> <target>Povolit pro všechny</target>
@@ -2013,10 +1993,6 @@ This cannot be undone!</source>
<target>Šifrovaná zpráva nebo jiná událost</target> <target>Šifrovaná zpráva nebo jiná událost</target>
<note>notification</note> <note>notification</note>
</trans-unit> </trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve">
<source>Encrypted message: app is stopped</source>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve"> <trans-unit id="Encrypted message: database error" xml:space="preserve">
<source>Encrypted message: database error</source> <source>Encrypted message: database error</source>
<target>Šifrovaná zpráva: chyba databáze</target> <target>Šifrovaná zpráva: chyba databáze</target>
@@ -2242,10 +2218,6 @@ This cannot be undone!</source>
<target>Chyba načítání %@ serverů</target> <target>Chyba načítání %@ serverů</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error receiving file" xml:space="preserve"> <trans-unit id="Error receiving file" xml:space="preserve">
<source>Error receiving file</source> <source>Error receiving file</source>
<target>Chyba při příjmu souboru</target> <target>Chyba při příjmu souboru</target>
@@ -2286,10 +2258,6 @@ This cannot be undone!</source>
<target>Chyba ukládání hesla uživatele</target> <target>Chyba ukládání hesla uživatele</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error scanning code: %@" xml:space="preserve">
<source>Error scanning code: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve"> <trans-unit id="Error sending email" xml:space="preserve">
<source>Error sending email</source> <source>Error sending email</source>
<target>Chyba odesílání e-mailu</target> <target>Chyba odesílání e-mailu</target>
@@ -2414,10 +2382,6 @@ This cannot be undone!</source>
<target>Rychle a bez čekání, než bude odesílatel online!</target> <target>Rychle a bez čekání, než bude odesílatel online!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve"> <trans-unit id="Favorite" xml:space="preserve">
<source>Favorite</source> <source>Favorite</source>
<target>Oblíbené</target> <target>Oblíbené</target>
@@ -2513,10 +2477,6 @@ This cannot be undone!</source>
<target>Pro konzoli</target> <target>Pro konzoli</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Found desktop" xml:space="preserve">
<source>Found desktop</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="French interface" xml:space="preserve"> <trans-unit id="French interface" xml:space="preserve">
<source>French interface</source> <source>French interface</source>
<target>Francouzské rozhraní</target> <target>Francouzské rozhraní</target>
@@ -2759,6 +2719,11 @@ This cannot be undone!</source>
<target>Pokud se nemůžete setkat osobně, zobrazte QR kód ve videohovoru nebo sdílejte odkaz.</target> <target>Pokud se nemůžete setkat osobně, zobrazte QR kód ve videohovoru nebo sdílejte odkaz.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve">
<source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source>
<target>Pokud se nemůžete setkat osobně, můžete **naskenovat QR kód během videohovoru**, nebo váš kontakt může sdílet odkaz na pozvánku.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve">
<source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source>
<target>Pokud tento přístupový kód zadáte při otevření aplikace, všechna data budou nenávratně smazána!</target> <target>Pokud tento přístupový kód zadáte při otevření aplikace, všechna data budou nenávratně smazána!</target>
@@ -2834,10 +2799,6 @@ This cannot be undone!</source>
<target>Inkognito</target> <target>Inkognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve"> <trans-unit id="Incognito mode" xml:space="preserve">
<source>Incognito mode</source> <source>Incognito mode</source>
<target>Režim inkognito</target> <target>Režim inkognito</target>
@@ -2914,27 +2875,15 @@ This cannot be undone!</source>
<target>Rozhranní</target> <target>Rozhranní</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid QR code" xml:space="preserve">
<source>Invalid QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve"> <trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source> <source>Invalid connection link</source>
<target>Neplatný odkaz na spojení</target> <target>Neplatný odkaz na spojení</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
<source>Invalid link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve"> <trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source> <source>Invalid name!</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid response" xml:space="preserve">
<source>Invalid response</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve"> <trans-unit id="Invalid server address!" xml:space="preserve">
<source>Invalid server address!</source> <source>Invalid server address!</source>
<target>Neplatná adresa serveru!</target> <target>Neplatná adresa serveru!</target>
@@ -3049,18 +2998,10 @@ This is your link for group %@!</source>
<target>Připojování ke skupině</target> <target>Připojování ke skupině</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep" xml:space="preserve">
<source>Keep</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
<source>Keep the app open to use it from desktop</source> <source>Keep the app open to use it from desktop</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep unused invitation?" xml:space="preserve">
<source>Keep unused invitation?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve"> <trans-unit id="Keep your connections" xml:space="preserve">
<source>Keep your connections</source> <source>Keep your connections</source>
<target>Zachovat vaše připojení</target> <target>Zachovat vaše připojení</target>
@@ -3121,10 +3062,6 @@ This is your link for group %@!</source>
<target>Omezení</target> <target>Omezení</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve"> <trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source> <source>Linked desktop options</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3143,11 +3080,6 @@ This is your link for group %@!</source>
<target>Živé zprávy</target> <target>Živé zprávy</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Local" xml:space="preserve">
<source>Local</source>
<target>Místní</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Local name" xml:space="preserve"> <trans-unit id="Local name" xml:space="preserve">
<source>Local name</source> <source>Local name</source>
<target>Místní název</target> <target>Místní název</target>
@@ -3387,10 +3319,6 @@ This is your link for group %@!</source>
<target>Nové heslo</target> <target>Nové heslo</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="New chat" xml:space="preserve">
<source>New chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve"> <trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source> <source>New contact request</source>
<target>Žádost o nový kontakt</target> <target>Žádost o nový kontakt</target>
@@ -3491,10 +3419,6 @@ This is your link for group %@!</source>
<target>Žádné přijaté ani odeslané soubory</target> <target>Žádné přijaté ani odeslané soubory</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Not compatible!" xml:space="preserve">
<source>Not compatible!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve"> <trans-unit id="Notifications" xml:space="preserve">
<source>Notifications</source> <source>Notifications</source>
<target>Oznámení</target> <target>Oznámení</target>
@@ -3514,15 +3438,16 @@ This is your link for group %@!</source>
- zakázat členy (role "pozorovatel")</target> - zakázat členy (role "pozorovatel")</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="OK" xml:space="preserve">
<source>OK</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Off" xml:space="preserve"> <trans-unit id="Off" xml:space="preserve">
<source>Off</source> <source>Off</source>
<target>Vypnout</target> <target>Vypnout</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Off (Local)" xml:space="preserve">
<source>Off (Local)</source>
<target>Vypnuto (místní)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ok" xml:space="preserve"> <trans-unit id="Ok" xml:space="preserve">
<source>Ok</source> <source>Ok</source>
<target>Ok</target> <target>Ok</target>
@@ -3662,16 +3587,9 @@ This is your link for group %@!</source>
<target>Protokol a kód s otevřeným zdrojovým kódem - servery může provozovat kdokoli.</target> <target>Protokol a kód s otevřeným zdrojovým kódem - servery může provozovat kdokoli.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Opening app…" xml:space="preserve"> <trans-unit id="Opening database…" xml:space="preserve">
<source>Opening app…</source> <source>Opening database…</source>
<note>No comment provided by engineer.</note> <target>Otvírání databáze…</target>
</trans-unit>
<trans-unit id="Or scan QR code" xml:space="preserve">
<source>Or scan QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
<source>Or show this code</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="PING count" xml:space="preserve"> <trans-unit id="PING count" xml:space="preserve">
@@ -3714,6 +3632,11 @@ This is your link for group %@!</source>
<target>Heslo k zobrazení</target> <target>Heslo k zobrazení</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste" xml:space="preserve">
<source>Paste</source>
<target>Vložit</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve"> <trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source> <source>Paste desktop address</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3723,10 +3646,16 @@ This is your link for group %@!</source>
<target>Vložit obrázek</target> <target>Vložit obrázek</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve"> <trans-unit id="Paste received link" xml:space="preserve">
<source>Paste the link you received</source> <source>Paste received link</source>
<target>Vložení přijatého odkazu</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Vložte odkaz, který jste obdrželi, do pole níže a spojte se se svým kontaktem.</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source> <source>People can connect to you only via the links you share.</source>
<target>Lidé se s vámi mohou spojit pouze prostřednictvím odkazů, které sdílíte.</target> <target>Lidé se s vámi mohou spojit pouze prostřednictvím odkazů, které sdílíte.</target>
@@ -3762,11 +3691,6 @@ This is your link for group %@!</source>
<target>Zkontrolujte prosím nastavení své i svého kontaktu.</target> <target>Zkontrolujte prosím nastavení své i svého kontaktu.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Please contact developers.&#10;Error: %@" xml:space="preserve">
<source>Please contact developers.
Error: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please contact group admin." xml:space="preserve"> <trans-unit id="Please contact group admin." xml:space="preserve">
<source>Please contact group admin.</source> <source>Please contact group admin.</source>
<target>Kontaktujte prosím správce skupiny.</target> <target>Kontaktujte prosím správce skupiny.</target>
@@ -3970,10 +3894,6 @@ Error: %@</source>
<target>Další informace naleznete v [Uživatelské příručce](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <target>Další informace naleznete v [Uživatelské příručce](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source>
<target>Přečtěte si více v [Uživatelské příručce](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> <target>Přečtěte si více v [Uživatelské příručce](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target>
@@ -4182,10 +4102,6 @@ Error: %@</source>
<target>Chyba obnovení databáze</target> <target>Chyba obnovení databáze</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Retry" xml:space="preserve">
<source>Retry</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reveal" xml:space="preserve"> <trans-unit id="Reveal" xml:space="preserve">
<source>Reveal</source> <source>Reveal</source>
<target>Odhalit</target> <target>Odhalit</target>
@@ -4340,10 +4256,6 @@ Error: %@</source>
<target>Hledat</target> <target>Hledat</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve"> <trans-unit id="Secure queue" xml:space="preserve">
<source>Secure queue</source> <source>Secure queue</source>
<target>Zabezpečit frontu</target> <target>Zabezpečit frontu</target>
@@ -4618,8 +4530,9 @@ Error: %@</source>
<target>Sdílet odkaz</target> <target>Sdílet odkaz</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve"> <trans-unit id="Share one-time invitation link" xml:space="preserve">
<source>Share this 1-time invite link</source> <source>Share one-time invitation link</source>
<target>Jednorázový zvací odkaz</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve"> <trans-unit id="Share with contacts" xml:space="preserve">
@@ -4742,15 +4655,16 @@ Error: %@</source>
<target>Někdo</target> <target>Někdo</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="Start a new chat" xml:space="preserve">
<source>Start a new chat</source>
<target>Začít nový chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start chat" xml:space="preserve"> <trans-unit id="Start chat" xml:space="preserve">
<source>Start chat</source> <source>Start chat</source>
<target>Začít chat</target> <target>Začít chat</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Start chat?" xml:space="preserve">
<source>Start chat?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start migration" xml:space="preserve"> <trans-unit id="Start migration" xml:space="preserve">
<source>Start migration</source> <source>Start migration</source>
<target>Zahájit přenesení</target> <target>Zahájit přenesení</target>
@@ -4875,14 +4789,6 @@ Error: %@</source>
<target>Klepnutím se připojíte inkognito</target> <target>Klepnutím se připojíte inkognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Tap to paste link" xml:space="preserve">
<source>Tap to paste link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to scan" xml:space="preserve">
<source>Tap to scan</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve"> <trans-unit id="Tap to start a new chat" xml:space="preserve">
<source>Tap to start a new chat</source> <source>Tap to start a new chat</source>
<target>Klepnutím na zahájíte nový chat</target> <target>Klepnutím na zahájíte nový chat</target>
@@ -4945,10 +4851,6 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován
<target>Pokus o změnu přístupové fráze databáze nebyl dokončen.</target> <target>Pokus o změnu přístupové fráze databáze nebyl dokončen.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source> <source>The connection you accepted will be cancelled!</source>
<target>Připojení, které jste přijali, bude zrušeno!</target> <target>Připojení, které jste přijali, bude zrušeno!</target>
@@ -5014,10 +4916,6 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován
<target>Servery pro nová připojení vašeho aktuálního chat profilu **%@**.</target> <target>Servery pro nová připojení vašeho aktuálního chat profilu **%@**.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve">
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve"> <trans-unit id="Theme" xml:space="preserve">
<source>Theme</source> <source>Theme</source>
<target>Téma</target> <target>Téma</target>
@@ -5095,10 +4993,6 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován
<target>Pro připojení může váš kontakt naskenovat QR kód, nebo použít odkaz v aplikaci.</target> <target>Pro připojení může váš kontakt naskenovat QR kód, nebo použít odkaz v aplikaci.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve"> <trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source> <source>To make a new connection</source>
<target>Vytvoření nového připojení</target> <target>Vytvoření nového připojení</target>
@@ -5166,6 +5060,11 @@ Před zapnutím této funkce budete vyzváni k dokončení ověření.</target>
<target>Vypnout</target> <target>Vypnout</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Turn off notifications?" xml:space="preserve">
<source>Turn off notifications?</source>
<target>Vypnout upozornění?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn on" xml:space="preserve"> <trans-unit id="Turn on" xml:space="preserve">
<source>Turn on</source> <source>Turn on</source>
<target>Zapnout</target> <target>Zapnout</target>
@@ -5362,10 +5261,6 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
<target>Použít nový inkognito profil</target> <target>Použít nový inkognito profil</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use only local notifications?" xml:space="preserve">
<source>Use only local notifications?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve"> <trans-unit id="Use server" xml:space="preserve">
<source>Use server</source> <source>Use server</source>
<target>Použít server</target> <target>Použít server</target>
@@ -5413,10 +5308,6 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
<target>Prostřednictvím prohlížeče</target> <target>Prostřednictvím prohlížeče</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve"> <trans-unit id="Video call" xml:space="preserve">
<source>Video call</source> <source>Video call</source>
<target>Videohovor</target> <target>Videohovor</target>
@@ -5467,10 +5358,6 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
<target>Hlasová zpráva…</target> <target>Hlasová zpráva…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Waiting for desktop..." xml:space="preserve">
<source>Waiting for desktop...</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Waiting for file" xml:space="preserve"> <trans-unit id="Waiting for file" xml:space="preserve">
<source>Waiting for file</source> <source>Waiting for file</source>
<target>Čekání na soubor</target> <target>Čekání na soubor</target>
@@ -5615,6 +5502,11 @@ Repeat join request?</source>
<target>Můžete přijímat hovory z obrazovky zámku, bez ověření zařízení a aplikace.</target> <target>Můžete přijímat hovory z obrazovky zámku, bez ověření zařízení a aplikace.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve">
<source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source>
<target>Můžete se také připojit kliknutím na odkaz. Pokud se otevře v prohlížeči, klikněte na tlačítko **Otevřít v mobilní aplikaci**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can create it later" xml:space="preserve"> <trans-unit id="You can create it later" xml:space="preserve">
<source>You can create it later</source> <source>You can create it later</source>
<target>Můžete vytvořit později</target> <target>Můžete vytvořit později</target>
@@ -5635,10 +5527,6 @@ Repeat join request?</source>
<target>Profil uživatele můžete skrýt nebo ztlumit - přejeďte prstem doprava.</target> <target>Profil uživatele můžete skrýt nebo ztlumit - přejeďte prstem doprava.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now send messages to %@" xml:space="preserve"> <trans-unit id="You can now send messages to %@" xml:space="preserve">
<source>You can now send messages to %@</source> <source>You can now send messages to %@</source>
<target>Nyní můžete posílat zprávy %@</target> <target>Nyní můžete posílat zprávy %@</target>
@@ -5679,10 +5567,6 @@ Repeat join request?</source>
<target>K formátování zpráv můžete použít markdown:</target> <target>K formátování zpráv můžete použít markdown:</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can view invitation link again in connection details." xml:space="preserve">
<source>You can view invitation link again in connection details.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can't send messages!" xml:space="preserve"> <trans-unit id="You can't send messages!" xml:space="preserve">
<source>You can't send messages!</source> <source>You can't send messages!</source>
<target>Nemůžete posílat zprávy!</target> <target>Nemůžete posílat zprávy!</target>
@@ -5867,6 +5751,13 @@ Toto připojení můžete zrušit a kontakt odebrat (a zkusit to později s nov
<target>Vaše kontakty mohou povolit úplné mazání zpráv.</target> <target>Vaše kontakty mohou povolit úplné mazání zpráv.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your contacts in SimpleX will see it.&#10;You can change it in Settings." xml:space="preserve">
<source>Your contacts in SimpleX will see it.
You can change it in Settings.</source>
<target>Vaše kontakty v SimpleX ji uvidí.
Můžete ji změnit v Nastavení.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve"> <trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source> <source>Your contacts will remain connected.</source>
<target>Vaše kontakty zůstanou připojeny.</target> <target>Vaše kontakty zůstanou připojeny.</target>
@@ -5997,10 +5888,6 @@ Servery SimpleX nevidí váš profil.</target>
<target>zvukový hovor (nešifrovaný e2e)</target> <target>zvukový hovor (nešifrovaný e2e)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="author" xml:space="preserve">
<source>author</source>
<note>member role</note>
</trans-unit>
<trans-unit id="bad message ID" xml:space="preserve"> <trans-unit id="bad message ID" xml:space="preserve">
<source>bad message ID</source> <source>bad message ID</source>
<target>špatné ID zprávy</target> <target>špatné ID zprávy</target>
@@ -299,12 +299,10 @@
</trans-unit> </trans-unit>
<trans-unit id="(new)" xml:space="preserve"> <trans-unit id="(new)" xml:space="preserve">
<source>(new)</source> <source>(new)</source>
<target>(Neu)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="(this device v%@)" xml:space="preserve"> <trans-unit id="(this device v%@)" xml:space="preserve">
<source>(this device v%@)</source> <source>(this device v%@)</source>
<target>(Dieses Gerät hat v%@)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id=")" xml:space="preserve"> <trans-unit id=")" xml:space="preserve">
@@ -312,17 +310,14 @@
<target>)</target> <target>)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve">
<source>**Add contact**: to create a new invitation link, or connect via a link you received.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target>**Fügen Sie einen neuen Kontakt hinzu**: Erzeugen Sie einen Einmal-QR-Code oder -Link für Ihren Kontakt.</target> <target>**Fügen Sie einen neuen Kontakt hinzu**: Erzeugen Sie einen Einmal-QR-Code oder -Link für Ihren Kontakt.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Create group**: to create a new group." xml:space="preserve"> <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<source>**Create group**: to create a new group.</source> <source>**Create link / QR code** for your contact to use.</source>
<target>**Generieren Sie einen Einladungs-Link / QR code** für Ihren Kontakt.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -335,6 +330,11 @@
<target>**Beste Privatsphäre**: Es wird kein SimpleX-Chat-Benachrichtigungs-Server genutzt, Nachrichten werden in periodischen Abständen im Hintergrund geprüft (dies hängt davon ab, wie häufig Sie die App nutzen).</target> <target>**Beste Privatsphäre**: Es wird kein SimpleX-Chat-Benachrichtigungs-Server genutzt, Nachrichten werden in periodischen Abständen im Hintergrund geprüft (dies hängt davon ab, wie häufig Sie die App nutzen).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve">
<source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source>
<target>**Fügen Sie den von Ihrem Kontakt erhaltenen Link ein** oder öffnen Sie ihn im Browser und tippen Sie auf **In mobiler App öffnen**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve">
<source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source>
<target>**Bitte beachten Sie**: Das Passwort kann NICHT wiederhergestellt oder geändert werden, wenn Sie es vergessen haben oder verlieren.</target> <target>**Bitte beachten Sie**: Das Passwort kann NICHT wiederhergestellt oder geändert werden, wenn Sie es vergessen haben oder verlieren.</target>
@@ -345,6 +345,11 @@
<target>**Empfohlen**: Nur Ihr Geräte-Token und ihre Benachrichtigungen werden an den SimpleX-Chat-Benachrichtigungs-Server gesendet, aber weder der Nachrichteninhalt noch deren Größe oder von wem sie gesendet wurde.</target> <target>**Empfohlen**: Nur Ihr Geräte-Token und ihre Benachrichtigungen werden an den SimpleX-Chat-Benachrichtigungs-Server gesendet, aber weder der Nachrichteninhalt noch deren Größe oder von wem sie gesendet wurde.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve">
<source>**Scan QR code**: to connect to your contact in person or via video call.</source>
<target>**Scannen Sie den QR-Code**, um sich während einem persönlichen Treffen oder per Videoanruf mit Ihrem Kontakt zu verbinden.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target>**Warnung**: Sofortige Push-Benachrichtigungen erfordern die Eingabe eines Passworts, welches in Ihrem Schlüsselbund gespeichert ist.</target> <target>**Warnung**: Sofortige Push-Benachrichtigungen erfordern die Eingabe eines Passworts, welches in Ihrem Schlüsselbund gespeichert ist.</target>
@@ -388,15 +393,6 @@
- und mehr!</target> - und mehr!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="- optionally notify deleted contacts.&#10;- profile names with spaces.&#10;- and more!" xml:space="preserve">
<source>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</source>
<target>- Optionale Benachrichtigung von gelöschten Kontakten.
- Profilnamen mit Leerzeichen.
- Und mehr!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve"> <trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve">
<source>- voice messages up to 5 minutes. <source>- voice messages up to 5 minutes.
- custom time to disappear. - custom time to disappear.
@@ -446,6 +442,11 @@
<target>wöchentlich</target> <target>wöchentlich</target>
<note>time interval</note> <note>time interval</note>
</trans-unit> </trans-unit>
<trans-unit id="1-time link" xml:space="preserve">
<source>1-time link</source>
<target>Einmal-Link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="5 minutes" xml:space="preserve"> <trans-unit id="5 minutes" xml:space="preserve">
<source>5 minutes</source> <source>5 minutes</source>
<target>5 Minuten</target> <target>5 Minuten</target>
@@ -561,10 +562,6 @@
<target>Fügen Sie die Adresse zu Ihrem Profil hinzu, damit Ihre Kontakte sie mit anderen Personen teilen können. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet.</target> <target>Fügen Sie die Adresse zu Ihrem Profil hinzu, damit Ihre Kontakte sie mit anderen Personen teilen können. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add contact" xml:space="preserve">
<source>Add contact</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve"> <trans-unit id="Add preset servers" xml:space="preserve">
<source>Add preset servers</source> <source>Add preset servers</source>
<target>Füge voreingestellte Server hinzu</target> <target>Füge voreingestellte Server hinzu</target>
@@ -882,7 +879,6 @@
</trans-unit> </trans-unit>
<trans-unit id="Bad desktop address" xml:space="preserve"> <trans-unit id="Bad desktop address" xml:space="preserve">
<source>Bad desktop address</source> <source>Bad desktop address</source>
<target>Falsche Desktop-Adresse</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Bad message ID" xml:space="preserve"> <trans-unit id="Bad message ID" xml:space="preserve">
@@ -895,11 +891,6 @@
<target>Ungültiger Nachrichten-Hash</target> <target>Ungültiger Nachrichten-Hash</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
<source>Better groups</source>
<target>Bessere Gruppen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better messages" xml:space="preserve"> <trans-unit id="Better messages" xml:space="preserve">
<source>Better messages</source> <source>Better messages</source>
<target>Verbesserungen bei Nachrichten</target> <target>Verbesserungen bei Nachrichten</target>
@@ -910,11 +901,6 @@
<target>Blockieren</target> <target>Blockieren</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
<source>Block group members</source>
<target>Gruppenmitglieder blockieren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve"> <trans-unit id="Block member" xml:space="preserve">
<source>Block member</source> <source>Block member</source>
<target>Mitglied blockieren</target> <target>Mitglied blockieren</target>
@@ -970,10 +956,6 @@
<target>Anrufe</target> <target>Anrufe</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Camera not available" xml:space="preserve">
<source>Camera not available</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Can't delete user profile!" xml:space="preserve"> <trans-unit id="Can't delete user profile!" xml:space="preserve">
<source>Can't delete user profile!</source> <source>Can't delete user profile!</source>
<target>Das Benutzerprofil kann nicht gelöscht werden!</target> <target>Das Benutzerprofil kann nicht gelöscht werden!</target>
@@ -1090,10 +1072,6 @@
<target>Der Chat ist beendet</target> <target>Der Chat ist beendet</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve">
<source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve"> <trans-unit id="Chat preferences" xml:space="preserve">
<source>Chat preferences</source> <source>Chat preferences</source>
<target>Chat-Präferenzen</target> <target>Chat-Präferenzen</target>
@@ -1194,11 +1172,6 @@
<target>Verbinden</target> <target>Verbinden</target>
<note>server test step</note> <note>server test step</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect automatically" xml:space="preserve">
<source>Connect automatically</source>
<target>Automatisch verbinden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve"> <trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source> <source>Connect incognito</source>
<target>Inkognito verbinden</target> <target>Inkognito verbinden</target>
@@ -1206,7 +1179,6 @@
</trans-unit> </trans-unit>
<trans-unit id="Connect to desktop" xml:space="preserve"> <trans-unit id="Connect to desktop" xml:space="preserve">
<source>Connect to desktop</source> <source>Connect to desktop</source>
<target>Mit dem Desktop verbinden</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve"> <trans-unit id="Connect to yourself?" xml:space="preserve">
@@ -1238,6 +1210,11 @@ Das ist Ihr eigener Einmal-Link!</target>
<target>Über einen Link verbinden</target> <target>Über einen Link verbinden</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link / QR code" xml:space="preserve">
<source>Connect via link / QR code</source>
<target>Über einen Link / QR-Code verbinden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link" xml:space="preserve"> <trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source> <source>Connect via one-time link</source>
<target>Über einen Einmal-Link verbinden</target> <target>Über einen Einmal-Link verbinden</target>
@@ -1250,12 +1227,10 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit> </trans-unit>
<trans-unit id="Connected desktop" xml:space="preserve"> <trans-unit id="Connected desktop" xml:space="preserve">
<source>Connected desktop</source> <source>Connected desktop</source>
<target>Verbundener Desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connected to desktop" xml:space="preserve"> <trans-unit id="Connected to desktop" xml:space="preserve">
<source>Connected to desktop</source> <source>Connected to desktop</source>
<target>Mit dem Desktop verbunden</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve"> <trans-unit id="Connecting server…" xml:space="preserve">
@@ -1270,7 +1245,6 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit> </trans-unit>
<trans-unit id="Connecting to desktop" xml:space="preserve"> <trans-unit id="Connecting to desktop" xml:space="preserve">
<source>Connecting to desktop</source> <source>Connecting to desktop</source>
<target>Mit dem Desktop verbinden</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connection" xml:space="preserve"> <trans-unit id="Connection" xml:space="preserve">
@@ -1295,7 +1269,6 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit> </trans-unit>
<trans-unit id="Connection terminated" xml:space="preserve"> <trans-unit id="Connection terminated" xml:space="preserve">
<source>Connection terminated</source> <source>Connection terminated</source>
<target>Verbindung beendet</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connection timeout" xml:space="preserve"> <trans-unit id="Connection timeout" xml:space="preserve">
@@ -1378,11 +1351,6 @@ Das ist Ihr eigener Einmal-Link!</target>
<target>SimpleX-Adresse erstellen</target> <target>SimpleX-Adresse erstellen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create a group using a random profile." xml:space="preserve">
<source>Create a group using a random profile.</source>
<target>Erstellen Sie eine Gruppe mit einem zufälligen Profil.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source> <source>Create an address to let people connect with you.</source>
<target>Erstellen Sie eine Adresse, damit sich Personen mit Ihnen verbinden können.</target> <target>Erstellen Sie eine Adresse, damit sich Personen mit Ihnen verbinden können.</target>
@@ -1413,6 +1381,11 @@ Das ist Ihr eigener Einmal-Link!</target>
<target>Neues Profil in der [Desktop-App] erstellen (https://simplex.chat/downloads/). 💻</target> <target>Neues Profil in der [Desktop-App] erstellen (https://simplex.chat/downloads/). 💻</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create one-time invitation link" xml:space="preserve">
<source>Create one-time invitation link</source>
<target>Einmal-Einladungslink erstellen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<target>Profil erstellen</target> <target>Profil erstellen</target>
@@ -1438,10 +1411,6 @@ Das ist Ihr eigener Einmal-Link!</target>
<target>Erstellt am %@</target> <target>Erstellt am %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve"> <trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source> <source>Current Passcode</source>
<target>Aktueller Zugangscode</target> <target>Aktueller Zugangscode</target>
@@ -1794,17 +1763,14 @@ Das kann nicht rückgängig gemacht werden!</target>
</trans-unit> </trans-unit>
<trans-unit id="Desktop address" xml:space="preserve"> <trans-unit id="Desktop address" xml:space="preserve">
<source>Desktop address</source> <source>Desktop address</source>
<target>Desktop-Adresse</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve"> <trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve">
<source>Desktop app version %@ is not compatible with this app.</source> <source>Desktop app version %@ is not compatible with this app.</source>
<target>Desktop App-Version %@ ist mit dieser App nicht kompatibel.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Desktop devices" xml:space="preserve"> <trans-unit id="Desktop devices" xml:space="preserve">
<source>Desktop devices</source> <source>Desktop devices</source>
<target>Desktop-Geräte</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Develop" xml:space="preserve"> <trans-unit id="Develop" xml:space="preserve">
@@ -1899,7 +1865,6 @@ Das kann nicht rückgängig gemacht werden!</target>
</trans-unit> </trans-unit>
<trans-unit id="Disconnect desktop?" xml:space="preserve"> <trans-unit id="Disconnect desktop?" xml:space="preserve">
<source>Disconnect desktop?</source> <source>Disconnect desktop?</source>
<target>Desktop-Verbindung trennen?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover and join groups" xml:space="preserve"> <trans-unit id="Discover and join groups" xml:space="preserve">
@@ -1907,9 +1872,8 @@ Das kann nicht rückgängig gemacht werden!</target>
<target>Gruppen entdecken und ihnen beitreten</target> <target>Gruppen entdecken und ihnen beitreten</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve"> <trans-unit id="Discover on network" xml:space="preserve">
<source>Discover via local network</source> <source>Discover on network</source>
<target>Lokales Netzwerk durchsuchen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -1992,10 +1956,6 @@ Das kann nicht rückgängig gemacht werden!</target>
<target>Automatisches Löschen von Nachrichten aktivieren?</target> <target>Automatisches Löschen von Nachrichten aktivieren?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enable camera access" xml:space="preserve">
<source>Enable camera access</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve"> <trans-unit id="Enable for all" xml:space="preserve">
<source>Enable for all</source> <source>Enable for all</source>
<target>Für Alle aktivieren</target> <target>Für Alle aktivieren</target>
@@ -2061,10 +2021,6 @@ Das kann nicht rückgängig gemacht werden!</target>
<target>Verschlüsselte Nachricht oder ein anderes Ereignis</target> <target>Verschlüsselte Nachricht oder ein anderes Ereignis</target>
<note>notification</note> <note>notification</note>
</trans-unit> </trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve">
<source>Encrypted message: app is stopped</source>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve"> <trans-unit id="Encrypted message: database error" xml:space="preserve">
<source>Encrypted message: database error</source> <source>Encrypted message: database error</source>
<target>Verschlüsselte Nachricht: Datenbankfehler</target> <target>Verschlüsselte Nachricht: Datenbankfehler</target>
@@ -2092,12 +2048,10 @@ Das kann nicht rückgängig gemacht werden!</target>
</trans-unit> </trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve"> <trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source> <source>Encryption re-negotiation error</source>
<target>Fehler bei der Neuverhandlung der Verschlüsselung</target>
<note>message decrypt error item</note> <note>message decrypt error item</note>
</trans-unit> </trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve"> <trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source> <source>Encryption re-negotiation failed.</source>
<target>Neuverhandlung der Verschlüsselung fehlgeschlagen.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve"> <trans-unit id="Enter Passcode" xml:space="preserve">
@@ -2132,7 +2086,6 @@ Das kann nicht rückgängig gemacht werden!</target>
</trans-unit> </trans-unit>
<trans-unit id="Enter this device name…" xml:space="preserve"> <trans-unit id="Enter this device name…" xml:space="preserve">
<source>Enter this device name…</source> <source>Enter this device name…</source>
<target>Geben Sie diesen Gerätenamen ein…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enter welcome message…" xml:space="preserve"> <trans-unit id="Enter welcome message…" xml:space="preserve">
@@ -2295,10 +2248,6 @@ Das kann nicht rückgängig gemacht werden!</target>
<target>Fehler beim Laden von %@ Servern</target> <target>Fehler beim Laden von %@ Servern</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error receiving file" xml:space="preserve"> <trans-unit id="Error receiving file" xml:space="preserve">
<source>Error receiving file</source> <source>Error receiving file</source>
<target>Fehler beim Empfangen der Datei</target> <target>Fehler beim Empfangen der Datei</target>
@@ -2339,10 +2288,6 @@ Das kann nicht rückgängig gemacht werden!</target>
<target>Fehler beim Speichern des Benutzer-Passworts</target> <target>Fehler beim Speichern des Benutzer-Passworts</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error scanning code: %@" xml:space="preserve">
<source>Error scanning code: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve"> <trans-unit id="Error sending email" xml:space="preserve">
<source>Error sending email</source> <source>Error sending email</source>
<target>Fehler beim Senden der eMail</target> <target>Fehler beim Senden der eMail</target>
@@ -2468,11 +2413,6 @@ Das kann nicht rückgängig gemacht werden!</target>
<target>Schnell und ohne warten auf den Absender, bis er online ist!</target> <target>Schnell und ohne warten auf den Absender, bis er online ist!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<target>Schnellerer Gruppenbeitritt und zuverlässigere Nachrichtenzustellung.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve"> <trans-unit id="Favorite" xml:space="preserve">
<source>Favorite</source> <source>Favorite</source>
<target>Favorit</target> <target>Favorit</target>
@@ -2568,11 +2508,6 @@ Das kann nicht rückgängig gemacht werden!</target>
<target>Für Konsole</target> <target>Für Konsole</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Found desktop" xml:space="preserve">
<source>Found desktop</source>
<target>Gefundener Desktop</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="French interface" xml:space="preserve"> <trans-unit id="French interface" xml:space="preserve">
<source>French interface</source> <source>French interface</source>
<target>Französische Bedienoberfläche</target> <target>Französische Bedienoberfläche</target>
@@ -2818,6 +2753,11 @@ Das kann nicht rückgängig gemacht werden!</target>
<target>Falls Sie sich nicht persönlich treffen können, zeigen Sie den QR-Code in einem Videoanruf oder teilen Sie den Link.</target> <target>Falls Sie sich nicht persönlich treffen können, zeigen Sie den QR-Code in einem Videoanruf oder teilen Sie den Link.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve">
<source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source>
<target>Wenn Sie sich nicht persönlich treffen können, kann der **QR-Code während eines Videoanrufs gescannt werden**, oder Ihr Kontakt kann den Einladungslink über einen anderen Kanal mit Ihnen teilen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve">
<source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source>
<target>Wenn Sie diesen Zugangscode während des Öffnens der App eingeben, werden alle App-Daten unwiederbringlich gelöscht!</target> <target>Wenn Sie diesen Zugangscode während des Öffnens der App eingeben, werden alle App-Daten unwiederbringlich gelöscht!</target>
@@ -2893,11 +2833,6 @@ Das kann nicht rückgängig gemacht werden!</target>
<target>Inkognito</target> <target>Inkognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<target>Inkognito-Gruppen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve"> <trans-unit id="Incognito mode" xml:space="preserve">
<source>Incognito mode</source> <source>Incognito mode</source>
<target>Inkognito-Modus</target> <target>Inkognito-Modus</target>
@@ -2930,7 +2865,6 @@ Das kann nicht rückgängig gemacht werden!</target>
</trans-unit> </trans-unit>
<trans-unit id="Incompatible version" xml:space="preserve"> <trans-unit id="Incompatible version" xml:space="preserve">
<source>Incompatible version</source> <source>Incompatible version</source>
<target>Inkompatible Version</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incorrect passcode" xml:space="preserve"> <trans-unit id="Incorrect passcode" xml:space="preserve">
@@ -2975,28 +2909,16 @@ Das kann nicht rückgängig gemacht werden!</target>
<target>Schnittstelle</target> <target>Schnittstelle</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid QR code" xml:space="preserve">
<source>Invalid QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve"> <trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source> <source>Invalid connection link</source>
<target>Ungültiger Verbindungslink</target> <target>Ungültiger Verbindungslink</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
<source>Invalid link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve"> <trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source> <source>Invalid name!</source>
<target>Ungültiger Name!</target> <target>Ungültiger Name!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid response" xml:space="preserve">
<source>Invalid response</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve"> <trans-unit id="Invalid server address!" xml:space="preserve">
<source>Invalid server address!</source> <source>Invalid server address!</source>
<target>Ungültige Serveradresse!</target> <target>Ungültige Serveradresse!</target>
@@ -3115,17 +3037,8 @@ Das ist Ihr Link für die Gruppe %@!</target>
<target>Der Gruppe beitreten</target> <target>Der Gruppe beitreten</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep" xml:space="preserve">
<source>Keep</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
<source>Keep the app open to use it from desktop</source> <source>Keep the app open to use it from desktop</source>
<target>Die App muss geöffnet bleiben, um sie vom Desktop aus nutzen zu können</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep unused invitation?" xml:space="preserve">
<source>Keep unused invitation?</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve"> <trans-unit id="Keep your connections" xml:space="preserve">
@@ -3188,19 +3101,12 @@ Das ist Ihr Link für die Gruppe %@!</target>
<target>Einschränkungen</target> <target>Einschränkungen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<target>Verknüpfe Mobiltelefon- und Desktop-Apps! 🔗</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve"> <trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source> <source>Linked desktop options</source>
<target>Verknüpfte Desktop-Optionen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Linked desktops" xml:space="preserve"> <trans-unit id="Linked desktops" xml:space="preserve">
<source>Linked desktops</source> <source>Linked desktops</source>
<target>Verknüpfte Desktops</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Live message!" xml:space="preserve"> <trans-unit id="Live message!" xml:space="preserve">
@@ -3213,11 +3119,6 @@ Das ist Ihr Link für die Gruppe %@!</target>
<target>Live Nachrichten</target> <target>Live Nachrichten</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Local" xml:space="preserve">
<source>Local</source>
<target>Lokal</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Local name" xml:space="preserve"> <trans-unit id="Local name" xml:space="preserve">
<source>Local name</source> <source>Local name</source>
<target>Lokaler Name</target> <target>Lokaler Name</target>
@@ -3458,10 +3359,6 @@ Das ist Ihr Link für die Gruppe %@!</target>
<target>Neuer Zugangscode</target> <target>Neuer Zugangscode</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="New chat" xml:space="preserve">
<source>New chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve"> <trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source> <source>New contact request</source>
<target>Neue Kontaktanfrage</target> <target>Neue Kontaktanfrage</target>
@@ -3562,11 +3459,6 @@ Das ist Ihr Link für die Gruppe %@!</target>
<target>Keine empfangenen oder gesendeten Dateien</target> <target>Keine empfangenen oder gesendeten Dateien</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Not compatible!" xml:space="preserve">
<source>Not compatible!</source>
<target>Nicht kompatibel!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve"> <trans-unit id="Notifications" xml:space="preserve">
<source>Notifications</source> <source>Notifications</source>
<target>Benachrichtigungen</target> <target>Benachrichtigungen</target>
@@ -3586,15 +3478,16 @@ Das ist Ihr Link für die Gruppe %@!</target>
- Gruppenmitglieder deaktivieren ("Beobachter"-Rolle)</target> - Gruppenmitglieder deaktivieren ("Beobachter"-Rolle)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="OK" xml:space="preserve">
<source>OK</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Off" xml:space="preserve"> <trans-unit id="Off" xml:space="preserve">
<source>Off</source> <source>Off</source>
<target>Aus</target> <target>Aus</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Off (Local)" xml:space="preserve">
<source>Off (Local)</source>
<target>Aus (Lokal)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ok" xml:space="preserve"> <trans-unit id="Ok" xml:space="preserve">
<source>Ok</source> <source>Ok</source>
<target>Ok</target> <target>Ok</target>
@@ -3735,16 +3628,9 @@ Das ist Ihr Link für die Gruppe %@!</target>
<target>Open-Source-Protokoll und -Code Jede Person kann ihre eigenen Server aufsetzen und nutzen.</target> <target>Open-Source-Protokoll und -Code Jede Person kann ihre eigenen Server aufsetzen und nutzen.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Opening app…" xml:space="preserve"> <trans-unit id="Opening database…" xml:space="preserve">
<source>Opening app…</source> <source>Opening database…</source>
<note>No comment provided by engineer.</note> <target>Öffne Datenbank …</target>
</trans-unit>
<trans-unit id="Or scan QR code" xml:space="preserve">
<source>Or scan QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
<source>Or show this code</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="PING count" xml:space="preserve"> <trans-unit id="PING count" xml:space="preserve">
@@ -3787,9 +3673,13 @@ Das ist Ihr Link für die Gruppe %@!</target>
<target>Passwort anzeigen</target> <target>Passwort anzeigen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste" xml:space="preserve">
<source>Paste</source>
<target>Einfügen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve"> <trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source> <source>Paste desktop address</source>
<target>Desktop-Adresse einfügen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste image" xml:space="preserve"> <trans-unit id="Paste image" xml:space="preserve">
@@ -3797,10 +3687,16 @@ Das ist Ihr Link für die Gruppe %@!</target>
<target>Bild einfügen</target> <target>Bild einfügen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve"> <trans-unit id="Paste received link" xml:space="preserve">
<source>Paste the link you received</source> <source>Paste received link</source>
<target>Fügen Sie den erhaltenen Link ein</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Um sich mit Ihrem Kontakt zu verbinden, fügen Sie den erhaltenen Link in das Feld unten ein.</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source> <source>People can connect to you only via the links you share.</source>
<target>Verbindungen mit Kontakten sind nur über Links möglich, die Sie oder Ihre Kontakte untereinander teilen.</target> <target>Verbindungen mit Kontakten sind nur über Links möglich, die Sie oder Ihre Kontakte untereinander teilen.</target>
@@ -3836,11 +3732,6 @@ Das ist Ihr Link für die Gruppe %@!</target>
<target>Bitte überprüfen sie sowohl Ihre, als auch die Präferenzen Ihres Kontakts.</target> <target>Bitte überprüfen sie sowohl Ihre, als auch die Präferenzen Ihres Kontakts.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Please contact developers.&#10;Error: %@" xml:space="preserve">
<source>Please contact developers.
Error: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please contact group admin." xml:space="preserve"> <trans-unit id="Please contact group admin." xml:space="preserve">
<source>Please contact group admin.</source> <source>Please contact group admin.</source>
<target>Bitte kontaktieren Sie den Gruppen-Administrator.</target> <target>Bitte kontaktieren Sie den Gruppen-Administrator.</target>
@@ -4046,10 +3937,6 @@ Error: %@</source>
<target>Mehr dazu in der [Benutzeranleitung](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address) lesen.</target> <target>Mehr dazu in der [Benutzeranleitung](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address) lesen.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source>
<target>Mehr dazu in der [Benutzeranleitung](https://simplex.chat/docs/guide/readme.html#connect-to-friends) lesen.</target> <target>Mehr dazu in der [Benutzeranleitung](https://simplex.chat/docs/guide/readme.html#connect-to-friends) lesen.</target>
@@ -4260,10 +4147,6 @@ Error: %@</source>
<target>Fehler bei der Wiederherstellung der Datenbank</target> <target>Fehler bei der Wiederherstellung der Datenbank</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Retry" xml:space="preserve">
<source>Retry</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reveal" xml:space="preserve"> <trans-unit id="Reveal" xml:space="preserve">
<source>Reveal</source> <source>Reveal</source>
<target>Aufdecken</target> <target>Aufdecken</target>
@@ -4396,7 +4279,6 @@ Error: %@</source>
</trans-unit> </trans-unit>
<trans-unit id="Scan QR code from desktop" xml:space="preserve"> <trans-unit id="Scan QR code from desktop" xml:space="preserve">
<source>Scan QR code from desktop</source> <source>Scan QR code from desktop</source>
<target>Den QR-Code vom Desktop scannen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Scan code" xml:space="preserve"> <trans-unit id="Scan code" xml:space="preserve">
@@ -4419,10 +4301,6 @@ Error: %@</source>
<target>Suche</target> <target>Suche</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve"> <trans-unit id="Secure queue" xml:space="preserve">
<source>Secure queue</source> <source>Secure queue</source>
<target>Sichere Warteschlange</target> <target>Sichere Warteschlange</target>
@@ -4625,7 +4503,6 @@ Error: %@</source>
</trans-unit> </trans-unit>
<trans-unit id="Session code" xml:space="preserve"> <trans-unit id="Session code" xml:space="preserve">
<source>Session code</source> <source>Session code</source>
<target>Sitzungscode</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Set 1 day" xml:space="preserve"> <trans-unit id="Set 1 day" xml:space="preserve">
@@ -4698,8 +4575,9 @@ Error: %@</source>
<target>Link teilen</target> <target>Link teilen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve"> <trans-unit id="Share one-time invitation link" xml:space="preserve">
<source>Share this 1-time invite link</source> <source>Share one-time invitation link</source>
<target>Einmal-Einladungslink teilen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve"> <trans-unit id="Share with contacts" xml:space="preserve">
@@ -4822,15 +4700,16 @@ Error: %@</source>
<target>Jemand</target> <target>Jemand</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="Start a new chat" xml:space="preserve">
<source>Start a new chat</source>
<target>Starten Sie einen neuen Chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start chat" xml:space="preserve"> <trans-unit id="Start chat" xml:space="preserve">
<source>Start chat</source> <source>Start chat</source>
<target>Starten Sie den Chat</target> <target>Starten Sie den Chat</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Start chat?" xml:space="preserve">
<source>Start chat?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start migration" xml:space="preserve"> <trans-unit id="Start migration" xml:space="preserve">
<source>Start migration</source> <source>Start migration</source>
<target>Starten Sie die Migration</target> <target>Starten Sie die Migration</target>
@@ -4956,14 +4835,6 @@ Error: %@</source>
<target>Tippen, um Inkognito beizutreten</target> <target>Tippen, um Inkognito beizutreten</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Tap to paste link" xml:space="preserve">
<source>Tap to paste link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to scan" xml:space="preserve">
<source>Tap to scan</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve"> <trans-unit id="Tap to start a new chat" xml:space="preserve">
<source>Tap to start a new chat</source> <source>Tap to start a new chat</source>
<target>Tippen, um einen neuen Chat zu starten</target> <target>Tippen, um einen neuen Chat zu starten</target>
@@ -5026,10 +4897,6 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
<target>Die Änderung des Datenbank-Passworts konnte nicht abgeschlossen werden.</target> <target>Die Änderung des Datenbank-Passworts konnte nicht abgeschlossen werden.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source> <source>The connection you accepted will be cancelled!</source>
<target>Die von Ihnen akzeptierte Verbindung wird abgebrochen!</target> <target>Die von Ihnen akzeptierte Verbindung wird abgebrochen!</target>
@@ -5095,10 +4962,6 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
<target>Server der neuen Verbindungen von Ihrem aktuellen Chat-Profil **%@**.</target> <target>Server der neuen Verbindungen von Ihrem aktuellen Chat-Profil **%@**.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve">
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve"> <trans-unit id="Theme" xml:space="preserve">
<source>Theme</source> <source>Theme</source>
<target>Design</target> <target>Design</target>
@@ -5141,7 +5004,6 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
</trans-unit> </trans-unit>
<trans-unit id="This device name" xml:space="preserve"> <trans-unit id="This device name" xml:space="preserve">
<source>This device name</source> <source>This device name</source>
<target>Dieser Gerätename</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
@@ -5179,11 +5041,6 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
<target>Um eine Verbindung herzustellen, kann Ihr Kontakt den QR-Code scannen oder den Link in der App verwenden.</target> <target>Um eine Verbindung herzustellen, kann Ihr Kontakt den QR-Code scannen oder den Link in der App verwenden.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<target>Um unerwünschte Nachrichten zu verbergen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve"> <trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source> <source>To make a new connection</source>
<target>Um eine Verbindung mit einem neuen Kontakt zu erstellen</target> <target>Um eine Verbindung mit einem neuen Kontakt zu erstellen</target>
@@ -5251,6 +5108,11 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt
<target>Abschalten</target> <target>Abschalten</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Turn off notifications?" xml:space="preserve">
<source>Turn off notifications?</source>
<target>Benachrichtigungen abschalten?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn on" xml:space="preserve"> <trans-unit id="Turn on" xml:space="preserve">
<source>Turn on</source> <source>Turn on</source>
<target>Einschalten</target> <target>Einschalten</target>
@@ -5340,12 +5202,10 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit> </trans-unit>
<trans-unit id="Unlink" xml:space="preserve"> <trans-unit id="Unlink" xml:space="preserve">
<source>Unlink</source> <source>Unlink</source>
<target>Entkoppeln</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Unlink desktop?" xml:space="preserve"> <trans-unit id="Unlink desktop?" xml:space="preserve">
<source>Unlink desktop?</source> <source>Unlink desktop?</source>
<target>Desktop entkoppeln?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Unlock" xml:space="preserve"> <trans-unit id="Unlock" xml:space="preserve">
@@ -5440,7 +5300,6 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit> </trans-unit>
<trans-unit id="Use from desktop" xml:space="preserve"> <trans-unit id="Use from desktop" xml:space="preserve">
<source>Use from desktop</source> <source>Use from desktop</source>
<target>Vom Desktop aus nutzen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use iOS call interface" xml:space="preserve"> <trans-unit id="Use iOS call interface" xml:space="preserve">
@@ -5453,10 +5312,6 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
<target>Nutzen Sie das neue Inkognito-Profil</target> <target>Nutzen Sie das neue Inkognito-Profil</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use only local notifications?" xml:space="preserve">
<source>Use only local notifications?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve"> <trans-unit id="Use server" xml:space="preserve">
<source>Use server</source> <source>Use server</source>
<target>Server nutzen</target> <target>Server nutzen</target>
@@ -5479,12 +5334,10 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit> </trans-unit>
<trans-unit id="Verify code with desktop" xml:space="preserve"> <trans-unit id="Verify code with desktop" xml:space="preserve">
<source>Verify code with desktop</source> <source>Verify code with desktop</source>
<target>Code mit dem Desktop überprüfen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify connection" xml:space="preserve"> <trans-unit id="Verify connection" xml:space="preserve">
<source>Verify connection</source> <source>Verify connection</source>
<target>Verbindung überprüfen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify connection security" xml:space="preserve"> <trans-unit id="Verify connection security" xml:space="preserve">
@@ -5494,7 +5347,6 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit> </trans-unit>
<trans-unit id="Verify connections" xml:space="preserve"> <trans-unit id="Verify connections" xml:space="preserve">
<source>Verify connections</source> <source>Verify connections</source>
<target>Verbindungen überprüfen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify security code" xml:space="preserve"> <trans-unit id="Verify security code" xml:space="preserve">
@@ -5507,11 +5359,6 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
<target>Über den Browser</target> <target>Über den Browser</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<target>Über ein sicheres quantenbeständiges Protokoll.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve"> <trans-unit id="Video call" xml:space="preserve">
<source>Video call</source> <source>Video call</source>
<target>Videoanruf</target> <target>Videoanruf</target>
@@ -5562,11 +5409,6 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
<target>Sprachnachrichten…</target> <target>Sprachnachrichten…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Waiting for desktop..." xml:space="preserve">
<source>Waiting for desktop...</source>
<target>Es wird auf den Desktop gewartet...</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Waiting for file" xml:space="preserve"> <trans-unit id="Waiting for file" xml:space="preserve">
<source>Waiting for file</source> <source>Waiting for file</source>
<target>Warte auf Datei</target> <target>Warte auf Datei</target>
@@ -5719,6 +5561,11 @@ Verbindungsanfrage wiederholen?</target>
<target>Sie können Anrufe ohne Geräte- und App-Authentifizierung vom Sperrbildschirm aus annehmen.</target> <target>Sie können Anrufe ohne Geräte- und App-Authentifizierung vom Sperrbildschirm aus annehmen.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve">
<source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source>
<target>Sie können sich auch verbinden, indem Sie auf den Link klicken. Wenn er im Browser geöffnet wird, klicken Sie auf die Schaltfläche **In mobiler App öffnen**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can create it later" xml:space="preserve"> <trans-unit id="You can create it later" xml:space="preserve">
<source>You can create it later</source> <source>You can create it later</source>
<target>Sie können dies später erstellen</target> <target>Sie können dies später erstellen</target>
@@ -5739,10 +5586,6 @@ Verbindungsanfrage wiederholen?</target>
<target>Sie können ein Benutzerprofil verbergen oder stummschalten - wischen Sie es nach rechts.</target> <target>Sie können ein Benutzerprofil verbergen oder stummschalten - wischen Sie es nach rechts.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now send messages to %@" xml:space="preserve"> <trans-unit id="You can now send messages to %@" xml:space="preserve">
<source>You can now send messages to %@</source> <source>You can now send messages to %@</source>
<target>Sie können nun Nachrichten an %@ versenden</target> <target>Sie können nun Nachrichten an %@ versenden</target>
@@ -5783,10 +5626,6 @@ Verbindungsanfrage wiederholen?</target>
<target>Um Nachrichteninhalte zu formatieren, können Sie Markdowns verwenden:</target> <target>Um Nachrichteninhalte zu formatieren, können Sie Markdowns verwenden:</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can view invitation link again in connection details." xml:space="preserve">
<source>You can view invitation link again in connection details.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can't send messages!" xml:space="preserve"> <trans-unit id="You can't send messages!" xml:space="preserve">
<source>You can't send messages!</source> <source>You can't send messages!</source>
<target>Sie können keine Nachrichten versenden!</target> <target>Sie können keine Nachrichten versenden!</target>
@@ -5976,6 +5815,13 @@ Sie können diese Verbindung abbrechen und den Kontakt entfernen (und es später
<target>Ihre Kontakte können die unwiederbringliche Löschung von Nachrichten erlauben.</target> <target>Ihre Kontakte können die unwiederbringliche Löschung von Nachrichten erlauben.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your contacts in SimpleX will see it.&#10;You can change it in Settings." xml:space="preserve">
<source>Your contacts in SimpleX will see it.
You can change it in Settings.</source>
<target>Ihre Kontakte in SimpleX werden es sehen.
Sie können es in den Einstellungen ändern.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve"> <trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source> <source>Your contacts will remain connected.</source>
<target>Ihre Kontakte bleiben verbunden.</target> <target>Ihre Kontakte bleiben verbunden.</target>
@@ -6108,11 +5954,6 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
<target>Audioanruf (nicht E2E verschlüsselt)</target> <target>Audioanruf (nicht E2E verschlüsselt)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="author" xml:space="preserve">
<source>author</source>
<target>Autor</target>
<note>member role</note>
</trans-unit>
<trans-unit id="bad message ID" xml:space="preserve"> <trans-unit id="bad message ID" xml:space="preserve">
<source>bad message ID</source> <source>bad message ID</source>
<target>Ungültige Nachrichten-ID</target> <target>Ungültige Nachrichten-ID</target>
@@ -6697,7 +6538,6 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit> </trans-unit>
<trans-unit id="v%@" xml:space="preserve"> <trans-unit id="v%@" xml:space="preserve">
<source>v%@</source> <source>v%@</source>
<target>v%@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="v%@ (%@)" xml:space="preserve"> <trans-unit id="v%@ (%@)" xml:space="preserve">
@@ -6839,7 +6679,6 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit> </trans-unit>
<trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve"> <trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve">
<source>SimpleX uses local network access to allow using user chat profile via desktop app on the same network.</source> <source>SimpleX uses local network access to allow using user chat profile via desktop app on the same network.</source>
<target>SimpleX nutzt den lokalen Netzwerkzugriff, um die Nutzung von Benutzer-Chatprofilen über eine Desktop-App im gleichen Netzwerk zu erlauben.</target>
<note>Privacy - Local Network Usage Description</note> <note>Privacy - Local Network Usage Description</note>
</trans-unit> </trans-unit>
<trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve"> <trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve">
@@ -31,39 +31,32 @@ Available in v5.1</source>
<source> (</source> <source> (</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id=" (can be copied)" xml:space="preserve" approved="no"> <trans-unit id=" (can be copied)" xml:space="preserve">
<source> (can be copied)</source> <source> (can be copied)</source>
<target state="translated"> (μπορεί να αντιγραφή)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="!1 colored!" xml:space="preserve" approved="no"> <trans-unit id="!1 colored!" xml:space="preserve">
<source>!1 colored!</source> <source>!1 colored!</source>
<target state="translated">!1 έγχρωμο!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="#secret#" xml:space="preserve" approved="no"> <trans-unit id="#secret#" xml:space="preserve">
<source>#secret#</source> <source>#secret#</source>
<target state="translated">#μυστικό#</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%@" xml:space="preserve" approved="no"> <trans-unit id="%@" xml:space="preserve">
<source>%@</source> <source>%@</source>
<target state="translated">%@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%@ %@" xml:space="preserve" approved="no"> <trans-unit id="%@ %@" xml:space="preserve">
<source>%@ %@</source> <source>%@ %@</source>
<target state="translated">%@ %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%@ / %@" xml:space="preserve" approved="no"> <trans-unit id="%@ / %@" xml:space="preserve">
<source>%@ / %@</source> <source>%@ / %@</source>
<target state="translated">%@ / %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%@ is connected!" xml:space="preserve" approved="no"> <trans-unit id="%@ is connected!" xml:space="preserve">
<source>%@ is connected!</source> <source>%@ is connected!</source>
<target state="translated">%@ είναι συνδεδεμένο!</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="%@ is not verified" xml:space="preserve"> <trans-unit id="%@ is not verified" xml:space="preserve">
@@ -4169,51 +4162,6 @@ SimpleX servers cannot see your profile.</source>
<source>\~strike~</source> <source>\~strike~</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%@ connected" xml:space="preserve" approved="no">
<source>%@ connected</source>
<target state="translated">%@ συνδεδεμένο</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve" approved="no">
<source># %@</source>
<target state="translated"># %@</target>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="%@ and %@" xml:space="preserve" approved="no">
<source>%@ and %@</source>
<target state="translated">%@ και %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ at %@:" xml:space="preserve" approved="no">
<source>%1$@ at %2$@:</source>
<target state="translated">%1$@ στις %2$@:</target>
<note>copied message info, &lt;sender&gt; at &lt;time&gt;</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve" approved="no">
<source>## History</source>
<target state="translated">## Ιστορικό</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="## In reply to" xml:space="preserve" approved="no">
<source>## In reply to</source>
<target state="translated">## Ως απαντηση σε</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="%@ (current)" xml:space="preserve" approved="no">
<source>%@ (current)</source>
<target state="translated">%@ (τωρινό)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ (current):" xml:space="preserve" approved="no">
<source>%@ (current):</source>
<target state="translated">%@ (τωρινό):</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="%@ and %@ connected" xml:space="preserve" approved="no">
<source>%@ and %@ connected</source>
<target state="translated">%@ και %@ συνδεδεμένο</target>
<note>No comment provided by engineer.</note>
</trans-unit>
</body> </body>
</file> </file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="el" datatype="plaintext"> <file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="el" datatype="plaintext">
@@ -312,19 +312,14 @@
<target>)</target> <target>)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve">
<source>**Add contact**: to create a new invitation link, or connect via a link you received.</source>
<target>**Add contact**: to create a new invitation link, or connect via a link you received.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target>**Add new contact**: to create your one-time QR Code or link for your contact.</target> <target>**Add new contact**: to create your one-time QR Code or link for your contact.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Create group**: to create a new group." xml:space="preserve"> <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<source>**Create group**: to create a new group.</source> <source>**Create link / QR code** for your contact to use.</source>
<target>**Create group**: to create a new group.</target> <target>**Create link / QR code** for your contact to use.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -337,6 +332,11 @@
<target>**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app).</target> <target>**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve">
<source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source>
<target>**Paste received link** or open it in the browser and tap **Open in mobile app**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve">
<source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source>
<target>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</target> <target>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</target>
@@ -347,6 +347,11 @@
<target>**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from.</target> <target>**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve">
<source>**Scan QR code**: to connect to your contact in person or via video call.</source>
<target>**Scan QR code**: to connect to your contact in person or via video call.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target>**Warning**: Instant push notifications require passphrase saved in Keychain.</target> <target>**Warning**: Instant push notifications require passphrase saved in Keychain.</target>
@@ -387,15 +392,6 @@
- and more!</source> - and more!</source>
<target>- more stable message delivery. <target>- more stable message delivery.
- a bit better groups. - a bit better groups.
- and more!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- optionally notify deleted contacts.&#10;- profile names with spaces.&#10;- and more!" xml:space="preserve">
<source>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</source>
<target>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</target> - and more!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
@@ -448,6 +444,11 @@
<target>1 week</target> <target>1 week</target>
<note>time interval</note> <note>time interval</note>
</trans-unit> </trans-unit>
<trans-unit id="1-time link" xml:space="preserve">
<source>1-time link</source>
<target>1-time link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="5 minutes" xml:space="preserve"> <trans-unit id="5 minutes" xml:space="preserve">
<source>5 minutes</source> <source>5 minutes</source>
<target>5 minutes</target> <target>5 minutes</target>
@@ -563,11 +564,6 @@
<target>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</target> <target>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add contact" xml:space="preserve">
<source>Add contact</source>
<target>Add contact</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve"> <trans-unit id="Add preset servers" xml:space="preserve">
<source>Add preset servers</source> <source>Add preset servers</source>
<target>Add preset servers</target> <target>Add preset servers</target>
@@ -898,11 +894,6 @@
<target>Bad message hash</target> <target>Bad message hash</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
<source>Better groups</source>
<target>Better groups</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better messages" xml:space="preserve"> <trans-unit id="Better messages" xml:space="preserve">
<source>Better messages</source> <source>Better messages</source>
<target>Better messages</target> <target>Better messages</target>
@@ -913,11 +904,6 @@
<target>Block</target> <target>Block</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
<source>Block group members</source>
<target>Block group members</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve"> <trans-unit id="Block member" xml:space="preserve">
<source>Block member</source> <source>Block member</source>
<target>Block member</target> <target>Block member</target>
@@ -973,11 +959,6 @@
<target>Calls</target> <target>Calls</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Camera not available" xml:space="preserve">
<source>Camera not available</source>
<target>Camera not available</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Can't delete user profile!" xml:space="preserve"> <trans-unit id="Can't delete user profile!" xml:space="preserve">
<source>Can't delete user profile!</source> <source>Can't delete user profile!</source>
<target>Can't delete user profile!</target> <target>Can't delete user profile!</target>
@@ -1094,11 +1075,6 @@
<target>Chat is stopped</target> <target>Chat is stopped</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve">
<source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source>
<target>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve"> <trans-unit id="Chat preferences" xml:space="preserve">
<source>Chat preferences</source> <source>Chat preferences</source>
<target>Chat preferences</target> <target>Chat preferences</target>
@@ -1199,11 +1175,6 @@
<target>Connect</target> <target>Connect</target>
<note>server test step</note> <note>server test step</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect automatically" xml:space="preserve">
<source>Connect automatically</source>
<target>Connect automatically</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve"> <trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source> <source>Connect incognito</source>
<target>Connect incognito</target> <target>Connect incognito</target>
@@ -1243,6 +1214,11 @@ This is your own one-time link!</target>
<target>Connect via link</target> <target>Connect via link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link / QR code" xml:space="preserve">
<source>Connect via link / QR code</source>
<target>Connect via link / QR code</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link" xml:space="preserve"> <trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source> <source>Connect via one-time link</source>
<target>Connect via one-time link</target> <target>Connect via one-time link</target>
@@ -1383,11 +1359,6 @@ This is your own one-time link!</target>
<target>Create SimpleX address</target> <target>Create SimpleX address</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create a group using a random profile." xml:space="preserve">
<source>Create a group using a random profile.</source>
<target>Create a group using a random profile.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source> <source>Create an address to let people connect with you.</source>
<target>Create an address to let people connect with you.</target> <target>Create an address to let people connect with you.</target>
@@ -1418,6 +1389,11 @@ This is your own one-time link!</target>
<target>Create new profile in [desktop app](https://simplex.chat/downloads/). 💻</target> <target>Create new profile in [desktop app](https://simplex.chat/downloads/). 💻</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create one-time invitation link" xml:space="preserve">
<source>Create one-time invitation link</source>
<target>Create one-time invitation link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<target>Create profile</target> <target>Create profile</target>
@@ -1443,11 +1419,6 @@ This is your own one-time link!</target>
<target>Created on %@</target> <target>Created on %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
<source>Creating link…</source>
<target>Creating link…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve"> <trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source> <source>Current Passcode</source>
<target>Current Passcode</target> <target>Current Passcode</target>
@@ -1913,9 +1884,9 @@ This cannot be undone!</target>
<target>Discover and join groups</target> <target>Discover and join groups</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve"> <trans-unit id="Discover on network" xml:space="preserve">
<source>Discover via local network</source> <source>Discover on network</source>
<target>Discover via local network</target> <target>Discover on network</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -1998,11 +1969,6 @@ This cannot be undone!</target>
<target>Enable automatic message deletion?</target> <target>Enable automatic message deletion?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enable camera access" xml:space="preserve">
<source>Enable camera access</source>
<target>Enable camera access</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve"> <trans-unit id="Enable for all" xml:space="preserve">
<source>Enable for all</source> <source>Enable for all</source>
<target>Enable for all</target> <target>Enable for all</target>
@@ -2068,11 +2034,6 @@ This cannot be undone!</target>
<target>Encrypted message or another event</target> <target>Encrypted message or another event</target>
<note>notification</note> <note>notification</note>
</trans-unit> </trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve">
<source>Encrypted message: app is stopped</source>
<target>Encrypted message: app is stopped</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve"> <trans-unit id="Encrypted message: database error" xml:space="preserve">
<source>Encrypted message: database error</source> <source>Encrypted message: database error</source>
<target>Encrypted message: database error</target> <target>Encrypted message: database error</target>
@@ -2303,11 +2264,6 @@ This cannot be undone!</target>
<target>Error loading %@ servers</target> <target>Error loading %@ servers</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<target>Error opening chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error receiving file" xml:space="preserve"> <trans-unit id="Error receiving file" xml:space="preserve">
<source>Error receiving file</source> <source>Error receiving file</source>
<target>Error receiving file</target> <target>Error receiving file</target>
@@ -2348,11 +2304,6 @@ This cannot be undone!</target>
<target>Error saving user password</target> <target>Error saving user password</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error scanning code: %@" xml:space="preserve">
<source>Error scanning code: %@</source>
<target>Error scanning code: %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve"> <trans-unit id="Error sending email" xml:space="preserve">
<source>Error sending email</source> <source>Error sending email</source>
<target>Error sending email</target> <target>Error sending email</target>
@@ -2478,11 +2429,6 @@ This cannot be undone!</target>
<target>Fast and no wait until the sender is online!</target> <target>Fast and no wait until the sender is online!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<target>Faster joining and more reliable messages.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve"> <trans-unit id="Favorite" xml:space="preserve">
<source>Favorite</source> <source>Favorite</source>
<target>Favorite</target> <target>Favorite</target>
@@ -2578,11 +2524,6 @@ This cannot be undone!</target>
<target>For console</target> <target>For console</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Found desktop" xml:space="preserve">
<source>Found desktop</source>
<target>Found desktop</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="French interface" xml:space="preserve"> <trans-unit id="French interface" xml:space="preserve">
<source>French interface</source> <source>French interface</source>
<target>French interface</target> <target>French interface</target>
@@ -2828,6 +2769,11 @@ This cannot be undone!</target>
<target>If you can't meet in person, show QR code in a video call, or share the link.</target> <target>If you can't meet in person, show QR code in a video call, or share the link.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve">
<source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source>
<target>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve">
<source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source>
<target>If you enter this passcode when opening the app, all app data will be irreversibly removed!</target> <target>If you enter this passcode when opening the app, all app data will be irreversibly removed!</target>
@@ -2903,11 +2849,6 @@ This cannot be undone!</target>
<target>Incognito</target> <target>Incognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<target>Incognito groups</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve"> <trans-unit id="Incognito mode" xml:space="preserve">
<source>Incognito mode</source> <source>Incognito mode</source>
<target>Incognito mode</target> <target>Incognito mode</target>
@@ -2985,31 +2926,16 @@ This cannot be undone!</target>
<target>Interface</target> <target>Interface</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid QR code" xml:space="preserve">
<source>Invalid QR code</source>
<target>Invalid QR code</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve"> <trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source> <source>Invalid connection link</source>
<target>Invalid connection link</target> <target>Invalid connection link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
<source>Invalid link</source>
<target>Invalid link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve"> <trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source> <source>Invalid name!</source>
<target>Invalid name!</target> <target>Invalid name!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid response" xml:space="preserve">
<source>Invalid response</source>
<target>Invalid response</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve"> <trans-unit id="Invalid server address!" xml:space="preserve">
<source>Invalid server address!</source> <source>Invalid server address!</source>
<target>Invalid server address!</target> <target>Invalid server address!</target>
@@ -3128,21 +3054,11 @@ This is your link for group %@!</target>
<target>Joining group</target> <target>Joining group</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep" xml:space="preserve">
<source>Keep</source>
<target>Keep</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
<source>Keep the app open to use it from desktop</source> <source>Keep the app open to use it from desktop</source>
<target>Keep the app open to use it from desktop</target> <target>Keep the app open to use it from desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep unused invitation?" xml:space="preserve">
<source>Keep unused invitation?</source>
<target>Keep unused invitation?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve"> <trans-unit id="Keep your connections" xml:space="preserve">
<source>Keep your connections</source> <source>Keep your connections</source>
<target>Keep your connections</target> <target>Keep your connections</target>
@@ -3203,11 +3119,6 @@ This is your link for group %@!</target>
<target>Limitations</target> <target>Limitations</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<target>Link mobile and desktop apps! 🔗</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve"> <trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source> <source>Linked desktop options</source>
<target>Linked desktop options</target> <target>Linked desktop options</target>
@@ -3228,11 +3139,6 @@ This is your link for group %@!</target>
<target>Live messages</target> <target>Live messages</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Local" xml:space="preserve">
<source>Local</source>
<target>Local</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Local name" xml:space="preserve"> <trans-unit id="Local name" xml:space="preserve">
<source>Local name</source> <source>Local name</source>
<target>Local name</target> <target>Local name</target>
@@ -3473,11 +3379,6 @@ This is your link for group %@!</target>
<target>New Passcode</target> <target>New Passcode</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="New chat" xml:space="preserve">
<source>New chat</source>
<target>New chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve"> <trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source> <source>New contact request</source>
<target>New contact request</target> <target>New contact request</target>
@@ -3578,11 +3479,6 @@ This is your link for group %@!</target>
<target>No received or sent files</target> <target>No received or sent files</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Not compatible!" xml:space="preserve">
<source>Not compatible!</source>
<target>Not compatible!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve"> <trans-unit id="Notifications" xml:space="preserve">
<source>Notifications</source> <source>Notifications</source>
<target>Notifications</target> <target>Notifications</target>
@@ -3602,16 +3498,16 @@ This is your link for group %@!</target>
- disable members ("observer" role)</target> - disable members ("observer" role)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="OK" xml:space="preserve">
<source>OK</source>
<target>OK</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Off" xml:space="preserve"> <trans-unit id="Off" xml:space="preserve">
<source>Off</source> <source>Off</source>
<target>Off</target> <target>Off</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Off (Local)" xml:space="preserve">
<source>Off (Local)</source>
<target>Off (Local)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ok" xml:space="preserve"> <trans-unit id="Ok" xml:space="preserve">
<source>Ok</source> <source>Ok</source>
<target>Ok</target> <target>Ok</target>
@@ -3752,19 +3648,9 @@ This is your link for group %@!</target>
<target>Open-source protocol and code anybody can run the servers.</target> <target>Open-source protocol and code anybody can run the servers.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Opening app…" xml:space="preserve"> <trans-unit id="Opening database…" xml:space="preserve">
<source>Opening app…</source> <source>Opening database…</source>
<target>Opening app…</target> <target>Opening database…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or scan QR code" xml:space="preserve">
<source>Or scan QR code</source>
<target>Or scan QR code</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
<source>Or show this code</source>
<target>Or show this code</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="PING count" xml:space="preserve"> <trans-unit id="PING count" xml:space="preserve">
@@ -3807,6 +3693,11 @@ This is your link for group %@!</target>
<target>Password to show</target> <target>Password to show</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste" xml:space="preserve">
<source>Paste</source>
<target>Paste</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve"> <trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source> <source>Paste desktop address</source>
<target>Paste desktop address</target> <target>Paste desktop address</target>
@@ -3817,11 +3708,16 @@ This is your link for group %@!</target>
<target>Paste image</target> <target>Paste image</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve"> <trans-unit id="Paste received link" xml:space="preserve">
<source>Paste the link you received</source> <source>Paste received link</source>
<target>Paste the link you received</target> <target>Paste received link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Paste the link you received to connect with your contact.</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source> <source>People can connect to you only via the links you share.</source>
<target>People can connect to you only via the links you share.</target> <target>People can connect to you only via the links you share.</target>
@@ -3857,13 +3753,6 @@ This is your link for group %@!</target>
<target>Please check yours and your contact preferences.</target> <target>Please check yours and your contact preferences.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Please contact developers.&#10;Error: %@" xml:space="preserve">
<source>Please contact developers.
Error: %@</source>
<target>Please contact developers.
Error: %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please contact group admin." xml:space="preserve"> <trans-unit id="Please contact group admin." xml:space="preserve">
<source>Please contact group admin.</source> <source>Please contact group admin.</source>
<target>Please contact group admin.</target> <target>Please contact group admin.</target>
@@ -4069,11 +3958,6 @@ Error: %@</target>
<target>Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <target>Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source>
<target>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source>
<target>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> <target>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target>
@@ -4284,11 +4168,6 @@ Error: %@</target>
<target>Restore database error</target> <target>Restore database error</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Retry" xml:space="preserve">
<source>Retry</source>
<target>Retry</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reveal" xml:space="preserve"> <trans-unit id="Reveal" xml:space="preserve">
<source>Reveal</source> <source>Reveal</source>
<target>Reveal</target> <target>Reveal</target>
@@ -4444,11 +4323,6 @@ Error: %@</target>
<target>Search</target> <target>Search</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<target>Search or paste SimpleX link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve"> <trans-unit id="Secure queue" xml:space="preserve">
<source>Secure queue</source> <source>Secure queue</source>
<target>Secure queue</target> <target>Secure queue</target>
@@ -4724,9 +4598,9 @@ Error: %@</target>
<target>Share link</target> <target>Share link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve"> <trans-unit id="Share one-time invitation link" xml:space="preserve">
<source>Share this 1-time invite link</source> <source>Share one-time invitation link</source>
<target>Share this 1-time invite link</target> <target>Share one-time invitation link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve"> <trans-unit id="Share with contacts" xml:space="preserve">
@@ -4849,16 +4723,16 @@ Error: %@</target>
<target>Somebody</target> <target>Somebody</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="Start a new chat" xml:space="preserve">
<source>Start a new chat</source>
<target>Start a new chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start chat" xml:space="preserve"> <trans-unit id="Start chat" xml:space="preserve">
<source>Start chat</source> <source>Start chat</source>
<target>Start chat</target> <target>Start chat</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Start chat?" xml:space="preserve">
<source>Start chat?</source>
<target>Start chat?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start migration" xml:space="preserve"> <trans-unit id="Start migration" xml:space="preserve">
<source>Start migration</source> <source>Start migration</source>
<target>Start migration</target> <target>Start migration</target>
@@ -4984,16 +4858,6 @@ Error: %@</target>
<target>Tap to join incognito</target> <target>Tap to join incognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Tap to paste link" xml:space="preserve">
<source>Tap to paste link</source>
<target>Tap to paste link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to scan" xml:space="preserve">
<source>Tap to scan</source>
<target>Tap to scan</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve"> <trans-unit id="Tap to start a new chat" xml:space="preserve">
<source>Tap to start a new chat</source> <source>Tap to start a new chat</source>
<target>Tap to start a new chat</target> <target>Tap to start a new chat</target>
@@ -5056,11 +4920,6 @@ It can happen because of some bug or when the connection is compromised.</target
<target>The attempt to change database passphrase was not completed.</target> <target>The attempt to change database passphrase was not completed.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<target>The code you scanned is not a SimpleX link QR code.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source> <source>The connection you accepted will be cancelled!</source>
<target>The connection you accepted will be cancelled!</target> <target>The connection you accepted will be cancelled!</target>
@@ -5126,11 +4985,6 @@ It can happen because of some bug or when the connection is compromised.</target
<target>The servers for new connections of your current chat profile **%@**.</target> <target>The servers for new connections of your current chat profile **%@**.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve">
<source>The text you pasted is not a SimpleX link.</source>
<target>The text you pasted is not a SimpleX link.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve"> <trans-unit id="Theme" xml:space="preserve">
<source>Theme</source> <source>Theme</source>
<target>Theme</target> <target>Theme</target>
@@ -5211,11 +5065,6 @@ It can happen because of some bug or when the connection is compromised.</target
<target>To connect, your contact can scan QR code or use the link in the app.</target> <target>To connect, your contact can scan QR code or use the link in the app.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<target>To hide unwanted messages.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve"> <trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source> <source>To make a new connection</source>
<target>To make a new connection</target> <target>To make a new connection</target>
@@ -5283,6 +5132,11 @@ You will be prompted to complete authentication before this feature is enabled.<
<target>Turn off</target> <target>Turn off</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Turn off notifications?" xml:space="preserve">
<source>Turn off notifications?</source>
<target>Turn off notifications?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn on" xml:space="preserve"> <trans-unit id="Turn on" xml:space="preserve">
<source>Turn on</source> <source>Turn on</source>
<target>Turn on</target> <target>Turn on</target>
@@ -5485,11 +5339,6 @@ To connect, please ask your contact to create another connection link and check
<target>Use new incognito profile</target> <target>Use new incognito profile</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use only local notifications?" xml:space="preserve">
<source>Use only local notifications?</source>
<target>Use only local notifications?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve"> <trans-unit id="Use server" xml:space="preserve">
<source>Use server</source> <source>Use server</source>
<target>Use server</target> <target>Use server</target>
@@ -5540,11 +5389,6 @@ To connect, please ask your contact to create another connection link and check
<target>Via browser</target> <target>Via browser</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<target>Via secure quantum resistant protocol.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve"> <trans-unit id="Video call" xml:space="preserve">
<source>Video call</source> <source>Video call</source>
<target>Video call</target> <target>Video call</target>
@@ -5595,11 +5439,6 @@ To connect, please ask your contact to create another connection link and check
<target>Voice message…</target> <target>Voice message…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Waiting for desktop..." xml:space="preserve">
<source>Waiting for desktop...</source>
<target>Waiting for desktop...</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Waiting for file" xml:space="preserve"> <trans-unit id="Waiting for file" xml:space="preserve">
<source>Waiting for file</source> <source>Waiting for file</source>
<target>Waiting for file</target> <target>Waiting for file</target>
@@ -5752,6 +5591,11 @@ Repeat join request?</target>
<target>You can accept calls from lock screen, without device and app authentication.</target> <target>You can accept calls from lock screen, without device and app authentication.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve">
<source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source>
<target>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can create it later" xml:space="preserve"> <trans-unit id="You can create it later" xml:space="preserve">
<source>You can create it later</source> <source>You can create it later</source>
<target>You can create it later</target> <target>You can create it later</target>
@@ -5772,11 +5616,6 @@ Repeat join request?</target>
<target>You can hide or mute a user profile - swipe it to the right.</target> <target>You can hide or mute a user profile - swipe it to the right.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<target>You can make it visible to your SimpleX contacts via Settings.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now send messages to %@" xml:space="preserve"> <trans-unit id="You can now send messages to %@" xml:space="preserve">
<source>You can now send messages to %@</source> <source>You can now send messages to %@</source>
<target>You can now send messages to %@</target> <target>You can now send messages to %@</target>
@@ -5817,11 +5656,6 @@ Repeat join request?</target>
<target>You can use markdown to format messages:</target> <target>You can use markdown to format messages:</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can view invitation link again in connection details." xml:space="preserve">
<source>You can view invitation link again in connection details.</source>
<target>You can view invitation link again in connection details.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can't send messages!" xml:space="preserve"> <trans-unit id="You can't send messages!" xml:space="preserve">
<source>You can't send messages!</source> <source>You can't send messages!</source>
<target>You can't send messages!</target> <target>You can't send messages!</target>
@@ -6011,6 +5845,13 @@ You can cancel this connection and remove the contact (and try later with a new
<target>Your contacts can allow full message deletion.</target> <target>Your contacts can allow full message deletion.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your contacts in SimpleX will see it.&#10;You can change it in Settings." xml:space="preserve">
<source>Your contacts in SimpleX will see it.
You can change it in Settings.</source>
<target>Your contacts in SimpleX will see it.
You can change it in Settings.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve"> <trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source> <source>Your contacts will remain connected.</source>
<target>Your contacts will remain connected.</target> <target>Your contacts will remain connected.</target>
@@ -6143,11 +5984,6 @@ SimpleX servers cannot see your profile.</target>
<target>audio call (not e2e encrypted)</target> <target>audio call (not e2e encrypted)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="author" xml:space="preserve">
<source>author</source>
<target>author</target>
<note>member role</note>
</trans-unit>
<trans-unit id="bad message ID" xml:space="preserve"> <trans-unit id="bad message ID" xml:space="preserve">
<source>bad message ID</source> <source>bad message ID</source>
<target>bad message ID</target> <target>bad message ID</target>
File diff suppressed because it is too large Load Diff
@@ -303,17 +303,14 @@
<target>)</target> <target>)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve">
<source>**Add contact**: to create a new invitation link, or connect via a link you received.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target>**Lisää uusi kontakti**: luo kertakäyttöinen QR-koodi tai linkki kontaktille.</target> <target>**Lisää uusi kontakti**: luo kertakäyttöinen QR-koodi tai linkki kontaktille.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Create group**: to create a new group." xml:space="preserve"> <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<source>**Create group**: to create a new group.</source> <source>**Create link / QR code** for your contact to use.</source>
<target>**Luo linkki / QR-koodi* kontaktille.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -326,6 +323,11 @@
<target>**Yksityisin**: älä käytä SimpleX Chat -ilmoituspalvelinta, tarkista viestit ajoittain taustalla (riippuu siitä, kuinka usein käytät sovellusta).</target> <target>**Yksityisin**: älä käytä SimpleX Chat -ilmoituspalvelinta, tarkista viestit ajoittain taustalla (riippuu siitä, kuinka usein käytät sovellusta).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve">
<source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source>
<target>**Liitä vastaanotettu linkki** tai avaa se selaimessa ja napauta **Avaa mobiilisovelluksessa**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve">
<source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source>
<target>**Huomaa**: et voi palauttaa tai muuttaa tunnuslausetta, jos kadotat sen.</target> <target>**Huomaa**: et voi palauttaa tai muuttaa tunnuslausetta, jos kadotat sen.</target>
@@ -336,6 +338,11 @@
<target>**Suositus**: laitetunnus ja ilmoitukset lähetetään SimpleX Chat -ilmoituspalvelimelle, mutta ei viestin sisältöä, kokoa tai sitä, keneltä se on peräisin.</target> <target>**Suositus**: laitetunnus ja ilmoitukset lähetetään SimpleX Chat -ilmoituspalvelimelle, mutta ei viestin sisältöä, kokoa tai sitä, keneltä se on peräisin.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve">
<source>**Scan QR code**: to connect to your contact in person or via video call.</source>
<target>**Skannaa QR-koodi**: muodosta yhteys kontaktiisi henkilökohtaisesti tai videopuhelun kautta.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target>**Varoitus**: Välittömät push-ilmoitukset vaativat tunnuslauseen, joka on tallennettu Keychainiin.</target> <target>**Varoitus**: Välittömät push-ilmoitukset vaativat tunnuslauseen, joka on tallennettu Keychainiin.</target>
@@ -376,12 +383,6 @@
- ja paljon muuta!</target> - ja paljon muuta!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="- optionally notify deleted contacts.&#10;- profile names with spaces.&#10;- and more!" xml:space="preserve">
<source>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve"> <trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve">
<source>- voice messages up to 5 minutes. <source>- voice messages up to 5 minutes.
- custom time to disappear. - custom time to disappear.
@@ -430,6 +431,11 @@
<target>1 viikko</target> <target>1 viikko</target>
<note>time interval</note> <note>time interval</note>
</trans-unit> </trans-unit>
<trans-unit id="1-time link" xml:space="preserve">
<source>1-time link</source>
<target>Kertakäyttölinkki</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="5 minutes" xml:space="preserve"> <trans-unit id="5 minutes" xml:space="preserve">
<source>5 minutes</source> <source>5 minutes</source>
<target>5 minuuttia</target> <target>5 minuuttia</target>
@@ -545,10 +551,6 @@
<target>Lisää osoite profiiliisi, jotta kontaktisi voivat jakaa sen muiden kanssa. Profiilipäivitys lähetetään kontakteillesi.</target> <target>Lisää osoite profiiliisi, jotta kontaktisi voivat jakaa sen muiden kanssa. Profiilipäivitys lähetetään kontakteillesi.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add contact" xml:space="preserve">
<source>Add contact</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve"> <trans-unit id="Add preset servers" xml:space="preserve">
<source>Add preset servers</source> <source>Add preset servers</source>
<target>Lisää esiasetettuja palvelimia</target> <target>Lisää esiasetettuja palvelimia</target>
@@ -874,10 +876,6 @@
<target>Virheellinen viestin tarkiste</target> <target>Virheellinen viestin tarkiste</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
<source>Better groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better messages" xml:space="preserve"> <trans-unit id="Better messages" xml:space="preserve">
<source>Better messages</source> <source>Better messages</source>
<target>Parempia viestejä</target> <target>Parempia viestejä</target>
@@ -887,10 +885,6 @@
<source>Block</source> <source>Block</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
<source>Block group members</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve"> <trans-unit id="Block member" xml:space="preserve">
<source>Block member</source> <source>Block member</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -943,10 +937,6 @@
<target>Puhelut</target> <target>Puhelut</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Camera not available" xml:space="preserve">
<source>Camera not available</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Can't delete user profile!" xml:space="preserve"> <trans-unit id="Can't delete user profile!" xml:space="preserve">
<source>Can't delete user profile!</source> <source>Can't delete user profile!</source>
<target>Käyttäjäprofiilia ei voi poistaa!</target> <target>Käyttäjäprofiilia ei voi poistaa!</target>
@@ -1063,10 +1053,6 @@
<target>Chat on pysäytetty</target> <target>Chat on pysäytetty</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve">
<source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve"> <trans-unit id="Chat preferences" xml:space="preserve">
<source>Chat preferences</source> <source>Chat preferences</source>
<target>Chat-asetukset</target> <target>Chat-asetukset</target>
@@ -1167,10 +1153,6 @@
<target>Yhdistä</target> <target>Yhdistä</target>
<note>server test step</note> <note>server test step</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect automatically" xml:space="preserve">
<source>Connect automatically</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve"> <trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source> <source>Connect incognito</source>
<target>Yhdistä Incognito</target> <target>Yhdistä Incognito</target>
@@ -1203,6 +1185,11 @@ This is your own one-time link!</source>
<target>Yhdistä linkin kautta</target> <target>Yhdistä linkin kautta</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link / QR code" xml:space="preserve">
<source>Connect via link / QR code</source>
<target>Yhdistä linkillä / QR-koodilla</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link" xml:space="preserve"> <trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source> <source>Connect via one-time link</source>
<target>Yhdistä kertalinkillä</target> <target>Yhdistä kertalinkillä</target>
@@ -1337,10 +1324,6 @@ This is your own one-time link!</source>
<target>Luo SimpleX-osoite</target> <target>Luo SimpleX-osoite</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create a group using a random profile." xml:space="preserve">
<source>Create a group using a random profile.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source> <source>Create an address to let people connect with you.</source>
<target>Luo osoite, jolla ihmiset voivat ottaa sinuun yhteyttä.</target> <target>Luo osoite, jolla ihmiset voivat ottaa sinuun yhteyttä.</target>
@@ -1370,6 +1353,11 @@ This is your own one-time link!</source>
<target>Luo uusi profiili [työpöytäsovelluksessa](https://simplex.chat/downloads/). 💻</target> <target>Luo uusi profiili [työpöytäsovelluksessa](https://simplex.chat/downloads/). 💻</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create one-time invitation link" xml:space="preserve">
<source>Create one-time invitation link</source>
<target>Luo kertakutsulinkki</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -1394,10 +1382,6 @@ This is your own one-time link!</source>
<target>Luotu %@</target> <target>Luotu %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve"> <trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source> <source>Current Passcode</source>
<target>Nykyinen pääsykoodi</target> <target>Nykyinen pääsykoodi</target>
@@ -1855,8 +1839,8 @@ This cannot be undone!</source>
<target>Löydä ryhmiä ja liity niihin</target> <target>Löydä ryhmiä ja liity niihin</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve"> <trans-unit id="Discover on network" xml:space="preserve">
<source>Discover via local network</source> <source>Discover on network</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -1939,10 +1923,6 @@ This cannot be undone!</source>
<target>Ota automaattinen viestien poisto käyttöön?</target> <target>Ota automaattinen viestien poisto käyttöön?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enable camera access" xml:space="preserve">
<source>Enable camera access</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve"> <trans-unit id="Enable for all" xml:space="preserve">
<source>Enable for all</source> <source>Enable for all</source>
<target>Salli kaikille</target> <target>Salli kaikille</target>
@@ -2007,10 +1987,6 @@ This cannot be undone!</source>
<target>Salattu viesti tai muu tapahtuma</target> <target>Salattu viesti tai muu tapahtuma</target>
<note>notification</note> <note>notification</note>
</trans-unit> </trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve">
<source>Encrypted message: app is stopped</source>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve"> <trans-unit id="Encrypted message: database error" xml:space="preserve">
<source>Encrypted message: database error</source> <source>Encrypted message: database error</source>
<target>Salattu viesti: tietokantavirhe</target> <target>Salattu viesti: tietokantavirhe</target>
@@ -2235,10 +2211,6 @@ This cannot be undone!</source>
<target>Virhe %@-palvelimien lataamisessa</target> <target>Virhe %@-palvelimien lataamisessa</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error receiving file" xml:space="preserve"> <trans-unit id="Error receiving file" xml:space="preserve">
<source>Error receiving file</source> <source>Error receiving file</source>
<target>Virhe tiedoston vastaanottamisessa</target> <target>Virhe tiedoston vastaanottamisessa</target>
@@ -2279,10 +2251,6 @@ This cannot be undone!</source>
<target>Virhe käyttäjän salasanan tallentamisessa</target> <target>Virhe käyttäjän salasanan tallentamisessa</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error scanning code: %@" xml:space="preserve">
<source>Error scanning code: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve"> <trans-unit id="Error sending email" xml:space="preserve">
<source>Error sending email</source> <source>Error sending email</source>
<target>Virhe sähköpostin lähettämisessä</target> <target>Virhe sähköpostin lähettämisessä</target>
@@ -2406,10 +2374,6 @@ This cannot be undone!</source>
<target>Nopea ja ei odotusta, kunnes lähettäjä on online-tilassa!</target> <target>Nopea ja ei odotusta, kunnes lähettäjä on online-tilassa!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve"> <trans-unit id="Favorite" xml:space="preserve">
<source>Favorite</source> <source>Favorite</source>
<target>Suosikki</target> <target>Suosikki</target>
@@ -2505,10 +2469,6 @@ This cannot be undone!</source>
<target>Konsoliin</target> <target>Konsoliin</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Found desktop" xml:space="preserve">
<source>Found desktop</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="French interface" xml:space="preserve"> <trans-unit id="French interface" xml:space="preserve">
<source>French interface</source> <source>French interface</source>
<target>Ranskalainen käyttöliittymä</target> <target>Ranskalainen käyttöliittymä</target>
@@ -2751,6 +2711,11 @@ This cannot be undone!</source>
<target>Jos et voi tavata henkilökohtaisesti, näytä QR-koodi videopuhelussa tai jaa linkki.</target> <target>Jos et voi tavata henkilökohtaisesti, näytä QR-koodi videopuhelussa tai jaa linkki.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve">
<source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source>
<target>Jos et voi tavata henkilökohtaisesti, voit **skannata QR-koodin videopuhelussa** tai kontaktisi voi jakaa kutsulinkin.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve">
<source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source>
<target>Jos syötät tämän pääsykoodin sovellusta avatessasi, kaikki sovelluksen tiedot poistetaan peruuttamattomasti!</target> <target>Jos syötät tämän pääsykoodin sovellusta avatessasi, kaikki sovelluksen tiedot poistetaan peruuttamattomasti!</target>
@@ -2826,10 +2791,6 @@ This cannot be undone!</source>
<target>Incognito</target> <target>Incognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve"> <trans-unit id="Incognito mode" xml:space="preserve">
<source>Incognito mode</source> <source>Incognito mode</source>
<target>Incognito-tila</target> <target>Incognito-tila</target>
@@ -2906,27 +2867,15 @@ This cannot be undone!</source>
<target>Käyttöliittymä</target> <target>Käyttöliittymä</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid QR code" xml:space="preserve">
<source>Invalid QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve"> <trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source> <source>Invalid connection link</source>
<target>Virheellinen yhteyslinkki</target> <target>Virheellinen yhteyslinkki</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
<source>Invalid link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve"> <trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source> <source>Invalid name!</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid response" xml:space="preserve">
<source>Invalid response</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve"> <trans-unit id="Invalid server address!" xml:space="preserve">
<source>Invalid server address!</source> <source>Invalid server address!</source>
<target>Virheellinen palvelinosoite!</target> <target>Virheellinen palvelinosoite!</target>
@@ -3041,18 +2990,10 @@ This is your link for group %@!</source>
<target>Liittyy ryhmään</target> <target>Liittyy ryhmään</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep" xml:space="preserve">
<source>Keep</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
<source>Keep the app open to use it from desktop</source> <source>Keep the app open to use it from desktop</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep unused invitation?" xml:space="preserve">
<source>Keep unused invitation?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve"> <trans-unit id="Keep your connections" xml:space="preserve">
<source>Keep your connections</source> <source>Keep your connections</source>
<target>Pidä kontaktisi</target> <target>Pidä kontaktisi</target>
@@ -3113,10 +3054,6 @@ This is your link for group %@!</source>
<target>Rajoitukset</target> <target>Rajoitukset</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve"> <trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source> <source>Linked desktop options</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3135,11 +3072,6 @@ This is your link for group %@!</source>
<target>Live-viestit</target> <target>Live-viestit</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Local" xml:space="preserve">
<source>Local</source>
<target>Paikallinen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Local name" xml:space="preserve"> <trans-unit id="Local name" xml:space="preserve">
<source>Local name</source> <source>Local name</source>
<target>Paikallinen nimi</target> <target>Paikallinen nimi</target>
@@ -3379,10 +3311,6 @@ This is your link for group %@!</source>
<target>Uusi pääsykoodi</target> <target>Uusi pääsykoodi</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="New chat" xml:space="preserve">
<source>New chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve"> <trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source> <source>New contact request</source>
<target>Uusi kontaktipyyntö</target> <target>Uusi kontaktipyyntö</target>
@@ -3482,10 +3410,6 @@ This is your link for group %@!</source>
<target>Ei vastaanotettuja tai lähetettyjä tiedostoja</target> <target>Ei vastaanotettuja tai lähetettyjä tiedostoja</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Not compatible!" xml:space="preserve">
<source>Not compatible!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve"> <trans-unit id="Notifications" xml:space="preserve">
<source>Notifications</source> <source>Notifications</source>
<target>Ilmoitukset</target> <target>Ilmoitukset</target>
@@ -3505,15 +3429,16 @@ This is your link for group %@!</source>
- poista jäsenet käytöstä ("tarkkailija" rooli)</target> - poista jäsenet käytöstä ("tarkkailija" rooli)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="OK" xml:space="preserve">
<source>OK</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Off" xml:space="preserve"> <trans-unit id="Off" xml:space="preserve">
<source>Off</source> <source>Off</source>
<target>Pois</target> <target>Pois</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Off (Local)" xml:space="preserve">
<source>Off (Local)</source>
<target>Pois (Paikallinen)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ok" xml:space="preserve"> <trans-unit id="Ok" xml:space="preserve">
<source>Ok</source> <source>Ok</source>
<target>Ok</target> <target>Ok</target>
@@ -3652,16 +3577,9 @@ This is your link for group %@!</source>
<target>Avoimen lähdekoodin protokolla ja koodi - kuka tahansa voi käyttää palvelimia.</target> <target>Avoimen lähdekoodin protokolla ja koodi - kuka tahansa voi käyttää palvelimia.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Opening app…" xml:space="preserve"> <trans-unit id="Opening database…" xml:space="preserve">
<source>Opening app…</source> <source>Opening database…</source>
<note>No comment provided by engineer.</note> <target>Avataan tietokantaa…</target>
</trans-unit>
<trans-unit id="Or scan QR code" xml:space="preserve">
<source>Or scan QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
<source>Or show this code</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="PING count" xml:space="preserve"> <trans-unit id="PING count" xml:space="preserve">
@@ -3704,6 +3622,11 @@ This is your link for group %@!</source>
<target>Salasana näytettäväksi</target> <target>Salasana näytettäväksi</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste" xml:space="preserve">
<source>Paste</source>
<target>Liitä</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve"> <trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source> <source>Paste desktop address</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3713,10 +3636,16 @@ This is your link for group %@!</source>
<target>Liitä kuva</target> <target>Liitä kuva</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve"> <trans-unit id="Paste received link" xml:space="preserve">
<source>Paste the link you received</source> <source>Paste received link</source>
<target>Liitä vastaanotettu linkki</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Liitä saamasi linkki, jonka avulla voit muodostaa yhteyden kontaktiisi.</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source> <source>People can connect to you only via the links you share.</source>
<target>Ihmiset voivat ottaa sinuun yhteyttä vain jakamiesi linkkien kautta.</target> <target>Ihmiset voivat ottaa sinuun yhteyttä vain jakamiesi linkkien kautta.</target>
@@ -3752,11 +3681,6 @@ This is your link for group %@!</source>
<target>Tarkista omasi ja kontaktin asetukset.</target> <target>Tarkista omasi ja kontaktin asetukset.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Please contact developers.&#10;Error: %@" xml:space="preserve">
<source>Please contact developers.
Error: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please contact group admin." xml:space="preserve"> <trans-unit id="Please contact group admin." xml:space="preserve">
<source>Please contact group admin.</source> <source>Please contact group admin.</source>
<target>Ota yhteyttä ryhmän ylläpitäjään.</target> <target>Ota yhteyttä ryhmän ylläpitäjään.</target>
@@ -3960,10 +3884,6 @@ Error: %@</source>
<target>Lue lisää [Käyttöoppaasta](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <target>Lue lisää [Käyttöoppaasta](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source>
<target>Lue lisää [Käyttöoppaasta](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> <target>Lue lisää [Käyttöoppaasta](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target>
@@ -4172,10 +4092,6 @@ Error: %@</source>
<target>Virhe tietokannan palauttamisessa</target> <target>Virhe tietokannan palauttamisessa</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Retry" xml:space="preserve">
<source>Retry</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reveal" xml:space="preserve"> <trans-unit id="Reveal" xml:space="preserve">
<source>Reveal</source> <source>Reveal</source>
<target>Paljasta</target> <target>Paljasta</target>
@@ -4330,10 +4246,6 @@ Error: %@</source>
<target>Haku</target> <target>Haku</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve"> <trans-unit id="Secure queue" xml:space="preserve">
<source>Secure queue</source> <source>Secure queue</source>
<target>Turvallinen jono</target> <target>Turvallinen jono</target>
@@ -4607,8 +4519,9 @@ Error: %@</source>
<target>Jaa linkki</target> <target>Jaa linkki</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve"> <trans-unit id="Share one-time invitation link" xml:space="preserve">
<source>Share this 1-time invite link</source> <source>Share one-time invitation link</source>
<target>Jaa kertakutsulinkki</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve"> <trans-unit id="Share with contacts" xml:space="preserve">
@@ -4730,15 +4643,16 @@ Error: %@</source>
<target>Joku</target> <target>Joku</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="Start a new chat" xml:space="preserve">
<source>Start a new chat</source>
<target>Aloita uusi keskustelu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start chat" xml:space="preserve"> <trans-unit id="Start chat" xml:space="preserve">
<source>Start chat</source> <source>Start chat</source>
<target>Aloita keskustelu</target> <target>Aloita keskustelu</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Start chat?" xml:space="preserve">
<source>Start chat?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start migration" xml:space="preserve"> <trans-unit id="Start migration" xml:space="preserve">
<source>Start migration</source> <source>Start migration</source>
<target>Aloita siirto</target> <target>Aloita siirto</target>
@@ -4863,14 +4777,6 @@ Error: %@</source>
<target>Napauta liittyäksesi incognito-tilassa</target> <target>Napauta liittyäksesi incognito-tilassa</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Tap to paste link" xml:space="preserve">
<source>Tap to paste link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to scan" xml:space="preserve">
<source>Tap to scan</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve"> <trans-unit id="Tap to start a new chat" xml:space="preserve">
<source>Tap to start a new chat</source> <source>Tap to start a new chat</source>
<target>Aloita uusi keskustelu napauttamalla</target> <target>Aloita uusi keskustelu napauttamalla</target>
@@ -4933,10 +4839,6 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.</t
<target>Tietokannan tunnuslauseen muuttamista ei suoritettu loppuun.</target> <target>Tietokannan tunnuslauseen muuttamista ei suoritettu loppuun.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source> <source>The connection you accepted will be cancelled!</source>
<target>Hyväksymäsi yhteys peruuntuu!</target> <target>Hyväksymäsi yhteys peruuntuu!</target>
@@ -5002,10 +4904,6 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.</t
<target>Palvelimet nykyisen keskusteluprofiilisi uusille yhteyksille **%@**.</target> <target>Palvelimet nykyisen keskusteluprofiilisi uusille yhteyksille **%@**.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve">
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve"> <trans-unit id="Theme" xml:space="preserve">
<source>Theme</source> <source>Theme</source>
<target>Teema</target> <target>Teema</target>
@@ -5083,10 +4981,6 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.</t
<target>Kontaktisi voi muodostaa yhteyden skannaamalla QR-koodin tai käyttämällä sovelluksessa olevaa linkkiä.</target> <target>Kontaktisi voi muodostaa yhteyden skannaamalla QR-koodin tai käyttämällä sovelluksessa olevaa linkkiä.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve"> <trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source> <source>To make a new connection</source>
<target>Uuden yhteyden luominen</target> <target>Uuden yhteyden luominen</target>
@@ -5153,6 +5047,11 @@ Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus ote
<target>Sammuta</target> <target>Sammuta</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Turn off notifications?" xml:space="preserve">
<source>Turn off notifications?</source>
<target>Kytke ilmoitukset pois päältä?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn on" xml:space="preserve"> <trans-unit id="Turn on" xml:space="preserve">
<source>Turn on</source> <source>Turn on</source>
<target>Kytke päälle</target> <target>Kytke päälle</target>
@@ -5349,10 +5248,6 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
<target>Käytä uutta incognito-profiilia</target> <target>Käytä uutta incognito-profiilia</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use only local notifications?" xml:space="preserve">
<source>Use only local notifications?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve"> <trans-unit id="Use server" xml:space="preserve">
<source>Use server</source> <source>Use server</source>
<target>Käytä palvelinta</target> <target>Käytä palvelinta</target>
@@ -5400,10 +5295,6 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
<target>Selaimella</target> <target>Selaimella</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve"> <trans-unit id="Video call" xml:space="preserve">
<source>Video call</source> <source>Video call</source>
<target>Videopuhelu</target> <target>Videopuhelu</target>
@@ -5454,10 +5345,6 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
<target>Ääniviesti…</target> <target>Ääniviesti…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Waiting for desktop..." xml:space="preserve">
<source>Waiting for desktop...</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Waiting for file" xml:space="preserve"> <trans-unit id="Waiting for file" xml:space="preserve">
<source>Waiting for file</source> <source>Waiting for file</source>
<target>Odottaa tiedostoa</target> <target>Odottaa tiedostoa</target>
@@ -5602,6 +5489,11 @@ Repeat join request?</source>
<target>Voit vastaanottaa puheluita lukitusnäytöltä ilman laitteen ja sovelluksen todennusta.</target> <target>Voit vastaanottaa puheluita lukitusnäytöltä ilman laitteen ja sovelluksen todennusta.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve">
<source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source>
<target>Voit myös muodostaa yhteyden klikkaamalla linkkiä. Jos se avautuu selaimessa, napsauta **Avaa mobiilisovelluksessa**-painiketta.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can create it later" xml:space="preserve"> <trans-unit id="You can create it later" xml:space="preserve">
<source>You can create it later</source> <source>You can create it later</source>
<target>Voit luoda sen myöhemmin</target> <target>Voit luoda sen myöhemmin</target>
@@ -5622,10 +5514,6 @@ Repeat join request?</source>
<target>Voit piilottaa tai mykistää käyttäjäprofiilin pyyhkäisemällä sitä oikealle.</target> <target>Voit piilottaa tai mykistää käyttäjäprofiilin pyyhkäisemällä sitä oikealle.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now send messages to %@" xml:space="preserve"> <trans-unit id="You can now send messages to %@" xml:space="preserve">
<source>You can now send messages to %@</source> <source>You can now send messages to %@</source>
<target>Voit nyt lähettää viestejä %@:lle</target> <target>Voit nyt lähettää viestejä %@:lle</target>
@@ -5666,10 +5554,6 @@ Repeat join request?</source>
<target>Voit käyttää markdownia viestien muotoiluun:</target> <target>Voit käyttää markdownia viestien muotoiluun:</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can view invitation link again in connection details." xml:space="preserve">
<source>You can view invitation link again in connection details.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can't send messages!" xml:space="preserve"> <trans-unit id="You can't send messages!" xml:space="preserve">
<source>You can't send messages!</source> <source>You can't send messages!</source>
<target>Et voi lähettää viestejä!</target> <target>Et voi lähettää viestejä!</target>
@@ -5854,6 +5738,13 @@ Voit peruuttaa tämän yhteyden ja poistaa kontaktin (ja yrittää myöhemmin uu
<target>Kontaktisi voivat sallia viestien täydellisen poistamisen.</target> <target>Kontaktisi voivat sallia viestien täydellisen poistamisen.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your contacts in SimpleX will see it.&#10;You can change it in Settings." xml:space="preserve">
<source>Your contacts in SimpleX will see it.
You can change it in Settings.</source>
<target>Kontaktisi SimpleX:ssä näkevät sen.
Voit muuttaa sitä Asetuksista.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve"> <trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source> <source>Your contacts will remain connected.</source>
<target>Kontaktisi pysyvät yhdistettyinä.</target> <target>Kontaktisi pysyvät yhdistettyinä.</target>
@@ -5984,10 +5875,6 @@ SimpleX-palvelimet eivät näe profiiliasi.</target>
<target>äänipuhelu (ei e2e-salattu)</target> <target>äänipuhelu (ei e2e-salattu)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="author" xml:space="preserve">
<source>author</source>
<note>member role</note>
</trans-unit>
<trans-unit id="bad message ID" xml:space="preserve"> <trans-unit id="bad message ID" xml:space="preserve">
<source>bad message ID</source> <source>bad message ID</source>
<target>virheellinen viestin tunniste</target> <target>virheellinen viestin tunniste</target>
@@ -299,12 +299,10 @@
</trans-unit> </trans-unit>
<trans-unit id="(new)" xml:space="preserve"> <trans-unit id="(new)" xml:space="preserve">
<source>(new)</source> <source>(new)</source>
<target>(nouveau)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="(this device v%@)" xml:space="preserve"> <trans-unit id="(this device v%@)" xml:space="preserve">
<source>(this device v%@)</source> <source>(this device v%@)</source>
<target>(cet appareil v%@)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id=")" xml:space="preserve"> <trans-unit id=")" xml:space="preserve">
@@ -312,17 +310,14 @@
<target>)</target> <target>)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve">
<source>**Add contact**: to create a new invitation link, or connect via a link you received.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target>**Ajouter un nouveau contact** : pour créer un lien ou code QR unique pour votre contact.</target> <target>**Ajouter un nouveau contact** : pour créer un lien ou code QR unique pour votre contact.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Create group**: to create a new group." xml:space="preserve"> <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<source>**Create group**: to create a new group.</source> <source>**Create link / QR code** for your contact to use.</source>
<target>**Créer un lien / code QR** que votre contact pourra utiliser.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -335,6 +330,11 @@
<target>**Confidentiel** : ne pas utiliser le serveur de notifications SimpleX, vérification de nouveaux messages periodiquement en arrière plan (dépend de l'utilisation de l'app).</target> <target>**Confidentiel** : ne pas utiliser le serveur de notifications SimpleX, vérification de nouveaux messages periodiquement en arrière plan (dépend de l'utilisation de l'app).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve">
<source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source>
<target>**Collez le lien reçu** ou ouvrez-le dans votre navigateur et appuyez sur **Open in mobile app**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve">
<source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source>
<target>**Veuillez noter** : vous NE pourrez PAS récupérer ou modifier votre phrase secrète si vous la perdez.</target> <target>**Veuillez noter** : vous NE pourrez PAS récupérer ou modifier votre phrase secrète si vous la perdez.</target>
@@ -345,6 +345,11 @@
<target>**Recommandé** : le token de l'appareil et les notifications sont envoyés au serveur de notifications SimpleX, mais pas le contenu du message, sa taille ou son auteur.</target> <target>**Recommandé** : le token de l'appareil et les notifications sont envoyés au serveur de notifications SimpleX, mais pas le contenu du message, sa taille ou son auteur.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve">
<source>**Scan QR code**: to connect to your contact in person or via video call.</source>
<target>**Scanner le code QR** : pour vous connecter à votre contact en personne ou par appel vidéo.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target>**Avertissement** : les notifications push instantanées nécessitent une phrase secrète enregistrée dans la keychain.</target> <target>**Avertissement** : les notifications push instantanées nécessitent une phrase secrète enregistrée dans la keychain.</target>
@@ -388,15 +393,6 @@
- et bien d'autres choses encore !</target> - et bien d'autres choses encore !</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="- optionally notify deleted contacts.&#10;- profile names with spaces.&#10;- and more!" xml:space="preserve">
<source>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</source>
<target>- option pour notifier les contacts supprimés.
- noms de profil avec espaces.
- et plus encore !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve"> <trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve">
<source>- voice messages up to 5 minutes. <source>- voice messages up to 5 minutes.
- custom time to disappear. - custom time to disappear.
@@ -446,6 +442,11 @@
<target>1 semaine</target> <target>1 semaine</target>
<note>time interval</note> <note>time interval</note>
</trans-unit> </trans-unit>
<trans-unit id="1-time link" xml:space="preserve">
<source>1-time link</source>
<target>Lien à usage unique</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="5 minutes" xml:space="preserve"> <trans-unit id="5 minutes" xml:space="preserve">
<source>5 minutes</source> <source>5 minutes</source>
<target>5 minutes</target> <target>5 minutes</target>
@@ -561,10 +562,6 @@
<target>Ajoutez une adresse à votre profil, afin que vos contacts puissent la partager avec d'autres personnes. La mise à jour du profil sera envoyée à vos contacts.</target> <target>Ajoutez une adresse à votre profil, afin que vos contacts puissent la partager avec d'autres personnes. La mise à jour du profil sera envoyée à vos contacts.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add contact" xml:space="preserve">
<source>Add contact</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve"> <trans-unit id="Add preset servers" xml:space="preserve">
<source>Add preset servers</source> <source>Add preset servers</source>
<target>Ajouter des serveurs prédéfinis</target> <target>Ajouter des serveurs prédéfinis</target>
@@ -882,7 +879,6 @@
</trans-unit> </trans-unit>
<trans-unit id="Bad desktop address" xml:space="preserve"> <trans-unit id="Bad desktop address" xml:space="preserve">
<source>Bad desktop address</source> <source>Bad desktop address</source>
<target>Mauvaise adresse de bureau</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Bad message ID" xml:space="preserve"> <trans-unit id="Bad message ID" xml:space="preserve">
@@ -895,11 +891,6 @@
<target>Mauvais hash de message</target> <target>Mauvais hash de message</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
<source>Better groups</source>
<target>Des groupes plus performants</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better messages" xml:space="preserve"> <trans-unit id="Better messages" xml:space="preserve">
<source>Better messages</source> <source>Better messages</source>
<target>Meilleurs messages</target> <target>Meilleurs messages</target>
@@ -910,11 +901,6 @@
<target>Bloquer</target> <target>Bloquer</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
<source>Block group members</source>
<target>Bloquer des membres d'un groupe</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve"> <trans-unit id="Block member" xml:space="preserve">
<source>Block member</source> <source>Block member</source>
<target>Bloquer ce membre</target> <target>Bloquer ce membre</target>
@@ -970,10 +956,6 @@
<target>Appels</target> <target>Appels</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Camera not available" xml:space="preserve">
<source>Camera not available</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Can't delete user profile!" xml:space="preserve"> <trans-unit id="Can't delete user profile!" xml:space="preserve">
<source>Can't delete user profile!</source> <source>Can't delete user profile!</source>
<target>Impossible de supprimer le profil d'utilisateur !</target> <target>Impossible de supprimer le profil d'utilisateur !</target>
@@ -1090,10 +1072,6 @@
<target>Le chat est arrêté</target> <target>Le chat est arrêté</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve">
<source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve"> <trans-unit id="Chat preferences" xml:space="preserve">
<source>Chat preferences</source> <source>Chat preferences</source>
<target>Préférences de chat</target> <target>Préférences de chat</target>
@@ -1194,11 +1172,6 @@
<target>Se connecter</target> <target>Se connecter</target>
<note>server test step</note> <note>server test step</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect automatically" xml:space="preserve">
<source>Connect automatically</source>
<target>Connexion automatique</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve"> <trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source> <source>Connect incognito</source>
<target>Se connecter incognito</target> <target>Se connecter incognito</target>
@@ -1206,7 +1179,6 @@
</trans-unit> </trans-unit>
<trans-unit id="Connect to desktop" xml:space="preserve"> <trans-unit id="Connect to desktop" xml:space="preserve">
<source>Connect to desktop</source> <source>Connect to desktop</source>
<target>Se connecter au bureau</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve"> <trans-unit id="Connect to yourself?" xml:space="preserve">
@@ -1238,6 +1210,11 @@ Il s'agit de votre propre lien unique !</target>
<target>Se connecter via un lien</target> <target>Se connecter via un lien</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link / QR code" xml:space="preserve">
<source>Connect via link / QR code</source>
<target>Se connecter via un lien / code QR</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link" xml:space="preserve"> <trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source> <source>Connect via one-time link</source>
<target>Se connecter via un lien unique</target> <target>Se connecter via un lien unique</target>
@@ -1250,12 +1227,10 @@ Il s'agit de votre propre lien unique !</target>
</trans-unit> </trans-unit>
<trans-unit id="Connected desktop" xml:space="preserve"> <trans-unit id="Connected desktop" xml:space="preserve">
<source>Connected desktop</source> <source>Connected desktop</source>
<target>Bureau connecté</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connected to desktop" xml:space="preserve"> <trans-unit id="Connected to desktop" xml:space="preserve">
<source>Connected to desktop</source> <source>Connected to desktop</source>
<target>Connecté au bureau</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve"> <trans-unit id="Connecting server…" xml:space="preserve">
@@ -1270,7 +1245,6 @@ Il s'agit de votre propre lien unique !</target>
</trans-unit> </trans-unit>
<trans-unit id="Connecting to desktop" xml:space="preserve"> <trans-unit id="Connecting to desktop" xml:space="preserve">
<source>Connecting to desktop</source> <source>Connecting to desktop</source>
<target>Connexion au bureau</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connection" xml:space="preserve"> <trans-unit id="Connection" xml:space="preserve">
@@ -1295,7 +1269,6 @@ Il s'agit de votre propre lien unique !</target>
</trans-unit> </trans-unit>
<trans-unit id="Connection terminated" xml:space="preserve"> <trans-unit id="Connection terminated" xml:space="preserve">
<source>Connection terminated</source> <source>Connection terminated</source>
<target>Connexion terminée</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connection timeout" xml:space="preserve"> <trans-unit id="Connection timeout" xml:space="preserve">
@@ -1378,11 +1351,6 @@ Il s'agit de votre propre lien unique !</target>
<target>Créer une adresse SimpleX</target> <target>Créer une adresse SimpleX</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create a group using a random profile." xml:space="preserve">
<source>Create a group using a random profile.</source>
<target>Création de groupes via un profil aléatoire.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source> <source>Create an address to let people connect with you.</source>
<target>Créez une adresse pour permettre aux gens de vous contacter.</target> <target>Créez une adresse pour permettre aux gens de vous contacter.</target>
@@ -1413,6 +1381,11 @@ Il s'agit de votre propre lien unique !</target>
<target>Créer un nouveau profil sur [l'application de bureau](https://simplex.chat/downloads/). 💻</target> <target>Créer un nouveau profil sur [l'application de bureau](https://simplex.chat/downloads/). 💻</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create one-time invitation link" xml:space="preserve">
<source>Create one-time invitation link</source>
<target>Créer un lien d'invitation unique</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<target>Créer le profil</target> <target>Créer le profil</target>
@@ -1438,10 +1411,6 @@ Il s'agit de votre propre lien unique !</target>
<target>Créé le %@</target> <target>Créé le %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve"> <trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source> <source>Current Passcode</source>
<target>Code d'accès actuel</target> <target>Code d'accès actuel</target>
@@ -1794,17 +1763,14 @@ Cette opération ne peut être annulée !</target>
</trans-unit> </trans-unit>
<trans-unit id="Desktop address" xml:space="preserve"> <trans-unit id="Desktop address" xml:space="preserve">
<source>Desktop address</source> <source>Desktop address</source>
<target>Adresse de bureau</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve"> <trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve">
<source>Desktop app version %@ is not compatible with this app.</source> <source>Desktop app version %@ is not compatible with this app.</source>
<target>La version de l'application de bureau %@ n'est pas compatible avec cette application.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Desktop devices" xml:space="preserve"> <trans-unit id="Desktop devices" xml:space="preserve">
<source>Desktop devices</source> <source>Desktop devices</source>
<target>Appareils de bureau</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Develop" xml:space="preserve"> <trans-unit id="Develop" xml:space="preserve">
@@ -1899,7 +1865,6 @@ Cette opération ne peut être annulée !</target>
</trans-unit> </trans-unit>
<trans-unit id="Disconnect desktop?" xml:space="preserve"> <trans-unit id="Disconnect desktop?" xml:space="preserve">
<source>Disconnect desktop?</source> <source>Disconnect desktop?</source>
<target>Déconnecter le bureau ?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover and join groups" xml:space="preserve"> <trans-unit id="Discover and join groups" xml:space="preserve">
@@ -1907,9 +1872,8 @@ Cette opération ne peut être annulée !</target>
<target>Découvrir et rejoindre des groupes</target> <target>Découvrir et rejoindre des groupes</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve"> <trans-unit id="Discover on network" xml:space="preserve">
<source>Discover via local network</source> <source>Discover on network</source>
<target>Rechercher sur le réseau</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -1992,10 +1956,6 @@ Cette opération ne peut être annulée !</target>
<target>Activer la suppression automatique des messages ?</target> <target>Activer la suppression automatique des messages ?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enable camera access" xml:space="preserve">
<source>Enable camera access</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve"> <trans-unit id="Enable for all" xml:space="preserve">
<source>Enable for all</source> <source>Enable for all</source>
<target>Activer pour tous</target> <target>Activer pour tous</target>
@@ -2061,10 +2021,6 @@ Cette opération ne peut être annulée !</target>
<target>Message chiffrée ou autre événement</target> <target>Message chiffrée ou autre événement</target>
<note>notification</note> <note>notification</note>
</trans-unit> </trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve">
<source>Encrypted message: app is stopped</source>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve"> <trans-unit id="Encrypted message: database error" xml:space="preserve">
<source>Encrypted message: database error</source> <source>Encrypted message: database error</source>
<target>Message chiffrée: erreur de base de données</target> <target>Message chiffrée: erreur de base de données</target>
@@ -2092,12 +2048,10 @@ Cette opération ne peut être annulée !</target>
</trans-unit> </trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve"> <trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source> <source>Encryption re-negotiation error</source>
<target>Erreur lors de la renégociation du chiffrement</target>
<note>message decrypt error item</note> <note>message decrypt error item</note>
</trans-unit> </trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve"> <trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source> <source>Encryption re-negotiation failed.</source>
<target>La renégociation du chiffrement a échoué.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve"> <trans-unit id="Enter Passcode" xml:space="preserve">
@@ -2132,7 +2086,6 @@ Cette opération ne peut être annulée !</target>
</trans-unit> </trans-unit>
<trans-unit id="Enter this device name…" xml:space="preserve"> <trans-unit id="Enter this device name…" xml:space="preserve">
<source>Enter this device name…</source> <source>Enter this device name…</source>
<target>Entrez le nom de l'appareil…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enter welcome message…" xml:space="preserve"> <trans-unit id="Enter welcome message…" xml:space="preserve">
@@ -2295,10 +2248,6 @@ Cette opération ne peut être annulée !</target>
<target>Erreur lors du chargement des serveurs %@</target> <target>Erreur lors du chargement des serveurs %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error receiving file" xml:space="preserve"> <trans-unit id="Error receiving file" xml:space="preserve">
<source>Error receiving file</source> <source>Error receiving file</source>
<target>Erreur lors de la réception du fichier</target> <target>Erreur lors de la réception du fichier</target>
@@ -2339,10 +2288,6 @@ Cette opération ne peut être annulée !</target>
<target>Erreur d'enregistrement du mot de passe de l'utilisateur</target> <target>Erreur d'enregistrement du mot de passe de l'utilisateur</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error scanning code: %@" xml:space="preserve">
<source>Error scanning code: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve"> <trans-unit id="Error sending email" xml:space="preserve">
<source>Error sending email</source> <source>Error sending email</source>
<target>Erreur lors de l'envoi de l'e-mail</target> <target>Erreur lors de l'envoi de l'e-mail</target>
@@ -2468,11 +2413,6 @@ Cette opération ne peut être annulée !</target>
<target>Rapide et ne nécessitant pas d'attendre que l'expéditeur soit en ligne !</target> <target>Rapide et ne nécessitant pas d'attendre que l'expéditeur soit en ligne !</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<target>Connexion plus rapide et messages plus fiables.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve"> <trans-unit id="Favorite" xml:space="preserve">
<source>Favorite</source> <source>Favorite</source>
<target>Favoris</target> <target>Favoris</target>
@@ -2568,11 +2508,6 @@ Cette opération ne peut être annulée !</target>
<target>Pour la console</target> <target>Pour la console</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Found desktop" xml:space="preserve">
<source>Found desktop</source>
<target>Bureau trouvé</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="French interface" xml:space="preserve"> <trans-unit id="French interface" xml:space="preserve">
<source>French interface</source> <source>French interface</source>
<target>Interface en français</target> <target>Interface en français</target>
@@ -2818,6 +2753,11 @@ Cette opération ne peut être annulée !</target>
<target>Si vous ne pouvez pas vous rencontrer en personne, montrez le code QR lors d'un appel vidéo ou partagez le lien.</target> <target>Si vous ne pouvez pas vous rencontrer en personne, montrez le code QR lors d'un appel vidéo ou partagez le lien.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve">
<source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source>
<target>Si vous ne pouvez pas voir la personne, vous pouvez **scanner le code QR dans un appel vidéo**, ou votre contact peut vous partager un lien d'invitation.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve">
<source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source>
<target>Si vous saisissez ce code à l'ouverture de l'application, toutes les données de l'application seront irréversiblement supprimées !</target> <target>Si vous saisissez ce code à l'ouverture de l'application, toutes les données de l'application seront irréversiblement supprimées !</target>
@@ -2893,11 +2833,6 @@ Cette opération ne peut être annulée !</target>
<target>Incognito</target> <target>Incognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<target>Groupes incognito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve"> <trans-unit id="Incognito mode" xml:space="preserve">
<source>Incognito mode</source> <source>Incognito mode</source>
<target>Mode Incognito</target> <target>Mode Incognito</target>
@@ -2930,7 +2865,6 @@ Cette opération ne peut être annulée !</target>
</trans-unit> </trans-unit>
<trans-unit id="Incompatible version" xml:space="preserve"> <trans-unit id="Incompatible version" xml:space="preserve">
<source>Incompatible version</source> <source>Incompatible version</source>
<target>Version incompatible</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incorrect passcode" xml:space="preserve"> <trans-unit id="Incorrect passcode" xml:space="preserve">
@@ -2975,28 +2909,16 @@ Cette opération ne peut être annulée !</target>
<target>Interface</target> <target>Interface</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid QR code" xml:space="preserve">
<source>Invalid QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve"> <trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source> <source>Invalid connection link</source>
<target>Lien de connection invalide</target> <target>Lien de connection invalide</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
<source>Invalid link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve"> <trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source> <source>Invalid name!</source>
<target>Nom invalide !</target> <target>Nom invalide !</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid response" xml:space="preserve">
<source>Invalid response</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve"> <trans-unit id="Invalid server address!" xml:space="preserve">
<source>Invalid server address!</source> <source>Invalid server address!</source>
<target>Adresse de serveur invalide !</target> <target>Adresse de serveur invalide !</target>
@@ -3115,17 +3037,8 @@ Voici votre lien pour le groupe %@ !</target>
<target>Entrain de rejoindre le groupe</target> <target>Entrain de rejoindre le groupe</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep" xml:space="preserve">
<source>Keep</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
<source>Keep the app open to use it from desktop</source> <source>Keep the app open to use it from desktop</source>
<target>Garder l'application ouverte pour l'utiliser depuis le bureau</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep unused invitation?" xml:space="preserve">
<source>Keep unused invitation?</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve"> <trans-unit id="Keep your connections" xml:space="preserve">
@@ -3188,19 +3101,12 @@ Voici votre lien pour le groupe %@ !</target>
<target>Limitations</target> <target>Limitations</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<target>Liez vos applications mobiles et de bureau ! 🔗</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve"> <trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source> <source>Linked desktop options</source>
<target>Options de bureau lié</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Linked desktops" xml:space="preserve"> <trans-unit id="Linked desktops" xml:space="preserve">
<source>Linked desktops</source> <source>Linked desktops</source>
<target>Bureaux liés</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Live message!" xml:space="preserve"> <trans-unit id="Live message!" xml:space="preserve">
@@ -3213,11 +3119,6 @@ Voici votre lien pour le groupe %@ !</target>
<target>Messages dynamiques</target> <target>Messages dynamiques</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Local" xml:space="preserve">
<source>Local</source>
<target>Local</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Local name" xml:space="preserve"> <trans-unit id="Local name" xml:space="preserve">
<source>Local name</source> <source>Local name</source>
<target>Nom local</target> <target>Nom local</target>
@@ -3458,10 +3359,6 @@ Voici votre lien pour le groupe %@ !</target>
<target>Nouveau code d'accès</target> <target>Nouveau code d'accès</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="New chat" xml:space="preserve">
<source>New chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve"> <trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source> <source>New contact request</source>
<target>Nouvelle demande de contact</target> <target>Nouvelle demande de contact</target>
@@ -3562,11 +3459,6 @@ Voici votre lien pour le groupe %@ !</target>
<target>Aucun fichier reçu ou envoyé</target> <target>Aucun fichier reçu ou envoyé</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Not compatible!" xml:space="preserve">
<source>Not compatible!</source>
<target>Non compatible !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve"> <trans-unit id="Notifications" xml:space="preserve">
<source>Notifications</source> <source>Notifications</source>
<target>Notifications</target> <target>Notifications</target>
@@ -3586,15 +3478,16 @@ Voici votre lien pour le groupe %@ !</target>
- désactiver des membres (rôle "observateur")</target> - désactiver des membres (rôle "observateur")</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="OK" xml:space="preserve">
<source>OK</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Off" xml:space="preserve"> <trans-unit id="Off" xml:space="preserve">
<source>Off</source> <source>Off</source>
<target>Off</target> <target>Off</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Off (Local)" xml:space="preserve">
<source>Off (Local)</source>
<target>Off (Local)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ok" xml:space="preserve"> <trans-unit id="Ok" xml:space="preserve">
<source>Ok</source> <source>Ok</source>
<target>Ok</target> <target>Ok</target>
@@ -3735,16 +3628,9 @@ Voici votre lien pour le groupe %@ !</target>
<target>Protocole et code open-source n'importe qui peut heberger un serveur.</target> <target>Protocole et code open-source n'importe qui peut heberger un serveur.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Opening app…" xml:space="preserve"> <trans-unit id="Opening database…" xml:space="preserve">
<source>Opening app…</source> <source>Opening database…</source>
<note>No comment provided by engineer.</note> <target>Ouverture de la base de données…</target>
</trans-unit>
<trans-unit id="Or scan QR code" xml:space="preserve">
<source>Or scan QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
<source>Or show this code</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="PING count" xml:space="preserve"> <trans-unit id="PING count" xml:space="preserve">
@@ -3787,9 +3673,13 @@ Voici votre lien pour le groupe %@ !</target>
<target>Mot de passe à entrer</target> <target>Mot de passe à entrer</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste" xml:space="preserve">
<source>Paste</source>
<target>Coller</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve"> <trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source> <source>Paste desktop address</source>
<target>Coller l'adresse du bureau</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste image" xml:space="preserve"> <trans-unit id="Paste image" xml:space="preserve">
@@ -3797,10 +3687,16 @@ Voici votre lien pour le groupe %@ !</target>
<target>Coller l'image</target> <target>Coller l'image</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve"> <trans-unit id="Paste received link" xml:space="preserve">
<source>Paste the link you received</source> <source>Paste received link</source>
<target>Coller le lien reçu</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Collez le lien que vous avez reçu dans le cadre ci-dessous pour vous connecter avec votre contact.</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source> <source>People can connect to you only via the links you share.</source>
<target>On ne peut se connecter à vous quavec les liens que vous partagez.</target> <target>On ne peut se connecter à vous quavec les liens que vous partagez.</target>
@@ -3836,11 +3732,6 @@ Voici votre lien pour le groupe %@ !</target>
<target>Veuillez vérifier vos préférences ainsi que celles de votre contact.</target> <target>Veuillez vérifier vos préférences ainsi que celles de votre contact.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Please contact developers.&#10;Error: %@" xml:space="preserve">
<source>Please contact developers.
Error: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please contact group admin." xml:space="preserve"> <trans-unit id="Please contact group admin." xml:space="preserve">
<source>Please contact group admin.</source> <source>Please contact group admin.</source>
<target>Veuillez contacter l'administrateur du groupe.</target> <target>Veuillez contacter l'administrateur du groupe.</target>
@@ -4046,10 +3937,6 @@ Error: %@</source>
<target>Pour en savoir plus, consultez le [Guide de l'utilisateur](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <target>Pour en savoir plus, consultez le [Guide de l'utilisateur](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source>
<target>Pour en savoir plus, consultez le [Guide de l'utilisateur](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> <target>Pour en savoir plus, consultez le [Guide de l'utilisateur](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target>
@@ -4260,10 +4147,6 @@ Error: %@</source>
<target>Erreur de restauration de la base de données</target> <target>Erreur de restauration de la base de données</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Retry" xml:space="preserve">
<source>Retry</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reveal" xml:space="preserve"> <trans-unit id="Reveal" xml:space="preserve">
<source>Reveal</source> <source>Reveal</source>
<target>Révéler</target> <target>Révéler</target>
@@ -4396,7 +4279,6 @@ Error: %@</source>
</trans-unit> </trans-unit>
<trans-unit id="Scan QR code from desktop" xml:space="preserve"> <trans-unit id="Scan QR code from desktop" xml:space="preserve">
<source>Scan QR code from desktop</source> <source>Scan QR code from desktop</source>
<target>Scanner le code QR du bureau</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Scan code" xml:space="preserve"> <trans-unit id="Scan code" xml:space="preserve">
@@ -4419,10 +4301,6 @@ Error: %@</source>
<target>Recherche</target> <target>Recherche</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve"> <trans-unit id="Secure queue" xml:space="preserve">
<source>Secure queue</source> <source>Secure queue</source>
<target>File d'attente sécurisée</target> <target>File d'attente sécurisée</target>
@@ -4625,7 +4503,6 @@ Error: %@</source>
</trans-unit> </trans-unit>
<trans-unit id="Session code" xml:space="preserve"> <trans-unit id="Session code" xml:space="preserve">
<source>Session code</source> <source>Session code</source>
<target>Code de session</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Set 1 day" xml:space="preserve"> <trans-unit id="Set 1 day" xml:space="preserve">
@@ -4698,8 +4575,9 @@ Error: %@</source>
<target>Partager le lien</target> <target>Partager le lien</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve"> <trans-unit id="Share one-time invitation link" xml:space="preserve">
<source>Share this 1-time invite link</source> <source>Share one-time invitation link</source>
<target>Partager un lien d'invitation unique</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve"> <trans-unit id="Share with contacts" xml:space="preserve">
@@ -4822,15 +4700,16 @@ Error: %@</source>
<target>Quelqu'un</target> <target>Quelqu'un</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="Start a new chat" xml:space="preserve">
<source>Start a new chat</source>
<target>Commencer une nouvelle conversation</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start chat" xml:space="preserve"> <trans-unit id="Start chat" xml:space="preserve">
<source>Start chat</source> <source>Start chat</source>
<target>Démarrer le chat</target> <target>Démarrer le chat</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Start chat?" xml:space="preserve">
<source>Start chat?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start migration" xml:space="preserve"> <trans-unit id="Start migration" xml:space="preserve">
<source>Start migration</source> <source>Start migration</source>
<target>Démarrer la migration</target> <target>Démarrer la migration</target>
@@ -4956,14 +4835,6 @@ Error: %@</source>
<target>Appuyez pour rejoindre incognito</target> <target>Appuyez pour rejoindre incognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Tap to paste link" xml:space="preserve">
<source>Tap to paste link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to scan" xml:space="preserve">
<source>Tap to scan</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve"> <trans-unit id="Tap to start a new chat" xml:space="preserve">
<source>Tap to start a new chat</source> <source>Tap to start a new chat</source>
<target>Appuyez ici pour démarrer une nouvelle discussion</target> <target>Appuyez ici pour démarrer une nouvelle discussion</target>
@@ -5026,10 +4897,6 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
<target>La tentative de modification de la phrase secrète de la base de données n'a pas abouti.</target> <target>La tentative de modification de la phrase secrète de la base de données n'a pas abouti.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source> <source>The connection you accepted will be cancelled!</source>
<target>La connexion que vous avez acceptée sera annulée !</target> <target>La connexion que vous avez acceptée sera annulée !</target>
@@ -5095,10 +4962,6 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
<target>Les serveurs pour les nouvelles connexions de votre profil de chat actuel **%@**.</target> <target>Les serveurs pour les nouvelles connexions de votre profil de chat actuel **%@**.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve">
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve"> <trans-unit id="Theme" xml:space="preserve">
<source>Theme</source> <source>Theme</source>
<target>Thème</target> <target>Thème</target>
@@ -5141,7 +5004,6 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
</trans-unit> </trans-unit>
<trans-unit id="This device name" xml:space="preserve"> <trans-unit id="This device name" xml:space="preserve">
<source>This device name</source> <source>This device name</source>
<target>Ce nom d'appareil</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
@@ -5179,11 +5041,6 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
<target>Pour se connecter, votre contact peut scanner le code QR ou utiliser le lien dans l'application.</target> <target>Pour se connecter, votre contact peut scanner le code QR ou utiliser le lien dans l'application.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<target>Pour cacher les messages indésirables.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve"> <trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source> <source>To make a new connection</source>
<target>Pour établir une nouvelle connexion</target> <target>Pour établir une nouvelle connexion</target>
@@ -5251,6 +5108,11 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s
<target>Désactiver</target> <target>Désactiver</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Turn off notifications?" xml:space="preserve">
<source>Turn off notifications?</source>
<target>Désactiver les notifications?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn on" xml:space="preserve"> <trans-unit id="Turn on" xml:space="preserve">
<source>Turn on</source> <source>Turn on</source>
<target>Activer</target> <target>Activer</target>
@@ -5340,12 +5202,10 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
</trans-unit> </trans-unit>
<trans-unit id="Unlink" xml:space="preserve"> <trans-unit id="Unlink" xml:space="preserve">
<source>Unlink</source> <source>Unlink</source>
<target>Délier</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Unlink desktop?" xml:space="preserve"> <trans-unit id="Unlink desktop?" xml:space="preserve">
<source>Unlink desktop?</source> <source>Unlink desktop?</source>
<target>Délier le bureau ?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Unlock" xml:space="preserve"> <trans-unit id="Unlock" xml:space="preserve">
@@ -5440,7 +5300,6 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
</trans-unit> </trans-unit>
<trans-unit id="Use from desktop" xml:space="preserve"> <trans-unit id="Use from desktop" xml:space="preserve">
<source>Use from desktop</source> <source>Use from desktop</source>
<target>Utilisation depuis le bureau</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use iOS call interface" xml:space="preserve"> <trans-unit id="Use iOS call interface" xml:space="preserve">
@@ -5453,10 +5312,6 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
<target>Utiliser un nouveau profil incognito</target> <target>Utiliser un nouveau profil incognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use only local notifications?" xml:space="preserve">
<source>Use only local notifications?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve"> <trans-unit id="Use server" xml:space="preserve">
<source>Use server</source> <source>Use server</source>
<target>Utiliser ce serveur</target> <target>Utiliser ce serveur</target>
@@ -5479,12 +5334,10 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
</trans-unit> </trans-unit>
<trans-unit id="Verify code with desktop" xml:space="preserve"> <trans-unit id="Verify code with desktop" xml:space="preserve">
<source>Verify code with desktop</source> <source>Verify code with desktop</source>
<target>Vérifier le code avec le bureau</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify connection" xml:space="preserve"> <trans-unit id="Verify connection" xml:space="preserve">
<source>Verify connection</source> <source>Verify connection</source>
<target>Vérifier la connexion</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify connection security" xml:space="preserve"> <trans-unit id="Verify connection security" xml:space="preserve">
@@ -5494,7 +5347,6 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
</trans-unit> </trans-unit>
<trans-unit id="Verify connections" xml:space="preserve"> <trans-unit id="Verify connections" xml:space="preserve">
<source>Verify connections</source> <source>Verify connections</source>
<target>Vérifier les connexions</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify security code" xml:space="preserve"> <trans-unit id="Verify security code" xml:space="preserve">
@@ -5507,11 +5359,6 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
<target>Via navigateur</target> <target>Via navigateur</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<target>Via un protocole sécurisé de cryptographie post-quantique.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve"> <trans-unit id="Video call" xml:space="preserve">
<source>Video call</source> <source>Video call</source>
<target>Appel vidéo</target> <target>Appel vidéo</target>
@@ -5562,11 +5409,6 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
<target>Message vocal…</target> <target>Message vocal…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Waiting for desktop..." xml:space="preserve">
<source>Waiting for desktop...</source>
<target>En attente du bureau...</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Waiting for file" xml:space="preserve"> <trans-unit id="Waiting for file" xml:space="preserve">
<source>Waiting for file</source> <source>Waiting for file</source>
<target>En attente du fichier</target> <target>En attente du fichier</target>
@@ -5719,6 +5561,11 @@ Répéter la demande d'adhésion ?</target>
<target>Vous pouvez accepter des appels à partir de l'écran de verrouillage, sans authentification de l'appareil ou de l'application.</target> <target>Vous pouvez accepter des appels à partir de l'écran de verrouillage, sans authentification de l'appareil ou de l'application.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve">
<source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source>
<target>Vous pouvez également vous connecter en cliquant sur le lien. S'il s'ouvre dans le navigateur, cliquez sur le bouton **Open in mobile app**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can create it later" xml:space="preserve"> <trans-unit id="You can create it later" xml:space="preserve">
<source>You can create it later</source> <source>You can create it later</source>
<target>Vous pouvez la créer plus tard</target> <target>Vous pouvez la créer plus tard</target>
@@ -5739,10 +5586,6 @@ Répéter la demande d'adhésion ?</target>
<target>Vous pouvez masquer ou mettre en sourdine un profil d'utilisateur - faites-le glisser vers la droite.</target> <target>Vous pouvez masquer ou mettre en sourdine un profil d'utilisateur - faites-le glisser vers la droite.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now send messages to %@" xml:space="preserve"> <trans-unit id="You can now send messages to %@" xml:space="preserve">
<source>You can now send messages to %@</source> <source>You can now send messages to %@</source>
<target>Vous pouvez maintenant envoyer des messages à %@</target> <target>Vous pouvez maintenant envoyer des messages à %@</target>
@@ -5783,10 +5626,6 @@ Répéter la demande d'adhésion ?</target>
<target>Vous pouvez utiliser le format markdown pour mettre en forme les messages :</target> <target>Vous pouvez utiliser le format markdown pour mettre en forme les messages :</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can view invitation link again in connection details." xml:space="preserve">
<source>You can view invitation link again in connection details.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can't send messages!" xml:space="preserve"> <trans-unit id="You can't send messages!" xml:space="preserve">
<source>You can't send messages!</source> <source>You can't send messages!</source>
<target>Vous ne pouvez pas envoyer de messages !</target> <target>Vous ne pouvez pas envoyer de messages !</target>
@@ -5976,6 +5815,13 @@ Vous pouvez annuler la connexion et supprimer le contact (et réessayer plus tar
<target>Vos contacts peuvent autoriser la suppression complète des messages.</target> <target>Vos contacts peuvent autoriser la suppression complète des messages.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your contacts in SimpleX will see it.&#10;You can change it in Settings." xml:space="preserve">
<source>Your contacts in SimpleX will see it.
You can change it in Settings.</source>
<target>Vos contacts dans SimpleX la verront.
Vous pouvez modifier ce choix dans les Paramètres.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve"> <trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source> <source>Your contacts will remain connected.</source>
<target>Vos contacts resteront connectés.</target> <target>Vos contacts resteront connectés.</target>
@@ -6108,11 +5954,6 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
<target>appel audio (sans chiffrement)</target> <target>appel audio (sans chiffrement)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="author" xml:space="preserve">
<source>author</source>
<target>auteur</target>
<note>member role</note>
</trans-unit>
<trans-unit id="bad message ID" xml:space="preserve"> <trans-unit id="bad message ID" xml:space="preserve">
<source>bad message ID</source> <source>bad message ID</source>
<target>ID de message incorrecte</target> <target>ID de message incorrecte</target>
@@ -6592,12 +6433,12 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
</trans-unit> </trans-unit>
<trans-unit id="offered %@" xml:space="preserve"> <trans-unit id="offered %@" xml:space="preserve">
<source>offered %@</source> <source>offered %@</source>
<target>propose %@</target> <target>offert %@</target>
<note>feature offered item</note> <note>feature offered item</note>
</trans-unit> </trans-unit>
<trans-unit id="offered %@: %@" xml:space="preserve"> <trans-unit id="offered %@: %@" xml:space="preserve">
<source>offered %1$@: %2$@</source> <source>offered %1$@: %2$@</source>
<target>propose %1$@: %2$@</target> <target>offert %1$@ : %2$@</target>
<note>feature offered item</note> <note>feature offered item</note>
</trans-unit> </trans-unit>
<trans-unit id="on" xml:space="preserve"> <trans-unit id="on" xml:space="preserve">
@@ -6697,7 +6538,6 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
</trans-unit> </trans-unit>
<trans-unit id="v%@" xml:space="preserve"> <trans-unit id="v%@" xml:space="preserve">
<source>v%@</source> <source>v%@</source>
<target>v%@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="v%@ (%@)" xml:space="preserve"> <trans-unit id="v%@ (%@)" xml:space="preserve">
@@ -6839,7 +6679,6 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
</trans-unit> </trans-unit>
<trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve"> <trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve">
<source>SimpleX uses local network access to allow using user chat profile via desktop app on the same network.</source> <source>SimpleX uses local network access to allow using user chat profile via desktop app on the same network.</source>
<target>SimpleX utilise un accès au réseau local pour permettre l'utilisation du profil de chat de l'utilisateur via l'application de bureau au sein de ce même réseau.</target>
<note>Privacy - Local Network Usage Description</note> <note>Privacy - Local Network Usage Description</note>
</trans-unit> </trans-unit>
<trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve"> <trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve">
@@ -94,7 +94,7 @@
</trans-unit> </trans-unit>
<trans-unit id="%@ and %@ connected" xml:space="preserve"> <trans-unit id="%@ and %@ connected" xml:space="preserve">
<source>%@ and %@ connected</source> <source>%@ and %@ connected</source>
<target>%@ e %@ si sono connessi/e</target> <target>%@ e %@ sono connessi/e</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%@ at %@:" xml:space="preserve"> <trans-unit id="%@ at %@:" xml:space="preserve">
@@ -139,7 +139,7 @@
</trans-unit> </trans-unit>
<trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve"> <trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve">
<source>%@, %@ and %lld other members connected</source> <source>%@, %@ and %lld other members connected</source>
<target>%@, %@ e altri %lld membri si sono connessi</target> <target>%@, %@ e altri %lld membri sono connessi</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%@:" xml:space="preserve"> <trans-unit id="%@:" xml:space="preserve">
@@ -299,12 +299,10 @@
</trans-unit> </trans-unit>
<trans-unit id="(new)" xml:space="preserve"> <trans-unit id="(new)" xml:space="preserve">
<source>(new)</source> <source>(new)</source>
<target>(nuovo)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="(this device v%@)" xml:space="preserve"> <trans-unit id="(this device v%@)" xml:space="preserve">
<source>(this device v%@)</source> <source>(this device v%@)</source>
<target>(questo dispositivo v%@)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id=")" xml:space="preserve"> <trans-unit id=")" xml:space="preserve">
@@ -312,17 +310,14 @@
<target>)</target> <target>)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve">
<source>**Add contact**: to create a new invitation link, or connect via a link you received.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target>**Aggiungi un contatto**: per creare il tuo codice QR o link una tantum per il tuo contatto.</target> <target>**Aggiungi un contatto**: per creare il tuo codice QR o link una tantum per il tuo contatto.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Create group**: to create a new group." xml:space="preserve"> <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<source>**Create group**: to create a new group.</source> <source>**Create link / QR code** for your contact to use.</source>
<target>**Crea link / codice QR** da usare per il tuo contatto.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -335,6 +330,11 @@
<target>**Il più privato**: non usare il server di notifica di SimpleX Chat, controlla i messaggi periodicamente in secondo piano (dipende da quanto spesso usi l'app).</target> <target>**Il più privato**: non usare il server di notifica di SimpleX Chat, controlla i messaggi periodicamente in secondo piano (dipende da quanto spesso usi l'app).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve">
<source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source>
<target>**Incolla il link ricevuto** o aprilo nel browser e tocca **Apri in app mobile**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve">
<source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source>
<target>**Nota bene**: NON potrai recuperare o cambiare la password se la perdi.</target> <target>**Nota bene**: NON potrai recuperare o cambiare la password se la perdi.</target>
@@ -345,6 +345,11 @@
<target>**Consigliato**: vengono inviati il token del dispositivo e le notifiche al server di notifica di SimpleX Chat, ma non il contenuto del messaggio,la sua dimensione o il suo mittente.</target> <target>**Consigliato**: vengono inviati il token del dispositivo e le notifiche al server di notifica di SimpleX Chat, ma non il contenuto del messaggio,la sua dimensione o il suo mittente.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve">
<source>**Scan QR code**: to connect to your contact in person or via video call.</source>
<target>**Scansiona codice QR**: per connetterti al contatto di persona o via videochiamata.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target>**Attenzione**: le notifiche push istantanee richiedono una password salvata nel portachiavi.</target> <target>**Attenzione**: le notifiche push istantanee richiedono una password salvata nel portachiavi.</target>
@@ -388,15 +393,6 @@
- e altro ancora!</target> - e altro ancora!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="- optionally notify deleted contacts.&#10;- profile names with spaces.&#10;- and more!" xml:space="preserve">
<source>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</source>
<target>- avvisa facoltativamente i contatti eliminati.
- nomi del profilo con spazi.
- e molto altro!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve"> <trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve">
<source>- voice messages up to 5 minutes. <source>- voice messages up to 5 minutes.
- custom time to disappear. - custom time to disappear.
@@ -446,6 +442,11 @@
<target>1 settimana</target> <target>1 settimana</target>
<note>time interval</note> <note>time interval</note>
</trans-unit> </trans-unit>
<trans-unit id="1-time link" xml:space="preserve">
<source>1-time link</source>
<target>Link una tantum</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="5 minutes" xml:space="preserve"> <trans-unit id="5 minutes" xml:space="preserve">
<source>5 minutes</source> <source>5 minutes</source>
<target>5 minuti</target> <target>5 minuti</target>
@@ -561,10 +562,6 @@
<target>Aggiungi l'indirizzo al tuo profilo, in modo che i tuoi contatti possano condividerlo con altre persone. L'aggiornamento del profilo verrà inviato ai tuoi contatti.</target> <target>Aggiungi l'indirizzo al tuo profilo, in modo che i tuoi contatti possano condividerlo con altre persone. L'aggiornamento del profilo verrà inviato ai tuoi contatti.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add contact" xml:space="preserve">
<source>Add contact</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve"> <trans-unit id="Add preset servers" xml:space="preserve">
<source>Add preset servers</source> <source>Add preset servers</source>
<target>Aggiungi server preimpostati</target> <target>Aggiungi server preimpostati</target>
@@ -882,7 +879,6 @@
</trans-unit> </trans-unit>
<trans-unit id="Bad desktop address" xml:space="preserve"> <trans-unit id="Bad desktop address" xml:space="preserve">
<source>Bad desktop address</source> <source>Bad desktop address</source>
<target>Indirizzo desktop errato</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Bad message ID" xml:space="preserve"> <trans-unit id="Bad message ID" xml:space="preserve">
@@ -895,11 +891,6 @@
<target>Hash del messaggio errato</target> <target>Hash del messaggio errato</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
<source>Better groups</source>
<target>Gruppi migliorati</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better messages" xml:space="preserve"> <trans-unit id="Better messages" xml:space="preserve">
<source>Better messages</source> <source>Better messages</source>
<target>Messaggi migliorati</target> <target>Messaggi migliorati</target>
@@ -910,11 +901,6 @@
<target>Blocca</target> <target>Blocca</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
<source>Block group members</source>
<target>Blocca i membri dei gruppi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve"> <trans-unit id="Block member" xml:space="preserve">
<source>Block member</source> <source>Block member</source>
<target>Blocca membro</target> <target>Blocca membro</target>
@@ -970,10 +956,6 @@
<target>Chiamate</target> <target>Chiamate</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Camera not available" xml:space="preserve">
<source>Camera not available</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Can't delete user profile!" xml:space="preserve"> <trans-unit id="Can't delete user profile!" xml:space="preserve">
<source>Can't delete user profile!</source> <source>Can't delete user profile!</source>
<target>Impossibile eliminare il profilo utente!</target> <target>Impossibile eliminare il profilo utente!</target>
@@ -1090,10 +1072,6 @@
<target>Chat fermata</target> <target>Chat fermata</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve">
<source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve"> <trans-unit id="Chat preferences" xml:space="preserve">
<source>Chat preferences</source> <source>Chat preferences</source>
<target>Preferenze della chat</target> <target>Preferenze della chat</target>
@@ -1181,7 +1159,7 @@
</trans-unit> </trans-unit>
<trans-unit id="Confirm new passphrase…" xml:space="preserve"> <trans-unit id="Confirm new passphrase…" xml:space="preserve">
<source>Confirm new passphrase…</source> <source>Confirm new passphrase…</source>
<target>Conferma nuova password…</target> <target>Conferma password nuova…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Confirm password" xml:space="preserve"> <trans-unit id="Confirm password" xml:space="preserve">
@@ -1194,11 +1172,6 @@
<target>Connetti</target> <target>Connetti</target>
<note>server test step</note> <note>server test step</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect automatically" xml:space="preserve">
<source>Connect automatically</source>
<target>Connetti automaticamente</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve"> <trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source> <source>Connect incognito</source>
<target>Connetti in incognito</target> <target>Connetti in incognito</target>
@@ -1206,7 +1179,6 @@
</trans-unit> </trans-unit>
<trans-unit id="Connect to desktop" xml:space="preserve"> <trans-unit id="Connect to desktop" xml:space="preserve">
<source>Connect to desktop</source> <source>Connect to desktop</source>
<target>Connetti al desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve"> <trans-unit id="Connect to yourself?" xml:space="preserve">
@@ -1238,6 +1210,11 @@ Questo è il tuo link una tantum!</target>
<target>Connetti via link</target> <target>Connetti via link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link / QR code" xml:space="preserve">
<source>Connect via link / QR code</source>
<target>Connetti via link / codice QR</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link" xml:space="preserve"> <trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source> <source>Connect via one-time link</source>
<target>Connetti via link una tantum</target> <target>Connetti via link una tantum</target>
@@ -1250,12 +1227,10 @@ Questo è il tuo link una tantum!</target>
</trans-unit> </trans-unit>
<trans-unit id="Connected desktop" xml:space="preserve"> <trans-unit id="Connected desktop" xml:space="preserve">
<source>Connected desktop</source> <source>Connected desktop</source>
<target>Desktop connesso</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connected to desktop" xml:space="preserve"> <trans-unit id="Connected to desktop" xml:space="preserve">
<source>Connected to desktop</source> <source>Connected to desktop</source>
<target>Connesso al desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve"> <trans-unit id="Connecting server…" xml:space="preserve">
@@ -1270,7 +1245,6 @@ Questo è il tuo link una tantum!</target>
</trans-unit> </trans-unit>
<trans-unit id="Connecting to desktop" xml:space="preserve"> <trans-unit id="Connecting to desktop" xml:space="preserve">
<source>Connecting to desktop</source> <source>Connecting to desktop</source>
<target>Connessione al desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connection" xml:space="preserve"> <trans-unit id="Connection" xml:space="preserve">
@@ -1295,7 +1269,6 @@ Questo è il tuo link una tantum!</target>
</trans-unit> </trans-unit>
<trans-unit id="Connection terminated" xml:space="preserve"> <trans-unit id="Connection terminated" xml:space="preserve">
<source>Connection terminated</source> <source>Connection terminated</source>
<target>Connessione terminata</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connection timeout" xml:space="preserve"> <trans-unit id="Connection timeout" xml:space="preserve">
@@ -1378,11 +1351,6 @@ Questo è il tuo link una tantum!</target>
<target>Crea indirizzo SimpleX</target> <target>Crea indirizzo SimpleX</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create a group using a random profile." xml:space="preserve">
<source>Create a group using a random profile.</source>
<target>Crea un gruppo usando un profilo casuale.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source> <source>Create an address to let people connect with you.</source>
<target>Crea un indirizzo per consentire alle persone di connettersi con te.</target> <target>Crea un indirizzo per consentire alle persone di connettersi con te.</target>
@@ -1413,6 +1381,11 @@ Questo è il tuo link una tantum!</target>
<target>Crea un nuovo profilo nell'[app desktop](https://simplex.chat/downloads/). 💻</target> <target>Crea un nuovo profilo nell'[app desktop](https://simplex.chat/downloads/). 💻</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create one-time invitation link" xml:space="preserve">
<source>Create one-time invitation link</source>
<target>Crea link di invito una tantum</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<target>Crea profilo</target> <target>Crea profilo</target>
@@ -1438,10 +1411,6 @@ Questo è il tuo link una tantum!</target>
<target>Creato il %@</target> <target>Creato il %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve"> <trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source> <source>Current Passcode</source>
<target>Codice di accesso attuale</target> <target>Codice di accesso attuale</target>
@@ -1794,17 +1763,14 @@ Non è reversibile!</target>
</trans-unit> </trans-unit>
<trans-unit id="Desktop address" xml:space="preserve"> <trans-unit id="Desktop address" xml:space="preserve">
<source>Desktop address</source> <source>Desktop address</source>
<target>Indirizzo desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve"> <trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve">
<source>Desktop app version %@ is not compatible with this app.</source> <source>Desktop app version %@ is not compatible with this app.</source>
<target>La versione dell'app desktop %@ non è compatibile con questa app.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Desktop devices" xml:space="preserve"> <trans-unit id="Desktop devices" xml:space="preserve">
<source>Desktop devices</source> <source>Desktop devices</source>
<target>Dispositivi desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Develop" xml:space="preserve"> <trans-unit id="Develop" xml:space="preserve">
@@ -1899,7 +1865,6 @@ Non è reversibile!</target>
</trans-unit> </trans-unit>
<trans-unit id="Disconnect desktop?" xml:space="preserve"> <trans-unit id="Disconnect desktop?" xml:space="preserve">
<source>Disconnect desktop?</source> <source>Disconnect desktop?</source>
<target>Disconnettere il desktop?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover and join groups" xml:space="preserve"> <trans-unit id="Discover and join groups" xml:space="preserve">
@@ -1907,9 +1872,8 @@ Non è reversibile!</target>
<target>Scopri ed unisciti ai gruppi</target> <target>Scopri ed unisciti ai gruppi</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve"> <trans-unit id="Discover on network" xml:space="preserve">
<source>Discover via local network</source> <source>Discover on network</source>
<target>Individua via rete locale</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -1992,10 +1956,6 @@ Non è reversibile!</target>
<target>Attivare l'eliminazione automatica dei messaggi?</target> <target>Attivare l'eliminazione automatica dei messaggi?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enable camera access" xml:space="preserve">
<source>Enable camera access</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve"> <trans-unit id="Enable for all" xml:space="preserve">
<source>Enable for all</source> <source>Enable for all</source>
<target>Attiva per tutti</target> <target>Attiva per tutti</target>
@@ -2061,10 +2021,6 @@ Non è reversibile!</target>
<target>Messaggio crittografato o altro evento</target> <target>Messaggio crittografato o altro evento</target>
<note>notification</note> <note>notification</note>
</trans-unit> </trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve">
<source>Encrypted message: app is stopped</source>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve"> <trans-unit id="Encrypted message: database error" xml:space="preserve">
<source>Encrypted message: database error</source> <source>Encrypted message: database error</source>
<target>Messaggio crittografato: errore del database</target> <target>Messaggio crittografato: errore del database</target>
@@ -2092,12 +2048,10 @@ Non è reversibile!</target>
</trans-unit> </trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve"> <trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source> <source>Encryption re-negotiation error</source>
<target>Errore di rinegoziazione crittografia</target>
<note>message decrypt error item</note> <note>message decrypt error item</note>
</trans-unit> </trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve"> <trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source> <source>Encryption re-negotiation failed.</source>
<target>Rinegoziazione crittografia fallita.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve"> <trans-unit id="Enter Passcode" xml:space="preserve">
@@ -2132,7 +2086,6 @@ Non è reversibile!</target>
</trans-unit> </trans-unit>
<trans-unit id="Enter this device name…" xml:space="preserve"> <trans-unit id="Enter this device name…" xml:space="preserve">
<source>Enter this device name…</source> <source>Enter this device name…</source>
<target>Inserisci il nome di questo dispositivo…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enter welcome message…" xml:space="preserve"> <trans-unit id="Enter welcome message…" xml:space="preserve">
@@ -2295,10 +2248,6 @@ Non è reversibile!</target>
<target>Errore nel caricamento dei server %@</target> <target>Errore nel caricamento dei server %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error receiving file" xml:space="preserve"> <trans-unit id="Error receiving file" xml:space="preserve">
<source>Error receiving file</source> <source>Error receiving file</source>
<target>Errore nella ricezione del file</target> <target>Errore nella ricezione del file</target>
@@ -2339,10 +2288,6 @@ Non è reversibile!</target>
<target>Errore nel salvataggio della password utente</target> <target>Errore nel salvataggio della password utente</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error scanning code: %@" xml:space="preserve">
<source>Error scanning code: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve"> <trans-unit id="Error sending email" xml:space="preserve">
<source>Error sending email</source> <source>Error sending email</source>
<target>Errore nell'invio dell'email</target> <target>Errore nell'invio dell'email</target>
@@ -2468,11 +2413,6 @@ Non è reversibile!</target>
<target>Veloce e senza aspettare che il mittente sia in linea!</target> <target>Veloce e senza aspettare che il mittente sia in linea!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<target>Ingresso più veloce e messaggi più affidabili.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve"> <trans-unit id="Favorite" xml:space="preserve">
<source>Favorite</source> <source>Favorite</source>
<target>Preferito</target> <target>Preferito</target>
@@ -2568,11 +2508,6 @@ Non è reversibile!</target>
<target>Per console</target> <target>Per console</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Found desktop" xml:space="preserve">
<source>Found desktop</source>
<target>Desktop trovato</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="French interface" xml:space="preserve"> <trans-unit id="French interface" xml:space="preserve">
<source>French interface</source> <source>French interface</source>
<target>Interfaccia francese</target> <target>Interfaccia francese</target>
@@ -2818,6 +2753,11 @@ Non è reversibile!</target>
<target>Se non potete incontrarvi di persona, mostra il codice QR in una videochiamata o condividi il link.</target> <target>Se non potete incontrarvi di persona, mostra il codice QR in una videochiamata o condividi il link.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve">
<source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source>
<target>Se non potete incontrarvi di persona, puoi **scansionare il codice QR durante la videochiamata** oppure il tuo contatto può condividere un link di invito.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve">
<source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source>
<target>Se inserisci questo codice all'apertura dell'app, tutti i dati di essa verranno rimossi in modo irreversibile!</target> <target>Se inserisci questo codice all'apertura dell'app, tutti i dati di essa verranno rimossi in modo irreversibile!</target>
@@ -2893,11 +2833,6 @@ Non è reversibile!</target>
<target>Incognito</target> <target>Incognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<target>Gruppi in incognito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve"> <trans-unit id="Incognito mode" xml:space="preserve">
<source>Incognito mode</source> <source>Incognito mode</source>
<target>Modalità incognito</target> <target>Modalità incognito</target>
@@ -2930,7 +2865,6 @@ Non è reversibile!</target>
</trans-unit> </trans-unit>
<trans-unit id="Incompatible version" xml:space="preserve"> <trans-unit id="Incompatible version" xml:space="preserve">
<source>Incompatible version</source> <source>Incompatible version</source>
<target>Versione incompatibile</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incorrect passcode" xml:space="preserve"> <trans-unit id="Incorrect passcode" xml:space="preserve">
@@ -2975,28 +2909,16 @@ Non è reversibile!</target>
<target>Interfaccia</target> <target>Interfaccia</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid QR code" xml:space="preserve">
<source>Invalid QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve"> <trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source> <source>Invalid connection link</source>
<target>Link di connessione non valido</target> <target>Link di connessione non valido</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
<source>Invalid link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve"> <trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source> <source>Invalid name!</source>
<target>Nome non valido!</target> <target>Nome non valido!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid response" xml:space="preserve">
<source>Invalid response</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve"> <trans-unit id="Invalid server address!" xml:space="preserve">
<source>Invalid server address!</source> <source>Invalid server address!</source>
<target>Indirizzo del server non valido!</target> <target>Indirizzo del server non valido!</target>
@@ -3115,17 +3037,8 @@ Questo è il tuo link per il gruppo %@!</target>
<target>Ingresso nel gruppo</target> <target>Ingresso nel gruppo</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep" xml:space="preserve">
<source>Keep</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
<source>Keep the app open to use it from desktop</source> <source>Keep the app open to use it from desktop</source>
<target>Tieni aperta l'app per usarla dal desktop</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep unused invitation?" xml:space="preserve">
<source>Keep unused invitation?</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve"> <trans-unit id="Keep your connections" xml:space="preserve">
@@ -3188,19 +3101,12 @@ Questo è il tuo link per il gruppo %@!</target>
<target>Limitazioni</target> <target>Limitazioni</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<target>Collega le app mobile e desktop! 🔗</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve"> <trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source> <source>Linked desktop options</source>
<target>Opzioni del desktop collegato</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Linked desktops" xml:space="preserve"> <trans-unit id="Linked desktops" xml:space="preserve">
<source>Linked desktops</source> <source>Linked desktops</source>
<target>Desktop collegati</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Live message!" xml:space="preserve"> <trans-unit id="Live message!" xml:space="preserve">
@@ -3213,11 +3119,6 @@ Questo è il tuo link per il gruppo %@!</target>
<target>Messaggi in diretta</target> <target>Messaggi in diretta</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Local" xml:space="preserve">
<source>Local</source>
<target>Locale</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Local name" xml:space="preserve"> <trans-unit id="Local name" xml:space="preserve">
<source>Local name</source> <source>Local name</source>
<target>Nome locale</target> <target>Nome locale</target>
@@ -3458,10 +3359,6 @@ Questo è il tuo link per il gruppo %@!</target>
<target>Nuovo codice di accesso</target> <target>Nuovo codice di accesso</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="New chat" xml:space="preserve">
<source>New chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve"> <trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source> <source>New contact request</source>
<target>Nuova richiesta di contatto</target> <target>Nuova richiesta di contatto</target>
@@ -3562,11 +3459,6 @@ Questo è il tuo link per il gruppo %@!</target>
<target>Nessun file ricevuto o inviato</target> <target>Nessun file ricevuto o inviato</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Not compatible!" xml:space="preserve">
<source>Not compatible!</source>
<target>Non compatibile!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve"> <trans-unit id="Notifications" xml:space="preserve">
<source>Notifications</source> <source>Notifications</source>
<target>Notifiche</target> <target>Notifiche</target>
@@ -3586,15 +3478,16 @@ Questo è il tuo link per il gruppo %@!</target>
- disattivare i membri (ruolo "osservatore")</target> - disattivare i membri (ruolo "osservatore")</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="OK" xml:space="preserve">
<source>OK</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Off" xml:space="preserve"> <trans-unit id="Off" xml:space="preserve">
<source>Off</source> <source>Off</source>
<target>Off</target> <target>Off</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Off (Local)" xml:space="preserve">
<source>Off (Local)</source>
<target>Off (Locale)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ok" xml:space="preserve"> <trans-unit id="Ok" xml:space="preserve">
<source>Ok</source> <source>Ok</source>
<target>Ok</target> <target>Ok</target>
@@ -3735,16 +3628,9 @@ Questo è il tuo link per il gruppo %@!</target>
<target>Protocollo e codice open source: chiunque può gestire i server.</target> <target>Protocollo e codice open source: chiunque può gestire i server.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Opening app…" xml:space="preserve"> <trans-unit id="Opening database…" xml:space="preserve">
<source>Opening app…</source> <source>Opening database…</source>
<note>No comment provided by engineer.</note> <target>Apertura del database…</target>
</trans-unit>
<trans-unit id="Or scan QR code" xml:space="preserve">
<source>Or scan QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
<source>Or show this code</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="PING count" xml:space="preserve"> <trans-unit id="PING count" xml:space="preserve">
@@ -3787,9 +3673,13 @@ Questo è il tuo link per il gruppo %@!</target>
<target>Password per mostrare</target> <target>Password per mostrare</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste" xml:space="preserve">
<source>Paste</source>
<target>Incolla</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve"> <trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source> <source>Paste desktop address</source>
<target>Incolla l'indirizzo desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste image" xml:space="preserve"> <trans-unit id="Paste image" xml:space="preserve">
@@ -3797,10 +3687,16 @@ Questo è il tuo link per il gruppo %@!</target>
<target>Incolla immagine</target> <target>Incolla immagine</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve"> <trans-unit id="Paste received link" xml:space="preserve">
<source>Paste the link you received</source> <source>Paste received link</source>
<target>Incolla il link ricevuto</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Incolla il link che hai ricevuto nella casella sottostante per connetterti con il tuo contatto.</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source> <source>People can connect to you only via the links you share.</source>
<target>Le persone possono connettersi a te solo tramite i link che condividi.</target> <target>Le persone possono connettersi a te solo tramite i link che condividi.</target>
@@ -3836,11 +3732,6 @@ Questo è il tuo link per il gruppo %@!</target>
<target>Controlla le preferenze tue e del tuo contatto.</target> <target>Controlla le preferenze tue e del tuo contatto.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Please contact developers.&#10;Error: %@" xml:space="preserve">
<source>Please contact developers.
Error: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please contact group admin." xml:space="preserve"> <trans-unit id="Please contact group admin." xml:space="preserve">
<source>Please contact group admin.</source> <source>Please contact group admin.</source>
<target>Contatta l'amministratore del gruppo.</target> <target>Contatta l'amministratore del gruppo.</target>
@@ -4046,10 +3937,6 @@ Error: %@</source>
<target>Maggiori informazioni nella [Guida per l'utente](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <target>Maggiori informazioni nella [Guida per l'utente](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source>
<target>Maggiori informazioni nella [Guida per l'utente](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> <target>Maggiori informazioni nella [Guida per l'utente](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target>
@@ -4260,10 +4147,6 @@ Error: %@</source>
<target>Errore di ripristino del database</target> <target>Errore di ripristino del database</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Retry" xml:space="preserve">
<source>Retry</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reveal" xml:space="preserve"> <trans-unit id="Reveal" xml:space="preserve">
<source>Reveal</source> <source>Reveal</source>
<target>Rivela</target> <target>Rivela</target>
@@ -4396,7 +4279,6 @@ Error: %@</source>
</trans-unit> </trans-unit>
<trans-unit id="Scan QR code from desktop" xml:space="preserve"> <trans-unit id="Scan QR code from desktop" xml:space="preserve">
<source>Scan QR code from desktop</source> <source>Scan QR code from desktop</source>
<target>Scansiona codice QR dal desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Scan code" xml:space="preserve"> <trans-unit id="Scan code" xml:space="preserve">
@@ -4419,10 +4301,6 @@ Error: %@</source>
<target>Cerca</target> <target>Cerca</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve"> <trans-unit id="Secure queue" xml:space="preserve">
<source>Secure queue</source> <source>Secure queue</source>
<target>Coda sicura</target> <target>Coda sicura</target>
@@ -4625,7 +4503,6 @@ Error: %@</source>
</trans-unit> </trans-unit>
<trans-unit id="Session code" xml:space="preserve"> <trans-unit id="Session code" xml:space="preserve">
<source>Session code</source> <source>Session code</source>
<target>Codice di sessione</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Set 1 day" xml:space="preserve"> <trans-unit id="Set 1 day" xml:space="preserve">
@@ -4698,8 +4575,9 @@ Error: %@</source>
<target>Condividi link</target> <target>Condividi link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve"> <trans-unit id="Share one-time invitation link" xml:space="preserve">
<source>Share this 1-time invite link</source> <source>Share one-time invitation link</source>
<target>Condividi link di invito una tantum</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve"> <trans-unit id="Share with contacts" xml:space="preserve">
@@ -4769,7 +4647,7 @@ Error: %@</source>
</trans-unit> </trans-unit>
<trans-unit id="SimpleX contact address" xml:space="preserve"> <trans-unit id="SimpleX contact address" xml:space="preserve">
<source>SimpleX contact address</source> <source>SimpleX contact address</source>
<target>Indirizzo di contatto SimpleX</target> <target>Indirizzo del contatto SimpleX</target>
<note>simplex link type</note> <note>simplex link type</note>
</trans-unit> </trans-unit>
<trans-unit id="SimpleX encrypted message or connection event" xml:space="preserve"> <trans-unit id="SimpleX encrypted message or connection event" xml:space="preserve">
@@ -4822,15 +4700,16 @@ Error: %@</source>
<target>Qualcuno</target> <target>Qualcuno</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="Start a new chat" xml:space="preserve">
<source>Start a new chat</source>
<target>Inizia una nuova chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start chat" xml:space="preserve"> <trans-unit id="Start chat" xml:space="preserve">
<source>Start chat</source> <source>Start chat</source>
<target>Avvia chat</target> <target>Avvia chat</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Start chat?" xml:space="preserve">
<source>Start chat?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start migration" xml:space="preserve"> <trans-unit id="Start migration" xml:space="preserve">
<source>Start migration</source> <source>Start migration</source>
<target>Avvia la migrazione</target> <target>Avvia la migrazione</target>
@@ -4956,14 +4835,6 @@ Error: %@</source>
<target>Toccare per entrare in incognito</target> <target>Toccare per entrare in incognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Tap to paste link" xml:space="preserve">
<source>Tap to paste link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to scan" xml:space="preserve">
<source>Tap to scan</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve"> <trans-unit id="Tap to start a new chat" xml:space="preserve">
<source>Tap to start a new chat</source> <source>Tap to start a new chat</source>
<target>Tocca per iniziare una chat</target> <target>Tocca per iniziare una chat</target>
@@ -5026,10 +4897,6 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta
<target>Il tentativo di cambiare la password del database non è stato completato.</target> <target>Il tentativo di cambiare la password del database non è stato completato.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source> <source>The connection you accepted will be cancelled!</source>
<target>La connessione che hai accettato verrà annullata!</target> <target>La connessione che hai accettato verrà annullata!</target>
@@ -5095,10 +4962,6 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta
<target>I server per le nuove connessioni del profilo di chat attuale **%@**.</target> <target>I server per le nuove connessioni del profilo di chat attuale **%@**.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve">
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve"> <trans-unit id="Theme" xml:space="preserve">
<source>Theme</source> <source>Theme</source>
<target>Tema</target> <target>Tema</target>
@@ -5141,7 +5004,6 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta
</trans-unit> </trans-unit>
<trans-unit id="This device name" xml:space="preserve"> <trans-unit id="This device name" xml:space="preserve">
<source>This device name</source> <source>This device name</source>
<target>Il nome di questo dispositivo</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
@@ -5179,11 +5041,6 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta
<target>Per connettervi, il tuo contatto può scansionare il codice QR o usare il link nell'app.</target> <target>Per connettervi, il tuo contatto può scansionare il codice QR o usare il link nell'app.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<target>Per nascondere messaggi indesiderati.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve"> <trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source> <source>To make a new connection</source>
<target>Per creare una nuova connessione</target> <target>Per creare una nuova connessione</target>
@@ -5251,6 +5108,11 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio
<target>Spegni</target> <target>Spegni</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Turn off notifications?" xml:space="preserve">
<source>Turn off notifications?</source>
<target>Spegnere le notifiche?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn on" xml:space="preserve"> <trans-unit id="Turn on" xml:space="preserve">
<source>Turn on</source> <source>Turn on</source>
<target>Attiva</target> <target>Attiva</target>
@@ -5340,12 +5202,10 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
</trans-unit> </trans-unit>
<trans-unit id="Unlink" xml:space="preserve"> <trans-unit id="Unlink" xml:space="preserve">
<source>Unlink</source> <source>Unlink</source>
<target>Scollega</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Unlink desktop?" xml:space="preserve"> <trans-unit id="Unlink desktop?" xml:space="preserve">
<source>Unlink desktop?</source> <source>Unlink desktop?</source>
<target>Scollegare il desktop?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Unlock" xml:space="preserve"> <trans-unit id="Unlock" xml:space="preserve">
@@ -5440,7 +5300,6 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
</trans-unit> </trans-unit>
<trans-unit id="Use from desktop" xml:space="preserve"> <trans-unit id="Use from desktop" xml:space="preserve">
<source>Use from desktop</source> <source>Use from desktop</source>
<target>Usa dal desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use iOS call interface" xml:space="preserve"> <trans-unit id="Use iOS call interface" xml:space="preserve">
@@ -5453,10 +5312,6 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
<target>Usa nuovo profilo in incognito</target> <target>Usa nuovo profilo in incognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use only local notifications?" xml:space="preserve">
<source>Use only local notifications?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve"> <trans-unit id="Use server" xml:space="preserve">
<source>Use server</source> <source>Use server</source>
<target>Usa il server</target> <target>Usa il server</target>
@@ -5479,12 +5334,10 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
</trans-unit> </trans-unit>
<trans-unit id="Verify code with desktop" xml:space="preserve"> <trans-unit id="Verify code with desktop" xml:space="preserve">
<source>Verify code with desktop</source> <source>Verify code with desktop</source>
<target>Verifica il codice con il desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify connection" xml:space="preserve"> <trans-unit id="Verify connection" xml:space="preserve">
<source>Verify connection</source> <source>Verify connection</source>
<target>Verifica la connessione</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify connection security" xml:space="preserve"> <trans-unit id="Verify connection security" xml:space="preserve">
@@ -5494,7 +5347,6 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
</trans-unit> </trans-unit>
<trans-unit id="Verify connections" xml:space="preserve"> <trans-unit id="Verify connections" xml:space="preserve">
<source>Verify connections</source> <source>Verify connections</source>
<target>Verifica le connessioni</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify security code" xml:space="preserve"> <trans-unit id="Verify security code" xml:space="preserve">
@@ -5507,11 +5359,6 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
<target>Via browser</target> <target>Via browser</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<target>Tramite protocollo sicuro resistente alla quantistica.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve"> <trans-unit id="Video call" xml:space="preserve">
<source>Video call</source> <source>Video call</source>
<target>Videochiamata</target> <target>Videochiamata</target>
@@ -5562,11 +5409,6 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
<target>Messaggio vocale…</target> <target>Messaggio vocale…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Waiting for desktop..." xml:space="preserve">
<source>Waiting for desktop...</source>
<target>In attesa del desktop...</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Waiting for file" xml:space="preserve"> <trans-unit id="Waiting for file" xml:space="preserve">
<source>Waiting for file</source> <source>Waiting for file</source>
<target>In attesa del file</target> <target>In attesa del file</target>
@@ -5719,6 +5561,11 @@ Ripetere la richiesta di ingresso?</target>
<target>Puoi accettare chiamate dalla schermata di blocco, senza l'autenticazione del dispositivo e dell'app.</target> <target>Puoi accettare chiamate dalla schermata di blocco, senza l'autenticazione del dispositivo e dell'app.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve">
<source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source>
<target>Puoi anche connetterti cliccando il link. Se si apre nel browser, clicca il pulsante **Apri nell'app mobile**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can create it later" xml:space="preserve"> <trans-unit id="You can create it later" xml:space="preserve">
<source>You can create it later</source> <source>You can create it later</source>
<target>Puoi crearlo più tardi</target> <target>Puoi crearlo più tardi</target>
@@ -5739,10 +5586,6 @@ Ripetere la richiesta di ingresso?</target>
<target>Puoi nascondere o silenziare un profilo utente - scorrilo verso destra.</target> <target>Puoi nascondere o silenziare un profilo utente - scorrilo verso destra.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now send messages to %@" xml:space="preserve"> <trans-unit id="You can now send messages to %@" xml:space="preserve">
<source>You can now send messages to %@</source> <source>You can now send messages to %@</source>
<target>Ora puoi inviare messaggi a %@</target> <target>Ora puoi inviare messaggi a %@</target>
@@ -5783,10 +5626,6 @@ Ripetere la richiesta di ingresso?</target>
<target>Puoi usare il markdown per formattare i messaggi:</target> <target>Puoi usare il markdown per formattare i messaggi:</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can view invitation link again in connection details." xml:space="preserve">
<source>You can view invitation link again in connection details.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can't send messages!" xml:space="preserve"> <trans-unit id="You can't send messages!" xml:space="preserve">
<source>You can't send messages!</source> <source>You can't send messages!</source>
<target>Non puoi inviare messaggi!</target> <target>Non puoi inviare messaggi!</target>
@@ -5976,6 +5815,13 @@ Puoi annullare questa connessione e rimuovere il contatto (e riprovare più tard
<target>I tuoi contatti possono consentire l'eliminazione completa dei messaggi.</target> <target>I tuoi contatti possono consentire l'eliminazione completa dei messaggi.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your contacts in SimpleX will see it.&#10;You can change it in Settings." xml:space="preserve">
<source>Your contacts in SimpleX will see it.
You can change it in Settings.</source>
<target>I tuoi contatti in SimpleX lo vedranno.
Puoi modificarlo nelle impostazioni.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve"> <trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source> <source>Your contacts will remain connected.</source>
<target>I tuoi contatti resteranno connessi.</target> <target>I tuoi contatti resteranno connessi.</target>
@@ -6055,7 +5901,7 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
</trans-unit> </trans-unit>
<trans-unit id="[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" xml:space="preserve"> <trans-unit id="[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" xml:space="preserve">
<source>[Star on GitHub](https://github.com/simplex-chat/simplex-chat)</source> <source>[Star on GitHub](https://github.com/simplex-chat/simplex-chat)</source>
<target>[Dai una stella su GitHub](https://github.com/simplex-chat/simplex-chat)</target> <target>[Stella su GitHub](https://github.com/simplex-chat/simplex-chat)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="_italic_" xml:space="preserve"> <trans-unit id="_italic_" xml:space="preserve">
@@ -6108,11 +5954,6 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
<target>chiamata audio (non crittografata e2e)</target> <target>chiamata audio (non crittografata e2e)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="author" xml:space="preserve">
<source>author</source>
<target>autore</target>
<note>member role</note>
</trans-unit>
<trans-unit id="bad message ID" xml:space="preserve"> <trans-unit id="bad message ID" xml:space="preserve">
<source>bad message ID</source> <source>bad message ID</source>
<target>ID messaggio errato</target> <target>ID messaggio errato</target>
@@ -6692,12 +6533,11 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
</trans-unit> </trans-unit>
<trans-unit id="updated group profile" xml:space="preserve"> <trans-unit id="updated group profile" xml:space="preserve">
<source>updated group profile</source> <source>updated group profile</source>
<target>ha aggiornato il profilo del gruppo</target> <target>profilo del gruppo aggiornato</target>
<note>rcv group event chat item</note> <note>rcv group event chat item</note>
</trans-unit> </trans-unit>
<trans-unit id="v%@" xml:space="preserve"> <trans-unit id="v%@" xml:space="preserve">
<source>v%@</source> <source>v%@</source>
<target>v%@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="v%@ (%@)" xml:space="preserve"> <trans-unit id="v%@ (%@)" xml:space="preserve">
@@ -6839,7 +6679,6 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
</trans-unit> </trans-unit>
<trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve"> <trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve">
<source>SimpleX uses local network access to allow using user chat profile via desktop app on the same network.</source> <source>SimpleX uses local network access to allow using user chat profile via desktop app on the same network.</source>
<target>SimpleX usa l'accesso alla rete locale per consentire di usare il profilo di chat tramite l'app desktop sulla stessa rete.</target>
<note>Privacy - Local Network Usage Description</note> <note>Privacy - Local Network Usage Description</note>
</trans-unit> </trans-unit>
<trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve"> <trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve">
@@ -103,7 +103,6 @@
</trans-unit> </trans-unit>
<trans-unit id="%@ connected" xml:space="preserve"> <trans-unit id="%@ connected" xml:space="preserve">
<source>%@ connected</source> <source>%@ connected</source>
<target>%@ 接続中</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%@ is connected!" xml:space="preserve"> <trans-unit id="%@ is connected!" xml:space="preserve">
@@ -215,12 +214,10 @@
</trans-unit> </trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve"> <trans-unit id="%lld messages marked deleted" xml:space="preserve">
<source>%lld messages marked deleted</source> <source>%lld messages marked deleted</source>
<target>%lld 件のメッセージが削除されました</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%lld messages moderated by %@" xml:space="preserve"> <trans-unit id="%lld messages moderated by %@" xml:space="preserve">
<source>%lld messages moderated by %@</source> <source>%lld messages moderated by %@</source>
<target>%@ により%lld 件のメッセージが検閲されました</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%lld minutes" xml:space="preserve"> <trans-unit id="%lld minutes" xml:space="preserve">
@@ -306,17 +303,14 @@
<target>)</target> <target>)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve">
<source>**Add contact**: to create a new invitation link, or connect via a link you received.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target>**新しい連絡先を追加**: 連絡先のワンタイム QR コードまたはリンクを作成します。</target> <target>**新しい連絡先を追加**: 連絡先のワンタイム QR コードまたはリンクを作成します。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Create group**: to create a new group." xml:space="preserve"> <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<source>**Create group**: to create a new group.</source> <source>**Create link / QR code** for your contact to use.</source>
<target>連絡先が使用する **リンク/QR コードを作成します**。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -329,6 +323,11 @@
<target>**最もプライベート**: SimpleX Chat 通知サーバーを使用せず、バックグラウンドで定期的にメッセージをチェックします (アプリの使用頻度によって異なります)。</target> <target>**最もプライベート**: SimpleX Chat 通知サーバーを使用せず、バックグラウンドで定期的にメッセージをチェックします (アプリの使用頻度によって異なります)。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve">
<source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source>
<target>**受信したリンク**を貼り付けるか、ブラウザーで開いて [**モバイル アプリで開く**] をタップします。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve">
<source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source>
<target>**注意**: パスフレーズを紛失すると、パスフレーズを復元または変更できなくなります。</target> <target>**注意**: パスフレーズを紛失すると、パスフレーズを復元または変更できなくなります。</target>
@@ -339,6 +338,11 @@
<target>**推奨**: デバイス トークンと通知は SimpleX Chat 通知サーバーに送信されますが、メッセージの内容、サイズ、送信者は送信されません。</target> <target>**推奨**: デバイス トークンと通知は SimpleX Chat 通知サーバーに送信されますが、メッセージの内容、サイズ、送信者は送信されません。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve">
<source>**Scan QR code**: to connect to your contact in person or via video call.</source>
<target>**QR コードをスキャン**: 直接またはビデオ通話で連絡先に接続します。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target>**警告**: 即時の プッシュ通知には、キーチェーンに保存されたパスフレーズが必要です。</target> <target>**警告**: 即時の プッシュ通知には、キーチェーンに保存されたパスフレーズが必要です。</target>
@@ -379,12 +383,6 @@
- などなど!</target> - などなど!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="- optionally notify deleted contacts.&#10;- profile names with spaces.&#10;- and more!" xml:space="preserve">
<source>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve"> <trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve">
<source>- voice messages up to 5 minutes. <source>- voice messages up to 5 minutes.
- custom time to disappear. - custom time to disappear.
@@ -433,6 +431,11 @@
<target>1週間</target> <target>1週間</target>
<note>time interval</note> <note>time interval</note>
</trans-unit> </trans-unit>
<trans-unit id="1-time link" xml:space="preserve">
<source>1-time link</source>
<target>使い捨てのリンク</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="5 minutes" xml:space="preserve"> <trans-unit id="5 minutes" xml:space="preserve">
<source>5 minutes</source> <source>5 minutes</source>
<target>5分</target> <target>5分</target>
@@ -548,10 +551,6 @@
<target>プロフィールにアドレスを追加し、連絡先があなたのアドレスを他の人と共有できるようにします。プロフィールの更新は連絡先に送信されます。</target> <target>プロフィールにアドレスを追加し、連絡先があなたのアドレスを他の人と共有できるようにします。プロフィールの更新は連絡先に送信されます。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add contact" xml:space="preserve">
<source>Add contact</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve"> <trans-unit id="Add preset servers" xml:space="preserve">
<source>Add preset servers</source> <source>Add preset servers</source>
<target>既存サーバを追加</target> <target>既存サーバを追加</target>
@@ -878,10 +877,6 @@
<target>メッセージのハッシュ値問題</target> <target>メッセージのハッシュ値問題</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
<source>Better groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better messages" xml:space="preserve"> <trans-unit id="Better messages" xml:space="preserve">
<source>Better messages</source> <source>Better messages</source>
<target>より良いメッセージ</target> <target>より良いメッセージ</target>
@@ -891,10 +886,6 @@
<source>Block</source> <source>Block</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
<source>Block group members</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve"> <trans-unit id="Block member" xml:space="preserve">
<source>Block member</source> <source>Block member</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -948,10 +939,6 @@
<target>通話</target> <target>通話</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Camera not available" xml:space="preserve">
<source>Camera not available</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Can't delete user profile!" xml:space="preserve"> <trans-unit id="Can't delete user profile!" xml:space="preserve">
<source>Can't delete user profile!</source> <source>Can't delete user profile!</source>
<target>ユーザープロフィールが削除できません!</target> <target>ユーザープロフィールが削除できません!</target>
@@ -1068,10 +1055,6 @@
<target>チャットが停止してます</target> <target>チャットが停止してます</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve">
<source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve"> <trans-unit id="Chat preferences" xml:space="preserve">
<source>Chat preferences</source> <source>Chat preferences</source>
<target>チャット設定</target> <target>チャット設定</target>
@@ -1172,10 +1155,6 @@
<target>接続</target> <target>接続</target>
<note>server test step</note> <note>server test step</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect automatically" xml:space="preserve">
<source>Connect automatically</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve"> <trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source> <source>Connect incognito</source>
<target>シークレットモードで接続</target> <target>シークレットモードで接続</target>
@@ -1208,6 +1187,11 @@ This is your own one-time link!</source>
<target>リンク経由で接続</target> <target>リンク経由で接続</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link / QR code" xml:space="preserve">
<source>Connect via link / QR code</source>
<target>リンク・QRコード経由で接続</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link" xml:space="preserve"> <trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source> <source>Connect via one-time link</source>
<target>使い捨てリンク経由で接続しますか?</target> <target>使い捨てリンク経由で接続しますか?</target>
@@ -1342,10 +1326,6 @@ This is your own one-time link!</source>
<target>SimpleXアドレスの作成</target> <target>SimpleXアドレスの作成</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create a group using a random profile." xml:space="preserve">
<source>Create a group using a random profile.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source> <source>Create an address to let people connect with you.</source>
<target>人とつながるためのアドレスを作成する。</target> <target>人とつながるためのアドレスを作成する。</target>
@@ -1375,6 +1355,11 @@ This is your own one-time link!</source>
<target>[デスクトップアプリ](https://simplex.chat/downloads/)で新しいプロファイルを作成します。 💻</target> <target>[デスクトップアプリ](https://simplex.chat/downloads/)で新しいプロファイルを作成します。 💻</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create one-time invitation link" xml:space="preserve">
<source>Create one-time invitation link</source>
<target>使い捨ての招待リンクを生成する</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -1399,10 +1384,6 @@ This is your own one-time link!</source>
<target>%@ によって作成されました</target> <target>%@ によって作成されました</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve"> <trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source> <source>Current Passcode</source>
<target>現在のパスコード</target> <target>現在のパスコード</target>
@@ -1860,8 +1841,8 @@ This cannot be undone!</source>
<target>グループを見つけて参加する</target> <target>グループを見つけて参加する</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve"> <trans-unit id="Discover on network" xml:space="preserve">
<source>Discover via local network</source> <source>Discover on network</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -1944,10 +1925,6 @@ This cannot be undone!</source>
<target>自動メッセージ削除を有効にしますか?</target> <target>自動メッセージ削除を有効にしますか?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enable camera access" xml:space="preserve">
<source>Enable camera access</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve"> <trans-unit id="Enable for all" xml:space="preserve">
<source>Enable for all</source> <source>Enable for all</source>
<target>すべて有効</target> <target>すべて有効</target>
@@ -2013,10 +1990,6 @@ This cannot be undone!</source>
<target>暗号化されたメッセージまたは別のイベント</target> <target>暗号化されたメッセージまたは別のイベント</target>
<note>notification</note> <note>notification</note>
</trans-unit> </trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve">
<source>Encrypted message: app is stopped</source>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve"> <trans-unit id="Encrypted message: database error" xml:space="preserve">
<source>Encrypted message: database error</source> <source>Encrypted message: database error</source>
<target>暗号化されたメッセージ : データベースエラー</target> <target>暗号化されたメッセージ : データベースエラー</target>
@@ -2241,10 +2214,6 @@ This cannot be undone!</source>
<target>%@ サーバーのロード中にエラーが発生</target> <target>%@ サーバーのロード中にエラーが発生</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error receiving file" xml:space="preserve"> <trans-unit id="Error receiving file" xml:space="preserve">
<source>Error receiving file</source> <source>Error receiving file</source>
<target>ファイル受信にエラー発生</target> <target>ファイル受信にエラー発生</target>
@@ -2285,10 +2254,6 @@ This cannot be undone!</source>
<target>ユーザーパスワード保存エラー</target> <target>ユーザーパスワード保存エラー</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error scanning code: %@" xml:space="preserve">
<source>Error scanning code: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve"> <trans-unit id="Error sending email" xml:space="preserve">
<source>Error sending email</source> <source>Error sending email</source>
<target>メールの送信にエラー発生</target> <target>メールの送信にエラー発生</target>
@@ -2412,10 +2377,6 @@ This cannot be undone!</source>
<target>送信者がオンラインになるまでの待ち時間がなく、速い!</target> <target>送信者がオンラインになるまでの待ち時間がなく、速い!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve"> <trans-unit id="Favorite" xml:space="preserve">
<source>Favorite</source> <source>Favorite</source>
<target>お気に入り</target> <target>お気に入り</target>
@@ -2511,10 +2472,6 @@ This cannot be undone!</source>
<target>コンソール</target> <target>コンソール</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Found desktop" xml:space="preserve">
<source>Found desktop</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="French interface" xml:space="preserve"> <trans-unit id="French interface" xml:space="preserve">
<source>French interface</source> <source>French interface</source>
<target>フランス語UI</target> <target>フランス語UI</target>
@@ -2757,6 +2714,11 @@ This cannot be undone!</source>
<target>直接会えない場合は、ビデオ通話で QR コードを表示するか、リンクを共有してください。</target> <target>直接会えない場合は、ビデオ通話で QR コードを表示するか、リンクを共有してください。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve">
<source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source>
<target>直接会えない場合は、**ビデオ通話で QR コードを表示する**か、リンクを共有してください。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve">
<source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source>
<target>アプリを開くときにこのパスコードを入力すると、アプリのすべてのデータが元に戻せないように削除されます!</target> <target>アプリを開くときにこのパスコードを入力すると、アプリのすべてのデータが元に戻せないように削除されます!</target>
@@ -2832,10 +2794,6 @@ This cannot be undone!</source>
<target>シークレットモード</target> <target>シークレットモード</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve"> <trans-unit id="Incognito mode" xml:space="preserve">
<source>Incognito mode</source> <source>Incognito mode</source>
<target>シークレットモード</target> <target>シークレットモード</target>
@@ -2912,27 +2870,15 @@ This cannot be undone!</source>
<target>インターフェース</target> <target>インターフェース</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid QR code" xml:space="preserve">
<source>Invalid QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve"> <trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source> <source>Invalid connection link</source>
<target>無効な接続リンク</target> <target>無効な接続リンク</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
<source>Invalid link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve"> <trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source> <source>Invalid name!</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid response" xml:space="preserve">
<source>Invalid response</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve"> <trans-unit id="Invalid server address!" xml:space="preserve">
<source>Invalid server address!</source> <source>Invalid server address!</source>
<target>無効なサーバアドレス!</target> <target>無効なサーバアドレス!</target>
@@ -3047,18 +2993,10 @@ This is your link for group %@!</source>
<target>グループに参加</target> <target>グループに参加</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep" xml:space="preserve">
<source>Keep</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
<source>Keep the app open to use it from desktop</source> <source>Keep the app open to use it from desktop</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep unused invitation?" xml:space="preserve">
<source>Keep unused invitation?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve"> <trans-unit id="Keep your connections" xml:space="preserve">
<source>Keep your connections</source> <source>Keep your connections</source>
<target>接続を維持</target> <target>接続を維持</target>
@@ -3119,10 +3057,6 @@ This is your link for group %@!</source>
<target>制限事項</target> <target>制限事項</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve"> <trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source> <source>Linked desktop options</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3141,11 +3075,6 @@ This is your link for group %@!</source>
<target>ライブメッセージ</target> <target>ライブメッセージ</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Local" xml:space="preserve">
<source>Local</source>
<target>自分のみ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Local name" xml:space="preserve"> <trans-unit id="Local name" xml:space="preserve">
<source>Local name</source> <source>Local name</source>
<target>ローカルネーム</target> <target>ローカルネーム</target>
@@ -3384,10 +3313,6 @@ This is your link for group %@!</source>
<target>新しいパスコード</target> <target>新しいパスコード</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="New chat" xml:space="preserve">
<source>New chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve"> <trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source> <source>New contact request</source>
<target>新しい繋がりのリクエスト</target> <target>新しい繋がりのリクエスト</target>
@@ -3488,10 +3413,6 @@ This is your link for group %@!</source>
<target>送受信済みのファイルがありません</target> <target>送受信済みのファイルがありません</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Not compatible!" xml:space="preserve">
<source>Not compatible!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve"> <trans-unit id="Notifications" xml:space="preserve">
<source>Notifications</source> <source>Notifications</source>
<target>通知</target> <target>通知</target>
@@ -3511,15 +3432,16 @@ This is your link for group %@!</source>
- メンバーを無効にする (メッセージの送信不可)</target> - メンバーを無効にする (メッセージの送信不可)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="OK" xml:space="preserve">
<source>OK</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Off" xml:space="preserve"> <trans-unit id="Off" xml:space="preserve">
<source>Off</source> <source>Off</source>
<target>オフ</target> <target>オフ</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Off (Local)" xml:space="preserve">
<source>Off (Local)</source>
<target>オフ(自分のみ)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ok" xml:space="preserve"> <trans-unit id="Ok" xml:space="preserve">
<source>Ok</source> <source>Ok</source>
<target>OK</target> <target>OK</target>
@@ -3659,16 +3581,9 @@ This is your link for group %@!</source>
<target>プロトコル技術とコードはオープンソースで、どなたでもご自分のサーバを運用できます。</target> <target>プロトコル技術とコードはオープンソースで、どなたでもご自分のサーバを運用できます。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Opening app…" xml:space="preserve"> <trans-unit id="Opening database…" xml:space="preserve">
<source>Opening app…</source> <source>Opening database…</source>
<note>No comment provided by engineer.</note> <target>データベースを開いています…</target>
</trans-unit>
<trans-unit id="Or scan QR code" xml:space="preserve">
<source>Or scan QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
<source>Or show this code</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="PING count" xml:space="preserve"> <trans-unit id="PING count" xml:space="preserve">
@@ -3711,6 +3626,11 @@ This is your link for group %@!</source>
<target>パスワードを表示する</target> <target>パスワードを表示する</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste" xml:space="preserve">
<source>Paste</source>
<target>貼り付け</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve"> <trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source> <source>Paste desktop address</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3720,10 +3640,16 @@ This is your link for group %@!</source>
<target>画像の貼り付け</target> <target>画像の貼り付け</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve"> <trans-unit id="Paste received link" xml:space="preserve">
<source>Paste the link you received</source> <source>Paste received link</source>
<target>頂いたリンクを貼り付ける</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>連絡相手から頂いたリンクを以下の入力欄に貼り付けて繋がります。</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source> <source>People can connect to you only via the links you share.</source>
<target>あなたと繋がることができるのは、あなたからリンクを頂いた方のみです。</target> <target>あなたと繋がることができるのは、あなたからリンクを頂いた方のみです。</target>
@@ -3759,11 +3685,6 @@ This is your link for group %@!</source>
<target>あなたと連絡先の設定を確認してください。</target> <target>あなたと連絡先の設定を確認してください。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Please contact developers.&#10;Error: %@" xml:space="preserve">
<source>Please contact developers.
Error: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please contact group admin." xml:space="preserve"> <trans-unit id="Please contact group admin." xml:space="preserve">
<source>Please contact group admin.</source> <source>Please contact group admin.</source>
<target>グループの管理者に連絡してください。</target> <target>グループの管理者に連絡してください。</target>
@@ -3967,10 +3888,6 @@ Error: %@</source>
<target>詳しくは[ユーザーガイド](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)をご覧ください。</target> <target>詳しくは[ユーザーガイド](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)をご覧ください。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source>
<target>詳しくは[ユーザーガイド](https://simplex.chat/docs/guide/readme.html#connect-to-friends)をご覧ください。</target> <target>詳しくは[ユーザーガイド](https://simplex.chat/docs/guide/readme.html#connect-to-friends)をご覧ください。</target>
@@ -4178,10 +4095,6 @@ Error: %@</source>
<target>データベース復元エラー</target> <target>データベース復元エラー</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Retry" xml:space="preserve">
<source>Retry</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reveal" xml:space="preserve"> <trans-unit id="Reveal" xml:space="preserve">
<source>Reveal</source> <source>Reveal</source>
<target>開示する</target> <target>開示する</target>
@@ -4336,10 +4249,6 @@ Error: %@</source>
<target>検索</target> <target>検索</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve"> <trans-unit id="Secure queue" xml:space="preserve">
<source>Secure queue</source> <source>Secure queue</source>
<target>待ち行列セキュリティ確認</target> <target>待ち行列セキュリティ確認</target>
@@ -4606,8 +4515,9 @@ Error: %@</source>
<target>リンクを送る</target> <target>リンクを送る</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve"> <trans-unit id="Share one-time invitation link" xml:space="preserve">
<source>Share this 1-time invite link</source> <source>Share one-time invitation link</source>
<target>使い捨ての招待リンクを共有</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve"> <trans-unit id="Share with contacts" xml:space="preserve">
@@ -4730,15 +4640,16 @@ Error: %@</source>
<target>誰か</target> <target>誰か</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="Start a new chat" xml:space="preserve">
<source>Start a new chat</source>
<target>新しいチャットを開始する</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start chat" xml:space="preserve"> <trans-unit id="Start chat" xml:space="preserve">
<source>Start chat</source> <source>Start chat</source>
<target>チャットを開始する</target> <target>チャットを開始する</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Start chat?" xml:space="preserve">
<source>Start chat?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start migration" xml:space="preserve"> <trans-unit id="Start migration" xml:space="preserve">
<source>Start migration</source> <source>Start migration</source>
<target>移行の開始</target> <target>移行の開始</target>
@@ -4863,14 +4774,6 @@ Error: %@</source>
<target>タップしてシークレットモードで参加</target> <target>タップしてシークレットモードで参加</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Tap to paste link" xml:space="preserve">
<source>Tap to paste link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to scan" xml:space="preserve">
<source>Tap to scan</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve"> <trans-unit id="Tap to start a new chat" xml:space="preserve">
<source>Tap to start a new chat</source> <source>Tap to start a new chat</source>
<target>タップして新しいチャットを始める</target> <target>タップして新しいチャットを始める</target>
@@ -4933,10 +4836,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>データベースのパスフレーズ変更が完了してません。</target> <target>データベースのパスフレーズ変更が完了してません。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source> <source>The connection you accepted will be cancelled!</source>
<target>承認済の接続がキャンセルされます!</target> <target>承認済の接続がキャンセルされます!</target>
@@ -5002,10 +4901,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>現在のチャットプロフィールの新しい接続のサーバ **%@**。</target> <target>現在のチャットプロフィールの新しい接続のサーバ **%@**。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve">
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve"> <trans-unit id="Theme" xml:space="preserve">
<source>Theme</source> <source>Theme</source>
<target>テーマ</target> <target>テーマ</target>
@@ -5082,10 +4977,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>接続するにはQRコードを読み込むか、アプリ内のリンクを使用する必要があります。</target> <target>接続するにはQRコードを読み込むか、アプリ内のリンクを使用する必要があります。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve"> <trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source> <source>To make a new connection</source>
<target>新規に接続する場合</target> <target>新規に接続する場合</target>
@@ -5152,6 +5043,11 @@ You will be prompted to complete authentication before this feature is enabled.<
<target>オフにする</target> <target>オフにする</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Turn off notifications?" xml:space="preserve">
<source>Turn off notifications?</source>
<target>通知をオフにしますか?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn on" xml:space="preserve"> <trans-unit id="Turn on" xml:space="preserve">
<source>Turn on</source> <source>Turn on</source>
<target>オンにする</target> <target>オンにする</target>
@@ -5348,10 +5244,6 @@ To connect, please ask your contact to create another connection link and check
<target>新しいシークレットプロファイルを使用する</target> <target>新しいシークレットプロファイルを使用する</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use only local notifications?" xml:space="preserve">
<source>Use only local notifications?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve"> <trans-unit id="Use server" xml:space="preserve">
<source>Use server</source> <source>Use server</source>
<target>サーバを使う</target> <target>サーバを使う</target>
@@ -5399,10 +5291,6 @@ To connect, please ask your contact to create another connection link and check
<target>ブラウザ経由</target> <target>ブラウザ経由</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve"> <trans-unit id="Video call" xml:space="preserve">
<source>Video call</source> <source>Video call</source>
<target>ビデオ通話</target> <target>ビデオ通話</target>
@@ -5453,10 +5341,6 @@ To connect, please ask your contact to create another connection link and check
<target>音声メッセージ…</target> <target>音声メッセージ…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Waiting for desktop..." xml:space="preserve">
<source>Waiting for desktop...</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Waiting for file" xml:space="preserve"> <trans-unit id="Waiting for file" xml:space="preserve">
<source>Waiting for file</source> <source>Waiting for file</source>
<target>ファイル待ち</target> <target>ファイル待ち</target>
@@ -5601,6 +5485,11 @@ Repeat join request?</source>
<target>デバイスやアプリの認証を行わずに、ロック画面から通話を受けることができます。</target> <target>デバイスやアプリの認証を行わずに、ロック画面から通話を受けることができます。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve">
<source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source>
<target>リンクをクリックすることでも接続できます。ブラウザで開いた場合は、**モバイルアプリで開く**ボタンをクリックしてください。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can create it later" xml:space="preserve"> <trans-unit id="You can create it later" xml:space="preserve">
<source>You can create it later</source> <source>You can create it later</source>
<target>後からでも作成できます</target> <target>後からでも作成できます</target>
@@ -5621,10 +5510,6 @@ Repeat join request?</source>
<target>ユーザープロファイルを右にスワイプすると、非表示またはミュートにすることができます。</target> <target>ユーザープロファイルを右にスワイプすると、非表示またはミュートにすることができます。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now send messages to %@" xml:space="preserve"> <trans-unit id="You can now send messages to %@" xml:space="preserve">
<source>You can now send messages to %@</source> <source>You can now send messages to %@</source>
<target>%@ にメッセージを送信できるようになりました</target> <target>%@ にメッセージを送信できるようになりました</target>
@@ -5665,10 +5550,6 @@ Repeat join request?</source>
<target>メッセージの書式にmarkdownを使用することができます:</target> <target>メッセージの書式にmarkdownを使用することができます:</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can view invitation link again in connection details." xml:space="preserve">
<source>You can view invitation link again in connection details.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can't send messages!" xml:space="preserve"> <trans-unit id="You can't send messages!" xml:space="preserve">
<source>You can't send messages!</source> <source>You can't send messages!</source>
<target>メッセージを送信できませんでした!</target> <target>メッセージを送信できませんでした!</target>
@@ -5853,6 +5734,13 @@ You can cancel this connection and remove the contact (and try later with a new
<target>連絡先がメッセージの完全削除を許可できます。</target> <target>連絡先がメッセージの完全削除を許可できます。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your contacts in SimpleX will see it.&#10;You can change it in Settings." xml:space="preserve">
<source>Your contacts in SimpleX will see it.
You can change it in Settings.</source>
<target>SimpleX の連絡先に表示されます。
設定で変更できます。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve"> <trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source> <source>Your contacts will remain connected.</source>
<target>連絡先は接続されたままになります。</target> <target>連絡先は接続されたままになります。</target>
@@ -5983,10 +5871,6 @@ SimpleX サーバーはあなたのプロファイルを参照できません。
<target>音声通話 (エンドツーエンド暗号化なし)</target> <target>音声通話 (エンドツーエンド暗号化なし)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="author" xml:space="preserve">
<source>author</source>
<note>member role</note>
</trans-unit>
<trans-unit id="bad message ID" xml:space="preserve"> <trans-unit id="bad message ID" xml:space="preserve">
<source>bad message ID</source> <source>bad message ID</source>
<target>メッセージ ID が正しくありません</target> <target>メッセージ ID が正しくありません</target>
@@ -299,12 +299,10 @@
</trans-unit> </trans-unit>
<trans-unit id="(new)" xml:space="preserve"> <trans-unit id="(new)" xml:space="preserve">
<source>(new)</source> <source>(new)</source>
<target>(nieuw)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="(this device v%@)" xml:space="preserve"> <trans-unit id="(this device v%@)" xml:space="preserve">
<source>(this device v%@)</source> <source>(this device v%@)</source>
<target>(dit apparaat v%@)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id=")" xml:space="preserve"> <trans-unit id=")" xml:space="preserve">
@@ -312,17 +310,14 @@
<target>)</target> <target>)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve">
<source>**Add contact**: to create a new invitation link, or connect via a link you received.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target>**Nieuw contact toevoegen**: om uw eenmalige QR-code of link voor uw contact te maken.</target> <target>**Nieuw contact toevoegen**: om uw eenmalige QR-code of link voor uw contact te maken.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Create group**: to create a new group." xml:space="preserve"> <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<source>**Create group**: to create a new group.</source> <source>**Create link / QR code** for your contact to use.</source>
<target>**Maak een link / QR-code aan** die uw contact kan gebruiken.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -335,6 +330,11 @@
<target>**Meest privé**: gebruik geen SimpleX Chat-notificatie server, controleer berichten regelmatig op de achtergrond (afhankelijk van hoe vaak u de app gebruikt).</target> <target>**Meest privé**: gebruik geen SimpleX Chat-notificatie server, controleer berichten regelmatig op de achtergrond (afhankelijk van hoe vaak u de app gebruikt).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve">
<source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source>
<target>**Plak de ontvangen link** of open deze in de browser en tik op **Openen in mobiele app**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve">
<source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source>
<target>**Let op**: u kunt het wachtwoord NIET herstellen of wijzigen als u het kwijtraakt.</target> <target>**Let op**: u kunt het wachtwoord NIET herstellen of wijzigen als u het kwijtraakt.</target>
@@ -345,6 +345,11 @@
<target>**Aanbevolen**: apparaattoken en meldingen worden naar de SimpleX Chat-meldingsserver gestuurd, maar niet de berichtinhoud, -grootte of van wie het afkomstig is.</target> <target>**Aanbevolen**: apparaattoken en meldingen worden naar de SimpleX Chat-meldingsserver gestuurd, maar niet de berichtinhoud, -grootte of van wie het afkomstig is.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve">
<source>**Scan QR code**: to connect to your contact in person or via video call.</source>
<target>**Scan QR-code**: om persoonlijk of via een video gesprek verbinding te maken met uw contact.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target>**Waarschuwing**: voor directe push meldingen is een wachtwoord vereist dat is opgeslagen in de Keychain.</target> <target>**Waarschuwing**: voor directe push meldingen is een wachtwoord vereist dat is opgeslagen in de Keychain.</target>
@@ -385,15 +390,6 @@
- and more!</source> - and more!</source>
<target>- stabielere berichtbezorging. <target>- stabielere berichtbezorging.
- een beetje betere groepen. - een beetje betere groepen.
- en meer!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- optionally notify deleted contacts.&#10;- profile names with spaces.&#10;- and more!" xml:space="preserve">
<source>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</source>
<target>- optioneel verwijderde contacten op de hoogte stellen.
- profielnamen met spaties.
- en meer!</target> - en meer!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
@@ -446,6 +442,11 @@
<target>1 week</target> <target>1 week</target>
<note>time interval</note> <note>time interval</note>
</trans-unit> </trans-unit>
<trans-unit id="1-time link" xml:space="preserve">
<source>1-time link</source>
<target>Eenmalige link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="5 minutes" xml:space="preserve"> <trans-unit id="5 minutes" xml:space="preserve">
<source>5 minutes</source> <source>5 minutes</source>
<target>5 minuten</target> <target>5 minuten</target>
@@ -561,10 +562,6 @@
<target>Voeg een adres toe aan uw profiel, zodat uw contacten het met andere mensen kunnen delen. Profiel update wordt naar uw contacten verzonden.</target> <target>Voeg een adres toe aan uw profiel, zodat uw contacten het met andere mensen kunnen delen. Profiel update wordt naar uw contacten verzonden.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add contact" xml:space="preserve">
<source>Add contact</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve"> <trans-unit id="Add preset servers" xml:space="preserve">
<source>Add preset servers</source> <source>Add preset servers</source>
<target>Vooraf ingestelde servers toevoegen</target> <target>Vooraf ingestelde servers toevoegen</target>
@@ -762,7 +759,7 @@
</trans-unit> </trans-unit>
<trans-unit id="Always use relay" xml:space="preserve"> <trans-unit id="Always use relay" xml:space="preserve">
<source>Always use relay</source> <source>Always use relay</source>
<target>Altijd relay gebruiken</target> <target>Verbinden via relais</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="An empty chat profile with the provided name is created, and the app opens as usual." xml:space="preserve"> <trans-unit id="An empty chat profile with the provided name is created, and the app opens as usual." xml:space="preserve">
@@ -882,7 +879,6 @@
</trans-unit> </trans-unit>
<trans-unit id="Bad desktop address" xml:space="preserve"> <trans-unit id="Bad desktop address" xml:space="preserve">
<source>Bad desktop address</source> <source>Bad desktop address</source>
<target>Onjuist desktopadres</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Bad message ID" xml:space="preserve"> <trans-unit id="Bad message ID" xml:space="preserve">
@@ -895,11 +891,6 @@
<target>Onjuiste bericht hash</target> <target>Onjuiste bericht hash</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
<source>Better groups</source>
<target>Betere groepen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better messages" xml:space="preserve"> <trans-unit id="Better messages" xml:space="preserve">
<source>Better messages</source> <source>Better messages</source>
<target>Betere berichten</target> <target>Betere berichten</target>
@@ -910,11 +901,6 @@
<target>Blokkeren</target> <target>Blokkeren</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
<source>Block group members</source>
<target>Groepsleden blokkeren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve"> <trans-unit id="Block member" xml:space="preserve">
<source>Block member</source> <source>Block member</source>
<target>Lid blokkeren</target> <target>Lid blokkeren</target>
@@ -970,10 +956,6 @@
<target>Oproepen</target> <target>Oproepen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Camera not available" xml:space="preserve">
<source>Camera not available</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Can't delete user profile!" xml:space="preserve"> <trans-unit id="Can't delete user profile!" xml:space="preserve">
<source>Can't delete user profile!</source> <source>Can't delete user profile!</source>
<target>Kan gebruikers profiel niet verwijderen!</target> <target>Kan gebruikers profiel niet verwijderen!</target>
@@ -1090,10 +1072,6 @@
<target>Chat is gestopt</target> <target>Chat is gestopt</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve">
<source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve"> <trans-unit id="Chat preferences" xml:space="preserve">
<source>Chat preferences</source> <source>Chat preferences</source>
<target>Gesprek voorkeuren</target> <target>Gesprek voorkeuren</target>
@@ -1194,11 +1172,6 @@
<target>Verbind</target> <target>Verbind</target>
<note>server test step</note> <note>server test step</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect automatically" xml:space="preserve">
<source>Connect automatically</source>
<target>Automatisch verbinden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve"> <trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source> <source>Connect incognito</source>
<target>Verbind incognito</target> <target>Verbind incognito</target>
@@ -1206,7 +1179,6 @@
</trans-unit> </trans-unit>
<trans-unit id="Connect to desktop" xml:space="preserve"> <trans-unit id="Connect to desktop" xml:space="preserve">
<source>Connect to desktop</source> <source>Connect to desktop</source>
<target>Verbinden met desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve"> <trans-unit id="Connect to yourself?" xml:space="preserve">
@@ -1238,6 +1210,11 @@ Dit is uw eigen eenmalige link!</target>
<target>Maak verbinding via link</target> <target>Maak verbinding via link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link / QR code" xml:space="preserve">
<source>Connect via link / QR code</source>
<target>Maak verbinding via link / QR-code</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link" xml:space="preserve"> <trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source> <source>Connect via one-time link</source>
<target>Verbinden via een eenmalige link?</target> <target>Verbinden via een eenmalige link?</target>
@@ -1250,12 +1227,10 @@ Dit is uw eigen eenmalige link!</target>
</trans-unit> </trans-unit>
<trans-unit id="Connected desktop" xml:space="preserve"> <trans-unit id="Connected desktop" xml:space="preserve">
<source>Connected desktop</source> <source>Connected desktop</source>
<target>Verbonden desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connected to desktop" xml:space="preserve"> <trans-unit id="Connected to desktop" xml:space="preserve">
<source>Connected to desktop</source> <source>Connected to desktop</source>
<target>Verbonden met desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve"> <trans-unit id="Connecting server…" xml:space="preserve">
@@ -1270,7 +1245,6 @@ Dit is uw eigen eenmalige link!</target>
</trans-unit> </trans-unit>
<trans-unit id="Connecting to desktop" xml:space="preserve"> <trans-unit id="Connecting to desktop" xml:space="preserve">
<source>Connecting to desktop</source> <source>Connecting to desktop</source>
<target>Verbinding maken met desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connection" xml:space="preserve"> <trans-unit id="Connection" xml:space="preserve">
@@ -1295,7 +1269,6 @@ Dit is uw eigen eenmalige link!</target>
</trans-unit> </trans-unit>
<trans-unit id="Connection terminated" xml:space="preserve"> <trans-unit id="Connection terminated" xml:space="preserve">
<source>Connection terminated</source> <source>Connection terminated</source>
<target>Verbinding beëindigd</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connection timeout" xml:space="preserve"> <trans-unit id="Connection timeout" xml:space="preserve">
@@ -1378,11 +1351,6 @@ Dit is uw eigen eenmalige link!</target>
<target>Maak een SimpleX adres aan</target> <target>Maak een SimpleX adres aan</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create a group using a random profile." xml:space="preserve">
<source>Create a group using a random profile.</source>
<target>Maak een groep met een willekeurig profiel.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source> <source>Create an address to let people connect with you.</source>
<target>Maak een adres aan zodat mensen contact met je kunnen opnemen.</target> <target>Maak een adres aan zodat mensen contact met je kunnen opnemen.</target>
@@ -1413,6 +1381,11 @@ Dit is uw eigen eenmalige link!</target>
<target>Maak een nieuw profiel aan in [desktop-app](https://simplex.chat/downloads/). 💻</target> <target>Maak een nieuw profiel aan in [desktop-app](https://simplex.chat/downloads/). 💻</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create one-time invitation link" xml:space="preserve">
<source>Create one-time invitation link</source>
<target>Maak een eenmalige uitnodiging link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<target>Maak een profiel aan</target> <target>Maak een profiel aan</target>
@@ -1438,10 +1411,6 @@ Dit is uw eigen eenmalige link!</target>
<target>Gemaakt op %@</target> <target>Gemaakt op %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve"> <trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source> <source>Current Passcode</source>
<target>Huidige toegangscode</target> <target>Huidige toegangscode</target>
@@ -1612,7 +1581,7 @@ Dit is uw eigen eenmalige link!</target>
</trans-unit> </trans-unit>
<trans-unit id="Delete and notify contact" xml:space="preserve"> <trans-unit id="Delete and notify contact" xml:space="preserve">
<source>Delete and notify contact</source> <source>Delete and notify contact</source>
<target>Verwijderen en contact op de hoogte stellen</target> <target>Contact verwijderen en op de hoogte stellen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Delete archive" xml:space="preserve"> <trans-unit id="Delete archive" xml:space="preserve">
@@ -1794,17 +1763,14 @@ Dit kan niet ongedaan gemaakt worden!</target>
</trans-unit> </trans-unit>
<trans-unit id="Desktop address" xml:space="preserve"> <trans-unit id="Desktop address" xml:space="preserve">
<source>Desktop address</source> <source>Desktop address</source>
<target>Desktop adres</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve"> <trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve">
<source>Desktop app version %@ is not compatible with this app.</source> <source>Desktop app version %@ is not compatible with this app.</source>
<target>Desktop-app-versie %@ is niet compatibel met deze app.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Desktop devices" xml:space="preserve"> <trans-unit id="Desktop devices" xml:space="preserve">
<source>Desktop devices</source> <source>Desktop devices</source>
<target>Desktop apparaten</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Develop" xml:space="preserve"> <trans-unit id="Develop" xml:space="preserve">
@@ -1899,7 +1865,6 @@ Dit kan niet ongedaan gemaakt worden!</target>
</trans-unit> </trans-unit>
<trans-unit id="Disconnect desktop?" xml:space="preserve"> <trans-unit id="Disconnect desktop?" xml:space="preserve">
<source>Disconnect desktop?</source> <source>Disconnect desktop?</source>
<target>Desktop loskoppelen?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover and join groups" xml:space="preserve"> <trans-unit id="Discover and join groups" xml:space="preserve">
@@ -1907,9 +1872,8 @@ Dit kan niet ongedaan gemaakt worden!</target>
<target>Ontdek en sluit je aan bij groepen</target> <target>Ontdek en sluit je aan bij groepen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve"> <trans-unit id="Discover on network" xml:space="preserve">
<source>Discover via local network</source> <source>Discover on network</source>
<target>Ontdek via het lokale netwerk</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -1992,10 +1956,6 @@ Dit kan niet ongedaan gemaakt worden!</target>
<target>Automatisch verwijderen van berichten aanzetten?</target> <target>Automatisch verwijderen van berichten aanzetten?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enable camera access" xml:space="preserve">
<source>Enable camera access</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve"> <trans-unit id="Enable for all" xml:space="preserve">
<source>Enable for all</source> <source>Enable for all</source>
<target>Inschakelen voor iedereen</target> <target>Inschakelen voor iedereen</target>
@@ -2061,10 +2021,6 @@ Dit kan niet ongedaan gemaakt worden!</target>
<target>Versleuteld bericht of een andere gebeurtenis</target> <target>Versleuteld bericht of een andere gebeurtenis</target>
<note>notification</note> <note>notification</note>
</trans-unit> </trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve">
<source>Encrypted message: app is stopped</source>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve"> <trans-unit id="Encrypted message: database error" xml:space="preserve">
<source>Encrypted message: database error</source> <source>Encrypted message: database error</source>
<target>Versleuteld bericht: database fout</target> <target>Versleuteld bericht: database fout</target>
@@ -2092,12 +2048,10 @@ Dit kan niet ongedaan gemaakt worden!</target>
</trans-unit> </trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve"> <trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source> <source>Encryption re-negotiation error</source>
<target>Fout bij heronderhandeling van codering</target>
<note>message decrypt error item</note> <note>message decrypt error item</note>
</trans-unit> </trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve"> <trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source> <source>Encryption re-negotiation failed.</source>
<target>Opnieuw onderhandelen over de codering is mislukt.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve"> <trans-unit id="Enter Passcode" xml:space="preserve">
@@ -2132,7 +2086,6 @@ Dit kan niet ongedaan gemaakt worden!</target>
</trans-unit> </trans-unit>
<trans-unit id="Enter this device name…" xml:space="preserve"> <trans-unit id="Enter this device name…" xml:space="preserve">
<source>Enter this device name…</source> <source>Enter this device name…</source>
<target>Voer deze apparaatnaam in…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enter welcome message…" xml:space="preserve"> <trans-unit id="Enter welcome message…" xml:space="preserve">
@@ -2295,10 +2248,6 @@ Dit kan niet ongedaan gemaakt worden!</target>
<target>Fout bij het laden van %@ servers</target> <target>Fout bij het laden van %@ servers</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error receiving file" xml:space="preserve"> <trans-unit id="Error receiving file" xml:space="preserve">
<source>Error receiving file</source> <source>Error receiving file</source>
<target>Fout bij ontvangen van bestand</target> <target>Fout bij ontvangen van bestand</target>
@@ -2339,10 +2288,6 @@ Dit kan niet ongedaan gemaakt worden!</target>
<target>Fout bij opslaan gebruikers wachtwoord</target> <target>Fout bij opslaan gebruikers wachtwoord</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error scanning code: %@" xml:space="preserve">
<source>Error scanning code: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve"> <trans-unit id="Error sending email" xml:space="preserve">
<source>Error sending email</source> <source>Error sending email</source>
<target>Fout bij het verzenden van e-mail</target> <target>Fout bij het verzenden van e-mail</target>
@@ -2435,7 +2380,7 @@ Dit kan niet ongedaan gemaakt worden!</target>
</trans-unit> </trans-unit>
<trans-unit id="Expand" xml:space="preserve"> <trans-unit id="Expand" xml:space="preserve">
<source>Expand</source> <source>Expand</source>
<target>Uitklappen</target> <target>Uitbreiden</target>
<note>chat item action</note> <note>chat item action</note>
</trans-unit> </trans-unit>
<trans-unit id="Export database" xml:space="preserve"> <trans-unit id="Export database" xml:space="preserve">
@@ -2468,11 +2413,6 @@ Dit kan niet ongedaan gemaakt worden!</target>
<target>Snel en niet wachten tot de afzender online is!</target> <target>Snel en niet wachten tot de afzender online is!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<target>Snellere deelname en betrouwbaardere berichten.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve"> <trans-unit id="Favorite" xml:space="preserve">
<source>Favorite</source> <source>Favorite</source>
<target>Favoriet</target> <target>Favoriet</target>
@@ -2568,11 +2508,6 @@ Dit kan niet ongedaan gemaakt worden!</target>
<target>Voor console</target> <target>Voor console</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Found desktop" xml:space="preserve">
<source>Found desktop</source>
<target>Desktop gevonden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="French interface" xml:space="preserve"> <trans-unit id="French interface" xml:space="preserve">
<source>French interface</source> <source>French interface</source>
<target>Franse interface</target> <target>Franse interface</target>
@@ -2818,6 +2753,11 @@ Dit kan niet ongedaan gemaakt worden!</target>
<target>Als je elkaar niet persoonlijk kunt ontmoeten, laat dan de QR-code zien in een videogesprek of deel de link.</target> <target>Als je elkaar niet persoonlijk kunt ontmoeten, laat dan de QR-code zien in een videogesprek of deel de link.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve">
<source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source>
<target>Als u elkaar niet persoonlijk kunt ontmoeten, kunt u **de QR-code scannen in het video gesprek**, of uw contact kan een uitnodiging link delen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve">
<source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source>
<target>Als u deze toegangscode invoert bij het openen van de app, worden alle app-gegevens onomkeerbaar verwijderd!</target> <target>Als u deze toegangscode invoert bij het openen van de app, worden alle app-gegevens onomkeerbaar verwijderd!</target>
@@ -2893,11 +2833,6 @@ Dit kan niet ongedaan gemaakt worden!</target>
<target>Incognito</target> <target>Incognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<target>Incognitogroepen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve"> <trans-unit id="Incognito mode" xml:space="preserve">
<source>Incognito mode</source> <source>Incognito mode</source>
<target>Incognito modus</target> <target>Incognito modus</target>
@@ -2930,7 +2865,6 @@ Dit kan niet ongedaan gemaakt worden!</target>
</trans-unit> </trans-unit>
<trans-unit id="Incompatible version" xml:space="preserve"> <trans-unit id="Incompatible version" xml:space="preserve">
<source>Incompatible version</source> <source>Incompatible version</source>
<target>Incompatibele versie</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incorrect passcode" xml:space="preserve"> <trans-unit id="Incorrect passcode" xml:space="preserve">
@@ -2967,7 +2901,7 @@ Dit kan niet ongedaan gemaakt worden!</target>
</trans-unit> </trans-unit>
<trans-unit id="Instantly" xml:space="preserve"> <trans-unit id="Instantly" xml:space="preserve">
<source>Instantly</source> <source>Instantly</source>
<target>Direct</target> <target>Meteen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Interface" xml:space="preserve"> <trans-unit id="Interface" xml:space="preserve">
@@ -2975,28 +2909,16 @@ Dit kan niet ongedaan gemaakt worden!</target>
<target>Interface</target> <target>Interface</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid QR code" xml:space="preserve">
<source>Invalid QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve"> <trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source> <source>Invalid connection link</source>
<target>Ongeldige verbinding link</target> <target>Ongeldige verbinding link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
<source>Invalid link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve"> <trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source> <source>Invalid name!</source>
<target>Ongeldige naam!</target> <target>Ongeldige naam!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid response" xml:space="preserve">
<source>Invalid response</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve"> <trans-unit id="Invalid server address!" xml:space="preserve">
<source>Invalid server address!</source> <source>Invalid server address!</source>
<target>Ongeldig server adres!</target> <target>Ongeldig server adres!</target>
@@ -3115,17 +3037,8 @@ Dit is jouw link voor groep %@!</target>
<target>Deel nemen aan groep</target> <target>Deel nemen aan groep</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep" xml:space="preserve">
<source>Keep</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
<source>Keep the app open to use it from desktop</source> <source>Keep the app open to use it from desktop</source>
<target>Houd de app geopend om deze vanaf de desktop te gebruiken</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep unused invitation?" xml:space="preserve">
<source>Keep unused invitation?</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve"> <trans-unit id="Keep your connections" xml:space="preserve">
@@ -3188,19 +3101,12 @@ Dit is jouw link voor groep %@!</target>
<target>Beperkingen</target> <target>Beperkingen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<target>Koppel mobiele en desktop-apps! 🔗</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve"> <trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source> <source>Linked desktop options</source>
<target>Gekoppelde desktop opties</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Linked desktops" xml:space="preserve"> <trans-unit id="Linked desktops" xml:space="preserve">
<source>Linked desktops</source> <source>Linked desktops</source>
<target>Gelinkte desktops</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Live message!" xml:space="preserve"> <trans-unit id="Live message!" xml:space="preserve">
@@ -3213,11 +3119,6 @@ Dit is jouw link voor groep %@!</target>
<target>Live berichten</target> <target>Live berichten</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Local" xml:space="preserve">
<source>Local</source>
<target>Lokaal</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Local name" xml:space="preserve"> <trans-unit id="Local name" xml:space="preserve">
<source>Local name</source> <source>Local name</source>
<target>Lokale naam</target> <target>Lokale naam</target>
@@ -3458,10 +3359,6 @@ Dit is jouw link voor groep %@!</target>
<target>Nieuwe toegangscode</target> <target>Nieuwe toegangscode</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="New chat" xml:space="preserve">
<source>New chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve"> <trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source> <source>New contact request</source>
<target>Nieuw contactverzoek</target> <target>Nieuw contactverzoek</target>
@@ -3562,11 +3459,6 @@ Dit is jouw link voor groep %@!</target>
<target>Geen ontvangen of verzonden bestanden</target> <target>Geen ontvangen of verzonden bestanden</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Not compatible!" xml:space="preserve">
<source>Not compatible!</source>
<target>Niet compatibel!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve"> <trans-unit id="Notifications" xml:space="preserve">
<source>Notifications</source> <source>Notifications</source>
<target>Meldingen</target> <target>Meldingen</target>
@@ -3586,15 +3478,16 @@ Dit is jouw link voor groep %@!</target>
- schakel leden uit ("waarnemer" rol)</target> - schakel leden uit ("waarnemer" rol)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="OK" xml:space="preserve">
<source>OK</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Off" xml:space="preserve"> <trans-unit id="Off" xml:space="preserve">
<source>Off</source> <source>Off</source>
<target>Uit</target> <target>Uit</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Off (Local)" xml:space="preserve">
<source>Off (Local)</source>
<target>Uit (lokaal)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ok" xml:space="preserve"> <trans-unit id="Ok" xml:space="preserve">
<source>Ok</source> <source>Ok</source>
<target>OK</target> <target>OK</target>
@@ -3735,16 +3628,9 @@ Dit is jouw link voor groep %@!</target>
<target>Open-source protocol en code. Iedereen kan de servers draaien.</target> <target>Open-source protocol en code. Iedereen kan de servers draaien.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Opening app…" xml:space="preserve"> <trans-unit id="Opening database…" xml:space="preserve">
<source>Opening app…</source> <source>Opening database…</source>
<note>No comment provided by engineer.</note> <target>Database openen…</target>
</trans-unit>
<trans-unit id="Or scan QR code" xml:space="preserve">
<source>Or scan QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
<source>Or show this code</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="PING count" xml:space="preserve"> <trans-unit id="PING count" xml:space="preserve">
@@ -3787,9 +3673,13 @@ Dit is jouw link voor groep %@!</target>
<target>Wachtwoord om weer te geven</target> <target>Wachtwoord om weer te geven</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste" xml:space="preserve">
<source>Paste</source>
<target>Plakken</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve"> <trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source> <source>Paste desktop address</source>
<target>Desktopadres plakken</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste image" xml:space="preserve"> <trans-unit id="Paste image" xml:space="preserve">
@@ -3797,10 +3687,16 @@ Dit is jouw link voor groep %@!</target>
<target>Afbeelding plakken</target> <target>Afbeelding plakken</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve"> <trans-unit id="Paste received link" xml:space="preserve">
<source>Paste the link you received</source> <source>Paste received link</source>
<target>Plak de ontvangen link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Plak de link die je hebt ontvangen in het vak hieronder om verbinding te maken met je contact.</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source> <source>People can connect to you only via the links you share.</source>
<target>Mensen kunnen alleen verbinding met u maken via de links die u deelt.</target> <target>Mensen kunnen alleen verbinding met u maken via de links die u deelt.</target>
@@ -3836,11 +3732,6 @@ Dit is jouw link voor groep %@!</target>
<target>Controleer de uwe en uw contact voorkeuren.</target> <target>Controleer de uwe en uw contact voorkeuren.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Please contact developers.&#10;Error: %@" xml:space="preserve">
<source>Please contact developers.
Error: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please contact group admin." xml:space="preserve"> <trans-unit id="Please contact group admin." xml:space="preserve">
<source>Please contact group admin.</source> <source>Please contact group admin.</source>
<target>Neem contact op met de groep beheerder.</target> <target>Neem contact op met de groep beheerder.</target>
@@ -4046,10 +3937,6 @@ Error: %@</source>
<target>Lees meer in de [Gebruikershandleiding](https://simplex.chat/docs/guide/app-settings.html#uw-simplex-contactadres).</target> <target>Lees meer in de [Gebruikershandleiding](https://simplex.chat/docs/guide/app-settings.html#uw-simplex-contactadres).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source>
<target>Lees meer in de [Gebruikershandleiding](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> <target>Lees meer in de [Gebruikershandleiding](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target>
@@ -4260,10 +4147,6 @@ Error: %@</source>
<target>Database fout herstellen</target> <target>Database fout herstellen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Retry" xml:space="preserve">
<source>Retry</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reveal" xml:space="preserve"> <trans-unit id="Reveal" xml:space="preserve">
<source>Reveal</source> <source>Reveal</source>
<target>Onthullen</target> <target>Onthullen</target>
@@ -4396,7 +4279,6 @@ Error: %@</source>
</trans-unit> </trans-unit>
<trans-unit id="Scan QR code from desktop" xml:space="preserve"> <trans-unit id="Scan QR code from desktop" xml:space="preserve">
<source>Scan QR code from desktop</source> <source>Scan QR code from desktop</source>
<target>Scan QR-code vanaf uw desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Scan code" xml:space="preserve"> <trans-unit id="Scan code" xml:space="preserve">
@@ -4419,10 +4301,6 @@ Error: %@</source>
<target>Zoeken</target> <target>Zoeken</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve"> <trans-unit id="Secure queue" xml:space="preserve">
<source>Secure queue</source> <source>Secure queue</source>
<target>Veilige wachtrij</target> <target>Veilige wachtrij</target>
@@ -4625,7 +4503,6 @@ Error: %@</source>
</trans-unit> </trans-unit>
<trans-unit id="Session code" xml:space="preserve"> <trans-unit id="Session code" xml:space="preserve">
<source>Session code</source> <source>Session code</source>
<target>Sessie code</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Set 1 day" xml:space="preserve"> <trans-unit id="Set 1 day" xml:space="preserve">
@@ -4698,8 +4575,9 @@ Error: %@</source>
<target>Deel link</target> <target>Deel link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve"> <trans-unit id="Share one-time invitation link" xml:space="preserve">
<source>Share this 1-time invite link</source> <source>Share one-time invitation link</source>
<target>Eenmalige uitnodiging link delen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve"> <trans-unit id="Share with contacts" xml:space="preserve">
@@ -4822,15 +4700,16 @@ Error: %@</source>
<target>Iemand</target> <target>Iemand</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="Start a new chat" xml:space="preserve">
<source>Start a new chat</source>
<target>Begin een nieuw gesprek</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start chat" xml:space="preserve"> <trans-unit id="Start chat" xml:space="preserve">
<source>Start chat</source> <source>Start chat</source>
<target>Begin gesprek</target> <target>Begin gesprek</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Start chat?" xml:space="preserve">
<source>Start chat?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start migration" xml:space="preserve"> <trans-unit id="Start migration" xml:space="preserve">
<source>Start migration</source> <source>Start migration</source>
<target>Start migratie</target> <target>Start migratie</target>
@@ -4956,14 +4835,6 @@ Error: %@</source>
<target>Tik om incognito lid te worden</target> <target>Tik om incognito lid te worden</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Tap to paste link" xml:space="preserve">
<source>Tap to paste link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to scan" xml:space="preserve">
<source>Tap to scan</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve"> <trans-unit id="Tap to start a new chat" xml:space="preserve">
<source>Tap to start a new chat</source> <source>Tap to start a new chat</source>
<target>Tik om een nieuw gesprek te starten</target> <target>Tik om een nieuw gesprek te starten</target>
@@ -5026,10 +4897,6 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target>
<target>De poging om het wachtwoord van de database te wijzigen is niet voltooid.</target> <target>De poging om het wachtwoord van de database te wijzigen is niet voltooid.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source> <source>The connection you accepted will be cancelled!</source>
<target>De door u geaccepteerde verbinding wordt geannuleerd!</target> <target>De door u geaccepteerde verbinding wordt geannuleerd!</target>
@@ -5095,10 +4962,6 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target>
<target>De servers voor nieuwe verbindingen van uw huidige chat profiel **%@**.</target> <target>De servers voor nieuwe verbindingen van uw huidige chat profiel **%@**.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve">
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve"> <trans-unit id="Theme" xml:space="preserve">
<source>Theme</source> <source>Theme</source>
<target>Thema</target> <target>Thema</target>
@@ -5141,7 +5004,6 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target>
</trans-unit> </trans-unit>
<trans-unit id="This device name" xml:space="preserve"> <trans-unit id="This device name" xml:space="preserve">
<source>This device name</source> <source>This device name</source>
<target>Deze apparaatnaam</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
@@ -5179,11 +5041,6 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target>
<target>Om verbinding te maken, kan uw contact de QR-code scannen of de link in de app gebruiken.</target> <target>Om verbinding te maken, kan uw contact de QR-code scannen of de link in de app gebruiken.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<target>Om ongewenste berichten te verbergen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve"> <trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source> <source>To make a new connection</source>
<target>Om een nieuwe verbinding te maken</target> <target>Om een nieuwe verbinding te maken</target>
@@ -5251,6 +5108,11 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc
<target>Uitschakelen</target> <target>Uitschakelen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Turn off notifications?" xml:space="preserve">
<source>Turn off notifications?</source>
<target>Schakel meldingen uit?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn on" xml:space="preserve"> <trans-unit id="Turn on" xml:space="preserve">
<source>Turn on</source> <source>Turn on</source>
<target>Zet aan</target> <target>Zet aan</target>
@@ -5340,12 +5202,10 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
</trans-unit> </trans-unit>
<trans-unit id="Unlink" xml:space="preserve"> <trans-unit id="Unlink" xml:space="preserve">
<source>Unlink</source> <source>Unlink</source>
<target>Ontkoppelen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Unlink desktop?" xml:space="preserve"> <trans-unit id="Unlink desktop?" xml:space="preserve">
<source>Unlink desktop?</source> <source>Unlink desktop?</source>
<target>Desktop ontkoppelen?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Unlock" xml:space="preserve"> <trans-unit id="Unlock" xml:space="preserve">
@@ -5440,7 +5300,6 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
</trans-unit> </trans-unit>
<trans-unit id="Use from desktop" xml:space="preserve"> <trans-unit id="Use from desktop" xml:space="preserve">
<source>Use from desktop</source> <source>Use from desktop</source>
<target>Gebruik vanaf desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use iOS call interface" xml:space="preserve"> <trans-unit id="Use iOS call interface" xml:space="preserve">
@@ -5453,10 +5312,6 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
<target>Gebruik een nieuw incognitoprofiel</target> <target>Gebruik een nieuw incognitoprofiel</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use only local notifications?" xml:space="preserve">
<source>Use only local notifications?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve"> <trans-unit id="Use server" xml:space="preserve">
<source>Use server</source> <source>Use server</source>
<target>Gebruik server</target> <target>Gebruik server</target>
@@ -5479,12 +5334,10 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
</trans-unit> </trans-unit>
<trans-unit id="Verify code with desktop" xml:space="preserve"> <trans-unit id="Verify code with desktop" xml:space="preserve">
<source>Verify code with desktop</source> <source>Verify code with desktop</source>
<target>Code verifiëren met desktop</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify connection" xml:space="preserve"> <trans-unit id="Verify connection" xml:space="preserve">
<source>Verify connection</source> <source>Verify connection</source>
<target>Controleer de verbinding</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify connection security" xml:space="preserve"> <trans-unit id="Verify connection security" xml:space="preserve">
@@ -5494,7 +5347,6 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
</trans-unit> </trans-unit>
<trans-unit id="Verify connections" xml:space="preserve"> <trans-unit id="Verify connections" xml:space="preserve">
<source>Verify connections</source> <source>Verify connections</source>
<target>Controleer verbindingen</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify security code" xml:space="preserve"> <trans-unit id="Verify security code" xml:space="preserve">
@@ -5507,11 +5359,6 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
<target>Via browser</target> <target>Via browser</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<target>Via een beveiligd kwantumbestendig protocol.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve"> <trans-unit id="Video call" xml:space="preserve">
<source>Video call</source> <source>Video call</source>
<target>video oproep</target> <target>video oproep</target>
@@ -5562,11 +5409,6 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
<target>Spraakbericht…</target> <target>Spraakbericht…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Waiting for desktop..." xml:space="preserve">
<source>Waiting for desktop...</source>
<target>Wachten op desktop...</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Waiting for file" xml:space="preserve"> <trans-unit id="Waiting for file" xml:space="preserve">
<source>Waiting for file</source> <source>Waiting for file</source>
<target>Wachten op bestand</target> <target>Wachten op bestand</target>
@@ -5719,6 +5561,11 @@ Deelnameverzoek herhalen?</target>
<target>U kunt oproepen van het vergrendelingsscherm accepteren, zonder apparaat- en app-verificatie.</target> <target>U kunt oproepen van het vergrendelingsscherm accepteren, zonder apparaat- en app-verificatie.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve">
<source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source>
<target>U kunt ook verbinding maken door op de link te klikken. Als het in de browser wordt geopend, klikt u op de knop **Openen in mobiele app**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can create it later" xml:space="preserve"> <trans-unit id="You can create it later" xml:space="preserve">
<source>You can create it later</source> <source>You can create it later</source>
<target>U kan het later maken</target> <target>U kan het later maken</target>
@@ -5739,10 +5586,6 @@ Deelnameverzoek herhalen?</target>
<target>U kunt een gebruikers profiel verbergen of dempen - veeg het naar rechts.</target> <target>U kunt een gebruikers profiel verbergen of dempen - veeg het naar rechts.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now send messages to %@" xml:space="preserve"> <trans-unit id="You can now send messages to %@" xml:space="preserve">
<source>You can now send messages to %@</source> <source>You can now send messages to %@</source>
<target>Je kunt nu berichten sturen naar %@</target> <target>Je kunt nu berichten sturen naar %@</target>
@@ -5783,10 +5626,6 @@ Deelnameverzoek herhalen?</target>
<target>U kunt markdown gebruiken voor opmaak in berichten:</target> <target>U kunt markdown gebruiken voor opmaak in berichten:</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can view invitation link again in connection details." xml:space="preserve">
<source>You can view invitation link again in connection details.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can't send messages!" xml:space="preserve"> <trans-unit id="You can't send messages!" xml:space="preserve">
<source>You can't send messages!</source> <source>You can't send messages!</source>
<target>Je kunt geen berichten versturen!</target> <target>Je kunt geen berichten versturen!</target>
@@ -5976,6 +5815,13 @@ U kunt deze verbinding verbreken en het contact verwijderen en later proberen me
<target>Uw contacten kunnen volledige verwijdering van berichten toestaan.</target> <target>Uw contacten kunnen volledige verwijdering van berichten toestaan.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your contacts in SimpleX will see it.&#10;You can change it in Settings." xml:space="preserve">
<source>Your contacts in SimpleX will see it.
You can change it in Settings.</source>
<target>Uw contacten in SimpleX kunnen het zien.
U kunt dit wijzigen in Instellingen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve"> <trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source> <source>Your contacts will remain connected.</source>
<target>Uw contacten blijven verbonden.</target> <target>Uw contacten blijven verbonden.</target>
@@ -6108,11 +5954,6 @@ SimpleX servers kunnen uw profiel niet zien.</target>
<target>audio oproep (niet e2e versleuteld)</target> <target>audio oproep (niet e2e versleuteld)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="author" xml:space="preserve">
<source>author</source>
<target>auteur</target>
<note>member role</note>
</trans-unit>
<trans-unit id="bad message ID" xml:space="preserve"> <trans-unit id="bad message ID" xml:space="preserve">
<source>bad message ID</source> <source>bad message ID</source>
<target>Onjuiste bericht-ID</target> <target>Onjuiste bericht-ID</target>
@@ -6697,7 +6538,6 @@ SimpleX servers kunnen uw profiel niet zien.</target>
</trans-unit> </trans-unit>
<trans-unit id="v%@" xml:space="preserve"> <trans-unit id="v%@" xml:space="preserve">
<source>v%@</source> <source>v%@</source>
<target>v%@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="v%@ (%@)" xml:space="preserve"> <trans-unit id="v%@ (%@)" xml:space="preserve">
@@ -6722,7 +6562,7 @@ SimpleX servers kunnen uw profiel niet zien.</target>
</trans-unit> </trans-unit>
<trans-unit id="via relay" xml:space="preserve"> <trans-unit id="via relay" xml:space="preserve">
<source>via relay</source> <source>via relay</source>
<target>via relay</target> <target>via relais</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="video call (not e2e encrypted)" xml:space="preserve"> <trans-unit id="video call (not e2e encrypted)" xml:space="preserve">
@@ -6839,7 +6679,6 @@ SimpleX servers kunnen uw profiel niet zien.</target>
</trans-unit> </trans-unit>
<trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve"> <trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve">
<source>SimpleX uses local network access to allow using user chat profile via desktop app on the same network.</source> <source>SimpleX uses local network access to allow using user chat profile via desktop app on the same network.</source>
<target>SimpleX maakt gebruik van lokale netwerktoegang om het gebruik van een gebruikerschatprofiel via de desktop-app op hetzelfde netwerk mogelijk te maken.</target>
<note>Privacy - Local Network Usage Description</note> <note>Privacy - Local Network Usage Description</note>
</trans-unit> </trans-unit>
<trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve"> <trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve">
@@ -299,12 +299,10 @@
</trans-unit> </trans-unit>
<trans-unit id="(new)" xml:space="preserve"> <trans-unit id="(new)" xml:space="preserve">
<source>(new)</source> <source>(new)</source>
<target>(nowy)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="(this device v%@)" xml:space="preserve"> <trans-unit id="(this device v%@)" xml:space="preserve">
<source>(this device v%@)</source> <source>(this device v%@)</source>
<target>(to urządzenie v%@)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id=")" xml:space="preserve"> <trans-unit id=")" xml:space="preserve">
@@ -312,17 +310,14 @@
<target>)</target> <target>)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve">
<source>**Add contact**: to create a new invitation link, or connect via a link you received.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target>**Dodaj nowy kontakt**: aby stworzyć swój jednorazowy kod QR lub link dla kontaktu.</target> <target>**Dodaj nowy kontakt**: aby stworzyć swój jednorazowy kod QR lub link dla kontaktu.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Create group**: to create a new group." xml:space="preserve"> <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<source>**Create group**: to create a new group.</source> <source>**Create link / QR code** for your contact to use.</source>
<target>**Utwórz link / kod QR**, aby Twój kontakt mógł z niego skorzystać.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -335,6 +330,11 @@
<target>**Najbardziej prywatny**: nie korzystaj z serwera powiadomień SimpleX Chat, sprawdzaj wiadomości okresowo w tle (zależy jak często korzystasz z aplikacji).</target> <target>**Najbardziej prywatny**: nie korzystaj z serwera powiadomień SimpleX Chat, sprawdzaj wiadomości okresowo w tle (zależy jak często korzystasz z aplikacji).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve">
<source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source>
<target>**Wklej otrzymany link** lub otwórz go w przeglądarce i dotknij **Otwórz w aplikacji mobilnej**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve">
<source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source>
<target>**Uwaga**: NIE będziesz w stanie odzyskać lub zmienić hasła, jeśli je stracisz.</target> <target>**Uwaga**: NIE będziesz w stanie odzyskać lub zmienić hasła, jeśli je stracisz.</target>
@@ -345,6 +345,11 @@
<target>**Zalecane**: token urządzenia i powiadomienia są wysyłane do serwera powiadomień SimpleX Chat, ale nie treść wiadomości, rozmiar lub od kogo jest.</target> <target>**Zalecane**: token urządzenia i powiadomienia są wysyłane do serwera powiadomień SimpleX Chat, ale nie treść wiadomości, rozmiar lub od kogo jest.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve">
<source>**Scan QR code**: to connect to your contact in person or via video call.</source>
<target>**Skanuj kod QR**: aby połączyć się z kontaktem osobiście lub za pomocą połączenia wideo.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target>**Uwaga**: Natychmiastowe powiadomienia push wymagają hasła zapisanego w Keychain.</target> <target>**Uwaga**: Natychmiastowe powiadomienia push wymagają hasła zapisanego w Keychain.</target>
@@ -388,15 +393,6 @@
- i więcej!</target> - i więcej!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="- optionally notify deleted contacts.&#10;- profile names with spaces.&#10;- and more!" xml:space="preserve">
<source>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</source>
<target>- opcjonalnie powiadamiaj usunięte kontakty.
- nazwy profili ze spacją.
- i wiele więcej!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve"> <trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve">
<source>- voice messages up to 5 minutes. <source>- voice messages up to 5 minutes.
- custom time to disappear. - custom time to disappear.
@@ -446,6 +442,11 @@
<target>1 tydzień</target> <target>1 tydzień</target>
<note>time interval</note> <note>time interval</note>
</trans-unit> </trans-unit>
<trans-unit id="1-time link" xml:space="preserve">
<source>1-time link</source>
<target>1-razowy link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="5 minutes" xml:space="preserve"> <trans-unit id="5 minutes" xml:space="preserve">
<source>5 minutes</source> <source>5 minutes</source>
<target>5 minut</target> <target>5 minut</target>
@@ -561,10 +562,6 @@
<target>Dodaj adres do swojego profilu, aby Twoje kontakty mogły go udostępnić innym osobom. Aktualizacja profilu zostanie wysłana do Twoich kontaktów.</target> <target>Dodaj adres do swojego profilu, aby Twoje kontakty mogły go udostępnić innym osobom. Aktualizacja profilu zostanie wysłana do Twoich kontaktów.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add contact" xml:space="preserve">
<source>Add contact</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve"> <trans-unit id="Add preset servers" xml:space="preserve">
<source>Add preset servers</source> <source>Add preset servers</source>
<target>Dodaj gotowe serwery</target> <target>Dodaj gotowe serwery</target>
@@ -882,7 +879,6 @@
</trans-unit> </trans-unit>
<trans-unit id="Bad desktop address" xml:space="preserve"> <trans-unit id="Bad desktop address" xml:space="preserve">
<source>Bad desktop address</source> <source>Bad desktop address</source>
<target>Zły adres komputera</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Bad message ID" xml:space="preserve"> <trans-unit id="Bad message ID" xml:space="preserve">
@@ -895,11 +891,6 @@
<target>Zły hash wiadomości</target> <target>Zły hash wiadomości</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
<source>Better groups</source>
<target>Lepsze grupy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better messages" xml:space="preserve"> <trans-unit id="Better messages" xml:space="preserve">
<source>Better messages</source> <source>Better messages</source>
<target>Lepsze wiadomości</target> <target>Lepsze wiadomości</target>
@@ -910,11 +901,6 @@
<target>Zablokuj</target> <target>Zablokuj</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
<source>Block group members</source>
<target>Blokuj członków grupy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve"> <trans-unit id="Block member" xml:space="preserve">
<source>Block member</source> <source>Block member</source>
<target>Zablokuj członka</target> <target>Zablokuj członka</target>
@@ -970,10 +956,6 @@
<target>Połączenia</target> <target>Połączenia</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Camera not available" xml:space="preserve">
<source>Camera not available</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Can't delete user profile!" xml:space="preserve"> <trans-unit id="Can't delete user profile!" xml:space="preserve">
<source>Can't delete user profile!</source> <source>Can't delete user profile!</source>
<target>Nie można usunąć profilu użytkownika!</target> <target>Nie można usunąć profilu użytkownika!</target>
@@ -1090,10 +1072,6 @@
<target>Czat jest zatrzymany</target> <target>Czat jest zatrzymany</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve">
<source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve"> <trans-unit id="Chat preferences" xml:space="preserve">
<source>Chat preferences</source> <source>Chat preferences</source>
<target>Preferencje czatu</target> <target>Preferencje czatu</target>
@@ -1194,11 +1172,6 @@
<target>Połącz</target> <target>Połącz</target>
<note>server test step</note> <note>server test step</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect automatically" xml:space="preserve">
<source>Connect automatically</source>
<target>Łącz automatycznie</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve"> <trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source> <source>Connect incognito</source>
<target>Połącz incognito</target> <target>Połącz incognito</target>
@@ -1206,7 +1179,6 @@
</trans-unit> </trans-unit>
<trans-unit id="Connect to desktop" xml:space="preserve"> <trans-unit id="Connect to desktop" xml:space="preserve">
<source>Connect to desktop</source> <source>Connect to desktop</source>
<target>Połącz do komputera</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve"> <trans-unit id="Connect to yourself?" xml:space="preserve">
@@ -1238,6 +1210,11 @@ To jest twój jednorazowy link!</target>
<target>Połącz się przez link</target> <target>Połącz się przez link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link / QR code" xml:space="preserve">
<source>Connect via link / QR code</source>
<target>Połącz się przez link / kod QR</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link" xml:space="preserve"> <trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source> <source>Connect via one-time link</source>
<target>Połącz przez jednorazowy link</target> <target>Połącz przez jednorazowy link</target>
@@ -1250,12 +1227,10 @@ To jest twój jednorazowy link!</target>
</trans-unit> </trans-unit>
<trans-unit id="Connected desktop" xml:space="preserve"> <trans-unit id="Connected desktop" xml:space="preserve">
<source>Connected desktop</source> <source>Connected desktop</source>
<target>Połączony komputer</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connected to desktop" xml:space="preserve"> <trans-unit id="Connected to desktop" xml:space="preserve">
<source>Connected to desktop</source> <source>Connected to desktop</source>
<target>Połączony do komputera</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve"> <trans-unit id="Connecting server…" xml:space="preserve">
@@ -1270,7 +1245,6 @@ To jest twój jednorazowy link!</target>
</trans-unit> </trans-unit>
<trans-unit id="Connecting to desktop" xml:space="preserve"> <trans-unit id="Connecting to desktop" xml:space="preserve">
<source>Connecting to desktop</source> <source>Connecting to desktop</source>
<target>Łączenie z komputerem</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connection" xml:space="preserve"> <trans-unit id="Connection" xml:space="preserve">
@@ -1295,7 +1269,6 @@ To jest twój jednorazowy link!</target>
</trans-unit> </trans-unit>
<trans-unit id="Connection terminated" xml:space="preserve"> <trans-unit id="Connection terminated" xml:space="preserve">
<source>Connection terminated</source> <source>Connection terminated</source>
<target>Połączenie zakończone</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connection timeout" xml:space="preserve"> <trans-unit id="Connection timeout" xml:space="preserve">
@@ -1378,11 +1351,6 @@ To jest twój jednorazowy link!</target>
<target>Utwórz adres SimpleX</target> <target>Utwórz adres SimpleX</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create a group using a random profile." xml:space="preserve">
<source>Create a group using a random profile.</source>
<target>Utwórz grupę używając losowego profilu.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source> <source>Create an address to let people connect with you.</source>
<target>Utwórz adres, aby ludzie mogli się z Tobą połączyć.</target> <target>Utwórz adres, aby ludzie mogli się z Tobą połączyć.</target>
@@ -1413,6 +1381,11 @@ To jest twój jednorazowy link!</target>
<target>Utwórz nowy profil w [aplikacji desktopowej](https://simplex.chat/downloads/). 💻</target> <target>Utwórz nowy profil w [aplikacji desktopowej](https://simplex.chat/downloads/). 💻</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create one-time invitation link" xml:space="preserve">
<source>Create one-time invitation link</source>
<target>Utwórz jednorazowy link do zaproszenia</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<target>Utwórz profil</target> <target>Utwórz profil</target>
@@ -1438,10 +1411,6 @@ To jest twój jednorazowy link!</target>
<target>Utworzony w dniu %@</target> <target>Utworzony w dniu %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve"> <trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source> <source>Current Passcode</source>
<target>Aktualny Pin</target> <target>Aktualny Pin</target>
@@ -1794,17 +1763,14 @@ To nie może być cofnięte!</target>
</trans-unit> </trans-unit>
<trans-unit id="Desktop address" xml:space="preserve"> <trans-unit id="Desktop address" xml:space="preserve">
<source>Desktop address</source> <source>Desktop address</source>
<target>Adres komputera</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve"> <trans-unit id="Desktop app version %@ is not compatible with this app." xml:space="preserve">
<source>Desktop app version %@ is not compatible with this app.</source> <source>Desktop app version %@ is not compatible with this app.</source>
<target>Wersja aplikacji komputerowej %@ nie jest kompatybilna z tą aplikacją.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Desktop devices" xml:space="preserve"> <trans-unit id="Desktop devices" xml:space="preserve">
<source>Desktop devices</source> <source>Desktop devices</source>
<target>Urządzenia komputerowe</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Develop" xml:space="preserve"> <trans-unit id="Develop" xml:space="preserve">
@@ -1899,7 +1865,6 @@ To nie może być cofnięte!</target>
</trans-unit> </trans-unit>
<trans-unit id="Disconnect desktop?" xml:space="preserve"> <trans-unit id="Disconnect desktop?" xml:space="preserve">
<source>Disconnect desktop?</source> <source>Disconnect desktop?</source>
<target>Rozłączyć komputer?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover and join groups" xml:space="preserve"> <trans-unit id="Discover and join groups" xml:space="preserve">
@@ -1907,9 +1872,8 @@ To nie może być cofnięte!</target>
<target>Odkrywaj i dołączaj do grup</target> <target>Odkrywaj i dołączaj do grup</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve"> <trans-unit id="Discover on network" xml:space="preserve">
<source>Discover via local network</source> <source>Discover on network</source>
<target>Odkryj przez sieć lokalną</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -1992,10 +1956,6 @@ To nie może być cofnięte!</target>
<target>Czy włączyć automatyczne usuwanie wiadomości?</target> <target>Czy włączyć automatyczne usuwanie wiadomości?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enable camera access" xml:space="preserve">
<source>Enable camera access</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve"> <trans-unit id="Enable for all" xml:space="preserve">
<source>Enable for all</source> <source>Enable for all</source>
<target>Włącz dla wszystkich</target> <target>Włącz dla wszystkich</target>
@@ -2061,10 +2021,6 @@ To nie może być cofnięte!</target>
<target>Zaszyfrowana wiadomość lub inne zdarzenie</target> <target>Zaszyfrowana wiadomość lub inne zdarzenie</target>
<note>notification</note> <note>notification</note>
</trans-unit> </trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve">
<source>Encrypted message: app is stopped</source>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve"> <trans-unit id="Encrypted message: database error" xml:space="preserve">
<source>Encrypted message: database error</source> <source>Encrypted message: database error</source>
<target>Zaszyfrowana wiadomość: błąd bazy danych</target> <target>Zaszyfrowana wiadomość: błąd bazy danych</target>
@@ -2092,12 +2048,10 @@ To nie może być cofnięte!</target>
</trans-unit> </trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve"> <trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source> <source>Encryption re-negotiation error</source>
<target>Błąd renegocjacji szyfrowania</target>
<note>message decrypt error item</note> <note>message decrypt error item</note>
</trans-unit> </trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve"> <trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source> <source>Encryption re-negotiation failed.</source>
<target>Renegocjacja szyfrowania nie powiodła się.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve"> <trans-unit id="Enter Passcode" xml:space="preserve">
@@ -2132,7 +2086,6 @@ To nie może być cofnięte!</target>
</trans-unit> </trans-unit>
<trans-unit id="Enter this device name…" xml:space="preserve"> <trans-unit id="Enter this device name…" xml:space="preserve">
<source>Enter this device name…</source> <source>Enter this device name…</source>
<target>Podaj nazwę urządzenia…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enter welcome message…" xml:space="preserve"> <trans-unit id="Enter welcome message…" xml:space="preserve">
@@ -2295,10 +2248,6 @@ To nie może być cofnięte!</target>
<target>Błąd ładowania %@ serwerów</target> <target>Błąd ładowania %@ serwerów</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error receiving file" xml:space="preserve"> <trans-unit id="Error receiving file" xml:space="preserve">
<source>Error receiving file</source> <source>Error receiving file</source>
<target>Błąd odbioru pliku</target> <target>Błąd odbioru pliku</target>
@@ -2339,10 +2288,6 @@ To nie może być cofnięte!</target>
<target>Błąd zapisu hasła użytkownika</target> <target>Błąd zapisu hasła użytkownika</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error scanning code: %@" xml:space="preserve">
<source>Error scanning code: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve"> <trans-unit id="Error sending email" xml:space="preserve">
<source>Error sending email</source> <source>Error sending email</source>
<target>Błąd wysyłania e-mail</target> <target>Błąd wysyłania e-mail</target>
@@ -2468,11 +2413,6 @@ To nie może być cofnięte!</target>
<target>Szybko i bez czekania aż nadawca będzie online!</target> <target>Szybko i bez czekania aż nadawca będzie online!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<target>Szybsze dołączenie i bardziej niezawodne wiadomości.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve"> <trans-unit id="Favorite" xml:space="preserve">
<source>Favorite</source> <source>Favorite</source>
<target>Ulubione</target> <target>Ulubione</target>
@@ -2568,11 +2508,6 @@ To nie może być cofnięte!</target>
<target>Dla konsoli</target> <target>Dla konsoli</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Found desktop" xml:space="preserve">
<source>Found desktop</source>
<target>Znaleziono komputer</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="French interface" xml:space="preserve"> <trans-unit id="French interface" xml:space="preserve">
<source>French interface</source> <source>French interface</source>
<target>Francuski interfejs</target> <target>Francuski interfejs</target>
@@ -2818,6 +2753,11 @@ To nie może być cofnięte!</target>
<target>Jeśli nie możesz spotkać się osobiście, pokaż kod QR w rozmowie wideo lub udostępnij link.</target> <target>Jeśli nie możesz spotkać się osobiście, pokaż kod QR w rozmowie wideo lub udostępnij link.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve">
<source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source>
<target>Jeśli nie możesz spotkać się osobiście, możesz **zeskanować kod QR w rozmowie wideo** lub Twój kontakt może udostępnić link z zaproszeniem.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve">
<source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source>
<target>Jeśli wprowadzisz ten pin podczas otwierania aplikacji, wszystkie dane aplikacji zostaną nieodwracalnie usunięte!</target> <target>Jeśli wprowadzisz ten pin podczas otwierania aplikacji, wszystkie dane aplikacji zostaną nieodwracalnie usunięte!</target>
@@ -2893,11 +2833,6 @@ To nie może być cofnięte!</target>
<target>Incognito</target> <target>Incognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<target>Grupy incognito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve"> <trans-unit id="Incognito mode" xml:space="preserve">
<source>Incognito mode</source> <source>Incognito mode</source>
<target>Tryb incognito</target> <target>Tryb incognito</target>
@@ -2930,7 +2865,6 @@ To nie może być cofnięte!</target>
</trans-unit> </trans-unit>
<trans-unit id="Incompatible version" xml:space="preserve"> <trans-unit id="Incompatible version" xml:space="preserve">
<source>Incompatible version</source> <source>Incompatible version</source>
<target>Niekompatybilna wersja</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incorrect passcode" xml:space="preserve"> <trans-unit id="Incorrect passcode" xml:space="preserve">
@@ -2975,28 +2909,16 @@ To nie może być cofnięte!</target>
<target>Interfejs</target> <target>Interfejs</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid QR code" xml:space="preserve">
<source>Invalid QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve"> <trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source> <source>Invalid connection link</source>
<target>Nieprawidłowy link połączenia</target> <target>Nieprawidłowy link połączenia</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
<source>Invalid link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve"> <trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source> <source>Invalid name!</source>
<target>Nieprawidłowa nazwa!</target> <target>Nieprawidłowa nazwa!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid response" xml:space="preserve">
<source>Invalid response</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve"> <trans-unit id="Invalid server address!" xml:space="preserve">
<source>Invalid server address!</source> <source>Invalid server address!</source>
<target>Nieprawidłowy adres serwera!</target> <target>Nieprawidłowy adres serwera!</target>
@@ -3115,17 +3037,8 @@ To jest twój link do grupy %@!</target>
<target>Dołączanie do grupy</target> <target>Dołączanie do grupy</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep" xml:space="preserve">
<source>Keep</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
<source>Keep the app open to use it from desktop</source> <source>Keep the app open to use it from desktop</source>
<target>Zostaw aplikację otwartą i używaj ją z komputera</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep unused invitation?" xml:space="preserve">
<source>Keep unused invitation?</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve"> <trans-unit id="Keep your connections" xml:space="preserve">
@@ -3188,19 +3101,12 @@ To jest twój link do grupy %@!</target>
<target>Ograniczenia</target> <target>Ograniczenia</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<target>Połącz mobile i komputerowe aplikacje! 🔗</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve"> <trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source> <source>Linked desktop options</source>
<target>Połączone opcje komputera</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Linked desktops" xml:space="preserve"> <trans-unit id="Linked desktops" xml:space="preserve">
<source>Linked desktops</source> <source>Linked desktops</source>
<target>Połączone komputery</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Live message!" xml:space="preserve"> <trans-unit id="Live message!" xml:space="preserve">
@@ -3213,11 +3119,6 @@ To jest twój link do grupy %@!</target>
<target>Wiadomości na żywo</target> <target>Wiadomości na żywo</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Local" xml:space="preserve">
<source>Local</source>
<target>Lokalnie</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Local name" xml:space="preserve"> <trans-unit id="Local name" xml:space="preserve">
<source>Local name</source> <source>Local name</source>
<target>Nazwa lokalna</target> <target>Nazwa lokalna</target>
@@ -3458,10 +3359,6 @@ To jest twój link do grupy %@!</target>
<target>Nowy Pin</target> <target>Nowy Pin</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="New chat" xml:space="preserve">
<source>New chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve"> <trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source> <source>New contact request</source>
<target>Nowa prośba o kontakt</target> <target>Nowa prośba o kontakt</target>
@@ -3562,11 +3459,6 @@ To jest twój link do grupy %@!</target>
<target>Brak odebranych lub wysłanych plików</target> <target>Brak odebranych lub wysłanych plików</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Not compatible!" xml:space="preserve">
<source>Not compatible!</source>
<target>Nie kompatybilny!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve"> <trans-unit id="Notifications" xml:space="preserve">
<source>Notifications</source> <source>Notifications</source>
<target>Powiadomienia</target> <target>Powiadomienia</target>
@@ -3586,15 +3478,16 @@ To jest twój link do grupy %@!</target>
- wyłączyć członków (rola "obserwatora")</target> - wyłączyć członków (rola "obserwatora")</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="OK" xml:space="preserve">
<source>OK</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Off" xml:space="preserve"> <trans-unit id="Off" xml:space="preserve">
<source>Off</source> <source>Off</source>
<target>Wyłączony</target> <target>Wyłączony</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Off (Local)" xml:space="preserve">
<source>Off (Local)</source>
<target>Wyłączony (Lokalnie)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ok" xml:space="preserve"> <trans-unit id="Ok" xml:space="preserve">
<source>Ok</source> <source>Ok</source>
<target>Ok</target> <target>Ok</target>
@@ -3735,16 +3628,9 @@ To jest twój link do grupy %@!</target>
<target>Otwarto źródłowy protokół i kod - każdy może uruchomić serwery.</target> <target>Otwarto źródłowy protokół i kod - każdy może uruchomić serwery.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Opening app…" xml:space="preserve"> <trans-unit id="Opening database…" xml:space="preserve">
<source>Opening app…</source> <source>Opening database…</source>
<note>No comment provided by engineer.</note> <target>Otwieranie bazy danych…</target>
</trans-unit>
<trans-unit id="Or scan QR code" xml:space="preserve">
<source>Or scan QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
<source>Or show this code</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="PING count" xml:space="preserve"> <trans-unit id="PING count" xml:space="preserve">
@@ -3787,9 +3673,13 @@ To jest twój link do grupy %@!</target>
<target>Hasło do wyświetlenia</target> <target>Hasło do wyświetlenia</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste" xml:space="preserve">
<source>Paste</source>
<target>Wklej</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve"> <trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source> <source>Paste desktop address</source>
<target>Wklej adres komputera</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste image" xml:space="preserve"> <trans-unit id="Paste image" xml:space="preserve">
@@ -3797,10 +3687,16 @@ To jest twój link do grupy %@!</target>
<target>Wklej obraz</target> <target>Wklej obraz</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve"> <trans-unit id="Paste received link" xml:space="preserve">
<source>Paste the link you received</source> <source>Paste received link</source>
<target>Wklej otrzymany link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Wklej otrzymany link w pole poniżej, aby połączyć się z kontaktem.</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source> <source>People can connect to you only via the links you share.</source>
<target>Ludzie mogą się z Tobą połączyć tylko poprzez linki, które udostępniasz.</target> <target>Ludzie mogą się z Tobą połączyć tylko poprzez linki, które udostępniasz.</target>
@@ -3836,11 +3732,6 @@ To jest twój link do grupy %@!</target>
<target>Proszę sprawdzić preferencje Twoje i Twojego kontaktu.</target> <target>Proszę sprawdzić preferencje Twoje i Twojego kontaktu.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Please contact developers.&#10;Error: %@" xml:space="preserve">
<source>Please contact developers.
Error: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please contact group admin." xml:space="preserve"> <trans-unit id="Please contact group admin." xml:space="preserve">
<source>Please contact group admin.</source> <source>Please contact group admin.</source>
<target>Skontaktuj się z administratorem grupy.</target> <target>Skontaktuj się z administratorem grupy.</target>
@@ -4046,10 +3937,6 @@ Error: %@</source>
<target>Przeczytaj więcej w [Podręczniku Użytkownika](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <target>Przeczytaj więcej w [Podręczniku Użytkownika](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source>
<target>Przeczytaj więcej w [Podręczniku Użytkownika](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> <target>Przeczytaj więcej w [Podręczniku Użytkownika](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target>
@@ -4260,10 +4147,6 @@ Error: %@</source>
<target>Błąd przywracania bazy danych</target> <target>Błąd przywracania bazy danych</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Retry" xml:space="preserve">
<source>Retry</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reveal" xml:space="preserve"> <trans-unit id="Reveal" xml:space="preserve">
<source>Reveal</source> <source>Reveal</source>
<target>Ujawnij</target> <target>Ujawnij</target>
@@ -4396,7 +4279,6 @@ Error: %@</source>
</trans-unit> </trans-unit>
<trans-unit id="Scan QR code from desktop" xml:space="preserve"> <trans-unit id="Scan QR code from desktop" xml:space="preserve">
<source>Scan QR code from desktop</source> <source>Scan QR code from desktop</source>
<target>Zeskanuj kod QR z komputera</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Scan code" xml:space="preserve"> <trans-unit id="Scan code" xml:space="preserve">
@@ -4419,10 +4301,6 @@ Error: %@</source>
<target>Szukaj</target> <target>Szukaj</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve"> <trans-unit id="Secure queue" xml:space="preserve">
<source>Secure queue</source> <source>Secure queue</source>
<target>Bezpieczna kolejka</target> <target>Bezpieczna kolejka</target>
@@ -4625,7 +4503,6 @@ Error: %@</source>
</trans-unit> </trans-unit>
<trans-unit id="Session code" xml:space="preserve"> <trans-unit id="Session code" xml:space="preserve">
<source>Session code</source> <source>Session code</source>
<target>Kod sesji</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Set 1 day" xml:space="preserve"> <trans-unit id="Set 1 day" xml:space="preserve">
@@ -4698,8 +4575,9 @@ Error: %@</source>
<target>Udostępnij link</target> <target>Udostępnij link</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve"> <trans-unit id="Share one-time invitation link" xml:space="preserve">
<source>Share this 1-time invite link</source> <source>Share one-time invitation link</source>
<target>Jednorazowy link zaproszenia</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve"> <trans-unit id="Share with contacts" xml:space="preserve">
@@ -4822,15 +4700,16 @@ Error: %@</source>
<target>Ktoś</target> <target>Ktoś</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="Start a new chat" xml:space="preserve">
<source>Start a new chat</source>
<target>Rozpocznij nowy czat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start chat" xml:space="preserve"> <trans-unit id="Start chat" xml:space="preserve">
<source>Start chat</source> <source>Start chat</source>
<target>Rozpocznij czat</target> <target>Rozpocznij czat</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Start chat?" xml:space="preserve">
<source>Start chat?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start migration" xml:space="preserve"> <trans-unit id="Start migration" xml:space="preserve">
<source>Start migration</source> <source>Start migration</source>
<target>Rozpocznij migrację</target> <target>Rozpocznij migrację</target>
@@ -4956,14 +4835,6 @@ Error: %@</source>
<target>Dotnij, aby dołączyć w trybie incognito</target> <target>Dotnij, aby dołączyć w trybie incognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Tap to paste link" xml:space="preserve">
<source>Tap to paste link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to scan" xml:space="preserve">
<source>Tap to scan</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve"> <trans-unit id="Tap to start a new chat" xml:space="preserve">
<source>Tap to start a new chat</source> <source>Tap to start a new chat</source>
<target>Dotknij, aby rozpocząć nowy czat</target> <target>Dotknij, aby rozpocząć nowy czat</target>
@@ -5026,10 +4897,6 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
<target>Próba zmiany hasła bazy danych nie została zakończona.</target> <target>Próba zmiany hasła bazy danych nie została zakończona.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source> <source>The connection you accepted will be cancelled!</source>
<target>Zaakceptowane przez Ciebie połączenie zostanie anulowane!</target> <target>Zaakceptowane przez Ciebie połączenie zostanie anulowane!</target>
@@ -5095,10 +4962,6 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
<target>Serwery dla nowych połączeń bieżącego profilu czatu **%@**.</target> <target>Serwery dla nowych połączeń bieżącego profilu czatu **%@**.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve">
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve"> <trans-unit id="Theme" xml:space="preserve">
<source>Theme</source> <source>Theme</source>
<target>Motyw</target> <target>Motyw</target>
@@ -5141,7 +5004,6 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
</trans-unit> </trans-unit>
<trans-unit id="This device name" xml:space="preserve"> <trans-unit id="This device name" xml:space="preserve">
<source>This device name</source> <source>This device name</source>
<target>Nazwa tego urządzenia</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve"> <trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
@@ -5179,11 +5041,6 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
<target>Aby się połączyć, Twój kontakt może zeskanować kod QR lub skorzystać z linku w aplikacji.</target> <target>Aby się połączyć, Twój kontakt może zeskanować kod QR lub skorzystać z linku w aplikacji.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<target>Aby ukryć niechciane wiadomości.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve"> <trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source> <source>To make a new connection</source>
<target>Aby nawiązać nowe połączenie</target> <target>Aby nawiązać nowe połączenie</target>
@@ -5251,6 +5108,11 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.</ta
<target>Wyłącz</target> <target>Wyłącz</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Turn off notifications?" xml:space="preserve">
<source>Turn off notifications?</source>
<target>Wyłączyć powiadomienia?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn on" xml:space="preserve"> <trans-unit id="Turn on" xml:space="preserve">
<source>Turn on</source> <source>Turn on</source>
<target>Włącz</target> <target>Włącz</target>
@@ -5340,12 +5202,10 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
</trans-unit> </trans-unit>
<trans-unit id="Unlink" xml:space="preserve"> <trans-unit id="Unlink" xml:space="preserve">
<source>Unlink</source> <source>Unlink</source>
<target>Odłącz</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Unlink desktop?" xml:space="preserve"> <trans-unit id="Unlink desktop?" xml:space="preserve">
<source>Unlink desktop?</source> <source>Unlink desktop?</source>
<target>Odłączyć komputer?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Unlock" xml:space="preserve"> <trans-unit id="Unlock" xml:space="preserve">
@@ -5440,7 +5300,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
</trans-unit> </trans-unit>
<trans-unit id="Use from desktop" xml:space="preserve"> <trans-unit id="Use from desktop" xml:space="preserve">
<source>Use from desktop</source> <source>Use from desktop</source>
<target>Użyj z komputera</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use iOS call interface" xml:space="preserve"> <trans-unit id="Use iOS call interface" xml:space="preserve">
@@ -5453,10 +5312,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
<target>Użyj nowego profilu incognito</target> <target>Użyj nowego profilu incognito</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use only local notifications?" xml:space="preserve">
<source>Use only local notifications?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve"> <trans-unit id="Use server" xml:space="preserve">
<source>Use server</source> <source>Use server</source>
<target>Użyj serwera</target> <target>Użyj serwera</target>
@@ -5479,12 +5334,10 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
</trans-unit> </trans-unit>
<trans-unit id="Verify code with desktop" xml:space="preserve"> <trans-unit id="Verify code with desktop" xml:space="preserve">
<source>Verify code with desktop</source> <source>Verify code with desktop</source>
<target>Zweryfikuj kod z komputera</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify connection" xml:space="preserve"> <trans-unit id="Verify connection" xml:space="preserve">
<source>Verify connection</source> <source>Verify connection</source>
<target>Zweryfikuj połączenie</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify connection security" xml:space="preserve"> <trans-unit id="Verify connection security" xml:space="preserve">
@@ -5494,7 +5347,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
</trans-unit> </trans-unit>
<trans-unit id="Verify connections" xml:space="preserve"> <trans-unit id="Verify connections" xml:space="preserve">
<source>Verify connections</source> <source>Verify connections</source>
<target>Zweryfikuj połączenia</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Verify security code" xml:space="preserve"> <trans-unit id="Verify security code" xml:space="preserve">
@@ -5507,11 +5359,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
<target>Przez przeglądarkę</target> <target>Przez przeglądarkę</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<target>Dzięki bezpiecznemu protokołowi odpornego kwantowo.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve"> <trans-unit id="Video call" xml:space="preserve">
<source>Video call</source> <source>Video call</source>
<target>Połączenie wideo</target> <target>Połączenie wideo</target>
@@ -5562,11 +5409,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
<target>Wiadomość głosowa…</target> <target>Wiadomość głosowa…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Waiting for desktop..." xml:space="preserve">
<source>Waiting for desktop...</source>
<target>Oczekiwanie na komputer...</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Waiting for file" xml:space="preserve"> <trans-unit id="Waiting for file" xml:space="preserve">
<source>Waiting for file</source> <source>Waiting for file</source>
<target>Oczekiwanie na plik</target> <target>Oczekiwanie na plik</target>
@@ -5719,6 +5561,11 @@ Powtórzyć prośbę dołączenia?</target>
<target>Możesz przyjmować połączenia z ekranu blokady, bez uwierzytelniania urządzenia i aplikacji.</target> <target>Możesz przyjmować połączenia z ekranu blokady, bez uwierzytelniania urządzenia i aplikacji.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve">
<source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source>
<target>Możesz też połączyć się klikając w link. Jeśli otworzy się on w przeglądarce, kliknij przycisk **Otwórz w aplikacji mobilnej**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can create it later" xml:space="preserve"> <trans-unit id="You can create it later" xml:space="preserve">
<source>You can create it later</source> <source>You can create it later</source>
<target>Możesz go utworzyć później</target> <target>Możesz go utworzyć później</target>
@@ -5739,10 +5586,6 @@ Powtórzyć prośbę dołączenia?</target>
<target>Możesz ukryć lub wyciszyć profil użytkownika - przesuń palcem w prawo.</target> <target>Możesz ukryć lub wyciszyć profil użytkownika - przesuń palcem w prawo.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now send messages to %@" xml:space="preserve"> <trans-unit id="You can now send messages to %@" xml:space="preserve">
<source>You can now send messages to %@</source> <source>You can now send messages to %@</source>
<target>Możesz teraz wysyłać wiadomości do %@</target> <target>Możesz teraz wysyłać wiadomości do %@</target>
@@ -5783,10 +5626,6 @@ Powtórzyć prośbę dołączenia?</target>
<target>Możesz używać markdown do formatowania wiadomości:</target> <target>Możesz używać markdown do formatowania wiadomości:</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can view invitation link again in connection details." xml:space="preserve">
<source>You can view invitation link again in connection details.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can't send messages!" xml:space="preserve"> <trans-unit id="You can't send messages!" xml:space="preserve">
<source>You can't send messages!</source> <source>You can't send messages!</source>
<target>Nie możesz wysyłać wiadomości!</target> <target>Nie możesz wysyłać wiadomości!</target>
@@ -5976,6 +5815,13 @@ Możesz anulować to połączenie i usunąć kontakt (i spróbować później z
<target>Twoje kontakty mogą zezwolić na pełne usunięcie wiadomości.</target> <target>Twoje kontakty mogą zezwolić na pełne usunięcie wiadomości.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your contacts in SimpleX will see it.&#10;You can change it in Settings." xml:space="preserve">
<source>Your contacts in SimpleX will see it.
You can change it in Settings.</source>
<target>Twoje kontakty w SimpleX będą to widzieć.
Możesz to zmienić w Ustawieniach.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve"> <trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source> <source>Your contacts will remain connected.</source>
<target>Twoje kontakty pozostaną połączone.</target> <target>Twoje kontakty pozostaną połączone.</target>
@@ -6108,11 +5954,6 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
<target>połączenie audio (nie szyfrowane e2e)</target> <target>połączenie audio (nie szyfrowane e2e)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="author" xml:space="preserve">
<source>author</source>
<target>autor</target>
<note>member role</note>
</trans-unit>
<trans-unit id="bad message ID" xml:space="preserve"> <trans-unit id="bad message ID" xml:space="preserve">
<source>bad message ID</source> <source>bad message ID</source>
<target>zły identyfikator wiadomości</target> <target>zły identyfikator wiadomości</target>
@@ -6697,7 +6538,6 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit> </trans-unit>
<trans-unit id="v%@" xml:space="preserve"> <trans-unit id="v%@" xml:space="preserve">
<source>v%@</source> <source>v%@</source>
<target>v%@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="v%@ (%@)" xml:space="preserve"> <trans-unit id="v%@ (%@)" xml:space="preserve">
@@ -6839,7 +6679,6 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit> </trans-unit>
<trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve"> <trans-unit id="NSLocalNetworkUsageDescription" xml:space="preserve">
<source>SimpleX uses local network access to allow using user chat profile via desktop app on the same network.</source> <source>SimpleX uses local network access to allow using user chat profile via desktop app on the same network.</source>
<target>SimpleX używa sieci lokalnej aby pozwolić na dostęp profilom czatu użytkownika przez aplikację komputerową na tej samej sieci.</target>
<note>Privacy - Local Network Usage Description</note> <note>Privacy - Local Network Usage Description</note>
</trans-unit> </trans-unit>
<trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve"> <trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve">
File diff suppressed because it is too large Load Diff
@@ -297,17 +297,14 @@
<target>)</target> <target>)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve">
<source>**Add contact**: to create a new invitation link, or connect via a link you received.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target>**เพิ่มผู้ติดต่อใหม่**: เพื่อสร้างคิวอาร์โค้ดแบบใช้ครั้งเดียวหรือลิงก์สำหรับผู้ติดต่อของคุณ</target> <target>**เพิ่มผู้ติดต่อใหม่**: เพื่อสร้างคิวอาร์โค้ดแบบใช้ครั้งเดียวหรือลิงก์สำหรับผู้ติดต่อของคุณ</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Create group**: to create a new group." xml:space="preserve"> <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<source>**Create group**: to create a new group.</source> <source>**Create link / QR code** for your contact to use.</source>
<target>**สร้างลิงค์ / คิวอาร์โค้ด** เพื่อให้ผู้ติดต่อของคุณใช้</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -320,6 +317,11 @@
<target>**ส่วนตัวที่สุด**: ไม่ใช้เซิร์ฟเวอร์การแจ้งเตือนของ SimpleX Chat ตรวจสอบข้อความเป็นระยะในพื้นหลัง (ขึ้นอยู่กับความถี่ที่คุณใช้แอป)</target> <target>**ส่วนตัวที่สุด**: ไม่ใช้เซิร์ฟเวอร์การแจ้งเตือนของ SimpleX Chat ตรวจสอบข้อความเป็นระยะในพื้นหลัง (ขึ้นอยู่กับความถี่ที่คุณใช้แอป)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve">
<source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source>
<target>**แปะลิงก์ที่ได้รับ** หรือเปิดในเบราว์เซอร์แล้วแตะ **เปิดในแอปมือถือ**</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve">
<source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source>
<target>**โปรดทราบ**: คุณจะไม่สามารถกู้คืนหรือเปลี่ยนรหัสผ่านได้หากคุณทำรหัสผ่านหาย</target> <target>**โปรดทราบ**: คุณจะไม่สามารถกู้คืนหรือเปลี่ยนรหัสผ่านได้หากคุณทำรหัสผ่านหาย</target>
@@ -330,6 +332,11 @@
<target>**แนะนำ**: โทเค็นอุปกรณ์และการแจ้งเตือนจะถูกส่งไปยังเซิร์ฟเวอร์การแจ้งเตือนของ SimpleX Chat แต่ไม่ใช่เนื้อหาข้อความ ขนาด หรือผู้ที่ส่ง</target> <target>**แนะนำ**: โทเค็นอุปกรณ์และการแจ้งเตือนจะถูกส่งไปยังเซิร์ฟเวอร์การแจ้งเตือนของ SimpleX Chat แต่ไม่ใช่เนื้อหาข้อความ ขนาด หรือผู้ที่ส่ง</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve">
<source>**Scan QR code**: to connect to your contact in person or via video call.</source>
<target>**สแกนคิวอาร์โค้ด**: เพื่อเชื่อมต่อกับผู้ติดต่อของคุณด้วยตนเองหรือผ่านการสนทนาทางวิดีโอ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target>**คำเตือน**: การแจ้งเตือนแบบพุชทันทีจำเป็นต้องบันทึกรหัสผ่านไว้ใน Keychain</target> <target>**คำเตือน**: การแจ้งเตือนแบบพุชทันทีจำเป็นต้องบันทึกรหัสผ่านไว้ใน Keychain</target>
@@ -370,12 +377,6 @@
- และอื่น ๆ!</target> - และอื่น ๆ!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="- optionally notify deleted contacts.&#10;- profile names with spaces.&#10;- and more!" xml:space="preserve">
<source>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve"> <trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve">
<source>- voice messages up to 5 minutes. <source>- voice messages up to 5 minutes.
- custom time to disappear. - custom time to disappear.
@@ -424,6 +425,11 @@
<target>1 สัปดาห์</target> <target>1 สัปดาห์</target>
<note>time interval</note> <note>time interval</note>
</trans-unit> </trans-unit>
<trans-unit id="1-time link" xml:space="preserve">
<source>1-time link</source>
<target>ลิงก์สำหรับใช้ 1 ครั้ง</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="5 minutes" xml:space="preserve"> <trans-unit id="5 minutes" xml:space="preserve">
<source>5 minutes</source> <source>5 minutes</source>
<target>5 นาที</target> <target>5 นาที</target>
@@ -537,10 +543,6 @@
<target>เพิ่มที่อยู่ลงในโปรไฟล์ของคุณ เพื่อให้ผู้ติดต่อของคุณสามารถแชร์กับผู้อื่นได้ การอัปเดตโปรไฟล์จะถูกส่งไปยังผู้ติดต่อของคุณ</target> <target>เพิ่มที่อยู่ลงในโปรไฟล์ของคุณ เพื่อให้ผู้ติดต่อของคุณสามารถแชร์กับผู้อื่นได้ การอัปเดตโปรไฟล์จะถูกส่งไปยังผู้ติดต่อของคุณ</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add contact" xml:space="preserve">
<source>Add contact</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve"> <trans-unit id="Add preset servers" xml:space="preserve">
<source>Add preset servers</source> <source>Add preset servers</source>
<target>เพิ่มเซิร์ฟเวอร์ที่ตั้งไว้ล่วงหน้า</target> <target>เพิ่มเซิร์ฟเวอร์ที่ตั้งไว้ล่วงหน้า</target>
@@ -866,10 +868,6 @@
<target>แฮชข้อความไม่ดี</target> <target>แฮชข้อความไม่ดี</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
<source>Better groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better messages" xml:space="preserve"> <trans-unit id="Better messages" xml:space="preserve">
<source>Better messages</source> <source>Better messages</source>
<target>ข้อความที่ดีขึ้น</target> <target>ข้อความที่ดีขึ้น</target>
@@ -879,10 +877,6 @@
<source>Block</source> <source>Block</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
<source>Block group members</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve"> <trans-unit id="Block member" xml:space="preserve">
<source>Block member</source> <source>Block member</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -935,10 +929,6 @@
<target>โทร</target> <target>โทร</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Camera not available" xml:space="preserve">
<source>Camera not available</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Can't delete user profile!" xml:space="preserve"> <trans-unit id="Can't delete user profile!" xml:space="preserve">
<source>Can't delete user profile!</source> <source>Can't delete user profile!</source>
<target>ไม่สามารถลบโปรไฟล์ผู้ใช้ได้!</target> <target>ไม่สามารถลบโปรไฟล์ผู้ใช้ได้!</target>
@@ -1055,10 +1045,6 @@
<target>การแชทหยุดทํางานแล้ว</target> <target>การแชทหยุดทํางานแล้ว</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve">
<source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve"> <trans-unit id="Chat preferences" xml:space="preserve">
<source>Chat preferences</source> <source>Chat preferences</source>
<target>ค่ากําหนดในการแชท</target> <target>ค่ากําหนดในการแชท</target>
@@ -1159,10 +1145,6 @@
<target>เชื่อมต่อ</target> <target>เชื่อมต่อ</target>
<note>server test step</note> <note>server test step</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect automatically" xml:space="preserve">
<source>Connect automatically</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve"> <trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source> <source>Connect incognito</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -1194,6 +1176,11 @@ This is your own one-time link!</source>
<target>เชื่อมต่อผ่านลิงก์</target> <target>เชื่อมต่อผ่านลิงก์</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link / QR code" xml:space="preserve">
<source>Connect via link / QR code</source>
<target>เชื่อมต่อผ่านลิงค์ / คิวอาร์โค้ด</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link" xml:space="preserve"> <trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source> <source>Connect via one-time link</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -1327,10 +1314,6 @@ This is your own one-time link!</source>
<target>สร้างที่อยู่ SimpleX</target> <target>สร้างที่อยู่ SimpleX</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create a group using a random profile." xml:space="preserve">
<source>Create a group using a random profile.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source> <source>Create an address to let people connect with you.</source>
<target>สร้างที่อยู่เพื่อให้ผู้อื่นเชื่อมต่อกับคุณ</target> <target>สร้างที่อยู่เพื่อให้ผู้อื่นเชื่อมต่อกับคุณ</target>
@@ -1359,6 +1342,11 @@ This is your own one-time link!</source>
<source>Create new profile in [desktop app](https://simplex.chat/downloads/). 💻</source> <source>Create new profile in [desktop app](https://simplex.chat/downloads/). 💻</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create one-time invitation link" xml:space="preserve">
<source>Create one-time invitation link</source>
<target>สร้างลิงก์เชิญแบบใช้ครั้งเดียว</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -1383,10 +1371,6 @@ This is your own one-time link!</source>
<target>สร้างเมื่อ %@</target> <target>สร้างเมื่อ %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve"> <trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source> <source>Current Passcode</source>
<target>รหัสผ่านปัจจุบัน</target> <target>รหัสผ่านปัจจุบัน</target>
@@ -1842,8 +1826,8 @@ This cannot be undone!</source>
<source>Discover and join groups</source> <source>Discover and join groups</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve"> <trans-unit id="Discover on network" xml:space="preserve">
<source>Discover via local network</source> <source>Discover on network</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -1926,10 +1910,6 @@ This cannot be undone!</source>
<target>เปิดใช้งานการลบข้อความอัตโนมัติ?</target> <target>เปิดใช้งานการลบข้อความอัตโนมัติ?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enable camera access" xml:space="preserve">
<source>Enable camera access</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve"> <trans-unit id="Enable for all" xml:space="preserve">
<source>Enable for all</source> <source>Enable for all</source>
<target>เปิดใช้งานสําหรับทุกคน</target> <target>เปิดใช้งานสําหรับทุกคน</target>
@@ -1993,10 +1973,6 @@ This cannot be undone!</source>
<target>ข้อความที่ encrypt หรือเหตุการณ์อื่น</target> <target>ข้อความที่ encrypt หรือเหตุการณ์อื่น</target>
<note>notification</note> <note>notification</note>
</trans-unit> </trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve">
<source>Encrypted message: app is stopped</source>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve"> <trans-unit id="Encrypted message: database error" xml:space="preserve">
<source>Encrypted message: database error</source> <source>Encrypted message: database error</source>
<target>ข้อความที่ encrypt: ความผิดพลาดในฐานข้อมูล</target> <target>ข้อความที่ encrypt: ความผิดพลาดในฐานข้อมูล</target>
@@ -2220,10 +2196,6 @@ This cannot be undone!</source>
<target>โหลดเซิร์ฟเวอร์ %@ ผิดพลาด</target> <target>โหลดเซิร์ฟเวอร์ %@ ผิดพลาด</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error receiving file" xml:space="preserve"> <trans-unit id="Error receiving file" xml:space="preserve">
<source>Error receiving file</source> <source>Error receiving file</source>
<target>เกิดข้อผิดพลาดในการรับไฟล์</target> <target>เกิดข้อผิดพลาดในการรับไฟล์</target>
@@ -2264,10 +2236,6 @@ This cannot be undone!</source>
<target>เกิดข้อผิดพลาดในการบันทึกรหัสผ่านผู้ใช้</target> <target>เกิดข้อผิดพลาดในการบันทึกรหัสผ่านผู้ใช้</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error scanning code: %@" xml:space="preserve">
<source>Error scanning code: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve"> <trans-unit id="Error sending email" xml:space="preserve">
<source>Error sending email</source> <source>Error sending email</source>
<target>เกิดข้อผิดพลาดในการส่งอีเมล</target> <target>เกิดข้อผิดพลาดในการส่งอีเมล</target>
@@ -2391,10 +2359,6 @@ This cannot be undone!</source>
<target>รวดเร็วและไม่ต้องรอจนกว่าผู้ส่งจะออนไลน์!</target> <target>รวดเร็วและไม่ต้องรอจนกว่าผู้ส่งจะออนไลน์!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve"> <trans-unit id="Favorite" xml:space="preserve">
<source>Favorite</source> <source>Favorite</source>
<target>ที่ชอบ</target> <target>ที่ชอบ</target>
@@ -2490,10 +2454,6 @@ This cannot be undone!</source>
<target>สำหรับคอนโซล</target> <target>สำหรับคอนโซล</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Found desktop" xml:space="preserve">
<source>Found desktop</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="French interface" xml:space="preserve"> <trans-unit id="French interface" xml:space="preserve">
<source>French interface</source> <source>French interface</source>
<target>อินเทอร์เฟซภาษาฝรั่งเศส</target> <target>อินเทอร์เฟซภาษาฝรั่งเศส</target>
@@ -2736,6 +2696,11 @@ This cannot be undone!</source>
<target>หากคุณไม่สามารถพบกันในชีวิตจริงได้ ให้แสดงคิวอาร์โค้ดในวิดีโอคอล หรือแชร์ลิงก์</target> <target>หากคุณไม่สามารถพบกันในชีวิตจริงได้ ให้แสดงคิวอาร์โค้ดในวิดีโอคอล หรือแชร์ลิงก์</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve">
<source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source>
<target>หากคุณไม่สามารถพบปะด้วยตนเอง คุณสามารถ **สแกนคิวอาร์โค้ดผ่านการสนทนาทางวิดีโอ** หรือผู้ติดต่อของคุณสามารถแชร์ลิงก์เชิญได้</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve">
<source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source>
<target>หากคุณใส่รหัสผ่านนี้เมื่อเปิดแอป ข้อมูลแอปทั้งหมดจะถูกลบอย่างถาวร!</target> <target>หากคุณใส่รหัสผ่านนี้เมื่อเปิดแอป ข้อมูลแอปทั้งหมดจะถูกลบอย่างถาวร!</target>
@@ -2811,10 +2776,6 @@ This cannot be undone!</source>
<target>ไม่ระบุตัวตน</target> <target>ไม่ระบุตัวตน</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve"> <trans-unit id="Incognito mode" xml:space="preserve">
<source>Incognito mode</source> <source>Incognito mode</source>
<target>โหมดไม่ระบุตัวตน</target> <target>โหมดไม่ระบุตัวตน</target>
@@ -2890,27 +2851,15 @@ This cannot be undone!</source>
<target>อินเตอร์เฟซ</target> <target>อินเตอร์เฟซ</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid QR code" xml:space="preserve">
<source>Invalid QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve"> <trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source> <source>Invalid connection link</source>
<target>ลิงค์เชื่อมต่อไม่ถูกต้อง</target> <target>ลิงค์เชื่อมต่อไม่ถูกต้อง</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
<source>Invalid link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve"> <trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source> <source>Invalid name!</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid response" xml:space="preserve">
<source>Invalid response</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve"> <trans-unit id="Invalid server address!" xml:space="preserve">
<source>Invalid server address!</source> <source>Invalid server address!</source>
<target>ที่อยู่เซิร์ฟเวอร์ไม่ถูกต้อง!</target> <target>ที่อยู่เซิร์ฟเวอร์ไม่ถูกต้อง!</target>
@@ -3024,18 +2973,10 @@ This is your link for group %@!</source>
<target>กำลังจะเข้าร่วมกลุ่ม</target> <target>กำลังจะเข้าร่วมกลุ่ม</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep" xml:space="preserve">
<source>Keep</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
<source>Keep the app open to use it from desktop</source> <source>Keep the app open to use it from desktop</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep unused invitation?" xml:space="preserve">
<source>Keep unused invitation?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve"> <trans-unit id="Keep your connections" xml:space="preserve">
<source>Keep your connections</source> <source>Keep your connections</source>
<target>รักษาการเชื่อมต่อของคุณ</target> <target>รักษาการเชื่อมต่อของคุณ</target>
@@ -3096,10 +3037,6 @@ This is your link for group %@!</source>
<target>ข้อจำกัด</target> <target>ข้อจำกัด</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve"> <trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source> <source>Linked desktop options</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3118,11 +3055,6 @@ This is your link for group %@!</source>
<target>ข้อความสด</target> <target>ข้อความสด</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Local" xml:space="preserve">
<source>Local</source>
<target>ในเครื่อง</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Local name" xml:space="preserve"> <trans-unit id="Local name" xml:space="preserve">
<source>Local name</source> <source>Local name</source>
<target>ชื่อภายในเครื่องเท่านั้น</target> <target>ชื่อภายในเครื่องเท่านั้น</target>
@@ -3361,10 +3293,6 @@ This is your link for group %@!</source>
<target>รหัสผ่านใหม่</target> <target>รหัสผ่านใหม่</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="New chat" xml:space="preserve">
<source>New chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve"> <trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source> <source>New contact request</source>
<target>คำขอติดต่อใหม่</target> <target>คำขอติดต่อใหม่</target>
@@ -3463,10 +3391,6 @@ This is your link for group %@!</source>
<target>ไม่มีไฟล์ที่ได้รับหรือส่ง</target> <target>ไม่มีไฟล์ที่ได้รับหรือส่ง</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Not compatible!" xml:space="preserve">
<source>Not compatible!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve"> <trans-unit id="Notifications" xml:space="preserve">
<source>Notifications</source> <source>Notifications</source>
<target>การแจ้งเตือน</target> <target>การแจ้งเตือน</target>
@@ -3486,15 +3410,16 @@ This is your link for group %@!</source>
- ปิดการใช้งานสมาชิก (บทบาท "ผู้สังเกตการณ์")</target> - ปิดการใช้งานสมาชิก (บทบาท "ผู้สังเกตการณ์")</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="OK" xml:space="preserve">
<source>OK</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Off" xml:space="preserve"> <trans-unit id="Off" xml:space="preserve">
<source>Off</source> <source>Off</source>
<target>ปิด</target> <target>ปิด</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Off (Local)" xml:space="preserve">
<source>Off (Local)</source>
<target>ปิด (ในเครื่อง)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ok" xml:space="preserve"> <trans-unit id="Ok" xml:space="preserve">
<source>Ok</source> <source>Ok</source>
<target>ตกลง</target> <target>ตกลง</target>
@@ -3633,16 +3558,9 @@ This is your link for group %@!</source>
<target>โปรโตคอลและโค้ดโอเพ่นซอร์ส – ใคร ๆ ก็สามารถเปิดใช้เซิร์ฟเวอร์ได้</target> <target>โปรโตคอลและโค้ดโอเพ่นซอร์ส – ใคร ๆ ก็สามารถเปิดใช้เซิร์ฟเวอร์ได้</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Opening app…" xml:space="preserve"> <trans-unit id="Opening database…" xml:space="preserve">
<source>Opening app…</source> <source>Opening database…</source>
<note>No comment provided by engineer.</note> <target>กำลังเปิดฐานข้อมูล…</target>
</trans-unit>
<trans-unit id="Or scan QR code" xml:space="preserve">
<source>Or scan QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
<source>Or show this code</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="PING count" xml:space="preserve"> <trans-unit id="PING count" xml:space="preserve">
@@ -3685,6 +3603,11 @@ This is your link for group %@!</source>
<target>รหัสผ่านที่จะแสดง</target> <target>รหัสผ่านที่จะแสดง</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste" xml:space="preserve">
<source>Paste</source>
<target>แปะ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve"> <trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source> <source>Paste desktop address</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3694,10 +3617,15 @@ This is your link for group %@!</source>
<target>แปะภาพ</target> <target>แปะภาพ</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve"> <trans-unit id="Paste received link" xml:space="preserve">
<source>Paste the link you received</source> <source>Paste received link</source>
<target>แปะลิงก์ที่ได้รับ</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source> <source>People can connect to you only via the links you share.</source>
<target>ผู้คนสามารถเชื่อมต่อกับคุณผ่านลิงก์ที่คุณแบ่งปันเท่านั้น</target> <target>ผู้คนสามารถเชื่อมต่อกับคุณผ่านลิงก์ที่คุณแบ่งปันเท่านั้น</target>
@@ -3733,11 +3661,6 @@ This is your link for group %@!</source>
<target>โปรดตรวจสอบความต้องการของคุณและการตั้งค่าผู้ติดต่อ</target> <target>โปรดตรวจสอบความต้องการของคุณและการตั้งค่าผู้ติดต่อ</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Please contact developers.&#10;Error: %@" xml:space="preserve">
<source>Please contact developers.
Error: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please contact group admin." xml:space="preserve"> <trans-unit id="Please contact group admin." xml:space="preserve">
<source>Please contact group admin.</source> <source>Please contact group admin.</source>
<target>โปรดติดต่อผู้ดูแลกลุ่ม</target> <target>โปรดติดต่อผู้ดูแลกลุ่ม</target>
@@ -3941,10 +3864,6 @@ Error: %@</source>
<target>อ่านเพิ่มเติมใน[คู่มือผู้ใช้](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)</target> <target>อ่านเพิ่มเติมใน[คู่มือผู้ใช้](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source>
<target>อ่านเพิ่มเติมใน[คู่มือผู้ใช้](https://simplex.chat/docs/guide/readme.html#connect-to-friends)</target> <target>อ่านเพิ่มเติมใน[คู่มือผู้ใช้](https://simplex.chat/docs/guide/readme.html#connect-to-friends)</target>
@@ -4151,10 +4070,6 @@ Error: %@</source>
<target>กู้คืนข้อผิดพลาดของฐานข้อมูล</target> <target>กู้คืนข้อผิดพลาดของฐานข้อมูล</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Retry" xml:space="preserve">
<source>Retry</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reveal" xml:space="preserve"> <trans-unit id="Reveal" xml:space="preserve">
<source>Reveal</source> <source>Reveal</source>
<target>เปิดเผย</target> <target>เปิดเผย</target>
@@ -4309,10 +4224,6 @@ Error: %@</source>
<target>ค้นหา</target> <target>ค้นหา</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve"> <trans-unit id="Secure queue" xml:space="preserve">
<source>Secure queue</source> <source>Secure queue</source>
<target>คิวที่ปลอดภัย</target> <target>คิวที่ปลอดภัย</target>
@@ -4584,8 +4495,9 @@ Error: %@</source>
<target>แชร์ลิงก์</target> <target>แชร์ลิงก์</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve"> <trans-unit id="Share one-time invitation link" xml:space="preserve">
<source>Share this 1-time invite link</source> <source>Share one-time invitation link</source>
<target>แชร์ลิงก์เชิญแบบใช้ครั้งเดียว</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve"> <trans-unit id="Share with contacts" xml:space="preserve">
@@ -4705,15 +4617,16 @@ Error: %@</source>
<target>ใครบางคน</target> <target>ใครบางคน</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="Start a new chat" xml:space="preserve">
<source>Start a new chat</source>
<target>เริ่มแชทใหม่</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start chat" xml:space="preserve"> <trans-unit id="Start chat" xml:space="preserve">
<source>Start chat</source> <source>Start chat</source>
<target>เริ่มแชท</target> <target>เริ่มแชท</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Start chat?" xml:space="preserve">
<source>Start chat?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start migration" xml:space="preserve"> <trans-unit id="Start migration" xml:space="preserve">
<source>Start migration</source> <source>Start migration</source>
<target>เริ่มการย้ายข้อมูล</target> <target>เริ่มการย้ายข้อมูล</target>
@@ -4838,14 +4751,6 @@ Error: %@</source>
<target>แตะเพื่อเข้าร่วมโหมดไม่ระบุตัวตน</target> <target>แตะเพื่อเข้าร่วมโหมดไม่ระบุตัวตน</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Tap to paste link" xml:space="preserve">
<source>Tap to paste link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to scan" xml:space="preserve">
<source>Tap to scan</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve"> <trans-unit id="Tap to start a new chat" xml:space="preserve">
<source>Tap to start a new chat</source> <source>Tap to start a new chat</source>
<target>แตะเพื่อเริ่มแชทใหม่</target> <target>แตะเพื่อเริ่มแชทใหม่</target>
@@ -4909,10 +4814,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>ความพยายามในการเปลี่ยนรหัสผ่านของฐานข้อมูลไม่เสร็จสมบูรณ์</target> <target>ความพยายามในการเปลี่ยนรหัสผ่านของฐานข้อมูลไม่เสร็จสมบูรณ์</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source> <source>The connection you accepted will be cancelled!</source>
<target>การเชื่อมต่อที่คุณยอมรับจะถูกยกเลิก!</target> <target>การเชื่อมต่อที่คุณยอมรับจะถูกยกเลิก!</target>
@@ -4978,10 +4879,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>เซิร์ฟเวอร์สำหรับการเชื่อมต่อใหม่ของโปรไฟล์การแชทปัจจุบันของคุณ **%@**</target> <target>เซิร์ฟเวอร์สำหรับการเชื่อมต่อใหม่ของโปรไฟล์การแชทปัจจุบันของคุณ **%@**</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve">
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve"> <trans-unit id="Theme" xml:space="preserve">
<source>Theme</source> <source>Theme</source>
<target>ธีม</target> <target>ธีม</target>
@@ -5057,10 +4954,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>เพื่อการเชื่อมต่อ ผู้ติดต่อของคุณสามารถสแกนคิวอาร์โค้ดหรือใช้ลิงก์ในแอป</target> <target>เพื่อการเชื่อมต่อ ผู้ติดต่อของคุณสามารถสแกนคิวอาร์โค้ดหรือใช้ลิงก์ในแอป</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve"> <trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source> <source>To make a new connection</source>
<target>เพื่อสร้างการเชื่อมต่อใหม่</target> <target>เพื่อสร้างการเชื่อมต่อใหม่</target>
@@ -5127,6 +5020,11 @@ You will be prompted to complete authentication before this feature is enabled.<
<target>ปิด</target> <target>ปิด</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Turn off notifications?" xml:space="preserve">
<source>Turn off notifications?</source>
<target>ปิดการแจ้งเตือนไหม?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn on" xml:space="preserve"> <trans-unit id="Turn on" xml:space="preserve">
<source>Turn on</source> <source>Turn on</source>
<target>เปิด</target> <target>เปิด</target>
@@ -5321,10 +5219,6 @@ To connect, please ask your contact to create another connection link and check
<source>Use new incognito profile</source> <source>Use new incognito profile</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use only local notifications?" xml:space="preserve">
<source>Use only local notifications?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve"> <trans-unit id="Use server" xml:space="preserve">
<source>Use server</source> <source>Use server</source>
<target>ใช้เซิร์ฟเวอร์</target> <target>ใช้เซิร์ฟเวอร์</target>
@@ -5372,10 +5266,6 @@ To connect, please ask your contact to create another connection link and check
<target>ผ่านเบราว์เซอร์</target> <target>ผ่านเบราว์เซอร์</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve"> <trans-unit id="Video call" xml:space="preserve">
<source>Video call</source> <source>Video call</source>
<target>การสนทนาทางวิดีโอ</target> <target>การสนทนาทางวิดีโอ</target>
@@ -5426,10 +5316,6 @@ To connect, please ask your contact to create another connection link and check
<target>ข้อความเสียง…</target> <target>ข้อความเสียง…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Waiting for desktop..." xml:space="preserve">
<source>Waiting for desktop...</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Waiting for file" xml:space="preserve"> <trans-unit id="Waiting for file" xml:space="preserve">
<source>Waiting for file</source> <source>Waiting for file</source>
<target>กำลังรอไฟล์</target> <target>กำลังรอไฟล์</target>
@@ -5574,6 +5460,11 @@ Repeat join request?</source>
<target>คุณสามารถรับสายจากหน้าจอล็อกโดยไม่ต้องมีการตรวจสอบสิทธิ์อุปกรณ์และแอป</target> <target>คุณสามารถรับสายจากหน้าจอล็อกโดยไม่ต้องมีการตรวจสอบสิทธิ์อุปกรณ์และแอป</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve">
<source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source>
<target>คุณสามารถเชื่อมต่อได้โดยคลิกที่ลิงค์ หากเปิดในเบราว์เซอร์ ให้คลิกปุ่ม **เปิดในแอปมือถือ**</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can create it later" xml:space="preserve"> <trans-unit id="You can create it later" xml:space="preserve">
<source>You can create it later</source> <source>You can create it later</source>
<target>คุณสามารถสร้างได้ในภายหลัง</target> <target>คุณสามารถสร้างได้ในภายหลัง</target>
@@ -5594,10 +5485,6 @@ Repeat join request?</source>
<target>คุณสามารถซ่อนหรือปิดเสียงโปรไฟล์ผู้ใช้ - ปัดไปทางขวา</target> <target>คุณสามารถซ่อนหรือปิดเสียงโปรไฟล์ผู้ใช้ - ปัดไปทางขวา</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now send messages to %@" xml:space="preserve"> <trans-unit id="You can now send messages to %@" xml:space="preserve">
<source>You can now send messages to %@</source> <source>You can now send messages to %@</source>
<target>ตอนนี้คุณสามารถส่งข้อความถึง %@</target> <target>ตอนนี้คุณสามารถส่งข้อความถึง %@</target>
@@ -5638,10 +5525,6 @@ Repeat join request?</source>
<target>คุณสามารถใช้มาร์กดาวน์เพื่อจัดรูปแบบข้อความ:</target> <target>คุณสามารถใช้มาร์กดาวน์เพื่อจัดรูปแบบข้อความ:</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can view invitation link again in connection details." xml:space="preserve">
<source>You can view invitation link again in connection details.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can't send messages!" xml:space="preserve"> <trans-unit id="You can't send messages!" xml:space="preserve">
<source>You can't send messages!</source> <source>You can't send messages!</source>
<target>คุณไม่สามารถส่งข้อความได้!</target> <target>คุณไม่สามารถส่งข้อความได้!</target>
@@ -5825,6 +5708,13 @@ You can cancel this connection and remove the contact (and try later with a new
<target>ผู้ติดต่อของคุณสามารถอนุญาตให้ลบข้อความทั้งหมดได้</target> <target>ผู้ติดต่อของคุณสามารถอนุญาตให้ลบข้อความทั้งหมดได้</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your contacts in SimpleX will see it.&#10;You can change it in Settings." xml:space="preserve">
<source>Your contacts in SimpleX will see it.
You can change it in Settings.</source>
<target>ผู้ติดต่อของคุณใน SimpleX จะเห็น
คุณสามารถเปลี่ยนได้ในการตั้งค่า</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve"> <trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source> <source>Your contacts will remain connected.</source>
<target>ผู้ติดต่อของคุณจะยังคงเชื่อมต่ออยู่</target> <target>ผู้ติดต่อของคุณจะยังคงเชื่อมต่ออยู่</target>
@@ -5954,10 +5844,6 @@ SimpleX servers cannot see your profile.</source>
<target>การโทรด้วยเสียง (ไม่ได้ encrypt จากต้นจนจบ)</target> <target>การโทรด้วยเสียง (ไม่ได้ encrypt จากต้นจนจบ)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="author" xml:space="preserve">
<source>author</source>
<note>member role</note>
</trans-unit>
<trans-unit id="bad message ID" xml:space="preserve"> <trans-unit id="bad message ID" xml:space="preserve">
<source>bad message ID</source> <source>bad message ID</source>
<target>ID ข้อความที่ไม่ดี</target> <target>ID ข้อความที่ไม่ดี</target>
@@ -5,31 +5,25 @@
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/> <tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
</header> </header>
<body> <body>
<trans-unit id="&#10;" xml:space="preserve" approved="no"> <trans-unit id="&#10;" xml:space="preserve">
<source> <source>
</source> </source>
<target state="needs-translation">
</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id=" " xml:space="preserve" approved="no"> <trans-unit id=" " xml:space="preserve">
<source> </source> <source> </source>
<target state="needs-translation"> </target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id=" " xml:space="preserve" approved="no"> <trans-unit id=" " xml:space="preserve">
<source> </source> <source> </source>
<target state="needs-translation"> </target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id=" " xml:space="preserve" approved="no"> <trans-unit id=" " xml:space="preserve">
<source> </source> <source> </source>
<target state="translated"> </target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id=" (" xml:space="preserve" approved="no"> <trans-unit id=" (" xml:space="preserve">
<source> (</source> <source> (</source>
<target state="needs-translation"> (</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id=" (can be copied)" xml:space="preserve" approved="no"> <trans-unit id=" (can be copied)" xml:space="preserve" approved="no">
@@ -349,9 +343,8 @@
<target state="translated">30 saniye</target> <target state="translated">30 saniye</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id=": " xml:space="preserve" approved="no"> <trans-unit id=": " xml:space="preserve">
<source>: </source> <source>: </source>
<target state="needs-translation">: </target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="&lt;p&gt;Hi!&lt;/p&gt;&#10;&lt;p&gt;&lt;a href=&quot;%@&quot;&gt;Connect to me via SimpleX Chat&lt;/a&gt;&lt;/p&gt;" xml:space="preserve" approved="no"> <trans-unit id="&lt;p&gt;Hi!&lt;/p&gt;&#10;&lt;p&gt;&lt;a href=&quot;%@&quot;&gt;Connect to me via SimpleX Chat&lt;/a&gt;&lt;/p&gt;" xml:space="preserve" approved="no">
@@ -397,9 +390,8 @@
<source>Abort changing address?</source> <source>Abort changing address?</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="About SimpleX" xml:space="preserve" approved="no"> <trans-unit id="About SimpleX" xml:space="preserve">
<source>About SimpleX</source> <source>About SimpleX</source>
<target state="translated">SimpleX Hakkında</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="About SimpleX Chat" xml:space="preserve"> <trans-unit id="About SimpleX Chat" xml:space="preserve">
@@ -414,9 +406,8 @@
<source>Accent color</source> <source>Accent color</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Accept" xml:space="preserve" approved="no"> <trans-unit id="Accept" xml:space="preserve">
<source>Accept</source> <source>Accept</source>
<target state="translated">Kabul et</target>
<note>accept contact request via notification <note>accept contact request via notification
accept incoming call via notification</note> accept incoming call via notification</note>
</trans-unit> </trans-unit>
@@ -444,57 +435,48 @@
<source>Add profile</source> <source>Add profile</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add servers by scanning QR codes." xml:space="preserve" approved="no"> <trans-unit id="Add servers by scanning QR codes." xml:space="preserve">
<source>Add servers by scanning QR codes.</source> <source>Add servers by scanning QR codes.</source>
<target state="translated">Karekod taratarak sunucuları ekleyin.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add server…" xml:space="preserve" approved="no"> <trans-unit id="Add server…" xml:space="preserve">
<source>Add server…</source> <source>Add server…</source>
<target state="translated">Sunucu ekle…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add to another device" xml:space="preserve"> <trans-unit id="Add to another device" xml:space="preserve">
<source>Add to another device</source> <source>Add to another device</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add welcome message" xml:space="preserve" approved="no"> <trans-unit id="Add welcome message" xml:space="preserve">
<source>Add welcome message</source> <source>Add welcome message</source>
<target state="translated">Karşılama mesajı ekleyin</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Address" xml:space="preserve" approved="no"> <trans-unit id="Address" xml:space="preserve">
<source>Address</source> <source>Address</source>
<target state="translated">Adres</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Address change will be aborted. Old receiving address will be used." xml:space="preserve" approved="no"> <trans-unit id="Address change will be aborted. Old receiving address will be used." xml:space="preserve">
<source>Address change will be aborted. Old receiving address will be used.</source> <source>Address change will be aborted. Old receiving address will be used.</source>
<target state="translated">Adres değişikliği iptal edilecek. Eski alıcı adresi kullanılacaktır.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Admins can create the links to join groups." xml:space="preserve"> <trans-unit id="Admins can create the links to join groups." xml:space="preserve">
<source>Admins can create the links to join groups.</source> <source>Admins can create the links to join groups.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Advanced network settings" xml:space="preserve" approved="no"> <trans-unit id="Advanced network settings" xml:space="preserve">
<source>Advanced network settings</source> <source>Advanced network settings</source>
<target state="translated">GGelişmiş ağ ayarları</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="All app data is deleted." xml:space="preserve" approved="no"> <trans-unit id="All app data is deleted." xml:space="preserve">
<source>All app data is deleted.</source> <source>All app data is deleted.</source>
<target state="translated">Tüm uygulama verileri silinir.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="All chats and messages will be deleted - this cannot be undone!" xml:space="preserve" approved="no"> <trans-unit id="All chats and messages will be deleted - this cannot be undone!" xml:space="preserve">
<source>All chats and messages will be deleted - this cannot be undone!</source> <source>All chats and messages will be deleted - this cannot be undone!</source>
<target state="translated">Tüm konuşmalar ve mesajlar silinecektir. Bu, geri alınamaz!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="All data is erased when it is entered." xml:space="preserve" approved="no"> <trans-unit id="All data is erased when it is entered." xml:space="preserve">
<source>All data is erased when it is entered.</source> <source>All data is erased when it is entered.</source>
<target state="translated">Kullanıldığında bütün veriler silinir.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="All group members will remain connected." xml:space="preserve" approved="no"> <trans-unit id="All group members will remain connected." xml:space="preserve" approved="no">
@@ -502,29 +484,24 @@
<target state="translated">Tüm grup üyeleri bağlı kalacaktır.</target> <target state="translated">Tüm grup üyeleri bağlı kalacaktır.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </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" approved="no"> <trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve">
<source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source> <source>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</source>
<target state="translated">Tüm mesajlar silinecektir. Bu, geri alınamaz! Mesajlar, YALNIZCA senin için silinecektir.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve" approved="no"> <trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source> <source>All your contacts will remain connected.</source>
<target state="translated">Konuştuğun kişilerin tümü bağlı kalacaktır.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="All your contacts will remain connected. Profile update will be sent to your contacts." xml:space="preserve" approved="no"> <trans-unit id="All your contacts will remain connected. Profile update will be sent to your contacts." xml:space="preserve">
<source>All your contacts will remain connected. Profile update will be sent to your contacts.</source> <source>All your contacts will remain connected. Profile update will be sent to your contacts.</source>
<target state="translated">Tüm kişileriniz bağlı kalacaktır. Profil güncellemesi kişilerinize gönderilecektir.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Allow" xml:space="preserve" approved="no"> <trans-unit id="Allow" xml:space="preserve">
<source>Allow</source> <source>Allow</source>
<target state="translated">İzin ver</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Allow calls only if your contact allows them." xml:space="preserve" approved="no"> <trans-unit id="Allow calls only if your contact allows them." xml:space="preserve">
<source>Allow calls only if your contact allows them.</source> <source>Allow calls only if your contact allows them.</source>
<target state="translated">Yalnızca irtibat kişiniz izin veriyorsa aramalara izin verin.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Allow disappearing messages only if your contact allows it to you." xml:space="preserve"> <trans-unit id="Allow disappearing messages only if your contact allows it to you." xml:space="preserve">
@@ -535,9 +512,8 @@
<source>Allow irreversible message deletion only if your contact allows it to you.</source> <source>Allow irreversible message deletion only if your contact allows it to you.</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve" approved="no"> <trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve">
<source>Allow message reactions only if your contact allows them.</source> <source>Allow message reactions only if your contact allows them.</source>
<target state="translated">Yalnızca kişin mesaj tepkilerine izin veriyorsa sen de ver.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Allow message reactions." xml:space="preserve"> <trans-unit id="Allow message reactions." xml:space="preserve">
@@ -549,39 +525,32 @@
<target state="translated">Üyelere direkt mesaj göndermeye izin ver.</target> <target state="translated">Üyelere direkt mesaj göndermeye izin ver.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Allow sending disappearing messages." xml:space="preserve" approved="no"> <trans-unit id="Allow sending disappearing messages." xml:space="preserve">
<source>Allow sending disappearing messages.</source> <source>Allow sending disappearing messages.</source>
<target state="translated">Kendiliğinden yok olan mesajlar göndermeye izin ver.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve" approved="no"> <trans-unit id="Allow to irreversibly delete sent messages." xml:space="preserve">
<source>Allow to irreversibly delete sent messages.</source> <source>Allow to irreversibly delete sent messages.</source>
<target state="translated">Gönderilen mesajların kalıcı olarak silinmesine izin ver.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Allow to send files and media." xml:space="preserve" approved="no"> <trans-unit id="Allow to send files and media." xml:space="preserve">
<source>Allow to send files and media.</source> <source>Allow to send files and media.</source>
<target state="translated">Dosya ve medya göndermeye izin ver.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Allow to send voice messages." xml:space="preserve" approved="no"> <trans-unit id="Allow to send voice messages." xml:space="preserve">
<source>Allow to send voice messages.</source> <source>Allow to send voice messages.</source>
<target state="translated">Sesli mesaj göndermeye izin ver.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Allow voice messages only if your contact allows them." xml:space="preserve" approved="no"> <trans-unit id="Allow voice messages only if your contact allows them." xml:space="preserve">
<source>Allow voice messages only if your contact allows them.</source> <source>Allow voice messages only if your contact allows them.</source>
<target state="translated">Yalnızca kişiniz sesli mesaj göndermeye izin veriyorsa sen de ver.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Allow voice messages?" xml:space="preserve" approved="no"> <trans-unit id="Allow voice messages?" xml:space="preserve">
<source>Allow voice messages?</source> <source>Allow voice messages?</source>
<target state="translated">Sesli mesajlara izin ver?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Allow your contacts adding message reactions." xml:space="preserve" approved="no"> <trans-unit id="Allow your contacts adding message reactions." xml:space="preserve">
<source>Allow your contacts adding message reactions.</source> <source>Allow your contacts adding message reactions.</source>
<target state="translated">Konuştuğun kişilerin mesajlarına tepki eklemesine izin ver.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Allow your contacts to call you." xml:space="preserve"> <trans-unit id="Allow your contacts to call you." xml:space="preserve">
@@ -608,28 +577,24 @@
<source>Always use relay</source> <source>Always use relay</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="An empty chat profile with the provided name is created, and the app opens as usual." xml:space="preserve" approved="no"> <trans-unit id="An empty chat profile with the provided name is created, and the app opens as usual." xml:space="preserve">
<source>An empty chat profile with the provided name is created, and the app opens as usual.</source> <source>An empty chat profile with the provided name is created, and the app opens as usual.</source>
<target state="translated">Verilen adla boş bir sohbet profili oluşturulur ve uygulama her zamanki gibi açılır.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Answer call" xml:space="preserve" approved="no"> <trans-unit id="Answer call" xml:space="preserve">
<source>Answer call</source> <source>Answer call</source>
<target state="translated">Aramayı cevapla</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="App build: %@" xml:space="preserve"> <trans-unit id="App build: %@" xml:space="preserve">
<source>App build: %@</source> <source>App build: %@</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="App icon" xml:space="preserve" approved="no"> <trans-unit id="App icon" xml:space="preserve">
<source>App icon</source> <source>App icon</source>
<target state="translated">Uygulama simgesi</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="App passcode" xml:space="preserve" approved="no"> <trans-unit id="App passcode" xml:space="preserve">
<source>App passcode</source> <source>App passcode</source>
<target state="translated">Uygulama erişim kodu</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="App passcode is replaced with self-destruct passcode." xml:space="preserve"> <trans-unit id="App passcode is replaced with self-destruct passcode." xml:space="preserve">
@@ -4928,41 +4893,6 @@ SimpleX servers cannot see your profile.</source>
<target state="needs-translation">\~strike~</target> <target state="needs-translation">\~strike~</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Accept connection request?" xml:space="preserve" approved="no">
<source>Accept connection request?</source>
<target state="translated">Bağlantı isteğini kabul et?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve" approved="no">
<source># %@</source>
<target state="needs-translation"># %@</target>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="Already connecting!" xml:space="preserve" approved="no">
<source>Already connecting!</source>
<target state="translated">Zaten bağlanılıyor!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A few more things" xml:space="preserve" approved="no">
<source>A few more things</source>
<target state="translated">Birkaç şey daha</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve" approved="no">
<source>## History</source>
<target state="translated">## Geçmiş</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="A new random profile will be shared." xml:space="preserve" approved="no">
<source>A new random profile will be shared.</source>
<target state="translated">Yeni bir rastgele profil paylaşılacak.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Already joining the group!" xml:space="preserve" approved="no">
<source>Already joining the group!</source>
<target state="translated">Zaten gruba bağlanılıyor!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
</body> </body>
</file> </file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="tr" datatype="plaintext"> <file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="tr" datatype="plaintext">
@@ -89,7 +89,6 @@
</trans-unit> </trans-unit>
<trans-unit id="%@ and %@" xml:space="preserve"> <trans-unit id="%@ and %@" xml:space="preserve">
<source>%@ and %@</source> <source>%@ and %@</source>
<target>%@ та %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%@ and %@ connected" xml:space="preserve"> <trans-unit id="%@ and %@ connected" xml:space="preserve">
@@ -104,7 +103,6 @@
</trans-unit> </trans-unit>
<trans-unit id="%@ connected" xml:space="preserve"> <trans-unit id="%@ connected" xml:space="preserve">
<source>%@ connected</source> <source>%@ connected</source>
<target>%@ підключено</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%@ is connected!" xml:space="preserve"> <trans-unit id="%@ is connected!" xml:space="preserve">
@@ -134,7 +132,6 @@
</trans-unit> </trans-unit>
<trans-unit id="%@, %@ and %lld members" xml:space="preserve"> <trans-unit id="%@, %@ and %lld members" xml:space="preserve">
<source>%@, %@ and %lld members</source> <source>%@, %@ and %lld members</source>
<target>%@, %@ та %lld учасників</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve"> <trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve">
@@ -204,7 +201,6 @@
</trans-unit> </trans-unit>
<trans-unit id="%lld group events" xml:space="preserve"> <trans-unit id="%lld group events" xml:space="preserve">
<source>%lld group events</source> <source>%lld group events</source>
<target>%lld групові заходи</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%lld members" xml:space="preserve"> <trans-unit id="%lld members" xml:space="preserve">
@@ -214,17 +210,14 @@
</trans-unit> </trans-unit>
<trans-unit id="%lld messages blocked" xml:space="preserve"> <trans-unit id="%lld messages blocked" xml:space="preserve">
<source>%lld messages blocked</source> <source>%lld messages blocked</source>
<target>%lld повідомлень заблоковано</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve"> <trans-unit id="%lld messages marked deleted" xml:space="preserve">
<source>%lld messages marked deleted</source> <source>%lld messages marked deleted</source>
<target>%lld повідомлень позначено як видалені</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%lld messages moderated by %@" xml:space="preserve"> <trans-unit id="%lld messages moderated by %@" xml:space="preserve">
<source>%lld messages moderated by %@</source> <source>%lld messages moderated by %@</source>
<target>%lld повідомлень модерує %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%lld minutes" xml:space="preserve"> <trans-unit id="%lld minutes" xml:space="preserve">
@@ -234,7 +227,6 @@
</trans-unit> </trans-unit>
<trans-unit id="%lld new interface languages" xml:space="preserve"> <trans-unit id="%lld new interface languages" xml:space="preserve">
<source>%lld new interface languages</source> <source>%lld new interface languages</source>
<target>%lld нові мови інтерфейсу</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%lld second(s)" xml:space="preserve"> <trans-unit id="%lld second(s)" xml:space="preserve">
@@ -299,12 +291,10 @@
</trans-unit> </trans-unit>
<trans-unit id="(new)" xml:space="preserve"> <trans-unit id="(new)" xml:space="preserve">
<source>(new)</source> <source>(new)</source>
<target>(новий)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="(this device v%@)" xml:space="preserve"> <trans-unit id="(this device v%@)" xml:space="preserve">
<source>(this device v%@)</source> <source>(this device v%@)</source>
<target>(цей пристрій v%@)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id=")" xml:space="preserve"> <trans-unit id=")" xml:space="preserve">
@@ -312,17 +302,14 @@
<target>)</target> <target>)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve">
<source>**Add contact**: to create a new invitation link, or connect via a link you received.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target>**Додати новий контакт**: щоб створити одноразовий QR-код або посилання для свого контакту.</target> <target>**Додати новий контакт**: щоб створити одноразовий QR-код або посилання для свого контакту.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Create group**: to create a new group." xml:space="preserve"> <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<source>**Create group**: to create a new group.</source> <source>**Create link / QR code** for your contact to use.</source>
<target>**Створіть посилання / QR-код** для використання вашим контактом.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -335,6 +322,11 @@
<target>**Найбільш приватний**: не використовуйте сервер сповіщень SimpleX Chat, періодично перевіряйте повідомлення у фоновому режимі (залежить від того, як часто ви користуєтесь додатком).</target> <target>**Найбільш приватний**: не використовуйте сервер сповіщень SimpleX Chat, періодично перевіряйте повідомлення у фоновому режимі (залежить від того, як часто ви користуєтесь додатком).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve">
<source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source>
<target>**Вставте отримане посилання** або відкрийте його в браузері і натисніть **Відкрити в мобільному додатку**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve">
<source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source>
<target>**Зверніть увагу: ви НЕ зможете відновити або змінити пароль, якщо втратите його.</target> <target>**Зверніть увагу: ви НЕ зможете відновити або змінити пароль, якщо втратите його.</target>
@@ -345,6 +337,11 @@
<target>**Рекомендується**: токен пристрою та сповіщення надсилаються на сервер сповіщень SimpleX Chat, але не вміст повідомлення, його розмір або від кого воно надійшло.</target> <target>**Рекомендується**: токен пристрою та сповіщення надсилаються на сервер сповіщень SimpleX Chat, але не вміст повідомлення, його розмір або від кого воно надійшло.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve">
<source>**Scan QR code**: to connect to your contact in person or via video call.</source>
<target>**Відскануйте QR-код**: щоб з'єднатися з вашим контактом особисто або за допомогою відеодзвінка.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target>**Попередження**: Для отримання миттєвих пуш-сповіщень потрібна парольна фраза, збережена у брелоку.</target> <target>**Попередження**: Для отримання миттєвих пуш-сповіщень потрібна парольна фраза, збережена у брелоку.</target>
@@ -374,9 +371,6 @@
<source>- connect to [directory service](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) (BETA)! <source>- connect to [directory service](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) (BETA)!
- delivery receipts (up to 20 members). - delivery receipts (up to 20 members).
- faster and more stable.</source> - faster and more stable.</source>
<target>- підключитися до [сервера каталогів](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. цибуля) (БЕТА)!
- підтвердження доставлення (до 20 учасників).
- швидше і стабільніше.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="- more stable message delivery.&#10;- a bit better groups.&#10;- and more!" xml:space="preserve"> <trans-unit id="- more stable message delivery.&#10;- a bit better groups.&#10;- and more!" xml:space="preserve">
@@ -388,15 +382,6 @@
- і багато іншого!</target> - і багато іншого!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="- optionally notify deleted contacts.&#10;- profile names with spaces.&#10;- and more!" xml:space="preserve">
<source>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</source>
<target>- опція сповіщати про видалені контакти.
- імена профілів з пробілами.
- та багато іншого!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve"> <trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve">
<source>- voice messages up to 5 minutes. <source>- voice messages up to 5 minutes.
- custom time to disappear. - custom time to disappear.
@@ -413,7 +398,6 @@
</trans-unit> </trans-unit>
<trans-unit id="0 sec" xml:space="preserve"> <trans-unit id="0 sec" xml:space="preserve">
<source>0 sec</source> <source>0 sec</source>
<target>0 сек</target>
<note>time to disappear</note> <note>time to disappear</note>
</trans-unit> </trans-unit>
<trans-unit id="0s" xml:space="preserve"> <trans-unit id="0s" xml:space="preserve">
@@ -446,6 +430,11 @@
<target>1 тиждень</target> <target>1 тиждень</target>
<note>time interval</note> <note>time interval</note>
</trans-unit> </trans-unit>
<trans-unit id="1-time link" xml:space="preserve">
<source>1-time link</source>
<target>1-разове посилання</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="5 minutes" xml:space="preserve"> <trans-unit id="5 minutes" xml:space="preserve">
<source>5 minutes</source> <source>5 minutes</source>
<target>5 хвилин</target> <target>5 хвилин</target>
@@ -561,10 +550,6 @@
<target>Додайте адресу до свого профілю, щоб ваші контакти могли поділитися нею з іншими людьми. Повідомлення про оновлення профілю буде надіслано вашим контактам.</target> <target>Додайте адресу до свого профілю, щоб ваші контакти могли поділитися нею з іншими людьми. Повідомлення про оновлення профілю буде надіслано вашим контактам.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add contact" xml:space="preserve">
<source>Add contact</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve"> <trans-unit id="Add preset servers" xml:space="preserve">
<source>Add preset servers</source> <source>Add preset servers</source>
<target>Додавання попередньо встановлених серверів</target> <target>Додавання попередньо встановлених серверів</target>
@@ -642,7 +627,6 @@
</trans-unit> </trans-unit>
<trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve"> <trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve">
<source>All new messages from %@ will be hidden!</source> <source>All new messages from %@ will be hidden!</source>
<target>Всі нові повідомлення від %@ будуть приховані!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve"> <trans-unit id="All your contacts will remain connected." xml:space="preserve">
@@ -752,12 +736,10 @@
</trans-unit> </trans-unit>
<trans-unit id="Already connecting!" xml:space="preserve"> <trans-unit id="Already connecting!" xml:space="preserve">
<source>Already connecting!</source> <source>Already connecting!</source>
<target>Вже підключаємось!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Already joining the group!" xml:space="preserve"> <trans-unit id="Already joining the group!" xml:space="preserve">
<source>Already joining the group!</source> <source>Already joining the group!</source>
<target>Вже приєднуємося до групи!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Always use relay" xml:space="preserve"> <trans-unit id="Always use relay" xml:space="preserve">
@@ -782,7 +764,6 @@
</trans-unit> </trans-unit>
<trans-unit id="App encrypts new local files (except videos)." xml:space="preserve"> <trans-unit id="App encrypts new local files (except videos)." xml:space="preserve">
<source>App encrypts new local files (except videos).</source> <source>App encrypts new local files (except videos).</source>
<target>Додаток шифрує нові локальні файли (крім відео).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="App icon" xml:space="preserve"> <trans-unit id="App icon" xml:space="preserve">
@@ -882,7 +863,6 @@
</trans-unit> </trans-unit>
<trans-unit id="Bad desktop address" xml:space="preserve"> <trans-unit id="Bad desktop address" xml:space="preserve">
<source>Bad desktop address</source> <source>Bad desktop address</source>
<target>Неправильна адреса робочого столу</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Bad message ID" xml:space="preserve"> <trans-unit id="Bad message ID" xml:space="preserve">
@@ -895,11 +875,6 @@
<target>Поганий хеш повідомлення</target> <target>Поганий хеш повідомлення</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
<source>Better groups</source>
<target>Кращі групи</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better messages" xml:space="preserve"> <trans-unit id="Better messages" xml:space="preserve">
<source>Better messages</source> <source>Better messages</source>
<target>Кращі повідомлення</target> <target>Кращі повідомлення</target>
@@ -907,22 +882,14 @@
</trans-unit> </trans-unit>
<trans-unit id="Block" xml:space="preserve"> <trans-unit id="Block" xml:space="preserve">
<source>Block</source> <source>Block</source>
<target>Блокувати</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
<source>Block group members</source>
<target>Учасники групи блокування</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block member" xml:space="preserve"> <trans-unit id="Block member" xml:space="preserve">
<source>Block member</source> <source>Block member</source>
<target>Заблокувати користувача</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block member?" xml:space="preserve"> <trans-unit id="Block member?" xml:space="preserve">
<source>Block member?</source> <source>Block member?</source>
<target>Заблокувати користувача?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve"> <trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@@ -952,7 +919,6 @@
</trans-unit> </trans-unit>
<trans-unit id="Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve"> <trans-unit id="Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve">
<source>Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source> <source>Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
<target>Болгарською, фінською, тайською та українською мовами - завдяки користувачам та [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)." xml:space="preserve"> <trans-unit id="By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)." xml:space="preserve">
@@ -970,10 +936,6 @@
<target>Дзвінки</target> <target>Дзвінки</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Camera not available" xml:space="preserve">
<source>Camera not available</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Can't delete user profile!" xml:space="preserve"> <trans-unit id="Can't delete user profile!" xml:space="preserve">
<source>Can't delete user profile!</source> <source>Can't delete user profile!</source>
<target>Не можу видалити профіль користувача!</target> <target>Не можу видалити профіль користувача!</target>
@@ -1090,10 +1052,6 @@
<target>Чат зупинено</target> <target>Чат зупинено</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve">
<source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve"> <trans-unit id="Chat preferences" xml:space="preserve">
<source>Chat preferences</source> <source>Chat preferences</source>
<target>Налаштування чату</target> <target>Налаштування чату</target>
@@ -1194,11 +1152,6 @@
<target>Підключіться</target> <target>Підключіться</target>
<note>server test step</note> <note>server test step</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect automatically" xml:space="preserve">
<source>Connect automatically</source>
<target>Підключення автоматично</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve"> <trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source> <source>Connect incognito</source>
<target>Підключайтеся інкогніто</target> <target>Підключайтеся інкогніто</target>
@@ -1206,31 +1159,24 @@
</trans-unit> </trans-unit>
<trans-unit id="Connect to desktop" xml:space="preserve"> <trans-unit id="Connect to desktop" xml:space="preserve">
<source>Connect to desktop</source> <source>Connect to desktop</source>
<target>Підключення до комп'ютера</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve"> <trans-unit id="Connect to yourself?" xml:space="preserve">
<source>Connect to yourself?</source> <source>Connect to yourself?</source>
<target>З'єднатися з самим собою?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own SimpleX address!" xml:space="preserve"> <trans-unit id="Connect to yourself?&#10;This is your own SimpleX address!" xml:space="preserve">
<source>Connect to yourself? <source>Connect to yourself?
This is your own SimpleX address!</source> This is your own SimpleX address!</source>
<target>З'єднатися з самим собою?
Це ваша власна SimpleX-адреса!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own one-time link!" xml:space="preserve"> <trans-unit id="Connect to yourself?&#10;This is your own one-time link!" xml:space="preserve">
<source>Connect to yourself? <source>Connect to yourself?
This is your own one-time link!</source> This is your own one-time link!</source>
<target>Підключитися до себе?
Це ваше власне одноразове посилання!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via contact address" xml:space="preserve"> <trans-unit id="Connect via contact address" xml:space="preserve">
<source>Connect via contact address</source> <source>Connect via contact address</source>
<target>Підключіться за контактною адресою</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link" xml:space="preserve"> <trans-unit id="Connect via link" xml:space="preserve">
@@ -1238,6 +1184,11 @@ This is your own one-time link!</source>
<target>Підключіться за посиланням</target> <target>Підключіться за посиланням</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link / QR code" xml:space="preserve">
<source>Connect via link / QR code</source>
<target>Підключитися за посиланням / QR-кодом</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link" xml:space="preserve"> <trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source> <source>Connect via one-time link</source>
<target>Під'єднатися за одноразовим посиланням</target> <target>Під'єднатися за одноразовим посиланням</target>
@@ -1245,12 +1196,10 @@ This is your own one-time link!</source>
</trans-unit> </trans-unit>
<trans-unit id="Connect with %@" xml:space="preserve"> <trans-unit id="Connect with %@" xml:space="preserve">
<source>Connect with %@</source> <source>Connect with %@</source>
<target>Підключитися до %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connected desktop" xml:space="preserve"> <trans-unit id="Connected desktop" xml:space="preserve">
<source>Connected desktop</source> <source>Connected desktop</source>
<target>Підключений робочий стіл</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connected to desktop" xml:space="preserve"> <trans-unit id="Connected to desktop" xml:space="preserve">
@@ -1374,10 +1323,6 @@ This is your own one-time link!</source>
<target>Створіть адресу SimpleX</target> <target>Створіть адресу SimpleX</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create a group using a random profile." xml:space="preserve">
<source>Create a group using a random profile.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source> <source>Create an address to let people connect with you.</source>
<target>Створіть адресу, щоб люди могли з вами зв'язатися.</target> <target>Створіть адресу, щоб люди могли з вами зв'язатися.</target>
@@ -1406,6 +1351,11 @@ This is your own one-time link!</source>
<source>Create new profile in [desktop app](https://simplex.chat/downloads/). 💻</source> <source>Create new profile in [desktop app](https://simplex.chat/downloads/). 💻</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create one-time invitation link" xml:space="preserve">
<source>Create one-time invitation link</source>
<target>Створіть одноразове посилання-запрошення</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -1430,10 +1380,6 @@ This is your own one-time link!</source>
<target>Створено %@</target> <target>Створено %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve"> <trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source> <source>Current Passcode</source>
<target>Поточний пароль</target> <target>Поточний пароль</target>
@@ -1890,8 +1836,8 @@ This cannot be undone!</source>
<source>Discover and join groups</source> <source>Discover and join groups</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve"> <trans-unit id="Discover on network" xml:space="preserve">
<source>Discover via local network</source> <source>Discover on network</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -1974,10 +1920,6 @@ This cannot be undone!</source>
<target>Увімкнути автоматичне видалення повідомлень?</target> <target>Увімкнути автоматичне видалення повідомлень?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enable camera access" xml:space="preserve">
<source>Enable camera access</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve"> <trans-unit id="Enable for all" xml:space="preserve">
<source>Enable for all</source> <source>Enable for all</source>
<target>Увімкнути для всіх</target> <target>Увімкнути для всіх</target>
@@ -2041,10 +1983,6 @@ This cannot be undone!</source>
<target>Зашифроване повідомлення або інша подія</target> <target>Зашифроване повідомлення або інша подія</target>
<note>notification</note> <note>notification</note>
</trans-unit> </trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve">
<source>Encrypted message: app is stopped</source>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve"> <trans-unit id="Encrypted message: database error" xml:space="preserve">
<source>Encrypted message: database error</source> <source>Encrypted message: database error</source>
<target>Зашифроване повідомлення: помилка бази даних</target> <target>Зашифроване повідомлення: помилка бази даних</target>
@@ -2268,10 +2206,6 @@ This cannot be undone!</source>
<target>Помилка завантаження %@ серверів</target> <target>Помилка завантаження %@ серверів</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error receiving file" xml:space="preserve"> <trans-unit id="Error receiving file" xml:space="preserve">
<source>Error receiving file</source> <source>Error receiving file</source>
<target>Помилка отримання файлу</target> <target>Помилка отримання файлу</target>
@@ -2312,10 +2246,6 @@ This cannot be undone!</source>
<target>Помилка збереження пароля користувача</target> <target>Помилка збереження пароля користувача</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error scanning code: %@" xml:space="preserve">
<source>Error scanning code: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve"> <trans-unit id="Error sending email" xml:space="preserve">
<source>Error sending email</source> <source>Error sending email</source>
<target>Помилка надсилання електронного листа</target> <target>Помилка надсилання електронного листа</target>
@@ -2439,10 +2369,6 @@ This cannot be undone!</source>
<target>Швидко і без очікування, поки відправник буде онлайн!</target> <target>Швидко і без очікування, поки відправник буде онлайн!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve"> <trans-unit id="Favorite" xml:space="preserve">
<source>Favorite</source> <source>Favorite</source>
<target>Улюблений</target> <target>Улюблений</target>
@@ -2538,10 +2464,6 @@ This cannot be undone!</source>
<target>Для консолі</target> <target>Для консолі</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Found desktop" xml:space="preserve">
<source>Found desktop</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="French interface" xml:space="preserve"> <trans-unit id="French interface" xml:space="preserve">
<source>French interface</source> <source>French interface</source>
<target>Французький інтерфейс</target> <target>Французький інтерфейс</target>
@@ -2784,6 +2706,11 @@ This cannot be undone!</source>
<target>Якщо ви не можете зустрітися особисто, покажіть QR-код у відеодзвінку або поділіться посиланням.</target> <target>Якщо ви не можете зустрітися особисто, покажіть QR-код у відеодзвінку або поділіться посиланням.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve">
<source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source>
<target>Якщо ви не можете зустрітися особисто, ви можете **сканувати QR-код у відеодзвінку**, або ваш контакт може поділитися посиланням на запрошення.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve">
<source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source>
<target>Якщо ви введете цей пароль при відкритті програми, всі дані програми будуть безповоротно видалені!</target> <target>Якщо ви введете цей пароль при відкритті програми, всі дані програми будуть безповоротно видалені!</target>
@@ -2859,10 +2786,6 @@ This cannot be undone!</source>
<target>Інкогніто</target> <target>Інкогніто</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve"> <trans-unit id="Incognito mode" xml:space="preserve">
<source>Incognito mode</source> <source>Incognito mode</source>
<target>Режим інкогніто</target> <target>Режим інкогніто</target>
@@ -2939,27 +2862,15 @@ This cannot be undone!</source>
<target>Інтерфейс</target> <target>Інтерфейс</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid QR code" xml:space="preserve">
<source>Invalid QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve"> <trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source> <source>Invalid connection link</source>
<target>Неправильне посилання для підключення</target> <target>Неправильне посилання для підключення</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
<source>Invalid link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve"> <trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source> <source>Invalid name!</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid response" xml:space="preserve">
<source>Invalid response</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve"> <trans-unit id="Invalid server address!" xml:space="preserve">
<source>Invalid server address!</source> <source>Invalid server address!</source>
<target>Неправильна адреса сервера!</target> <target>Неправильна адреса сервера!</target>
@@ -3074,18 +2985,10 @@ This is your link for group %@!</source>
<target>Приєднання до групи</target> <target>Приєднання до групи</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep" xml:space="preserve">
<source>Keep</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
<source>Keep the app open to use it from desktop</source> <source>Keep the app open to use it from desktop</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep unused invitation?" xml:space="preserve">
<source>Keep unused invitation?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve"> <trans-unit id="Keep your connections" xml:space="preserve">
<source>Keep your connections</source> <source>Keep your connections</source>
<target>Зберігайте свої зв'язки</target> <target>Зберігайте свої зв'язки</target>
@@ -3146,10 +3049,6 @@ This is your link for group %@!</source>
<target>Обмеження</target> <target>Обмеження</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve"> <trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source> <source>Linked desktop options</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3168,11 +3067,6 @@ This is your link for group %@!</source>
<target>Живі повідомлення</target> <target>Живі повідомлення</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Local" xml:space="preserve">
<source>Local</source>
<target>Локально</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Local name" xml:space="preserve"> <trans-unit id="Local name" xml:space="preserve">
<source>Local name</source> <source>Local name</source>
<target>Місцева назва</target> <target>Місцева назва</target>
@@ -3412,10 +3306,6 @@ This is your link for group %@!</source>
<target>Новий пароль</target> <target>Новий пароль</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="New chat" xml:space="preserve">
<source>New chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve"> <trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source> <source>New contact request</source>
<target>Новий запит на контакт</target> <target>Новий запит на контакт</target>
@@ -3515,10 +3405,6 @@ This is your link for group %@!</source>
<target>Немає отриманих або відправлених файлів</target> <target>Немає отриманих або відправлених файлів</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Not compatible!" xml:space="preserve">
<source>Not compatible!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve"> <trans-unit id="Notifications" xml:space="preserve">
<source>Notifications</source> <source>Notifications</source>
<target>Сповіщення</target> <target>Сповіщення</target>
@@ -3538,15 +3424,16 @@ This is your link for group %@!</source>
- відключати користувачів (роль "спостерігач")</target> - відключати користувачів (роль "спостерігач")</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="OK" xml:space="preserve">
<source>OK</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Off" xml:space="preserve"> <trans-unit id="Off" xml:space="preserve">
<source>Off</source> <source>Off</source>
<target>Вимкнено</target> <target>Вимкнено</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Off (Local)" xml:space="preserve">
<source>Off (Local)</source>
<target>Вимкнено (локально)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ok" xml:space="preserve"> <trans-unit id="Ok" xml:space="preserve">
<source>Ok</source> <source>Ok</source>
<target>Гаразд</target> <target>Гаразд</target>
@@ -3685,16 +3572,9 @@ This is your link for group %@!</source>
<target>Протокол і код з відкритим вихідним кодом - будь-хто може запускати сервери.</target> <target>Протокол і код з відкритим вихідним кодом - будь-хто може запускати сервери.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Opening app…" xml:space="preserve"> <trans-unit id="Opening database…" xml:space="preserve">
<source>Opening app…</source> <source>Opening database…</source>
<note>No comment provided by engineer.</note> <target>Відкриття бази даних…</target>
</trans-unit>
<trans-unit id="Or scan QR code" xml:space="preserve">
<source>Or scan QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
<source>Or show this code</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="PING count" xml:space="preserve"> <trans-unit id="PING count" xml:space="preserve">
@@ -3737,6 +3617,11 @@ This is your link for group %@!</source>
<target>Показати пароль</target> <target>Показати пароль</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste" xml:space="preserve">
<source>Paste</source>
<target>Вставити</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve"> <trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source> <source>Paste desktop address</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3746,10 +3631,16 @@ This is your link for group %@!</source>
<target>Вставити зображення</target> <target>Вставити зображення</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve"> <trans-unit id="Paste received link" xml:space="preserve">
<source>Paste the link you received</source> <source>Paste received link</source>
<target>Вставте отримане посилання</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Вставте отримане посилання для зв'язку з вашим контактом.</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source> <source>People can connect to you only via the links you share.</source>
<target>Люди можуть зв'язатися з вами лише за посиланнями, якими ви ділитеся.</target> <target>Люди можуть зв'язатися з вами лише за посиланнями, якими ви ділитеся.</target>
@@ -3785,11 +3676,6 @@ This is your link for group %@!</source>
<target>Будь ласка, перевірте свої та контактні налаштування.</target> <target>Будь ласка, перевірте свої та контактні налаштування.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Please contact developers.&#10;Error: %@" xml:space="preserve">
<source>Please contact developers.
Error: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please contact group admin." xml:space="preserve"> <trans-unit id="Please contact group admin." xml:space="preserve">
<source>Please contact group admin.</source> <source>Please contact group admin.</source>
<target>Зверніться до адміністратора групи.</target> <target>Зверніться до адміністратора групи.</target>
@@ -3993,10 +3879,6 @@ Error: %@</source>
<target>Читайте більше в [Посібнику користувача](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target> <target>Читайте більше в [Посібнику користувача](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source>
<target>Читайте більше в [Посібнику користувача](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target> <target>Читайте більше в [Посібнику користувача](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</target>
@@ -4205,10 +4087,6 @@ Error: %@</source>
<target>Відновлення помилки бази даних</target> <target>Відновлення помилки бази даних</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Retry" xml:space="preserve">
<source>Retry</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reveal" xml:space="preserve"> <trans-unit id="Reveal" xml:space="preserve">
<source>Reveal</source> <source>Reveal</source>
<target>Показувати</target> <target>Показувати</target>
@@ -4363,10 +4241,6 @@ Error: %@</source>
<target>Пошук</target> <target>Пошук</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve"> <trans-unit id="Secure queue" xml:space="preserve">
<source>Secure queue</source> <source>Secure queue</source>
<target>Безпечна черга</target> <target>Безпечна черга</target>
@@ -4640,8 +4514,9 @@ Error: %@</source>
<target>Поділіться посиланням</target> <target>Поділіться посиланням</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve"> <trans-unit id="Share one-time invitation link" xml:space="preserve">
<source>Share this 1-time invite link</source> <source>Share one-time invitation link</source>
<target>Поділіться посиланням на одноразове запрошення</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve"> <trans-unit id="Share with contacts" xml:space="preserve">
@@ -4763,15 +4638,16 @@ Error: %@</source>
<target>Хтось</target> <target>Хтось</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="Start a new chat" xml:space="preserve">
<source>Start a new chat</source>
<target>Почніть новий чат</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start chat" xml:space="preserve"> <trans-unit id="Start chat" xml:space="preserve">
<source>Start chat</source> <source>Start chat</source>
<target>Почати чат</target> <target>Почати чат</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Start chat?" xml:space="preserve">
<source>Start chat?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start migration" xml:space="preserve"> <trans-unit id="Start migration" xml:space="preserve">
<source>Start migration</source> <source>Start migration</source>
<target>Почати міграцію</target> <target>Почати міграцію</target>
@@ -4896,14 +4772,6 @@ Error: %@</source>
<target>Натисніть, щоб приєднатися інкогніто</target> <target>Натисніть, щоб приєднатися інкогніто</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Tap to paste link" xml:space="preserve">
<source>Tap to paste link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to scan" xml:space="preserve">
<source>Tap to scan</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve"> <trans-unit id="Tap to start a new chat" xml:space="preserve">
<source>Tap to start a new chat</source> <source>Tap to start a new chat</source>
<target>Натисніть, щоб почати новий чат</target> <target>Натисніть, щоб почати новий чат</target>
@@ -4966,10 +4834,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Спроба змінити пароль до бази даних не була завершена.</target> <target>Спроба змінити пароль до бази даних не була завершена.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source> <source>The connection you accepted will be cancelled!</source>
<target>Прийняте вами з'єднання буде скасовано!</target> <target>Прийняте вами з'єднання буде скасовано!</target>
@@ -5035,10 +4899,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Сервери для нових підключень вашого поточного профілю чату **%@**.</target> <target>Сервери для нових підключень вашого поточного профілю чату **%@**.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve">
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve"> <trans-unit id="Theme" xml:space="preserve">
<source>Theme</source> <source>Theme</source>
<target>Тема</target> <target>Тема</target>
@@ -5116,10 +4976,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Щоб підключитися, ваш контакт може відсканувати QR-код або скористатися посиланням у додатку.</target> <target>Щоб підключитися, ваш контакт може відсканувати QR-код або скористатися посиланням у додатку.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve"> <trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source> <source>To make a new connection</source>
<target>Щоб створити нове з'єднання</target> <target>Щоб створити нове з'єднання</target>
@@ -5186,6 +5042,11 @@ You will be prompted to complete authentication before this feature is enabled.<
<target>Вимкнути</target> <target>Вимкнути</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Turn off notifications?" xml:space="preserve">
<source>Turn off notifications?</source>
<target>Вимкнути сповіщення?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn on" xml:space="preserve"> <trans-unit id="Turn on" xml:space="preserve">
<source>Turn on</source> <source>Turn on</source>
<target>Ввімкнути</target> <target>Ввімкнути</target>
@@ -5382,10 +5243,6 @@ To connect, please ask your contact to create another connection link and check
<target>Використовуйте новий профіль інкогніто</target> <target>Використовуйте новий профіль інкогніто</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use only local notifications?" xml:space="preserve">
<source>Use only local notifications?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve"> <trans-unit id="Use server" xml:space="preserve">
<source>Use server</source> <source>Use server</source>
<target>Використовувати сервер</target> <target>Використовувати сервер</target>
@@ -5433,10 +5290,6 @@ To connect, please ask your contact to create another connection link and check
<target>Через браузер</target> <target>Через браузер</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve"> <trans-unit id="Video call" xml:space="preserve">
<source>Video call</source> <source>Video call</source>
<target>Відеодзвінок</target> <target>Відеодзвінок</target>
@@ -5487,10 +5340,6 @@ To connect, please ask your contact to create another connection link and check
<target>Голосове повідомлення…</target> <target>Голосове повідомлення…</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Waiting for desktop..." xml:space="preserve">
<source>Waiting for desktop...</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Waiting for file" xml:space="preserve"> <trans-unit id="Waiting for file" xml:space="preserve">
<source>Waiting for file</source> <source>Waiting for file</source>
<target>Очікування файлу</target> <target>Очікування файлу</target>
@@ -5635,6 +5484,11 @@ Repeat join request?</source>
<target>Ви можете приймати дзвінки з екрана блокування без автентифікації пристрою та програми.</target> <target>Ви можете приймати дзвінки з екрана блокування без автентифікації пристрою та програми.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve">
<source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source>
<target>Ви також можете підключитися за посиланням. Якщо воно відкриється в браузері, натисніть кнопку **Відкрити в мобільному додатку**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can create it later" xml:space="preserve"> <trans-unit id="You can create it later" xml:space="preserve">
<source>You can create it later</source> <source>You can create it later</source>
<target>Ви можете створити його пізніше</target> <target>Ви можете створити його пізніше</target>
@@ -5655,10 +5509,6 @@ Repeat join request?</source>
<target>Ви можете приховати або вимкнути звук профілю користувача - проведіть по ньому вправо.</target> <target>Ви можете приховати або вимкнути звук профілю користувача - проведіть по ньому вправо.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now send messages to %@" xml:space="preserve"> <trans-unit id="You can now send messages to %@" xml:space="preserve">
<source>You can now send messages to %@</source> <source>You can now send messages to %@</source>
<target>Тепер ви можете надсилати повідомлення на адресу %@</target> <target>Тепер ви можете надсилати повідомлення на адресу %@</target>
@@ -5699,10 +5549,6 @@ Repeat join request?</source>
<target>Ви можете використовувати розмітку для форматування повідомлень:</target> <target>Ви можете використовувати розмітку для форматування повідомлень:</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can view invitation link again in connection details." xml:space="preserve">
<source>You can view invitation link again in connection details.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can't send messages!" xml:space="preserve"> <trans-unit id="You can't send messages!" xml:space="preserve">
<source>You can't send messages!</source> <source>You can't send messages!</source>
<target>Ви не можете надсилати повідомлення!</target> <target>Ви не можете надсилати повідомлення!</target>
@@ -5887,6 +5733,13 @@ You can cancel this connection and remove the contact (and try later with a new
<target>Ваші контакти можуть дозволити повне видалення повідомлень.</target> <target>Ваші контакти можуть дозволити повне видалення повідомлень.</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your contacts in SimpleX will see it.&#10;You can change it in Settings." xml:space="preserve">
<source>Your contacts in SimpleX will see it.
You can change it in Settings.</source>
<target>Ваші контакти в SimpleX побачать це.
Ви можете змінити його в Налаштуваннях.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve"> <trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source> <source>Your contacts will remain connected.</source>
<target>Ваші контакти залишаться на зв'язку.</target> <target>Ваші контакти залишаться на зв'язку.</target>
@@ -6017,10 +5870,6 @@ SimpleX servers cannot see your profile.</source>
<target>аудіовиклик (без шифрування e2e)</target> <target>аудіовиклик (без шифрування e2e)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="author" xml:space="preserve">
<source>author</source>
<note>member role</note>
</trans-unit>
<trans-unit id="bad message ID" xml:space="preserve"> <trans-unit id="bad message ID" xml:space="preserve">
<source>bad message ID</source> <source>bad message ID</source>
<target>невірний ідентифікатор повідомлення</target> <target>невірний ідентифікатор повідомлення</target>
@@ -303,17 +303,14 @@
<target>)</target> <target>)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Add contact**: to create a new invitation link, or connect via a link you received." xml:space="preserve">
<source>**Add contact**: to create a new invitation link, or connect via a link you received.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve"> <trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source> <source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target>**添加新联系人**:为您的联系人创建一次性二维码或者链接。</target> <target>**添加新联系人**:为您的联系人创建一次性二维码或者链接。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Create group**: to create a new group." xml:space="preserve"> <trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<source>**Create group**: to create a new group.</source> <source>**Create link / QR code** for your contact to use.</source>
<target>**创建链接 / 二维码** 给您的联系人使用。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve"> <trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -326,6 +323,11 @@
<target>**最私密**:不使用 SimpleX Chat 通知服务器,在后台定期检查消息(取决于您多经常使用应用程序)。</target> <target>**最私密**:不使用 SimpleX Chat 通知服务器,在后台定期检查消息(取决于您多经常使用应用程序)。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Paste received link** or open it in the browser and tap **Open in mobile app**." xml:space="preserve">
<source>**Paste received link** or open it in the browser and tap **Open in mobile app**.</source>
<target>**粘贴收到的链接**或者在浏览器里打开并且点击**在移动应用程序里打开**。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve"> <trans-unit id="**Please note**: you will NOT be able to recover or change passphrase if you lose it." xml:space="preserve">
<source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source> <source>**Please note**: you will NOT be able to recover or change passphrase if you lose it.</source>
<target>**请注意**:如果您丢失密码,您将无法恢复或者更改密码。</target> <target>**请注意**:如果您丢失密码,您将无法恢复或者更改密码。</target>
@@ -336,6 +338,11 @@
<target>**推荐**:设备令牌和通知会发送至 SimpleX Chat 通知服务器,但是消息内容、大小或者发送人不会。</target> <target>**推荐**:设备令牌和通知会发送至 SimpleX Chat 通知服务器,但是消息内容、大小或者发送人不会。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="**Scan QR code**: to connect to your contact in person or via video call." xml:space="preserve">
<source>**Scan QR code**: to connect to your contact in person or via video call.</source>
<target>**扫描二维码**:见面或者通过视频通话来连接您的联系人。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve"> <trans-unit id="**Warning**: Instant push notifications require passphrase saved in Keychain." xml:space="preserve">
<source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source> <source>**Warning**: Instant push notifications require passphrase saved in Keychain.</source>
<target>**警告**:及时推送通知需要保存在钥匙串的密码。</target> <target>**警告**:及时推送通知需要保存在钥匙串的密码。</target>
@@ -379,12 +386,6 @@
- 以及更多!</target> - 以及更多!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="- optionally notify deleted contacts.&#10;- profile names with spaces.&#10;- and more!" xml:space="preserve">
<source>- optionally notify deleted contacts.
- profile names with spaces.
- and more!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve"> <trans-unit id="- voice messages up to 5 minutes.&#10;- custom time to disappear.&#10;- editing history." xml:space="preserve">
<source>- voice messages up to 5 minutes. <source>- voice messages up to 5 minutes.
- custom time to disappear. - custom time to disappear.
@@ -433,6 +434,11 @@
<target>1周</target> <target>1周</target>
<note>time interval</note> <note>time interval</note>
</trans-unit> </trans-unit>
<trans-unit id="1-time link" xml:space="preserve">
<source>1-time link</source>
<target>一次性链接</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="5 minutes" xml:space="preserve"> <trans-unit id="5 minutes" xml:space="preserve">
<source>5 minutes</source> <source>5 minutes</source>
<target>5分钟</target> <target>5分钟</target>
@@ -548,10 +554,6 @@
<target>将地址添加到您的个人资料,以便您的联系人可以与其他人共享。个人资料更新将发送给您的联系人。</target> <target>将地址添加到您的个人资料,以便您的联系人可以与其他人共享。个人资料更新将发送给您的联系人。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Add contact" xml:space="preserve">
<source>Add contact</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve"> <trans-unit id="Add preset servers" xml:space="preserve">
<source>Add preset servers</source> <source>Add preset servers</source>
<target>添加预设服务器</target> <target>添加预设服务器</target>
@@ -878,10 +880,6 @@
<target>错误消息散列</target> <target>错误消息散列</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Better groups" xml:space="preserve">
<source>Better groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Better messages" xml:space="preserve"> <trans-unit id="Better messages" xml:space="preserve">
<source>Better messages</source> <source>Better messages</source>
<target>更好的消息</target> <target>更好的消息</target>
@@ -891,10 +889,6 @@
<source>Block</source> <source>Block</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
<source>Block group members</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve"> <trans-unit id="Block member" xml:space="preserve">
<source>Block member</source> <source>Block member</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -948,10 +942,6 @@
<target>通话</target> <target>通话</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Camera not available" xml:space="preserve">
<source>Camera not available</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Can't delete user profile!" xml:space="preserve"> <trans-unit id="Can't delete user profile!" xml:space="preserve">
<source>Can't delete user profile!</source> <source>Can't delete user profile!</source>
<target>无法删除用户个人资料!</target> <target>无法删除用户个人资料!</target>
@@ -1068,10 +1058,6 @@
<target>聊天已停止</target> <target>聊天已停止</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat." xml:space="preserve">
<source>Chat is stopped. If you already used this database on another device, you should transfer it back before starting chat.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve"> <trans-unit id="Chat preferences" xml:space="preserve">
<source>Chat preferences</source> <source>Chat preferences</source>
<target>聊天偏好设置</target> <target>聊天偏好设置</target>
@@ -1172,10 +1158,6 @@
<target>连接</target> <target>连接</target>
<note>server test step</note> <note>server test step</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect automatically" xml:space="preserve">
<source>Connect automatically</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve"> <trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source> <source>Connect incognito</source>
<target>在隐身状态下连接</target> <target>在隐身状态下连接</target>
@@ -1208,6 +1190,11 @@ This is your own one-time link!</source>
<target>通过链接连接</target> <target>通过链接连接</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Connect via link / QR code" xml:space="preserve">
<source>Connect via link / QR code</source>
<target>通过群组链接/二维码连接</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link" xml:space="preserve"> <trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source> <source>Connect via one-time link</source>
<target>通过一次性链接连接</target> <target>通过一次性链接连接</target>
@@ -1342,10 +1329,6 @@ This is your own one-time link!</source>
<target>创建 SimpleX 地址</target> <target>创建 SimpleX 地址</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create a group using a random profile." xml:space="preserve">
<source>Create a group using a random profile.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve"> <trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source> <source>Create an address to let people connect with you.</source>
<target>创建一个地址,让人们与您联系。</target> <target>创建一个地址,让人们与您联系。</target>
@@ -1375,6 +1358,11 @@ This is your own one-time link!</source>
<target>在[桌面应用程序](https://simplex.chat/downloads/)中创建新的个人资料。 💻</target> <target>在[桌面应用程序](https://simplex.chat/downloads/)中创建新的个人资料。 💻</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Create one-time invitation link" xml:space="preserve">
<source>Create one-time invitation link</source>
<target>创建一次性邀请链接</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve"> <trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source> <source>Create profile</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -1399,10 +1387,6 @@ This is your own one-time link!</source>
<target>创建于 %@</target> <target>创建于 %@</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Creating link…" xml:space="preserve">
<source>Creating link…</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Current Passcode" xml:space="preserve"> <trans-unit id="Current Passcode" xml:space="preserve">
<source>Current Passcode</source> <source>Current Passcode</source>
<target>当前密码</target> <target>当前密码</target>
@@ -1860,8 +1844,8 @@ This cannot be undone!</source>
<target>发现和加入群组</target> <target>发现和加入群组</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve"> <trans-unit id="Discover on network" xml:space="preserve">
<source>Discover via local network</source> <source>Discover on network</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve"> <trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -1944,10 +1928,6 @@ This cannot be undone!</source>
<target>启用自动删除消息?</target> <target>启用自动删除消息?</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Enable camera access" xml:space="preserve">
<source>Enable camera access</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve"> <trans-unit id="Enable for all" xml:space="preserve">
<source>Enable for all</source> <source>Enable for all</source>
<target>全部启用</target> <target>全部启用</target>
@@ -2013,10 +1993,6 @@ This cannot be undone!</source>
<target>加密消息或其他事件</target> <target>加密消息或其他事件</target>
<note>notification</note> <note>notification</note>
</trans-unit> </trans-unit>
<trans-unit id="Encrypted message: app is stopped" xml:space="preserve">
<source>Encrypted message: app is stopped</source>
<note>notification</note>
</trans-unit>
<trans-unit id="Encrypted message: database error" xml:space="preserve"> <trans-unit id="Encrypted message: database error" xml:space="preserve">
<source>Encrypted message: database error</source> <source>Encrypted message: database error</source>
<target>加密消息:数据库错误</target> <target>加密消息:数据库错误</target>
@@ -2242,10 +2218,6 @@ This cannot be undone!</source>
<target>加载 %@ 服务器错误</target> <target>加载 %@ 服务器错误</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error opening chat" xml:space="preserve">
<source>Error opening chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error receiving file" xml:space="preserve"> <trans-unit id="Error receiving file" xml:space="preserve">
<source>Error receiving file</source> <source>Error receiving file</source>
<target>接收文件错误</target> <target>接收文件错误</target>
@@ -2286,10 +2258,6 @@ This cannot be undone!</source>
<target>保存用户密码时出错</target> <target>保存用户密码时出错</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Error scanning code: %@" xml:space="preserve">
<source>Error scanning code: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve"> <trans-unit id="Error sending email" xml:space="preserve">
<source>Error sending email</source> <source>Error sending email</source>
<target>发送电邮错误</target> <target>发送电邮错误</target>
@@ -2414,10 +2382,6 @@ This cannot be undone!</source>
<target>快速且无需等待发件人在线!</target> <target>快速且无需等待发件人在线!</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve"> <trans-unit id="Favorite" xml:space="preserve">
<source>Favorite</source> <source>Favorite</source>
<target>最喜欢</target> <target>最喜欢</target>
@@ -2513,10 +2477,6 @@ This cannot be undone!</source>
<target>用于控制台</target> <target>用于控制台</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Found desktop" xml:space="preserve">
<source>Found desktop</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="French interface" xml:space="preserve"> <trans-unit id="French interface" xml:space="preserve">
<source>French interface</source> <source>French interface</source>
<target>法语界面</target> <target>法语界面</target>
@@ -2759,6 +2719,11 @@ This cannot be undone!</source>
<target>如果您不能亲自见面,可以在视频通话中展示二维码,或分享链接。</target> <target>如果您不能亲自见面,可以在视频通话中展示二维码,或分享链接。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link." xml:space="preserve">
<source>If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.</source>
<target>如果您不能亲自见面,您可以**扫描视频通话中的二维码**,或者您的联系人可以分享邀请链接。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve"> <trans-unit id="If you enter this passcode when opening the app, all app data will be irreversibly removed!" xml:space="preserve">
<source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source> <source>If you enter this passcode when opening the app, all app data will be irreversibly removed!</source>
<target>如果您在打开应用时输入该密码,所有应用程序数据将被不可撤回地删除!</target> <target>如果您在打开应用时输入该密码,所有应用程序数据将被不可撤回地删除!</target>
@@ -2834,10 +2799,6 @@ This cannot be undone!</source>
<target>隐身聊天</target> <target>隐身聊天</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve"> <trans-unit id="Incognito mode" xml:space="preserve">
<source>Incognito mode</source> <source>Incognito mode</source>
<target>隐身模式</target> <target>隐身模式</target>
@@ -2914,27 +2875,15 @@ This cannot be undone!</source>
<target>界面</target> <target>界面</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid QR code" xml:space="preserve">
<source>Invalid QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid connection link" xml:space="preserve"> <trans-unit id="Invalid connection link" xml:space="preserve">
<source>Invalid connection link</source> <source>Invalid connection link</source>
<target>无效的连接链接</target> <target>无效的连接链接</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
<source>Invalid link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve"> <trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source> <source>Invalid name!</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Invalid response" xml:space="preserve">
<source>Invalid response</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve"> <trans-unit id="Invalid server address!" xml:space="preserve">
<source>Invalid server address!</source> <source>Invalid server address!</source>
<target>无效的服务器地址!</target> <target>无效的服务器地址!</target>
@@ -3049,18 +2998,10 @@ This is your link for group %@!</source>
<target>加入群组中</target> <target>加入群组中</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep" xml:space="preserve">
<source>Keep</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep the app open to use it from desktop" xml:space="preserve"> <trans-unit id="Keep the app open to use it from desktop" xml:space="preserve">
<source>Keep the app open to use it from desktop</source> <source>Keep the app open to use it from desktop</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Keep unused invitation?" xml:space="preserve">
<source>Keep unused invitation?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve"> <trans-unit id="Keep your connections" xml:space="preserve">
<source>Keep your connections</source> <source>Keep your connections</source>
<target>保持连接</target> <target>保持连接</target>
@@ -3121,10 +3062,6 @@ This is your link for group %@!</source>
<target>限制</target> <target>限制</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve"> <trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source> <source>Linked desktop options</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3143,11 +3080,6 @@ This is your link for group %@!</source>
<target>实时消息</target> <target>实时消息</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Local" xml:space="preserve">
<source>Local</source>
<target>本地</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Local name" xml:space="preserve"> <trans-unit id="Local name" xml:space="preserve">
<source>Local name</source> <source>Local name</source>
<target>本地名称</target> <target>本地名称</target>
@@ -3387,10 +3319,6 @@ This is your link for group %@!</source>
<target>新密码</target> <target>新密码</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="New chat" xml:space="preserve">
<source>New chat</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="New contact request" xml:space="preserve"> <trans-unit id="New contact request" xml:space="preserve">
<source>New contact request</source> <source>New contact request</source>
<target>新联系人请求</target> <target>新联系人请求</target>
@@ -3491,10 +3419,6 @@ This is your link for group %@!</source>
<target>未收到或发送文件</target> <target>未收到或发送文件</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Not compatible!" xml:space="preserve">
<source>Not compatible!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Notifications" xml:space="preserve"> <trans-unit id="Notifications" xml:space="preserve">
<source>Notifications</source> <source>Notifications</source>
<target>通知</target> <target>通知</target>
@@ -3514,15 +3438,16 @@ This is your link for group %@!</source>
- 禁用成员(“观察员”角色)</target> - 禁用成员(“观察员”角色)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="OK" xml:space="preserve">
<source>OK</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Off" xml:space="preserve"> <trans-unit id="Off" xml:space="preserve">
<source>Off</source> <source>Off</source>
<target>关闭</target> <target>关闭</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Off (Local)" xml:space="preserve">
<source>Off (Local)</source>
<target>关闭(本地)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Ok" xml:space="preserve"> <trans-unit id="Ok" xml:space="preserve">
<source>Ok</source> <source>Ok</source>
<target>好的</target> <target>好的</target>
@@ -3662,16 +3587,9 @@ This is your link for group %@!</source>
<target>开源协议和代码——任何人都可以运行服务器。</target> <target>开源协议和代码——任何人都可以运行服务器。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Opening app…" xml:space="preserve"> <trans-unit id="Opening database…" xml:space="preserve">
<source>Opening app…</source> <source>Opening database…</source>
<note>No comment provided by engineer.</note> <target>打开数据库中……</target>
</trans-unit>
<trans-unit id="Or scan QR code" xml:space="preserve">
<source>Or scan QR code</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Or show this code" xml:space="preserve">
<source>Or show this code</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="PING count" xml:space="preserve"> <trans-unit id="PING count" xml:space="preserve">
@@ -3714,6 +3632,11 @@ This is your link for group %@!</source>
<target>显示密码</target> <target>显示密码</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste" xml:space="preserve">
<source>Paste</source>
<target>粘贴</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve"> <trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source> <source>Paste desktop address</source>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
@@ -3723,10 +3646,16 @@ This is your link for group %@!</source>
<target>粘贴图片</target> <target>粘贴图片</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve"> <trans-unit id="Paste received link" xml:space="preserve">
<source>Paste the link you received</source> <source>Paste received link</source>
<target>粘贴收到的链接</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>将您收到的链接粘贴到下面的框中以与您的联系人联系。</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve"> <trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source> <source>People can connect to you only via the links you share.</source>
<target>人们只能通过您共享的链接与您建立联系。</target> <target>人们只能通过您共享的链接与您建立联系。</target>
@@ -3762,11 +3691,6 @@ This is your link for group %@!</source>
<target>请检查您和您的联系人偏好设置。</target> <target>请检查您和您的联系人偏好设置。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Please contact developers.&#10;Error: %@" xml:space="preserve">
<source>Please contact developers.
Error: %@</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Please contact group admin." xml:space="preserve"> <trans-unit id="Please contact group admin." xml:space="preserve">
<source>Please contact group admin.</source> <source>Please contact group admin.</source>
<target>请联系群组管理员。</target> <target>请联系群组管理员。</target>
@@ -3970,10 +3894,6 @@ Error: %@</source>
<target>在 [用户指南](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address) 中阅读更多内容。</target> <target>在 [用户指南](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address) 中阅读更多内容。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve"> <trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source> <source>Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).</source>
<target>在 [用户指南](https://simplex.chat/docs/guide/readme.html#connect-to-friends) 中阅读更多内容。</target> <target>在 [用户指南](https://simplex.chat/docs/guide/readme.html#connect-to-friends) 中阅读更多内容。</target>
@@ -4182,10 +4102,6 @@ Error: %@</source>
<target>恢复数据库错误</target> <target>恢复数据库错误</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Retry" xml:space="preserve">
<source>Retry</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reveal" xml:space="preserve"> <trans-unit id="Reveal" xml:space="preserve">
<source>Reveal</source> <source>Reveal</source>
<target>揭示</target> <target>揭示</target>
@@ -4340,10 +4256,6 @@ Error: %@</source>
<target>搜索</target> <target>搜索</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<source>Search or paste SimpleX link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve"> <trans-unit id="Secure queue" xml:space="preserve">
<source>Secure queue</source> <source>Secure queue</source>
<target>保护队列</target> <target>保护队列</target>
@@ -4618,8 +4530,9 @@ Error: %@</source>
<target>分享链接</target> <target>分享链接</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share this 1-time invite link" xml:space="preserve"> <trans-unit id="Share one-time invitation link" xml:space="preserve">
<source>Share this 1-time invite link</source> <source>Share one-time invitation link</source>
<target>分享一次性邀请链接</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve"> <trans-unit id="Share with contacts" xml:space="preserve">
@@ -4742,15 +4655,16 @@ Error: %@</source>
<target>某人</target> <target>某人</target>
<note>notification title</note> <note>notification title</note>
</trans-unit> </trans-unit>
<trans-unit id="Start a new chat" xml:space="preserve">
<source>Start a new chat</source>
<target>开始新聊天</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start chat" xml:space="preserve"> <trans-unit id="Start chat" xml:space="preserve">
<source>Start chat</source> <source>Start chat</source>
<target>开始聊天</target> <target>开始聊天</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Start chat?" xml:space="preserve">
<source>Start chat?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Start migration" xml:space="preserve"> <trans-unit id="Start migration" xml:space="preserve">
<source>Start migration</source> <source>Start migration</source>
<target>开始迁移</target> <target>开始迁移</target>
@@ -4875,14 +4789,6 @@ Error: %@</source>
<target>点击以加入隐身聊天</target> <target>点击以加入隐身聊天</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Tap to paste link" xml:space="preserve">
<source>Tap to paste link</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to scan" xml:space="preserve">
<source>Tap to scan</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve"> <trans-unit id="Tap to start a new chat" xml:space="preserve">
<source>Tap to start a new chat</source> <source>Tap to start a new chat</source>
<target>点击开始一个新聊天</target> <target>点击开始一个新聊天</target>
@@ -4945,10 +4851,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>更改数据库密码的尝试未完成。</target> <target>更改数据库密码的尝试未完成。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The code you scanned is not a SimpleX link QR code." xml:space="preserve">
<source>The code you scanned is not a SimpleX link QR code.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve"> <trans-unit id="The connection you accepted will be cancelled!" xml:space="preserve">
<source>The connection you accepted will be cancelled!</source> <source>The connection you accepted will be cancelled!</source>
<target>您接受的连接将被取消!</target> <target>您接受的连接将被取消!</target>
@@ -5014,10 +4916,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>您当前聊天资料 **%@** 的新连接服务器。</target> <target>您当前聊天资料 **%@** 的新连接服务器。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="The text you pasted is not a SimpleX link." xml:space="preserve">
<source>The text you pasted is not a SimpleX link.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Theme" xml:space="preserve"> <trans-unit id="Theme" xml:space="preserve">
<source>Theme</source> <source>Theme</source>
<target>主题</target> <target>主题</target>
@@ -5095,10 +4993,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>您的联系人可以扫描二维码或使用应用程序中的链接来建立连接。</target> <target>您的联系人可以扫描二维码或使用应用程序中的链接来建立连接。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve"> <trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source> <source>To make a new connection</source>
<target>建立新连接</target> <target>建立新连接</target>
@@ -5166,6 +5060,11 @@ You will be prompted to complete authentication before this feature is enabled.<
<target>关闭</target> <target>关闭</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Turn off notifications?" xml:space="preserve">
<source>Turn off notifications?</source>
<target>关闭通知?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn on" xml:space="preserve"> <trans-unit id="Turn on" xml:space="preserve">
<source>Turn on</source> <source>Turn on</source>
<target>打开</target> <target>打开</target>
@@ -5362,10 +5261,6 @@ To connect, please ask your contact to create another connection link and check
<target>使用新的隐身配置文件</target> <target>使用新的隐身配置文件</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Use only local notifications?" xml:space="preserve">
<source>Use only local notifications?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve"> <trans-unit id="Use server" xml:space="preserve">
<source>Use server</source> <source>Use server</source>
<target>使用服务器</target> <target>使用服务器</target>
@@ -5413,10 +5308,6 @@ To connect, please ask your contact to create another connection link and check
<target>通过浏览器</target> <target>通过浏览器</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve"> <trans-unit id="Video call" xml:space="preserve">
<source>Video call</source> <source>Video call</source>
<target>视频通话</target> <target>视频通话</target>
@@ -5467,10 +5358,6 @@ To connect, please ask your contact to create another connection link and check
<target>语音消息……</target> <target>语音消息……</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Waiting for desktop..." xml:space="preserve">
<source>Waiting for desktop...</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Waiting for file" xml:space="preserve"> <trans-unit id="Waiting for file" xml:space="preserve">
<source>Waiting for file</source> <source>Waiting for file</source>
<target>等待文件中</target> <target>等待文件中</target>
@@ -5615,6 +5502,11 @@ Repeat join request?</source>
<target>您可以从锁屏上接听电话,无需设备和应用程序的认证。</target> <target>您可以从锁屏上接听电话,无需设备和应用程序的认证。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button." xml:space="preserve">
<source>You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.</source>
<target>您也可以通过点击链接进行连接。如果在浏览器中打开,请点击“在移动应用程序中打开”按钮。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can create it later" xml:space="preserve"> <trans-unit id="You can create it later" xml:space="preserve">
<source>You can create it later</source> <source>You can create it later</source>
<target>您可以以后创建它</target> <target>您可以以后创建它</target>
@@ -5635,10 +5527,6 @@ Repeat join request?</source>
<target>您可以隐藏或静音用户个人资料——只需向右滑动。</target> <target>您可以隐藏或静音用户个人资料——只需向右滑动。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can make it visible to your SimpleX contacts via Settings." xml:space="preserve">
<source>You can make it visible to your SimpleX contacts via Settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can now send messages to %@" xml:space="preserve"> <trans-unit id="You can now send messages to %@" xml:space="preserve">
<source>You can now send messages to %@</source> <source>You can now send messages to %@</source>
<target>您现在可以给 %@ 发送消息</target> <target>您现在可以给 %@ 发送消息</target>
@@ -5679,10 +5567,6 @@ Repeat join request?</source>
<target>您可以使用 markdown 来编排消息格式:</target> <target>您可以使用 markdown 来编排消息格式:</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="You can view invitation link again in connection details." xml:space="preserve">
<source>You can view invitation link again in connection details.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can't send messages!" xml:space="preserve"> <trans-unit id="You can't send messages!" xml:space="preserve">
<source>You can't send messages!</source> <source>You can't send messages!</source>
<target>您无法发送消息!</target> <target>您无法发送消息!</target>
@@ -5867,6 +5751,13 @@ You can cancel this connection and remove the contact (and try later with a new
<target>您的联系人可以允许完全删除消息。</target> <target>您的联系人可以允许完全删除消息。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="Your contacts in SimpleX will see it.&#10;You can change it in Settings." xml:space="preserve">
<source>Your contacts in SimpleX will see it.
You can change it in Settings.</source>
<target>您的 SimpleX 的联系人会看到它。
您可以在设置中更改它。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve"> <trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source> <source>Your contacts will remain connected.</source>
<target>与您的联系人保持连接。</target> <target>与您的联系人保持连接。</target>
@@ -5997,10 +5888,6 @@ SimpleX 服务器无法看到您的资料。</target>
<target>语音通话(非端到端加密)</target> <target>语音通话(非端到端加密)</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="author" xml:space="preserve">
<source>author</source>
<note>member role</note>
</trans-unit>
<trans-unit id="bad message ID" xml:space="preserve"> <trans-unit id="bad message ID" xml:space="preserve">
<source>bad message ID</source> <source>bad message ID</source>
<target>错误消息 ID</target> <target>错误消息 ID</target>
@@ -5868,36 +5868,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target state="translated">你和你的聯絡人可以新增訊息互動。</target> <target state="translated">你和你的聯絡人可以新增訊息互動。</target>
<note>No comment provided by engineer.</note> <note>No comment provided by engineer.</note>
</trans-unit> </trans-unit>
<trans-unit id="%@ connected" xml:space="preserve" approved="no">
<source>%@ connected</source>
<target state="translated">%@ 已連接</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve" approved="no">
<source># %@</source>
<target state="translated"># %@</target>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="%@ and %@" xml:space="preserve" approved="no">
<source>%@ and %@</source>
<target state="translated">%@ 和 %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve" approved="no">
<source>## History</source>
<target state="translated">紀錄</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="## In reply to" xml:space="preserve" approved="no">
<source>## In reply to</source>
<target state="translated">回覆</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="%@ and %@ connected" xml:space="preserve" approved="no">
<source>%@ and %@ connected</source>
<target state="translated">%@ 和 %@ 已連接</target>
<note>No comment provided by engineer.</note>
</trans-unit>
</body> </body>
</file> </file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="zh-Hant" datatype="plaintext"> <file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="zh-Hant" datatype="plaintext">
@@ -1,64 +0,0 @@
//
// ConcurrentQueue.swift
// SimpleX NSE
//
// Created by Evgeny on 08/12/2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import Foundation
struct DequeueElement<T> {
var elementId: UUID?
var task: Task<T?, Never>
}
class ConcurrentQueue<T> {
private var queue: [T] = []
private var queueLock = DispatchQueue(label: "chat.simplex.app.SimpleX-NSE.concurrent-queue.lock.\(UUID())")
private var continuations = [(elementId: UUID, continuation: CheckedContinuation<T?, Never>)]()
func enqueue(_ el: T) {
resumeContinuation(el) { self.queue.append(el) }
}
func frontEnqueue(_ el: T) {
resumeContinuation(el) { self.queue.insert(el, at: 0) }
}
private func resumeContinuation(_ el: T, add: @escaping () -> Void) {
queueLock.sync {
if let (_, cont) = continuations.first {
continuations.remove(at: 0)
cont.resume(returning: el)
} else {
add()
}
}
}
func dequeue() -> DequeueElement<T> {
queueLock.sync {
if queue.isEmpty {
let elementId = UUID()
let task = Task {
await withCheckedContinuation { cont in
continuations.append((elementId, cont))
}
}
return DequeueElement(elementId: elementId, task: task)
} else {
let el = queue.remove(at: 0)
return DequeueElement(task: Task { el })
}
}
}
func cancelDequeue(_ elementId: UUID) {
queueLock.sync {
let cancelled = continuations.filter { $0.elementId == elementId }
continuations.removeAll { $0.elementId == elementId }
cancelled.forEach { $0.continuation.resume(returning: nil) }
}
}
}
+98 -486
View File
@@ -14,233 +14,91 @@ import SimpleXChat
let logger = Logger() let logger = Logger()
let appSuspendingDelay: UInt64 = 2_500_000_000 let suspendingDelay: UInt64 = 2_000_000_000
typealias SuspendSchedule = (delay: TimeInterval, timeout: Int) typealias NtfStream = AsyncStream<NSENotification>
let nseSuspendSchedule: SuspendSchedule = (2, 4)
let fastNSESuspendSchedule: SuspendSchedule = (1, 1)
typealias NtfStream = ConcurrentQueue<NSENotification>
// Notifications are delivered via concurrent queues, as they are all received from chat controller in a single loop that
// writes to ConcurrentQueue and when notification is processed, the instance of Notification service extension reads from the queue.
// One queue per connection (entity) is used.
// The concurrent queues allow read cancellation, to ensure that notifications are not lost in case the current thread completes
// before expected notification is read (multiple notifications can be expected, because one notification can be delivered for several messages).
actor PendingNtfs { actor PendingNtfs {
static let shared = PendingNtfs() static let shared = PendingNtfs()
private var ntfStreams: [String: NtfStream] = [:] private var ntfStreams: [String: NtfStream] = [:]
private var ntfConts: [String: NtfStream.Continuation] = [:]
func createStream(_ id: String) async { func createStream(_ id: String) {
logger.debug("NotificationService PendingNtfs.createStream: \(id)") logger.debug("PendingNtfs.createStream: \(id, privacy: .public)")
if ntfStreams[id] == nil { if ntfStreams.index(forKey: id) == nil {
ntfStreams[id] = ConcurrentQueue() ntfStreams[id] = AsyncStream { cont in
logger.debug("NotificationService PendingNtfs.createStream: created ConcurrentQueue") ntfConts[id] = cont
logger.debug("PendingNtfs.createStream: store continuation")
}
} }
} }
func readStream(_ id: String, for nse: NotificationService, ntfInfo: NtfMessages) async { func readStream(_ id: String, for nse: NotificationService, msgCount: Int = 1, showNotifications: Bool) async {
logger.debug("NotificationService PendingNtfs.readStream: \(id) \(ntfInfo.ntfMessages.count)") logger.debug("PendingNtfs.readStream: \(id, privacy: .public) \(msgCount, privacy: .public)")
if !ntfInfo.user.showNotifications {
nse.setBestAttemptNtf(.empty)
}
if let s = ntfStreams[id] { if let s = ntfStreams[id] {
logger.debug("NotificationService PendingNtfs.readStream: has stream") logger.debug("PendingNtfs.readStream: has stream")
var expected = Set(ntfInfo.ntfMessages.map { $0.msgId }) var rcvCount = max(1, msgCount)
logger.debug("NotificationService PendingNtfs.readStream: expecting: \(expected)") for await ntf in s {
var readCancelled = false nse.setBestAttemptNtf(showNotifications ? ntf : .empty)
var dequeued: DequeueElement<NSENotification>? rcvCount -= 1
nse.cancelRead = { if rcvCount == 0 || ntf.categoryIdentifier == ntfCategoryCallInvitation { break }
readCancelled = true
if let elementId = dequeued?.elementId {
s.cancelDequeue(elementId)
}
} }
while !readCancelled { logger.debug("PendingNtfs.readStream: exiting")
dequeued = s.dequeue()
if let ntf = await dequeued?.task.value {
if readCancelled {
logger.debug("NotificationService PendingNtfs.readStream: read cancelled, put ntf to queue front")
s.frontEnqueue(ntf)
break
} else if case let .msgInfo(info) = ntf {
let found = expected.remove(info.msgId)
if found != nil {
logger.debug("NotificationService PendingNtfs.readStream: msgInfo, last: \(expected.isEmpty)")
if expected.isEmpty { break }
} else if let msgTs = ntfInfo.msgTs, info.msgTs > msgTs {
logger.debug("NotificationService PendingNtfs.readStream: unexpected msgInfo")
s.frontEnqueue(ntf)
break
}
} else if ntfInfo.user.showNotifications {
logger.debug("NotificationService PendingNtfs.readStream: setting best attempt")
nse.setBestAttemptNtf(ntf)
if ntf.isCallInvitation { break }
}
} else {
break
}
}
nse.cancelRead = nil
logger.debug("NotificationService PendingNtfs.readStream: exiting")
} }
} }
func writeStream(_ id: String, _ ntf: NSENotification) async { func writeStream(_ id: String, _ ntf: NSENotification) {
logger.debug("NotificationService PendingNtfs.writeStream: \(id)") logger.debug("PendingNtfs.writeStream: \(id, privacy: .public)")
if let s = ntfStreams[id] { if let cont = ntfConts[id] {
logger.debug("NotificationService PendingNtfs.writeStream: writing ntf") logger.debug("PendingNtfs.writeStream: writing ntf")
s.enqueue(ntf) cont.yield(ntf)
}
}
}
// The current implementation assumes concurrent notification delivery and uses semaphores
// to process only one notification per connection (entity) at a time.
class NtfStreamSemaphores {
static let shared = NtfStreamSemaphores()
private static let queue = DispatchQueue(label: "chat.simplex.app.SimpleX-NSE.notification-semaphores.lock")
private var semaphores: [String: DispatchSemaphore] = [:]
func waitForStream(_ id: String) {
streamSemaphore(id, value: 0)?.wait()
}
func signalStreamReady(_ id: String) {
streamSemaphore(id, value: 1)?.signal()
}
// this function returns nil if semaphore is just created, so passed value shoud be coordinated with the desired end value of the semaphore
private func streamSemaphore(_ id: String, value: Int) -> DispatchSemaphore? {
NtfStreamSemaphores.queue.sync {
if let s = semaphores[id] {
return s
} else {
semaphores[id] = DispatchSemaphore(value: value)
return nil
}
} }
} }
} }
enum NSENotification { enum NSENotification {
case nse(UNMutableNotificationContent) case nse(notification: UNMutableNotificationContent)
case callkit(RcvCallInvitation) case callkit(invitation: RcvCallInvitation)
case empty case empty
case msgInfo(NtfMsgInfo)
var isCallInvitation: Bool { var categoryIdentifier: String? {
switch self { switch self {
case let .nse(ntf): ntf.categoryIdentifier == ntfCategoryCallInvitation case let .nse(ntf): return ntf.categoryIdentifier
case .callkit: true case .callkit: return ntfCategoryCallInvitation
case .empty: false case .empty: return nil
case .msgInfo: false
} }
} }
} }
// Once the last thread in the process completes processing chat controller is suspended, and the database is closed, to avoid
// background crashes and contention for database with the application (both UI and background fetch triggered either on schedule
// or when background notification is received.
class NSEThreads {
static let shared = NSEThreads()
private static let queue = DispatchQueue(label: "chat.simplex.app.SimpleX-NSE.notification-threads.lock")
private var allThreads: Set<UUID> = []
private var activeThreads: Set<UUID> = []
func newThread() -> UUID {
NSEThreads.queue.sync {
let (_, t) = allThreads.insert(UUID())
return t
}
}
func startThread(_ t: UUID) {
NSEThreads.queue.sync {
if allThreads.contains(t) {
_ = activeThreads.insert(t)
} else {
logger.warning("NotificationService startThread: thread \(t) was removed before it started")
}
}
}
func endThread(_ t: UUID) -> Bool {
NSEThreads.queue.sync {
let tActive = activeThreads.remove(t)
let t = allThreads.remove(t)
if tActive != nil && activeThreads.isEmpty {
return true
}
if t != nil && allThreads.isEmpty {
NSEChatState.shared.set(.suspended)
}
return false
}
}
var noThreads: Bool {
allThreads.isEmpty
}
}
// Notification service extension creates a new instance of the class and calls didReceive for each notification.
// Each didReceive is called in its own thread, but multiple calls can be made in one process, and, empirically, there is never
// more than one process of notification service extension exists at a time.
// Soon after notification service delivers the last notification it is either suspended or terminated.
class NotificationService: UNNotificationServiceExtension { class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)? var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptNtf: NSENotification? var bestAttemptNtf: NSENotification?
var badgeCount: Int = 0 var badgeCount: Int = 0
// thread is added to allThreads here - if thread did not start chat,
// chat does not need to be suspended but NSE state still needs to be set to "suspended".
var threadId: UUID? = NSEThreads.shared.newThread()
var receiveEntityId: String?
var cancelRead: (() -> Void)?
var appSubscriber: AppSubscriber?
var returnedSuspension = false
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
logger.debug("DEBUGGING: NotificationService.didReceive") logger.debug("DEBUGGING: NotificationService.didReceive")
let ntf = if let ntf_ = request.content.mutableCopy() as? UNMutableNotificationContent { ntf_ } else { UNMutableNotificationContent() } if let ntf = request.content.mutableCopy() as? UNMutableNotificationContent {
setBestAttemptNtf(ntf) setBestAttemptNtf(ntf)
}
self.contentHandler = contentHandler self.contentHandler = contentHandler
registerGroupDefaults() registerGroupDefaults()
let appState = appStateGroupDefault.get() let appState = appStateGroupDefault.get()
logger.debug("NotificationService: app is \(appState.rawValue)")
switch appState { switch appState {
case .stopped:
setBadgeCount()
setBestAttemptNtf(createAppStoppedNtf())
deliverBestAttemptNtf()
case .suspended: case .suspended:
logger.debug("NotificationService: app is suspended")
setBadgeCount() setBadgeCount()
receiveNtfMessages(request, contentHandler) receiveNtfMessages(request, contentHandler)
case .suspending: case .suspending:
logger.debug("NotificationService: app is suspending")
setBadgeCount() setBadgeCount()
Task { Task {
let state: AppState = await withCheckedContinuation { cont in var state = appState
appSubscriber = appStateSubscriber { s in for _ in 1...5 {
if s == .suspended { appSuspension(s) } _ = try await Task.sleep(nanoseconds: suspendingDelay)
} state = appStateGroupDefault.get()
DispatchQueue.global().asyncAfter(deadline: .now() + Double(appSuspendTimeout) + 1) { if state == .suspended || state != .suspending { break }
logger.debug("NotificationService: appSuspension timeout")
appSuspension(appStateGroupDefault.get())
}
@Sendable
func appSuspension(_ s: AppState) {
if !self.returnedSuspension {
self.returnedSuspension = true
self.appSubscriber = nil // this disposes of appStateSubscriber
cont.resume(returning: s)
}
}
} }
logger.debug("NotificationService: app state is now \(state.rawValue)") logger.debug("NotificationService: app state is \(state.rawValue, privacy: .public)")
if state.inactive { if state.inactive {
receiveNtfMessages(request, contentHandler) receiveNtfMessages(request, contentHandler)
} else { } else {
@@ -248,6 +106,7 @@ class NotificationService: UNNotificationServiceExtension {
} }
} }
default: default:
logger.debug("NotificationService: app state is \(appState.rawValue, privacy: .public)")
deliverBestAttemptNtf() deliverBestAttemptNtf()
} }
} }
@@ -262,35 +121,27 @@ class NotificationService: UNNotificationServiceExtension {
if let ntfData = userInfo["notificationData"] as? [AnyHashable : Any], if let ntfData = userInfo["notificationData"] as? [AnyHashable : Any],
let nonce = ntfData["nonce"] as? String, let nonce = ntfData["nonce"] as? String,
let encNtfInfo = ntfData["message"] as? String, let encNtfInfo = ntfData["message"] as? String,
// check it here again let dbStatus = startChat() {
appStateGroupDefault.get().inactive {
// thread is added to activeThreads tracking set here - if thread started chat it needs to be suspended
if let t = threadId { NSEThreads.shared.startThread(t) }
let dbStatus = startChat()
if case .ok = dbStatus, if case .ok = dbStatus,
let ntfInfo = apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo) { let ntfMsgInfo = apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo) {
logger.debug("NotificationService: receiveNtfMessages: apiGetNtfMessage \(String(describing: ntfInfo.ntfMessages.count))") logger.debug("NotificationService: receiveNtfMessages: apiGetNtfMessage \(String(describing: ntfMsgInfo), privacy: .public)")
if let connEntity = ntfInfo.connEntity_ { if let connEntity = ntfMsgInfo.connEntity {
setBestAttemptNtf( setBestAttemptNtf(
ntfInfo.ntfsEnabled ntfMsgInfo.ntfsEnabled
? .nse(createConnectionEventNtf(ntfInfo.user, connEntity)) ? .nse(notification: createConnectionEventNtf(ntfMsgInfo.user, connEntity))
: .empty : .empty
) )
if let id = connEntity.id { if let id = connEntity.id {
receiveEntityId = id Task {
NtfStreamSemaphores.shared.waitForStream(id) logger.debug("NotificationService: receiveNtfMessages: in Task, connEntity id \(id, privacy: .public)")
if receiveEntityId != nil { await PendingNtfs.shared.createStream(id)
Task { await PendingNtfs.shared.readStream(id, for: self, msgCount: ntfMsgInfo.ntfMessages.count, showNotifications: ntfMsgInfo.user.showNotifications)
logger.debug("NotificationService: receiveNtfMessages: in Task, connEntity id \(id)") deliverBestAttemptNtf()
await PendingNtfs.shared.createStream(id)
await PendingNtfs.shared.readStream(id, for: self, ntfInfo: ntfInfo)
deliverBestAttemptNtf()
}
} }
return
} }
} }
} else if let dbStatus = dbStatus { return
} else {
setBestAttemptNtf(createErrorNtf(dbStatus)) setBestAttemptNtf(createErrorNtf(dbStatus))
} }
} }
@@ -299,7 +150,7 @@ class NotificationService: UNNotificationServiceExtension {
override func serviceExtensionTimeWillExpire() { override func serviceExtensionTimeWillExpire() {
logger.debug("DEBUGGING: NotificationService.serviceExtensionTimeWillExpire") logger.debug("DEBUGGING: NotificationService.serviceExtensionTimeWillExpire")
deliverBestAttemptNtf(urgent: true) deliverBestAttemptNtf()
} }
func setBadgeCount() { func setBadgeCount() {
@@ -308,301 +159,91 @@ class NotificationService: UNNotificationServiceExtension {
} }
func setBestAttemptNtf(_ ntf: UNMutableNotificationContent) { func setBestAttemptNtf(_ ntf: UNMutableNotificationContent) {
setBestAttemptNtf(.nse(ntf)) setBestAttemptNtf(.nse(notification: ntf))
} }
func setBestAttemptNtf(_ ntf: NSENotification) { func setBestAttemptNtf(_ ntf: NSENotification) {
logger.debug("NotificationService.setBestAttemptNtf") logger.debug("NotificationService.setBestAttemptNtf")
if case let .nse(notification) = ntf { if case let .nse(notification) = ntf {
notification.badge = badgeCount as NSNumber notification.badge = badgeCount as NSNumber
bestAttemptNtf = .nse(notification) bestAttemptNtf = .nse(notification: notification)
} else { } else {
bestAttemptNtf = ntf bestAttemptNtf = ntf
} }
} }
private func deliverBestAttemptNtf(urgent: Bool = false) { private func deliverBestAttemptNtf() {
logger.debug("NotificationService.deliverBestAttemptNtf") logger.debug("NotificationService.deliverBestAttemptNtf")
if let cancel = cancelRead {
cancelRead = nil
cancel()
}
if let id = receiveEntityId {
receiveEntityId = nil
NtfStreamSemaphores.shared.signalStreamReady(id)
}
let suspend: Bool
if let t = threadId {
threadId = nil
suspend = NSEThreads.shared.endThread(t) && NSEThreads.shared.noThreads
} else {
suspend = false
}
deliverCallkitOrNotification(urgent: urgent, suspend: suspend)
}
private func deliverCallkitOrNotification(urgent: Bool, suspend: Bool = false) {
if case .callkit = bestAttemptNtf {
logger.debug("NotificationService.deliverCallkitOrNotification: will suspend, callkit")
if urgent {
// suspending NSE even though there may be other notifications
// to allow the app to process callkit call
suspendChat(0)
deliverNotification()
} else {
// suspending NSE with delay and delivering after the suspension
// because pushkit notification must be processed without delay
// to avoid app termination
DispatchQueue.global().asyncAfter(deadline: .now() + fastNSESuspendSchedule.delay) {
suspendChat(fastNSESuspendSchedule.timeout)
DispatchQueue.global().asyncAfter(deadline: .now() + Double(fastNSESuspendSchedule.timeout)) {
self.deliverNotification()
}
}
}
} else {
if suspend {
logger.debug("NotificationService.deliverCallkitOrNotification: will suspend")
if urgent {
suspendChat(0)
} else {
// suspension is delayed to allow chat core finalise any processing
// (e.g., send delivery receipts)
DispatchQueue.global().asyncAfter(deadline: .now() + nseSuspendSchedule.delay) {
if NSEThreads.shared.noThreads {
suspendChat(nseSuspendSchedule.timeout)
}
}
}
}
deliverNotification()
}
}
private func deliverNotification() {
if let handler = contentHandler, let ntf = bestAttemptNtf { if let handler = contentHandler, let ntf = bestAttemptNtf {
contentHandler = nil
bestAttemptNtf = nil
let deliver: (UNMutableNotificationContent?) -> Void = { ntf in
let useNtf = if let ntf = ntf {
appStateGroupDefault.get().running ? UNMutableNotificationContent() : ntf
} else {
UNMutableNotificationContent()
}
handler(useNtf)
}
switch ntf { switch ntf {
case let .nse(content): deliver(content) case let .nse(content): handler(content)
case let .callkit(invitation): case let .callkit(invitation):
logger.debug("NotificationService reportNewIncomingVoIPPushPayload for \(invitation.contact.id)")
CXProvider.reportNewIncomingVoIPPushPayload([ CXProvider.reportNewIncomingVoIPPushPayload([
"displayName": invitation.contact.displayName, "displayName": invitation.contact.displayName,
"contactId": invitation.contact.id, "contactId": invitation.contact.id,
"media": invitation.callType.media.rawValue "media": invitation.callType.media.rawValue
]) { error in ]) { error in
logger.debug("reportNewIncomingVoIPPushPayload result: \(error)") if error == nil {
deliver(error == nil ? nil : createCallInvitationNtf(invitation)) handler(UNMutableNotificationContent())
} else {
logger.debug("reportNewIncomingVoIPPushPayload success to CallController for \(invitation.contact.id)")
handler(createCallInvitationNtf(invitation))
}
} }
case .empty: deliver(nil) // used to mute notifications that did not unsubscribe yet case .empty: handler(UNMutableNotificationContent())
case .msgInfo: deliver(nil) // unreachable, the best attempt is never set to msgInfo
} }
bestAttemptNtf = nil
} }
} }
} }
// nseStateGroupDefault must not be used in NSE directly, only via this singleton var chatStarted = false
class NSEChatState {
static let shared = NSEChatState()
private var value_ = NSEState.created
var value: NSEState {
value_
}
func set(_ state: NSEState) {
nseStateGroupDefault.set(state)
sendNSEState(state)
value_ = state
}
init() {
// This is always set to .created state, as in case previous start of NSE crashed in .active state, it is stored correctly.
// Otherwise the app will be activating slower
set(.created)
}
}
var appSubscriber: AppSubscriber = appStateSubscriber { state in
logger.debug("NotificationService: appSubscriber")
if state.running && NSEChatState.shared.value.canSuspend {
logger.debug("NotificationService: appSubscriber app state \(state.rawValue), suspending")
suspendChat(fastNSESuspendSchedule.timeout)
}
}
func appStateSubscriber(onState: @escaping (AppState) -> Void) -> AppSubscriber {
appMessageSubscriber { msg in
if case let .state(state) = msg {
logger.debug("NotificationService: appStateSubscriber \(state.rawValue)")
onState(state)
}
}
}
var receiverStarted = false
let startLock = DispatchSemaphore(value: 1)
let suspendLock = DispatchSemaphore(value: 1)
var networkConfig: NetCfg = getNetCfg() var networkConfig: NetCfg = getNetCfg()
let xftpConfig: XFTPFileConfig? = getXFTPCfg() var 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
func startChat() -> DBMigrationResult? { func startChat() -> DBMigrationResult? {
logger.debug("NotificationService: startChat") hs_init(0, nil)
// only skip creating if there is chat controller if chatStarted { return .ok }
if case .active = NSEChatState.shared.value, hasChatCtrl() { return .ok } let (_, dbStatus) = chatMigrateInit(confirmMigrations: defaultMigrationConfirmation())
startLock.wait()
defer { startLock.signal() }
if hasChatCtrl() {
return switch NSEChatState.shared.value {
case .created: doStartChat()
case .starting: .ok // it should never get to this branch, as it would be waiting for start on startLock
case .active: .ok
case .suspending: activateChat()
case .suspended: activateChat()
}
} else {
// Ignore state in preference if there is no chat controller.
// State in preference may have failed to update e.g. because of a crash.
NSEChatState.shared.set(.created)
return doStartChat()
}
}
func doStartChat() -> DBMigrationResult? {
logger.debug("NotificationService: doStartChat")
haskell_init_nse()
let (_, dbStatus) = chatMigrateInit(confirmMigrations: defaultMigrationConfirmation(), backgroundMode: true)
logger.debug("NotificationService: doStartChat \(String(describing: dbStatus))")
if dbStatus != .ok { if dbStatus != .ok {
resetChatCtrl() resetChatCtrl()
NSEChatState.shared.set(.created)
return dbStatus return dbStatus
} }
let state = NSEChatState.shared.value
NSEChatState.shared.set(.starting)
if let user = apiGetActiveUser() { if let user = apiGetActiveUser() {
logger.debug("NotificationService active user \(String(describing: user))") logger.debug("active user \(String(describing: user))")
do { do {
try setNetworkConfig(networkConfig) try setNetworkConfig(networkConfig)
try apiSetTempFolder(tempFolder: getTempFilesDirectory().path) try apiSetTempFolder(tempFolder: getTempFilesDirectory().path)
try apiSetFilesFolder(filesFolder: getAppFilesDirectory().path) try apiSetFilesFolder(filesFolder: getAppFilesDirectory().path)
try setXFTPConfig(xftpConfig) try setXFTPConfig(xftpConfig)
try apiSetEncryptLocalFiles(privacyEncryptLocalFilesGroupDefault.get()) try apiSetEncryptLocalFiles(privacyEncryptLocalFilesGroupDefault.get())
// prevent suspension while starting chat let justStarted = try apiStartChat()
suspendLock.wait() chatStarted = true
defer { suspendLock.signal() } if justStarted {
if NSEChatState.shared.value == .starting { chatLastStartGroupDefault.set(Date.now)
updateNetCfg() Task { await receiveMessages() }
let justStarted = try apiStartChat()
NSEChatState.shared.set(.active)
if justStarted {
chatLastStartGroupDefault.set(Date.now)
Task {
if !receiverStarted {
receiverStarted = true
await receiveMessages()
}
}
}
return .ok
} }
return .ok
} catch { } catch {
logger.error("NotificationService startChat error: \(responseError(error))") logger.error("NotificationService startChat error: \(responseError(error), privacy: .public)")
} }
} else { } else {
logger.debug("NotificationService: no active user") logger.debug("no active user")
} }
if NSEChatState.shared.value == .starting { NSEChatState.shared.set(state) }
return nil return nil
} }
func activateChat() -> DBMigrationResult? {
logger.debug("NotificationService: activateChat")
let state = NSEChatState.shared.value
NSEChatState.shared.set(.active)
if apiActivateChat() {
logger.debug("NotificationService: activateChat: after apiActivateChat")
return .ok
} else {
NSEChatState.shared.set(state)
return nil
}
}
// suspendChat uses semaphore suspendLock to ensure that only one suspension can happen.
func suspendChat(_ timeout: Int) {
logger.debug("NotificationService: suspendChat")
let state = NSEChatState.shared.value
if !state.canSuspend {
logger.error("NotificationService suspendChat called, current state: \(state.rawValue)")
} else if hasChatCtrl() {
// only suspend if we have chat controller to avoid crashes when suspension is
// attempted when chat controller was not created
suspendLock.wait()
defer { suspendLock.signal() }
NSEChatState.shared.set(.suspending)
if apiSuspendChat(timeoutMicroseconds: timeout * 1000000) {
logger.debug("NotificationService: suspendChat: after apiSuspendChat")
DispatchQueue.global().asyncAfter(deadline: .now() + Double(timeout) + 1, execute: chatSuspended)
} else {
NSEChatState.shared.set(state)
}
}
}
func chatSuspended() {
logger.debug("NotificationService chatSuspended")
if case .suspending = NSEChatState.shared.value {
NSEChatState.shared.set(.suspended)
chatCloseStore()
logger.debug("NotificationService chatSuspended: suspended")
}
}
// A single loop is used per Notification service extension process to receive and process all messages depending on the NSE state
// If the extension is not active yet, or suspended/suspending, or the app is running, the notifications will no be received.
func receiveMessages() async { func receiveMessages() async {
logger.debug("NotificationService receiveMessages") logger.debug("NotificationService receiveMessages")
while true { while true {
switch NSEChatState.shared.value { updateNetCfg()
// it should never get to "created" and "starting" branches, as NSE state is set to .active before the loop start
case .created: await delayWhenInactive()
case .starting: await delayWhenInactive()
case .active: await receiveMsg()
case .suspending: await receiveMsg()
case .suspended: await delayWhenInactive()
}
}
func receiveMsg() async {
if let msg = await chatRecvMsg() { if let msg = await chatRecvMsg() {
logger.debug("NotificationService receiveMsg: message")
if let (id, ntf) = await receivedMsgNtf(msg) { if let (id, ntf) = await receivedMsgNtf(msg) {
logger.debug("NotificationService receiveMsg: notification")
await PendingNtfs.shared.createStream(id) await PendingNtfs.shared.createStream(id)
await PendingNtfs.shared.writeStream(id, ntf) await PendingNtfs.shared.writeStream(id, ntf)
} }
} }
} }
func delayWhenInactive() async {
logger.debug("NotificationService delayWhenInactive")
_ = try? await Task.sleep(nanoseconds: 1000_000000)
}
} }
func chatRecvMsg() async -> ChatResponse? { func chatRecvMsg() async -> ChatResponse? {
@@ -616,14 +257,14 @@ private let isInChina = SKStorefront().countryCode == "CHN"
private func useCallKit() -> Bool { !isInChina && callKitEnabledGroupDefault.get() } private func useCallKit() -> Bool { !isInChina && callKitEnabledGroupDefault.get() }
func receivedMsgNtf(_ res: ChatResponse) async -> (String, NSENotification)? { func receivedMsgNtf(_ res: ChatResponse) async -> (String, NSENotification)? {
logger.debug("NotificationService receivedMsgNtf: \(res.responseType)") logger.debug("NotificationService processReceivedMsg: \(res.responseType)")
switch res { switch res {
case let .contactConnected(user, contact, _): case let .contactConnected(user, contact, _):
return (contact.id, .nse(createContactConnectedNtf(user, contact))) return (contact.id, .nse(notification: createContactConnectedNtf(user, contact)))
// case let .contactConnecting(contact): // case let .contactConnecting(contact):
// TODO profile update // TODO profile update
case let .receivedContactRequest(user, contactRequest): case let .receivedContactRequest(user, contactRequest):
return (UserContact(contactRequest: contactRequest).id, .nse(createContactRequestNtf(user, contactRequest))) return (UserContact(contactRequest: contactRequest).id, .nse(notification: createContactRequestNtf(user, contactRequest)))
case let .newChatItem(user, aChatItem): case let .newChatItem(user, aChatItem):
let cInfo = aChatItem.chatInfo let cInfo = aChatItem.chatInfo
var cItem = aChatItem.chatItem var cItem = aChatItem.chatItem
@@ -633,7 +274,7 @@ func receivedMsgNtf(_ res: ChatResponse) async -> (String, NSENotification)? {
if let file = cItem.autoReceiveFile() { if let file = cItem.autoReceiveFile() {
cItem = autoReceiveFile(file, encrypted: cItem.encryptLocalFile) ?? cItem cItem = autoReceiveFile(file, encrypted: cItem.encryptLocalFile) ?? cItem
} }
let ntf: NSENotification = cInfo.ntfsEnabled ? .nse(createMessageReceivedNtf(user, cInfo, cItem)) : .empty let ntf: NSENotification = cInfo.ntfsEnabled ? .nse(notification: createMessageReceivedNtf(user, cInfo, cItem)) : .empty
return cItem.showNotification ? (aChatItem.chatId, ntf) : nil return cItem.showNotification ? (aChatItem.chatId, ntf) : nil
case let .rcvFileSndCancelled(_, aChatItem, _): case let .rcvFileSndCancelled(_, aChatItem, _):
cleanupFile(aChatItem) cleanupFile(aChatItem)
@@ -651,18 +292,10 @@ func receivedMsgNtf(_ res: ChatResponse) async -> (String, NSENotification)? {
// Do not post it without CallKit support, iOS will stop launching the app without showing CallKit // Do not post it without CallKit support, iOS will stop launching the app without showing CallKit
return ( return (
invitation.contact.id, invitation.contact.id,
useCallKit() ? .callkit(invitation) : .nse(createCallInvitationNtf(invitation)) useCallKit() ? .callkit(invitation: invitation) : .nse(notification: createCallInvitationNtf(invitation))
) )
case let .ntfMessage(_, connEntity, ntfMessage):
return if let id = connEntity.id { (id, .msgInfo(ntfMessage)) } else { nil }
case .chatSuspended:
chatSuspended()
return nil
case let .chatError(_, err):
logger.error("NotificationService receivedMsgNtf error: \(String(describing: err))")
return nil
default: default:
logger.debug("NotificationService receivedMsgNtf ignored event: \(res.responseType)") logger.debug("NotificationService processReceivedMsg ignored event: \(res.responseType)")
return nil return nil
} }
} }
@@ -675,22 +308,17 @@ func updateNetCfg() {
try setNetworkConfig(networkConfig) try setNetworkConfig(networkConfig)
networkConfig = newNetConfig networkConfig = newNetConfig
} catch { } catch {
logger.error("NotificationService apply changed network config error: \(responseError(error))") logger.error("NotificationService apply changed network config error: \(responseError(error), privacy: .public)")
} }
} }
} }
func apiGetActiveUser() -> User? { func apiGetActiveUser() -> User? {
let r = sendSimpleXCmd(.showActiveUser) let r = sendSimpleXCmd(.showActiveUser)
logger.debug("apiGetActiveUser sendSimpleXCmd response: \(r.responseType)") logger.debug("apiGetActiveUser sendSimpleXCmd response: \(String(describing: r))")
switch r { switch r {
case let .activeUser(user): return user case let .activeUser(user): return user
case .chatCmdError(_, .error(.noActiveUser)): case .chatCmdError(_, .error(.noActiveUser)): return nil
logger.debug("apiGetActiveUser sendSimpleXCmd no active user")
return nil
case let .chatCmdError(_, err):
logger.debug("apiGetActiveUser sendSimpleXCmd error: \(String(describing: err))")
return nil
default: default:
logger.error("NotificationService apiGetActiveUser unexpected response: \(String(describing: r))") logger.error("NotificationService apiGetActiveUser unexpected response: \(String(describing: r))")
return nil return nil
@@ -698,7 +326,7 @@ func apiGetActiveUser() -> User? {
} }
func apiStartChat() throws -> Bool { func apiStartChat() throws -> Bool {
let r = sendSimpleXCmd(.startChat(mainApp: false)) let r = sendSimpleXCmd(.startChat(subscribe: false, expire: false, xftp: false))
switch r { switch r {
case .chatStarted: return true case .chatStarted: return true
case .chatRunning: return false case .chatRunning: return false
@@ -706,21 +334,6 @@ func apiStartChat() throws -> Bool {
} }
} }
func apiActivateChat() -> Bool {
chatReopenStore()
let r = sendSimpleXCmd(.apiActivateChat(restoreChat: false))
if case .cmdOk = r { return true }
logger.error("NotificationService apiActivateChat error: \(String(describing: r))")
return false
}
func apiSuspendChat(timeoutMicroseconds: Int) -> Bool {
let r = sendSimpleXCmd(.apiSuspendChat(timeoutMicroseconds: timeoutMicroseconds))
if case .cmdOk = r { return true }
logger.error("NotificationService apiSuspendChat error: \(String(describing: r))")
return false
}
func apiSetTempFolder(tempFolder: String) throws { func apiSetTempFolder(tempFolder: String) throws {
let r = sendSimpleXCmd(.setTempFolder(tempFolder: tempFolder)) let r = sendSimpleXCmd(.setTempFolder(tempFolder: tempFolder))
if case .cmdOk = r { return } if case .cmdOk = r { return }
@@ -751,13 +364,12 @@ func apiGetNtfMessage(nonce: String, encNtfInfo: String) -> NtfMessages? {
return nil return nil
} }
let r = sendSimpleXCmd(.apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo)) let r = sendSimpleXCmd(.apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo))
if case let .ntfMessages(user, connEntity_, msgTs, ntfMessages) = r, let user = user { if case let .ntfMessages(user, connEntity, msgTs, ntfMessages) = r, let user = user {
logger.debug("apiGetNtfMessage response ntfMessages: \(ntfMessages.count)") return NtfMessages(user: user, connEntity: connEntity, msgTs: msgTs, ntfMessages: ntfMessages)
return NtfMessages(user: user, connEntity_: connEntity_, msgTs: msgTs, ntfMessages: ntfMessages)
} else if case let .chatCmdError(_, error) = r { } else if case let .chatCmdError(_, error) = r {
logger.debug("apiGetNtfMessage error response: \(String.init(describing: error))") logger.debug("apiGetNtfMessage error response: \(String.init(describing: error))")
} else { } else {
logger.debug("apiGetNtfMessage ignored response: \(r.responseType) \(String.init(describing: r))") logger.debug("apiGetNtfMessage ignored response: \(r.responseType, privacy: .public) \(String.init(describing: r), privacy: .private)")
} }
return nil return nil
} }
@@ -793,11 +405,11 @@ func setNetworkConfig(_ cfg: NetCfg) throws {
struct NtfMessages { struct NtfMessages {
var user: User var user: User
var connEntity_: ConnectionEntity? var connEntity: ConnectionEntity?
var msgTs: Date? var msgTs: Date?
var ntfMessages: [NtfMsgInfo] var ntfMessages: [NtfMsgInfo]
var ntfsEnabled: Bool { var ntfsEnabled: Bool {
user.showNotifications && (connEntity_?.ntfsEnabled ?? false) user.showNotifications && (connEntity?.ntfsEnabled ?? false)
} }
} }
+56 -64
View File
@@ -16,6 +16,7 @@
18415C6C56DBCEC2CBBD2F11 /* WebRTCClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18415323A4082FC92887F906 /* WebRTCClient.swift */; }; 18415C6C56DBCEC2CBBD2F11 /* WebRTCClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18415323A4082FC92887F906 /* WebRTCClient.swift */; };
18415F9A2D551F9757DA4654 /* CIVideoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18415FD2E36F13F596A45BB4 /* CIVideoView.swift */; }; 18415F9A2D551F9757DA4654 /* CIVideoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18415FD2E36F13F596A45BB4 /* CIVideoView.swift */; };
18415FEFE153C5920BFB7828 /* GroupWelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1841516F0CE5992B0EDFB377 /* GroupWelcomeView.swift */; }; 18415FEFE153C5920BFB7828 /* GroupWelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1841516F0CE5992B0EDFB377 /* GroupWelcomeView.swift */; };
3C8C548928133C84000A3EC7 /* PasteToConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C8C548828133C84000A3EC7 /* PasteToConnectView.swift */; };
3CDBCF4227FAE51000354CDD /* ComposeLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CDBCF4127FAE51000354CDD /* ComposeLinkView.swift */; }; 3CDBCF4227FAE51000354CDD /* ComposeLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CDBCF4127FAE51000354CDD /* ComposeLinkView.swift */; };
3CDBCF4827FF621E00354CDD /* CILinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CDBCF4727FF621E00354CDD /* CILinkView.swift */; }; 3CDBCF4827FF621E00354CDD /* CILinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CDBCF4727FF621E00354CDD /* CILinkView.swift */; };
5C00164428A26FBC0094D739 /* ContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C00164328A26FBC0094D739 /* ContextMenu.swift */; }; 5C00164428A26FBC0094D739 /* ContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C00164328A26FBC0094D739 /* ContextMenu.swift */; };
@@ -29,11 +30,6 @@
5C116CDC27AABE0400E66D01 /* ContactRequestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C116CDB27AABE0400E66D01 /* ContactRequestView.swift */; }; 5C116CDC27AABE0400E66D01 /* ContactRequestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C116CDB27AABE0400E66D01 /* ContactRequestView.swift */; };
5C13730B28156D2700F43030 /* ContactConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C13730A28156D2700F43030 /* ContactConnectionView.swift */; }; 5C13730B28156D2700F43030 /* ContactConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C13730A28156D2700F43030 /* ContactConnectionView.swift */; };
5C1A4C1E27A715B700EAD5AD /* ChatItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C1A4C1D27A715B700EAD5AD /* ChatItemView.swift */; }; 5C1A4C1E27A715B700EAD5AD /* ChatItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C1A4C1D27A715B700EAD5AD /* ChatItemView.swift */; };
5C245F192B4DB982001CC39F /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C245F142B4DB982001CC39F /* libgmpxx.a */; };
5C245F1A2B4DB982001CC39F /* libHSsimplex-chat-5.5.0.0-K5xQiJJwtSUKGqIyB7d1Tl-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C245F152B4DB982001CC39F /* libHSsimplex-chat-5.5.0.0-K5xQiJJwtSUKGqIyB7d1Tl-ghc9.6.3.a */; };
5C245F1B2B4DB982001CC39F /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C245F162B4DB982001CC39F /* libgmp.a */; };
5C245F1C2B4DB982001CC39F /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C245F172B4DB982001CC39F /* libffi.a */; };
5C245F1D2B4DB982001CC39F /* libHSsimplex-chat-5.5.0.0-K5xQiJJwtSUKGqIyB7d1Tl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C245F182B4DB982001CC39F /* libHSsimplex-chat-5.5.0.0-K5xQiJJwtSUKGqIyB7d1Tl.a */; };
5C2E260727A2941F00F70299 /* SimpleXAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260627A2941F00F70299 /* SimpleXAPI.swift */; }; 5C2E260727A2941F00F70299 /* SimpleXAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260627A2941F00F70299 /* SimpleXAPI.swift */; };
5C2E260B27A30CFA00F70299 /* ChatListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260A27A30CFA00F70299 /* ChatListView.swift */; }; 5C2E260B27A30CFA00F70299 /* ChatListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260A27A30CFA00F70299 /* ChatListView.swift */; };
5C2E260F27A30FDC00F70299 /* ChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260E27A30FDC00F70299 /* ChatView.swift */; }; 5C2E260F27A30FDC00F70299 /* ChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260E27A30FDC00F70299 /* ChatView.swift */; };
@@ -60,6 +56,7 @@
5C5F2B7027EBC704006A9D5F /* ProfileImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5F2B6F27EBC704006A9D5F /* ProfileImage.swift */; }; 5C5F2B7027EBC704006A9D5F /* ProfileImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5F2B6F27EBC704006A9D5F /* ProfileImage.swift */; };
5C65DAF929D0CC20003CEE45 /* DeveloperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C65DAF829D0CC20003CEE45 /* DeveloperView.swift */; }; 5C65DAF929D0CC20003CEE45 /* DeveloperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C65DAF829D0CC20003CEE45 /* DeveloperView.swift */; };
5C65F343297D45E100B67AF3 /* VersionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C65F341297D3F3600B67AF3 /* VersionView.swift */; }; 5C65F343297D45E100B67AF3 /* VersionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C65F341297D3F3600B67AF3 /* VersionView.swift */; };
5C6AD81327A834E300348BD7 /* NewChatButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C6AD81227A834E300348BD7 /* NewChatButton.swift */; };
5C6BA667289BD954009B8ECC /* DismissSheets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C6BA666289BD954009B8ECC /* DismissSheets.swift */; }; 5C6BA667289BD954009B8ECC /* DismissSheets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C6BA666289BD954009B8ECC /* DismissSheets.swift */; };
5C7031162953C97F00150A12 /* CIFeaturePreferenceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7031152953C97F00150A12 /* CIFeaturePreferenceView.swift */; }; 5C7031162953C97F00150A12 /* CIFeaturePreferenceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7031152953C97F00150A12 /* CIFeaturePreferenceView.swift */; };
5C7505A227B65FDB00BE3227 /* CIMetaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7505A127B65FDB00BE3227 /* CIMetaView.swift */; }; 5C7505A227B65FDB00BE3227 /* CIMetaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7505A127B65FDB00BE3227 /* CIMetaView.swift */; };
@@ -96,6 +93,8 @@
5CB0BA92282713FD00B3292C /* CreateProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB0BA91282713FD00B3292C /* CreateProfile.swift */; }; 5CB0BA92282713FD00B3292C /* CreateProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB0BA91282713FD00B3292C /* CreateProfile.swift */; };
5CB0BA9A2827FD8800B3292C /* HowItWorks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB0BA992827FD8800B3292C /* HowItWorks.swift */; }; 5CB0BA9A2827FD8800B3292C /* HowItWorks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB0BA992827FD8800B3292C /* HowItWorks.swift */; };
5CB2084F28DA4B4800D024EC /* RTCServers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB2084E28DA4B4800D024EC /* RTCServers.swift */; }; 5CB2084F28DA4B4800D024EC /* RTCServers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB2084E28DA4B4800D024EC /* RTCServers.swift */; };
5CB2085128DB64CA00D024EC /* CreateLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB2085028DB64CA00D024EC /* CreateLinkView.swift */; };
5CB2085328DB7CAF00D024EC /* ConnectViaLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB2085228DB7CAF00D024EC /* ConnectViaLinkView.swift */; };
5CB346E52868AA7F001FD2EF /* SuspendChat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB346E42868AA7F001FD2EF /* SuspendChat.swift */; }; 5CB346E52868AA7F001FD2EF /* SuspendChat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB346E42868AA7F001FD2EF /* SuspendChat.swift */; };
5CB346E72868D76D001FD2EF /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB346E62868D76D001FD2EF /* NotificationsView.swift */; }; 5CB346E72868D76D001FD2EF /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB346E62868D76D001FD2EF /* NotificationsView.swift */; };
5CB346E92869E8BA001FD2EF /* PushEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB346E82869E8BA001FD2EF /* PushEnvironment.swift */; }; 5CB346E92869E8BA001FD2EF /* PushEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB346E82869E8BA001FD2EF /* PushEnvironment.swift */; };
@@ -117,8 +116,13 @@
5CC2C0FF2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CC2C0FD2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings */; }; 5CC2C0FF2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CC2C0FD2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings */; };
5CC868F329EB540C0017BBFD /* CIRcvDecryptionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC868F229EB540C0017BBFD /* CIRcvDecryptionError.swift */; }; 5CC868F329EB540C0017BBFD /* CIRcvDecryptionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC868F229EB540C0017BBFD /* CIRcvDecryptionError.swift */; };
5CCB939C297EFCB100399E78 /* NavStackCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCB939B297EFCB100399E78 /* NavStackCompat.swift */; }; 5CCB939C297EFCB100399E78 /* NavStackCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCB939B297EFCB100399E78 /* NavStackCompat.swift */; };
5CD67B8F2B0E858A00C510B1 /* hs_init.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CD67B8D2B0E858A00C510B1 /* hs_init.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5CCD403427A5F6DF00368C90 /* AddContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403327A5F6DF00368C90 /* AddContactView.swift */; };
5CD67B902B0E858A00C510B1 /* hs_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 5CD67B8E2B0E858A00C510B1 /* hs_init.c */; }; 5CCD403727A5F9A200368C90 /* ScanToConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */; };
5CDA5A2D2B04FE2D00A71D61 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CDA5A282B04FE2D00A71D61 /* libgmp.a */; };
5CDA5A2E2B04FE2D00A71D61 /* libHSsimplex-chat-5.4.0.3-rODxCBVsb2BkD1fnTAqXL-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CDA5A292B04FE2D00A71D61 /* libHSsimplex-chat-5.4.0.3-rODxCBVsb2BkD1fnTAqXL-ghc9.6.3.a */; };
5CDA5A2F2B04FE2D00A71D61 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CDA5A2A2B04FE2D00A71D61 /* libffi.a */; };
5CDA5A302B04FE2D00A71D61 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CDA5A2B2B04FE2D00A71D61 /* libgmpxx.a */; };
5CDA5A312B04FE2D00A71D61 /* libHSsimplex-chat-5.4.0.3-rODxCBVsb2BkD1fnTAqXL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CDA5A2C2B04FE2D00A71D61 /* libHSsimplex-chat-5.4.0.3-rODxCBVsb2BkD1fnTAqXL.a */; };
5CDCAD482818589900503DA2 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CDCAD472818589900503DA2 /* NotificationService.swift */; }; 5CDCAD482818589900503DA2 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CDCAD472818589900503DA2 /* NotificationService.swift */; };
5CE2BA702845308900EC33A6 /* SimpleXChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; }; 5CE2BA702845308900EC33A6 /* SimpleXChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; };
5CE2BA712845308900EC33A6 /* SimpleXChat.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 5CE2BA712845308900EC33A6 /* SimpleXChat.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@@ -144,15 +148,10 @@
5CEACCED27DEA495000BD591 /* MsgContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEACCEC27DEA495000BD591 /* MsgContentView.swift */; }; 5CEACCED27DEA495000BD591 /* MsgContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEACCEC27DEA495000BD591 /* MsgContentView.swift */; };
5CEBD7462A5C0A8F00665FE2 /* KeyboardPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */; }; 5CEBD7462A5C0A8F00665FE2 /* KeyboardPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */; };
5CEBD7482A5F115D00665FE2 /* SetDeliveryReceiptsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEBD7472A5F115D00665FE2 /* SetDeliveryReceiptsView.swift */; }; 5CEBD7482A5F115D00665FE2 /* SetDeliveryReceiptsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEBD7472A5F115D00665FE2 /* SetDeliveryReceiptsView.swift */; };
5CF9371E2B23429500E1D781 /* ConcurrentQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF9371D2B23429500E1D781 /* ConcurrentQueue.swift */; };
5CF937202B24DE8C00E1D781 /* SharedFileSubscriber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF9371F2B24DE8C00E1D781 /* SharedFileSubscriber.swift */; };
5CF937232B2503D000E1D781 /* NSESubscriber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF937212B25034A00E1D781 /* NSESubscriber.swift */; };
5CFA59C42860BC6200863A68 /* MigrateToAppGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */; }; 5CFA59C42860BC6200863A68 /* MigrateToAppGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */; };
5CFA59D12864782E00863A68 /* ChatArchiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFA59CF286477B400863A68 /* ChatArchiveView.swift */; }; 5CFA59D12864782E00863A68 /* ChatArchiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFA59CF286477B400863A68 /* ChatArchiveView.swift */; };
5CFE0921282EEAF60002594B /* ZoomableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */; }; 5CFE0921282EEAF60002594B /* ZoomableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */; };
5CFE0922282EEAF60002594B /* ZoomableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */; }; 5CFE0922282EEAF60002594B /* ZoomableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */; };
640417CD2B29B8C200CCB412 /* NewChatMenuButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640417CB2B29B8C200CCB412 /* NewChatMenuButton.swift */; };
640417CE2B29B8C200CCB412 /* NewChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640417CC2B29B8C200CCB412 /* NewChatView.swift */; };
6407BA83295DA85D0082BA18 /* CIInvalidJSONView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6407BA82295DA85D0082BA18 /* CIInvalidJSONView.swift */; }; 6407BA83295DA85D0082BA18 /* CIInvalidJSONView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6407BA82295DA85D0082BA18 /* CIInvalidJSONView.swift */; };
6419EC562AB8BC8B004A607A /* ContextInvitingContactMemberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */; }; 6419EC562AB8BC8B004A607A /* ContextInvitingContactMemberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */; };
6419EC582AB97507004A607A /* CIMemberCreatedContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */; }; 6419EC582AB97507004A607A /* CIMemberCreatedContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */; };
@@ -184,7 +183,6 @@
64D0C2C629FAC1EC00B38D5F /* AddContactLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C529FAC1EC00B38D5F /* AddContactLearnMore.swift */; }; 64D0C2C629FAC1EC00B38D5F /* AddContactLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C529FAC1EC00B38D5F /* AddContactLearnMore.swift */; };
64E972072881BB22008DBC02 /* CIGroupInvitationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E972062881BB22008DBC02 /* CIGroupInvitationView.swift */; }; 64E972072881BB22008DBC02 /* CIGroupInvitationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E972062881BB22008DBC02 /* CIGroupInvitationView.swift */; };
64F1CC3B28B39D8600CD1FB1 /* IncognitoHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */; }; 64F1CC3B28B39D8600CD1FB1 /* IncognitoHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */; };
8C05382E2B39887E006436DC /* VideoUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C05382D2B39887E006436DC /* VideoUtils.swift */; };
D7197A1829AE89660055C05A /* WebRTC in Frameworks */ = {isa = PBXBuildFile; productRef = D7197A1729AE89660055C05A /* WebRTC */; }; D7197A1829AE89660055C05A /* WebRTC in Frameworks */ = {isa = PBXBuildFile; productRef = D7197A1729AE89660055C05A /* WebRTC */; };
D72A9088294BD7A70047C86D /* NativeTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A9087294BD7A70047C86D /* NativeTextEditor.swift */; }; D72A9088294BD7A70047C86D /* NativeTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A9087294BD7A70047C86D /* NativeTextEditor.swift */; };
D741547829AF89AF0022400A /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D741547729AF89AF0022400A /* StoreKit.framework */; }; D741547829AF89AF0022400A /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D741547729AF89AF0022400A /* StoreKit.framework */; };
@@ -259,6 +257,7 @@
18415B08031E8FB0F7FC27F9 /* CallViewRenderers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallViewRenderers.swift; sourceTree = "<group>"; }; 18415B08031E8FB0F7FC27F9 /* CallViewRenderers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallViewRenderers.swift; sourceTree = "<group>"; };
18415DAAAD1ADBEDB0EDA852 /* VideoPlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = "<group>"; }; 18415DAAAD1ADBEDB0EDA852 /* VideoPlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = "<group>"; };
18415FD2E36F13F596A45BB4 /* CIVideoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CIVideoView.swift; sourceTree = "<group>"; }; 18415FD2E36F13F596A45BB4 /* CIVideoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CIVideoView.swift; sourceTree = "<group>"; };
3C8C548828133C84000A3EC7 /* PasteToConnectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasteToConnectView.swift; sourceTree = "<group>"; };
3CDBCF4127FAE51000354CDD /* ComposeLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeLinkView.swift; sourceTree = "<group>"; }; 3CDBCF4127FAE51000354CDD /* ComposeLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeLinkView.swift; sourceTree = "<group>"; };
3CDBCF4727FF621E00354CDD /* CILinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CILinkView.swift; sourceTree = "<group>"; }; 3CDBCF4727FF621E00354CDD /* CILinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CILinkView.swift; sourceTree = "<group>"; };
5C00164328A26FBC0094D739 /* ContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenu.swift; sourceTree = "<group>"; }; 5C00164328A26FBC0094D739 /* ContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenu.swift; sourceTree = "<group>"; };
@@ -275,11 +274,6 @@
5C13730A28156D2700F43030 /* ContactConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactConnectionView.swift; sourceTree = "<group>"; }; 5C13730A28156D2700F43030 /* ContactConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactConnectionView.swift; sourceTree = "<group>"; };
5C13730C2815740A00F43030 /* DebugJSON.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = DebugJSON.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 5C13730C2815740A00F43030 /* DebugJSON.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = DebugJSON.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
5C1A4C1D27A715B700EAD5AD /* ChatItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemView.swift; sourceTree = "<group>"; }; 5C1A4C1D27A715B700EAD5AD /* ChatItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemView.swift; sourceTree = "<group>"; };
5C245F142B4DB982001CC39F /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
5C245F152B4DB982001CC39F /* libHSsimplex-chat-5.5.0.0-K5xQiJJwtSUKGqIyB7d1Tl-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.0.0-K5xQiJJwtSUKGqIyB7d1Tl-ghc9.6.3.a"; sourceTree = "<group>"; };
5C245F162B4DB982001CC39F /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
5C245F172B4DB982001CC39F /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
5C245F182B4DB982001CC39F /* libHSsimplex-chat-5.5.0.0-K5xQiJJwtSUKGqIyB7d1Tl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.0.0-K5xQiJJwtSUKGqIyB7d1Tl.a"; sourceTree = "<group>"; };
5C2E260627A2941F00F70299 /* SimpleXAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleXAPI.swift; sourceTree = "<group>"; }; 5C2E260627A2941F00F70299 /* SimpleXAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleXAPI.swift; sourceTree = "<group>"; };
5C2E260A27A30CFA00F70299 /* ChatListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListView.swift; sourceTree = "<group>"; }; 5C2E260A27A30CFA00F70299 /* ChatListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListView.swift; sourceTree = "<group>"; };
5C2E260E27A30FDC00F70299 /* ChatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatView.swift; sourceTree = "<group>"; }; 5C2E260E27A30FDC00F70299 /* ChatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatView.swift; sourceTree = "<group>"; };
@@ -319,6 +313,7 @@
5C65DAED29CB8908003CEE45 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 5C65DAED29CB8908003CEE45 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
5C65DAF829D0CC20003CEE45 /* DeveloperView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperView.swift; sourceTree = "<group>"; }; 5C65DAF829D0CC20003CEE45 /* DeveloperView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperView.swift; sourceTree = "<group>"; };
5C65F341297D3F3600B67AF3 /* VersionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionView.swift; sourceTree = "<group>"; }; 5C65F341297D3F3600B67AF3 /* VersionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionView.swift; sourceTree = "<group>"; };
5C6AD81227A834E300348BD7 /* NewChatButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewChatButton.swift; sourceTree = "<group>"; };
5C6BA666289BD954009B8ECC /* DismissSheets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DismissSheets.swift; sourceTree = "<group>"; }; 5C6BA666289BD954009B8ECC /* DismissSheets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DismissSheets.swift; sourceTree = "<group>"; };
5C6D183229E93FBA00D430B3 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = "pl.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = "<group>"; }; 5C6D183229E93FBA00D430B3 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = "pl.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = "<group>"; };
5C6D183329E93FBA00D430B3 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 5C6D183329E93FBA00D430B3 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@@ -375,6 +370,8 @@
5CB0BA91282713FD00B3292C /* CreateProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateProfile.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>"; }; 5CB0BA992827FD8800B3292C /* HowItWorks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HowItWorks.swift; sourceTree = "<group>"; };
5CB2084E28DA4B4800D024EC /* RTCServers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RTCServers.swift; sourceTree = "<group>"; }; 5CB2084E28DA4B4800D024EC /* RTCServers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RTCServers.swift; sourceTree = "<group>"; };
5CB2085028DB64CA00D024EC /* CreateLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateLinkView.swift; sourceTree = "<group>"; };
5CB2085228DB7CAF00D024EC /* ConnectViaLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectViaLinkView.swift; sourceTree = "<group>"; };
5CB2085428DE647400D024EC /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; 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>"; }; 5CB346E42868AA7F001FD2EF /* SuspendChat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuspendChat.swift; sourceTree = "<group>"; };
5CB346E62868D76D001FD2EF /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = "<group>"; }; 5CB346E62868D76D001FD2EF /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = "<group>"; };
@@ -400,8 +397,13 @@
5CC2C0FE2809BF11000C35E3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = "ru.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 5CCB939B297EFCB100399E78 /* NavStackCompat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavStackCompat.swift; sourceTree = "<group>"; };
5CD67B8D2B0E858A00C510B1 /* hs_init.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hs_init.h; sourceTree = "<group>"; }; 5CCD403327A5F6DF00368C90 /* AddContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddContactView.swift; sourceTree = "<group>"; };
5CD67B8E2B0E858A00C510B1 /* hs_init.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = hs_init.c; sourceTree = "<group>"; }; 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanToConnectView.swift; sourceTree = "<group>"; };
5CDA5A282B04FE2D00A71D61 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
5CDA5A292B04FE2D00A71D61 /* libHSsimplex-chat-5.4.0.3-rODxCBVsb2BkD1fnTAqXL-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.3-rODxCBVsb2BkD1fnTAqXL-ghc9.6.3.a"; sourceTree = "<group>"; };
5CDA5A2A2B04FE2D00A71D61 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
5CDA5A2B2B04FE2D00A71D61 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
5CDA5A2C2B04FE2D00A71D61 /* libHSsimplex-chat-5.4.0.3-rODxCBVsb2BkD1fnTAqXL.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.3-rODxCBVsb2BkD1fnTAqXL.a"; sourceTree = "<group>"; };
5CDCAD452818589900503DA2 /* SimpleX NSE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "SimpleX NSE.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 5CDCAD452818589900503DA2 /* SimpleX NSE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "SimpleX NSE.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
5CDCAD472818589900503DA2 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; }; 5CDCAD472818589900503DA2 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
5CDCAD492818589900503DA2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 5CDCAD492818589900503DA2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -428,14 +430,9 @@
5CEACCEC27DEA495000BD591 /* MsgContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MsgContentView.swift; sourceTree = "<group>"; }; 5CEACCEC27DEA495000BD591 /* MsgContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MsgContentView.swift; sourceTree = "<group>"; };
5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardPadding.swift; sourceTree = "<group>"; }; 5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardPadding.swift; sourceTree = "<group>"; };
5CEBD7472A5F115D00665FE2 /* SetDeliveryReceiptsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetDeliveryReceiptsView.swift; sourceTree = "<group>"; }; 5CEBD7472A5F115D00665FE2 /* SetDeliveryReceiptsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetDeliveryReceiptsView.swift; sourceTree = "<group>"; };
5CF9371D2B23429500E1D781 /* ConcurrentQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConcurrentQueue.swift; sourceTree = "<group>"; };
5CF9371F2B24DE8C00E1D781 /* SharedFileSubscriber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedFileSubscriber.swift; sourceTree = "<group>"; };
5CF937212B25034A00E1D781 /* NSESubscriber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSESubscriber.swift; sourceTree = "<group>"; };
5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrateToAppGroupView.swift; sourceTree = "<group>"; }; 5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrateToAppGroupView.swift; sourceTree = "<group>"; };
5CFA59CF286477B400863A68 /* ChatArchiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatArchiveView.swift; sourceTree = "<group>"; }; 5CFA59CF286477B400863A68 /* ChatArchiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatArchiveView.swift; sourceTree = "<group>"; };
5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ZoomableScrollView.swift; path = Shared/Views/ZoomableScrollView.swift; sourceTree = SOURCE_ROOT; }; 5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ZoomableScrollView.swift; path = Shared/Views/ZoomableScrollView.swift; sourceTree = SOURCE_ROOT; };
640417CB2B29B8C200CCB412 /* NewChatMenuButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewChatMenuButton.swift; sourceTree = "<group>"; };
640417CC2B29B8C200CCB412 /* NewChatView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewChatView.swift; sourceTree = "<group>"; };
6407BA82295DA85D0082BA18 /* CIInvalidJSONView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIInvalidJSONView.swift; sourceTree = "<group>"; }; 6407BA82295DA85D0082BA18 /* CIInvalidJSONView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIInvalidJSONView.swift; sourceTree = "<group>"; };
6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextInvitingContactMemberView.swift; sourceTree = "<group>"; }; 6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextInvitingContactMemberView.swift; sourceTree = "<group>"; };
6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIMemberCreatedContactView.swift; sourceTree = "<group>"; }; 6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIMemberCreatedContactView.swift; sourceTree = "<group>"; };
@@ -469,7 +466,6 @@
64DAE1502809D9F5000DA960 /* FileUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = "<group>"; }; 64DAE1502809D9F5000DA960 /* FileUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = "<group>"; };
64E972062881BB22008DBC02 /* CIGroupInvitationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIGroupInvitationView.swift; sourceTree = "<group>"; }; 64E972062881BB22008DBC02 /* CIGroupInvitationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIGroupInvitationView.swift; sourceTree = "<group>"; };
64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncognitoHelp.swift; sourceTree = "<group>"; }; 64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncognitoHelp.swift; sourceTree = "<group>"; };
8C05382D2B39887E006436DC /* VideoUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoUtils.swift; sourceTree = "<group>"; };
D72A9087294BD7A70047C86D /* NativeTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeTextEditor.swift; sourceTree = "<group>"; }; D72A9087294BD7A70047C86D /* NativeTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeTextEditor.swift; sourceTree = "<group>"; };
D741547729AF89AF0022400A /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/StoreKit.framework; sourceTree = DEVELOPER_DIR; }; D741547729AF89AF0022400A /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/StoreKit.framework; sourceTree = DEVELOPER_DIR; };
D741547929AF90B00022400A /* PushKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PushKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/PushKit.framework; sourceTree = DEVELOPER_DIR; }; D741547929AF90B00022400A /* PushKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PushKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/PushKit.framework; sourceTree = DEVELOPER_DIR; };
@@ -511,13 +507,13 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
5C245F192B4DB982001CC39F /* libgmpxx.a in Frameworks */, 5CDA5A302B04FE2D00A71D61 /* libgmpxx.a in Frameworks */,
5C245F1C2B4DB982001CC39F /* libffi.a in Frameworks */,
5C245F1D2B4DB982001CC39F /* libHSsimplex-chat-5.5.0.0-K5xQiJJwtSUKGqIyB7d1Tl.a in Frameworks */,
5C245F1B2B4DB982001CC39F /* libgmp.a in Frameworks */,
5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */, 5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */,
5C245F1A2B4DB982001CC39F /* libHSsimplex-chat-5.5.0.0-K5xQiJJwtSUKGqIyB7d1Tl-ghc9.6.3.a in Frameworks */, 5CDA5A2D2B04FE2D00A71D61 /* libgmp.a in Frameworks */,
5CDA5A2E2B04FE2D00A71D61 /* libHSsimplex-chat-5.4.0.3-rODxCBVsb2BkD1fnTAqXL-ghc9.6.3.a in Frameworks */,
5CDA5A2F2B04FE2D00A71D61 /* libffi.a in Frameworks */,
5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */, 5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */,
5CDA5A312B04FE2D00A71D61 /* libHSsimplex-chat-5.4.0.3-rODxCBVsb2BkD1fnTAqXL.a in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -579,11 +575,11 @@
5C764E5C279C70B7000C6508 /* Libraries */ = { 5C764E5C279C70B7000C6508 /* Libraries */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
5C245F172B4DB982001CC39F /* libffi.a */, 5CDA5A2A2B04FE2D00A71D61 /* libffi.a */,
5C245F162B4DB982001CC39F /* libgmp.a */, 5CDA5A282B04FE2D00A71D61 /* libgmp.a */,
5C245F142B4DB982001CC39F /* libgmpxx.a */, 5CDA5A2B2B04FE2D00A71D61 /* libgmpxx.a */,
5C245F152B4DB982001CC39F /* libHSsimplex-chat-5.5.0.0-K5xQiJJwtSUKGqIyB7d1Tl-ghc9.6.3.a */, 5CDA5A292B04FE2D00A71D61 /* libHSsimplex-chat-5.4.0.3-rODxCBVsb2BkD1fnTAqXL-ghc9.6.3.a */,
5C245F182B4DB982001CC39F /* libHSsimplex-chat-5.5.0.0-K5xQiJJwtSUKGqIyB7d1Tl.a */, 5CDA5A2C2B04FE2D00A71D61 /* libHSsimplex-chat-5.4.0.3-rODxCBVsb2BkD1fnTAqXL.a */,
); );
path = Libraries; path = Libraries;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -608,7 +604,6 @@
5C35CFC727B2782E00FB6C6D /* BGManager.swift */, 5C35CFC727B2782E00FB6C6D /* BGManager.swift */,
5C35CFCA27B2E91D00FB6C6D /* NtfManager.swift */, 5C35CFCA27B2E91D00FB6C6D /* NtfManager.swift */,
5CB346E42868AA7F001FD2EF /* SuspendChat.swift */, 5CB346E42868AA7F001FD2EF /* SuspendChat.swift */,
5CF937212B25034A00E1D781 /* NSESubscriber.swift */,
5CB346E82869E8BA001FD2EF /* PushEnvironment.swift */, 5CB346E82869E8BA001FD2EF /* PushEnvironment.swift */,
5C93293E2928E0FD0090FFF9 /* AudioRecPlay.swift */, 5C93293E2928E0FD0090FFF9 /* AudioRecPlay.swift */,
5CBD2859295711D700EC2CF4 /* ImageUtils.swift */, 5CBD2859295711D700EC2CF4 /* ImageUtils.swift */,
@@ -636,7 +631,6 @@
64466DCB29FFE3E800E3D48D /* MailView.swift */, 64466DCB29FFE3E800E3D48D /* MailView.swift */,
64C3B0202A0D359700E19930 /* CustomTimePicker.swift */, 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */,
5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */, 5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */,
8C05382D2B39887E006436DC /* VideoUtils.swift */,
); );
path = Helpers; path = Helpers;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -729,10 +723,14 @@
5CB924DD27A8622200ACCCDD /* NewChat */ = { 5CB924DD27A8622200ACCCDD /* NewChat */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
640417CB2B29B8C200CCB412 /* NewChatMenuButton.swift */, 5C6AD81227A834E300348BD7 /* NewChatButton.swift */,
640417CC2B29B8C200CCB412 /* NewChatView.swift */, 5CCD403327A5F6DF00368C90 /* AddContactView.swift */,
5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */,
3C8C548828133C84000A3EC7 /* PasteToConnectView.swift */,
5CC1C99127A6C7F5000D9FF6 /* QRCode.swift */, 5CC1C99127A6C7F5000D9FF6 /* QRCode.swift */,
6442E0B9287F169300CEC0F9 /* AddGroupView.swift */, 6442E0B9287F169300CEC0F9 /* AddGroupView.swift */,
5CB2085028DB64CA00D024EC /* CreateLinkView.swift */,
5CB2085228DB7CAF00D024EC /* ConnectViaLinkView.swift */,
64D0C2C529FAC1EC00B38D5F /* AddContactLearnMore.swift */, 64D0C2C529FAC1EC00B38D5F /* AddContactLearnMore.swift */,
); );
path = NewChat; path = NewChat;
@@ -786,7 +784,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
5CDCAD5128186DE400503DA2 /* SimpleX NSE.entitlements */, 5CDCAD5128186DE400503DA2 /* SimpleX NSE.entitlements */,
5CF9371D2B23429500E1D781 /* ConcurrentQueue.swift */,
5CDCAD472818589900503DA2 /* NotificationService.swift */, 5CDCAD472818589900503DA2 /* NotificationService.swift */,
5CDCAD492818589900503DA2 /* Info.plist */, 5CDCAD492818589900503DA2 /* Info.plist */,
5CB0BA862826CB3A00B3292C /* InfoPlist.strings */, 5CB0BA862826CB3A00B3292C /* InfoPlist.strings */,
@@ -807,13 +804,10 @@
64DAE1502809D9F5000DA960 /* FileUtils.swift */, 64DAE1502809D9F5000DA960 /* FileUtils.swift */,
5C9D81182AA7A4F1001D49FD /* CryptoFile.swift */, 5C9D81182AA7A4F1001D49FD /* CryptoFile.swift */,
5C00168028C4FE760094D739 /* KeyChain.swift */, 5C00168028C4FE760094D739 /* KeyChain.swift */,
5CF9371F2B24DE8C00E1D781 /* SharedFileSubscriber.swift */,
5CE2BA76284530BF00EC33A6 /* SimpleXChat.h */, 5CE2BA76284530BF00EC33A6 /* SimpleXChat.h */,
5CE2BA8A2845332200EC33A6 /* SimpleX.h */, 5CE2BA8A2845332200EC33A6 /* SimpleX.h */,
5CE2BA78284530CC00EC33A6 /* SimpleXChat.docc */, 5CE2BA78284530CC00EC33A6 /* SimpleXChat.docc */,
5CE2BA96284537A800EC33A6 /* dummy.m */, 5CE2BA96284537A800EC33A6 /* dummy.m */,
5CD67B8D2B0E858A00C510B1 /* hs_init.h */,
5CD67B8E2B0E858A00C510B1 /* hs_init.c */,
); );
path = SimpleXChat; path = SimpleXChat;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -898,7 +892,6 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
5CE2BA77284530BF00EC33A6 /* SimpleXChat.h in Headers */, 5CE2BA77284530BF00EC33A6 /* SimpleXChat.h in Headers */,
5CD67B8F2B0E858A00C510B1 /* hs_init.h in Headers */,
5CE2BA952845354B00EC33A6 /* SimpleX.h in Headers */, 5CE2BA952845354B00EC33A6 /* SimpleX.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@@ -1101,8 +1094,8 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
64C06EB52A0A4A7C00792D4D /* ChatItemInfoView.swift in Sources */, 64C06EB52A0A4A7C00792D4D /* ChatItemInfoView.swift in Sources */,
640417CE2B29B8C200CCB412 /* NewChatView.swift in Sources */,
6440CA03288AECA70062C672 /* AddGroupMembersView.swift in Sources */, 6440CA03288AECA70062C672 /* AddGroupMembersView.swift in Sources */,
5C6AD81327A834E300348BD7 /* NewChatButton.swift in Sources */,
5C3F1D58284363C400EC8A82 /* PrivacySettings.swift in Sources */, 5C3F1D58284363C400EC8A82 /* PrivacySettings.swift in Sources */,
5C55A923283CEDE600C4E99E /* SoundPlayer.swift in Sources */, 5C55A923283CEDE600C4E99E /* SoundPlayer.swift in Sources */,
5C93292F29239A170090FFF9 /* ProtocolServersView.swift in Sources */, 5C93292F29239A170090FFF9 /* ProtocolServersView.swift in Sources */,
@@ -1149,11 +1142,13 @@
5C063D2727A4564100AEC577 /* ChatPreviewView.swift in Sources */, 5C063D2727A4564100AEC577 /* ChatPreviewView.swift in Sources */,
5CC868F329EB540C0017BBFD /* CIRcvDecryptionError.swift in Sources */, 5CC868F329EB540C0017BBFD /* CIRcvDecryptionError.swift in Sources */,
5C35CFCB27B2E91D00FB6C6D /* NtfManager.swift in Sources */, 5C35CFCB27B2E91D00FB6C6D /* NtfManager.swift in Sources */,
3C8C548928133C84000A3EC7 /* PasteToConnectView.swift in Sources */,
5C9D13A3282187BB00AB8B43 /* WebRTC.swift in Sources */, 5C9D13A3282187BB00AB8B43 /* WebRTC.swift in Sources */,
5C9A5BDB2871E05400A5B906 /* SetNotificationsMode.swift in Sources */, 5C9A5BDB2871E05400A5B906 /* SetNotificationsMode.swift in Sources */,
5CB0BA8E2827126500B3292C /* OnboardingView.swift in Sources */, 5CB0BA8E2827126500B3292C /* OnboardingView.swift in Sources */,
6442E0BE2880182D00CEC0F9 /* GroupChatInfoView.swift in Sources */, 6442E0BE2880182D00CEC0F9 /* GroupChatInfoView.swift in Sources */,
5C2E261227A30FEA00F70299 /* TerminalView.swift in Sources */, 5C2E261227A30FEA00F70299 /* TerminalView.swift in Sources */,
5CB2085128DB64CA00D024EC /* CreateLinkView.swift in Sources */,
5C9FD96E27A5D6ED0075386C /* SendMessageView.swift in Sources */, 5C9FD96E27A5D6ED0075386C /* SendMessageView.swift in Sources */,
5CA7DFC329302AF000F7FDDE /* AppSheet.swift in Sources */, 5CA7DFC329302AF000F7FDDE /* AppSheet.swift in Sources */,
64E972072881BB22008DBC02 /* CIGroupInvitationView.swift in Sources */, 64E972072881BB22008DBC02 /* CIGroupInvitationView.swift in Sources */,
@@ -1162,8 +1157,8 @@
5CB9250D27A9432000ACCCDD /* ChatListNavLink.swift in Sources */, 5CB9250D27A9432000ACCCDD /* ChatListNavLink.swift in Sources */,
649BCDA0280460FD00C3A862 /* ComposeImageView.swift in Sources */, 649BCDA0280460FD00C3A862 /* ComposeImageView.swift in Sources */,
5CA059ED279559F40002BEB4 /* ContentView.swift in Sources */, 5CA059ED279559F40002BEB4 /* ContentView.swift in Sources */,
5CCD403427A5F6DF00368C90 /* AddContactView.swift in Sources */,
5C05DF532840AA1D00C683F9 /* CallSettings.swift in Sources */, 5C05DF532840AA1D00C683F9 /* CallSettings.swift in Sources */,
640417CD2B29B8C200CCB412 /* NewChatMenuButton.swift in Sources */,
5CFE0921282EEAF60002594B /* ZoomableScrollView.swift in Sources */, 5CFE0921282EEAF60002594B /* ZoomableScrollView.swift in Sources */,
5C3A88CE27DF50170060F1C2 /* DetermineWidth.swift in Sources */, 5C3A88CE27DF50170060F1C2 /* DetermineWidth.swift in Sources */,
5C7505A527B679EE00BE3227 /* NavLinkPlain.swift in Sources */, 5C7505A527B679EE00BE3227 /* NavLinkPlain.swift in Sources */,
@@ -1178,7 +1173,6 @@
5C2E260F27A30FDC00F70299 /* ChatView.swift in Sources */, 5C2E260F27A30FDC00F70299 /* ChatView.swift in Sources */,
5C2E260B27A30CFA00F70299 /* ChatListView.swift in Sources */, 5C2E260B27A30CFA00F70299 /* ChatListView.swift in Sources */,
6442E0BA287F169300CEC0F9 /* AddGroupView.swift in Sources */, 6442E0BA287F169300CEC0F9 /* AddGroupView.swift in Sources */,
5CF937232B2503D000E1D781 /* NSESubscriber.swift in Sources */,
6419EC582AB97507004A607A /* CIMemberCreatedContactView.swift in Sources */, 6419EC582AB97507004A607A /* CIMemberCreatedContactView.swift in Sources */,
64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */, 64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */,
64466DCC29FFE3E800E3D48D /* MailView.swift in Sources */, 64466DCC29FFE3E800E3D48D /* MailView.swift in Sources */,
@@ -1198,9 +1192,9 @@
6448BBB628FA9D56000D2AB9 /* GroupLinkView.swift in Sources */, 6448BBB628FA9D56000D2AB9 /* GroupLinkView.swift in Sources */,
5CB346E92869E8BA001FD2EF /* PushEnvironment.swift in Sources */, 5CB346E92869E8BA001FD2EF /* PushEnvironment.swift in Sources */,
5C55A91F283AD0E400C4E99E /* CallManager.swift in Sources */, 5C55A91F283AD0E400C4E99E /* CallManager.swift in Sources */,
5CCD403727A5F9A200368C90 /* ScanToConnectView.swift in Sources */,
5CFA59D12864782E00863A68 /* ChatArchiveView.swift in Sources */, 5CFA59D12864782E00863A68 /* ChatArchiveView.swift in Sources */,
649BCDA22805D6EF00C3A862 /* CIImageView.swift in Sources */, 649BCDA22805D6EF00C3A862 /* CIImageView.swift in Sources */,
8C05382E2B39887E006436DC /* VideoUtils.swift in Sources */,
5CADE79C292131E900072E13 /* ContactPreferencesView.swift in Sources */, 5CADE79C292131E900072E13 /* ContactPreferencesView.swift in Sources */,
5CB346E52868AA7F001FD2EF /* SuspendChat.swift in Sources */, 5CB346E52868AA7F001FD2EF /* SuspendChat.swift in Sources */,
5C9C2DA52894777E00CC63B1 /* GroupProfileView.swift in Sources */, 5C9C2DA52894777E00CC63B1 /* GroupProfileView.swift in Sources */,
@@ -1220,6 +1214,7 @@
5C93293F2928E0FD0090FFF9 /* AudioRecPlay.swift in Sources */, 5C93293F2928E0FD0090FFF9 /* AudioRecPlay.swift in Sources */,
5C029EA82837DBB3004A9677 /* CICallItemView.swift in Sources */, 5C029EA82837DBB3004A9677 /* CICallItemView.swift in Sources */,
5CE4407227ADB1D0007B033A /* Emoji.swift in Sources */, 5CE4407227ADB1D0007B033A /* Emoji.swift in Sources */,
5CB2085328DB7CAF00D024EC /* ConnectViaLinkView.swift in Sources */,
5C9CC7A928C532AB00BEF955 /* DatabaseErrorView.swift in Sources */, 5C9CC7A928C532AB00BEF955 /* DatabaseErrorView.swift in Sources */,
5C1A4C1E27A715B700EAD5AD /* ChatItemView.swift in Sources */, 5C1A4C1E27A715B700EAD5AD /* ChatItemView.swift in Sources */,
64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */, 64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */,
@@ -1257,7 +1252,6 @@
files = ( files = (
5CDCAD482818589900503DA2 /* NotificationService.swift in Sources */, 5CDCAD482818589900503DA2 /* NotificationService.swift in Sources */,
5CFE0922282EEAF60002594B /* ZoomableScrollView.swift in Sources */, 5CFE0922282EEAF60002594B /* ZoomableScrollView.swift in Sources */,
5CF9371E2B23429500E1D781 /* ConcurrentQueue.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -1265,11 +1259,9 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
5CF937202B24DE8C00E1D781 /* SharedFileSubscriber.swift in Sources */,
5C00168128C4FE760094D739 /* KeyChain.swift in Sources */, 5C00168128C4FE760094D739 /* KeyChain.swift in Sources */,
5CE2BA97284537A800EC33A6 /* dummy.m in Sources */, 5CE2BA97284537A800EC33A6 /* dummy.m in Sources */,
5CE2BA922845340900EC33A6 /* FileUtils.swift in Sources */, 5CE2BA922845340900EC33A6 /* FileUtils.swift in Sources */,
5CD67B902B0E858A00C510B1 /* hs_init.c in Sources */,
5CE2BA91284533A300EC33A6 /* Notifications.swift in Sources */, 5CE2BA91284533A300EC33A6 /* Notifications.swift in Sources */,
5CE2BA79284530CC00EC33A6 /* SimpleXChat.docc in Sources */, 5CE2BA79284530CC00EC33A6 /* SimpleXChat.docc in Sources */,
5CE2BA90284533A300EC33A6 /* JSON.swift in Sources */, 5CE2BA90284533A300EC33A6 /* JSON.swift in Sources */,
@@ -1502,7 +1494,7 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 187; CURRENT_PROJECT_VERSION = 181;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
@@ -1524,7 +1516,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 5.5; MARKETING_VERSION = 5.4;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX; PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@@ -1545,7 +1537,7 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 187; CURRENT_PROJECT_VERSION = 181;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
@@ -1567,7 +1559,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 5.5; MARKETING_VERSION = 5.4;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX; PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@@ -1626,7 +1618,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 187; CURRENT_PROJECT_VERSION = 181;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@@ -1639,7 +1631,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 5.5; MARKETING_VERSION = 5.4;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1658,7 +1650,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 187; CURRENT_PROJECT_VERSION = 181;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@@ -1671,7 +1663,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 5.5; MARKETING_VERSION = 5.4;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1690,7 +1682,7 @@
APPLICATION_EXTENSION_API_ONLY = YES; APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 187; CURRENT_PROJECT_VERSION = 181;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1714,7 +1706,7 @@
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Libraries/sim", "$(PROJECT_DIR)/Libraries/sim",
); );
MARKETING_VERSION = 5.5; MARKETING_VERSION = 5.4;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@@ -1736,7 +1728,7 @@
APPLICATION_EXTENSION_API_ONLY = YES; APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 187; CURRENT_PROJECT_VERSION = 181;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T; DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1760,7 +1752,7 @@
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Libraries/sim", "$(PROJECT_DIR)/Libraries/sim",
); );
MARKETING_VERSION = 5.5; MARKETING_VERSION = 5.4;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@@ -41,7 +41,7 @@
</Testables> </Testables>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug" buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"
@@ -2,7 +2,7 @@
<Scheme <Scheme
LastUpgradeVersion = "1400" LastUpgradeVersion = "1400"
wasCreatedForAppExtension = "YES" wasCreatedForAppExtension = "YES"
version = "1.3"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"> buildImplicitDependencies = "YES">
@@ -47,14 +47,16 @@
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug" buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0" launchStyle = "0"
askForAppToLaunch = "Yes"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal" debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable <BuildableProductRunnable
runnableDebuggingMode = "0"> runnableDebuggingMode = "0">
<BuildableReference <BuildableReference
+3 -14
View File
@@ -12,16 +12,12 @@ private var chatController: chat_ctrl?
private var migrationResult: (Bool, DBMigrationResult)? private var migrationResult: (Bool, DBMigrationResult)?
public func hasChatCtrl() -> Bool { public func getChatCtrl(_ useKey: String? = nil) -> chat_ctrl {
chatController != nil
}
public func getChatCtrl() -> chat_ctrl {
if let controller = chatController { return controller } if let controller = chatController { return controller }
fatalError("chat controller not initialized") fatalError("chat controller not initialized")
} }
public func chatMigrateInit(_ useKey: String? = nil, confirmMigrations: MigrationConfirmation? = nil, backgroundMode: Bool = false) -> (Bool, DBMigrationResult) { public func chatMigrateInit(_ useKey: String? = nil, confirmMigrations: MigrationConfirmation? = nil) -> (Bool, DBMigrationResult) {
if let res = migrationResult { return res } if let res = migrationResult { return res }
let dbPath = getAppDatabasePath().path let dbPath = getAppDatabasePath().path
var dbKey = "" var dbKey = ""
@@ -45,7 +41,7 @@ public func chatMigrateInit(_ useKey: String? = nil, confirmMigrations: Migratio
var cKey = dbKey.cString(using: .utf8)! var cKey = dbKey.cString(using: .utf8)!
var cConfirm = confirm.rawValue.cString(using: .utf8)! var cConfirm = confirm.rawValue.cString(using: .utf8)!
// the last parameter of chat_migrate_init is used to return the pointer to chat controller // the last parameter of chat_migrate_init is used to return the pointer to chat controller
let cjson = chat_migrate_init_key(&cPath, &cKey, 1, &cConfirm, backgroundMode ? 1 : 0, &chatController)! let cjson = chat_migrate_init(&cPath, &cKey, &cConfirm, &chatController)!
let dbRes = dbMigrationResult(fromCString(cjson)) let dbRes = dbMigrationResult(fromCString(cjson))
let encrypted = dbKey != "" let encrypted = dbKey != ""
let keychainErr = dbRes == .ok && useKeychain && encrypted && !kcDatabasePassword.set(dbKey) let keychainErr = dbRes == .ok && useKeychain && encrypted && !kcDatabasePassword.set(dbKey)
@@ -61,13 +57,6 @@ public func chatCloseStore() {
} }
} }
public func chatReopenStore() {
let err = fromCString(chat_reopen_store(getChatCtrl()))
if err != "" {
logger.error("chatReopenStore error: \(err)")
}
}
public func resetChatCtrl() { public func resetChatCtrl() {
chatController = nil chatController = nil
migrationResult = nil migrationResult = nil
+22 -33
View File
@@ -25,9 +25,9 @@ public enum ChatCommand {
case apiMuteUser(userId: Int64) case apiMuteUser(userId: Int64)
case apiUnmuteUser(userId: Int64) case apiUnmuteUser(userId: Int64)
case apiDeleteUser(userId: Int64, delSMPQueues: Bool, viewPwd: String?) case apiDeleteUser(userId: Int64, delSMPQueues: Bool, viewPwd: String?)
case startChat(mainApp: Bool) case startChat(subscribe: Bool, expire: Bool, xftp: Bool)
case apiStopChat case apiStopChat
case apiActivateChat(restoreChat: Bool) case apiActivateChat
case apiSuspendChat(timeoutMicroseconds: Int) case apiSuspendChat(timeoutMicroseconds: Int)
case setTempFolder(tempFolder: String) case setTempFolder(tempFolder: String)
case setFilesFolder(filesFolder: String) case setFilesFolder(filesFolder: String)
@@ -154,9 +154,9 @@ public enum ChatCommand {
case let .apiMuteUser(userId): return "/_mute user \(userId)" case let .apiMuteUser(userId): return "/_mute user \(userId)"
case let .apiUnmuteUser(userId): return "/_unmute user \(userId)" case let .apiUnmuteUser(userId): return "/_unmute user \(userId)"
case let .apiDeleteUser(userId, delSMPQueues, viewPwd): return "/_delete user \(userId) del_smp=\(onOff(delSMPQueues))\(maybePwd(viewPwd))" case let .apiDeleteUser(userId, delSMPQueues, viewPwd): return "/_delete user \(userId) del_smp=\(onOff(delSMPQueues))\(maybePwd(viewPwd))"
case let .startChat(mainApp): return "/_start main=\(onOff(mainApp))" case let .startChat(subscribe, expire, xftp): return "/_start subscribe=\(onOff(subscribe)) expire=\(onOff(expire)) xftp=\(onOff(xftp))"
case .apiStopChat: return "/_stop" case .apiStopChat: return "/_stop"
case let .apiActivateChat(restore): return "/_app activate restore=\(onOff(restore))" case .apiActivateChat: return "/_app activate"
case let .apiSuspendChat(timeoutMicroseconds): return "/_app suspend \(timeoutMicroseconds)" case let .apiSuspendChat(timeoutMicroseconds): return "/_app suspend \(timeoutMicroseconds)"
case let .setTempFolder(tempFolder): return "/_temp_folder \(tempFolder)" case let .setTempFolder(tempFolder): return "/_temp_folder \(tempFolder)"
case let .setFilesFolder(filesFolder): return "/_files_folder \(filesFolder)" case let .setFilesFolder(filesFolder): return "/_files_folder \(filesFolder)"
@@ -505,8 +505,8 @@ public enum ChatResponse: Decodable, Error {
case invitation(user: UserRef, connReqInvitation: String, connection: PendingContactConnection) case invitation(user: UserRef, connReqInvitation: String, connection: PendingContactConnection)
case connectionIncognitoUpdated(user: UserRef, toConnection: PendingContactConnection) case connectionIncognitoUpdated(user: UserRef, toConnection: PendingContactConnection)
case connectionPlan(user: UserRef, connectionPlan: ConnectionPlan) case connectionPlan(user: UserRef, connectionPlan: ConnectionPlan)
case sentConfirmation(user: UserRef, connection: PendingContactConnection) case sentConfirmation(user: UserRef)
case sentInvitation(user: UserRef, connection: PendingContactConnection) case sentInvitation(user: UserRef)
case sentInvitationToContact(user: UserRef, contact: Contact, customUserProfile: Profile?) case sentInvitationToContact(user: UserRef, contact: Contact, customUserProfile: Profile?)
case contactAlreadyExists(user: UserRef, contact: Contact) case contactAlreadyExists(user: UserRef, contact: Contact)
case contactRequestAlreadyAccepted(user: UserRef, contact: Contact) case contactRequestAlreadyAccepted(user: UserRef, contact: Contact)
@@ -604,16 +604,16 @@ public enum ChatResponse: Decodable, Error {
case callInvitations(callInvitations: [RcvCallInvitation]) case callInvitations(callInvitations: [RcvCallInvitation])
case ntfTokenStatus(status: NtfTknStatus) case ntfTokenStatus(status: NtfTknStatus)
case ntfToken(token: DeviceToken, status: NtfTknStatus, ntfMode: NotificationsMode) case ntfToken(token: DeviceToken, status: NtfTknStatus, ntfMode: NotificationsMode)
case ntfMessages(user_: User?, connEntity_: ConnectionEntity?, msgTs: Date?, ntfMessages: [NtfMsgInfo]) case ntfMessages(user_: User?, connEntity: ConnectionEntity?, msgTs: Date?, ntfMessages: [NtfMsgInfo])
case ntfMessage(user: UserRef, connEntity: ConnectionEntity, ntfMessage: NtfMsgInfo) case newContactConnection(user: UserRef, connection: PendingContactConnection)
case contactConnectionDeleted(user: UserRef, connection: PendingContactConnection) case contactConnectionDeleted(user: UserRef, connection: PendingContactConnection)
// remote desktop responses/events // remote desktop responses/events
case remoteCtrlList(remoteCtrls: [RemoteCtrlInfo]) case remoteCtrlList(remoteCtrls: [RemoteCtrlInfo])
case remoteCtrlFound(remoteCtrl: RemoteCtrlInfo, ctrlAppInfo_: CtrlAppInfo?, appVersion: String, compatible: Bool) case remoteCtrlFound(remoteCtrl: RemoteCtrlInfo)
case remoteCtrlConnecting(remoteCtrl_: RemoteCtrlInfo?, ctrlAppInfo: CtrlAppInfo, appVersion: String) case remoteCtrlConnecting(remoteCtrl_: RemoteCtrlInfo?, ctrlAppInfo: CtrlAppInfo, appVersion: String)
case remoteCtrlSessionCode(remoteCtrl_: RemoteCtrlInfo?, sessionCode: String) case remoteCtrlSessionCode(remoteCtrl_: RemoteCtrlInfo?, sessionCode: String)
case remoteCtrlConnected(remoteCtrl: RemoteCtrlInfo) case remoteCtrlConnected(remoteCtrl: RemoteCtrlInfo)
case remoteCtrlStopped(rcsState: RemoteCtrlSessionState, rcStopReason: RemoteCtrlStopReason) case remoteCtrlStopped
// misc // misc
case versionInfo(versionInfo: CoreVersionInfo, chatMigrations: [UpMigration], agentMigrations: [UpMigration]) case versionInfo(versionInfo: CoreVersionInfo, chatMigrations: [UpMigration], agentMigrations: [UpMigration])
case cmdOk(user: UserRef?) case cmdOk(user: UserRef?)
@@ -752,7 +752,7 @@ public enum ChatResponse: Decodable, Error {
case .ntfTokenStatus: return "ntfTokenStatus" case .ntfTokenStatus: return "ntfTokenStatus"
case .ntfToken: return "ntfToken" case .ntfToken: return "ntfToken"
case .ntfMessages: return "ntfMessages" case .ntfMessages: return "ntfMessages"
case .ntfMessage: return "ntfMessage" case .newContactConnection: return "newContactConnection"
case .contactConnectionDeleted: return "contactConnectionDeleted" case .contactConnectionDeleted: return "contactConnectionDeleted"
case .remoteCtrlList: return "remoteCtrlList" case .remoteCtrlList: return "remoteCtrlList"
case .remoteCtrlFound: return "remoteCtrlFound" case .remoteCtrlFound: return "remoteCtrlFound"
@@ -803,11 +803,11 @@ public enum ChatResponse: Decodable, Error {
case let .contactCode(u, contact, connectionCode): return withUser(u, "contact: \(String(describing: contact))\nconnectionCode: \(connectionCode)") case let .contactCode(u, contact, connectionCode): return withUser(u, "contact: \(String(describing: contact))\nconnectionCode: \(connectionCode)")
case let .groupMemberCode(u, groupInfo, member, connectionCode): return withUser(u, "groupInfo: \(String(describing: groupInfo))\nmember: \(String(describing: member))\nconnectionCode: \(connectionCode)") case let .groupMemberCode(u, groupInfo, member, connectionCode): return withUser(u, "groupInfo: \(String(describing: groupInfo))\nmember: \(String(describing: member))\nconnectionCode: \(connectionCode)")
case let .connectionVerified(u, verified, expectedCode): return withUser(u, "verified: \(verified)\nconnectionCode: \(expectedCode)") case let .connectionVerified(u, verified, expectedCode): return withUser(u, "verified: \(verified)\nconnectionCode: \(expectedCode)")
case let .invitation(u, connReqInvitation, connection): return withUser(u, "connReqInvitation: \(connReqInvitation)\nconnection: \(connection)") case let .invitation(u, connReqInvitation, _): return withUser(u, connReqInvitation)
case let .connectionIncognitoUpdated(u, toConnection): return withUser(u, String(describing: toConnection)) case let .connectionIncognitoUpdated(u, toConnection): return withUser(u, String(describing: toConnection))
case let .connectionPlan(u, connectionPlan): return withUser(u, String(describing: connectionPlan)) case let .connectionPlan(u, connectionPlan): return withUser(u, String(describing: connectionPlan))
case let .sentConfirmation(u, connection): return withUser(u, String(describing: connection)) case .sentConfirmation: return noDetails
case let .sentInvitation(u, connection): return withUser(u, String(describing: connection)) case .sentInvitation: return noDetails
case let .sentInvitationToContact(u, contact, _): return withUser(u, String(describing: contact)) case let .sentInvitationToContact(u, contact, _): return withUser(u, String(describing: contact))
case let .contactAlreadyExists(u, contact): return withUser(u, String(describing: contact)) case let .contactAlreadyExists(u, contact): return withUser(u, String(describing: contact))
case let .contactRequestAlreadyAccepted(u, contact): return withUser(u, String(describing: contact)) case let .contactRequestAlreadyAccepted(u, contact): return withUser(u, String(describing: contact))
@@ -900,10 +900,10 @@ public enum ChatResponse: Decodable, Error {
case let .ntfTokenStatus(status): return String(describing: status) case let .ntfTokenStatus(status): return String(describing: status)
case let .ntfToken(token, status, ntfMode): return "token: \(token)\nstatus: \(status.rawValue)\nntfMode: \(ntfMode.rawValue)" case let .ntfToken(token, status, ntfMode): return "token: \(token)\nstatus: \(status.rawValue)\nntfMode: \(ntfMode.rawValue)"
case let .ntfMessages(u, connEntity, msgTs, ntfMessages): return withUser(u, "connEntity: \(String(describing: connEntity))\nmsgTs: \(String(describing: msgTs))\nntfMessages: \(String(describing: ntfMessages))") case let .ntfMessages(u, connEntity, msgTs, ntfMessages): return withUser(u, "connEntity: \(String(describing: connEntity))\nmsgTs: \(String(describing: msgTs))\nntfMessages: \(String(describing: ntfMessages))")
case let .ntfMessage(u, connEntity, ntfMessage): return withUser(u, "connEntity: \(String(describing: connEntity))\nntfMessage: \(String(describing: ntfMessage))") case let .newContactConnection(u, connection): return withUser(u, String(describing: connection))
case let .contactConnectionDeleted(u, connection): return withUser(u, String(describing: connection)) case let .contactConnectionDeleted(u, connection): return withUser(u, String(describing: connection))
case let .remoteCtrlList(remoteCtrls): return String(describing: remoteCtrls) case let .remoteCtrlList(remoteCtrls): return String(describing: remoteCtrls)
case let .remoteCtrlFound(remoteCtrl, ctrlAppInfo_, appVersion, compatible): return "remoteCtrl:\n\(String(describing: remoteCtrl))\nctrlAppInfo_:\n\(String(describing: ctrlAppInfo_))\nappVersion: \(appVersion)\ncompatible: \(compatible)" case let .remoteCtrlFound(remoteCtrl): return String(describing: remoteCtrl)
case let .remoteCtrlConnecting(remoteCtrl_, ctrlAppInfo, appVersion): return "remoteCtrl_:\n\(String(describing: remoteCtrl_))\nctrlAppInfo:\n\(String(describing: ctrlAppInfo))\nappVersion: \(appVersion)" case let .remoteCtrlConnecting(remoteCtrl_, ctrlAppInfo, appVersion): return "remoteCtrl_:\n\(String(describing: remoteCtrl_))\nctrlAppInfo:\n\(String(describing: ctrlAppInfo))\nappVersion: \(appVersion)"
case let .remoteCtrlSessionCode(remoteCtrl_, sessionCode): return "remoteCtrl_:\n\(String(describing: remoteCtrl_))\nsessionCode: \(sessionCode)" case let .remoteCtrlSessionCode(remoteCtrl_, sessionCode): return "remoteCtrl_:\n\(String(describing: remoteCtrl_))\nsessionCode: \(sessionCode)"
case let .remoteCtrlConnected(remoteCtrl): return String(describing: remoteCtrl) case let .remoteCtrlConnected(remoteCtrl): return String(describing: remoteCtrl)
@@ -1207,9 +1207,9 @@ public struct NetCfg: Codable, Equatable {
public static let defaults: NetCfg = NetCfg( public static let defaults: NetCfg = NetCfg(
socksProxy: nil, socksProxy: nil,
sessionMode: TransportSessionMode.user, sessionMode: TransportSessionMode.user,
tcpConnectTimeout: 20_000_000, tcpConnectTimeout: 15_000_000,
tcpTimeout: 15_000_000, tcpTimeout: 10_000_000,
tcpTimeoutPerKb: 45_000, tcpTimeoutPerKb: 30_000,
tcpKeepAlive: KeepAliveOpts.defaults, tcpKeepAlive: KeepAliveOpts.defaults,
smpPingInterval: 1200_000_000, smpPingInterval: 1200_000_000,
smpPingCount: 3, smpPingCount: 3,
@@ -1498,8 +1498,6 @@ public enum PushProvider: String, Decodable {
} }
} }
// This notification mode is for app core, UI uses AppNotificationsMode.off to mean completely disable,
// and .local for periodic background checks
public enum NotificationsMode: String, Decodable, SelectableItem { public enum NotificationsMode: String, Decodable, SelectableItem {
case off = "OFF" case off = "OFF"
case periodic = "PERIODIC" case periodic = "PERIODIC"
@@ -1507,9 +1505,9 @@ public enum NotificationsMode: String, Decodable, SelectableItem {
public var label: LocalizedStringKey { public var label: LocalizedStringKey {
switch self { switch self {
case .off: "Local" case .off: return "Off (Local)"
case .periodic: "Periodically" case .periodic: return "Periodically"
case .instant: "Instantly" case .instant: return "Instantly"
} }
} }
@@ -1548,19 +1546,11 @@ public struct RemoteCtrlInfo: Decodable {
public enum RemoteCtrlSessionState: Decodable { public enum RemoteCtrlSessionState: Decodable {
case starting case starting
case searching
case connecting case connecting
case pendingConfirmation(sessionCode: String) case pendingConfirmation(sessionCode: String)
case connected(sessionCode: String) case connected(sessionCode: String)
} }
public enum RemoteCtrlStopReason: Decodable {
case discoveryFailed(chatError: ChatError)
case connectionFailed(chatError: ChatError)
case setupFailed(chatError: ChatError)
case disconnected
}
public struct CtrlAppInfo: Decodable { public struct CtrlAppInfo: Decodable {
public var appVersionRange: AppVersionRange public var appVersionRange: AppVersionRange
public var deviceName: String public var deviceName: String
@@ -1610,7 +1600,6 @@ public enum ChatErrorType: Decodable {
case userUnknown case userUnknown
case activeUserExists case activeUserExists
case userExists case userExists
case invalidDisplayName
case differentActiveUser(commandUserId: Int64, activeUserId: Int64) case differentActiveUser(commandUserId: Int64, activeUserId: Int64)
case cantDeleteActiveUser(userId: Int64) case cantDeleteActiveUser(userId: Int64)
case cantDeleteLastUser(userId: Int64) case cantDeleteLastUser(userId: Int64)
+7 -53
View File
@@ -9,16 +9,12 @@
import Foundation import Foundation
import SwiftUI import SwiftUI
public let appSuspendTimeout: Int = 15 // seconds
let GROUP_DEFAULT_APP_STATE = "appState" let GROUP_DEFAULT_APP_STATE = "appState"
let GROUP_DEFAULT_NSE_STATE = "nseState"
let GROUP_DEFAULT_DB_CONTAINER = "dbContainer" let GROUP_DEFAULT_DB_CONTAINER = "dbContainer"
public let GROUP_DEFAULT_CHAT_LAST_START = "chatLastStart" public let GROUP_DEFAULT_CHAT_LAST_START = "chatLastStart"
public let GROUP_DEFAULT_CHAT_LAST_BACKGROUND_RUN = "chatLastBackgroundRun"
let GROUP_DEFAULT_NTF_PREVIEW_MODE = "ntfPreviewMode" let GROUP_DEFAULT_NTF_PREVIEW_MODE = "ntfPreviewMode"
public let GROUP_DEFAULT_NTF_ENABLE_LOCAL = "ntfEnableLocal" // no longer used public let GROUP_DEFAULT_NTF_ENABLE_LOCAL = "ntfEnableLocal"
public let GROUP_DEFAULT_NTF_ENABLE_PERIODIC = "ntfEnablePeriodic" // no longer used public let GROUP_DEFAULT_NTF_ENABLE_PERIODIC = "ntfEnablePeriodic"
let GROUP_DEFAULT_PRIVACY_ACCEPT_IMAGES = "privacyAcceptImages" let GROUP_DEFAULT_PRIVACY_ACCEPT_IMAGES = "privacyAcceptImages"
public let GROUP_DEFAULT_PRIVACY_TRANSFER_IMAGES_INLINE = "privacyTransferImagesInline" // no longer used public let GROUP_DEFAULT_PRIVACY_TRANSFER_IMAGES_INLINE = "privacyTransferImagesInline" // no longer used
public let GROUP_DEFAULT_PRIVACY_ENCRYPT_LOCAL_FILES = "privacyEncryptLocalFiles" public let GROUP_DEFAULT_PRIVACY_ENCRYPT_LOCAL_FILES = "privacyEncryptLocalFiles"
@@ -70,23 +66,13 @@ public func registerGroupDefaults() {
]) ])
} }
public enum AppState: String, Codable { public enum AppState: String {
case active case active
case activating
case bgRefresh case bgRefresh
case suspending case suspending
case suspended case suspended
case stopped case stopped
public var running: Bool {
switch self {
case .active: return true
case .activating: return true
case .bgRefresh: return true
default: return false
}
}
public var inactive: Bool { public var inactive: Bool {
switch self { switch self {
case .suspending: return true case .suspending: return true
@@ -98,57 +84,23 @@ public enum AppState: String, Codable {
public var canSuspend: Bool { public var canSuspend: Bool {
switch self { switch self {
case .active: return true case .active: return true
case .activating: return true
case .bgRefresh: return true case .bgRefresh: return true
default: return false default: return false
} }
} }
} }
public enum NSEState: String, Codable {
case created
case starting
case active
case suspending
case suspended
public var inactive: Bool {
switch self {
case .created: true
case .suspended: true
default: false
}
}
public var canSuspend: Bool {
if case .active = self { true } else { false }
}
}
public enum DBContainer: String { public enum DBContainer: String {
case documents case documents
case group case group
} }
// appStateGroupDefault must not be used in the app directly, only via AppChatState singleton
public let appStateGroupDefault = EnumDefault<AppState>( public let appStateGroupDefault = EnumDefault<AppState>(
defaults: groupDefaults, defaults: groupDefaults,
forKey: GROUP_DEFAULT_APP_STATE, forKey: GROUP_DEFAULT_APP_STATE,
withDefault: .active withDefault: .active
) )
// nseStateGroupDefault must not be used in NSE directly, only via NSEChatState singleton
public let nseStateGroupDefault = EnumDefault<NSEState>(
defaults: groupDefaults,
forKey: GROUP_DEFAULT_NSE_STATE,
withDefault: .suspended // so that NSE that was never launched does not delay the app from resuming
)
// inactive app states do not include "stopped" state
public func allowBackgroundRefresh() -> Bool {
appStateGroupDefault.get().inactive && nseStateGroupDefault.get().inactive
}
public let dbContainerGroupDefault = EnumDefault<DBContainer>( public let dbContainerGroupDefault = EnumDefault<DBContainer>(
defaults: groupDefaults, defaults: groupDefaults,
forKey: GROUP_DEFAULT_DB_CONTAINER, forKey: GROUP_DEFAULT_DB_CONTAINER,
@@ -157,8 +109,6 @@ public let dbContainerGroupDefault = EnumDefault<DBContainer>(
public let chatLastStartGroupDefault = DateDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_CHAT_LAST_START) public let chatLastStartGroupDefault = DateDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_CHAT_LAST_START)
public let chatLastBackgroundRunGroupDefault = DateDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_CHAT_LAST_BACKGROUND_RUN)
public let ntfPreviewModeGroupDefault = EnumDefault<NotificationPreviewMode>( public let ntfPreviewModeGroupDefault = EnumDefault<NotificationPreviewMode>(
defaults: groupDefaults, defaults: groupDefaults,
forKey: GROUP_DEFAULT_NTF_PREVIEW_MODE, forKey: GROUP_DEFAULT_NTF_PREVIEW_MODE,
@@ -167,6 +117,10 @@ public let ntfPreviewModeGroupDefault = EnumDefault<NotificationPreviewMode>(
public let incognitoGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_INCOGNITO) public let incognitoGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_INCOGNITO)
public let ntfEnableLocalGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_NTF_ENABLE_LOCAL)
public let ntfEnablePeriodicGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_NTF_ENABLE_PERIODIC)
public let privacyAcceptImagesGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_PRIVACY_ACCEPT_IMAGES) public let privacyAcceptImagesGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_PRIVACY_ACCEPT_IMAGES)
public let privacyEncryptLocalFilesGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_PRIVACY_ENCRYPT_LOCAL_FILES) public let privacyEncryptLocalFilesGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_PRIVACY_ENCRYPT_LOCAL_FILES)
+23 -62
View File
@@ -172,6 +172,7 @@ public func fromLocalProfile (_ profile: LocalProfile) -> Profile {
} }
public struct UserProfileUpdateSummary: Decodable { public struct UserProfileUpdateSummary: Decodable {
public var notChanged: Int
public var updateSuccesses: Int public var updateSuccesses: Int
public var updateFailures: Int public var updateFailures: Int
public var changedContacts: [Contact] public var changedContacts: [Contact]
@@ -615,8 +616,8 @@ public enum ChatFeature: String, Decodable, Feature {
} }
case .fullDelete: case .fullDelete:
switch allowed { switch allowed {
case .always: return "Allow your contacts to irreversibly delete sent messages. (24 hours)" case .always: return "Allow your contacts to irreversibly delete sent messages."
case .yes: return "Allow irreversible message deletion only if your contact allows it to you. (24 hours)" case .yes: return "Allow irreversible message deletion only if your contact allows it to you."
case .no: return "Contacts can mark messages for deletion; you will be able to view them." case .no: return "Contacts can mark messages for deletion; you will be able to view them."
} }
case .reactions: case .reactions:
@@ -652,11 +653,11 @@ public enum ChatFeature: String, Decodable, Feature {
: "Disappearing messages are prohibited in this chat." : "Disappearing messages are prohibited in this chat."
case .fullDelete: case .fullDelete:
return enabled.forUser && enabled.forContact return enabled.forUser && enabled.forContact
? "Both you and your contact can irreversibly delete sent messages. (24 hours)" ? "Both you and your contact can irreversibly delete sent messages."
: enabled.forUser : enabled.forUser
? "Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" ? "Only you can irreversibly delete messages (your contact can mark them for deletion)."
: enabled.forContact : enabled.forContact
? "Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" ? "Only your contact can irreversibly delete messages (you can mark them for deletion)."
: "Irreversible message deletion is prohibited in this chat." : "Irreversible message deletion is prohibited in this chat."
case .reactions: case .reactions:
return enabled.forUser && enabled.forContact return enabled.forUser && enabled.forContact
@@ -693,7 +694,6 @@ public enum GroupFeature: String, Decodable, Feature {
case reactions case reactions
case voice case voice
case files case files
case history
public var id: Self { self } public var id: Self { self }
@@ -712,7 +712,6 @@ public enum GroupFeature: String, Decodable, Feature {
case .reactions: return NSLocalizedString("Message reactions", comment: "chat feature") case .reactions: return NSLocalizedString("Message reactions", comment: "chat feature")
case .voice: return NSLocalizedString("Voice messages", comment: "chat feature") case .voice: return NSLocalizedString("Voice messages", comment: "chat feature")
case .files: return NSLocalizedString("Files and media", comment: "chat feature") case .files: return NSLocalizedString("Files and media", comment: "chat feature")
case .history: return NSLocalizedString("Visible history", comment: "chat feature")
} }
} }
@@ -724,7 +723,6 @@ public enum GroupFeature: String, Decodable, Feature {
case .reactions: return "face.smiling" case .reactions: return "face.smiling"
case .voice: return "mic" case .voice: return "mic"
case .files: return "doc" case .files: return "doc"
case .history: return "clock"
} }
} }
@@ -736,7 +734,6 @@ public enum GroupFeature: String, Decodable, Feature {
case .reactions: return "face.smiling.fill" case .reactions: return "face.smiling.fill"
case .voice: return "mic.fill" case .voice: return "mic.fill"
case .files: return "doc.fill" case .files: return "doc.fill"
case .history: return "clock.fill"
} }
} }
@@ -762,7 +759,7 @@ public enum GroupFeature: String, Decodable, Feature {
} }
case .fullDelete: case .fullDelete:
switch enabled { switch enabled {
case .on: return "Allow to irreversibly delete sent messages. (24 hours)" case .on: return "Allow to irreversibly delete sent messages."
case .off: return "Prohibit irreversible message deletion." case .off: return "Prohibit irreversible message deletion."
} }
case .reactions: case .reactions:
@@ -780,11 +777,6 @@ public enum GroupFeature: String, Decodable, Feature {
case .on: return "Allow to send files and media." case .on: return "Allow to send files and media."
case .off: return "Prohibit sending files and media." case .off: return "Prohibit sending files and media."
} }
case .history:
switch enabled {
case .on: return "Send up to 100 last messages to new members."
case .off: return "Do not send history to new members."
}
} }
} else { } else {
switch self { switch self {
@@ -800,7 +792,7 @@ public enum GroupFeature: String, Decodable, Feature {
} }
case .fullDelete: case .fullDelete:
switch enabled { switch enabled {
case .on: return "Group members can irreversibly delete sent messages. (24 hours)" case .on: return "Group members can irreversibly delete sent messages."
case .off: return "Irreversible message deletion is prohibited in this group." case .off: return "Irreversible message deletion is prohibited in this group."
} }
case .reactions: case .reactions:
@@ -818,11 +810,6 @@ public enum GroupFeature: String, Decodable, Feature {
case .on: return "Group members can send files and media." case .on: return "Group members can send files and media."
case .off: return "Files and media are prohibited in this group." case .off: return "Files and media are prohibited in this group."
} }
case .history:
switch enabled {
case .on: return "Up to 100 last messages are sent to new members."
case .off: return "History is not sent to new members."
}
} }
} }
} }
@@ -962,7 +949,6 @@ public struct FullGroupPreferences: Decodable, Equatable {
public var reactions: GroupPreference public var reactions: GroupPreference
public var voice: GroupPreference public var voice: GroupPreference
public var files: GroupPreference public var files: GroupPreference
public var history: GroupPreference
public init( public init(
timedMessages: TimedMessagesGroupPreference, timedMessages: TimedMessagesGroupPreference,
@@ -970,8 +956,7 @@ public struct FullGroupPreferences: Decodable, Equatable {
fullDelete: GroupPreference, fullDelete: GroupPreference,
reactions: GroupPreference, reactions: GroupPreference,
voice: GroupPreference, voice: GroupPreference,
files: GroupPreference, files: GroupPreference
history: GroupPreference
) { ) {
self.timedMessages = timedMessages self.timedMessages = timedMessages
self.directMessages = directMessages self.directMessages = directMessages
@@ -979,7 +964,6 @@ public struct FullGroupPreferences: Decodable, Equatable {
self.reactions = reactions self.reactions = reactions
self.voice = voice self.voice = voice
self.files = files self.files = files
self.history = history
} }
public static let sampleData = FullGroupPreferences( public static let sampleData = FullGroupPreferences(
@@ -988,8 +972,7 @@ public struct FullGroupPreferences: Decodable, Equatable {
fullDelete: GroupPreference(enable: .off), fullDelete: GroupPreference(enable: .off),
reactions: GroupPreference(enable: .on), reactions: GroupPreference(enable: .on),
voice: GroupPreference(enable: .on), voice: GroupPreference(enable: .on),
files: GroupPreference(enable: .on), files: GroupPreference(enable: .on)
history: GroupPreference(enable: .on)
) )
} }
@@ -1000,16 +983,14 @@ public struct GroupPreferences: Codable {
public var reactions: GroupPreference? public var reactions: GroupPreference?
public var voice: GroupPreference? public var voice: GroupPreference?
public var files: GroupPreference? public var files: GroupPreference?
public var history: GroupPreference?
public init( public init(
timedMessages: TimedMessagesGroupPreference? = nil, timedMessages: TimedMessagesGroupPreference?,
directMessages: GroupPreference? = nil, directMessages: GroupPreference?,
fullDelete: GroupPreference? = nil, fullDelete: GroupPreference?,
reactions: GroupPreference? = nil, reactions: GroupPreference?,
voice: GroupPreference? = nil, voice: GroupPreference?,
files: GroupPreference? = nil, files: GroupPreference?
history: GroupPreference? = nil
) { ) {
self.timedMessages = timedMessages self.timedMessages = timedMessages
self.directMessages = directMessages self.directMessages = directMessages
@@ -1017,7 +998,6 @@ public struct GroupPreferences: Codable {
self.reactions = reactions self.reactions = reactions
self.voice = voice self.voice = voice
self.files = files self.files = files
self.history = history
} }
public static let sampleData = GroupPreferences( public static let sampleData = GroupPreferences(
@@ -1026,8 +1006,7 @@ public struct GroupPreferences: Codable {
fullDelete: GroupPreference(enable: .off), fullDelete: GroupPreference(enable: .off),
reactions: GroupPreference(enable: .on), reactions: GroupPreference(enable: .on),
voice: GroupPreference(enable: .on), voice: GroupPreference(enable: .on),
files: GroupPreference(enable: .on), files: GroupPreference(enable: .on)
history: GroupPreference(enable: .on)
) )
} }
@@ -1038,8 +1017,7 @@ public func toGroupPreferences(_ fullPreferences: FullGroupPreferences) -> Group
fullDelete: fullPreferences.fullDelete, fullDelete: fullPreferences.fullDelete,
reactions: fullPreferences.reactions, reactions: fullPreferences.reactions,
voice: fullPreferences.voice, voice: fullPreferences.voice,
files: fullPreferences.files, files: fullPreferences.files
history: fullPreferences.history
) )
} }
@@ -1869,7 +1847,7 @@ public struct GroupMember: Identifiable, Decodable {
public func canChangeRoleTo(groupInfo: GroupInfo) -> [GroupMemberRole]? { public func canChangeRoleTo(groupInfo: GroupInfo) -> [GroupMemberRole]? {
if !canBeRemoved(groupInfo: groupInfo) { return nil } if !canBeRemoved(groupInfo: groupInfo) { return nil }
let userRole = groupInfo.membership.memberRole let userRole = groupInfo.membership.memberRole
return GroupMemberRole.allCases.filter { $0 <= userRole && $0 != .author } return GroupMemberRole.allCases.filter { $0 <= userRole }
} }
public var memberIncognito: Bool { public var memberIncognito: Bool {
@@ -1909,7 +1887,6 @@ public struct GroupMemberIds: Decodable {
public enum GroupMemberRole: String, Identifiable, CaseIterable, Comparable, Decodable { public enum GroupMemberRole: String, Identifiable, CaseIterable, Comparable, Decodable {
case observer = "observer" case observer = "observer"
case author = "author"
case member = "member" case member = "member"
case admin = "admin" case admin = "admin"
case owner = "owner" case owner = "owner"
@@ -1919,7 +1896,6 @@ public enum GroupMemberRole: String, Identifiable, CaseIterable, Comparable, Dec
public var text: String { public var text: String {
switch self { switch self {
case .observer: return NSLocalizedString("observer", comment: "member role") case .observer: return NSLocalizedString("observer", comment: "member role")
case .author: return NSLocalizedString("author", comment: "member role")
case .member: return NSLocalizedString("member", comment: "member role") case .member: return NSLocalizedString("member", comment: "member role")
case .admin: return NSLocalizedString("admin", comment: "member role") case .admin: return NSLocalizedString("admin", comment: "member role")
case .owner: return NSLocalizedString("owner", comment: "member role") case .owner: return NSLocalizedString("owner", comment: "member role")
@@ -1929,10 +1905,9 @@ public enum GroupMemberRole: String, Identifiable, CaseIterable, Comparable, Dec
private var comparisonValue: Int { private var comparisonValue: Int {
switch self { switch self {
case .observer: return 0 case .observer: return 0
case .author: return 1 case .member: return 1
case .member: return 2 case .admin: return 2
case .admin: return 3 case .owner: return 3
case .owner: return 4
} }
} }
@@ -2038,8 +2013,7 @@ public enum ConnectionEntity: Decodable {
} }
public struct NtfMsgInfo: Decodable { public struct NtfMsgInfo: Decodable {
public var msgId: String
public var msgTs: Date
} }
public struct AChatItem: Decodable { public struct AChatItem: Decodable {
@@ -3130,10 +3104,6 @@ extension MsgContent: Encodable {
public struct FormattedText: Decodable { public struct FormattedText: Decodable {
public var text: String public var text: String
public var format: Format? public var format: Format?
public var isSecret: Bool {
if case .secret = format { true } else { false }
}
} }
public enum Format: Decodable, Equatable { public enum Format: Decodable, Equatable {
@@ -3147,15 +3117,6 @@ public enum Format: Decodable, Equatable {
case simplexLink(linkType: SimplexLinkType, simplexUri: String, smpHosts: [String]) case simplexLink(linkType: SimplexLinkType, simplexUri: String, smpHosts: [String])
case email case email
case phone case phone
public var isSimplexLink: Bool {
get {
switch (self) {
case .simplexLink: return true
default: return false
}
}
}
} }
public enum SimplexLinkType: String, Decodable { public enum SimplexLinkType: String, Decodable {
+2 -2
View File
@@ -17,7 +17,7 @@ public func writeCryptoFile(path: String, data: Data) throws -> CryptoFileArgs {
let ptr: UnsafeMutableRawPointer = malloc(data.count) let ptr: UnsafeMutableRawPointer = malloc(data.count)
memcpy(ptr, (data as NSData).bytes, data.count) memcpy(ptr, (data as NSData).bytes, data.count)
var cPath = path.cString(using: .utf8)! var cPath = path.cString(using: .utf8)!
let cjson = chat_write_file(getChatCtrl(), &cPath, ptr, Int32(data.count))! let cjson = chat_write_file(&cPath, ptr, Int32(data.count))!
let d = fromCString(cjson).data(using: .utf8)! let d = fromCString(cjson).data(using: .utf8)!
switch try jsonDecoder.decode(WriteFileResult.self, from: d) { switch try jsonDecoder.decode(WriteFileResult.self, from: d) {
case let .result(cfArgs): return cfArgs case let .result(cfArgs): return cfArgs
@@ -50,7 +50,7 @@ public func readCryptoFile(path: String, cryptoArgs: CryptoFileArgs) throws -> D
public func encryptCryptoFile(fromPath: String, toPath: String) throws -> CryptoFileArgs { public func encryptCryptoFile(fromPath: String, toPath: String) throws -> CryptoFileArgs {
var cFromPath = fromPath.cString(using: .utf8)! var cFromPath = fromPath.cString(using: .utf8)!
var cToPath = toPath.cString(using: .utf8)! var cToPath = toPath.cString(using: .utf8)!
let cjson = chat_encrypt_file(getChatCtrl(), &cFromPath, &cToPath)! let cjson = chat_encrypt_file(&cFromPath, &cToPath)!
let d = fromCString(cjson).data(using: .utf8)! let d = fromCString(cjson).data(using: .utf8)!
switch try jsonDecoder.decode(WriteFileResult.self, from: d) { switch try jsonDecoder.decode(WriteFileResult.self, from: d) {
case let .result(cfArgs): return cfArgs case let .result(cfArgs): return cfArgs
+4 -20
View File
@@ -69,29 +69,13 @@ func fileModificationDate(_ path: String) -> Date? {
} }
} }
public func deleteAppDatabaseAndFiles() {
let fm = FileManager.default
let dbPath = getAppDatabasePath().path
do {
try fm.removeItem(atPath: dbPath + CHAT_DB)
try fm.removeItem(atPath: dbPath + AGENT_DB)
} catch let error {
logger.error("Failed to delete all databases: \(error)")
}
try? fm.removeItem(atPath: dbPath + CHAT_DB_BAK)
try? fm.removeItem(atPath: dbPath + AGENT_DB_BAK)
try? fm.removeItem(at: getTempFilesDirectory())
try? fm.createDirectory(at: getTempFilesDirectory(), withIntermediateDirectories: true)
deleteAppFiles()
_ = kcDatabasePassword.remove()
storeDBPassphraseGroupDefault.set(true)
}
public func deleteAppFiles() { public func deleteAppFiles() {
let fm = FileManager.default let fm = FileManager.default
do { do {
try fm.removeItem(at: getAppFilesDirectory()) let fileNames = try fm.contentsOfDirectory(atPath: getAppFilesDirectory().path)
try fm.createDirectory(at: getAppFilesDirectory(), withIntermediateDirectories: true) for fileName in fileNames {
removeFile(fileName)
}
} catch { } catch {
logger.error("FileUtils deleteAppFiles error: \(error.localizedDescription)") logger.error("FileUtils deleteAppFiles error: \(error.localizedDescription)")
} }
-7
View File
@@ -146,13 +146,6 @@ public func createErrorNtf(_ dbStatus: DBMigrationResult) -> UNMutableNotificati
) )
} }
public func createAppStoppedNtf() -> UNMutableNotificationContent {
return createNotification(
categoryIdentifier: ntfCategoryConnectionEvent,
title: NSLocalizedString("Encrypted message: app is stopped", comment: "notification")
)
}
private func groupMsgNtfTitle(_ groupInfo: GroupInfo, _ groupMember: GroupMember, hideContent: Bool) -> String { private func groupMsgNtfTitle(_ groupInfo: GroupInfo, _ groupMember: GroupMember, hideContent: Bool) -> String {
hideContent hideContent
? NSLocalizedString("Group message:", comment: "notification") ? NSLocalizedString("Group message:", comment: "notification")
@@ -1,99 +0,0 @@
//
// SharedFileSubscriber.swift
// SimpleXChat
//
// Created by Evgeny on 09/12/2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import Foundation
public typealias AppSubscriber = SharedFileSubscriber<ProcessMessage<AppProcessMessage>>
public typealias NSESubscriber = SharedFileSubscriber<ProcessMessage<NSEProcessMessage>>
public class SharedFileSubscriber<Message: Codable>: NSObject, NSFilePresenter {
var fileURL: URL
public var presentedItemURL: URL?
public var presentedItemOperationQueue: OperationQueue = .main
var subscriber: (Message) -> Void
init(fileURL: URL, onMessage: @escaping (Message) -> Void) {
self.fileURL = fileURL
presentedItemURL = fileURL
subscriber = onMessage
super.init()
NSFileCoordinator.addFilePresenter(self)
}
public func presentedItemDidChange() {
do {
let data = try Data(contentsOf: fileURL)
let msg = try jsonDecoder.decode(Message.self, from: data)
subscriber(msg)
} catch let error {
logger.error("presentedItemDidChange error: \(error)")
}
}
static func notify(url: URL, message: Message) {
let fc = NSFileCoordinator(filePresenter: nil)
fc.coordinate(writingItemAt: url, options: [], error: nil) { newURL in
do {
let data = try jsonEncoder.encode(message)
try data.write(to: newURL, options: [.atomic])
} catch {
logger.error("notifyViaSharedFile error: \(error)")
}
}
}
deinit {
NSFileCoordinator.removeFilePresenter(self)
}
}
let appMessagesSharedFile = getGroupContainerDirectory().appendingPathComponent("chat.simplex.app.messages", isDirectory: false)
let nseMessagesSharedFile = getGroupContainerDirectory().appendingPathComponent("chat.simplex.app.SimpleX-NSE.messages", isDirectory: false)
public struct ProcessMessage<Message: Codable>: Codable {
var createdAt: Date = Date.now
var message: Message
}
public enum AppProcessMessage: Codable {
case state(state: AppState)
}
public enum NSEProcessMessage: Codable {
case state(state: NSEState)
}
public func sendAppProcessMessage(_ message: AppProcessMessage) {
SharedFileSubscriber.notify(url: appMessagesSharedFile, message: ProcessMessage(message: message))
}
public func sendNSEProcessMessage(_ message: NSEProcessMessage) {
SharedFileSubscriber.notify(url: nseMessagesSharedFile, message: ProcessMessage(message: message))
}
public func appMessageSubscriber(onMessage: @escaping (AppProcessMessage) -> Void) -> AppSubscriber {
SharedFileSubscriber(fileURL: appMessagesSharedFile) { (msg: ProcessMessage<AppProcessMessage>) in
onMessage(msg.message)
}
}
public func nseMessageSubscriber(onMessage: @escaping (NSEProcessMessage) -> Void) -> NSESubscriber {
SharedFileSubscriber(fileURL: nseMessagesSharedFile) { (msg: ProcessMessage<NSEProcessMessage>) in
onMessage(msg.message)
}
}
public func sendAppState(_ state: AppState) {
sendAppProcessMessage(.state(state: state))
}
public func sendNSEState(_ state: NSEState) {
sendNSEProcessMessage(.state(state: state))
}
+6 -8
View File
@@ -9,27 +9,27 @@
#ifndef SimpleX_h #ifndef SimpleX_h
#define SimpleX_h #define SimpleX_h
#include "hs_init.h" #endif /* SimpleX_h */
extern void hs_init(int argc, char **argv[]); extern void hs_init(int argc, char **argv[]);
typedef void* chat_ctrl; typedef void* chat_ctrl;
// the last parameter is used to return the pointer to chat controller // the last parameter is used to return the pointer to chat controller
extern char *chat_migrate_init_key(char *path, char *key, int keepKey, char *confirm, int backgroundMode, chat_ctrl *ctrl); extern char *chat_migrate_init(char *path, char *key, char *confirm, chat_ctrl *ctrl);
extern char *chat_close_store(chat_ctrl ctl); extern char *chat_close_store(chat_ctrl ctl);
extern char *chat_reopen_store(chat_ctrl ctl);
extern char *chat_send_cmd(chat_ctrl ctl, char *cmd); extern char *chat_send_cmd(chat_ctrl ctl, char *cmd);
extern char *chat_recv_msg(chat_ctrl ctl);
extern char *chat_recv_msg_wait(chat_ctrl ctl, int wait); extern char *chat_recv_msg_wait(chat_ctrl ctl, int wait);
extern char *chat_parse_markdown(char *str); extern char *chat_parse_markdown(char *str);
extern char *chat_parse_server(char *str); extern char *chat_parse_server(char *str);
extern char *chat_password_hash(char *pwd, char *salt); extern char *chat_password_hash(char *pwd, char *salt);
extern char *chat_valid_name(char *name); extern char *chat_valid_name(char *name);
extern char *chat_encrypt_media(chat_ctrl ctl, char *key, char *frame, int len); extern char *chat_encrypt_media(char *key, char *frame, int len);
extern char *chat_decrypt_media(char *key, char *frame, int len); extern char *chat_decrypt_media(char *key, char *frame, int len);
// chat_write_file returns null-terminated string with JSON of WriteFileResult // chat_write_file returns null-terminated string with JSON of WriteFileResult
extern char *chat_write_file(chat_ctrl ctl, char *path, char *data, int len); extern char *chat_write_file(char *path, char *data, int len);
// chat_read_file returns a buffer with: // chat_read_file returns a buffer with:
// result status (1 byte), then if // result status (1 byte), then if
@@ -38,9 +38,7 @@ extern char *chat_write_file(chat_ctrl ctl, char *path, char *data, int len);
extern char *chat_read_file(char *path, char *key, char *nonce); extern char *chat_read_file(char *path, char *key, char *nonce);
// chat_encrypt_file returns null-terminated string with JSON of WriteFileResult // chat_encrypt_file returns null-terminated string with JSON of WriteFileResult
extern char *chat_encrypt_file(chat_ctrl ctl, char *fromPath, char *toPath); extern char *chat_encrypt_file(char *fromPath, char *toPath);
// chat_decrypt_file returns null-terminated string with the error message // chat_decrypt_file returns null-terminated string with the error message
extern char *chat_decrypt_file(char *fromPath, char *key, char *nonce, char *toPath); extern char *chat_decrypt_file(char *fromPath, char *key, char *nonce, char *toPath);
#endif /* SimpleX_h */
-41
View File
@@ -1,41 +0,0 @@
//
// hs_init.c
// SimpleXChat
//
// Created by Evgeny on 22/11/2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
#include "hs_init.h"
extern void hs_init_with_rtsopts(int * argc, char **argv[]);
void haskell_init(void) {
int argc = 5;
char *argv[] = {
"simplex",
"+RTS", // requires `hs_init_with_rtsopts`
"-A16m", // chunk size for new allocations
"-H64m", // initial heap size
"-xn", // non-moving GC
0
};
char **pargv = argv;
hs_init_with_rtsopts(&argc, &pargv);
}
void haskell_init_nse(void) {
int argc = 7;
char *argv[] = {
"simplex",
"+RTS", // requires `hs_init_with_rtsopts`
"-A1m", // chunk size for new allocations
"-H1m", // initial heap size
"-F0.5", // heap growth triggering GC
"-Fd1", // memory return
"-c", // compacting garbage collector
0
};
char **pargv = argv;
hs_init_with_rtsopts(&argc, &pargv);
}
-16
View File
@@ -1,16 +0,0 @@
//
// hs_init.h
// SimpleXChat
//
// Created by Evgeny on 22/11/2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
#ifndef hs_init_h
#define hs_init_h
void haskell_init(void);
void haskell_init_nse(void);
#endif /* hs_init_h */
+12 -3
View File
@@ -1959,9 +1959,6 @@
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Live messages" = "Съобщения на живо"; "Live messages" = "Съобщения на живо";
/* No comment provided by engineer. */
"Local" = "Локално";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Local name" = "Локално име"; "Local name" = "Локално име";
@@ -2225,6 +2222,9 @@
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Off" = "Изключено"; "Off" = "Изключено";
/* No comment provided by engineer. */
"Off (Local)" = "Изключено (Локално)";
/* feature offered item */ /* feature offered item */
"offered %@" = "предлага %@"; "offered %@" = "предлага %@";
@@ -2315,6 +2315,9 @@
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Open-source protocol and code anybody can run the servers." = "Протокол и код с отворен код – всеки може да оперира собствени сървъри."; "Open-source protocol and code anybody can run the servers." = "Протокол и код с отворен код – всеки може да оперира собствени сървъри.";
/* No comment provided by engineer. */
"Opening database…" = "Отваряне на база данни…";
/* member role */ /* member role */
"owner" = "собственик"; "owner" = "собственик";
@@ -3215,6 +3218,9 @@
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Turn off" = "Изключи"; "Turn off" = "Изключи";
/* No comment provided by engineer. */
"Turn off notifications?" = "Изключи известията?";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Turn on" = "Включи"; "Turn on" = "Включи";
@@ -3635,6 +3641,9 @@
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Your contacts can allow full message deletion." = "Вашите контакти могат да позволят пълното изтриване на съобщението."; "Your contacts can allow full message deletion." = "Вашите контакти могат да позволят пълното изтриване на съобщението.";
/* No comment provided by engineer. */
"Your contacts in SimpleX will see it.\nYou can change it in Settings." = "Вашите контакти в SimpleX ще го видят.\nМожете да го промените в Настройки.";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Your contacts will remain connected." = "Вашите контакти ще останат свързани."; "Your contacts will remain connected." = "Вашите контакти ще останат свързани.";

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