浏览代码

ran swiftformat

Bastian van de Wetering 6 年之前
父节点
当前提交
1f731df51e

+ 4 - 7
deltachat-ios/AccountSetupController.swift

@@ -455,9 +455,6 @@ extension AccountSetupController: UITextFieldDelegate {
     let currentTag = textField.tag
 
     if textField.accessibilityIdentifier == "emailTextField", showOAuthAlertIfNeeded(emailAddress: textField.text ?? "", handleCancel: {
-      // special case: email field should check for potential oAuth
-
-      // this will activate passwordTextField if oAuth-Dialogue was canceled
       self.passwordCell.textField.becomeFirstResponder()
     }) {
       // all the action is defined in if condition
@@ -577,10 +574,10 @@ class AdvancedSectionHeader: UIView {
 
  // TODO: to add Eye-icon -> uncomment -> add to inputField.rightView
  /*
-   lazy var makeVisibleIcon: UIImageView = {
-   let view = UIImageView(image: )
-   return view
-   }()
+     lazy var makeVisibleIcon: UIImageView = {
+     let view = UIImageView(image: )
+     return view
+     }()
   */
  init() {
  super.init(style: .default, reuseIdentifier: nil)

+ 2 - 2
deltachat-ios/ChatViewController.swift

@@ -199,9 +199,9 @@ class ChatViewController: MessagesViewController {
   override func viewDidLoad() {
     messagesCollectionView.register(CustomCell.self)
     super.viewDidLoad()
-		self.view.backgroundColor = DCColors.chatBackgroundColor
+    view.backgroundColor = DCColors.chatBackgroundColor
 
-		if !MRConfig.configured {
+    if !MRConfig.configured {
       // TODO: display message about nothing being configured
       return
     }

+ 38 - 41
deltachat-ios/Colors.swift

@@ -9,55 +9,52 @@
 import UIKit
 
 struct DCColors {
-	static let primary = UIColor.systemBlue
-	// static let accent =
-
-	static let messagePrimaryColor = UIColor.rgb(red: 220, green: 248, blue: 198)
-	static let messageSecondaryColor = UIColor.rgb(red: 245, green: 245, blue: 245)
-	static let chatBackgroundColor = UIColor.rgb(red: 236, green: 229, blue: 221)
+  static let primary = UIColor.systemBlue
+  // static let accent =
 
+  static let messagePrimaryColor = UIColor.rgb(red: 220, green: 248, blue: 198)
+  static let messageSecondaryColor = UIColor.rgb(red: 245, green: 245, blue: 245)
+  static let chatBackgroundColor = UIColor.rgb(red: 236, green: 229, blue: 221)
 }
 
 enum SystemColor {
-
-	case red
-	case orange
-	case yellow
-	case green
-	case tealBlue
-	case blue
-	case purple
-	case pink
-
-	var uiColor: UIColor {
-		switch self {
-		case .red:
-			return UIColor(red: 255/255, green: 59/255, blue: 48/255, alpha: 1)
-		case .orange:
-			return UIColor(red: 255/255, green: 149/255, blue: 0/255, alpha: 1)
-		case .yellow:
-			return UIColor(red: 255/255, green: 204/255, blue: 0/255, alpha: 1)
-		case .green:
-			return UIColor(red: 76/255, green: 217/255, blue: 100/255, alpha: 1)
-		case .tealBlue:
-			return UIColor(red: 90/255, green: 200/255, blue: 250/255, alpha: 1)
-		case .blue:
-			return UIColor(red: 0/255, green: 122/255, blue: 255/255, alpha: 1)
-		case .purple:
-			return UIColor(red: 88/255, green: 86/255, blue: 214/255, alpha: 1)
-		case .pink:
-			return UIColor(red: 255/255, green: 45/255, blue: 85/255, alpha: 1)
-		}
-	}
+  case red
+  case orange
+  case yellow
+  case green
+  case tealBlue
+  case blue
+  case purple
+  case pink
+
+  var uiColor: UIColor {
+    switch self {
+    case .red:
+      return UIColor(red: 255 / 255, green: 59 / 255, blue: 48 / 255, alpha: 1)
+    case .orange:
+      return UIColor(red: 255 / 255, green: 149 / 255, blue: 0 / 255, alpha: 1)
+    case .yellow:
+      return UIColor(red: 255 / 255, green: 204 / 255, blue: 0 / 255, alpha: 1)
+    case .green:
+      return UIColor(red: 76 / 255, green: 217 / 255, blue: 100 / 255, alpha: 1)
+    case .tealBlue:
+      return UIColor(red: 90 / 255, green: 200 / 255, blue: 250 / 255, alpha: 1)
+    case .blue:
+      return UIColor(red: 0 / 255, green: 122 / 255, blue: 255 / 255, alpha: 1)
+    case .purple:
+      return UIColor(red: 88 / 255, green: 86 / 255, blue: 214 / 255, alpha: 1)
+    case .pink:
+      return UIColor(red: 255 / 255, green: 45 / 255, blue: 85 / 255, alpha: 1)
+    }
+  }
 }
 
-
 extension UIColor {
-	static func rgb(red: CGFloat, green: CGFloat, blue: CGFloat) -> UIColor {
-		return UIColor(red: red/255, green: green/255, blue: blue/255, alpha: 1)
-	}
+  static func rgb(red: CGFloat, green: CGFloat, blue: CGFloat) -> UIColor {
+    return UIColor(red: red / 255, green: green / 255, blue: blue / 255, alpha: 1)
+  }
 
-	static var systemBlue: UIColor {
+  static var systemBlue: UIColor {
     return UIButton(type: .system).tintColor
   }
 }

+ 2 - 2
deltachat-ios/Constants.swift

@@ -22,8 +22,8 @@ struct Constants {
   }
 
   // static let primaryColor = UIColor(red: 81 / 255, green: 73 / 255, blue: 255 / 255, alpha: 1)
-  //static let messagePrimaryColor = Constants.primaryColor.withAlphaComponent(0.5)
- // static let messageSecondaryColor = UIColor(red: 245 / 255, green: 245 / 255, blue: 245 / 255, alpha: 1)
+  // static let messagePrimaryColor = Constants.primaryColor.withAlphaComponent(0.5)
+  // static let messageSecondaryColor = UIColor(red: 245 / 255, green: 245 / 255, blue: 245 / 255, alpha: 1)
 
   static let defaultShadow = UIImage(color: UIColor(hexString: "ff2b82"), size: CGSize(width: 1, height: 1))
   static let onlineShadow = UIImage(color: UIColor(hexString: "3ed67e"), size: CGSize(width: 1, height: 1))

+ 4 - 4
deltachat-ios/DeviceContactsHandler.swift

@@ -11,7 +11,7 @@ import UIKit
 
 class DeviceContactsHandler {
   private let store = CNContactStore()
-	weak var contactListDelegate: ContactListDelegate?
+  weak var contactListDelegate: ContactListDelegate?
 
   private func makeContactString(contacts: [CNContact]) -> String {
     var contactString: String = ""
@@ -29,7 +29,7 @@ class DeviceContactsHandler {
     let storedContacts = fetchContactsWithEmailFromDevice()
     let contactString = makeContactString(contacts: storedContacts)
     dc_add_address_book(mailboxPointer, contactString)
-		contactListDelegate?.deviceContactsImported()
+    contactListDelegate?.deviceContactsImported()
   }
 
   private func fetchContactsWithEmailFromDevice() -> [CNContact] {
@@ -61,9 +61,9 @@ class DeviceContactsHandler {
     switch CNContactStore.authorizationStatus(for: .contacts) {
     case .authorized:
       addContactsToCore()
-      self.contactListDelegate?.accessGranted()
+      contactListDelegate?.accessGranted()
     case .denied:
-      self.contactListDelegate?.accessDenied()
+      contactListDelegate?.accessDenied()
     case .restricted, .notDetermined:
       store.requestAccess(for: .contacts) { [unowned self] granted, _ in
         if granted {

+ 105 - 107
deltachat-ios/Extensions/Extensions.swift

@@ -9,131 +9,129 @@
 import UIKit
 
 extension String {
-	func containsCharacters() -> Bool {
-		return !trimmingCharacters(in: [" "]).isEmpty
-	}
-
-	// O(n) - returns indexes of subsequences -> can be used to highlight subsequence within string
-	func contains(subSequence: String) -> [Int] {
-		if subSequence.count > self.count {
-			return []
-		}
-
-		let str = self.lowercased()
-		let sub = subSequence.lowercased()
-
-		var j = 0
-
-		var foundIndexes: [Int] = []
-
-		for (index, char) in str.enumerated() {
-			if j == sub.count {
-				break
-			}
-
-			if char == sub.subScript(j) {
-				foundIndexes.append(index)
-				j += 1
-
-			}
-		}
-		return foundIndexes.count == sub.count ? foundIndexes : []
-	}
-
-	func subScript(_ i: Int) -> Character {
-		return self[index(startIndex, offsetBy: i)]
-	}
-
-	func boldAt(indexes: [Int], fontSize: CGFloat) -> NSAttributedString {
-		let attributedText = NSMutableAttributedString.init(string: self)
-
-		for index in indexes {
-			if index < 0 || self.count <= index {
-				break
-			}
-			attributedText.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: fontSize), range: NSMakeRange(index, 1))
-		}
-		return attributedText
-	}
+  func containsCharacters() -> Bool {
+    return !trimmingCharacters(in: [" "]).isEmpty
+  }
+
+  // O(n) - returns indexes of subsequences -> can be used to highlight subsequence within string
+  func contains(subSequence: String) -> [Int] {
+    if subSequence.count > count {
+      return []
+    }
+
+    let str = lowercased()
+    let sub = subSequence.lowercased()
+
+    var j = 0
+
+    var foundIndexes: [Int] = []
+
+    for (index, char) in str.enumerated() {
+      if j == sub.count {
+        break
+      }
+
+      if char == sub.subScript(j) {
+        foundIndexes.append(index)
+        j += 1
+      }
+    }
+    return foundIndexes.count == sub.count ? foundIndexes : []
+  }
+
+  func subScript(_ i: Int) -> Character {
+    return self[index(startIndex, offsetBy: i)]
+  }
+
+  func boldAt(indexes: [Int], fontSize: CGFloat) -> NSAttributedString {
+    let attributedText = NSMutableAttributedString(string: self)
+
+    for index in indexes {
+      if index < 0 || count <= index {
+        break
+      }
+      attributedText.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: fontSize), range: NSMakeRange(index, 1))
+    }
+    return attributedText
+  }
 }
 
 extension URL {
-	public var queryParameters: [String: String]? {
-		guard
-			let components = URLComponents(url: self, resolvingAgainstBaseURL: true),
-			let queryItems = components.queryItems else { return nil }
-		return queryItems.reduce(into: [String: String]()) { result, item in
-			result[item.name] = item.value
-		}
-	}
+  public var queryParameters: [String: String]? {
+    guard
+      let components = URLComponents(url: self, resolvingAgainstBaseURL: true),
+      let queryItems = components.queryItems else { return nil }
+    return queryItems.reduce(into: [String: String]()) { result, item in
+      result[item.name] = item.value
+    }
+  }
 }
 
 extension Dictionary {
-	func percentEscaped() -> String {
-		return map { key, value in
-			let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
-			let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
-			return escapedKey + "=" + escapedValue
-			}
-			.joined(separator: "&")
-	}
+  func percentEscaped() -> String {
+    return map { key, value in
+      let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
+      let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
+      return escapedKey + "=" + escapedValue
+    }
+    .joined(separator: "&")
+  }
 }
 
 extension CharacterSet {
-	static let urlQueryValueAllowed: CharacterSet = {
-		let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
-		let subDelimitersToEncode = "!$&'()*+,;="
-
-		var allowed = CharacterSet.urlQueryAllowed
-		allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
-		return allowed
-	}()
+  static let urlQueryValueAllowed: CharacterSet = {
+    let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
+    let subDelimitersToEncode = "!$&'()*+,;="
+
+    var allowed = CharacterSet.urlQueryAllowed
+    allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
+    return allowed
+  }()
 }
 
 extension URLSession {
-	func synchronousDataTask(request: URLRequest) -> (Data?, URLResponse?, Error?) {
-		var data: Data?
-		var response: URLResponse?
-		var error: Error?
+  func synchronousDataTask(request: URLRequest) -> (Data?, URLResponse?, Error?) {
+    var data: Data?
+    var response: URLResponse?
+    var error: Error?
 
-		let semaphore = DispatchSemaphore(value: 0)
+    let semaphore = DispatchSemaphore(value: 0)
 
-		let task = dataTask(with: request) {
-			data = $0
-			response = $1
-			error = $2
+    let task = dataTask(with: request) {
+      data = $0
+      response = $1
+      error = $2
 
-			semaphore.signal()
-		}
-		task.resume()
+      semaphore.signal()
+    }
+    task.resume()
 
-		_ = semaphore.wait(timeout: .distantFuture)
+    _ = semaphore.wait(timeout: .distantFuture)
 
-		return (data, response, error)
-	}
+    return (data, response, error)
+  }
 }
 
 extension MRContact {
-	func contains(searchText text: String) -> [ContactHighlights] {
-
-		var nameIndexes = [Int]()
-		var emailIndexes = [Int]()
-
-		let contactString = name + email
-		let subsequenceIndexes = contactString.contains(subSequence: text)
-
-		if !subsequenceIndexes.isEmpty {
-			for index in subsequenceIndexes {
-				if index < name.count {
-					nameIndexes.append(index)
-				} else {
-					let emailIndex = index - name.count
-					emailIndexes.append(emailIndex)
-				}
-			}
-			return [ContactHighlights(contactDetail: .NAME, indexes: nameIndexes), ContactHighlights(contactDetail: .EMAIL, indexes: emailIndexes)]
-		} else {
-			return []
-		}
-	}
+  func contains(searchText text: String) -> [ContactHighlights] {
+    var nameIndexes = [Int]()
+    var emailIndexes = [Int]()
+
+    let contactString = name + email
+    let subsequenceIndexes = contactString.contains(subSequence: text)
+
+    if !subsequenceIndexes.isEmpty {
+      for index in subsequenceIndexes {
+        if index < name.count {
+          nameIndexes.append(index)
+        } else {
+          let emailIndex = index - name.count
+          emailIndexes.append(emailIndex)
+        }
+      }
+      return [ContactHighlights(contactDetail: .NAME, indexes: nameIndexes), ContactHighlights(contactDetail: .EMAIL, indexes: emailIndexes)]
+    } else {
+      return []
+    }
+  }
 }

+ 234 - 239
deltachat-ios/NewChatViewController.swift

@@ -16,44 +16,44 @@ protocol ChatDisplayer: class {
 }
 
 class NewChatViewController: UITableViewController {
+  private lazy var searchController: UISearchController = {
+    let searchController = UISearchController(searchResultsController: nil)
+    searchController.searchResultsUpdater = self
+    searchController.obscuresBackgroundDuringPresentation = false
+    searchController.searchBar.placeholder = "Search Contact"
+    return searchController
+  }()
+
+  var contactIds: [Int] = Utils.getContactIds() {
+    didSet {
+      tableView.reloadData()
+    }
+  }
 
-	private lazy var searchController: UISearchController = {
-		let searchController = UISearchController(searchResultsController: nil)
-		searchController.searchResultsUpdater = self
-		searchController.obscuresBackgroundDuringPresentation = false
-		searchController.searchBar.placeholder = "Search Contact"
-		return searchController
-	}()
-
-	var contactIds: [Int] = Utils.getContactIds() {
-		didSet {
-			tableView.reloadData()
-		}
-	}
-
-	// contactWithSearchResults.indexesToHightLight empty by default
-	var contacts:[ContactWithSearchResults] {
-		return contactIds.map({ return ContactWithSearchResults(contact: MRContact(id: $0), indexesToHighlight: [])})
-	}
-
-	// used when seachbar is active
-	var filteredContacts: [ContactWithSearchResults] = []
-
-	// searchBar active?
-	func isFiltering() -> Bool {
-		return searchController.isActive && !searchBarIsEmpty()
-	}
+  // contactWithSearchResults.indexesToHightLight empty by default
+  var contacts: [ContactWithSearchResults] {
+    return contactIds.map { ContactWithSearchResults(contact: MRContact(id: $0), indexesToHighlight: []) }
+  }
+
+  // used when seachbar is active
+  var filteredContacts: [ContactWithSearchResults] = []
+
+  // searchBar active?
+  func isFiltering() -> Bool {
+    return searchController.isActive && !searchBarIsEmpty()
+  }
 
   weak var chatDisplayer: ChatDisplayer?
 
   var syncObserver: Any?
   var hud: ProgressHud?
 
-	lazy var deviceContactHandler: DeviceContactsHandler = {
-		let handler = DeviceContactsHandler()
-		handler.contactListDelegate = self
-		return handler
-	}()
+  lazy var deviceContactHandler: DeviceContactsHandler = {
+    let handler = DeviceContactsHandler()
+    handler.contactListDelegate = self
+    return handler
+  }()
+
   var deviceContactAccessGranted: Bool = false {
     didSet {
       tableView.reloadData()
@@ -78,27 +78,26 @@ class NewChatViewController: UITableViewController {
     navigationItem.rightBarButtonItem = cancelButton
 
     deviceContactHandler.importDeviceContacts()
-		navigationItem.searchController = searchController
-		definesPresentationContext = true // to make sure searchbar will only be shown in this viewController
+    navigationItem.searchController = searchController
+    definesPresentationContext = true // to make sure searchbar will only be shown in this viewController
   }
 
-	override func viewWillAppear(_ animated: Bool) {
-		super.viewWillAppear(animated)
-		self.deviceContactAccessGranted = CNContactStore.authorizationStatus(for: .contacts) == .authorized
-		contactIds = Utils.getContactIds()
+  override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    deviceContactAccessGranted = CNContactStore.authorizationStatus(for: .contacts) == .authorized
+    contactIds = Utils.getContactIds()
 
-		// this will show the searchbar on launch -> will be set back to true on viewDidAppear
-		if #available(iOS 11.0, *) {
-			navigationItem.hidesSearchBarWhenScrolling = false
-		}
-
-	}
+    // this will show the searchbar on launch -> will be set back to true on viewDidAppear
+    if #available(iOS 11.0, *) {
+      navigationItem.hidesSearchBarWhenScrolling = false
+    }
+  }
 
   override func viewDidAppear(_ animated: Bool) {
     super.viewDidAppear(animated)
-		if #available(iOS 11.0, *) {
-			navigationItem.hidesSearchBarWhenScrolling = true
-		}
+    if #available(iOS 11.0, *) {
+      navigationItem.hidesSearchBarWhenScrolling = true
+    }
 
     let nc = NotificationCenter.default
     syncObserver = nc.addObserver(
@@ -140,160 +139,159 @@ class NewChatViewController: UITableViewController {
   // MARK: - Table view data source
 
   override func numberOfSections(in _: UITableView) -> Int {
-		return deviceContactAccessGranted ? 2 : 3
+    return deviceContactAccessGranted ? 2 : 3
   }
 
   override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
-		if section == 0 {
-			return 3
-		} else if section == 1 {
-			if deviceContactAccessGranted {
-				return isFiltering() ? filteredContacts.count : contacts.count
-			} else {
-				return 1
-			}
-		} else {
-			return isFiltering() ? filteredContacts.count : contacts.count
-		}
+    if section == 0 {
+      return 3
+    } else if section == 1 {
+      if deviceContactAccessGranted {
+        return isFiltering() ? filteredContacts.count : contacts.count
+      } else {
+        return 1
+      }
+    } else {
+      return isFiltering() ? filteredContacts.count : contacts.count
+    }
   }
 
   override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-		let section = indexPath.section
+    let section = indexPath.section
     let row = indexPath.row
 
-		if section == 0 {
-			if row == 0 {
-				// new group row
-				let cell: UITableViewCell
-				if let c = tableView.dequeueReusableCell(withIdentifier: "newContactCell") {
-					cell = c
-				} else {
-					cell = UITableViewCell(style: .default, reuseIdentifier: "newContactCell")
-				}
-				cell.textLabel?.text = "New Group"
-				cell.textLabel?.textColor = view.tintColor
-
-				return cell
-			}
-			if row == 1 {
-				// new contact row
-				let cell: UITableViewCell
-				if let c = tableView.dequeueReusableCell(withIdentifier: "scanGroupCell") {
-					cell = c
-				} else {
-					cell = UITableViewCell(style: .default, reuseIdentifier: "scanGroupCell")
-				}
-				cell.textLabel?.text = "Scan Group QR Code"
-				cell.textLabel?.textColor = view.tintColor
-
-				return cell
-			}
-
-			if row == 2 {
-				// 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 = "New Contact"
-				cell.textLabel?.textColor = view.tintColor
-
-				return cell
-			}
-		} else if section == 1 {
-			if deviceContactAccessGranted {
-				let cell: ContactCell
-				if let c = tableView.dequeueReusableCell(withIdentifier: "contactCell") as? ContactCell {
-					cell = c
-				} else {
-					cell = ContactCell(style: .default, reuseIdentifier: "contactCell")
-				}
-				let contact: ContactWithSearchResults = isFiltering() ? filteredContacts[row] : contacts[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")
-				}
-				cell.actionTitle = "Import Device Contacts"
-				return cell
-			}
-		} else {
-			// section 2
-			let cell: ContactCell
-			if let c = tableView.dequeueReusableCell(withIdentifier: "contactCell") as? ContactCell {
-				cell = c
-			} else {
-				cell = ContactCell(style: .default, reuseIdentifier: "contactCell")
-			}
-
-			let contact: ContactWithSearchResults = isFiltering() ? filteredContacts[row] : contacts[row]
-			updateContactCell(cell: cell, contactWithHighlight: contact)
-			return cell
-		}
-		// will actually never get here but compiler not happy
-		return UITableViewCell(style: .default, reuseIdentifier: "cell")
+    if section == 0 {
+      if row == 0 {
+        // new group row
+        let cell: UITableViewCell
+        if let c = tableView.dequeueReusableCell(withIdentifier: "newContactCell") {
+          cell = c
+        } else {
+          cell = UITableViewCell(style: .default, reuseIdentifier: "newContactCell")
+        }
+        cell.textLabel?.text = "New Group"
+        cell.textLabel?.textColor = view.tintColor
+
+        return cell
+      }
+      if row == 1 {
+        // new contact row
+        let cell: UITableViewCell
+        if let c = tableView.dequeueReusableCell(withIdentifier: "scanGroupCell") {
+          cell = c
+        } else {
+          cell = UITableViewCell(style: .default, reuseIdentifier: "scanGroupCell")
+        }
+        cell.textLabel?.text = "Scan Group QR Code"
+        cell.textLabel?.textColor = view.tintColor
+
+        return cell
+      }
+
+      if row == 2 {
+        // 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 = "New Contact"
+        cell.textLabel?.textColor = view.tintColor
+
+        return cell
+      }
+    } else if section == 1 {
+      if deviceContactAccessGranted {
+        let cell: ContactCell
+        if let c = tableView.dequeueReusableCell(withIdentifier: "contactCell") as? ContactCell {
+          cell = c
+        } else {
+          cell = ContactCell(style: .default, reuseIdentifier: "contactCell")
+        }
+        let contact: ContactWithSearchResults = isFiltering() ? filteredContacts[row] : contacts[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")
+        }
+        cell.actionTitle = "Import Device Contacts"
+        return cell
+      }
+    } else {
+      // section 2
+      let cell: ContactCell
+      if let c = tableView.dequeueReusableCell(withIdentifier: "contactCell") as? ContactCell {
+        cell = c
+      } else {
+        cell = ContactCell(style: .default, reuseIdentifier: "contactCell")
+      }
+
+      let contact: ContactWithSearchResults = isFiltering() ? filteredContacts[row] : contacts[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) {
     let row = indexPath.row
-		let section = indexPath.section
-
-		if section == 0 {
-			if row == 0 {
-				let newGroupController = NewGroupViewController()
-				navigationController?.pushViewController(newGroupController, animated: true)
-			}
-			if row == 1 {
-				if UIImagePickerController.isSourceTypeAvailable(.camera) {
-					let controller = QrCodeReaderController()
-					controller.delegate = self
-					present(controller, animated: true, completion: nil)
-
-				} else {
-					let alert = UIAlertController(title: "Camera is not available", message: nil, preferredStyle: .alert)
-					alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: { _ in
-						self.dismiss(animated: true, completion: nil)
-					}))
-					present(alert, animated: true, completion: nil)
-				}
-			}
-			if row == 2 {
-				let newContactController = NewContactController()
-				navigationController?.pushViewController(newContactController, animated: true)
-			}
-		} else if section == 1 {
-
-			if deviceContactAccessGranted {
-				if searchController.isActive {
-					// edge case: when searchController is active but searchBar is empty -> filteredContacts is empty, so we fallback to contactIds
-					let contactId = isFiltering() ? filteredContacts[row].contact.id : self.contactIds[row]
-					searchController.dismiss(animated: false, completion: {
-						self.dismiss(animated: false, completion: {
-							self.chatDisplayer?.displayNewChat(contactId: contactId)
-						})
-					})
-				} else {
-					let contactId = contactIds[row]
-					dismiss(animated: false) {
-						self.chatDisplayer?.displayNewChat(contactId: contactId)
-					}
-				}
-			} else {
-				showSettingsAlert()
-			}
-		} else {
-			let contactIndex = row
-			let contactId = contactIds[contactIndex]
-			dismiss(animated: false) {
-				self.chatDisplayer?.displayNewChat(contactId: contactId)
-			}
-		}
+    let section = indexPath.section
+
+    if section == 0 {
+      if row == 0 {
+        let newGroupController = NewGroupViewController()
+        navigationController?.pushViewController(newGroupController, animated: true)
+      }
+      if row == 1 {
+        if UIImagePickerController.isSourceTypeAvailable(.camera) {
+          let controller = QrCodeReaderController()
+          controller.delegate = self
+          present(controller, animated: true, completion: nil)
+
+        } else {
+          let alert = UIAlertController(title: "Camera is not available", message: nil, preferredStyle: .alert)
+          alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: { _ in
+            self.dismiss(animated: true, completion: nil)
+          }))
+          present(alert, animated: true, completion: nil)
+        }
+      }
+      if row == 2 {
+        let newContactController = NewContactController()
+        navigationController?.pushViewController(newContactController, animated: true)
+      }
+    } else if section == 1 {
+      if deviceContactAccessGranted {
+        if searchController.isActive {
+          // edge case: when searchController is active but searchBar is empty -> filteredContacts is empty, so we fallback to contactIds
+          let contactId = isFiltering() ? filteredContacts[row].contact.id : contactIds[row]
+          searchController.dismiss(animated: false, completion: {
+            self.dismiss(animated: false, completion: {
+              self.chatDisplayer?.displayNewChat(contactId: contactId)
+            })
+          })
+        } else {
+          let contactId = contactIds[row]
+          dismiss(animated: false) {
+            self.chatDisplayer?.displayNewChat(contactId: contactId)
+          }
+        }
+      } else {
+        showSettingsAlert()
+      }
+    } else {
+      let contactIndex = row
+      let contactId = contactIds[contactIndex]
+      dismiss(animated: false) {
+        self.chatDisplayer?.displayNewChat(contactId: contactId)
+      }
+    }
   }
 
   override func tableView(_: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
@@ -308,42 +306,39 @@ class NewChatViewController: UITableViewController {
     }
   }
 
-	private func updateContactCell(cell: ContactCell, contactWithHighlight: ContactWithSearchResults) {
-
-		let contact = contactWithHighlight.contact
+  private func updateContactCell(cell: ContactCell, contactWithHighlight: ContactWithSearchResults) {
+    let contact = contactWithHighlight.contact
 
-		if let nameHighlightedIndexes = contactWithHighlight.indexesToHighlight.filter({$0.contactDetail == .NAME}).first,
-			let emailHighlightedIndexes = contactWithHighlight.indexesToHighlight.filter({$0.contactDetail == .EMAIL}).first {
-			// gets here when contact is a result of current search -> highlights relevant indexes
-			let nameLabelFontSize = cell.nameLabel.font.pointSize
-			let emailLabelFontSize = cell.emailLabel.font.pointSize
+    if let nameHighlightedIndexes = contactWithHighlight.indexesToHighlight.filter({ $0.contactDetail == .NAME }).first,
+      let emailHighlightedIndexes = contactWithHighlight.indexesToHighlight.filter({ $0.contactDetail == .EMAIL }).first {
+      // gets here when contact is a result of current search -> highlights relevant indexes
+      let nameLabelFontSize = cell.nameLabel.font.pointSize
+      let emailLabelFontSize = cell.emailLabel.font.pointSize
 
-			cell.nameLabel.attributedText = contact.name.boldAt(indexes: nameHighlightedIndexes.indexes, fontSize: nameLabelFontSize)
-			cell.emailLabel.attributedText = contact.email.boldAt(indexes: emailHighlightedIndexes.indexes, fontSize: emailLabelFontSize)
-		} else {
-			cell.nameLabel.text = contact.name
-			cell.emailLabel.text = contact.email
-		}
-		cell.initialsLabel.text = Utils.getInitials(inputName: contact.name)
-		cell.setColor(contact.color)
-		cell.accessoryType = .detailDisclosureButton
-	}
-
-	private func searchBarIsEmpty() -> Bool {
-		return searchController.searchBar.text?.isEmpty ?? true
-	}
-
-	private func filterContentForSearchText(_ searchText: String, scope: String = "All") {
+      cell.nameLabel.attributedText = contact.name.boldAt(indexes: nameHighlightedIndexes.indexes, fontSize: nameLabelFontSize)
+      cell.emailLabel.attributedText = contact.email.boldAt(indexes: emailHighlightedIndexes.indexes, fontSize: emailLabelFontSize)
+    } else {
+      cell.nameLabel.text = contact.name
+      cell.emailLabel.text = contact.email
+    }
+    cell.initialsLabel.text = Utils.getInitials(inputName: contact.name)
+    cell.setColor(contact.color)
+    cell.accessoryType = .detailDisclosureButton
+  }
 
-		let contactsWithHighlights:[ContactWithSearchResults] = contacts.map({contact in
-			let indexes = contact.contact.contains(searchText: searchText)
-			return ContactWithSearchResults(contact: contact.contact, indexesToHighlight: indexes)
-		})
+  private func searchBarIsEmpty() -> Bool {
+    return searchController.searchBar.text?.isEmpty ?? true
+  }
 
-		filteredContacts = contactsWithHighlights.filter({!$0.indexesToHighlight.isEmpty})
-		tableView.reloadData()
-	}
+  private func filterContentForSearchText(_ searchText: String, scope _: String = "All") {
+    let contactsWithHighlights: [ContactWithSearchResults] = contacts.map { contact in
+      let indexes = contact.contact.contains(searchText: searchText)
+      return ContactWithSearchResults(contact: contact.contact, indexesToHighlight: indexes)
+    }
 
+    filteredContacts = contactsWithHighlights.filter { !$0.indexesToHighlight.isEmpty }
+    tableView.reloadData()
+  }
 }
 
 extension NewChatViewController: QrCodeReaderDelegate {
@@ -376,10 +371,10 @@ extension NewChatViewController: QrCodeReaderDelegate {
 }
 
 extension NewChatViewController: ContactListDelegate {
-	func deviceContactsImported() {
-		self.contactIds = Utils.getContactIds()
-//		tableView.reloadData()
-	}
+  func deviceContactsImported() {
+    contactIds = Utils.getContactIds()
+    //		tableView.reloadData()
+  }
 
   func accessGranted() {
     deviceContactAccessGranted = true
@@ -391,9 +386,10 @@ extension NewChatViewController: ContactListDelegate {
 
   private func showSettingsAlert() {
     let alert = UIAlertController(
-			title: "Import Contacts from to your device",
-			message: "To chat with contacts from your device open the settings menu and enable the Contacts option",
-			preferredStyle: .alert)
+      title: "Import Contacts from to your device",
+      message: "To chat with contacts from your device open the settings menu and enable the Contacts option",
+      preferredStyle: .alert
+    )
     alert.addAction(UIAlertAction(title: "Open Settings", style: .default) { _ in
       UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
     })
@@ -404,32 +400,31 @@ extension NewChatViewController: ContactListDelegate {
 }
 
 extension NewChatViewController: UISearchResultsUpdating {
-
-	func updateSearchResults(for searchController: UISearchController) {
-		if let searchText = searchController.searchBar.text {
-			filterContentForSearchText(searchText)
-		}
-	}
+  func updateSearchResults(for searchController: UISearchController) {
+    if let searchText = searchController.searchBar.text {
+      filterContentForSearchText(searchText)
+    }
+  }
 }
 
 protocol ContactListDelegate: class {
   func accessGranted()
   func accessDenied()
-	func deviceContactsImported()
+  func deviceContactsImported()
 }
 
 // TODO: find better name
 struct ContactHighlights {
-	let contactDetail: ContactDetail
-	let indexes:[Int]
+  let contactDetail: ContactDetail
+  let indexes: [Int]
 }
 
 enum ContactDetail {
-	case NAME
-	case EMAIL
+  case NAME
+  case EMAIL
 }
 
 struct ContactWithSearchResults {
-	let contact: MRContact
-	let indexesToHighlight:[ContactHighlights]
+  let contact: MRContact
+  let indexesToHighlight: [ContactHighlights]
 }

+ 19 - 19
deltachat-ios/TopViews/ChatListController.swift

@@ -11,14 +11,14 @@ import UIKit
 class ChatListController: UIViewController {
   var chatList: MRChatList?
 
-	lazy var chatTable: UITableView = {
-		let chatTable = UITableView()
-		chatTable.dataSource = chatTableDataSource
-		chatTableDelegate.chatPresenter = self
-		chatTable.delegate = chatTableDelegate
-		chatTable.rowHeight = 80
-		return chatTable
-	}()
+  lazy var chatTable: UITableView = {
+    let chatTable = UITableView()
+    chatTable.dataSource = chatTableDataSource
+    chatTableDelegate.chatPresenter = self
+    chatTable.delegate = chatTableDelegate
+    chatTable.rowHeight = 80
+    return chatTable
+  }()
 
   let chatTableDataSource = ChatTableDataSource()
   let chatTableDelegate = ChatTableDelegate()
@@ -93,17 +93,17 @@ class ChatListController: UIViewController {
     newButton.tintColor = DCColors.primary
     navigationItem.rightBarButtonItem = newButton
 
-		setupChatTable()
-	}
-
-	private func setupChatTable() {
-		view.addSubview(chatTable)
-		chatTable.translatesAutoresizingMaskIntoConstraints = false
-		chatTable.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
-		chatTable.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
-		chatTable.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
-		chatTable.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
-	}
+    setupChatTable()
+  }
+
+  private func setupChatTable() {
+    view.addSubview(chatTable)
+    chatTable.translatesAutoresizingMaskIntoConstraints = false
+    chatTable.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
+    chatTable.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
+    chatTable.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
+    chatTable.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
+  }
 
   @objc func didPressNewChat() {
     let ncv = NewChatViewController()

+ 38 - 42
deltachat-iosTests/deltachat_iosTests.swift

@@ -6,61 +6,57 @@
 //  Copyright © 2019 Jonas Reinsch. All rights reserved.
 //
 
-import XCTest
 @testable import deltachat_ios
+import XCTest
 
 class DeltachatTests: XCTestCase {
+  var testContact: MRContact?
 
-	var testContact: MRContact?
-
-	override func setUp() {
-		let contactIds = Utils.getContactIds()
-
-		let contacts = contactIds.map({ return MRContact(id: $0) })
-
-		testContact = contacts.filter({$0.name == "John Appleseed"}).first
-		// Put setup code here. This method is called before the invocation of each test method in the class.
-	}
-
-	override func tearDown() {
-		// Put teardown code here. This method is called after the invocation of each test method in the class.
-	}
+  override func setUp() {
+    let contactIds = Utils.getContactIds()
 
-	func testContactSearchForSubsequences() {
+    let contacts = contactIds.map { MRContact(id: $0) }
 
-		// this test will only success if run on a simulator (assuming one of the sample contacts is named John Appleseed)
-		guard let appleseedContact = testContact else {
-			return
-		}
+    testContact = contacts.filter { $0.name == "John Appleseed" }.first
+    // Put setup code here. This method is called before the invocation of each test method in the class.
+  }
 
-		XCTAssert(appleseedContact.name == "John Appleseed", "Test contacts name is John Appleseed")
-		XCTAssert(appleseedContact.email == "John-Appleseed@mac.com", "Test contacts email is john.appleseed@mac.com")
+  override func tearDown() {
+    // Put teardown code here. This method is called after the invocation of each test method in the class.
+  }
 
-		let indexDetailA = appleseedContact.contains(searchText: "jmc")
+  func testContactSearchForSubsequences() {
+    // this test will only success if run on a simulator (assuming one of the sample contacts is named John Appleseed)
+    guard let appleseedContact = testContact else {
+      return
+    }
 
-		XCTAssert(indexDetailA.count == 2)
-		XCTAssert(indexDetailA[0].contactDetail == .NAME)
-		XCTAssert(indexDetailA[0].indexes == [0])
-		XCTAssert(indexDetailA[1].indexes == [15, 17])
+    XCTAssert(appleseedContact.name == "John Appleseed", "Test contacts name is John Appleseed")
+    XCTAssert(appleseedContact.email == "John-Appleseed@mac.com", "Test contacts email is john.appleseed@mac.com")
 
-		let indexDetailB = appleseedContact.contains(searchText: "joj")
-		XCTAssert(indexDetailB[0].indexes == [0, 1])
-		XCTAssert(indexDetailB[1].indexes == [0])
+    let indexDetailA = appleseedContact.contains(searchText: "jmc")
 
-		let indexDetailC = appleseedContact.contains(searchText: "jojh")
-		XCTAssert(indexDetailC[0].indexes == [0, 1])
-		XCTAssert(indexDetailC[1].indexes == [0, 2])
+    XCTAssert(indexDetailA.count == 2)
+    XCTAssert(indexDetailA[0].contactDetail == .NAME)
+    XCTAssert(indexDetailA[0].indexes == [0])
+    XCTAssert(indexDetailA[1].indexes == [15, 17])
 
-		let indexDetailD = appleseedContact.contains(searchText: "joz")
-		XCTAssert(indexDetailD.isEmpty)
-	}
+    let indexDetailB = appleseedContact.contains(searchText: "joj")
+    XCTAssert(indexDetailB[0].indexes == [0, 1])
+    XCTAssert(indexDetailB[1].indexes == [0])
 
+    let indexDetailC = appleseedContact.contains(searchText: "jojh")
+    XCTAssert(indexDetailC[0].indexes == [0, 1])
+    XCTAssert(indexDetailC[1].indexes == [0, 2])
 
-	func testPerformanceExample() {
-		// This is an example of a performance test case.
-		self.measure {
-			// Put the code you want to measure the time of here.
-		}
-	}
+    let indexDetailD = appleseedContact.contains(searchText: "joz")
+    XCTAssert(indexDetailD.isEmpty)
+  }
 
+  func testPerformanceExample() {
+    // This is an example of a performance test case.
+    measure {
+      // Put the code you want to measure the time of here.
+    }
+  }
 }