Merge branch 'master' into master-ghc8107

This commit is contained in:
Evgeny Poberezkin 2023-11-24 19:00:30 +00:00
commit 0c096e2c89
78 changed files with 2625 additions and 340 deletions

View File

@ -770,7 +770,7 @@ final class GMember: ObservableObject, Identifiable {
}
struct RemoteCtrlSession {
var ctrlAppInfo: CtrlAppInfo
var ctrlAppInfo: CtrlAppInfo?
var appVersion: String
var sessionState: UIRemoteCtrlSessionState
@ -782,6 +782,10 @@ struct RemoteCtrlSession {
if case .connected = sessionState { true } else { false }
}
var discovery: Bool {
if case .searching = sessionState { true } else { false }
}
var sessionCode: String? {
switch sessionState {
case let .pendingConfirmation(_, sessionCode): sessionCode
@ -793,6 +797,8 @@ struct RemoteCtrlSession {
enum UIRemoteCtrlSessionState {
case starting
case searching
case found(remoteCtrl: RemoteCtrlInfo, compatible: Bool)
case connecting(remoteCtrl_: RemoteCtrlInfo?)
case pendingConfirmation(remoteCtrl_: RemoteCtrlInfo?, sessionCode: String)
case connected(remoteCtrl: RemoteCtrlInfo, sessionCode: String)

View File

@ -919,8 +919,10 @@ func findKnownRemoteCtrl() async throws {
try await sendCommandOkResp(.findKnownRemoteCtrl)
}
func confirmRemoteCtrl(_ rcId: Int64) async throws {
try await sendCommandOkResp(.confirmRemoteCtrl(remoteCtrlId: rcId))
func confirmRemoteCtrl(_ rcId: Int64) async throws -> (RemoteCtrlInfo?, CtrlAppInfo, String) {
let r = await chatSendCmd(.confirmRemoteCtrl(remoteCtrlId: rcId))
if case let .remoteCtrlConnecting(rc_, ctrlAppInfo, v) = r { return (rc_, ctrlAppInfo, v) }
throw r
}
func verifyRemoteCtrlSession(_ sessCode: String) async throws -> RemoteCtrlInfo {
@ -1714,9 +1716,17 @@ func processReceivedMsg(_ res: ChatResponse) async {
await MainActor.run {
m.updateGroupMemberConnectionStats(groupInfo, member, ratchetSyncProgress.connectionStats)
}
case let .remoteCtrlFound(remoteCtrl):
// TODO multicast
logger.debug("\(String(describing: remoteCtrl))")
case let .remoteCtrlFound(remoteCtrl, ctrlAppInfo_, appVersion, compatible):
await MainActor.run {
if let sess = m.remoteCtrlSession, case .searching = sess.sessionState {
let state = UIRemoteCtrlSessionState.found(remoteCtrl: remoteCtrl, compatible: compatible)
m.remoteCtrlSession = RemoteCtrlSession(
ctrlAppInfo: ctrlAppInfo_,
appVersion: appVersion,
sessionState: state
)
}
}
case let .remoteCtrlSessionCode(remoteCtrl_, sessionCode):
await MainActor.run {
let state = UIRemoteCtrlSessionState.pendingConfirmation(remoteCtrl_: remoteCtrl_, sessionCode: sessionCode)
@ -1731,8 +1741,13 @@ func processReceivedMsg(_ res: ChatResponse) async {
case .remoteCtrlStopped:
// 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.
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
switchToLocalSession()
if let sess = m.remoteCtrlSession {
m.remoteCtrlSession = nil
if case .connected = sess.sessionState {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
switchToLocalSession()
}
}
}
default:
logger.debug("unsupported event: \(res.responseType)")

View File

@ -16,12 +16,19 @@ struct ConnectDesktopView: View {
var viaSettings = false
@AppStorage(DEFAULT_DEVICE_NAME_FOR_REMOTE_ACCESS) private var deviceName = UIDevice.current.name
@AppStorage(DEFAULT_CONFIRM_REMOTE_SESSIONS) private var confirmRemoteSessions = false
@AppStorage(DEFAULT_CONNECT_REMOTE_VIA_MULTICAST) private var connectRemoteViaMulticast = false
@AppStorage(DEFAULT_OFFER_REMOTE_MULTICAST) private var offerRemoteMulticast = true
@AppStorage(DEFAULT_CONNECT_REMOTE_VIA_MULTICAST) private var connectRemoteViaMulticast = true
@AppStorage(DEFAULT_CONNECT_REMOTE_VIA_MULTICAST_AUTO) private var connectRemoteViaMulticastAuto = true
@AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false
@State private var sessionAddress: String = ""
@State private var remoteCtrls: [RemoteCtrlInfo] = []
@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 {
case unlinkDesktop(rc: RemoteCtrlInfo)
@ -67,9 +74,14 @@ struct ConnectDesktopView: View {
var viewBody: some View {
Group {
if let session = m.remoteCtrlSession {
let discovery = m.remoteCtrlSession?.discovery
if discovery == true || (discovery == nil && !showConnectScreen) {
searchingDesktopView()
} else if let session = m.remoteCtrlSession {
switch session.sessionState {
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 .pendingConfirmation(rc_, sessCode):
if confirmRemoteSessions || rc_ == nil {
@ -81,16 +93,35 @@ struct ConnectDesktopView: View {
}
case let .connected(rc, _): activeSessionView(session, rc)
}
} else {
// 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 {
connectDesktopView(showScanner: false)
}
}
.onAppear {
setDeviceName(deviceName)
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 {
if m.remoteCtrlSession != nil {
showConnectScreen = false
disconnectDesktop()
}
}
@ -134,12 +165,14 @@ struct ConnectDesktopView: View {
.interactiveDismissDisabled(m.activeRemoteCtrl)
}
private func connectDesktopView() -> some View {
private func connectDesktopView(showScanner: Bool = true) -> some View {
List {
Section("This device name") {
devicesView()
}
scanDesctopAddressView()
if showScanner {
scanDesctopAddressView()
}
if developerTools {
desktopAddressView()
}
@ -167,6 +200,56 @@ struct ConnectDesktopView: View {
.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(.dismiss)
} 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 {
List {
Section("Connected to desktop") {
@ -191,7 +274,7 @@ struct ConnectDesktopView: View {
}
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) {
t = t + Text(" ") + Text("(new)").italic()
}
@ -199,8 +282,8 @@ struct ConnectDesktopView: View {
}
private func ctrlDeviceVersionText(_ session: RemoteCtrlSession) -> Text {
let v = session.ctrlAppInfo.appVersionRange.maxVersion
var t = Text("v\(v)")
let v = session.ctrlAppInfo?.appVersionRange.maxVersion
var t = Text("v\(v ?? "")")
if v != session.appVersion {
t = t + Text(" ") + Text("(this device v\(session.appVersion))").italic()
}
@ -301,7 +384,10 @@ struct ConnectDesktopView: View {
Section("Linked desktop options") {
Toggle("Verify connections", isOn: $confirmRemoteSessions)
Toggle("Discover on network", isOn: $connectRemoteViaMulticast).disabled(true)
Toggle("Discover via local network", isOn: $connectRemoteViaMulticast)
if connectRemoteViaMulticast {
Toggle("Connect automatically", isOn: $connectRemoteViaMulticastAuto)
}
}
}
.navigationTitle("Linked desktops")
@ -335,10 +421,42 @@ struct ConnectDesktopView: View {
}
}
private func connectDesktopAddress(_ addr: String) {
private func findKnownDesktop() {
Task {
do {
let (rc_, ctrlAppInfo, v) = try await connectRemoteCtrl(desktopAddress: addr)
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) {
connectDesktop_ {
try await connectRemoteCtrl(desktopAddress: addr)
}
}
private func connectDesktop_(_ connect: @escaping () async throws -> (RemoteCtrlInfo?, CtrlAppInfo, String)) {
Task {
do {
let (rc_, ctrlAppInfo, v) = try await connect()
await MainActor.run {
sessionAddress = ""
m.remoteCtrlSession = RemoteCtrlSession(
@ -380,11 +498,11 @@ struct ConnectDesktopView: View {
}
}
private func disconnectButton() -> some View {
private func disconnectButton(_ label: LocalizedStringKey = "Disconnect") -> some View {
Button {
disconnectDesktop(.dismiss)
} label: {
Label("Disconnect", systemImage: "multiply")
Label(label, systemImage: "multiply")
}
}
@ -393,7 +511,11 @@ struct ConnectDesktopView: View {
do {
try await stopRemoteCtrl()
await MainActor.run {
switchToLocalSession()
if case .connected = m.remoteCtrlSession?.sessionState {
switchToLocalSession()
} else {
m.remoteCtrlSession = nil
}
switch action {
case .back: dismiss()
case .dismiss: dismiss()

View File

@ -56,7 +56,7 @@ let DEFAULT_SHOW_UNREAD_AND_FAVORITES = "showUnreadAndFavorites"
let DEFAULT_DEVICE_NAME_FOR_REMOTE_ACCESS = "deviceNameForRemoteAccess"
let DEFAULT_CONFIRM_REMOTE_SESSIONS = "confirmRemoteSessions"
let DEFAULT_CONNECT_REMOTE_VIA_MULTICAST = "connectRemoteViaMulticast"
let DEFAULT_OFFER_REMOTE_MULTICAST = "offerRemoteMulticast"
let DEFAULT_CONNECT_REMOTE_VIA_MULTICAST_AUTO = "connectRemoteViaMulticastAuto"
let appDefaults: [String: Any] = [
DEFAULT_SHOW_LA_NOTICE: false,
@ -91,8 +91,8 @@ let appDefaults: [String: Any] = [
DEFAULT_CUSTOM_DISAPPEARING_MESSAGE_TIME: 300,
DEFAULT_SHOW_UNREAD_AND_FAVORITES: false,
DEFAULT_CONFIRM_REMOTE_SESSIONS: false,
DEFAULT_CONNECT_REMOTE_VIA_MULTICAST: false,
DEFAULT_OFFER_REMOTE_MULTICAST: true
DEFAULT_CONNECT_REMOTE_VIA_MULTICAST: true,
DEFAULT_CONNECT_REMOTE_VIA_MULTICAST_AUTO: true,
]
enum SimpleXLinkMode: String, Identifiable {

View File

@ -1172,6 +1172,10 @@
<target>Свързване</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>Свързване инкогнито</target>
@ -1862,8 +1866,8 @@ This cannot be undone!</source>
<target>Открийте и се присъединете към групи</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2499,6 +2503,10 @@ This cannot be undone!</source>
<target>За конзолата</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>Френски интерфейс</target>
@ -3449,6 +3457,10 @@ This is your link for group %@!</source>
<target>Няма получени или изпратени файлове</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>Известия</target>
@ -5396,6 +5408,10 @@ To connect, please ask your contact to create another connection link and check
<target>Гласово съобщение…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>Изчаква се получаването на файла</target>
@ -5926,6 +5942,10 @@ SimpleX сървърите не могат да видят вашия профи
<target>аудио разговор (не е e2e криптиран)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>лошо ID на съобщението</target>

View File

@ -1172,6 +1172,10 @@
<target>Připojit</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>Spojit se inkognito</target>
@ -1862,8 +1866,8 @@ This cannot be undone!</source>
<target>Objevte a připojte skupiny</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2499,6 +2503,10 @@ This cannot be undone!</source>
<target>Pro konzoli</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>Francouzské rozhraní</target>
@ -3449,6 +3457,10 @@ This is your link for group %@!</source>
<target>Žádné přijaté ani odeslané soubory</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>Oznámení</target>
@ -5396,6 +5408,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
<target>Hlasová zpráva…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>Čekání na soubor</target>
@ -5926,6 +5942,10 @@ Servery SimpleX nevidí váš profil.</target>
<target>zvukový hovor (nešifrovaný e2e)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>špatné ID zprávy</target>

View File

@ -299,10 +299,12 @@
</trans-unit>
<trans-unit id="(new)" xml:space="preserve">
<source>(new)</source>
<target>(Neu)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="(this device v%@)" xml:space="preserve">
<source>(this device v%@)</source>
<target>(Dieses Gerät hat v%@)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=")" xml:space="preserve">
@ -397,6 +399,9 @@
<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">
@ -885,6 +890,7 @@
</trans-unit>
<trans-unit id="Bad desktop address" xml:space="preserve">
<source>Bad desktop address</source>
<target>Falsche Desktop-Adresse</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Bad message ID" xml:space="preserve">
@ -899,6 +905,7 @@
</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">
@ -913,6 +920,7 @@
</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">
@ -1186,6 +1194,10 @@
<target>Verbinden</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>Inkognito verbinden</target>
@ -1193,6 +1205,7 @@
</trans-unit>
<trans-unit id="Connect to desktop" xml:space="preserve">
<source>Connect to desktop</source>
<target>Mit dem Desktop verbinden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve">
@ -1241,10 +1254,12 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit>
<trans-unit id="Connected desktop" xml:space="preserve">
<source>Connected desktop</source>
<target>Verbundener Desktop</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connected to desktop" xml:space="preserve">
<source>Connected to desktop</source>
<target>Mit dem Desktop verbunden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve">
@ -1259,6 +1274,7 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit>
<trans-unit id="Connecting to desktop" xml:space="preserve">
<source>Connecting to desktop</source>
<target>Mit dem Desktop verbinden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection" xml:space="preserve">
@ -1283,6 +1299,7 @@ Das ist Ihr eigener Einmal-Link!</target>
</trans-unit>
<trans-unit id="Connection terminated" xml:space="preserve">
<source>Connection terminated</source>
<target>Verbindung beendet</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection timeout" xml:space="preserve">
@ -1367,6 +1384,7 @@ Das ist Ihr eigener Einmal-Link!</target>
</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">
@ -1781,14 +1799,17 @@ Das kann nicht rückgängig gemacht werden!</target>
</trans-unit>
<trans-unit id="Desktop address" xml:space="preserve">
<source>Desktop address</source>
<target>Desktop-Adresse</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<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>
<target>Desktop App-Version %@ ist mit dieser App nicht kompatibel.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Desktop devices" xml:space="preserve">
<source>Desktop devices</source>
<target>Desktop-Geräte</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Develop" xml:space="preserve">
@ -1883,6 +1904,7 @@ Das kann nicht rückgängig gemacht werden!</target>
</trans-unit>
<trans-unit id="Disconnect desktop?" xml:space="preserve">
<source>Disconnect desktop?</source>
<target>Desktop-Verbindung trennen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover and join groups" xml:space="preserve">
@ -1890,8 +1912,8 @@ Das kann nicht rückgängig gemacht werden!</target>
<target>Gruppen entdecken und ihnen beitreten</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2066,10 +2088,12 @@ Das kann nicht rückgängig gemacht werden!</target>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<target>Fehler bei der Neuverhandlung der Verschlüsselung</target>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<target>Neuverhandlung der Verschlüsselung fehlgeschlagen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
@ -2104,6 +2128,7 @@ Das kann nicht rückgängig gemacht werden!</target>
</trans-unit>
<trans-unit id="Enter this device name…" xml:space="preserve">
<source>Enter this device name…</source>
<target>Geben Sie diesen Gerätenamen ein…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter welcome message…" xml:space="preserve">
@ -2433,6 +2458,7 @@ Das kann nicht rückgängig gemacht werden!</target>
</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">
@ -2530,6 +2556,10 @@ Das kann nicht rückgängig gemacht werden!</target>
<target>Für Konsole</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>Französische Bedienoberfläche</target>
@ -2857,6 +2887,7 @@ Das kann nicht rückgängig gemacht werden!</target>
</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">
@ -2891,6 +2922,7 @@ Das kann nicht rückgängig gemacht werden!</target>
</trans-unit>
<trans-unit id="Incompatible version" xml:space="preserve">
<source>Incompatible version</source>
<target>Inkompatible Version</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incorrect passcode" xml:space="preserve">
@ -3065,6 +3097,7 @@ Das ist Ihr Link für die Gruppe %@!</target>
</trans-unit>
<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>
<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 your connections" xml:space="preserve">
@ -3129,14 +3162,17 @@ Das ist Ihr Link für die Gruppe %@!</target>
</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">
<source>Linked desktop options</source>
<target>Verknüpfte Desktop-Optionen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktops" xml:space="preserve">
<source>Linked desktops</source>
<target>Verknüpfte Desktops</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Live message!" xml:space="preserve">
@ -3489,6 +3525,10 @@ Das ist Ihr Link für die Gruppe %@!</target>
<target>Keine empfangenen oder gesendeten Dateien</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>Benachrichtigungen</target>
@ -3710,6 +3750,7 @@ Das ist Ihr Link für die Gruppe %@!</target>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source>
<target>Desktop-Adresse einfügen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste image" xml:space="preserve">
@ -4309,6 +4350,7 @@ Das ist Ihr Link für die Gruppe %@!</target>
</trans-unit>
<trans-unit id="Scan QR code from desktop" xml:space="preserve">
<source>Scan QR code from desktop</source>
<target>Den QR-Code vom Desktop scannen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Scan code" xml:space="preserve">
@ -4533,6 +4575,7 @@ Das ist Ihr Link für die Gruppe %@!</target>
</trans-unit>
<trans-unit id="Session code" xml:space="preserve">
<source>Session code</source>
<target>Sitzungscode</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Set 1 day" xml:space="preserve">
@ -5034,6 +5077,7 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
</trans-unit>
<trans-unit id="This device name" xml:space="preserve">
<source>This device name</source>
<target>Dieser Gerätename</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
@ -5073,6 +5117,7 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
</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">
@ -5236,10 +5281,12 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit>
<trans-unit id="Unlink" xml:space="preserve">
<source>Unlink</source>
<target>Entkoppeln</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unlink desktop?" xml:space="preserve">
<source>Unlink desktop?</source>
<target>Desktop entkoppeln?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unlock" xml:space="preserve">
@ -5334,6 +5381,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit>
<trans-unit id="Use from desktop" xml:space="preserve">
<source>Use from desktop</source>
<target>Vom Desktop aus nutzen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use iOS call interface" xml:space="preserve">
@ -5368,10 +5416,12 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit>
<trans-unit id="Verify code with desktop" xml:space="preserve">
<source>Verify code with desktop</source>
<target>Code mit dem Desktop überprüfen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify connection" xml:space="preserve">
<source>Verify connection</source>
<target>Verbindung überprüfen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify connection security" xml:space="preserve">
@ -5381,6 +5431,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit>
<trans-unit id="Verify connections" xml:space="preserve">
<source>Verify connections</source>
<target>Verbindungen überprüfen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify security code" xml:space="preserve">
@ -5395,6 +5446,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</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">
@ -5447,6 +5499,10 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
<target>Sprachnachrichten…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>Warte auf Datei</target>
@ -5992,6 +6048,10 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
<target>Audioanruf (nicht E2E verschlüsselt)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>Ungültige Nachrichten-ID</target>
@ -6576,6 +6636,7 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="v%@" xml:space="preserve">
<source>v%@</source>
<target>v%@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="v%@ (%@)" xml:space="preserve">
@ -6717,6 +6778,7 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<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>
<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>
</trans-unit>
<trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve">

View File

@ -1194,6 +1194,11 @@
<target>Connect</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>Connect incognito</target>
@ -1908,9 +1913,9 @@ This cannot be undone!</target>
<target>Discover and join groups</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<target>Discover on network</target>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<target>Discover via local network</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2553,6 +2558,11 @@ This cannot be undone!</target>
<target>For console</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>French interface</target>
@ -3518,6 +3528,11 @@ This is your link for group %@!</target>
<target>No received or sent files</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>Notifications</target>
@ -5488,6 +5503,11 @@ To connect, please ask your contact to create another connection link and check
<target>Voice message…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>Waiting for file</target>
@ -6033,6 +6053,11 @@ SimpleX servers cannot see your profile.</target>
<target>audio call (not e2e encrypted)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>bad message ID</target>

View File

@ -1172,6 +1172,10 @@
<target>Conectar</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>Conectar incognito</target>
@ -1862,8 +1866,8 @@ This cannot be undone!</source>
<target>Descubre y únete a grupos</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2499,6 +2503,10 @@ This cannot be undone!</source>
<target>Para consola</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>Interfaz en francés</target>
@ -3449,6 +3457,10 @@ This is your link for group %@!</source>
<target>Sin archivos recibidos o enviados</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>Notificaciones</target>
@ -5397,6 +5409,10 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb
<target>Mensaje de voz…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>Esperando archivo</target>
@ -5927,6 +5943,10 @@ Los servidores de SimpleX no pueden ver tu perfil.</target>
<target>llamada (sin cifrar)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>ID de mensaje erróneo</target>

View File

@ -1167,6 +1167,10 @@
<target>Yhdistä</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>Yhdistä Incognito</target>
@ -1857,8 +1861,8 @@ This cannot be undone!</source>
<target>Löydä ryhmiä ja liity niihin</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2491,6 +2495,10 @@ This cannot be undone!</source>
<target>Konsoliin</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>Ranskalainen käyttöliittymä</target>
@ -3440,6 +3448,10 @@ This is your link for group %@!</source>
<target>Ei vastaanotettuja tai lähetettyjä tiedostoja</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>Ilmoitukset</target>
@ -5383,6 +5395,10 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja
<target>Ääniviesti…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>Odottaa tiedostoa</target>
@ -5913,6 +5929,10 @@ SimpleX-palvelimet eivät näe profiiliasi.</target>
<target>äänipuhelu (ei e2e-salattu)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>virheellinen viestin tunniste</target>

View File

@ -299,10 +299,12 @@
</trans-unit>
<trans-unit id="(new)" xml:space="preserve">
<source>(new)</source>
<target>(nouveau)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="(this device v%@)" xml:space="preserve">
<source>(this device v%@)</source>
<target>(cet appareil v%@)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=")" xml:space="preserve">
@ -397,6 +399,9 @@
<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">
@ -885,6 +890,7 @@
</trans-unit>
<trans-unit id="Bad desktop address" xml:space="preserve">
<source>Bad desktop address</source>
<target>Mauvaise adresse de bureau</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Bad message ID" xml:space="preserve">
@ -899,6 +905,7 @@
</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">
@ -913,6 +920,7 @@
</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">
@ -1186,6 +1194,10 @@
<target>Se connecter</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>Se connecter incognito</target>
@ -1193,6 +1205,7 @@
</trans-unit>
<trans-unit id="Connect to desktop" xml:space="preserve">
<source>Connect to desktop</source>
<target>Se connecter au bureau</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve">
@ -1241,10 +1254,12 @@ Il s'agit de votre propre lien unique !</target>
</trans-unit>
<trans-unit id="Connected desktop" xml:space="preserve">
<source>Connected desktop</source>
<target>Bureau connecté</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connected to desktop" xml:space="preserve">
<source>Connected to desktop</source>
<target>Connecté au bureau</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve">
@ -1259,6 +1274,7 @@ Il s'agit de votre propre lien unique !</target>
</trans-unit>
<trans-unit id="Connecting to desktop" xml:space="preserve">
<source>Connecting to desktop</source>
<target>Connexion au bureau</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection" xml:space="preserve">
@ -1283,6 +1299,7 @@ Il s'agit de votre propre lien unique !</target>
</trans-unit>
<trans-unit id="Connection terminated" xml:space="preserve">
<source>Connection terminated</source>
<target>Connexion terminée</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection timeout" xml:space="preserve">
@ -1367,6 +1384,7 @@ Il s'agit de votre propre lien unique !</target>
</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">
@ -1781,14 +1799,17 @@ Cette opération ne peut être annulée !</target>
</trans-unit>
<trans-unit id="Desktop address" xml:space="preserve">
<source>Desktop address</source>
<target>Adresse de bureau</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<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>
<target>La version de l'application de bureau %@ n'est pas compatible avec cette application.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Desktop devices" xml:space="preserve">
<source>Desktop devices</source>
<target>Appareils de bureau</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Develop" xml:space="preserve">
@ -1883,6 +1904,7 @@ Cette opération ne peut être annulée !</target>
</trans-unit>
<trans-unit id="Disconnect desktop?" xml:space="preserve">
<source>Disconnect desktop?</source>
<target>Déconnecter le bureau ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover and join groups" xml:space="preserve">
@ -1890,8 +1912,8 @@ Cette opération ne peut être annulée !</target>
<target>Découvrir et rejoindre des groupes</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2066,10 +2088,12 @@ Cette opération ne peut être annulée !</target>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<target>Erreur lors de la renégociation du chiffrement</target>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<target>La renégociation du chiffrement a échoué.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
@ -2104,6 +2128,7 @@ Cette opération ne peut être annulée !</target>
</trans-unit>
<trans-unit id="Enter this device name…" xml:space="preserve">
<source>Enter this device name…</source>
<target>Entrez le nom de l'appareil…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter welcome message…" xml:space="preserve">
@ -2433,6 +2458,7 @@ Cette opération ne peut être annulée !</target>
</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">
@ -2530,6 +2556,10 @@ Cette opération ne peut être annulée !</target>
<target>Pour la console</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>Interface en français</target>
@ -2857,6 +2887,7 @@ Cette opération ne peut être annulée !</target>
</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">
@ -2891,6 +2922,7 @@ Cette opération ne peut être annulée !</target>
</trans-unit>
<trans-unit id="Incompatible version" xml:space="preserve">
<source>Incompatible version</source>
<target>Version incompatible</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incorrect passcode" xml:space="preserve">
@ -3065,6 +3097,7 @@ Voici votre lien pour le groupe %@ !</target>
</trans-unit>
<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>
<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 your connections" xml:space="preserve">
@ -3129,14 +3162,17 @@ Voici votre lien pour le groupe %@ !</target>
</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">
<source>Linked desktop options</source>
<target>Options de bureau lié</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktops" xml:space="preserve">
<source>Linked desktops</source>
<target>Bureaux liés</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Live message!" xml:space="preserve">
@ -3489,6 +3525,10 @@ Voici votre lien pour le groupe %@ !</target>
<target>Aucun fichier reçu ou envoyé</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>Notifications</target>
@ -3710,6 +3750,7 @@ Voici votre lien pour le groupe %@ !</target>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source>
<target>Coller l'adresse du bureau</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste image" xml:space="preserve">
@ -4309,6 +4350,7 @@ Voici votre lien pour le groupe %@ !</target>
</trans-unit>
<trans-unit id="Scan QR code from desktop" xml:space="preserve">
<source>Scan QR code from desktop</source>
<target>Scanner le code QR du bureau</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Scan code" xml:space="preserve">
@ -4533,6 +4575,7 @@ Voici votre lien pour le groupe %@ !</target>
</trans-unit>
<trans-unit id="Session code" xml:space="preserve">
<source>Session code</source>
<target>Code de session</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Set 1 day" xml:space="preserve">
@ -5034,6 +5077,7 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
</trans-unit>
<trans-unit id="This device name" xml:space="preserve">
<source>This device name</source>
<target>Ce nom d'appareil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
@ -5073,6 +5117,7 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
</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">
@ -5236,10 +5281,12 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
</trans-unit>
<trans-unit id="Unlink" xml:space="preserve">
<source>Unlink</source>
<target>Délier</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unlink desktop?" xml:space="preserve">
<source>Unlink desktop?</source>
<target>Délier le bureau ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unlock" xml:space="preserve">
@ -5334,6 +5381,7 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
</trans-unit>
<trans-unit id="Use from desktop" xml:space="preserve">
<source>Use from desktop</source>
<target>Utilisation depuis le bureau</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use iOS call interface" xml:space="preserve">
@ -5368,10 +5416,12 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
</trans-unit>
<trans-unit id="Verify code with desktop" xml:space="preserve">
<source>Verify code with desktop</source>
<target>Vérifier le code avec le bureau</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify connection" xml:space="preserve">
<source>Verify connection</source>
<target>Vérifier la connexion</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify connection security" xml:space="preserve">
@ -5381,6 +5431,7 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
</trans-unit>
<trans-unit id="Verify connections" xml:space="preserve">
<source>Verify connections</source>
<target>Vérifier les connexions</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify security code" xml:space="preserve">
@ -5395,6 +5446,7 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
</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">
@ -5447,6 +5499,10 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
<target>Message vocal…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>En attente du fichier</target>
@ -5992,6 +6048,10 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
<target>appel audio (sans chiffrement)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>ID de message incorrecte</target>
@ -6576,6 +6636,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
</trans-unit>
<trans-unit id="v%@" xml:space="preserve">
<source>v%@</source>
<target>v%@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="v%@ (%@)" xml:space="preserve">
@ -6717,6 +6778,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
</trans-unit>
<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>
<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>
</trans-unit>
<trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve">

View File

@ -399,6 +399,9 @@
<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">
@ -902,6 +905,7 @@
</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">
@ -916,6 +920,7 @@
</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">
@ -1189,6 +1194,10 @@
<target>Connetti</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>Connetti in incognito</target>
@ -1375,6 +1384,7 @@ Questo è il tuo link una tantum!</target>
</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">
@ -1902,9 +1912,8 @@ Non è reversibile!</target>
<target>Scopri ed unisciti ai gruppi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<target>Trova nella rete</target>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2449,6 +2458,7 @@ Non è reversibile!</target>
</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">
@ -2546,6 +2556,10 @@ Non è reversibile!</target>
<target>Per console</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>Interfaccia francese</target>
@ -2873,6 +2887,7 @@ Non è reversibile!</target>
</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">
@ -3147,6 +3162,7 @@ Questo è il tuo link per il gruppo %@!</target>
</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">
@ -3509,6 +3525,10 @@ Questo è il tuo link per il gruppo %@!</target>
<target>Nessun file ricevuto o inviato</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>Notifiche</target>
@ -5097,6 +5117,7 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta
</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">
@ -5425,6 +5446,7 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
</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">
@ -5477,6 +5499,10 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
<target>Messaggio vocale…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>In attesa del file</target>
@ -6022,6 +6048,10 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
<target>chiamata audio (non crittografata e2e)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>ID messaggio errato</target>

View File

@ -1169,6 +1169,10 @@
<target>接続</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>シークレットモードで接続</target>
@ -1859,8 +1863,8 @@ This cannot be undone!</source>
<target>グループを見つけて参加する</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2494,6 +2498,10 @@ This cannot be undone!</source>
<target>コンソール</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>フランス語UI</target>
@ -3443,6 +3451,10 @@ This is your link for group %@!</source>
<target>送受信済みのファイルがありません</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>通知</target>
@ -5379,6 +5391,10 @@ To connect, please ask your contact to create another connection link and check
<target>音声メッセージ…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>ファイル待ち</target>
@ -5909,6 +5925,10 @@ SimpleX サーバーはあなたのプロファイルを参照できません。
<target>音声通話 (エンドツーエンド暗号化なし)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>メッセージ ID が正しくありません</target>

View File

@ -399,6 +399,9 @@
<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>
<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">
@ -902,6 +905,7 @@
</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">
@ -916,6 +920,7 @@
</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">
@ -1189,6 +1194,10 @@
<target>Verbind</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>Verbind incognito</target>
@ -1375,6 +1384,7 @@ Dit is uw eigen eenmalige link!</target>
</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">
@ -1902,9 +1912,8 @@ Dit kan niet ongedaan gemaakt worden!</target>
<target>Ontdek en sluit je aan bij groepen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<target>Ontdek via netwerk</target>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2449,6 +2458,7 @@ Dit kan niet ongedaan gemaakt worden!</target>
</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">
@ -2546,6 +2556,10 @@ Dit kan niet ongedaan gemaakt worden!</target>
<target>Voor console</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>Franse interface</target>
@ -2873,6 +2887,7 @@ Dit kan niet ongedaan gemaakt worden!</target>
</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">
@ -3147,6 +3162,7 @@ Dit is jouw link voor groep %@!</target>
</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">
@ -3509,6 +3525,10 @@ Dit is jouw link voor groep %@!</target>
<target>Geen ontvangen of verzonden bestanden</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>Meldingen</target>
@ -5097,6 +5117,7 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target>
</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">
@ -5425,6 +5446,7 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
</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">
@ -5477,6 +5499,10 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
<target>Spraakbericht…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>Wachten op bestand</target>
@ -6022,6 +6048,10 @@ SimpleX servers kunnen uw profiel niet zien.</target>
<target>audio oproep (niet e2e versleuteld)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>Onjuiste bericht-ID</target>

View File

@ -1186,6 +1186,10 @@
<target>Połącz</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>Połącz incognito</target>
@ -1890,8 +1894,8 @@ To nie może być cofnięte!</target>
<target>Odkrywaj i dołączaj do grup</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2530,6 +2534,10 @@ To nie może być cofnięte!</target>
<target>Dla konsoli</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>Francuski interfejs</target>
@ -3489,6 +3497,10 @@ To jest twój link do grupy %@!</target>
<target>Brak odebranych lub wysłanych plików</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>Powiadomienia</target>
@ -5447,6 +5459,10 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
<target>Wiadomość głosowa…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>Oczekiwanie na plik</target>
@ -5992,6 +6008,10 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
<target>połączenie audio (nie szyfrowane e2e)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>zły identyfikator wiadomości</target>

View File

@ -89,6 +89,7 @@
</trans-unit>
<trans-unit id="%@ and %@" xml:space="preserve">
<source>%@ and %@</source>
<target>%@ и %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ and %@ connected" xml:space="preserve">
@ -103,6 +104,7 @@
</trans-unit>
<trans-unit id="%@ connected" xml:space="preserve">
<source>%@ connected</source>
<target>%@ соединен(а)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ is connected!" xml:space="preserve">
@ -132,6 +134,7 @@
</trans-unit>
<trans-unit id="%@, %@ and %lld members" xml:space="preserve">
<source>%@, %@ and %lld members</source>
<target>%@, %@ и %lld членов группы</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve">
@ -201,6 +204,7 @@
</trans-unit>
<trans-unit id="%lld group events" xml:space="preserve">
<source>%lld group events</source>
<target>%lld событий</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld members" xml:space="preserve">
@ -210,14 +214,17 @@
</trans-unit>
<trans-unit id="%lld messages blocked" xml:space="preserve">
<source>%lld messages blocked</source>
<target>%lld сообщений заблокировано</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve">
<source>%lld messages marked deleted</source>
<target>%lld сообщений помечено удалёнными</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages moderated by %@" xml:space="preserve">
<source>%lld messages moderated by %@</source>
<target>%lld сообщений модерировано членом %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld minutes" xml:space="preserve">
@ -292,10 +299,12 @@
</trans-unit>
<trans-unit id="(new)" xml:space="preserve">
<source>(new)</source>
<target>(новое)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="(this device v%@)" xml:space="preserve">
<source>(this device v%@)</source>
<target>(это устройство v%@)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=")" xml:space="preserve">
@ -390,6 +399,9 @@
<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">
@ -408,6 +420,7 @@
</trans-unit>
<trans-unit id="0 sec" xml:space="preserve">
<source>0 sec</source>
<target>0 сек</target>
<note>time to disappear</note>
</trans-unit>
<trans-unit id="0s" xml:space="preserve">
@ -637,6 +650,7 @@
</trans-unit>
<trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve">
<source>All new messages from %@ will be hidden!</source>
<target>Все новые сообщения от %@ будут скрыты!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
@ -746,10 +760,12 @@
</trans-unit>
<trans-unit id="Already connecting!" xml:space="preserve">
<source>Already connecting!</source>
<target>Уже соединяется!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Already joining the group!" xml:space="preserve">
<source>Already joining the group!</source>
<target>Вступление в группу уже начато!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Always use relay" xml:space="preserve">
@ -874,6 +890,7 @@
</trans-unit>
<trans-unit id="Bad desktop address" xml:space="preserve">
<source>Bad desktop address</source>
<target>Неверный адрес компьютера</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Bad message ID" xml:space="preserve">
@ -888,6 +905,7 @@
</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">
@ -897,18 +915,22 @@
</trans-unit>
<trans-unit id="Block" xml:space="preserve">
<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>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve">
<source>Block member</source>
<target>Заблокировать члена группы</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member?" xml:space="preserve">
<source>Block member?</source>
<target>Заблокировать члена группы?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@ -1172,6 +1194,10 @@
<target>Соединиться</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>Соединиться Инкогнито</target>
@ -1179,24 +1205,31 @@
</trans-unit>
<trans-unit id="Connect to desktop" xml:space="preserve">
<source>Connect to desktop</source>
<target>Подключиться к компьютеру</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve">
<source>Connect to yourself?</source>
<target>Соединиться с самим собой?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own SimpleX address!" xml:space="preserve">
<source>Connect to yourself?
This is your own SimpleX address!</source>
<target>Соединиться с самим собой?
Это ваш собственный адрес SimpleX!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own one-time link!" xml:space="preserve">
<source>Connect to yourself?
This is your own one-time link!</source>
<target>Соединиться с самим собой?
Это ваша собственная одноразовая ссылка!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact address" xml:space="preserve">
<source>Connect via contact address</source>
<target>Соединиться через адрес</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via link" xml:space="preserve">
@ -1216,14 +1249,17 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Connect with %@" xml:space="preserve">
<source>Connect with %@</source>
<target>Соединиться с %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connected desktop" xml:space="preserve">
<source>Connected desktop</source>
<target>Подключенный компьютер</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connected to desktop" xml:space="preserve">
<source>Connected to desktop</source>
<target>Компьютер подключен</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve">
@ -1238,6 +1274,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Connecting to desktop" xml:space="preserve">
<source>Connecting to desktop</source>
<target>Подключение к компьютеру</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection" xml:space="preserve">
@ -1262,6 +1299,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Connection terminated" xml:space="preserve">
<source>Connection terminated</source>
<target>Подключение прервано</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection timeout" xml:space="preserve">
@ -1331,6 +1369,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Correct name to %@?" xml:space="preserve">
<source>Correct name to %@?</source>
<target>Исправить имя на %@?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create" xml:space="preserve">
@ -1345,6 +1384,7 @@ This is your own one-time link!</source>
</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>Создайте группу, используя случайный профиль.</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">
@ -1359,6 +1399,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Create group" xml:space="preserve">
<source>Create group</source>
<target>Создать группу</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create group link" xml:space="preserve">
@ -1383,6 +1424,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source>
<target>Создать профиль</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create queue" xml:space="preserve">
@ -1545,6 +1587,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Delete %lld messages?" xml:space="preserve">
<source>Delete %lld messages?</source>
<target>Удалить %lld сообщений?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete Contact" xml:space="preserve">
@ -1574,6 +1617,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Delete and notify contact" xml:space="preserve">
<source>Delete and notify contact</source>
<target>Удалить и уведомить контакт</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete archive" xml:space="preserve">
@ -1609,6 +1653,8 @@ This is your own one-time link!</source>
<trans-unit id="Delete contact?&#10;This cannot be undone!" xml:space="preserve">
<source>Delete contact?
This cannot be undone!</source>
<target>Удалить контакт?
Это не может быть отменено!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete database" xml:space="preserve">
@ -1753,14 +1799,17 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Desktop address" xml:space="preserve">
<source>Desktop address</source>
<target>Адрес компьютера</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<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>
<target>Версия настольного приложения %@ несовместима с этим приложением.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Desktop devices" xml:space="preserve">
<source>Desktop devices</source>
<target>Компьютеры</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Develop" xml:space="preserve">
@ -1855,6 +1904,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Disconnect desktop?" xml:space="preserve">
<source>Disconnect desktop?</source>
<target>Отключить компьютер?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover and join groups" xml:space="preserve">
@ -1862,8 +1912,8 @@ This cannot be undone!</source>
<target>Найдите и вступите в группы</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2038,10 +2088,12 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<target>Ошибка нового соглашения о шифровании</target>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<target>Ошибка нового соглашения о шифровании.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
@ -2056,6 +2108,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Enter group name…" xml:space="preserve">
<source>Enter group name…</source>
<target>Введите имя группы…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter passphrase…" xml:space="preserve">
@ -2075,6 +2128,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Enter this device name…" xml:space="preserve">
<source>Enter this device name…</source>
<target>Введите имя этого устройства…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter welcome message…" xml:space="preserve">
@ -2089,6 +2143,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Enter your name…" xml:space="preserve">
<source>Enter your name…</source>
<target>Введите ваше имя…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error" xml:space="preserve">
@ -2148,6 +2203,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Error creating member contact" xml:space="preserve">
<source>Error creating member contact</source>
<target>Ошибка создания контакта с членом группы</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error creating profile!" xml:space="preserve">
@ -2282,6 +2338,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Error sending member contact invitation" xml:space="preserve">
<source>Error sending member contact invitation</source>
<target>Ошибка отправки приглашения члену группы</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending message" xml:space="preserve">
@ -2366,6 +2423,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Expand" xml:space="preserve">
<source>Expand</source>
<target>Раскрыть</target>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Export database" xml:space="preserve">
@ -2400,6 +2458,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Faster joining and more reliable messages." xml:space="preserve">
<source>Faster joining and more reliable messages.</source>
<target>Быстрое вступление и надежная доставка сообщений.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Favorite" xml:space="preserve">
@ -2497,6 +2556,10 @@ This cannot be undone!</source>
<target>Для консоли</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>Французский интерфейс</target>
@ -2519,6 +2582,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Группа полностью децентрализована она видна только членам.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully re-implemented - work in background!" xml:space="preserve">
@ -2543,10 +2607,12 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Group already exists" xml:space="preserve">
<source>Group already exists</source>
<target>Группа уже существует</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group already exists!" xml:space="preserve">
<source>Group already exists!</source>
<target>Группа уже существует!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group display name" xml:space="preserve">
@ -2821,6 +2887,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Incognito groups" xml:space="preserve">
<source>Incognito groups</source>
<target>Инкогнито группы</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode" xml:space="preserve">
@ -2855,6 +2922,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Incompatible version" xml:space="preserve">
<source>Incompatible version</source>
<target>Несовместимая версия</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incorrect passcode" xml:space="preserve">
@ -2906,6 +2974,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source>
<target>Неверное имя!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve">
@ -3001,6 +3070,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Join group?" xml:space="preserve">
<source>Join group?</source>
<target>Вступить в группу?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join incognito" xml:space="preserve">
@ -3010,11 +3080,14 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Join with current profile" xml:space="preserve">
<source>Join with current profile</source>
<target>Вступить с активным профилем</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join your group?&#10;This is your link for group %@!" xml:space="preserve">
<source>Join your group?
This is your link for group %@!</source>
<target>Вступить в вашу группу?
Это ваша ссылка на группу %@!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Joining group" xml:space="preserve">
@ -3024,6 +3097,7 @@ This is your link for group %@!</source>
</trans-unit>
<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>
<target>Оставьте приложение открытым, чтобы использовать его с компьютера</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve">
@ -3088,14 +3162,17 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Link mobile and desktop apps! 🔗" xml:space="preserve">
<source>Link mobile and desktop apps! 🔗</source>
<target>Свяжите мобильное и настольное приложения! 🔗</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktop options" xml:space="preserve">
<source>Linked desktop options</source>
<target>Опции связанных компьютеров</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Linked desktops" xml:space="preserve">
<source>Linked desktops</source>
<target>Связанные компьютеры</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Live message!" xml:space="preserve">
@ -3250,6 +3327,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Messages from %@ will be shown!" xml:space="preserve">
<source>Messages from %@ will be shown!</source>
<target>Сообщения от %@ будут показаны!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrating database archive…" xml:space="preserve">
@ -3447,6 +3525,10 @@ This is your link for group %@!</source>
<target>Нет полученных или отправленных файлов</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>Уведомления</target>
@ -3583,6 +3665,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Open" xml:space="preserve">
<source>Open</source>
<target>Открыть</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open Settings" xml:space="preserve">
@ -3602,6 +3685,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Open group" xml:space="preserve">
<source>Open group</source>
<target>Открыть группу</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open user profiles" xml:space="preserve">
@ -3666,6 +3750,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve">
<source>Paste desktop address</source>
<target>Вставить адрес компьютера</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste image" xml:space="preserve">
@ -3815,10 +3900,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Имя профиля</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Имя профиля:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
@ -4068,10 +4155,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Repeat connection request?" xml:space="preserve">
<source>Repeat connection request?</source>
<target>Повторить запрос на соединение?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Repeat join request?" xml:space="preserve">
<source>Repeat join request?</source>
<target>Повторить запрос на вступление?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reply" xml:space="preserve">
@ -4261,6 +4350,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Scan QR code from desktop" xml:space="preserve">
<source>Scan QR code from desktop</source>
<target>Сканировать QR код с компьютера</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Scan code" xml:space="preserve">
@ -4345,6 +4435,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Send direct message to connect" xml:space="preserve">
<source>Send direct message to connect</source>
<target>Отправьте сообщение чтобы соединиться</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Send disappearing message" xml:space="preserve">
@ -4484,6 +4575,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Session code" xml:space="preserve">
<source>Session code</source>
<target>Код сессии</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Set 1 day" xml:space="preserve">
@ -4798,6 +4890,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Tap to Connect" xml:space="preserve">
<source>Tap to Connect</source>
<target>Нажмите чтобы соединиться</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to activate profile." xml:space="preserve">
@ -4984,6 +5077,7 @@ It can happen because of some bug or when the connection is compromised.</source
</trans-unit>
<trans-unit id="This device name" xml:space="preserve">
<source>This device name</source>
<target>Имя этого устройства</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
@ -4998,10 +5092,12 @@ It can happen because of some bug or when the connection is compromised.</source
</trans-unit>
<trans-unit id="This is your own SimpleX address!" xml:space="preserve">
<source>This is your own SimpleX address!</source>
<target>Это ваш собственный адрес SimpleX!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This is your own one-time link!" xml:space="preserve">
<source>This is your own one-time link!</source>
<target>Это ваша собственная одноразовая ссылка!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting applies to messages in your current chat profile **%@**." xml:space="preserve">
@ -5021,6 +5117,7 @@ It can happen because of some bug or when the connection is compromised.</source
</trans-unit>
<trans-unit id="To hide unwanted messages." xml:space="preserve">
<source>To hide unwanted messages.</source>
<target>Чтобы скрыть нежелательные сообщения.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve">
@ -5107,14 +5204,17 @@ You will be prompted to complete authentication before this feature is enabled.<
</trans-unit>
<trans-unit id="Unblock" xml:space="preserve">
<source>Unblock</source>
<target>Разблокировать</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member" xml:space="preserve">
<source>Unblock member</source>
<target>Разблокировать члена группы</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
<source>Unblock member?</source>
<target>Разблокировать члена группы?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unexpected error: %@" xml:space="preserve">
@ -5181,10 +5281,12 @@ To connect, please ask your contact to create another connection link and check
</trans-unit>
<trans-unit id="Unlink" xml:space="preserve">
<source>Unlink</source>
<target>Забыть</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unlink desktop?" xml:space="preserve">
<source>Unlink desktop?</source>
<target>Забыть компьютер?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unlock" xml:space="preserve">
@ -5279,6 +5381,7 @@ To connect, please ask your contact to create another connection link and check
</trans-unit>
<trans-unit id="Use from desktop" xml:space="preserve">
<source>Use from desktop</source>
<target>Использовать с компьютера</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use iOS call interface" xml:space="preserve">
@ -5313,10 +5416,12 @@ To connect, please ask your contact to create another connection link and check
</trans-unit>
<trans-unit id="Verify code with desktop" xml:space="preserve">
<source>Verify code with desktop</source>
<target>Сверьте код с компьютером</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify connection" xml:space="preserve">
<source>Verify connection</source>
<target>Проверить соединение</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify connection security" xml:space="preserve">
@ -5326,6 +5431,7 @@ To connect, please ask your contact to create another connection link and check
</trans-unit>
<trans-unit id="Verify connections" xml:space="preserve">
<source>Verify connections</source>
<target>Проверять соединения</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify security code" xml:space="preserve">
@ -5340,6 +5446,7 @@ To connect, please ask your contact to create another connection link and check
</trans-unit>
<trans-unit id="Via secure quantum resistant protocol." xml:space="preserve">
<source>Via secure quantum resistant protocol.</source>
<target>Через безопасный квантово-устойчивый протокол.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video call" xml:space="preserve">
@ -5392,6 +5499,10 @@ To connect, please ask your contact to create another connection link and check
<target>Голосовое сообщение…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>Ожидается прием файла</target>
@ -5494,31 +5605,39 @@ To connect, please ask your contact to create another connection link and check
</trans-unit>
<trans-unit id="You are already connecting to %@." xml:space="preserve">
<source>You are already connecting to %@.</source>
<target>Вы уже соединяетесь с %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already connecting via this one-time link!" xml:space="preserve">
<source>You are already connecting via this one-time link!</source>
<target>Вы уже соединяетесь по этой одноразовой ссылке!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already in group %@." xml:space="preserve">
<source>You are already in group %@.</source>
<target>Вы уже состоите в группе %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group %@." xml:space="preserve">
<source>You are already joining the group %@.</source>
<target>Вы уже вступаете в группу %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group via this link!" xml:space="preserve">
<source>You are already joining the group via this link!</source>
<target>Вы уже вступаете в группу по этой ссылке!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group via this link." xml:space="preserve">
<source>You are already joining the group via this link.</source>
<target>Вы уже вступаете в группу по этой ссылке.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group!&#10;Repeat join request?" xml:space="preserve">
<source>You are already joining the group!
Repeat join request?</source>
<target>Вы уже вступаете в группу!
Повторить запрос на вступление?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are connected to the server used to receive messages from this contact." xml:space="preserve">
@ -5618,11 +5737,14 @@ Repeat join request?</source>
</trans-unit>
<trans-unit id="You have already requested connection via this address!" xml:space="preserve">
<source>You have already requested connection via this address!</source>
<target>Вы уже запросили соединение через этот адрес!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You have already requested connection!&#10;Repeat connection request?" xml:space="preserve">
<source>You have already requested connection!
Repeat connection request?</source>
<target>Вы уже запросили соединение!
Повторить запрос?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You have no chats" xml:space="preserve">
@ -5677,6 +5799,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="You will be connected when group link host's device is online, please wait or check later!" xml:space="preserve">
<source>You will be connected when group link host's device is online, please wait or check later!</source>
<target>Соединение будет установлено, когда владелец ссылки группы будет онлайн. Пожалуйста, подождите или проверьте позже!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You will be connected when your connection request is accepted, please wait or check later!" xml:space="preserve">
@ -5696,6 +5819,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="You will connect to all group members." xml:space="preserve">
<source>You will connect to all group members.</source>
<target>Вы соединитесь со всеми членами группы.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You will still receive calls and notifications from muted profiles when they are active." xml:space="preserve">
@ -5819,6 +5943,7 @@ You can change it in Settings.</source>
</trans-unit>
<trans-unit id="Your profile" xml:space="preserve">
<source>Your profile</source>
<target>Ваш профиль</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
@ -5915,6 +6040,7 @@ SimpleX серверы не могут получить доступ к Ваше
</trans-unit>
<trans-unit id="and %lld other events" xml:space="preserve">
<source>and %lld other events</source>
<target>и %lld других событий</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="audio call (not e2e encrypted)" xml:space="preserve">
@ -5922,6 +6048,10 @@ SimpleX серверы не могут получить доступ к Ваше
<target>аудиозвонок (не e2e зашифрованный)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>ошибка ID сообщения</target>
@ -5934,6 +6064,7 @@ SimpleX серверы не могут получить доступ к Ваше
</trans-unit>
<trans-unit id="blocked" xml:space="preserve">
<source>blocked</source>
<target>заблокировано</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="bold" xml:space="preserve">
@ -6008,6 +6139,7 @@ SimpleX серверы не могут получить доступ к Ваше
</trans-unit>
<trans-unit id="connected directly" xml:space="preserve">
<source>connected directly</source>
<target>соединен(а) напрямую</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="connecting" xml:space="preserve">
@ -6107,6 +6239,7 @@ SimpleX серверы не могут получить доступ к Ваше
</trans-unit>
<trans-unit id="deleted contact" xml:space="preserve">
<source>deleted contact</source>
<target>удалил(а) контакт</target>
<note>rcv direct event chat item</note>
</trans-unit>
<trans-unit id="deleted group" xml:space="preserve">
@ -6473,6 +6606,7 @@ SimpleX серверы не могут получить доступ к Ваше
</trans-unit>
<trans-unit id="send direct message" xml:space="preserve">
<source>send direct message</source>
<target>отправьте сообщение</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="starting…" xml:space="preserve">
@ -6502,6 +6636,7 @@ SimpleX серверы не могут получить доступ к Ваше
</trans-unit>
<trans-unit id="v%@" xml:space="preserve">
<source>v%@</source>
<target>v%@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="v%@ (%@)" xml:space="preserve">
@ -6643,6 +6778,7 @@ SimpleX серверы не могут получить доступ к Ваше
</trans-unit>
<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>
<target>SimpleX использует доступ к локальной сети, чтобы разрешить использование профиля чата через компьютер в той же сети.</target>
<note>Privacy - Local Network Usage Description</note>
</trans-unit>
<trans-unit id="NSMicrophoneUsageDescription" xml:space="preserve">

View File

@ -1159,6 +1159,10 @@
<target>เชื่อมต่อ</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<note>No comment provided by engineer.</note>
@ -1844,8 +1848,8 @@ This cannot be undone!</source>
<source>Discover and join groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2476,6 +2480,10 @@ This cannot be undone!</source>
<target>สำหรับคอนโซล</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>อินเทอร์เฟซภาษาฝรั่งเศส</target>
@ -3421,6 +3429,10 @@ This is your link for group %@!</source>
<target>ไม่มีไฟล์ที่ได้รับหรือส่ง</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>การแจ้งเตือน</target>
@ -5354,6 +5366,10 @@ To connect, please ask your contact to create another connection link and check
<target>ข้อความเสียง…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>กำลังรอไฟล์</target>
@ -5882,6 +5898,10 @@ SimpleX servers cannot see your profile.</source>
<target>การโทรด้วยเสียง (ไม่ได้ encrypt จากต้นจนจบ)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>ID ข้อความที่ไม่ดี</target>

View File

@ -1166,6 +1166,10 @@
<target>Підключіться</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>Підключайтеся інкогніто</target>
@ -1854,8 +1858,8 @@ This cannot be undone!</source>
<source>Discover and join groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2486,6 +2490,10 @@ This cannot be undone!</source>
<target>Для консолі</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>Французький інтерфейс</target>
@ -3435,6 +3443,10 @@ This is your link for group %@!</source>
<target>Немає отриманих або відправлених файлів</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>Сповіщення</target>
@ -5378,6 +5390,10 @@ To connect, please ask your contact to create another connection link and check
<target>Голосове повідомлення…</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>Очікування файлу</target>
@ -5908,6 +5924,10 @@ SimpleX servers cannot see your profile.</source>
<target>аудіовиклик (без шифрування e2e)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>невірний ідентифікатор повідомлення</target>

View File

@ -1172,6 +1172,10 @@
<target>连接</target>
<note>server test step</note>
</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">
<source>Connect incognito</source>
<target>在隐身状态下连接</target>
@ -1862,8 +1866,8 @@ This cannot be undone!</source>
<target>发现和加入群组</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover on network" xml:space="preserve">
<source>Discover on network</source>
<trans-unit id="Discover via local network" xml:space="preserve">
<source>Discover via local network</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@ -2499,6 +2503,10 @@ This cannot be undone!</source>
<target>用于控制台</target>
<note>No comment provided by engineer.</note>
</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">
<source>French interface</source>
<target>法语界面</target>
@ -3449,6 +3457,10 @@ This is your link for group %@!</source>
<target>未收到或发送文件</target>
<note>No comment provided by engineer.</note>
</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">
<source>Notifications</source>
<target>通知</target>
@ -5396,6 +5408,10 @@ To connect, please ask your contact to create another connection link and check
<target>语音消息……</target>
<note>No comment provided by engineer.</note>
</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">
<source>Waiting for file</source>
<target>等待文件中</target>
@ -5926,6 +5942,10 @@ SimpleX 服务器无法看到您的资料。</target>
<target>语音通话(非端到端加密)</target>
<note>No comment provided by engineer.</note>
</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">
<source>bad message ID</source>
<target>错误消息 ID</target>

View File

@ -609,7 +609,7 @@ public enum ChatResponse: Decodable, Error {
case contactConnectionDeleted(user: UserRef, connection: PendingContactConnection)
// remote desktop responses/events
case remoteCtrlList(remoteCtrls: [RemoteCtrlInfo])
case remoteCtrlFound(remoteCtrl: RemoteCtrlInfo)
case remoteCtrlFound(remoteCtrl: RemoteCtrlInfo, ctrlAppInfo_: CtrlAppInfo?, appVersion: String, compatible: Bool)
case remoteCtrlConnecting(remoteCtrl_: RemoteCtrlInfo?, ctrlAppInfo: CtrlAppInfo, appVersion: String)
case remoteCtrlSessionCode(remoteCtrl_: RemoteCtrlInfo?, sessionCode: String)
case remoteCtrlConnected(remoteCtrl: RemoteCtrlInfo)
@ -903,7 +903,7 @@ public enum ChatResponse: Decodable, Error {
case let .newContactConnection(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 .remoteCtrlFound(remoteCtrl): return String(describing: remoteCtrl)
case let .remoteCtrlFound(remoteCtrl, ctrlAppInfo_, appVersion, compatible): return "remoteCtrl:\n\(String(describing: remoteCtrl))\nctrlAppInfo_:\n\(String(describing: ctrlAppInfo_))\nappVersion: \(appVersion)\ncompatible: \(compatible)"
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 .remoteCtrlConnected(remoteCtrl): return String(describing: remoteCtrl)
@ -1546,6 +1546,7 @@ public struct RemoteCtrlInfo: Decodable {
public enum RemoteCtrlSessionState: Decodable {
case starting
case searching
case connecting
case pendingConfirmation(sessionCode: String)
case connected(sessionCode: String)

View File

@ -25,6 +25,9 @@
/* No comment provided by engineer. */
"- more stable message delivery.\n- a bit better groups.\n- and more!" = "- stabilere Zustellung von Nachrichten.\n- ein bisschen verbesserte Gruppen.\n- und mehr!";
/* No comment provided by engineer. */
"- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- Optionale Benachrichtigung von gelöschten Kontakten.\n- Profilnamen mit Leerzeichen.\n- Und mehr!";
/* No comment provided by engineer. */
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- Bis zu 5 Minuten lange Sprachnachrichten.\n- Zeitdauer für verschwindende Nachrichten anpassen.\n- Nachrichten-Historie bearbeiten.";
@ -43,6 +46,12 @@
/* No comment provided by engineer. */
"(" = "(";
/* No comment provided by engineer. */
"(new)" = "(Neu)";
/* No comment provided by engineer. */
"(this device v%@)" = "(Dieses Gerät hat v%@)";
/* No comment provided by engineer. */
")" = ")";
@ -548,6 +557,9 @@
/* No comment provided by engineer. */
"Back" = "Zurück";
/* No comment provided by engineer. */
"Bad desktop address" = "Falsche Desktop-Adresse";
/* integrity error chat item */
"bad message hash" = "Ungültiger Nachrichten-Hash";
@ -560,12 +572,18 @@
/* No comment provided by engineer. */
"Bad message ID" = "Falsche Nachrichten-ID";
/* No comment provided by engineer. */
"Better groups" = "Bessere Gruppen";
/* No comment provided by engineer. */
"Better messages" = "Verbesserungen bei Nachrichten";
/* No comment provided by engineer. */
"Block" = "Blockieren";
/* No comment provided by engineer. */
"Block group members" = "Gruppenmitglieder blockieren";
/* No comment provided by engineer. */
"Block member" = "Mitglied blockieren";
@ -771,6 +789,9 @@
/* No comment provided by engineer. */
"Connect incognito" = "Inkognito verbinden";
/* No comment provided by engineer. */
"Connect to desktop" = "Mit dem Desktop verbinden";
/* No comment provided by engineer. */
"connect to SimpleX Chat developers." = "Mit den SimpleX Chat-Entwicklern verbinden.";
@ -801,9 +822,15 @@
/* No comment provided by engineer. */
"connected" = "Verbunden";
/* No comment provided by engineer. */
"Connected desktop" = "Verbundener Desktop";
/* rcv group event chat item */
"connected directly" = "Direkt miteinander verbunden";
/* No comment provided by engineer. */
"Connected to desktop" = "Mit dem Desktop verbunden";
/* No comment provided by engineer. */
"connecting" = "verbinde";
@ -828,6 +855,9 @@
/* No comment provided by engineer. */
"Connecting server… (error: %@)" = "Mit dem Server verbinden… (Fehler: %@)";
/* No comment provided by engineer. */
"Connecting to desktop" = "Mit dem Desktop verbinden";
/* chat list item title */
"connecting…" = "Verbinde…";
@ -846,6 +876,9 @@
/* No comment provided by engineer. */
"Connection request sent!" = "Verbindungsanfrage wurde gesendet!";
/* No comment provided by engineer. */
"Connection terminated" = "Verbindung beendet";
/* No comment provided by engineer. */
"Connection timeout" = "Verbindungszeitüberschreitung";
@ -900,6 +933,9 @@
/* No comment provided by engineer. */
"Create" = "Erstellen";
/* No comment provided by engineer. */
"Create a group using a random profile." = "Erstellen Sie eine Gruppe mit einem zufälligen Profil.";
/* No comment provided by engineer. */
"Create an address to let people connect with you." = "Erstellen Sie eine Adresse, damit sich Personen mit Ihnen verbinden können.";
@ -1173,6 +1209,15 @@
/* No comment provided by engineer. */
"Description" = "Beschreibung";
/* No comment provided by engineer. */
"Desktop address" = "Desktop-Adresse";
/* No comment provided by engineer. */
"Desktop app version %@ is not compatible with this app." = "Desktop App-Version %@ ist mit dieser App nicht kompatibel.";
/* No comment provided by engineer. */
"Desktop devices" = "Desktop-Geräte";
/* No comment provided by engineer. */
"Develop" = "Entwicklung";
@ -1236,6 +1281,9 @@
/* server test step */
"Disconnect" = "Trennen";
/* No comment provided by engineer. */
"Disconnect desktop?" = "Desktop-Verbindung trennen?";
/* No comment provided by engineer. */
"Discover and join groups" = "Gruppen entdecken und ihnen beitreten";
@ -1374,6 +1422,12 @@
/* chat item text */
"encryption re-negotiation allowed for %@" = "Neuaushandlung der Verschlüsselung von %@ erlaubt";
/* message decrypt error item */
"Encryption re-negotiation error" = "Fehler bei der Neuverhandlung der Verschlüsselung";
/* No comment provided by engineer. */
"Encryption re-negotiation failed." = "Neuverhandlung der Verschlüsselung fehlgeschlagen.";
/* chat item text */
"encryption re-negotiation required" = "Neuaushandlung der Verschlüsselung notwendig";
@ -1404,6 +1458,9 @@
/* No comment provided by engineer. */
"Enter server manually" = "Geben Sie den Server manuell ein";
/* No comment provided by engineer. */
"Enter this device name…" = "Geben Sie diesen Gerätenamen ein…";
/* placeholder */
"Enter welcome message…" = "Geben Sie eine Begrüßungsmeldung ein …";
@ -1605,6 +1662,9 @@
/* No comment provided by engineer. */
"Fast and no wait until the sender is online!" = "Schnell und ohne warten auf den Absender, bis er online ist!";
/* No comment provided by engineer. */
"Faster joining and more reliable messages." = "Schnellerer Gruppenbeitritt und zuverlässigere Nachrichtenzustellung.";
/* No comment provided by engineer. */
"Favorite" = "Favorit";
@ -1866,6 +1926,9 @@
/* No comment provided by engineer. */
"Incognito" = "Inkognito";
/* No comment provided by engineer. */
"Incognito groups" = "Inkognito-Gruppen";
/* No comment provided by engineer. */
"Incognito mode" = "Inkognito-Modus";
@ -1893,6 +1956,9 @@
/* No comment provided by engineer. */
"Incompatible database version" = "Inkompatible Datenbank-Version";
/* No comment provided by engineer. */
"Incompatible version" = "Inkompatible Version";
/* PIN entry */
"Incorrect passcode" = "Zugangscode ist falsch";
@ -2028,6 +2094,9 @@
/* No comment provided by engineer. */
"Joining group" = "Der Gruppe beitreten";
/* No comment provided by engineer. */
"Keep the app open to use it from desktop" = "Die App muss geöffnet bleiben, um sie vom Desktop aus nutzen zu können";
/* No comment provided by engineer. */
"Keep your connections" = "Ihre Verbindungen beibehalten";
@ -2064,6 +2133,15 @@
/* No comment provided by engineer. */
"Limitations" = "Einschränkungen";
/* No comment provided by engineer. */
"Link mobile and desktop apps! 🔗" = "Verknüpfe Mobiltelefon- und Desktop-Apps! 🔗";
/* No comment provided by engineer. */
"Linked desktop options" = "Verknüpfte Desktop-Optionen";
/* No comment provided by engineer. */
"Linked desktops" = "Verknüpfte Desktops";
/* No comment provided by engineer. */
"LIVE" = "LIVE";
@ -2462,6 +2540,9 @@
/* No comment provided by engineer. */
"Paste" = "Einfügen";
/* No comment provided by engineer. */
"Paste desktop address" = "Desktop-Adresse einfügen";
/* No comment provided by engineer. */
"Paste image" = "Bild einfügen";
@ -2846,6 +2927,9 @@
/* No comment provided by engineer. */
"Scan QR code" = "QR-Code scannen";
/* No comment provided by engineer. */
"Scan QR code from desktop" = "Den QR-Code vom Desktop scannen";
/* No comment provided by engineer. */
"Scan security code from your contact's app." = "Scannen Sie den Sicherheitscode von der App Ihres Kontakts.";
@ -2990,6 +3074,9 @@
/* No comment provided by engineer. */
"Servers" = "Server";
/* No comment provided by engineer. */
"Session code" = "Sitzungscode";
/* No comment provided by engineer. */
"Set 1 day" = "Einen Tag festlegen";
@ -3299,6 +3386,9 @@
/* notification title */
"this contact" = "Dieser Kontakt";
/* No comment provided by engineer. */
"This device name" = "Dieser Gerätename";
/* No comment provided by engineer. */
"This group has over %lld members, delivery receipts are not sent." = "Es werden keine Empfangsbestätigungen gesendet, da diese Gruppe über %lld Mitglieder hat.";
@ -3320,6 +3410,9 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "Um eine Verbindung herzustellen, kann Ihr Kontakt den QR-Code scannen oder den Link in der App verwenden.";
/* No comment provided by engineer. */
"To hide unwanted messages." = "Um unerwünschte Nachrichten zu verbergen.";
/* No comment provided by engineer. */
"To make a new connection" = "Um eine Verbindung mit einem neuen Kontakt zu erstellen";
@ -3416,6 +3509,12 @@
/* No comment provided by engineer. */
"Unless your contact deleted the connection or this link was already used, it might be a bug - please report it.\nTo connect, please ask your contact to create another connection link and check that you have a stable network connection." = "Entweder hat Ihr Kontakt die Verbindung gelöscht, oder dieser Link wurde bereits verwendet, es könnte sich um einen Fehler handeln - Bitte melden Sie es uns.\nBitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um sich neu verbinden zu können und stellen Sie sicher, dass Sie eine stabile Netzwerk-Verbindung haben.";
/* No comment provided by engineer. */
"Unlink" = "Entkoppeln";
/* No comment provided by engineer. */
"Unlink desktop?" = "Desktop entkoppeln?";
/* No comment provided by engineer. */
"Unlock" = "Entsperren";
@ -3470,6 +3569,9 @@
/* No comment provided by engineer. */
"Use for new connections" = "Für neue Verbindungen nutzen";
/* No comment provided by engineer. */
"Use from desktop" = "Vom Desktop aus nutzen";
/* No comment provided by engineer. */
"Use iOS call interface" = "iOS Anrufschnittstelle nutzen";
@ -3491,12 +3593,24 @@
/* No comment provided by engineer. */
"Using SimpleX Chat servers." = "Verwendung von SimpleX-Chat-Servern.";
/* No comment provided by engineer. */
"v%@" = "v%@";
/* No comment provided by engineer. */
"v%@ (%@)" = "v%@ (%@)";
/* No comment provided by engineer. */
"Verify code with desktop" = "Code mit dem Desktop überprüfen";
/* No comment provided by engineer. */
"Verify connection" = "Verbindung überprüfen";
/* No comment provided by engineer. */
"Verify connection security" = "Sicherheit der Verbindung überprüfen";
/* No comment provided by engineer. */
"Verify connections" = "Verbindungen überprüfen";
/* No comment provided by engineer. */
"Verify security code" = "Sicherheitscode überprüfen";
@ -3515,6 +3629,9 @@
/* No comment provided by engineer. */
"via relay" = "über Relais";
/* No comment provided by engineer. */
"Via secure quantum resistant protocol." = "Über ein sicheres quantenbeständiges Protokoll.";
/* No comment provided by engineer. */
"Video call" = "Videoanruf";

View File

@ -7,6 +7,9 @@
/* Privacy - Face ID Usage Description */
"NSFaceIDUsageDescription" = "Face ID wird von SimpleX für die lokale Authentifizierung genutzt";
/* Privacy - Local Network Usage Description */
"NSLocalNetworkUsageDescription" = "SimpleX nutzt den lokalen Netzwerkzugriff, um die Nutzung von Benutzer-Chatprofilen über eine Desktop-App im gleichen Netzwerk zu erlauben.";
/* Privacy - Microphone Usage Description */
"NSMicrophoneUsageDescription" = "SimpleX benötigt Zugriff auf das Mikrofon, um Audio- und Videoanrufe und die Aufnahme von Sprachnachrichten zu ermöglichen.";

View File

@ -25,6 +25,9 @@
/* No comment provided by engineer. */
"- more stable message delivery.\n- a bit better groups.\n- and more!" = "- une diffusion plus stable des messages.\n- des groupes un peu plus performants.\n- et bien d'autres choses encore !";
/* No comment provided by engineer. */
"- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- option pour notifier les contacts supprimés.\n- noms de profil avec espaces.\n- et plus encore !";
/* No comment provided by engineer. */
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- messages vocaux pouvant durer jusqu'à 5 minutes.\n- délai personnalisé de disparition.\n- l'historique de modification.";
@ -43,6 +46,12 @@
/* No comment provided by engineer. */
"(" = "(";
/* No comment provided by engineer. */
"(new)" = "(nouveau)";
/* No comment provided by engineer. */
"(this device v%@)" = "(cet appareil v%@)";
/* No comment provided by engineer. */
")" = ")";
@ -548,6 +557,9 @@
/* No comment provided by engineer. */
"Back" = "Retour";
/* No comment provided by engineer. */
"Bad desktop address" = "Mauvaise adresse de bureau";
/* integrity error chat item */
"bad message hash" = "hash de message incorrect";
@ -560,12 +572,18 @@
/* No comment provided by engineer. */
"Bad message ID" = "Mauvais ID de message";
/* No comment provided by engineer. */
"Better groups" = "Des groupes plus performants";
/* No comment provided by engineer. */
"Better messages" = "Meilleurs messages";
/* No comment provided by engineer. */
"Block" = "Bloquer";
/* No comment provided by engineer. */
"Block group members" = "Bloquer des membres d'un groupe";
/* No comment provided by engineer. */
"Block member" = "Bloquer ce membre";
@ -771,6 +789,9 @@
/* No comment provided by engineer. */
"Connect incognito" = "Se connecter incognito";
/* No comment provided by engineer. */
"Connect to desktop" = "Se connecter au bureau";
/* No comment provided by engineer. */
"connect to SimpleX Chat developers." = "se connecter aux developpeurs de SimpleX Chat.";
@ -801,9 +822,15 @@
/* No comment provided by engineer. */
"connected" = "connecté";
/* No comment provided by engineer. */
"Connected desktop" = "Bureau connecté";
/* rcv group event chat item */
"connected directly" = "s'est connecté.e de manière directe";
/* No comment provided by engineer. */
"Connected to desktop" = "Connecté au bureau";
/* No comment provided by engineer. */
"connecting" = "connexion";
@ -828,6 +855,9 @@
/* No comment provided by engineer. */
"Connecting server… (error: %@)" = "Connexion au serveur… (erreur : %@)";
/* No comment provided by engineer. */
"Connecting to desktop" = "Connexion au bureau";
/* chat list item title */
"connecting…" = "connexion…";
@ -846,6 +876,9 @@
/* No comment provided by engineer. */
"Connection request sent!" = "Demande de connexion envoyée !";
/* No comment provided by engineer. */
"Connection terminated" = "Connexion terminée";
/* No comment provided by engineer. */
"Connection timeout" = "Délai de connexion";
@ -900,6 +933,9 @@
/* No comment provided by engineer. */
"Create" = "Créer";
/* No comment provided by engineer. */
"Create a group using a random profile." = "Création de groupes via un profil aléatoire.";
/* No comment provided by engineer. */
"Create an address to let people connect with you." = "Créez une adresse pour permettre aux gens de vous contacter.";
@ -1173,6 +1209,15 @@
/* No comment provided by engineer. */
"Description" = "Description";
/* No comment provided by engineer. */
"Desktop address" = "Adresse de bureau";
/* No comment provided by engineer. */
"Desktop app version %@ is not compatible with this app." = "La version de l'application de bureau %@ n'est pas compatible avec cette application.";
/* No comment provided by engineer. */
"Desktop devices" = "Appareils de bureau";
/* No comment provided by engineer. */
"Develop" = "Développer";
@ -1236,6 +1281,9 @@
/* server test step */
"Disconnect" = "Se déconnecter";
/* No comment provided by engineer. */
"Disconnect desktop?" = "Déconnecter le bureau ?";
/* No comment provided by engineer. */
"Discover and join groups" = "Découvrir et rejoindre des groupes";
@ -1374,6 +1422,12 @@
/* chat item text */
"encryption re-negotiation allowed for %@" = "renégociation de chiffrement autorisée pour %@";
/* message decrypt error item */
"Encryption re-negotiation error" = "Erreur lors de la renégociation du chiffrement";
/* No comment provided by engineer. */
"Encryption re-negotiation failed." = "La renégociation du chiffrement a échoué.";
/* chat item text */
"encryption re-negotiation required" = "renégociation de chiffrement requise";
@ -1404,6 +1458,9 @@
/* No comment provided by engineer. */
"Enter server manually" = "Entrer un serveur manuellement";
/* No comment provided by engineer. */
"Enter this device name…" = "Entrez le nom de l'appareil…";
/* placeholder */
"Enter welcome message…" = "Entrez un message de bienvenue…";
@ -1605,6 +1662,9 @@
/* No comment provided by engineer. */
"Fast and no wait until the sender is online!" = "Rapide et ne nécessitant pas d'attendre que l'expéditeur soit en ligne !";
/* No comment provided by engineer. */
"Faster joining and more reliable messages." = "Connexion plus rapide et messages plus fiables.";
/* No comment provided by engineer. */
"Favorite" = "Favoris";
@ -1866,6 +1926,9 @@
/* No comment provided by engineer. */
"Incognito" = "Incognito";
/* No comment provided by engineer. */
"Incognito groups" = "Groupes incognito";
/* No comment provided by engineer. */
"Incognito mode" = "Mode Incognito";
@ -1893,6 +1956,9 @@
/* No comment provided by engineer. */
"Incompatible database version" = "Version de la base de données incompatible";
/* No comment provided by engineer. */
"Incompatible version" = "Version incompatible";
/* PIN entry */
"Incorrect passcode" = "Code d'accès erroné";
@ -2028,6 +2094,9 @@
/* No comment provided by engineer. */
"Joining group" = "Entrain de rejoindre le groupe";
/* No comment provided by engineer. */
"Keep the app open to use it from desktop" = "Garder l'application ouverte pour l'utiliser depuis le bureau";
/* No comment provided by engineer. */
"Keep your connections" = "Conserver vos connexions";
@ -2064,6 +2133,15 @@
/* No comment provided by engineer. */
"Limitations" = "Limitations";
/* No comment provided by engineer. */
"Link mobile and desktop apps! 🔗" = "Liez vos applications mobiles et de bureau ! 🔗";
/* No comment provided by engineer. */
"Linked desktop options" = "Options de bureau lié";
/* No comment provided by engineer. */
"Linked desktops" = "Bureaux liés";
/* No comment provided by engineer. */
"LIVE" = "LIVE";
@ -2462,6 +2540,9 @@
/* No comment provided by engineer. */
"Paste" = "Coller";
/* No comment provided by engineer. */
"Paste desktop address" = "Coller l'adresse du bureau";
/* No comment provided by engineer. */
"Paste image" = "Coller l'image";
@ -2846,6 +2927,9 @@
/* No comment provided by engineer. */
"Scan QR code" = "Scanner un code QR";
/* No comment provided by engineer. */
"Scan QR code from desktop" = "Scanner le code QR du bureau";
/* No comment provided by engineer. */
"Scan security code from your contact's app." = "Scannez le code de sécurité depuis l'application de votre contact.";
@ -2990,6 +3074,9 @@
/* No comment provided by engineer. */
"Servers" = "Serveurs";
/* No comment provided by engineer. */
"Session code" = "Code de session";
/* No comment provided by engineer. */
"Set 1 day" = "Définir 1 jour";
@ -3299,6 +3386,9 @@
/* notification title */
"this contact" = "ce contact";
/* No comment provided by engineer. */
"This device name" = "Ce nom d'appareil";
/* No comment provided by engineer. */
"This group has over %lld members, delivery receipts are not sent." = "Ce groupe compte plus de %lld membres, les accusés de réception ne sont pas envoyés.";
@ -3320,6 +3410,9 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "Pour se connecter, votre contact peut scanner le code QR ou utiliser le lien dans l'application.";
/* No comment provided by engineer. */
"To hide unwanted messages." = "Pour cacher les messages indésirables.";
/* No comment provided by engineer. */
"To make a new connection" = "Pour établir une nouvelle connexion";
@ -3416,6 +3509,12 @@
/* No comment provided by engineer. */
"Unless your contact deleted the connection or this link was already used, it might be a bug - please report it.\nTo connect, please ask your contact to create another connection link and check that you have a stable network connection." = "A moins que votre contact ait supprimé la connexion ou que ce lien ait déjà été utilisé, il peut s'agir d'un bug - veuillez le signaler.\nPour vous connecter, veuillez demander à votre contact de créer un autre lien de connexion et vérifiez que vous disposez d'une connexion réseau stable.";
/* No comment provided by engineer. */
"Unlink" = "Délier";
/* No comment provided by engineer. */
"Unlink desktop?" = "Délier le bureau ?";
/* No comment provided by engineer. */
"Unlock" = "Déverrouiller";
@ -3470,6 +3569,9 @@
/* No comment provided by engineer. */
"Use for new connections" = "Utiliser pour les nouvelles connexions";
/* No comment provided by engineer. */
"Use from desktop" = "Utilisation depuis le bureau";
/* No comment provided by engineer. */
"Use iOS call interface" = "Utiliser l'interface d'appel d'iOS";
@ -3491,12 +3593,24 @@
/* No comment provided by engineer. */
"Using SimpleX Chat servers." = "Utilisation des serveurs SimpleX Chat.";
/* No comment provided by engineer. */
"v%@" = "v%@";
/* No comment provided by engineer. */
"v%@ (%@)" = "v%@ (%@)";
/* No comment provided by engineer. */
"Verify code with desktop" = "Vérifier le code avec le bureau";
/* No comment provided by engineer. */
"Verify connection" = "Vérifier la connexion";
/* No comment provided by engineer. */
"Verify connection security" = "Vérifier la sécurité de la connexion";
/* No comment provided by engineer. */
"Verify connections" = "Vérifier les connexions";
/* No comment provided by engineer. */
"Verify security code" = "Vérifier le code de sécurité";
@ -3515,6 +3629,9 @@
/* No comment provided by engineer. */
"via relay" = "via relais";
/* No comment provided by engineer. */
"Via secure quantum resistant protocol." = "Via un protocole sécurisé de cryptographie post-quantique.";
/* No comment provided by engineer. */
"Video call" = "Appel vidéo";

View File

@ -7,6 +7,9 @@
/* Privacy - Face ID Usage Description */
"NSFaceIDUsageDescription" = "SimpleGroup not found!X utilise Face ID pour l'authentification locale";
/* Privacy - Local Network Usage Description */
"NSLocalNetworkUsageDescription" = "SimpleX utilise un accès au réseau local pour permettre l'utilisation du profil de chat de l'utilisateur via l'application de bureau au sein de ce même réseau.";
/* Privacy - Microphone Usage Description */
"NSMicrophoneUsageDescription" = "SimpleX a besoin d'un accès au microphone pour les appels audio et vidéo ainsi que pour enregistrer des messages vocaux.";

View File

@ -25,6 +25,9 @@
/* No comment provided by engineer. */
"- more stable message delivery.\n- a bit better groups.\n- and more!" = "- recapito dei messaggi più stabile.\n- gruppi un po' migliorati.\n- e altro ancora!";
/* No comment provided by engineer. */
"- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- avvisa facoltativamente i contatti eliminati.\n- nomi del profilo con spazi.\n- e molto altro!";
/* No comment provided by engineer. */
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- messaggi vocali fino a 5 minuti.\n- tempo di scomparsa personalizzato.\n- cronologia delle modifiche.";
@ -569,12 +572,18 @@
/* No comment provided by engineer. */
"Bad message ID" = "ID del messaggio errato";
/* No comment provided by engineer. */
"Better groups" = "Gruppi migliorati";
/* No comment provided by engineer. */
"Better messages" = "Messaggi migliorati";
/* No comment provided by engineer. */
"Block" = "Blocca";
/* No comment provided by engineer. */
"Block group members" = "Blocca i membri dei gruppi";
/* No comment provided by engineer. */
"Block member" = "Blocca membro";
@ -924,6 +933,9 @@
/* No comment provided by engineer. */
"Create" = "Crea";
/* No comment provided by engineer. */
"Create a group using a random profile." = "Crea un gruppo usando un profilo casuale.";
/* No comment provided by engineer. */
"Create an address to let people connect with you." = "Crea un indirizzo per consentire alle persone di connettersi con te.";
@ -1275,9 +1287,6 @@
/* No comment provided by engineer. */
"Discover and join groups" = "Scopri ed unisciti ai gruppi";
/* No comment provided by engineer. */
"Discover on network" = "Trova nella rete";
/* No comment provided by engineer. */
"Do it later" = "Fallo dopo";
@ -1653,6 +1662,9 @@
/* No comment provided by engineer. */
"Fast and no wait until the sender is online!" = "Veloce e senza aspettare che il mittente sia in linea!";
/* No comment provided by engineer. */
"Faster joining and more reliable messages." = "Ingresso più veloce e messaggi più affidabili.";
/* No comment provided by engineer. */
"Favorite" = "Preferito";
@ -1914,6 +1926,9 @@
/* No comment provided by engineer. */
"Incognito" = "Incognito";
/* No comment provided by engineer. */
"Incognito groups" = "Gruppi in incognito";
/* No comment provided by engineer. */
"Incognito mode" = "Modalità incognito";
@ -2118,6 +2133,9 @@
/* No comment provided by engineer. */
"Limitations" = "Limitazioni";
/* No comment provided by engineer. */
"Link mobile and desktop apps! 🔗" = "Collega le app mobile e desktop! 🔗";
/* No comment provided by engineer. */
"Linked desktop options" = "Opzioni del desktop collegato";
@ -3392,6 +3410,9 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "Per connettervi, il tuo contatto può scansionare il codice QR o usare il link nell'app.";
/* No comment provided by engineer. */
"To hide unwanted messages." = "Per nascondere messaggi indesiderati.";
/* No comment provided by engineer. */
"To make a new connection" = "Per creare una nuova connessione";
@ -3608,6 +3629,9 @@
/* No comment provided by engineer. */
"via relay" = "via relay";
/* No comment provided by engineer. */
"Via secure quantum resistant protocol." = "Tramite protocollo sicuro resistente alla quantistica.";
/* No comment provided by engineer. */
"Video call" = "Videochiamata";

View File

@ -25,6 +25,9 @@
/* No comment provided by engineer. */
"- more stable message delivery.\n- a bit better groups.\n- and more!" = "- stabielere berichtbezorging.\n- een beetje betere groepen.\n- en meer!";
/* No comment provided by engineer. */
"- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- optioneel verwijderde contacten op de hoogte stellen.\n- profielnamen met spaties.\n- en meer!";
/* No comment provided by engineer. */
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- spraakberichten tot 5 minuten.\n- aangepaste tijd om te verdwijnen.\n- bewerkingsgeschiedenis.";
@ -569,12 +572,18 @@
/* No comment provided by engineer. */
"Bad message ID" = "Onjuiste bericht-ID";
/* No comment provided by engineer. */
"Better groups" = "Betere groepen";
/* No comment provided by engineer. */
"Better messages" = "Betere berichten";
/* No comment provided by engineer. */
"Block" = "Blokkeren";
/* No comment provided by engineer. */
"Block group members" = "Groepsleden blokkeren";
/* No comment provided by engineer. */
"Block member" = "Lid blokkeren";
@ -924,6 +933,9 @@
/* No comment provided by engineer. */
"Create" = "Maak";
/* No comment provided by engineer. */
"Create a group using a random profile." = "Maak een groep met een willekeurig profiel.";
/* No comment provided by engineer. */
"Create an address to let people connect with you." = "Maak een adres aan zodat mensen contact met je kunnen opnemen.";
@ -1275,9 +1287,6 @@
/* No comment provided by engineer. */
"Discover and join groups" = "Ontdek en sluit je aan bij groepen";
/* No comment provided by engineer. */
"Discover on network" = "Ontdek via netwerk";
/* No comment provided by engineer. */
"Do it later" = "Doe het later";
@ -1653,6 +1662,9 @@
/* No comment provided by engineer. */
"Fast and no wait until the sender is online!" = "Snel en niet wachten tot de afzender online is!";
/* No comment provided by engineer. */
"Faster joining and more reliable messages." = "Snellere deelname en betrouwbaardere berichten.";
/* No comment provided by engineer. */
"Favorite" = "Favoriet";
@ -1914,6 +1926,9 @@
/* No comment provided by engineer. */
"Incognito" = "Incognito";
/* No comment provided by engineer. */
"Incognito groups" = "Incognitogroepen";
/* No comment provided by engineer. */
"Incognito mode" = "Incognito modus";
@ -2118,6 +2133,9 @@
/* No comment provided by engineer. */
"Limitations" = "Beperkingen";
/* No comment provided by engineer. */
"Link mobile and desktop apps! 🔗" = "Koppel mobiele en desktop-apps! 🔗";
/* No comment provided by engineer. */
"Linked desktop options" = "Gekoppelde desktop opties";
@ -3392,6 +3410,9 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "Om verbinding te maken, kan uw contact de QR-code scannen of de link in de app gebruiken.";
/* No comment provided by engineer. */
"To hide unwanted messages." = "Om ongewenste berichten te verbergen.";
/* No comment provided by engineer. */
"To make a new connection" = "Om een nieuwe verbinding te maken";
@ -3608,6 +3629,9 @@
/* No comment provided by engineer. */
"via relay" = "via relais";
/* No comment provided by engineer. */
"Via secure quantum resistant protocol." = "Via een beveiligd kwantumbestendig protocol.";
/* No comment provided by engineer. */
"Video call" = "video oproep";

View File

@ -25,6 +25,9 @@
/* No comment provided by engineer. */
"- more stable message delivery.\n- a bit better groups.\n- and more!" = "- более стабильная доставка сообщений.\n- немного улучшенные группы.\n- и прочее!";
/* No comment provided by engineer. */
"- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- опционально уведомляйте удалённые контакты.\n- имена профилей с пробелами.\n- и прочее!";
/* No comment provided by engineer. */
"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- голосовые сообщения до 5 минут.\n- настройка времени исчезающих сообщений.\n- история редактирования.";
@ -43,6 +46,12 @@
/* No comment provided by engineer. */
"(" = "(";
/* No comment provided by engineer. */
"(new)" = "(новое)";
/* No comment provided by engineer. */
"(this device v%@)" = "(это устройство v%@)";
/* No comment provided by engineer. */
")" = ")";
@ -118,12 +127,18 @@
/* No comment provided by engineer. */
"%@ %@" = "%@ %@";
/* No comment provided by engineer. */
"%@ and %@" = "%@ и %@";
/* No comment provided by engineer. */
"%@ and %@ connected" = "%@ и %@ соединены";
/* copied message info, <sender> at <time> */
"%@ at %@:" = "%1$@ в %2$@:";
/* No comment provided by engineer. */
"%@ connected" = "%@ соединен(а)";
/* notification title */
"%@ is connected!" = "Установлено соединение с %@!";
@ -139,6 +154,9 @@
/* notification title */
"%@ wants to connect!" = "%@ хочет соединиться!";
/* No comment provided by engineer. */
"%@, %@ and %lld members" = "%@, %@ и %lld членов группы";
/* No comment provided by engineer. */
"%@, %@ and %lld other members connected" = "%@, %@ и %lld других членов соединены";
@ -178,9 +196,21 @@
/* No comment provided by engineer. */
"%lld file(s) with total size of %@" = "%lld файл(ов) общим размером %@";
/* No comment provided by engineer. */
"%lld group events" = "%lld событий";
/* No comment provided by engineer. */
"%lld members" = "Членов группы: %lld";
/* No comment provided by engineer. */
"%lld messages blocked" = "%lld сообщений заблокировано";
/* No comment provided by engineer. */
"%lld messages marked deleted" = "%lld сообщений помечено удалёнными";
/* No comment provided by engineer. */
"%lld messages moderated by %@" = "%lld сообщений модерировано членом %@";
/* No comment provided by engineer. */
"%lld minutes" = "%lld минуты";
@ -229,6 +259,9 @@
/* No comment provided by engineer. */
"~strike~" = "\\~зачеркнуть~";
/* time to disappear */
"0 sec" = "0 сек";
/* No comment provided by engineer. */
"0s" = "0с";
@ -371,6 +404,9 @@
/* No comment provided by engineer. */
"All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Все сообщения будут удалены - это действие нельзя отменить! Сообщения будут удалены только для Вас.";
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Все новые сообщения от %@ будут скрыты!";
/* No comment provided by engineer. */
"All your contacts will remain connected." = "Все контакты, которые соединились через этот адрес, сохранятся.";
@ -434,6 +470,12 @@
/* No comment provided by engineer. */
"Already connected?" = "Соединение уже установлено?";
/* No comment provided by engineer. */
"Already connecting!" = "Уже соединяется!";
/* No comment provided by engineer. */
"Already joining the group!" = "Вступление в группу уже начато!";
/* pref value */
"always" = "всегда";
@ -443,6 +485,9 @@
/* No comment provided by engineer. */
"An empty chat profile with the provided name is created, and the app opens as usual." = "Будет создан пустой профиль чата с указанным именем, и приложение откроется в обычном режиме.";
/* No comment provided by engineer. */
"and %lld other events" = "и %lld других событий";
/* No comment provided by engineer. */
"Answer call" = "Принять звонок";
@ -512,6 +557,9 @@
/* No comment provided by engineer. */
"Back" = "Назад";
/* No comment provided by engineer. */
"Bad desktop address" = "Неверный адрес компьютера";
/* integrity error chat item */
"bad message hash" = "ошибка хэш сообщения";
@ -524,9 +572,27 @@
/* No comment provided by engineer. */
"Bad message ID" = "Ошибка ID сообщения";
/* No comment provided by engineer. */
"Better groups" = "Улучшенные группы";
/* No comment provided by engineer. */
"Better messages" = "Улучшенные сообщения";
/* No comment provided by engineer. */
"Block" = "Заблокировать";
/* No comment provided by engineer. */
"Block group members" = "Блокируйте членов группы";
/* No comment provided by engineer. */
"Block member" = "Заблокировать члена группы";
/* No comment provided by engineer. */
"Block member?" = "Заблокировать члена группы?";
/* No comment provided by engineer. */
"blocked" = "заблокировано";
/* No comment provided by engineer. */
"bold" = "жирный";
@ -723,9 +789,24 @@
/* No comment provided by engineer. */
"Connect incognito" = "Соединиться Инкогнито";
/* No comment provided by engineer. */
"Connect to desktop" = "Подключиться к компьютеру";
/* No comment provided by engineer. */
"connect to SimpleX Chat developers." = "соединитесь с разработчиками.";
/* No comment provided by engineer. */
"Connect to yourself?" = "Соединиться с самим собой?";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own one-time link!" = "Соединиться с самим собой?\nЭто ваша собственная одноразовая ссылка!";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own SimpleX address!" = "Соединиться с самим собой?\nЭто ваш собственный адрес SimpleX!";
/* No comment provided by engineer. */
"Connect via contact address" = "Соединиться через адрес";
/* No comment provided by engineer. */
"Connect via link" = "Соединиться через ссылку";
@ -735,9 +816,21 @@
/* No comment provided by engineer. */
"Connect via one-time link" = "Соединиться через одноразовую ссылку";
/* No comment provided by engineer. */
"Connect with %@" = "Соединиться с %@";
/* No comment provided by engineer. */
"connected" = "соединение установлено";
/* No comment provided by engineer. */
"Connected desktop" = "Подключенный компьютер";
/* rcv group event chat item */
"connected directly" = "соединен(а) напрямую";
/* No comment provided by engineer. */
"Connected to desktop" = "Компьютер подключен";
/* No comment provided by engineer. */
"connecting" = "соединяется";
@ -762,6 +855,9 @@
/* No comment provided by engineer. */
"Connecting server… (error: %@)" = "Устанавливается соединение с сервером… (ошибка: %@)";
/* No comment provided by engineer. */
"Connecting to desktop" = "Подключение к компьютеру";
/* chat list item title */
"connecting…" = "соединяется…";
@ -780,6 +876,9 @@
/* No comment provided by engineer. */
"Connection request sent!" = "Запрос на соединение отправлен!";
/* No comment provided by engineer. */
"Connection terminated" = "Подключение прервано";
/* No comment provided by engineer. */
"Connection timeout" = "Превышено время соединения";
@ -828,15 +927,24 @@
/* No comment provided by engineer. */
"Core version: v%@" = "Версия ядра: v%@";
/* No comment provided by engineer. */
"Correct name to %@?" = "Исправить имя на %@?";
/* No comment provided by engineer. */
"Create" = "Создать";
/* No comment provided by engineer. */
"Create a group using a random profile." = "Создайте группу, используя случайный профиль.";
/* No comment provided by engineer. */
"Create an address to let people connect with you." = "Создайте адрес, чтобы можно было соединиться с вами.";
/* server test step */
"Create file" = "Создание файла";
/* No comment provided by engineer. */
"Create group" = "Создать группу";
/* No comment provided by engineer. */
"Create group link" = "Создать ссылку группы";
@ -849,6 +957,9 @@
/* No comment provided by engineer. */
"Create one-time invitation link" = "Создать ссылку-приглашение";
/* No comment provided by engineer. */
"Create profile" = "Создать профиль";
/* server test step */
"Create queue" = "Создание очереди";
@ -963,6 +1074,9 @@
/* chat item action */
"Delete" = "Удалить";
/* No comment provided by engineer. */
"Delete %lld messages?" = "Удалить %lld сообщений?";
/* No comment provided by engineer. */
"Delete address" = "Удалить адрес";
@ -975,6 +1089,9 @@
/* No comment provided by engineer. */
"Delete all files" = "Удалить все файлы";
/* No comment provided by engineer. */
"Delete and notify contact" = "Удалить и уведомить контакт";
/* No comment provided by engineer. */
"Delete archive" = "Удалить архив";
@ -996,6 +1113,9 @@
/* No comment provided by engineer. */
"Delete Contact" = "Удалить контакт";
/* No comment provided by engineer. */
"Delete contact?\nThis cannot be undone!" = "Удалить контакт?\nЭто не может быть отменено!";
/* No comment provided by engineer. */
"Delete database" = "Удалить данные чата";
@ -1071,6 +1191,9 @@
/* copied message info */
"Deleted at: %@" = "Удалено: %@";
/* rcv direct event chat item */
"deleted contact" = "удалил(а) контакт";
/* rcv group event chat item */
"deleted group" = "удалил(а) группу";
@ -1086,6 +1209,15 @@
/* No comment provided by engineer. */
"Description" = "Описание";
/* No comment provided by engineer. */
"Desktop address" = "Адрес компьютера";
/* No comment provided by engineer. */
"Desktop app version %@ is not compatible with this app." = "Версия настольного приложения %@ несовместима с этим приложением.";
/* No comment provided by engineer. */
"Desktop devices" = "Компьютеры";
/* No comment provided by engineer. */
"Develop" = "Для разработчиков";
@ -1149,6 +1281,9 @@
/* server test step */
"Disconnect" = "Разрыв соединения";
/* No comment provided by engineer. */
"Disconnect desktop?" = "Отключить компьютер?";
/* No comment provided by engineer. */
"Discover and join groups" = "Найдите и вступите в группы";
@ -1287,6 +1422,12 @@
/* chat item text */
"encryption re-negotiation allowed for %@" = "новое соглашение о шифровании разрешено для %@";
/* message decrypt error item */
"Encryption re-negotiation error" = "Ошибка нового соглашения о шифровании";
/* No comment provided by engineer. */
"Encryption re-negotiation failed." = "Ошибка нового соглашения о шифровании.";
/* chat item text */
"encryption re-negotiation required" = "требуется новое соглашение о шифровании";
@ -1302,6 +1443,9 @@
/* No comment provided by engineer. */
"Enter correct passphrase." = "Введите правильный пароль.";
/* No comment provided by engineer. */
"Enter group name…" = "Введите имя группы…";
/* No comment provided by engineer. */
"Enter Passcode" = "Введите Код";
@ -1314,12 +1458,18 @@
/* No comment provided by engineer. */
"Enter server manually" = "Ввести сервер вручную";
/* No comment provided by engineer. */
"Enter this device name…" = "Введите имя этого устройства…";
/* placeholder */
"Enter welcome message…" = "Введите приветственное сообщение…";
/* placeholder */
"Enter welcome message… (optional)" = "Введите приветственное сообщение... (опционально)";
/* No comment provided by engineer. */
"Enter your name…" = "Введите ваше имя…";
/* No comment provided by engineer. */
"error" = "ошибка";
@ -1356,6 +1506,9 @@
/* No comment provided by engineer. */
"Error creating group link" = "Ошибка при создании ссылки группы";
/* No comment provided by engineer. */
"Error creating member contact" = "Ошибка создания контакта с членом группы";
/* No comment provided by engineer. */
"Error creating profile!" = "Ошибка создания профиля!";
@ -1434,6 +1587,9 @@
/* No comment provided by engineer. */
"Error sending email" = "Ошибка отправки email";
/* No comment provided by engineer. */
"Error sending member contact invitation" = "Ошибка отправки приглашения члену группы";
/* No comment provided by engineer. */
"Error sending message" = "Ошибка при отправке сообщения";
@ -1485,6 +1641,9 @@
/* No comment provided by engineer. */
"Exit without saving" = "Выйти без сохранения";
/* chat item action */
"Expand" = "Раскрыть";
/* No comment provided by engineer. */
"Export database" = "Экспорт архива чата";
@ -1503,6 +1662,9 @@
/* No comment provided by engineer. */
"Fast and no wait until the sender is online!" = "Быстрые и не нужно ждать, когда отправитель онлайн!";
/* No comment provided by engineer. */
"Faster joining and more reliable messages." = "Быстрое вступление и надежная доставка сообщений.";
/* No comment provided by engineer. */
"Favorite" = "Избранный";
@ -1572,6 +1734,9 @@
/* No comment provided by engineer. */
"Full name:" = "Полное имя:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Группа полностью децентрализована она видна только членам.";
/* No comment provided by engineer. */
"Fully re-implemented - work in background!" = "Полностью обновлены - работают в фоне!";
@ -1584,6 +1749,12 @@
/* No comment provided by engineer. */
"Group" = "Группа";
/* No comment provided by engineer. */
"Group already exists" = "Группа уже существует";
/* No comment provided by engineer. */
"Group already exists!" = "Группа уже существует!";
/* No comment provided by engineer. */
"group deleted" = "группа удалена";
@ -1755,6 +1926,9 @@
/* No comment provided by engineer. */
"Incognito" = "Инкогнито";
/* No comment provided by engineer. */
"Incognito groups" = "Инкогнито группы";
/* No comment provided by engineer. */
"Incognito mode" = "Режим Инкогнито";
@ -1782,6 +1956,9 @@
/* No comment provided by engineer. */
"Incompatible database version" = "Несовместимая версия базы данных";
/* No comment provided by engineer. */
"Incompatible version" = "Несовместимая версия";
/* PIN entry */
"Incorrect passcode" = "Неправильный код";
@ -1821,6 +1998,9 @@
/* invalid chat item */
"invalid data" = "ошибка данных";
/* No comment provided by engineer. */
"Invalid name!" = "Неверное имя!";
/* No comment provided by engineer. */
"Invalid server address!" = "Ошибка в адресе сервера!";
@ -1899,12 +2079,24 @@
/* No comment provided by engineer. */
"Join group" = "Вступить в группу";
/* No comment provided by engineer. */
"Join group?" = "Вступить в группу?";
/* No comment provided by engineer. */
"Join incognito" = "Вступить инкогнито";
/* No comment provided by engineer. */
"Join with current profile" = "Вступить с активным профилем";
/* No comment provided by engineer. */
"Join your group?\nThis is your link for group %@!" = "Вступить в вашу группу?\nЭто ваша ссылка на группу %@!";
/* No comment provided by engineer. */
"Joining group" = "Вступление в группу";
/* No comment provided by engineer. */
"Keep the app open to use it from desktop" = "Оставьте приложение открытым, чтобы использовать его с компьютера";
/* No comment provided by engineer. */
"Keep your connections" = "Сохраните Ваши соединения";
@ -1941,6 +2133,15 @@
/* No comment provided by engineer. */
"Limitations" = "Ограничения";
/* No comment provided by engineer. */
"Link mobile and desktop apps! 🔗" = "Свяжите мобильное и настольное приложения! 🔗";
/* No comment provided by engineer. */
"Linked desktop options" = "Опции связанных компьютеров";
/* No comment provided by engineer. */
"Linked desktops" = "Связанные компьютеры";
/* No comment provided by engineer. */
"LIVE" = "LIVE";
@ -2046,6 +2247,9 @@
/* No comment provided by engineer. */
"Messages & files" = "Сообщения";
/* No comment provided by engineer. */
"Messages from %@ will be shown!" = "Сообщения от %@ будут показаны!";
/* No comment provided by engineer. */
"Migrating database archive…" = "Данные чата перемещаются…";
@ -2288,12 +2492,18 @@
/* No comment provided by engineer. */
"Only your contact can send voice messages." = "Только Ваш контакт может отправлять голосовые сообщения.";
/* No comment provided by engineer. */
"Open" = "Открыть";
/* No comment provided by engineer. */
"Open chat" = "Открыть чат";
/* authentication reason */
"Open chat console" = "Открыть консоль";
/* No comment provided by engineer. */
"Open group" = "Открыть группу";
/* No comment provided by engineer. */
"Open Settings" = "Открыть Настройки";
@ -2330,6 +2540,9 @@
/* No comment provided by engineer. */
"Paste" = "Вставить";
/* No comment provided by engineer. */
"Paste desktop address" = "Вставить адрес компьютера";
/* No comment provided by engineer. */
"Paste image" = "Вставить изображение";
@ -2426,6 +2639,12 @@
/* No comment provided by engineer. */
"Profile image" = "Аватар";
/* No comment provided by engineer. */
"Profile name" = "Имя профиля";
/* No comment provided by engineer. */
"Profile name:" = "Имя профиля:";
/* No comment provided by engineer. */
"Profile password" = "Пароль профиля";
@ -2591,6 +2810,12 @@
/* No comment provided by engineer. */
"Renegotiate encryption?" = "Пересогласовать шифрование?";
/* No comment provided by engineer. */
"Repeat connection request?" = "Повторить запрос на соединение?";
/* No comment provided by engineer. */
"Repeat join request?" = "Повторить запрос на вступление?";
/* chat item action */
"Reply" = "Ответить";
@ -2702,6 +2927,9 @@
/* No comment provided by engineer. */
"Scan QR code" = "Сканировать QR код";
/* No comment provided by engineer. */
"Scan QR code from desktop" = "Сканировать QR код с компьютера";
/* No comment provided by engineer. */
"Scan security code from your contact's app." = "Сканируйте код безопасности из приложения контакта.";
@ -2756,9 +2984,15 @@
/* No comment provided by engineer. */
"Send delivery receipts to" = "Отправка отчётов о доставке";
/* No comment provided by engineer. */
"send direct message" = "отправьте сообщение";
/* No comment provided by engineer. */
"Send direct message" = "Отправить сообщение";
/* No comment provided by engineer. */
"Send direct message to connect" = "Отправьте сообщение чтобы соединиться";
/* No comment provided by engineer. */
"Send disappearing message" = "Отправить исчезающее сообщение";
@ -2840,6 +3074,9 @@
/* No comment provided by engineer. */
"Servers" = "Серверы";
/* No comment provided by engineer. */
"Session code" = "Код сессии";
/* No comment provided by engineer. */
"Set 1 day" = "Установить 1 день";
@ -3026,6 +3263,9 @@
/* No comment provided by engineer. */
"Tap to activate profile." = "Нажмите, чтобы сделать профиль активным.";
/* No comment provided by engineer. */
"Tap to Connect" = "Нажмите чтобы соединиться";
/* No comment provided by engineer. */
"Tap to join" = "Нажмите, чтобы вступить";
@ -3146,12 +3386,21 @@
/* notification title */
"this contact" = "этот контакт";
/* No comment provided by engineer. */
"This device name" = "Имя этого устройства";
/* No comment provided by engineer. */
"This group has over %lld members, delivery receipts are not sent." = "В группе более %lld членов, отчёты о доставке выключены.";
/* No comment provided by engineer. */
"This group no longer exists." = "Эта группа больше не существует.";
/* No comment provided by engineer. */
"This is your own one-time link!" = "Это ваша собственная одноразовая ссылка!";
/* No comment provided by engineer. */
"This is your own SimpleX address!" = "Это ваш собственный адрес SimpleX!";
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "Эта настройка применяется к сообщениям в Вашем текущем профиле чата **%@**.";
@ -3161,6 +3410,9 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "Чтобы соединиться с Вами, Ваш контакт может отсканировать QR-код или использовать ссылку в приложении.";
/* No comment provided by engineer. */
"To hide unwanted messages." = "Чтобы скрыть нежелательные сообщения.";
/* No comment provided by engineer. */
"To make a new connection" = "Чтобы соединиться";
@ -3209,6 +3461,15 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "Невозможно записать голосовое сообщение";
/* No comment provided by engineer. */
"Unblock" = "Разблокировать";
/* No comment provided by engineer. */
"Unblock member" = "Разблокировать члена группы";
/* No comment provided by engineer. */
"Unblock member?" = "Разблокировать члена группы?";
/* item status description */
"Unexpected error: %@" = "Неожиданная ошибка: %@";
@ -3248,6 +3509,12 @@
/* No comment provided by engineer. */
"Unless your contact deleted the connection or this link was already used, it might be a bug - please report it.\nTo connect, please ask your contact to create another connection link and check that you have a stable network connection." = "Возможно, Ваш контакт удалил ссылку, или она уже была использована. Если это не так, то это может быть ошибкой - пожалуйста, сообщите нам об этом.\nЧтобы установить соединение, попросите Ваш контакт создать еще одну ссылку и проверьте Ваше соединение с сетью.";
/* No comment provided by engineer. */
"Unlink" = "Забыть";
/* No comment provided by engineer. */
"Unlink desktop?" = "Забыть компьютер?";
/* No comment provided by engineer. */
"Unlock" = "Разблокировать";
@ -3302,6 +3569,9 @@
/* No comment provided by engineer. */
"Use for new connections" = "Использовать для новых соединений";
/* No comment provided by engineer. */
"Use from desktop" = "Использовать с компьютера";
/* No comment provided by engineer. */
"Use iOS call interface" = "Использовать интерфейс iOS для звонков";
@ -3323,12 +3593,24 @@
/* No comment provided by engineer. */
"Using SimpleX Chat servers." = "Используются серверы, предоставленные SimpleX Chat.";
/* No comment provided by engineer. */
"v%@" = "v%@";
/* No comment provided by engineer. */
"v%@ (%@)" = "v%@ (%@)";
/* No comment provided by engineer. */
"Verify code with desktop" = "Сверьте код с компьютером";
/* No comment provided by engineer. */
"Verify connection" = "Проверить соединение";
/* No comment provided by engineer. */
"Verify connection security" = "Проверить безопасность соединения";
/* No comment provided by engineer. */
"Verify connections" = "Проверять соединения";
/* No comment provided by engineer. */
"Verify security code" = "Подтвердить код безопасности";
@ -3347,6 +3629,9 @@
/* No comment provided by engineer. */
"via relay" = "через relay сервер";
/* No comment provided by engineer. */
"Via secure quantum resistant protocol." = "Через безопасный квантово-устойчивый протокол.";
/* No comment provided by engineer. */
"Video call" = "Видеозвонок";
@ -3455,6 +3740,27 @@
/* No comment provided by engineer. */
"You are already connected to %@." = "Вы уже соединены с контактом %@.";
/* No comment provided by engineer. */
"You are already connecting to %@." = "Вы уже соединяетесь с %@.";
/* No comment provided by engineer. */
"You are already connecting via this one-time link!" = "Вы уже соединяетесь по этой одноразовой ссылке!";
/* No comment provided by engineer. */
"You are already in group %@." = "Вы уже состоите в группе %@.";
/* No comment provided by engineer. */
"You are already joining the group %@." = "Вы уже вступаете в группу %@.";
/* No comment provided by engineer. */
"You are already joining the group via this link!" = "Вы уже вступаете в группу по этой ссылке!";
/* No comment provided by engineer. */
"You are already joining the group via this link." = "Вы уже вступаете в группу по этой ссылке.";
/* No comment provided by engineer. */
"You are already joining the group!\nRepeat join request?" = "Вы уже вступаете в группу!\nПовторить запрос на вступление?";
/* No comment provided by engineer. */
"You are connected to the server used to receive messages from this contact." = "Установлено соединение с сервером, через который Вы получаете сообщения от этого контакта.";
@ -3530,6 +3836,12 @@
/* No comment provided by engineer. */
"You could not be verified; please try again." = "Верификация не удалась; пожалуйста, попробуйте ещё раз.";
/* No comment provided by engineer. */
"You have already requested connection via this address!" = "Вы уже запросили соединение через этот адрес!";
/* No comment provided by engineer. */
"You have already requested connection!\nRepeat connection request?" = "Вы уже запросили соединение!\nПовторить запрос?";
/* No comment provided by engineer. */
"You have no chats" = "У Вас нет чатов";
@ -3572,6 +3884,9 @@
/* No comment provided by engineer. */
"You will be connected to group when the group host's device is online, please wait or check later!" = "Соединение с группой будет установлено, когда хост группы будет онлайн. Пожалуйста, подождите или проверьте позже!";
/* No comment provided by engineer. */
"You will be connected when group link host's device is online, please wait or check later!" = "Соединение будет установлено, когда владелец ссылки группы будет онлайн. Пожалуйста, подождите или проверьте позже!";
/* No comment provided by engineer. */
"You will be connected when your connection request is accepted, please wait or check later!" = "Соединение будет установлено, когда Ваш запрос будет принят. Пожалуйста, подождите или проверьте позже!";
@ -3581,6 +3896,9 @@
/* No comment provided by engineer. */
"You will be required to authenticate when you start or resume the app after 30 seconds in background." = "Вы будете аутентифицированы при запуске и возобновлении приложения, которое было 30 секунд в фоновом режиме.";
/* No comment provided by engineer. */
"You will connect to all group members." = "Вы соединитесь со всеми членами группы.";
/* No comment provided by engineer. */
"You will still receive calls and notifications from muted profiles when they are active." = "Вы все равно получите звонки и уведомления в профилях без звука, когда они активные.";
@ -3644,6 +3962,9 @@
/* No comment provided by engineer. */
"Your privacy" = "Конфиденциальность";
/* No comment provided by engineer. */
"Your profile" = "Ваш профиль";
/* No comment provided by engineer. */
"Your profile **%@** will be shared." = "Будет отправлен Ваш профиль **%@**.";

View File

@ -7,6 +7,9 @@
/* Privacy - Face ID Usage Description */
"NSFaceIDUsageDescription" = "SimpleX использует Face ID для аутентификации";
/* Privacy - Local Network Usage Description */
"NSLocalNetworkUsageDescription" = "SimpleX использует доступ к локальной сети, чтобы разрешить использование профиля чата через компьютер в той же сети.";
/* Privacy - Microphone Usage Description */
"NSMicrophoneUsageDescription" = "SimpleX использует микрофон для аудио и видео звонков, и для записи голосовых сообщений.";

View File

@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import com.google.accompanist.insets.navigationBarsWithImePadding
import java.io.File
actual fun Modifier.navigationBarsWithImePadding(): Modifier = navigationBarsWithImePadding()
@ -19,7 +20,7 @@ actual fun ProvideWindowInsets(
@Composable
actual fun Modifier.desktopOnExternalDrag(
enabled: Boolean,
onFiles: (List<String>) -> Unit,
onFiles: (List<File>) -> Unit,
onImage: (Painter) -> Unit,
onText: (String) -> Unit
): Modifier = this

View File

@ -71,7 +71,7 @@ actual class VideoPlayer actual constructor(
private fun start(seek: Long? = null, onProgressUpdate: (position: Long?, state: TrackState) -> Unit): Boolean {
val filepath = getAppFilePath(uri)
if (filepath == null || !File(filepath).exists()) {
Log.e(TAG, "No such file: $uri")
Log.e(TAG, "No such file: $filepath")
brokenVideo.value = true
return false
}

View File

@ -65,7 +65,7 @@ fun MainScreen() {
!chatModel.controller.appPrefs.laNoticeShown.get()
&& showAdvertiseLAAlert
&& chatModel.controller.appPrefs.onboardingStage.get() == OnboardingStage.OnboardingComplete
&& chatModel.chats.isNotEmpty()
&& chatModel.chats.count() > 1
&& chatModel.activeCallInvitation.value == null
) {
AppLock.showLANotice(ChatModel.controller.appPrefs.laNoticeShown) }

View File

@ -3,6 +3,7 @@ package chat.simplex.common.model
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.runtime.snapshots.SnapshotStateMap
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.font.*
@ -27,7 +28,6 @@ import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.*
import java.io.File
import java.net.URI
import java.net.URLDecoder
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import java.util.*
@ -113,7 +113,7 @@ object ChatModel {
val currentRemoteHost = mutableStateOf<RemoteHostInfo?>(null)
val remoteHostId: Long? @Composable get() = remember { currentRemoteHost }.value?.remoteHostId
fun remoteHostId(): Long? = currentRemoteHost.value?.remoteHostId
val newRemoteHostPairing = mutableStateOf<Pair<RemoteHostInfo?, RemoteHostSessionState>?>(null)
val remoteHostPairing = mutableStateOf<Pair<RemoteHostInfo?, RemoteHostSessionState>?>(null)
val remoteCtrlSession = mutableStateOf<RemoteCtrlSession?>(null)
fun getUser(userId: Long): User? = if (currentUser.value?.userId == userId) {
@ -638,6 +638,9 @@ data class User(
val addressShared: Boolean = profile.contactLink != null
fun updateRemoteHostId(rh: Long?): User =
if (rh == null) this else this.copy(remoteHostId = rh)
companion object {
val sampleData = User(
remoteHostId = null,
@ -2301,7 +2304,7 @@ data class CIFile(
sent = fileStatus.sent,
fileSource = fileSource
)
cachedRemoteFileRequests.add(fileSource)
cachedRemoteFileRequests[fileSource] = false
val showAlert = fileSize > 5_000_000 && allowToShowAlert
if (showAlert) {
AlertManager.shared.showAlertMsgWithProgress(
@ -2310,7 +2313,7 @@ data class CIFile(
)
}
val res = chatModel.controller.getRemoteFile(rh.remoteHostId, rf)
cachedRemoteFileRequests.remove(fileSource)
cachedRemoteFileRequests[fileSource] = res
if (showAlert) {
AlertManager.shared.hideAlert()
}
@ -2327,7 +2330,7 @@ data class CIFile(
): CIFile =
CIFile(fileId = fileId, fileName = fileName, fileSize = fileSize, fileSource = if (filePath == null) null else CryptoFile.plain(filePath), fileStatus = fileStatus, fileProtocol = FileProtocol.XFTP)
val cachedRemoteFileRequests = SnapshotStateList<CryptoFile>()
val cachedRemoteFileRequests = SnapshotStateMap<CryptoFile, Boolean>()
}
}
@ -2360,7 +2363,7 @@ data class CryptoFile(
companion object {
fun plain(f: String): CryptoFile = CryptoFile(f, null)
fun desktopPlain(f: URI): CryptoFile = CryptoFile(URLDecoder.decode(f.rawPath, "UTF-8"), null)
fun desktopPlain(f: URI): CryptoFile = CryptoFile(f.toFile().absolutePath, null)
}
}
@ -2918,7 +2921,7 @@ enum class NotificationPreviewMode {
}
data class RemoteCtrlSession(
val ctrlAppInfo: CtrlAppInfo,
val ctrlAppInfo: CtrlAppInfo?,
val appVersion: String,
val sessionState: UIRemoteCtrlSessionState
) {
@ -2936,14 +2939,17 @@ data class RemoteCtrlSession(
@Serializable
sealed class RemoteCtrlSessionState {
@Serializable @SerialName("starting") object Starting: RemoteCtrlSessionState()
@Serializable @SerialName("searching") object Searching: RemoteCtrlSessionState()
@Serializable @SerialName("connecting") object Connecting: RemoteCtrlSessionState()
@Serializable @SerialName("pendingConfirmation") data class PendingConfirmation(val sessionCode: String): RemoteCtrlSessionState()
@Serializable @SerialName("connected") data class Connected(val sessionCode: String): RemoteCtrlSessionState()
}
sealed class UIRemoteCtrlSessionState {
@Serializable @SerialName("starting") object Starting: UIRemoteCtrlSessionState()
@Serializable @SerialName("connecting") data class Connecting(val remoteCtrl_: RemoteCtrlInfo? = null): UIRemoteCtrlSessionState()
@Serializable @SerialName("pendingConfirmation") data class PendingConfirmation(val remoteCtrl_: RemoteCtrlInfo? = null, val sessionCode: String): UIRemoteCtrlSessionState()
@Serializable @SerialName("connected") data class Connected(val remoteCtrl: RemoteCtrlInfo, val sessionCode: String): UIRemoteCtrlSessionState()
object Starting: UIRemoteCtrlSessionState()
object Searching: UIRemoteCtrlSessionState()
data class Found(val remoteCtrl: RemoteCtrlInfo, val compatible: Boolean): UIRemoteCtrlSessionState()
data class Connecting(val remoteCtrl_: RemoteCtrlInfo? = null): UIRemoteCtrlSessionState()
data class PendingConfirmation(val remoteCtrl_: RemoteCtrlInfo? = null, val sessionCode: String): UIRemoteCtrlSessionState()
data class Connected(val remoteCtrl: RemoteCtrlInfo, val sessionCode: String): UIRemoteCtrlSessionState()
}

View File

@ -170,6 +170,7 @@ class AppPreferences {
val confirmRemoteSessions = mkBoolPreference(SHARED_PREFS_CONFIRM_REMOTE_SESSIONS, false)
val connectRemoteViaMulticast = mkBoolPreference(SHARED_PREFS_CONNECT_REMOTE_VIA_MULTICAST, false)
val connectRemoteViaMulticastAuto = mkBoolPreference(SHARED_PREFS_CONNECT_REMOTE_VIA_MULTICAST_AUTO, true)
val offerRemoteMulticast = mkBoolPreference(SHARED_PREFS_OFFER_REMOTE_MULTICAST, true)
private fun mkIntPreference(prefName: String, default: Int) =
@ -314,6 +315,7 @@ class AppPreferences {
private const val SHARED_PREFS_DEVICE_NAME_FOR_REMOTE_ACCESS = "DeviceNameForRemoteAccess"
private const val SHARED_PREFS_CONFIRM_REMOTE_SESSIONS = "ConfirmRemoteSessions"
private const val SHARED_PREFS_CONNECT_REMOTE_VIA_MULTICAST = "ConnectRemoteViaMulticast"
private const val SHARED_PREFS_CONNECT_REMOTE_VIA_MULTICAST_AUTO = "ConnectRemoteViaMulticastAuto"
private const val SHARED_PREFS_OFFER_REMOTE_MULTICAST = "OfferRemoteMulticast"
}
}
@ -468,7 +470,7 @@ object ChatController {
suspend fun apiGetActiveUser(rh: Long?): User? {
val r = sendCmd(rh, CC.ShowActiveUser())
if (r is CR.ActiveUser) return r.user
if (r is CR.ActiveUser) return r.user.updateRemoteHostId(rh)
Log.d(TAG, "apiGetActiveUser: ${r.responseType} ${r.details}")
chatModel.userCreated.value = false
return null
@ -476,7 +478,7 @@ object ChatController {
suspend fun apiCreateActiveUser(rh: Long?, p: Profile?, sameServers: Boolean = false, pastTimestamp: Boolean = false): User? {
val r = sendCmd(rh, CC.CreateActiveUser(p, sameServers = sameServers, pastTimestamp = pastTimestamp))
if (r is CR.ActiveUser) return r.user
if (r is CR.ActiveUser) return r.user.updateRemoteHostId(rh)
else if (
r is CR.ChatCmdError && r.chatError is ChatError.ChatErrorStore && r.chatError.storeError is StoreError.DuplicateName ||
r is CR.ChatCmdError && r.chatError is ChatError.ChatErrorChat && r.chatError.errorType is ChatErrorType.UserExists
@ -501,7 +503,7 @@ object ChatController {
suspend fun apiSetActiveUser(rh: Long?, userId: Long, viewPwd: String?): User {
val r = sendCmd(rh, CC.ApiSetActiveUser(userId, viewPwd))
if (r is CR.ActiveUser) return if (rh == null) r.user else r.user.copy(remoteHostId = rh)
if (r is CR.ActiveUser) return r.user.updateRemoteHostId(rh)
Log.d(TAG, "apiSetActiveUser: ${r.responseType} ${r.details}")
throw Exception("failed to set the user as active ${r.responseType} ${r.details}")
}
@ -538,7 +540,7 @@ object ChatController {
private suspend fun setUserPrivacy(rh: Long?, cmd: CC): User {
val r = sendCmd(rh, cmd)
if (r is CR.UserPrivacy) return if (rh == null) r.updatedUser else r.updatedUser.copy(remoteHostId = rh)
if (r is CR.UserPrivacy) return r.updatedUser.updateRemoteHostId(rh)
else throw Exception("Failed to change user privacy: ${r.responseType} ${r.details}")
}
@ -989,7 +991,7 @@ object ChatController {
val userId = try { currentUserId("apiSetProfileAddress") } catch (e: Exception) { return null }
return when (val r = sendCmd(rh, CC.ApiSetProfileAddress(userId, on))) {
is CR.UserProfileNoChange -> null
is CR.UserProfileUpdated -> r.user
is CR.UserProfileUpdated -> r.user.updateRemoteHostId(rh)
else -> throw Exception("failed to set profile address: ${r.responseType} ${r.details}")
}
}
@ -1032,7 +1034,7 @@ object ChatController {
suspend fun apiDeleteUserAddress(rh: Long?): User? {
val userId = try { currentUserId("apiDeleteUserAddress") } catch (e: Exception) { return null }
val r = sendCmd(rh, CC.ApiDeleteMyAddress(userId))
if (r is CR.UserContactLinkDeleted) return r.user
if (r is CR.UserContactLinkDeleted) return r.user.updateRemoteHostId(rh)
Log.e(TAG, "apiDeleteUserAddress bad response: ${r.responseType} ${r.details}")
return null
}
@ -1392,7 +1394,7 @@ object ChatController {
chatModel.remoteHosts.addAll(hosts)
}
suspend fun startRemoteHost(rhId: Long?, multicast: Boolean = false): Triple<RemoteHostInfo?, String, String>? {
suspend fun startRemoteHost(rhId: Long?, multicast: Boolean = true): Triple<RemoteHostInfo?, String, String>? {
val r = sendCmd(null, CC.StartRemoteHost(rhId, multicast))
if (r is CR.RemoteHostStarted) return Triple(r.remoteHost_, r.invitation, r.ctrlPort)
apiErrorAlert("startRemoteHost", generalGetString(MR.strings.error_alert_title), r)
@ -1428,18 +1430,29 @@ object ChatController {
return null
}
suspend fun getRemoteFile(rhId: Long, file: RemoteFile): Boolean = sendCommandOkResp(null, CC.GetRemoteFile(rhId, file))
suspend fun getRemoteFile(rhId: Long, file: RemoteFile): Boolean = sendCmd(null, CC.GetRemoteFile(rhId, file)) is CR.CmdOk
suspend fun connectRemoteCtrl(desktopAddress: String): Pair<SomeRemoteCtrl?, CR.ChatCmdError?> {
val r = sendCmd(null, CC.ConnectRemoteCtrl(desktopAddress))
if (r is CR.RemoteCtrlConnecting) return SomeRemoteCtrl(r.remoteCtrl_, r.ctrlAppInfo, r.appVersion) to null
else if (r is CR.ChatCmdError) return null to r
else throw Exception("connectRemoteCtrl error: ${r.responseType} ${r.details}")
return if (r is CR.RemoteCtrlConnecting) SomeRemoteCtrl(r.remoteCtrl_, r.ctrlAppInfo, r.appVersion) to null
else if (r is CR.ChatCmdError) null to r
else {
apiErrorAlert("connectRemoteCtrl", generalGetString(MR.strings.error_alert_title), r)
null to null
}
}
suspend fun findKnownRemoteCtrl(): Boolean = sendCommandOkResp(null, CC.FindKnownRemoteCtrl())
suspend fun confirmRemoteCtrl(rcId: Long): Boolean = sendCommandOkResp(null, CC.ConfirmRemoteCtrl(rcId))
suspend fun confirmRemoteCtrl(rcId: Long): Pair<SomeRemoteCtrl?, CR.ChatCmdError?> {
val r = sendCmd(null, CC.ConfirmRemoteCtrl(remoteCtrlId = rcId))
return if (r is CR.RemoteCtrlConnecting) SomeRemoteCtrl(r.remoteCtrl_, r.ctrlAppInfo, r.appVersion) to null
else if (r is CR.ChatCmdError) null to r
else {
apiErrorAlert("confirmRemoteCtrl", generalGetString(MR.strings.error_alert_title), r)
null to null
}
}
suspend fun verifyRemoteCtrlSession(sessionCode: String): RemoteCtrlInfo? {
val r = sendCmd(null, CC.VerifyRemoteCtrlSession(sessionCode))
@ -1836,7 +1849,7 @@ object ChatController {
is CR.GroupMemberRatchetSync ->
chatModel.updateGroupMemberConnectionStats(rhId, r.groupInfo, r.member, r.ratchetSyncProgress.connectionStats)
is CR.RemoteHostSessionCode -> {
chatModel.newRemoteHostPairing.value = r.remoteHost_ to RemoteHostSessionState.PendingConfirmation(r.sessionCode)
chatModel.remoteHostPairing.value = r.remoteHost_ to RemoteHostSessionState.PendingConfirmation(r.sessionCode)
}
is CR.RemoteHostConnected -> {
// TODO needs to update it instead in sessions
@ -1845,7 +1858,7 @@ object ChatController {
}
is CR.RemoteHostStopped -> {
val disconnectedHost = chatModel.remoteHosts.firstOrNull { it.remoteHostId == r.remoteHostId_ }
chatModel.newRemoteHostPairing.value = null
chatModel.remoteHostPairing.value = null
if (disconnectedHost != null) {
showToast(
generalGetString(MR.strings.remote_host_was_disconnected_toast).format(disconnectedHost.hostDeviceName.ifEmpty { disconnectedHost.remoteHostId.toString() })
@ -1857,8 +1870,15 @@ object ChatController {
}
}
is CR.RemoteCtrlFound -> {
// TODO multicast
Log.d(TAG, "RemoteCtrlFound: ${r.remoteCtrl}")
val sess = chatModel.remoteCtrlSession.value
if (sess != null && sess.sessionState is UIRemoteCtrlSessionState.Searching) {
val state = UIRemoteCtrlSessionState.Found(remoteCtrl = r.remoteCtrl, compatible = r.compatible)
chatModel.remoteCtrlSession.value = RemoteCtrlSession(
ctrlAppInfo = r.ctrlAppInfo_,
appVersion = r.appVersion,
sessionState = state
)
}
}
is CR.RemoteCtrlSessionCode -> {
val state = UIRemoteCtrlSessionState.PendingConfirmation(remoteCtrl_ = r.remoteCtrl_, sessionCode = r.sessionCode)
@ -1870,7 +1890,13 @@ object ChatController {
chatModel.remoteCtrlSession.value = chatModel.remoteCtrlSession.value?.copy(sessionState = state)
}
is CR.RemoteCtrlStopped -> {
switchToLocalSession()
val sess = chatModel.remoteCtrlSession.value
if (sess != null) {
chatModel.remoteCtrlSession.value = null
if (sess.sessionState is UIRemoteCtrlSessionState.Connected) {
switchToLocalSession()
}
}
}
else ->
Log.d(TAG , "unsupported event: ${r.responseType}")
@ -2322,7 +2348,7 @@ sealed class CC {
is DeleteRemoteHost -> "/delete remote host $remoteHostId"
is StoreRemoteFile ->
"/store remote file $remoteHostId " +
(if (storeEncrypted == null) "" else " encrypt=${onOff(storeEncrypted)} ") +
(if (storeEncrypted == null) "" else "encrypt=${onOff(storeEncrypted)} ") +
localPath
is GetRemoteFile -> "/get remote file $remoteHostId ${json.encodeToString(file)}"
is ConnectRemoteCtrl -> "/connect remote ctrl $xrcpInvitation"
@ -3782,7 +3808,7 @@ sealed class CR {
@Serializable @SerialName("remoteFileStored") class RemoteFileStored(val remoteHostId: Long, val remoteFileSource: CryptoFile): CR()
// remote events (mobile)
@Serializable @SerialName("remoteCtrlList") class RemoteCtrlList(val remoteCtrls: List<RemoteCtrlInfo>): CR()
@Serializable @SerialName("remoteCtrlFound") class RemoteCtrlFound(val remoteCtrl: RemoteCtrlInfo): CR()
@Serializable @SerialName("remoteCtrlFound") class RemoteCtrlFound(val remoteCtrl: RemoteCtrlInfo, val ctrlAppInfo_: CtrlAppInfo?, val appVersion: String, val compatible: Boolean): CR()
@Serializable @SerialName("remoteCtrlConnecting") class RemoteCtrlConnecting(val remoteCtrl_: RemoteCtrlInfo?, val ctrlAppInfo: CtrlAppInfo, val appVersion: String): CR()
@Serializable @SerialName("remoteCtrlSessionCode") class RemoteCtrlSessionCode(val remoteCtrl_: RemoteCtrlInfo?, val sessionCode: String): CR()
@Serializable @SerialName("remoteCtrlConnected") class RemoteCtrlConnected(val remoteCtrl: RemoteCtrlInfo): CR()
@ -4080,7 +4106,11 @@ sealed class CR {
is RemoteHostStopped -> "remote host ID: $remoteHostId_"
is RemoteFileStored -> "remote host ID: $remoteHostId\nremoteFileSource:\n" + json.encodeToString(remoteFileSource)
is RemoteCtrlList -> json.encodeToString(remoteCtrls)
is RemoteCtrlFound -> json.encodeToString(remoteCtrl)
is RemoteCtrlFound -> "remote ctrl: " + json.encodeToString(remoteCtrl) +
"\nctrlAppInfo: " +
(if (ctrlAppInfo_ == null) "null" else json.encodeToString(ctrlAppInfo_)) +
"\nappVersion: $appVersion" +
"\ncompatible: $compatible"
is RemoteCtrlConnecting ->
"remote ctrl: " +
(if (remoteCtrl_ == null) "null" else json.encodeToString(remoteCtrl_)) +

View File

@ -7,6 +7,8 @@ import chat.simplex.common.views.helpers.generalGetString
import chat.simplex.res.MR
import java.io.*
import java.net.URI
import java.net.URLDecoder
import java.net.URLEncoder
expect val dataDir: File
expect val tmpDir: File
@ -28,6 +30,10 @@ expect val remoteHostsDir: File
expect fun desktopOpenDatabaseDir()
fun createURIFromPath(absolutePath: String): URI = URI.create(URLEncoder.encode(absolutePath, "UTF-8"))
fun URI.toFile(): File = File(URLDecoder.decode(rawPath, "UTF-8").removePrefix("file:"))
fun copyFileToFile(from: File, to: URI, finally: () -> Unit) {
try {
to.outputStream().use { stream ->
@ -92,7 +98,7 @@ fun getLoadedFileSource(file: CIFile?): CryptoFile? {
private fun fileReady(file: CIFile, filePath: String) =
File(filePath).exists() &&
!CIFile.cachedRemoteFileRequests.contains(file.fileSource)
CIFile.cachedRemoteFileRequests[file.fileSource] != false
&& File(filePath).length() >= file.fileSize
/**

View File

@ -3,6 +3,7 @@ package chat.simplex.common.platform
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import java.io.File
expect fun Modifier.navigationBarsWithImePadding(): Modifier
@ -16,7 +17,7 @@ expect fun ProvideWindowInsets(
@Composable
expect fun Modifier.desktopOnExternalDrag(
enabled: Boolean = true,
onFiles: (List<String>) -> Unit = {},
onFiles: (List<File>) -> Unit = {},
onImage: (Painter) -> Unit = {},
onText: (String) -> Unit = {}
): Modifier

View File

@ -43,16 +43,13 @@ object VideoPlayerHolder {
): VideoPlayer =
players.getOrPut(uri to gallery) { VideoPlayer(uri, gallery, defaultPreview, defaultDuration, soundEnabled) }
fun enableSound(enable: Boolean, fileName: String?, gallery: Boolean): Boolean =
player(fileName, gallery)?.enableSound(enable) == true
private fun player(fileName: String?, gallery: Boolean): VideoPlayer? {
fileName ?: return null
return players.values.firstOrNull { player -> player.uri.path?.endsWith(fileName) == true && player.gallery == gallery }
private fun player(uri: URI?, gallery: Boolean): VideoPlayer? {
uri ?: return null
return players.values.firstOrNull { player -> player.uri == uri && player.gallery == gallery }
}
fun release(uri: URI, gallery: Boolean, remove: Boolean) =
player(uri.path, gallery)?.release(remove).run { }
player(uri, gallery)?.release(remove).run { }
fun stopAll() {
players.values.forEach { it.stop() }

View File

@ -501,7 +501,7 @@ fun ChatLayout(
.fillMaxWidth()
.desktopOnExternalDrag(
enabled = !attachmentDisabled.value && rememberUpdatedState(chat.userCanSend).value,
onFiles = { paths -> composeState.onFilesAttached(paths.map { URI.create(it) }) },
onFiles = { paths -> composeState.onFilesAttached(paths.map { it.toURI() }) },
onImage = {
// TODO: file is not saved anywhere?!
val tmpFile = File.createTempFile("image", ".bmp", tmpDir)

View File

@ -850,6 +850,7 @@ fun ComposeView(
deleteUnusedFiles()
}
chatModel.removeLiveDummy()
CIFile.cachedRemoteFileRequests.clear()
}
val timedMessageAllowed = remember(chat.chatInfo) { chat.chatInfo.featureEnabled(ChatFeature.TimedMessages) }

View File

@ -133,7 +133,7 @@ fun ChatItemView(
}
fun deleteMessageQuestionText(): String {
return if (fullDeleteAllowed) {
return if (!sent || fullDeleteAllowed) {
generalGetString(MR.strings.delete_message_cannot_be_undone_warning)
} else {
generalGetString(MR.strings.delete_message_mark_deleted_warning)
@ -195,7 +195,7 @@ fun ChatItemView(
}
val clipboard = LocalClipboardManager.current
val cachedRemoteReqs = remember { CIFile.cachedRemoteFileRequests }
val copyAndShareAllowed = cItem.file == null || !chatModel.connectedToRemote() || getLoadedFilePath(cItem.file) != null || !cachedRemoteReqs.contains(cItem.file.fileSource)
val copyAndShareAllowed = cItem.file == null || !chatModel.connectedToRemote() || getLoadedFilePath(cItem.file) != null || cachedRemoteReqs[cItem.file.fileSource] != false
if (copyAndShareAllowed) {
ItemAction(stringResource(MR.strings.share_verb), painterResource(MR.images.ic_share), onClick = {
var fileSource = getLoadedFileSource(cItem.file)
@ -221,7 +221,7 @@ fun ChatItemView(
showMenu.value = false
})
}
if ((cItem.content.msgContent is MsgContent.MCImage || cItem.content.msgContent is MsgContent.MCVideo || cItem.content.msgContent is MsgContent.MCFile || cItem.content.msgContent is MsgContent.MCVoice) && (getLoadedFilePath(cItem.file) != null || (chatModel.connectedToRemote() && !cachedRemoteReqs.contains(cItem.file?.fileSource)))) {
if ((cItem.content.msgContent is MsgContent.MCImage || cItem.content.msgContent is MsgContent.MCVideo || cItem.content.msgContent is MsgContent.MCFile || cItem.content.msgContent is MsgContent.MCVoice) && (getLoadedFilePath(cItem.file) != null || (chatModel.connectedToRemote() && cachedRemoteReqs[cItem.file?.fileSource] != false))) {
SaveContentItemAction(cItem, saveFileLauncher, showMenu)
}
if (cItem.meta.editable && cItem.content.msgContent !is MsgContent.MCVoice && !live) {

View File

@ -40,6 +40,7 @@ fun DatabaseView(
m: ChatModel,
showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit)
) {
val currentRemoteHost by remember { chatModel.currentRemoteHost }
val progressIndicator = remember { mutableStateOf(false) }
val prefs = m.controller.appPrefs
val useKeychain = remember { mutableStateOf(prefs.storeDBPassphrase.get()) }
@ -68,6 +69,7 @@ fun DatabaseView(
val user = m.currentUser.value
val rhId = user?.remoteHostId
DatabaseLayout(
currentRemoteHost = currentRemoteHost,
progressIndicator.value,
remember { m.chatRunning }.value != false,
m.chatDbChanged.value,
@ -119,6 +121,7 @@ fun DatabaseView(
@Composable
fun DatabaseLayout(
currentRemoteHost: RemoteHostInfo?,
progressIndicator: Boolean,
runChat: Boolean,
chatDbChanged: Boolean,
@ -165,103 +168,107 @@ fun DatabaseLayout(
}
}
)
SectionDividerSpaced(maxTopPadding = true)
SectionView(stringResource(MR.strings.run_chat_section)) {
RunChatSetting(runChat, stopped, startChat, stopChatAlert)
}
SectionTextFooter(
if (stopped) {
stringResource(MR.strings.you_must_use_the_most_recent_version_of_database)
} else {
stringResource(MR.strings.stop_chat_to_enable_database_actions)
if (currentRemoteHost == null) {
SectionDividerSpaced(maxTopPadding = true)
SectionView(stringResource(MR.strings.run_chat_section)) {
RunChatSetting(runChat, stopped, startChat, stopChatAlert)
}
)
SectionDividerSpaced()
SectionView(stringResource(MR.strings.chat_database_section)) {
val unencrypted = chatDbEncrypted == false
SettingsActionItem(
if (unencrypted) painterResource(MR.images.ic_lock_open_right) else if (useKeyChain) painterResource(MR.images.ic_vpn_key_filled)
else painterResource(MR.images.ic_lock),
stringResource(MR.strings.database_passphrase),
click = showSettingsModal() { DatabaseEncryptionView(it) },
iconColor = if (unencrypted || (appPlatform.isDesktop && passphraseSaved)) WarningOrange else MaterialTheme.colors.secondary,
disabled = operationsDisabled
SectionTextFooter(
if (stopped) {
stringResource(MR.strings.you_must_use_the_most_recent_version_of_database)
} else {
stringResource(MR.strings.stop_chat_to_enable_database_actions)
}
)
if (appPlatform.isDesktop && developerTools) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.chat_database_section)) {
val unencrypted = chatDbEncrypted == false
SettingsActionItem(
painterResource(MR.images.ic_folder_open),
stringResource(MR.strings.open_database_folder),
::desktopOpenDatabaseDir,
if (unencrypted) painterResource(MR.images.ic_lock_open_right) else if (useKeyChain) painterResource(MR.images.ic_vpn_key_filled)
else painterResource(MR.images.ic_lock),
stringResource(MR.strings.database_passphrase),
click = showSettingsModal() { DatabaseEncryptionView(it) },
iconColor = if (unencrypted || (appPlatform.isDesktop && passphraseSaved)) WarningOrange else MaterialTheme.colors.secondary,
disabled = operationsDisabled
)
if (appPlatform.isDesktop && developerTools) {
SettingsActionItem(
painterResource(MR.images.ic_folder_open),
stringResource(MR.strings.open_database_folder),
::desktopOpenDatabaseDir,
disabled = operationsDisabled
)
}
SettingsActionItem(
painterResource(MR.images.ic_ios_share),
stringResource(MR.strings.export_database),
click = {
if (initialRandomDBPassphrase.get()) {
exportProhibitedAlert()
} else {
exportArchive()
}
},
textColor = MaterialTheme.colors.primary,
iconColor = MaterialTheme.colors.primary,
disabled = operationsDisabled
)
SettingsActionItem(
painterResource(MR.images.ic_download),
stringResource(MR.strings.import_database),
{ withApi { importArchiveLauncher.launch("application/zip") } },
textColor = Color.Red,
iconColor = Color.Red,
disabled = operationsDisabled
)
val chatArchiveNameVal = chatArchiveName.value
val chatArchiveTimeVal = chatArchiveTime.value
val chatLastStartVal = chatLastStart.value
if (chatArchiveNameVal != null && chatArchiveTimeVal != null && chatLastStartVal != null) {
val title = chatArchiveTitle(chatArchiveTimeVal, chatLastStartVal)
SettingsActionItem(
painterResource(MR.images.ic_inventory_2),
title,
click = showSettingsModal { ChatArchiveView(it, title, chatArchiveNameVal, chatArchiveTimeVal) },
disabled = operationsDisabled
)
}
SettingsActionItem(
painterResource(MR.images.ic_delete_forever),
stringResource(MR.strings.delete_database),
deleteChatAlert,
textColor = Color.Red,
iconColor = Color.Red,
disabled = operationsDisabled
)
}
SettingsActionItem(
painterResource(MR.images.ic_ios_share),
stringResource(MR.strings.export_database),
click = {
if (initialRandomDBPassphrase.get()) {
exportProhibitedAlert()
} else {
exportArchive()
}
},
textColor = MaterialTheme.colors.primary,
iconColor = MaterialTheme.colors.primary,
disabled = operationsDisabled
)
SettingsActionItem(
painterResource(MR.images.ic_download),
stringResource(MR.strings.import_database),
{ withApi { importArchiveLauncher.launch("application/zip") }},
textColor = Color.Red,
iconColor = Color.Red,
disabled = operationsDisabled
)
val chatArchiveNameVal = chatArchiveName.value
val chatArchiveTimeVal = chatArchiveTime.value
val chatLastStartVal = chatLastStart.value
if (chatArchiveNameVal != null && chatArchiveTimeVal != null && chatLastStartVal != null) {
val title = chatArchiveTitle(chatArchiveTimeVal, chatLastStartVal)
SettingsActionItem(
painterResource(MR.images.ic_inventory_2),
title,
click = showSettingsModal { ChatArchiveView(it, title, chatArchiveNameVal, chatArchiveTimeVal) },
disabled = operationsDisabled
)
}
SettingsActionItem(
painterResource(MR.images.ic_delete_forever),
stringResource(MR.strings.delete_database),
deleteChatAlert,
textColor = Color.Red,
iconColor = Color.Red,
disabled = operationsDisabled
)
}
SectionDividerSpaced(maxTopPadding = true)
SectionDividerSpaced(maxTopPadding = true)
SectionView(stringResource(MR.strings.files_and_media_section).uppercase()) {
val deleteFilesDisabled = operationsDisabled || appFilesCountAndSize.value.first == 0
SectionItemView(
deleteAppFilesAndMedia,
disabled = deleteFilesDisabled
) {
Text(
stringResource(if (users.size > 1) MR.strings.delete_files_and_media_for_all_users else MR.strings.delete_files_and_media_all),
color = if (deleteFilesDisabled) MaterialTheme.colors.secondary else Color.Red
)
SectionView(stringResource(MR.strings.files_and_media_section).uppercase()) {
val deleteFilesDisabled = operationsDisabled || appFilesCountAndSize.value.first == 0
SectionItemView(
deleteAppFilesAndMedia,
disabled = deleteFilesDisabled
) {
Text(
stringResource(if (users.size > 1) MR.strings.delete_files_and_media_for_all_users else MR.strings.delete_files_and_media_all),
color = if (deleteFilesDisabled) MaterialTheme.colors.secondary else Color.Red
)
}
}
val (count, size) = appFilesCountAndSize.value
SectionTextFooter(
if (count == 0) {
stringResource(MR.strings.no_received_app_files)
} else {
String.format(stringResource(MR.strings.total_files_count_and_size), count, formatBytes(size))
}
)
}
val (count, size) = appFilesCountAndSize.value
SectionTextFooter(
if (count == 0) {
stringResource(MR.strings.no_received_app_files)
} else {
String.format(stringResource(MR.strings.total_files_count_and_size), count, formatBytes(size))
}
)
SectionBottomSpacer()
}
}
@ -666,6 +673,7 @@ private fun operationEnded(m: ChatModel, progressIndicator: MutableState<Boolean
fun PreviewDatabaseLayout() {
SimpleXTheme {
DatabaseLayout(
currentRemoteHost = null,
progressIndicator = false,
runChat = true,
chatDbChanged = false,

View File

@ -125,7 +125,7 @@ fun DefaultConfigurableTextField(
keyboardType: KeyboardType = KeyboardType.Text,
dependsOn: State<Any?>? = null,
) {
var valid by remember { mutableStateOf(validKey(state.value.text)) }
var valid by remember { mutableStateOf(isValid(state.value.text)) }
var showKey by remember { mutableStateOf(false) }
val icon = if (valid) {
if (showKey) painterResource(MR.images.ic_visibility_off_filled) else painterResource(MR.images.ic_visibility_filled)

View File

@ -67,7 +67,7 @@ fun CreateLinkView(m: ChatModel, rh: RemoteHostInfo?, initialSelection: CreateLi
AddContactView(m, rh,connReqInvitation.value ?: "", contactConnection)
}
CreateLinkTab.LONG_TERM -> {
UserAddressView(m, rh?.remoteHostId, viaCreateLinkView = true, close = {})
UserAddressView(m, viaCreateLinkView = true, close = {})
}
}
}

View File

@ -21,6 +21,7 @@ import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@ -37,6 +38,7 @@ import chat.simplex.common.views.newchat.QRCodeScanner
import chat.simplex.common.views.usersettings.PreferenceToggle
import chat.simplex.common.views.usersettings.SettingsActionItem
import chat.simplex.res.MR
import dev.icerock.moko.resources.ImageResource
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
@ -69,15 +71,21 @@ fun ConnectDesktopView(close: () -> Unit) {
@Composable
private fun ConnectDesktopLayout(deviceName: String, close: () -> Unit) {
val showConnectScreen = remember { mutableStateOf(true) }
val sessionAddress = remember { mutableStateOf("") }
val remoteCtrls = remember { mutableStateListOf<RemoteCtrlInfo>() }
val session = remember { chatModel.remoteCtrlSession }.value
Column(
Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
) {
if (session != null) {
val discovery = if (session == null) null else session.sessionState is UIRemoteCtrlSessionState.Searching
if (discovery == true || (discovery == null && !showConnectScreen.value)) {
SearchingDesktop(deviceName, remoteCtrls)
} else if (session != null) {
when (session.sessionState) {
is UIRemoteCtrlSessionState.Starting -> ConnectingDesktop(session, null)
is UIRemoteCtrlSessionState.Searching -> SearchingDesktop(deviceName, remoteCtrls)
is UIRemoteCtrlSessionState.Found -> FoundDesktop(session, session.sessionState.remoteCtrl, session.sessionState.compatible, remember { controller.appPrefs.connectRemoteViaMulticastAuto.state }, deviceName, remoteCtrls, sessionAddress)
is UIRemoteCtrlSessionState.Connecting -> ConnectingDesktop(session, session.sessionState.remoteCtrl_)
is UIRemoteCtrlSessionState.PendingConfirmation -> {
if (controller.appPrefs.confirmRemoteSessions.get() || session.sessionState.remoteCtrl_ == null) {
@ -97,11 +105,21 @@ private fun ConnectDesktopLayout(deviceName: String, close: () -> Unit) {
}
SectionBottomSpacer()
}
DisposableEffect(Unit) {
LaunchedEffect(Unit) {
setDeviceName(deviceName)
updateRemoteCtrls(remoteCtrls)
val useMulticast = useMulticast(remoteCtrls)
showConnectScreen.value = !useMulticast
if (chatModel.remoteCtrlSession.value != null) {
disconnectDesktop()
} else if (useMulticast) {
findKnownDesktop(showConnectScreen)
}
}
DisposableEffect(Unit) {
onDispose {
if (chatModel.remoteCtrlSession.value != null) {
showConnectScreen.value = false
disconnectDesktop()
}
}
@ -146,7 +164,75 @@ private fun ConnectingDesktop(session: RemoteCtrlSession, rc: RemoteCtrlInfo?) {
SectionSpacer()
SectionView {
DisconnectButton(::disconnectDesktop)
DisconnectButton(onClick = ::disconnectDesktop)
}
}
@Composable
private fun SearchingDesktop(deviceName: String, remoteCtrls: SnapshotStateList<RemoteCtrlInfo>) {
AppBarTitle(stringResource(MR.strings.connecting_to_desktop))
SectionView(stringResource(MR.strings.this_device_name).uppercase()) {
DevicesView(deviceName, remoteCtrls) {
if (it != "") {
setDeviceName(it)
controller.appPrefs.deviceNameForRemoteAccess.set(it)
}
}
}
SectionDividerSpaced()
SectionView(stringResource(MR.strings.found_desktop).uppercase(), padding = PaddingValues(horizontal = DEFAULT_PADDING)) {
Text(stringResource(MR.strings.waiting_for_desktop), fontStyle = FontStyle.Italic)
}
SectionSpacer()
DisconnectButton(stringResource(MR.strings.scan_QR_code).replace('\n', ' '), MR.images.ic_qr_code, ::disconnectDesktop)
}
@Composable
private fun FoundDesktop(
session: RemoteCtrlSession,
rc: RemoteCtrlInfo,
compatible: Boolean,
connectRemoteViaMulticastAuto: State<Boolean>,
deviceName: String,
remoteCtrls: SnapshotStateList<RemoteCtrlInfo>,
sessionAddress: MutableState<String>,
) {
AppBarTitle(stringResource(MR.strings.found_desktop))
SectionView(stringResource(MR.strings.this_device_name).uppercase()) {
DevicesView(deviceName, remoteCtrls) {
if (it != "") {
setDeviceName(it)
controller.appPrefs.deviceNameForRemoteAccess.set(it)
}
}
}
SectionDividerSpaced()
SectionView(stringResource(MR.strings.found_desktop).uppercase(), padding = PaddingValues(horizontal = DEFAULT_PADDING)) {
CtrlDeviceNameText(session, rc)
CtrlDeviceVersionText(session)
if (!compatible) {
Text(stringResource(MR.strings.not_compatible), color = MaterialTheme.colors.error)
}
}
SectionSpacer()
if (compatible) {
SectionItemView({ confirmKnownDesktop(sessionAddress, rc) }) {
Icon(painterResource(MR.images.ic_check), generalGetString(MR.strings.connect_button), tint = MaterialTheme.colors.secondary)
TextIconSpaced(false)
Text(generalGetString(MR.strings.connect_button))
}
}
if (!compatible || !connectRemoteViaMulticastAuto.value) {
DisconnectButton(stringResource(MR.strings.cancel_verb), onClick = ::disconnectDesktop)
}
if (compatible && connectRemoteViaMulticastAuto.value) {
LaunchedEffect(Unit) {
confirmKnownDesktop(sessionAddress, rc)
}
}
}
@ -174,7 +260,7 @@ private fun VerifySession(session: RemoteCtrlSession, rc: RemoteCtrlInfo?, sessC
}
SectionView {
DisconnectButton(::disconnectDesktop)
DisconnectButton(onClick = ::disconnectDesktop)
}
}
@ -182,7 +268,7 @@ private fun VerifySession(session: RemoteCtrlSession, rc: RemoteCtrlInfo?, sessC
private fun CtrlDeviceNameText(session: RemoteCtrlSession, rc: RemoteCtrlInfo?) {
val newDesktop = annotatedStringResource(MR.strings.new_desktop)
val text = remember(rc) {
var t = AnnotatedString(rc?.deviceViewName ?: session.ctrlAppInfo.deviceName)
var t = AnnotatedString(rc?.deviceViewName ?: session.ctrlAppInfo?.deviceName ?: "")
if (rc == null) {
t = t + AnnotatedString(" ") + newDesktop
}
@ -195,7 +281,7 @@ private fun CtrlDeviceNameText(session: RemoteCtrlSession, rc: RemoteCtrlInfo?)
private fun CtrlDeviceVersionText(session: RemoteCtrlSession) {
val thisDeviceVersion = annotatedStringResource(MR.strings.this_device_version, session.appVersion)
val text = remember(session) {
val v = AnnotatedString(session.ctrlAppInfo.appVersionRange.maxVersion)
val v = AnnotatedString(session.ctrlAppInfo?.appVersionRange?.maxVersion ?: "")
var t = AnnotatedString("v$v")
if (v.text != session.appVersion) {
t = t + AnnotatedString(" ") + thisDeviceVersion
@ -243,7 +329,8 @@ private fun SessionCodeText(code: String) {
private fun DevicesView(deviceName: String, remoteCtrls: SnapshotStateList<RemoteCtrlInfo>, updateDeviceName: (String) -> Unit) {
DeviceNameField(deviceName) { updateDeviceName(it) }
if (remoteCtrls.isNotEmpty()) {
SectionItemView({ ModalManager.start.showModal { LinkedDesktopsView(remoteCtrls) } }) {
SectionItemView({ ModalManager.start.showModal { LinkedDesktopsView(remoteCtrls) }
}) {
Text(generalGetString(MR.strings.linked_desktops))
}
}
@ -336,8 +423,13 @@ private fun LinkedDesktopsView(remoteCtrls: SnapshotStateList<RemoteCtrlInfo>) {
PreferenceToggle(stringResource(MR.strings.verify_connections), remember { controller.appPrefs.confirmRemoteSessions.state }.value) {
controller.appPrefs.confirmRemoteSessions.set(it)
}
PreferenceToggle(stringResource(MR.strings.discover_on_network), remember { controller.appPrefs.connectRemoteViaMulticast.state }.value && false) {
controller.appPrefs.confirmRemoteSessions.set(it)
PreferenceToggle(stringResource(MR.strings.discover_on_network), remember { controller.appPrefs.connectRemoteViaMulticast.state }.value) {
controller.appPrefs.connectRemoteViaMulticast.set(it)
}
if (remember { controller.appPrefs.connectRemoteViaMulticast.state }.value) {
PreferenceToggle(stringResource(MR.strings.multicast_connect_automatically), remember { controller.appPrefs.connectRemoteViaMulticastAuto.state }.value) {
controller.appPrefs.connectRemoteViaMulticastAuto.set(it)
}
}
}
SectionBottomSpacer()
@ -355,13 +447,11 @@ private fun setDeviceName(name: String) {
}
}
private fun updateRemoteCtrls(remoteCtrls: SnapshotStateList<RemoteCtrlInfo>) {
withBGApi {
val res = controller.listRemoteCtrls()
if (res != null) {
remoteCtrls.clear()
remoteCtrls.addAll(res)
}
private suspend fun updateRemoteCtrls(remoteCtrls: SnapshotStateList<RemoteCtrlInfo>) {
val res = controller.listRemoteCtrls()
if (res != null) {
remoteCtrls.clear()
remoteCtrls.addAll(res)
}
}
@ -369,9 +459,34 @@ private fun processDesktopQRCode(sessionAddress: MutableState<String>, resp: Str
connectDesktopAddress(sessionAddress, resp)
}
private fun connectDesktopAddress(sessionAddress: MutableState<String>, addr: String) {
private fun findKnownDesktop(showConnectScreen: MutableState<Boolean>) {
withBGApi {
val res = controller.connectRemoteCtrl(desktopAddress = addr)
if (controller.findKnownRemoteCtrl()) {
chatModel.remoteCtrlSession.value = RemoteCtrlSession(
ctrlAppInfo = null,
appVersion = "",
sessionState = UIRemoteCtrlSessionState.Searching
)
showConnectScreen.value = true
}
}
}
private fun confirmKnownDesktop(sessionAddress: MutableState<String>, rc: RemoteCtrlInfo) {
connectDesktop(sessionAddress) {
controller.confirmRemoteCtrl(rc.remoteCtrlId)
}
}
private fun connectDesktopAddress(sessionAddress: MutableState<String>, addr: String) {
connectDesktop(sessionAddress) {
controller.connectRemoteCtrl(addr)
}
}
private fun connectDesktop(sessionAddress: MutableState<String>, connect: suspend () -> Pair<SomeRemoteCtrl?, CR.ChatCmdError?>) {
withBGApi {
val res = connect()
if (res.first != null) {
val (rc_, ctrlAppInfo, v) = res.first!!
sessionAddress.value = ""
@ -409,18 +524,25 @@ private fun verifyDesktopSessionCode(remoteCtrls: SnapshotStateList<RemoteCtrlIn
}
@Composable
private fun DisconnectButton(onClick: () -> Unit) {
private fun DisconnectButton(label: String = generalGetString(MR.strings.disconnect_remote_host), icon: ImageResource = MR.images.ic_close, onClick: () -> Unit) {
SectionItemView(onClick) {
Icon(painterResource(MR.images.ic_close), generalGetString(MR.strings.disconnect_remote_host), tint = MaterialTheme.colors.secondary)
Icon(painterResource(icon), label, tint = MaterialTheme.colors.secondary)
TextIconSpaced(false)
Text(generalGetString(MR.strings.disconnect_remote_host))
Text(label)
}
}
private fun useMulticast(remoteCtrls: List<RemoteCtrlInfo>): Boolean =
controller.appPrefs.connectRemoteViaMulticast.get() && remoteCtrls.isNotEmpty()
private fun disconnectDesktop(close: (() -> Unit)? = null) {
withBGApi {
controller.stopRemoteCtrl()
switchToLocalSession()
if (chatModel.remoteCtrlSession.value?.sessionState is UIRemoteCtrlSessionState.Connected) {
switchToLocalSession()
} else {
chatModel.remoteCtrlSession.value = null
}
close?.invoke()
}
}

View File

@ -30,6 +30,7 @@ import chat.simplex.common.views.chat.item.ItemAction
import chat.simplex.common.views.chatlist.*
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.newchat.QRCode
import chat.simplex.common.views.usersettings.PreferenceToggle
import chat.simplex.common.views.usersettings.SettingsActionItemWithContent
import chat.simplex.res.MR
import dev.icerock.moko.resources.compose.painterResource
@ -90,6 +91,9 @@ fun ConnectMobileLayout(
SectionView(generalGetString(MR.strings.this_device_name).uppercase()) {
DeviceNameField(deviceName.value ?: "") { updateDeviceName(it) }
SectionTextFooter(generalGetString(MR.strings.this_device_name_shared_with_mobile))
PreferenceToggle(stringResource(MR.strings.multicast_discoverable_via_local_network), remember { controller.appPrefs.offerRemoteMulticast.state }.value) {
controller.appPrefs.offerRemoteMulticast.set(it)
}
SectionDividerSpaced(maxBottomPadding = false)
}
SectionView(stringResource(MR.strings.devices).uppercase()) {
@ -235,7 +239,7 @@ private fun showAddingMobileDevice(connecting: MutableState<Boolean>) {
ModalManager.start.showModalCloseable { close ->
val invitation = rememberSaveable { mutableStateOf<String?>(null) }
val port = rememberSaveable { mutableStateOf<String?>(null) }
val pairing = remember { chatModel.newRemoteHostPairing }
val pairing = remember { chatModel.remoteHostPairing }
val sessionCode = when (val state = pairing.value?.second) {
is RemoteHostSessionState.PendingConfirmation -> state.sessionCode
else -> null
@ -266,11 +270,12 @@ private fun showAddingMobileDevice(connecting: MutableState<Boolean>) {
}
DisposableEffect(Unit) {
withBGApi {
val r = chatModel.controller.startRemoteHost(null)
val r = chatModel.controller.startRemoteHost(null, controller.appPrefs.offerRemoteMulticast.get())
if (r != null) {
connecting.value = true
invitation.value = r.second
port.value = r.third
chatModel.remoteHostPairing.value = null to RemoteHostSessionState.Starting
}
}
onDispose {
@ -279,7 +284,7 @@ private fun showAddingMobileDevice(connecting: MutableState<Boolean>) {
chatController.stopRemoteHost(null)
}
}
chatModel.newRemoteHostPairing.value = null
chatModel.remoteHostPairing.value = null
}
}
}
@ -287,7 +292,7 @@ private fun showAddingMobileDevice(connecting: MutableState<Boolean>) {
private fun showConnectMobileDevice(rh: RemoteHostInfo, connecting: MutableState<Boolean>) {
ModalManager.start.showModalCloseable { close ->
val pairing = remember { chatModel.newRemoteHostPairing }
val pairing = remember { chatModel.remoteHostPairing }
val invitation = rememberSaveable { mutableStateOf<String?>(null) }
val port = rememberSaveable { mutableStateOf<String?>(null) }
val sessionCode = when (val state = pairing.value?.second) {
@ -308,13 +313,14 @@ private fun showConnectMobileDevice(rh: RemoteHostInfo, connecting: MutableState
)
var remoteHostId by rememberSaveable { mutableStateOf<Long?>(null) }
LaunchedEffect(Unit) {
val r = chatModel.controller.startRemoteHost(rh.remoteHostId)
val r = chatModel.controller.startRemoteHost(rh.remoteHostId, controller.appPrefs.offerRemoteMulticast.get())
if (r != null) {
val (rh_, inv) = r
connecting.value = true
remoteHostId = rh_?.remoteHostId
invitation.value = inv
port.value = r.third
chatModel.remoteHostPairing.value = null to RemoteHostSessionState.Starting
}
}
LaunchedEffect(remember { chatModel.currentRemoteHost }.value) {
@ -334,7 +340,7 @@ private fun showConnectMobileDevice(rh: RemoteHostInfo, connecting: MutableState
chatController.stopRemoteHost(remoteHostId)
}
}
chatModel.newRemoteHostPairing.value = null
chatModel.remoteHostPairing.value = null
}
}
}

View File

@ -28,7 +28,6 @@ import chat.simplex.common.model.*
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.chat.item.ClickableText
import chat.simplex.common.views.helpers.*
import chat.simplex.common.model.*
import chat.simplex.common.views.helpers.annotatedStringResource
import chat.simplex.res.MR
@ -39,6 +38,7 @@ fun NetworkAndServersView(
showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit),
showCustomModal: (@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit),
) {
val currentRemoteHost by remember { chatModel.currentRemoteHost }
// It's not a state, just a one-time value. Shouldn't be used in any state-related situations
val netCfg = remember { chatModel.controller.getNetCfg() }
val networkUseSocksProxy: MutableState<Boolean> = remember { mutableStateOf(netCfg.useSocksProxy) }
@ -52,6 +52,7 @@ fun NetworkAndServersView(
val proxyPort = remember { derivedStateOf { chatModel.controller.appPrefs.networkProxyHostPort.state.value?.split(":")?.lastOrNull()?.toIntOrNull() ?: 9050 } }
NetworkAndServersLayout(
currentRemoteHost = currentRemoteHost,
developerTools = developerTools,
networkUseSocksProxy = networkUseSocksProxy,
onionHosts = onionHosts,
@ -150,6 +151,7 @@ fun NetworkAndServersView(
}
@Composable fun NetworkAndServersLayout(
currentRemoteHost: RemoteHostInfo?,
developerTools: Boolean,
networkUseSocksProxy: MutableState<Boolean>,
onionHosts: MutableState<OnionHosts>,
@ -172,14 +174,16 @@ fun NetworkAndServersView(
SettingsActionItem(painterResource(MR.images.ic_dns), stringResource(MR.strings.xftp_servers), showCustomModal { m, close -> ProtocolServersView(m, m.remoteHostId, ServerProtocol.XFTP, close) })
UseSocksProxySwitch(networkUseSocksProxy, proxyPort, toggleSocksProxy, showSettingsModal)
UseOnionHosts(onionHosts, networkUseSocksProxy, showSettingsModal, useOnion)
if (developerTools) {
SessionModePicker(sessionMode, showSettingsModal, updateSessionMode)
if (currentRemoteHost == null) {
UseSocksProxySwitch(networkUseSocksProxy, proxyPort, toggleSocksProxy, showSettingsModal)
UseOnionHosts(onionHosts, networkUseSocksProxy, showSettingsModal, useOnion)
if (developerTools) {
SessionModePicker(sessionMode, showSettingsModal, updateSessionMode)
}
SettingsActionItem(painterResource(MR.images.ic_cable), stringResource(MR.strings.network_settings), showSettingsModal { AdvancedNetworkSettingsView(it) })
}
SettingsActionItem(painterResource(MR.images.ic_cable), stringResource(MR.strings.network_settings), showSettingsModal { AdvancedNetworkSettingsView(it) })
}
if (networkUseSocksProxy.value) {
if (currentRemoteHost == null && networkUseSocksProxy.value) {
SectionCustomFooter {
Column {
Text(annotatedStringResource(MR.strings.disable_onion_hosts_when_not_supported))
@ -448,6 +452,7 @@ private fun showUpdateNetworkSettingsDialog(
fun PreviewNetworkAndServersLayout() {
SimpleXTheme {
NetworkAndServersLayout(
currentRemoteHost = null,
developerTools = true,
networkUseSocksProxy = remember { mutableStateOf(true) },
proxyPort = remember { mutableStateOf(9050) },

View File

@ -21,7 +21,10 @@ import chat.simplex.res.MR
fun PreferencesView(m: ChatModel, user: User, close: () -> Unit,) {
var preferences by rememberSaveable(stateSaver = serializableSaver()) { mutableStateOf(user.fullPreferences) }
var currentPreferences by rememberSaveable(stateSaver = serializableSaver()) { mutableStateOf(preferences) }
val u = remember { m.currentUser }
KeyChangeEffect(u.value?.remoteHostId, u.value?.userId) {
close()
}
fun savePrefs(afterSave: () -> Unit = {}) {
withApi {
val newProfile = user.profile.toProfile().copy(preferences = preferences.toPreferences())

View File

@ -155,7 +155,7 @@ fun SettingsLayout(
}
val profileHidden = rememberSaveable { mutableStateOf(false) }
SettingsActionItem(painterResource(MR.images.ic_manage_accounts), stringResource(MR.strings.your_chat_profiles), { withAuth(generalGetString(MR.strings.auth_open_chat_profiles), generalGetString(MR.strings.auth_log_in_using_credential)) { showSettingsModalWithSearch { it, search -> UserProfilesView(it, search, profileHidden) } } }, disabled = stopped, extraPadding = true)
SettingsActionItem(painterResource(MR.images.ic_qr_code), stringResource(MR.strings.your_simplex_contact_address), showCustomModal { it, close -> UserAddressView(it, it.currentUser.value?.remoteHostId, shareViaProfile = it.currentUser.value!!.addressShared, close = close) }, disabled = stopped, extraPadding = true)
SettingsActionItem(painterResource(MR.images.ic_qr_code), stringResource(MR.strings.your_simplex_contact_address), showCustomModal { it, close -> UserAddressView(it, shareViaProfile = it.currentUser.value!!.addressShared, close = close) }, disabled = stopped, extraPadding = true)
ChatPreferencesItem(showCustomModal, stopped = stopped)
if (appPlatform.isDesktop) {
SettingsActionItem(painterResource(MR.images.ic_smartphone), stringResource(if (remember { chatModel.remoteHosts }.isEmpty()) MR.strings.link_a_mobile else MR.strings.linked_mobiles), showModal { ConnectMobileView() }, disabled = stopped, extraPadding = true)

View File

@ -33,7 +33,6 @@ import chat.simplex.res.MR
@Composable
fun UserAddressView(
chatModel: ChatModel,
rhId: Long?,
viaCreateLinkView: Boolean = false,
shareViaProfile: Boolean = false,
close: () -> Unit
@ -42,12 +41,15 @@ fun UserAddressView(
val shareViaProfile = remember { mutableStateOf(shareViaProfile) }
var progressIndicator by remember { mutableStateOf(false) }
val onCloseHandler: MutableState<(close: () -> Unit) -> Unit> = remember { mutableStateOf({ _ -> }) }
val user = remember { chatModel.currentUser }
KeyChangeEffect(user.value?.remoteHostId, user.value?.userId) {
close()
}
fun setProfileAddress(on: Boolean) {
progressIndicator = true
withBGApi {
try {
val u = chatModel.controller.apiSetProfileAddress(rhId, on)
val u = chatModel.controller.apiSetProfileAddress(user?.value?.remoteHostId, on)
if (u != null) {
chatModel.updateUser(u)
}
@ -63,14 +65,14 @@ fun UserAddressView(
val uriHandler = LocalUriHandler.current
val showLayout = @Composable {
UserAddressLayout(
user = user.value,
userAddress = userAddress.value,
shareViaProfile,
rhId,
onCloseHandler,
createAddress = {
withApi {
progressIndicator = true
val connReqContact = chatModel.controller.apiCreateUserAddress(rhId)
val connReqContact = chatModel.controller.apiCreateUserAddress(user?.value?.remoteHostId)
if (connReqContact != null) {
chatModel.userAddress.value = UserContactLinkRec(connReqContact)
@ -115,7 +117,7 @@ fun UserAddressView(
onConfirm = {
progressIndicator = true
withApi {
val u = chatModel.controller.apiDeleteUserAddress(rhId)
val u = chatModel.controller.apiDeleteUserAddress(user?.value?.remoteHostId)
if (u != null) {
chatModel.userAddress.value = null
chatModel.updateUser(u)
@ -129,7 +131,7 @@ fun UserAddressView(
},
saveAas = { aas: AutoAcceptState, savedAAS: MutableState<AutoAcceptState> ->
withBGApi {
val address = chatModel.controller.userAddressAutoAccept(rhId, aas.autoAccept)
val address = chatModel.controller.userAddressAutoAccept(user?.value?.remoteHostId, aas.autoAccept)
if (address != null) {
chatModel.userAddress.value = address
savedAAS.value = aas
@ -168,9 +170,9 @@ fun UserAddressView(
@Composable
private fun UserAddressLayout(
user: User?,
userAddress: UserContactLinkRec?,
shareViaProfile: MutableState<Boolean>,
rhId: Long?,
onCloseHandler: MutableState<(close: () -> Unit) -> Unit>,
createAddress: () -> Unit,
learnMore: () -> Unit,
@ -183,7 +185,7 @@ private fun UserAddressLayout(
Column(
Modifier.verticalScroll(rememberScrollState()),
) {
AppBarTitle(stringResource(MR.strings.simplex_address), hostDevice(rhId), withPadding = false)
AppBarTitle(stringResource(MR.strings.simplex_address), hostDevice(user?.remoteHostId), withPadding = false)
Column(
Modifier.fillMaxWidth().padding(bottom = DEFAULT_PADDING_HALF),
horizontalAlignment = Alignment.CenterHorizontally,
@ -432,6 +434,7 @@ private fun SaveAASButton(disabled: Boolean, onClick: () -> Unit) {
fun PreviewUserAddressLayoutNoAddress() {
SimpleXTheme {
UserAddressLayout(
user = User.sampleData,
userAddress = null,
createAddress = {},
share = { _ -> },
@ -440,7 +443,6 @@ fun PreviewUserAddressLayoutNoAddress() {
setProfileAddress = { _ -> },
learnMore = {},
shareViaProfile = remember { mutableStateOf(false) },
rhId = null,
onCloseHandler = remember { mutableStateOf({}) },
sendEmail = {},
)
@ -466,6 +468,7 @@ private fun showUnsavedChangesAlert(save: () -> Unit, revert: () -> Unit) {
fun PreviewUserAddressLayoutAddressCreated() {
SimpleXTheme {
UserAddressLayout(
user = User.sampleData,
userAddress = UserContactLinkRec("https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D"),
createAddress = {},
share = { _ -> },
@ -474,7 +477,6 @@ fun PreviewUserAddressLayoutAddressCreated() {
setProfileAddress = { _ -> },
learnMore = {},
shareViaProfile = remember { mutableStateOf(false) },
rhId = null,
onCloseHandler = remember { mutableStateOf({}) },
sendEmail = {},
)

View File

@ -29,7 +29,11 @@ import java.net.URI
@Composable
fun UserProfileView(chatModel: ChatModel, close: () -> Unit) {
val user = chatModel.currentUser.value
val u = remember {chatModel.currentUser}
val user = u.value
KeyChangeEffect(u.value?.remoteHostId, u.value?.userId) {
close()
}
if (user != null) {
var profile by remember { mutableStateOf(user.profile.toProfile()) }
UserProfileLayout(

View File

@ -1404,4 +1404,12 @@
<string name="v5_3_simpler_incognito_mode_descr">فعّل وضع التخفي عند الاتصال.</string>
<string name="member_contact_send_direct_message">أرسل رسالة مباشرة</string>
<string name="rcv_group_event_member_created_contact">متصل مباشرةً</string>
<string name="connect_plan_already_connecting">جارٍ الاتصال بالفعل!</string>
<string name="v5_4_better_groups">مجموعات أفضل</string>
<string name="rcv_group_and_other_events">و%d أحداث أخرى</string>
<string name="connect_plan_already_joining_the_group">جارٍ انضمام بالفعل إلى المجموعة!</string>
<string name="block_member_confirmation">حجب</string>
<string name="bad_desktop_address">عنوان سطح المكتب غير صالح</string>
<string name="block_member_desc">سيتم إخفاء كافة الرسائل الجديدة من %s!</string>
<string name="blocked_item_description">محجوب</string>
</resources>

View File

@ -1670,6 +1670,8 @@
<string name="desktop_connection_terminated">Connection terminated</string>
<string name="session_code">Session code</string>
<string name="connecting_to_desktop">Connecting to desktop</string>
<string name="waiting_for_desktop">Waiting for desktop…</string>
<string name="found_desktop">Found desktop</string>
<string name="connect_to_desktop">Connect to desktop</string>
<string name="connected_to_desktop">Connected to desktop</string>
<string name="connected_desktop">Connected desktop</string>
@ -1681,9 +1683,12 @@
<string name="scan_qr_code_from_desktop">Scan QR code from desktop</string>
<string name="desktop_address">Desktop address</string>
<string name="verify_connections">Verify connections</string>
<string name="discover_on_network">Discover on network</string>
<string name="discover_on_network">Discover via local network</string>
<string name="multicast_discoverable_via_local_network">Discoverable via local network</string>
<string name="multicast_connect_automatically">Connect automatically</string>
<string name="paste_desktop_address">Paste desktop address</string>
<string name="desktop_device">Desktop</string>
<string name="not_compatible">Not compatible!</string>
<!-- Under development -->
<string name="in_developing_title">Coming soon!</string>

View File

@ -1542,4 +1542,67 @@
<string name="blocked_item_description">blockiert</string>
<string name="encryption_renegotiation_error">Fehler bei der Neuverhandlung der Verschlüsselung</string>
<string name="alert_text_encryption_renegotiation_failed">Neuverhandlung der Verschlüsselung fehlgeschlagen</string>
<string name="v5_4_block_group_members">Gruppenmitglieder blockieren</string>
<string name="v5_4_incognito_groups_descr">Erstellen Sie eine Gruppe mit einem zufälligen Profil.</string>
<string name="connected_desktop">Verbundener Desktop</string>
<string name="desktop_address">Desktop-Adresse</string>
<string name="v5_4_better_groups">Bessere Gruppen</string>
<string name="discover_on_network">Lokales Netzwerk durchsuchen</string>
<string name="desktop_device">Desktop</string>
<string name="connected_to_desktop">Mit dem Desktop verbunden</string>
<string name="connecting_to_desktop">Mit dem Desktop verbinden</string>
<string name="desktop_devices">Desktop-Geräte</string>
<string name="connected_mobile">Verbundenes Mobiltelefon</string>
<string name="desktop_connection_terminated">Verbindung beendet</string>
<string name="enter_this_device_name">Geben Sie diesen Gerätenamen ein…</string>
<string name="error">Fehler</string>
<string name="connect_to_desktop">Mit dem Desktop verbinden</string>
<string name="disconnect_remote_host">Trenne Verbindung</string>
<string name="group_member_role_author">Autor</string>
<string name="connected_to_mobile">Mit dem Mobiltelefon verbunden</string>
<string name="bad_desktop_address">Falsche Desktop-Adresse</string>
<string name="devices">Geräte</string>
<string name="disconnect_desktop_question">Desktop-Verbindung trennen?</string>
<string name="desktop_app_version_is_incompatible">Desktop-App-Version %s ist mit dieser App nicht kompatibel.</string>
<string name="new_mobile_device">Neues Mobiltelefon-Gerät</string>
<string name="only_one_device_can_work_at_the_same_time">Nur ein Gerät kann gleichzeitig genutzt werden</string>
<string name="v5_4_link_mobile_desktop">Verknüpfe Mobiltelefon- und Desktop-Apps! 🔗</string>
<string name="v5_4_link_mobile_desktop_descr">Über ein sicheres quantenbeständiges Protokoll</string>
<string name="open_on_mobile_and_scan_qr_code"><![CDATA[Öffnen Sie in den Einstellungen der Mobiltelefon-App <i>Vom Desktop aus nutzen</i> und scannen Sie den QR-Code.]]></string>
<string name="v5_4_block_group_members_descr">Um unerwünschte Nachrichten zu verbergen.</string>
<string name="desktop_incompatible_version">Inkompatible Version</string>
<string name="new_desktop"><![CDATA[<i>(Neu)</i>]]></string>
<string name="unlink_desktop_question">Desktop entkoppeln?</string>
<string name="linked_desktop_options">Verknüpfte Desktop-Optionen</string>
<string name="linked_desktops">Verknüpfte Desktops</string>
<string name="v5_4_incognito_groups">Inkognito-Gruppen</string>
<string name="this_device">Dieses Gerät</string>
<string name="remote_host_was_disconnected_toast"><![CDATA[Mobiltelefon <b>%s</b> wurde getrennt]]></string>
<string name="v5_4_better_groups_descr">Schnellerer Gruppenbeitritt und zuverlässigere Nachrichtenzustellung.</string>
<string name="linked_mobiles">Verknüpfte Mobiltelefone</string>
<string name="this_device_name">Dieser Gerätename</string>
<string name="waiting_for_mobile_to_connect_on_port"><![CDATA[Auf die Mobiltelefonverbindung über Port <i>%s</i> warten]]></string>
<string name="loading_remote_file_title">Laden der Datei</string>
<string name="link_a_mobile">Zu einem Mobiltelefon verbinden</string>
<string name="settings_section_title_use_from_desktop">Vom Desktop aus nutzen</string>
<string name="session_code">Sitzungscode</string>
<string name="this_device_version"><![CDATA[<i>(Dieses Gerät hat v%s)</i>]]></string>
<string name="unlink_desktop">Entkoppeln</string>
<string name="this_device_name_shared_with_mobile">Der Gerätename wird mit dem verbundenen Mobiltelefon-Client geteilt.</string>
<string name="verify_code_on_mobile">Code auf dem Mobiltelefon überprüfen</string>
<string name="paste_desktop_address">Desktop-Adresse einfügen</string>
<string name="verify_code_with_desktop">Code mit dem Desktop überprüfen</string>
<string name="scan_qr_code_from_desktop">Den QR-Code vom Desktop scannen</string>
<string name="v5_4_more_things_descr">- Optionale Benachrichtigung von gelöschten Kontakten.
\n- Profilnamen mit Leerzeichen.
\n- Und mehr!</string>
<string name="scan_from_mobile">Vom Mobiltelefon scannen</string>
<string name="verify_connections">Verbindungen überprüfen</string>
<string name="loading_remote_file_desc">Bitte warten Sie, solange die Datei von dem verknüpften Mobiltelefon geladen wird</string>
<string name="verify_connection">Verbindung überprüfen</string>
<string name="multicast_connect_automatically">Automatisch verbinden</string>
<string name="waiting_for_desktop">Auf Desktop warten…</string>
<string name="found_desktop">Gefundener Desktop</string>
<string name="not_compatible">Nicht kompatibel!</string>
<string name="multicast_discoverable_via_local_network">Über das lokale Netzwerk auffindbar</string>
</resources>

View File

@ -1461,4 +1461,62 @@
<string name="blocked_item_description">blocké</string>
<string name="encryption_renegotiation_error">Erreur lors de la renégociation du chiffrement</string>
<string name="alert_text_encryption_renegotiation_failed">La renégociation du chiffrement a échoué.</string>
<string name="v5_4_block_group_members">Bloquer des membres d\'un groupe</string>
<string name="v5_4_incognito_groups_descr">Création de groupes via un profil aléatoire.</string>
<string name="connected_desktop">Bureau connecté</string>
<string name="new_mobile_device">Nouvel appareil mobile</string>
<string name="desktop_address">Adresse de bureau</string>
<string name="only_one_device_can_work_at_the_same_time">Un seul appareil peut fonctionner en même temps</string>
<string name="v5_4_link_mobile_desktop">Liez vos applications mobiles et de bureau ! 🔗</string>
<string name="v5_4_link_mobile_desktop_descr">Via un protocole sécurisé de cryptographie post-quantique.</string>
<string name="open_on_mobile_and_scan_qr_code"><![CDATA[Ouvrez <i>Utiliser depuis le bureau</i> dans l\'application mobile et scannez le code QR.]]></string>
<string name="v5_4_block_group_members_descr">Pour cacher les messages indésirables.</string>
<string name="desktop_incompatible_version">Version incompatible</string>
<string name="new_desktop"><![CDATA[<i>(nouveau)</i>]]></string>
<string name="unlink_desktop_question">Délier le bureau ?</string>
<string name="v5_4_better_groups">Des groupes plus performants</string>
<string name="linked_desktop_options">Options de bureau lié</string>
<string name="linked_desktops">Bureaux liés</string>
<string name="discover_on_network">Rechercher sur le réseau</string>
<string name="v5_4_incognito_groups">Groupes incognito</string>
<string name="this_device">Cet appareil</string>
<string name="remote_host_was_disconnected_toast"><![CDATA[Le mobile <b>%s</b> a été déconnecté]]></string>
<string name="v5_4_better_groups_descr">Connexion plus rapide et messages plus fiables.</string>
<string name="linked_mobiles">Mobiles liés</string>
<string name="desktop_device">Bureau</string>
<string name="connected_to_desktop">Connecté au bureau</string>
<string name="this_device_name">Ce nom d\'appareil</string>
<string name="waiting_for_mobile_to_connect_on_port"><![CDATA[En attente d\'une connexion mobile sur le port <i>%s</i>]]></string>
<string name="loading_remote_file_title">Chargement du fichier</string>
<string name="connecting_to_desktop">Connexion au bureau</string>
<string name="desktop_devices">Appareils de bureau</string>
<string name="link_a_mobile">Lier un portable</string>
<string name="settings_section_title_use_from_desktop">Utilisation depuis le bureau</string>
<string name="connected_mobile">Mobile connecté</string>
<string name="session_code">Code de session</string>
<string name="desktop_connection_terminated">Connexion terminée</string>
<string name="this_device_version"><![CDATA[<i>(cet appareil v%s)</i>]]></string>
<string name="unlink_desktop">Délier</string>
<string name="this_device_name_shared_with_mobile">Le nom de l\'appareil sera partagé avec le client mobile connecté.</string>
<string name="verify_code_on_mobile">Vérifier le code sur le mobile</string>
<string name="enter_this_device_name">Entrez le nom de l\'appareil…</string>
<string name="error">Erreur</string>
<string name="connect_to_desktop">Se connecter au bureau</string>
<string name="disconnect_remote_host">Se déconnecter</string>
<string name="group_member_role_author">auteur</string>
<string name="connected_to_mobile">Connecté au portable</string>
<string name="bad_desktop_address">Mauvaise adresse de bureau</string>
<string name="paste_desktop_address">Coller l\'adresse du bureau</string>
<string name="verify_code_with_desktop">Vérifier le code avec le bureau</string>
<string name="scan_qr_code_from_desktop">Scanner le code QR du bureau</string>
<string name="devices">Appareils</string>
<string name="v5_4_more_things_descr">- option pour notifier les contacts supprimés.
\n- noms de profil avec espaces.
\n- et plus encore !</string>
<string name="scan_from_mobile">Numériser depuis un mobile</string>
<string name="verify_connections">Vérifier les connexions</string>
<string name="disconnect_desktop_question">Déconnecter le bureau ?</string>
<string name="loading_remote_file_desc">Veuillez patienter le temps que le fichier soit chargé depuis le mobile lié.</string>
<string name="desktop_app_version_is_incompatible">La version de l\'application de bureau %s n\'est pas compatible avec cette application.</string>
<string name="verify_connection">Vérifier la connexion</string>
</resources>

View File

@ -0,0 +1,359 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="alert_text_decryption_error_n_messages_failed_to_decrypt">%1$d az üzenetek visszafejtése sikertelen</string>
<string name="alert_text_decryption_error_too_many_skipped">%1$d üzenetek kihagyva.</string>
<string name="integrity_msg_skipped">%1$d kihagyott üzenet(ek)</string>
<string name="group_info_section_title_num_members">%1$s TAGOK</string>
<string name="chat_item_ttl_month">1 hónap</string>
<string name="chat_item_ttl_week">1 hét</string>
<string name="v5_3_new_interface_languages">6 új kezelőfelület nyelv</string>
<string name="send_disappearing_message_5_minutes">5 perc</string>
<string name="send_disappearing_message_1_minute">1 perc</string>
<string name="learn_more_about_address">A SimpleX azonosítóról</string>
<string name="abort_switch_receiving_address_question">Címváltoztatás megszakítása?</string>
<string name="abort_switch_receiving_address_confirm">Megszakítás</string>
<string name="send_disappearing_message_30_seconds">30 másodperc</string>
<string name="one_time_link_short">Egyszer használatos link</string>
<string name="contact_wants_to_connect_via_call">%1$s szeretne kapcsolatba lépni veled</string>
<string name="about_simplex_chat">A SimpleX chatről</string>
<string name="chat_item_ttl_day">1 nap</string>
<string name="abort_switch_receiving_address">Címváltoztatás megszakítása</string>
<string name="about_simplex">A SimpleX-ről</string>
<string name="color_primary">Kiemelőszín</string>
<string name="callstatus_accepted">elfogadott hívás</string>
<string name="network_enable_socks_info">Kapcsolódás a szerverekhez SOCKS proxy segítségével a %d? porton? A proxyt el kell indítani mielőtt bekapcsolná ezt az opciót.</string>
<string name="accept_feature">Elfogad</string>
<string name="accept_call_on_lock_screen">Elfogad</string>
<string name="above_then_preposition_continuation">felül, majd pedig:</string>
<string name="accept_contact_incognito_button">Elfogadás inkognítóban</string>
<string name="accept_connection_request__question">Elfogadod a kapcsolatfelvételt?</string>
<string name="accept_contact_button">Elfogad</string>
<string name="accept">Elfogad</string>
<string name="add_address_to_your_profile">Add hozzá az azonosítót a profilodhoz, így a kapcsolataid megosztatják azt más emberekkel. A profilod változtatásai így frissítésre kerülnek a kapcsolataidnál is!</string>
<string name="color_primary_variant">További kiemelőszín</string>
<string name="callstatus_error">hiba a hívásban</string>
<string name="v5_4_block_group_members">Csoporttagok blokkolása</string>
<string name="la_authenticate">Hitelesítés</string>
<string name="empty_chat_profile_is_created">Egy üres chat profil létre lett hozva a megadott névvel és az app normál módon megnyílik.</string>
<string name="feature_cancelled_item">megszakítva %s</string>
<string name="smp_servers_preset_add">Adj hozzá egyedi szervereket</string>
<string name="calls_prohibited_with_this_contact">Hang-/videóhívások megtiltva.</string>
<string name="network_session_mode_entity_description">Külön TCP kapcsolat (és SOCKS bejelentkezési adatok) lesznek használva <b>minden ismerősre és csoport tagra</b>
\n<b>Tudnivaló</b>: ha sok ismerősöd van, az akkumulátor- és adat használatod jelentősen megnőhet és néhány kapcsolódási kísérlet sikertelen lehet.</string>
<string name="icon_descr_cancel_link_preview">URL link előnézet megszakítása</string>
<string name="network_session_mode_user_description"><![CDATA[Külön TCP kapcsolat (és SOCKS bejelentkezési adatok) lesznek használva <b>minden chat profilodra az appban</b>.]]></string>
<string name="both_you_and_your_contact_can_send_disappearing">Mindketten, te és az ismerősöd is küldhettek eltűnő üzeneteket.</string>
<string name="keychain_is_storing_securely">Az Android Keystore-t jelmondat biztonságos tárolására használják - lehetővé teszi az értesítési szolgáltatás működését.</string>
<string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>QR-kód beolvasása</b>: kapcsolódás ismerőshöz a megmutatott QR-kódja alapján]]></string>
<string name="alert_title_msg_bad_hash">Téves üzenet hash</string>
<string name="cant_delete_user_profile">Felhasználói profil törlése nem lehetséges!</string>
<string name="color_background">Háttér</string>
<string name="socks_proxy_setting_limitations"><![CDATA[<b>Tudnivaló</b>: az üzenet- és fájl relay szerverek SOCKS proxy által vannak kapcsolatban. A hívások és URL link előnézetek közvetlen kapcsolatot használnak.]]></string>
<string name="full_backup">App adatmentés</string>
<string name="database_initialization_error_title">Adatbázis inicializálása nem lehetséges</string>
<string name="all_your_contacts_will_remain_connected_update_sent">A kapcsolat megmarad az összes Ismerősöddel. Profil változtatások frissítésre kerülnek az ismerőseidnél.</string>
<string name="v4_5_transport_isolation_descr">Chat profile (alap beállítás) avagy kapcsolat által (BÉTA).</string>
<string name="connect__a_new_random_profile_will_be_shared">Egy új véletlenszerű profil lesz megosztva.</string>
<string name="allow_voice_messages_only_if">Hangüzenetek küldésének engedélyezése kizárólag az esetre ha a másik fél is engedélyezi.</string>
<string name="app_version_code">App build: %s</string>
<string name="audio_video_calls">Hang-/videóhívások</string>
<string name="network_settings">Haladó hálózati beállítások</string>
<string name="allow_your_contacts_to_send_voice_messages">Ismerősök küldhetnek hangüzeneteket engedélyezése.</string>
<string name="settings_audio_video_calls">Hang- és videóhívások</string>
<string name="v5_3_encrypt_local_files_descr">Az app titkosítja a helyi fájlokat (a videók kivételével).</string>
<string name="answer_call">Hívás fogadása</string>
<string name="allow_your_contacts_to_send_disappearing_messages">Ismerősök küldhetnek eltűnő üzeneteket engedélyezve.</string>
<string name="connect_plan_already_connecting">Már kapcsolódik!</string>
<string name="cannot_receive_file">Fájl fogadás nem lehetséges</string>
<string name="auth_unavailable">Hitelesítés elérhetetlen</string>
<string name="app_version_title">App verzió</string>
<string name="button_add_welcome_message">Üdvözlőszöveg hozzáadása</string>
<string name="snd_conn_event_ratchet_sync_started">titkosítás egyeztetése %s számára…</string>
<string name="available_in_v51">"
\nElérhető a v5.1-ben"</string>
<string name="both_you_and_your_contacts_can_delete">Mindketten, te és az ismerősöd is visszaállíthatatlanul törölhettek elküldött üzeneteket.</string>
<string name="v5_4_better_groups">Jobb csoportok</string>
<string name="clear_chat_warning">Minden üzenet törlésre kerül - ez visszafordíthatatlan! Az üzenetek csak NÁLAD törlődnek.</string>
<string name="icon_descr_call_ended">Hívás befejeződött</string>
<string name="settings_section_title_calls">HÍVÁSOK</string>
<string name="rcv_group_and_other_events">és %d egyéb események</string>
<string name="address_section_title">Azonosító</string>
<string name="connect_plan_already_joining_the_group">Már csatlakozik a csoporthoz!</string>
<string name="auto_accept_contact">Automatikus elfogadás</string>
<string name="notifications_mode_service_desc">Háttérszolgáltatás mindig fut - az értesítések azonnal megjelennek, amint üzenetek vannak.</string>
<string name="allow_to_delete_messages">Elküldött üzenetek visszafordíthatatlan törlésének engedélyezése.</string>
<string name="both_you_and_your_contact_can_send_voice">Mindketten, te és az ismerősöd is küldhettek hangüzeneteket.</string>
<string name="alert_title_msg_bad_id">Téves üzenet ID</string>
<string name="allow_your_contacts_adding_message_reactions">Üzenet rakciók -emojik- engedélyezése az ismerősei számára.</string>
<string name="allow_to_send_voice">Hangüzenetek küldésének engedélyezése.</string>
<string name="allow_message_reactions_only_if">Üzenet reakciók -emojik- engedélyezése kizárólag az esetre ha a másik fél is engedélyezi.</string>
<string name="back">Vissza</string>
<string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b>Kikapcsolható a beállításokban</b> az értesítések továbbra is megjelenítésre kerülnek amíg az app fut.]]></string>
<string name="v4_2_group_links_desc">Adminok létrehozhatnak linkeket csoporthoz való csatlakozáshoz.</string>
<string name="call_on_lock_screen">Hívások a lezárási képernyőn:</string>
<string name="conn_event_ratchet_sync_started">titkosítás egyeztetése…</string>
<string name="invite_prohibited">Ismerős meghívása sikertelen!</string>
<string name="integrity_msg_bad_id">téves üzenet ID</string>
<string name="v4_2_auto_accept_contact_requests">Ismerősnek jelölések automatikus elfogadása</string>
<string name="impossible_to_recover_passphrase"><![CDATA[<b>Tudnivaló</b>: NEM fogod tudni helyreállítani vagy megváltoztatni a jelmondatot az esetben ha elveszíted.]]></string>
<string name="callstatus_calling">hívás…</string>
<string name="color_secondary_variant">További másodlagos</string>
<string name="smp_servers_add_to_another_device">Hozzáadás másik eszközhöz</string>
<string name="allow_message_reactions">Üzenet reakciók -emojik- engedélyezése.</string>
<string name="icon_descr_cancel_file_preview">Fájl előnézet megszakítása</string>
<string name="all_group_members_will_remain_connected">Minden csoporttag kapcsolatban marad.</string>
<string name="onboarding_notifications_mode_service_desc"><![CDATA[<b>Több akkumulátort használ</b>! Háttérszolgáltatás mindig fut - értesítések megjelennek azonnal, ahogy új üzenetek érkeznek.]]></string>
<string name="block_member_confirmation">Blokkolás</string>
<string name="group_member_role_admin">admin</string>
<string name="icon_descr_cancel_image_preview">Fénykép előnézet megszakítása</string>
<string name="v5_1_self_destruct_passcode_descr">Minden adat törlődik amint bevitelre kerül.</string>
<string name="icon_descr_video_asked_to_receive">Kérte a videó elfogadását</string>
<string name="block_member_button">Tag blokkolása</string>
<string name="v5_2_more_things">Néhány további dolog</string>
<string name="authentication_cancelled">Hitelesítés megszakítva</string>
<string name="allow_to_send_files">Fájlok és fotók/videók küldésének engedélyezése.</string>
<string name="users_delete_all_chats_deleted">Minden chat illetve az összes üzenet törlésre kerül - ez visszafordíthatatlan!</string>
<string name="icon_descr_audio_call">hanghívás</string>
<string name="bold_text">vastagított</string>
<string name="app_passcode_replaced_with_self_destruct">Az app számkód helyettesítésre kerül egy önmegsemmisítő számkóddal.</string>
<string name="v5_3_new_interface_languages_descr">Arab, bulgár, finn, héber, thai és ukrán - köszönet a felhasználóknak és a Weblate-nek!</string>
<string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Új ismerős hozzáadása</b>: egyszer használatos QR-kód készítése az ismerős számára.]]></string>
<string name="allow_voice_messages_question">Hangüzenetek engedélyezése?</string>
<string name="always_use_relay">Mindig használt relay szervert</string>
<string name="chat_preferences_always">mindig</string>
<string name="call_already_ended">A hívás már befejeződött!</string>
<string name="turn_off_battery_optimization_button">Engedélyez</string>
<string name="all_your_contacts_will_remain_connected">A kapcsolat megmarad az összes Ismerősöddel.</string>
<string name="icon_descr_cancel_live_message">Élő chat üzenet megszakítása</string>
<string name="allow_irreversible_message_deletion_only_if">Helyreállíthatatlan üzenet törlés engedélyezése kizárólag az esetre ha a másik fél is engedélyezi.</string>
<string name="v4_6_audio_video_calls">Hang- és videóhívások</string>
<string name="integrity_msg_bad_hash">téves üzenet hash</string>
<string name="notifications_mode_service">Mindig bekapcsolva</string>
<string name="keychain_allows_to_receive_ntfs">Az Android Keystore fogja biztonságosan tárolni a jelmondatot app újraindítás vagy jelmondat változtatás után - lehetővé téve az értesítések fogadását.</string>
<string name="all_app_data_will_be_cleared">Minden app adat törölve.</string>
<string name="onboarding_notifications_mode_off_desc"><![CDATA[<b>Legjobb akkumulátoridő</b>. Kizárólag akkor kapsz értesítéseket amikor fut az app (NINCS háttérszolgáltatás).]]></string>
<string name="appearance_settings">Megjelenés</string>
<string name="turning_off_service_and_periodic">Akkumulátor optimizáció aktív, a háttérszolgáltatás és a rendszeres új üzenet ellenőrzés kikapcsolva. Újra bekapcsolhatod ezeket a beállításokban.</string>
<string name="block_member_question">Tag blokkolása?</string>
<string name="callstatus_ended">hívás befejeződött %1$s</string>
<string name="onboarding_notifications_mode_periodic_desc"><![CDATA[<b>Jó akkumulátoridő</b>. A háttérszolgáltatás ellenőrzi az új üzeneteket 10 percenként. Hívásokról és fontos üzenetekről maradhatsz le.]]></string>
<string name="group_member_role_author">szerző</string>
<string name="allow_your_contacts_irreversibly_delete">Ismerősök visszafordíthatatlanul törölhetnek elküldött üzeneteket engedélyezve.</string>
<string name="cancel_verb">Megszakítás</string>
<string name="notifications_mode_off_desc">Az app csak akkor tud értesítéseket fogadni amikor fut, héttérszolgáltatás nem kerül elindításra.</string>
<string name="v5_1_better_messages">Jobb üzenetek</string>
<string name="abort_switch_receiving_address_desc">A cím változtatás megszakításra kerül. A régi fogadó cím marad használatban.</string>
<string name="allow_verb">Engedélyez</string>
<string name="bad_desktop_address">Rossz asztal cím</string>
<string name="users_add">Adj hozzá profilt</string>
<string name="attach">Csatolás</string>
<string name="v5_0_app_passcode">App számkód</string>
<string name="icon_descr_asked_to_receive">Kérte, hogy fogfaja a képet</string>
<string name="use_camera_button">Fényképező</string>
<string name="cannot_access_keychain">A Keystore-hoz nem sikerül hozzáférni az adatbázis jelszó elmentése végett</string>
<string name="callstatus_in_progress">hívás folyamatban</string>
<string name="auto_accept_images">Fényképek automatiklus elfogadása</string>
<string name="allow_your_contacts_to_call">Hang- és videóhívás engedélyezése az ismerősei számára.</string>
<string name="settings_section_title_icon">APP IKON</string>
<string name="v4_3_improved_server_configuration_desc">Szerver hozzáadása QR kód befotózásával.</string>
<string name="allow_to_send_disappearing">Eltünő üzenetek küldésének engedélyezése.</string>
<string name="allow_disappearing_messages_only_if">Eltűnő üzenetek engedélyezése kizárólag az esetre ha a másik fél is engedélyezi.</string>
<string name="icon_descr_audio_off">Hang kikapcsolva</string>
<string name="allow_direct_messages">Közvetlen üzenetküldés tagok számára engedélyezett.</string>
<string name="settings_section_title_app">APP</string>
<string name="icon_descr_call_progress">Hívás folyamatban</string>
<string name="both_you_and_your_contact_can_add_message_reactions">Mindketten, te és az ismerősöd is használhattok üzenet reakciókat (emojik).</string>
<string name="both_you_and_your_contact_can_make_calls">Mindketten, te és az ismerősöd is tudok hívásokat indítani.</string>
<string name="la_auth_failed">Hitelesítés sikertelen</string>
<string name="block_member_desc">Minden új üzenet %s -tól/től elrejtésre kerül.</string>
<string name="app_version_name">App verzió: v%s</string>
<string name="allow_calls_only_if">Hívások engedélyezése kizárólag az esetre ha a másik fél is engedélyezi.</string>
<string name="smp_servers_add">Szerver hozzáadása…</string>
<string name="icon_descr_audio_on">Hang bekapcsolva</string>
<string name="audio_call_no_encryption">hanghívás (nem e2e titkosított)</string>
<string name="blocked_item_description">blokkolva</string>
<string name="change_database_passphrase_question">Adatbázis jelmondat megváltoztatása?</string>
<string name="callstate_connected">kapcsolódva</string>
<string name="la_change_app_passcode">Számkód megváltoztatása</string>
<string name="rcv_group_event_changed_member_role">%s to %s megváltozott szerepköre</string>
<string name="switch_receiving_address">Fogadó szerver cím megváltoztatása</string>
<string name="change_verb">Változtatás</string>
<string name="confirm_passcode">Számkód megerősítése</string>
<string name="confirm_password">Jelszó megerősítése</string>
<string name="change_member_role_question">Csoport szerepkör megváltoztatása?</string>
<string name="change_lock_mode">Lezárási mód megváltoztatása</string>
<string name="notification_contact_connected">Kapcsolódva</string>
<string name="rcv_group_event_member_connected">kapcsolódva</string>
<string name="connect_via_link_verb">Kapcsolódás</string>
<string name="group_member_status_connected">kapcsolódva</string>
<string name="connected_mobile">Összekapcsolt telefon</string>
<string name="server_connected">kapcsolódva</string>
<string name="change_role">Szerepkör megváltoztatása</string>
<string name="icon_descr_server_status_connected">Kapcsolódva</string>
<string name="auth_confirm_credential">Belépési adatok megerősítése</string>
<string name="switch_receiving_address_question">Fogadó szerver cím megváltoztatása</string>
<string name="rcv_conn_event_switch_queue_phase_completed">megváltozott azonosító számodra</string>
<string name="change_self_destruct_mode">Önmegsemmisítő mód megváltoztatása</string>
<string name="rcv_group_event_changed_your_role">a szerepköröd megváltoztatva %s-ra(-re)</string>
<string name="connect_button">Kapcsolódás</string>
<string name="connect_via_member_address_alert_title">Kapcsolódás közvetlenül?</string>
<string name="smp_server_test_connect">Kapcsolódás</string>
<string name="rcv_group_event_member_created_contact">közvetlenül kapcsolódva</string>
<string name="connection_local_display_name">kapcsolat %1$d</string>
<string name="status_contact_has_e2e_encryption">az ismerősnél az e2e titkosítás elérhető</string>
<string name="v5_4_incognito_groups_descr">Csoport létrehozása véletlenszerűen létrehozott profillal.</string>
<string name="delete_contact_all_messages_deleted_cannot_undo_warning">Az ismerős és az összes üzenet törlésre kerül - ez visszafordíthatatlan!</string>
<string name="contacts_can_mark_messages_for_deletion">Ismerősök megjelölhetik az üzeneteket törlendőként; de láthatod azokat.</string>
<string name="connect_via_invitation_link">Kapcsolódás egy Egyszer használatos linkkel?</string>
<string name="connect_via_link_or_qr">Kapcsolódás egy link / QR-kód által</string>
<string name="connection_error_auth">Kapcsolódási hiba (AUTH)</string>
<string name="notification_preview_mode_contact">Ismerős neve</string>
<string name="connect_via_contact_link">Kapcsolódás ismerős azonosítója által?</string>
<string name="create_address">Azonosító létrehozása</string>
<string name="copy_verb">Másolás</string>
<string name="continue_to_next_step">Folytatás</string>
<string name="connect_plan_connect_via_link">Kapcsolódás egy linken keresztül?</string>
<string name="contact_already_exists">Az ismerős már létezik</string>
<string name="core_version">Fő verzió: v%s</string>
<string name="icon_descr_contact_checked">Ismerős ellenőrizve</string>
<string name="connect_plan_connect_to_yourself">Kapcsolódás saját magához?</string>
<string name="copied">Kimásolva a vágólapra</string>
<string name="connection_request_sent">Kapcsolódási kérés elküldve!</string>
<string name="connecting_to_desktop">Kapcsolódás az asztalhoz</string>
<string name="network_session_mode_entity">Kapcsolat</string>
<string name="correct_name_to">Név helyesbítése erre: %s?</string>
<string name="connection_timeout">Kapcsolat időtúllépés</string>
<string name="connect_with_contact_name_question">Kapcsolódás %1$s által?</string>
<string name="create_profile_button">Létrehozás</string>
<string name="contact_preferences">Ismerős beállításai</string>
<string name="info_row_connection">Kapcsolat</string>
<string name="desktop_connection_terminated">Kapcsolat megszakítva</string>
<string name="display_name_connection_established">Kapcsolat létrehozva</string>
<string name="status_contact_has_no_e2e_encryption">az ismerősnél az e2e titkosítás nem elérhető</string>
<string name="chat_preferences_contact_allows">Az ismerős engedélyezi</string>
<string name="notification_preview_somebody">Ismerős elrejtve:</string>
<string name="connect_to_desktop">Kapcsolódás az asztalhoz</string>
<string name="icon_descr_context">Kontextus ikon</string>
<string name="connect_via_link">Kapcsolódás egy linken keresztül</string>
<string name="receipts_section_contacts">Ismerősök</string>
<string name="connection_error">Kapcsolódási hiba</string>
<string name="alert_title_contact_connection_pending">Az ismerős még nem kapcsolódott!</string>
<string name="v5_3_discover_join_groups_descr">- kapcsolódás könyvtár szolgáltatáshoz (BÉTA)!
\n- kézbesítési igazolások (20 tagig).
\n- gyorsabb és stabilabb</string>
<string name="contribute">Hozzájárulás</string>
<string name="group_member_status_intro_invitation">kapcsolódás (meghívás bemutatkozásra)</string>
<string name="create_simplex_address">SimpleX azonosító létrehozása</string>
<string name="rcv_direct_event_contact_deleted">törölt ismerős</string>
<string name="delete_member_message__question">Tag üzenetének törlése?</string>
<string name="chat_is_running">A chat szolgáltatás működik (fut)</string>
<string name="share_one_time_link">Egyszer használatos meghívó link létrehozása</string>
<string name="delete_link">Link törlése</string>
<string name="notifications_mode_periodic_desc">Új üzenetek ellenőrzése 10 percenként, legfeljebb 1 percen keresztül.</string>
<string name="delete_database">Adatbázis törlése</string>
<string name="create_group_button">Csoport létrehozása</string>
<string name="network_session_mode_user">Chat profil</string>
<string name="create_another_profile_button">Profil létrehozása</string>
<string name="connected_desktop">Csatlakoztatott asztal</string>
<string name="share_text_deleted_at">Törölve ekkor: %s</string>
<string name="info_row_deleted_at">Törölve ekkor</string>
<string name="v4_6_chinese_spanish_interface">Kínai és spanyol kezelőfelület.</string>
<string name="alert_title_cant_invite_contacts">Ismerősök meghívása nem lehetséges!</string>
<string name="chat_is_stopped_indication">A chat szolgáltatás leállt (nem fut)</string>
<string name="theme_dark">Sötét</string>
<string name="create_profile">Profil létrehozása</string>
<string name="rcv_group_event_group_deleted">törölt csoport</string>
<string name="full_deletion">Törlés mindenkinek</string>
<string name="button_create_group_link">Link létrehozása</string>
<string name="chat_preferences">Chat beállítások</string>
<string name="chat_archive_header">Chat archívum</string>
<string name="delete_profile">Profil törlése</string>
<string name="la_current_app_passcode">Jelenlegi Számkód</string>
<string name="group_member_status_connecting">kapcsolódás</string>
<string name="confirm_new_passphrase">Új jelmondat megerősítése…</string>
<string name="group_connection_pending">kapcsolódás…</string>
<string name="delete_chat_profile">Chat profil törlés</string>
<string name="custom_time_picker_custom">egyedi</string>
<string name="callstatus_connecting">hívás kapcsolódik…</string>
<string name="customize_theme_title">Színséma személyreszabása</string>
<string name="maximum_supported_file_size">Jelenleg támogatott legnagyobb fájl méret: %1$s.</string>
<string name="smp_server_test_delete_file">Fájl törlése</string>
<string name="in_developing_title">Hamarosan!</string>
<string name="snd_conn_event_switch_queue_phase_changing_for_member">azonosító megváltoztatása %s számára…</string>
<string name="chat_database_imported">Chat adatbázis importálva</string>
<string name="chat_archive_section">CHAT ARCHÍVUM</string>
<string name="delete_messages">Üzenetek törlése?</string>
<string name="clear_chat_menu_action">Kiürítés</string>
<string name="icon_descr_close_button">Bezárás gomb</string>
<string name="chat_is_stopped">A chat szolgáltatás leállt (nem fut)</string>
<string name="item_info_current">(jelenlegi)</string>
<string name="v5_1_custom_themes_descr">Színsémák személyreszabása és megosztása</string>
<string name="delete_chat_profile_question">Chat profil törlése?</string>
<string name="create_group">Titkos csoport létrehozása</string>
<string name="connected_to_desktop">Kapcsolódva az asztalhoz</string>
<string name="configure_ICE_servers">ICE sezrverek beállítása</string>
<string name="button_delete_group">Csoport törlése</string>
<string name="clear_verification">Chat hitelesításe</string>
<string name="group_member_status_creator">szerző</string>
<string name="confirm_verb">Megerősítés</string>
<string name="for_me_only">Törlés nálam</string>
<string name="delete_messages__question">%d üzenet törlése?</string>
<string name="v5_1_custom_themes">Egyedi színsémák</string>
<string name="group_member_status_accepted">kapcsolódás (elfogadva)</string>
<string name="smp_servers_check_address">Szerver cím ellenőrzése és újrapróbálkozás.</string>
<string name="delete_group_question">Csoport törlése?</string>
<string name="confirm_database_upgrades">Adatbázis frissítés megerősítése</string>
<string name="create_your_profile">Saját profil létrehozása</string>
<string name="snd_conn_event_switch_queue_phase_changing">azonosító megváltoztatása…</string>
<string name="display_name_connecting">kapcsolódás…</string>
<string name="icon_descr_call_connecting">Hívás kapcsolása</string>
<string name="delete_files_and_media_question">Fájlok illetve fotók/videók törlése?</string>
<string name="group_member_status_complete">befejezve</string>
<string name="chat_database_section">CHAT ADATBÁZIS</string>
<string name="change_self_destruct_passcode">Önmegsemmisító számkód megváltoztatása</string>
<string name="smp_server_test_create_queue">Várólista létrehozása</string>
<string name="colored_text">színes</string>
<string name="callstate_connecting">kapcsolódás…</string>
<string name="dark_theme">Sötét színséma</string>
<string name="deleted_description">törölve</string>
<string name="users_delete_question">Chat profil törlése?</string>
<string name="chat_with_developers">Chat a SimpleX fejlesztőivel</string>
<string name="delete_link_question">Link törlése?</string>
<string name="server_connecting">kapcsolódás</string>
<string name="send_disappearing_message_custom_time">Személyreszabott idő</string>
<string name="connect_via_link_incognito">Inkognítóban csatlakozva</string>
<string name="settings_section_title_chats">CHATEK</string>
<string name="v5_3_new_desktop_app_descr">Új profil létrehozása a számítógépen futó appban. 💻</string>
<string name="group_member_status_announced">kapcsolódás (bejelentve)</string>
<string name="contact_connection_pending">kapcsolódás…</string>
<string name="chat_database_deleted">Chat adatbázis törölve</string>
<string name="group_member_status_introduced">kapcsolódás (bejelentve)</string>
<string name="create_group_link">Csoporthoz link létrehozása</string>
<string name="chat_console">Chat konzol</string>
<string name="delete_files_and_media_for_all_users">Fájlok törlése minden chat profil alatt</string>
<string name="smp_server_test_delete_queue">Várólista törlése</string>
<string name="button_delete_contact">Ismerős törlése</string>
<string name="archive_created_on_ts">Létrehozva: %1$s</string>
<string name="rcv_conn_event_switch_queue_phase_changing">azonosító megváltoztatása…</string>
<string name="connected_to_mobile">Kapcsolódva a mobilhoz</string>
<string name="current_passphrase">Jelenlegi jelmondat…</string>
<string name="choose_file_title">Fájl választása</string>
<string name="create_one_time_link">Egyszer használatos meghívó link létrehozása</string>
<string name="delete_image">Kép törlése</string>
<string name="smp_server_test_create_file">Fájl létrehozása</string>
<string name="create_secret_group_title">Tikos csoport létrehozása</string>
<string name="clear_contacts_selection_button">Kiürítés</string>
<string name="delete_contact_question">Ismerős törlése?</string>
<string name="clear_verb">Kiürítés</string>
<string name="create_address_and_let_people_connect">Hozz létre egy azonosítót, hogy az ismerősök kapcsolatba léphessenek veled.</string>
<string name="v4_4_verify_connection_security_desc">Biztonsági kódok ösezhasonlítása az ismerősökkel.</string>
<string name="smp_server_test_compare_file">Fájl összehasonlítása</string>
<string name="your_chats">Chatek</string>
<string name="delete_message__question">Üzenet törlése?</string>
<string name="delete_pending_connection__question">Függő kapcsolatfelvételi kérés törlése?</string>
<string name="database_encrypted">Adatbázis titkosítva!</string>
<string name="clear_chat_question">Chat kiürítése?</string>
<string name="database_downgrade">Adatbázis downgrade?</string>
<string name="clear_chat_button">Chat kiürítése</string>
<string name="database_passphrase_will_be_updated">Adatbázis titkosítási jelmondat meg lesz változtatva.</string>
</resources>

View File

@ -1505,4 +1505,18 @@
<string name="loading_remote_file_desc">Si prega di attendere mentre il file viene caricato dal cellulare collegato</string>
<string name="desktop_app_version_is_incompatible">La versione dell\'app desktop %s non è compatibile con questa app.</string>
<string name="verify_connection">Verifica la connessione</string>
<string name="v5_4_block_group_members">Blocca i membri dei gruppi</string>
<string name="v5_4_incognito_groups_descr">Crea un gruppo usando un profilo casuale.</string>
<string name="v5_4_link_mobile_desktop">Collega le app mobile e desktop! 🔗</string>
<string name="v5_4_link_mobile_desktop_descr">Tramite protocollo sicuro resistente alla quantistica.</string>
<string name="v5_4_block_group_members_descr">Per nascondere messaggi indesiderati.</string>
<string name="v5_4_better_groups">Gruppi migliorati</string>
<string name="v5_4_incognito_groups">Gruppi in incognito</string>
<string name="remote_host_was_disconnected_toast"><![CDATA[Il cellulare <b>%s</b> è stato disconnesso]]></string>
<string name="v5_4_better_groups_descr">Ingresso più veloce e messaggi più affidabili.</string>
<string name="v5_4_more_things_descr">- avvisa facoltativamente i contatti eliminati.
\n- nomi del profilo con spazi.
\n- e molto altro!</string>
<string name="waiting_for_mobile_to_connect_on_port"><![CDATA[In attesa che il cellulare si connetta alla porta <i>%s</i>]]></string>
<string name="group_member_role_author">autore</string>
</resources>

View File

@ -1469,7 +1469,7 @@
<string name="unlink_desktop_question">Desktop ontkoppelen?</string>
<string name="linked_desktop_options">Gekoppelde desktop opties</string>
<string name="linked_desktops">Gelinkte desktops</string>
<string name="discover_on_network">Ontdek via netwerk</string>
<string name="discover_on_network">Ontdek via het lokale netwerk</string>
<string name="this_device">Dit apparaat</string>
<string name="linked_mobiles">Gekoppelde mobiele apparaten</string>
<string name="desktop_device">Desktop</string>
@ -1503,4 +1503,23 @@
<string name="loading_remote_file_desc">Wacht terwijl het bestand wordt geladen vanaf de gekoppelde mobiele telefoon</string>
<string name="desktop_app_version_is_incompatible">Desktop-app-versie %s is niet compatibel met deze app.</string>
<string name="verify_connection">Controleer de verbinding</string>
<string name="v5_4_block_group_members">Groepsleden blokkeren</string>
<string name="v5_4_incognito_groups_descr">Maak een groep met een willekeurig profiel.</string>
<string name="v5_4_link_mobile_desktop">Koppel mobiele en desktop-apps! 🔗</string>
<string name="v5_4_link_mobile_desktop_descr">Via een beveiligd kwantumbestendig protocol.</string>
<string name="v5_4_block_group_members_descr">Om ongewenste berichten te verbergen.</string>
<string name="v5_4_better_groups">Betere groepen</string>
<string name="v5_4_incognito_groups">Incognitogroepen</string>
<string name="v5_4_better_groups_descr">Snellere deelname en betrouwbaardere berichten.</string>
<string name="v5_4_more_things_descr">- optioneel verwijderde contacten op de hoogte stellen.
\n- profielnamen met spaties.
\n- en meer!</string>
<string name="remote_host_was_disconnected_toast"><![CDATA[Mobiele verbinding <b>%s</b> is verbroken]]></string>
<string name="group_member_role_author">auteur</string>
<string name="waiting_for_mobile_to_connect_on_port"><![CDATA[Wachten tot mobiel verbinding maakt op poort <i>%s</i>]]></string>
<string name="multicast_connect_automatically">Automatisch verbinden</string>
<string name="waiting_for_desktop">Wachten op desktop…</string>
<string name="found_desktop">Desktop gevonden</string>
<string name="not_compatible">Niet compatibel!</string>
<string name="multicast_discoverable_via_local_network">Vindbaar via lokaal netwerk</string>
</resources>

View File

@ -3,11 +3,11 @@
<string name="app_name">SimpleX</string>
<string name="thousand_abbreviation">т</string>
<!-- Connect via Link - MainActivity.kt -->
<string name="connect_via_contact_link">Соединиться через ссылку-контакт?</string>
<string name="connect_via_invitation_link">Соединиться через ссылку-приглашение?</string>
<string name="connect_via_group_link">Соединиться через ссылку группы?</string>
<string name="connect_via_contact_link">Соединиться через адрес?</string>
<string name="connect_via_invitation_link">Соединиться через одноразовую ссылку?</string>
<string name="connect_via_group_link">Вступить в группу?</string>
<string name="profile_will_be_sent_to_contact_sending_link">Ваш профиль будет отправлен контакту, от которого Вы получили эту ссылку.</string>
<string name="you_will_join_group">Вы вступите в группу, на которую ссылается эта ссылка.</string>
<string name="you_will_join_group">Вы соединитесь со всеми членами группы.</string>
<string name="connect_via_link_verb">Соединиться</string>
<!-- Server info - ChatModel.kt -->
<string name="server_connected">соединено</string>
@ -435,7 +435,7 @@
<string name="your_profile_is_stored_on_your_device">Ваш профиль, контакты и доставленные сообщения хранятся на Вашем устройстве.</string>
<string name="profile_is_only_shared_with_your_contacts">Профиль отправляется только Вашим контактам.</string>
<string name="display_name_cannot_contain_whitespace">Имя профиля не может содержать пробелы.</string>
<string name="display_name">Имя профиля</string>
<string name="display_name">Введите ваше имя:</string>
<string name="create_profile_button">Создать</string>
<string name="about_simplex">О SimpleX</string>
<!-- markdown demo - MarkdownHelpView.kt -->
@ -818,8 +818,8 @@
<string name="switch_receiving_address">Переключить адрес получения</string>
<!-- AddGroupView.kt -->
<string name="create_secret_group_title">Создать скрытую группу</string>
<string name="group_is_decentralized">Группа полностью децентрализована она видна только членам.</string>
<string name="group_display_name_field">Имя группы:</string>
<string name="group_is_decentralized">Группа полностью децентрализована она видна только членам.</string>
<string name="group_display_name_field">Введите имя группы:</string>
<string name="group_full_name_field">Полное имя:</string>
<string name="group_main_profile_sent">Ваш профиль чата будет отправлен членам группы</string>
<!-- GroupProfileView.kt -->
@ -1489,4 +1489,114 @@
<string name="error_sending_message_contact_invitation">Ошибка отправки приглашения</string>
<string name="member_contact_send_direct_message">Послать прямое сообщение</string>
<string name="rcv_group_event_member_created_contact">соединен напрямую</string>
<string name="expand_verb">Раскрыть</string>
<string name="v5_4_block_group_members">Блокируйте членов группы</string>
<string name="connect_plan_repeat_connection_request">Повторить запрос на соединение?</string>
<string name="encryption_renegotiation_error">Ошибка нового соглашения о шифровании</string>
<string name="rcv_direct_event_contact_deleted">удалил(а) контакт</string>
<string name="error_alert_title">Ошибка</string>
<string name="v5_4_incognito_groups_descr">Создайте группу, используя случайный профиль.</string>
<string name="create_group_button">Создать группу</string>
<string name="create_another_profile_button">Создать профиль</string>
<string name="connected_desktop">Подключенный компьютер</string>
<string name="group_members_2">%s и %s</string>
<string name="new_mobile_device">Новое мобильное устройство</string>
<string name="desktop_address">Адрес компьютера</string>
<string name="only_one_device_can_work_at_the_same_time">Одновременно может работать только одно устройство</string>
<string name="connect_plan_join_your_group">Вступить в вашу группу?</string>
<string name="v5_4_link_mobile_desktop">Свяжите мобильное и настольное приложения! 🔗</string>
<string name="marked_deleted_items_description">%d сообщений помечено удалёнными</string>
<string name="connect_plan_group_already_exists">Группа уже существует!</string>
<string name="open_on_mobile_and_scan_qr_code"><![CDATA[Откройте <i>Использовать с компьютера</i> в мобильном приложении и сосканируйте QR код]]></string>
<string name="connect_plan_already_connecting">Уже соединяется!</string>
<string name="desktop_incompatible_version">Несовместимая версия</string>
<string name="new_desktop"><![CDATA[<i>(новое)</i>]]></string>
<string name="v5_4_better_groups">Улучшенные группы</string>
<string name="linked_desktop_options">Опции связанных компьютеров</string>
<string name="linked_desktops">Связанные компьютеры</string>
<string name="discover_on_network">Обнаружение по локальной сети</string>
<string name="rcv_group_and_other_events">и %d других событий</string>
<string name="connect_plan_connect_via_link">Соединиться через ссылку?</string>
<string name="v5_4_incognito_groups">Инкогнито группы</string>
<string name="connect_plan_already_joining_the_group">Вступление в группу уже начато!</string>
<string name="moderated_items_description">%d сообщений модерировано членом %s</string>
<string name="remote_host_was_disconnected_toast"><![CDATA[Удаленный хост был отключен: <b>%s</b>]]></string>
<string name="v5_4_better_groups_descr">Быстрое вступление и надежная доставка сообщений.</string>
<string name="connect_plan_connect_to_yourself">Соединиться с самим собой?</string>
<string name="linked_mobiles">Связанные мобильные</string>
<string name="desktop_device">Компьютер</string>
<string name="connected_to_desktop">Компьютер подключен</string>
<string name="loading_remote_file_title">Загрузка файла</string>
<string name="connecting_to_desktop">Подключение к компьютеру</string>
<string name="alert_text_encryption_renegotiation_failed">Ошибка нового соглашения о шифровании</string>
<string name="desktop_devices">Компьютеры</string>
<string name="correct_name_to">Исправить имя на %s?</string>
<string name="delete_messages__question">Удалить %d сообщений?</string>
<string name="link_a_mobile">Связать мобильный</string>
<string name="connect_with_contact_name_question">Соединиться с %1$s?</string>
<string name="remove_member_button">Удалить члена группы</string>
<string name="block_member_confirmation">Заблокировать</string>
<string name="blocked_items_description">%d сообщений заблокировано</string>
<string name="block_member_button">Заблокировать члена группы</string>
<string name="connected_mobile">Подключенный мобильный</string>
<string name="connect_plan_repeat_join_request">Повторить запрос на вступление?</string>
<string name="button_remove_member_question">Удалить члена группы?</string>
<string name="delete_and_notify_contact">Удалить и уведомить контакт</string>
<string name="connect_plan_open_group">Открыть группу</string>
<string name="desktop_connection_terminated">Подключение прервано</string>
<string name="this_device_version"><![CDATA[<i>(это устройство v%s)</i>]]></string>
<string name="unblock_member_desc">Сообщения от %s будут показаны!</string>
<string name="enter_this_device_name">Введите имя этого устройства…</string>
<string name="error">Ошибка</string>
<string name="connect_to_desktop">Подключиться к компьютеру</string>
<string name="disconnect_remote_host">Отключить</string>
<string name="block_member_question">Заблокировать члена группы?</string>
<string name="rcv_group_events_count">%d событий</string>
<string name="invalid_name">Неверное имя!</string>
<string name="connected_to_mobile">Мобильный подключен</string>
<string name="bad_desktop_address">Неверный адрес компьютера</string>
<string name="paste_desktop_address">Вставить адрес компьютера</string>
<string name="devices">Устройства</string>
<string name="v5_4_more_things_descr">- опционально уведомляйте удалённые контакты.
\n- имена профилей с пробелами.
\n- и прочее!</string>
<string name="non_content_uri_alert_title">Неверный путь к файлу</string>
<string name="scan_from_mobile">Сканируйте с мобильного</string>
<string name="disconnect_desktop_question">Отключить компьютер?</string>
<string name="loading_remote_file_desc">Пожалуйста, подождите, пока файл загружается со связанного мобильного устройства.</string>
<string name="block_member_desc">Все новые сообщения от %s будут скрыты!</string>
<string name="desktop_app_version_is_incompatible">Версия настольного приложения %s несовместима с этим приложением.</string>
<string name="blocked_item_description">заблокировано</string>
<string name="connect_plan_you_are_already_connecting_to_vName">Вы уже соединяетесь с %1$s.</string>
<string name="connect_plan_you_are_already_joining_the_group_via_this_link">Вы уже вступаете в группу по этой ссылке.</string>
<string name="connect_plan_you_are_already_joining_the_group_vName">Вы уже вступаете в группу %1$s.</string>
<string name="connect_plan_this_is_your_own_one_time_link">Это ваша собственная одноразовая ссылка!</string>
<string name="v5_4_link_mobile_desktop_descr">Через безопасный квантово-устойчивый протокол.</string>
<string name="v5_4_block_group_members_descr">Чтобы скрыть нежелательные сообщения.</string>
<string name="unlink_desktop_question">Забыть компьютер?</string>
<string name="video_decoding_exception_desc">Видео невозможно декодировать. Пожалуйста, попробуйте другое видео или свяжитесь с разработчиками.</string>
<string name="rcv_group_event_1_member_connected">%@ соединен(а)</string>
<string name="group_members_n">%s, %s и %d членов группы</string>
<string name="this_device">Это устройство</string>
<string name="unblock_member_button">Разблокировать члена группы</string>
<string name="contact_tap_to_connect">Нажмите чтобы соединиться</string>
<string name="this_device_name">Имя этого устройства</string>
<string name="connect_plan_you_are_already_in_group_vName">Вы уже состоите в группе %1$s.</string>
<string name="connect_plan_this_is_your_own_simplex_address">Это ваш собственный адрес SimpleX!</string>
<string name="unblock_member_question">Разблокировать члена группы?</string>
<string name="settings_section_title_use_from_desktop">Использовать с компьютера</string>
<string name="session_code">Код сессии</string>
<string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Вы уже соединяетесь по этой одноразовой ссылке!</string>
<string name="unlink_desktop">Забыть</string>
<string name="this_device_name_shared_with_mobile">Имя устройства будет доступно подключенному мобильному клиенту.</string>
<string name="verify_code_on_mobile">Сверьте код на мобильном</string>
<string name="non_content_uri_alert_text">Указан неверный путь к файлу. Сообщите о проблеме разработчикам приложения.</string>
<string name="connect_plan_this_is_your_link_for_group_vName">Это ваша ссылка на группу %1$s!</string>
<string name="verify_code_with_desktop">Сверьте код с компьютером</string>
<string name="scan_qr_code_from_desktop">Сканировать QR код с компьютера</string>
<string name="unblock_member_confirmation">Разблокировать</string>
<string name="connect_plan_you_have_already_requested_connection_via_this_address">Вы уже запросили соединение через этот адрес!</string>
<string name="terminal_always_visible">Показывать консоль в новом окне</string>
<string name="verify_connections">Проверять соединения</string>
<string name="verify_connection">Проверить соединение</string>
</resources>

View File

@ -1048,4 +1048,27 @@
<string name="users_delete_data_only">Sadece yerel profil verisi</string>
<string name="info_row_local_name">Yerel ad</string>
<string name="only_you_can_add_message_reactions">Sadece sen mesaj tepkileri ekleyebilirsin.</string>
<string name="stop_file__confirm">Durdur</string>
<string name="stop_file__action">Dosyayı durdur</string>
<string name="error_alert_title">Hata</string>
<string name="create_another_profile_button">ProfilProfil oluştur</string>
<string name="stop_chat_to_enable_database_actions">Veri tabanı eylemlerini etkinleştirmek için sohbeti durdur.</string>
<string name="stop_snd_file__title">Dosya göndermeyi durdur?</string>
<string name="auth_stop_chat">Sohbeti durdur</string>
<string name="connect_use_current_profile">Mevcut profili kullan</string>
<string name="la_mode_system">Sistem</string>
<string name="settings_section_title_support">SIMPLEX CHAT\'İ DESTEKLE</string>
<string name="stop_chat_to_export_import_or_delete_chat_database">Sohbet veri tabanını dışa aktarmak, içe aktarmak veya silmek için sohbeti durdur. Sohbet durdurulduğunda mesaj alamaz ve gönderemezsiniz.</string>
<string name="desktop_device">Masaüstü</string>
<string name="contact_tap_to_connect">Bağlanmak için dokun</string>
<string name="block_member_confirmation">Engelle</string>
<string name="tap_to_activate_profile">Profili etkinleştirmek için dokun.</string>
<string name="stop_chat_confirmation">Durdur</string>
<string name="stop_sharing_address">Adres paylaşmayı durdur?</string>
<string name="send_receipts_disabled">kapalı</string>
<string name="turn_off_battery_optimization_button">İzin ver</string>
<string name="error">Hata</string>
<string name="stop_sharing">Paylaşmayı durdur</string>
<string name="stop_rcv_file__title">Dosya almayı durdur?</string>
<string name="stop_chat_question">Sohbeti durdur?</string>
</resources>

View File

@ -1471,7 +1471,7 @@
<string name="unlink_desktop_question">取消链接桌面端?</string>
<string name="linked_desktop_options">已链接桌面选项</string>
<string name="linked_desktops">已链接桌面</string>
<string name="discover_on_network">网络发现</string>
<string name="discover_on_network">通过本地网络发现</string>
<string name="this_device">此设备</string>
<string name="linked_mobiles">已链接的移动设备</string>
<string name="desktop_device">桌面</string>
@ -1505,4 +1505,23 @@
<string name="loading_remote_file_desc">从已链接移动设备加载文件时请稍候片刻</string>
<string name="desktop_app_version_is_incompatible">桌面应用版本 %s 不兼容此应用。</string>
<string name="verify_connection">验证连接</string>
<string name="v5_4_block_group_members">屏蔽群组成员</string>
<string name="v5_4_incognito_groups_descr">使用随机身份创建群组</string>
<string name="v5_4_link_mobile_desktop">连接移动端和桌面端应用程序!🔗</string>
<string name="v5_4_link_mobile_desktop_descr">通过安全的、抗量子计算机破解的协议。</string>
<string name="v5_4_block_group_members_descr">隐藏不需要的信息。</string>
<string name="v5_4_better_groups">更佳的群组</string>
<string name="v5_4_incognito_groups">匿名群组</string>
<string name="remote_host_was_disconnected_toast"><![CDATA[远程主机 <b>%s</b> 已断开连接]]></string>
<string name="v5_4_better_groups_descr">加入速度更快、信息更可靠。</string>
<string name="v5_4_more_things_descr">- 可选择通知已删除的联系人。
\n- 带空格的个人资料名称。
\n- 以及更多!</string>
<string name="waiting_for_mobile_to_connect_on_port"><![CDATA[正等待移动设备在端口 <i>%s</i> 进行连接]]></string>
<string name="group_member_role_author">作者</string>
<string name="multicast_connect_automatically">自动连接</string>
<string name="waiting_for_desktop">等待桌面中…</string>
<string name="found_desktop">找到了桌面</string>
<string name="not_compatible">不兼容!</string>
<string name="multicast_discoverable_via_local_network">可通过本地网络发现</string>
</resources>

View File

@ -104,5 +104,5 @@ private fun fileFilterDescription(input: String): String = when(input) {
else -> ""
}
actual fun URI.inputStream(): InputStream? = File(URI("file:" + toString().removePrefix("file:"))).inputStream()
actual fun URI.outputStream(): OutputStream = File(URI("file:" + toString().removePrefix("file:"))).outputStream()
actual fun URI.inputStream(): InputStream? = toFile().inputStream()
actual fun URI.outputStream(): OutputStream = toFile().outputStream()

View File

@ -157,7 +157,7 @@ actual fun ImageBitmap.scale(width: Int, height: Int): ImageBitmap {
// LALAL
actual fun isImage(uri: URI): Boolean {
val path = uri.path.lowercase()
val path = uri.toFile().path.lowercase()
return path.endsWith(".gif") ||
path.endsWith(".webp") ||
path.endsWith(".png") ||
@ -166,7 +166,7 @@ actual fun isImage(uri: URI): Boolean {
}
actual fun isAnimImage(uri: URI, drawable: Any?): Boolean {
val path = uri.path.lowercase()
val path = uri.toFile().path.lowercase()
return path.endsWith(".gif") || path.endsWith(".webp")
}

View File

@ -4,6 +4,8 @@ import androidx.compose.foundation.contextMenuOpenDetector
import androidx.compose.runtime.Composable
import androidx.compose.ui.*
import androidx.compose.ui.graphics.painter.Painter
import java.io.File
import java.net.URI
actual fun Modifier.navigationBarsWithImePadding(): Modifier = this
@ -19,13 +21,15 @@ actual fun ProvideWindowInsets(
@Composable
actual fun Modifier.desktopOnExternalDrag(
enabled: Boolean,
onFiles: (List<String>) -> Unit,
onFiles: (List<File>) -> Unit,
onImage: (Painter) -> Unit,
onText: (String) -> Unit
): Modifier =
onExternalDrag(enabled) {
when(val data = it.dragData) {
is DragData.FilesList -> onFiles(data.readFiles())
// data.readFiles() returns filePath in URI format (where spaces replaces with %20). But it's an error-prone idea to work later
// with such format when everywhere we use absolutePath in File() format
is DragData.FilesList -> onFiles(data.readFiles().map { URI.create(it).toFile() })
is DragData.Image -> onImage(data.readImage())
is DragData.Text -> onText(data.readText())
}

View File

@ -37,7 +37,7 @@ actual object AudioPlayer: AudioPlayerInterface {
// Returns real duration of the track
private fun start(fileSource: CryptoFile, seek: Int? = null, onProgressUpdate: (position: Int?, state: TrackState) -> Unit): Int? {
val absoluteFilePath = if (fileSource.isAbsolutePath) fileSource.filePath else getAppFilePath(fileSource.filePath)
val absoluteFilePath = if (fileSource.isAbsolutePath) fileSource.filePath else getAppFilePath(fileSource.filePath)
if (!File(absoluteFilePath).exists()) {
Log.e(TAG, "No such file: ${fileSource.filePath}")
return null
@ -46,16 +46,16 @@ actual object AudioPlayer: AudioPlayerInterface {
VideoPlayerHolder.stopAll()
RecorderInterface.stopRecording?.invoke()
val current = currentlyPlaying.value
if (current == null || current.first != fileSource) {
if (current == null || current.first != fileSource || !player.status().isPlayable) {
stopListener()
player.stop()
runCatching {
if (fileSource.cryptoArgs != null) {
val tmpFile = fileSource.createTmpFileIfNeeded()
decryptCryptoFile(absoluteFilePath, fileSource.cryptoArgs, tmpFile.absolutePath)
player.media().prepare(tmpFile.toURI().toString().replaceFirst("file:", "file://"))
player.media().prepare(tmpFile.absolutePath)
} else {
player.media().prepare(File(absoluteFilePath).toURI().toString().replaceFirst("file:", "file://"))
player.media().prepare(absoluteFilePath)
}
}.onFailure {
Log.e(TAG, it.stackTraceToString())
@ -171,7 +171,7 @@ actual object AudioPlayer: AudioPlayerInterface {
var res: Int? = null
try {
val helperPlayer = AudioPlayerComponent().mediaPlayer()
helperPlayer.media().startPaused(File(unencryptedFilePath).toURI().toString().replaceFirst("file:", "file://"))
helperPlayer.media().startPaused(unencryptedFilePath)
res = helperPlayer.duration
helperPlayer.stop()
helperPlayer.release()

View File

@ -4,6 +4,7 @@ import androidx.compose.ui.platform.ClipboardManager
import androidx.compose.ui.platform.UriHandler
import androidx.compose.ui.text.AnnotatedString
import chat.simplex.common.model.*
import chat.simplex.common.views.helpers.generalGetString
import chat.simplex.common.views.helpers.withApi
import java.io.File
import java.net.URI
@ -25,14 +26,16 @@ actual fun shareFile(text: String, fileSource: CryptoFile) {
withApi {
FileChooserLauncher(false) { to: URI? ->
if (to != null) {
val absolutePath = if (fileSource.isAbsolutePath) fileSource.filePath else getAppFilePath(fileSource.filePath)
if (fileSource.cryptoArgs != null) {
try {
decryptCryptoFile(getAppFilePath(fileSource.filePath), fileSource.cryptoArgs, to.path)
decryptCryptoFile(absolutePath, fileSource.cryptoArgs, to.toFile().absolutePath)
showToast(generalGetString(MR.strings.file_saved))
} catch (e: Exception) {
Log.e(TAG, "Unable to decrypt crypto file: " + e.stackTraceToString())
}
} else {
copyFileToFile(File(fileSource.filePath), to) {}
copyFileToFile(File(absolutePath), to) {}
}
}
}.launch(fileSource.filePath)

View File

@ -52,7 +52,7 @@ actual class VideoPlayer actual constructor(
private fun start(seek: Long? = null, onProgressUpdate: (position: Long?, state: TrackState) -> Unit): Boolean {
val filepath = getAppFilePath(uri)
if (filepath == null || !File(filepath).exists()) {
Log.e(TAG, "No such file: $uri")
Log.e(TAG, "No such file: $filepath")
brokenVideo.value = true
return false
}
@ -62,10 +62,9 @@ actual class VideoPlayer actual constructor(
}
AudioPlayer.stop()
VideoPlayerHolder.stopAll()
val playerFilePath = uri.toString().replaceFirst("file:", "file://")
if (listener.value == null) {
runCatching {
player.media().prepare(playerFilePath)
player.media().prepare(uri.toFile().absolutePath)
if (seek != null) {
player.seekTo(seek.toInt())
}
@ -217,12 +216,12 @@ actual class VideoPlayer actual constructor(
suspend fun getBitmapFromVideo(defaultPreview: ImageBitmap?, uri: URI?, withAlertOnException: Boolean = true): VideoPlayerInterface.PreviewAndDuration = withContext(playerThread.asCoroutineDispatcher()) {
val mediaComponent = getOrCreateHelperPlayer()
val player = mediaComponent.mediaPlayer()
if (uri == null || !File(uri.rawPath).exists()) {
if (uri == null || !uri.toFile().exists()) {
if (withAlertOnException) showVideoDecodingException()
return@withContext VideoPlayerInterface.PreviewAndDuration(preview = defaultPreview, timestamp = 0L, duration = 0L)
}
player.media().startPaused(uri.toString().replaceFirst("file:", "file://"))
player.media().startPaused(uri.toFile().absolutePath)
val start = System.currentTimeMillis()
var snap: BufferedImage? = null
while (snap == null && start + 5000 > System.currentTimeMillis()) {

View File

@ -3,7 +3,7 @@ package chat.simplex.common.platform
import java.net.URI
fun isVideo(uri: URI): Boolean {
val path = uri.path.lowercase()
val path = uri.toFile().path.lowercase()
return path.endsWith(".mov") ||
path.endsWith(".avi") ||
path.endsWith(".mp4") ||

View File

@ -8,14 +8,12 @@ import androidx.compose.ui.unit.Density
import chat.simplex.common.model.*
import chat.simplex.common.platform.*
import chat.simplex.common.simplexWindowState
import chat.simplex.res.MR
import java.io.ByteArrayInputStream
import java.io.File
import java.net.URI
import javax.imageio.ImageIO
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi
import kotlin.io.path.toPath
private val bStyle = SpanStyle(fontWeight = FontWeight.Bold)
private val iStyle = SpanStyle(fontStyle = FontStyle.Italic)
@ -90,9 +88,9 @@ actual fun escapedHtmlToAnnotatedString(text: String, density: Density): Annotat
actual fun getAppFileUri(fileName: String): URI {
val rh = chatModel.currentRemoteHost.value
return if (rh == null) {
URI(appFilesDir.toURI().toString() + "/" + fileName)
createURIFromPath(appFilesDir.absolutePath + "/" + fileName)
} else {
URI(dataDir.absolutePath + "/remote_hosts/" + rh.storePath + "/simplex_v1_files/" + fileName)
createURIFromPath(dataDir.absolutePath + "/remote_hosts/" + rh.storePath + "/simplex_v1_files/" + fileName)
}
}
@ -116,11 +114,11 @@ actual suspend fun getLoadedImage(file: CIFile?): Pair<ImageBitmap, ByteArray>?
}
}
actual fun getFileName(uri: URI): String? = uri.toPath().toFile().name
actual fun getFileName(uri: URI): String? = uri.toFile().name
actual fun getAppFilePath(uri: URI): String? = uri.path
actual fun getAppFilePath(uri: URI): String? = uri.toFile().absolutePath
actual fun getFileSize(uri: URI): Long? = uri.toPath().toFile().length()
actual fun getFileSize(uri: URI): Long? = uri.toFile().length()
actual fun getBitmapFromUri(uri: URI, withAlertOnException: Boolean): ImageBitmap? =
try {

View File

@ -1,5 +1,5 @@
name: simplex-chat
version: 5.4.0.5
version: 5.4.0.6
#synopsis:
#description:
homepage: https://github.com/simplex-chat/simplex-chat#readme

View File

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

View File

@ -6066,8 +6066,9 @@ chatCommandP =
("/help groups" <|> "/help group" <|> "/hg") $> ChatHelp HSGroups,
("/help contacts" <|> "/help contact" <|> "/hc") $> ChatHelp HSContacts,
("/help address" <|> "/ha") $> ChatHelp HSMyAddress,
"/help incognito" $> ChatHelp HSIncognito,
("/help incognito" <|> "/hi") $> ChatHelp HSIncognito,
("/help messages" <|> "/hm") $> ChatHelp HSMessages,
("/help remote" <|> "/hr") $> ChatHelp HSRemote,
("/help settings" <|> "/hs") $> ChatHelp HSSettings,
("/help db" <|> "/hd") $> ChatHelp HSDatabase,
("/help" <|> "/h") $> ChatHelp HSMain,
@ -6174,7 +6175,6 @@ chatCommandP =
"/set disappear " *> (SetUserTimedMessages <$> (("yes" $> True) <|> ("no" $> False))),
("/incognito" <* optional (A.space *> onOffP)) $> ChatHelp HSIncognito,
"/set device name " *> (SetLocalDeviceName <$> textP),
-- "/create remote host" $> CreateRemoteHost,
"/list remote hosts" $> ListRemoteHosts,
"/switch remote host " *> (SwitchRemoteHost <$> ("local" $> Nothing <|> (Just <$> A.decimal))),
"/start remote host " *> (StartRemoteHost <$> ("new" $> Nothing <|> (Just <$> ((,) <$> A.decimal <*> (" multicast=" *> onOffP <|> pure False))))),

View File

@ -203,7 +203,7 @@ data ChatController = ChatController
contactMergeEnabled :: TVar Bool
}
data HelpSection = HSMain | HSFiles | HSGroups | HSContacts | HSMyAddress | HSIncognito | HSMarkdown | HSMessages | HSSettings | HSDatabase
data HelpSection = HSMain | HSFiles | HSGroups | HSContacts | HSMyAddress | HSIncognito | HSMarkdown | HSMessages | HSRemote | HSSettings | HSDatabase
deriving (Show)
data ChatCommand
@ -662,14 +662,14 @@ data ChatResponse
| CRRemoteHostSessionCode {remoteHost_ :: Maybe RemoteHostInfo, sessionCode :: Text}
| CRNewRemoteHost {remoteHost :: RemoteHostInfo}
| CRRemoteHostConnected {remoteHost :: RemoteHostInfo}
| CRRemoteHostStopped {remoteHostId_ :: Maybe RemoteHostId}
| CRRemoteHostStopped {remoteHostId_ :: Maybe RemoteHostId, rhsState :: RemoteHostSessionState, rhStopReason :: RemoteHostStopReason}
| CRRemoteFileStored {remoteHostId :: RemoteHostId, remoteFileSource :: CryptoFile}
| CRRemoteCtrlList {remoteCtrls :: [RemoteCtrlInfo]}
| CRRemoteCtrlFound {remoteCtrl :: RemoteCtrlInfo, ctrlAppInfo_ :: Maybe CtrlAppInfo, appVersion :: AppVersion, compatible :: Bool}
| CRRemoteCtrlConnecting {remoteCtrl_ :: Maybe RemoteCtrlInfo, ctrlAppInfo :: CtrlAppInfo, appVersion :: AppVersion}
| CRRemoteCtrlSessionCode {remoteCtrl_ :: Maybe RemoteCtrlInfo, sessionCode :: Text}
| CRRemoteCtrlConnected {remoteCtrl :: RemoteCtrlInfo}
| CRRemoteCtrlStopped
| CRRemoteCtrlStopped {rcsState :: RemoteCtrlSessionState, rcStopReason :: RemoteCtrlStopReason}
| CRSQLResult {rows :: [Text]}
| CRSlowSQLQueries {chatQueries :: [SlowSQLQuery], agentQueries :: [SlowSQLQuery]}
| CRDebugLocks {chatLockName :: Maybe String, agentLocks :: AgentLocks}
@ -700,14 +700,14 @@ allowRemoteEvent = \case
CRRemoteHostSessionCode {} -> False
CRNewRemoteHost _ -> False
CRRemoteHostConnected _ -> False
CRRemoteHostStopped _ -> False
CRRemoteHostStopped {} -> False
CRRemoteFileStored {} -> False
CRRemoteCtrlList _ -> False
CRRemoteCtrlFound {} -> False
CRRemoteCtrlConnecting {} -> False
CRRemoteCtrlSessionCode {} -> False
CRRemoteCtrlConnected _ -> False
CRRemoteCtrlStopped -> False
CRRemoteCtrlStopped {} -> False
CRSQLResult _ -> False
CRSlowSQLQueries {} -> False
_ -> True
@ -1083,6 +1083,12 @@ data RemoteHostError
| RHEProtocolError RemoteProtocolError
deriving (Show, Exception)
data RemoteHostStopReason
= RHSRConnectionFailed ChatError
| RHSRCrashed ChatError
| RHSRDisconnected
deriving (Show, Exception)
-- TODO review errors, some of it can be covered by HTTP2 errors
data RemoteCtrlError
= RCEInactive -- ^ No session is running
@ -1098,6 +1104,13 @@ data RemoteCtrlError
| RCEProtocolError {protocolError :: RemoteProtocolError}
deriving (Show, Exception)
data RemoteCtrlStopReason
= RCSRDiscoveryFailed ChatError
| RCSRConnectionFailed ChatError
| RCSRSetupFailed ChatError
| RCSRDisconnected
deriving (Show, Exception)
data ArchiveError
= AEImport {chatError :: ChatError}
| AEImportFile {file :: String, chatError :: ChatError}
@ -1323,6 +1336,10 @@ $(JQ.deriveJSON (sumTypeJSON $ dropPrefix "RCS") ''RemoteCtrlSessionState)
$(JQ.deriveJSON defaultJSON ''RemoteCtrlInfo)
$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "RCSR") ''RemoteCtrlStopReason)
$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "RHSR") ''RemoteHostStopReason)
$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "CR") ''ChatResponse)
$(JQ.deriveFromJSON defaultJSON ''ArchiveConfig)

View File

@ -10,6 +10,7 @@ module Simplex.Chat.Help
myAddressHelpInfo,
incognitoHelpInfo,
messagesHelpInfo,
remoteHelpInfo,
markdownInfo,
settingsInfo,
databaseHelpInfo,
@ -87,7 +88,7 @@ chatHelpInfo =
green "Create your address: " <> highlight "/address",
"",
green "Other commands:",
indent <> highlight "/help <topic> " <> " - help on: " <> listHighlight ["groups", "contacts", "messages", "files", "address", "settings", "db"],
indent <> highlight "/help <topic> " <> " - help on: " <> listHighlight ["groups", "contacts", "messages", "files", "address", "incognito", "remote", "settings", "db"],
indent <> highlight "/profile " <> " - show / update user profile",
indent <> highlight "/delete <contact>" <> " - delete contact and all messages with them",
indent <> highlight "/chats " <> " - most recent chats",
@ -272,6 +273,34 @@ messagesHelpInfo =
indent <> highlight "! #team (hi) <new msg> " <> " - to edit your message in the group #team"
]
remoteHelpInfo :: [StyledString]
remoteHelpInfo =
map
styleMarkdown
[ green "Remote control",
"You can use CLI as a remote controller for a mobile app or as a remote host for a desktop app (or another CLI).",
"For example, you can run CLI on a server and use it from a desktop computer, connecting via SSH port forwarding.",
"",
indent <> highlight "/set device name <name> " <> " - set CLI name for remote connections",
"",
green "Using as remote controller",
indent <> highlight "/start remote host new " <> " - pair and connect a new remote host",
indent <> highlight "/start remote host <id> [multicast=on] " <> " - start connection with a known (paired) remote host",
indent <> highlight "/stop remote host new " <> " - cancel pairing with a new remote host",
indent <> highlight "/stop remote host <id> " <> " - stop connection with connected remote host",
indent <> highlight "/switch remote host local " <> " - switch to using local database",
indent <> highlight "/switch remote host <id> " <> " - switch to connected remote host",
indent <> highlight "/list remote hosts " <> " - list known remote hosts",
indent <> highlight "/delete remote host <id> " <> " - delete (unpair) known remote hosts - also deletes all host files from controller",
"",
green "Using as remote host",
indent <> highlight "/connect remote ctrl <session_address> " <> " - connect to remote controller via the adress from /start remote host",
indent <> highlight "/stop remote ctrl " <> " - stop connection with remote controller",
indent <> highlight "/find remote ctrl " <> " - find known remote controller on the local network (it should be started with multicast=on)",
indent <> highlight "/list remote ctrls " <> " - list known remote controllers",
indent <> highlight "/delete remote ctrl <id> " <> " - delete known remote controller"
]
markdownInfo :: [StyledString]
markdownInfo =
map

View File

@ -169,12 +169,12 @@ startRemoteHost rh_ = do
handleConnectError :: ChatMonad m => RHKey -> SessionSeq -> m a -> m a
handleConnectError rhKey sessSeq action = action `catchChatError` \err -> do
logError $ "startRemoteHost.rcConnectHost crashed: " <> tshow err
cancelRemoteHostSession (Just sessSeq) rhKey
cancelRemoteHostSession (Just (sessSeq, RHSRConnectionFailed err)) rhKey
throwError err
handleHostError :: ChatMonad m => SessionSeq -> TVar RHKey -> m () -> m ()
handleHostError sessSeq rhKeyVar action = action `catchChatError` \err -> do
logError $ "startRemoteHost.waitForHostSession crashed: " <> tshow err
readTVarIO rhKeyVar >>= cancelRemoteHostSession (Just sessSeq)
readTVarIO rhKeyVar >>= cancelRemoteHostSession (Just (sessSeq, RHSRCrashed err))
waitForHostSession :: ChatMonad m => Maybe RemoteHostInfo -> RHKey -> SessionSeq -> TVar RHKey -> RCStepTMVar (ByteString, TLS, RCStepTMVar (RCHostSession, RCHostHello, RCHostPairing)) -> m ()
waitForHostSession remoteHost_ rhKey sseq rhKeyVar vars = do
(sessId, tls, vars') <- timeoutThrow (ChatErrorRemoteHost rhKey RHETimeout) 60000000 $ takeRCStep vars
@ -220,7 +220,7 @@ startRemoteHost rh_ = do
onDisconnected :: ChatMonad m => RHKey -> SessionSeq -> m ()
onDisconnected rhKey sseq = do
logDebug $ "HTTP2 client disconnected: " <> tshow (rhKey, sseq)
cancelRemoteHostSession (Just sseq) rhKey
cancelRemoteHostSession (Just (sseq, RHSRDisconnected)) rhKey
pollEvents :: ChatMonad m => RemoteHostId -> RemoteHostClient -> m ()
pollEvents rhId rhClient = do
oq <- asks outputQ
@ -246,24 +246,25 @@ closeRemoteHost rhKey = do
logNote $ "Closing remote host session for " <> tshow rhKey
cancelRemoteHostSession Nothing rhKey
cancelRemoteHostSession :: ChatMonad m => Maybe SessionSeq -> RHKey -> m ()
cancelRemoteHostSession sseq_ rhKey = do
cancelRemoteHostSession :: ChatMonad m => Maybe (SessionSeq, RemoteHostStopReason) -> RHKey -> m ()
cancelRemoteHostSession handlerInfo_ rhKey = do
sessions <- asks remoteHostSessions
crh <- asks currentRemoteHost
deregistered <- atomically $
TM.lookup rhKey sessions >>= \case
Nothing -> pure Nothing
Just (sessSeq, _) | maybe False (/= sessSeq) sseq_ -> pure Nothing -- ignore cancel from a ghost session handler
Just (sessSeq, _) | maybe False (/= sessSeq) (fst <$> handlerInfo_) -> pure Nothing -- ignore cancel from a ghost session handler
Just (_, rhs) -> do
TM.delete rhKey sessions
modifyTVar' crh $ \cur -> if (RHId <$> cur) == Just rhKey then Nothing else cur -- only wipe the closing RH
pure $ Just rhs
forM_ deregistered $ \session -> do
liftIO $ cancelRemoteHost handlingError session `catchAny` (logError . tshow)
when handlingError $ toView $ CRRemoteHostStopped rhId_
forM_ (snd <$> handlerInfo_) $ \rhStopReason ->
toView $ CRRemoteHostStopped {remoteHostId_, rhsState = rhsSessionState session, rhStopReason}
where
handlingError = isJust sseq_
rhId_ = case rhKey of
handlingError = isJust handlerInfo_
remoteHostId_ = case rhKey of
RHNew -> Nothing
RHId rhId -> Just rhId
@ -395,7 +396,7 @@ findKnownRemoteCtrl = do
sseq <- startRemoteCtrlSession
foundCtrl <- newEmptyTMVarIO
cmdOk <- newEmptyTMVarIO
action <- async $ handleCtrlError sseq "findKnownRemoteCtrl.discover" $ do
action <- async $ handleCtrlError sseq RCSRDiscoveryFailed "findKnownRemoteCtrl.discover" $ do
atomically $ takeTMVar cmdOk
(RCCtrlPairing {ctrlFingerprint}, inv@(RCVerifiedInvitation RCInvitation {app})) <-
timeoutThrow (ChatErrorRemoteCtrl RCETimeout) discoveryTimeout . withAgent $ \a -> rcDiscoverCtrl a pairings
@ -441,7 +442,7 @@ startRemoteCtrlSession = do
Right sseq <$ writeTVar session (Just (sseq, RCSessionStarting))
connectRemoteCtrl :: ChatMonad m => RCVerifiedInvitation -> SessionSeq -> m (Maybe RemoteCtrlInfo, CtrlAppInfo)
connectRemoteCtrl verifiedInv@(RCVerifiedInvitation inv@RCInvitation {ca, app}) sseq = handleCtrlError sseq "connectRemoteCtrl" $ do
connectRemoteCtrl verifiedInv@(RCVerifiedInvitation inv@RCInvitation {ca, app}) sseq = handleCtrlError sseq RCSRConnectionFailed "connectRemoteCtrl" $ do
ctrlInfo@CtrlAppInfo {deviceName = ctrlDeviceName} <- parseCtrlAppInfo app
v <- checkAppVersion ctrlInfo
rc_ <- withStore' $ \db -> getRemoteCtrlByFingerprint db ca
@ -452,7 +453,7 @@ connectRemoteCtrl verifiedInv@(RCVerifiedInvitation inv@RCInvitation {ca, app})
cmdOk <- newEmptyTMVarIO
rcsWaitSession <- async $ do
atomically $ takeTMVar cmdOk
handleCtrlError sseq "waitForCtrlSession" $ waitForCtrlSession rc_ ctrlDeviceName rcsClient vars
handleCtrlError sseq RCSRConnectionFailed "waitForCtrlSession" $ waitForCtrlSession rc_ ctrlDeviceName rcsClient vars
updateRemoteCtrlSession sseq $ \case
RCSessionStarting -> Right RCSessionConnecting {remoteCtrlId_ = remoteCtrlId' <$> rc_, rcsClient, rcsWaitSession}
_ -> Left $ ChatErrorRemoteCtrl RCEBadState
@ -602,7 +603,7 @@ verifyRemoteCtrlSession execChatCommand sessCode' = do
Nothing -> throwError $ ChatErrorRemoteCtrl RCEInactive
Just (sseq, RCSessionPendingConfirmation {rcsClient, ctrlDeviceName = ctrlName, sessionCode, rcsWaitConfirmation}) -> pure (sseq, rcsClient, ctrlName, sessionCode, rcsWaitConfirmation)
_ -> throwError $ ChatErrorRemoteCtrl RCEBadState
handleCtrlError sseq "verifyRemoteCtrlSession" $ do
handleCtrlError sseq RCSRSetupFailed "verifyRemoteCtrlSession" $ do
let verified = sameVerificationCode sessCode' sessionCode
timeoutThrow (ChatErrorRemoteCtrl RCETimeout) networkIOTimeout . liftIO $ confirmCtrlSession client verified -- signal verification result before crashing
unless verified $ throwError $ ChatErrorRemoteCtrl $ RCEProtocolError PRESessionCode
@ -630,31 +631,32 @@ verifyRemoteCtrlSession execChatCommand sessCode' = do
monitor sseq server = do
res <- waitCatch server
logInfo $ "HTTP2 server stopped: " <> tshow res
cancelActiveRemoteCtrl (Just sseq)
cancelActiveRemoteCtrl $ Just (sseq, RCSRDisconnected)
stopRemoteCtrl :: ChatMonad m => m ()
stopRemoteCtrl = cancelActiveRemoteCtrl Nothing
handleCtrlError :: ChatMonad m => SessionSeq -> Text -> m a -> m a
handleCtrlError sseq name action =
handleCtrlError :: ChatMonad m => SessionSeq -> (ChatError -> RemoteCtrlStopReason) -> Text -> m a -> m a
handleCtrlError sseq mkReason name action =
action `catchChatError` \e -> do
logError $ name <> " remote ctrl error: " <> tshow e
cancelActiveRemoteCtrl (Just sseq)
cancelActiveRemoteCtrl $ Just (sseq, mkReason e)
throwError e
-- | Stop session controller, unless session update key is present but stale
cancelActiveRemoteCtrl :: ChatMonad m => Maybe SessionSeq -> m ()
cancelActiveRemoteCtrl sseq_ = handleAny (logError . tshow) $ do
cancelActiveRemoteCtrl :: ChatMonad m => Maybe (SessionSeq, RemoteCtrlStopReason) -> m ()
cancelActiveRemoteCtrl handlerInfo_ = handleAny (logError . tshow) $ do
var <- asks remoteCtrlSession
session_ <- atomically $ readTVar var >>= \case
Nothing -> pure Nothing
Just (oldSeq, _) | maybe False (/= oldSeq) sseq_ -> pure Nothing
Just (oldSeq, _) | maybe False (/= oldSeq) (fst <$> handlerInfo_) -> pure Nothing
Just (_, s) -> Just s <$ writeTVar var Nothing
forM_ session_ $ \session -> do
liftIO $ cancelRemoteCtrl handlingError session
when handlingError $ toView CRRemoteCtrlStopped
forM_ (snd <$> handlerInfo_) $ \rcStopReason ->
toView CRRemoteCtrlStopped {rcsState = rcsSessionState session, rcStopReason}
where
handlingError = isJust sseq_
handlingError = isJust handlerInfo_
cancelRemoteCtrl :: Bool -> RemoteCtrlSession -> IO ()
cancelRemoteCtrl handlingError = \case

View File

@ -58,13 +58,15 @@ runInputLoop ct@ChatTerminal {termState, liveMessageState} cc = forever $ do
rh' = if either (const False) allowRemoteCommand cmd then rh else Nothing
unless (isMessage cmd) $ echo s
r <- runReaderT (execChatCommand rh' bs) cc
processResp s cmd r
processResp s cmd rh r
printRespToTerminal ct cc False rh r
startLiveMessage cmd r
where
echo s = printToTerminal ct [plain s]
processResp s cmd = \case
CRActiveUser _ -> setActive ct ""
processResp s cmd rh = \case
CRActiveUser u -> case rh of
Nothing -> setActive ct ""
Just rhId -> updateRemoteUser ct u rhId
CRChatItems u chatName_ _ -> whenCurrUser cc u $ mapM_ (setActive ct . chatActiveTo) chatName_
CRNewChatItem u (AChatItem _ SMDSnd cInfo _) -> whenCurrUser cc u $ setActiveChat ct cInfo
CRChatItemUpdated u (AChatItem _ SMDSnd cInfo _) -> whenCurrUser cc u $ setActiveChat ct cInfo

View File

@ -10,6 +10,8 @@
module Simplex.Chat.Terminal.Output where
import Control.Concurrent (ThreadId)
import Control.Logger.Simple
import Control.Monad
import Control.Monad.Catch (MonadMask)
import Control.Monad.Except
import Control.Monad.Reader
@ -18,21 +20,23 @@ import Data.Text (Text)
import qualified Data.Text as T
import Data.Time.Clock (getCurrentTime)
import Data.Time.LocalTime (getCurrentTimeZone)
import Simplex.Chat (processChatCommand)
import Simplex.Chat (execChatCommand, processChatCommand)
import Simplex.Chat.Controller
import Simplex.Chat.Markdown
import Simplex.Chat.Messages
import Simplex.Chat.Messages.CIContent (CIContent(..), SMsgDirection (..))
import Simplex.Chat.Options
import Simplex.Chat.Protocol (MsgContent (..), msgContentText)
import Simplex.Chat.Remote.Types (RemoteHostId)
import Simplex.Chat.Remote.Types (RHKey (..), RemoteHostId, RemoteHostInfo (..), RemoteHostSession (..))
import Simplex.Chat.Styled
import Simplex.Chat.Terminal.Notification (Notification (..), initializeNotifications)
import Simplex.Chat.Types
import Simplex.Chat.View
import Simplex.Messaging.Agent.Protocol
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Util (safeDecodeUtf8)
import Simplex.Messaging.TMap (TMap)
import qualified Simplex.Messaging.TMap as TM
import Simplex.Messaging.Util (safeDecodeUtf8, tshow)
import System.Console.ANSI.Types
import System.IO (IOMode (..), hPutStrLn, withFile)
import System.Mem.Weak (Weak)
@ -48,7 +52,8 @@ data ChatTerminal = ChatTerminal
nextMessageRow :: TVar Int,
termLock :: TMVar (),
sendNotification :: Maybe (Notification -> IO ()),
activeTo :: TVar String
activeTo :: TVar String,
currentRemoteUsers :: TMap RemoteHostId User
}
data TerminalState = TerminalState
@ -103,6 +108,7 @@ newChatTerminal t opts = do
nextMessageRow <- newTVarIO lastRow
sendNotification <- if muteNotifications opts then pure Nothing else Just <$> initializeNotifications
activeTo <- newTVarIO ""
currentRemoteUsers <- newTVarIO mempty
-- threadDelay 500000 -- this delay is the same as timeout in getTerminalSize
pure
ChatTerminal
@ -113,7 +119,8 @@ newChatTerminal t opts = do
nextMessageRow,
termLock,
sendNotification,
activeTo
activeTo,
currentRemoteUsers
}
mkTermState :: TerminalState
@ -142,12 +149,14 @@ runTerminalOutput ct cc@ChatController {outputQ, showLiveItems, logFilePath} = d
case r of
CRNewChatItem u ci -> markChatItemRead u ci
CRChatItemUpdated u ci -> markChatItemRead u ci
CRRemoteHostConnected {remoteHost = RemoteHostInfo {remoteHostId}} -> getRemoteUser remoteHostId
CRRemoteHostStopped {remoteHostId_} -> mapM_ removeRemoteUser remoteHostId_
_ -> pure ()
let printResp = case logFilePath of
Just path -> if logResponseToFile r then logResponse path else printToTerminal ct
_ -> printToTerminal ct
liveItems <- readTVarIO showLiveItems
responseString cc liveItems outputRH r >>= printResp
responseString ct cc liveItems outputRH r >>= printResp
responseNotification ct cc r
where
markChatItemRead u (AChatItem _ _ chat ci@ChatItem {chatDir, meta = CIMeta {itemStatus}}) =
@ -158,6 +167,10 @@ runTerminalOutput ct cc@ChatController {outputQ, showLiveItems, logFilePath} = d
void $ runReaderT (runExceptT $ processChatCommand (APIChatRead chatRef (Just (itemId, itemId)))) cc
_ -> pure ()
logResponse path s = withFile path AppendMode $ \h -> mapM_ (hPutStrLn h . unStyle) s
getRemoteUser rhId = runReaderT (execChatCommand (Just rhId) "/user") cc >>= \case
CRActiveUser {user} -> updateRemoteUser ct user rhId
cr -> logError $ "Unexpected reply while getting remote user: " <> tshow cr
removeRemoteUser rhId = atomically $ TM.delete rhId (currentRemoteUsers ct)
responseNotification :: ChatTerminal -> ChatController -> ChatResponse -> IO ()
responseNotification t@ChatTerminal {sendNotification} cc = \case
@ -254,15 +267,29 @@ whenCurrUser cc u a = do
sameUser User {userId = uId} = maybe False $ \User {userId} -> userId == uId
printRespToTerminal :: ChatTerminal -> ChatController -> Bool -> Maybe RemoteHostId -> ChatResponse -> IO ()
printRespToTerminal ct cc liveItems outputRH r = responseString cc liveItems outputRH r >>= printToTerminal ct
printRespToTerminal ct cc liveItems outputRH r = responseString ct cc liveItems outputRH r >>= printToTerminal ct
responseString :: ChatController -> Bool -> Maybe RemoteHostId -> ChatResponse -> IO [StyledString]
responseString cc liveItems outputRH r = do
currentRH <- readTVarIO $ currentRemoteHost cc
user <- readTVarIO $ currentUser cc -- XXX: local user, should be subsumed by remote when connected
responseString :: ChatTerminal -> ChatController -> Bool -> Maybe RemoteHostId -> ChatResponse -> IO [StyledString]
responseString ct cc liveItems outputRH r = do
cu <- getCurrentUser ct cc
ts <- getCurrentTime
tz <- getCurrentTimeZone
pure $ responseToView (currentRH, user) (config cc) liveItems ts tz outputRH r
pure $ responseToView cu (config cc) liveItems ts tz outputRH r
updateRemoteUser :: ChatTerminal -> User -> RemoteHostId -> IO ()
updateRemoteUser ct user rhId = atomically $ TM.insert rhId user (currentRemoteUsers ct)
getCurrentUser :: ChatTerminal -> ChatController -> IO (Maybe RemoteHostId, Maybe User)
getCurrentUser ct cc = atomically $ do
localUser_ <- readTVar (currentUser cc)
readTVar (currentRemoteHost cc) >>= \case
Nothing -> pure (Nothing, localUser_)
Just rhId ->
TM.lookup (RHId rhId) (remoteHostSessions cc) >>= \case
Just (_, RHSessionConnected {}) -> do
hostUser_ <- TM.lookup rhId (currentRemoteUsers ct)
pure (Just rhId, hostUser_)
_ -> pure (Nothing, localUser_)
printToTerminal :: ChatTerminal -> [StyledString] -> IO ()
printToTerminal ct s =

View File

@ -135,6 +135,7 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe
HSIncognito -> incognitoHelpInfo
HSMessages -> messagesHelpInfo
HSMarkdown -> markdownInfo
HSRemote -> remoteHelpInfo
HSSettings -> settingsInfo
HSDatabase -> databaseHelpInfo
CRWelcome user -> chatWelcome user
@ -298,8 +299,8 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe
]
CRNewRemoteHost RemoteHostInfo {remoteHostId = rhId, hostDeviceName} -> ["new remote host " <> sShow rhId <> " added: " <> plain hostDeviceName]
CRRemoteHostConnected RemoteHostInfo {remoteHostId = rhId} -> ["remote host " <> sShow rhId <> " connected"]
CRRemoteHostStopped rhId_ ->
[ maybe "new remote host" (mappend "remote host " . sShow) rhId_ <> " stopped"
CRRemoteHostStopped {remoteHostId_} ->
[ maybe "new remote host" (mappend "remote host " . sShow) remoteHostId_ <> " stopped"
]
CRRemoteFileStored rhId (CryptoFile filePath cfArgs_) ->
[plain $ "file " <> filePath <> " stored on remote host " <> show rhId]
@ -309,8 +310,9 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe
[ "remote controller " <> sShow remoteCtrlId <> " found: "
<> maybe (deviceName <> "not compatible") (\info -> viewRemoteCtrl info appVersion compatible) ctrlAppInfo_
]
<> [ "use " <> highlight ("/confirm remote ctrl " <> show remoteCtrlId) <> " to connect" | isJust ctrlAppInfo_ && compatible]
where
deviceName = if T.null ctrlDeviceName then "" else plain ctrlDeviceName <> ", "
deviceName = if T.null ctrlDeviceName then "" else plain ctrlDeviceName <> ", "
CRRemoteCtrlConnecting {remoteCtrl_, ctrlAppInfo, appVersion} ->
[ (maybe "connecting new remote controller" (\RemoteCtrlInfo {remoteCtrlId} -> "connecting remote controller " <> sShow remoteCtrlId) remoteCtrl_ <> ": ")
<> viewRemoteCtrl ctrlAppInfo appVersion True
@ -322,7 +324,7 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe
]
CRRemoteCtrlConnected RemoteCtrlInfo {remoteCtrlId = rcId, ctrlDeviceName} ->
["remote controller " <> sShow rcId <> " session started with " <> plain ctrlDeviceName]
CRRemoteCtrlStopped -> ["remote controller stopped"]
CRRemoteCtrlStopped {} -> ["remote controller stopped"]
CRSQLResult rows -> map plain rows
CRSlowSQLQueries {chatQueries, agentQueries} ->
let viewQuery SlowSQLQuery {query, queryStats = SlowQueryStats {count, timeMax, timeAvg}} =

View File

@ -44,6 +44,7 @@ remoteTests = describe "Remote" $ do
it "should send files from CLI without /store" remoteCLIFileTest
it "switches remote hosts" switchRemoteHostTest
it "indicates remote hosts" indicateRemoteHostTest
it "works with multiple profiles" multipleProfilesTest
-- * Chat commands
@ -416,6 +417,55 @@ indicateRemoteHostTest = testChat4 aliceProfile aliceDesktopProfile bobProfile c
desktop <##> cath
cath <##> desktop
multipleProfilesTest :: FilePath -> IO ()
multipleProfilesTest = testChat4 aliceProfile aliceDesktopProfile bobProfile cathProfile $ \mobile desktop bob cath -> do
connectUsers desktop cath
desktop ##> "/create user desk_bottom"
desktop <## "user profile: desk_bottom"
desktop <## "use /p <display name> to change it"
desktop <## "(the updated profile will be sent to all your contacts)"
desktop ##> "/users"
desktop <## "alice_desktop (Alice Desktop)"
desktop <## "desk_bottom (active)"
startRemote mobile desktop
contactBob desktop bob
desktop ##> "/users"
desktop <## "alice (Alice) (active)"
desktop ##> "/create user alt_alice"
desktop <## "user profile: alt_alice"
desktop <## "use /p <display name> to change it"
desktop <## "(the updated profile will be sent to all your contacts)"
desktop ##> "/users"
desktop <## "alice (Alice)"
desktop <## "alt_alice (active)"
desktop ##> "/user"
desktop <## "user profile: alt_alice"
desktop <## "use /p <display name> to change it"
desktop <## "(the updated profile will be sent to all your contacts)"
bob #> "@alice hi"
(desktop, "[user: alice] ") ^<# "bob> hi"
cath #> "@alice_desktop hello"
(desktop, "[local, user: alice_desktop] ") ^<# "cath> hello"
desktop ##> "/switch remote host local"
desktop <## "Using local profile"
desktop ##> "/user"
desktop <## "user profile: desk_bottom"
desktop <## "use /p <display name> to change it"
desktop <## "(the updated profile will be sent to all your contacts)"
bob #> "@alice hey"
(desktop, "[remote: 1, user: alice] ") ^<# "bob> hey"
stopDesktop mobile desktop
-- * Utils
startRemote :: TestCC -> TestCC -> IO ()
@ -460,6 +510,7 @@ startRemoteDiscover mobile desktop = do
mobile ##> "/find remote ctrl"
mobile <## "ok"
mobile <## ("remote controller 1 found: My desktop, v" <> versionNumber)
mobile <## "use /confirm remote ctrl 1 to connect"
mobile ##> "/confirm remote ctrl 1"
mobile <## ("connecting remote controller 1: My desktop, v" <> versionNumber)

View File

@ -164,7 +164,7 @@
"simplex-unique-card-3-p-1": "يخزن SimpleX جميع بيانات المستخدم على الأجهزة العميلة<strong> بتنسيق قاعدة بيانات محمولة مشفرة &mdash; </strong>يمكن نقله إلى جهاز آخر.",
"simplex-unique-card-4-p-1": "شبكة SimpleX لا مركزية بالكامل ومستقلة عن أي عملة مشفرة أو أي منصة أخرى، بخلاف الإنترنت.",
"simplex-unique-card-4-p-2": "يمكنك<strong> استخدام SimpleX مع خوادمك الخاصة </strong> أو مع الخوادم التي نوفرها &mdash; ولا يزال الاتصال ممكن بأي مستخدم.",
"join": "انضم الى",
"join": "انضم إلى",
"we-invite-you-to-join-the-conversation": "نحن ندعوك للانضمام إلى محادثة",
"join-the-REDDIT-community": "انضم إلى مجتمع REDDIT",
"join-us-on-GitHub": "انضم إلينا على GitHub",