pEpForiOS/UI/EmailDisplay/EmailListViewController.swift
author Dirk Zimmermann <dirk@pep-project.org>
Fri, 16 Sep 2016 18:52:51 +0200
changeset 723 adbc37ab3f03
parent 719 5dbce4ba5e53
child 744 de515991129e
permissions -rw-r--r--
IOS-104 flagging drafts as seen when reopening them
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@591
    13
class EmailListViewController: UITableViewController {
dirk@591
    14
    struct EmailListConfig {
dirk@591
    15
        let appConfig: AppConfig
dirk@583
    16
dirk@591
    17
        /** Set to whatever criteria you want to have mails displayed */
dirk@591
    18
        let predicate: NSPredicate?
dirk@583
    19
dirk@591
    20
        /** The sort descriptors to be used for displaying emails */
dirk@591
    21
        let sortDescriptors: [NSSortDescriptor]?
dirk@583
    22
dirk@606
    23
        /** If applicable, the account to refresh from */
dirk@591
    24
        let account: IAccount?
dirk@585
    25
dirk@591
    26
        /** If applicable, the folder name to sync */
dirk@591
    27
        let folderName: String?
dirk@593
    28
dirk@593
    29
        /** Should there be a sync directly when the view appears? */
dirk@593
    30
        let syncOnAppear: Bool
dirk@591
    31
    }
dirk@58
    32
dirk@583
    33
    struct UIState {
dirk@583
    34
        var isSynching: Bool = false
dirk@583
    35
    }
dirk@583
    36
    
dirk@273
    37
    let comp = "EmailListViewController"
dirk@361
    38
dirk@273
    39
    let segueShowEmail = "segueShowEmail"
dirk@397
    40
    let segueCompose = "segueCompose"
dirk@397
    41
    let segueUserSettings = "segueUserSettings"
dirk@30
    42
dirk@583
    43
    var config: EmailListConfig!
dirk@583
    44
dirk@212
    45
    var fetchController: NSFetchedResultsController?
dirk@275
    46
    var state = UIState()
dirk@342
    47
    let dateFormatter = UIHelper.dateFormatterEmailList()
dirk@275
    48
dirk@502
    49
    /**
dirk@502
    50
     The default background color for an email cell, as determined the first time a cell is
dirk@502
    51
     created.
dirk@502
    52
     */
dirk@502
    53
    var defaultCellBackgroundColor: UIColor?
dirk@502
    54
dirk@502
    55
    /**
dirk@502
    56
     Indicates whether `defaultCellBackgroundColor` has been determined or not.
dirk@502
    57
     */
dirk@502
    58
    var determinedCellBackgroundColor: Bool = false
dirk@502
    59
dirk@594
    60
    var refreshController: UIRefreshControl!
dirk@594
    61
dirk@705
    62
    /**
dirk@705
    63
     The message that should be saved as a draft when compose gets aborted.
dirk@705
    64
     */
dirk@705
    65
    var draftMessageToStore: IMessage?
dirk@705
    66
dirk@719
    67
    /**
dirk@719
    68
     When the user taps on a draft email, this is the message that was selected
dirk@719
    69
     and should be given to the compose view.
dirk@719
    70
     */
dirk@719
    71
    var draftMessageToCompose: IMessage?
dirk@719
    72
ana@620
    73
    func isReadedMessage(message: IMessage)-> Bool {
dirk@637
    74
        return message.flagSeen.boolValue
ana@614
    75
    }
ana@614
    76
ana@620
    77
    func isImportantMessage(message: IMessage)-> Bool {
ana@621
    78
        return message.flagFlagged.boolValue
ana@614
    79
    }
ana@614
    80
dirk@275
    81
    override func viewDidLoad() {
dirk@594
    82
        refreshController = UIRefreshControl.init()
dirk@593
    83
        refreshController.addTarget(self, action: #selector(self.fetchMailsRefreshControl(_:)),
dirk@275
    84
                                    forControlEvents: UIControlEvents.ValueChanged)
dirk@356
    85
        UIHelper.variableCellHeightsTableView(self.tableView)
dirk@275
    86
    }
dirk@31
    87
dirk@31
    88
    override func viewWillAppear(animated: Bool) {
dirk@594
    89
        // Disable fetching if there is no account
dirk@594
    90
        if config.account != nil {
dirk@594
    91
            self.refreshControl = refreshController
dirk@594
    92
        } else {
dirk@594
    93
            self.refreshControl = nil
dirk@594
    94
        }
dirk@594
    95
dirk@209
    96
        prepareFetchRequest()
dirk@593
    97
        if config.syncOnAppear {
dirk@593
    98
            fetchMailsRefreshControl()
dirk@593
    99
        }
ana@207
   100
        super.viewWillAppear(animated)
ana@207
   101
    }
ana@152
   102
dirk@275
   103
    func fetchMailsRefreshControl(refreshControl: UIRefreshControl? = nil) {
dirk@583
   104
        if let account = config.account {
dirk@55
   105
            let connectInfo = account.connectInfo
dirk@55
   106
dirk@275
   107
            state.isSynching = true
dirk@588
   108
            updateUI()
dirk@368
   109
dirk@588
   110
            config.appConfig.grandOperator.fetchEmailsAndDecryptConnectInfos(
dirk@590
   111
                [connectInfo], folderName: config.folderName,
dirk@466
   112
                completionBlock: { error in
dirk@466
   113
                    Log.infoComponent(self.comp, "Sync completed, error: \(error)")
dirk@707
   114
                    UIHelper.displayError(error, controller: self)
dirk@583
   115
                    self.config.appConfig.model.save()
dirk@466
   116
                    self.state.isSynching = false
dirk@466
   117
                    refreshControl?.endRefreshing()
dirk@466
   118
                    self.updateUI()
dirk@466
   119
            })
dirk@594
   120
        } else {
dirk@594
   121
            state.isSynching = false
dirk@594
   122
            updateUI()
dirk@55
   123
        }
dirk@31
   124
    }
dirk@31
   125
dirk@452
   126
    @IBAction func mailSentSegue(segue: UIStoryboardSegue) {
dirk@452
   127
    }
dirk@452
   128
dirk@705
   129
    @IBAction func backFromComposeWithoutSavingDraftSegue(segue: UIStoryboardSegue) {
dirk@705
   130
    }
dirk@705
   131
dirk@705
   132
    @IBAction func backFromComposeSaveDraftSegue(segue: UIStoryboardSegue) {
dirk@705
   133
        guard let msg = draftMessageToStore else {
dirk@705
   134
            return
dirk@705
   135
        }
dirk@707
   136
dirk@707
   137
        state.isSynching = true
dirk@707
   138
        updateUI()
dirk@707
   139
dirk@706
   140
        config.appConfig.grandOperator.saveDraftMail(
dirk@706
   141
            msg, account: msg.folder.account, completionBlock: { error in
dirk@707
   142
                GCD.onMain() {
dirk@709
   143
                    UIHelper.displayError(error, controller: self)
dirk@707
   144
                    self.state.isSynching = false
dirk@707
   145
                    self.updateUI()
dirk@707
   146
                }
dirk@706
   147
        })
dirk@705
   148
    }
dirk@705
   149
ana@143
   150
    func prepareFetchRequest() {
dirk@31
   151
        let fetchRequest = NSFetchRequest.init(entityName: Message.entityName())
dirk@583
   152
        fetchRequest.predicate = config.predicate
dirk@583
   153
        fetchRequest.sortDescriptors = config.sortDescriptors
dirk@31
   154
        fetchController = NSFetchedResultsController.init(
dirk@31
   155
            fetchRequest: fetchRequest,
dirk@583
   156
            managedObjectContext: config.appConfig.coreDataUtil.managedObjectContext,
dirk@31
   157
            sectionNameKeyPath: nil, cacheName: nil)
dirk@31
   158
        fetchController?.delegate = self
dirk@31
   159
        do {
dirk@31
   160
            try fetchController?.performFetch()
dirk@31
   161
        } catch let err as NSError {
dirk@414
   162
            Log.errorComponent(comp, error: err)
dirk@31
   163
        }
dirk@31
   164
    }
dirk@31
   165
dirk@58
   166
    // MARK: - UI State
dirk@58
   167
dirk@58
   168
    func updateUI() {
dirk@275
   169
        if state.isSynching {
dirk@58
   170
            UIApplication.sharedApplication().networkActivityIndicatorVisible = true
dirk@58
   171
        } else {
dirk@58
   172
            UIApplication.sharedApplication().networkActivityIndicatorVisible = false
dirk@594
   173
            self.refreshControl?.endRefreshing()
dirk@58
   174
        }
dirk@58
   175
    }
dirk@58
   176
dirk@31
   177
    // MARK: - UITableViewDataSource
dirk@31
   178
dirk@31
   179
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
dirk@209
   180
        if let count = fetchController?.sections?.count {
dirk@209
   181
            return count
dirk@209
   182
        } else {
dirk@209
   183
            return 0
dirk@209
   184
        }
dirk@31
   185
    }
dirk@31
   186
dirk@31
   187
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
dirk@31
   188
        if fetchController?.sections?.count > 0 {
dirk@31
   189
            if let sections = fetchController?.sections {
dirk@31
   190
                let sectionInfo = sections[section]
dirk@31
   191
                return sectionInfo.numberOfObjects
dirk@31
   192
            }
dirk@31
   193
        }
dirk@31
   194
        return 0
dirk@31
   195
    }
dirk@31
   196
dirk@31
   197
    override func tableView(tableView: UITableView,
dirk@31
   198
                            cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
dirk@209
   199
        let cell = tableView.dequeueReusableCellWithIdentifier(
dirk@209
   200
            "EmailListViewCell", forIndexPath: indexPath) as! EmailListViewCell
dirk@502
   201
        if !determinedCellBackgroundColor {
dirk@502
   202
            defaultCellBackgroundColor = cell.backgroundColor
dirk@502
   203
            determinedCellBackgroundColor = true
dirk@502
   204
        }
dirk@31
   205
        configureCell(cell, indexPath: indexPath)
dirk@31
   206
        return cell
dirk@31
   207
    }
dirk@31
   208
dirk@719
   209
    // MARK: - UITableViewDelegate
dirk@719
   210
dirk@719
   211
    override func tableView(tableView: UITableView,
dirk@719
   212
                            didSelectRowAtIndexPath indexPath: NSIndexPath) {
dirk@719
   213
        draftMessageToCompose = nil
dirk@719
   214
dirk@719
   215
        let cell = tableView.cellForRowAtIndexPath(indexPath)
dirk@719
   216
dirk@719
   217
        if let fn = config.folderName, let ac = config.account,
dirk@719
   218
            let folder = config.appConfig.model.folderByName(fn, email: ac.email) {
dirk@719
   219
            if folder.folderType.integerValue == FolderType.Drafts.rawValue {
dirk@719
   220
                draftMessageToCompose = fetchController?.objectAtIndexPath(indexPath)
dirk@719
   221
                    as? IMessage
dirk@719
   222
                performSegueWithIdentifier(segueCompose, sender: cell)
dirk@719
   223
                return
dirk@719
   224
            }
dirk@719
   225
        }
dirk@719
   226
dirk@719
   227
        performSegueWithIdentifier(segueShowEmail, sender: cell)
dirk@719
   228
    }
dirk@719
   229
dirk@719
   230
    // MARK: - Misc
dirk@719
   231
dirk@31
   232
    func configureCell(cell: EmailListViewCell, indexPath: NSIndexPath) {
dirk@31
   233
        if let email = fetchController?.objectAtIndexPath(indexPath) as? Message {
dirk@502
   234
            if let colorRating = PEPUtil.colorRatingFromInt(email.pepColorRating?.integerValue) {
dirk@574
   235
                let privacyColor = PEPUtil.colorFromPepRating(colorRating)
dirk@502
   236
                if let uiColor = UIHelper.textBackgroundUIColorFromPrivacyColor(privacyColor) {
dirk@502
   237
                    cell.backgroundColor = uiColor
dirk@502
   238
                } else {
dirk@502
   239
                    if determinedCellBackgroundColor {
dirk@502
   240
                        cell.backgroundColor = defaultCellBackgroundColor
dirk@502
   241
                    }
dirk@502
   242
                }
dirk@502
   243
            }
dirk@342
   244
            UIHelper.putString(email.from?.displayString(), toLabel: cell.senderLabel)
dirk@342
   245
            UIHelper.putString(email.subject, toLabel: cell.subjectLabel)
dirk@572
   246
dirk@572
   247
            // Snippet
dirk@565
   248
            if let text = email.longMessage {
dirk@572
   249
                let theText = text.replaceNewLinesWith(" ").trimmedWhiteSpace()
dirk@565
   250
                UIHelper.putString(theText, toLabel: cell.summaryLabel)
dirk@572
   251
            } else if let html = email.longMessageFormatted {
dirk@568
   252
                var text = html.extractTextFromHTML()
dirk@572
   253
                text = text.replaceNewLinesWith(" ").trimmedWhiteSpace()
dirk@568
   254
                UIHelper.putString(text, toLabel: cell.summaryLabel)
dirk@568
   255
            } else {
dirk@568
   256
                UIHelper.putString(nil, toLabel: cell.summaryLabel)
dirk@565
   257
            }
dirk@32
   258
dirk@480
   259
            if let receivedDate = email.receivedDate {
dirk@480
   260
                UIHelper.putString(dateFormatter.stringFromDate(receivedDate),
dirk@342
   261
                                   toLabel: cell.dateLabel)
dirk@32
   262
            } else {
dirk@342
   263
                UIHelper.putString(nil, toLabel: cell.dateLabel)
dirk@32
   264
            }
ana@620
   265
ana@656
   266
            if (isImportantMessage(email) && isReadedMessage(email)) {
ana@666
   267
                cell.isImportantImage.hidden = false
ana@666
   268
                cell.isImportantImage.backgroundColor = UIColor.orangeColor()
ana@666
   269
            }
ana@666
   270
            else if (isImportantMessage(email) && !isReadedMessage(email)) {
ana@666
   271
                cell.isImportantImage.hidden = false
ana@656
   272
                cell.isImportantImage.backgroundColor = UIColor.blueColor()
ana@656
   273
                cell.isImportantImage.layer.borderWidth = 2
ana@656
   274
                cell.isImportantImage.layer.borderColor = UIColor.orangeColor().CGColor
ana@666
   275
            } else if (!isImportantMessage(email) && isReadedMessage(email)) {
ana@666
   276
                    cell.isImportantImage.hidden = true
ana@666
   277
            } else if (!isImportantMessage(email) && !isReadedMessage(email)) {
ana@620
   278
                cell.isImportantImage.hidden = false
ana@666
   279
                cell.isImportantImage.backgroundColor = UIColor.blueColor()
ana@620
   280
            }
dirk@31
   281
        }
dirk@30
   282
    }
dirk@30
   283
ana@246
   284
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
dirk@606
   285
        // Make sure the current account is set, if defined
dirk@606
   286
        config.appConfig.currentAccount = config.account
dirk@606
   287
dirk@361
   288
        if segue.identifier == segueCompose {
dirk@397
   289
            let destination = segue.destinationViewController
dirk@434
   290
                as! ComposeViewController
dirk@583
   291
            destination.appConfig = config.appConfig
dirk@719
   292
            if let draft = draftMessageToCompose {
dirk@723
   293
                draft.flagSeen = true
dirk@723
   294
                draft.updateFlags()
dirk@723
   295
                config.appConfig.model.save()
dirk@723
   296
dirk@719
   297
                destination.originalMessage = draft
dirk@719
   298
                destination.composeMode = .ComposeDraft
dirk@719
   299
            }
dirk@273
   300
        } else if segue.identifier == segueShowEmail {
dirk@273
   301
            guard
dirk@273
   302
                let vc = segue.destinationViewController as? EmailViewController,
dirk@273
   303
                let cell = sender as? UITableViewCell,
dirk@273
   304
                let indexPath = self.tableView.indexPathForCell(cell),
dirk@273
   305
                let email = fetchController?.objectAtIndexPath(indexPath) as? Message else {
dirk@273
   306
                    return
dirk@273
   307
            }
dirk@583
   308
            vc.appConfig = config.appConfig
dirk@273
   309
            vc.message = email
ana@246
   310
        }
ana@246
   311
    }
dirk@30
   312
}
dirk@30
   313
dirk@31
   314
extension EmailListViewController: NSFetchedResultsControllerDelegate {
dirk@31
   315
    func controllerWillChangeContent(controller: NSFetchedResultsController) {
dirk@31
   316
        tableView.beginUpdates()
dirk@30
   317
    }
dirk@30
   318
dirk@31
   319
    func controller(controller: NSFetchedResultsController,
dirk@31
   320
                    didChangeSection sectionInfo: NSFetchedResultsSectionInfo,
dirk@31
   321
                                     atIndex sectionIndex: Int,
dirk@31
   322
                                             forChangeType type: NSFetchedResultsChangeType) {
dirk@31
   323
        switch (type) {
dirk@31
   324
        case .Insert:
dirk@31
   325
            tableView.insertSections(NSIndexSet.init(index: sectionIndex),
dirk@31
   326
                                     withRowAnimation: .Fade)
dirk@31
   327
        case .Delete:
dirk@31
   328
            tableView.deleteSections(NSIndexSet.init(index: sectionIndex),
dirk@31
   329
                                     withRowAnimation: .Fade)
dirk@31
   330
        default:
dirk@414
   331
            Log.infoComponent(comp, "unhandled changeSectionType: \(type)")
dirk@31
   332
        }
dirk@30
   333
    }
dirk@30
   334
dirk@31
   335
    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject,
dirk@31
   336
                    atIndexPath indexPath: NSIndexPath?,
dirk@31
   337
                                forChangeType type: NSFetchedResultsChangeType,
dirk@31
   338
                                              newIndexPath: NSIndexPath?) {
dirk@40
   339
        switch type {
dirk@40
   340
        case .Insert:
dirk@40
   341
            tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
dirk@40
   342
        case .Delete:
dirk@40
   343
            tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
dirk@40
   344
        case .Update:
dirk@40
   345
            if let cell = tableView.cellForRowAtIndexPath(indexPath!) {
dirk@40
   346
                self.configureCell(cell as! EmailListViewCell, indexPath: indexPath!)
dirk@40
   347
            } else {
dirk@414
   348
                Log.warnComponent(comp, "Could not find cell for changed indexPath: \(indexPath!)")
dirk@31
   349
            }
dirk@40
   350
        case .Move:
dirk@40
   351
            if newIndexPath != indexPath {
dirk@40
   352
                tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
dirk@40
   353
                tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
dirk@40
   354
            }
dirk@31
   355
        }
dirk@31
   356
    }
dirk@31
   357
dirk@31
   358
    func controllerDidChangeContent(controller: NSFetchedResultsController) {
dirk@31
   359
        tableView.endUpdates()
dirk@31
   360
    }
ana@562
   361
ana@653
   362
    func syncFlagsToServer(message: IMessage) {
dirk@678
   363
        self.config.appConfig.grandOperator.syncFlagsToServerForFolder(
dirk@678
   364
            message.folder,
dirk@678
   365
            completionBlock: { error in
dirk@707
   366
                UIHelper.displayError(error, controller: self)
dirk@678
   367
        })
ana@653
   368
    }
ana@653
   369
ana@621
   370
    func createIsFlagAction(message: Message, cell: EmailListViewCell) -> UITableViewRowAction {
ana@599
   371
ana@620
   372
        // preparing the title action to show when user swipe
ana@620
   373
        var localizedIsFlagTitle = " "
ana@621
   374
        if (isImportantMessage(message)) {
ana@651
   375
            localizedIsFlagTitle = NSLocalizedString("Unflag",
ana@651
   376
            comment: "Unflag button title in swipe action on EmailListViewController")
ana@651
   377
        } else {
ana@620
   378
            localizedIsFlagTitle = NSLocalizedString("Flag",
ana@620
   379
            comment: "Flag button title in swipe action on EmailListViewController")
ana@620
   380
        }
ana@620
   381
ana@620
   382
        // preparing action to trigger when user swipe
ana@614
   383
        let isFlagCompletionHandler: (UITableViewRowAction, NSIndexPath) -> Void =
ana@601
   384
            { (action, indexPath) in
ana@651
   385
                if (self.isImportantMessage(message)) {
ana@651
   386
                    message.flagFlagged = false
ana@666
   387
ana@651
   388
                } else {
ana@651
   389
                    message.flagFlagged = true
ana@651
   390
                }
ana@666
   391
                message.updateFlags()
ana@653
   392
                self.syncFlagsToServer(message)
ana@614
   393
                self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
ana@601
   394
            }
ana@620
   395
        // creating the action
ana@620
   396
        let isFlagAction = UITableViewRowAction(style: .Default, title: localizedIsFlagTitle,
ana@620
   397
                                                handler: isFlagCompletionHandler)
ana@620
   398
        // changing default action color
ana@620
   399
        isFlagAction.backgroundColor = UIColor.orangeColor()
ana@602
   400
ana@620
   401
        return isFlagAction
ana@620
   402
    }
ana@620
   403
ana@620
   404
    func createDeleteAction (cell: EmailListViewCell) -> UITableViewRowAction {
ana@620
   405
ana@620
   406
        // preparing the title action to show when user swipe
ana@620
   407
        let localizedDeleteTitle = NSLocalizedString("Erase",
ana@620
   408
        comment: "Erase button title in swipe action on EmailListViewController")
ana@599
   409
ana@601
   410
        let deleteCompletionHandler: (UITableViewRowAction, NSIndexPath) -> Void =
ana@601
   411
            { (action, indexPath) in
ana@650
   412
                let managedObject = self.fetchController?.objectAtIndexPath(indexPath) as? IMessage
ana@650
   413
                managedObject?.flagDeleted = true
ana@651
   414
                managedObject?.updateFlags()
ana@653
   415
                self.syncFlagsToServer(managedObject!)
ana@601
   416
            }
ana@620
   417
ana@620
   418
        // creating the action
ana@601
   419
        let deleteAction = UITableViewRowAction(style: .Default, title: localizedDeleteTitle,
ana@601
   420
                                                handler: deleteCompletionHandler)
ana@620
   421
        return deleteAction
ana@620
   422
    }
ana@620
   423
ana@621
   424
    func createIsReadAction (message: Message, cell: EmailListViewCell) -> UITableViewRowAction {
ana@620
   425
ana@620
   426
        // preparing the title action to show when user swipe
ana@620
   427
        var localizedisReadTitle = " "
ana@621
   428
        if (isReadedMessage(message)) {
ana@651
   429
            localizedisReadTitle = NSLocalizedString("Unread",
ana@651
   430
            comment: "Unread button title in swipe action on EmailListViewController")
ana@651
   431
        } else {
ana@620
   432
            localizedisReadTitle = NSLocalizedString("Read",
ana@620
   433
            comment: "Read button title in swipe action on EmailListViewController")
ana@620
   434
        }
ana@620
   435
ana@620
   436
        // creating the action
ana@614
   437
        let isReadCompletionHandler: (UITableViewRowAction, NSIndexPath) -> Void =
ana@614
   438
            { (action, indexPath) in
ana@651
   439
                if (self.isReadedMessage(message)) {
ana@651
   440
                    message.flagSeen = false
ana@651
   441
                    message.updateFlags()
ana@651
   442
                } else {
ana@651
   443
                    message.flagSeen = true
ana@651
   444
                    message.updateFlags()
ana@651
   445
                }
ana@653
   446
                self.syncFlagsToServer(message)
ana@614
   447
                self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
ana@614
   448
            }
ana@614
   449
        let isReadAction = UITableViewRowAction(style: .Default, title: localizedisReadTitle,
ana@614
   450
                                                handler: isReadCompletionHandler)
ana@614
   451
        isReadAction.backgroundColor = UIColor.blueColor()
ana@620
   452
ana@620
   453
        return isReadAction
ana@620
   454
    }
ana@620
   455
ana@620
   456
    override func tableView(tableView: UITableView, editActionsForRowAtIndexPath
ana@620
   457
                  indexPath: NSIndexPath)-> [UITableViewRowAction]? {
ana@620
   458
ana@620
   459
        let cell = tableView.cellForRowAtIndexPath(indexPath) as! EmailListViewCell
ana@620
   460
        let email = fetchController?.objectAtIndexPath(indexPath) as! Message
ana@621
   461
ana@621
   462
        let isFlagAction = createIsFlagAction(email, cell: cell)
ana@620
   463
        let deleteAction = createDeleteAction(cell)
ana@621
   464
        let isReadAction = createIsReadAction(email, cell: cell)
ana@614
   465
        return [deleteAction,isFlagAction,isReadAction]
ana@599
   466
    }
dirk@30
   467
}