// // MailViewController.swift // // Created by Jeremy Koch // Copyright © 2017 Jeremy Koch. All rights reserved. // import UIKit import SwipeCellKit class MailViewController: UITableViewController { var emails: [Email] = [] var defaultOptions = SwipeTableOptions() var isSwipeRightEnabled = true var buttonDisplayMode: ButtonDisplayMode = .titleAndImage var buttonStyle: ButtonStyle = .backgroundColor // MARK: - Lifecycle override func viewDidLoad() { tableView.allowsSelection = true tableView.allowsMultipleSelectionDuringEditing = true tableView.rowHeight = UITableViewAutomaticDimension tableView.estimatedRowHeight = 100 navigationItem.rightBarButtonItem = editButtonItem view.layoutMargins.left = 32 resetData() } // MARK: - Table view data source override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return emails.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "MailCell") as! MailTableCell cell.delegate = self cell.selectedBackgroundView = createSelectedBackgroundView() let email = emails[indexPath.row] cell.fromLabel.text = email.from cell.dateLabel.text = email.relativeDateString cell.subjectLabel.text = email.subject cell.bodyLabel.text = email.body cell.unread = email.unread return cell } // MARK: - Actions @IBAction func moreTapped(_ sender: Any) { let controller = UIAlertController(title: "Swipe Transition Style", message: nil, preferredStyle: .actionSheet) controller.addAction(UIAlertAction(title: "Border", style: .default, handler: { _ in self.defaultOptions.transitionStyle = .border })) controller.addAction(UIAlertAction(title: "Drag", style: .default, handler: { _ in self.defaultOptions.transitionStyle = .drag })) controller.addAction(UIAlertAction(title: "Reveal", style: .default, handler: { _ in self.defaultOptions.transitionStyle = .reveal })) controller.addAction(UIAlertAction(title: "\(isSwipeRightEnabled ? "Disable" : "Enable") Swipe Right", style: .default, handler: { _ in self.isSwipeRightEnabled = !self.isSwipeRightEnabled })) controller.addAction(UIAlertAction(title: "Button Display Mode", style: .default, handler: { _ in self.buttonDisplayModeTapped() })) controller.addAction(UIAlertAction(title: "Button Style", style: .default, handler: { _ in self.buttonStyleTapped() })) controller.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil)) controller.addAction(UIAlertAction(title: "Reset", style: .destructive, handler: { _ in self.resetData() })) present(controller, animated: true, completion: nil) } func buttonDisplayModeTapped() { let controller = UIAlertController(title: "Button Display Mode", message: nil, preferredStyle: .actionSheet) controller.addAction(UIAlertAction(title: "Image + Title", style: .default, handler: { _ in self.buttonDisplayMode = .titleAndImage })) controller.addAction(UIAlertAction(title: "Image Only", style: .default, handler: { _ in self.buttonDisplayMode = .imageOnly })) controller.addAction(UIAlertAction(title: "Title Only", style: .default, handler: { _ in self.buttonDisplayMode = .titleOnly })) controller.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil)) present(controller, animated: true, completion: nil) } func buttonStyleTapped() { let controller = UIAlertController(title: "Button Style", message: nil, preferredStyle: .actionSheet) controller.addAction(UIAlertAction(title: "Background Color", style: .default, handler: { _ in self.buttonStyle = .backgroundColor self.defaultOptions.transitionStyle = .border })) controller.addAction(UIAlertAction(title: "Circular", style: .default, handler: { _ in self.buttonStyle = .circular self.defaultOptions.transitionStyle = .reveal })) controller.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil)) present(controller, animated: true, completion: nil) } // MARK: - Helpers func createSelectedBackgroundView() -> UIView { let view = UIView() view.backgroundColor = UIColor.lightGray.withAlphaComponent(0.2) return view } func resetData() { emails = mockEmails emails.forEach { $0.unread = false } tableView.reloadData() } } extension MailViewController: SwipeTableViewCellDelegate { func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? { let email = emails[indexPath.row] if orientation == .left { guard isSwipeRightEnabled else { return nil } let read = SwipeAction(style: .default, title: nil) { action, indexPath in let updatedStatus = !email.unread email.unread = updatedStatus let cell = tableView.cellForRow(at: indexPath) as! MailTableCell cell.setUnread(updatedStatus, animated: true) } read.hidesWhenSelected = true read.accessibilityLabel = email.unread ? "Mark as Read" : "Mark as Unread" let descriptor: ActionDescriptor = email.unread ? .read : .unread configure(action: read, with: descriptor) return [read] } else { let flag = SwipeAction(style: .default, title: nil, handler: nil) flag.hidesWhenSelected = true configure(action: flag, with: .flag) let delete = SwipeAction(style: .destructive, title: nil) { action, indexPath in self.emails.remove(at: indexPath.row) } configure(action: delete, with: .trash) let cell = tableView.cellForRow(at: indexPath) as! MailTableCell let closure: (UIAlertAction) -> Void = { _ in cell.hideSwipe(animated: true) } let more = SwipeAction(style: .default, title: nil) { action, indexPath in let controller = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) controller.addAction(UIAlertAction(title: "Reply", style: .default, handler: closure)) controller.addAction(UIAlertAction(title: "Forward", style: .default, handler: closure)) controller.addAction(UIAlertAction(title: "Mark...", style: .default, handler: closure)) controller.addAction(UIAlertAction(title: "Notify Me...", style: .default, handler: closure)) controller.addAction(UIAlertAction(title: "Move Message...", style: .default, handler: closure)) controller.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: closure)) self.present(controller, animated: true, completion: nil) } configure(action: more, with: .more) return [delete, flag, more] } } func tableView(_ tableView: UITableView, editActionsOptionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> SwipeTableOptions { var options = SwipeTableOptions() options.expansionStyle = orientation == .left ? .selection : .destructive options.transitionStyle = defaultOptions.transitionStyle switch buttonStyle { case .backgroundColor: options.buttonSpacing = 11 case .circular: options.buttonSpacing = 4 options.backgroundColor = #colorLiteral(red: 0.9467939734, green: 0.9468161464, blue: 0.9468042254, alpha: 1) } return options } func configure(action: SwipeAction, with descriptor: ActionDescriptor) { action.title = descriptor.title(forDisplayMode: buttonDisplayMode) action.image = descriptor.image(forStyle: buttonStyle, displayMode: buttonDisplayMode) switch buttonStyle { case .backgroundColor: action.backgroundColor = descriptor.color case .circular: action.backgroundColor = .clear action.textColor = descriptor.color action.font = .systemFont(ofSize: 13) action.transitionDelegate = ScaleTransition.default } } }