Refactor swipe actions into TableViewSwipeActionProvider

This commit is contained in:
Shadowfacts 2018-09-15 13:01:13 -04:00
parent 4c9be91162
commit 6ec0ae5489
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
7 changed files with 158 additions and 99 deletions

View File

@ -67,6 +67,7 @@
D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AAC2128D88B005A6F37 /* LocalData.swift */; }; D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AAC2128D88B005A6F37 /* LocalData.swift */; };
D64D0AAF2128D954005A6F37 /* Onboarding.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D64D0AAE2128D954005A6F37 /* Onboarding.storyboard */; }; D64D0AAF2128D954005A6F37 /* Onboarding.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D64D0AAE2128D954005A6F37 /* Onboarding.storyboard */; };
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */; }; D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */; };
D6538945214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6538944214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift */; };
D65A37F321472F300087646E /* SwiftSoup.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6BED16E212663DA00F02DA0 /* SwiftSoup.framework */; }; D65A37F321472F300087646E /* SwiftSoup.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6BED16E212663DA00F02DA0 /* SwiftSoup.framework */; };
D663625D2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D663625C2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib */; }; D663625D2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D663625C2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib */; };
D663625F2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D663625E2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift */; }; D663625F2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D663625E2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift */; };
@ -221,6 +222,7 @@
D64D0AAC2128D88B005A6F37 /* LocalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalData.swift; sourceTree = "<group>"; }; D64D0AAC2128D88B005A6F37 /* LocalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalData.swift; sourceTree = "<group>"; };
D64D0AAE2128D954005A6F37 /* Onboarding.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Onboarding.storyboard; sourceTree = "<group>"; }; D64D0AAE2128D954005A6F37 /* Onboarding.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Onboarding.storyboard; sourceTree = "<group>"; };
D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = "<group>"; }; D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = "<group>"; };
D6538944214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewSwipeActionProvider.swift; sourceTree = "<group>"; };
D663625C2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ConversationMainStatusTableViewCell.xib; sourceTree = "<group>"; }; D663625C2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ConversationMainStatusTableViewCell.xib; sourceTree = "<group>"; };
D663625E2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationMainStatusTableViewCell.swift; sourceTree = "<group>"; }; D663625E2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationMainStatusTableViewCell.swift; sourceTree = "<group>"; };
D663626121360B1900C9CBA2 /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; }; D663626121360B1900C9CBA2 /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; };
@ -571,6 +573,7 @@
D6333B762138D94E00CE884A /* ComposeMediaView.swift */, D6333B762138D94E00CE884A /* ComposeMediaView.swift */,
D641C77E213DC78A004B4513 /* InlineTextAttachment.swift */, D641C77E213DC78A004B4513 /* InlineTextAttachment.swift */,
04ED00B021481ED800567C53 /* SteppedProgressView.swift */, 04ED00B021481ED800567C53 /* SteppedProgressView.swift */,
D6538944214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift */,
D641C78A213DD926004B4513 /* Status */, D641C78A213DD926004B4513 /* Status */,
D641C78B213DD92F004B4513 /* Profile Header */, D641C78B213DD92F004B4513 /* Profile Header */,
D641C78C213DD937004B4513 /* Notifications */, D641C78C213DD937004B4513 /* Notifications */,
@ -926,6 +929,7 @@
D6333B772138D94E00CE884A /* ComposeMediaView.swift in Sources */, D6333B772138D94E00CE884A /* ComposeMediaView.swift in Sources */,
04ED00B121481ED800567C53 /* SteppedProgressView.swift in Sources */, 04ED00B121481ED800567C53 /* SteppedProgressView.swift in Sources */,
D663626421360D2300C9CBA2 /* AvatarStyle.swift in Sources */, D663626421360D2300C9CBA2 /* AvatarStyle.swift in Sources */,
D6538945214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift in Sources */,
D6BED174212667E900F02DA0 /* StatusTableViewCell.swift in Sources */, D6BED174212667E900F02DA0 /* StatusTableViewCell.swift in Sources */,
D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */, D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */,
D6C94D892139E6EC00CB5196 /* AttachmentView.swift in Sources */, D6C94D892139E6EC00CB5196 /* AttachmentView.swift in Sources */,

View File

@ -117,6 +117,18 @@ class ConversationViewController: UIViewController, UITableViewDataSource, UITab
let status = statuses[indexPath.row] let status = statuses[indexPath.row]
return status == mainStatus ? nil : indexPath return status == mainStatus ? nil : indexPath
} }
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return tableView.cellForRow(at: indexPath) is TableViewSwipeActionProvider
}
func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
return (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.leadingSwipeActionsConfiguration()
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
return (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.trailingSwipeActionsConfiguration()
}
} }

View File

@ -118,6 +118,18 @@ class NotificationsTableViewController: UITableViewController {
} }
} }
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return tableView.cellForRow(at: indexPath) is TableViewSwipeActionProvider
}
override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
return (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.leadingSwipeActionsConfiguration()
}
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
return (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.trailingSwipeActionsConfiguration()
}
@IBAction func refreshNotifications(_ sender: Any) { @IBAction func refreshNotifications(_ sender: Any) {
guard let newer = newer else { return } guard let newer = newer else { return }

View File

@ -132,6 +132,18 @@ class ProfileTableViewController: UITableViewController, PreferencesAdaptive {
} }
} }
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return tableView.cellForRow(at: indexPath) is TableViewSwipeActionProvider
}
override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
return (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.leadingSwipeActionsConfiguration()
}
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
return (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.trailingSwipeActionsConfiguration()
}
@IBAction func refreshStatuses(_ sender: Any) { @IBAction func refreshStatuses(_ sender: Any) {
guard let newer = newer else { return } guard let newer = newer else { return }

View File

@ -133,107 +133,16 @@ class TimelineTableViewController: UITableViewController {
} }
} }
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return tableView.cellForRow(at: indexPath) is TableViewSwipeActionProvider
}
override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let status = statuses[indexPath.row] return (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.leadingSwipeActionsConfiguration()
let favorite: UIContextualAction
if status.favourited ?? false {
favorite = UIContextualAction(style: .normal, title: "Unfavorite", handler: { (action, view, completion) in
status.unfavourite(completion: { response in
DispatchQueue.main.async {
if case .success = response {
completion(true)
guard let cell = tableView.cellForRow(at: indexPath) as? StatusTableViewCell else { return }
cell.updateUI(for: cell.status)
} else {
completion(false)
}
}
})
})
favorite.backgroundColor = UIColor(displayP3Red: 235/255, green: 77/255, blue: 62/255, alpha: 1)
} else {
favorite = UIContextualAction(style: .normal, title: "Favorite") { (action, view, completion) in
status.favourite(completion: { response in
DispatchQueue.main.async {
if case .success = response {
completion(true)
guard let cell = tableView.cellForRow(at: indexPath) as? StatusTableViewCell else { return }
cell.updateUI(for: cell.status)
} else {
completion(false)
}
}
})
}
favorite.backgroundColor = UIColor(displayP3Red: 1, green: 204/255, blue: 0, alpha: 1)
}
favorite.image = favoriteActionImage
let reblog: UIContextualAction
if status.reblogged ?? false {
reblog = UIContextualAction(style: .normal, title: "Unreblog", handler: { (action, view, completion) in
status.unreblog(completion: { response in
DispatchQueue.main.async {
if case .success = response {
completion(true)
guard let cell = tableView.cellForRow(at: indexPath) as? StatusTableViewCell else { return }
cell.updateUI(for: cell.status)
} else {
completion(false)
}
}
})
})
reblog.backgroundColor = UIColor(displayP3Red: 235/255, green: 77/255, blue: 62/255, alpha: 1)
} else {
reblog = UIContextualAction(style: .normal, title: "Reblog") { (action, view, completion) in
status.reblog(completion: { response in
DispatchQueue.main.async {
if case .success = response {
completion(true)
guard let cell = tableView.cellForRow(at: indexPath) as? StatusTableViewCell else { return }
cell.updateUI(for: cell.status)
} else {
completion(false)
}
}
})
}
reblog.backgroundColor = view.tintColor
}
reblog.image = reblogActionImage
let actions = [
favorite,
reblog
]
return UISwipeActionsConfiguration(actions: actions)
} }
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let status = statuses[indexPath.row] return (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.trailingSwipeActionsConfiguration()
let reply = UIContextualAction(style: .normal, title: "Reply") { (action, view, completion) in
completion(true)
self.reply(to: status)
}
reply.image = replyActionImage
reply.backgroundColor = view.tintColor
let more = UIContextualAction(style: .normal, title: "More") { (action, view, completion) in
completion(true)
self.showMoreOptions(status: status)
}
more.image = moreActionImage
more.backgroundColor = .gray
let actions = [
reply,
more
]
return UISwipeActionsConfiguration(actions: actions)
} }
@IBAction func refreshStatuses(_ sender: Any) { @IBAction func refreshStatuses(_ sender: Any) {

View File

@ -215,8 +215,8 @@ class StatusTableViewCell: UITableViewCell, PreferencesAdaptive {
let realStatus: Status = status.reblog ?? status let realStatus: Status = status.reblog ?? status
(favorited ? realStatus.favourite : realStatus.unfavourite)() { response in (favorited ? realStatus.favourite : realStatus.unfavourite)() { response in
self.favorited = realStatus.favourited ?? false
DispatchQueue.main.async { DispatchQueue.main.async {
self.favorited = realStatus.favourited ?? false
if case .success = response { if case .success = response {
UIImpactFeedbackGenerator(style: .light).impactOccurred() UIImpactFeedbackGenerator(style: .light).impactOccurred()
} else { } else {
@ -235,8 +235,8 @@ class StatusTableViewCell: UITableViewCell, PreferencesAdaptive {
let realStatus: Status = status.reblog ?? status let realStatus: Status = status.reblog ?? status
(reblogged ? realStatus.reblog : realStatus.unreblog)() { response in (reblogged ? realStatus.reblog : realStatus.unreblog)() { response in
self.reblogged = realStatus.reblogged ?? false
DispatchQueue.main.async { DispatchQueue.main.async {
self.reblogged = realStatus.reblogged ?? false
if case .success = response { if case .success = response {
UIImpactFeedbackGenerator(style: .light).impactOccurred() UIImpactFeedbackGenerator(style: .light).impactOccurred()
} else { } else {
@ -254,6 +254,99 @@ class StatusTableViewCell: UITableViewCell, PreferencesAdaptive {
} }
extension StatusTableViewCell: TableViewSwipeActionProvider {
static var favoriteActionImage: UIImage = UIGraphicsImageRenderer(size: CGSize(width: 30 * 137/131, height: 30)).image { _ in
UIImage(named: "Favorite")!.draw(in: CGRect(x: 0, y: 0, width: 30 * 137/131, height: 30))
}
static var reblogActionImage: UIImage = UIGraphicsImageRenderer(size: CGSize(width: 30 * 927/558, height: 30)).image { _ in
UIImage(named: "Reblog")!.draw(in: CGRect(x: 0, y: 0, width: 30 * 927/558, height: 30))
}
static var replyActionImage: UIImage = UIGraphicsImageRenderer(size: CGSize(width: 30 * 205/151, height: 30)).image { _ in
UIImage(named: "Reply")!.draw(in: CGRect(x: 0, y: 0, width: 30 * 205/151, height: 30))
}
static var moreActionImage: UIImage = UIGraphicsImageRenderer(size: CGSize(width: 30 * 2/1, height: 30)).image { _ in
UIImage(named: "More")!.draw(in: CGRect(x: 0, y: 0, width: 30 * 2/1, height: 30))
}
func leadingSwipeActionsConfiguration() -> UISwipeActionsConfiguration? {
let favoriteTitle: String
let favoriteAction: (@escaping Client.Callback<Status>) -> Void
let favoriteColor: UIColor
if status.favourited ?? false {
favoriteTitle = "Unfavorite"
favoriteAction = status.unfavourite
favoriteColor = UIColor(displayP3Red: 235/255, green: 77/255, blue: 62/255, alpha: 1)
} else {
favoriteTitle = "Favorite"
favoriteAction = status.favourite
favoriteColor = UIColor(displayP3Red: 1, green: 204/255, blue: 0, alpha: 1)
}
let favorite = UIContextualAction(style: .normal, title: favoriteTitle) { (action, view, completion) in
favoriteAction { response in
DispatchQueue.main.async {
if case .success = response {
completion(true)
self.updateUI(for: self.status)
} else {
completion(false)
}
}
}
}
favorite.image = StatusTableViewCell.favoriteActionImage
favorite.backgroundColor = favoriteColor
let reblogTitle: String
let reblogAction: (@escaping Client.Callback<Status>) -> Void
let reblogColor: UIColor
if status.reblogged ?? false {
reblogTitle = "Unreblog"
reblogAction = status.unreblog
reblogColor = UIColor(displayP3Red: 235/255, green: 77/255, blue: 62/255, alpha: 1)
} else {
reblogTitle = "Reblog"
reblogAction = status.reblog
reblogColor = tintColor
}
let reblog = UIContextualAction(style: .normal, title: reblogTitle) { (action, view, completion) in
reblogAction { response in
DispatchQueue.main.async {
if case .success = response {
completion(true)
self.updateUI(for: self.status)
} else {
completion(false)
}
}
}
}
reblog.image = StatusTableViewCell.reblogActionImage
reblog.backgroundColor = reblogColor
return UISwipeActionsConfiguration(actions: [favorite, reblog])
}
func trailingSwipeActionsConfiguration() -> UISwipeActionsConfiguration? {
let reply = UIContextualAction(style: .normal, title: "Reply") { (action, view, completion) in
completion(true)
self.delegate?.reply(to: self.status)
}
reply.image = StatusTableViewCell.replyActionImage
reply.backgroundColor = tintColor
let more = UIContextualAction(style: .normal, title: "More") { (action, view, completion) in
completion(true)
self.delegate?.showMoreOptions(status: self.status)
}
more.image = StatusTableViewCell.moreActionImage
more.backgroundColor = .gray
return UISwipeActionsConfiguration(actions: [reply, more])
}
}
extension StatusTableViewCell: HTMLContentLabelDelegate { extension StatusTableViewCell: HTMLContentLabelDelegate {
func selected(mention: Mention) { func selected(mention: Mention) {

View File

@ -0,0 +1,17 @@
//
// TableViewSwipeActionProvider.swift
// Tusker
//
// Created by Shadowfacts on 9/15/18.
// Copyright © 2018 Shadowfacts. All rights reserved.
//
import UIKit
protocol TableViewSwipeActionProvider {
func leadingSwipeActionsConfiguration() -> UISwipeActionsConfiguration?
func trailingSwipeActionsConfiguration() -> UISwipeActionsConfiguration?
}