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