ソースを参照

Merge pull request #118 from deltachat/EnhancementBranch

Enhancements
nayooti 6 年 前
コミット
31047f575b

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

@@ -54,6 +54,7 @@
 		AE851AC9227C77CF00ED86F0 /* Media.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE851AC8227C77CF00ED86F0 /* Media.swift */; };
 		AE851ACE227CA54400ED86F0 /* InitialsBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE851ACD227CA54300ED86F0 /* InitialsBadge.swift */; };
 		AE851AD0227DF50900ED86F0 /* GroupChatDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE851ACF227DF50900ED86F0 /* GroupChatDetailViewController.swift */; };
+		AE9DAF0D22C1215D004C9591 /* EditContactController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE9DAF0C22C1215D004C9591 /* EditContactController.swift */; };
 		AEACE2DD1FB323CA00DCDD78 /* ChatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEACE2DC1FB323CA00DCDD78 /* ChatViewController.swift */; };
 		AEACE2DF1FB3246400DCDD78 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEACE2DE1FB3246400DCDD78 /* Message.swift */; };
 		AEACE2E31FB32B5C00DCDD78 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEACE2E21FB32B5C00DCDD78 /* Constants.swift */; };
@@ -135,6 +136,7 @@
 		AE851AC8227C77CF00ED86F0 /* Media.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Media.swift; sourceTree = "<group>"; };
 		AE851ACD227CA54300ED86F0 /* InitialsBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitialsBadge.swift; sourceTree = "<group>"; };
 		AE851ACF227DF50900ED86F0 /* GroupChatDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupChatDetailViewController.swift; sourceTree = "<group>"; };
+		AE9DAF0C22C1215D004C9591 /* EditContactController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditContactController.swift; sourceTree = "<group>"; };
 		AEACE2DC1FB323CA00DCDD78 /* ChatViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatViewController.swift; sourceTree = "<group>"; };
 		AEACE2DE1FB3246400DCDD78 /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = "<group>"; };
 		AEACE2E21FB32B5C00DCDD78 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
@@ -294,6 +296,7 @@
 				AEE6EC472283045D00EDC689 /* EditSettingsController.swift */,
 				AE52EA1F229EB9F000C586C9 /* EditGroupViewController.swift */,
 				AE4AEE3422B1030D000AA495 /* PreviewController.swift */,
+				AE9DAF0C22C1215D004C9591 /* EditContactController.swift */,
 			);
 			path = Controller;
 			sourceTree = "<group>";
@@ -657,6 +660,7 @@
 				AE851AD0227DF50900ED86F0 /* GroupChatDetailViewController.swift in Sources */,
 				7A451DB01FB1F84900177250 /* AppCoordinator.swift in Sources */,
 				AE38B31822672DFC00EC37A1 /* ActionCell.swift in Sources */,
+				AE9DAF0D22C1215D004C9591 /* EditContactController.swift in Sources */,
 				785BE16821E247F1003BE98C /* MessageInfoViewController.swift in Sources */,
 				AE851AC5227C755A00ED86F0 /* Protocols.swift in Sources */,
 				AE728F15229D5C390047565B /* PhotoPickerAlertAction.swift in Sources */,

+ 23 - 0
deltachat-ios/Assets.xcassets/ic_add.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "ic_add.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_add_2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_add_3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

BIN
deltachat-ios/Assets.xcassets/ic_add.imageset/ic_add.png


BIN
deltachat-ios/Assets.xcassets/ic_add.imageset/ic_add_2x.png


BIN
deltachat-ios/Assets.xcassets/ic_add.imageset/ic_add_3x.png


+ 13 - 8
deltachat-ios/Controller/AccountSetupController.swift

@@ -14,8 +14,7 @@ class AccountSetupController: UITableViewController {
 
 	weak var coordinator: AccountSetupCoordinator?
 
-	private var userHasCancelledOAuth = false
-	private var useCustomSettings = false
+	private var skipOauth = false
 
 	private var backupProgressObserver: Any?
 	private var configureProgressObserver: Any?
@@ -151,7 +150,11 @@ class AccountSetupController: UITableViewController {
 	}()
 
 	// this loginButton can be enabled and disabled
-	lazy var loginButton: UIBarButtonItem = UIBarButtonItem(title: "Login", style: .done, target: self, action: #selector(loginButtonPressed))
+	private lazy var loginButton: UIBarButtonItem = {
+		let button = UIBarButtonItem(title: "Login", style: .done, target: self, action: #selector(loginButtonPressed))
+		button.isEnabled = dc_is_configured(mailboxPointer) == 0
+		return button
+	}()
 
 	private lazy var basicSectionCells: [UITableViewCell] = [emailCell, passwordCell]
 	private lazy var restoreCells: [UITableViewCell] = [restoreCell]
@@ -358,7 +361,7 @@ class AccountSetupController: UITableViewController {
 		MRConfig.addr = emailAddress
 		MRConfig.mailPw = password
 
-		if useCustomSettings && !skipAdvanceSetup {
+		if !skipAdvanceSetup {
 			evaluluateAdvancedSetup() // this will set MRConfig related to advanced fields
 		}
 
@@ -373,7 +376,7 @@ class AccountSetupController: UITableViewController {
 
 	// returns true if needed
 	private func showOAuthAlertIfNeeded(emailAddress: String, handleCancel: (() -> Void)?) -> Bool {
-		if userHasCancelledOAuth {
+		if skipOauth {
 			assert(MRConfig.getAuthFlags() == Int(DC_LP_AUTH_NORMAL))
 			// user has previously denied oAuth2-setup
 			return false
@@ -401,7 +404,7 @@ class AccountSetupController: UITableViewController {
 			let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: {
 				_ in
 				MRConfig.setAuthFlags(flags: Int(DC_LP_AUTH_NORMAL))
-				self.userHasCancelledOAuth = true
+				self.skipOauth = true
 				handleCancel?()
 
 			})
@@ -564,8 +567,9 @@ extension AccountSetupController: UITextFieldDelegate {
 
 	func textFieldDidBeginEditing(_ textField: UITextField) {
 		if textField.accessibilityIdentifier == "emailTextField" {
+			loginButton.isEnabled = true
 			// this will re-enable possible oAuth2-login
-			userHasCancelledOAuth = false
+			skipOauth = false
 		}
 	}
 
@@ -636,7 +640,7 @@ extension AccountSetupController {
 	func showProgressHud() {
 		configProgressAlert.actions[0].isEnabled = true
 		configProgressAlert.title = "Configuring Account"
-		configProgressAlert.message = "\n\n\n"
+		configProgressAlert.message = "\n\n\n"	// workaround to create space for progress indicator
 		configProgressIndicator.alpha = 1
 		configProgressIndicator.value = 0
 		present(configProgressAlert, animated: true, completion: nil)
@@ -654,6 +658,7 @@ extension AccountSetupController {
 		configProgressIndicator.alpha = 0
 		configProgressAlert.title = "Login Successful!"
 		configProgressAlert.message = "You are ready to use Delta Chat."
+		loginButton.isEnabled = dc_is_configured(mailboxPointer) == 0
 		DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
 			self.configProgressAlert.dismiss(animated: true) {
 				self.handleLoginSuccess()

+ 1 - 3
deltachat-ios/Controller/ChatListController.swift

@@ -30,10 +30,9 @@ class ChatListController: UIViewController {
 		super.viewWillAppear(animated)
 
 		if #available(iOS 11.0, *) {
-			// TODO: check if this is really nessesary - dc navigationController has large titles
 			navigationController?.navigationBar.prefersLargeTitles = true
+			navigationItem.largeTitleDisplayMode = .always
 		}
-
 		getChatList()
 	}
 
@@ -52,7 +51,6 @@ class ChatListController: UIViewController {
 																					_ in
 																					self.getChatList()
 		}
-
 		incomingMsgObserver = nc.addObserver(forName: dcNotificationIncoming,
 																				 object: nil, queue: nil) {
 																					_ in

+ 1 - 1
deltachat-ios/Controller/ChatViewController.swift

@@ -302,7 +302,7 @@ class ChatViewController: MessagesViewController {
 	private func configureMessageInputBar() {
 		messageInputBar.delegate = self
 		messageInputBar.inputTextView.tintColor = DCColors.primary
-
+		messageInputBar.inputTextView.placeholder = "Message"
 		messageInputBar.isTranslucent = true
 		messageInputBar.separatorLine.isHidden = true
 		messageInputBar.inputTextView.tintColor = DCColors.primary

+ 232 - 87
deltachat-ios/Controller/ContactListController.swift

@@ -7,103 +7,248 @@
 //
 
 import UIKit
+import Contacts
 
 class ContactListController: UITableViewController {
-  weak var coordinator: ContactListCoordinator?
-
-  let contactCellReuseIdentifier = "ChatCell"
-  var contactIds: [Int] = Utils.getContactIds()
-  var contactIdsForGroup: Set<Int> = []
-
-  override func viewDidLoad() {
-    super.viewDidLoad()
-    title = "Contacts"
-    navigationController?.navigationBar.prefersLargeTitles = true
-
-    tableView.rowHeight = 80
-    tableView.register(ContactCell.self, forCellReuseIdentifier: contactCellReuseIdentifier)
-  }
-
-  private func getContactIds() {
-    contactIds = Utils.getContactIds()
-    tableView.reloadData()
-  }
-
-  override func viewWillAppear(_ animated: Bool) {
-    super.viewWillAppear(animated)
-
-    if #available(iOS 11.0, *) {
-      navigationController?.navigationBar.prefersLargeTitles = true
-    }
-
-    getContactIds()
-  }
-
-  override func viewWillDisappear(_ animated: Bool) {
-    super.viewWillDisappear(animated)
-    if #available(iOS 11.0, *) {
-      navigationController?.navigationBar.prefersLargeTitles = false
-    }
-  }
-
-  override func didReceiveMemoryWarning() {
-    super.didReceiveMemoryWarning()
-  }
-
-  override func numberOfSections(in _: UITableView) -> Int {
-    return 1
-  }
-
-  override func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int {
-    return contactIds.count
-  }
-
-  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-    let cell: ContactCell
-    if let c = tableView.dequeueReusableCell(withIdentifier: contactCellReuseIdentifier) as? ContactCell {
-      cell = c
-    } else {
-      cell = ContactCell(style: .subtitle, reuseIdentifier: contactCellReuseIdentifier)
-    }
-    let row = indexPath.row
-    let contactRow = row
-
-    if contactRow < contactIds.count {
-      let contact = MRContact(id: contactIds[contactRow])
-      cell.nameLabel.text = contact.name
-      cell.emailLabel.text = contact.email
-
-      cell.selectionStyle = .none
-
-      if let img = contact.profileImage {
-        cell.setImage(img)
-      } else {
-        cell.setBackupImage(name: contact.name, color: contact.color)
-      }
-      cell.setVerified(isVerified: contact.isVerified)
-    }
-    return cell
-  }
-
-  override func tableView(_: UITableView, didSelectRowAt indexPath: IndexPath) {
-    let contactId = contactIds[indexPath.row]
-		let chatId = dc_create_chat_by_contact_id(mailboxPointer, UInt32(contactId))
-
-		coordinator?.showChat(chatId: Int(chatId))
-		// coordinator?.showContactDetail(contactId: contactId)
-  }
+	weak var coordinator: ContactListCoordinator?
 
-	override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
-		let row = indexPath.row
+	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()
+
+	// 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()
+	}
+
+	let contactCellReuseIdentifier = "ChatCell"
+
+	lazy var deviceContactHandler: DeviceContactsHandler = {
+		let handler = DeviceContactsHandler()
+		handler.contactListDelegate = self
+		return handler
+	}()
+
+	lazy var newContactButton: UIBarButtonItem = {
+		let button = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(newContactButtonPressed))
+		// UIBarButtonItem(image: #imageLiteral(resourceName: "ic_add").withRenderingMode(.alwaysTemplate), style: .plain, target: self, action: #selector(newContactButtonPressed))
+		return button
+	}()
+
+	var deviceContactAccessGranted: Bool = false {
+		didSet {
+			tableView.reloadData()
+		}
+	}
+
+	override func viewDidLoad() {
+		super.viewDidLoad()
+		title = "Contacts"
+		navigationController?.navigationBar.prefersLargeTitles = true
+		navigationItem.searchController = searchController
+		tableView.register(ContactCell.self, forCellReuseIdentifier: contactCellReuseIdentifier)
+		tableView.register(ActionCell.self, forCellReuseIdentifier: "actionCell")
+
+		navigationItem.rightBarButtonItem = newContactButton
+	}
+
+	private func getContactIds() {
+		contactIds = Utils.getContactIds()
+		tableView.reloadData()
+	}
+
+	private func searchBarIsEmpty() -> Bool {
+		return searchController.searchBar.text?.isEmpty ?? true
+	}
+
+	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()
+	}
+
+	override func viewWillAppear(_ animated: Bool) {
+		super.viewWillAppear(animated)
+		if #available(iOS 11.0, *) {
+			navigationController?.navigationBar.prefersLargeTitles = true
+		}
+		deviceContactHandler.importDeviceContacts()
+		deviceContactAccessGranted = CNContactStore.authorizationStatus(for: .contacts) == .authorized
+		searchController.searchBar.text = nil
+		getContactIds()
+	}
+
+	override func viewWillDisappear(_ animated: Bool) {
+		super.viewWillDisappear(animated)
+		if #available(iOS 11.0, *) {
+			navigationController?.navigationBar.prefersLargeTitles = false
+		}
+	}
+
+	override func didReceiveMemoryWarning() {
+		super.didReceiveMemoryWarning()
+	}
+
+	override func numberOfSections(in _: UITableView) -> Int {
+		return deviceContactAccessGranted ? 1 : 2
+	}
 
-		let contactId = contactIds[row]
+	override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
+		if !deviceContactAccessGranted && section == 0 {
+			return 1
+		}
+		return isFiltering() ? filteredContacts.count : contactIds.count
+	}
+
+	override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+		let section = indexPath.section
+
+		if !deviceContactAccessGranted && section == 0 {
+			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 {
+
+			let cell: ContactCell
+			if let c = tableView.dequeueReusableCell(withIdentifier: contactCellReuseIdentifier) as? ContactCell {
+				cell = c
+			} else {
+				cell = ContactCell(style: .subtitle, reuseIdentifier: contactCellReuseIdentifier)
+			}
+			let row = indexPath.row
+			let contactRow = row
+
+			if contactRow < contactIds.count {
+				let contact: ContactWithSearchResults = isFiltering() ? filteredContacts[contactRow] : contacts[contactRow]
+				updateContactCell(cell: cell, contactWithHighlight: contact)
+				cell.selectionStyle = .none
+
+				cell.setVerified(isVerified: contact.contact.isVerified)
+			}
+			return cell
+		}
+	}
+
+	override func tableView(_: UITableView, didSelectRowAt indexPath: IndexPath) {
+		if !deviceContactAccessGranted && indexPath.section == 0 {
+			showSettingsAlert()
+		} else {
+			let contact = contactByIndexPath(indexPath)
+			let contactId = contact.contact.id
+			let chatId = dc_create_chat_by_contact_id(mailboxPointer, UInt32(contactId))
+
+			if searchController.isActive {
+				searchController.dismiss(animated: false) {
+					self.coordinator?.showChat(chatId: Int(chatId))
+				}
+			} else {
+				self.coordinator?.showChat(chatId: Int(chatId))
+			}
+		}
+	}
+
+	override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
+		let contactId = contactByIndexPath(indexPath).contact.id
 
 		// assigning swipe by delete to chats
 		let edit = UITableViewRowAction(style: .default, title: "Edit") {
 			[unowned self] _, indexPath in
-			self.coordinator?.showContactDetail(contactId: contactId)
+			if self.searchController.isActive {
+				self.searchController.dismiss(animated: false) {
+					self.coordinator?.showContactDetail(contactId: contactId)
+				}
+			} else {
+				self.coordinator?.showContactDetail(contactId: contactId)
+			}
 		}
 		edit.backgroundColor = DCColors.primary
 		return [edit]
 	}
+
+	@objc func newContactButtonPressed() {
+		coordinator?.showNewContactController()
+	}
+
+	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
+
+			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)
+	}
+
+	private func contactByIndexPath(_ indexPath: IndexPath) -> ContactWithSearchResults {
+		return isFiltering() ? filteredContacts[indexPath.row] : contacts[indexPath.row]
+	}
+}
+
+extension ContactListController: ContactListDelegate {
+	func deviceContactsImported() {
+		contactIds = Utils.getContactIds()
+	}
+
+	func accessGranted() {
+		deviceContactAccessGranted = true
+	}
+
+	func accessDenied() {
+		deviceContactAccessGranted = false
+		getContactIds()
+	}
+
+	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
+		)
+		alert.addAction(UIAlertAction(title: "Open Settings", style: .default) { _ in
+			UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
+		})
+		alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
+		})
+		present(alert, animated: true)
+	}
+}
+
+extension ContactListController: UISearchResultsUpdating {
+	func updateSearchResults(for searchController: UISearchController) {
+		if let searchText = searchController.searchBar.text {
+			filterContentForSearchText(searchText)
+		}
+	}
 }

+ 1 - 1
deltachat-ios/Controller/DCNavigationController.swift

@@ -36,7 +36,7 @@ final class DCNavigationController: UINavigationController {
   }
 
 	override func viewWillAppear(_ animated: Bool) {
-
+		super.viewWillAppear(animated)
 		if let connection = Reachability()?.connection {
 			switch connection {
 			case Reachability.Connection.cellular, Reachability.Connection.wifi:

+ 43 - 0
deltachat-ios/Controller/EditContactController.swift

@@ -0,0 +1,43 @@
+//
+//  EditContactController.swift
+//  deltachat-ios
+//
+//  Created by Bastian van de Wetering on 24.06.19.
+//  Copyright © 2019 Jonas Reinsch. All rights reserved.
+//
+
+import UIKit
+
+class EditContactController: NewContactController {
+
+	// for editing existing contacts (only
+	// the name may be edited, therefore disable
+	// the email field)
+	init(contactIdForUpdate: Int) {
+		super.init()
+		title = "Edit Contact"
+
+		let contact = MRContact(id: contactIdForUpdate)
+		nameCell.textField.text = contact.name
+		emailCell.textField.text = contact.email
+		emailCell.textField.isEnabled = false
+		emailCell.contentView.alpha = 0.3
+
+		model.name = contact.name
+		model.email = contact.email
+
+		if contactIsValid() {
+			doneButton?.isEnabled = true
+		}
+	}
+
+	required init?(coder _: NSCoder) {
+		fatalError("init(coder:) has not been implemented")
+	}
+
+	@objc override func saveContactButtonPressed() {
+		dc_create_contact(mailboxPointer, model.name, model.email)
+		coordinator?.navigateBack()
+	}
+
+}

+ 0 - 35
deltachat-ios/Controller/NewContactController.swift

@@ -8,39 +8,6 @@
 
 import UIKit
 
-class EditContactController: NewContactController {
-
-	// for editing existing contacts (only
-	// the name may be edited, therefore disable
-	// the email field)
-	init(contactIdForUpdate: Int) {
-		super.init()
-		title = "Edit Contact"
-
-		let contact = MRContact(id: contactIdForUpdate)
-		nameCell.textField.text = contact.name
-		emailCell.textField.text = contact.email
-		emailCell.textField.isEnabled = false
-		emailCell.contentView.alpha = 0.3
-
-		model.name = contact.name
-		model.email = contact.email
-
-		if contactIsValid() {
-			doneButton?.isEnabled = true
-		}
-	}
-
-	required init?(coder _: NSCoder) {
-		fatalError("init(coder:) has not been implemented")
-	}
-
-	@objc override func saveContactButtonPressed() {
-		dc_create_contact(mailboxPointer, model.name, model.email)
-		coordinator?.navigateBack()
-	}
-
-}
 
 class NewContactController: UITableViewController {
 
@@ -67,8 +34,6 @@ class NewContactController: UITableViewController {
 
   let cells: [UITableViewCell]
 
-
-
   // for creating a new contact
   init() {
     cells = [emailCell, nameCell]

+ 1 - 1
deltachat-ios/Controller/ProfileViewController.swift

@@ -45,7 +45,7 @@ class ProfileViewController: UITableViewController {
   }
 
   override func viewWillAppear(_: Bool) {
-    navigationController?.navigationBar.prefersLargeTitles = false
+   navigationController?.navigationBar.prefersLargeTitles = false
     tableView.reloadData()
   }
 

+ 33 - 8
deltachat-ios/Coordinator/AppCoordinator.swift

@@ -12,7 +12,7 @@ import Photos
 import MobileCoreServices
 
 
-class AppCoordinator: NSObject, Coordinator, UITabBarControllerDelegate {
+class AppCoordinator: NSObject, Coordinator {
 	private let window: UIWindow
 
 	var rootViewController: UIViewController {
@@ -27,7 +27,6 @@ class AppCoordinator: NSObject, Coordinator, UITabBarControllerDelegate {
 		// put viewControllers here
 		tabBarController.delegate = self
 		tabBarController.tabBar.tintColor = DCColors.primary
-		// tabBarController.tabBar.isTranslucent = false
 		return tabBarController
 	}()
 
@@ -37,7 +36,7 @@ class AppCoordinator: NSObject, Coordinator, UITabBarControllerDelegate {
 		let controller = ContactListController()
 		let nav = DCNavigationController(rootViewController: controller)
 		let settingsImage = UIImage(named: "contacts")
-		nav.tabBarItem = UITabBarItem(title: "Contacts", image: settingsImage, tag: 4)
+		nav.tabBarItem = UITabBarItem(title: "Contacts", image: settingsImage, tag: 0)
 		let coordinator = ContactListCoordinator(navigationController: nav)
 		self.childCoordinators.append(coordinator)
 		controller.coordinator = coordinator
@@ -49,7 +48,7 @@ class AppCoordinator: NSObject, Coordinator, UITabBarControllerDelegate {
 		controller.disableWriting = true
 		let nav = DCNavigationController(rootViewController: controller)
 		let settingsImage = UIImage(named: "message")
-		nav.tabBarItem = UITabBarItem(title: "Mailbox", image: settingsImage, tag: 0)
+		nav.tabBarItem = UITabBarItem(title: "Mailbox", image: settingsImage, tag: 1)
 		let coordinator = MailboxCoordinator(navigationController: nav)
 		self.childCoordinators.append(coordinator)
 		controller.coordinator = coordinator
@@ -60,7 +59,7 @@ class AppCoordinator: NSObject, Coordinator, UITabBarControllerDelegate {
 		let controller = ProfileViewController()
 		let nav = DCNavigationController(rootViewController: controller)
 		let settingsImage = UIImage(named: "report_card")
-		nav.tabBarItem = UITabBarItem(title: "My Profile", image: settingsImage, tag: 1)
+		nav.tabBarItem = UITabBarItem(title: "My Profile", image: settingsImage, tag: 2)
 		let coordinator = ProfileCoordinator(rootViewController: nav)
 		self.childCoordinators.append(coordinator)
 		controller.coordinator = coordinator
@@ -71,7 +70,7 @@ class AppCoordinator: NSObject, Coordinator, UITabBarControllerDelegate {
 		let controller = ChatListController()
 		let nav = DCNavigationController(rootViewController: controller)
 		let settingsImage = UIImage(named: "chat")
-		nav.tabBarItem = UITabBarItem(title: "Chats", image: settingsImage, tag: 2)
+		nav.tabBarItem = UITabBarItem(title: "Chats", image: settingsImage, tag: 3)
 		let coordinator = ChatListCoordinator(navigationController: nav)
 		self.childCoordinators.append(coordinator)
 		controller.coordinator = coordinator
@@ -82,7 +81,7 @@ class AppCoordinator: NSObject, Coordinator, UITabBarControllerDelegate {
 		let controller = SettingsViewController()
 		let nav = DCNavigationController(rootViewController: controller)
 		let settingsImage = UIImage(named: "settings")
-		nav.tabBarItem = UITabBarItem(title: "Settings", image: settingsImage, tag: 3)
+		nav.tabBarItem = UITabBarItem(title: "Settings", image: settingsImage, tag: 4)
 		let coordinator = SettingsCoordinator(navigationController: nav)
 		self.childCoordinators.append(coordinator)
 		controller.coordinator = coordinator
@@ -112,9 +111,26 @@ class AppCoordinator: NSObject, Coordinator, UITabBarControllerDelegate {
 	}
 }
 
+extension AppCoordinator: UITabBarControllerDelegate {
+	func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
+		if let dcNav = viewController as? DCNavigationController {
+			switch tabBarController.selectedIndex {
+			case 0,3,4:
+				dcNav.navigationBar.prefersLargeTitles = true
+			case 1,2:
+				dcNav.navigationBar.prefersLargeTitles = false
+			default:
+				// should never get here
+				dcNav.navigationBar.prefersLargeTitles = false
+			}
+		}
+	}
+
+}
+
 extension AppCoordinator: UITabBarDelegate {
 	func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
-		print("item selected")
+
 	}
 
 	func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
@@ -148,6 +164,15 @@ class ContactListCoordinator: Coordinator {
 		chatVC.coordinator = coordinator
 		navigationController.pushViewController(chatVC, animated: true)
 	}
+
+	func showNewContactController() {
+		let newContactController = NewContactController()
+		let coordinator = EditContactCoordinator(navigationController: navigationController)
+		childCoordinators.append(coordinator)
+		newContactController.coordinator = coordinator
+		newContactController.hidesBottomBarWhenPushed = true
+		navigationController.pushViewController(newContactController, animated: true)
+	}
 }
 
 // since mailbox and chatView -tab both use ChatViewController we want to be able to assign different functionality via coordinators -> therefore we override unneeded functions such as showChatDetail -> maybe find better solution in longterm

+ 5 - 1
deltachat-ios/Helper/Utils.swift

@@ -17,7 +17,11 @@ struct Utils {
   }
 
   static func getInitials(inputName: String) -> String {
-    let nameParts = inputName.split(separator: " ")
+    var nameParts = inputName.split(separator: " ")
+		// this limits initials to max 2, otherwise just takes first letter to avoid messy badges
+		if nameParts.count > 2 {
+			nameParts = [nameParts[0]]
+		}
     let initials: [Character] = nameParts.compactMap { part in part.capitalized.first }
     let initialsString: String = String(initials)
     return initialsString

+ 46 - 30
deltachat-ios/View/InitialsBadge.swift

@@ -6,36 +6,52 @@
 //  Copyright © 2019 Jonas Reinsch. All rights reserved.
 //
 
-
 import UIKit
 
-class InitialsBadge: UILabel {
-  convenience init(name: String, color: UIColor, size: CGFloat) {
-    self.init(size: size)
-    setName(name)
-    setColor(color)
-  }
-
-  init(size: CGFloat) {
-    super.init(frame: CGRect(x: 0, y: 0, width: size, height: size))
-    textAlignment = NSTextAlignment.center
-    textColor = UIColor.white
-    adjustsFontSizeToFitWidth = true
-    let initialsLabelCornerRadius = size / 2
-    layer.cornerRadius = initialsLabelCornerRadius
-    clipsToBounds = true
-  }
-
-  required init?(coder _: NSCoder) {
-    fatalError("init(coder:) has not been implemented")
-  }
-
-  func setName(_ name: String) {
-    text = Utils.getInitials(inputName: name)
-  }
-
-  func setColor(_ color: UIColor) {
-    backgroundColor = color
-  }
+class InitialsBadge: UIView {
+
+	private var label: UILabel = {
+		let label = UILabel()
+		label.adjustsFontSizeToFitWidth = true
+		label.textAlignment = NSTextAlignment.center
+		label.textColor = UIColor.white
+		return label
+	}()
+
+	convenience init(name: String, color: UIColor, size: CGFloat) {
+		self.init(size: size)
+		setName(name)
+		setColor(color)
+	}
+
+	init(size: CGFloat) {
+		super.init(frame: CGRect(x: 0, y: 0, width: size, height: size))
+		let initialsLabelCornerRadius = size / 2
+		layer.cornerRadius = initialsLabelCornerRadius
+		translatesAutoresizingMaskIntoConstraints = false
+		heightAnchor.constraint(equalToConstant: size).isActive = true
+		widthAnchor.constraint(equalToConstant: size).isActive = true
+		clipsToBounds = true
+		setupSubviews()
+	}
+
+	private func setupSubviews() {
+		addSubview(label)
+		label.translatesAutoresizingMaskIntoConstraints = false
+		label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 2).isActive = true
+		label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -2).isActive = true
+		label.centerYAnchor.constraint(equalTo: centerYAnchor, constant: 0).isActive = true
+	}
+
+	required init?(coder _: NSCoder) {
+		fatalError("init(coder:) has not been implemented")
+	}
+
+	func setName(_ name: String) {
+		label.text = Utils.getInitials(inputName: name)
+	}
+
+	func setColor(_ color: UIColor) {
+		backgroundColor = color
+	}
 }
-