pEpForiOS/UI/EmailDisplay/EmailListViewController.swift
author Dirk Zimmermann <dirk@pep-project.org>
Fri, 17 Jun 2016 18:03:31 +0200
changeset 356 e8d2f5b226ce
parent 342 d3c468468cfa
child 361 fff53ba1bbbb
permissions -rw-r--r--
Attempt: RecipientView for displaying recipients of an email
dirk@30
     1
//
dirk@30
     2
//  EmailListViewController.swift
dirk@30
     3
//  pEpForiOS
dirk@30
     4
//
dirk@30
     5
//  Created by Dirk Zimmermann on 16/04/16.
dirk@30
     6
//  Copyright © 2016 p≡p Security S.A. All rights reserved.
dirk@30
     7
//
dirk@30
     8
dirk@30
     9
import Foundation
dirk@30
    10
import UIKit
dirk@31
    11
import CoreData
dirk@30
    12
dirk@58
    13
struct UIState {
dirk@275
    14
    var isSynching: Bool = false
dirk@58
    15
}
dirk@58
    16
dirk@31
    17
class EmailListViewController: UITableViewController {
dirk@273
    18
    let comp = "EmailListViewController"
dirk@273
    19
    let segueShowEmail = "segueShowEmail"
dirk@30
    20
dirk@31
    21
    var appConfig: AppConfig?
dirk@212
    22
    var fetchController: NSFetchedResultsController?
dirk@275
    23
    var state = UIState()
dirk@342
    24
    let dateFormatter = UIHelper.dateFormatterEmailList()
dirk@275
    25
dirk@275
    26
    override func viewDidLoad() {
dirk@275
    27
        let refreshController = UIRefreshControl.init()
dirk@275
    28
        refreshController.addTarget(self, action: #selector(self.refresh(_:)),
dirk@275
    29
                                    forControlEvents: UIControlEvents.ValueChanged)
dirk@275
    30
        self.refreshControl = refreshController
dirk@356
    31
        UIHelper.variableCellHeightsTableView(self.tableView)
dirk@275
    32
    }
dirk@31
    33
dirk@31
    34
    override func viewWillAppear(animated: Bool) {
dirk@31
    35
        if appConfig == nil {
dirk@31
    36
            if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
dirk@31
    37
                appConfig = appDelegate.appConfig
dirk@31
    38
            }
dirk@273
    39
        }
dirk@209
    40
        prepareFetchRequest()
dirk@209
    41
ana@152
    42
        let account:IAccount? = appConfig!.model.fetchLastAccount()
ana@152
    43
        if (account == nil)  {
ana@152
    44
            self.performSegueWithIdentifier("userSettings", sender: self)
ana@207
    45
        } else {
dirk@275
    46
            fetchMailsRefreshControl()
ana@152
    47
        }
ana@207
    48
        super.viewWillAppear(animated)
ana@207
    49
    }
ana@152
    50
dirk@275
    51
    func refresh(refreshControl: UIRefreshControl) {
dirk@275
    52
        fetchMailsRefreshControl(refreshControl)
dirk@275
    53
    }
dirk@275
    54
dirk@275
    55
    func fetchMailsRefreshControl(refreshControl: UIRefreshControl? = nil) {
dirk@115
    56
        if let account = appConfig?.model.fetchLastAccount() {
dirk@55
    57
            let connectInfo = account.connectInfo
dirk@55
    58
dirk@275
    59
            state.isSynching = true
dirk@67
    60
            appConfig!.grandOperator.prefetchEmails(
dirk@55
    61
                connectInfo, folder: ImapSync.defaultImapInboxName, completionBlock: {
dirk@67
    62
                    [unowned self] error in
dirk@58
    63
                    GCD.onMain({
dirk@67
    64
                        Log.info(self.comp, "Sync completed, error: \(error)")
dirk@325
    65
                        self.appConfig?.model.save()
dirk@275
    66
                        self.state.isSynching = false
dirk@275
    67
                        refreshControl?.endRefreshing()
dirk@149
    68
                        self.updateUI()
dirk@58
    69
                    })
ana@207
    70
                })
dirk@149
    71
            updateUI()
dirk@55
    72
        }
dirk@31
    73
    }
dirk@31
    74
dirk@196
    75
    @IBAction func newAccountCreatedSegue(segue: UIStoryboardSegue) {
dirk@275
    76
        fetchMailsRefreshControl()
dirk@196
    77
    }
dirk@196
    78
ana@143
    79
    func prepareFetchRequest() {
dirk@324
    80
        let predicates: [NSPredicate] = [NSPredicate.init(format: "bodyFetched = true")]
dirk@31
    81
        let fetchRequest = NSFetchRequest.init(entityName: Message.entityName())
dirk@31
    82
        fetchRequest.predicate = NSCompoundPredicate.init(
dirk@31
    83
            andPredicateWithSubpredicates: predicates)
dirk@324
    84
        fetchRequest.sortDescriptors = [NSSortDescriptor.init(key: "originationDate",
dirk@324
    85
            ascending: false)]
dirk@31
    86
        fetchController = NSFetchedResultsController.init(
dirk@31
    87
            fetchRequest: fetchRequest,
dirk@31
    88
            managedObjectContext: appConfig!.coreDataUtil.managedObjectContext,
dirk@31
    89
            sectionNameKeyPath: nil, cacheName: nil)
dirk@31
    90
        fetchController?.delegate = self
dirk@31
    91
        do {
dirk@31
    92
            try fetchController?.performFetch()
dirk@31
    93
        } catch let err as NSError {
dirk@31
    94
            Log.error(comp, error: err)
dirk@31
    95
        }
dirk@31
    96
    }
dirk@31
    97
dirk@58
    98
    // MARK: - UI State
dirk@58
    99
dirk@58
   100
    func updateUI() {
dirk@275
   101
        if state.isSynching {
dirk@58
   102
            UIApplication.sharedApplication().networkActivityIndicatorVisible = true
dirk@58
   103
        } else {
dirk@58
   104
            UIApplication.sharedApplication().networkActivityIndicatorVisible = false
dirk@58
   105
        }
dirk@58
   106
    }
dirk@58
   107
dirk@31
   108
    // MARK: - UITableViewDataSource
dirk@31
   109
dirk@31
   110
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
dirk@209
   111
        if let count = fetchController?.sections?.count {
dirk@209
   112
            return count
dirk@209
   113
        } else {
dirk@209
   114
            return 0
dirk@209
   115
        }
dirk@31
   116
    }
dirk@31
   117
dirk@31
   118
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
dirk@31
   119
        if fetchController?.sections?.count > 0 {
dirk@31
   120
            if let sections = fetchController?.sections {
dirk@31
   121
                let sectionInfo = sections[section]
dirk@31
   122
                return sectionInfo.numberOfObjects
dirk@31
   123
            }
dirk@31
   124
        }
dirk@31
   125
        return 0
dirk@31
   126
    }
dirk@31
   127
dirk@31
   128
    override func tableView(tableView: UITableView,
dirk@31
   129
                            cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
dirk@209
   130
        let cell = tableView.dequeueReusableCellWithIdentifier(
dirk@209
   131
            "EmailListViewCell", forIndexPath: indexPath) as! EmailListViewCell
dirk@31
   132
        configureCell(cell, indexPath: indexPath)
dirk@31
   133
        return cell
dirk@31
   134
    }
dirk@31
   135
dirk@31
   136
    func configureCell(cell: EmailListViewCell, indexPath: NSIndexPath) {
dirk@31
   137
        if let email = fetchController?.objectAtIndexPath(indexPath) as? Message {
dirk@342
   138
            UIHelper.putString(email.from?.displayString(), toLabel: cell.senderLabel)
dirk@342
   139
            UIHelper.putString(email.subject, toLabel: cell.subjectLabel)
dirk@342
   140
            UIHelper.putString(nil, toLabel: cell.summaryLabel)
dirk@32
   141
dirk@119
   142
            if let originationDate = email.originationDate {
dirk@342
   143
                UIHelper.putString(dateFormatter.stringFromDate(originationDate),
dirk@342
   144
                                   toLabel: cell.dateLabel)
dirk@32
   145
            } else {
dirk@342
   146
                UIHelper.putString(nil, toLabel: cell.dateLabel)
dirk@32
   147
            }
dirk@31
   148
        }
dirk@30
   149
    }
dirk@30
   150
ana@246
   151
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
ana@246
   152
        if segue.identifier == "composeSegue" {
ana@334
   153
            let destination = segue.destinationViewController as! ComposeWithAutocompleteViewController
ana@246
   154
            destination.appConfig = appConfig
dirk@273
   155
        } else if segue.identifier == segueShowEmail {
dirk@273
   156
            guard
dirk@273
   157
                let vc = segue.destinationViewController as? EmailViewController,
dirk@273
   158
                let cell = sender as? UITableViewCell,
dirk@273
   159
                let indexPath = self.tableView.indexPathForCell(cell),
dirk@273
   160
                let email = fetchController?.objectAtIndexPath(indexPath) as? Message else {
dirk@273
   161
                    return
dirk@273
   162
            }
dirk@273
   163
            vc.appConfig = appConfig
dirk@273
   164
            vc.message = email
ana@246
   165
        }
ana@246
   166
    }
ana@246
   167
dirk@30
   168
}
dirk@30
   169
dirk@31
   170
extension EmailListViewController: NSFetchedResultsControllerDelegate {
dirk@31
   171
    func controllerWillChangeContent(controller: NSFetchedResultsController) {
dirk@31
   172
        tableView.beginUpdates()
dirk@30
   173
    }
dirk@30
   174
dirk@31
   175
    func controller(controller: NSFetchedResultsController,
dirk@31
   176
                    didChangeSection sectionInfo: NSFetchedResultsSectionInfo,
dirk@31
   177
                                     atIndex sectionIndex: Int,
dirk@31
   178
                                             forChangeType type: NSFetchedResultsChangeType) {
dirk@31
   179
        switch (type) {
dirk@31
   180
        case .Insert:
dirk@31
   181
            tableView.insertSections(NSIndexSet.init(index: sectionIndex),
dirk@31
   182
                                     withRowAnimation: .Fade)
dirk@31
   183
        case .Delete:
dirk@31
   184
            tableView.deleteSections(NSIndexSet.init(index: sectionIndex),
dirk@31
   185
                                     withRowAnimation: .Fade)
dirk@31
   186
        default:
dirk@31
   187
            Log.info(comp, "unhandled changeSectionType: \(type)")
dirk@31
   188
        }
dirk@30
   189
    }
dirk@30
   190
dirk@31
   191
    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject,
dirk@31
   192
                    atIndexPath indexPath: NSIndexPath?,
dirk@31
   193
                                forChangeType type: NSFetchedResultsChangeType,
dirk@31
   194
                                              newIndexPath: NSIndexPath?) {
dirk@40
   195
        switch type {
dirk@40
   196
        case .Insert:
dirk@40
   197
            tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
dirk@40
   198
        case .Delete:
dirk@40
   199
            tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
dirk@40
   200
        case .Update:
dirk@40
   201
            if let cell = tableView.cellForRowAtIndexPath(indexPath!) {
dirk@40
   202
                self.configureCell(cell as! EmailListViewCell, indexPath: indexPath!)
dirk@40
   203
            } else {
dirk@40
   204
                Log.warn(comp, "Could not find cell for changed indexPath: \(indexPath!)")
dirk@31
   205
            }
dirk@40
   206
        case .Move:
dirk@40
   207
            if newIndexPath != indexPath {
dirk@40
   208
                tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
dirk@40
   209
                tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
dirk@40
   210
            }
dirk@31
   211
        }
dirk@31
   212
    }
dirk@31
   213
dirk@31
   214
    func controllerDidChangeContent(controller: NSFetchedResultsController) {
dirk@31
   215
        tableView.endUpdates()
dirk@31
   216
    }
dirk@30
   217
}