mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-24 17:25:42 +00:00
Merge branch 'master' into master-android
This commit is contained in:
@@ -80,6 +80,7 @@ enum ChatCommand: ChatCmdProtocol {
|
||||
case apiGroupLinkMemberRole(groupId: Int64, memberRole: GroupMemberRole)
|
||||
case apiDeleteGroupLink(groupId: Int64)
|
||||
case apiGetGroupLink(groupId: Int64)
|
||||
case apiAddGroupShortLink(groupId: Int64)
|
||||
case apiCreateMemberContact(groupId: Int64, groupMemberId: Int64)
|
||||
case apiSendMemberContactInvitation(contactId: Int64, msg: MsgContent)
|
||||
case apiTestProtoServer(userId: Int64, server: String)
|
||||
@@ -134,6 +135,7 @@ enum ChatCommand: ChatCmdProtocol {
|
||||
case apiCreateMyAddress(userId: Int64, short: Bool)
|
||||
case apiDeleteMyAddress(userId: Int64)
|
||||
case apiShowMyAddress(userId: Int64)
|
||||
case apiAddMyAddressShortLink(userId: Int64)
|
||||
case apiSetProfileAddress(userId: Int64, on: Bool)
|
||||
case apiAddressAutoAccept(userId: Int64, autoAccept: AutoAccept?)
|
||||
case apiAcceptContact(incognito: Bool, contactReqId: Int64)
|
||||
@@ -262,6 +264,7 @@ enum ChatCommand: ChatCmdProtocol {
|
||||
case let .apiGroupLinkMemberRole(groupId, memberRole): return "/_set link role #\(groupId) \(memberRole)"
|
||||
case let .apiDeleteGroupLink(groupId): return "/_delete link #\(groupId)"
|
||||
case let .apiGetGroupLink(groupId): return "/_get link #\(groupId)"
|
||||
case let .apiAddGroupShortLink(groupId): return "/_short link #\(groupId)"
|
||||
case let .apiCreateMemberContact(groupId, groupMemberId): return "/_create member contact #\(groupId) \(groupMemberId)"
|
||||
case let .apiSendMemberContactInvitation(contactId, mc): return "/_invite member contact @\(contactId) \(mc.cmdString)"
|
||||
case let .apiTestProtoServer(userId, server): return "/_server test \(userId) \(server)"
|
||||
@@ -326,6 +329,7 @@ enum ChatCommand: ChatCmdProtocol {
|
||||
case let .apiCreateMyAddress(userId, short): return "/_address \(userId) short=\(onOff(short))"
|
||||
case let .apiDeleteMyAddress(userId): return "/_delete_address \(userId)"
|
||||
case let .apiShowMyAddress(userId): return "/_show_address \(userId)"
|
||||
case let .apiAddMyAddressShortLink(userId): return "/_short_link_address \(userId)"
|
||||
case let .apiSetProfileAddress(userId, on): return "/_profile_address \(userId) \(onOff(on))"
|
||||
case let .apiAddressAutoAccept(userId, autoAccept): return "/_auto_accept \(userId) \(AutoAccept.cmdString(autoAccept))"
|
||||
case let .apiAcceptContact(incognito, contactReqId): return "/_accept incognito=\(onOff(incognito)) \(contactReqId)"
|
||||
@@ -438,6 +442,7 @@ enum ChatCommand: ChatCmdProtocol {
|
||||
case .apiGroupLinkMemberRole: return "apiGroupLinkMemberRole"
|
||||
case .apiDeleteGroupLink: return "apiDeleteGroupLink"
|
||||
case .apiGetGroupLink: return "apiGetGroupLink"
|
||||
case .apiAddGroupShortLink: return "apiAddGroupShortLink"
|
||||
case .apiCreateMemberContact: return "apiCreateMemberContact"
|
||||
case .apiSendMemberContactInvitation: return "apiSendMemberContactInvitation"
|
||||
case .apiTestProtoServer: return "apiTestProtoServer"
|
||||
@@ -491,6 +496,7 @@ enum ChatCommand: ChatCmdProtocol {
|
||||
case .apiCreateMyAddress: return "apiCreateMyAddress"
|
||||
case .apiDeleteMyAddress: return "apiDeleteMyAddress"
|
||||
case .apiShowMyAddress: return "apiShowMyAddress"
|
||||
case .apiAddMyAddressShortLink: return "apiAddMyAddressShortLink"
|
||||
case .apiSetProfileAddress: return "apiSetProfileAddress"
|
||||
case .apiAddressAutoAccept: return "apiAddressAutoAccept"
|
||||
case .apiAcceptContact: return "apiAcceptContact"
|
||||
|
||||
@@ -1210,6 +1210,13 @@ private func userAddressResponse(_ r: APIResult<ChatResponse1>) throws -> UserCo
|
||||
}
|
||||
}
|
||||
|
||||
func apiAddMyAddressShortLink() async throws -> UserContactLink {
|
||||
let userId = try currentUserId("apiAddMyAddressShortLink")
|
||||
let r: ChatResponse1 = try await chatSendCmd(.apiAddMyAddressShortLink(userId: userId))
|
||||
if case let .userContactLink(_, contactLink) = r { return contactLink }
|
||||
throw r.unexpected
|
||||
}
|
||||
|
||||
func userAddressAutoAccept(_ autoAccept: AutoAccept?) async throws -> UserContactLink? {
|
||||
let userId = try currentUserId("userAddressAutoAccept")
|
||||
let r: APIResult<ChatResponse1> = await chatApiSendCmd(.apiAddressAutoAccept(userId: userId, autoAccept: autoAccept))
|
||||
@@ -1736,6 +1743,12 @@ func apiGetGroupLink(_ groupId: Int64) throws -> (CreatedConnLink, GroupMemberRo
|
||||
}
|
||||
}
|
||||
|
||||
func apiAddGroupShortLink(_ groupId: Int64) async throws -> (CreatedConnLink, GroupMemberRole) {
|
||||
let r: ChatResponse2 = try await chatSendCmd(.apiAddGroupShortLink(groupId: groupId))
|
||||
if case let .groupLink(_, _, connLink, memberRole) = r { return (connLink, memberRole) }
|
||||
throw r.unexpected
|
||||
}
|
||||
|
||||
func apiCreateMemberContact(_ groupId: Int64, _ groupMemberId: Int64) async throws -> Contact {
|
||||
let r: ChatResponse2 = try await chatSendCmd(.apiCreateMemberContact(groupId: groupId, groupMemberId: groupMemberId))
|
||||
if case let .newMemberContact(_, contact, _, _) = r { return contact }
|
||||
|
||||
@@ -633,9 +633,6 @@ struct GroupChatInfoView: View {
|
||||
groupInfo: $groupInfo,
|
||||
groupProfile: groupInfo.groupProfile
|
||||
)
|
||||
.navigationBarTitle("Group profile")
|
||||
.modifier(ThemedBackground())
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
} label: {
|
||||
Label("Edit group profile", systemImage: "pencil")
|
||||
}
|
||||
|
||||
@@ -35,16 +35,23 @@ struct GroupLinkView: View {
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if creatingGroup {
|
||||
groupLinkView()
|
||||
.navigationBarBackButtonHidden()
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Button ("Continue") { linkCreatedCb?() }
|
||||
ZStack {
|
||||
if creatingGroup {
|
||||
groupLinkView()
|
||||
.navigationBarBackButtonHidden()
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Button ("Continue") { linkCreatedCb?() }
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
groupLinkView()
|
||||
} else {
|
||||
groupLinkView()
|
||||
}
|
||||
if creatingLink {
|
||||
ProgressView()
|
||||
.scaleEffect(2)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +86,14 @@ struct GroupLinkView: View {
|
||||
Label("Share link", systemImage: "square.and.arrow.up")
|
||||
}
|
||||
|
||||
if (groupLink.connShortLink == nil && UserDefaults.standard.bool(forKey: DEFAULT_PRIVACY_SHORT_LINKS)) {
|
||||
Button {
|
||||
addShortLink()
|
||||
} label: {
|
||||
Label("Add short link", systemImage: "plus")
|
||||
}
|
||||
}
|
||||
|
||||
if !creatingGroup {
|
||||
Button(role: .destructive) { alert = .deleteLink } label: {
|
||||
Label("Delete link", systemImage: "trash")
|
||||
@@ -89,11 +104,6 @@ struct GroupLinkView: View {
|
||||
Label("Create link", systemImage: "link.badge.plus")
|
||||
}
|
||||
.disabled(creatingLink)
|
||||
if creatingLink {
|
||||
ProgressView()
|
||||
.scaleEffect(2)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
||||
} header: {
|
||||
if let groupLink, groupLink.connShortLink != nil {
|
||||
@@ -160,6 +170,26 @@ struct GroupLinkView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func addShortLink() {
|
||||
Task {
|
||||
do {
|
||||
creatingLink = true
|
||||
let link = try await apiAddGroupShortLink(groupId)
|
||||
await MainActor.run {
|
||||
creatingLink = false
|
||||
(groupLink, groupLinkMemberRole) = link
|
||||
}
|
||||
} catch let error {
|
||||
logger.error("apiAddGroupShortLink: \(responseError(error))")
|
||||
await MainActor.run {
|
||||
creatingLink = false
|
||||
let a = getErrorAlert(error, "Error adding short link")
|
||||
alert = .error(title: a.title, error: a.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct GroupLinkView_Previews: PreviewProvider {
|
||||
|
||||
@@ -26,6 +26,7 @@ struct GroupProfileView: View {
|
||||
@Environment(\.dismiss) var dismiss: DismissAction
|
||||
@Binding var groupInfo: GroupInfo
|
||||
@State var groupProfile: GroupProfile
|
||||
@State private var currentProfileHash: Int?
|
||||
@State private var showChooseSource = false
|
||||
@State private var showImagePicker = false
|
||||
@State private var showTakePhoto = false
|
||||
@@ -34,60 +35,40 @@ struct GroupProfileView: View {
|
||||
@FocusState private var focusDisplayName
|
||||
|
||||
var body: some View {
|
||||
return VStack(alignment: .leading) {
|
||||
Text("Group profile is stored on members' devices, not on the servers.")
|
||||
.padding(.vertical)
|
||||
List {
|
||||
EditProfileImage(profileImage: $groupProfile.image, showChooseSource: $showChooseSource)
|
||||
.if(!focusDisplayName) { $0.padding(.top) }
|
||||
|
||||
ZStack(alignment: .center) {
|
||||
ZStack(alignment: .topTrailing) {
|
||||
profileImageView(groupProfile.image)
|
||||
if groupProfile.image != nil {
|
||||
Button {
|
||||
groupProfile.image = nil
|
||||
} label: {
|
||||
Image(systemName: "multiply")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 12)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
editImageButton { showChooseSource = true }
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
ZStack(alignment: .topLeading) {
|
||||
if !validNewProfileName() {
|
||||
Section {
|
||||
HStack {
|
||||
TextField("Group display name", text: $groupProfile.displayName)
|
||||
.focused($focusDisplayName)
|
||||
if !validNewProfileName {
|
||||
Button {
|
||||
alert = .invalidName(validName: mkValidName(groupProfile.displayName))
|
||||
} label: {
|
||||
Image(systemName: "exclamationmark.circle").foregroundColor(.red)
|
||||
}
|
||||
} else {
|
||||
Image(systemName: "exclamationmark.circle").foregroundColor(.clear)
|
||||
}
|
||||
profileNameTextEdit("Group display name", $groupProfile.displayName)
|
||||
.focused($focusDisplayName)
|
||||
}
|
||||
.padding(.bottom)
|
||||
let fullName = groupInfo.groupProfile.fullName
|
||||
if fullName != "" && fullName != groupProfile.displayName {
|
||||
profileNameTextEdit("Group full name (optional)", $groupProfile.fullName)
|
||||
.padding(.bottom)
|
||||
}
|
||||
HStack(spacing: 20) {
|
||||
Button("Cancel") { dismiss() }
|
||||
Button("Save group profile") { saveProfile() }
|
||||
.disabled(!canUpdateProfile())
|
||||
TextField("Group full name (optional)", text: $groupProfile.fullName)
|
||||
}
|
||||
} footer: {
|
||||
Text("Group profile is stored on members' devices, not on the servers.")
|
||||
}
|
||||
.frame(maxWidth: .infinity, minHeight: 120, alignment: .leading)
|
||||
|
||||
Section {
|
||||
Button("Reset") {
|
||||
groupProfile = groupInfo.groupProfile
|
||||
currentProfileHash = groupProfile.hashValue
|
||||
}
|
||||
.disabled(currentProfileHash == groupProfile.hashValue)
|
||||
Button("Save group profile", action: saveProfile)
|
||||
.disabled(!canUpdateProfile)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.frame(maxHeight: .infinity, alignment: .top)
|
||||
.confirmationDialog("Group image", isPresented: $showChooseSource, titleVisibility: .visible) {
|
||||
Button("Take picture") {
|
||||
showTakePhoto = true
|
||||
@@ -95,6 +76,11 @@ struct GroupProfileView: View {
|
||||
Button("Choose from library") {
|
||||
showImagePicker = true
|
||||
}
|
||||
if UIPasteboard.general.hasImages {
|
||||
Button("Paste image") {
|
||||
chosenImage = UIPasteboard.general.image
|
||||
}
|
||||
}
|
||||
}
|
||||
.fullScreenCover(isPresented: $showTakePhoto) {
|
||||
ZStack {
|
||||
@@ -120,8 +106,20 @@ struct GroupProfileView: View {
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
currentProfileHash = groupProfile.hashValue
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
focusDisplayName = true
|
||||
withAnimation { focusDisplayName = true }
|
||||
}
|
||||
}
|
||||
.onDisappear {
|
||||
if canUpdateProfile {
|
||||
showAlert(
|
||||
title: NSLocalizedString("Save group profile?", comment: "alert title"),
|
||||
message: NSLocalizedString("Group profile was changed. If you save it, the updated profile will be sent to group members.", comment: "alert message"),
|
||||
buttonTitle: NSLocalizedString("Save (and notify members)", comment: "alert button"),
|
||||
buttonAction: saveProfile,
|
||||
cancelButton: true
|
||||
)
|
||||
}
|
||||
}
|
||||
.alert(item: $alert) { a in
|
||||
@@ -135,30 +133,30 @@ struct GroupProfileView: View {
|
||||
return createInvalidNameAlert(name, $groupProfile.displayName)
|
||||
}
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture { hideKeyboard() }
|
||||
.navigationBarTitle("Group profile")
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
.navigationBarTitleDisplayMode(focusDisplayName ? .inline : .large)
|
||||
}
|
||||
|
||||
private func canUpdateProfile() -> Bool {
|
||||
groupProfile.displayName.trimmingCharacters(in: .whitespaces) != "" && validNewProfileName()
|
||||
private var canUpdateProfile: Bool {
|
||||
currentProfileHash != groupProfile.hashValue &&
|
||||
groupProfile.displayName.trimmingCharacters(in: .whitespaces) != "" &&
|
||||
validNewProfileName
|
||||
}
|
||||
|
||||
private func validNewProfileName() -> Bool {
|
||||
private var validNewProfileName: Bool {
|
||||
groupProfile.displayName == groupInfo.groupProfile.displayName
|
||||
|| validDisplayName(groupProfile.displayName.trimmingCharacters(in: .whitespaces))
|
||||
}
|
||||
|
||||
func profileNameTextEdit(_ label: LocalizedStringKey, _ name: Binding<String>) -> some View {
|
||||
TextField(label, text: name)
|
||||
.padding(.leading, 32)
|
||||
}
|
||||
|
||||
func saveProfile() {
|
||||
Task {
|
||||
do {
|
||||
groupProfile.displayName = groupProfile.displayName.trimmingCharacters(in: .whitespaces)
|
||||
groupProfile.fullName = groupProfile.fullName.trimmingCharacters(in: .whitespaces)
|
||||
let gInfo = try await apiUpdateGroup(groupInfo.groupId, groupProfile)
|
||||
await MainActor.run {
|
||||
currentProfileHash = groupProfile.hashValue
|
||||
groupInfo = gInfo
|
||||
chatModel.updateGroup(gInfo)
|
||||
dismiss()
|
||||
|
||||
@@ -24,85 +24,70 @@ struct VerifyCodeView: View {
|
||||
}
|
||||
|
||||
private func verifyCodeView(_ code: String) -> some View {
|
||||
ScrollView {
|
||||
let splitCode = splitToParts(code, length: 24)
|
||||
VStack(alignment: .leading) {
|
||||
Group {
|
||||
let splitCode = splitToParts(code, length: 24)
|
||||
return List {
|
||||
Section {
|
||||
QRCode(uri: code, small: true)
|
||||
|
||||
Text(splitCode)
|
||||
.multilineTextAlignment(.leading)
|
||||
.font(.body.monospaced())
|
||||
.lineLimit(20)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
} header: {
|
||||
if connectionVerified {
|
||||
HStack {
|
||||
if connectionVerified {
|
||||
Image(systemName: "checkmark.shield")
|
||||
.foregroundColor(theme.colors.secondary)
|
||||
Text("\(displayName) is verified")
|
||||
} else {
|
||||
Text("\(displayName) is not verified")
|
||||
}
|
||||
Image(systemName: "checkmark.shield").foregroundColor(theme.colors.secondary)
|
||||
Text("\(displayName) is verified").textCase(.none)
|
||||
}
|
||||
.frame(height: 24)
|
||||
|
||||
QRCode(uri: code)
|
||||
.padding(.horizontal)
|
||||
|
||||
Text(splitCode)
|
||||
.multilineTextAlignment(.leading)
|
||||
.font(.body.monospaced())
|
||||
.lineLimit(20)
|
||||
.padding(.bottom, 8)
|
||||
} else {
|
||||
Text("\(displayName) is not verified").textCase(.none)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
|
||||
} footer: {
|
||||
Text("To verify end-to-end encryption with your contact compare (or scan) the code on your devices.")
|
||||
.padding(.bottom)
|
||||
}
|
||||
|
||||
Group {
|
||||
if connectionVerified {
|
||||
Button {
|
||||
verifyCode(nil)
|
||||
} label: {
|
||||
Label("Clear verification", systemImage: "shield")
|
||||
}
|
||||
.padding()
|
||||
} else {
|
||||
HStack {
|
||||
NavigationLink {
|
||||
ScanCodeView(connectionVerified: $connectionVerified, verify: verify)
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
.navigationTitle("Scan code")
|
||||
.modifier(ThemedBackground())
|
||||
} label: {
|
||||
Label("Scan code", systemImage: "qrcode")
|
||||
}
|
||||
.padding()
|
||||
Button {
|
||||
verifyCode(code) { verified in
|
||||
if !verified { showCodeError = true }
|
||||
}
|
||||
} label: {
|
||||
Label("Mark verified", systemImage: "checkmark.shield")
|
||||
}
|
||||
.padding()
|
||||
.alert(isPresented: $showCodeError) {
|
||||
Alert(title: Text("Incorrect security code!"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
}
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Section {
|
||||
if connectionVerified {
|
||||
Button {
|
||||
showShareSheet(items: [splitCode])
|
||||
verifyCode(nil)
|
||||
} label: {
|
||||
Image(systemName: "square.and.arrow.up")
|
||||
Label("Clear verification", systemImage: "shield")
|
||||
}
|
||||
} else {
|
||||
NavigationLink {
|
||||
ScanCodeView(connectionVerified: $connectionVerified, verify: verify)
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
.navigationTitle("Scan code")
|
||||
.modifier(ThemedBackground())
|
||||
} label: {
|
||||
Label("Scan code", systemImage: "qrcode")
|
||||
}
|
||||
Button {
|
||||
verifyCode(code) { verified in
|
||||
if !verified { showCodeError = true }
|
||||
}
|
||||
} label: {
|
||||
Label("Mark verified", systemImage: "checkmark.shield")
|
||||
}
|
||||
.alert(isPresented: $showCodeError) {
|
||||
Alert(title: Text("Incorrect security code!"))
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: connectionVerified) { _ in
|
||||
if connectionVerified { dismiss() }
|
||||
}
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
showShareSheet(items: [splitCode])
|
||||
} label: {
|
||||
Image(systemName: "square.and.arrow.up")
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: connectionVerified) { _ in
|
||||
if connectionVerified { dismiss() }
|
||||
}
|
||||
}
|
||||
|
||||
private func verifyCode(_ code: String?, _ cb: ((Bool) -> Void)? = nil) {
|
||||
|
||||
@@ -21,7 +21,7 @@ enum DatabaseAlert: Identifiable {
|
||||
case deleteLegacyDatabase
|
||||
case deleteFilesAndMedia
|
||||
case setChatItemTTL(ttl: ChatItemTTL)
|
||||
case error(title: LocalizedStringKey, error: String = "")
|
||||
case error(title: String, error: String = "")
|
||||
|
||||
var id: String {
|
||||
switch self {
|
||||
@@ -456,7 +456,7 @@ struct DatabaseView: View {
|
||||
}
|
||||
} catch let error {
|
||||
await MainActor.run {
|
||||
alert = .error(title: "Error exporting chat database", error: responseError(error))
|
||||
alert = .error(title: NSLocalizedString("Error exporting chat database", comment: "alert title"), error: responseError(error))
|
||||
progressIndicator = false
|
||||
}
|
||||
}
|
||||
@@ -492,10 +492,10 @@ struct DatabaseView: View {
|
||||
return migration
|
||||
}
|
||||
} catch let error {
|
||||
await operationEnded(.error(title: "Error importing chat database", error: responseError(error)), progressIndicator, alert)
|
||||
await operationEnded(.error(title: NSLocalizedString("Error importing chat database", comment: "alert title"), error: responseError(error)), progressIndicator, alert)
|
||||
}
|
||||
} catch let error {
|
||||
await operationEnded(.error(title: "Error deleting chat database", error: responseError(error)), progressIndicator, alert)
|
||||
await operationEnded(.error(title: NSLocalizedString("Error deleting chat database", comment: "alert title"), error: responseError(error)), progressIndicator, alert)
|
||||
}
|
||||
} else {
|
||||
showAlert("Error accessing database file")
|
||||
@@ -513,7 +513,7 @@ struct DatabaseView: View {
|
||||
await DatabaseView.operationEnded(.chatDeleted, $progressIndicator, $alert)
|
||||
return true
|
||||
} catch let error {
|
||||
await DatabaseView.operationEnded(.error(title: "Error deleting database", error: responseError(error)), $progressIndicator, $alert)
|
||||
await DatabaseView.operationEnded(.error(title: NSLocalizedString("Error deleting database", comment: "alert title"), error: responseError(error)), $progressIndicator, $alert)
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -522,7 +522,7 @@ struct DatabaseView: View {
|
||||
if removeLegacyDatabaseAndFiles() {
|
||||
legacyDatabase = false
|
||||
} else {
|
||||
alert = .error(title: "Error deleting old database")
|
||||
alert = .error(title: NSLocalizedString("Error deleting old database", comment: "alert title"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,7 +546,7 @@ struct DatabaseView: View {
|
||||
let (title, message) = chatDeletedAlertText()
|
||||
showAlert(title, message: message, actions: { [okAlertActionWaiting] })
|
||||
} else if case let .error(title, error) = dbAlert {
|
||||
showAlert("\(title)", message: error, actions: { [okAlertActionWaiting] })
|
||||
showAlert(title, message: error, actions: { [okAlertActionWaiting] })
|
||||
} else {
|
||||
alert.wrappedValue = dbAlert
|
||||
cont.resume()
|
||||
@@ -567,7 +567,7 @@ struct DatabaseView: View {
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
alert = .error(title: "Error changing setting", error: responseError(error))
|
||||
alert = .error(title: NSLocalizedString("Error changing setting", comment: "alert title"), error: responseError(error))
|
||||
chatItemTTL = currentChatItemTTL
|
||||
afterSetCiTTL()
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ struct NewChatSheet: View {
|
||||
}
|
||||
NavigationLink {
|
||||
AddGroupView()
|
||||
.navigationTitle("Create secret group")
|
||||
.navigationTitle("Create group")
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
} label: {
|
||||
|
||||
@@ -12,11 +12,12 @@ import SimpleXChat
|
||||
|
||||
struct MutableQRCode: View {
|
||||
@Binding var uri: String
|
||||
var small: Bool = false
|
||||
var withLogo: Bool = true
|
||||
var tintColor = UIColor(red: 0.023, green: 0.176, blue: 0.337, alpha: 1)
|
||||
|
||||
var body: some View {
|
||||
QRCode(uri: uri, withLogo: withLogo, tintColor: tintColor)
|
||||
QRCode(uri: uri, small: small, withLogo: withLogo, tintColor: tintColor)
|
||||
.id("simplex-qrcode-view-for-\(uri)")
|
||||
}
|
||||
}
|
||||
@@ -27,7 +28,7 @@ struct SimpleXCreatedLinkQRCode: View {
|
||||
var onShare: (() -> Void)? = nil
|
||||
|
||||
var body: some View {
|
||||
QRCode(uri: link.simplexChatUri(short: short), onShare: onShare)
|
||||
QRCode(uri: link.simplexChatUri(short: short), small: short && link.connShortLink != nil, onShare: onShare)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,50 +39,57 @@ struct SimpleXLinkQRCode: View {
|
||||
var onShare: (() -> Void)? = nil
|
||||
|
||||
var body: some View {
|
||||
QRCode(uri: simplexChatLink(uri), withLogo: withLogo, tintColor: tintColor, onShare: onShare)
|
||||
QRCode(uri: simplexChatLink(uri), small: uri.count < 200, withLogo: withLogo, tintColor: tintColor, onShare: onShare)
|
||||
}
|
||||
}
|
||||
|
||||
private let smallQRRatio: CGFloat = 0.63
|
||||
|
||||
struct QRCode: View {
|
||||
let uri: String
|
||||
var small: Bool = false
|
||||
var withLogo: Bool = true
|
||||
var tintColor = UIColor(red: 0.023, green: 0.176, blue: 0.337, alpha: 1)
|
||||
var onShare: (() -> Void)? = nil
|
||||
@State private var image: UIImage? = nil
|
||||
@State private var makeScreenshotFunc: () -> Void = {}
|
||||
@State private var width: CGFloat = .infinity
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
if let image = image {
|
||||
qrCodeImage(image)
|
||||
GeometryReader { geo in
|
||||
qrCodeImage(image).frame(width: width, height: width)
|
||||
GeometryReader { g in
|
||||
let w = g.size.width * (small ? smallQRRatio : 1)
|
||||
let l = w * (small ? 0.195 : 0.16)
|
||||
let m = w * 0.005
|
||||
ZStack {
|
||||
if withLogo {
|
||||
let w = geo.size.width
|
||||
Image("icon-light")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: w * 0.16, height: w * 0.16)
|
||||
.frame(width: w * 0.165, height: w * 0.165)
|
||||
.frame(width: l, height: l)
|
||||
.frame(width: l + m, height: l + m)
|
||||
.background(.white)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
width = w
|
||||
makeScreenshotFunc = {
|
||||
let size = CGSizeMake(1024 / UIScreen.main.scale, 1024 / UIScreen.main.scale)
|
||||
showShareSheet(items: [makeScreenshot(geo.frame(in: .local).origin, size)])
|
||||
showShareSheet(items: [makeScreenshot(g.frame(in: .local).origin, size)])
|
||||
onShare?()
|
||||
}
|
||||
}
|
||||
.frame(width: geo.size.width, height: geo.size.height)
|
||||
.frame(width: g.size.width, height: g.size.height)
|
||||
}
|
||||
} else {
|
||||
Color.clear.aspectRatio(1, contentMode: .fit)
|
||||
Color.clear.aspectRatio(small ? 1 / smallQRRatio : 1, contentMode: .fit)
|
||||
}
|
||||
}
|
||||
.onTapGesture(perform: makeScreenshotFunc)
|
||||
.task { image = await generateImage(uri, tintColor: tintColor) }
|
||||
.task { image = await generateImage(uri, tintColor: tintColor, errorLevel: small ? "M" : "L") }
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
}
|
||||
}
|
||||
@@ -94,10 +102,11 @@ private func qrCodeImage(_ image: UIImage) -> some View {
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
|
||||
private func generateImage(_ uri: String, tintColor: UIColor) async -> UIImage? {
|
||||
private func generateImage(_ uri: String, tintColor: UIColor, errorLevel: String) async -> UIImage? {
|
||||
let context = CIContext()
|
||||
let filter = CIFilter.qrCodeGenerator()
|
||||
filter.message = Data(uri.utf8)
|
||||
filter.correctionLevel = errorLevel
|
||||
if let outputImage = filter.outputImage,
|
||||
let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
|
||||
return UIImage(cgImage: cgImage).replaceColor(UIColor.black, tintColor)
|
||||
|
||||
@@ -65,7 +65,7 @@ struct NewServerView: View {
|
||||
useServerSection(valid)
|
||||
if valid {
|
||||
Section(header: Text("Add to another device").foregroundColor(theme.colors.secondary)) {
|
||||
MutableQRCode(uri: $serverToEdit.server)
|
||||
MutableQRCode(uri: $serverToEdit.server, small: true)
|
||||
.listRowInsets(EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ struct ProtocolServerView: View {
|
||||
useServerSection(valid)
|
||||
if valid {
|
||||
Section(header: Text("Add to another device").foregroundColor(theme.colors.secondary)) {
|
||||
MutableQRCode(uri: $serverToEdit.server)
|
||||
MutableQRCode(uri: $serverToEdit.server, small: true)
|
||||
.listRowInsets(EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +153,9 @@ struct UserAddressView: View {
|
||||
}
|
||||
}
|
||||
addressSettingsButton(userAddress)
|
||||
if (userAddress.connLinkContact.connShortLink == nil && UserDefaults.standard.bool(forKey: DEFAULT_PRIVACY_SHORT_LINKS)) {
|
||||
addShortLinkButton()
|
||||
}
|
||||
} header: {
|
||||
ToggleShortLinkHeader(text: Text("For social media"), link: userAddress.connLinkContact, short: $showShortLink)
|
||||
} footer: {
|
||||
@@ -209,6 +212,32 @@ struct UserAddressView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private func addShortLinkButton() -> some View {
|
||||
Button {
|
||||
addShortLink()
|
||||
} label: {
|
||||
Label("Add short link", systemImage: "plus")
|
||||
}
|
||||
}
|
||||
|
||||
private func addShortLink() {
|
||||
progressIndicator = true
|
||||
Task {
|
||||
do {
|
||||
let userAddress = try await apiAddMyAddressShortLink()
|
||||
await MainActor.run {
|
||||
chatModel.userAddress = userAddress
|
||||
}
|
||||
await MainActor.run { progressIndicator = false }
|
||||
} catch let error {
|
||||
logger.error("apiAddMyAddressShortLink: \(responseError(error))")
|
||||
let a = getErrorAlert(error, "Error creating address")
|
||||
alert = .error(title: a.title, error: a.message)
|
||||
await MainActor.run { progressIndicator = false }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func createOneTimeLinkButton() -> some View {
|
||||
NavigationLink {
|
||||
NewChatView(selection: .invite)
|
||||
|
||||
@@ -25,28 +25,8 @@ struct UserProfile: View {
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Group {
|
||||
if profile.image != nil {
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
ZStack(alignment: .topTrailing) {
|
||||
profileImageView(profile.image)
|
||||
.onTapGesture { showChooseSource = true }
|
||||
overlayButton("multiply", edge: .top) { profile.image = nil }
|
||||
}
|
||||
overlayButton("camera", edge: .bottom) { showChooseSource = true }
|
||||
}
|
||||
} else {
|
||||
ZStack(alignment: .center) {
|
||||
profileImageView(profile.image)
|
||||
editImageButton { showChooseSource = true }
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
.listRowBackground(Color.clear)
|
||||
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
|
||||
.padding(.top)
|
||||
.contentShape(Rectangle())
|
||||
EditProfileImage(profileImage: $profile.image, showChooseSource: $showChooseSource)
|
||||
.padding(.top)
|
||||
|
||||
Section {
|
||||
HStack {
|
||||
@@ -133,25 +113,6 @@ struct UserProfile: View {
|
||||
.alert(item: $alert) { a in userProfileAlert(a, $profile.displayName) }
|
||||
}
|
||||
|
||||
private func overlayButton(
|
||||
_ systemName: String,
|
||||
edge: Edge.Set,
|
||||
action: @escaping () -> Void
|
||||
) -> some View {
|
||||
Image(systemName: systemName)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(height: 12)
|
||||
.foregroundColor(theme.colors.primary)
|
||||
.padding(6)
|
||||
.frame(width: 36, height: 36, alignment: .center)
|
||||
.background(radius >= 20 ? Color.clear : theme.colors.background.opacity(0.5))
|
||||
.clipShape(Circle())
|
||||
.contentShape(Circle())
|
||||
.padding([.trailing, edge], -12)
|
||||
.onTapGesture(perform: action)
|
||||
}
|
||||
|
||||
private func showFullName(_ user: User) -> Bool {
|
||||
user.profile.fullName != "" && user.profile.fullName != user.profile.displayName
|
||||
}
|
||||
@@ -189,8 +150,54 @@ struct UserProfile: View {
|
||||
}
|
||||
}
|
||||
|
||||
func profileImageView(_ imageStr: String?) -> some View {
|
||||
ProfileImage(imageStr: imageStr, size: 192)
|
||||
struct EditProfileImage: View {
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
@AppStorage(DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) private var radius = defaultProfileImageCorner
|
||||
@Binding var profileImage: String?
|
||||
@Binding var showChooseSource: Bool
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if profileImage != nil {
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
ZStack(alignment: .topTrailing) {
|
||||
ProfileImage(imageStr: profileImage, size: 160)
|
||||
.onTapGesture { showChooseSource = true }
|
||||
overlayButton("multiply", edge: .top) { profileImage = nil }
|
||||
}
|
||||
overlayButton("camera", edge: .bottom) { showChooseSource = true }
|
||||
}
|
||||
} else {
|
||||
ZStack(alignment: .center) {
|
||||
ProfileImage(imageStr: profileImage, size: 160)
|
||||
editImageButton { showChooseSource = true }
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
.listRowBackground(Color.clear)
|
||||
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
|
||||
private func overlayButton(
|
||||
_ systemName: String,
|
||||
edge: Edge.Set,
|
||||
action: @escaping () -> Void
|
||||
) -> some View {
|
||||
Image(systemName: systemName)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(height: 12)
|
||||
.foregroundColor(theme.colors.primary)
|
||||
.padding(6)
|
||||
.frame(width: 36, height: 36, alignment: .center)
|
||||
.background(radius >= 20 ? Color.clear : theme.colors.background.opacity(0.5))
|
||||
.clipShape(Circle())
|
||||
.contentShape(Circle())
|
||||
.padding([.trailing, edge], -12)
|
||||
.onTapGesture(perform: action)
|
||||
}
|
||||
}
|
||||
|
||||
func editImageButton(action: @escaping () -> Void) -> some View {
|
||||
|
||||
@@ -567,10 +567,12 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accept as member" xml:space="preserve">
|
||||
<source>Accept as member</source>
|
||||
<target>Als Mitglied übernehmen</target>
|
||||
<note>alert action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accept as observer" xml:space="preserve">
|
||||
<source>Accept as observer</source>
|
||||
<target>Als Beobachter übernehmen</target>
|
||||
<note>alert action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accept conditions" xml:space="preserve">
|
||||
@@ -596,6 +598,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accept member" xml:space="preserve">
|
||||
<source>Accept member</source>
|
||||
<target>Mitglied übernehmen</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accepted conditions" xml:space="preserve">
|
||||
@@ -1596,10 +1599,12 @@ set passcode view</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Chat with admins" xml:space="preserve">
|
||||
<source>Chat with admins</source>
|
||||
<target>Chat mit Administratoren</target>
|
||||
<note>chat toolbar</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Chat with member" xml:space="preserve">
|
||||
<source>Chat with member</source>
|
||||
<target>Chat mit einem Mitglied</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Chats" xml:space="preserve">
|
||||
@@ -1609,6 +1614,7 @@ set passcode view</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Chats with members" xml:space="preserve">
|
||||
<source>Chats with members</source>
|
||||
<target>Chats mit Mitgliedern</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Check messages every 20 min." xml:space="preserve">
|
||||
@@ -2428,6 +2434,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Delete chat with member?" xml:space="preserve">
|
||||
<source>Delete chat with member?</source>
|
||||
<target>Chat mit dem Mitglied löschen?</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Delete chat?" xml:space="preserve">
|
||||
@@ -3173,6 +3180,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error accepting member" xml:space="preserve">
|
||||
<source>Error accepting member</source>
|
||||
<target>Fehler beim Übernehmen des Mitglieds</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error adding member(s)" xml:space="preserve">
|
||||
@@ -3272,6 +3280,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error deleting chat with member" xml:space="preserve">
|
||||
<source>Error deleting chat with member</source>
|
||||
<target>Fehler beim Löschen des Chats mit dem Mitglied</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error deleting chat!" xml:space="preserve">
|
||||
@@ -4768,6 +4777,7 @@ Das ist Ihr Link für die Gruppe %@!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member admission" xml:space="preserve">
|
||||
<source>Member admission</source>
|
||||
<target>Aufnahme von Mitgliedern</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member inactive" xml:space="preserve">
|
||||
@@ -4807,6 +4817,7 @@ Das ist Ihr Link für die Gruppe %@!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member will join the group, accept member?" xml:space="preserve">
|
||||
<source>Member will join the group, accept member?</source>
|
||||
<target>Ein Mitglied wird der Gruppe beitreten. Übernehmen?</target>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can add message reactions." xml:space="preserve">
|
||||
@@ -5231,6 +5242,7 @@ Das ist Ihr Link für die Gruppe %@!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="New member wants to join the group." xml:space="preserve">
|
||||
<source>New member wants to join the group.</source>
|
||||
<target>Ein neues Mitglied will der Gruppe beitreten.</target>
|
||||
<note>rcv group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New message" xml:space="preserve">
|
||||
@@ -5275,6 +5287,7 @@ Das ist Ihr Link für die Gruppe %@!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="No chats with members" xml:space="preserve">
|
||||
<source>No chats with members</source>
|
||||
<target>Keine Chats mit Mitgliedern</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No contacts selected" xml:space="preserve">
|
||||
@@ -5884,6 +5897,7 @@ Fehler: %@</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for group moderators to review your request to join the group." xml:space="preserve">
|
||||
<source>Please wait for group moderators to review your request to join the group.</source>
|
||||
<target>Bitte warten Sie auf die Überprüfung Ihrer Anfrage durch die Gruppen-Moderatoren, um der Gruppe beitreten zu können.</target>
|
||||
<note>snd group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
@@ -6341,6 +6355,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject member?" xml:space="preserve">
|
||||
<source>Reject member?</source>
|
||||
<target>Mitglied ablehnen?</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Relay server is only used if necessary. Another party can observe your IP address." xml:space="preserve">
|
||||
@@ -6455,6 +6470,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report sent to moderators" xml:space="preserve">
|
||||
<source>Report sent to moderators</source>
|
||||
<target>Meldung wurde an die Moderatoren gesendet</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report spam: only group moderators will see it." xml:space="preserve">
|
||||
@@ -6574,10 +6590,12 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Review members" xml:space="preserve">
|
||||
<source>Review members</source>
|
||||
<target>Überprüfung der Mitglieder</target>
|
||||
<note>admission stage</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Review members before admitting ("knocking")." xml:space="preserve">
|
||||
<source>Review members before admitting ("knocking").</source>
|
||||
<target>Überprüfung der Mitglieder vor der Aufnahme ("Anklopfen").</target>
|
||||
<note>admission stage description</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Revoke" xml:space="preserve">
|
||||
@@ -6638,6 +6656,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Save admission settings?" xml:space="preserve">
|
||||
<source>Save admission settings?</source>
|
||||
<target>Speichern der Aufnahme-Einstellungen?</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Save and notify contact" xml:space="preserve">
|
||||
@@ -7157,6 +7176,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set member admission" xml:space="preserve">
|
||||
<source>Set member admission</source>
|
||||
<target>Aufnahme von Mitgliedern festlegen</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
@@ -8923,6 +8943,7 @@ Verbindungsanfrage wiederholen?</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="You can view your reports in Chat with admins." xml:space="preserve">
|
||||
<source>You can view your reports in Chat with admins.</source>
|
||||
<target>Sie können Ihre Meldungen im Chat mit den Administratoren sehen.</target>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You can't send messages!" xml:space="preserve">
|
||||
@@ -9229,6 +9250,7 @@ Verbindungsanfrage wiederholen?</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="accepted %@" xml:space="preserve">
|
||||
<source>accepted %@</source>
|
||||
<target>%@ übernommen</target>
|
||||
<note>rcv group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="accepted call" xml:space="preserve">
|
||||
@@ -9243,6 +9265,7 @@ Verbindungsanfrage wiederholen?</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="accepted you" xml:space="preserve">
|
||||
<source>accepted you</source>
|
||||
<target>hat Sie übernommen</target>
|
||||
<note>rcv group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="admin" xml:space="preserve">
|
||||
@@ -9267,6 +9290,7 @@ Verbindungsanfrage wiederholen?</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="all" xml:space="preserve">
|
||||
<source>all</source>
|
||||
<target>alle</target>
|
||||
<note>member criteria value</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="all members" xml:space="preserve">
|
||||
@@ -9357,6 +9381,7 @@ marked deleted chat item preview text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="can't send messages" xml:space="preserve">
|
||||
<source>can't send messages</source>
|
||||
<target>Es können keine Nachrichten gesendet werden</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="cancelled %@" xml:space="preserve">
|
||||
@@ -9466,10 +9491,12 @@ marked deleted chat item preview text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="contact deleted" xml:space="preserve">
|
||||
<source>contact deleted</source>
|
||||
<target>Kontakt gelöscht</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="contact disabled" xml:space="preserve">
|
||||
<source>contact disabled</source>
|
||||
<target>Kontakt deaktiviert</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="contact has e2e encryption" xml:space="preserve">
|
||||
@@ -9484,6 +9511,7 @@ marked deleted chat item preview text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="contact not ready" xml:space="preserve">
|
||||
<source>contact not ready</source>
|
||||
<target>Kontakt nicht bereit</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="creator" xml:space="preserve">
|
||||
@@ -9659,6 +9687,7 @@ pref value</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="group is deleted" xml:space="preserve">
|
||||
<source>group is deleted</source>
|
||||
<target>Gruppe wird gelöscht</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="group profile updated" xml:space="preserve">
|
||||
@@ -9788,6 +9817,7 @@ pref value</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="member has old version" xml:space="preserve">
|
||||
<source>member has old version</source>
|
||||
<target>Das Mitglied hat eine alte App-Version</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="message" xml:space="preserve">
|
||||
@@ -9857,6 +9887,7 @@ pref value</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="not synchronized" xml:space="preserve">
|
||||
<source>not synchronized</source>
|
||||
<target>Nicht synchronisiert</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="observer" xml:space="preserve">
|
||||
@@ -9924,6 +9955,7 @@ time to disappear</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending review" xml:space="preserve">
|
||||
<source>pending review</source>
|
||||
<target>Ausstehende Überprüfung</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
@@ -9968,6 +10000,7 @@ time to disappear</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="removed from group" xml:space="preserve">
|
||||
<source>removed from group</source>
|
||||
<target>Von der Gruppe entfernt</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="removed profile picture" xml:space="preserve">
|
||||
@@ -9982,6 +10015,7 @@ time to disappear</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="request to join rejected" xml:space="preserve">
|
||||
<source>request to join rejected</source>
|
||||
<target>Beitrittsanfrage abgelehnt</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="requested to connect" xml:space="preserve">
|
||||
@@ -9991,10 +10025,12 @@ time to disappear</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="review" xml:space="preserve">
|
||||
<source>review</source>
|
||||
<target>Überprüfung</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="reviewed by admins" xml:space="preserve">
|
||||
<source>reviewed by admins</source>
|
||||
<target>Von Administratoren überprüft</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="saved" xml:space="preserve">
|
||||
@@ -10188,6 +10224,7 @@ Zuletzt empfangene Nachricht: %2$@</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="you accepted this member" xml:space="preserve">
|
||||
<source>you accepted this member</source>
|
||||
<target>Sie haben dieses Mitglied übernommen</target>
|
||||
<note>snd group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="you are invited to group" xml:space="preserve">
|
||||
|
||||
@@ -567,10 +567,12 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accept as member" xml:space="preserve">
|
||||
<source>Accept as member</source>
|
||||
<target>Accetta come membro</target>
|
||||
<note>alert action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accept as observer" xml:space="preserve">
|
||||
<source>Accept as observer</source>
|
||||
<target>Accetta come osservatore</target>
|
||||
<note>alert action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accept conditions" xml:space="preserve">
|
||||
@@ -596,6 +598,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accept member" xml:space="preserve">
|
||||
<source>Accept member</source>
|
||||
<target>Accetta membro</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accepted conditions" xml:space="preserve">
|
||||
@@ -1596,10 +1599,12 @@ set passcode view</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Chat with admins" xml:space="preserve">
|
||||
<source>Chat with admins</source>
|
||||
<target>Chat con amministratori</target>
|
||||
<note>chat toolbar</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Chat with member" xml:space="preserve">
|
||||
<source>Chat with member</source>
|
||||
<target>Chatta con il membro</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Chats" xml:space="preserve">
|
||||
@@ -1609,6 +1614,7 @@ set passcode view</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Chats with members" xml:space="preserve">
|
||||
<source>Chats with members</source>
|
||||
<target>Chat con membri</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Check messages every 20 min." xml:space="preserve">
|
||||
@@ -2428,6 +2434,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Delete chat with member?" xml:space="preserve">
|
||||
<source>Delete chat with member?</source>
|
||||
<target>Eliminare la chat con il membro?</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Delete chat?" xml:space="preserve">
|
||||
@@ -3173,6 +3180,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error accepting member" xml:space="preserve">
|
||||
<source>Error accepting member</source>
|
||||
<target>Errore di accettazione del membro</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error adding member(s)" xml:space="preserve">
|
||||
@@ -3272,6 +3280,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error deleting chat with member" xml:space="preserve">
|
||||
<source>Error deleting chat with member</source>
|
||||
<target>Errore di eliminazione della chat con il membro</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error deleting chat!" xml:space="preserve">
|
||||
@@ -4768,6 +4777,7 @@ Questo è il tuo link per il gruppo %@!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member admission" xml:space="preserve">
|
||||
<source>Member admission</source>
|
||||
<target>Ammissione del membro</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member inactive" xml:space="preserve">
|
||||
@@ -4807,6 +4817,7 @@ Questo è il tuo link per il gruppo %@!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member will join the group, accept member?" xml:space="preserve">
|
||||
<source>Member will join the group, accept member?</source>
|
||||
<target>Il membro entrerà nel gruppo, accettarlo?</target>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can add message reactions." xml:space="preserve">
|
||||
@@ -5231,6 +5242,7 @@ Questo è il tuo link per il gruppo %@!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="New member wants to join the group." xml:space="preserve">
|
||||
<source>New member wants to join the group.</source>
|
||||
<target>Un nuovo membro vuole entrare nel gruppo.</target>
|
||||
<note>rcv group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New message" xml:space="preserve">
|
||||
@@ -5275,6 +5287,7 @@ Questo è il tuo link per il gruppo %@!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="No chats with members" xml:space="preserve">
|
||||
<source>No chats with members</source>
|
||||
<target>Nessuna chat con membri</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No contacts selected" xml:space="preserve">
|
||||
@@ -5884,6 +5897,7 @@ Errore: %@</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for group moderators to review your request to join the group." xml:space="preserve">
|
||||
<source>Please wait for group moderators to review your request to join the group.</source>
|
||||
<target>Attendi che i moderatori del gruppo revisionino la tua richiesta di entrare nel gruppo.</target>
|
||||
<note>snd group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
@@ -6341,6 +6355,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject member?" xml:space="preserve">
|
||||
<source>Reject member?</source>
|
||||
<target>Rifiutare il membro?</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Relay server is only used if necessary. Another party can observe your IP address." xml:space="preserve">
|
||||
@@ -6455,6 +6470,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report sent to moderators" xml:space="preserve">
|
||||
<source>Report sent to moderators</source>
|
||||
<target>Segnalazione inviata ai moderatori</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report spam: only group moderators will see it." xml:space="preserve">
|
||||
@@ -6574,10 +6590,12 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Review members" xml:space="preserve">
|
||||
<source>Review members</source>
|
||||
<target>Revisiona i membri</target>
|
||||
<note>admission stage</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Review members before admitting ("knocking")." xml:space="preserve">
|
||||
<source>Review members before admitting ("knocking").</source>
|
||||
<target>Revisiona i membri prima di ammetterli ("bussare").</target>
|
||||
<note>admission stage description</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Revoke" xml:space="preserve">
|
||||
@@ -6638,6 +6656,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Save admission settings?" xml:space="preserve">
|
||||
<source>Save admission settings?</source>
|
||||
<target>Salvare le impostazioni di ammissione?</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Save and notify contact" xml:space="preserve">
|
||||
@@ -7157,6 +7176,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set member admission" xml:space="preserve">
|
||||
<source>Set member admission</source>
|
||||
<target>Imposta l'ammissione del membro</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
@@ -8923,6 +8943,7 @@ Ripetere la richiesta di ingresso?</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="You can view your reports in Chat with admins." xml:space="preserve">
|
||||
<source>You can view your reports in Chat with admins.</source>
|
||||
<target>Puoi vedere le tue segnalazioni nella chat con gli amministratori.</target>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You can't send messages!" xml:space="preserve">
|
||||
@@ -9229,6 +9250,7 @@ Ripetere la richiesta di connessione?</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="accepted %@" xml:space="preserve">
|
||||
<source>accepted %@</source>
|
||||
<target>%@ accettato</target>
|
||||
<note>rcv group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="accepted call" xml:space="preserve">
|
||||
@@ -9243,6 +9265,7 @@ Ripetere la richiesta di connessione?</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="accepted you" xml:space="preserve">
|
||||
<source>accepted you</source>
|
||||
<target>ti ha accettato/a</target>
|
||||
<note>rcv group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="admin" xml:space="preserve">
|
||||
@@ -9267,6 +9290,7 @@ Ripetere la richiesta di connessione?</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="all" xml:space="preserve">
|
||||
<source>all</source>
|
||||
<target>tutti</target>
|
||||
<note>member criteria value</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="all members" xml:space="preserve">
|
||||
@@ -9357,6 +9381,7 @@ marked deleted chat item preview text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="can't send messages" xml:space="preserve">
|
||||
<source>can't send messages</source>
|
||||
<target>impossibile inviare messaggi</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="cancelled %@" xml:space="preserve">
|
||||
@@ -9466,10 +9491,12 @@ marked deleted chat item preview text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="contact deleted" xml:space="preserve">
|
||||
<source>contact deleted</source>
|
||||
<target>contatto eliminato</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="contact disabled" xml:space="preserve">
|
||||
<source>contact disabled</source>
|
||||
<target>contatto disattivato</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="contact has e2e encryption" xml:space="preserve">
|
||||
@@ -9484,6 +9511,7 @@ marked deleted chat item preview text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="contact not ready" xml:space="preserve">
|
||||
<source>contact not ready</source>
|
||||
<target>contatto non pronto</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="creator" xml:space="preserve">
|
||||
@@ -9659,6 +9687,7 @@ pref value</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="group is deleted" xml:space="preserve">
|
||||
<source>group is deleted</source>
|
||||
<target>il gruppo è eliminato</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="group profile updated" xml:space="preserve">
|
||||
@@ -9788,6 +9817,7 @@ pref value</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="member has old version" xml:space="preserve">
|
||||
<source>member has old version</source>
|
||||
<target>il membro ha una versione vecchia</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="message" xml:space="preserve">
|
||||
@@ -9857,6 +9887,7 @@ pref value</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="not synchronized" xml:space="preserve">
|
||||
<source>not synchronized</source>
|
||||
<target>non sincronizzato</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="observer" xml:space="preserve">
|
||||
@@ -9924,6 +9955,7 @@ time to disappear</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending review" xml:space="preserve">
|
||||
<source>pending review</source>
|
||||
<target>in attesa di revisione</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
@@ -9968,6 +10000,7 @@ time to disappear</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="removed from group" xml:space="preserve">
|
||||
<source>removed from group</source>
|
||||
<target>rimosso dal gruppo</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="removed profile picture" xml:space="preserve">
|
||||
@@ -9982,6 +10015,7 @@ time to disappear</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="request to join rejected" xml:space="preserve">
|
||||
<source>request to join rejected</source>
|
||||
<target>richiesta di entrare rifiutata</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="requested to connect" xml:space="preserve">
|
||||
@@ -9991,10 +10025,12 @@ time to disappear</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="review" xml:space="preserve">
|
||||
<source>review</source>
|
||||
<target>revisiona</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="reviewed by admins" xml:space="preserve">
|
||||
<source>reviewed by admins</source>
|
||||
<target>revisionato dagli amministratori</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="saved" xml:space="preserve">
|
||||
@@ -10188,6 +10224,7 @@ ultimo msg ricevuto: %2$@</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="you accepted this member" xml:space="preserve">
|
||||
<source>you accepted this member</source>
|
||||
<target>hai accettato questo membro</target>
|
||||
<note>snd group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="you are invited to group" xml:space="preserve">
|
||||
|
||||
@@ -167,7 +167,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit id="%d hours" xml:space="preserve">
|
||||
<source>%d hours</source>
|
||||
<target>%d ч.</target>
|
||||
<target>%d час.</target>
|
||||
<note>time interval</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="%d messages not forwarded" xml:space="preserve">
|
||||
@@ -567,10 +567,12 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accept as member" xml:space="preserve">
|
||||
<source>Accept as member</source>
|
||||
<target>Принять в группу</target>
|
||||
<note>alert action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accept as observer" xml:space="preserve">
|
||||
<source>Accept as observer</source>
|
||||
<target>Принять как читателя</target>
|
||||
<note>alert action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accept conditions" xml:space="preserve">
|
||||
@@ -596,6 +598,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accept member" xml:space="preserve">
|
||||
<source>Accept member</source>
|
||||
<target>Принять члена</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Accepted conditions" xml:space="preserve">
|
||||
@@ -810,6 +813,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All servers" xml:space="preserve">
|
||||
<source>All servers</source>
|
||||
<target>Все серверы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
|
||||
@@ -1595,10 +1599,12 @@ set passcode view</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Chat with admins" xml:space="preserve">
|
||||
<source>Chat with admins</source>
|
||||
<target>Чат с админами</target>
|
||||
<note>chat toolbar</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Chat with member" xml:space="preserve">
|
||||
<source>Chat with member</source>
|
||||
<target>Чат с членом группы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Chats" xml:space="preserve">
|
||||
@@ -1608,6 +1614,7 @@ set passcode view</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Chats with members" xml:space="preserve">
|
||||
<source>Chats with members</source>
|
||||
<target>Чаты с членами группы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Check messages every 20 min." xml:space="preserve">
|
||||
@@ -2427,6 +2434,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Delete chat with member?" xml:space="preserve">
|
||||
<source>Delete chat with member?</source>
|
||||
<target>Удалить чат с членом группы?</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Delete chat?" xml:space="preserve">
|
||||
@@ -2716,6 +2724,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Direct messages between members are prohibited." xml:space="preserve">
|
||||
<source>Direct messages between members are prohibited.</source>
|
||||
<target>Прямые сообщения между членами запрещены.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Disable (keep overrides)" xml:space="preserve">
|
||||
@@ -2820,6 +2829,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Do not send history to new members." xml:space="preserve">
|
||||
<source>Do not send history to new members.</source>
|
||||
<target>Не отправлять историю новым членам.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Do not use credentials with proxy." xml:space="preserve">
|
||||
@@ -2945,6 +2955,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Enable Flux in Network & servers settings for better metadata privacy." xml:space="preserve">
|
||||
<source>Enable Flux in Network & servers settings for better metadata privacy.</source>
|
||||
<target>Включите Flux в настройках Сеть и серверы для лучшей конфиденциальности метаданных.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Enable SimpleX Lock" xml:space="preserve">
|
||||
@@ -3169,10 +3180,12 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error accepting member" xml:space="preserve">
|
||||
<source>Error accepting member</source>
|
||||
<target>Ошибка вступления члена группы</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error adding member(s)" xml:space="preserve">
|
||||
<source>Error adding member(s)</source>
|
||||
<target>Ошибка при добавлении членов группы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error adding server" xml:space="preserve">
|
||||
@@ -3237,6 +3250,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error creating member contact" xml:space="preserve">
|
||||
<source>Error creating member contact</source>
|
||||
<target>Ошибка при создании контакта</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error creating message" xml:space="preserve">
|
||||
@@ -3266,6 +3280,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error deleting chat with member" xml:space="preserve">
|
||||
<source>Error deleting chat with member</source>
|
||||
<target>Ошибка при удалении чата с членом группы</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error deleting chat!" xml:space="preserve">
|
||||
@@ -3375,6 +3390,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error removing member" xml:space="preserve">
|
||||
<source>Error removing member</source>
|
||||
<target>Ошибка при удалении члена группы</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error reordering lists" xml:space="preserve">
|
||||
@@ -3439,6 +3455,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error sending member contact invitation" xml:space="preserve">
|
||||
<source>Error sending member contact invitation</source>
|
||||
<target>Ошибка при отправке приглашения члену</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Error sending message" xml:space="preserve">
|
||||
@@ -3774,6 +3791,7 @@ snd error text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Fix not supported by group member" xml:space="preserve">
|
||||
<source>Fix not supported by group member</source>
|
||||
<target>Починка не поддерживается членом группы.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="For all moderators" xml:space="preserve">
|
||||
@@ -3907,6 +3925,7 @@ Error: %2$@</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="Fully decentralized – visible only to members." xml:space="preserve">
|
||||
<source>Fully decentralized – visible only to members.</source>
|
||||
<target>Группа полностью децентрализована – она видна только членам.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Fully re-implemented - work in background!" xml:space="preserve">
|
||||
@@ -4016,6 +4035,7 @@ Error: %2$@</source>
|
||||
</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>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Group welcome message" xml:space="preserve">
|
||||
@@ -4025,6 +4045,7 @@ Error: %2$@</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="Group will be deleted for all members - this cannot be undone!" xml:space="preserve">
|
||||
<source>Group will be deleted for all members - this cannot be undone!</source>
|
||||
<target>Группа будет удалена для всех членов - это действие нельзя отменить!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Group will be deleted for you - this cannot be undone!" xml:space="preserve">
|
||||
@@ -4089,6 +4110,7 @@ Error: %2$@</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="History is not sent to new members." xml:space="preserve">
|
||||
<source>History is not sent to new members.</source>
|
||||
<target>История не отправляется новым членам.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="How SimpleX works" xml:space="preserve">
|
||||
@@ -4436,6 +4458,7 @@ More improvements are coming soon!</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invite members" xml:space="preserve">
|
||||
<source>Invite members</source>
|
||||
<target>Пригласить членов группы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Invite to chat" xml:space="preserve">
|
||||
@@ -4748,14 +4771,17 @@ This is your link for group %@!</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member" xml:space="preserve">
|
||||
<source>Member</source>
|
||||
<target>Член группы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member admission" xml:space="preserve">
|
||||
<source>Member admission</source>
|
||||
<target>Приём членов в группу</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member inactive" xml:space="preserve">
|
||||
<source>Member inactive</source>
|
||||
<target>Член неактивен</target>
|
||||
<note>item status text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member reports" xml:space="preserve">
|
||||
@@ -4770,58 +4796,72 @@ This is your link for group %@!</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member role will be changed to "%@". All group members will be notified." xml:space="preserve">
|
||||
<source>Member role will be changed to "%@". All group members will be notified.</source>
|
||||
<target>Роль члена будет изменена на "%@". Все члены группы получат уведомление.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member role will be changed to "%@". The member will receive a new invitation." xml:space="preserve">
|
||||
<source>Member role will be changed to "%@". The member will receive a new invitation.</source>
|
||||
<target>Роль члена будет изменена на "%@". Будет отправлено новое приглашение.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member will be removed from chat - this cannot be undone!" xml:space="preserve">
|
||||
<source>Member will be removed from chat - this cannot be undone!</source>
|
||||
<target>Член будет удален из разговора - это действие нельзя отменить!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member will be removed from group - this cannot be undone!" xml:space="preserve">
|
||||
<source>Member will be removed from group - this cannot be undone!</source>
|
||||
<target>Член группы будет удален - это действие нельзя отменить!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Member will join the group, accept member?" xml:space="preserve">
|
||||
<source>Member will join the group, accept member?</source>
|
||||
<target>Участник хочет присоединиться к группе. Принять?</target>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can add message reactions." xml:space="preserve">
|
||||
<source>Members can add message reactions.</source>
|
||||
<target>Члены могут добавлять реакции на сообщения.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can irreversibly delete sent messages. (24 hours)" xml:space="preserve">
|
||||
<source>Members can irreversibly delete sent messages. (24 hours)</source>
|
||||
<target>Члены могут необратимо удалять отправленные сообщения. (24 часа)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can report messsages to moderators." xml:space="preserve">
|
||||
<source>Members can report messsages to moderators.</source>
|
||||
<target>Члены группы могут пожаловаться модераторам.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send SimpleX links." xml:space="preserve">
|
||||
<source>Members can send SimpleX links.</source>
|
||||
<target>Члены могут отправлять ссылки SimpleX.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send direct messages." xml:space="preserve">
|
||||
<source>Members can send direct messages.</source>
|
||||
<target>Члены могут посылать прямые сообщения.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send disappearing messages." xml:space="preserve">
|
||||
<source>Members can send disappearing messages.</source>
|
||||
<target>Члены могут посылать исчезающие сообщения.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send files and media." xml:space="preserve">
|
||||
<source>Members can send files and media.</source>
|
||||
<target>Члены могут слать файлы и медиа.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Members can send voice messages." xml:space="preserve">
|
||||
<source>Members can send voice messages.</source>
|
||||
<target>Члены могут отправлять голосовые сообщения.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Mention members 👋" xml:space="preserve">
|
||||
<source>Mention members 👋</source>
|
||||
<target>Упоминайте участников 👋</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Menus" xml:space="preserve">
|
||||
@@ -4856,6 +4896,7 @@ This is your link for group %@!</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="Message may be delivered later if member becomes active." xml:space="preserve">
|
||||
<source>Message may be delivered later if member becomes active.</source>
|
||||
<target>Сообщение может быть доставлено позже, если член группы станет активным.</target>
|
||||
<note>item status description</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Message queue info" xml:space="preserve">
|
||||
@@ -5195,10 +5236,12 @@ This is your link for group %@!</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="New member role" xml:space="preserve">
|
||||
<source>New member role</source>
|
||||
<target>Роль члена группы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New member wants to join the group." xml:space="preserve">
|
||||
<source>New member wants to join the group.</source>
|
||||
<target>Новый участник хочет присоединиться к группе.</target>
|
||||
<note>rcv group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="New message" xml:space="preserve">
|
||||
@@ -5243,6 +5286,7 @@ This is your link for group %@!</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="No chats with members" xml:space="preserve">
|
||||
<source>No chats with members</source>
|
||||
<target>Нет чатов с членами группы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="No contacts selected" xml:space="preserve">
|
||||
@@ -5419,6 +5463,9 @@ This is your link for group %@!</source>
|
||||
<source>Now admins can:
|
||||
- delete members' messages.
|
||||
- disable members ("observer" role)</source>
|
||||
<target>Теперь админы могут:
|
||||
- удалять сообщения членов.
|
||||
- приостанавливать членов (роль наблюдатель)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="OK" xml:space="preserve">
|
||||
@@ -5593,6 +5640,7 @@ Requires compatible VPN.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="Open link?" xml:space="preserve">
|
||||
<source>Open link?</source>
|
||||
<target>Открыть ссылку?</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Open migration to another device" xml:space="preserve">
|
||||
@@ -5709,6 +5757,7 @@ Requires compatible VPN.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="Past member %@" xml:space="preserve">
|
||||
<source>Past member %@</source>
|
||||
<target>Бывший член %@</target>
|
||||
<note>past/unknown group member</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Paste desktop address" xml:space="preserve">
|
||||
@@ -5847,6 +5896,7 @@ Error: %@</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for group moderators to review your request to join the group." xml:space="preserve">
|
||||
<source>Please wait for group moderators to review your request to join the group.</source>
|
||||
<target>Пожалуйста, подождите, пока модераторы группы рассмотрят ваш запрос на вступление.</target>
|
||||
<note>snd group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Please wait for token activation to complete." xml:space="preserve">
|
||||
@@ -6021,6 +6071,7 @@ Error: %@</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit sending direct messages to members." xml:space="preserve">
|
||||
<source>Prohibit sending direct messages to members.</source>
|
||||
<target>Запретить посылать прямые сообщения членам группы.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Prohibit sending disappearing messages." xml:space="preserve">
|
||||
@@ -6303,6 +6354,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Reject member?" xml:space="preserve">
|
||||
<source>Reject member?</source>
|
||||
<target>Отклонить участника?</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Relay server is only used if necessary. Another party can observe your IP address." xml:space="preserve">
|
||||
@@ -6332,10 +6384,12 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Remove member" xml:space="preserve">
|
||||
<source>Remove member</source>
|
||||
<target>Удалить члена группы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Remove member?" xml:space="preserve">
|
||||
<source>Remove member?</source>
|
||||
<target>Удалить члена группы?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Remove passphrase from keychain?" xml:space="preserve">
|
||||
@@ -6415,6 +6469,7 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report sent to moderators" xml:space="preserve">
|
||||
<source>Report sent to moderators</source>
|
||||
<target>Жалоба отправлена модераторам</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Report spam: only group moderators will see it." xml:space="preserve">
|
||||
@@ -6534,10 +6589,12 @@ swipe action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Review members" xml:space="preserve">
|
||||
<source>Review members</source>
|
||||
<target>Одобрять членов</target>
|
||||
<note>admission stage</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Review members before admitting ("knocking")." xml:space="preserve">
|
||||
<source>Review members before admitting ("knocking").</source>
|
||||
<target>Одобрять членов для вступления в группу.</target>
|
||||
<note>admission stage description</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Revoke" xml:space="preserve">
|
||||
@@ -6598,6 +6655,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Save admission settings?" xml:space="preserve">
|
||||
<source>Save admission settings?</source>
|
||||
<target>Сохранить настройки вступления?</target>
|
||||
<note>alert title</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Save and notify contact" xml:space="preserve">
|
||||
@@ -6607,6 +6665,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Save and notify group members" xml:space="preserve">
|
||||
<source>Save and notify group members</source>
|
||||
<target>Сохранить и уведомить членов группы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Save and reconnect" xml:space="preserve">
|
||||
@@ -6891,6 +6950,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Send up to 100 last messages to new members." xml:space="preserve">
|
||||
<source>Send up to 100 last messages to new members.</source>
|
||||
<target>Отправить до 100 последних сообщений новым членам.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Sender cancelled file transfer." xml:space="preserve">
|
||||
@@ -7115,6 +7175,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set member admission" xml:space="preserve">
|
||||
<source>Set member admission</source>
|
||||
<target>Приём членов в группу</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set message expiration in chats." xml:space="preserve">
|
||||
@@ -7139,6 +7200,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set the message shown to new members!" xml:space="preserve">
|
||||
<source>Set the message shown to new members!</source>
|
||||
<target>Установить сообщение для новых членов группы!</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Set timeouts for proxy/VPN" xml:space="preserve">
|
||||
@@ -7229,6 +7291,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Short link" xml:space="preserve">
|
||||
<source>Short link</source>
|
||||
<target>Короткая ссылка</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Show QR code" xml:space="preserve">
|
||||
@@ -7333,6 +7396,7 @@ chat item action</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SimpleX channel link" xml:space="preserve">
|
||||
<source>SimpleX channel link</source>
|
||||
<target>SimpleX ссылка канала</target>
|
||||
<note>simplex link type</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SimpleX contact address" xml:space="preserve">
|
||||
@@ -7777,18 +7841,22 @@ It can happen because of some bug or when the connection is compromised.</source
|
||||
</trans-unit>
|
||||
<trans-unit id="The message will be deleted for all members." xml:space="preserve">
|
||||
<source>The message will be deleted for all members.</source>
|
||||
<target>Сообщение будет удалено для всех членов группы.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The message will be marked as moderated for all members." xml:space="preserve">
|
||||
<source>The message will be marked as moderated for all members.</source>
|
||||
<target>Сообщение будет помечено как удаленное для всех членов группы.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The messages will be deleted for all members." xml:space="preserve">
|
||||
<source>The messages will be deleted for all members.</source>
|
||||
<target>Сообщения будут удалены для всех членов группы.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The messages will be marked as moderated for all members." xml:space="preserve">
|
||||
<source>The messages will be marked as moderated for all members.</source>
|
||||
<target>Сообщения будут помечены как удаленные для всех членов группы.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="The old database was not removed during the migration, it can be deleted." xml:space="preserve">
|
||||
@@ -7898,6 +7966,7 @@ It can happen because of some bug or when the connection is compromised.</source
|
||||
</trans-unit>
|
||||
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
|
||||
<source>This group has over %lld members, delivery receipts are not sent.</source>
|
||||
<target>В этой группе более %lld членов, отчёты о доставке не отправляются.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="This group no longer exists." xml:space="preserve">
|
||||
@@ -7917,6 +7986,7 @@ It can happen because of some bug or when the connection is compromised.</source
|
||||
</trans-unit>
|
||||
<trans-unit id="This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link." xml:space="preserve">
|
||||
<source>This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link.</source>
|
||||
<target>Эта ссылка требует новую версию. Обновите приложение или попросите Ваш контакт прислать совместимую ссылку.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="This link was used with another mobile device, please create a new link on the desktop." xml:space="preserve">
|
||||
@@ -8108,14 +8178,17 @@ You will be prompted to complete authentication before this feature is enabled.<
|
||||
</trans-unit>
|
||||
<trans-unit id="Unblock member" xml:space="preserve">
|
||||
<source>Unblock member</source>
|
||||
<target>Разблокировать члена группы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Unblock member for all?" xml:space="preserve">
|
||||
<source>Unblock member for all?</source>
|
||||
<target>Разблокировать члена для всех?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Unblock member?" xml:space="preserve">
|
||||
<source>Unblock member?</source>
|
||||
<target>Разблокировать члена группы?</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Undelivered messages" xml:space="preserve">
|
||||
@@ -8217,10 +8290,12 @@ To connect, please ask your contact to create another connection link and check
|
||||
</trans-unit>
|
||||
<trans-unit id="Unsupported connection link" xml:space="preserve">
|
||||
<source>Unsupported connection link</source>
|
||||
<target>Ссылка не поддерживается</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve">
|
||||
<source>Up to 100 last messages are sent to new members.</source>
|
||||
<target>До 100 последних сообщений отправляются новым членам.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Update" xml:space="preserve">
|
||||
@@ -8315,6 +8390,7 @@ To connect, please ask your contact to create another connection link and check
|
||||
</trans-unit>
|
||||
<trans-unit id="Use TCP port 443 for preset servers only." xml:space="preserve">
|
||||
<source>Use TCP port 443 for preset servers only.</source>
|
||||
<target>Использовать TCP-порт 443 только для серверов по умолчанию.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use chat" xml:space="preserve">
|
||||
@@ -8384,6 +8460,7 @@ To connect, please ask your contact to create another connection link and check
|
||||
</trans-unit>
|
||||
<trans-unit id="Use short links (BETA)" xml:space="preserve">
|
||||
<source>Use short links (BETA)</source>
|
||||
<target>Короткие ссылки (БЕТА)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="Use the app while in the call." xml:space="preserve">
|
||||
@@ -8830,6 +8907,7 @@ Repeat join request?</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="You can share a link or a QR code - anybody will be able to join the group. You won't lose members of the group if you later delete it." xml:space="preserve">
|
||||
<source>You can share a link or a QR code - anybody will be able to join the group. You won't lose members of the group if you later delete it.</source>
|
||||
<target>Вы можете поделиться ссылкой или QR кодом - через них можно присоединиться к группе. Вы сможете удалить ссылку, сохранив членов группы, которые через нее соединились.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You can share this address with your contacts to let them connect with **%@**." xml:space="preserve">
|
||||
@@ -8864,6 +8942,7 @@ Repeat join request?</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="You can view your reports in Chat with admins." xml:space="preserve">
|
||||
<source>You can view your reports in Chat with admins.</source>
|
||||
<target>Вы можете найти Ваши жалобы в Чате с админами.</target>
|
||||
<note>alert message</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You can't send messages!" xml:space="preserve">
|
||||
@@ -8910,6 +8989,7 @@ Repeat connection request?</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="You joined this group. Connecting to inviting group member." xml:space="preserve">
|
||||
<source>You joined this group. Connecting to inviting group member.</source>
|
||||
<target>Вы вступили в эту группу. Устанавливается соединение с пригласившим членом группы.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You may migrate the exported database." xml:space="preserve">
|
||||
@@ -8979,6 +9059,7 @@ Repeat connection request?</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="You will connect to all group members." xml:space="preserve">
|
||||
<source>You will connect to all group members.</source>
|
||||
<target>Вы соединитесь со всеми членами группы.</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="You will still receive calls and notifications from muted profiles when they are active." xml:space="preserve">
|
||||
@@ -9168,6 +9249,7 @@ Repeat connection request?</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="accepted %@" xml:space="preserve">
|
||||
<source>accepted %@</source>
|
||||
<target>принят %@</target>
|
||||
<note>rcv group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="accepted call" xml:space="preserve">
|
||||
@@ -9182,6 +9264,7 @@ Repeat connection request?</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="accepted you" xml:space="preserve">
|
||||
<source>accepted you</source>
|
||||
<target>Вы приняты</target>
|
||||
<note>rcv group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="admin" xml:space="preserve">
|
||||
@@ -9206,10 +9289,12 @@ Repeat connection request?</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="all" xml:space="preserve">
|
||||
<source>all</source>
|
||||
<target>все</target>
|
||||
<note>member criteria value</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="all members" xml:space="preserve">
|
||||
<source>all members</source>
|
||||
<target>все члены</target>
|
||||
<note>feature role</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="always" xml:space="preserve">
|
||||
@@ -9295,6 +9380,7 @@ marked deleted chat item preview text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="can't send messages" xml:space="preserve">
|
||||
<source>can't send messages</source>
|
||||
<target>нельзя отправлять</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="cancelled %@" xml:space="preserve">
|
||||
@@ -9404,10 +9490,12 @@ marked deleted chat item preview text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="contact deleted" xml:space="preserve">
|
||||
<source>contact deleted</source>
|
||||
<target>контакт удален</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="contact disabled" xml:space="preserve">
|
||||
<source>contact disabled</source>
|
||||
<target>контакт выключен</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="contact has e2e encryption" xml:space="preserve">
|
||||
@@ -9422,6 +9510,7 @@ marked deleted chat item preview text</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="contact not ready" xml:space="preserve">
|
||||
<source>contact not ready</source>
|
||||
<target>контакт не готов</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="creator" xml:space="preserve">
|
||||
@@ -9597,6 +9686,7 @@ pref value</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="group is deleted" xml:space="preserve">
|
||||
<source>group is deleted</source>
|
||||
<target>группа удалена</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="group profile updated" xml:space="preserve">
|
||||
@@ -9711,10 +9801,12 @@ pref value</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="member" xml:space="preserve">
|
||||
<source>member</source>
|
||||
<target>член группы</target>
|
||||
<note>member role</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="member %@ changed to %@" xml:space="preserve">
|
||||
<source>member %1$@ changed to %2$@</source>
|
||||
<target>член %1$@ изменился на %2$@</target>
|
||||
<note>profile update event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="member connected" xml:space="preserve">
|
||||
@@ -9724,6 +9816,7 @@ pref value</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="member has old version" xml:space="preserve">
|
||||
<source>member has old version</source>
|
||||
<target>член имеет старую версию</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="message" xml:space="preserve">
|
||||
@@ -9793,6 +9886,7 @@ pref value</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="not synchronized" xml:space="preserve">
|
||||
<source>not synchronized</source>
|
||||
<target>не синхронизирован</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="observer" xml:space="preserve">
|
||||
@@ -9860,6 +9954,7 @@ time to disappear</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="pending review" xml:space="preserve">
|
||||
<source>pending review</source>
|
||||
<target>ожидает одобрения</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="quantum resistant e2e encryption" xml:space="preserve">
|
||||
@@ -9904,6 +9999,7 @@ time to disappear</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="removed from group" xml:space="preserve">
|
||||
<source>removed from group</source>
|
||||
<target>удален из группы</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="removed profile picture" xml:space="preserve">
|
||||
@@ -9918,6 +10014,7 @@ time to disappear</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="request to join rejected" xml:space="preserve">
|
||||
<source>request to join rejected</source>
|
||||
<target>запрос на вступление отклонён</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="requested to connect" xml:space="preserve">
|
||||
@@ -9927,10 +10024,12 @@ time to disappear</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="review" xml:space="preserve">
|
||||
<source>review</source>
|
||||
<target>рассмотрение</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="reviewed by admins" xml:space="preserve">
|
||||
<source>reviewed by admins</source>
|
||||
<target>одобрен админами</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="saved" xml:space="preserve">
|
||||
@@ -10124,6 +10223,7 @@ last received msg: %2$@</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="you accepted this member" xml:space="preserve">
|
||||
<source>you accepted this member</source>
|
||||
<target>Вы приняли этого члена</target>
|
||||
<note>snd group event chat item</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="you are invited to group" xml:space="preserve">
|
||||
@@ -10269,6 +10369,7 @@ last received msg: %2$@</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="From %d chat(s)" xml:space="preserve">
|
||||
<source>From %d chat(s)</source>
|
||||
<target>Из %d чатов</target>
|
||||
<note>notification body</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="From: %@" xml:space="preserve">
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/* notification body */
|
||||
"%d new events" = "%d новых сообщений";
|
||||
|
||||
/* notification body */
|
||||
"From %d chat(s)" = "Из %d чатов";
|
||||
|
||||
/* notification body */
|
||||
"From: %@" = "От: %@";
|
||||
|
||||
|
||||
@@ -184,8 +184,8 @@
|
||||
64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */; };
|
||||
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829982D54AEED006B9E89 /* libgmp.a */; };
|
||||
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829992D54AEEE006B9E89 /* libffi.a */; };
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.1-7Y3Lr8U6bNmEaeIx88dGf7-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.1-7Y3Lr8U6bNmEaeIx88dGf7-ghc9.6.3.a */; };
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.1-7Y3Lr8U6bNmEaeIx88dGf7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.1-7Y3Lr8U6bNmEaeIx88dGf7.a */; };
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.2-K4qWCwk6PxbL8qHn42QC4F-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.2-K4qWCwk6PxbL8qHn42QC4F-ghc9.6.3.a */; };
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.2-K4qWCwk6PxbL8qHn42QC4F.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.2-K4qWCwk6PxbL8qHn42QC4F.a */; };
|
||||
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */; };
|
||||
64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; };
|
||||
64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */; };
|
||||
@@ -553,8 +553,8 @@
|
||||
64C3B0202A0D359700E19930 /* CustomTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTimePicker.swift; sourceTree = "<group>"; };
|
||||
64C829982D54AEED006B9E89 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
|
||||
64C829992D54AEEE006B9E89 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.1-7Y3Lr8U6bNmEaeIx88dGf7-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.4.0.1-7Y3Lr8U6bNmEaeIx88dGf7-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.1-7Y3Lr8U6bNmEaeIx88dGf7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.4.0.1-7Y3Lr8U6bNmEaeIx88dGf7.a"; sourceTree = "<group>"; };
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.2-K4qWCwk6PxbL8qHn42QC4F-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.4.0.2-K4qWCwk6PxbL8qHn42QC4F-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.2-K4qWCwk6PxbL8qHn42QC4F.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.4.0.2-K4qWCwk6PxbL8qHn42QC4F.a"; sourceTree = "<group>"; };
|
||||
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
|
||||
64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = "<group>"; };
|
||||
64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressLearnMore.swift; sourceTree = "<group>"; };
|
||||
@@ -712,8 +712,8 @@
|
||||
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */,
|
||||
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */,
|
||||
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */,
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.1-7Y3Lr8U6bNmEaeIx88dGf7-ghc9.6.3.a in Frameworks */,
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.1-7Y3Lr8U6bNmEaeIx88dGf7.a in Frameworks */,
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.2-K4qWCwk6PxbL8qHn42QC4F-ghc9.6.3.a in Frameworks */,
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.2-K4qWCwk6PxbL8qHn42QC4F.a in Frameworks */,
|
||||
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -798,8 +798,8 @@
|
||||
64C829992D54AEEE006B9E89 /* libffi.a */,
|
||||
64C829982D54AEED006B9E89 /* libgmp.a */,
|
||||
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */,
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.1-7Y3Lr8U6bNmEaeIx88dGf7-ghc9.6.3.a */,
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.1-7Y3Lr8U6bNmEaeIx88dGf7.a */,
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.2-K4qWCwk6PxbL8qHn42QC4F-ghc9.6.3.a */,
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.2-K4qWCwk6PxbL8qHn42QC4F.a */,
|
||||
);
|
||||
path = Libraries;
|
||||
sourceTree = "<group>";
|
||||
@@ -2001,7 +2001,7 @@
|
||||
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 278;
|
||||
CURRENT_PROJECT_VERSION = 279;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -2051,7 +2051,7 @@
|
||||
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 278;
|
||||
CURRENT_PROJECT_VERSION = 279;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -2093,7 +2093,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 278;
|
||||
CURRENT_PROJECT_VERSION = 279;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
@@ -2113,7 +2113,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 278;
|
||||
CURRENT_PROJECT_VERSION = 279;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
@@ -2138,7 +2138,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 278;
|
||||
CURRENT_PROJECT_VERSION = 279;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = s;
|
||||
@@ -2175,7 +2175,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 278;
|
||||
CURRENT_PROJECT_VERSION = 279;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_BITCODE = NO;
|
||||
ENABLE_CODE_COVERAGE = NO;
|
||||
@@ -2212,7 +2212,7 @@
|
||||
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
|
||||
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 278;
|
||||
CURRENT_PROJECT_VERSION = 279;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
@@ -2263,7 +2263,7 @@
|
||||
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
|
||||
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 278;
|
||||
CURRENT_PROJECT_VERSION = 279;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
@@ -2314,7 +2314,7 @@
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 278;
|
||||
CURRENT_PROJECT_VERSION = 279;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
@@ -2348,7 +2348,7 @@
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 278;
|
||||
CURRENT_PROJECT_VERSION = 279;
|
||||
DEVELOPMENT_TEAM = 5NN7GUYB6T;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
|
||||
@@ -3158,7 +3158,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "Острани член";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "Острани член?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
||||
@@ -2478,7 +2478,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "Odstranit člena";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "Odebrat člena?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
||||
@@ -345,6 +345,12 @@ accept incoming call via notification
|
||||
swipe action */
|
||||
"Accept" = "Annehmen";
|
||||
|
||||
/* alert action */
|
||||
"Accept as member" = "Als Mitglied übernehmen";
|
||||
|
||||
/* alert action */
|
||||
"Accept as observer" = "Als Beobachter übernehmen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Accept conditions" = "Nutzungsbedingungen akzeptieren";
|
||||
|
||||
@@ -358,6 +364,12 @@ swipe action */
|
||||
swipe action */
|
||||
"Accept incognito" = "Inkognito akzeptieren";
|
||||
|
||||
/* alert title */
|
||||
"Accept member" = "Mitglied übernehmen";
|
||||
|
||||
/* rcv group event chat item */
|
||||
"accepted %@" = "%@ übernommen";
|
||||
|
||||
/* call status */
|
||||
"accepted call" = "Anruf angenommen";
|
||||
|
||||
@@ -367,6 +379,9 @@ swipe action */
|
||||
/* chat list item title */
|
||||
"accepted invitation" = "Einladung angenommen";
|
||||
|
||||
/* rcv group event chat item */
|
||||
"accepted you" = "hat Sie übernommen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Acknowledged" = "Bestätigt";
|
||||
|
||||
@@ -463,6 +478,9 @@ swipe action */
|
||||
/* chat item text */
|
||||
"agreeing encryption…" = "Verschlüsselung zustimmen…";
|
||||
|
||||
/* member criteria value */
|
||||
"all" = "alle";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All" = "Alle";
|
||||
|
||||
@@ -905,6 +923,9 @@ marked deleted chat item preview text */
|
||||
/* No comment provided by engineer. */
|
||||
"Can't message member" = "Mitglied kann nicht benachrichtigt werden";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"can't send messages" = "Es können keine Nachrichten gesendet werden";
|
||||
|
||||
/* alert action
|
||||
alert button */
|
||||
"Cancel" = "Abbrechen";
|
||||
@@ -1042,9 +1063,18 @@ set passcode view */
|
||||
/* No comment provided by engineer. */
|
||||
"Chat will be deleted for you - this cannot be undone!" = "Der Chat wird für Sie gelöscht. Dies kann nicht rückgängig gemacht werden!";
|
||||
|
||||
/* chat toolbar */
|
||||
"Chat with admins" = "Chat mit Administratoren";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Chat with member" = "Chat mit einem Mitglied";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Chats" = "Chats";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Chats with members" = "Chats mit Mitgliedern";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Check messages every 20 min." = "Alle 20min Nachrichten überprüfen.";
|
||||
|
||||
@@ -1333,9 +1363,15 @@ set passcode view */
|
||||
/* No comment provided by engineer. */
|
||||
"Contact already exists" = "Der Kontakt ist bereits vorhanden";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"contact deleted" = "Kontakt gelöscht";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Contact deleted!" = "Kontakt gelöscht!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"contact disabled" = "Kontakt deaktiviert";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"contact has e2e encryption" = "Kontakt nutzt E2E-Verschlüsselung";
|
||||
|
||||
@@ -1354,6 +1390,9 @@ set passcode view */
|
||||
/* No comment provided by engineer. */
|
||||
"Contact name" = "Kontaktname";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"contact not ready" = "Kontakt nicht bereit";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Contact preferences" = "Kontakt-Präferenzen";
|
||||
|
||||
@@ -1602,6 +1641,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Delete chat profile?" = "Chat-Profil löschen?";
|
||||
|
||||
/* alert title */
|
||||
"Delete chat with member?" = "Chat mit dem Mitglied löschen?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Delete chat?" = "Chat löschen?";
|
||||
|
||||
@@ -2116,6 +2158,9 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"Error accepting contact request" = "Fehler beim Annehmen der Kontaktanfrage";
|
||||
|
||||
/* alert title */
|
||||
"Error accepting member" = "Fehler beim Übernehmen des Mitglieds";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error adding member(s)" = "Fehler beim Hinzufügen von Mitgliedern";
|
||||
|
||||
@@ -2173,6 +2218,9 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"Error deleting chat database" = "Fehler beim Löschen der Chat-Datenbank";
|
||||
|
||||
/* alert title */
|
||||
"Error deleting chat with member" = "Fehler beim Löschen des Chats mit dem Mitglied";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error deleting chat!" = "Fehler beim Löschen des Chats!";
|
||||
|
||||
@@ -2610,6 +2658,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"Group invitation is no longer valid, it was removed by sender." = "Die Gruppeneinladung ist nicht mehr gültig, da sie vom Absender entfernt wurde.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"group is deleted" = "Gruppe wird gelöscht";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Group link" = "Gruppen-Link";
|
||||
|
||||
@@ -3138,9 +3189,15 @@ snd error text */
|
||||
/* profile update event chat item */
|
||||
"member %@ changed to %@" = "Der Mitgliedsname von %1$@ wurde auf %2$@ geändert";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Member admission" = "Aufnahme von Mitgliedern";
|
||||
|
||||
/* rcv group event chat item */
|
||||
"member connected" = "ist der Gruppe beigetreten";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"member has old version" = "Das Mitglied hat eine alte App-Version";
|
||||
|
||||
/* item status text */
|
||||
"Member inactive" = "Mitglied inaktiv";
|
||||
|
||||
@@ -3162,6 +3219,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"Member will be removed from group - this cannot be undone!" = "Das Mitglied wird aus der Gruppe entfernt. Dies kann nicht rückgängig gemacht werden!";
|
||||
|
||||
/* alert message */
|
||||
"Member will join the group, accept member?" = "Ein Mitglied wird der Gruppe beitreten. Übernehmen?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Members can add message reactions." = "Gruppenmitglieder können eine Reaktion auf Nachrichten geben.";
|
||||
|
||||
@@ -3432,6 +3492,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"New member role" = "Neue Mitgliedsrolle";
|
||||
|
||||
/* rcv group event chat item */
|
||||
"New member wants to join the group." = "Ein neues Mitglied will der Gruppe beitreten.";
|
||||
|
||||
/* notification */
|
||||
"new message" = "Neue Nachricht";
|
||||
|
||||
@@ -3471,6 +3534,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"No chats in list %@" = "Keine Chats in der Liste %@";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"No chats with members" = "Keine Chats mit Mitgliedern";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"No contacts selected" = "Keine Kontakte ausgewählt";
|
||||
|
||||
@@ -3555,6 +3621,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"Not compatible!" = "Nicht kompatibel!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"not synchronized" = "Nicht synchronisiert";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Notes" = "Anmerkungen";
|
||||
|
||||
@@ -3802,6 +3871,9 @@ alert button */
|
||||
/* No comment provided by engineer. */
|
||||
"pending approval" = "ausstehende Genehmigung";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"pending review" = "Ausstehende Überprüfung";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Periodic" = "Periodisch";
|
||||
|
||||
@@ -3871,6 +3943,9 @@ alert button */
|
||||
/* token info */
|
||||
"Please try to disable and re-enable notfications." = "Bitte versuchen Sie, die Benachrichtigungen zu deaktivieren und wieder zu aktivieren.";
|
||||
|
||||
/* snd group event chat item */
|
||||
"Please wait for group moderators to review your request to join the group." = "Bitte warten Sie auf die Überprüfung Ihrer Anfrage durch die Gruppen-Moderatoren, um der Gruppe beitreten zu können.";
|
||||
|
||||
/* token info */
|
||||
"Please wait for token activation to complete." = "Bitte warten Sie, bis die Token-Aktivierung abgeschlossen ist.";
|
||||
|
||||
@@ -4151,6 +4226,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Reject contact request" = "Kontaktanfrage ablehnen";
|
||||
|
||||
/* alert title */
|
||||
"Reject member?" = "Mitglied ablehnen?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"rejected" = "abgelehnt";
|
||||
|
||||
@@ -4175,7 +4253,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "Mitglied entfernen";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "Das Mitglied entfernen?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
@@ -4190,6 +4268,9 @@ swipe action */
|
||||
/* profile update event chat item */
|
||||
"removed contact address" = "Die Kontaktadresse wurde entfernt";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"removed from group" = "Von der Gruppe entfernt";
|
||||
|
||||
/* profile update event chat item */
|
||||
"removed profile picture" = "Das Profil-Bild wurde entfernt";
|
||||
|
||||
@@ -4238,6 +4319,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Report reason?" = "Grund der Meldung?";
|
||||
|
||||
/* alert title */
|
||||
"Report sent to moderators" = "Meldung wurde an die Moderatoren gesendet";
|
||||
|
||||
/* report reason */
|
||||
"Report spam: only group moderators will see it." = "Spam melden: Nur Gruppenmoderatoren werden es sehen.";
|
||||
|
||||
@@ -4253,6 +4337,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Reports" = "Meldungen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"request to join rejected" = "Beitrittsanfrage abgelehnt";
|
||||
|
||||
/* chat list item title */
|
||||
"requested to connect" = "Zur Verbindung aufgefordert";
|
||||
|
||||
@@ -4307,9 +4394,21 @@ swipe action */
|
||||
/* chat item action */
|
||||
"Reveal" = "Aufdecken";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"review" = "Überprüfung";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Review conditions" = "Nutzungsbedingungen einsehen";
|
||||
|
||||
/* admission stage */
|
||||
"Review members" = "Überprüfung der Mitglieder";
|
||||
|
||||
/* admission stage description */
|
||||
"Review members before admitting (\"knocking\")." = "Überprüfung der Mitglieder vor der Aufnahme (\"Anklopfen\").";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"reviewed by admins" = "Von Administratoren überprüft";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Revoke" = "Widerrufen";
|
||||
|
||||
@@ -4338,6 +4437,9 @@ chat item action */
|
||||
/* alert button */
|
||||
"Save (and notify contacts)" = "Speichern (und Kontakte benachrichtigen)";
|
||||
|
||||
/* alert title */
|
||||
"Save admission settings?" = "Speichern der Aufnahme-Einstellungen?";
|
||||
|
||||
/* alert button */
|
||||
"Save and notify contact" = "Speichern und Kontakt benachrichtigen";
|
||||
|
||||
@@ -4674,6 +4776,9 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"Set it instead of system authentication." = "Anstelle der System-Authentifizierung festlegen.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Set member admission" = "Aufnahme von Mitgliedern festlegen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Set message expiration in chats." = "Verfallsdatum von Nachrichten in Chats festlegen.";
|
||||
|
||||
@@ -5714,6 +5819,9 @@ report reason */
|
||||
/* No comment provided by engineer. */
|
||||
"You accepted connection" = "Sie haben die Verbindung akzeptiert";
|
||||
|
||||
/* snd group event chat item */
|
||||
"you accepted this member" = "Sie haben dieses Mitglied übernommen";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"You allow" = "Sie erlauben";
|
||||
|
||||
@@ -5825,6 +5933,9 @@ report reason */
|
||||
/* alert message */
|
||||
"You can view invitation link again in connection details." = "Den Einladungslink können Sie in den Details der Verbindung nochmals sehen.";
|
||||
|
||||
/* alert message */
|
||||
"You can view your reports in Chat with admins." = "Sie können Ihre Meldungen im Chat mit den Administratoren sehen.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"You can't send messages!" = "Sie können keine Nachrichten versenden!";
|
||||
|
||||
|
||||
@@ -4172,7 +4172,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "Expulsar miembro";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "¿Expulsar miembro?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
||||
@@ -2409,7 +2409,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "Poista jäsen";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "Poista jäsen?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
||||
@@ -4016,7 +4016,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "Retirer le membre";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "Retirer ce membre ?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
||||
@@ -345,6 +345,12 @@ accept incoming call via notification
|
||||
swipe action */
|
||||
"Accept" = "Accetta";
|
||||
|
||||
/* alert action */
|
||||
"Accept as member" = "Accetta come membro";
|
||||
|
||||
/* alert action */
|
||||
"Accept as observer" = "Accetta come osservatore";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Accept conditions" = "Accetta le condizioni";
|
||||
|
||||
@@ -358,6 +364,12 @@ swipe action */
|
||||
swipe action */
|
||||
"Accept incognito" = "Accetta in incognito";
|
||||
|
||||
/* alert title */
|
||||
"Accept member" = "Accetta membro";
|
||||
|
||||
/* rcv group event chat item */
|
||||
"accepted %@" = "%@ accettato";
|
||||
|
||||
/* call status */
|
||||
"accepted call" = "chiamata accettata";
|
||||
|
||||
@@ -367,6 +379,9 @@ swipe action */
|
||||
/* chat list item title */
|
||||
"accepted invitation" = "invito accettato";
|
||||
|
||||
/* rcv group event chat item */
|
||||
"accepted you" = "ti ha accettato/a";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Acknowledged" = "Riconosciuto";
|
||||
|
||||
@@ -463,6 +478,9 @@ swipe action */
|
||||
/* chat item text */
|
||||
"agreeing encryption…" = "concordando la crittografia…";
|
||||
|
||||
/* member criteria value */
|
||||
"all" = "tutti";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All" = "Tutte";
|
||||
|
||||
@@ -905,6 +923,9 @@ marked deleted chat item preview text */
|
||||
/* No comment provided by engineer. */
|
||||
"Can't message member" = "Impossibile inviare un messaggio al membro";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"can't send messages" = "impossibile inviare messaggi";
|
||||
|
||||
/* alert action
|
||||
alert button */
|
||||
"Cancel" = "Annulla";
|
||||
@@ -1042,9 +1063,18 @@ set passcode view */
|
||||
/* No comment provided by engineer. */
|
||||
"Chat will be deleted for you - this cannot be undone!" = "La chat verrà eliminata solo per te, non è reversibile!";
|
||||
|
||||
/* chat toolbar */
|
||||
"Chat with admins" = "Chat con amministratori";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Chat with member" = "Chatta con il membro";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Chats" = "Chat";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Chats with members" = "Chat con membri";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Check messages every 20 min." = "Controlla i messaggi ogni 20 min.";
|
||||
|
||||
@@ -1333,9 +1363,15 @@ set passcode view */
|
||||
/* No comment provided by engineer. */
|
||||
"Contact already exists" = "Il contatto esiste già";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"contact deleted" = "contatto eliminato";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Contact deleted!" = "Contatto eliminato!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"contact disabled" = "contatto disattivato";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"contact has e2e encryption" = "il contatto ha la crittografia e2e";
|
||||
|
||||
@@ -1354,6 +1390,9 @@ set passcode view */
|
||||
/* No comment provided by engineer. */
|
||||
"Contact name" = "Nome del contatto";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"contact not ready" = "contatto non pronto";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Contact preferences" = "Preferenze del contatto";
|
||||
|
||||
@@ -1602,6 +1641,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Delete chat profile?" = "Eliminare il profilo di chat?";
|
||||
|
||||
/* alert title */
|
||||
"Delete chat with member?" = "Eliminare la chat con il membro?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Delete chat?" = "Eliminare la chat?";
|
||||
|
||||
@@ -2116,6 +2158,9 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"Error accepting contact request" = "Errore nell'accettazione della richiesta di contatto";
|
||||
|
||||
/* alert title */
|
||||
"Error accepting member" = "Errore di accettazione del membro";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error adding member(s)" = "Errore di aggiunta membro/i";
|
||||
|
||||
@@ -2173,6 +2218,9 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"Error deleting chat database" = "Errore nell'eliminazione del database della chat";
|
||||
|
||||
/* alert title */
|
||||
"Error deleting chat with member" = "Errore di eliminazione della chat con il membro";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error deleting chat!" = "Errore nell'eliminazione della chat!";
|
||||
|
||||
@@ -2610,6 +2658,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"Group invitation is no longer valid, it was removed by sender." = "L'invito al gruppo non è più valido, è stato rimosso dal mittente.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"group is deleted" = "il gruppo è eliminato";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Group link" = "Link del gruppo";
|
||||
|
||||
@@ -3138,9 +3189,15 @@ snd error text */
|
||||
/* profile update event chat item */
|
||||
"member %@ changed to %@" = "il membro %1$@ è diventato %2$@";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Member admission" = "Ammissione del membro";
|
||||
|
||||
/* rcv group event chat item */
|
||||
"member connected" = "si è connesso/a";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"member has old version" = "il membro ha una versione vecchia";
|
||||
|
||||
/* item status text */
|
||||
"Member inactive" = "Membro inattivo";
|
||||
|
||||
@@ -3162,6 +3219,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"Member will be removed from group - this cannot be undone!" = "Il membro verrà rimosso dal gruppo, non è reversibile!";
|
||||
|
||||
/* alert message */
|
||||
"Member will join the group, accept member?" = "Il membro entrerà nel gruppo, accettarlo?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Members can add message reactions." = "I membri del gruppo possono aggiungere reazioni ai messaggi.";
|
||||
|
||||
@@ -3432,6 +3492,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"New member role" = "Nuovo ruolo del membro";
|
||||
|
||||
/* rcv group event chat item */
|
||||
"New member wants to join the group." = "Un nuovo membro vuole entrare nel gruppo.";
|
||||
|
||||
/* notification */
|
||||
"new message" = "messaggio nuovo";
|
||||
|
||||
@@ -3471,6 +3534,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"No chats in list %@" = "Nessuna chat nell'elenco %@";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"No chats with members" = "Nessuna chat con membri";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"No contacts selected" = "Nessun contatto selezionato";
|
||||
|
||||
@@ -3555,6 +3621,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"Not compatible!" = "Non compatibile!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"not synchronized" = "non sincronizzato";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Notes" = "Note";
|
||||
|
||||
@@ -3802,6 +3871,9 @@ alert button */
|
||||
/* No comment provided by engineer. */
|
||||
"pending approval" = "in attesa di approvazione";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"pending review" = "in attesa di revisione";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Periodic" = "Periodicamente";
|
||||
|
||||
@@ -3871,6 +3943,9 @@ alert button */
|
||||
/* token info */
|
||||
"Please try to disable and re-enable notfications." = "Prova a disattivare e riattivare le notifiche.";
|
||||
|
||||
/* snd group event chat item */
|
||||
"Please wait for group moderators to review your request to join the group." = "Attendi che i moderatori del gruppo revisionino la tua richiesta di entrare nel gruppo.";
|
||||
|
||||
/* token info */
|
||||
"Please wait for token activation to complete." = "Attendi il completamento dell'attivazione del token.";
|
||||
|
||||
@@ -4151,6 +4226,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Reject contact request" = "Rifiuta la richiesta di contatto";
|
||||
|
||||
/* alert title */
|
||||
"Reject member?" = "Rifiutare il membro?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"rejected" = "rifiutato";
|
||||
|
||||
@@ -4175,7 +4253,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "Rimuovi membro";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "Rimuovere il membro?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
@@ -4190,6 +4268,9 @@ swipe action */
|
||||
/* profile update event chat item */
|
||||
"removed contact address" = "indirizzo di contatto rimosso";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"removed from group" = "rimosso dal gruppo";
|
||||
|
||||
/* profile update event chat item */
|
||||
"removed profile picture" = "immagine del profilo rimossa";
|
||||
|
||||
@@ -4238,6 +4319,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Report reason?" = "Motivo della segnalazione?";
|
||||
|
||||
/* alert title */
|
||||
"Report sent to moderators" = "Segnalazione inviata ai moderatori";
|
||||
|
||||
/* report reason */
|
||||
"Report spam: only group moderators will see it." = "Segnala spam: solo i moderatori del gruppo lo vedranno.";
|
||||
|
||||
@@ -4253,6 +4337,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Reports" = "Segnalazioni";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"request to join rejected" = "richiesta di entrare rifiutata";
|
||||
|
||||
/* chat list item title */
|
||||
"requested to connect" = "richiesto di connettersi";
|
||||
|
||||
@@ -4307,9 +4394,21 @@ swipe action */
|
||||
/* chat item action */
|
||||
"Reveal" = "Rivela";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"review" = "revisiona";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Review conditions" = "Leggi le condizioni";
|
||||
|
||||
/* admission stage */
|
||||
"Review members" = "Revisiona i membri";
|
||||
|
||||
/* admission stage description */
|
||||
"Review members before admitting (\"knocking\")." = "Revisiona i membri prima di ammetterli (\"bussare\").";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"reviewed by admins" = "revisionato dagli amministratori";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Revoke" = "Revoca";
|
||||
|
||||
@@ -4338,6 +4437,9 @@ chat item action */
|
||||
/* alert button */
|
||||
"Save (and notify contacts)" = "Salva (e avvisa i contatti)";
|
||||
|
||||
/* alert title */
|
||||
"Save admission settings?" = "Salvare le impostazioni di ammissione?";
|
||||
|
||||
/* alert button */
|
||||
"Save and notify contact" = "Salva e avvisa il contatto";
|
||||
|
||||
@@ -4674,6 +4776,9 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"Set it instead of system authentication." = "Impostalo al posto dell'autenticazione di sistema.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Set member admission" = "Imposta l'ammissione del membro";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Set message expiration in chats." = "Imposta la scadenza dei messaggi nelle chat.";
|
||||
|
||||
@@ -5714,6 +5819,9 @@ report reason */
|
||||
/* No comment provided by engineer. */
|
||||
"You accepted connection" = "Hai accettato la connessione";
|
||||
|
||||
/* snd group event chat item */
|
||||
"you accepted this member" = "hai accettato questo membro";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"You allow" = "Lo consenti";
|
||||
|
||||
@@ -5825,6 +5933,9 @@ report reason */
|
||||
/* alert message */
|
||||
"You can view invitation link again in connection details." = "Puoi vedere di nuovo il link di invito nei dettagli di connessione.";
|
||||
|
||||
/* alert message */
|
||||
"You can view your reports in Chat with admins." = "Puoi vedere le tue segnalazioni nella chat con gli amministratori.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"You can't send messages!" = "Non puoi inviare messaggi!";
|
||||
|
||||
|
||||
@@ -2628,7 +2628,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "メンバーを除名する";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "メンバーを除名しますか?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
||||
@@ -4169,7 +4169,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "Lid verwijderen";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "Lid verwijderen?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
||||
@@ -3746,7 +3746,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "Usuń członka";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "Usunąć członka?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
"%d file(s) were not downloaded." = "%d файлов не было загружено.";
|
||||
|
||||
/* time interval */
|
||||
"%d hours" = "%d ч.";
|
||||
"%d hours" = "%d час.";
|
||||
|
||||
/* alert title */
|
||||
"%d messages not forwarded" = "%d сообщений не переслано";
|
||||
@@ -345,6 +345,12 @@ accept incoming call via notification
|
||||
swipe action */
|
||||
"Accept" = "Принять";
|
||||
|
||||
/* alert action */
|
||||
"Accept as member" = "Принять в группу";
|
||||
|
||||
/* alert action */
|
||||
"Accept as observer" = "Принять как читателя";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Accept conditions" = "Принять условия";
|
||||
|
||||
@@ -358,6 +364,12 @@ swipe action */
|
||||
swipe action */
|
||||
"Accept incognito" = "Принять инкогнито";
|
||||
|
||||
/* alert title */
|
||||
"Accept member" = "Принять члена";
|
||||
|
||||
/* rcv group event chat item */
|
||||
"accepted %@" = "принят %@";
|
||||
|
||||
/* call status */
|
||||
"accepted call" = "принятый звонок";
|
||||
|
||||
@@ -367,6 +379,9 @@ swipe action */
|
||||
/* chat list item title */
|
||||
"accepted invitation" = "принятое приглашение";
|
||||
|
||||
/* rcv group event chat item */
|
||||
"accepted you" = "Вы приняты";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Acknowledged" = "Подтверждено";
|
||||
|
||||
@@ -463,6 +478,9 @@ swipe action */
|
||||
/* chat item text */
|
||||
"agreeing encryption…" = "шифрование согласовывается…";
|
||||
|
||||
/* member criteria value */
|
||||
"all" = "все";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All" = "Все";
|
||||
|
||||
@@ -484,6 +502,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"All group members will remain connected." = "Все члены группы останутся соединены.";
|
||||
|
||||
/* feature role */
|
||||
"all members" = "все члены";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages." = "Все сообщения и файлы отправляются с **end-to-end шифрованием**, с постквантовой безопасностью в прямых разговорах.";
|
||||
|
||||
@@ -502,6 +523,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"All reports will be archived for you." = "Все сообщения о нарушениях будут заархивированы для вас.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All servers" = "Все серверы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"All your contacts will remain connected." = "Все контакты, которые соединились через этот адрес, сохранятся.";
|
||||
|
||||
@@ -899,6 +923,9 @@ marked deleted chat item preview text */
|
||||
/* No comment provided by engineer. */
|
||||
"Can't message member" = "Не удаётся отправить сообщение члену группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"can't send messages" = "нельзя отправлять";
|
||||
|
||||
/* alert action
|
||||
alert button */
|
||||
"Cancel" = "Отменить";
|
||||
@@ -1036,9 +1063,18 @@ set passcode view */
|
||||
/* No comment provided by engineer. */
|
||||
"Chat will be deleted for you - this cannot be undone!" = "Разговор будет удален для Вас - это действие нельзя отменить!";
|
||||
|
||||
/* chat toolbar */
|
||||
"Chat with admins" = "Чат с админами";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Chat with member" = "Чат с членом группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Chats" = "Чаты";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Chats with members" = "Чаты с членами группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Check messages every 20 min." = "Проверять сообщения каждые 20 минут.";
|
||||
|
||||
@@ -1327,9 +1363,15 @@ set passcode view */
|
||||
/* No comment provided by engineer. */
|
||||
"Contact already exists" = "Существующий контакт";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"contact deleted" = "контакт удален";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Contact deleted!" = "Контакт удален!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"contact disabled" = "контакт выключен";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"contact has e2e encryption" = "у контакта есть e2e шифрование";
|
||||
|
||||
@@ -1348,6 +1390,9 @@ set passcode view */
|
||||
/* No comment provided by engineer. */
|
||||
"Contact name" = "Имена контактов";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"contact not ready" = "контакт не готов";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Contact preferences" = "Предпочтения контакта";
|
||||
|
||||
@@ -1551,13 +1596,13 @@ set passcode view */
|
||||
|
||||
/* delete after time
|
||||
pref value */
|
||||
"default (%@)" = "по умолчанию (%@)";
|
||||
"default (%@)" = "базовый (%@)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"default (no)" = "по умолчанию (нет)";
|
||||
"default (no)" = "базовый (нет)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"default (yes)" = "по умолчанию (да)";
|
||||
"default (yes)" = "базовый (да)";
|
||||
|
||||
/* alert action
|
||||
swipe action */
|
||||
@@ -1596,6 +1641,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Delete chat profile?" = "Удалить профиль?";
|
||||
|
||||
/* alert title */
|
||||
"Delete chat with member?" = "Удалить чат с членом группы?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Delete chat?" = "Удалить разговор?";
|
||||
|
||||
@@ -1657,7 +1705,7 @@ swipe action */
|
||||
"Delete messages" = "Удалить сообщения";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Delete messages after" = "Удалять сообщения через";
|
||||
"Delete messages after" = "Удалять сообщения";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Delete old database" = "Удалить предыдущую версию данных";
|
||||
@@ -1782,6 +1830,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Direct messages between members are prohibited in this chat." = "Личные сообщения запрещены в этой группе.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Direct messages between members are prohibited." = "Прямые сообщения между членами запрещены.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Disable (keep overrides)" = "Выключить (кроме исключений)";
|
||||
|
||||
@@ -1836,6 +1887,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Do it later" = "Отложить";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Do not send history to new members." = "Не отправлять историю новым членам.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Do NOT send messages directly, even if your or destination server does not support private routing." = "Не отправлять сообщения напрямую, даже если сервер получателя не поддерживает конфиденциальную доставку.";
|
||||
|
||||
@@ -1933,6 +1987,9 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"Enable camera access" = "Включить доступ к камере";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Enable Flux in Network & servers settings for better metadata privacy." = "Включите Flux в настройках Сеть и серверы для лучшей конфиденциальности метаданных.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Enable for all" = "Включить для всех";
|
||||
|
||||
@@ -2101,6 +2158,12 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"Error accepting contact request" = "Ошибка при принятии запроса на соединение";
|
||||
|
||||
/* alert title */
|
||||
"Error accepting member" = "Ошибка вступления члена группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error adding member(s)" = "Ошибка при добавлении членов группы";
|
||||
|
||||
/* alert title */
|
||||
"Error adding server" = "Ошибка добавления сервера";
|
||||
|
||||
@@ -2137,6 +2200,9 @@ chat item action */
|
||||
/* alert title */
|
||||
"Error creating list" = "Ошибка создания списка";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error creating member contact" = "Ошибка при создании контакта";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error creating message" = "Ошибка создания сообщения";
|
||||
|
||||
@@ -2152,6 +2218,9 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"Error deleting chat database" = "Ошибка при удалении данных чата";
|
||||
|
||||
/* alert title */
|
||||
"Error deleting chat with member" = "Ошибка при удалении чата с членом группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error deleting chat!" = "Ошибка при удалении чата!";
|
||||
|
||||
@@ -2215,6 +2284,9 @@ chat item action */
|
||||
/* alert title */
|
||||
"Error registering for notifications" = "Ошибка регистрации для уведомлений";
|
||||
|
||||
/* alert title */
|
||||
"Error removing member" = "Ошибка при удалении члена группы";
|
||||
|
||||
/* alert title */
|
||||
"Error reordering lists" = "Ошибка сортировки списков";
|
||||
|
||||
@@ -2251,6 +2323,9 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"Error sending email" = "Ошибка отправки email";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error sending member contact invitation" = "Ошибка при отправке приглашения члену";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Error sending message" = "Ошибка при отправке сообщения";
|
||||
|
||||
@@ -2451,6 +2526,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"Fix not supported by contact" = "Починка не поддерживается контактом";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Fix not supported by group member" = "Починка не поддерживается членом группы.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"For all moderators" = "Для всех модераторов";
|
||||
|
||||
@@ -2529,6 +2607,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"Full name (optional)" = "Полное имя (не обязательно)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Fully decentralized – visible only to members." = "Группа полностью децентрализована – она видна только членам.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Fully re-implemented - work in background!" = "Полностью обновлены - работают в фоне!";
|
||||
|
||||
@@ -2577,6 +2658,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"Group invitation is no longer valid, it was removed by sender." = "Приглашение в группу больше не действительно, оно было удалено отправителем.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"group is deleted" = "группа удалена";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Group link" = "Ссылка группы";
|
||||
|
||||
@@ -2595,12 +2679,18 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"Group profile" = "Профиль группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Group profile is stored on members' devices, not on the servers." = "Профиль группы хранится на устройствах членов, а не на серверах.";
|
||||
|
||||
/* snd group event chat item */
|
||||
"group profile updated" = "профиль группы обновлен";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Group welcome message" = "Приветственное сообщение группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Group will be deleted for all members - this cannot be undone!" = "Группа будет удалена для всех членов - это действие нельзя отменить!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Group will be deleted for you - this cannot be undone!" = "Группа будет удалена для Вас - это действие нельзя отменить!";
|
||||
|
||||
@@ -2637,6 +2727,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"History" = "История";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"History is not sent to new members." = "История не отправляется новым членам.";
|
||||
|
||||
/* time unit */
|
||||
"hours" = "часов";
|
||||
|
||||
@@ -2871,6 +2964,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"Invite friends" = "Пригласить друзей";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Invite members" = "Пригласить членов группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Invite to chat" = "Пригласить в разговор";
|
||||
|
||||
@@ -3084,15 +3180,75 @@ snd error text */
|
||||
/* blur media */
|
||||
"Medium" = "Среднее";
|
||||
|
||||
/* member role */
|
||||
"member" = "член группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Member" = "Член группы";
|
||||
|
||||
/* profile update event chat item */
|
||||
"member %@ changed to %@" = "член %1$@ изменился на %2$@";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Member admission" = "Приём членов в группу";
|
||||
|
||||
/* rcv group event chat item */
|
||||
"member connected" = "соединен(а)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"member has old version" = "член имеет старую версию";
|
||||
|
||||
/* item status text */
|
||||
"Member inactive" = "Член неактивен";
|
||||
|
||||
/* chat feature */
|
||||
"Member reports" = "Сообщения о нарушениях";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Member role will be changed to \"%@\". All chat members will be notified." = "Роль участника будет изменена на \"%@\". Все участники разговора получат уведомление.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Member role will be changed to \"%@\". All group members will be notified." = "Роль члена будет изменена на \"%@\". Все члены группы получат уведомление.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Member role will be changed to \"%@\". The member will receive a new invitation." = "Роль члена будет изменена на \"%@\". Будет отправлено новое приглашение.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Member will be removed from chat - this cannot be undone!" = "Член будет удален из разговора - это действие нельзя отменить!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Member will be removed from group - this cannot be undone!" = "Член группы будет удален - это действие нельзя отменить!";
|
||||
|
||||
/* alert message */
|
||||
"Member will join the group, accept member?" = "Участник хочет присоединиться к группе. Принять?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Members can add message reactions." = "Члены могут добавлять реакции на сообщения.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Members can irreversibly delete sent messages. (24 hours)" = "Члены могут необратимо удалять отправленные сообщения. (24 часа)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Members can report messsages to moderators." = "Члены группы могут пожаловаться модераторам.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Members can send direct messages." = "Члены могут посылать прямые сообщения.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Members can send disappearing messages." = "Члены могут посылать исчезающие сообщения.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Members can send files and media." = "Члены могут слать файлы и медиа.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Members can send SimpleX links." = "Члены могут отправлять ссылки SimpleX.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Members can send voice messages." = "Члены могут отправлять голосовые сообщения.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Mention members 👋" = "Упоминайте участников 👋";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Menus" = "Меню";
|
||||
|
||||
@@ -3114,6 +3270,9 @@ snd error text */
|
||||
/* item status text */
|
||||
"Message forwarded" = "Сообщение переслано";
|
||||
|
||||
/* item status description */
|
||||
"Message may be delivered later if member becomes active." = "Сообщение может быть доставлено позже, если член группы станет активным.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Message queue info" = "Информация об очереди сообщений";
|
||||
|
||||
@@ -3330,6 +3489,12 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"New media options" = "Новые медиа-опции";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"New member role" = "Роль члена группы";
|
||||
|
||||
/* rcv group event chat item */
|
||||
"New member wants to join the group." = "Новый участник хочет присоединиться к группе.";
|
||||
|
||||
/* notification */
|
||||
"new message" = "новое сообщение";
|
||||
|
||||
@@ -3369,6 +3534,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"No chats in list %@" = "Нет чатов в списке %@";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"No chats with members" = "Нет чатов с членами группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"No contacts selected" = "Контакты не выбраны";
|
||||
|
||||
@@ -3453,6 +3621,9 @@ snd error text */
|
||||
/* No comment provided by engineer. */
|
||||
"Not compatible!" = "Несовместимая версия!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"not synchronized" = "не синхронизирован";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Notes" = "Заметки";
|
||||
|
||||
@@ -3477,6 +3648,9 @@ snd error text */
|
||||
/* alert title */
|
||||
"Notifications status" = "Статус уведомлений";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Now admins can:\n- delete members' messages.\n- disable members (\"observer\" role)" = "Теперь админы могут:\n- удалять сообщения членов.\n- приостанавливать членов (роль наблюдатель)";
|
||||
|
||||
/* member role */
|
||||
"observer" = "читатель";
|
||||
|
||||
@@ -3592,6 +3766,9 @@ alert button */
|
||||
/* No comment provided by engineer. */
|
||||
"Open group" = "Открыть группу";
|
||||
|
||||
/* alert title */
|
||||
"Open link?" = "Открыть ссылку?";
|
||||
|
||||
/* authentication reason */
|
||||
"Open migration to another device" = "Открытие миграции на другое устройство";
|
||||
|
||||
@@ -3620,7 +3797,7 @@ alert button */
|
||||
"Or securely share this file link" = "Или передайте эту ссылку";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Or show this code" = "Или покажите этот код";
|
||||
"Or show this code" = "Или покажите код";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Or to share privately" = "Или поделиться конфиденциально";
|
||||
@@ -3667,6 +3844,9 @@ alert button */
|
||||
/* No comment provided by engineer. */
|
||||
"Password to show" = "Пароль чтобы раскрыть";
|
||||
|
||||
/* past/unknown group member */
|
||||
"Past member %@" = "Бывший член %@";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Paste desktop address" = "Вставить адрес компьютера";
|
||||
|
||||
@@ -3691,6 +3871,9 @@ alert button */
|
||||
/* No comment provided by engineer. */
|
||||
"pending approval" = "ожидает утверждения";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"pending review" = "ожидает одобрения";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Periodic" = "Периодически";
|
||||
|
||||
@@ -3760,6 +3943,9 @@ alert button */
|
||||
/* token info */
|
||||
"Please try to disable and re-enable notfications." = "Попробуйте выключить и снова включить уведомления.";
|
||||
|
||||
/* snd group event chat item */
|
||||
"Please wait for group moderators to review your request to join the group." = "Пожалуйста, подождите, пока модераторы группы рассмотрят ваш запрос на вступление.";
|
||||
|
||||
/* token info */
|
||||
"Please wait for token activation to complete." = "Пожалуйста, дождитесь завершения активации токена.";
|
||||
|
||||
@@ -3859,6 +4045,9 @@ alert button */
|
||||
/* No comment provided by engineer. */
|
||||
"Prohibit reporting messages to moderators." = "Запретить жаловаться модераторам группы.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Prohibit sending direct messages to members." = "Запретить посылать прямые сообщения членам группы.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Prohibit sending disappearing messages." = "Запретить посылать исчезающие сообщения.";
|
||||
|
||||
@@ -4037,6 +4226,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Reject contact request" = "Отклонить запрос";
|
||||
|
||||
/* alert title */
|
||||
"Reject member?" = "Отклонить участника?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"rejected" = "отклонён";
|
||||
|
||||
@@ -4058,6 +4250,12 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove image" = "Удалить изображение";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "Удалить члена группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "Удалить члена группы?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Remove passphrase from keychain?" = "Удалить пароль из Keychain?";
|
||||
|
||||
@@ -4070,6 +4268,9 @@ swipe action */
|
||||
/* profile update event chat item */
|
||||
"removed contact address" = "удалён адрес контакта";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"removed from group" = "удален из группы";
|
||||
|
||||
/* profile update event chat item */
|
||||
"removed profile picture" = "удалена картинка профиля";
|
||||
|
||||
@@ -4118,6 +4319,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Report reason?" = "Причина сообщения?";
|
||||
|
||||
/* alert title */
|
||||
"Report sent to moderators" = "Жалоба отправлена модераторам";
|
||||
|
||||
/* report reason */
|
||||
"Report spam: only group moderators will see it." = "Пожаловаться на спам: увидят только модераторы группы.";
|
||||
|
||||
@@ -4133,6 +4337,9 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Reports" = "Сообщения о нарушениях";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"request to join rejected" = "запрос на вступление отклонён";
|
||||
|
||||
/* chat list item title */
|
||||
"requested to connect" = "запрошено соединение";
|
||||
|
||||
@@ -4187,9 +4394,21 @@ swipe action */
|
||||
/* chat item action */
|
||||
"Reveal" = "Показать";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"review" = "рассмотрение";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Review conditions" = "Посмотреть условия";
|
||||
|
||||
/* admission stage */
|
||||
"Review members" = "Одобрять членов";
|
||||
|
||||
/* admission stage description */
|
||||
"Review members before admitting (\"knocking\")." = "Одобрять членов для вступления в группу.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"reviewed by admins" = "одобрен админами";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Revoke" = "Отозвать";
|
||||
|
||||
@@ -4218,9 +4437,15 @@ chat item action */
|
||||
/* alert button */
|
||||
"Save (and notify contacts)" = "Сохранить (и уведомить контакты)";
|
||||
|
||||
/* alert title */
|
||||
"Save admission settings?" = "Сохранить настройки вступления?";
|
||||
|
||||
/* alert button */
|
||||
"Save and notify contact" = "Сохранить и уведомить контакт";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Save and notify group members" = "Сохранить и уведомить членов группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Save and reconnect" = "Сохранить и переподключиться";
|
||||
|
||||
@@ -4408,11 +4633,14 @@ chat item action */
|
||||
"Send questions and ideas" = "Отправьте вопросы и идеи";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Send receipts" = "Отправлять отчёты о доставке";
|
||||
"Send receipts" = "Отчёты о доставке";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Send them from gallery or custom keyboards." = "Отправьте из галереи или из дополнительных клавиатур.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Send up to 100 last messages to new members." = "Отправить до 100 последних сообщений новым членам.";
|
||||
|
||||
/* alert message */
|
||||
"Sender cancelled file transfer." = "Отправитель отменил передачу файла.";
|
||||
|
||||
@@ -4548,6 +4776,9 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"Set it instead of system authentication." = "Установите код вместо системной аутентификации.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Set member admission" = "Приём членов в группу";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Set message expiration in chats." = "Установите срок хранения сообщений в чатах.";
|
||||
|
||||
@@ -4566,6 +4797,9 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"Set passphrase to export" = "Установите пароль";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Set the message shown to new members!" = "Установить сообщение для новых членов группы!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Set timeouts for proxy/VPN" = "Установить таймауты для прокси/VPN";
|
||||
|
||||
@@ -4610,7 +4844,7 @@ chat item action */
|
||||
"Share SimpleX address on social media." = "Поделитесь SimpleX адресом в социальных сетях.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Share this 1-time invite link" = "Поделиться одноразовой ссылкой-приглашением";
|
||||
"Share this 1-time invite link" = "Поделитесь одноразовой ссылкой";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Share to SimpleX" = "Поделиться в SimpleX";
|
||||
@@ -4618,6 +4852,9 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"Share with contacts" = "Поделиться с контактами";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Short link" = "Короткая ссылка";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Show → on messages sent via private routing." = "Показать → на сообщениях доставленных конфиденциально.";
|
||||
|
||||
@@ -4660,6 +4897,9 @@ chat item action */
|
||||
/* No comment provided by engineer. */
|
||||
"SimpleX address or 1-time link?" = "Адрес SimpleX или одноразовая ссылка?";
|
||||
|
||||
/* simplex link type */
|
||||
"SimpleX channel link" = "SimpleX ссылка канала";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app." = "SimpleX Chat и Flux заключили соглашение добавить серверы под управлением Flux в приложение.";
|
||||
|
||||
@@ -4955,6 +5195,18 @@ report reason */
|
||||
/* No comment provided by engineer. */
|
||||
"The ID of the next message is incorrect (less or equal to the previous).\nIt can happen because of some bug or when the connection is compromised." = "Неправильный ID предыдущего сообщения (меньше или равен предыдущему).\nЭто может произойти из-за ошибки программы, или когда соединение компроментировано.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"The message will be deleted for all members." = "Сообщение будет удалено для всех членов группы.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"The message will be marked as moderated for all members." = "Сообщение будет помечено как удаленное для всех членов группы.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"The messages will be deleted for all members." = "Сообщения будут удалены для всех членов группы.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"The messages will be marked as moderated for all members." = "Сообщения будут помечены как удаленные для всех членов группы.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"The old database was not removed during the migration, it can be deleted." = "Предыдущая версия данных чата не удалена при перемещении, её можно удалить.";
|
||||
|
||||
@@ -5021,6 +5273,9 @@ report reason */
|
||||
/* No comment provided by engineer. */
|
||||
"This display name is invalid. Please choose another name." = "Ошибка имени профиля. Пожалуйста, выберите другое имя.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"This group has over %lld members, delivery receipts are not sent." = "В этой группе более %lld членов, отчёты о доставке не отправляются.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"This group no longer exists." = "Эта группа больше не существует.";
|
||||
|
||||
@@ -5030,6 +5285,9 @@ report reason */
|
||||
/* No comment provided by engineer. */
|
||||
"This is your own SimpleX address!" = "Это ваш собственный адрес SimpleX!";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link." = "Эта ссылка требует новую версию. Обновите приложение или попросите Ваш контакт прислать совместимую ссылку.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"This link was used with another mobile device, please create a new link on the desktop." = "Эта ссылка была использована на другом мобильном, пожалуйста, создайте новую ссылку на компьютере.";
|
||||
|
||||
@@ -5141,6 +5399,15 @@ report reason */
|
||||
/* No comment provided by engineer. */
|
||||
"Unblock for all" = "Разблокировать для всех";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Unblock member" = "Разблокировать члена группы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Unblock member for all?" = "Разблокировать члена для всех?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Unblock member?" = "Разблокировать члена группы?";
|
||||
|
||||
/* rcv group event chat item */
|
||||
"unblocked %@" = "%@ разблокирован";
|
||||
|
||||
@@ -5213,6 +5480,12 @@ report reason */
|
||||
/* swipe action */
|
||||
"Unread" = "Не прочитано";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Unsupported connection link" = "Ссылка не поддерживается";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Up to 100 last messages are sent to new members." = "До 100 последних сообщений отправляются новым членам.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Update" = "Обновить";
|
||||
|
||||
@@ -5303,6 +5576,9 @@ report reason */
|
||||
/* No comment provided by engineer. */
|
||||
"Use servers" = "Использовать серверы";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use short links (BETA)" = "Короткие ссылки (БЕТА)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use SimpleX Chat servers?" = "Использовать серверы предосталенные SimpleX Chat?";
|
||||
|
||||
@@ -5312,6 +5588,9 @@ report reason */
|
||||
/* No comment provided by engineer. */
|
||||
"Use TCP port %@ when no port is specified." = "Использовать TCP-порт %@, когда порт не указан.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use TCP port 443 for preset servers only." = "Использовать TCP-порт 443 только для серверов по умолчанию.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Use the app while in the call." = "Используйте приложение во время звонка.";
|
||||
|
||||
@@ -5540,6 +5819,9 @@ report reason */
|
||||
/* No comment provided by engineer. */
|
||||
"You accepted connection" = "Вы приняли приглашение соединиться";
|
||||
|
||||
/* snd group event chat item */
|
||||
"you accepted this member" = "Вы приняли этого члена";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"You allow" = "Вы разрешаете";
|
||||
|
||||
@@ -5630,6 +5912,9 @@ report reason */
|
||||
/* No comment provided by engineer. */
|
||||
"You can set lock screen notification preview via settings." = "Вы можете установить просмотр уведомлений на экране блокировки в настройках.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"You can share a link or a QR code - anybody will be able to join the group. You won't lose members of the group if you later delete it." = "Вы можете поделиться ссылкой или QR кодом - через них можно присоединиться к группе. Вы сможете удалить ссылку, сохранив членов группы, которые через нее соединились.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"You can share this address with your contacts to let them connect with **%@**." = "Вы можете поделиться этим адресом с Вашими контактами, чтобы они могли соединиться с **%@**.";
|
||||
|
||||
@@ -5648,6 +5933,9 @@ report reason */
|
||||
/* alert message */
|
||||
"You can view invitation link again in connection details." = "Вы можете увидеть ссылку-приглашение снова открыв соединение.";
|
||||
|
||||
/* alert message */
|
||||
"You can view your reports in Chat with admins." = "Вы можете найти Ваши жалобы в Чате с админами.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"You can't send messages!" = "Вы не можете отправлять сообщения!";
|
||||
|
||||
@@ -5684,6 +5972,9 @@ report reason */
|
||||
/* No comment provided by engineer. */
|
||||
"You joined this group" = "Вы вступили в эту группу";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"You joined this group. Connecting to inviting group member." = "Вы вступили в эту группу. Устанавливается соединение с пригласившим членом группы.";
|
||||
|
||||
/* snd group event chat item */
|
||||
"you left" = "Вы покинули группу";
|
||||
|
||||
@@ -5738,6 +6029,9 @@ report reason */
|
||||
/* No comment provided by engineer. */
|
||||
"You will be required to authenticate when you start or resume the app after 30 seconds in background." = "Вы будете аутентифицированы при запуске и возобновлении приложения, которое было 30 секунд в фоновом режиме.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"You will connect to all group members." = "Вы соединитесь со всеми членами группы.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"You will still receive calls and notifications from muted profiles when they are active." = "Вы все равно получите звонки и уведомления в профилях без звука, когда они активные.";
|
||||
|
||||
@@ -5833,4 +6127,3 @@ report reason */
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Your SimpleX address" = "Ваш адрес SimpleX";
|
||||
|
||||
|
||||
@@ -2340,7 +2340,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "ลบสมาชิกออก";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "ลบสมาชิกออก?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
||||
@@ -3782,7 +3782,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "Kişiyi sil";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "Kişi silinsin mi?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
||||
@@ -3854,7 +3854,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "Видалити учасника";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "Видалити учасника?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
||||
@@ -4109,7 +4109,7 @@ swipe action */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member" = "删除成员";
|
||||
|
||||
/* alert title */
|
||||
/* No comment provided by engineer. */
|
||||
"Remove member?" = "删除成员吗?";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
||||
+3
-3
@@ -101,13 +101,13 @@ actual fun GrayU8.toImageBitmap(): ImageBitmap = ConvertBitmap.grayToBitmap(this
|
||||
|
||||
actual fun ImageBitmap.hasAlpha(): Boolean = hasAlpha
|
||||
|
||||
actual fun ImageBitmap.addLogo(): ImageBitmap = asAndroidBitmap().applyCanvas {
|
||||
val radius = (width * 0.16f) / 2
|
||||
actual fun ImageBitmap.addLogo(size: Float): ImageBitmap = asAndroidBitmap().applyCanvas {
|
||||
val radius = (width * size) / 2
|
||||
val paint = android.graphics.Paint()
|
||||
paint.color = android.graphics.Color.WHITE
|
||||
drawCircle(width / 2f, height / 2f, radius, paint)
|
||||
val logo = androidAppContext.resources.getDrawable(R.drawable.icon_foreground_android_common, null).toBitmap()
|
||||
val logoSize = (width * 0.24).toInt()
|
||||
val logoSize = (width * size * 1.5).toInt()
|
||||
translate((width - logoSize) / 2f, (height - logoSize) / 2f)
|
||||
drawBitmap(logo, null, android.graphics.Rect(0, 0, logoSize, logoSize), null)
|
||||
}.asImageBitmap()
|
||||
|
||||
+25
@@ -1570,6 +1570,16 @@ object ChatController {
|
||||
return null
|
||||
}
|
||||
|
||||
suspend fun apiAddMyAddressShortLink(rh: Long?): UserContactLinkRec? {
|
||||
val userId = kotlin.runCatching { currentUserId("apiAddMyAddressShortLink") }.getOrElse { return null }
|
||||
val r = sendCmd(rh, CC.ApiAddMyAddressShortLink(userId))
|
||||
if (r is API.Result && r.res is CR.UserContactLink) return r.res.contactLink
|
||||
if (!(networkErrorAlert(r))) {
|
||||
apiErrorAlert("apiAddMyAddressShortLink", generalGetString(MR.strings.error_creating_address), r)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
suspend fun userAddressAutoAccept(rh: Long?, autoAccept: AutoAccept?): UserContactLinkRec? {
|
||||
val userId = kotlin.runCatching { currentUserId("userAddressAutoAccept") }.getOrElse { return null }
|
||||
val r = sendCmd(rh, CC.ApiAddressAutoAccept(userId, autoAccept))
|
||||
@@ -2016,6 +2026,15 @@ object ChatController {
|
||||
return null
|
||||
}
|
||||
|
||||
suspend fun apiAddGroupShortLink(rh: Long?, groupId: Long): Pair<CreatedConnLink, GroupMemberRole>? {
|
||||
val r = sendCmd(rh, CC.ApiAddGroupShortLink(groupId))
|
||||
if (r is API.Result && r.res is CR.GroupLink) return r.res.connLinkContact to r.res.memberRole
|
||||
if (!(networkErrorAlert(r))) {
|
||||
apiErrorAlert("apiAddGroupShortLink", generalGetString(MR.strings.error_creating_link_for_group), r)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
suspend fun apiCreateMemberContact(rh: Long?, groupId: Long, groupMemberId: Long): Contact? {
|
||||
val r = sendCmd(rh, CC.APICreateMemberContact(groupId, groupMemberId))
|
||||
if (r is API.Result && r.res is CR.NewMemberContact) return r.res.contact
|
||||
@@ -3368,6 +3387,7 @@ sealed class CC {
|
||||
class APIGroupLinkMemberRole(val groupId: Long, val memberRole: GroupMemberRole): CC()
|
||||
class APIDeleteGroupLink(val groupId: Long): CC()
|
||||
class APIGetGroupLink(val groupId: Long): CC()
|
||||
class ApiAddGroupShortLink(val groupId: Long): CC()
|
||||
class APICreateMemberContact(val groupId: Long, val groupMemberId: Long): CC()
|
||||
class APISendMemberContactInvitation(val contactId: Long, val mc: MsgContent): CC()
|
||||
class APITestProtoServer(val userId: Long, val server: String): CC()
|
||||
@@ -3422,6 +3442,7 @@ sealed class CC {
|
||||
class ApiCreateMyAddress(val userId: Long, val short: Boolean): CC()
|
||||
class ApiDeleteMyAddress(val userId: Long): CC()
|
||||
class ApiShowMyAddress(val userId: Long): CC()
|
||||
class ApiAddMyAddressShortLink(val userId: Long): CC()
|
||||
class ApiSetProfileAddress(val userId: Long, val on: Boolean): CC()
|
||||
class ApiAddressAutoAccept(val userId: Long, val autoAccept: AutoAccept?): CC()
|
||||
class ApiGetCallInvitations: CC()
|
||||
@@ -3555,6 +3576,7 @@ sealed class CC {
|
||||
is APIGroupLinkMemberRole -> "/_set link role #$groupId ${memberRole.name.lowercase()}"
|
||||
is APIDeleteGroupLink -> "/_delete link #$groupId"
|
||||
is APIGetGroupLink -> "/_get link #$groupId"
|
||||
is ApiAddGroupShortLink -> "/_short link #$groupId"
|
||||
is APICreateMemberContact -> "/_create member contact #$groupId $groupMemberId"
|
||||
is APISendMemberContactInvitation -> "/_invite member contact @$contactId ${mc.cmdString}"
|
||||
is APITestProtoServer -> "/_server test $userId $server"
|
||||
@@ -3609,6 +3631,7 @@ sealed class CC {
|
||||
is ApiCreateMyAddress -> "/_address $userId short=${onOff(short)}"
|
||||
is ApiDeleteMyAddress -> "/_delete_address $userId"
|
||||
is ApiShowMyAddress -> "/_show_address $userId"
|
||||
is ApiAddMyAddressShortLink -> "/_short_link_address $userId"
|
||||
is ApiSetProfileAddress -> "/_profile_address $userId ${onOff(on)}"
|
||||
is ApiAddressAutoAccept -> "/_auto_accept $userId ${AutoAccept.cmdString(autoAccept)}"
|
||||
is ApiAcceptContact -> "/_accept incognito=${onOff(incognito)} $contactReqId"
|
||||
@@ -3720,6 +3743,7 @@ sealed class CC {
|
||||
is APIGroupLinkMemberRole -> "apiGroupLinkMemberRole"
|
||||
is APIDeleteGroupLink -> "apiDeleteGroupLink"
|
||||
is APIGetGroupLink -> "apiGetGroupLink"
|
||||
is ApiAddGroupShortLink -> "apiAddGroupShortLink"
|
||||
is APICreateMemberContact -> "apiCreateMemberContact"
|
||||
is APISendMemberContactInvitation -> "apiSendMemberContactInvitation"
|
||||
is APITestProtoServer -> "testProtoServer"
|
||||
@@ -3774,6 +3798,7 @@ sealed class CC {
|
||||
is ApiCreateMyAddress -> "apiCreateMyAddress"
|
||||
is ApiDeleteMyAddress -> "apiDeleteMyAddress"
|
||||
is ApiShowMyAddress -> "apiShowMyAddress"
|
||||
is ApiAddMyAddressShortLink -> "apiAddMyAddressShortLink"
|
||||
is ApiSetProfileAddress -> "apiSetProfileAddress"
|
||||
is ApiAddressAutoAccept -> "apiAddressAutoAccept"
|
||||
is ApiAcceptContact -> "apiAcceptContact"
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ expect fun compressImageData(bitmap: ImageBitmap, usePng: Boolean): ByteArrayOut
|
||||
expect fun GrayU8.toImageBitmap(): ImageBitmap
|
||||
|
||||
expect fun ImageBitmap.hasAlpha(): Boolean
|
||||
expect fun ImageBitmap.addLogo(): ImageBitmap
|
||||
expect fun ImageBitmap.addLogo(size: Float): ImageBitmap
|
||||
expect fun ImageBitmap.scale(width: Int, height: Int): ImageBitmap
|
||||
|
||||
expect fun isImage(uri: URI): Boolean
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ private fun VerifyCodeLayout(
|
||||
}
|
||||
}
|
||||
|
||||
QRCode(connectionCode, padding = PaddingValues(vertical = DEFAULT_PADDING_HALF))
|
||||
QRCode(connectionCode, small = true, padding = PaddingValues(vertical = DEFAULT_PADDING_HALF))
|
||||
|
||||
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
||||
Spacer(Modifier.weight(2f))
|
||||
|
||||
+28
@@ -49,6 +49,18 @@ fun GroupLinkView(
|
||||
creatingLink = false
|
||||
}
|
||||
}
|
||||
fun addShortLink() {
|
||||
creatingLink = true
|
||||
withBGApi {
|
||||
val link = chatModel.controller.apiAddGroupShortLink(rhId, groupInfo.groupId)
|
||||
if (link != null) {
|
||||
groupLink = link.first
|
||||
groupLinkMemberRole.value = link.second
|
||||
onGroupLinkUpdated?.invoke(link)
|
||||
}
|
||||
creatingLink = false
|
||||
}
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
if (groupLink == null && !creatingLink) {
|
||||
createLink()
|
||||
@@ -60,6 +72,7 @@ fun GroupLinkView(
|
||||
groupLinkMemberRole,
|
||||
creatingLink,
|
||||
createLink = ::createLink,
|
||||
addShortLink = ::addShortLink,
|
||||
updateLink = {
|
||||
val role = groupLinkMemberRole.value
|
||||
if (role != null) {
|
||||
@@ -105,6 +118,7 @@ fun GroupLinkLayout(
|
||||
groupLinkMemberRole: MutableState<GroupMemberRole?>,
|
||||
creatingLink: Boolean,
|
||||
createLink: () -> Unit,
|
||||
addShortLink: () -> Unit,
|
||||
updateLink: () -> Unit,
|
||||
deleteLink: () -> Unit,
|
||||
creatingGroup: Boolean = false,
|
||||
@@ -182,12 +196,26 @@ fun GroupLinkLayout(
|
||||
)
|
||||
}
|
||||
}
|
||||
if (groupLink.connShortLink == null && appPreferences.privacyShortLinks.get()) {
|
||||
AddShortLinkButton(addShortLink)
|
||||
}
|
||||
}
|
||||
}
|
||||
SectionBottomSpacer()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AddShortLinkButton(onClick: () -> Unit) {
|
||||
SettingsActionItem(
|
||||
painterResource(MR.images.ic_add),
|
||||
stringResource(MR.strings.add_short_link),
|
||||
onClick,
|
||||
iconColor = MaterialTheme.colors.primary,
|
||||
textColor = MaterialTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RoleSelectionRow(groupInfo: GroupInfo, selectedRole: MutableState<GroupMemberRole?>, enabled: Boolean = true) {
|
||||
Row(
|
||||
|
||||
+12
-6
@@ -31,6 +31,7 @@ fun SimpleXCreatedLinkQRCode(
|
||||
) {
|
||||
QRCode(
|
||||
connLink.simplexChatUri(short),
|
||||
small = short && connLink.connShortLink != null,
|
||||
modifier,
|
||||
padding,
|
||||
tintColor,
|
||||
@@ -50,6 +51,7 @@ fun SimpleXLinkQRCode(
|
||||
) {
|
||||
QRCode(
|
||||
simplexChatLink(connReq),
|
||||
small = connReq.count() < 200,
|
||||
modifier,
|
||||
padding,
|
||||
tintColor,
|
||||
@@ -61,6 +63,7 @@ fun SimpleXLinkQRCode(
|
||||
@Composable
|
||||
fun QRCode(
|
||||
connReq: String,
|
||||
small: Boolean = false,
|
||||
modifier: Modifier = Modifier,
|
||||
padding: PaddingValues = PaddingValues(horizontal = DEFAULT_PADDING * 2f, vertical = DEFAULT_PADDING_HALF),
|
||||
tintColor: Color = Color(0xff062d56),
|
||||
@@ -68,9 +71,11 @@ fun QRCode(
|
||||
onShare: (() -> Unit)? = null,
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val logoSize = if (small) 0.21f else 0.16f
|
||||
val errorLevel = if (small) QrCode.ErrorLevel.M else QrCode.ErrorLevel.L
|
||||
val qr = remember(connReq, tintColor, withLogo) {
|
||||
qrCodeBitmap(connReq, 1024).replaceColor(Color.Black.toArgb(), tintColor.toArgb())
|
||||
.let { if (withLogo) it.addLogo() else it }
|
||||
qrCodeBitmap(connReq, 1024, errorLevel).replaceColor(Color.Black.toArgb(), tintColor.toArgb())
|
||||
.let { if (withLogo) it.addLogo(logoSize) else it }
|
||||
}
|
||||
Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
|
||||
Image(
|
||||
@@ -79,12 +84,13 @@ fun QRCode(
|
||||
Modifier
|
||||
.padding(padding)
|
||||
.widthIn(max = 400.dp)
|
||||
.fillMaxWidth(if (small) 0.63f else 1f)
|
||||
.aspectRatio(1f)
|
||||
.then(modifier)
|
||||
.clickable {
|
||||
scope.launch {
|
||||
val image = qrCodeBitmap(connReq, 1024).replaceColor(Color.Black.toArgb(), tintColor.toArgb())
|
||||
.let { if (withLogo) it.addLogo() else it }
|
||||
val image = qrCodeBitmap(connReq, 1024, errorLevel).replaceColor(Color.Black.toArgb(), tintColor.toArgb())
|
||||
.let { if (withLogo) it.addLogo(logoSize) else it }
|
||||
val file = saveTempImageUncompressed(image, true)
|
||||
if (file != null) {
|
||||
shareFile("", CryptoFile.plain(file.absolutePath))
|
||||
@@ -96,8 +102,8 @@ fun QRCode(
|
||||
}
|
||||
}
|
||||
|
||||
fun qrCodeBitmap(content: String, size: Int = 1024): ImageBitmap {
|
||||
val qrCode = QrCodeEncoder().addAutomatic(content).setError(QrCode.ErrorLevel.L).fixate()
|
||||
fun qrCodeBitmap(content: String, size: Int = 1024, errorLevel: QrCode.ErrorLevel): ImageBitmap {
|
||||
val qrCode = QrCodeEncoder().addAutomatic(content).setError(errorLevel).fixate()
|
||||
/** See [QrCodeGeneratorImage.initialize] and [FiducialImageEngine.configure] for size calculation */
|
||||
val numModules = QrCode.totalModules(qrCode.version)
|
||||
// Hide border on light themes to make it fit to the same place as camera in QRCodeScanner.
|
||||
|
||||
+30
@@ -43,6 +43,7 @@ fun UserAddressView(
|
||||
KeyChangeEffect(user.value?.remoteHostId, user.value?.userId) {
|
||||
close()
|
||||
}
|
||||
|
||||
fun setProfileAddress(on: Boolean) {
|
||||
progressIndicator = true
|
||||
withBGApi {
|
||||
@@ -81,6 +82,17 @@ fun UserAddressView(
|
||||
}
|
||||
}
|
||||
|
||||
fun addShortLink() {
|
||||
withBGApi {
|
||||
progressIndicator = true
|
||||
val userAddress = chatModel.controller.apiAddMyAddressShortLink(user.value?.remoteHostId)
|
||||
if (userAddress != null) {
|
||||
chatModel.userAddress.value = userAddress
|
||||
}
|
||||
progressIndicator = false
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(autoCreateAddress) {
|
||||
if (chatModel.userAddress.value == null && autoCreateAddress) {
|
||||
createAddress()
|
||||
@@ -95,6 +107,7 @@ fun UserAddressView(
|
||||
userAddress = userAddress.value,
|
||||
shareViaProfile,
|
||||
createAddress = { createAddress() },
|
||||
addShortLink = { addShortLink() },
|
||||
learnMore = {
|
||||
ModalManager.start.showModal {
|
||||
UserAddressLearnMore()
|
||||
@@ -169,6 +182,7 @@ private fun UserAddressLayout(
|
||||
userAddress: UserContactLinkRec?,
|
||||
shareViaProfile: MutableState<Boolean>,
|
||||
createAddress: () -> Unit,
|
||||
addShortLink: () -> Unit,
|
||||
learnMore: () -> Unit,
|
||||
share: (String) -> Unit,
|
||||
sendEmail: (UserContactLinkRec) -> Unit,
|
||||
@@ -211,6 +225,9 @@ private fun UserAddressLayout(
|
||||
// ShareViaEmailButton { sendEmail(userAddress) }
|
||||
BusinessAddressToggle(autoAcceptState) { saveAas(autoAcceptState.value, autoAcceptStateSaved) }
|
||||
AddressSettingsButton(user, userAddress, shareViaProfile, setProfileAddress, saveAas)
|
||||
if (userAddress.connLinkContact.connShortLink == null && appPreferences.privacyShortLinks.get()) {
|
||||
AddShortLinkButton(addShortLink)
|
||||
}
|
||||
|
||||
if (autoAcceptState.value.business) {
|
||||
SectionTextFooter(stringResource(MR.strings.add_your_team_members_to_conversations))
|
||||
@@ -248,6 +265,17 @@ private fun CreateAddressButton(onClick: () -> Unit) {
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AddShortLinkButton(onClick: () -> Unit) {
|
||||
SettingsActionItem(
|
||||
painterResource(MR.images.ic_add),
|
||||
stringResource(MR.strings.add_short_link),
|
||||
onClick,
|
||||
iconColor = MaterialTheme.colors.primary,
|
||||
textColor = MaterialTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CreateOneTimeLinkButton() {
|
||||
val closeAll = { ModalManager.start.closeModals() }
|
||||
@@ -559,6 +587,7 @@ fun PreviewUserAddressLayoutNoAddress() {
|
||||
user = User.sampleData,
|
||||
userAddress = null,
|
||||
createAddress = {},
|
||||
addShortLink = {},
|
||||
share = { _ -> },
|
||||
deleteAddress = {},
|
||||
saveAas = { _, _ -> },
|
||||
@@ -592,6 +621,7 @@ fun PreviewUserAddressLayoutAddressCreated() {
|
||||
user = User.sampleData,
|
||||
userAddress = UserContactLinkRec(CreatedConnLink("https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D", null)),
|
||||
createAddress = {},
|
||||
addShortLink = {},
|
||||
share = { _ -> },
|
||||
deleteAddress = {},
|
||||
saveAas = { _, _ -> },
|
||||
|
||||
+1
-1
@@ -189,7 +189,7 @@ fun CustomServer(
|
||||
if (valid.value) {
|
||||
SectionDividerSpaced()
|
||||
SectionView(stringResource(MR.strings.smp_servers_add_to_another_device).uppercase()) {
|
||||
QRCode(serverAddress.value)
|
||||
QRCode(serverAddress.value, small = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1058,6 +1058,7 @@
|
||||
<string name="address_settings">Address settings</string>
|
||||
<string name="business_address">Business address</string>
|
||||
<string name="add_your_team_members_to_conversations">Add your team members to the conversations.</string>
|
||||
<string name="add_short_link">Add short link</string>
|
||||
|
||||
<!-- CreateSimpleXAddress.kt -->
|
||||
<string name="continue_to_next_step">Continue</string>
|
||||
|
||||
@@ -1014,7 +1014,7 @@
|
||||
<string name="moderate_verb">Moderieren</string>
|
||||
<string name="moderate_message_will_be_marked_warning">Diese Nachricht wird für alle Mitglieder als moderiert gekennzeichnet.</string>
|
||||
<string name="you_are_observer">Sie sind Beobachter</string>
|
||||
<string name="observer_cant_send_message_title">Sie können keine Nachrichten versenden!</string>
|
||||
<string name="observer_cant_send_message_title">Sie sind Beobachter</string>
|
||||
<string name="group_member_role_observer">Beobachter</string>
|
||||
<string name="initial_member_role">Anfängliche Rolle</string>
|
||||
<string name="delete_member_message__question">Nachricht des Mitglieds löschen\?</string>
|
||||
@@ -2466,7 +2466,7 @@
|
||||
<string name="group_new_support_chats_short">%d Chat(s)</string>
|
||||
<string name="report_sent_alert_title">Meldung wurde an die Moderatoren gesendet</string>
|
||||
<string name="snd_group_event_member_accepted">Sie haben dieses Mitglied übernommen</string>
|
||||
<string name="admission_stage_review_descr">Überprüfung der Mitglieder vor der Aufnahme (Anklopfen).</string>
|
||||
<string name="admission_stage_review_descr">Überprüfung der Mitglieder vor der Aufnahme (\"Anklopfen\").</string>
|
||||
<string name="admission_stage_review">Überprüfung der Mitglieder</string>
|
||||
<string name="member_criteria_all">alle</string>
|
||||
<string name="member_criteria_off">Aus</string>
|
||||
@@ -2489,10 +2489,25 @@
|
||||
<string name="button_support_chat">Chat mit Administratoren</string>
|
||||
<string name="rcv_group_event_member_accepted">%1$s übernommen</string>
|
||||
<string name="accept_pending_member_alert_confirmation_as_member">Als Mitglied übernehmen</string>
|
||||
<string name="error_accepting_member">Fehler beim Übernehmen eines Mitglieds</string>
|
||||
<string name="error_accepting_member">Fehler beim Übernehmen des Mitglieds</string>
|
||||
<string name="member_admission">Aufnahme von Mitgliedern</string>
|
||||
<string name="group_member_status_pending_review">Ausstehende Überprüfung</string>
|
||||
<string name="group_new_support_chat_one">Chat mit einem Mitglied</string>
|
||||
<string name="accept_pending_member_button">Übernehmen</string>
|
||||
<string name="snd_group_event_user_pending_review">Bitte warten Sie auf die Überprüfung Ihrer Anfrage durch die Gruppen-Moderatoren, um der Gruppe beitreten zu können.</string>
|
||||
<string name="cant_send_message_group_deleted">Gruppe wird gelöscht</string>
|
||||
<string name="cant_send_message_rejected">Beitrittsanfrage abgelehnt</string>
|
||||
<string name="cant_send_message_mem_removed">Von der Gruppe entfernt</string>
|
||||
<string name="cant_send_message_you_left">Sie haben die Gruppe verlassen</string>
|
||||
<string name="cant_send_message_contact_disabled">Kontakt deaktiviert</string>
|
||||
<string name="cant_send_message_contact_not_synchronized">Nicht synchronisiert</string>
|
||||
<string name="error_deleting_member_support_chat">Fehler beim Löschen des Chats mit dem Mitglied</string>
|
||||
<string name="cant_send_message_contact_not_ready">Kontakt nicht bereit</string>
|
||||
<string name="cant_send_message_alert_title">Sie können keine Nachrichten senden!</string>
|
||||
<string name="delete_member_support_chat_button">Chat löschen</string>
|
||||
<string name="delete_member_support_chat_alert_title">Chat mit dem Mitglied löschen?</string>
|
||||
<string name="reject_pending_member_alert_title">Mitglied ablehnen?</string>
|
||||
<string name="cant_send_message_generic">Es können keine Nachrichten gesendet werden</string>
|
||||
<string name="cant_send_message_contact_deleted">Kontakt gelöscht</string>
|
||||
<string name="cant_send_message_member_has_old_version">Das Mitglied hat eine alte App-Version</string>
|
||||
</resources>
|
||||
|
||||
@@ -940,7 +940,7 @@
|
||||
<string name="error_updating_link_for_group">Errore nell\'aggiornamento del link del gruppo</string>
|
||||
<string name="group_member_role_observer">osservatore</string>
|
||||
<string name="observer_cant_send_message_desc">Contatta l\'amministratore del gruppo.</string>
|
||||
<string name="observer_cant_send_message_title">Non puoi inviare messaggi!</string>
|
||||
<string name="observer_cant_send_message_title">sei un osservatore</string>
|
||||
<string name="language_system">Sistema</string>
|
||||
<string name="button_add_welcome_message">Aggiungi messaggio di benvenuto</string>
|
||||
<string name="button_welcome_message">Messaggio di benvenuto</string>
|
||||
@@ -2414,14 +2414,29 @@
|
||||
<string name="accept_pending_member_alert_title">Accetta membro</string>
|
||||
<string name="button_support_chat">Chatta con gli amministratori</string>
|
||||
<string name="accept_pending_member_alert_confirmation_as_observer">Accetta come osservatore</string>
|
||||
<string name="rcv_group_event_new_member_pending_review">Il nuovo membro vuole entrare nel gruppo.</string>
|
||||
<string name="rcv_group_event_new_member_pending_review">Un nuovo membro vuole entrare nel gruppo.</string>
|
||||
<string name="member_criteria_all">tutti</string>
|
||||
<string name="button_support_chat_member">Chatta con il membro</string>
|
||||
<string name="member_support">Chat con membri</string>
|
||||
<string name="error_accepting_member">Errore di accettazione del membro</string>
|
||||
<string name="accept_pending_member_alert_confirmation_as_member">Accetta come membro</string>
|
||||
<string name="set_member_admission">Imposta l\'ammissione del membro</string>
|
||||
<string name="set_member_admission">Imposta l\'ammissione dei membri</string>
|
||||
<string name="report_sent_alert_title">Segnalazione inviata ai moderatori</string>
|
||||
<string name="group_member_status_pending_review">in attesa di revisione</string>
|
||||
<string name="report_sent_alert_msg_view_in_support_chat">Puoi vedere i tuoi resoconti nella chat con gli amministratori.</string>
|
||||
<string name="report_sent_alert_msg_view_in_support_chat">Puoi vedere le tue segnalazioni nella chat con gli amministratori.</string>
|
||||
<string name="cant_send_message_alert_title">Non puoi inviare messaggi!</string>
|
||||
<string name="cant_send_message_contact_not_ready">contatto non pronto</string>
|
||||
<string name="cant_send_message_contact_deleted">contatto eliminato</string>
|
||||
<string name="cant_send_message_contact_disabled">contatto disattivato</string>
|
||||
<string name="cant_send_message_contact_not_synchronized">non sincronizzato</string>
|
||||
<string name="cant_send_message_rejected">richiesta di entrare rifiutata</string>
|
||||
<string name="cant_send_message_generic">impossibile inviare messaggi</string>
|
||||
<string name="cant_send_message_group_deleted">il gruppo è eliminato</string>
|
||||
<string name="cant_send_message_member_has_old_version">il membro ha una versione vecchia</string>
|
||||
<string name="cant_send_message_mem_removed">rimosso dal gruppo</string>
|
||||
<string name="cant_send_message_you_left">sei uscito/a</string>
|
||||
<string name="delete_member_support_chat_alert_title">Eliminare la chat con il membro?</string>
|
||||
<string name="reject_pending_member_alert_title">Rifiutare il membro?</string>
|
||||
<string name="delete_member_support_chat_button">Elimina chat</string>
|
||||
<string name="error_deleting_member_support_chat">Errore di eliminazione della chat con il membro</string>
|
||||
</resources>
|
||||
|
||||
@@ -1019,7 +1019,7 @@
|
||||
<string name="moderate_message_will_be_deleted_warning">Сообщение будет удалено для всех членов группы.</string>
|
||||
<string name="moderate_message_will_be_marked_warning">Сообщение будет помечено как удаленное для всех членов группы.</string>
|
||||
<string name="observer_cant_send_message_desc">Пожалуйста, свяжитесь с админом группы.</string>
|
||||
<string name="observer_cant_send_message_title">Вы не можете отправлять сообщения!</string>
|
||||
<string name="observer_cant_send_message_title">Вы \"читатель\"</string>
|
||||
<string name="you_are_observer">только чтение сообщений</string>
|
||||
<string name="group_member_role_observer">читатель</string>
|
||||
<string name="initial_member_role">Роль при вступлении</string>
|
||||
@@ -1132,7 +1132,7 @@
|
||||
<string name="decryption_error">Ошибка расшифровки</string>
|
||||
<string name="lock_not_enabled">Блокировка SimpleX не включена!</string>
|
||||
<string name="alert_title_msg_bad_hash">Ошибка хэш сообщения</string>
|
||||
<string name="alert_text_msg_bad_hash">Хэш предыдущего сообщения отличается\"</string>
|
||||
<string name="alert_text_msg_bad_hash">Хэш предыдущего сообщения отличается.</string>
|
||||
<string name="confirm_passcode">Подтвердить код</string>
|
||||
<string name="incorrect_passcode">Неправильный код</string>
|
||||
<string name="lock_after">Заблокировать через</string>
|
||||
@@ -2467,4 +2467,58 @@
|
||||
<string name="onboarding_conditions_private_chats_not_accessible">Частные разговоры, группы и Ваши контакты недоступны для операторов серверов.</string>
|
||||
<string name="onboarding_conditions_configure_server_operators">Настроить операторов серверов</string>
|
||||
<string name="onboarding_conditions_privacy_policy_and_conditions_of_use">Политика конфиденциальности и условия использования.</string>
|
||||
<string name="member_criteria_all">все</string>
|
||||
<string name="accept_pending_member_button">Принять</string>
|
||||
<string name="accept_pending_member_alert_question">Участник хочет присоединиться к группе. Принять?</string>
|
||||
<string name="cant_send_message_group_deleted">группа удалена</string>
|
||||
<string name="cant_send_message_mem_removed">удален из группы</string>
|
||||
<string name="group_new_support_chats_short">%d чата(ов)</string>
|
||||
<string name="cant_send_message_contact_not_ready">контакт не готов</string>
|
||||
<string name="cant_send_message_contact_deleted">контакт удален</string>
|
||||
<string name="cant_send_message_contact_not_synchronized">не синхронизирован</string>
|
||||
<string name="cant_send_message_rejected">запрос на вступление отклонён</string>
|
||||
<string name="rcv_group_event_new_member_pending_review">Новый участник хочет присоединиться к группе.</string>
|
||||
<string name="snd_group_event_user_pending_review">Пожалуйста, подождите, пока модераторы группы рассмотрят ваш запрос на вступление.</string>
|
||||
<string name="group_member_status_pending_review">ожидает одобрения</string>
|
||||
<string name="reject_pending_member_button">Отклонить</string>
|
||||
<string name="reject_pending_member_alert_title">Отклонить участника?</string>
|
||||
<string name="error_deleting_member_support_chat">Ошибка при удалении чата с членом группы</string>
|
||||
<string name="full_link_button_text">Полная ссылка</string>
|
||||
<string name="error_accepting_member">Ошибка вступления члена группы</string>
|
||||
<string name="unsupported_connection_link">Ссылка не поддерживается</string>
|
||||
<string name="link_requires_newer_app_version_please_upgrade">Эта ссылка требует новую версию. Обновите приложение или попросите Ваш контакт прислать совместимую ссылку.</string>
|
||||
<string name="group_new_support_messages">%d сообщений</string>
|
||||
<string name="report_sent_alert_msg_view_in_support_chat">Вы можете найти Ваши жалобы в Чате с админами.</string>
|
||||
<string name="button_support_chat">Чат с админами</string>
|
||||
<string name="button_support_chat_member">Чат с членом группы</string>
|
||||
<string name="member_criteria_off">выключено</string>
|
||||
<string name="admission_stage_review">Одобрять членов</string>
|
||||
<string name="member_support">Чаты с членами группы</string>
|
||||
<string name="member_admission">Приём членов в группу</string>
|
||||
<string name="admission_stage_review_descr">Одобрять членов для вступления в группу.</string>
|
||||
<string name="no_support_chats">Нет чатов с членами группы</string>
|
||||
<string name="accept_pending_member_alert_confirmation_as_observer">Принять как читателя</string>
|
||||
<string name="accept_pending_member_alert_confirmation_as_member">Принять в группу</string>
|
||||
<string name="accept_pending_member_alert_title">Принять члена</string>
|
||||
<string name="reviewed_by_admins">одобрен админами</string>
|
||||
<string name="report_sent_alert_title">Жалоба отправлена модераторам</string>
|
||||
<string name="cant_send_message_you_left">Вы вышли</string>
|
||||
<string name="cant_send_message_generic">нельзя отправлять</string>
|
||||
<string name="group_new_support_chats">%d чатов с членами группы</string>
|
||||
<string name="cant_send_message_contact_disabled">контакт выключен</string>
|
||||
<string name="cant_send_message_member_has_old_version">член имеет старую версию</string>
|
||||
<string name="cant_send_message_alert_title">Вы не можете отправлять сообщения!</string>
|
||||
<string name="short_link_button_text">Короткая ссылка</string>
|
||||
<string name="save_admission_question">Сохранить настройки вступления?</string>
|
||||
<string name="snd_group_event_member_accepted">Вы приняли этого члена</string>
|
||||
<string name="group_member_status_pending_review_short">рассмотрение</string>
|
||||
<string name="set_member_admission">Установить вступление в группу</string>
|
||||
<string name="delete_member_support_chat_alert_title">Удалить чат с членом группы?</string>
|
||||
<string name="delete_member_support_chat_button">Удалить разговор</string>
|
||||
<string name="rcv_group_event_member_accepted">принят %1$s</string>
|
||||
<string name="support_chat">Чат с админами</string>
|
||||
<string name="rcv_group_event_user_accepted">Вы приняты</string>
|
||||
<string name="group_new_support_chat_one">1 чат с членом группы</string>
|
||||
<string name="simplex_link_channel">SimpleX ссылка канала</string>
|
||||
<string name="privacy_short_links">Короткие ссылки (БЕТА)</string>
|
||||
</resources>
|
||||
|
||||
@@ -929,7 +929,7 @@
|
||||
<string name="group_member_role_observer">观察员</string>
|
||||
<string name="you_are_observer">你是观察者</string>
|
||||
<string name="error_updating_link_for_group">更新群链接错误</string>
|
||||
<string name="observer_cant_send_message_title">你无法发送消息!</string>
|
||||
<string name="observer_cant_send_message_title">你是观察员</string>
|
||||
<string name="initial_member_role">初始角色</string>
|
||||
<string name="observer_cant_send_message_desc">请联系群管理员。</string>
|
||||
<string name="language_system">系统</string>
|
||||
@@ -2408,4 +2408,19 @@
|
||||
<string name="report_sent_alert_msg_view_in_support_chat">你可以在和管理员和聊天中查看你的举报。</string>
|
||||
<string name="accept_pending_member_alert_confirmation_as_observer">接受为观察员</string>
|
||||
<string name="group_new_support_chat_one">和一名成员的一个聊天</string>
|
||||
<string name="cant_send_message_generic">无法发送消息</string>
|
||||
<string name="cant_send_message_you_left">你离开了</string>
|
||||
<string name="error_deleting_member_support_chat">删除和成员的聊天出错</string>
|
||||
<string name="cant_send_message_alert_title">你无法发送消息!</string>
|
||||
<string name="cant_send_message_contact_disabled">禁用了联系人</string>
|
||||
<string name="cant_send_message_group_deleted">群被删除了</string>
|
||||
<string name="cant_send_message_mem_removed">从群被删除了</string>
|
||||
<string name="cant_send_message_rejected">加入请求被拒绝</string>
|
||||
<string name="delete_member_support_chat_button">删除聊天</string>
|
||||
<string name="delete_member_support_chat_alert_title">删除和成员的聊天吗?</string>
|
||||
<string name="cant_send_message_contact_not_synchronized">未同步</string>
|
||||
<string name="cant_send_message_member_has_old_version">成员有旧版本</string>
|
||||
<string name="cant_send_message_contact_deleted">删除了联系人</string>
|
||||
<string name="cant_send_message_contact_not_ready">联系人未就绪</string>
|
||||
<string name="reject_pending_member_alert_title">拒绝成员?</string>
|
||||
</resources>
|
||||
|
||||
+3
-3
@@ -133,9 +133,9 @@ actual fun ImageBitmap.hasAlpha(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
actual fun ImageBitmap.addLogo(): ImageBitmap {
|
||||
val radius = (width * 0.16f).toInt()
|
||||
val logoSize = (width * 0.24).toInt()
|
||||
actual fun ImageBitmap.addLogo(size: Float): ImageBitmap {
|
||||
val radius = (width * size).toInt()
|
||||
val logoSize = (width * size * 1.5).toInt()
|
||||
val logo: BufferedImage = MR.images.icon_foreground_common.image
|
||||
val original = toAwtImage()
|
||||
val withLogo = BufferedImage(width, height, original.type)
|
||||
|
||||
@@ -24,11 +24,11 @@ android.nonTransitiveRClass=true
|
||||
kotlin.mpp.androidSourceSetLayoutVersion=2
|
||||
kotlin.jvm.target=11
|
||||
|
||||
android.version_name=6.4-beta.0
|
||||
android.version_code=290
|
||||
android.version_name=6.4-beta.1
|
||||
android.version_code=291
|
||||
|
||||
desktop.version_name=6.4-beta.0
|
||||
desktop.version_code=102
|
||||
desktop.version_name=6.4-beta.1
|
||||
desktop.version_code=103
|
||||
|
||||
kotlin.version=1.9.23
|
||||
gradle.plugin.version=8.2.0
|
||||
|
||||
@@ -713,7 +713,7 @@ directoryServiceEvent st opts@DirectoryOpts {adminUsers, superUsers, serviceName
|
||||
case mRole_ of
|
||||
Nothing ->
|
||||
getGroupLinkRole cc user g >>= \case
|
||||
Just (_, CCLink gLink _, mRole) -> do
|
||||
Just (_, CCLink gLink _, _, mRole) -> do
|
||||
let anotherRole = case mRole of GRObserver -> GRMember; _ -> GRObserver
|
||||
sendReply $
|
||||
initialRole n mRole
|
||||
@@ -1045,7 +1045,7 @@ vr :: ChatController -> VersionRangeChat
|
||||
vr ChatController {config = ChatConfig {chatVRange}} = chatVRange
|
||||
{-# INLINE vr #-}
|
||||
|
||||
getGroupLinkRole :: ChatController -> User -> GroupInfo -> IO (Maybe (Int64, CreatedLinkContact, GroupMemberRole))
|
||||
getGroupLinkRole :: ChatController -> User -> GroupInfo -> IO (Maybe (Int64, CreatedLinkContact, GroupLinkId, GroupMemberRole))
|
||||
getGroupLinkRole cc user gInfo =
|
||||
withDB "getGroupLink" cc $ \db -> getGroupLink db user gInfo
|
||||
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/simplex-chat/simplexmq.git
|
||||
tag: d352d518c2b3a42bc7a298954dde799422e1457f
|
||||
tag: 4c33d8ac43874660c342c00cb078bd3814d5d9eb
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
|
||||
@@ -10,11 +10,13 @@ vlc_dir=$root_dir/apps/multiplatform/common/src/commonMain/cpp/desktop/libs/linu
|
||||
|
||||
mkdir $vlc_dir || exit 0
|
||||
|
||||
vlc_tag='v3.0.21-1'
|
||||
vlc_url="https://github.com/simplex-chat/vlc/releases/download/${vlc_tag}/vlc-linux-x86_64.appimage"
|
||||
|
||||
cd /tmp
|
||||
mkdir tmp 2>/dev/null || true
|
||||
cd tmp
|
||||
curl --tlsv1.2 https://github.com/cmatomic/VLCplayer-AppImage/releases/download/3.0.11.1/VLC_media_player-3.0.11.1-x86_64.AppImage -L -o appimage
|
||||
curl --tlsv1.2 "${vlc_url}" -L -o appimage
|
||||
chmod +x appimage
|
||||
./appimage --appimage-extract
|
||||
cp -r squashfs-root/usr/lib/* $vlc_dir
|
||||
|
||||
@@ -9,7 +9,9 @@ if [ "$ARCH" == "arm64" ]; then
|
||||
else
|
||||
vlc_arch=intel64
|
||||
fi
|
||||
vlc_version=3.0.19
|
||||
|
||||
vlc_tag='v3.0.21-1'
|
||||
vlc_url="https://github.com/simplex-chat/vlc/releases/download/${vlc_tag}/vlc-macos-${ARCH}.zip"
|
||||
|
||||
function readlink() {
|
||||
echo "$(cd "$(dirname "$1")"; pwd -P)"
|
||||
@@ -23,7 +25,7 @@ mkdir -p $vlc_dir/vlc || exit 0
|
||||
cd /tmp
|
||||
mkdir tmp 2>/dev/null || true
|
||||
cd tmp
|
||||
curl --tlsv1.2 https://github.com/simplex-chat/vlc/releases/download/v$vlc_version/vlc-macos-$ARCH.zip -L -o vlc
|
||||
curl --tlsv1.2 "${vlc_url}" -L -o vlc
|
||||
unzip -oqq vlc
|
||||
install_name_tool -add_rpath "@loader_path/VLC.app/Contents/MacOS/lib" vlc-cache-gen
|
||||
cd VLC.app/Contents/MacOS/lib
|
||||
|
||||
@@ -10,10 +10,13 @@ vlc_dir=$root_dir/apps/multiplatform/common/src/commonMain/cpp/desktop/libs/wind
|
||||
rm -rf $vlc_dir
|
||||
mkdir -p $vlc_dir/vlc || exit 0
|
||||
|
||||
vlc_tag='v3.0.21-1'
|
||||
vlc_url="https://github.com/simplex-chat/vlc/releases/download/${vlc_tag}/vlc-win-x86_64.zip"
|
||||
|
||||
cd /tmp
|
||||
mkdir tmp 2>/dev/null || true
|
||||
cd tmp
|
||||
curl --tlsv1.2 https://irltoolkit.mm.fcix.net/videolan-ftp/vlc/3.0.18/win64/vlc-3.0.18-win64.zip -L -o vlc
|
||||
curl --tlsv1.2 "${vlc_url}" -L -o vlc
|
||||
$WINDIR\\System32\\tar.exe -xf vlc
|
||||
cd vlc-*
|
||||
# Setting the same date as the date that will be on the file after extraction from JAR to make VLC cache checker happy
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"https://github.com/simplex-chat/simplexmq.git"."d352d518c2b3a42bc7a298954dde799422e1457f" = "1rha84pfpaqx3mf218szkfra334vhijqf17hanxqmp1sicfbf1x3";
|
||||
"https://github.com/simplex-chat/simplexmq.git"."4c33d8ac43874660c342c00cb078bd3814d5d9eb" = "0223qr6vz3vigcx9279kmfxjwb7vwfsqgd7qz271wz86sfxg9hip";
|
||||
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
|
||||
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
|
||||
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
|
||||
|
||||
+1
-1
@@ -256,6 +256,7 @@ library
|
||||
, constraints >=0.12 && <0.14
|
||||
, containers ==0.6.*
|
||||
, crypton ==0.34.*
|
||||
, crypton-x509 ==1.7.*
|
||||
, data-default ==0.7.*
|
||||
, directory ==1.3.*
|
||||
, email-validate ==2.3.*
|
||||
@@ -271,7 +272,6 @@ library
|
||||
, optparse-applicative >=0.15 && <0.17
|
||||
, random >=1.1 && <1.3
|
||||
, record-hasfield ==1.0.*
|
||||
, scientific ==0.3.7.*
|
||||
, simple-logger ==0.1.*
|
||||
, simplexmq >=6.3
|
||||
, socks ==0.6.*
|
||||
|
||||
@@ -44,6 +44,7 @@ import Simplex.Messaging.Agent.Env.SQLite (AgentConfig (..), InitialAgentServers
|
||||
import Simplex.Messaging.Agent.Protocol
|
||||
import Simplex.Messaging.Agent.Store.Common (DBStore (dbNew))
|
||||
import qualified Simplex.Messaging.Agent.Store.DB as DB
|
||||
import Simplex.Messaging.Agent.Store.Entity
|
||||
import Simplex.Messaging.Agent.Store.Shared (MigrationConfirmation (..), MigrationError)
|
||||
import Simplex.Messaging.Client (defaultNetworkConfig)
|
||||
import qualified Simplex.Messaging.Crypto as C
|
||||
|
||||
@@ -87,7 +87,7 @@ import Simplex.Messaging.Notifications.Protocol (DeviceToken (..), NtfTknStatus)
|
||||
import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, enumJSON, parseAll, parseString, sumTypeJSON)
|
||||
import Simplex.Messaging.Protocol (AProtoServerWithAuth, AProtocolType (..), MsgId, NMsgMeta (..), NtfServer, ProtocolType (..), QueueId, SMPMsgMeta (..), SubscriptionMode (..), XFTPServer)
|
||||
import Simplex.Messaging.TMap (TMap)
|
||||
import Simplex.Messaging.Transport (TLS, simplexMQVersion)
|
||||
import Simplex.Messaging.Transport (TLS, TransportPeer (..), simplexMQVersion)
|
||||
import Simplex.Messaging.Transport.Client (SocksProxyWithAuth, TransportHost)
|
||||
import Simplex.Messaging.Util (allFinally, catchAllErrors, catchAllErrors', tryAllErrors, tryAllErrors', (<$$>))
|
||||
import Simplex.RemoteControl.Client
|
||||
@@ -373,6 +373,7 @@ data ChatCommand
|
||||
| APIGroupLinkMemberRole GroupId GroupMemberRole
|
||||
| APIDeleteGroupLink GroupId
|
||||
| APIGetGroupLink GroupId
|
||||
| APIAddGroupShortLink GroupId
|
||||
| APICreateMemberContact GroupId GroupMemberId
|
||||
| APISendMemberContactInvitation {contactId :: ContactId, msgContent_ :: Maybe MsgContent}
|
||||
| GetUserProtoServers AProtocolType
|
||||
@@ -461,6 +462,7 @@ data ChatCommand
|
||||
| DeleteMyAddress
|
||||
| APIShowMyAddress UserId
|
||||
| ShowMyAddress
|
||||
| APIAddMyAddressShortLink UserId
|
||||
| APISetProfileAddress UserId Bool
|
||||
| SetProfileAddress Bool
|
||||
| APIAddressAutoAccept UserId (Maybe AutoAccept)
|
||||
@@ -854,6 +856,7 @@ data ChatEvent
|
||||
| CEvtChatErrors {chatErrors :: [ChatError]}
|
||||
| CEvtTimedAction {action :: String, durationMilliseconds :: Int64}
|
||||
| CEvtTerminalEvent TerminalEvent
|
||||
| CEvtCustomChatEvent {user_ :: Maybe User, response :: Text}
|
||||
deriving (Show)
|
||||
|
||||
data TerminalEvent
|
||||
@@ -1412,7 +1415,7 @@ data RemoteCtrlSession
|
||||
{ remoteCtrlId_ :: Maybe RemoteCtrlId,
|
||||
ctrlDeviceName :: Text,
|
||||
rcsClient :: RCCtrlClient,
|
||||
tls :: TLS,
|
||||
tls :: TLS 'TClient,
|
||||
sessionCode :: Text,
|
||||
rcsWaitSession :: Async (),
|
||||
rcsWaitConfirmation :: TMVar (Either RCErrorType (RCCtrlSession, RCCtrlPairing))
|
||||
@@ -1420,7 +1423,7 @@ data RemoteCtrlSession
|
||||
| RCSessionConnected
|
||||
{ remoteCtrlId :: RemoteCtrlId,
|
||||
rcsClient :: RCCtrlClient,
|
||||
tls :: TLS,
|
||||
tls :: TLS 'TClient,
|
||||
rcsSession :: RCCtrlSession,
|
||||
http2Server :: Async (),
|
||||
remoteOutputQ :: TBQueue (Either ChatError ChatEvent)
|
||||
|
||||
@@ -88,6 +88,7 @@ import Simplex.FileTransfer.Description (FileDescriptionURI (..), maxFileSize, m
|
||||
import Simplex.Messaging.Agent as Agent
|
||||
import Simplex.Messaging.Agent.Env.SQLite (ServerCfg (..), ServerRoles (..), allRoles)
|
||||
import Simplex.Messaging.Agent.Protocol
|
||||
import Simplex.Messaging.Agent.Store.Entity
|
||||
import Simplex.Messaging.Agent.Store.Interface (execSQL)
|
||||
import Simplex.Messaging.Agent.Store.Shared (upMigration)
|
||||
import qualified Simplex.Messaging.Agent.Store.DB as DB
|
||||
@@ -197,7 +198,7 @@ startChatController mainApp enableSndFiles = do
|
||||
startExpireCIThread user
|
||||
setExpireCIFlag user True
|
||||
where
|
||||
shouldExpireChats =
|
||||
shouldExpireChats =
|
||||
fmap (fromRight False) $ runExceptT $ withStore' $ \db -> do
|
||||
ttl <- getChatItemTTL db user
|
||||
ttlCount <- getChatTTLCount db user
|
||||
@@ -1796,9 +1797,9 @@ processChatCommand' vr = \case
|
||||
CreateMyAddress short -> withUser $ \User {userId} ->
|
||||
processChatCommand $ APICreateMyAddress userId short
|
||||
APIDeleteMyAddress userId -> withUserId userId $ \user@User {profile = p} -> do
|
||||
conns <- withFastStore $ \db -> getUserAddressConnections db vr user
|
||||
conn <- withFastStore $ \db -> getUserAddressConnection db vr user
|
||||
withChatLock "deleteMyAddress" $ do
|
||||
deleteAgentConnectionsAsync $ map aConnId conns
|
||||
deleteAgentConnectionAsync $ aConnId conn
|
||||
withFastStore' (`deleteUserAddress` user)
|
||||
let p' = (fromLocalProfile p :: Profile) {contactLink = Nothing}
|
||||
r <- updateProfile_ user p' $ withFastStore' $ \db -> setUserProfileContactLink db user Nothing
|
||||
@@ -1812,6 +1813,17 @@ processChatCommand' vr = \case
|
||||
CRUserContactLink user <$> withFastStore (`getUserAddress` user)
|
||||
ShowMyAddress -> withUser' $ \User {userId} ->
|
||||
processChatCommand $ APIShowMyAddress userId
|
||||
APIAddMyAddressShortLink userId -> withUserId' userId $ \user -> do
|
||||
(ucl@UserContactLink {connLinkContact = CCLink connFullLink sLnk_}, conn) <-
|
||||
withFastStore $ \db -> (,) <$> getUserAddress db user <*> getUserAddressConnection db vr user
|
||||
when (isJust sLnk_) $ throwCmdError "address already has short link"
|
||||
sLnk <- shortenShortLink' =<< withAgent (\a -> setConnShortLink a (aConnId conn) SCMContact "" Nothing)
|
||||
case entityId conn of
|
||||
Just uclId -> do
|
||||
withFastStore' $ \db -> setUserContactLinkShortLink db uclId sLnk
|
||||
let ucl' = (ucl :: UserContactLink) {connLinkContact = CCLink connFullLink (Just sLnk)}
|
||||
pure $ CRUserContactLink user ucl'
|
||||
Nothing -> throwChatError $ CEException "no user contact link id"
|
||||
APISetProfileAddress userId False -> withUserId userId $ \user@User {profile = p} -> do
|
||||
let p' = (fromLocalProfile p :: Profile) {contactLink = Nothing}
|
||||
updateProfile_ user p' $ withFastStore' $ \db -> setUserProfileContactLink db user Nothing
|
||||
@@ -2390,7 +2402,7 @@ processChatCommand' vr = \case
|
||||
pure $ CRGroupLinkCreated user gInfo ccLink' mRole
|
||||
APIGroupLinkMemberRole groupId mRole' -> withUser $ \user -> withGroupLock "groupLinkMemberRole" groupId $ do
|
||||
gInfo <- withFastStore $ \db -> getGroupInfo db vr user groupId
|
||||
(groupLinkId, groupLink, mRole) <- withFastStore $ \db -> getGroupLink db user gInfo
|
||||
(groupLinkId, groupLink, _, mRole) <- withFastStore $ \db -> getGroupLink db user gInfo
|
||||
assertUserGroupRole gInfo GRAdmin
|
||||
when (mRole' > GRMember) $ throwChatError $ CEGroupMemberInitialRole gInfo mRole'
|
||||
when (mRole' /= mRole) $ withFastStore' $ \db -> setGroupLinkMemberRole db user groupLinkId mRole'
|
||||
@@ -2401,8 +2413,20 @@ processChatCommand' vr = \case
|
||||
pure $ CRGroupLinkDeleted user gInfo
|
||||
APIGetGroupLink groupId -> withUser $ \user -> do
|
||||
gInfo <- withFastStore $ \db -> getGroupInfo db vr user groupId
|
||||
(_, groupLink, mRole) <- withFastStore $ \db -> getGroupLink db user gInfo
|
||||
(_, groupLink, _, mRole) <- withFastStore $ \db -> getGroupLink db user gInfo
|
||||
pure $ CRGroupLink user gInfo groupLink mRole
|
||||
APIAddGroupShortLink groupId -> withUser $ \user -> do
|
||||
(gInfo, (uclId, _gLink@(CCLink connFullLink sLnk_), gLinkId, mRole), conn) <- withFastStore $ \db -> do
|
||||
gInfo <- getGroupInfo db vr user groupId
|
||||
gLink <- getGroupLink db user gInfo
|
||||
conn <- getGroupLinkConnection db vr user gInfo
|
||||
pure (gInfo, gLink, conn)
|
||||
when (isJust sLnk_) $ throwCmdError "group link already has short link"
|
||||
let crClientData = encodeJSON $ CRDataGroup gLinkId
|
||||
sLnk <- shortenShortLink' =<< toShortGroupLink <$> withAgent (\a -> setConnShortLink a (aConnId conn) SCMContact "" (Just crClientData))
|
||||
withFastStore' $ \db -> setUserContactLinkShortLink db uclId sLnk
|
||||
let groupLink' = CCLink connFullLink (Just sLnk)
|
||||
pure $ CRGroupLink user gInfo groupLink' mRole
|
||||
APICreateMemberContact gId gMemberId -> withUser $ \user -> do
|
||||
(g, m) <- withFastStore $ \db -> (,) <$> getGroupInfo db vr user gId <*> getGroupMember db vr user gId gMemberId
|
||||
assertUserGroupRole g GRAuthor
|
||||
@@ -3273,13 +3297,14 @@ processChatCommand' vr = \case
|
||||
CSLContact _ ct srv linkKey -> CSLContact SLSServer ct srv linkKey
|
||||
restoreShortLink' l = (`restoreShortLink` l) <$> asks (shortLinkPresetServers . config)
|
||||
shortLinkUserData short = if short then Just "" else Nothing
|
||||
shortenShortLink' :: ConnShortLink m -> CM (ConnShortLink m)
|
||||
shortenShortLink' l = (`shortenShortLink` l) <$> asks (shortLinkPresetServers . config)
|
||||
shortenCreatedLink :: CreatedConnLink m -> CM (CreatedConnLink m)
|
||||
shortenCreatedLink (CCLink cReq sLnk) = CCLink cReq <$> mapM (\l -> (`shortenShortLink` l) <$> asks (shortLinkPresetServers . config)) sLnk
|
||||
shortenCreatedLink (CCLink cReq sLnk) = CCLink cReq <$> mapM shortenShortLink' sLnk
|
||||
createdGroupLink :: CreatedLinkContact -> CreatedLinkContact
|
||||
createdGroupLink (CCLink cReq shortLink) = CCLink cReq (toGroupLink <$> shortLink)
|
||||
where
|
||||
toGroupLink :: ShortLinkContact -> ShortLinkContact
|
||||
toGroupLink (CSLContact sch _ srv k) = CSLContact sch CCTGroup srv k
|
||||
createdGroupLink (CCLink cReq shortLink) = CCLink cReq (toShortGroupLink <$> shortLink)
|
||||
toShortGroupLink :: ShortLinkContact -> ShortLinkContact
|
||||
toShortGroupLink (CSLContact sch _ srv k) = CSLContact sch CCTGroup srv k
|
||||
updateCIGroupInvitationStatus :: User -> GroupInfo -> CIGroupInvitationStatus -> CM ()
|
||||
updateCIGroupInvitationStatus user GroupInfo {groupId} newStatus = do
|
||||
AChatItem _ _ cInfo ChatItem {content, meta = CIMeta {itemId}} <- withFastStore $ \db -> getChatItemByGroupId db vr user groupId
|
||||
@@ -3659,7 +3684,7 @@ startExpireCIThread user@User {userId} = do
|
||||
liftIO $ threadDelay' interval
|
||||
|
||||
setChatItemsExpiration :: User -> Int64 -> Int -> CM' ()
|
||||
setChatItemsExpiration user newTTL ttlCount
|
||||
setChatItemsExpiration user newTTL ttlCount
|
||||
| newTTL > 0 || ttlCount > 0 = do
|
||||
startExpireCIThread user
|
||||
whenM chatStarted $ setExpireCIFlag user True
|
||||
@@ -4222,6 +4247,7 @@ chatCommandP =
|
||||
"/_set link role #" *> (APIGroupLinkMemberRole <$> A.decimal <*> memberRole),
|
||||
"/_delete link #" *> (APIDeleteGroupLink <$> A.decimal),
|
||||
"/_get link #" *> (APIGetGroupLink <$> A.decimal),
|
||||
"/_short link #" *> (APIAddGroupShortLink <$> A.decimal),
|
||||
"/create link #" *> (CreateGroupLink <$> displayNameP <*> (memberRole <|> pure GRMember) <*> shortP),
|
||||
"/set link role #" *> (GroupLinkMemberRole <$> displayNameP <*> memberRole),
|
||||
"/delete link #" *> (DeleteGroupLink <$> displayNameP),
|
||||
@@ -4277,6 +4303,7 @@ chatCommandP =
|
||||
("/delete_address" <|> "/da") $> DeleteMyAddress,
|
||||
"/_show_address " *> (APIShowMyAddress <$> A.decimal),
|
||||
("/show_address" <|> "/sa") $> ShowMyAddress,
|
||||
"/_short_link_address " *> (APIAddMyAddressShortLink <$> A.decimal),
|
||||
"/_profile_address " *> (APISetProfileAddress <$> A.decimal <* A.space <*> onOffP),
|
||||
("/profile_address " <|> "/pa ") *> (SetProfileAddress <$> onOffP),
|
||||
"/_auto_accept " *> (APIAddressAutoAccept <$> A.decimal <* A.space <*> autoAcceptP),
|
||||
|
||||
@@ -37,7 +37,6 @@ import qualified Data.List.NonEmpty as L
|
||||
import Data.Map.Strict (Map)
|
||||
import qualified Data.Map.Strict as M
|
||||
import Data.Maybe (fromMaybe, isNothing, mapMaybe)
|
||||
import Data.Scientific (floatingOrInteger)
|
||||
import Data.Set (Set)
|
||||
import qualified Data.Set as S
|
||||
import Data.Text (Text)
|
||||
@@ -46,11 +45,11 @@ import Data.Time (addUTCTime)
|
||||
import Data.Time.Clock (UTCTime, nominalDay)
|
||||
import Language.Haskell.TH.Syntax (lift)
|
||||
import Simplex.Chat.Operators.Conditions
|
||||
import Simplex.Chat.Options.DB (FromField (..), ToField (..))
|
||||
import Simplex.Chat.Types (User)
|
||||
import Simplex.Chat.Types.Util (textParseJSON)
|
||||
import Simplex.Messaging.Agent.Env.SQLite (ServerCfg (..), ServerRoles (..), allRoles)
|
||||
import Simplex.Messaging.Agent.Store.DB (fromTextField_)
|
||||
import Simplex.Messaging.Agent.Store.DB (FromField (..), ToField (..), fromTextField_)
|
||||
import Simplex.Messaging.Agent.Store.Entity
|
||||
import Simplex.Messaging.Encoding.String
|
||||
import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, sumTypeJSON)
|
||||
import Simplex.Messaging.Protocol (AProtocolType (..), ProtoServerWithAuth (..), ProtocolServer (..), ProtocolType (..), ProtocolTypeI, SProtocolType (..), UserProtocol)
|
||||
@@ -69,32 +68,6 @@ usageConditionsText =
|
||||
in [|stripFrontMatter $(lift (safeDecodeUtf8 s))|]
|
||||
)
|
||||
|
||||
data DBStored = DBStored | DBNew
|
||||
|
||||
data SDBStored (s :: DBStored) where
|
||||
SDBStored :: SDBStored 'DBStored
|
||||
SDBNew :: SDBStored 'DBNew
|
||||
|
||||
deriving instance Show (SDBStored s)
|
||||
|
||||
class DBStoredI s where sdbStored :: SDBStored s
|
||||
|
||||
instance DBStoredI 'DBStored where sdbStored = SDBStored
|
||||
|
||||
instance DBStoredI 'DBNew where sdbStored = SDBNew
|
||||
|
||||
data DBEntityId' (s :: DBStored) where
|
||||
DBEntityId :: Int64 -> DBEntityId' 'DBStored
|
||||
DBNewEntity :: DBEntityId' 'DBNew
|
||||
|
||||
deriving instance Show (DBEntityId' s)
|
||||
|
||||
deriving instance Eq (DBEntityId' s)
|
||||
|
||||
type DBEntityId = DBEntityId' 'DBStored
|
||||
|
||||
type DBNewEntity = DBEntityId' 'DBNew
|
||||
|
||||
data OperatorTag = OTSimplex | OTFlux
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
@@ -118,19 +91,6 @@ instance TextEncoding OperatorTag where
|
||||
OTSimplex -> "simplex"
|
||||
OTFlux -> "flux"
|
||||
|
||||
-- this and other types only define instances of serialization for known DB IDs only,
|
||||
-- entities without IDs cannot be serialized to JSON
|
||||
instance FromField DBEntityId
|
||||
#if defined(dbPostgres)
|
||||
where
|
||||
fromField f dat = DBEntityId <$> fromField f dat
|
||||
#else
|
||||
where
|
||||
fromField f = DBEntityId <$> fromField f
|
||||
#endif
|
||||
|
||||
instance ToField DBEntityId where toField (DBEntityId i) = toField i
|
||||
|
||||
data UsageConditions = UsageConditions
|
||||
{ conditionsId :: Int64,
|
||||
conditionsCommit :: Text,
|
||||
@@ -486,25 +446,6 @@ validateUserServers curr others = currUserErrs <> concatMap otherUserErrs others
|
||||
userServers :: (UserServersClass u, UserProtocol p) => SProtocolType p -> [u] -> [AUserServer p]
|
||||
userServers p = map aUserServer' . concatMap (servers' p)
|
||||
|
||||
instance ToJSON (DBEntityId' s) where
|
||||
toEncoding = \case
|
||||
DBEntityId i -> toEncoding i
|
||||
DBNewEntity -> JE.null_
|
||||
toJSON = \case
|
||||
DBEntityId i -> toJSON i
|
||||
DBNewEntity -> J.Null
|
||||
|
||||
instance DBStoredI s => FromJSON (DBEntityId' s) where
|
||||
parseJSON v = case (v, sdbStored @s) of
|
||||
(J.Null, SDBNew) -> pure DBNewEntity
|
||||
(J.Number n, SDBStored) -> case floatingOrInteger n of
|
||||
Left (_ :: Double) -> fail "bad DBEntityId"
|
||||
Right i -> pure $ DBEntityId (fromInteger i)
|
||||
_ -> fail "bad DBEntityId"
|
||||
omittedField = case sdbStored @s of
|
||||
SDBStored -> Nothing
|
||||
SDBNew -> Just DBNewEntity
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''UsageConditions)
|
||||
|
||||
$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "CA") ''ConditionsAcceptance)
|
||||
|
||||
@@ -9,6 +9,7 @@ import Data.List.NonEmpty (NonEmpty)
|
||||
import qualified Data.List.NonEmpty as L
|
||||
import Simplex.Chat.Operators
|
||||
import Simplex.Messaging.Agent.Env.SQLite (ServerRoles (..), allRoles)
|
||||
import Simplex.Messaging.Agent.Store.Entity
|
||||
import Simplex.Messaging.Protocol (ProtocolType (..), SMPServer)
|
||||
|
||||
operatorSimpleXChat :: NewServerOperator
|
||||
|
||||
@@ -58,7 +58,7 @@ import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..))
|
||||
import qualified Simplex.Messaging.Crypto.File as CF
|
||||
import Simplex.Messaging.Encoding.String (StrEncoding (..))
|
||||
import qualified Simplex.Messaging.TMap as TM
|
||||
import Simplex.Messaging.Transport (TLS, closeConnection, tlsUniq)
|
||||
import Simplex.Messaging.Transport (TLS, TransportPeer (..), closeConnection, tlsUniq)
|
||||
import Simplex.Messaging.Transport.HTTP2.Client (HTTP2ClientError, closeHTTP2Client)
|
||||
import Simplex.Messaging.Transport.HTTP2.Server (HTTP2Request (..))
|
||||
import Simplex.Messaging.Util
|
||||
@@ -184,7 +184,7 @@ startRemoteHost rh_ rcAddrPrefs_ port_ = do
|
||||
action `catchChatError` \err -> do
|
||||
logError $ "startRemoteHost.waitForHostSession crashed: " <> tshow err
|
||||
readTVarIO rhKeyVar >>= cancelRemoteHostSession (Just (sessSeq, RHSRCrashed err))
|
||||
waitForHostSession :: Maybe RemoteHostInfo -> RHKey -> SessionSeq -> Maybe RCCtrlAddress -> TVar RHKey -> RCStepTMVar (ByteString, TLS, RCStepTMVar (RCHostSession, RCHostHello, RCHostPairing)) -> CM ()
|
||||
waitForHostSession :: Maybe RemoteHostInfo -> RHKey -> SessionSeq -> Maybe RCCtrlAddress -> TVar RHKey -> RCStepTMVar (ByteString, TLS 'TServer, RCStepTMVar (RCHostSession, RCHostHello, RCHostPairing)) -> CM ()
|
||||
waitForHostSession remoteHost_ rhKey sseq rcAddr_ rhKeyVar vars = do
|
||||
(sessId, tls, vars') <- timeoutThrow (ChatErrorRemoteHost rhKey RHETimeout) 60000000 $ takeRCStep vars
|
||||
let sessionCode = verificationCode sessId
|
||||
@@ -474,7 +474,7 @@ connectRemoteCtrl verifiedInv@(RCVerifiedInvitation inv@RCInvitation {ca, app})
|
||||
where
|
||||
validateRemoteCtrl RCInvitation {idkey} RemoteCtrl {ctrlPairing = RCCtrlPairing {idPubKey}} =
|
||||
unless (idkey == idPubKey) $ throwError $ ChatErrorRemoteCtrl $ RCEProtocolError $ PRERemoteControl RCEIdentity
|
||||
waitForCtrlSession :: Maybe RemoteCtrl -> Text -> RCCtrlClient -> RCStepTMVar (ByteString, TLS, RCStepTMVar (RCCtrlSession, RCCtrlPairing)) -> CM ()
|
||||
waitForCtrlSession :: Maybe RemoteCtrl -> Text -> RCCtrlClient -> RCStepTMVar (ByteString, TLS 'TClient, RCStepTMVar (RCCtrlSession, RCCtrlPairing)) -> CM ()
|
||||
waitForCtrlSession rc_ ctrlName rcsClient vars = do
|
||||
(uniq, tls, rcsWaitConfirmation) <- timeoutThrow (ChatErrorRemoteCtrl RCETimeout) networkIOTimeout $ takeRCStep vars
|
||||
let sessionCode = verificationCode uniq
|
||||
|
||||
@@ -8,18 +8,18 @@
|
||||
|
||||
module Simplex.Chat.Remote.RevHTTP where
|
||||
|
||||
import Simplex.Messaging.Transport (TLS)
|
||||
import Simplex.Messaging.Transport (TLS, TransportPeer (..))
|
||||
import Simplex.Messaging.Transport.HTTP2 (defaultHTTP2BufferSize, getHTTP2Body)
|
||||
import Simplex.Messaging.Transport.HTTP2.Client (HTTP2Client, HTTP2ClientError (..), attachHTTP2Client, bodyHeadSize, connTimeout, defaultHTTP2ClientConfig)
|
||||
import Simplex.Messaging.Transport.HTTP2.Server (HTTP2Request (..), runHTTP2ServerWith)
|
||||
import Simplex.RemoteControl.Discovery
|
||||
|
||||
attachRevHTTP2Client :: IO () -> TLS -> IO (Either HTTP2ClientError HTTP2Client)
|
||||
attachRevHTTP2Client :: IO () -> TLS 'TServer -> IO (Either HTTP2ClientError HTTP2Client)
|
||||
attachRevHTTP2Client disconnected = attachHTTP2Client config ANY_ADDR_V4 "0" disconnected defaultHTTP2BufferSize
|
||||
where
|
||||
config = defaultHTTP2ClientConfig {bodyHeadSize = doNotPrefetchHead, connTimeout = maxBound}
|
||||
|
||||
attachHTTP2Server :: TLS -> (HTTP2Request -> IO ()) -> IO ()
|
||||
attachHTTP2Server :: TLS 'TClient -> (HTTP2Request -> IO ()) -> IO ()
|
||||
attachHTTP2Server tls processRequest =
|
||||
runHTTP2ServerWith defaultHTTP2BufferSize ($ tls) $ \sessionId sessionALPN r sendResponse -> do
|
||||
reqBody <- getHTTP2Body r doNotPrefetchHead
|
||||
|
||||
@@ -25,7 +25,7 @@ import Simplex.Chat.Types (verificationCode)
|
||||
import qualified Simplex.Messaging.Crypto as C
|
||||
import Simplex.Messaging.Crypto.File (CryptoFile)
|
||||
import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, enumJSON, sumTypeJSON)
|
||||
import Simplex.Messaging.Transport (TLS (..), TSbChainKeys (..))
|
||||
import Simplex.Messaging.Transport (TLS (..), TSbChainKeys (..), TransportPeer (..))
|
||||
import Simplex.Messaging.Transport.HTTP2.Client (HTTP2Client)
|
||||
import qualified Simplex.Messaging.TMap as TM
|
||||
import Simplex.RemoteControl.Client
|
||||
@@ -102,11 +102,11 @@ data RHPendingSession = RHPendingSession
|
||||
data RemoteHostSession
|
||||
= RHSessionStarting
|
||||
| RHSessionConnecting {invitation :: Text, rhPendingSession :: RHPendingSession}
|
||||
| RHSessionPendingConfirmation {sessionCode :: Text, tls :: TLS, rhPendingSession :: RHPendingSession}
|
||||
| RHSessionConfirmed {tls :: TLS, rhPendingSession :: RHPendingSession}
|
||||
| RHSessionPendingConfirmation {sessionCode :: Text, tls :: TLS 'TServer, rhPendingSession :: RHPendingSession}
|
||||
| RHSessionConfirmed {tls :: TLS 'TServer, rhPendingSession :: RHPendingSession}
|
||||
| RHSessionConnected
|
||||
{ rchClient :: RCHostClient,
|
||||
tls :: TLS,
|
||||
tls :: TLS 'TServer,
|
||||
rhClient :: RemoteHostClient,
|
||||
pollAction :: Async (),
|
||||
storePath :: FilePath
|
||||
@@ -128,7 +128,7 @@ rhsSessionState = \case
|
||||
RHSessionConfirmed {tls} -> RHSConfirmed {sessionCode = tlsSessionCode tls}
|
||||
RHSessionConnected {tls} -> RHSConnected {sessionCode = tlsSessionCode tls}
|
||||
|
||||
tlsSessionCode :: TLS -> Text
|
||||
tlsSessionCode :: TLS p -> Text
|
||||
tlsSessionCode = verificationCode . tlsUniq
|
||||
|
||||
data RemoteProtocolError
|
||||
|
||||
@@ -256,12 +256,12 @@ deleteGroupLink db User {userId} GroupInfo {groupId} = do
|
||||
(userId, groupId)
|
||||
DB.execute db "DELETE FROM user_contact_links WHERE user_id = ? AND group_id = ?" (userId, groupId)
|
||||
|
||||
getGroupLink :: DB.Connection -> User -> GroupInfo -> ExceptT StoreError IO (Int64, CreatedLinkContact, GroupMemberRole)
|
||||
getGroupLink :: DB.Connection -> User -> GroupInfo -> ExceptT StoreError IO (Int64, CreatedLinkContact, GroupLinkId, GroupMemberRole)
|
||||
getGroupLink db User {userId} gInfo@GroupInfo {groupId} =
|
||||
ExceptT . firstRow groupLink (SEGroupLinkNotFound gInfo) $
|
||||
DB.query db "SELECT user_contact_link_id, conn_req_contact, short_link_contact, group_link_member_role FROM user_contact_links WHERE user_id = ? AND group_id = ? LIMIT 1" (userId, groupId)
|
||||
DB.query db "SELECT user_contact_link_id, conn_req_contact, short_link_contact, group_link_id, group_link_member_role FROM user_contact_links WHERE user_id = ? AND group_id = ? LIMIT 1" (userId, groupId)
|
||||
where
|
||||
groupLink (linkId, cReq, shortLink, mRole_) = (linkId, CCLink cReq shortLink, fromMaybe GRMember mRole_)
|
||||
groupLink (linkId, cReq, shortLink, gLinkId, mRole_) = (linkId, CCLink cReq shortLink, gLinkId, fromMaybe GRMember mRole_)
|
||||
|
||||
getGroupLinkId :: DB.Connection -> User -> GroupInfo -> IO (Maybe GroupLinkId)
|
||||
getGroupLinkId db User {userId} GroupInfo {groupId} =
|
||||
|
||||
@@ -43,7 +43,7 @@ module Simplex.Chat.Store.Profiles
|
||||
setUserProfileContactLink,
|
||||
getUserContactProfiles,
|
||||
createUserContactLink,
|
||||
getUserAddressConnections,
|
||||
getUserAddressConnection,
|
||||
getUserContactLinks,
|
||||
deleteUserAddress,
|
||||
getUserAddress,
|
||||
@@ -51,6 +51,7 @@ module Simplex.Chat.Store.Profiles
|
||||
getGroupLinkInfo,
|
||||
getUserContactLinkByConnReq,
|
||||
getUserContactLinkViaShortLink,
|
||||
setUserContactLinkShortLink,
|
||||
getContactWithoutConnViaAddress,
|
||||
updateUserAddressAutoAccept,
|
||||
getProtocolServers,
|
||||
@@ -110,6 +111,7 @@ import qualified Simplex.Messaging.Crypto.Ratchet as CR
|
||||
import Simplex.Messaging.Encoding.String
|
||||
import Simplex.Messaging.Parsers (defaultJSON)
|
||||
import Simplex.Messaging.Protocol (BasicAuth (..), ProtoServerWithAuth (..), ProtocolServer (..), ProtocolType (..), ProtocolTypeI (..), SProtocolType (..), SubscriptionMode)
|
||||
import Simplex.Messaging.Agent.Store.Entity
|
||||
import Simplex.Messaging.Transport.Client (TransportHost)
|
||||
import Simplex.Messaging.Util (eitherToMaybe, safeDecodeUtf8)
|
||||
#if defined(dbPostgres)
|
||||
@@ -363,26 +365,21 @@ createUserContactLink db User {userId} agentConnId (CCLink cReq shortLink) subMo
|
||||
userContactLinkId <- insertedRowId db
|
||||
void $ createConnection_ db userId ConnUserContact (Just userContactLinkId) agentConnId ConnNew initialChatVersion chatInitialVRange Nothing Nothing Nothing 0 currentTs subMode CR.PQSupportOff
|
||||
|
||||
getUserAddressConnections :: DB.Connection -> VersionRangeChat -> User -> ExceptT StoreError IO [Connection]
|
||||
getUserAddressConnections db vr User {userId} = do
|
||||
cs <- liftIO getUserAddressConnections_
|
||||
if null cs then throwError SEUserContactLinkNotFound else pure cs
|
||||
where
|
||||
getUserAddressConnections_ :: IO [Connection]
|
||||
getUserAddressConnections_ =
|
||||
map (toConnection vr)
|
||||
<$> DB.query
|
||||
db
|
||||
[sql|
|
||||
SELECT c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id,
|
||||
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id,
|
||||
c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter,
|
||||
c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version
|
||||
FROM connections c
|
||||
JOIN user_contact_links uc ON c.user_contact_link_id = uc.user_contact_link_id
|
||||
WHERE c.user_id = ? AND uc.user_id = ? AND uc.local_display_name = '' AND uc.group_id IS NULL
|
||||
|]
|
||||
(userId, userId)
|
||||
getUserAddressConnection :: DB.Connection -> VersionRangeChat -> User -> ExceptT StoreError IO Connection
|
||||
getUserAddressConnection db vr User {userId} = do
|
||||
ExceptT . firstRow (toConnection vr) SEUserContactLinkNotFound $
|
||||
DB.query
|
||||
db
|
||||
[sql|
|
||||
SELECT c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id,
|
||||
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id,
|
||||
c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter,
|
||||
c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version
|
||||
FROM connections c
|
||||
JOIN user_contact_links uc ON c.user_contact_link_id = uc.user_contact_link_id
|
||||
WHERE c.user_id = ? AND uc.user_id = ? AND uc.local_display_name = '' AND uc.group_id IS NULL
|
||||
|]
|
||||
(userId, userId)
|
||||
|
||||
getUserContactLinks :: DB.Connection -> VersionRangeChat -> User -> IO [(Connection, UserContact)]
|
||||
getUserContactLinks db vr User {userId} =
|
||||
@@ -504,14 +501,14 @@ toGroupLinkInfo (groupId_, mRole_) =
|
||||
|
||||
getGroupLinkInfo :: DB.Connection -> UserId -> GroupId -> IO (Maybe GroupLinkInfo)
|
||||
getGroupLinkInfo db userId groupId =
|
||||
fmap join $ maybeFirstRow toGroupLinkInfo $
|
||||
fmap join $ maybeFirstRow toGroupLinkInfo $
|
||||
DB.query
|
||||
db
|
||||
[sql|
|
||||
SELECT group_id, group_link_member_role
|
||||
FROM user_contact_links
|
||||
WHERE user_id = ? AND group_id = ?
|
||||
|]
|
||||
|]
|
||||
(userId, groupId)
|
||||
|
||||
getUserContactLinkByConnReq :: DB.Connection -> User -> (ConnReqContact, ConnReqContact) -> IO (Maybe UserContactLink)
|
||||
@@ -531,6 +528,17 @@ userContactLinkQuery =
|
||||
FROM user_contact_links
|
||||
|]
|
||||
|
||||
setUserContactLinkShortLink :: DB.Connection -> Int64 -> ShortLinkContact -> IO ()
|
||||
setUserContactLinkShortLink db userContactLinkId shortLink =
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE user_contact_links
|
||||
SET short_link_contact = ?
|
||||
WHERE user_contact_link_id = ?
|
||||
|]
|
||||
(shortLink, userContactLinkId)
|
||||
|
||||
getContactWithoutConnViaAddress :: DB.Connection -> VersionRangeChat -> User -> (ConnReqContact, ConnReqContact) -> IO (Maybe Contact)
|
||||
getContactWithoutConnViaAddress db vr user@User {userId} (cReqSchema1, cReqSchema2) = do
|
||||
ctId_ <-
|
||||
|
||||
@@ -10,6 +10,7 @@ import Control.Monad.Except
|
||||
import Data.Int (Int64)
|
||||
import Data.Text (Text)
|
||||
import Data.Text.Encoding (decodeASCII, encodeUtf8)
|
||||
import qualified Data.X509 as X
|
||||
import Data.Word (Word16)
|
||||
import Simplex.Chat.Remote.Types
|
||||
import Simplex.Chat.Store.Shared
|
||||
@@ -66,7 +67,7 @@ remoteHostQuery =
|
||||
FROM remote_hosts
|
||||
|]
|
||||
|
||||
toRemoteHost :: (Int64, Text, FilePath, C.APrivateSignKey, C.SignedObject C.Certificate, C.PrivateKeyEd25519, C.KeyHash, C.PublicKeyX25519, Maybe Text, Maybe Text, Maybe Word16) -> RemoteHost
|
||||
toRemoteHost :: (Int64, Text, FilePath, C.APrivateSignKey, C.SignedObject X.Certificate, C.PrivateKeyEd25519, C.KeyHash, C.PublicKeyX25519, Maybe Text, Maybe Text, Maybe Word16) -> RemoteHost
|
||||
toRemoteHost (remoteHostId, hostDeviceName, storePath, caKey, C.SignedObject caCert, idPrivKey, hostFingerprint, hostDhPubKey, ifaceName_, ifaceAddr_, bindPort_) =
|
||||
RemoteHost {remoteHostId, hostDeviceName, storePath, hostPairing, bindAddress_, bindPort_}
|
||||
where
|
||||
@@ -133,7 +134,7 @@ toRemoteCtrl ::
|
||||
( RemoteCtrlId,
|
||||
Text,
|
||||
C.APrivateSignKey,
|
||||
C.SignedObject C.Certificate,
|
||||
C.SignedObject X.Certificate,
|
||||
C.KeyHash,
|
||||
C.PublicKeyEd25519,
|
||||
C.PrivateKeyX25519,
|
||||
|
||||
@@ -501,19 +501,6 @@ Query:
|
||||
Plan:
|
||||
SEARCH messages USING INDEX idx_messages_group_id_shared_msg_id (group_id=? AND shared_msg_id=?)
|
||||
|
||||
Query:
|
||||
SELECT c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id,
|
||||
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id,
|
||||
c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter,
|
||||
c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version
|
||||
FROM connections c
|
||||
JOIN user_contact_links uc ON c.user_contact_link_id = uc.user_contact_link_id
|
||||
WHERE c.user_id = ? AND uc.user_id = ? AND uc.local_display_name = '' AND uc.group_id IS NULL
|
||||
|
||||
Plan:
|
||||
SEARCH uc USING INDEX sqlite_autoindex_user_contact_links_1 (user_id=? AND local_display_name=?)
|
||||
SEARCH c USING INDEX idx_connections_user_contact_link_id (user_contact_link_id=?)
|
||||
|
||||
Query:
|
||||
SELECT chat_item_id, contact_id, group_id, group_scope_tag, group_scope_group_member_id, note_folder_id
|
||||
FROM chat_items
|
||||
@@ -2823,6 +2810,19 @@ Plan:
|
||||
SEARCH uc USING INDEX idx_user_contact_links_group_id (group_id=?)
|
||||
SEARCH c USING INDEX idx_connections_user_contact_link_id (user_contact_link_id=?)
|
||||
|
||||
Query:
|
||||
SELECT c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id,
|
||||
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id,
|
||||
c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter,
|
||||
c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version
|
||||
FROM connections c
|
||||
JOIN user_contact_links uc ON c.user_contact_link_id = uc.user_contact_link_id
|
||||
WHERE c.user_id = ? AND uc.user_id = ? AND uc.local_display_name = '' AND uc.group_id IS NULL
|
||||
|
||||
Plan:
|
||||
SEARCH uc USING INDEX sqlite_autoindex_user_contact_links_1 (user_id=? AND local_display_name=?)
|
||||
SEARCH c USING INDEX idx_connections_user_contact_link_id (user_contact_link_id=?)
|
||||
|
||||
Query:
|
||||
SELECT c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id,
|
||||
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id,
|
||||
@@ -5794,7 +5794,7 @@ Query: SELECT user_contact_link_id FROM contact_requests WHERE contact_request_i
|
||||
Plan:
|
||||
SEARCH contact_requests USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: SELECT user_contact_link_id, conn_req_contact, short_link_contact, group_link_member_role FROM user_contact_links WHERE user_id = ? AND group_id = ? LIMIT 1
|
||||
Query: SELECT user_contact_link_id, conn_req_contact, short_link_contact, group_link_id, group_link_member_role FROM user_contact_links WHERE user_id = ? AND group_id = ? LIMIT 1
|
||||
Plan:
|
||||
SEARCH user_contact_links USING INDEX idx_user_contact_links_group_id (group_id=?)
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ import qualified Simplex.FileTransfer.Transport as XFTP
|
||||
import Simplex.Messaging.Agent.Client (ProtocolTestFailure (..), ProtocolTestStep (..), SubscriptionsInfo (..))
|
||||
import Simplex.Messaging.Agent.Env.SQLite (NetworkConfig (..), ServerRoles (..))
|
||||
import Simplex.Messaging.Agent.Protocol
|
||||
import Simplex.Messaging.Agent.Store.Entity
|
||||
import Simplex.Messaging.Client (SMPProxyFallback, SMPProxyMode (..), SocksMode (..))
|
||||
import qualified Simplex.Messaging.Crypto as C
|
||||
import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..))
|
||||
@@ -532,6 +533,7 @@ chatEventToView hu ChatConfig {logLevel, showReactions, showReceipts, testView}
|
||||
ttyUser u ["sent file " <> sShow fileId <> " (" <> plain fileName <> ") error: " <> sShow e]
|
||||
TERcvFileSubError u RcvFileTransfer {fileId, fileInvitation = FileInvitation {fileName}} e ->
|
||||
ttyUser u ["received file " <> sShow fileId <> " (" <> plain fileName <> ") error: " <> sShow e]
|
||||
CEvtCustomChatEvent u r -> ttyUser' u $ map plain $ T.lines r
|
||||
where
|
||||
ttyUser :: User -> [StyledString] -> [StyledString]
|
||||
ttyUser user@User {showNtfs, activeUser, viewPwdHash} ss
|
||||
|
||||
@@ -23,6 +23,7 @@ import Simplex.Chat.Operators.Presets
|
||||
import Simplex.Chat.Types
|
||||
import Simplex.FileTransfer.Client.Presets (defaultXFTPServers)
|
||||
import Simplex.Messaging.Agent.Env.SQLite (ServerRoles (..), allRoles)
|
||||
import Simplex.Messaging.Agent.Store.Entity
|
||||
import Simplex.Messaging.Protocol
|
||||
import Test.Hspec
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"simplex-explained-tab-2-p-1": "Minden kapcsolathoz két különböző üzenetküldési sorbaállítást használ a különböző kiszolgálókon keresztül történő üzenetküldéshez és -fogadáshoz.",
|
||||
"simplex-explained-tab-2-p-2": "A kiszolgálók csak egyetlen irányba továbbítják az üzeneteket, anélkül, hogy teljes képet kapnának a felhasználók beszélgetéseiről vagy kapcsolatairól.",
|
||||
"simplex-explained-tab-3-p-1": "A kiszolgálók minden egyes üzenetsorbaállításhoz külön névtelen hitelesítő-adatokkal rendelkeznek, és nem tudják, hogy melyik felhasználóhoz tartoznak.",
|
||||
"simplex-explained-tab-3-p-2": "A felhasználók tovább fokozhatják a metaadatok adatvédelmét, ha a Tor segítségével férnek hozzá a kiszolgálókhoz, így megakadályozva az IP-cím szerinti korrelációt.",
|
||||
"simplex-explained-tab-3-p-2": "A felhasználók tovább fokozhatják a metaadatok adatvédelmét, ha a Tor-hálózat használatával férnek hozzá a kiszolgálókhoz, így megakadályozva az IP-cím szerinti korrelációt.",
|
||||
"smp-protocol": "SMP-protokoll",
|
||||
"chat-protocol": "Csevegési protokoll",
|
||||
"donate": "Adományozás",
|
||||
@@ -59,7 +59,7 @@
|
||||
"simplex-private-card-3-point-1": "A kliens és a kiszolgálók közötti kapcsolatokhoz csak az erős algoritmusokkal rendelkező TLS 1.2/1.3 protokollt használja.",
|
||||
"simplex-private-card-3-point-2": "A kiszolgáló ujjlenyomata és a csatornakötés megakadályozza a MITM- és a visszajátszási támadásokat.",
|
||||
"simplex-private-card-3-point-3": "Az újrakapcsolódás le van tiltva a munkamenet elleni támadások megelőzése érdekében.",
|
||||
"simplex-private-card-4-point-1": "Az IP-címe védelme érdekében a kiszolgálókat a Tor hálózaton vagy más átvitelátfedő hálózaton keresztül is elérheti.",
|
||||
"simplex-private-card-4-point-1": "Az IP-címe védelme érdekében a kiszolgálókat a Tor-hálózaton vagy más átvitelátfedő hálózaton keresztül is elérheti.",
|
||||
"simplex-private-card-6-point-1": "Számos kommunikációs hálózat sebezhető a kiszolgálók vagy a hálózat-szolgáltatók MITM-támadásaival szemben.",
|
||||
"simplex-private-card-6-point-2": "Ennek megakadályozása érdekében a SimpleX-alkalmazások egyszeri kulcsokat adnak át sávon kívül, amikor egy címet hivatkozásként vagy QR-kódként oszt meg.",
|
||||
"simplex-private-card-7-point-1": "Az integritás garantálása érdekében az üzenetek sorszámozással vannak ellátva, és tartalmazzák az előző üzenet hasítóértékét.",
|
||||
@@ -87,7 +87,7 @@
|
||||
"simplex-unique-4-overlay-1-title": "Teljesen decentralizált — a SimpleX-hálózat a felhasználóké",
|
||||
"hero-overlay-card-1-p-1": "Sok felhasználó kérdezte: <em>ha a SimpleXnek nincsenek felhasználói azonosítói, honnan tudja, hogy hová kell eljuttatni az üzeneteket?</em>",
|
||||
"hero-overlay-card-1-p-2": "Az üzenetek kézbesítéséhez az összes többi hálózat által használt felhasználói azonosítók helyett a SimpleX az üzenetek sorbaállításához ideiglenes, névtelen, páros azonosítókat használ, külön-külön minden egyes kapcsolathoz — nincsenek hosszú távú azonosítók.",
|
||||
"hero-overlay-card-1-p-4": "Ez a kialakítás megakadályozza a felhasználók metaadatainak kiszivárgását az alkalmazás szintjén. Az adatvédelem további javítása és az IP-cím védelme érdekében az üzenetküldő kiszolgálókhoz Tor hálózaton keresztül is kapcsolódhat.",
|
||||
"hero-overlay-card-1-p-4": "Ez a kialakítás megakadályozza a felhasználók metaadatainak kiszivárgását az alkalmazás szintjén. Az adatvédelem további javítása és az IP-cím védelme érdekében az üzenetküldő kiszolgálókhoz Tor-hálózaton keresztül is kapcsolódhat.",
|
||||
"hero-overlay-card-1-p-5": "Csak a kliensek tárolják a felhasználói profilokat, kapcsolatokat és csoportokat; az üzenetek küldése 2 rétegű végpontok közötti titkosítással történik.",
|
||||
"hero-overlay-card-1-p-6": "További leírást a <a href='https://github.com/simplex-chat/simplexmq/blob/stable/protocol/overview-tjr.md' target='_blank'>SimpleX ismertetőben</a> olvashat.",
|
||||
"hero-overlay-card-2-p-1": "Ha a felhasználók állandó azonosítóval rendelkeznek, még akkor is, ha ez csak egy véletlenszerű szám, például egy munkamenet-azonosító, fennáll annak a veszélye, hogy a szolgáltató vagy egy támadó megfigyelheti, azt hogy hogyan kapcsolódnak a felhasználók egymáshoz, és hány üzenetet küldenek egymásnak.",
|
||||
@@ -114,7 +114,7 @@
|
||||
"privacy-matters-overlay-card-3-p-4": "Nem elég csak egy végpontok között titkosított üzenetváltó-alkalmazást használnunk, mindannyiunknak olyan üzenetváltó-alkalmazásokat kell használnunk, amelyek védik a személyes partnereink magánéletét — akikkel kapcsolatban állunk.",
|
||||
"simplex-unique-overlay-card-1-p-1": "Más üzenetküldő hálózatoktól eltérően a SimpleX <strong>nem rendel azonosítókat a felhasználókhoz</strong>. Nem támaszkodik telefonszámokra, tartomány-alapú címekre (mint az e-mail, XMPP vagy a Matrix), felhasználónevekre, nyilvános kulcsokra vagy akár véletlenszerű számokra a felhasználók azonosításához — a SimpleX-kiszolgálók üzemeltetői nem tudják, hogy hányan használják a kiszolgálóikat.",
|
||||
"simplex-unique-overlay-card-1-p-2": "Az üzenetek kézbesítéséhez a SimpleX az egyirányú üzenet várakoztatást használ <a href='https://csrc.nist.gov/glossary/term/Pairwise_Pseudonymous_Identifier'>páronkénti névtelen címekkel</a>, külön a fogadott és külön az elküldött üzenetek számára, általában különböző kiszolgálókon keresztül.",
|
||||
"simplex-unique-overlay-card-1-p-3": "Ez a kialakítás megvédi annak titkosságát, hogy kivel kommunikál, elrejtve azt a SimpleX-hálózat kiszolgálói és a megfigyelők elől. IP-címének a kiszolgálók elől való elrejtéséhez azt teheti meg, hogy <strong> Toron keresztül kapcsolódik a SimpleX-kiszolgálókhoz</strong>.",
|
||||
"simplex-unique-overlay-card-1-p-3": "Ez a kialakítás védi partnerének adatait, elrejtve azt a SimpleX-hálózat kiszolgálói és a külső megfigyelők elől. Az IP-címe elrejtésének érdekében a<strong>Tor-hálózaton keresztül is kapcsolódhat a SimpleX-kiszolgálókhoz</strong>.",
|
||||
"simplex-unique-overlay-card-2-p-1": "Mivel ön nem rendelkezik azonosítóval a SimpleX-hálózaton, senki sem tud kapcsolatba lépni önnel, hacsak nem oszt meg egy egyszeri vagy ideiglenes felhasználói címet, például QR-kódot vagy hivatkozást.",
|
||||
"simplex-unique-overlay-card-2-p-2": "Még a felhasználói cím használata esetén is, aminek használata nem kötelező – ugyanakkor ez a kéretlen kapcsolatkérelmek küldésére is használható – módosíthatja vagy teljesen törölheti anélkül, hogy elveszítené a meglévő kapcsolatait.",
|
||||
"simplex-unique-overlay-card-3-p-1": "A SimpleX Chat az összes felhasználói adatot kizárólag a klienseken tárolja egy <strong>hordozható titkosított adatbázis-formátumban</strong>, amely exportálható és átvihető bármely más támogatott eszközre.",
|
||||
@@ -256,4 +256,4 @@
|
||||
"stable-and-beta-versions-built-by-developers": "A fejlesztők által készített stabil és béta verziók",
|
||||
"hero-overlay-card-3-p-3": "A Trail of Bits 2024 júliusában ismét auditálta a SimpleX-protokollok kriptográfiai és hálózati komponenseit. <a href=\"/blog/20241014-simplex-network-v6-1-security-review-better-calls-user-experience.html\">További információk</a>.",
|
||||
"docs-dropdown-14": "SimpleX üzleti célra"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@
|
||||
"simplex-network-overlay-card-1-li-6": "Сети P2P могут быть уязвимы для <a href='https://www.usenix.org/conference/woot15/workshop-program/presentation/p2p-file-sharing-hell-exploiting-bittorrent'>DRDoS атаки</a>, когда клиенты могут ретранслировать и увеличивать трафик, что приводит к отказу всей сети. Клиенты SimpleX ретранслируют трафик только из известного соединения и не могут быть использованы злоумышленником для создания трафика во всей сети.",
|
||||
"if-you-already-installed-simplex-chat-for-the-terminal": "Если Вы уже установили SimpleX Chat для терминала",
|
||||
"docs-dropdown-8": "Служба Каталогов SimpleX",
|
||||
"simplex-private-card-1-point-1": "Протокол двойного обновления ключей —<br>\"отрицаемые\" сообщения с идеальной прямой секретностью и восстановлением после взлома",
|
||||
"simplex-private-card-1-point-1": "Протокол двойного обновления ключей —<br>\"отрицаемые\" сообщения с идеальной прямой секретностью и восстановлением после взлома.",
|
||||
"simplex-private-card-8-point-1": "Серверы SimpleX действуют как узлы-миксеры с низкой задержкой — входящие и исходящие сообщения имеют разный порядок.",
|
||||
"simplex-unique-overlay-card-2-p-1": "Поскольку у Вас нет идентификатора в сети SimpleX, никто не сможет связаться с Вами, если Вы сами не предоставите одноразовый или временный адрес в виде QR-кода или ссылки.",
|
||||
"sign-up-to-receive-our-updates": "Подпишитесь на нашу рассылку новостей",
|
||||
|
||||
Reference in New Issue
Block a user