pEpForiOS/UI/EmailDisplay/EmailListViewController.swift
author igor <igor@pep-project.org>
Wed, 11 Jan 2017 13:55:34 +0100
changeset 1395 8e66dc53be32
parent 1350 7a6d0a04448a
child 1408 d4f3ec47c2c7
permissions -rw-r--r--
IOS-370 Fixed
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@810
    12
import MessageModel
dirk@810
    13
igor@1260
    14
struct EmailListConfig {
igor@1338
    15
    var appConfig: AppConfig?
dirk@1333
    16
igor@1260
    17
    /** The folder to display, if it exists */
igor@1260
    18
    var folder: Folder?
igor@1260
    19
}
dirk@30
    20
dirk@854
    21
class EmailListViewController: UITableViewController {
igor@1260
    22
    
dirk@583
    23
    struct UIState {
dirk@583
    24
        var isSynching: Bool = false
dirk@583
    25
    }
dirk@30
    26
dirk@1344
    27
    var config: EmailListConfig?
dirk@275
    28
    var state = UIState()
igor@1301
    29
    let searchController = UISearchController(searchResultsController: nil)
dirk@719
    30
dirk@275
    31
    override func viewDidLoad() {
ylandert@935
    32
        super.viewDidLoad()
igor@1301
    33
        
igor@1284
    34
        UIHelper.emailListTableHeight(self.tableView)
igor@1301
    35
        addSearchBar()
dirk@275
    36
    }
dirk@31
    37
dirk@784
    38
    override func viewWillAppear(_ animated: Bool) {
igor@1301
    39
        super.viewWillAppear(animated)
igor@1301
    40
        
dirk@1344
    41
        if MiscUtil.isUnitTest() {
dirk@1344
    42
            return
dirk@1344
    43
        }
dirk@1344
    44
dirk@1344
    45
        initialConfig()
dirk@854
    46
        updateModel()
dirk@1348
    47
dirk@1348
    48
        MessageModelConfig.messageFolderDelegate = self
dirk@1348
    49
    }
dirk@1348
    50
dirk@1348
    51
    override func viewWillDisappear(_ animated: Bool) {
dirk@1348
    52
        super.viewWillDisappear(animated)
dirk@1348
    53
        MessageModelConfig.messageFolderDelegate = nil
igor@1301
    54
    }
igor@1301
    55
    
igor@1338
    56
    func initialConfig() {
dirk@1344
    57
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
igor@1338
    58
            return
igor@1338
    59
        }
dirk@1344
    60
dirk@1344
    61
        if config == nil {
igor@1395
    62
            config = EmailListConfig(appConfig: appDelegate.appConfig, folder: Folder.unifiedInbox())
dirk@1344
    63
        }
dirk@1348
    64
        if Account.all().isEmpty {
igor@1338
    65
            performSegue(withIdentifier:.segueAddNewAccount, sender: self)
igor@1338
    66
        }
igor@1338
    67
    }
igor@1338
    68
    
igor@1301
    69
    func addSearchBar() {
igor@1301
    70
        searchController.searchResultsUpdater = self
igor@1301
    71
        searchController.dimsBackgroundDuringPresentation = false
igor@1301
    72
        searchController.delegate = self
igor@1301
    73
        definesPresentationContext = true
igor@1301
    74
        tableView.tableHeaderView = searchController.searchBar
igor@1301
    75
        tableView.setContentOffset(CGPoint(x: 0.0, y: 40.0), animated: false)
igor@1301
    76
    }
dirk@705
    77
igor@941
    78
    
dirk@1330
    79
    @IBAction func showUnreadButtonTapped(_ sender: UIBarButtonItem) {}
igor@941
    80
    
dirk@854
    81
    func updateModel() {
igor@1318
    82
        tableView.reloadData()
dirk@31
    83
    }
dirk@31
    84
dirk@58
    85
    // MARK: - UI State
dirk@58
    86
dirk@58
    87
    func updateUI() {
dirk@784
    88
        UIApplication.shared.isNetworkActivityIndicatorVisible = state.isSynching
dirk@748
    89
        if !state.isSynching {
igor@1260
    90
            refreshControl?.endRefreshing()
dirk@58
    91
        }
dirk@58
    92
    }
dirk@58
    93
dirk@31
    94
    // MARK: - UITableViewDataSource
dirk@31
    95
dirk@784
    96
    override func numberOfSections(in tableView: UITableView) -> Int {
dirk@1344
    97
        if let _ = config?.folder {
dirk@854
    98
            return 1
dirk@209
    99
        }
dirk@854
   100
        return 0
dirk@31
   101
    }
dirk@31
   102
dirk@784
   103
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
dirk@1344
   104
        if let fol = config?.folder  {
dirk@854
   105
            return fol.messageCount()
dirk@31
   106
        }
dirk@31
   107
        return 0
dirk@31
   108
    }
dirk@31
   109
dirk@784
   110
    override func tableView(_ tableView: UITableView,
dirk@784
   111
                            cellForRowAt indexPath: IndexPath) -> UITableViewCell {
dirk@784
   112
        let cell = tableView.dequeueReusableCell(
dirk@784
   113
            withIdentifier: "EmailListViewCell", for: indexPath) as! EmailListViewCell
igor@1260
   114
        cell.configureCell(indexPath: indexPath, config: config)
dirk@31
   115
        return cell
dirk@31
   116
    }
dirk@31
   117
dirk@719
   118
    // MARK: - UITableViewDelegate
dirk@719
   119
dirk@1333
   120
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
igor@1260
   121
        let cell = tableView.cellForRow(at: indexPath) as! EmailListViewCell
dirk@719
   122
dirk@1344
   123
        if let fol = config?.folder {
dirk@855
   124
            if fol.folderType == .drafts {
igor@1395
   125
                //performSegue(withIdentifier: .segueCompose, sender: cell)
dirk@719
   126
                return
dirk@719
   127
            }
dirk@719
   128
        }
igor@1395
   129
        //performSegue(withIdentifier: .segueShowEmail, sender: cell)
dirk@719
   130
    }
dirk@719
   131
dirk@784
   132
    override func tableView(_ tableView: UITableView, editActionsForRowAt
dirk@784
   133
        indexPath: IndexPath)-> [UITableViewRowAction]? {
dirk@784
   134
        let cell = tableView.cellForRow(at: indexPath) as! EmailListViewCell
igor@1260
   135
        if let email = cell.messageAt(indexPath: indexPath, config: config) {
dirk@855
   136
            let isFlagAction = createIsFlagAction(message: email, cell: cell)
dirk@855
   137
            let deleteAction = createDeleteAction(cell)
igor@1242
   138
            //let isReadAction = createIsReadAction(message: email, cell: cell)
igor@1242
   139
            let moreAction = createMoreAction(message: email, cell: cell)
igor@1242
   140
            return [deleteAction,isFlagAction,moreAction]
dirk@855
   141
        }
dirk@855
   142
        return nil
dirk@744
   143
    }
dirk@744
   144
dirk@719
   145
    // MARK: - Misc
dirk@719
   146
dirk@855
   147
    func createIsFlagAction(message: Message, cell: EmailListViewCell) -> UITableViewRowAction {
dirk@744
   148
        // preparing action to trigger when user swipe
dirk@784
   149
        let isFlagCompletionHandler: (UITableViewRowAction, IndexPath) -> Void =
dirk@744
   150
            { (action, indexPath) in
igor@1260
   151
                if (cell.isImportant(message: message)) {
dirk@965
   152
                    message.imapFlags?.flagged = false
dirk@744
   153
dirk@744
   154
                } else {
dirk@965
   155
                    message.imapFlags?.flagged = true
dirk@744
   156
                }
dirk@784
   157
                self.tableView.reloadRows(at: [indexPath], with: .none)
dirk@744
   158
        }
dirk@744
   159
        // creating the action
igor@1242
   160
        let isFlagAction = UITableViewRowAction(style: .normal, title: "          ",
dirk@744
   161
                                                handler: isFlagCompletionHandler)
dirk@744
   162
        // changing default action color
igor@1242
   163
        let swipeFlagImage = UIImage(named: "swipe-flag")
igor@1242
   164
        let flagIconColor = UIColor(patternImage: swipeFlagImage!)
igor@1242
   165
        isFlagAction.backgroundColor = flagIconColor
dirk@744
   166
dirk@744
   167
        return isFlagAction
dirk@744
   168
    }
dirk@744
   169
dirk@784
   170
    func createDeleteAction (_ cell: EmailListViewCell) -> UITableViewRowAction {
dirk@744
   171
dirk@744
   172
        // preparing the title action to show when user swipe
dirk@744
   173
dirk@784
   174
        let deleteCompletionHandler: (UITableViewRowAction, IndexPath) -> Void =
dirk@744
   175
            { (action, indexPath) in
igor@1260
   176
                let message = cell.messageAt(indexPath: indexPath, config: self.config)
dirk@965
   177
                message?.imapFlags?.deleted = true
dirk@744
   178
        }
dirk@744
   179
dirk@744
   180
        // creating the action
igor@1242
   181
        let deleteAction = UITableViewRowAction(style: .normal, title: "          ",
dirk@744
   182
                                                handler: deleteCompletionHandler)
igor@1242
   183
        let swipeTrashImage = UIImage(named: "swipe-trash")
igor@1242
   184
        let trashIconColor = UIColor(patternImage: swipeTrashImage!)
igor@1242
   185
        deleteAction.backgroundColor = trashIconColor
dirk@744
   186
        return deleteAction
dirk@744
   187
    }
dirk@744
   188
dirk@855
   189
    func createIsReadAction(message: Message, cell: EmailListViewCell) -> UITableViewRowAction {
dirk@744
   190
        // preparing the title action to show when user swipe
dirk@744
   191
        var localizedisReadTitle = " "
igor@1260
   192
        if (cell.isRead(message: message)) {
dirk@855
   193
            localizedisReadTitle = NSLocalizedString(
dirk@855
   194
                "Unread",
dirk@855
   195
                comment: "Unread button title in swipe action on EmailListViewController")
dirk@744
   196
        } else {
dirk@855
   197
            localizedisReadTitle = NSLocalizedString(
dirk@855
   198
                "Read",
dirk@855
   199
                comment: "Read button title in swipe action on EmailListViewController")
dirk@744
   200
        }
dirk@744
   201
dirk@744
   202
        // creating the action
dirk@784
   203
        let isReadCompletionHandler: (UITableViewRowAction, IndexPath) -> Void =
dirk@744
   204
            { (action, indexPath) in
igor@1260
   205
                if (cell.isRead(message: message)) {
dirk@965
   206
                    message.imapFlags?.seen = false
dirk@744
   207
                } else {
dirk@965
   208
                    message.imapFlags?.seen = true
dirk@744
   209
                }
dirk@784
   210
                self.tableView.reloadRows(at: [indexPath], with: .none)
dirk@744
   211
        }
dirk@784
   212
        let isReadAction = UITableViewRowAction(style: .default, title: localizedisReadTitle,
dirk@744
   213
                                                handler: isReadCompletionHandler)
dirk@784
   214
        isReadAction.backgroundColor = UIColor.blue
dirk@744
   215
dirk@744
   216
        return isReadAction
dirk@744
   217
    }
igor@1242
   218
    
igor@1242
   219
    func createMoreAction(message: Message, cell: EmailListViewCell) -> UITableViewRowAction {
igor@1242
   220
        let moreCompletitionHandler :(UITableViewRowAction, IndexPath) -> Void = {(action, indexPath) in
igor@1242
   221
            self.showMoreActionSheet(cell: cell)
igor@1242
   222
        }
igor@1242
   223
        let moreAction = UITableViewRowAction(style: .normal, title: "          ", handler: moreCompletitionHandler)
igor@1242
   224
        let swipeMoreImage = UIImage(named: "swipe-more")
igor@1242
   225
        let moreIconColor = UIColor(patternImage: swipeMoreImage!)
igor@1242
   226
        moreAction.backgroundColor = moreIconColor
igor@1242
   227
        return moreAction
igor@1242
   228
    }
igor@1242
   229
    
igor@1242
   230
    // MARK: - Action Sheet
igor@1242
   231
    
igor@1242
   232
    func showMoreActionSheet(cell: EmailListViewCell) {
igor@1242
   233
        let alertControler = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
igor@1242
   234
        let cancelAction = createCancelAction()
igor@1242
   235
        let replyAction = createReplyAction(cell: cell)
igor@1242
   236
        let forwardAction = createForwardAction(cell: cell)
igor@1242
   237
        let markAction = createMarkAction()
igor@1242
   238
        alertControler.addAction(cancelAction)
igor@1242
   239
        alertControler.addAction(replyAction)
igor@1242
   240
        alertControler.addAction(forwardAction)
igor@1242
   241
        alertControler.addAction(markAction)
igor@1242
   242
        present(alertControler, animated: true, completion: nil)
igor@1242
   243
    }
igor@1242
   244
    
igor@1242
   245
    // MARK: - Action Sheet Actions
igor@1242
   246
igor@1242
   247
    func createCancelAction() -> UIAlertAction {
igor@1242
   248
      return  UIAlertAction(title: "Cancel", style: .cancel) { (action) in}
igor@1242
   249
    }
igor@1242
   250
    
igor@1242
   251
    func createReplyAction(cell: EmailListViewCell) ->  UIAlertAction {
igor@1242
   252
        return UIAlertAction(title: "Reply", style: .default) { (action) in
igor@1338
   253
           // self.performSegue(withIdentifier: self.segueCompose, sender: cell)
igor@1338
   254
            self.performSegue(withIdentifier: .segueCompose, sender: cell)
igor@1242
   255
        }
igor@1242
   256
    }
igor@1242
   257
    
igor@1242
   258
    func createForwardAction(cell: EmailListViewCell) -> UIAlertAction {
igor@1242
   259
        return UIAlertAction(title: "Forward", style: .default) { (action) in
igor@1338
   260
            //self.performSegue(withIdentifier: self.segueCompose, sender: cell)
igor@1338
   261
            self.performSegue(withIdentifier: .segueCompose, sender: cell)
igor@1242
   262
        }
igor@1242
   263
    }
igor@1242
   264
    
igor@1242
   265
    func createMarkAction() -> UIAlertAction {
igor@1242
   266
        return UIAlertAction(title: "Mark", style: .default) { (action) in
igor@1242
   267
        }
igor@1242
   268
    }
igor@1301
   269
    
igor@1301
   270
    // MARK: - Content Search
igor@1301
   271
    
igor@1301
   272
    func filterContentForSearchText(searchText: String) {
igor@1301
   273
        
igor@1301
   274
    }
igor@1395
   275
 
igor@1338
   276
    // MARK: - Actions
igor@1395
   277
//    @IBAction func unwindToEmailList(for unwindSegue: UIStoryboardSegue) {
igor@1395
   278
//        
igor@1395
   279
//    }
igor@1338
   280
   
dirk@784
   281
}
igor@1301
   282
igor@1301
   283
extension EmailListViewController: UISearchResultsUpdating, UISearchControllerDelegate {
igor@1301
   284
    public func updateSearchResults(for searchController: UISearchController) {
igor@1301
   285
        filterContentForSearchText(searchText: searchController.searchBar.text!)
igor@1301
   286
    }
igor@1301
   287
    
igor@1301
   288
    func didDismissSearchController(_ searchController: UISearchController) {
igor@1301
   289
    }
igor@1301
   290
}
igor@1338
   291
igor@1338
   292
// MARK: - Navigation
igor@1338
   293
igor@1338
   294
extension EmailListViewController: SegueHandlerType {
igor@1338
   295
    
igor@1338
   296
    // MARK: - SegueHandlerType
igor@1338
   297
    
igor@1338
   298
    enum SegueIdentifier: String {
igor@1338
   299
        case segueAddNewAccount
igor@1338
   300
        case segueEditAccounts
igor@1338
   301
        case segueShowEmail
igor@1338
   302
        case segueCompose
igor@1338
   303
        case noSegue
igor@1338
   304
    }
igor@1338
   305
    
igor@1338
   306
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
igor@1338
   307
        switch segueIdentifier(for: segue) {
igor@1338
   308
        case .segueCompose:
igor@1338
   309
            //let destination = segue.destination as! ComposeTableViewController
igor@1338
   310
            // destination.appConfig = config.appConfig
igor@1338
   311
            //            if let draft = draftMessageToCompose {
igor@1338
   312
            //                draft.imapFlags?.seen = true
igor@1338
   313
            //
igor@1338
   314
            //                destination.originalMessage = draft
igor@1338
   315
            //                destination.composeMode = .draft
igor@1338
   316
        //            }
igor@1338
   317
            break
igor@1338
   318
        case .segueShowEmail:
igor@1338
   319
            guard
igor@1338
   320
                let vc = segue.destination as? EmailViewController,
igor@1338
   321
                let cell = sender as? EmailListViewCell,
igor@1338
   322
                let indexPath = self.tableView.indexPath(for: cell),
igor@1338
   323
                let email = cell.messageAt(indexPath: indexPath, config: config) else {
igor@1338
   324
                    return
igor@1338
   325
            }
dirk@1344
   326
            vc.appConfig = config?.appConfig
igor@1338
   327
            vc.message = email
igor@1338
   328
            break
igor@1338
   329
        default: ()
igor@1338
   330
        }
igor@1338
   331
    }
dirk@1350
   332
dirk@1350
   333
    func didChangeInternal(messageFolder: MessageFolder) {
dirk@1350
   334
        if let folder = config?.folder,
dirk@1350
   335
            let message = messageFolder as? Message,
dirk@1350
   336
            folder.contains(message: message) {
dirk@1350
   337
            if let msg = messageFolder as? Message {
dirk@1350
   338
                if msg.isOriginal {
dirk@1350
   339
                    self.tableView.reloadData()
dirk@1350
   340
                }
dirk@1350
   341
            }
dirk@1350
   342
        }
dirk@1350
   343
    }
igor@1338
   344
}
dirk@1348
   345
dirk@1348
   346
// MARK: - MessageFolderDelegate
dirk@1348
   347
dirk@1348
   348
extension EmailListViewController: MessageFolderDelegate {
dirk@1348
   349
    func didChange(messageFolder: MessageFolder) {
dirk@1350
   350
        GCD.onMain {
dirk@1350
   351
            self.didChangeInternal(messageFolder: messageFolder)
dirk@1348
   352
        }
dirk@1348
   353
    }
dirk@1348
   354
}