SettingsController.swift 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import JGProgressHUD
  2. import QuickTableViewController
  3. import UIKit
  4. internal final class SettingsViewController: QuickTableViewController {
  5. weak var coordinator: SettingsCoordinator?
  6. let documentInteractionController = UIDocumentInteractionController()
  7. var backupProgressObserver: Any?
  8. var configureProgressObserver: Any?
  9. private lazy var hudHandler: HudHandler = {
  10. let hudHandler = HudHandler(parentView: self.view)
  11. return hudHandler
  12. }()
  13. static let e2eeEnabled: Int = 1
  14. static let readReceipts: Int = 2
  15. static let watchInbox: Int = 3
  16. static let watchSentbox: Int = 4
  17. static let watchMvBox: Int = 5
  18. static let MvToMvbox: Int = 6
  19. static let SaveMimeHeaders: Int = 7
  20. private typealias SVC = SettingsViewController
  21. override func viewDidLoad() {
  22. super.viewDidLoad()
  23. title = String.localized("menu_settings")
  24. documentInteractionController.delegate = self as? UIDocumentInteractionControllerDelegate
  25. }
  26. override func viewDidAppear(_ animated: Bool) {
  27. super.viewDidAppear(animated)
  28. let nc = NotificationCenter.default
  29. backupProgressObserver = nc.addObserver(
  30. forName: dcNotificationBackupProgress,
  31. object: nil,
  32. queue: nil
  33. ) { notification in
  34. if let ui = notification.userInfo {
  35. if ui["error"] as! Bool {
  36. self.hudHandler.setHudError(ui["errorMessage"] as? String)
  37. } else if ui["done"] as! Bool {
  38. self.hudHandler.setHudDone(callback: nil)
  39. } else {
  40. self.hudHandler.setHudProgress(ui["progress"] as! Int)
  41. }
  42. }
  43. }
  44. configureProgressObserver = nc.addObserver(
  45. forName: dcNotificationConfigureProgress,
  46. object: nil,
  47. queue: nil
  48. ) { notification in
  49. if let ui = notification.userInfo {
  50. if ui["error"] as! Bool {
  51. self.hudHandler.setHudError(ui["errorMessage"] as? String)
  52. } else if ui["done"] as! Bool {
  53. self.hudHandler.setHudDone(callback: nil)
  54. } else {
  55. self.hudHandler.setHudProgress(ui["progress"] as! Int)
  56. }
  57. }
  58. }
  59. }
  60. override func viewWillAppear(_ animated: Bool) {
  61. super.viewWillAppear(animated)
  62. setTable()
  63. if #available(iOS 11.0, *) {
  64. navigationController?.navigationBar.prefersLargeTitles = true
  65. }
  66. }
  67. override func viewWillDisappear(_ animated: Bool) {
  68. super.viewWillDisappear(animated)
  69. if #available(iOS 11.0, *) {
  70. navigationController?.navigationBar.prefersLargeTitles = false
  71. }
  72. }
  73. override func viewDidDisappear(_ animated: Bool) {
  74. super.viewDidDisappear(animated)
  75. let nc = NotificationCenter.default
  76. if let backupProgressObserver = self.backupProgressObserver {
  77. nc.removeObserver(backupProgressObserver)
  78. }
  79. if let configureProgressObserver = self.configureProgressObserver {
  80. nc.removeObserver(configureProgressObserver)
  81. }
  82. }
  83. private func setTable() {
  84. var backupRows = [
  85. TapActionRow(text: String.localized("create_backup"), action: { [weak self] in self?.createBackup($0) }),
  86. ]
  87. let deleteRow = TapActionRow(text: String.localized("delete_account"), action: { [weak self] in self?.deleteAccount($0) })
  88. tableContents = [
  89. Section(
  90. title: String.localized("user_details"),
  91. rows: [
  92. //FIXME: fix action callback!
  93. NavigationRow(text: String.localized("display_name"), detailText: .value1(DCConfig.displayname ?? ""), action: {
  94. [weak self] in self?.editNameAndStatus($0, option: SettingsEditOption.DISPLAYNAME)
  95. }),
  96. NavigationRow(text: String.localized("status"), detailText: .value1(DCConfig.selfstatus ?? ""), action: {
  97. [weak self] in self?.editNameAndStatus($0, option: SettingsEditOption.STATUS)
  98. }),
  99. TapActionRow(text: String.localized("configure_my_account"), action: { [weak self] in self?.presentAccountSetup($0) }),
  100. ]
  101. ),
  102. Section(
  103. title: String.localized("flags"),
  104. rows: [
  105. SwitchRow(text: String.localized("autocrypt_prefer_e2ee"), switchValue: DCConfig.e2eeEnabled, action: editCell(key: SVC.e2eeEnabled)),
  106. SwitchRow(text: String.localized("pref_read_receipts"), switchValue: DCConfig.mdnsEnabled, action: editCell(key: SVC.readReceipts)),
  107. SwitchRow(text: String.localized("pref_watch_inbox_folder"), switchValue: DCConfig.inboxWatch, action: editCell(key: SVC.watchMvBox)),
  108. SwitchRow(text: String.localized("pref_watch_sent_folder"), switchValue: DCConfig.sentboxWatch, action: editCell(key: SVC.watchSentbox)),
  109. SwitchRow(text: String.localized("pref_watch_mvbox_folder"), switchValue: DCConfig.mvboxWatch, action: editCell(key: SVC.watchMvBox)),
  110. SwitchRow(text: String.localized("pref_auto_folder_moves"), switchValue: DCConfig.mvboxMove, action: editCell(key: SVC.MvToMvbox)),
  111. SwitchRow(text: String.localized("save_mime_headers"), switchValue: DCConfig.saveMimeHeaders, action: editCell(key: SVC.SaveMimeHeaders))
  112. ]
  113. ),
  114. Section(
  115. title: String.localized("pref_backup"),
  116. rows: backupRows
  117. ),
  118. Section(title: String.localized("danger"), rows: [
  119. deleteRow,
  120. ]),
  121. ]
  122. }
  123. // FIXME: simplify this method
  124. private func editCell(key: Int) -> (Row) -> Void {
  125. return { sender in
  126. logger.info("row edit", sender.text)
  127. if let sender = sender as? SwitchRow {
  128. logger.info("got bool switch")
  129. let value = sender.switchValue
  130. switch key {
  131. case SVC.e2eeEnabled:
  132. DCConfig.e2eeEnabled = value
  133. case SVC.readReceipts:
  134. DCConfig.mdnsEnabled = value
  135. case SVC.watchInbox:
  136. DCConfig.inboxWatch = value
  137. case SVC.watchSentbox:
  138. DCConfig.sentboxWatch = value
  139. case SVC.watchMvBox:
  140. DCConfig.mvboxWatch = value
  141. case SVC.MvToMvbox:
  142. DCConfig.mvboxMove = value
  143. case SVC.SaveMimeHeaders:
  144. DCConfig.saveMimeHeaders = value
  145. default:
  146. logger.info("unknown key", String(key))
  147. }
  148. return
  149. }
  150. }
  151. }
  152. private func createBackup(_: Row) {
  153. // if let documents = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.delta.chat.ios")?.path {
  154. let documents = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
  155. if !documents.isEmpty {
  156. logger.info("create backup in \(documents)")
  157. hudHandler.showHud(String.localized("creating_backup"))
  158. DispatchQueue.main.async {
  159. dc_imex(mailboxPointer, DC_IMEX_EXPORT_BACKUP, documents[0], nil)
  160. }
  161. } else {
  162. logger.error("document directory not found")
  163. }
  164. }
  165. private func configure(_: Row) {
  166. hudHandler.showHud(String.localized("configuring_account"))
  167. dc_configure(mailboxPointer)
  168. }
  169. private func deleteAccount(_: Row) {
  170. logger.info("deleting account")
  171. guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
  172. return
  173. }
  174. let dbfile = appDelegate.dbfile()
  175. let dburl = URL(fileURLWithPath: dbfile, isDirectory: false)
  176. let alert = UIAlertController(title: String.localized("delete_account"), message: String.localized("delete_account_message"), preferredStyle: .actionSheet)
  177. alert.addAction(UIAlertAction(title: String.localized("delete"), style: .destructive, handler: { _ in
  178. appDelegate.stop()
  179. appDelegate.close()
  180. do {
  181. try FileManager.default.removeItem(at: dburl)
  182. } catch {
  183. logger.error("failed to delete db: \(error)")
  184. }
  185. appDelegate.open()
  186. appDelegate.start()
  187. // refresh our view
  188. self.setTable()
  189. self.tableView.reloadData()
  190. self.dismiss(animated: false, completion: nil)
  191. self.coordinator?.showLoginController()
  192. }))
  193. alert.addAction(UIAlertAction(title: String.localized("cancel"), style: .cancel))
  194. present(alert, animated: true, completion: nil)
  195. }
  196. private func presentAccountSetup(_: Row) {
  197. coordinator?.showAccountSetupController()
  198. }
  199. private func editNameAndStatus(_ row: Row, option: SettingsEditOption) {
  200. coordinator?.showEditSettingsController(option: option)
  201. }
  202. }
  203. enum SettingsEditOption: String {
  204. case DISPLAYNAME = "Display Name"
  205. case STATUS = "Status"
  206. }