Просмотр исходного кода

Merge pull request #69 from deltachat/AccountSetupExtended

Account setup extended
cyBerta 6 лет назад
Родитель
Сommit
b22181a28a

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

@@ -87,6 +87,8 @@
 		7AE0A5491FC42F65005ECB4B /* NewChatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE0A5481FC42F65005ECB4B /* NewChatViewController.swift */; };
 		8B6D425BC604F7C43B65D436 /* Pods_deltachat_ios.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6241BE1534A653E79AD5D01D /* Pods_deltachat_ios.framework */; };
 		AE0D26FD1FB1FE88002FAFCE /* ChatListController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE0D26FC1FB1FE88002FAFCE /* ChatListController.swift */; };
+		AE18F292228C17BC0007B1BE /* PortSettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE18F291228C17BC0007B1BE /* PortSettingsController.swift */; };
+		AE18F294228C602A0007B1BE /* SecuritySettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE18F293228C602A0007B1BE /* SecuritySettingsController.swift */; };
 		AE25F09022807AD800CDEA66 /* GroupNameCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE25F08F22807AD800CDEA66 /* GroupNameCell.swift */; };
 		AE38B31822672DFC00EC37A1 /* ActionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE38B31722672DFC00EC37A1 /* ActionCell.swift */; };
 		AE38B31A2267328200EC37A1 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE38B3192267328200EC37A1 /* Colors.swift */; };
@@ -107,6 +109,7 @@
 		AEE6EC382281AF2D00EDC689 /* InitialsBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE6EC372281AF2D00EDC689 /* InitialsBadge.swift */; };
 		AEE6EC3F2282C59C00EDC689 /* GroupMembersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE6EC3E2282C59C00EDC689 /* GroupMembersViewController.swift */; };
 		AEE6EC412282DF5700EDC689 /* MailboxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE6EC402282DF5700EDC689 /* MailboxViewController.swift */; };
+		AEE6EC482283045D00EDC689 /* EditSettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE6EC472283045D00EDC689 /* EditSettingsController.swift */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -280,6 +283,8 @@
 		8DE110C607A0E4485C43B5FA /* Pods-deltachat-ios.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-deltachat-ios.debug.xcconfig"; path = "Pods/Target Support Files/Pods-deltachat-ios/Pods-deltachat-ios.debug.xcconfig"; sourceTree = "<group>"; };
 		A8615D4600859851E53CAA9C /* Pods-deltachat-ios.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-deltachat-ios.release.xcconfig"; path = "Pods/Target Support Files/Pods-deltachat-ios/Pods-deltachat-ios.release.xcconfig"; sourceTree = "<group>"; };
 		AE0D26FC1FB1FE88002FAFCE /* ChatListController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListController.swift; sourceTree = "<group>"; };
+		AE18F291228C17BC0007B1BE /* PortSettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortSettingsController.swift; sourceTree = "<group>"; };
+		AE18F293228C602A0007B1BE /* SecuritySettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecuritySettingsController.swift; sourceTree = "<group>"; };
 		AE25F08F22807AD800CDEA66 /* GroupNameCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupNameCell.swift; sourceTree = "<group>"; };
 		AE38B31722672DFC00EC37A1 /* ActionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionCell.swift; sourceTree = "<group>"; };
 		AE38B3192267328200EC37A1 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = "<group>"; };
@@ -303,6 +308,7 @@
 		AEE6EC372281AF2D00EDC689 /* InitialsBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitialsBadge.swift; sourceTree = "<group>"; };
 		AEE6EC3E2282C59C00EDC689 /* GroupMembersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupMembersViewController.swift; sourceTree = "<group>"; };
 		AEE6EC402282DF5700EDC689 /* MailboxViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailboxViewController.swift; sourceTree = "<group>"; };
+		AEE6EC472283045D00EDC689 /* EditSettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditSettingsController.swift; sourceTree = "<group>"; };
 		FECB35E2B04CD5F5D02C157A /* Pods-deltachat-iosTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-deltachat-iosTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-deltachat-iosTests/Pods-deltachat-iosTests.release.xcconfig"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
@@ -565,6 +571,15 @@
 			name = Pods;
 			sourceTree = "<group>";
 		};
+		AE18F28B228C17630007B1BE /* AccountSetup */ = {
+			isa = PBXGroup;
+			children = (
+				AE18F291228C17BC0007B1BE /* PortSettingsController.swift */,
+				AE18F293228C602A0007B1BE /* SecuritySettingsController.swift */,
+			);
+			path = AccountSetup;
+			sourceTree = "<group>";
+		};
 		AE851A02227AECDE00ED86F0 /* deltachat-iosTests */ = {
 			isa = PBXGroup;
 			children = (
@@ -587,6 +602,7 @@
 		AE851AC0227C693B00ED86F0 /* Controller */ = {
 			isa = PBXGroup;
 			children = (
+				AE18F28B228C17630007B1BE /* AccountSetup */,
 				78E45E3D21D3D28C00D4B15E /* NavigationController.swift */,
 				785BE16721E247F1003BE98C /* MessageInfoViewController.swift */,
 				7A0052C71FBE6CB40048C3BF /* NewContactController.swift */,
@@ -603,6 +619,7 @@
 				AE851ACF227DF50900ED86F0 /* SingleChatDetailViewController.swift */,
 				AEE6EC3E2282C59C00EDC689 /* GroupMembersViewController.swift */,
 				AEE6EC402282DF5700EDC689 /* MailboxViewController.swift */,
+				AEE6EC472283045D00EDC689 /* EditSettingsController.swift */,
 			);
 			path = Controller;
 			sourceTree = "<group>";
@@ -960,6 +977,7 @@
 				7070FB6A20FF345F000DC258 /* dc_saxparser.c in Sources */,
 				7070FB8A20FF4118000DC258 /* dc_log.c in Sources */,
 				7070FB9020FF4118000DC258 /* dc_stock.c in Sources */,
+				AE18F294228C602A0007B1BE /* SecuritySettingsController.swift in Sources */,
 				78ED838D21D577D000243125 /* events.swift in Sources */,
 				7070FB8F20FF4118000DC258 /* dc_loginparam.c in Sources */,
 				AE851AC7227C776400ED86F0 /* Location.swift in Sources */,
@@ -984,6 +1002,7 @@
 				7070FB7320FF345F000DC258 /* dc_aheader.c in Sources */,
 				7070FB6120FF345F000DC258 /* dc_securejoin.c in Sources */,
 				78ED838F21D5927A00243125 /* ProfileViewController.swift in Sources */,
+				AEE6EC482283045D00EDC689 /* EditSettingsController.swift in Sources */,
 				78E45E4221D3DB4000D4B15E /* UIViewController+Extension.swift in Sources */,
 				7A9FB1441FB061E2001FEA36 /* AppDelegate.swift in Sources */,
 				AEE56D7D2253ADB4007DC082 /* HudHandler.swift in Sources */,
@@ -1010,6 +1029,7 @@
 				7A451D941FB1B1DB00177250 /* wrapper.c in Sources */,
 				7092474120B3869500AF8799 /* ContactDetailViewController.swift in Sources */,
 				7070FB5E20FF345F000DC258 /* dc_token.c in Sources */,
+				AE18F292228C17BC0007B1BE /* PortSettingsController.swift in Sources */,
 				AE851AD0227DF50900ED86F0 /* SingleChatDetailViewController.swift in Sources */,
 				7070FB6C20FF345F000DC258 /* dc_keyring.c in Sources */,
 				7A451DB01FB1F84900177250 /* AppCoordinator.swift in Sources */,

+ 171 - 0
deltachat-ios/Controller/AccountSetup/PortSettingsController.swift

@@ -0,0 +1,171 @@
+//
+//  PortSettingsController.swift
+//  deltachat-ios
+//
+//  Created by Bastian van de Wetering on 15.05.19.
+//  Copyright © 2019 Jonas Reinsch. All rights reserved.
+//
+
+import UIKit
+
+class PortSettingsController: UITableViewController {
+
+	var ports: [Int]
+
+	private var sectionTitle: String?
+
+	var resetButton: UIBarButtonItem!
+
+	var onDismiss:((String)->Void)?
+
+	var currentPort: Int {
+		didSet {
+			// activate resetButton once something was changed
+			resetButton.isEnabled = true
+		}
+	}
+
+	var selectedIndex: Int?
+
+	let backupValue: Int
+
+	var staticCells: [UITableViewCell] {
+		return ports.map({
+			let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
+			cell.textLabel?.text = "\($0)"
+			cell.selectionStyle = .none
+			return cell
+		})
+	}
+
+	lazy var customCell: TextFieldCell = {
+		let cell = TextFieldCell(description: "", placeholder: "\(self.currentPort)")
+		cell.selectionStyle = .none
+		cell.textLabel?.text = nil
+		cell.textField.keyboardType = .numberPad
+		cell.onTextFieldChange = textFieldDidChange
+		return cell
+	}()
+
+	init(sectionTitle: String?, ports: [Int], currentPort: Int?) {
+		self.ports = ports
+		self.sectionTitle = sectionTitle
+		self.currentPort = currentPort ?? 0
+		for (index, port) in ports.enumerated() where currentPort == port {
+			selectedIndex = index
+		}
+		backupValue = self.currentPort
+		super.init(style: .grouped)
+		self.title = sectionTitle
+	}
+
+	required init?(coder aDecoder: NSCoder) {
+		fatalError("init(coder:) has not been implemented")
+	}
+
+	override func viewDidLoad() {
+		super.viewDidLoad()
+
+		resetButton = UIBarButtonItem(title: "Reset", style: .plain, target: self, action: #selector(resetButtonPressed))
+		navigationItem.rightBarButtonItem = resetButton
+		resetButton.isEnabled = false
+	}
+
+	override func viewWillDisappear(_ animated: Bool) {
+		onDismiss?("\(currentPort)")
+	}
+
+	// MARK: - Table view data source
+
+	override func numberOfSections(in tableView: UITableView) -> Int {
+		// #warning Incomplete implementation, return the number of sections
+		return 2
+	}
+
+	override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+		if section == 0 {
+			return ports.count
+		} else {
+			return 1
+		}
+	}
+
+	override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+		if indexPath.section == 0 {
+			let row = indexPath.row
+			selectItem(at: row)
+		}
+	}
+
+	override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+
+		let section = indexPath.section
+		let row = indexPath.row
+		if section == 0 {
+			let cell = staticCells[row]
+			if row == selectedIndex || cell.textLabel?.text == "\(currentPort)" {
+				cell.accessoryType = .checkmark
+			} else {
+				cell.accessoryType = .none
+			}
+			return cell
+		} else {
+			// section == 1
+			return customCell
+		}
+	}
+
+	override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
+		if section == 0 {
+			return sectionTitle
+		} else {
+			return "Custom Port"
+		}
+	}
+
+	private func textFieldDidChange(_ textField: UITextField) {
+		selectItem(at: nil)
+		if let text = textField.text, let port = Int(text) {
+			self.currentPort = port
+		}
+	}
+
+	private func selectItem(at index: Int? ) {
+		// unselect old cell
+		// select new cell
+		// update port
+		if let oldIndex = selectedIndex {
+			let cell = tableView.cellForRow(at: IndexPath.init(row: oldIndex, section: 0))
+			cell?.accessoryType = .none
+		}
+		if let newIndex = index {
+			// activate accesoryType on selected cell
+			let cell = tableView.cellForRow(at: IndexPath.init(row: newIndex, section: 0))
+			cell?.accessoryType = .checkmark
+			currentPort = ports[newIndex]
+			// update customCell
+			customCell.textField.placeholder = "\(currentPort)"
+			customCell.textField.resignFirstResponder()
+			customCell.textField.text = nil // will display currentValue as placeholder
+		}
+		selectedIndex = index
+	}
+
+	@objc private func resetButtonPressed() {
+
+		if let index = ports.index(of: backupValue) {
+			selectItem(at: index)
+		} else {
+			selectItem(at: nil)
+		}
+		self.currentPort = backupValue
+		customCell.textField.placeholder = "\(currentPort)"
+		customCell.textField.resignFirstResponder()
+		customCell.textField.text = nil // will display currentValue as placeholder
+
+		tableView.reloadData()
+	}
+
+}
+
+

+ 171 - 0
deltachat-ios/Controller/AccountSetup/SecuritySettingsController.swift

@@ -0,0 +1,171 @@
+//
+//  SecuritySettingsController.swift
+//  deltachat-ios
+//
+//  Created by Bastian van de Wetering on 15.05.19.
+//  Copyright © 2019 Jonas Reinsch. All rights reserved.
+//
+
+import UIKit
+
+class SecuritySettingsController: UITableViewController {
+
+	private var options: [String]
+	private var selectedIndex: Int {
+		didSet {
+			print(selectedIndex)
+		}
+	}
+
+	private var backupIndex: Int
+
+	var onDismiss: ((String) -> Void)?
+
+	private var resetButton: UIBarButtonItem!
+
+	private var staticCells: [UITableViewCell] {
+		return options.map {
+			let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
+			cell.textLabel?.text = $0
+			cell.selectionStyle = .none
+			return cell
+		}
+	}
+
+	init(title: String, options: [String], selectedOption: String) {
+		self.options = options
+		selectedIndex = options.index(of: selectedOption)!
+		backupIndex = selectedIndex
+		super.init(style: .grouped)
+		self.title = title
+	}
+
+	required init?(coder aDecoder: NSCoder) {
+		fatalError("init(coder:) has not been implemented")
+	}
+
+	override func viewDidLoad() {
+		super.viewDidLoad()
+		resetButton = UIBarButtonItem(title: "Reset", style: .done, target: self, action: #selector(resetButtonPressed))
+		resetButton.isEnabled = false
+		navigationItem.rightBarButtonItem = resetButton
+	}
+
+	override func viewWillDisappear(_ animated: Bool) {
+		let selectedOption = options[selectedIndex]
+		onDismiss?(selectedOption)
+	}
+
+	// MARK: - Table view data source
+
+	override func numberOfSections(in tableView: UITableView) -> Int {
+		return 1
+	}
+
+	override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+		return options.count
+	}
+
+	override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+		let cell = staticCells[indexPath.row]
+		if selectedIndex == indexPath.row {
+			cell.accessoryType = .checkmark
+		} else {
+			cell.accessoryType = .none
+		}
+		return cell
+	}
+
+	override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+		// uselect old
+		if let cell = tableView.cellForRow(at: IndexPath(item: selectedIndex, section: 0)) {
+			cell.accessoryType = .none
+		}
+		// select new
+		if let cell = tableView.cellForRow(at: indexPath) {
+			cell.accessoryType = .checkmark
+		}
+		selectedIndex = indexPath.row
+		resetButton.isEnabled = true
+	}
+
+	@objc func resetButtonPressed() {
+		selectedIndex = backupIndex
+		tableView.reloadData()
+	}
+
+}
+
+
+enum SecurityType {
+	case IMAPSecurity
+	case SMTPSecurity
+}
+
+enum SecurityValue: String {
+	case AUTO = "Automatic"
+	case TLS = "SSL / TLS"
+	case STARTTLS = "STARTTLS"
+	case PLAIN = "OFF"
+}
+
+class SecurityConverter {
+
+	static func convertValueToInt(type: SecurityType, value: SecurityValue) -> Int {
+		switch type {
+		case .IMAPSecurity:
+			switch value {
+			case .AUTO:
+				return 0x000
+			case .STARTTLS:
+				return 0x100
+			case .TLS:
+				return 0x200
+			case .PLAIN:
+				return 0x400
+			}
+		case .SMTPSecurity:
+			switch value{
+			case .AUTO:
+				return 0x00000
+			case .STARTTLS:
+				return 0x10000
+			case .TLS:
+				return 0x20000
+			case .PLAIN:
+				return 0x40000
+			}
+		}
+	}
+
+	static func convertHexToString(type: SecurityType, hex value: Int) -> String {
+		switch type {
+		case .IMAPSecurity:
+			switch value {
+			case 0x00:
+				return "Automatic"
+			case 0x100:
+				return "STARTTLS"
+			case 0x200:
+				return "SSL / TLS"
+			case  0x400:
+				return "OFF"
+			default:
+				return "Undefined"
+			}
+		case .SMTPSecurity:
+			switch value {
+			case 0x00000:
+				return "Automatic"
+			case 0x10000:
+					return "STARTTLS"
+			case 0x20000:
+				return "SSL / TLS"
+			case  0x40000:
+				return "OFF"
+			default:
+				return "Undefined"
+			}
+		}
+	}
+}

+ 83 - 25
deltachat-ios/Controller/AccountSetupController.swift

@@ -10,6 +10,9 @@ import SafariServices
 import UIKit
 
 class AccountSetupController: UITableViewController {
+
+	weak var coordinator: AccountSetupCoordinator?
+
   private var backupProgressObserver: Any?
   private var configureProgressObserver: Any?
   private var oauth2Observer: Any?
@@ -36,8 +39,9 @@ class AccountSetupController: UITableViewController {
   }()
 
   private lazy var restoreCell: ActionCell = {
-    let cell = ActionCell(title: "Restore from backup")
-    cell.accessibilityIdentifier = "restoreCell"
+		let cell = ActionCell(frame: .zero)
+		cell.actionTitle = "Restore from backup"
+		cell.accessibilityIdentifier = "restoreCell"
     return cell
   }()
 
@@ -55,56 +59,67 @@ class AccountSetupController: UITableViewController {
     return cell
   }()
 
-  lazy var imapPortCell: TextFieldCell = {
-    let cell = TextFieldCell(description: "IMAP Port", placeholder: MRConfig.mailPort ?? MRConfig.configuredMailPort, delegate: self)
+  lazy var imapPortCell: UITableViewCell = {
+		let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
+		cell.textLabel?.text = "IMAP Port"
+		cell.accessoryType = .disclosureIndicator
+		cell.detailTextLabel?.text = MRConfig.mailPort ?? MRConfig.configuredMailPort
     cell.accessibilityIdentifier = "IMAPPortCell"
-    cell.textField.tag = 4
+		cell.selectionStyle = .none 
     return cell
   }()
 
-  lazy var imapSecurityCell: TextFieldCell = {
+  lazy var imapSecurityCell: UITableViewCell = {
     let text = "\(MRConfig.getImapSecurity())"
-    let cell = TextFieldCell(description: "IMAP Security", placeholder: text, delegate: self)
+		let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
+		cell.textLabel?.text = "IMAP Security"
+		// let cell = TextFieldCell(description: "IMAP Security", placeholder: text, delegate: self)
     cell.accessibilityIdentifier = "IMAPSecurityCell"
-    cell.textField.tag = 5
-    cell.textField.keyboardType = UIKeyboardType.numberPad
-    return cell
+		cell.accessoryType = .disclosureIndicator
+		cell.detailTextLabel?.text = "\(MRConfig.getImapSecurity())"
+		cell.selectionStyle = .none
+		return cell
   }()
 
   lazy var smtpServerCell: TextFieldCell = {
     let cell = TextFieldCell(description: "SMTP Server", placeholder: MRConfig.sendServer ?? MRConfig.configuredSendServer, delegate: self)
     cell.accessibilityIdentifier = "SMTPServerCell"
-    cell.textField.tag = 6
+    cell.textField.tag = 4
     return cell
   }()
 
   lazy var smtpUserCell: TextFieldCell = {
     let cell = TextFieldCell(description: "SMTP User", placeholder: MRConfig.sendUser ?? MRConfig.configuredSendUser, delegate: self)
     cell.accessibilityIdentifier = "SMTPUserCell"
-    cell.textField.tag = 7
+    cell.textField.tag = 5
     return cell
   }()
 
-  lazy var smtpPortCell: TextFieldCell = {
-    let cell = TextFieldCell(description: "SMTP Port", placeholder: MRConfig.sendPort ?? MRConfig.configuredSendPort, delegate: self)
-    cell.accessibilityIdentifier = "SMTPPortCell"
-    cell.textField.tag = 8
+  lazy var smtpPortCell: UITableViewCell = {
+		let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
+		cell.textLabel?.text = "SMTP Port"
+		cell.accessoryType = .disclosureIndicator
+		cell.detailTextLabel?.text = MRConfig.sendPort ?? MRConfig.configuredSendPort
+		cell.accessibilityIdentifier = "SMTPPortCell"
+		cell.selectionStyle = .none
     return cell
   }()
 
   lazy var smtpPasswordCell: TextFieldCell = {
     let cell = TextFieldCell(description: "SMTP Password", placeholder: "*************", delegate: self)
     cell.accessibilityIdentifier = "SMTPPasswordCell"
-    cell.textField.tag = 9
+    cell.textField.tag = 6
     return cell
   }()
 
-  lazy var smtpSecurityCell: TextFieldCell = {
-    let text = "\(MRConfig.getSmtpSecurity())"
-    let cell = TextFieldCell(description: "SMTP Security", placeholder: text, delegate: self)
-    cell.accessibilityIdentifier = "SMTPSecurityCell"
-    cell.textField.tag = 10
-    cell.textField.keyboardType = UIKeyboardType.numberPad
+  lazy var smtpSecurityCell: UITableViewCell = {
+    let security = "\(MRConfig.getSmtpSecurity())"
+		let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
+		cell.textLabel?.text = "SMTP Security"
+		cell.detailTextLabel?.text = security
+	  cell.accessibilityIdentifier = "SMTPSecurityCell"
+		cell.accessoryType = .disclosureIndicator
+		cell.selectionStyle = .none
     return cell
   }()
 
@@ -122,7 +137,7 @@ class AccountSetupController: UITableViewController {
     smtpUserCell,
     smtpPortCell,
     smtpPasswordCell,
-    smtpSecurityCell,
+    smtpSecurityCell
   ]
 
   private var advancedSectionShowing: Bool = false
@@ -143,13 +158,28 @@ class AccountSetupController: UITableViewController {
     navigationItem.rightBarButtonItem = loginButton
   }
 
+	override func viewWillAppear(_ animated: Bool) {
+		super.viewWillAppear(animated)
+		// needs to be changed if returning from portSettingsController
+		smtpPortCell.detailTextLabel?.text = MRConfig.sendPort ?? MRConfig.configuredSendPort
+		imapPortCell.detailTextLabel?.text = MRConfig.mailPort ?? MRConfig.configuredMailPort
+		smtpSecurityCell.detailTextLabel?.text = SecurityConverter.convertHexToString(type: .SMTPSecurity, hex: MRConfig.getSmtpSecurity())
+		imapSecurityCell.detailTextLabel?.text  = SecurityConverter.convertHexToString(type: .IMAPSecurity, hex: MRConfig.getImapSecurity())
+	}
+
   override func viewDidAppear(_ animated: Bool) {
     super.viewDidAppear(animated)
     addProgressHudEventListener()
     // loginButton.isEnabled = false
   }
 
+	override func viewWillDisappear(_ animated: Bool) {
+		resignFirstResponderOnAllCells()
+	}
+
   override func viewDidDisappear(_: Bool) {
+
+
     let nc = NotificationCenter.default
     if let backupProgressObserver = self.backupProgressObserver {
       nc.removeObserver(backupProgressObserver)
@@ -243,7 +273,15 @@ class AccountSetupController: UITableViewController {
 
     if tappedCell.accessibilityIdentifier == "restoreCell" {
       restoreBackup()
-    }
+		} else if tappedCell.accessibilityIdentifier == "IMAPPortCell" {
+			coordinator?.showImapPortOptions()
+		} else if tappedCell.accessibilityIdentifier == "SMTPPortCell" {
+			coordinator?.showSmtpPortsOptions()
+		} else if tappedCell.accessibilityIdentifier == "IMAPSecurityCell" {
+			coordinator?.showImapSecurityOptions()
+		} else if tappedCell.accessibilityIdentifier == "SMTPSecurityCell" {
+			coordinator?.showSmptpSecurityOptions()
+		}
   }
 
   private func toggleAdvancedSection(button: UILabel) {
@@ -449,6 +487,26 @@ class AccountSetupController: UITableViewController {
     // used when login hud successfully went trough
     dismiss(animated: true, completion: nil)
   }
+
+	private func resignFirstResponderOnAllCells() {
+		basicSectionCells.map({
+			resignCell(cell: $0)
+		})
+
+		advancedSectionCells.map({
+			 resignCell(cell: $0)
+			}
+		)
+	}
+
+
+	func resignCell(cell: UITableViewCell) {
+		if let c = cell as? TextFieldCell {
+			c.textField.resignFirstResponder()
+		}
+	}
+
+
 }
 
 extension AccountSetupController: UITextFieldDelegate {

+ 87 - 0
deltachat-ios/Controller/EditSettingsController.swift

@@ -0,0 +1,87 @@
+//
+//  EditSettingsController.swift
+//  deltachat-ios
+//
+//  Created by Bastian van de Wetering on 08.05.19.
+//  Copyright © 2019 Jonas Reinsch. All rights reserved.
+//
+
+import UIKit
+
+class EditSettingsController: UITableViewController {
+
+	private var displayNameBackup: String?
+	private var statusCellBackup: String?
+
+	private lazy var displayNameCell: TextFieldCell = {
+		let cell = TextFieldCell(description: "Display Name", placeholder: "Display Name")
+		cell.setText(text: MRConfig.displayname ?? nil)
+		return cell
+	}()
+
+	private lazy var statusCell: TextFieldCell = {
+		let cell = TextFieldCell(description: "Status", placeholder: "Your Status")
+		cell.setText(text: MRConfig.selfstatus ?? nil)
+		return cell
+	}()
+
+	init() {
+		super.init(style: .grouped)
+	}
+
+	required init?(coder aDecoder: NSCoder) {
+		fatalError("init(coder:) has not been implemented")
+	}
+
+	override func viewDidLoad() {
+		super.viewDidLoad()
+		// Uncomment the following line to preserve selection between presentations
+		// self.clearsSelectionOnViewWillAppear = false
+
+		// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
+		// self.navigationItem.rightBarButtonItem = self.editButtonItem
+	}
+
+	override func viewWillAppear(_ animated: Bool) {
+		displayNameBackup = MRConfig.displayname
+		statusCellBackup = MRConfig.selfstatus
+	}
+
+	override func viewWillDisappear(_ animated: Bool) {
+		if displayNameBackup != displayNameCell.getText() || statusCellBackup != displayNameCell.getText() {
+			MRConfig.selfstatus = statusCell.getText()
+			MRConfig.displayname = displayNameCell.getText()	
+			dc_configure(mailboxPointer)
+		}
+	}
+
+	// MARK: - Table view data source
+
+	override func numberOfSections(in tableView: UITableView) -> Int {
+		// #warning Incomplete implementation, return the number of sections
+		return 2
+	}
+
+	override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+		// #warning Incomplete implementation, return the number of rows
+		return 1
+	}
+
+	override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+		let section = indexPath.section
+		if section == 0 {
+			return displayNameCell
+		} else {
+			return statusCell
+		}
+	}
+
+	func activateField(option: SettingsEditOption) {
+		switch option {
+		case .DISPLAYNAME:
+			displayNameCell.textField.becomeFirstResponder()
+		case .STATUS:
+			statusCell.textField.becomeFirstResponder()
+		}
+	}
+}

+ 225 - 264
deltachat-ios/Controller/SettingsController.swift

@@ -13,268 +13,229 @@ import QuickTableViewController
 import UIKit
 
 internal final class SettingsViewController: QuickTableViewController {
-  weak var coordinator: SettingsCoordinator?
-
-  let documentInteractionController = UIDocumentInteractionController()
-  var backupProgressObserver: Any?
-  var configureProgressObserver: Any?
-
-  private lazy var hudHandler: HudHandler = {
-    let hudHandler = HudHandler(parentView: self.tableView)
-    return hudHandler
-  }()
-
-  override func viewDidLoad() {
-    super.viewDidLoad()
-    title = "Settings"
-    documentInteractionController.delegate = self as? UIDocumentInteractionControllerDelegate
-    setTable()
-  }
-
-  override func viewDidAppear(_ animated: Bool) {
-    super.viewDidAppear(animated)
-    let nc = NotificationCenter.default
-    backupProgressObserver = nc.addObserver(
-      forName: dcNotificationBackupProgress,
-      object: nil,
-      queue: nil
-    ) { notification in
-      if let ui = notification.userInfo {
-        if ui["error"] as! Bool {
-          self.hudHandler.setHudError(ui["errorMessage"] as? String)
-        } else if ui["done"] as! Bool {
-          self.hudHandler.setHudDone(callback: nil)
-        } else {
-          self.hudHandler.setHudProgress(ui["progress"] as! Int)
-        }
-      }
-    }
-    configureProgressObserver = nc.addObserver(
-      forName: dcNotificationConfigureProgress,
-      object: nil,
-      queue: nil
-    ) { notification in
-      if let ui = notification.userInfo {
-        if ui["error"] as! Bool {
-          self.hudHandler.setHudError(ui["errorMessage"] as? String)
-        } else if ui["done"] as! Bool {
-          self.hudHandler.setHudDone(callback: nil)
-        } else {
-          self.hudHandler.setHudProgress(ui["progress"] as! Int)
-        }
-      }
-    }
-  }
-
-  override func viewWillAppear(_ animated: Bool) {
-    super.viewWillAppear(animated)
-
-    if #available(iOS 11.0, *) {
-      navigationController?.navigationBar.prefersLargeTitles = true
-    }
-  }
-
-  override func viewWillDisappear(_ animated: Bool) {
-    super.viewWillDisappear(animated)
-    if #available(iOS 11.0, *) {
-      navigationController?.navigationBar.prefersLargeTitles = false
-    }
-  }
-
-  override func viewDidDisappear(_ animated: Bool) {
-    super.viewDidDisappear(animated)
-
-    let nc = NotificationCenter.default
-    if let backupProgressObserver = self.backupProgressObserver {
-      nc.removeObserver(backupProgressObserver)
-    }
-    if let configureProgressObserver = self.configureProgressObserver {
-      nc.removeObserver(configureProgressObserver)
-    }
-  }
-
-  private func setTable() {
-    var backupRows = [
-      TapActionRow(text: "Create backup", action: { [weak self] in self?.createBackup($0) }),
-    ]
-
-    let deleteRow = TapActionRow(text: "Delete Account", action: { [weak self] in self?.deleteAccount($0) })
-
-    tableContents = [
-      Section(
-        title: "User Details",
-        rows: [
-          NavigationRow(text: "Display Name", detailText: .value1(MRConfig.displayname ?? ""), action: editCell()),
-          NavigationRow(text: "Status", detailText: .value1(MRConfig.selfstatus ?? ""), action: editCell()),
-          TapActionRow(text: "Configure my Account", action: { [weak self] in self?.presentAccountSetup($0) }),
-        ]
-      ),
-      Section(
-        title: "Flags",
-        rows: [
-          SwitchRow(text: "E2EE enabled", switchValue: MRConfig.e2eeEnabled, action: editCell()),
-          SwitchRow(text: "Read Receipts", switchValue: MRConfig.mdnsEnabled, action: editCell()),
-          SwitchRow(text: "Watch Inbox", switchValue: MRConfig.inboxWatch, action: editCell()),
-          SwitchRow(text: "Watch Sentbox", switchValue: MRConfig.sentboxWatch, action: editCell()),
-          SwitchRow(text: "Watch Mvbox", switchValue: MRConfig.mvboxWatch, action: editCell()),
-          SwitchRow(text: "Move to Mvbox", switchValue: MRConfig.mvboxMove, action: editCell()),
-          SwitchRow(text: "Save Mime Headers", switchValue: MRConfig.saveMimeHeaders, action: editCell()),
-        ]
-      ),
-
-      Section(
-        title: "Backup",
-        rows: backupRows
-      ),
-
-      Section(title: "Danger", rows: [
-        deleteRow,
-      ]),
-    ]
-  }
-
-  // FIXME: simplify this method
-  // swiftlint:disable cyclomatic_complexity
-  private func editCell() -> (Row) -> Void {
-    return { [weak self] sender in
-      logger.info("row edit", sender.text)
-
-      let title = sender.text
-      let subtitle: String = sender.detailText?.text ?? ""
-      let alertController = UIAlertController(title: title, message: nil, preferredStyle: .alert)
-
-      if title == "Email" {
-        if MRConfig.configured {
-          // Don't change emails in the running system
-          return
-        }
-      }
-
-      if let sender = sender as? SwitchRow {
-        logger.info("got bool switch")
-        let value = sender.switchValue
-
-        switch title {
-        case "E2EE enabled":
-          MRConfig.e2eeEnabled = value
-        case "Read Receipts":
-          MRConfig.mdnsEnabled = value
-        case "Watch Inbox":
-          MRConfig.inboxWatch = value
-        case "Watch Sentbox":
-          MRConfig.sentboxWatch = value
-        case "Watch Mvbox":
-          MRConfig.mvboxWatch = value
-        case "Move to Mvbox":
-          MRConfig.mvboxMove = value
-        case "Save Mime Headers":
-          MRConfig.saveMimeHeaders = value
-        default:
-          logger.info("unknown title", title)
-        }
-        dc_configure(mailboxPointer)
-        return
-      }
-
-      let confirmAction = UIAlertAction(title: "Save", style: .default) { _ in
-        guard let textFields = alertController.textFields,
-          !textFields.isEmpty else {
-          // Could not find textfield
-          return
-        }
-
-        let field = textFields[0]
-
-        // TODO: add field validation
-        var needRefresh = false
-
-        switch title {
-        case "Display Name":
-          MRConfig.displayname = field.text
-          needRefresh = true
-        case "Status":
-          MRConfig.selfstatus = field.text
-          needRefresh = true
-        default:
-          logger.info("unknown title", title)
-        }
-
-        if needRefresh {
-          dc_configure(mailboxPointer)
-          self?.setTable()
-          self?.tableView.reloadData()
-        }
-      }
-
-      let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { _ in
-        logger.info("canceled")
-      }
-
-      alertController.addTextField { textField in
-        textField.placeholder = subtitle
-      }
-
-      alertController.addAction(confirmAction)
-      alertController.addAction(cancelAction)
-
-      self?.present(alertController, animated: true, completion: nil)
-    }
-  }
-
-  private func createBackup(_: Row) {
-    // if let documents = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.delta.chat.ios")?.path {
-
-    let documents = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
-    if !documents.isEmpty {
-      logger.info("create backup in \(documents)")
-      hudHandler.showBackupHud("Creating Backup")
-      DispatchQueue.main.async {
-        dc_imex(mailboxPointer, DC_IMEX_EXPORT_BACKUP, documents[0], nil)
-      }
-    } else {
-      logger.error("document directory not found")
-    }
-  }
-
-  private func configure(_: Row) {
-    hudHandler.showBackupHud("Configuring account")
-    dc_configure(mailboxPointer)
-  }
-
-  private func deleteAccount(_: Row) {
-    logger.info("deleting account")
-    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
-      return
-    }
-
-    let dbfile = appDelegate.dbfile()
-    let dburl = URL(fileURLWithPath: dbfile, isDirectory: false)
-    let alert = UIAlertController(title: "Delete Account", message: "Are you sure you wante to delete your account data?", preferredStyle: .alert)
-
-    alert.addAction(UIAlertAction(title: "Delete", style: .destructive, handler: { _ in
-      appDelegate.stop()
-      appDelegate.close()
-      do {
-        try FileManager.default.removeItem(at: dburl)
-      } catch {
-        logger.error("failed to delete db: \(error)")
-      }
-
-      appDelegate.open()
-      appDelegate.start()
-
-      // refresh our view
-      self.setTable()
-      self.tableView.reloadData()
-
-      self.dismiss(animated: true, completion: nil)
-    }))
-    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
-
-    present(alert, animated: true, completion: nil)
-  }
-
-  private func presentAccountSetup(_: Row) {
-    coordinator?.showAccountSetupController()
-  }
+	weak var coordinator: SettingsCoordinator?
+
+	let documentInteractionController = UIDocumentInteractionController()
+	var backupProgressObserver: Any?
+	var configureProgressObserver: Any?
+
+	private lazy var hudHandler: HudHandler = {
+		let hudHandler = HudHandler(parentView: self.tableView)
+		return hudHandler
+	}()
+
+	override func viewDidLoad() {
+		super.viewDidLoad()
+		title = "Settings"
+		documentInteractionController.delegate = self as? UIDocumentInteractionControllerDelegate
+	}
+
+
+	override func viewDidAppear(_ animated: Bool) {
+
+		super.viewDidAppear(animated)
+		let nc = NotificationCenter.default
+		backupProgressObserver = nc.addObserver(
+			forName: dcNotificationBackupProgress,
+			object: nil,
+			queue: nil
+		) { notification in
+			if let ui = notification.userInfo {
+				if ui["error"] as! Bool {
+					self.hudHandler.setHudError(ui["errorMessage"] as? String)
+				} else if ui["done"] as! Bool {
+					self.hudHandler.setHudDone(callback: nil)
+				} else {
+					self.hudHandler.setHudProgress(ui["progress"] as! Int)
+				}
+			}
+		}
+		configureProgressObserver = nc.addObserver(
+			forName: dcNotificationConfigureProgress,
+			object: nil,
+			queue: nil
+		) { notification in
+			if let ui = notification.userInfo {
+				if ui["error"] as! Bool {
+					self.hudHandler.setHudError(ui["errorMessage"] as? String)
+				} else if ui["done"] as! Bool {
+					self.hudHandler.setHudDone(callback: nil)
+				} else {
+					self.hudHandler.setHudProgress(ui["progress"] as! Int)
+				}
+			}
+		}
+	}
+
+	override func viewWillAppear(_ animated: Bool) {
+		super.viewWillAppear(animated)
+		setTable()
+		if #available(iOS 11.0, *) {
+			navigationController?.navigationBar.prefersLargeTitles = true
+		}
+	}
+
+	override func viewWillDisappear(_ animated: Bool) {
+		super.viewWillDisappear(animated)
+		if #available(iOS 11.0, *) {
+			navigationController?.navigationBar.prefersLargeTitles = false
+		}
+	}
+
+	override func viewDidDisappear(_ animated: Bool) {
+		super.viewDidDisappear(animated)
+
+		let nc = NotificationCenter.default
+		if let backupProgressObserver = self.backupProgressObserver {
+			nc.removeObserver(backupProgressObserver)
+		}
+		if let configureProgressObserver = self.configureProgressObserver {
+			nc.removeObserver(configureProgressObserver)
+		}
+	}
+
+	private func setTable() {
+		var backupRows = [
+			TapActionRow(text: "Create backup", action: { [weak self] in self?.createBackup($0) }),
+		]
+
+		let deleteRow = TapActionRow(text: "Delete Account", action: { [weak self] in self?.deleteAccount($0) })
+
+		tableContents = [
+			Section(
+				title: "User Details",
+				rows: [
+					NavigationRow(text: "Display Name", detailText: .value1(MRConfig.displayname ?? ""), action: { [weak self] in self?.editNameAndStatus($0)}),
+					NavigationRow(text: "Status", detailText: .value1(MRConfig.selfstatus ?? ""), action: { [weak self] in self?.editNameAndStatus($0)}),
+					TapActionRow(text: "Configure my Account", action: { [weak self] in self?.presentAccountSetup($0) }),
+				]
+			),
+			Section(
+				title: "Flags",
+				rows: [
+					SwitchRow(text: "E2EE enabled", switchValue: MRConfig.e2eeEnabled, action: editCell()),
+					SwitchRow(text: "Read Receipts", switchValue: MRConfig.mdnsEnabled, action: editCell()),
+					SwitchRow(text: "Watch Inbox", switchValue: MRConfig.inboxWatch, action: editCell()),
+					SwitchRow(text: "Watch Sentbox", switchValue: MRConfig.sentboxWatch, action: editCell()),
+					SwitchRow(text: "Watch Mvbox", switchValue: MRConfig.mvboxWatch, action: editCell()),
+					SwitchRow(text: "Move to Mvbox", switchValue: MRConfig.mvboxMove, action: editCell()),
+					SwitchRow(text: "Save Mime Headers", switchValue: MRConfig.saveMimeHeaders, action: editCell()),
+				]
+			),
+
+			Section(
+				title: "Backup",
+				rows: backupRows
+			),
+
+			Section(title: "Danger", rows: [
+				deleteRow,
+				]),
+		]
+	}
+
+	// FIXME: simplify this method
+	// swiftlint:disable cyclomatic_complexity
+	private func editCell() -> (Row) -> Void {
+		return { [weak self] sender in
+			logger.info("row edit", sender.text)
+
+			let title = sender.text
+			let subtitle: String = sender.detailText?.text ?? ""
+
+
+			if let sender = sender as? SwitchRow {
+				logger.info("got bool switch")
+				let value = sender.switchValue
+
+				switch title {
+				case "E2EE enabled":
+					MRConfig.e2eeEnabled = value
+				case "Read Receipts":
+					MRConfig.mdnsEnabled = value
+				case "Watch Inbox":
+					MRConfig.inboxWatch = value
+				case "Watch Sentbox":
+					MRConfig.sentboxWatch = value
+				case "Watch Mvbox":
+					MRConfig.mvboxWatch = value
+				case "Move to Mvbox":
+					MRConfig.mvboxMove = value
+				case "Save Mime Headers":
+					MRConfig.saveMimeHeaders = value
+				default:
+					logger.info("unknown title", title)
+				}
+				dc_configure(mailboxPointer)
+				return
+			}
+		}
+	}
+
+	private func createBackup(_: Row) {
+		// if let documents = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.delta.chat.ios")?.path {
+
+		let documents = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
+		if !documents.isEmpty {
+			logger.info("create backup in \(documents)")
+			hudHandler.showBackupHud("Creating Backup")
+			DispatchQueue.main.async {
+				dc_imex(mailboxPointer, DC_IMEX_EXPORT_BACKUP, documents[0], nil)
+			}
+		} else {
+			logger.error("document directory not found")
+		}
+	}
+
+	private func configure(_: Row) {
+		hudHandler.showBackupHud("Configuring account")
+		dc_configure(mailboxPointer)
+	}
+
+	private func deleteAccount(_: Row) {
+		logger.info("deleting account")
+		guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
+			return
+		}
+
+		let dbfile = appDelegate.dbfile()
+		let dburl = URL(fileURLWithPath: dbfile, isDirectory: false)
+		let alert = UIAlertController(title: "Delete Account", message: "Are you sure you wante to delete your account data?", preferredStyle: .alert)
+
+		alert.addAction(UIAlertAction(title: "Delete", style: .destructive, handler: { _ in
+			appDelegate.stop()
+			appDelegate.close()
+			do {
+				try FileManager.default.removeItem(at: dburl)
+			} catch {
+				logger.error("failed to delete db: \(error)")
+			}
+
+			appDelegate.open()
+			appDelegate.start()
+
+			// refresh our view
+			self.setTable()
+			self.tableView.reloadData()
+
+			self.dismiss(animated: true, completion: nil)
+		}))
+		alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
+
+		present(alert, animated: true, completion: nil)
+	}
+
+	private func presentAccountSetup(_: Row) {
+		coordinator?.showAccountSetupController()
+	}
+
+	private func editNameAndStatus(_ row: Row) {
+		guard let option = SettingsEditOption(rawValue: row.text) else { return }
+		coordinator?.showEditSettingsController(option: option)
+	}
+}
+
+enum SettingsEditOption: String {
+	case DISPLAYNAME = "Display Name"
+	case STATUS = "Status"
 }

+ 350 - 266
deltachat-ios/Coordinator/AppCoordinator.swift

@@ -9,316 +9,400 @@
 import UIKit
 
 class AppCoordinator: NSObject, Coordinator, UITabBarControllerDelegate {
-  private let window: UIWindow
-
-  var rootViewController: UIViewController {
-    return tabBarController
-  }
-
-  private var childCoordinators: [Coordinator] = []
-
-  private lazy var tabBarController: UITabBarController = {
-    let tabBarController = UITabBarController()
-    tabBarController.viewControllers = [contactListController, mailboxController, profileController, chatListController, settingsController]
-    // put viewControllers here
-    tabBarController.delegate = self
-    tabBarController.tabBar.tintColor = DCColors.primary
-    // tabBarController.tabBar.isTranslucent = false
-    return tabBarController
-  }()
-
-  // MARK: viewControllers
-
-  private lazy var contactListController: UIViewController = {
-    let controller = ContactListController()
-    let nav = NavigationController(rootViewController: controller)
-    let settingsImage = UIImage(named: "contacts")
-    nav.tabBarItem = UITabBarItem(title: "Contacts", image: settingsImage, tag: 4)
-    let coordinator = ContactListCoordinator(navigationController: nav)
-    self.childCoordinators.append(coordinator)
-    controller.coordinator = coordinator
-    return nav
-  }()
-
-  private lazy var mailboxController: UIViewController = {
-    let controller = MailboxViewController(chatId: Int(DC_CHAT_ID_DEADDROP), title: "Mailbox")
-    controller.disableWriting = true
-    let nav = NavigationController(rootViewController: controller)
-    let settingsImage = UIImage(named: "message")
-    nav.tabBarItem = UITabBarItem(title: "Mailbox", image: settingsImage, tag: 4)
-    let coordinator = MailboxCoordinator(navigationController: nav)
-    self.childCoordinators.append(coordinator)
-    controller.coordinator = coordinator
-    return nav
-  }()
-
-  private lazy var profileController: UIViewController = {
-    let controller = ProfileViewController()
-    let nav = NavigationController(rootViewController: controller)
-    let settingsImage = UIImage(named: "report_card")
-    nav.tabBarItem = UITabBarItem(title: "My Profile", image: settingsImage, tag: 4)
-    let coordinator = ProfileCoordinator(rootViewController: nav)
-    self.childCoordinators.append(coordinator)
-    controller.coordinator = coordinator
-    return nav
-  }()
-
-  private lazy var chatListController: UIViewController = {
-    let controller = ChatListController()
-    let nav = NavigationController(rootViewController: controller)
-    let settingsImage = UIImage(named: "chat")
-    nav.tabBarItem = UITabBarItem(title: "Chats", image: settingsImage, tag: 4)
-    let coordinator = ChatListCoordinator(navigationController: nav)
-    self.childCoordinators.append(coordinator)
-    controller.coordinator = coordinator
-    return nav
-  }()
-
-  private lazy var settingsController: UIViewController = {
-    let controller = SettingsViewController()
-    let nav = NavigationController(rootViewController: controller)
-    let settingsImage = UIImage(named: "settings")
-    nav.tabBarItem = UITabBarItem(title: "Settings", image: settingsImage, tag: 4)
-    let coordinator = SettingsCoordinator(navigationController: nav)
-    self.childCoordinators.append(coordinator)
-    controller.coordinator = coordinator
-    return nav
-  }()
-
-  init(window: UIWindow) {
-    self.window = window
-    super.init()
-    window.rootViewController = rootViewController
-    window.makeKeyAndVisible()
-  }
-
-  public func start() {
-    showTab(index: 3)
-  }
-
-  public func showTab(index: Int) {
-    tabBarController.selectedIndex = index
-  }
-
-  public func presentLoginController() {
-    let accountSetupController = AccountSetupController()
-    let accountSetupNavigationController = UINavigationController(rootViewController: accountSetupController)
-    rootViewController.present(accountSetupNavigationController, animated: false, completion: nil)
-  }
+	private let window: UIWindow
+
+	var rootViewController: UIViewController {
+		return tabBarController
+	}
+
+	private var childCoordinators: [Coordinator] = []
+
+	private lazy var tabBarController: UITabBarController = {
+		let tabBarController = UITabBarController()
+		tabBarController.viewControllers = [contactListController, mailboxController, profileController, chatListController, settingsController]
+		// put viewControllers here
+		tabBarController.delegate = self
+		tabBarController.tabBar.tintColor = DCColors.primary
+		// tabBarController.tabBar.isTranslucent = false
+		return tabBarController
+	}()
+
+	// MARK: viewControllers
+
+	private lazy var contactListController: UIViewController = {
+		let controller = ContactListController()
+		let nav = NavigationController(rootViewController: controller)
+		let settingsImage = UIImage(named: "contacts")
+		nav.tabBarItem = UITabBarItem(title: "Contacts", image: settingsImage, tag: 4)
+		let coordinator = ContactListCoordinator(navigationController: nav)
+		self.childCoordinators.append(coordinator)
+		controller.coordinator = coordinator
+		return nav
+	}()
+
+	private lazy var mailboxController: UIViewController = {
+		let controller = MailboxViewController(chatId: Int(DC_CHAT_ID_DEADDROP), title: "Mailbox")
+		controller.disableWriting = true
+		let nav = NavigationController(rootViewController: controller)
+		let settingsImage = UIImage(named: "message")
+		nav.tabBarItem = UITabBarItem(title: "Mailbox", image: settingsImage, tag: 4)
+		let coordinator = MailboxCoordinator(navigationController: nav)
+		self.childCoordinators.append(coordinator)
+		controller.coordinator = coordinator
+		return nav
+	}()
+
+	private lazy var profileController: UIViewController = {
+		let controller = ProfileViewController()
+		let nav = NavigationController(rootViewController: controller)
+		let settingsImage = UIImage(named: "report_card")
+		nav.tabBarItem = UITabBarItem(title: "My Profile", image: settingsImage, tag: 4)
+		let coordinator = ProfileCoordinator(rootViewController: nav)
+		self.childCoordinators.append(coordinator)
+		controller.coordinator = coordinator
+		return nav
+	}()
+
+	private lazy var chatListController: UIViewController = {
+		let controller = ChatListController()
+		let nav = NavigationController(rootViewController: controller)
+		let settingsImage = UIImage(named: "chat")
+		nav.tabBarItem = UITabBarItem(title: "Chats", image: settingsImage, tag: 4)
+		let coordinator = ChatListCoordinator(navigationController: nav)
+		self.childCoordinators.append(coordinator)
+		controller.coordinator = coordinator
+		return nav
+	}()
+
+	private lazy var settingsController: UIViewController = {
+		let controller = SettingsViewController()
+		let nav = NavigationController(rootViewController: controller)
+		let settingsImage = UIImage(named: "settings")
+		nav.tabBarItem = UITabBarItem(title: "Settings", image: settingsImage, tag: 4)
+		let coordinator = SettingsCoordinator(navigationController: nav)
+		self.childCoordinators.append(coordinator)
+		controller.coordinator = coordinator
+		return nav
+	}()
+
+	init(window: UIWindow) {
+		self.window = window
+		super.init()
+		window.rootViewController = rootViewController
+		window.makeKeyAndVisible()
+	}
+
+	public func start() {
+		showTab(index: 3)
+	}
+
+	func showTab(index: Int) {
+		tabBarController.selectedIndex = index
+	}
+
+	func presentLoginController() {
+		let accountSetupController = AccountSetupController()
+		let accountSetupNavigationController = UINavigationController(rootViewController: accountSetupController)
+		rootViewController.present(accountSetupNavigationController, animated: false, completion: nil)
+	}
+}
+
+extension AppCoordinator: UITabBarDelegate {
+	func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
+		print("item selected")
+	}
+
+	func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
+		print("shouldSelect")
+		return true 
+	}
 }
 
 class ContactListCoordinator: Coordinator {
-  let navigationController: UINavigationController
+	let navigationController: UINavigationController
 
-  var childCoordinators: [Coordinator] = []
+	var childCoordinators: [Coordinator] = []
 
-  init(navigationController: UINavigationController) {
-    self.navigationController = navigationController
-  }
+	init(navigationController: UINavigationController) {
+		self.navigationController = navigationController
+	}
 
-  func showContactDetail(contactId: Int) {
-    let contactDetailController = ContactDetailViewController(contactId: contactId)
-    let coordinator = ContactDetailCoordinator(navigationController: navigationController)
-    childCoordinators.append(coordinator)
-    contactDetailController.coordinator = coordinator
-    navigationController.pushViewController(contactDetailController, animated: true)
-  }
+	func showContactDetail(contactId: Int) {
+		let contactDetailController = ContactDetailViewController(contactId: contactId)
+		let coordinator = ContactDetailCoordinator(navigationController: navigationController)
+		childCoordinators.append(coordinator)
+		contactDetailController.coordinator = coordinator
+		navigationController.pushViewController(contactDetailController, 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
 class MailboxCoordinator: ChatViewCoordinator {
-  override func showChatDetail(chatId _: Int) {
-    // ignore for now
-  }
+	override func showChatDetail(chatId _: Int) {
+		// ignore for now
+	}
 }
 
 class ProfileCoordinator: Coordinator {
-  var rootViewController: UIViewController
+	var rootViewController: UIViewController
 
-  init(rootViewController: UIViewController) {
-    self.rootViewController = rootViewController
-  }
+	init(rootViewController: UIViewController) {
+		self.rootViewController = rootViewController
+	}
 }
 
 class ChatListCoordinator: Coordinator {
-  let navigationController: UINavigationController
-
-  var childCoordinators: [Coordinator] = []
-
-  init(navigationController: UINavigationController) {
-    self.navigationController = navigationController
-  }
-
-  func showNewChatController() {
-    let newChatVC = NewChatViewController()
-    let coordinator = NewChatCoordinator(navigationController: navigationController)
-    childCoordinators.append(coordinator)
-    newChatVC.coordinator = coordinator
-    navigationController.pushViewController(newChatVC, animated: true)
-  }
-
-  func showChat(chatId: Int) {
-    let chatVC = ChatViewController(chatId: chatId)
-    let coordinator = ChatViewCoordinator(navigationController: navigationController)
-    childCoordinators.append(coordinator)
-    chatVC.coordinator = coordinator
-    navigationController.pushViewController(chatVC, animated: true)
-  }
+	let navigationController: UINavigationController
+
+	var childCoordinators: [Coordinator] = []
+
+	init(navigationController: UINavigationController) {
+		self.navigationController = navigationController
+	}
+
+	func showNewChatController() {
+		let newChatVC = NewChatViewController()
+		let coordinator = NewChatCoordinator(navigationController: navigationController)
+		childCoordinators.append(coordinator)
+		newChatVC.coordinator = coordinator
+		navigationController.pushViewController(newChatVC, animated: true)
+	}
+
+	func showChat(chatId: Int) {
+		let chatVC = ChatViewController(chatId: chatId)
+		let coordinator = ChatViewCoordinator(navigationController: navigationController)
+		childCoordinators.append(coordinator)
+		chatVC.coordinator = coordinator
+		navigationController.pushViewController(chatVC, animated: true)
+	}
 }
 
 class SettingsCoordinator: Coordinator {
-  let navigationController: UINavigationController
-
-  init(navigationController: UINavigationController) {
-    self.navigationController = navigationController
-  }
+	let navigationController: UINavigationController
+
+	var childCoordinators:[Coordinator] = []
+
+	init(navigationController: UINavigationController) {
+		self.navigationController = navigationController
+	}
+
+	func showAccountSetupController() {
+		let accountSetupVC = AccountSetupController()
+		let coordinator = AccountSetupCoordinator(navigationController: navigationController)
+		childCoordinators.append(coordinator)
+		accountSetupVC.coordinator = coordinator
+		navigationController.pushViewController(accountSetupVC, animated: true)
+	}
+
+	func showEditSettingsController(option: SettingsEditOption) {
+		let editController = EditSettingsController()
+		editController.activateField(option: option)
+		navigationController.pushViewController(editController, animated: true)
+	}
+}
 
-  func showAccountSetupController() {
-    let accountSetupVC = AccountSetupController()
-    navigationController.pushViewController(accountSetupVC, animated: true)
-  }
+class AccountSetupCoordinator: Coordinator {
+	let navigationController: UINavigationController
+
+	init(navigationController: UINavigationController) {
+		self.navigationController = navigationController
+	}
+
+	func showImapPortOptions() {
+		let currentMailPort = MRConfig.mailPort ?? MRConfig.configuredMailPort
+		let currentPort = Int(currentMailPort)
+		let portSettingsController = PortSettingsController(sectionTitle: "IMAP Port", ports: [143, 993], currentPort: currentPort)
+		portSettingsController.onDismiss = {
+			port in
+			MRConfig.mailPort = port
+			dc_configure(mailboxPointer)
+		}
+		navigationController.pushViewController(portSettingsController, animated: true)
+	}
+
+	func showImapSecurityOptions() {
+		let currentSecurityOption = MRConfig.getImapSecurity()
+		let convertedOption = SecurityConverter.convertHexToString(type: .IMAPSecurity, hex: currentSecurityOption)
+		let securitySettingsController = SecuritySettingsController(title: "IMAP Security", options: ["Automatic", "SSL / TLS", "STARTTLS", "OFF"], selectedOption: convertedOption)
+		securitySettingsController.onDismiss = {
+			option in
+			if let secValue = SecurityValue(rawValue: option) {
+				let value = SecurityConverter.convertValueToInt(type: .IMAPSecurity, value: secValue)
+				MRConfig.setImapSecurity(imapFlags: value)
+				dc_configure(mailboxPointer)
+			}
+		}
+		navigationController.pushViewController(securitySettingsController, animated: true)
+	}
+
+	func showSmtpPortsOptions() {
+		let currentMailPort = MRConfig.sendPort ?? MRConfig.configuredSendPort
+		let currentPort = Int(currentMailPort)
+		let portSettingsController = PortSettingsController(sectionTitle: "SMTP Port", ports: [25, 465, 587], currentPort: currentPort)
+		portSettingsController.onDismiss = {
+			port in
+			MRConfig.sendPort = port
+			dc_configure(mailboxPointer)
+		}
+		navigationController.pushViewController(portSettingsController, animated: true)
+	}
+
+	func showSmptpSecurityOptions() {
+		let currentSecurityOption = MRConfig.getSmtpSecurity()
+		let convertedOption = SecurityConverter.convertHexToString(type: .SMTPSecurity, hex: currentSecurityOption)
+		let securitySettingsController = SecuritySettingsController(title: "IMAP Security", options: ["Automatic", "SSL / TLS", "STARTTLS", "OFF"], selectedOption: convertedOption)
+		securitySettingsController.onDismiss = {
+			option in
+			if let secValue = SecurityValue(rawValue: option) {
+				let value = SecurityConverter.convertValueToInt(type: .SMTPSecurity, value: secValue)
+				MRConfig.setSmtpSecurity(smptpFlags: value)
+				dc_configure(mailboxPointer)
+			}
+		}
+		navigationController.pushViewController(securitySettingsController, animated: true)
+	}
 }
 
 class NewChatCoordinator: Coordinator {
-  let navigationController: UINavigationController
-
-  private var childCoordinators: [Coordinator] = []
-
-  init(navigationController: UINavigationController) {
-    self.navigationController = navigationController
-  }
-
-  func showNewGroupController() {
-    let newGroupController = NewGroupViewController()
-    let coordinator = NewGroupCoordinator(navigationController: navigationController)
-    childCoordinators.append(coordinator)
-    newGroupController.coordinator = coordinator
-    navigationController.pushViewController(newGroupController, animated: true)
-  }
-
-  func showQRCodeController() {
-    let controller = QrCodeReaderController()
-    // controller.delegate = self
-    // present(controller, animated: true, completion: nil)
-  }
-
-  func showNewContactController() {
-    let newContactController = NewContactController()
-    navigationController.pushViewController(newContactController, animated: true)
-  }
-
-  func showNewChat(contactId: Int) {
-    let chatId = dc_create_chat_by_contact_id(mailboxPointer, UInt32(contactId))
-    showChat(chatId: Int(chatId))
-  }
-
-  func showChat(chatId: Int) {
-    let chatViewController = ChatViewController(chatId: chatId)
-    let coordinator = ChatViewCoordinator(navigationController: navigationController)
-    childCoordinators.append(coordinator)
-    chatViewController.coordinator = coordinator
-    navigationController.pushViewController(chatViewController, animated: true)
-    navigationController.viewControllers.remove(at: 1)
-  }
+	let navigationController: UINavigationController
+
+	private var childCoordinators: [Coordinator] = []
+
+	init(navigationController: UINavigationController) {
+		self.navigationController = navigationController
+	}
+
+	func showNewGroupController() {
+		let newGroupController = NewGroupViewController()
+		let coordinator = NewGroupCoordinator(navigationController: navigationController)
+		childCoordinators.append(coordinator)
+		newGroupController.coordinator = coordinator
+		navigationController.pushViewController(newGroupController, animated: true)
+	}
+
+	func showQRCodeController() {
+		let controller = QrCodeReaderController()
+		// controller.delegate = self
+		// present(controller, animated: true, completion: nil)
+	}
+
+	func showNewContactController() {
+		let newContactController = NewContactController()
+		navigationController.pushViewController(newContactController, animated: true)
+	}
+
+	func showNewChat(contactId: Int) {
+		let chatId = dc_create_chat_by_contact_id(mailboxPointer, UInt32(contactId))
+		showChat(chatId: Int(chatId))
+	}
+
+	func showChat(chatId: Int) {
+		let chatViewController = ChatViewController(chatId: chatId)
+		let coordinator = ChatViewCoordinator(navigationController: navigationController)
+		childCoordinators.append(coordinator)
+		chatViewController.coordinator = coordinator
+		navigationController.pushViewController(chatViewController, animated: true)
+		navigationController.viewControllers.remove(at: 1)
+	}
 }
 
 class ChatDetailCoordinator: Coordinator {
-  let navigationController: UINavigationController
+	let navigationController: UINavigationController
 
-  private var childCoordinators: [Coordinator] = []
+	private var childCoordinators: [Coordinator] = []
 
-  init(navigationController: UINavigationController) {
-    self.navigationController = navigationController
-  }
+	init(navigationController: UINavigationController) {
+		self.navigationController = navigationController
+	}
 
-  func showSingleChatEdit(contactId: Int) {
-    let newContactController = NewContactController(contactIdForUpdate: contactId)
-    navigationController.pushViewController(newContactController, animated: true)
-  }
+	func showSingleChatEdit(contactId: Int) {
+		let newContactController = NewContactController(contactIdForUpdate: contactId)
+		navigationController.pushViewController(newContactController, animated: true)
+	}
 
-  func showAddGroupMember(chatId: Int) {
-    let groupMemberViewController = AddGroupMembersViewController(chatId: chatId)
-    navigationController.pushViewController(groupMemberViewController, animated: true)
-  }
+	func showAddGroupMember(chatId: Int) {
+		let groupMemberViewController = AddGroupMembersViewController(chatId: chatId)
+		navigationController.pushViewController(groupMemberViewController, animated: true)
+	}
 }
 
 class ChatViewCoordinator: Coordinator {
-  let navigationController: UINavigationController
-
-  var childCoordinators: [Coordinator] = []
-
-  init(navigationController: UINavigationController) {
-    self.navigationController = navigationController
-  }
-
-  func showChatDetail(chatId: Int) {
-    let chat = MRChat(id: chatId)
-    let chatDetailViewController: ChatDetailViewController
-    switch chat.chatType {
-    case .SINGLE:
-      chatDetailViewController = SingleChatDetailViewController(chatId: chatId) // inherits from ChatDetailViewController
-    case .GROUP, .VERYFIEDGROUP:
-      chatDetailViewController = GroupChatDetailViewController(chatId: chatId) // inherits from ChatDetailViewController
-    }
-    let coordinator = ChatDetailCoordinator(navigationController: navigationController)
-    childCoordinators.append(coordinator)
-    chatDetailViewController.coordinator = coordinator
-    navigationController.pushViewController(chatDetailViewController, animated: true)
-  }
+	let navigationController: UINavigationController
+
+	var childCoordinators: [Coordinator] = []
+
+	init(navigationController: UINavigationController) {
+		self.navigationController = navigationController
+	}
+
+	func showChatDetail(chatId: Int) {
+		let chat = MRChat(id: chatId)
+		let chatDetailViewController: ChatDetailViewController
+		switch chat.chatType {
+		case .SINGLE:
+			chatDetailViewController = SingleChatDetailViewController(chatId: chatId) // inherits from ChatDetailViewController
+		case .GROUP, .VERYFIEDGROUP:
+			chatDetailViewController = GroupChatDetailViewController(chatId: chatId) // inherits from ChatDetailViewController
+		}
+		let coordinator = ChatDetailCoordinator(navigationController: navigationController)
+		childCoordinators.append(coordinator)
+		chatDetailViewController.coordinator = coordinator
+		navigationController.pushViewController(chatDetailViewController, animated: true)
+	}
 }
 
 class NewGroupCoordinator: Coordinator {
-  let navigationController: UINavigationController
+	let navigationController: UINavigationController
 
-  private var childCoordinators: [Coordinator] = []
+	private var childCoordinators: [Coordinator] = []
 
-  init(navigationController: UINavigationController) {
-    self.navigationController = navigationController
-  }
+	init(navigationController: UINavigationController) {
+		self.navigationController = navigationController
+	}
 
-  func showGroupNameController(contactIdsForGroup: Set<Int>) {
-    let groupNameController = GroupNameController(contactIdsForGroup: contactIdsForGroup)
-    let coordinator = GroupNameCoordinator(navigationController: navigationController)
-    childCoordinators.append(coordinator)
-    groupNameController.coordinator = coordinator
-    navigationController.pushViewController(groupNameController, animated: true)
-  }
+	func showGroupNameController(contactIdsForGroup: Set<Int>) {
+		let groupNameController = GroupNameController(contactIdsForGroup: contactIdsForGroup)
+		let coordinator = GroupNameCoordinator(navigationController: navigationController)
+		childCoordinators.append(coordinator)
+		groupNameController.coordinator = coordinator
+		navigationController.pushViewController(groupNameController, animated: true)
+	}
 }
 
 class GroupNameCoordinator: Coordinator {
-  let navigationController: UINavigationController
-
-  private var childCoordinators: [Coordinator] = []
-
-  init(navigationController: UINavigationController) {
-    self.navigationController = navigationController
-  }
-
-  func showGroupChat(chatId: Int) {
-    let chatViewController = ChatViewController(chatId: chatId)
-    let coordinator = ChatViewCoordinator(navigationController: navigationController)
-    childCoordinators.append(coordinator)
-    chatViewController.coordinator = coordinator
-    navigationController.popToRootViewController(animated: false)
-    navigationController.pushViewController(chatViewController, animated: true)
-  }
+	let navigationController: UINavigationController
+
+	private var childCoordinators: [Coordinator] = []
+
+	init(navigationController: UINavigationController) {
+		self.navigationController = navigationController
+	}
+
+	func showGroupChat(chatId: Int) {
+		let chatViewController = ChatViewController(chatId: chatId)
+		let coordinator = ChatViewCoordinator(navigationController: navigationController)
+		childCoordinators.append(coordinator)
+		chatViewController.coordinator = coordinator
+		navigationController.popToRootViewController(animated: false)
+		navigationController.pushViewController(chatViewController, animated: true)
+	}
 }
 
 class ContactDetailCoordinator: Coordinator {
-  let navigationController: UINavigationController
-
-  private var childCoordinators: [Coordinator] = []
-
-  init(navigationController: UINavigationController) {
-    self.navigationController = navigationController
-  }
-
-  func showChat(chatId: Int) {
-    let chatViewController = ChatViewController(chatId: chatId)
-    let coordinator = ChatViewCoordinator(navigationController: navigationController)
-    childCoordinators.append(coordinator)
-    chatViewController.coordinator = coordinator
-    navigationController.popToRootViewController(animated: false)
-    navigationController.pushViewController(chatViewController, animated: true)
-  }
+	let navigationController: UINavigationController
+
+	private var childCoordinators: [Coordinator] = []
+
+	init(navigationController: UINavigationController) {
+		self.navigationController = navigationController
+	}
+
+	func showChat(chatId: Int) {
+		let chatViewController = ChatViewController(chatId: chatId)
+		let coordinator = ChatViewCoordinator(navigationController: navigationController)
+		childCoordinators.append(coordinator)
+		chatViewController.coordinator = coordinator
+		navigationController.popToRootViewController(animated: false)
+		navigationController.pushViewController(chatViewController, animated: true)
+	}
 }

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

@@ -933,3 +933,4 @@ class MRConfig {
     set {}
   }
 }
+

+ 1 - 1
deltachat-ios/DC/events.swift

@@ -93,7 +93,7 @@ public func callbackSwift(event: CInt, data1: CUnsignedLong, data2: CUnsignedLon
         UserDefaults.standard.set(true, forKey: Constants.Keys.deltachatUserProvidedCredentialsKey)
         UserDefaults.standard.synchronize()
         let appDelegate = UIApplication.shared.delegate as! AppDelegate
-        appDelegate.appCoordinator?.showTab(index: 3)
+       // appDelegate.appCoordinator?.showTab(index: 3)
         AppDelegate.lastErrorDuringConfig = nil
       }
     }

+ 1 - 0
deltachat-ios/Helper/Constants.swift

@@ -26,3 +26,4 @@ struct Constants {
 
   static let notificationIdentifier = "deltachat-ios-local-notifications"
 }
+

+ 0 - 7
deltachat-ios/View/ActionCell.swift

@@ -30,13 +30,6 @@ class ActionCell: UITableViewCell {
     return label
   }()
 
-  // use this constructor if cell won't be reused
-  convenience init(title: String) {
-    self.init(style: .default, reuseIdentifier: nil)
-    actionTitle = title
-    selectionStyle = .none
-  }
-
   override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
     super.init(style: style, reuseIdentifier: reuseIdentifier)
     setupSubviews()

+ 7 - 0
deltachat-ios/View/TextFieldCell.swift

@@ -11,11 +11,14 @@ import UIKit
 class TextFieldCell: UITableViewCell {
   private let placeholder: String
 
+	var onTextFieldChange:((_:UITextField)->Void)?	// set this from outside to get notified about textfield changes
+
   lazy var textField: UITextField = {
     let textField = UITextField()
     textField.textAlignment = .right
     // textField.enablesReturnKeyAutomatically = true
     textField.placeholder = self.placeholder
+		textField.addTarget(self, action: #selector(textFieldChanged), for: .editingChanged)
     return textField
   }()
 
@@ -56,6 +59,10 @@ class TextFieldCell: UITableViewCell {
     }
   }
 
+	@objc func textFieldChanged() {
+		onTextFieldChange?(self.textField)
+	}
+
   func getText() -> String? {
     if let text = textField.text {
       if text.isEmpty {