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