IOS-700 fixes: might take up to 3 seconds to show an email IOS-700-sluggish-ui
authorbuff <andreas@pep-project.org>
Tue, 17 Oct 2017 12:26:27 +0200
branchIOS-700-sluggish-ui
changeset 32088f4f8ed89784
parent 3207 fd02f249ef59
child 3210 bc5726f9398a
IOS-700 fixes: might take up to 3 seconds to show an email
pEpForiOS/UI/Compose/ComposeTableViewController.swift
pEpForiOS/UI/EmailDisplay/EmailListViewController.swift
pEpForiOS/UI/EmailDisplay/EmailViewController.swift
pEpForiOS/UI/Util/UIViewController+Extension.swift
     1.1 --- a/pEpForiOS/UI/Compose/ComposeTableViewController.swift	Tue Oct 17 12:09:52 2017 +0200
     1.2 +++ b/pEpForiOS/UI/Compose/ComposeTableViewController.swift	Tue Oct 17 12:26:27 2017 +0200
     1.3 @@ -72,7 +72,7 @@
     1.4      override func viewWillAppear(_ animated: Bool) {
     1.5          super.viewWillAppear(animated)
     1.6          tableData?.filterRows(message: nil)
     1.7 -        setEmailDisplayColors()
     1.8 +        setEmailDisplayDefaultNavigationBarStyle()
     1.9      }
    1.10  
    1.11      func prepareColor() {
     2.1 --- a/pEpForiOS/UI/EmailDisplay/EmailListViewController.swift	Tue Oct 17 12:09:52 2017 +0200
     2.2 +++ b/pEpForiOS/UI/EmailDisplay/EmailListViewController.swift	Tue Oct 17 12:26:27 2017 +0200
     2.3 @@ -31,16 +31,16 @@
     2.4              return _folderToShow
     2.5          }
     2.6      }
     2.7 -
     2.8 +    
     2.9      func updateLastLookAt() {
    2.10          guard let saveFolder = model?.folderToShow else {
    2.11              return
    2.12          }
    2.13          saveFolder.updateLastLookAt()
    2.14      }
    2.15 -
    2.16 +    
    2.17      private var model: EmailListViewModel?
    2.18 -
    2.19 +    
    2.20      private let queue: OperationQueue = {
    2.21          let createe = OperationQueue()
    2.22          createe.qualityOfService = .userInteractive
    2.23 @@ -50,17 +50,17 @@
    2.24      private var operations = [IndexPath:Operation]()
    2.25      public static let storyboardId = "EmailListViewController"
    2.26      fileprivate var lastSelectedIndexPath: IndexPath?
    2.27 -
    2.28 +    
    2.29      let searchController = UISearchController(searchResultsController: nil)
    2.30 -
    2.31 +    
    2.32      // MARK: - Outlets
    2.33 -
    2.34 +    
    2.35      @IBOutlet weak var enableFilterButton: UIBarButtonItem!
    2.36      @IBOutlet weak var textFilterButton: UIBarButtonItem!
    2.37      @IBOutlet var showFoldersButton: UIBarButtonItem!
    2.38 -
    2.39 +    
    2.40      // MARK: - Life Cycle
    2.41 -
    2.42 +    
    2.43      override func viewDidLoad() {
    2.44          super.viewDidLoad()
    2.45          title = NSLocalizedString("Inbox", comment: "General name for (unified) inbox")
    2.46 @@ -68,14 +68,14 @@
    2.47          self.textFilterButton.isEnabled = false
    2.48          addSearchBar()
    2.49      }
    2.50 -
    2.51 +    
    2.52      override func viewWillAppear(_ animated: Bool) {
    2.53          super.viewWillAppear(animated)
    2.54          self.navigationController?.setToolbarHidden(false, animated: true)
    2.55          if MiscUtil.isUnitTest() {
    2.56              return
    2.57          }
    2.58 -
    2.59 +        
    2.60          if let vm = model {
    2.61              // We came back from e.g EmailView ...
    2.62              self.textFilterButton.isEnabled = vm.isFilterEnabled
    2.63 @@ -85,49 +85,49 @@
    2.64          } else {
    2.65              self.textFilterButton.isEnabled = false
    2.66          }
    2.67 -
    2.68 +        
    2.69          setDefaultColors()
    2.70          setup()
    2.71 -
    2.72 +        
    2.73          // Mark this folder as having been looked at by the user
    2.74          updateLastLookAt()
    2.75          setupFoldersBarButton()
    2.76      }
    2.77 -
    2.78 +    
    2.79      // MARK: - NavigationBar
    2.80 -
    2.81 +    
    2.82      private func hideFoldersNavigationBarButton() {
    2.83          self.showFoldersButton.isEnabled = false
    2.84          self.showFoldersButton.tintColor = UIColor.clear
    2.85      }
    2.86 -
    2.87 +    
    2.88      private func showFoldersNavigationBarButton() {
    2.89          self.showFoldersButton.isEnabled = true
    2.90          self.showFoldersButton.tintColor = nil
    2.91      }
    2.92 -
    2.93 +    
    2.94      private func resetModel() {
    2.95          if _folderToShow != nil {
    2.96              model = EmailListViewModel(delegate: self, folderToShow: _folderToShow)
    2.97          }
    2.98      }
    2.99 -
   2.100 +    
   2.101      private func setup() {
   2.102          // We have not been created to show a specific folder, thus we show unified inbox
   2.103          if model?.folderToShow == nil {
   2.104              folderToShow = UnifiedInbox()
   2.105          }
   2.106 -
   2.107 +        
   2.108          if noAccountsExist() {
   2.109              performSegue(withIdentifier:.segueAddNewAccount, sender: self)
   2.110          }
   2.111          self.title = realNameOfFolderToShow()
   2.112      }
   2.113 -
   2.114 +    
   2.115      private func noAccountsExist() -> Bool {
   2.116          return Account.all().isEmpty
   2.117      }
   2.118 -
   2.119 +    
   2.120      private func setupFoldersBarButton() {
   2.121          if let size = navigationController?.viewControllers.count, size > 1 {
   2.122              hideFoldersNavigationBarButton()
   2.123 @@ -135,7 +135,7 @@
   2.124              showFoldersNavigationBarButton()
   2.125          }
   2.126      }
   2.127 -
   2.128 +    
   2.129      private func addSearchBar() {
   2.130          searchController.searchResultsUpdater = self
   2.131          searchController.dimsBackgroundDuringPresentation = false
   2.132 @@ -144,13 +144,13 @@
   2.133          tableView.tableHeaderView = searchController.searchBar
   2.134          tableView.setContentOffset(CGPoint(x: 0.0, y: 40.0), animated: false)
   2.135      }
   2.136 -
   2.137 +    
   2.138      // MARK: - Other
   2.139 -
   2.140 +    
   2.141      private func realNameOfFolderToShow() -> String? {
   2.142          return model?.folderToShow?.realName
   2.143      }
   2.144 -
   2.145 +    
   2.146      private func configure(cell: EmailListViewCell, for indexPath: IndexPath) {
   2.147          // Configure lightweight stuff on main thread ...
   2.148          guard let saveModel = model else {
   2.149 @@ -169,20 +169,20 @@
   2.150          cell.dateLabel.text = row.dateText
   2.151          // Set image from cache if any
   2.152          cell.setContactImage(image: row.senderContactImage)
   2.153 -
   2.154 +        
   2.155          let op = BlockOperation() { [weak self] in
   2.156              // ... and expensive computations in background
   2.157              guard let strongSelf = self else {
   2.158                  // View is gone, nothing to do.
   2.159                  return
   2.160              }
   2.161 -
   2.162 +            
   2.163              var senderImage: UIImage?
   2.164              if row.senderContactImage == nil {
   2.165                  // image for identity has not been cached yet, get and cache it
   2.166                  senderImage = strongSelf.model?.senderImage(forCellAt: indexPath)
   2.167              }
   2.168 -
   2.169 +            
   2.170              // Set data on cell on main queue.
   2.171              // In theory we want to set all data in *one* async call. But as pEpRatingColorImage takes
   2.172              // very long, we are setting the sender image seperatelly.
   2.173 @@ -191,9 +191,9 @@
   2.174                      cell.contactImageView.image  = senderImage
   2.175                  }
   2.176              }
   2.177 -
   2.178 +            
   2.179              let pEpRatingImage = strongSelf.model?.pEpRatingColorImage(forCellAt: indexPath)
   2.180 -
   2.181 +            
   2.182              // Set data on cell on main queue, again ...
   2.183              DispatchQueue.main.async {
   2.184                  if pEpRatingImage != nil {
   2.185 @@ -203,9 +203,9 @@
   2.186          }
   2.187          queue(operation: op, for: indexPath)
   2.188      }
   2.189 -
   2.190 +    
   2.191      // MARK: - Actions
   2.192 -
   2.193 +    
   2.194      @IBAction func filterButtonHasBeenPressed(_ sender: UIBarButtonItem) {
   2.195          guard let vm = model else {
   2.196              Log.shared.errorAndCrash(component: #function, errorString: "We should have a model here")
   2.197 @@ -214,13 +214,13 @@
   2.198          vm.isFilterEnabled = !vm.isFilterEnabled
   2.199          updateFilterButtonView()
   2.200      }
   2.201 -
   2.202 +    
   2.203      func updateFilterButtonView() {
   2.204          guard let vm = model else {
   2.205              Log.shared.errorAndCrash(component: #function, errorString: "We should have a model here")
   2.206              return
   2.207          }
   2.208 -
   2.209 +        
   2.210          textFilterButton.isEnabled = vm.isFilterEnabled
   2.211          if textFilterButton.isEnabled {
   2.212              enableFilterButton.image = UIImage(named: "unread-icon-active")
   2.213 @@ -230,19 +230,19 @@
   2.214              enableFilterButton.image = UIImage(named: "unread-icon")
   2.215          }
   2.216      }
   2.217 -
   2.218 +    
   2.219      func updateFilterText() {
   2.220          if let vm = model, let txt = vm.activeFilter?.title {
   2.221              textFilterButton.title = "Filter by: " + txt
   2.222          }
   2.223      }
   2.224 -
   2.225 +    
   2.226      // MARK: - UITableViewDataSource
   2.227 -
   2.228 +    
   2.229      override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
   2.230          return model?.rowCount ?? 0
   2.231      }
   2.232 -
   2.233 +    
   2.234      override func tableView(_ tableView: UITableView,
   2.235                              cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   2.236          guard let cell = tableView.dequeueReusableCell(withIdentifier: EmailListViewCell.storyboardId,
   2.237 @@ -254,9 +254,9 @@
   2.238          configure(cell: cell, for: indexPath)
   2.239          return cell
   2.240      }
   2.241 -
   2.242 +    
   2.243      // MARK: - UITableViewDelegate
   2.244 -
   2.245 +    
   2.246      override func tableView(_ tableView: UITableView, editActionsForRowAt
   2.247          indexPath: IndexPath)-> [UITableViewRowAction]? {
   2.248          guard let flagAction = createFlagAction(forCellAt: indexPath),
   2.249 @@ -267,24 +267,24 @@
   2.250          }
   2.251          return [deleteAction, flagAction, moreAction]
   2.252      }
   2.253 -
   2.254 +    
   2.255      override func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
   2.256          cancelOperation(for: indexPath)
   2.257      }
   2.258 -
   2.259 +    
   2.260      override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
   2.261          lastSelectedIndexPath = indexPath
   2.262          tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
   2.263          performSegue(withIdentifier: SegueIdentifier.segueShowEmail, sender: self)
   2.264      }
   2.265 -
   2.266 +    
   2.267      // MARK: - Queue Handling
   2.268 -
   2.269 +    
   2.270      private func queue(operation op:Operation, for indexPath: IndexPath) {
   2.271          operations[indexPath] = op
   2.272          queue.addOperation(op)
   2.273      }
   2.274 -
   2.275 +    
   2.276      private func cancelOperation(for indexPath:IndexPath) {
   2.277          guard let op = operations.removeValue(forKey: indexPath) else {
   2.278              return
   2.279 @@ -293,7 +293,7 @@
   2.280              op.cancel()
   2.281          }
   2.282      }
   2.283 -
   2.284 +    
   2.285      override func didReceiveMemoryWarning() {
   2.286          model?.freeMemory()
   2.287      }
   2.288 @@ -308,7 +308,7 @@
   2.289          }
   2.290          vm.setSearchFilter(forSearchText: searchText)
   2.291      }
   2.292 -
   2.293 +    
   2.294      func didDismissSearchController(_ searchController: UISearchController) {
   2.295          guard let vm = model else {
   2.296              return
   2.297 @@ -325,19 +325,19 @@
   2.298          tableView.insertRows(at: [indexPath], with: .automatic)
   2.299          tableView.endUpdates()
   2.300      }
   2.301 -
   2.302 +    
   2.303      func emailListViewModel(viewModel: EmailListViewModel, didRemoveDataAt indexPath: IndexPath) {
   2.304          tableView.beginUpdates()
   2.305          tableView.deleteRows(at: [indexPath], with: .automatic)
   2.306          tableView.endUpdates()
   2.307      }
   2.308 -
   2.309 +    
   2.310      func emailListViewModel(viewModel: EmailListViewModel, didUpdateDataAt indexPath: IndexPath) {
   2.311          tableView.beginUpdates()
   2.312          tableView.reloadRows(at: [indexPath], with: .none)
   2.313          tableView.endUpdates()
   2.314      }
   2.315 -
   2.316 +    
   2.317      func updateView() {
   2.318          self.tableView.reloadData()
   2.319      }
   2.320 @@ -363,9 +363,9 @@
   2.321          }
   2.322          present(alertControler, animated: true, completion: nil)
   2.323      }
   2.324 -
   2.325 +    
   2.326      // MARK: Action Sheet Actions
   2.327 -
   2.328 +    
   2.329      func createCancelAction() -> UIAlertAction {
   2.330          return  UIAlertAction(title: "Cancel", style: .cancel) { (action) in
   2.331              self.tableView.beginUpdates()
   2.332 @@ -373,19 +373,19 @@
   2.333              self.tableView.endUpdates()
   2.334          }
   2.335      }
   2.336 -
   2.337 +    
   2.338      func createReplyAction() ->  UIAlertAction {
   2.339          return UIAlertAction(title: "Reply", style: .default) { (action) in
   2.340              self.performSegue(withIdentifier: .segueReply, sender: self)
   2.341          }
   2.342      }
   2.343 -
   2.344 +    
   2.345      func createReplyAllAction() ->  UIAlertAction {
   2.346          return UIAlertAction(title: "Reply All", style: .default) { (action) in
   2.347              self.performSegue(withIdentifier: .segueReplyAll, sender: self)
   2.348          }
   2.349      }
   2.350 -
   2.351 +    
   2.352      func createForwardAction() -> UIAlertAction {
   2.353          return UIAlertAction(title: "Forward", style: .default) { (action) in
   2.354              self.performSegue(withIdentifier: .segueForward, sender: self)
   2.355 @@ -406,7 +406,7 @@
   2.356          }
   2.357          return rowAction
   2.358      }
   2.359 -
   2.360 +    
   2.361      func createFlagAction(forCellAt indexPath: IndexPath) -> UITableViewRowAction? {
   2.362          guard let row = model?.row(for: indexPath) else {
   2.363              Log.shared.errorAndCrash(component: #function, errorString: "No data for indexPath!")
   2.364 @@ -433,7 +433,7 @@
   2.365          }
   2.366          return createRowAction(image: UIImage(named: "swipe-flag"), action: action, title: title)
   2.367      }
   2.368 -
   2.369 +    
   2.370      func createDeleteAction(forCellAt indexPath: IndexPath) -> UITableViewRowAction? {
   2.371          func action(action: UITableViewRowAction, indexPath: IndexPath) -> Void {
   2.372              tableView.beginUpdates()
   2.373 @@ -441,17 +441,17 @@
   2.374              tableView.deleteRows(at: [indexPath], with: .none)
   2.375              tableView.endUpdates()
   2.376          }
   2.377 -
   2.378 +        
   2.379          let title = NSLocalizedString("Delete", comment: "Message action (on swipe)")
   2.380          return createRowAction(image: UIImage(named: "swipe-trash"), action: action,
   2.381                                 title: "\n\n\(title)")
   2.382      }
   2.383 -
   2.384 +    
   2.385      func createMoreAction(forCellAt indexPath: IndexPath) -> UITableViewRowAction? {
   2.386          func action(action: UITableViewRowAction, indexPath: IndexPath) -> Void {
   2.387              self.showMoreActionSheet(forRowAt: indexPath)
   2.388          }
   2.389 -
   2.390 +        
   2.391          let title = NSLocalizedString("More", comment: "Message action (on swipe)")
   2.392          return createRowAction(image: UIImage(named: "swipe-more"),
   2.393                                 action: action,
   2.394 @@ -462,7 +462,7 @@
   2.395  // MARK: - SegueHandlerType
   2.396  
   2.397  extension EmailListViewController: SegueHandlerType {
   2.398 -
   2.399 +    
   2.400      enum SegueIdentifier: String {
   2.401          case segueAddNewAccount
   2.402          case segueShowEmail
   2.403 @@ -474,7 +474,7 @@
   2.404          case segueFolderViews
   2.405          case noSegue
   2.406      }
   2.407 -
   2.408 +    
   2.409      private func setup(composeViewController vc: ComposeTableViewController,
   2.410                         composeMode: ComposeTableViewController.ComposeMode = .normal,
   2.411                         originalMessage: Message? = nil) {
   2.412 @@ -483,7 +483,7 @@
   2.413          vc.originalMessage = originalMessage
   2.414          vc.origin = model?.folderToShow?.account.user
   2.415      }
   2.416 -
   2.417 +    
   2.418      override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
   2.419          switch segueIdentifier(for: segue) {
   2.420          case .segueReply:
   2.421 @@ -509,7 +509,7 @@
   2.422          case .segueShowEmail:
   2.423              guard let vc = segue.destination as? EmailViewController,
   2.424                  let indexPath = lastSelectedIndexPath,
   2.425 -                let message = model?.message(representedByRowAt: indexPath) else { //BUFF: maybe remove message(representedByRowAt: and handle in dvc.
   2.426 +                let message = model?.message(representedByRowAt: indexPath) else {
   2.427                      Log.shared.errorAndCrash(component: #function, errorString: "Segue issue")
   2.428                      return
   2.429              }
   2.430 @@ -565,7 +565,7 @@
   2.431              break
   2.432          }
   2.433      }
   2.434 -
   2.435 +    
   2.436      @IBAction func segueUnwindAccountAdded(segue: UIStoryboardSegue) {
   2.437          // nothing to do.
   2.438      }
     3.1 --- a/pEpForiOS/UI/EmailDisplay/EmailViewController.swift	Tue Oct 17 12:09:52 2017 +0200
     3.2 +++ b/pEpForiOS/UI/EmailDisplay/EmailViewController.swift	Tue Oct 17 12:26:27 2017 +0200
     3.3 @@ -45,6 +45,8 @@
     3.4  
     3.5          self.title = message.shortMessage//NSLocalizedString("Message", comment: "Message view title")
     3.6          saveTitleView()
     3.7 +
     3.8 +        setEmailDisplayDefaultNavigationBarStyle()
     3.9      }
    3.10  
    3.11      @IBAction func next(_ sender: Any) {
    3.12 @@ -74,20 +76,25 @@
    3.13  
    3.14      func configureView() {
    3.15          tableData?.filterRows(message: message)
    3.16 -        checkMessageReEvaluation()
    3.17 -        showPepRating()
    3.18 -        message.markAsSeen()
    3.19 +
    3.20          if messageId <= 0 {
    3.21              self.previousMessage.isEnabled = false
    3.22          } else {
    3.23              self.previousMessage.isEnabled = true
    3.24          }
    3.25 -        if let total = folderShow?.messageCount(), messageId >= total - 1 {
    3.26 -            self.nextMessage.isEnabled = false
    3.27 -        } else {
    3.28 -            self.nextMessage.isEnabled = true
    3.29 +
    3.30 +        DispatchQueue.main.async {
    3.31 +            self.checkMessageReEvaluation()
    3.32 +            self.showPepRating()
    3.33 +
    3.34 +            self.message.markAsSeen()
    3.35 +
    3.36 +            if let total = self.folderShow?.messageCount(), self.messageId >= total - 1 {
    3.37 +                self.nextMessage.isEnabled = false
    3.38 +            } else {
    3.39 +                self.nextMessage.isEnabled = true
    3.40 +            }
    3.41          }
    3.42 -
    3.43          updateFlaggedStatus()
    3.44      }
    3.45  
    3.46 @@ -349,6 +356,7 @@
    3.47  }
    3.48  
    3.49  // MARK: - Title View Extension
    3.50 +
    3.51  extension EmailViewController {
    3.52  
    3.53      func saveTitleView() {
     4.1 --- a/pEpForiOS/UI/Util/UIViewController+Extension.swift	Tue Oct 17 12:09:52 2017 +0200
     4.2 +++ b/pEpForiOS/UI/Util/UIViewController+Extension.swift	Tue Oct 17 12:26:27 2017 +0200
     4.3 @@ -12,10 +12,8 @@
     4.4  extension UIViewController {
     4.5  
     4.6      func showPepRating(pEpRating: PEP_rating?, pEpProtection: Bool = true) -> UIView? {
     4.7 -        setEmailDisplayColors()
     4.8 -        
     4.9 +        setEmailDisplayDefaultNavigationBarStyle()
    4.10          // icon
    4.11 -        navigationItem.title = nil
    4.12          if let img = pEpRating?.pepColor().statusIcon(enabled: pEpProtection) {
    4.13              let v = UIImageView(image: img)
    4.14              navigationItem.titleView = v
    4.15 @@ -34,7 +32,8 @@
    4.16          navigationController?.navigationBar.backgroundColor = nil
    4.17      }
    4.18  
    4.19 -    func setEmailDisplayColors() {
    4.20 +    func setEmailDisplayDefaultNavigationBarStyle() {
    4.21 +        navigationItem.title = nil
    4.22          setNoColor()
    4.23          navigationController?.navigationBar.titleTextAttributes =
    4.24              [NSAttributedStringKey.foregroundColor: UIColor.black]