mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-07-21 09:01:36 +00:00
ios: advanced server configuration (#1388)
* ios: advanced server configuration * UI is mostly working, QR code scan * refactor * error alerts * fixes * remove old view * rename view * translations * only show valid QR code, spinner during server test * update tested status on edit * space wtf Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com> * moar space * translation Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com> * translations * translations Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>
This commit is contained in:
co-authored by
JRoberts
parent
7544d2f9e7
commit
7e3d53b621
@@ -31,7 +31,8 @@ final class ChatModel: ObservableObject {
|
||||
// items in the terminal view
|
||||
@Published var terminalItems: [TerminalItem] = []
|
||||
@Published var userAddress: UserContactLink?
|
||||
@Published var userSMPServers: [String]?
|
||||
@Published var userSMPServers: [ServerCfg]?
|
||||
@Published var presetSMPServers: [String]?
|
||||
@Published var chatItemTTL: ChatItemTTL = .none
|
||||
@Published var appOpenUrl: URL?
|
||||
@Published var deviceToken: DeviceToken?
|
||||
|
||||
@@ -309,19 +309,19 @@ func apiDeleteToken(token: DeviceToken) async throws {
|
||||
try await sendCommandOkResp(.apiDeleteToken(token: token))
|
||||
}
|
||||
|
||||
func getUserSMPServers() throws -> [String] {
|
||||
func getUserSMPServers() throws -> ([ServerCfg], [String]) {
|
||||
let r = chatSendCmdSync(.getUserSMPServers)
|
||||
if case let .userSMPServers(smpServers, _) = r { return smpServers.map { $0.server } }
|
||||
if case let .userSMPServers(smpServers, presetServers) = r { return (smpServers, presetServers) }
|
||||
throw r
|
||||
}
|
||||
|
||||
func setUserSMPServers(smpServers: [String]) async throws {
|
||||
func setUserSMPServers(smpServers: [ServerCfg]) async throws {
|
||||
try await sendCommandOkResp(.setUserSMPServers(smpServers: smpServers))
|
||||
}
|
||||
|
||||
func testSMPServer(smpServer: String) async throws -> Result<(), SMPTestFailure> {
|
||||
let r = await chatSendCmd(.testSMPServer(smpServer: smpServer))
|
||||
if case let .sMPTestResult(testFailure) = r {
|
||||
if case let .smpTestResult(testFailure) = r {
|
||||
if let t = testFailure {
|
||||
return .failure(t)
|
||||
}
|
||||
@@ -843,7 +843,7 @@ func startChat() throws {
|
||||
let justStarted = try apiStartChat()
|
||||
if justStarted {
|
||||
m.userAddress = try apiGetUserAddress()
|
||||
m.userSMPServers = try getUserSMPServers()
|
||||
(m.userSMPServers, m.presetSMPServers) = try getUserSMPServers()
|
||||
m.chatItemTTL = try getChatItemTTL()
|
||||
let chats = try apiGetChats()
|
||||
m.chats = chats.map { Chat.init($0) }
|
||||
|
||||
@@ -131,7 +131,9 @@ struct GroupMemberInfoView: View {
|
||||
}
|
||||
if let chat = chat {
|
||||
dismissAllSheets(animated: true)
|
||||
chatModel.chatId = chat.id
|
||||
DispatchQueue.main.async {
|
||||
chatModel.chatId = chat.id
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Label("Send direct message", systemImage: "message")
|
||||
|
||||
@@ -9,6 +9,25 @@
|
||||
import SwiftUI
|
||||
import CoreImage.CIFilterBuiltins
|
||||
|
||||
struct MutableQRCode: View {
|
||||
@Binding var uri: String
|
||||
@State private var image: UIImage?
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
if let image = image {
|
||||
qrCodeImage(image)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
image = generateImage(uri)
|
||||
}
|
||||
.onChange(of: uri) { _ in
|
||||
image = generateImage(uri)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct QRCode: View {
|
||||
let uri: String
|
||||
@State private var image: UIImage?
|
||||
@@ -16,32 +35,32 @@ struct QRCode: View {
|
||||
var body: some View {
|
||||
ZStack {
|
||||
if let image = image {
|
||||
Image(uiImage: image)
|
||||
.resizable()
|
||||
.interpolation(.none)
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.textSelection(.enabled)
|
||||
qrCodeImage(image)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
generateImage()
|
||||
image = image ?? generateImage(uri)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func generateImage() {
|
||||
guard image == nil else { return }
|
||||
private func qrCodeImage(_ image: UIImage) -> some View {
|
||||
Image(uiImage: image)
|
||||
.resizable()
|
||||
.interpolation(.none)
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
|
||||
let context = CIContext()
|
||||
let filter = CIFilter.qrCodeGenerator()
|
||||
filter.message = Data(uri.utf8)
|
||||
|
||||
guard
|
||||
let outputImage = filter.outputImage,
|
||||
let cgImage = context.createCGImage(outputImage, from: outputImage.extent)
|
||||
else { return }
|
||||
|
||||
self.image = UIImage(cgImage: cgImage)
|
||||
private func generateImage(_ uri: String) -> UIImage? {
|
||||
let context = CIContext()
|
||||
let filter = CIFilter.qrCodeGenerator()
|
||||
filter.message = Data(uri.utf8)
|
||||
if let outputImage = filter.outputImage,
|
||||
let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
|
||||
return UIImage(cgImage: cgImage)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
struct QRCode_Previews: PreviewProvider {
|
||||
|
||||
@@ -33,18 +33,11 @@ struct NetworkAndServers: View {
|
||||
VStack {
|
||||
List {
|
||||
Section {
|
||||
NavigationLink {
|
||||
SMPServers()
|
||||
.navigationTitle("Your SMP servers")
|
||||
} label: {
|
||||
Text("SMP servers")
|
||||
}
|
||||
|
||||
NavigationLink {
|
||||
SMPServersView()
|
||||
.navigationTitle("Your SMP servers")
|
||||
} label: {
|
||||
Text("SMP servers (new)")
|
||||
Text("SMP servers")
|
||||
}
|
||||
|
||||
Picker("Use .onion hosts", selection: $onionHosts) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import SwiftUI
|
||||
|
||||
private let howToUrl = URL(string: "https://github.com/simplex-chat/simplex-chat/blob/stable/docs/WEBRTC.md#configure-mobile-apps")!
|
||||
|
||||
let serversFont = Font.custom("Menlo", size: 14)
|
||||
|
||||
struct RTCServers: View {
|
||||
@State private var userRTCServers: [String] = []
|
||||
|
||||
@@ -10,13 +10,46 @@ import SwiftUI
|
||||
import SimpleXChat
|
||||
|
||||
struct SMPServerView: View {
|
||||
@State var server: ServerCfg
|
||||
@Environment(\.dismiss) var dismiss: DismissAction
|
||||
@Binding var server: ServerCfg
|
||||
@State var serverToEdit: ServerCfg
|
||||
@State private var showTestFailure = false
|
||||
@State private var testing = false
|
||||
@State private var testFailure: SMPTestFailure?
|
||||
|
||||
var body: some View {
|
||||
if server.preset {
|
||||
presetServer()
|
||||
} else {
|
||||
customServer()
|
||||
ZStack {
|
||||
if server.preset {
|
||||
presetServer()
|
||||
} else {
|
||||
customServer()
|
||||
}
|
||||
if testing {
|
||||
ProgressView().scaleEffect(2)
|
||||
}
|
||||
}
|
||||
.navigationBarBackButtonHidden(true)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarLeading) {
|
||||
Button {
|
||||
server = serverToEdit
|
||||
dismiss()
|
||||
} label: {
|
||||
HStack {
|
||||
Image(systemName: "chevron.left")
|
||||
Text("Your SMP servers")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.alert(isPresented: $showTestFailure) {
|
||||
Alert(
|
||||
title: Text("Server test failed!"),
|
||||
message: Text(testFailure?.localizedDescription ?? "")
|
||||
)
|
||||
}
|
||||
.onChange(of: serverToEdit.server) { _ in
|
||||
serverToEdit.tested = serverToEdit.server == server.server ? server.tested : nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,47 +57,66 @@ struct SMPServerView: View {
|
||||
return VStack {
|
||||
List {
|
||||
Section("Preset server address") {
|
||||
Text(server.server)
|
||||
Text(serverToEdit.server)
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
useServerSection()
|
||||
useServerSection(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func customServer() -> some View {
|
||||
VStack {
|
||||
let valid = parseServerAddress(serverToEdit.server)?.valid == true
|
||||
List {
|
||||
Section("Your server address") {
|
||||
TextEditor(text: $server.server)
|
||||
Section {
|
||||
TextEditor(text: $serverToEdit.server)
|
||||
.multilineTextAlignment(.leading)
|
||||
.autocorrectionDisabled(true)
|
||||
.autocapitalization(.none)
|
||||
.allowsTightening(true)
|
||||
.lineLimit(10)
|
||||
.frame(height: 108)
|
||||
.frame(height: 144)
|
||||
.padding(-6)
|
||||
} header: {
|
||||
HStack {
|
||||
Text("Your server address")
|
||||
if !valid {
|
||||
Spacer()
|
||||
Image(systemName: "exclamationmark.circle").foregroundColor(.red)
|
||||
}
|
||||
}
|
||||
}
|
||||
useServerSection()
|
||||
Section("Add to another device") {
|
||||
QRCode(uri: server.server)
|
||||
.listRowInsets(EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12))
|
||||
useServerSection(valid)
|
||||
if valid {
|
||||
Section("Add to another device") {
|
||||
MutableQRCode(uri: $serverToEdit.server)
|
||||
.listRowInsets(EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func useServerSection() -> some View {
|
||||
private func useServerSection(_ valid: Bool) -> some View {
|
||||
Section("Use server") {
|
||||
HStack {
|
||||
Button("Test server") {
|
||||
Task { await testServerConnection(server: $server) }
|
||||
testing = true
|
||||
serverToEdit.tested = nil
|
||||
Task {
|
||||
if let f = await testServerConnection(server: $serverToEdit) {
|
||||
showTestFailure = true
|
||||
testFailure = f
|
||||
}
|
||||
await MainActor.run { testing = false }
|
||||
}
|
||||
}
|
||||
.disabled(!valid || testing)
|
||||
Spacer()
|
||||
showTestStatus(server: server)
|
||||
}
|
||||
Toggle("Enabled", isOn: $server.enabled)
|
||||
Button("Remove server", role: .destructive) {
|
||||
|
||||
showTestStatus(server: serverToEdit)
|
||||
}
|
||||
Toggle("Use for new connections", isOn: $serverToEdit.enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,24 +134,33 @@ struct SMPServerView: View {
|
||||
}
|
||||
}
|
||||
|
||||
func testServerConnection(server: Binding<ServerCfg>) async {
|
||||
func testServerConnection(server: Binding<ServerCfg>) async -> SMPTestFailure? {
|
||||
do {
|
||||
let r = try await testSMPServer(smpServer: server.wrappedValue.server)
|
||||
await MainActor.run {
|
||||
|
||||
switch r {
|
||||
case .success: server.wrappedValue.tested = true
|
||||
case .failure: server.wrappedValue.tested = false
|
||||
case .success:
|
||||
await MainActor.run { server.wrappedValue.tested = true }
|
||||
return nil
|
||||
case let .failure(f):
|
||||
await MainActor.run { server.wrappedValue.tested = false }
|
||||
return f
|
||||
}
|
||||
}
|
||||
} catch let error {
|
||||
logger.error("testServerConnection \(responseError(error))")
|
||||
await MainActor.run {
|
||||
server.wrappedValue.tested = false
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func serverHostname(_ srv: ServerCfg) -> String {
|
||||
parseServerAddress(srv.server)?.hostnames.first ?? srv.server
|
||||
}
|
||||
|
||||
struct SMPServerView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
SMPServerView(server: ServerCfg.sampleData.custom)
|
||||
SMPServerView(server: Binding.constant(ServerCfg.sampleData.custom), serverToEdit: ServerCfg.sampleData.custom)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
//
|
||||
// SMPServers.swift
|
||||
// SimpleX
|
||||
//
|
||||
// Created by Efim Poberezkin on 02.03.2022.
|
||||
// Copyright © 2022 SimpleX Chat. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SimpleXChat
|
||||
|
||||
let serversFont = Font.custom("Menlo", size: 14)
|
||||
|
||||
private let howToUrl = URL(string: "https://github.com/simplex-chat/simplexmq#using-smp-server-and-smp-agent")!
|
||||
|
||||
struct SMPServers: View {
|
||||
@EnvironmentObject var chatModel: ChatModel
|
||||
@State var isUserSMPServers = false
|
||||
@State var isUserSMPServersToggle = false
|
||||
@State var editSMPServers = true
|
||||
@State var userSMPServersStr = ""
|
||||
@State var showBadServersAlert = false
|
||||
@State var showResetServersAlert = false
|
||||
@FocusState private var keyboardVisible: Bool
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section {
|
||||
Toggle("Configure SMP servers", isOn: $isUserSMPServersToggle)
|
||||
.onChange(of: isUserSMPServersToggle) { _ in
|
||||
if (isUserSMPServersToggle) {
|
||||
isUserSMPServers = true
|
||||
} else {
|
||||
let servers = chatModel.userSMPServers ?? []
|
||||
if (!servers.isEmpty) {
|
||||
showResetServersAlert = true
|
||||
} else {
|
||||
isUserSMPServers = false
|
||||
userSMPServersStr = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
.alert(isPresented: $showResetServersAlert) {
|
||||
Alert(
|
||||
title: Text("Use SimpleX Chat servers?"),
|
||||
message: Text("Saved SMP servers will be removed"),
|
||||
primaryButton: .destructive(Text("Confirm")) {
|
||||
saveSMPServers(smpServers: [])
|
||||
isUserSMPServers = false
|
||||
userSMPServersStr = ""
|
||||
}, secondaryButton: .cancel() {
|
||||
withAnimation() {
|
||||
isUserSMPServersToggle = true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
} header: {
|
||||
Text("")
|
||||
} footer: {
|
||||
if !isUserSMPServers {
|
||||
Text("Using SimpleX Chat servers.")
|
||||
}
|
||||
}
|
||||
|
||||
if isUserSMPServers {
|
||||
Section {
|
||||
if editSMPServers {
|
||||
TextEditor(text: $userSMPServersStr)
|
||||
.focused($keyboardVisible)
|
||||
.font(serversFont)
|
||||
.disableAutocorrection(true)
|
||||
.textInputAutocapitalization(.never)
|
||||
.padding(.horizontal, -5)
|
||||
.padding(.top, -8)
|
||||
.frame(height: 160, alignment: .topLeading)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
} else {
|
||||
ScrollView {
|
||||
Text(userSMPServersStr)
|
||||
.font(serversFont)
|
||||
.frame(minHeight: 0, alignment: .topLeading)
|
||||
.textSelection(.enabled)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
.frame(height: 160)
|
||||
}
|
||||
} header: {
|
||||
Text("SMP servers (one per line)")
|
||||
} footer: {
|
||||
HStack(spacing: 20) {
|
||||
if editSMPServers {
|
||||
Button("Cancel") {
|
||||
initialize()
|
||||
}
|
||||
Button("Save") {
|
||||
saveUserSMPServers()
|
||||
}
|
||||
.alert(isPresented: $showBadServersAlert) {
|
||||
Alert(title: Text("Error saving SMP servers"), message: Text("Make sure SMP server addresses are in correct format, line separated and are not duplicated."))
|
||||
}
|
||||
Spacer()
|
||||
howToButton()
|
||||
} else {
|
||||
Button("Edit") {
|
||||
editSMPServers = true
|
||||
}
|
||||
Spacer()
|
||||
howToButton()
|
||||
}
|
||||
}
|
||||
.font(.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
.onAppear { initialize() }
|
||||
}
|
||||
|
||||
func initialize() {
|
||||
let userSMPServers = chatModel.userSMPServers ?? []
|
||||
isUserSMPServers = !userSMPServers.isEmpty
|
||||
isUserSMPServersToggle = isUserSMPServers
|
||||
editSMPServers = !isUserSMPServers
|
||||
userSMPServersStr = isUserSMPServers ? userSMPServers.joined(separator: "\n") : ""
|
||||
}
|
||||
|
||||
func saveUserSMPServers() {
|
||||
let userSMPServers = userSMPServersStr.components(separatedBy: "\n")
|
||||
saveSMPServers(smpServers: userSMPServers)
|
||||
}
|
||||
|
||||
func saveSMPServers(smpServers: [String]) {
|
||||
Task {
|
||||
do {
|
||||
try await setUserSMPServers(smpServers: smpServers)
|
||||
DispatchQueue.main.async {
|
||||
chatModel.userSMPServers = smpServers
|
||||
if smpServers.isEmpty {
|
||||
isUserSMPServers = false
|
||||
editSMPServers = true
|
||||
} else {
|
||||
editSMPServers = false
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
let err = error.localizedDescription
|
||||
logger.error("SMPServers.saveServers setUserSMPServers error: \(err)")
|
||||
DispatchQueue.main.async {
|
||||
showBadServersAlert = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func howToButton() -> some View {
|
||||
Button {
|
||||
DispatchQueue.main.async {
|
||||
UIApplication.shared.open(howToUrl)
|
||||
}
|
||||
} label: {
|
||||
HStack{
|
||||
Text("How to")
|
||||
Image(systemName: "arrow.up.right.circle")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO preview doesn't work
|
||||
struct SMPServers_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let chatModel = ChatModel()
|
||||
chatModel.currentUser = User.sampleData
|
||||
chatModel.userSMPServers = []
|
||||
return SMPServers()
|
||||
.environmentObject(chatModel)
|
||||
}
|
||||
}
|
||||
@@ -9,20 +9,43 @@
|
||||
import SwiftUI
|
||||
import SimpleXChat
|
||||
|
||||
private let howToUrl = URL(string: "https://github.com/simplex-chat/simplexmq#using-smp-server-and-smp-agent")!
|
||||
|
||||
struct SMPServersView: View {
|
||||
@Environment(\.editMode) var editMode
|
||||
@State var servers: [ServerCfg] = [
|
||||
ServerCfg.sampleData.preset,
|
||||
ServerCfg.sampleData.custom,
|
||||
ServerCfg.sampleData.untested,
|
||||
]
|
||||
@State var showAddServer = false
|
||||
@State var showSaveAlert = false
|
||||
@EnvironmentObject private var m: ChatModel
|
||||
@Environment(\.editMode) private var editMode
|
||||
@State private var servers = ChatModel.shared.userSMPServers ?? []
|
||||
@State private var selectedServer: String? = nil
|
||||
@State private var showAddServer = false
|
||||
@State private var showScanSMPServer = false
|
||||
@State private var testing = false
|
||||
@State private var alert: SMPServerAlert? = nil
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
smpServersView()
|
||||
if testing {
|
||||
ProgressView().scaleEffect(2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum SMPServerAlert: Identifiable {
|
||||
case testsFailed(failures: [String: SMPTestFailure])
|
||||
case error(title: LocalizedStringKey, error: String = "")
|
||||
|
||||
var id: String {
|
||||
switch self {
|
||||
case .testsFailed: return "testsFailed"
|
||||
case let .error(title, _): return "error \(title)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func smpServersView() -> some View {
|
||||
List {
|
||||
Section("SMP servers") {
|
||||
ForEach(servers) { srv in
|
||||
ForEach($servers) { srv in
|
||||
smpServerView(srv)
|
||||
}
|
||||
.onMove { indexSet, offset in
|
||||
@@ -31,68 +54,189 @@ struct SMPServersView: View {
|
||||
.onDelete { indexSet in
|
||||
servers.remove(atOffsets: indexSet)
|
||||
}
|
||||
if isEditing {
|
||||
Button("Add server…") {
|
||||
showAddServer = true
|
||||
}
|
||||
Button("Add server…") {
|
||||
showAddServer = true
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: isEditing) { value in
|
||||
if value == false {
|
||||
showSaveAlert = true
|
||||
|
||||
Section {
|
||||
Button("Reset") { servers = m.userSMPServers ?? [] }
|
||||
.disabled(servers == m.userSMPServers || testing)
|
||||
Button("Test servers", action: testServers)
|
||||
.disabled(testing)
|
||||
Button("Save servers", action: saveSMPServers)
|
||||
.disabled(saveDisabled)
|
||||
howToButton()
|
||||
}
|
||||
}
|
||||
.toolbar { EditButton() }
|
||||
.confirmationDialog("Add server…", isPresented: $showAddServer, titleVisibility: .hidden) {
|
||||
Button("Scan server QR code") {
|
||||
}
|
||||
Button("Add preset servers") {
|
||||
}
|
||||
Button("Enter server manually") {
|
||||
servers.append(ServerCfg.empty)
|
||||
selectedServer = servers.last?.id
|
||||
}
|
||||
Button("Scan server QR code") { showScanSMPServer = true }
|
||||
Button("Add preset servers", action: addAllPresets)
|
||||
.disabled(hasAllPresets())
|
||||
}
|
||||
.confirmationDialog("Save servers?", isPresented: $showSaveAlert, titleVisibility: .visible) {
|
||||
Button("Test & save servers") {
|
||||
for i in 0..<servers.count {
|
||||
servers[i].tested = nil
|
||||
}
|
||||
Task {
|
||||
for i in 0..<servers.count {
|
||||
await testServerConnection(server: $servers[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
Button("Save servers") {
|
||||
}
|
||||
Button("Revert changes") {
|
||||
}
|
||||
Button("Cancel", role: .cancel) {
|
||||
editMode?.wrappedValue = .active
|
||||
.sheet(isPresented: $showScanSMPServer) {
|
||||
ScanSMPServer(servers: $servers)
|
||||
}
|
||||
.alert(item: $alert) { a in
|
||||
switch a {
|
||||
case let .testsFailed(fs):
|
||||
let msg = fs.map { (srv, f) in
|
||||
"\(srv): \(f.localizedDescription)"
|
||||
}.joined(separator: "\n")
|
||||
return Alert(
|
||||
title: Text("Tests failed!"),
|
||||
message: Text("Some servers failed the test:\n" + msg)
|
||||
)
|
||||
case .error:
|
||||
return Alert(
|
||||
title: Text("Error")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var isEditing: Bool {
|
||||
editMode?.wrappedValue.isEditing == true
|
||||
private var saveDisabled: Bool {
|
||||
servers.count == 0 || servers == m.userSMPServers || testing || !servers.allSatisfy { srv in
|
||||
if let address = parseServerAddress(srv.server) {
|
||||
return uniqueAddress(srv, address)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private func smpServerView(_ srv: ServerCfg) -> some View {
|
||||
NavigationLink {
|
||||
SMPServerView(server: srv)
|
||||
.navigationBarTitle("Server")
|
||||
private func smpServerView(_ server: Binding<ServerCfg>) -> some View {
|
||||
let srv = server.wrappedValue
|
||||
return NavigationLink(tag: srv.id, selection: $selectedServer) {
|
||||
SMPServerView(server: server, serverToEdit: srv)
|
||||
.navigationBarTitle(srv.preset ? "Preset server" : "Your server")
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
} label: {
|
||||
let v = Text(srv.server)
|
||||
let address = parseServerAddress(srv.server)
|
||||
HStack {
|
||||
showTestStatus(server: srv)
|
||||
.frame(width: 16, alignment: .center)
|
||||
.padding(.trailing, 4)
|
||||
Group {
|
||||
if let address = address {
|
||||
if !address.valid {
|
||||
invalidServer()
|
||||
} else if !uniqueAddress(srv, address) {
|
||||
Image(systemName: "exclamationmark.circle").foregroundColor(.red)
|
||||
} else if !srv.enabled {
|
||||
Image(systemName: "slash.circle").foregroundColor(.secondary)
|
||||
} else {
|
||||
showTestStatus(server: srv)
|
||||
}
|
||||
} else {
|
||||
invalidServer()
|
||||
}
|
||||
}
|
||||
.frame(width: 16, alignment: .center)
|
||||
.padding(.trailing, 4)
|
||||
|
||||
let v = Text(address?.hostnames.first ?? srv.server).lineLimit(1)
|
||||
if srv.enabled {
|
||||
v
|
||||
} else {
|
||||
(v + Text(" (disabled)")).foregroundColor(.secondary)
|
||||
v.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func howToButton() -> some View {
|
||||
Button {
|
||||
DispatchQueue.main.async {
|
||||
UIApplication.shared.open(howToUrl)
|
||||
}
|
||||
} label: {
|
||||
HStack {
|
||||
Text("How to use your servers")
|
||||
Image(systemName: "arrow.up.right.circle")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func invalidServer() -> some View {
|
||||
Image(systemName: "exclamationmark.circle").foregroundColor(.red)
|
||||
}
|
||||
|
||||
private func uniqueAddress(_ s: ServerCfg, _ address: ServerAddress) -> Bool {
|
||||
servers.allSatisfy { srv in
|
||||
address.hostnames.allSatisfy { host in
|
||||
srv.id == s.id || !srv.server.contains(host)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func hasAllPresets() -> Bool {
|
||||
m.presetSMPServers?.allSatisfy { hasPreset($0) } ?? true
|
||||
}
|
||||
|
||||
private func addAllPresets() {
|
||||
for srv in m.presetSMPServers ?? [] {
|
||||
if !hasPreset(srv) {
|
||||
servers.append(ServerCfg(server: srv, preset: true, tested: nil, enabled: true))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func hasPreset(_ srv: String) -> Bool {
|
||||
servers.contains(where: { $0.server == srv })
|
||||
}
|
||||
|
||||
private func testServers() {
|
||||
resetTestStatus()
|
||||
testing = true
|
||||
Task {
|
||||
let fs = await runServersTest()
|
||||
await MainActor.run {
|
||||
testing = false
|
||||
if !fs.isEmpty {
|
||||
alert = .testsFailed(failures: fs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func resetTestStatus() {
|
||||
for i in 0..<servers.count {
|
||||
if servers[i].enabled {
|
||||
servers[i].tested = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func runServersTest() async -> [String: SMPTestFailure] {
|
||||
var fs: [String: SMPTestFailure] = [:]
|
||||
for i in 0..<servers.count {
|
||||
if servers[i].enabled {
|
||||
if let f = await testServerConnection(server: $servers[i]) {
|
||||
fs[serverHostname(servers[i])] = f
|
||||
}
|
||||
}
|
||||
}
|
||||
return fs
|
||||
}
|
||||
|
||||
func saveSMPServers() {
|
||||
Task {
|
||||
do {
|
||||
try await setUserSMPServers(smpServers: servers)
|
||||
await MainActor.run {
|
||||
m.userSMPServers = servers
|
||||
editMode?.wrappedValue = .inactive
|
||||
}
|
||||
} catch let error {
|
||||
let err = responseError(error)
|
||||
logger.error("saveSMPServers setUserSMPServers error: \(err)")
|
||||
await MainActor.run {
|
||||
alert = .error(
|
||||
title: "Error saving SMP servers",
|
||||
error: "Make sure SMP server addresses are in correct format, line separated and are not duplicated (\(responseError(error))."
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// ScanSMPServer.swift
|
||||
// SimpleX (iOS)
|
||||
//
|
||||
// Created by Evgeny on 19/11/2022.
|
||||
// Copyright © 2022 SimpleX Chat. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SimpleXChat
|
||||
import CodeScanner
|
||||
|
||||
struct ScanSMPServer: View {
|
||||
@Environment(\.dismiss) var dismiss: DismissAction
|
||||
@Binding var servers: [ServerCfg]
|
||||
@State private var showAddressError = false
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Text("Scan server QR code")
|
||||
.font(.largeTitle)
|
||||
.bold()
|
||||
.padding(.vertical)
|
||||
ZStack {
|
||||
CodeScannerView(codeTypes: [.qr], completion: processQRCode)
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.border(.gray)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
|
||||
.alert(isPresented: $showAddressError) {
|
||||
Alert(
|
||||
title: Text("Invalid server address!"),
|
||||
message: Text("Check server address and try again.")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func processQRCode(_ resp: Result<ScanResult, ScanError>) {
|
||||
switch resp {
|
||||
case let .success(r):
|
||||
if parseServerAddress(r.string) != nil {
|
||||
servers.append(ServerCfg(server: r.string, preset: false, tested: nil, enabled: true))
|
||||
dismiss()
|
||||
} else {
|
||||
showAddressError = true
|
||||
}
|
||||
case let .failure(e):
|
||||
logger.error("ConnectContactView.processQRCode QR code error: \(e.localizedDescription)")
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ScanSMPServer_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ScanSMPServer(servers: Binding.constant([]))
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,16 @@
|
||||
<target> (kann kopiert werden)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
||||
<source>Possibly, certificate fingerprint in server address is incorrect</source>
|
||||
<target>***Possibly, certificate fingerprint in server address is incorrect</target>
|
||||
<note>server test error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Server requires authorization to create queues, check password" xml:space="preserve">
|
||||
<source>Server requires authorization to create queues, check password</source>
|
||||
<target>***Server requires authorization to create queues, check password</target>
|
||||
<note>server test error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="!1 colored!" xml:space="preserve">
|
||||
<source>!1 colored!</source>
|
||||
<target>!1 farbig!</target>
|
||||
@@ -258,6 +268,21 @@
|
||||
<target>Anfragen annehmen</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Add preset servers" xml:space="preserve">
|
||||
<source>Add preset servers</source>
|
||||
<target>***Add preset servers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Add server…" xml:space="preserve">
|
||||
<source>Add server…</source>
|
||||
<target>***Add server…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Add to another device" xml:space="preserve">
|
||||
<source>Add to another device</source>
|
||||
<target>***Add to another device</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Advanced network settings" xml:space="preserve">
|
||||
<source>Advanced network settings</source>
|
||||
<target>Erweiterte Netzwerkeinstellungen</target>
|
||||
@@ -478,6 +503,11 @@
|
||||
<target>Chats</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Check server address and try again." xml:space="preserve">
|
||||
<source>Check server address and try again.</source>
|
||||
<target>***Check server address and try again.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Choose file" xml:space="preserve">
|
||||
<source>Choose file</source>
|
||||
<target>Datei auswählen</target>
|
||||
@@ -513,11 +543,6 @@
|
||||
<target>ICE-Server konfigurieren</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Configure SMP servers" xml:space="preserve">
|
||||
<source>Configure SMP servers</source>
|
||||
<target>SMP-Server konfigurieren</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirm" xml:space="preserve">
|
||||
<source>Confirm</source>
|
||||
<target>Bestätigen</target>
|
||||
@@ -531,7 +556,7 @@
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>Verbinden</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect via contact link?" xml:space="preserve">
|
||||
<source>Connect via contact link?</source>
|
||||
@@ -678,6 +703,11 @@
|
||||
<target>Erstellen Sie einen einmaligen Einladungslink</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Create queue" xml:space="preserve">
|
||||
<source>Create queue</source>
|
||||
<target>***Create queue</target>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Create secret group" xml:space="preserve">
|
||||
<source>Create secret group</source>
|
||||
<target>Geheime Gruppe erstellen</target>
|
||||
@@ -931,6 +961,11 @@
|
||||
<target>Die ausstehende Verbindung löschen?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Delete queue" xml:space="preserve">
|
||||
<source>Delete queue</source>
|
||||
<target>***Delete queue</target>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Develop" xml:space="preserve">
|
||||
<source>Develop</source>
|
||||
<target>Entwicklung</target>
|
||||
@@ -961,6 +996,11 @@
|
||||
<target>SimpleX Sperre deaktivieren</target>
|
||||
<note>authentication reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Disconnect" xml:space="preserve">
|
||||
<source>Disconnect</source>
|
||||
<target>***Disconnect</target>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Display name" xml:space="preserve">
|
||||
<source>Display name</source>
|
||||
<target>Angezeigter Name</target>
|
||||
@@ -1076,6 +1116,16 @@
|
||||
<target>Passwort eingeben…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Enter server manually" xml:space="preserve">
|
||||
<source>Enter server manually</source>
|
||||
<target>***Enter server manually</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error" xml:space="preserve">
|
||||
<source>Error</source>
|
||||
<target>***Error</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error accepting contact request" xml:space="preserve">
|
||||
<source>Error accepting contact request</source>
|
||||
<target>Fehler beim Annehmen der Kontaktanfrage</target>
|
||||
@@ -1356,6 +1406,11 @@
|
||||
<target>***Group preferences</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Group profile" xml:space="preserve">
|
||||
<source>Group profile</source>
|
||||
<target>***Group profile</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Group profile is stored on members' devices, not on the servers." xml:space="preserve">
|
||||
<source>Group profile is stored on members' devices, not on the servers.</source>
|
||||
<target>Das Gruppenprofil wird nur auf den Mitglieds-Systemen gespeichtert und nicht auf den Servern.</target>
|
||||
@@ -1406,6 +1461,11 @@
|
||||
<target>Markdowns verwenden</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="How to use your servers" xml:space="preserve">
|
||||
<source>How to use your servers</source>
|
||||
<target>***How to use your servers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="ICE servers (one per line)" xml:space="preserve">
|
||||
<source>ICE servers (one per line)</source>
|
||||
<target>ICE-Server (einer pro Zeile)</target>
|
||||
@@ -1518,6 +1578,11 @@
|
||||
<target>Ungültiger Verbindungslink</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid server address!" xml:space="preserve">
|
||||
<source>Invalid server address!</source>
|
||||
<target>***Invalid server address!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invitation expired!" xml:space="preserve">
|
||||
<source>Invitation expired!</source>
|
||||
<target>Einladung abgelaufen!</target>
|
||||
@@ -1628,11 +1693,6 @@ Wir werden Serverredundanzen hinzufügen, um verloren gegangene Nachrichten zu v
|
||||
<target>Stellen Sie eine private Verbindung her</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Make sure SMP server addresses are in correct format, line separated and are not duplicated." xml:space="preserve">
|
||||
<source>Make sure SMP server addresses are in correct format, line separated and are not duplicated.</source>
|
||||
<target>Stellen Sie sicher, dass die SMP-Server Adressen das richtige Format haben, zeilenweise angeordnet und nicht kopiert sind.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." xml:space="preserve">
|
||||
<source>Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated.</source>
|
||||
<target>Stellen Sie sicher, dass die WebRTC ICE-Server Adressen das richtige Format haben, zeilenweise angeordnet und nicht kopiert sind.</target>
|
||||
@@ -1968,9 +2028,14 @@ Wir werden Serverredundanzen hinzufügen, um verloren gegangene Nachrichten zu v
|
||||
<target>Bitte bewahren Sie das Passwort sicher auf, Sie können es NICHT mehr ändern, wenn Sie es vergessen haben oder verlieren.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Preferences" xml:space="preserve">
|
||||
<source>Preferences</source>
|
||||
<target>***Preferences</target>
|
||||
<trans-unit id="Preset server" xml:space="preserve">
|
||||
<source>Preset server</source>
|
||||
<target>***Preset server</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Preset server address" xml:space="preserve">
|
||||
<source>Preset server address</source>
|
||||
<target>***Preset server address</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Privacy & security" xml:space="preserve">
|
||||
@@ -2158,11 +2223,6 @@ Wir werden Serverredundanzen hinzufügen, um verloren gegangene Nachrichten zu v
|
||||
<target>SMP-Server</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SMP servers (one per line)" xml:space="preserve">
|
||||
<source>SMP servers (one per line)</source>
|
||||
<target>SMP-Server (einer pro Zeile)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Save" xml:space="preserve">
|
||||
<source>Save</source>
|
||||
<target>Speichern</target>
|
||||
@@ -2203,9 +2263,9 @@ Wir werden Serverredundanzen hinzufügen, um verloren gegangene Nachrichten zu v
|
||||
<target>Passwort im Schlüsselbund speichern</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Saved SMP servers will be removed" xml:space="preserve">
|
||||
<source>Saved SMP servers will be removed</source>
|
||||
<target>Gespeicherte SMP-Server werden entfernt</target>
|
||||
<trans-unit id="Save servers" xml:space="preserve">
|
||||
<source>Save servers</source>
|
||||
<target>***Save servers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Saved WebRTC ICE servers will be removed" xml:space="preserve">
|
||||
@@ -2218,11 +2278,21 @@ Wir werden Serverredundanzen hinzufügen, um verloren gegangene Nachrichten zu v
|
||||
<target>QR-Code scannen</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Scan server QR code" xml:space="preserve">
|
||||
<source>Scan server QR code</source>
|
||||
<target>***Scan server QR code</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Search" xml:space="preserve">
|
||||
<source>Search</source>
|
||||
<target>Suche</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Secure queue" xml:space="preserve">
|
||||
<source>Secure queue</source>
|
||||
<target>***Secure queue</target>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send direct message" xml:space="preserve">
|
||||
<source>Send direct message</source>
|
||||
<target>Direktnachricht senden</target>
|
||||
@@ -2268,6 +2338,11 @@ Wir werden Serverredundanzen hinzufügen, um verloren gegangene Nachrichten zu v
|
||||
<target>Datei-Ereignis wurde gesendet</target>
|
||||
<note>notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Server test failed!" xml:space="preserve">
|
||||
<source>Server test failed!</source>
|
||||
<target>***Server test failed!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Servers" xml:space="preserve">
|
||||
<source>Servers</source>
|
||||
<target>Server</target>
|
||||
@@ -2448,6 +2523,26 @@ Wir werden Serverredundanzen hinzufügen, um verloren gegangene Nachrichten zu v
|
||||
<target>Tippen, um einen neuen Chat zu starten</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test failed at step %@." xml:space="preserve">
|
||||
<source>Test failed at step %@.</source>
|
||||
<target>***Test failed at step %@.</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>***Test server</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test servers" xml:space="preserve">
|
||||
<source>Test servers</source>
|
||||
<target>***Test servers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Tests failed!" xml:space="preserve">
|
||||
<source>Tests failed!</source>
|
||||
<target>***Tests failed!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Thank you for installing SimpleX Chat!" xml:space="preserve">
|
||||
<source>Thank you for installing SimpleX Chat!</source>
|
||||
<target>Vielen Dank, dass Sie SimpleX Chat installiert haben!</target>
|
||||
@@ -2697,6 +2792,16 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
|
||||
<target>Verwenden Sie Chat</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use for new connections" xml:space="preserve">
|
||||
<source>Use for new connections</source>
|
||||
<target>***Use for new connections</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use server" xml:space="preserve">
|
||||
<source>Use server</source>
|
||||
<target>***Use server</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Using .onion hosts requires compatible VPN provider." xml:space="preserve">
|
||||
<source>Using .onion hosts requires compatible VPN provider.</source>
|
||||
<target>Für die Nutzung von .onion-Hosts sind kompatible VPN-Anbieter erforderlich.</target>
|
||||
@@ -3031,6 +3136,16 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
|
||||
<target>Ihr Zufallsprofil</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Your server" xml:space="preserve">
|
||||
<source>Your server</source>
|
||||
<target>***Your server</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Your server address" xml:space="preserve">
|
||||
<source>Your server address</source>
|
||||
<target>***Your server address</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Your settings" xml:space="preserve">
|
||||
<source>Your settings</source>
|
||||
<target>Meine Einstellungen</target>
|
||||
|
||||
@@ -27,6 +27,16 @@
|
||||
<target> (can be copied)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
||||
<source>Possibly, certificate fingerprint in server address is incorrect</source>
|
||||
<target>Possibly, certificate fingerprint in server address is incorrect</target>
|
||||
<note>server test error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Server requires authorization to create queues, check password" xml:space="preserve">
|
||||
<source>Server requires authorization to create queues, check password</source>
|
||||
<target>Server requires authorization to create queues, check password</target>
|
||||
<note>server test error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="!1 colored!" xml:space="preserve">
|
||||
<source>!1 colored!</source>
|
||||
<target>!1 colored!</target>
|
||||
@@ -258,6 +268,21 @@
|
||||
<target>Accept requests</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Add preset servers" xml:space="preserve">
|
||||
<source>Add preset servers</source>
|
||||
<target>Add preset servers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Add server…" xml:space="preserve">
|
||||
<source>Add server…</source>
|
||||
<target>Add server…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Add to another device" xml:space="preserve">
|
||||
<source>Add to another device</source>
|
||||
<target>Add to another device</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Advanced network settings" xml:space="preserve">
|
||||
<source>Advanced network settings</source>
|
||||
<target>Advanced network settings</target>
|
||||
@@ -478,6 +503,11 @@
|
||||
<target>Chats</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Check server address and try again." xml:space="preserve">
|
||||
<source>Check server address and try again.</source>
|
||||
<target>Check server address and try again.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Choose file" xml:space="preserve">
|
||||
<source>Choose file</source>
|
||||
<target>Choose file</target>
|
||||
@@ -513,11 +543,6 @@
|
||||
<target>Configure ICE servers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Configure SMP servers" xml:space="preserve">
|
||||
<source>Configure SMP servers</source>
|
||||
<target>Configure SMP servers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirm" xml:space="preserve">
|
||||
<source>Confirm</source>
|
||||
<target>Confirm</target>
|
||||
@@ -531,7 +556,7 @@
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>Connect</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect via contact link?" xml:space="preserve">
|
||||
<source>Connect via contact link?</source>
|
||||
@@ -678,6 +703,11 @@
|
||||
<target>Create one-time invitation link</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Create queue" xml:space="preserve">
|
||||
<source>Create queue</source>
|
||||
<target>Create queue</target>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Create secret group" xml:space="preserve">
|
||||
<source>Create secret group</source>
|
||||
<target>Create secret group</target>
|
||||
@@ -931,6 +961,11 @@
|
||||
<target>Delete pending connection?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Delete queue" xml:space="preserve">
|
||||
<source>Delete queue</source>
|
||||
<target>Delete queue</target>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Develop" xml:space="preserve">
|
||||
<source>Develop</source>
|
||||
<target>Develop</target>
|
||||
@@ -961,6 +996,11 @@
|
||||
<target>Disable SimpleX Lock</target>
|
||||
<note>authentication reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Disconnect" xml:space="preserve">
|
||||
<source>Disconnect</source>
|
||||
<target>Disconnect</target>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Display name" xml:space="preserve">
|
||||
<source>Display name</source>
|
||||
<target>Display name</target>
|
||||
@@ -1076,6 +1116,16 @@
|
||||
<target>Enter passphrase…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Enter server manually" xml:space="preserve">
|
||||
<source>Enter server manually</source>
|
||||
<target>Enter server manually</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error" xml:space="preserve">
|
||||
<source>Error</source>
|
||||
<target>Error</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error accepting contact request" xml:space="preserve">
|
||||
<source>Error accepting contact request</source>
|
||||
<target>Error accepting contact request</target>
|
||||
@@ -1356,6 +1406,11 @@
|
||||
<target>Group preferences</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Group profile" xml:space="preserve">
|
||||
<source>Group profile</source>
|
||||
<target>Group profile</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Group profile is stored on members' devices, not on the servers." xml:space="preserve">
|
||||
<source>Group profile is stored on members' devices, not on the servers.</source>
|
||||
<target>Group profile is stored on members' devices, not on the servers.</target>
|
||||
@@ -1406,6 +1461,11 @@
|
||||
<target>How to use markdown</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="How to use your servers" xml:space="preserve">
|
||||
<source>How to use your servers</source>
|
||||
<target>How to use your servers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="ICE servers (one per line)" xml:space="preserve">
|
||||
<source>ICE servers (one per line)</source>
|
||||
<target>ICE servers (one per line)</target>
|
||||
@@ -1518,6 +1578,11 @@
|
||||
<target>Invalid connection link</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid server address!" xml:space="preserve">
|
||||
<source>Invalid server address!</source>
|
||||
<target>Invalid server address!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invitation expired!" xml:space="preserve">
|
||||
<source>Invitation expired!</source>
|
||||
<target>Invitation expired!</target>
|
||||
@@ -1628,11 +1693,6 @@ We will be adding server redundancy to prevent lost messages.</target>
|
||||
<target>Make a private connection</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Make sure SMP server addresses are in correct format, line separated and are not duplicated." xml:space="preserve">
|
||||
<source>Make sure SMP server addresses are in correct format, line separated and are not duplicated.</source>
|
||||
<target>Make sure SMP server addresses are in correct format, line separated and are not duplicated.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." xml:space="preserve">
|
||||
<source>Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated.</source>
|
||||
<target>Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated.</target>
|
||||
@@ -1968,9 +2028,14 @@ We will be adding server redundancy to prevent lost messages.</target>
|
||||
<target>Please store passphrase securely, you will NOT be able to change it if you lose it.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Preferences" xml:space="preserve">
|
||||
<source>Preferences</source>
|
||||
<target>Preferences</target>
|
||||
<trans-unit id="Preset server" xml:space="preserve">
|
||||
<source>Preset server</source>
|
||||
<target>Preset server</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Preset server address" xml:space="preserve">
|
||||
<source>Preset server address</source>
|
||||
<target>Preset server address</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Privacy & security" xml:space="preserve">
|
||||
@@ -2158,11 +2223,6 @@ We will be adding server redundancy to prevent lost messages.</target>
|
||||
<target>SMP servers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SMP servers (one per line)" xml:space="preserve">
|
||||
<source>SMP servers (one per line)</source>
|
||||
<target>SMP servers (one per line)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Save" xml:space="preserve">
|
||||
<source>Save</source>
|
||||
<target>Save</target>
|
||||
@@ -2203,9 +2263,9 @@ We will be adding server redundancy to prevent lost messages.</target>
|
||||
<target>Save passphrase in Keychain</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Saved SMP servers will be removed" xml:space="preserve">
|
||||
<source>Saved SMP servers will be removed</source>
|
||||
<target>Saved SMP servers will be removed</target>
|
||||
<trans-unit id="Save servers" xml:space="preserve">
|
||||
<source>Save servers</source>
|
||||
<target>Save servers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Saved WebRTC ICE servers will be removed" xml:space="preserve">
|
||||
@@ -2218,11 +2278,21 @@ We will be adding server redundancy to prevent lost messages.</target>
|
||||
<target>Scan QR code</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Scan server QR code" xml:space="preserve">
|
||||
<source>Scan server QR code</source>
|
||||
<target>Scan server QR code</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Search" xml:space="preserve">
|
||||
<source>Search</source>
|
||||
<target>Search</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Secure queue" xml:space="preserve">
|
||||
<source>Secure queue</source>
|
||||
<target>Secure queue</target>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send direct message" xml:space="preserve">
|
||||
<source>Send direct message</source>
|
||||
<target>Send direct message</target>
|
||||
@@ -2268,6 +2338,11 @@ We will be adding server redundancy to prevent lost messages.</target>
|
||||
<target>Sent file event</target>
|
||||
<note>notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Server test failed!" xml:space="preserve">
|
||||
<source>Server test failed!</source>
|
||||
<target>Server test failed!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Servers" xml:space="preserve">
|
||||
<source>Servers</source>
|
||||
<target>Servers</target>
|
||||
@@ -2448,6 +2523,26 @@ We will be adding server redundancy to prevent lost messages.</target>
|
||||
<target>Tap to start a new chat</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test failed at step %@." xml:space="preserve">
|
||||
<source>Test failed at step %@.</source>
|
||||
<target>Test failed at step %@.</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>Test server</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test servers" xml:space="preserve">
|
||||
<source>Test servers</source>
|
||||
<target>Test servers</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Tests failed!" xml:space="preserve">
|
||||
<source>Tests failed!</source>
|
||||
<target>Tests failed!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Thank you for installing SimpleX Chat!" xml:space="preserve">
|
||||
<source>Thank you for installing SimpleX Chat!</source>
|
||||
<target>Thank you for installing SimpleX Chat!</target>
|
||||
@@ -2697,6 +2792,16 @@ To connect, please ask your contact to create another connection link and check
|
||||
<target>Use chat</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use for new connections" xml:space="preserve">
|
||||
<source>Use for new connections</source>
|
||||
<target>Use for new connections</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use server" xml:space="preserve">
|
||||
<source>Use server</source>
|
||||
<target>Use server</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Using .onion hosts requires compatible VPN provider." xml:space="preserve">
|
||||
<source>Using .onion hosts requires compatible VPN provider.</source>
|
||||
<target>Using .onion hosts requires compatible VPN provider.</target>
|
||||
@@ -3031,6 +3136,16 @@ SimpleX servers cannot see your profile.</target>
|
||||
<target>Your random profile</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Your server" xml:space="preserve">
|
||||
<source>Your server</source>
|
||||
<target>Your server</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Your server address" xml:space="preserve">
|
||||
<source>Your server address</source>
|
||||
<target>Your server address</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Your settings" xml:space="preserve">
|
||||
<source>Your settings</source>
|
||||
<target>Your settings</target>
|
||||
|
||||
@@ -27,6 +27,16 @@
|
||||
<target> (можно скопировать)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Possibly, certificate fingerprint in server address is incorrect" xml:space="preserve">
|
||||
<source>Possibly, certificate fingerprint in server address is incorrect</source>
|
||||
<target>Возможно, хэш сертификата в адресе сервера неверный</target>
|
||||
<note>server test error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Server requires authorization to create queues, check password" xml:space="preserve">
|
||||
<source>Server requires authorization to create queues, check password</source>
|
||||
<target>Сервер требует авторизации для создания очередей, проверьте пароль</target>
|
||||
<note>server test error</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="!1 colored!" xml:space="preserve">
|
||||
<source>!1 colored!</source>
|
||||
<target>!1 цвет!</target>
|
||||
@@ -258,6 +268,21 @@
|
||||
<target>Принимать запросы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Add preset servers" xml:space="preserve">
|
||||
<source>Add preset servers</source>
|
||||
<target>Добавить серверы по умолчанию</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Add server…" xml:space="preserve">
|
||||
<source>Add server…</source>
|
||||
<target>Добавить сервер…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Add to another device" xml:space="preserve">
|
||||
<source>Add to another device</source>
|
||||
<target>Добавить на другое устройство</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Advanced network settings" xml:space="preserve">
|
||||
<source>Advanced network settings</source>
|
||||
<target>Настройки сети</target>
|
||||
@@ -478,6 +503,11 @@
|
||||
<target>Чаты</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Check server address and try again." xml:space="preserve">
|
||||
<source>Check server address and try again.</source>
|
||||
<target>Проверьте адрес сервера и попробуйте снова.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Choose file" xml:space="preserve">
|
||||
<source>Choose file</source>
|
||||
<target>Выбрать файл</target>
|
||||
@@ -513,11 +543,6 @@
|
||||
<target>Настройка ICE серверов</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Configure SMP servers" xml:space="preserve">
|
||||
<source>Configure SMP servers</source>
|
||||
<target>Настройка SMP серверов</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Confirm" xml:space="preserve">
|
||||
<source>Confirm</source>
|
||||
<target>Подтвердить</target>
|
||||
@@ -531,7 +556,7 @@
|
||||
<trans-unit id="Connect" xml:space="preserve">
|
||||
<source>Connect</source>
|
||||
<target>Соединиться</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Connect via contact link?" xml:space="preserve">
|
||||
<source>Connect via contact link?</source>
|
||||
@@ -678,6 +703,11 @@
|
||||
<target>Создать ссылку-приглашение</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Create queue" xml:space="preserve">
|
||||
<source>Create queue</source>
|
||||
<target>Создание очереди</target>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Create secret group" xml:space="preserve">
|
||||
<source>Create secret group</source>
|
||||
<target>Создать скрытую группу</target>
|
||||
@@ -931,6 +961,11 @@
|
||||
<target>Удалить ожидаемое соединение?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Delete queue" xml:space="preserve">
|
||||
<source>Delete queue</source>
|
||||
<target>Удаление очереди</target>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Develop" xml:space="preserve">
|
||||
<source>Develop</source>
|
||||
<target>Для разработчиков</target>
|
||||
@@ -961,6 +996,11 @@
|
||||
<target>Отключить блокировку SimpleX</target>
|
||||
<note>authentication reason</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Disconnect" xml:space="preserve">
|
||||
<source>Disconnect</source>
|
||||
<target>Разрыв соединения</target>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Display name" xml:space="preserve">
|
||||
<source>Display name</source>
|
||||
<target>Имя профиля</target>
|
||||
@@ -1076,6 +1116,16 @@
|
||||
<target>Введите пароль…</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Enter server manually" xml:space="preserve">
|
||||
<source>Enter server manually</source>
|
||||
<target>Ввести сервер вручную</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error" xml:space="preserve">
|
||||
<source>Error</source>
|
||||
<target>Ошибка</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error accepting contact request" xml:space="preserve">
|
||||
<source>Error accepting contact request</source>
|
||||
<target>Ошибка при принятии запроса на соединение</target>
|
||||
@@ -1356,6 +1406,11 @@
|
||||
<target>Предпочтения группы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Group profile" xml:space="preserve">
|
||||
<source>Group profile</source>
|
||||
<target>Профиль группы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Group profile is stored on members' devices, not on the servers." xml:space="preserve">
|
||||
<source>Group profile is stored on members' devices, not on the servers.</source>
|
||||
<target>Профиль группы хранится на устройствах членов, а не на серверах.</target>
|
||||
@@ -1406,6 +1461,11 @@
|
||||
<target>Как форматировать</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="How to use your servers" xml:space="preserve">
|
||||
<source>How to use your servers</source>
|
||||
<target>Как использовать серверы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="ICE servers (one per line)" xml:space="preserve">
|
||||
<source>ICE servers (one per line)</source>
|
||||
<target>ICE серверы (один на строке)</target>
|
||||
@@ -1518,6 +1578,11 @@
|
||||
<target>Ошибка в ссылке контакта</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invalid server address!" xml:space="preserve">
|
||||
<source>Invalid server address!</source>
|
||||
<target>Ошибка в адресе сервера!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invitation expired!" xml:space="preserve">
|
||||
<source>Invitation expired!</source>
|
||||
<target>Приглашение истекло!</target>
|
||||
@@ -1628,11 +1693,6 @@ We will be adding server redundancy to prevent lost messages.</source>
|
||||
<target>Добавьте контакт</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Make sure SMP server addresses are in correct format, line separated and are not duplicated." xml:space="preserve">
|
||||
<source>Make sure SMP server addresses are in correct format, line separated and are not duplicated.</source>
|
||||
<target>Пожалуйста, проверьте, что адреса SMP серверов имеют правильный формат, каждый адрес на отдельной строке и не повторяется.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." xml:space="preserve">
|
||||
<source>Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated.</source>
|
||||
<target>Пожалуйста, проверьте, что адреса WebRTC ICE серверов имеют правильный формат, каждый адрес на отдельной строке и не повторяется.</target>
|
||||
@@ -1968,9 +2028,14 @@ We will be adding server redundancy to prevent lost messages.</source>
|
||||
<target>Пожалуйста, надежно сохраните пароль, вы НЕ сможете его поменять, если потеряете.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Preferences" xml:space="preserve">
|
||||
<source>Preferences</source>
|
||||
<target>Предпочтения</target>
|
||||
<trans-unit id="Preset server" xml:space="preserve">
|
||||
<source>Preset server</source>
|
||||
<target>Сервер по умолчанию</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Preset server address" xml:space="preserve">
|
||||
<source>Preset server address</source>
|
||||
<target>Адрес сервера по умолчанию</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Privacy & security" xml:space="preserve">
|
||||
@@ -2158,11 +2223,6 @@ We will be adding server redundancy to prevent lost messages.</source>
|
||||
<target>SMP серверы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SMP servers (one per line)" xml:space="preserve">
|
||||
<source>SMP servers (one per line)</source>
|
||||
<target>SMP серверы (один на строке)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Save" xml:space="preserve">
|
||||
<source>Save</source>
|
||||
<target>Сохранить</target>
|
||||
@@ -2203,9 +2263,9 @@ We will be adding server redundancy to prevent lost messages.</source>
|
||||
<target>Сохранить пароль в Keychain</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Saved SMP servers will be removed" xml:space="preserve">
|
||||
<source>Saved SMP servers will be removed</source>
|
||||
<target>Сохраненные SMP серверы будут удалены</target>
|
||||
<trans-unit id="Save servers" xml:space="preserve">
|
||||
<source>Save servers</source>
|
||||
<target>Сохранить серверы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Saved WebRTC ICE servers will be removed" xml:space="preserve">
|
||||
@@ -2218,11 +2278,21 @@ We will be adding server redundancy to prevent lost messages.</source>
|
||||
<target>Сканировать QR код</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Scan server QR code" xml:space="preserve">
|
||||
<source>Scan server QR code</source>
|
||||
<target>Сканировать QR код сервера</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Search" xml:space="preserve">
|
||||
<source>Search</source>
|
||||
<target>Поиск</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Secure queue" xml:space="preserve">
|
||||
<source>Secure queue</source>
|
||||
<target>Защита очереди</target>
|
||||
<note>server test step</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send direct message" xml:space="preserve">
|
||||
<source>Send direct message</source>
|
||||
<target>Отправить сообщение</target>
|
||||
@@ -2268,6 +2338,11 @@ We will be adding server redundancy to prevent lost messages.</source>
|
||||
<target>Отправка файла</target>
|
||||
<note>notification</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Server test failed!" xml:space="preserve">
|
||||
<source>Server test failed!</source>
|
||||
<target>Ошибка теста сервера!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Servers" xml:space="preserve">
|
||||
<source>Servers</source>
|
||||
<target>Серверы</target>
|
||||
@@ -2448,6 +2523,26 @@ We will be adding server redundancy to prevent lost messages.</source>
|
||||
<target>Нажмите, чтобы начать чат</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test failed at step %@." xml:space="preserve">
|
||||
<source>Test failed at step %@.</source>
|
||||
<target>Ошибка теста на шаге %@.</target>
|
||||
<note>server test failure</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test server" xml:space="preserve">
|
||||
<source>Test server</source>
|
||||
<target>Тестировать сервер</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Test servers" xml:space="preserve">
|
||||
<source>Test servers</source>
|
||||
<target>Тестировать серверы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Tests failed!" xml:space="preserve">
|
||||
<source>Tests failed!</source>
|
||||
<target>Ошибка тестов!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Thank you for installing SimpleX Chat!" xml:space="preserve">
|
||||
<source>Thank you for installing SimpleX Chat!</source>
|
||||
<target>Спасибо, что установили SimpleX Chat!</target>
|
||||
@@ -2697,6 +2792,16 @@ 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="Use for new connections" xml:space="preserve">
|
||||
<source>Use for new connections</source>
|
||||
<target>Использовать для новых соединений</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use server" xml:space="preserve">
|
||||
<source>Use server</source>
|
||||
<target>Использовать сервер</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Using .onion hosts requires compatible VPN provider." xml:space="preserve">
|
||||
<source>Using .onion hosts requires compatible VPN provider.</source>
|
||||
<target>Для использования .onion хостов требуется совместимый VPN провайдер.</target>
|
||||
@@ -2932,6 +3037,11 @@ To connect, please ask your contact to create another connection link and check
|
||||
<target>Ваши SMP серверы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Your SMP servers" xml:space="preserve">
|
||||
<source>Your SMP servers</source>
|
||||
<target>Ваши SMP серверы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Your SimpleX contact address" xml:space="preserve">
|
||||
<source>Your SimpleX contact address</source>
|
||||
<target>Ваш SimpleX адрес</target>
|
||||
@@ -3031,6 +3141,16 @@ SimpleX серверы не могут получить доступ к ваше
|
||||
<target>Ваш случайный профиль</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Your server" xml:space="preserve">
|
||||
<source>Your server</source>
|
||||
<target>Ваш сервер</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Your server address" xml:space="preserve">
|
||||
<source>Your server address</source>
|
||||
<target>Адрес вашего сервер</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Your settings" xml:space="preserve">
|
||||
<source>Your settings</source>
|
||||
<target>Настройки</target>
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
5C93293929241CDA0090FFF9 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C93293429241CD90090FFF9 /* libgmpxx.a */; };
|
||||
5C93293A29241CDA0090FFF9 /* libHSsimplex-chat-4.2.1-HrC8bBnv4qm8Sq6Eue57W1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C93293529241CD90090FFF9 /* libHSsimplex-chat-4.2.1-HrC8bBnv4qm8Sq6Eue57W1.a */; };
|
||||
5C93293B29241CDA0090FFF9 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C93293629241CDA0090FFF9 /* libgmp.a */; };
|
||||
5C9329412929248A0090FFF9 /* ScanSMPServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C9329402929248A0090FFF9 /* ScanSMPServer.swift */; };
|
||||
5C971E1D27AEBEF600C8A3CE /* ChatInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C971E1C27AEBEF600C8A3CE /* ChatInfoView.swift */; };
|
||||
5C971E2127AEBF8300C8A3CE /* ChatInfoImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C971E2027AEBF8300C8A3CE /* ChatInfoImage.swift */; };
|
||||
5C9A5BDB2871E05400A5B906 /* SetNotificationsMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C9A5BDA2871E05400A5B906 /* SetNotificationsMode.swift */; };
|
||||
@@ -128,7 +129,6 @@
|
||||
5CFA59D12864782E00863A68 /* ChatArchiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFA59CF286477B400863A68 /* ChatArchiveView.swift */; };
|
||||
5CFE0921282EEAF60002594B /* ZoomableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */; };
|
||||
5CFE0922282EEAF60002594B /* ZoomableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */; };
|
||||
640F50E327CF991C001E05C2 /* SMPServers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640F50E227CF991C001E05C2 /* SMPServers.swift */; };
|
||||
6432857C2925443C00FBE5C8 /* GroupPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6432857B2925443C00FBE5C8 /* GroupPreferencesView.swift */; };
|
||||
6440CA00288857A10062C672 /* CIEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6440C9FF288857A10062C672 /* CIEventView.swift */; };
|
||||
6440CA03288AECA70062C672 /* AddGroupMembersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6440CA02288AECA70062C672 /* AddGroupMembersView.swift */; };
|
||||
@@ -260,6 +260,7 @@
|
||||
5C93293429241CD90090FFF9 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
|
||||
5C93293529241CD90090FFF9 /* libHSsimplex-chat-4.2.1-HrC8bBnv4qm8Sq6Eue57W1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-4.2.1-HrC8bBnv4qm8Sq6Eue57W1.a"; sourceTree = "<group>"; };
|
||||
5C93293629241CDA0090FFF9 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
|
||||
5C9329402929248A0090FFF9 /* ScanSMPServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanSMPServer.swift; sourceTree = "<group>"; };
|
||||
5C971E1C27AEBEF600C8A3CE /* ChatInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatInfoView.swift; sourceTree = "<group>"; };
|
||||
5C971E2027AEBF8300C8A3CE /* ChatInfoImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatInfoImage.swift; sourceTree = "<group>"; };
|
||||
5C9A5BDA2871E05400A5B906 /* SetNotificationsMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetNotificationsMode.swift; sourceTree = "<group>"; };
|
||||
@@ -332,7 +333,6 @@
|
||||
5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrateToAppGroupView.swift; sourceTree = "<group>"; };
|
||||
5CFA59CF286477B400863A68 /* ChatArchiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatArchiveView.swift; sourceTree = "<group>"; };
|
||||
5CFE0920282EEAF60002594B /* ZoomableScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ZoomableScrollView.swift; path = Shared/Views/ZoomableScrollView.swift; sourceTree = SOURCE_ROOT; };
|
||||
640F50E227CF991C001E05C2 /* SMPServers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMPServers.swift; sourceTree = "<group>"; };
|
||||
6432857B2925443C00FBE5C8 /* GroupPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupPreferencesView.swift; sourceTree = "<group>"; };
|
||||
6440C9FF288857A10062C672 /* CIEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIEventView.swift; sourceTree = "<group>"; };
|
||||
6440CA02288AECA70062C672 /* AddGroupMembersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddGroupMembersView.swift; sourceTree = "<group>"; };
|
||||
@@ -590,9 +590,9 @@
|
||||
5CCA7DF22905735700C8FEBA /* AcceptRequestsView.swift */,
|
||||
5CB924E027A867BA00ACCCDD /* UserProfile.swift */,
|
||||
5C577F7C27C83AA10006112D /* MarkdownHelp.swift */,
|
||||
640F50E227CF991C001E05C2 /* SMPServers.swift */,
|
||||
5C93292E29239A170090FFF9 /* SMPServersView.swift */,
|
||||
5C93293029239BED0090FFF9 /* SMPServerView.swift */,
|
||||
5C9329402929248A0090FFF9 /* ScanSMPServer.swift */,
|
||||
5CB2084E28DA4B4800D024EC /* RTCServers.swift */,
|
||||
5C3F1D592844B4DE00EC8A82 /* ExperimentalFeaturesView.swift */,
|
||||
64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */,
|
||||
@@ -927,7 +927,6 @@
|
||||
5C00164428A26FBC0094D739 /* ContextMenu.swift in Sources */,
|
||||
5C3A88D127DF57800060F1C2 /* FramedItemView.swift in Sources */,
|
||||
5CB924E427A8683A00ACCCDD /* UserAddress.swift in Sources */,
|
||||
640F50E327CF991C001E05C2 /* SMPServers.swift in Sources */,
|
||||
64F1CC3B28B39D8600CD1FB1 /* IncognitoHelp.swift in Sources */,
|
||||
5CB0BA90282713D900B3292C /* SimpleXInfo.swift in Sources */,
|
||||
5C063D2727A4564100AEC577 /* ChatPreviewView.swift in Sources */,
|
||||
@@ -988,6 +987,7 @@
|
||||
6440CA00288857A10062C672 /* CIEventView.swift in Sources */,
|
||||
5CB0BA92282713FD00B3292C /* CreateProfile.swift in Sources */,
|
||||
5C5F2B7027EBC704006A9D5F /* ProfileImage.swift in Sources */,
|
||||
5C9329412929248A0090FFF9 /* ScanSMPServer.swift in Sources */,
|
||||
64AA1C6C27F3537400AC7277 /* DeletedItemView.swift in Sources */,
|
||||
5C029EA82837DBB3004A9677 /* CICallItemView.swift in Sources */,
|
||||
5CE4407227ADB1D0007B033A /* Emoji.swift in Sources */,
|
||||
|
||||
@@ -89,6 +89,26 @@ struct ParsedMarkdown: Decodable {
|
||||
var formattedText: [FormattedText]?
|
||||
}
|
||||
|
||||
public func parseServerAddress(_ s: String) -> ServerAddress? {
|
||||
var c = s.cString(using: .utf8)!
|
||||
if let cjson = chat_parse_server(&c) {
|
||||
if let d = fromCString(cjson).data(using: .utf8) {
|
||||
do {
|
||||
let r = try jsonDecoder.decode(ParsedServerAddress.self, from: d)
|
||||
return r.serverAddress
|
||||
} catch {
|
||||
logger.error("parseServerAddress jsonDecoder.decode error: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
struct ParsedServerAddress: Decodable {
|
||||
var serverAddress: ServerAddress?
|
||||
var parseError: String
|
||||
}
|
||||
|
||||
private func fromCString(_ c: UnsafeMutablePointer<CChar>) -> String {
|
||||
let s = String.init(cString: c)
|
||||
free(c)
|
||||
|
||||
@@ -47,7 +47,7 @@ public enum ChatCommand {
|
||||
case apiDeleteGroupLink(groupId: Int64)
|
||||
case apiGetGroupLink(groupId: Int64)
|
||||
case getUserSMPServers
|
||||
case setUserSMPServers(smpServers: [String])
|
||||
case setUserSMPServers(smpServers: [ServerCfg])
|
||||
case testSMPServer(smpServer: String)
|
||||
case apiSetChatItemTTL(seconds: Int64?)
|
||||
case apiGetChatItemTTL
|
||||
@@ -127,7 +127,7 @@ public enum ChatCommand {
|
||||
case let .apiDeleteGroupLink(groupId): return "/_delete link #\(groupId)"
|
||||
case let .apiGetGroupLink(groupId): return "/_get link #\(groupId)"
|
||||
case .getUserSMPServers: return "/smp"
|
||||
case let .setUserSMPServers(smpServers): return "/smp \(smpServersStr(smpServers: smpServers))"
|
||||
case let .setUserSMPServers(smpServers): return "/_smp \(smpServersStr(smpServers: smpServers))"
|
||||
case let .testSMPServer(smpServer): return "/smp test \(smpServer)"
|
||||
case let .apiSetChatItemTTL(seconds): return "/_ttl \(chatItemTTLStr(seconds: seconds))"
|
||||
case .apiGetChatItemTTL: return "/ttl"
|
||||
@@ -252,8 +252,8 @@ public enum ChatCommand {
|
||||
"\(type.rawValue)\(id)"
|
||||
}
|
||||
|
||||
func smpServersStr(smpServers: [String]) -> String {
|
||||
smpServers.isEmpty ? "default" : smpServers.joined(separator: ";")
|
||||
func smpServersStr(smpServers: [ServerCfg]) -> String {
|
||||
smpServers.isEmpty ? "default" : encodeJSON(SMPServersConfig(smpServers: smpServers))
|
||||
}
|
||||
|
||||
func chatItemTTLStr(seconds: Int64?) -> String {
|
||||
@@ -295,7 +295,7 @@ public enum ChatResponse: Decodable, Error {
|
||||
case apiChats(chats: [ChatData])
|
||||
case apiChat(chat: ChatData)
|
||||
case userSMPServers(smpServers: [ServerCfg], presetSMPServers: [String])
|
||||
case sMPTestResult(smpTestFailure: SMPTestFailure?)
|
||||
case smpTestResult(smpTestFailure: SMPTestFailure?)
|
||||
case chatItemTTL(chatItemTTL: Int64?)
|
||||
case networkConfig(networkConfig: NetCfg)
|
||||
case contactInfo(contact: Contact, connectionStats: ConnectionStats, customUserProfile: Profile?)
|
||||
@@ -398,7 +398,7 @@ public enum ChatResponse: Decodable, Error {
|
||||
case .apiChats: return "apiChats"
|
||||
case .apiChat: return "apiChat"
|
||||
case .userSMPServers: return "userSMPServers"
|
||||
case .sMPTestResult: return "smpTestResult"
|
||||
case .smpTestResult: return "smpTestResult"
|
||||
case .chatItemTTL: return "chatItemTTL"
|
||||
case .networkConfig: return "networkConfig"
|
||||
case .contactInfo: return "contactInfo"
|
||||
@@ -500,8 +500,8 @@ public enum ChatResponse: Decodable, Error {
|
||||
case .chatSuspended: return noDetails
|
||||
case let .apiChats(chats): return String(describing: chats)
|
||||
case let .apiChat(chat): return String(describing: chat)
|
||||
case let .userSMPServers(smpServers, _): return String(describing: smpServers)
|
||||
case let .sMPTestResult(smpTestFailure): return String(describing: smpTestFailure)
|
||||
case let .userSMPServers(smpServers, presetServers): return "smpServers: \(String(describing: smpServers))\npresetServers: \(String(describing: presetServers))"
|
||||
case let .smpTestResult(smpTestFailure): return String(describing: smpTestFailure)
|
||||
case let .chatItemTTL(chatItemTTL): return String(describing: chatItemTTL)
|
||||
case let .networkConfig(networkConfig): return String(describing: networkConfig)
|
||||
case let .contactInfo(contact, connectionStats, customUserProfile): return "contact: \(String(describing: contact))\nconnectionStats: \(String(describing: connectionStats))\ncustomUserProfile: \(String(describing: customUserProfile))"
|
||||
@@ -635,11 +635,16 @@ public struct DBEncryptionConfig: Codable {
|
||||
public var newKey: String
|
||||
}
|
||||
|
||||
public struct ServerCfg: Identifiable, Decodable {
|
||||
struct SMPServersConfig: Encodable {
|
||||
var smpServers: [ServerCfg]
|
||||
}
|
||||
|
||||
public struct ServerCfg: Identifiable, Equatable, Codable {
|
||||
public var server: String
|
||||
public var preset: Bool
|
||||
public var tested: Bool?
|
||||
public var enabled: Bool
|
||||
var createdAt = Date()
|
||||
// public var sendEnabled: Bool // can we potentially want to prevent sending on the servers we use to receive?
|
||||
// Even if we don't see the use case, it's probably better to allow it in the model
|
||||
// In any case, "trusted/known" servers are out of scope of this change
|
||||
@@ -651,9 +656,17 @@ public struct ServerCfg: Identifiable, Decodable {
|
||||
self.enabled = enabled
|
||||
}
|
||||
|
||||
public var id: String { server }
|
||||
public static func == (l: ServerCfg, r: ServerCfg) -> Bool {
|
||||
l.server == r.server && l.preset == r.preset && l.tested == r.tested && l.enabled == r.enabled
|
||||
}
|
||||
|
||||
public static var empty = ServerCfg(server: "", preset: false, tested: false, enabled: true)
|
||||
public var id: String { "\(server) \(createdAt)" }
|
||||
|
||||
public static var empty = ServerCfg(server: "", preset: false, tested: nil, enabled: true)
|
||||
|
||||
public var isEmpty: Bool {
|
||||
server.trimmingCharacters(in: .whitespaces) == ""
|
||||
}
|
||||
|
||||
public struct SampleData {
|
||||
public var preset: ServerCfg
|
||||
@@ -663,27 +676,34 @@ public struct ServerCfg: Identifiable, Decodable {
|
||||
|
||||
public static var sampleData = SampleData(
|
||||
preset: ServerCfg(
|
||||
server: "smp://0YuTwO05YJWS8rkjn9eLJDjQhFKvIYd8d4xG8X1blIU=@smp8.simplex.im,beccx4yfxxbvyhqypaavemqurytl6hozr47wfc7uuecacjqdvwpw2xid.onion",
|
||||
server: "smp://abcd@smp8.simplex.im",
|
||||
preset: true,
|
||||
tested: true,
|
||||
enabled: true
|
||||
),
|
||||
custom: ServerCfg(
|
||||
server: "smp://SkIkI6EPd2D63F4xFKfHk7I1UGZVNn6k1QWZ5rcyr6w=@smp9.simplex.im,jssqzccmrcws6bhmn77vgmhfjmhwlyr3u7puw4erkyoosywgl67slqqd.onion",
|
||||
server: "smp://abcd@smp9.simplex.im",
|
||||
preset: false,
|
||||
tested: false,
|
||||
enabled: false
|
||||
),
|
||||
untested: ServerCfg(
|
||||
server: "smp://6iIcWT_dF2zN_w5xzZEY7HI2Prbh3ldP07YTyDexPjE=@smp10.simplex.im,rb2pbttocvnbrngnwziclp2f4ckjq65kebafws6g4hy22cdaiv5dwjqd.onion",
|
||||
server: "smp://abcd@smp10.simplex.im",
|
||||
preset: false,
|
||||
tested: nil,
|
||||
enabled: true
|
||||
)
|
||||
)
|
||||
|
||||
enum CodingKeys: CodingKey {
|
||||
case server
|
||||
case preset
|
||||
case tested
|
||||
case enabled
|
||||
}
|
||||
}
|
||||
|
||||
public enum SMPTestStep: String, Decodable {
|
||||
public enum SMPTestStep: String, Decodable, Equatable {
|
||||
case connect
|
||||
case createQueue
|
||||
case secureQueue
|
||||
@@ -701,24 +721,28 @@ public enum SMPTestStep: String, Decodable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct SMPTestFailure: Decodable, Error {
|
||||
public struct SMPTestFailure: Decodable, Error, Equatable {
|
||||
var testStep: SMPTestStep
|
||||
var testError: AgentErrorType
|
||||
|
||||
var localizedDescription: String {
|
||||
let err = String.localizedStringWithFormat(NSLocalizedString("Test failed at step %@", comment: "server test failure"), testStep.text)
|
||||
public static func == (l: SMPTestFailure, r: SMPTestFailure) -> Bool {
|
||||
l.testStep == r.testStep
|
||||
}
|
||||
|
||||
public var localizedDescription: String {
|
||||
let err = String.localizedStringWithFormat(NSLocalizedString("Test failed at step %@.", comment: "server test failure"), testStep.text)
|
||||
switch testError {
|
||||
case .SMP(.AUTH):
|
||||
return err + "," + NSLocalizedString("Server requires authentication to create queues, check password", comment: "server test error")
|
||||
return err + " " + NSLocalizedString("Server requires authorization to create queues, check password", comment: "server test error")
|
||||
case .BROKER(.NETWORK):
|
||||
return err + "," + NSLocalizedString("Possibly, certificate fingerprint in server address is incorrect", comment: "server test error")
|
||||
return err + " " + NSLocalizedString("Possibly, certificate fingerprint in server address is incorrect", comment: "server test error")
|
||||
default:
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct ServerAddress {
|
||||
public struct ServerAddress: Decodable {
|
||||
public var hostnames: [String]
|
||||
public var port: String
|
||||
public var keyHash: String
|
||||
@@ -735,6 +759,10 @@ public struct ServerAddress {
|
||||
"smp://\(keyHash)\(basicAuth == "" ? "" : ":" + basicAuth)@\(hostnames.joined(separator: ","))"
|
||||
}
|
||||
|
||||
public var valid: Bool {
|
||||
hostnames.count > 0 && Set(hostnames).count == hostnames.count
|
||||
}
|
||||
|
||||
static public var empty = ServerAddress(
|
||||
hostnames: [],
|
||||
port: "",
|
||||
|
||||
@@ -21,3 +21,4 @@ extern char *chat_send_cmd(chat_ctrl ctl, char *cmd);
|
||||
extern char *chat_recv_msg(chat_ctrl ctl);
|
||||
extern char *chat_recv_msg_wait(chat_ctrl ctl, int wait);
|
||||
extern char *chat_parse_markdown(char *str);
|
||||
extern char *chat_parse_server(char *str);
|
||||
|
||||
@@ -173,6 +173,15 @@
|
||||
/* call status */
|
||||
"accepted call" = "Anruf angenommen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add preset servers" = "***Add preset servers";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add server…" = "***Add server…";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add to another device" = "***Add to another device";
|
||||
|
||||
/* member role */
|
||||
"admin" = "Admin";
|
||||
|
||||
@@ -347,6 +356,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Chats" = "Chats";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Check server address and try again." = "***Check server address and try again.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Choose file" = "Datei auswählen";
|
||||
|
||||
@@ -374,16 +386,13 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Configure ICE servers" = "ICE-Server konfigurieren";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Configure SMP servers" = "SMP-Server konfigurieren";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Confirm" = "Bestätigen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Confirm new passphrase…" = "Neues Passwort bestätigen…";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
/* server test step */
|
||||
"Connect" = "Verbinden";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
@@ -512,6 +521,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Create one-time invitation link" = "Erstellen Sie einen einmaligen Einladungslink";
|
||||
|
||||
/* server test step */
|
||||
"Create queue" = "***Create queue";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Create secret group" = "Geheime Gruppe erstellen";
|
||||
|
||||
@@ -665,6 +677,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Delete pending connection?" = "Die ausstehende Verbindung löschen?";
|
||||
|
||||
/* server test step */
|
||||
"Delete queue" = "***Delete queue";
|
||||
|
||||
/* deleted chat item */
|
||||
"deleted" = "Gelöscht";
|
||||
|
||||
@@ -692,6 +707,9 @@
|
||||
/* authentication reason */
|
||||
"Disable SimpleX Lock" = "SimpleX Sperre deaktivieren";
|
||||
|
||||
/* server test step */
|
||||
"Disconnect" = "***Disconnect";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Display name" = "Angezeigter Name";
|
||||
|
||||
@@ -773,9 +791,15 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Enter passphrase…" = "Passwort eingeben…";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Enter server manually" = "***Enter server manually";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"error" = "Fehler";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error" = "***Error";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error accepting contact request" = "Fehler beim Annehmen der Kontaktanfrage";
|
||||
|
||||
@@ -947,6 +971,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Group preferences" = "***Group preferences";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Group profile" = "***Group profile";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Group profile is stored on members' devices, not on the servers." = "Das Gruppenprofil wird nur auf den Mitglieds-Systemen gespeichtert und nicht auf den Servern.";
|
||||
|
||||
@@ -980,6 +1007,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"How to use markdown" = "Markdowns verwenden";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"How to use your servers" = "***How to use your servers";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"ICE servers (one per line)" = "ICE-Server (einer pro Zeile)";
|
||||
|
||||
@@ -1058,6 +1088,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Invalid connection link" = "Ungültiger Verbindungslink";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Invalid server address!" = "***Invalid server address!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Invitation expired!" = "Einladung abgelaufen!";
|
||||
|
||||
@@ -1148,9 +1181,6 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Make a private connection" = "Stellen Sie eine private Verbindung her";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Make sure SMP server addresses are in correct format, line separated and are not duplicated." = "Stellen Sie sicher, dass die SMP-Server Adressen das richtige Format haben, zeilenweise angeordnet und nicht kopiert sind.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." = "Stellen Sie sicher, dass die WebRTC ICE-Server Adressen das richtige Format haben, zeilenweise angeordnet und nicht kopiert sind.";
|
||||
|
||||
@@ -1391,8 +1421,14 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Please store passphrase securely, you will NOT be able to change it if you lose it." = "Bitte bewahren Sie das Passwort sicher auf, Sie können es NICHT mehr ändern, wenn Sie es vergessen haben oder verlieren.";
|
||||
|
||||
/* server test error */
|
||||
"Possibly, certificate fingerprint in server address is incorrect" = "***Possibly, certificate fingerprint in server address is incorrect";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Preferences" = "***Preferences";
|
||||
"Preset server" = "***Preset server";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Preset server address" = "***Preset server address";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Privacy & security" = "Datenschutz & Sicherheit";
|
||||
@@ -1545,7 +1581,7 @@
|
||||
"Save passphrase in Keychain" = "Passwort im Schlüsselbund speichern";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Saved SMP servers will be removed" = "Gespeicherte SMP-Server werden entfernt";
|
||||
"Save servers" = "***Save servers";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Saved WebRTC ICE servers will be removed" = "Gespeicherte WebRTC ICE-Server werden entfernt";
|
||||
@@ -1553,6 +1589,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Scan QR code" = "QR-Code scannen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Scan server QR code" = "***Scan server QR code";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Search" = "Suche";
|
||||
|
||||
@@ -1562,6 +1601,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"secret" = "geheim";
|
||||
|
||||
/* server test step */
|
||||
"Secure queue" = "***Secure queue";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Send direct message" = "Direktnachricht senden";
|
||||
|
||||
@@ -1589,6 +1631,12 @@
|
||||
/* notification */
|
||||
"Sent file event" = "Datei-Ereignis wurde gesendet";
|
||||
|
||||
/* server test error */
|
||||
"Server requires authorization to create queues, check password" = "***Server requires authorization to create queues, check password";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Server test failed!" = "***Server test failed!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Servers" = "Server";
|
||||
|
||||
@@ -1640,9 +1688,6 @@
|
||||
/* No comment provided by engineer. */
|
||||
"SMP servers" = "SMP-Server";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"SMP servers (one per line)" = "SMP-Server (einer pro Zeile)";
|
||||
|
||||
/* notification title */
|
||||
"Somebody" = "Jemand";
|
||||
|
||||
@@ -1709,6 +1754,18 @@
|
||||
/* No comment provided by engineer. */
|
||||
"TCP_KEEPINTVL" = "TCP_KEEPINTVL";
|
||||
|
||||
/* server test failure */
|
||||
"Test failed at step %@." = "***Test failed at step %@.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Test server" = "***Test server";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Test servers" = "***Test servers";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Tests failed!" = "***Tests failed!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Thank you for installing SimpleX Chat!" = "Vielen Dank, dass Sie SimpleX Chat installiert haben!";
|
||||
|
||||
@@ -1862,6 +1919,12 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Use chat" = "Verwenden Sie Chat";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use for new connections" = "***Use for new connections";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use server" = "***Use server";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use SimpleX Chat servers?" = "Verwenden Sie SimpleX Chat Server?";
|
||||
|
||||
@@ -2117,6 +2180,12 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Your random profile" = "Ihr Zufallsprofil";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Your server" = "***Your server";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Your server address" = "***Your server address";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Your settings" = "Meine Einstellungen";
|
||||
|
||||
|
||||
@@ -173,6 +173,15 @@
|
||||
/* call status */
|
||||
"accepted call" = " принятый звонок";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add preset servers" = "Добавить серверы по умолчанию";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add server…" = "Добавить сервер…";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Add to another device" = "Добавить на другое устройство";
|
||||
|
||||
/* member role */
|
||||
"admin" = "админ";
|
||||
|
||||
@@ -347,6 +356,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Chats" = "Чаты";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Check server address and try again." = "Проверьте адрес сервера и попробуйте снова.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Choose file" = "Выбрать файл";
|
||||
|
||||
@@ -374,16 +386,13 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Configure ICE servers" = "Настройка ICE серверов";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Configure SMP servers" = "Настройка SMP серверов";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Confirm" = "Подтвердить";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Confirm new passphrase…" = "Подтвердите новый пароль…";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
/* server test step */
|
||||
"Connect" = "Соединиться";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
@@ -512,6 +521,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Create one-time invitation link" = "Создать ссылку-приглашение";
|
||||
|
||||
/* server test step */
|
||||
"Create queue" = "Создание очереди";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Create secret group" = "Создать скрытую группу";
|
||||
|
||||
@@ -665,6 +677,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Delete pending connection?" = "Удалить ожидаемое соединение?";
|
||||
|
||||
/* server test step */
|
||||
"Delete queue" = "Удаление очереди";
|
||||
|
||||
/* deleted chat item */
|
||||
"deleted" = "удалено";
|
||||
|
||||
@@ -692,6 +707,9 @@
|
||||
/* authentication reason */
|
||||
"Disable SimpleX Lock" = "Отключить блокировку SimpleX";
|
||||
|
||||
/* server test step */
|
||||
"Disconnect" = "Разрыв соединения";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Display name" = "Имя профиля";
|
||||
|
||||
@@ -773,9 +791,15 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Enter passphrase…" = "Введите пароль…";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Enter server manually" = "Ввести сервер вручную";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"error" = "ошибка";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error" = "Ошибка";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error accepting contact request" = "Ошибка при принятии запроса на соединение";
|
||||
|
||||
@@ -947,6 +971,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Group preferences" = "Предпочтения группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Group profile" = "Профиль группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Group profile is stored on members' devices, not on the servers." = "Профиль группы хранится на устройствах членов, а не на серверах.";
|
||||
|
||||
@@ -980,6 +1007,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"How to use markdown" = "Как форматировать";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"How to use your servers" = "Как использовать серверы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"ICE servers (one per line)" = "ICE серверы (один на строке)";
|
||||
|
||||
@@ -1058,6 +1088,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Invalid connection link" = "Ошибка в ссылке контакта";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Invalid server address!" = "Ошибка в адресе сервера!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Invitation expired!" = "Приглашение истекло!";
|
||||
|
||||
@@ -1148,9 +1181,6 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Make a private connection" = "Добавьте контакт";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Make sure SMP server addresses are in correct format, line separated and are not duplicated." = "Пожалуйста, проверьте, что адреса SMP серверов имеют правильный формат, каждый адрес на отдельной строке и не повторяется.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." = "Пожалуйста, проверьте, что адреса WebRTC ICE серверов имеют правильный формат, каждый адрес на отдельной строке и не повторяется.";
|
||||
|
||||
@@ -1391,8 +1421,14 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Please store passphrase securely, you will NOT be able to change it if you lose it." = "Пожалуйста, надежно сохраните пароль, вы НЕ сможете его поменять, если потеряете.";
|
||||
|
||||
/* server test error */
|
||||
"Possibly, certificate fingerprint in server address is incorrect" = "Возможно, хэш сертификата в адресе сервера неверный";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Preferences" = "Предпочтения";
|
||||
"Preset server" = "Сервер по умолчанию";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Preset server address" = "Адрес сервера по умолчанию";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Privacy & security" = "Конфиденциальность";
|
||||
@@ -1545,7 +1581,7 @@
|
||||
"Save passphrase in Keychain" = "Сохранить пароль в Keychain";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Saved SMP servers will be removed" = "Сохраненные SMP серверы будут удалены";
|
||||
"Save servers" = "Сохранить серверы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Saved WebRTC ICE servers will be removed" = "Сохраненные WebRTC ICE серверы будут удалены";
|
||||
@@ -1553,6 +1589,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Scan QR code" = "Сканировать QR код";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Scan server QR code" = "Сканировать QR код сервера";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Search" = "Поиск";
|
||||
|
||||
@@ -1562,6 +1601,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"secret" = "секрет";
|
||||
|
||||
/* server test step */
|
||||
"Secure queue" = "Защита очереди";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Send direct message" = "Отправить сообщение";
|
||||
|
||||
@@ -1589,6 +1631,12 @@
|
||||
/* notification */
|
||||
"Sent file event" = "Отправка файла";
|
||||
|
||||
/* server test error */
|
||||
"Server requires authorization to create queues, check password" = "Сервер требует авторизации для создания очередей, проверьте пароль";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Server test failed!" = "Ошибка теста сервера!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Servers" = "Серверы";
|
||||
|
||||
@@ -1640,9 +1688,6 @@
|
||||
/* No comment provided by engineer. */
|
||||
"SMP servers" = "SMP серверы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"SMP servers (one per line)" = "SMP серверы (один на строке)";
|
||||
|
||||
/* notification title */
|
||||
"Somebody" = "Контакт";
|
||||
|
||||
@@ -1709,6 +1754,18 @@
|
||||
/* No comment provided by engineer. */
|
||||
"TCP_KEEPINTVL" = "TCP_KEEPINTVL";
|
||||
|
||||
/* server test failure */
|
||||
"Test failed at step %@." = "Ошибка теста на шаге %@.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Test server" = "Тестировать сервер";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Test servers" = "Тестировать серверы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Tests failed!" = "Ошибка тестов!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Thank you for installing SimpleX Chat!" = "Спасибо, что установили SimpleX Chat!";
|
||||
|
||||
@@ -1862,6 +1919,12 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Use chat" = "Использовать чат";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use for new connections" = "Использовать для новых соединений";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use server" = "Использовать сервер";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use SimpleX Chat servers?" = "Использовать серверы предосталенные SimpleX Chat?";
|
||||
|
||||
@@ -2117,6 +2180,12 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Your random profile" = "Ваш случайный профиль";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Your server" = "Ваш сервер";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Your server address" = "Адрес вашего сервер";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Your settings" = "Настройки";
|
||||
|
||||
|
||||
@@ -645,7 +645,7 @@ viewSMPTestResult :: Maybe SMPTestFailure -> [StyledString]
|
||||
viewSMPTestResult = \case
|
||||
Just SMPTestFailure {testStep, testError} ->
|
||||
result
|
||||
<> ["Server requires authentication to create queues, check password" | testStep == TSCreateQueue && testError == SMP SMP.AUTH]
|
||||
<> ["Server requires authorization to create queues, check password" | testStep == TSCreateQueue && testError == SMP SMP.AUTH]
|
||||
<> ["Possibly, certificate fingerprint in server address is incorrect" | testStep == TSConnect && testError == BROKER NETWORK]
|
||||
where
|
||||
result = ["SMP server test failed at " <> plain (drop 2 $ show testStep) <> ", error: " <> plain (strEncode testError)]
|
||||
|
||||
Reference in New Issue
Block a user