浏览代码

Merge pull request #464 from deltachat/verified_groups

Verified groups
bjoern 5 年之前
父节点
当前提交
e7210b04f1
共有 32 个文件被更改,包括 319 次插入202 次删除
  1. 4 4
      deltachat-ios.xcodeproj/project.pbxproj
  2. 44 10
      deltachat-ios/Controller/GroupMembersViewController.swift
  3. 30 53
      deltachat-ios/Controller/NewChatViewController.swift
  4. 103 22
      deltachat-ios/Controller/NewGroupController.swift
  5. 31 18
      deltachat-ios/Coordinator/AppCoordinator.swift
  6. 12 0
      deltachat-ios/DC/Wrapper.swift
  7. 12 0
      deltachat-ios/Extensions/Extensions.swift
  8. 1 4
      deltachat-ios/az.lproj/Localizable.strings
  9. 1 4
      deltachat-ios/ca.lproj/Localizable.strings
  10. 1 4
      deltachat-ios/da.lproj/Localizable.strings
  11. 4 0
      deltachat-ios/de.lproj/InfoPlist.strings
  12. 4 5
      deltachat-ios/de.lproj/Localizable.strings
  13. 3 1
      deltachat-ios/en.lproj/Localizable.strings
  14. 1 4
      deltachat-ios/es.lproj/Localizable.strings
  15. 1 4
      deltachat-ios/eu.lproj/Localizable.strings
  16. 1 4
      deltachat-ios/fr.lproj/Localizable.strings
  17. 1 4
      deltachat-ios/gl.lproj/Localizable.strings
  18. 1 1
      deltachat-ios/hu.lproj/Localizable.strings
  19. 4 0
      deltachat-ios/it.lproj/InfoPlist.strings
  20. 10 4
      deltachat-ios/it.lproj/Localizable.strings
  21. 3 2
      deltachat-ios/lt.lproj/Localizable.strings
  22. 2 3
      deltachat-ios/nl.lproj/Localizable.strings
  23. 4 0
      deltachat-ios/pl.lproj/InfoPlist.strings
  24. 25 18
      deltachat-ios/pl.lproj/Localizable.strings
  25. 1 4
      deltachat-ios/pt-BR.lproj/Localizable.strings
  26. 1 4
      deltachat-ios/pt-PT.lproj/Localizable.strings
  27. 2 5
      deltachat-ios/ru.lproj/Localizable.strings
  28. 2 3
      deltachat-ios/sq.lproj/Localizable.strings
  29. 6 7
      deltachat-ios/tr.lproj/Localizable.strings
  30. 1 4
      deltachat-ios/uk.lproj/Localizable.strings
  31. 1 1
      deltachat-ios/zh-Hant-TW.lproj/Localizable.strings
  32. 2 5
      deltachat-ios/zh-Hant.lproj/Localizable.strings

+ 4 - 4
deltachat-ios.xcodeproj/project.pbxproj

@@ -92,7 +92,7 @@
 		30C0D49D237C4908008E2A0E /* CertificateCheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C0D49C237C4908008E2A0E /* CertificateCheckController.swift */; };
 		30F9B9EC235F2116006E7ACF /* MessageCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30F9B9EB235F2116006E7ACF /* MessageCounter.swift */; };
 		6795F63A82E94FF7CD2CEC0F /* Pods_deltachat_iosTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F7009234DB9408201A6CDCB /* Pods_deltachat_iosTests.framework */; };
-		7070FB9B2101ECBB000DC258 /* GroupNameController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7070FB9A2101ECBB000DC258 /* GroupNameController.swift */; };
+		7070FB9B2101ECBB000DC258 /* NewGroupController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7070FB9A2101ECBB000DC258 /* NewGroupController.swift */; };
 		7092474120B3869500AF8799 /* ContactDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7092474020B3869500AF8799 /* ContactDetailViewController.swift */; };
 		70B08FCD21073B910097D3EA /* NewGroupMemberChoiceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70B08FCC21073B910097D3EA /* NewGroupMemberChoiceController.swift */; };
 		70B8882E2091B8550074812E /* ContactCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70B8882D2091B8550074812E /* ContactCell.swift */; };
@@ -306,7 +306,7 @@
 		30C0D49C237C4908008E2A0E /* CertificateCheckController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CertificateCheckController.swift; sourceTree = "<group>"; };
 		30F9B9EB235F2116006E7ACF /* MessageCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageCounter.swift; sourceTree = "<group>"; };
 		6241BE1534A653E79AD5D01D /* Pods_deltachat_ios.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_deltachat_ios.framework; sourceTree = BUILT_PRODUCTS_DIR; };
-		7070FB9A2101ECBB000DC258 /* GroupNameController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupNameController.swift; sourceTree = "<group>"; };
+		7070FB9A2101ECBB000DC258 /* NewGroupController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewGroupController.swift; sourceTree = "<group>"; };
 		7092474020B3869500AF8799 /* ContactDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactDetailViewController.swift; sourceTree = "<group>"; };
 		70B08FCC21073B910097D3EA /* NewGroupMemberChoiceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewGroupMemberChoiceController.swift; sourceTree = "<group>"; };
 		70B8882D2091B8550074812E /* ContactCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactCell.swift; sourceTree = "<group>"; };
@@ -676,7 +676,7 @@
 				AEE6EC472283045D00EDC689 /* EditSettingsController.swift */,
 				AE851ACF227DF50900ED86F0 /* GroupChatDetailViewController.swift */,
 				AEE6EC3E2282C59C00EDC689 /* GroupMembersViewController.swift */,
-				7070FB9A2101ECBB000DC258 /* GroupNameController.swift */,
+				7070FB9A2101ECBB000DC258 /* NewGroupController.swift */,
 				AEE6EC402282DF5700EDC689 /* MailboxViewController.swift */,
 				785BE16721E247F1003BE98C /* MessageInfoViewController.swift */,
 				7AE0A5481FC42F65005ECB4B /* NewChatViewController.swift */,
@@ -1044,7 +1044,7 @@
 				AEACE2DF1FB3246400DCDD78 /* Message.swift in Sources */,
 				AE9DAF0F22C278C6004C9591 /* ChatTitleView.swift in Sources */,
 				AE4AEE3522B1030D000AA495 /* PreviewController.swift in Sources */,
-				7070FB9B2101ECBB000DC258 /* GroupNameController.swift in Sources */,
+				7070FB9B2101ECBB000DC258 /* NewGroupController.swift in Sources */,
 				305961EA2346125100C80F33 /* MessageStyle.swift in Sources */,
 				305961F92346125100C80F33 /* MessageLabel.swift in Sources */,
 				305961FA2346125100C80F33 /* MessageReusableView.swift in Sources */,

+ 44 - 10
deltachat-ios/Controller/GroupMembersViewController.swift

@@ -1,17 +1,41 @@
 import UIKit
 
-class NewGroupViewController: GroupMembersViewController {
-    weak var coordinator: NewGroupCoordinator?
+class NewGroupAddMembersViewController: GroupMembersViewController {
+    weak var coordinator: NewGroupAddMembersCoordinator?
+    let dcContext: DcContext
+
+    var onMembersSelected: ((Set<Int>) -> Void)?
+    let isVerifiedGroup: Bool
+
+    private lazy var cancelButton: UIBarButtonItem = {
+        let button = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelButtonPressed))
+        return button
+    }()
+
+   lazy var doneButton: UIBarButtonItem = {
+       let button = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonPressed))
+       return button
+   }()
+
+    init(dcContext: DcContext, preselected: Set<Int>, isVerified: Bool) {
+        self.dcContext = dcContext
+        isVerifiedGroup = isVerified
+        super.init()
+        selectedContactIds = preselected
+    }
+
+    required init?(coder _: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
 
     override func viewDidLoad() {
         super.viewDidLoad()
         title = String.localized("group_add_members")
-        let groupCreationNextButton = UIBarButtonItem(title: String.localized("next"),
-                                                      style: .done,
-                                                      target: self,
-                                                      action: #selector(nextButtonPressed))
-        navigationItem.rightBarButtonItem = groupCreationNextButton
-        contactIds = Utils.getContactIds()
+        navigationItem.rightBarButtonItem = doneButton
+        navigationItem.leftBarButtonItem = cancelButton
+        contactIds = isVerifiedGroup ?
+            dcContext.getContacts(flags: DC_GCL_VERIFIED_ONLY) :
+            dcContext.getContacts(flags: 0)
     }
 
     override func viewWillAppear(_ animated: Bool) {
@@ -22,9 +46,19 @@ class NewGroupViewController: GroupMembersViewController {
         super.didReceiveMemoryWarning()
     }
 
-    @objc func nextButtonPressed() {
-        coordinator?.showGroupNameController(contactIdsForGroup: selectedContactIds)
+    @objc func cancelButtonPressed() {
+        navigationController?.popViewController(animated: true)
     }
+
+    @objc func doneButtonPressed() {
+        if let onMembersSelected = onMembersSelected {
+            selectedContactIds.insert(Int(DC_CONTACT_ID_SELF))
+            onMembersSelected(selectedContactIds)
+        } else {
+            navigationController?.popViewController(animated: true)
+        }
+    }
+
 }
 
 class AddGroupMembersViewController: GroupMembersViewController {

+ 30 - 53
deltachat-ios/Controller/NewChatViewController.swift

@@ -9,8 +9,9 @@ class NewChatViewController: UITableViewController {
 
     private let sectionNew = 0
     private let sectionNewRowNewGroup = 0
-    private let sectionNewRowNewContact = 1
-    private let sectionNewRowCount = 2
+    private let sectionNewRowNewVerifiedGroup = 1
+    private let sectionNewRowNewContact = 2
+    private let sectionNewRowCount = 3
 
     private let sectionImportedContacts = 1
 
@@ -80,6 +81,8 @@ class NewChatViewController: UITableViewController {
         if #available(iOS 11.0, *) {
             navigationItem.hidesSearchBarWhenScrolling = false
         }
+        tableView.register(ActionCell.self, forCellReuseIdentifier: "actionCell")
+        tableView.register(ContactCell.self, forCellReuseIdentifier: "contactCell")
     }
 
     override func viewWillAppear(_ animated: Bool) {
@@ -166,70 +169,43 @@ class NewChatViewController: UITableViewController {
         let row = indexPath.row
 
         if section == sectionNew {
-            if row == sectionNewRowNewGroup {
-                // new group row
-                let cell: UITableViewCell
-                if let c = tableView.dequeueReusableCell(withIdentifier: "newContactCell") {
-                    cell = c
-                } else {
-                    cell = UITableViewCell(style: .default, reuseIdentifier: "newContactCell")
+            let cell = tableView.dequeueReusableCell(withIdentifier: "actionCell", for: indexPath)
+            if let actionCell = cell as? ActionCell {
+                switch row {
+                case sectionNewRowNewGroup:
+                    actionCell.actionTitle = String.localized("menu_new_group")
+                case sectionNewRowNewVerifiedGroup:
+                    actionCell.actionTitle = String.localized("menu_new_verified_group")
+                default:
+                    actionCell.actionTitle = String.localized("menu_new_contact")
                 }
-                cell.textLabel?.text = String.localized("menu_new_group")
-                cell.textLabel?.textColor = view.tintColor
-
-                return cell
-            }
-
-            if row == sectionNewRowNewContact {
-                // new contact row
-                let cell: UITableViewCell
-                if let c = tableView.dequeueReusableCell(withIdentifier: "newContactCell") {
-                    cell = c
-                } else {
-                    cell = UITableViewCell(style: .default, reuseIdentifier: "newContactCell")
-                }
-                cell.textLabel?.text = String.localized("menu_new_contact")
-                cell.textLabel?.textColor = view.tintColor
-
-                return cell
             }
+            return cell
         } else if section == sectionImportedContacts {
             // import device contacts section
             if deviceContactAccessGranted {
-                let cell: ContactCell
-                if let c = tableView.dequeueReusableCell(withIdentifier: "contactCell") as? ContactCell {
-                    cell = c
-                } else {
-                    cell = ContactCell(style: .default, reuseIdentifier: "contactCell")
+                let cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath)
+                if let contactCell = cell as? ContactCell {
+                    let contact: ContactWithSearchResults = contactSearchResultByRow(row)
+                    updateContactCell(cell: contactCell, contactWithHighlight: contact)
                 }
-                let contact: ContactWithSearchResults = contactSearchResultByRow(row)
-                updateContactCell(cell: cell, contactWithHighlight: contact)
                 return cell
             } else {
-                let cell: ActionCell
-                if let c = tableView.dequeueReusableCell(withIdentifier: "actionCell") as? ActionCell {
-                    cell = c
-                } else {
-                    cell = ActionCell(style: .default, reuseIdentifier: "actionCell")
+                let cell = tableView.dequeueReusableCell(withIdentifier: "actionCell", for: indexPath)
+                if let actionCell = cell as? ActionCell {
+                    actionCell.actionTitle = String.localized("import_contacts")
                 }
-                cell.actionTitle = String.localized("import_contacts")
                 return cell
             }
         } else {
             // section contact list if device contacts are not imported
-            let cell: ContactCell
-            if let c = tableView.dequeueReusableCell(withIdentifier: "contactCell") as? ContactCell {
-                cell = c
-            } else {
-                cell = ContactCell(style: .default, reuseIdentifier: "contactCell")
+            let cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath)
+            if let contactCell = cell as? ContactCell {
+                let contact: ContactWithSearchResults = contactSearchResultByRow(row)
+                updateContactCell(cell: contactCell, contactWithHighlight: contact)
             }
-
-            let contact: ContactWithSearchResults = contactSearchResultByRow(row)
-            updateContactCell(cell: cell, contactWithHighlight: contact)
             return cell
         }
-        // will actually never get here but compiler not happy
-        return UITableViewCell(style: .default, reuseIdentifier: "cell")
     }
 
     override func tableView(_: UITableView, didSelectRowAt indexPath: IndexPath) {
@@ -238,9 +214,10 @@ class NewChatViewController: UITableViewController {
 
         if section == sectionNew {
             if row == sectionNewRowNewGroup {
-                coordinator?.showNewGroupController()
-            }
-            if row == sectionNewRowNewContact {
+                coordinator?.showNewGroupController(isVerified: false)
+            } else if row == sectionNewRowNewVerifiedGroup {
+                coordinator?.showNewGroupController(isVerified: true)
+            } else if row == sectionNewRowNewContact {
                 coordinator?.showNewContactController()
             }
         } else if section == sectionImportedContacts {

+ 103 - 22
deltachat-ios/Controller/GroupNameController.swift → deltachat-ios/Controller/NewGroupController.swift

@@ -1,23 +1,31 @@
 import UIKit
 
-class GroupNameController: UITableViewController, MediaPickerDelegate {
+class NewGroupController: UITableViewController, MediaPickerDelegate {
 
-    weak var coordinator: GroupNameCoordinator?
+    weak var coordinator: NewGroupCoordinator?
 
     var groupName: String = ""
+    var groupChatId: Int = 0
 
     var doneButton: UIBarButtonItem!
-    let contactIdsForGroup: Set<Int> // TODO: check if array is sufficient
-    let groupContactIds: [Int]
+    var contactIdsForGroup: Set<Int> // TODO: check if array is sufficient
+    var groupContactIds: [Int]
     var groupImage: UIImage?
+    let isVerifiedGroup: Bool
+    let dcContext: DcContext
 
     private let sectionGroupDetails = 0
     private let sectionGroupDetailsRowAvatar = 0
     private let sectionGroupDetailsRowName = 1
     private let countSectionGroupDetails = 2
+    private let sectionInvite = 1
+    private let sectionInviteRowAddMembers = 0
+    private let sectionInviteRowShowQrCode = 1
+    private lazy var countSectionInvite: Int = 2
+    private let sectionGroupMembers = 2
 
     lazy var groupNameCell: TextFieldCell = {
-        let cell = TextFieldCell(description: String.localized("group_name"), placeholder: String.localized("menu_edit_group_name"))
+        let cell = TextFieldCell(description: String.localized("group_name"), placeholder: String.localized("group_name"))
         cell.onTextFieldChange = self.updateGroupName
         return cell
     }()
@@ -27,11 +35,15 @@ class GroupNameController: UITableViewController, MediaPickerDelegate {
         cell.hintLabel.text = String.localized("group_avatar")
         cell.onAvatarTapped = onAvatarTapped
         return cell
-    }()    
+    }()
+
+    var qrInviteCodeCell: ActionCell?
 
-    init(contactIdsForGroup: Set<Int>) {
-        self.contactIdsForGroup = contactIdsForGroup
-        groupContactIds = Array(contactIdsForGroup)
+    init(dcContext: DcContext, isVerified: Bool) {
+        self.contactIdsForGroup = [Int(DC_CONTACT_ID_SELF)]
+        self.groupContactIds = Array(contactIdsForGroup)
+        self.isVerifiedGroup = isVerified
+        self.dcContext = dcContext
         super.init(style: .grouped)
     }
 
@@ -41,24 +53,38 @@ class GroupNameController: UITableViewController, MediaPickerDelegate {
 
     override func viewDidLoad() {
         super.viewDidLoad()
-        title = String.localized("menu_new_group")
+        title = isVerifiedGroup ? String.localized("menu_new_verified_group") : String.localized("menu_new_group")
         doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonPressed))
         navigationItem.rightBarButtonItem = doneButton
         tableView.bounces = false
         doneButton.isEnabled = false
         tableView.register(ContactCell.self, forCellReuseIdentifier: "contactCell")
+        tableView.register(ActionCell.self, forCellReuseIdentifier: "actionCell")
+        self.hideKeyboardOnTap() 
+    }
+
+    override func viewWillAppear(_ animated: Bool) {
+        if groupChatId != 0 {
+            let chat = DcChat.init(id: groupChatId)
+            updateGroupContactIds(Set(chat.contactIds))
+        }
     }
 
     @objc func doneButtonPressed() {
-        let groupChatId = dc_create_group_chat(mailboxPointer, 0, groupName)
+        if groupChatId == 0 {
+            groupChatId = dcContext.createGroupChat(verified: isVerifiedGroup, name: groupName)
+        } else {
+            _ = dcContext.setChatName(chatId: groupChatId, name: groupName)
+        }
+
         for contactId in contactIdsForGroup {
-            let success = dc_add_contact_to_chat(mailboxPointer, groupChatId, UInt32(contactId))
+            let success = dcContext.addContactToChat(chatId: groupChatId, contactId: contactId)
 
             if let groupImage = groupImage, let dcContext = coordinator?.dcContext {
                     AvatarHelper.saveChatAvatar(dcContext: dcContext, image: groupImage, for: Int(groupChatId))
             }
 
-            if success == 1 {
+            if success {
                 logger.info("successfully added \(contactId) to group \(groupName)")
             } else {
                 logger.error("failed to add \(contactId) to group \(groupName)")
@@ -74,20 +100,40 @@ class GroupNameController: UITableViewController, MediaPickerDelegate {
     }
 
     override func numberOfSections(in _: UITableView) -> Int {
-        return 2
+        return 3
     }
 
     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
         let section = indexPath.section
         let row = indexPath.row
 
-        if section == sectionGroupDetails {
-            if row == sectionGroupDetailsRowAvatar {
+        switch section {
+        case sectionGroupDetails:
+             if row == sectionGroupDetailsRowAvatar {
                 return avatarSelectionCell
             } else {
                 return groupNameCell
             }
-        } else {
+        case sectionInvite:
+            if row == sectionInviteRowAddMembers {
+                let cell = tableView.dequeueReusableCell(withIdentifier: "actionCell", for: indexPath)
+                if let actionCell = cell as? ActionCell {
+                    actionCell.actionTitle = String.localized("group_add_members")
+                    actionCell.actionColor = UIColor.systemBlue
+                    actionCell.isUserInteractionEnabled = true
+                }
+                return cell
+            } else {
+                let cell = tableView.dequeueReusableCell(withIdentifier: "actionCell", for: indexPath)
+                if let actionCell = cell as? ActionCell {
+                    actionCell.actionTitle = String.localized("qrshow_join_group_title")
+                    actionCell.actionColor = groupName.isEmpty ? DcColors.colorDisabled : UIColor.systemBlue
+                    actionCell.isUserInteractionEnabled = !groupName.isEmpty
+                    qrInviteCodeCell = actionCell
+                }
+                return cell
+            }
+        default:
             let cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath)
             if let contactCell = cell as? ContactCell {
                 let contact = DcContact(id: groupContactIds[row])
@@ -105,40 +151,70 @@ class GroupNameController: UITableViewController, MediaPickerDelegate {
         }
     }
 
+    override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
+        if section == sectionGroupDetails && isVerifiedGroup {
+            return String.localized("verified_group_explain")
+        }
+        return nil
+    }
+
     override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
         let section = indexPath.section
         let row = indexPath.row
-        if section == sectionGroupDetails {
+        switch section {
+        case sectionGroupDetails:
             if row == sectionGroupDetailsRowAvatar {
                 return AvatarSelectionCell.cellSize
             } else {
                 return Constants.defaultCellHeight
             }
-        } else {
+        case sectionInvite:
+            return Constants.defaultCellHeight
+        default:
             return ContactCell.cellHeight
         }
     }
 
     override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
-        if section == sectionGroupDetails {
+        switch section {
+        case sectionGroupDetails:
             return countSectionGroupDetails
-        } else {
+        case sectionInvite:
+            return countSectionInvite
+        default:
             return contactIdsForGroup.count
         }
     }
 
     override func tableView(_: UITableView, titleForHeaderInSection section: Int) -> String? {
-        if section == 1 {
+        if section == sectionGroupMembers {
             return String.localized("in_this_group_desktop")
         } else {
             return nil
         }
     }
 
+    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        let section = indexPath.section
+        let row = indexPath.row
+        if section == sectionInvite {
+            if row == sectionInviteRowAddMembers {
+                var contactsWithoutSelf = contactIdsForGroup
+                contactsWithoutSelf.remove(Int(DC_CONTACT_ID_SELF))
+                coordinator?.showAddMembers(preselectedMembers: contactsWithoutSelf, isVerified: self.isVerifiedGroup)
+            } else {
+                self.groupChatId = dcContext.createGroupChat(verified: isVerifiedGroup, name: groupName)
+                coordinator?.showQrCodeInvite(chatId: Int(self.groupChatId))
+            }
+        }
+    }
+
     private func updateGroupName(textView: UITextField) {
         let name = textView.text ?? ""
         groupName = name
         doneButton.isEnabled = name.containsCharacters()
+        qrInviteCodeCell?.isUserInteractionEnabled = name.containsCharacters()
+        qrInviteCodeCell?.actionColor = groupName.isEmpty ? DcColors.colorDisabled : UIColor.systemBlue
     }
 
     private func onAvatarTapped() {
@@ -172,4 +248,9 @@ class GroupNameController: UITableViewController, MediaPickerDelegate {
         self.tableView.endUpdates()
     }
 
+    func updateGroupContactIds(_ members: Set<Int>) {
+        contactIdsForGroup = members
+        groupContactIds = Array(members)
+        self.tableView.reloadData()
+    }
 }

+ 31 - 18
deltachat-ios/Coordinator/AppCoordinator.swift

@@ -291,8 +291,8 @@ class NewChatCoordinator: Coordinator {
         self.navigationController = navigationController
     }
 
-    func showNewGroupController() {
-        let newGroupController = NewGroupViewController()
+    func showNewGroupController(isVerified: Bool) {
+        let newGroupController = NewGroupController(dcContext: dcContext, isVerified: isVerified)
         let coordinator = NewGroupCoordinator(dcContext: dcContext, navigationController: navigationController)
         childCoordinators.append(coordinator)
         newGroupController.coordinator = coordinator
@@ -454,7 +454,7 @@ class ChatViewCoordinator: NSObject, Coordinator {
     }
 }
 
-class NewGroupCoordinator: Coordinator {
+class NewGroupAddMembersCoordinator: Coordinator {
     var dcContext: DcContext
     let navigationController: UINavigationController
 
@@ -464,14 +464,6 @@ class NewGroupCoordinator: Coordinator {
         self.dcContext = dcContext
         self.navigationController = navigationController
     }
-
-    func showGroupNameController(contactIdsForGroup: Set<Int>) {
-        let groupNameController = GroupNameController(contactIdsForGroup: contactIdsForGroup)
-        let coordinator = GroupNameCoordinator(dcContext: dcContext, navigationController: navigationController)
-        childCoordinators.append(coordinator)
-        groupNameController.coordinator = coordinator
-        navigationController.pushViewController(groupNameController, animated: true)
-    }
 }
 
 class AddGroupMembersCoordinator: Coordinator {
@@ -495,12 +487,11 @@ class AddGroupMembersCoordinator: Coordinator {
     }
 }
 
-class GroupNameCoordinator: Coordinator {
+class NewGroupCoordinator: Coordinator {
     var dcContext: DcContext
     let navigationController: UINavigationController
     let mediaPicker: MediaPicker
 
-
     private var childCoordinators: [Coordinator] = []
 
     init(dcContext: DcContext, navigationController: UINavigationController) {
@@ -519,13 +510,35 @@ class GroupNameCoordinator: Coordinator {
     }
 
     func showPhotoPicker(delegate: MediaPickerDelegate) {
-          mediaPicker.showPhotoGallery(delegate: delegate)
-      }
+        mediaPicker.showPhotoGallery(delegate: delegate)
+    }
+
+    func showCamera(delegate: MediaPickerDelegate) {
+        mediaPicker.showCamera(delegate: delegate)
+    }
 
-      func showCamera(delegate: MediaPickerDelegate) {
-          mediaPicker.showCamera(delegate: delegate)
-      }
+    func showQrCodeInvite(chatId: Int) {
+        let qrInviteCodeController = QrInviteViewController(dcContext: dcContext, chatId: chatId)
+        navigationController.pushViewController(qrInviteCodeController, animated: true)
+    }
+
+    func showAddMembers(preselectedMembers: Set<Int>, isVerified: Bool) {
+        let newGroupController = NewGroupAddMembersViewController(dcContext: dcContext,
+                                                                  preselected: preselectedMembers,
+                                                                  isVerified: isVerified)
+        let coordinator = NewGroupAddMembersCoordinator(dcContext: dcContext, navigationController: navigationController)
+        childCoordinators.append(coordinator)
+        newGroupController.coordinator = coordinator
+        newGroupController.onMembersSelected = onGroupMembersSelected
+        navigationController.pushViewController(newGroupController, animated: true)
+    }
 
+    func onGroupMembersSelected(_ memberIds: Set<Int>) {
+        navigationController.popViewController(animated: true)
+        if let groupNameController = navigationController.topViewController as? NewGroupController {
+            groupNameController.updateGroupContactIds(memberIds)
+        }
+    }
 }
 
 class ContactDetailCoordinator: Coordinator, ContactDetailCoordinatorProtocol {

+ 12 - 0
deltachat-ios/DC/Wrapper.swift

@@ -42,6 +42,18 @@ class DcContext {
         return Int(dc_create_chat_by_contact_id(contextPointer, UInt32(contactId)))
     }
 
+    func createGroupChat(verified: Bool, name: String) -> Int {
+        return Int(dc_create_group_chat(contextPointer, verified ? 1 : 0, name))
+    }
+
+    func addContactToChat(chatId: Int, contactId: Int) -> Bool {
+        return dc_add_contact_to_chat(contextPointer, UInt32(chatId), UInt32(contactId)) == 1
+    }
+
+    func setChatName(chatId: Int, name: String) -> Bool {
+        return dc_set_chat_name(contextPointer, UInt32(chatId), name) == 1
+    }
+
     func deleteChat(chatId: Int) {
         dc_delete_chat(contextPointer, UInt32(chatId))
     }

+ 12 - 0
deltachat-ios/Extensions/Extensions.swift

@@ -45,3 +45,15 @@ extension URLSession {
         return (data, response, error)
     }
 }
+
+extension UIViewController {
+    func hideKeyboardOnTap() {
+        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
+        tap.cancelsTouchesInView = false
+        view.addGestureRecognizer(tap)
+    }
+
+    @objc func dismissKeyboard() {
+        view.endEditing(true)
+    }
+}

+ 1 - 4
deltachat-ios/az.lproj/Localizable.strings

@@ -99,7 +99,7 @@
 "menu_new_contact" = "Yeni kontakt";
 "menu_new_chat" = "Yeni çat";
 "menu_new_group" = "Yeni qrup";
-"menu_new_verified_group" = "Yeni yoxlanılmış qrup (eksperimental)";
+"menu_new_verified_group" = "Yeni yoxlanılmış qrup";
 "menu_send" = "Göndər";
 "menu_toggle_keyboard" = "Emoji klaviatura keçidi";
 "menu_edit_group" = "Qrupu dəyiş";
@@ -465,8 +465,6 @@
 "contact_not_verified" = "%1$@Doğrula bilmir";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "%1$@üçün quraşdırma dəyişdirildi";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d yeni mesaj %2$d çatda";
 "notify_most_recent_from" = "Ən son olanlar: %1$@";
@@ -497,7 +495,6 @@
 "perm_explain_access_to_location_denied" = "Delta Chat yer əlavə etmək üçün yer icazə tələb edir, lakin daimi olaraq rədd edilmişdir. \"İcazələr\"-i seçin və\"Yerləşmə\" izni verin. ";
 "perm_enable_bg_reminder_title" = "Delta Chat arxa fonda mesajları almaq üçün bura toxunun.";
 "perm_enable_bg_reminder_text" = "Delta Chat minimum resurslardan istifadə edir və batareyanı boşaltmamaq üçün qayğı göstərir.";
-
 // dc_str_* resources
 "encrypted_message" = "Şifrələnmiş mesaj";
 

+ 1 - 4
deltachat-ios/ca.lproj/Localizable.strings

@@ -81,7 +81,7 @@
 "menu_new_contact" = "Contacte nou";
 "menu_new_chat" = "Nova conversa";
 "menu_new_group" = "Grup nou";
-"menu_new_verified_group" = "Nou grup verificat (experimental)";
+"menu_new_verified_group" = "Nou grup verificat";
 "menu_send" = "Envia";
 "menu_toggle_keyboard" = "Canvia al teclat d\'emoticones";
 "menu_edit_group" = "Modifica el grup";
@@ -396,8 +396,6 @@
 "contact_not_verified" = "No es pot verificar%1$@";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Configuració canviada per %1$@";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d missatges nous en %2$d xats";
 "notify_most_recent_from" = "El més nou des de : %1$@";
@@ -428,7 +426,6 @@
 "perm_explain_access_to_location_denied" = "Delta Chat necessita accedir a la ubicació per poder-la adjuntar, però li ha estat denegada de forma permanent. Vés a les preferències del menú de l\'aplicació, tria \"Permisos i activa-hi la \"Ubicació\".";
 "perm_enable_bg_reminder_title" = "Prem aquí per rebre missatges mentre Delta Chat és en segon pla.";
 "perm_enable_bg_reminder_text" = "Delta Chat fa servir els recursos mínims i procura no gastar gaire bateria.";
-
 // dc_str_* resources
 "encrypted_message" = "Missatge encriptat";
 

+ 1 - 4
deltachat-ios/da.lproj/Localizable.strings

@@ -82,7 +82,7 @@
 "menu_new_contact" = "Ny kontakt";
 "menu_new_chat" = "Ny samtale";
 "menu_new_group" = "Ny gruppe";
-"menu_new_verified_group" = "Ny efterprøvet gruppe (eksperimentel)";
+"menu_new_verified_group" = "Ny efterprøvet gruppe";
 "menu_send" = "Sende";
 "menu_toggle_keyboard" = "Skifte emoji tastatur";
 "menu_edit_group" = "Redigere gruppe";
@@ -433,8 +433,6 @@
 "contact_not_verified" = "Kan ikke efterprøve %1$@";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Ændret opsætning for %1$@";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d nye beskeder i %2$d samtaler";
 "notify_most_recent_from" = "Nylig fra: %1$@";
@@ -465,7 +463,6 @@
 "perm_explain_access_to_location_denied" = "Delta Chat kræver placering tilladelse for at kunne vedhæfte placering, men det er blevet afvist permanent. Fortsæt til program indstillings-menuen, vælg \"Tilladelser\" og aktiver \"Placering\".";
 "perm_enable_bg_reminder_title" = "Tryk her for at modtage beskeder når Delta Chat er i baggrunden.";
 "perm_enable_bg_reminder_text" = "Delta Chat bruger minimal resurse og passer på ikke at dræne batteriet.";
-
 // dc_str_* resources
 "encrypted_message" = "Krypteret besked";
 

+ 4 - 0
deltachat-ios/de.lproj/InfoPlist.strings

@@ -0,0 +1,4 @@
+"Privacy - Camera Usage Description" = "Zugriff auf die Kamera ermöglicht das Aufnehmen von Fotos und Videos.";
+"Privacy - Contacts Usage Description" = "Wenn Du Zugriff auf das Adressbuch zulässt, kannst du von Deinem Gerät aus mit Kontakten chatten.";
+"Privacy - Microphone Usage Description" = "Wenn Du den Zugriff auf das Mikrofon zulässt, kannst Du Audio aufnehmen.";
+"Privacy - Photo Library Usage Description" = "Wenn Du Zugriff auf die Fotobibliothek erlaubst, kannst Du Bilder aus der Bibliothek hochladen.";

+ 4 - 5
deltachat-ios/de.lproj/Localizable.strings

@@ -105,7 +105,7 @@
 "menu_new_contact" = "Neuer Kontakt";
 "menu_new_chat" = "Neuer Chat";
 "menu_new_group" = "Neue Gruppe";
-"menu_new_verified_group" = "Neue verifizierte Gruppe (experimentell)";
+"menu_new_verified_group" = "Neue verifizierte Gruppe";
 "menu_send" = "Senden";
 "menu_toggle_keyboard" = "Emojis einblenden";
 "menu_edit_group" = "Gruppe bearbeiten";
@@ -216,6 +216,7 @@
 "chat_no_messages" = "Keine Nachrichten.";
 "chat_self_talk_subtitle" = "Nachrichten, die ich mir selber geschickt habe";
 "saved_messages" = "Gespeichertes";
+"saved_messages_explain" = "• Nachrichten zum Merken hierher weiterleiten\n\n• Notizen oder Sprachmemos machen\n\n• Medien zum Speichern einfügen";
 "chat_contact_request" = "Kontaktanfrage";
 "chat_no_contact_requests" = "Keine Kontaktanfragen.\n\nWenn normale E-Mails hier erscheinen sollen, müssen Sie die entsprechende erweiterte Einstellung ändern.";
 "retry_send" = "Nachricht erneut senden";
@@ -414,7 +415,7 @@
 "pref_show_emails_no" = "Nein, nur Chats";
 "pref_show_emails_accepted_contacts" = "Akzeptierte Kontakte";
 "pref_show_emails_all" = "Alle";
-"pref_empty_server_title" = "E-Mails vom Server löschen!";
+"pref_empty_server_title" = "E-Mails vom Server löschen";
 "pref_empty_server_msg" = "Mit dieser Funktion können Sie Speicherplatz auf Ihrem IMAP-Server freigeben, indem Sie ALLE E-Mails, einschließlich Chat-Nachrichten, in den angegebenen Ordnern löschen. Nachrichten auf diesem Gerät werden nicht gelöscht. Die Löschung kann nicht rückgängig gemacht werden!";
 "pref_empty_server_inbox" = "Löschen ALLER e-mails im Nachrichteneingangsordner (INBOX)";
 "pref_empty_server_mvbox" = "Löschen ALLER e-mails im DeltaChat Ordner.";
@@ -496,8 +497,6 @@
 "contact_not_verified" = "Kann %1$@ nicht verifizieren";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Geändertes Setup für %1$@";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d neue Nachrichten in %2$d Chats";
 "notify_most_recent_from" = "Letzter Stand von: %1$@";
@@ -528,7 +527,6 @@
 "perm_explain_access_to_location_denied" = "Delta Chat benötigt eine Standortberechtigung, um einen Standort anzuhängen, aber er wurde dauerhaft abgelehnt. Bitte fahre mit dem Menü App-Einstellungen fort, wähle \"Berechtigungen\" und aktiviere \"Standort\".";
 "perm_enable_bg_reminder_title" = "Tippen Sie hier, um Nachrichten zu empfangen, während Delta Chat im Hintergrund läuft.";
 "perm_enable_bg_reminder_text" = "Delta Chat verbraucht nur minimale Ressourcen und achtet darauf, den Akku zu schonen.";
-
 // dc_str_* resources
 "encrypted_message" = "Verschlüsselte Nachricht";
 
@@ -616,3 +614,4 @@
 "a11y_message_context_menu_btn_label" = "Nachrichtaktionen";
 "a11y_background_preview_label" = "Vorschau für Hintergrundbild";
 
+// Translators: These strings are only used on iOS

+ 3 - 1
deltachat-ios/en.lproj/Localizable.strings

@@ -105,7 +105,7 @@
 "menu_new_contact" = "New contact";
 "menu_new_chat" = "New chat";
 "menu_new_group" = "New group";
-"menu_new_verified_group" = "New verified group (experimental)";
+"menu_new_verified_group" = "New verified group";
 "menu_send" = "Send";
 "menu_toggle_keyboard" = "Toggle emoji keyboard";
 "menu_edit_group" = "Edit group";
@@ -497,6 +497,7 @@
 "contact_not_verified" = "Cannot verify %1$@.";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Changed setup for %1$@.";
+"verified_group_explain" = "Verified groups (experimental) provide safety against active attacks. Members are verified with a second factor by other members and messages are always end-to-end-encrypted.";
 
 
 // notifications 
@@ -529,6 +530,7 @@
 "perm_explain_access_to_location_denied" = "To attach a location, go to the app settings, select \"Permissions\", and enable \"Location\".";
 "perm_enable_bg_reminder_title" = "Tap here to receive messages while Delta Chat is in the background.";
 "perm_enable_bg_reminder_text" = "Delta Chat uses few resources and takes care not to drain your battery.";
+"perm_enable_bg_already_done" = "You already allowed Delta Chat to receive messages in the background.\n\nIf messages still do not arrive in background, please also check your system settings.";
 
 // dc_str_* resources
 "encrypted_message" = "Encrypted message";

+ 1 - 4
deltachat-ios/es.lproj/Localizable.strings

@@ -105,7 +105,7 @@
 "menu_new_contact" = "Nuevo contacto";
 "menu_new_chat" = "Nuevo chat";
 "menu_new_group" = "Nuevo grupo";
-"menu_new_verified_group" = "Nuevo grupo verificado (experimental)";
+"menu_new_verified_group" = "Nuevo grupo verificado";
 "menu_send" = "Enviar";
 "menu_toggle_keyboard" = "Alternar teclado emoji";
 "menu_edit_group" = "Editar grupo";
@@ -497,8 +497,6 @@
 "contact_not_verified" = "No se pudo verificar %1$@";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Configuración cambiada para %1$@";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d nuevos mensajes en %2$d chats";
 "notify_most_recent_from" = "Más reciente de: %1$@";
@@ -529,7 +527,6 @@
 "perm_explain_access_to_location_denied" = "Delta Chat requiere el permiso de Ubicación para adjuntar una ubicación, pero ha sido denegado de forma permanente. Por favor, vaya al menú de configuración de aplicaciones, seleccione \"Permisos\" y habilite \"Ubicación\".";
 "perm_enable_bg_reminder_title" = "Toque aquí para recibir mensajes mientras Delta Chat está en segundo plano.";
 "perm_enable_bg_reminder_text" = "Delta Chat utiliza los recursos al mínimo y tiene cuidado de no drenar tu batería.";
-
 // dc_str_* resources
 "encrypted_message" = "Mensaje cifrado";
 

+ 1 - 4
deltachat-ios/eu.lproj/Localizable.strings

@@ -105,7 +105,7 @@
 "menu_new_contact" = "Kontaktu berria";
 "menu_new_chat" = "Txat berria";
 "menu_new_group" = "Talde berria";
-"menu_new_verified_group" = "Egiaztatutako talde berria (esperimentala)";
+"menu_new_verified_group" = "Egiaztatutako talde berria";
 "menu_send" = "Bidali";
 "menu_toggle_keyboard" = "Txandakatu emoji teklatua";
 "menu_edit_group" = "Editatu taldea";
@@ -497,8 +497,6 @@
 "contact_not_verified" = "Ezin da %1$@ egiaztatu";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Aldatu %1$@(r)en ezarpena";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d mezu berri %2$d txatetan";
 "notify_most_recent_from" = "%1$@(r)en azkena";
@@ -529,7 +527,6 @@
 "perm_explain_access_to_location_denied" = "Delta Chat-ek kokaleku aatzitzeko baimena behar du kokalekua eransteko, baina behin betiko ukatu zaio. Joan aplikazioaren ezarpen menura, hautatu \"baimenak\", eta gaitu \"Kokalekua\".";
 "perm_enable_bg_reminder_title" = "Sakatu hemen mezuak jasotzeko Delta Chat bigarren planoan dagoenean.";
 "perm_enable_bg_reminder_text" = "Delta Chat-ek baliabide gutxi erabiltzen ditu eta zure bateria ez agortzeaz arduratzen da.";
-
 // dc_str_* resources
 "encrypted_message" = "Zifratutako mezua";
 

+ 1 - 4
deltachat-ios/fr.lproj/Localizable.strings

@@ -100,7 +100,7 @@
 "menu_new_contact" = "Nouveau contact";
 "menu_new_chat" = "Nouvelle discussion";
 "menu_new_group" = "Nouveau groupe";
-"menu_new_verified_group" = "Nouveau groupe vérifié (expérimental)";
+"menu_new_verified_group" = "Nouveau groupe vérifié";
 "menu_send" = "Envoyer";
 "menu_toggle_keyboard" = "Basculer le clavier emoji";
 "menu_edit_group" = "Modifier le groupe";
@@ -480,8 +480,6 @@
 "contact_not_verified" = "Ne peut pas vérifier %1$@";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Configuration modifiée pour %1$@";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d nouveaux messages dans %2$d tchats";
 "notify_most_recent_from" = "Plus récents depuis : %1$@";
@@ -512,7 +510,6 @@
 "perm_explain_access_to_location_denied" = "DeltaChat nécessite l\'autorisation de la position pour attacher une position, mais elle a été définitivement refusée. Continuez jusqu\'au menu des paramètres de l\'application, sélectionnez \"Autorisations\" et activez \"Position\".";
 "perm_enable_bg_reminder_title" = "Touchez ici pour recevoir des messages pendant que DeltaChat est en arrière-plan.";
 "perm_enable_bg_reminder_text" = "DeltaChat utilise un minimum de ressources et veille à ne pas vider votre batterie.";
-
 // dc_str_* resources
 "encrypted_message" = "Message chiffré";
 

+ 1 - 4
deltachat-ios/gl.lproj/Localizable.strings

@@ -105,7 +105,7 @@
 "menu_new_contact" = "Novo contacto";
 "menu_new_chat" = "Nova conversa";
 "menu_new_group" = "Novo grupo";
-"menu_new_verified_group" = "Novo grupo verificado (experimental)";
+"menu_new_verified_group" = "Novo grupo verificado";
 "menu_send" = "Enviar";
 "menu_toggle_keyboard" = "Activar teclado emoji";
 "menu_edit_group" = "Editar grupo";
@@ -497,8 +497,6 @@
 "contact_not_verified" = "Non se puido verificar %1$@.";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Cambiaron os axustes para %1$@.";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d novas mensaxes en %2$d conversas";
 "notify_most_recent_from" = "Máis recente desde: %1$@";
@@ -529,7 +527,6 @@
 "perm_explain_access_to_location_denied" = "Para engadir a localización, vaite aos axustes da app, escolle \"Permisos\" e activa \"Localización\".";
 "perm_enable_bg_reminder_title" = "Toca aquí para recibir mensaxes mentras Delta Chat está en segundo plano.";
 "perm_enable_bg_reminder_text" = "Delta Chat utiliza poucos recursos e procura non esgotar a batería.";
-
 // dc_str_* resources
 "encrypted_message" = "Mensaxe cifrada";
 

+ 1 - 1
deltachat-ios/hu.lproj/Localizable.strings

@@ -78,7 +78,7 @@
 "menu_new_contact" = "Új partner";
 "menu_new_chat" = "Új beszélgetés";
 "menu_new_group" = "Új csoport";
-"menu_new_verified_group" = "Új ellenőrzött csoport (kísérleti)";
+"menu_new_verified_group" = "Új ellenőrzött csoport";
 "menu_send" = "Küldés";
 "menu_edit_group" = "Csoport szerkesztése";
 "menu_group_name_and_image" = "Csoportnév és -kép";

+ 4 - 0
deltachat-ios/it.lproj/InfoPlist.strings

@@ -0,0 +1,4 @@
+"Privacy - Camera Usage Description" = "Autorizzare l\'accesso alla camera ti permette di fare foto e video";
+"Privacy - Contacts Usage Description" = "Autorizzare l\'accesso alla rubrica ti permette di chattare con i contatti nel tuo dispositivo.";
+"Privacy - Microphone Usage Description" = "Autorizzare l\'accesso al microfono ti permette di registrare audio.";
+"Privacy - Photo Library Usage Description" = "Autorizzare l\'accesso alla galleria ti permette di caricare foto da essa.";

+ 10 - 4
deltachat-ios/it.lproj/Localizable.strings

@@ -19,6 +19,10 @@
 "attachment" = "Allegato";
 "back" = "Indietro";
 "close" = "Chiudi";
+"forward" = "Inoltra";
+"archive" = "Archivia";
+"unarchive" = "Ripristina";
+"mute" = "Silenzia";
 "save" = "Salva";
 "chat" = "Chat";
 "media" = "Media";
@@ -101,7 +105,7 @@
 "menu_new_contact" = "Nuovo contatto";
 "menu_new_chat" = "Nuova chat";
 "menu_new_group" = "Nuovo gruppo";
-"menu_new_verified_group" = "Nuovo gruppo verificato (sperimentale)";
+"menu_new_verified_group" = "Nuovo gruppo verificato";
 "menu_send" = "Inviato";
 "menu_toggle_keyboard" = "Alterna tastiera emoji";
 "menu_edit_group" = "Modifica grupp";
@@ -151,6 +155,8 @@
 "title_share_location" = "Condividi posizione con tutti i membri";
 "device_talk" = "Messaggi del dispositivo";
 "device_talk_subtitle" = "Messaggi generati localmente";
+"device_talk_explain" = "I messaggio in questa chat vengono generati localmente da Delta Chat. Gli sviluppatori li usano per informarti sugli aggiornamenti o sui problemi d\'utilizzo.";
+"device_talk_welcome_message" = "Benvenuto in Delta Chat! - Delta Chat ha l\'aspetto e lo stile di altre popolari applicazioni di messaggistica, ma non costringe ad un controllo centralizzato, al tracciamento o alla vendita tua,  dei tuoi amici, colleghi o familiari a grandi organizzazioni.\n \n Tecnicamente, Delta Chat è un\'applicazione di posta elettronica con un\'interfaccia moderna. L\'email sotto una nuova vesta 👻 \n \nUtilizza Delta Chat con chiunque: basta conoscere il loro indirizzo e-mail. I destinatari non hanno bisogno di installare Delta Chat, visitare siti web o iscriversi da nessuna parte -  ma, naturalmente se lo desiderano, puoi suggerirgli 👉 https://get.delta.chat";
 "edit_contact" = "Modifica contatto";
 
 "mute_for_one_hour" = "Silenzia per 1 ora";
@@ -209,6 +215,8 @@
 "chat_archived_label" = "Archiviato";
 "chat_no_messages" = "Nessun messaggio.";
 "chat_self_talk_subtitle" = "Messaggi inviati a me stesso";
+"saved_messages" = "Messaggi salvati";
+"saved_messages_explain" = "• Inoltra i messaggi per trovarli facilmente\n\n• Memorizza note scritte o vocali\n\n• Allega oggetti per salvarli";
 "chat_contact_request" = "Richiesta di contatto";
 "chat_no_contact_requests" = "Nessuna richiesta di contatto.\n\nSe vuoi che le email tradizionali appaiano qui come richieste di contatto puoi selezionare la relativa opzione nelle impostazioni.";
 "retry_send" = "Riprova l\'invio del messaggio";
@@ -489,8 +497,6 @@
 "contact_not_verified" = "Impossibile verificare %1$@";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Impostazioni modificate per %1$@";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d nuovi messaggi in %2$d chat";
 "notify_most_recent_from" = "Più recente da: %1$@";
@@ -521,7 +527,6 @@
 "perm_explain_access_to_location_denied" = "Delta Chat richiede l\'autorizzazione per allegare la posizione, ma è stata bloccata permanentemente. Vai nelle impostazioni delle App, seleziona \"Autorizzazioni\" e abilita \"Posizione\".";
 "perm_enable_bg_reminder_title" = "Premi qui per ricevere i messaggi anche quando Delta Chat è in background.";
 "perm_enable_bg_reminder_text" = "Delta Chat usa poche risorse ed è progettata per consumare meno batteria possibile.";
-
 // dc_str_* resources
 "encrypted_message" = "Messaggio cifrato";
 
@@ -609,3 +614,4 @@
 "a11y_message_context_menu_btn_label" = "Azioni messaggio";
 "a11y_background_preview_label" = "Anteprima sfondo";
 
+// Translators: These strings are only used on iOS

+ 3 - 2
deltachat-ios/lt.lproj/Localizable.strings

@@ -97,7 +97,7 @@
 "menu_new_contact" = "Naujas adresatas";
 "menu_new_chat" = "Naujas pokalbis";
 "menu_new_group" = "Nauja grupė";
-"menu_new_verified_group" = "Nauja patvirtinta grupė (eksperimentinis)";
+"menu_new_verified_group" = "Nauja patvirtinta grupė";
 "menu_send" = "Siųsti";
 "menu_toggle_keyboard" = "Perjungti šypsniukų klaviatūrą";
 "menu_edit_group" = "Taisyti grupę";
@@ -390,6 +390,8 @@
 "screenlock_inactivity_timeout_interval" = "Neveiklumui skirtas laiko intervalas";
 
 
+// qr code stuff
+"qr_code" = "QR kodas";
 "qrscan_title" = "Nuskenuokite QR kodą";
 "qrscan_hint" = "Laikykite savo kamerą virš QR kodo";
 "qrscan_ask_join_group" = "Ar norite prisijungti prie grupės \"%1$@\"?";
@@ -429,7 +431,6 @@
 "perm_explain_need_for_storage_access_share" = "Norint bendrinti pasirinktus failus, Delta Chat reikia prieigos prie jūsų failų.";
 "perm_enable_bg_reminder_title" = "Bakstelėkite čia, norėdami gauti žinutes, kol Delta Chat veikia fone.";
 "perm_enable_bg_reminder_text" = "Delta Chat naudoja mažai išteklių ir rūpinasi, kad neiškrautų jūsų baterijos.";
-
 // dc_str_* resources
 "encrypted_message" = "Šifruota žinutė";
 

+ 2 - 3
deltachat-ios/nl.lproj/Localizable.strings

@@ -105,7 +105,7 @@
 "menu_new_contact" = "Nieuw contactpersoon";
 "menu_new_chat" = "Nieuw gesprek";
 "menu_new_group" = "Nieuwe groep";
-"menu_new_verified_group" = "Nieuwe goedgekeurde groep (experimenteel)";
+"menu_new_verified_group" = "Nieuwe goedgekeurde groep";
 "menu_send" = "Versturen";
 "menu_toggle_keyboard" = "Emoji-toetsenbord tonen/verbergen";
 "menu_edit_group" = "Groep aanpassen";
@@ -497,8 +497,6 @@
 "contact_not_verified" = "Kan %1$@ niet goedkeuren";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Gewijzigde instellingen voor %1$@";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d nieuwe berichten in %2$d gesprekken";
 "notify_most_recent_from" = "Recentste van: %1$@";
@@ -529,6 +527,7 @@
 "perm_explain_access_to_location_denied" = "Delta Chat vereist de locatiemachtiging om je locatie te kunnen delen, maar je hebt dit permanent geweigerd. Ga naar de app-instellingen, kies \"Machtigingen\" en schakel \"Locatie\" in.";
 "perm_enable_bg_reminder_title" = "Druk hier om berichten te ontvangen als Delta Chat niet geopend is.";
 "perm_enable_bg_reminder_text" = "Delta Chat\'s accugebruik is laag omdat het slechts een minimaal aantal systeembronnen gebruikt.";
+"perm_enable_bg_already_done" = "Je hebt al toestemming gegeven voor het ophalen van berichten op de achtergrond.\n\nAls het nog steeds niet werkt, controleer dan de systeeminstellingen.";
 
 // dc_str_* resources
 "encrypted_message" = "Versleuteld bericht";

+ 4 - 0
deltachat-ios/pl.lproj/InfoPlist.strings

@@ -0,0 +1,4 @@
+"Privacy - Camera Usage Description" = "Zezwolenie na dostęp do aparatu pozwala robić zdjęcia i nagrywać filmy.";
+"Privacy - Contacts Usage Description" = "Zezwolenie na dostęp do książki adresowej pozwala czatować z kontaktami z urządzenia.";
+"Privacy - Microphone Usage Description" = "Zezwolenie na dostęp do mikrofonu pozwala nagrywać dźwięk.";
+"Privacy - Photo Library Usage Description" = "Zezwolenie na dostęp do biblioteki zdjęć umożliwia przesyłanie z niej zdjęć.";

+ 25 - 18
deltachat-ios/pl.lproj/Localizable.strings

@@ -9,6 +9,8 @@
 "def" = "Domyślne";
 "custom" = "Własne";
 "none" = "Brak";
+"automatic" = "Automatyczne";
+"strict" = "Dokładne";
 "open" = "Otwórz";
 "delete" = "Usuń";
 "emoji" = "Emoji";
@@ -100,7 +102,7 @@
 "menu_new_contact" = "Nowy kontakt";
 "menu_new_chat" = "Nowy czat";
 "menu_new_group" = "Nowa grupa";
-"menu_new_verified_group" = "Nowa zweryfikowana grupa (eksperymentalne)";
+"menu_new_verified_group" = "Nowa zweryfikowana grupa";
 "menu_send" = "Wyślij";
 "menu_toggle_keyboard" = "Przełącz klawiaturę emoji";
 "menu_edit_group" = "Edytuj grupę";
@@ -130,8 +132,8 @@
 "menu_unblock_contact" = "Odblokuj kontakt";
 "menu_play" = "Odtwarzaj";
 "menu_pause" = "Wstrzymaj";
-"menu_scroll_to_bottom" = "Przewiń do dołu";
-"menu_scroll_to_top" = "Przesuń do góry";
+"menu_scroll_to_bottom" = "Przewiń na dołu";
+"menu_scroll_to_top" = "Przewiń na górę";
 "menu_invite" = "Zaproś znajomych";
 "menu_help" = "Pomoc";
 "menu_select_all" = "Zaznacz wszystko";
@@ -148,13 +150,17 @@
 "menu_zoom_out" = "Pomniejsz";
 "menu_save_log" = "Zapisz log";
 "title_share_location" = "Udostępnij lokalizację dla wszystki czlonków grup";
+"device_talk" = "Komunikaty urządzenia";
+"device_talk_subtitle" = "Wiadomości generowane lokalnie";
+"device_talk_explain" = "Wiadomości w tym czacie są generowane lokalnie przez twoją aplikację Delta Chat. Twórcy używają go do informowania o aktualizacjach aplikacji i problemach podczas użytkowania.";
+"device_talk_welcome_message" = "Witamy w Delta Chat! - Delta Chat wygląda i działa podobnie jak inne popularne komunikatory, ale nie miesza się w scentralizowaną kontrolę, śledzenie ani sprzedaż ciebie, przyjaciół, kolegów lub rodziny dużym organizacjom.\n\nTechnicznie Delta Chat jest aplikacją e-mail z nowoczesnym interfejsem czatu. Jeśli chcesz, wyślij e-mail w nowej sukience 👻.\n\nKorzystaj z Delta Chat z każdym spośród miliardów ludzi: po prostu użyj ich adresu e-mail. Odbiorcy nie muszą instalować Delta Chat, odwiedzać stron internetowych ani rejestrować się gdziekolwiek - oczywiście, jeśli im się spodoba, możesz ich skierować na 👉 https://get.delta.chat.";
 "edit_contact" = "Edytuj kontakt";
 
 "mute_for_one_hour" = "Wyłącz na 1 godzinę";
 "mute_for_two_hours" = "Wyłącz na 2 godziny";
 "mute_for_one_day" = "Wyłącz na 1 dzień";
 "mute_for_seven_days" = "Wyłącz na 7 dni";
-"mute_forever" = "Wycisz na zawsze";
+"mute_forever" = "Wyłącz na zawsze";
 
 "share_location_once" = "raz";
 "share_location_for_5_minutes" = "na 5 minut";
@@ -173,7 +179,7 @@
 "ask_delete_contacts" = "Usunąć kontakty? Spowoduje to trwałe usunięcie wybranych kontaktów.\n\nKontaktów z trwającymi rozmowami i kontaktów z książki adresowej systemu nie można trwale usunąć.";
 "ask_delete_contact" = "Usunąć trwale kontakt %1$@?\n\nKontaktów z trwającymi czatami i kontaktów z książki adresowej systemu nie można trwale usunąć.";
 "cannot_delete_contacts_in_use" = "Nie można usunąć kontaktów z trwającymi czatami.";
-"ask_start_chat_with" = "Czat z %1$@?";
+"ask_start_chat_with" = "Rozpocząć czat z %1$@?";
 // Translators: %1$s will be replaces by a comma separated list of names
 "ask_remove_members" = "Usunąć %1$@ z grupy?";
 "info_outdated_app_title" = "Twoja wersja aplikacji jest nieaktualna.";
@@ -207,6 +213,7 @@
 "chat_no_messages" = "Brak wiadomości.";
 "chat_self_talk_subtitle" = "Wiadomości wysłane do siebie";
 "saved_messages" = "Zapisane wiadomości";
+"saved_messages_explain" = "• Przesyłaj tu wiadomości, aby mieć je pod ręką\n\n• Rób notatki lub notatki głosowe\n\n• Dołączaj media, aby je zachować";
 "chat_contact_request" = "Prośba o kontakt";
 "chat_no_contact_requests" = "Brak zaproszenia do kontaktów.\n\nJeśli chcesz, aby klasyczne wiadomości e-mail pojawiały się tutaj jako prośby o kontakt, możesz zmienić odpowiednie ustawienia w ustawieniach aplikacji.";
 "retry_send" = "Spróbuj ponownie wysłać wiadomość";
@@ -241,8 +248,8 @@
 "tab_docs" = "Dokumenty";
 "tab_links" = "Linki";
 "tab_map" = "Mapa";
-"tab_gallery_empty_hint" = "Wyświetlone zostaną tutaj zdjęcia i filmy udostępnione na tym czacie.";
-"tab_docs_empty_hint" = "Wyświetlone zostaną tutaj dokumenty, muzyka i inne pliki udostępnione na tym czacie.";
+"tab_gallery_empty_hint" = "Tutaj zostaną wyświetlone zdjęcia i filmy udostępnione na tym czacie.";
+"tab_docs_empty_hint" = "Tutaj zostaną wyświetlone dokumenty, muzyka i inne pliki udostępnione na tym czacie.";
 "media_preview" = "Podgląd multimediów";
 
 
@@ -260,20 +267,21 @@
 "login_subheader" = "Dla znanych dostawców usług poczty elektronicznej poniższe ustawienia są ustawiane automatycznie. Czasami IMAP musi być włączony w interfejsie WWW. O pomoc należy zwrócić się do usługodawcy e-mail lub znajomych.";
 "login_no_servers_hint" = "Nie ma serwerów Delta Chat, Twoje dane pozostają na Twoim urządzeniu!";
 "login_inbox" = "Skrzynka odbiorcza";
-"login_imap_login" = "nazwa użytkownika IMAP";
-"login_imap_server" = "serwer IMAP";
-"login_imap_port" = "port IMAP";
+"login_imap_login" = "Nazwa użytkownika IMAP";
+"login_imap_server" = "Serwer IMAP";
+"login_imap_port" = "Port IMAP";
 "login_imap_security" = "Bezpieczeństwo IMAP";
 "login_outbox" = "Skrzynka nadawcza";
-"login_smtp_login" = "nazwa użytkownika SMTP";
-"login_smtp_password" = "hasło SMTP";
-"login_smtp_server" = "serwer SMTP";
-"login_smtp_port" = "port SMTP";
+"login_smtp_login" = "Nazwa użytkownika SMTP";
+"login_smtp_password" = "Hasło SMTP";
+"login_smtp_server" = "Serwer SMTP";
+"login_smtp_port" = "Port SMTP";
 "login_smtp_security" = "Bezpieczeństwo SMTP";
 "login_auth_method" = "Metoda autoryzacji";
 "login_info_oauth2_title" = "Kontynuuj w uproszczonej konfiguracji?";
-"login_info_oauth2_text" = "Wprowadzony adres e-mail obsługuje uproszczoną konfigurację (OAuth2).\n\nW następnym kroku pozwól, aby Delta Chat działał jako czat z aplikacją e-mail.\n\nNie ma serwerów Delta Chat, Twoje dane pozostają na Twoim urządzeniu!";
+"login_info_oauth2_text" = "Wprowadzony adres e-mail obsługuje uproszczoną konfigurację (OAuth2.0).\n\nW następnym kroku pozwól, aby Delta Chat działał jako czat z aplikacją e-mail.\n\nNie ma serwerów Delta Chat, Twoje dane pozostają na Twoim urządzeniu!";
 "login_info_gmail_text" = "W przypadku kont GMail, jeśli masz włączone 2FA, musisz utworzyć hasło aplikacji. Jeśli to ustawienie nie jest dostępne, musisz włączyć mniej bezpieczne aplikacje.";
+"login_certificate_checks" = "Sprawdzanie certyfikatów";
 "login_error_mail" = "Podaj ważny adres e-mail";
 "login_error_server" = "Wprowadź poprawny adres serwera / IP";
 "login_error_port" = "Podaj poprawny numer portu (1–65535)";
@@ -410,6 +418,7 @@
 "pref_empty_server_mvbox" = " Usuń WSZYSTKIE wiadomości e-mail w folderze DeltaChat";
 "pref_empty_server_do_button" = "Usuń e-maile";
 "pref_experimental_features" = "Funkcje eksperymentalne";
+"pref_on_demand_location_streaming" = "Przesyłanie strumieniowe lokalizacji na żądanie";
 "pref_background_default" = "Domyślne tło";
 "pref_background_default_color" = "Domyślny kolor";
 "pref_background_custom_image" = "Własny obraz";
@@ -485,8 +494,6 @@
 "contact_not_verified" = "Nie można zweryfikować %1$@";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Zmieniono konfigurację dla %1$@";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d nowe wiadomości w %2$d czatach";
 "notify_most_recent_from" = "Najnowsze z: %1$@";
@@ -517,7 +524,6 @@
 "perm_explain_access_to_location_denied" = "Delta Chat wymaga zezwolenia na lokalizację, aby dołączyć lokalizację, ale zostało ono trwale odrzucone. Przejdź do menu ustawień aplikacji, wybierz „Uprawnienia” i włącz „Lokalizacja”.";
 "perm_enable_bg_reminder_title" = "Dotknij tutaj, aby odbierać wiadomości, podczas gdy Delta Chat działa w tle.";
 "perm_enable_bg_reminder_text" = "Delta Chat wykorzystuje minimalne zasoby i dba o to, aby nie rozładować baterii.";
-
 // dc_str_* resources
 "encrypted_message" = "Zaszyfrowana wiadomość";
 
@@ -603,3 +609,4 @@
 "a11y_remove_account_btn_label" = "Usuń konto";
 "a11y_background_preview_label" = "Podgląd tła";
 
+// Translators: These strings are only used on iOS

+ 1 - 4
deltachat-ios/pt-BR.lproj/Localizable.strings

@@ -82,7 +82,7 @@
 "menu_new_contact" = "Novo contato";
 "menu_new_chat" = "Nova conversa";
 "menu_new_group" = "Novo grupo";
-"menu_new_verified_group" = "Novo grupo verificado (experimental)";
+"menu_new_verified_group" = "Novo grupo verificado";
 "menu_send" = "Enviar";
 "menu_toggle_keyboard" = "Ativar teclado emoji";
 "menu_edit_group" = "Editar grupo";
@@ -442,8 +442,6 @@
 "contact_not_verified" = "Impossível verificar %1$@";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "A configuração Autocrypt mudou para %1$@";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d novas mensagens em %2$d conversas";
 "notify_most_recent_from" = "Mais recentes de: %1$@";
@@ -474,7 +472,6 @@
 "perm_explain_access_to_location_denied" = "O Delta Chat precisa acessar sua localização para que você possa enviá-la, mas o acesso foi negado. Por favor, habilite o seu acesso nas configurações de permissões do aplicativo.";
 "perm_enable_bg_reminder_title" = "Toque aqui para receber mensagens enquanto o Delta Chat estiver em segundo plano.";
 "perm_enable_bg_reminder_text" = "O Delta Chat usa pouquíssimos recursos e cuida para que sua bateria não esvazie rápido.";
-
 // dc_str_* resources
 "encrypted_message" = "Mensagem criptografada";
 

+ 1 - 4
deltachat-ios/pt-PT.lproj/Localizable.strings

@@ -81,7 +81,7 @@
 "menu_new_contact" = "Novo contacto";
 "menu_new_chat" = "Nova chat";
 "menu_new_group" = "Novo grupo";
-"menu_new_verified_group" = "Novo grupo verificado (experimental)";
+"menu_new_verified_group" = "Novo grupo verificado";
 "menu_send" = "Enviar";
 "menu_toggle_keyboard" = "Alternar teclado emoji";
 "menu_edit_group" = "Editar grupo";
@@ -375,8 +375,6 @@
 "contact_not_verified" = "Não é possível verificar %1$@";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Configuração alterada para %1$@";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d novas mensagens em %2$d chats";
 "notify_most_recent_from" = "Mais recentes de: %1$@";
@@ -406,7 +404,6 @@
 "perm_explain_access_to_location_denied" = "O Delta Chat necessita permissão de acesso à localização para anexar um local, mas ele negado. Por favor, continue no menu de configurações do aplicativo, selecione \"Permissões \"e ative \"Localização\".";
 "perm_enable_bg_reminder_title" = "Toque aqui para receber mensagens mesmo que o Delta Chat esteja em segundo plano.";
 "perm_enable_bg_reminder_text" = "O Delta Chat usa pouquíssimos recursos e busca não consumir muito a bateria.";
-
 // dc_str_* resources
 "encrypted_message" = "Mensagem encriptada";
 

+ 2 - 5
deltachat-ios/ru.lproj/Localizable.strings

@@ -50,7 +50,7 @@
 "password" = "Пароль";
 "now" = "Сейчас";
 // Translators: used as a headline in sections with actions that cannot be undone. could also be "Caution" or "Cave" or so.
-"danger" = "Внимание";
+"danger" = "Опасность";
 // n_min_ago is deprecated, use n_minutes instead
 "n_min_ago" = "%d мин";
 "today" = "Сегодня";
@@ -105,7 +105,7 @@
 "menu_new_contact" = "Новый контакт";
 "menu_new_chat" = "Новый чат";
 "menu_new_group" = "Новая группа";
-"menu_new_verified_group" = "Новая проверенная группа (экспериментальная функция)";
+"menu_new_verified_group" = "Новая проверенная группа";
 "menu_send" = "Отправить";
 "menu_toggle_keyboard" = "Включить эмодзи клавиатуру";
 "menu_edit_group" = "Редактировать группу";
@@ -497,8 +497,6 @@
 "contact_not_verified" = "Невозможно подтвердить %1$@";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Изменены параметры для %1$@";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d новых сообщений в %2$d чатах.";
 "notify_most_recent_from" = "Последнее от: %1$@";
@@ -529,7 +527,6 @@
 "perm_explain_access_to_location_denied" = "Чтобы передать местоположение приложению Delta Chat нужно разрешить доступ к нему, но сейчас он заблокирован. Перейдите в меню настроек приложения, выберите \"Разрешения приложений\" и включите \"Местоположение\".";
 "perm_enable_bg_reminder_title" = "Нажмите здесь, чтобы получать сообщения, когда Delta Chat находится в фоновом режиме.";
 "perm_enable_bg_reminder_text" = "Delta Chat использует минимальные ресурсы и старается не разряжать батарею.";
-
 // dc_str_* resources
 "encrypted_message" = "Зашифрованное сообщение";
 

+ 2 - 3
deltachat-ios/sq.lproj/Localizable.strings

@@ -105,7 +105,7 @@
 "menu_new_contact" = "Kontakt i ri";
 "menu_new_chat" = "Fjalosje e re";
 "menu_new_group" = "Grup i ri";
-"menu_new_verified_group" = "Grup i ri i verifikuar (eksperimentale)";
+"menu_new_verified_group" = "Grup i ri i verifikuar";
 "menu_send" = "Dërgoje";
 "menu_toggle_keyboard" = "Shfaq/fshih tastierë emoji";
 "menu_edit_group" = "Përpunoni grup";
@@ -496,8 +496,6 @@
 "contact_not_verified" = "S\’verifikohet dot %1$@";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "U ndryshua rregullimi për %1$@";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d mesazhe të rinj në %2$d fjalosje";
 "notify_most_recent_from" = "Më të rejat nga: %1$@";
@@ -528,6 +526,7 @@
 "perm_explain_access_to_location_denied" = "Delta Chat lyp leje mbi Vendndodhjen që të mund të bashkëngjisë një vendndodhje, por kjo i është mohuar. Ju lutemi, vazhdoni te menuja e rregullimeve të aplikacionit, përzgjidhni \"Leje\", dhe aktivizojini për \"Vendndodhjen\".";
 "perm_enable_bg_reminder_title" = "Prekeni këtu që të merrni mesazhe, teksa Delta Chat rri në prapaskenë.";
 "perm_enable_bg_reminder_text" = "Delta Chat-i përdor burime minimale dhe kujdeset të mos thajë baterinë.";
+"perm_enable_bg_already_done" = "E keni lejuar tashmë Delta Chat-in të marrë mesazhe në prapaskenë.\n\nNëse mesazhet prapë nuk mbërrijnë në prapaskenë, ju lutemi, kontrolloni edhe rregullimet e sistemit tuaj.";
 
 // dc_str_* resources
 "encrypted_message" = "Mesazh i fshehtëzuar";

+ 6 - 7
deltachat-ios/tr.lproj/Localizable.strings

@@ -105,7 +105,7 @@
 "menu_new_contact" = "Yeni kişi";
 "menu_new_chat" = "Yeni sohbet";
 "menu_new_group" = "Yeni grup";
-"menu_new_verified_group" = "Yeni doğrulanan grup (deneysel)";
+"menu_new_verified_group" = "Yeni doğrulanan grup";
 "menu_send" = "Gönder";
 "menu_toggle_keyboard" = "Emoji klavyesine geç";
 "menu_edit_group" = "Grubu düzenle";
@@ -155,7 +155,7 @@
 "title_share_location" = "Tüm grup üyeleriyle konum paylaş";
 "device_talk" = "Aygıt iletileri";
 "device_talk_subtitle" = "Yerel olarak oluşturulan iletiler";
-"device_talk_explain" = "Bu sohbetteki iletiler, Delta Chat uygulamanız tarafından yerel olarak oluşturulur. Üreticiler, uygulama güncelleştirmeleri ve kullanım sırasındaki sorunlar hakkında bilgilendirmek için onu kullanır.";
+"device_talk_explain" = "Bu sohbetteki iletiler, Delta Chat uygulamanız tarafından yerel olarak oluşturulur. Oluşturucuları onu uygulama güncelleştirmeleri ve kullanım sırasındaki sorunlar hakkında bilgilendirmek için kullanır.";
 "device_talk_welcome_message" = "Delta Chat\'e hoş geldiniz! – Delta Chat, diğer yaygın ulak uygulamaları gibi görünür ve hissettirir ama merkezi denetim, izleme içermez ya da sizi, arkadaşlarınızı, iş arkadaşlarınızı ya da ailenizi büyük kuruluşlara satmaz.\n\nTeknik olarak Delta Chat, çağdaş bir sohbet arabirimli bir e-posta uygulamasıdır. 👻 olacaksanız, e-posta yeni bir elbisedir\n\nMilyarlarca insanın herhangi biriyle Delta Chat kullanın: Yalnızca onların e-posta adresini kullanın. Alıcıların Delta Chat\'i kurması, web sitelerini ziyaret etmesi ya da herhangi bir yere kaydolması gerekmez - ancak, elbette isterlerse, onlara 👉 https://get.delta.chat adresini işaret edebilirsiniz";
 "edit_contact" = "Kişiyi düzenle";
 
@@ -468,7 +468,7 @@
 "screenlock_unlock_title" = "Delta Chat kilidini aç";
 "screenlock_unlock_description" = "Delta Chat kilidini açmak için lütfen sistem tanımlı sırrınızı girin.";
 "screenlock_inactivity_timeout" = "Etkisizlik zaman aşımı kilidi";
-"screenlock_inactivity_timeout_explain" = "Belirtilen bir etkisizlik zaman aralığından sonra Delta Chat\'i otomatik kilitle";
+"screenlock_inactivity_timeout_explain" = "Belirtilen bir etkisizlik zaman diliminden sonra Delta Chat\'i otomatik kilitle";
 "screenlock_inactivity_timeout_interval" = "Etkin kalma zamanı";
 
 
@@ -497,11 +497,9 @@
 "contact_not_verified" = "%1$@ doğrulanamıyor.";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "%1$@ için ayarlama değiştirildi.";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%2$d sohbette %1$d yeni ileti";
-"notify_most_recent_from" = "En yeni: %1$@";
+"notify_most_recent_from" = "Şundan en yeni: %1$@";
 "notify_media_message_with_text" = "Ortam iletisi: %s";
 "notify_mark_all_read" = "Tümünü okundu olarak imle";
 "notify_mark_read" = "Okundu imi";
@@ -529,6 +527,7 @@
 "perm_explain_access_to_location_denied" = "Bir konum iliştirmek için uygulama ayarlarına gidin, \"İzinler\"i seçin ve \"Konum\"u etkinleştirin.";
 "perm_enable_bg_reminder_title" = "Delta Chat artalandayken iletileri almak için buraya dokunun.";
 "perm_enable_bg_reminder_text" = "Delta Chat, kaynakların en azını kullanır ve pilinizi boşaltmamaya özen gösterir.";
+"perm_enable_bg_already_done" = "Delta Chat\'in iletileri artalanda almasına zaten izin verdiniz.\n\nArtalanda iletiler hâlâ gelmiyorsa, lütfen sistem ayarlarınızı da denetleyin.";
 
 // dc_str_* resources
 "encrypted_message" = "Şifrelenen ileti";
@@ -584,7 +583,7 @@
 "export_backup_desktop" = "Yedeği dışa aktar";
 "transfer_key_desktop" = "Anahtarı aktar";
 "show_key_transfer_message_desktop" = "Anahtarınız kendinize gönderildi. Diğer aygıta geçin ve ayarlama iletisini açın. Size bir ayarlama kodu sorulmalı. Aşağıdaki sayıları girin:";
-"new_message_from_desktop" = "Yeni iletiyi gönderen";
+"new_message_from_desktop" = "Şundan yeni ileti";
 "unblock_contacts_desktop" = "Kişilerin engellemesini kaldır";
 "none_blocked_desktop" = "Henüz engellenen kişi yok";
 "autocrypt_correct_desktop" = "Autocrypt ayarlaması aktarıldı.";

+ 1 - 4
deltachat-ios/uk.lproj/Localizable.strings

@@ -81,7 +81,7 @@
 "menu_new_contact" = "Новий контакт";
 "menu_new_chat" = "Новий чат";
 "menu_new_group" = "Нова група";
-"menu_new_verified_group" = "Нова перевірена група (експериментальна функція)";
+"menu_new_verified_group" = "Нова перевірена група";
 "menu_send" = "Відправити";
 "menu_toggle_keyboard" = "Увімкнути емодзі-клавіатуру";
 "menu_edit_group" = "Редагувати групу";
@@ -372,8 +372,6 @@
 "contact_not_verified" = "Неможливо підтвердити %1$@";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "Змінені параметри для %1$@";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%1$d нових повідомлень з %2$d чатів";
 "notify_most_recent_from" = "Останнє від: %1$@";
@@ -403,7 +401,6 @@
 "perm_explain_access_to_location_denied" = "Щоб передати місцезнаходження, додатку потрібен доступ до геоданих пристрою, але зараз його не надано. Для надання доступу перейдіть у системне меню налаштувань, у розділі «Додатки» знайдіть Delta Chat, виберіть пункт «Права доступу» і дозвольте доступ до місцезнаходження пристрою.";
 "perm_enable_bg_reminder_title" = "Натисніть тут, щоб отримувати повідомлення, коли Delta Chat знаходиться у фоновому режимі.";
 "perm_enable_bg_reminder_text" = "Delta Chat використовує мінімальні ресурси і дбає про те, щоб не розрядити батарею.";
-
 // dc_str_* resources
 "encrypted_message" = "Зашифроване повідомлення";
 

+ 1 - 1
deltachat-ios/zh-Hant-TW.lproj/Localizable.strings

@@ -82,7 +82,7 @@
 "menu_new_contact" = "新增聯絡人";
 "menu_new_chat" = "新增對話";
 "menu_new_group" = "新增群組";
-"menu_new_verified_group" = "新增驗證專用群組(實驗性)";
+"menu_new_verified_group" = "新增驗證專用群組";
 "menu_send" = "送出";
 "menu_toggle_keyboard" = "切換表情符號鍵盤";
 "menu_edit_group" = "編輯群組";

+ 2 - 5
deltachat-ios/zh-Hant.lproj/Localizable.strings

@@ -105,7 +105,7 @@
 "menu_new_contact" = "新建联系人";
 "menu_new_chat" = "新建聊天";
 "menu_new_group" = "新建群组";
-"menu_new_verified_group" = "新建已验证群组(实验性)";
+"menu_new_verified_group" = "新建已验证群组";
 "menu_send" = "发送";
 "menu_toggle_keyboard" = "切换emoji键盘";
 "menu_edit_group" = "编辑群组";
@@ -155,7 +155,7 @@
 "title_share_location" = "与群组所有成员共享位置";
 "device_talk" = "设备消息";
 "device_talk_subtitle" = "本地生成的消息";
-"device_talk_explain" = "此聊天中的消息是由您的Delta Chat应用本地生成的。 它的制作者使用它来通知应用更新使用过程中的问题。";
+"device_talk_explain" = "此聊天中的消息是由您的Delta Chat应用本地生成的。 它的制作者使用它来通知应用更新以及使用过程中的问题。";
 "device_talk_welcome_message" = "欢迎使用Delta Chat! – Delta Chat看起来、用起来就跟其他流行的通讯应用一样,但是却不涉及中心化的控制、跟踪以及将您、朋友、同事或家庭出卖给大型组织。\n从技术上来说,Delta Chat是具有现代聊天界面的电子邮件应用程序。若您愿意,电子邮件将装扮一新👻\n\n与数十亿人中的任何人一起使用Delta Chat:只需使用他们的电子邮件地址即可。收件人不需要安装Delta Chat、访问网站或是在什么地方注册 - 当然,如果他们愿意,您可以指给他们👉https://get.delta.chat";
 "edit_contact" = "编辑联系人";
 
@@ -497,8 +497,6 @@
 "contact_not_verified" = "无法验证%1$@。";
 // translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message"
 "contact_setup_changed" = "更改了%1$@的设置";
-
-
 // notifications 
 "notify_n_messages_in_m_chats" = "%2$d个聊天中有%1$d条新消息";
 "notify_most_recent_from" = "最新来自:%1$@";
@@ -529,7 +527,6 @@
 "perm_explain_access_to_location_denied" = "要附加位置,请转至应用设置,选择“权限”,然后启用“位置”。";
 "perm_enable_bg_reminder_title" = "点击此处以在Delta Chat处于后台时接收消息。";
 "perm_enable_bg_reminder_text" = "Delta Chat 仅使用少量的资源并且会注意不去耗尽电池电量。";
-
 // dc_str_* resources
 "encrypted_message" = "加密消息";