Add button to conversation table view to collapse/expand all posts

This needs a refactor once StatusTableViewCell and
ConversationMainStatusTableViewCell are merged. See #54
This commit is contained in:
Shadowfacts 2019-11-18 22:23:15 -05:00
parent da6ff67a51
commit 8fb3b211b6
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
5 changed files with 73 additions and 6 deletions

View File

@ -28,6 +28,7 @@
D60A548F21ED515800F1F87C /* GMImagePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = D60A548D21ED515800F1F87C /* GMImagePicker.h */; settings = {ATTRIBUTES = (Public, ); }; }; D60A548F21ED515800F1F87C /* GMImagePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = D60A548D21ED515800F1F87C /* GMImagePicker.h */; settings = {ATTRIBUTES = (Public, ); }; };
D60A549221ED515800F1F87C /* GMImagePicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D60A548B21ED515800F1F87C /* GMImagePicker.framework */; }; D60A549221ED515800F1F87C /* GMImagePicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D60A548B21ED515800F1F87C /* GMImagePicker.framework */; };
D60A549321ED515800F1F87C /* GMImagePicker.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D60A548B21ED515800F1F87C /* GMImagePicker.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; D60A549321ED515800F1F87C /* GMImagePicker.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D60A548B21ED515800F1F87C /* GMImagePicker.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
D60BAFB82383921D00EED893 /* StatusCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60BAFB72383921D00EED893 /* StatusCell.swift */; };
D60C07E421E8176B0057FAA8 /* ComposeMediaView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D60C07E321E8176B0057FAA8 /* ComposeMediaView.xib */; }; D60C07E421E8176B0057FAA8 /* ComposeMediaView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D60C07E321E8176B0057FAA8 /* ComposeMediaView.xib */; };
D61099B42144B0CC00432DC2 /* Pachyderm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D61099AB2144B0CC00432DC2 /* Pachyderm.framework */; }; D61099B42144B0CC00432DC2 /* Pachyderm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D61099AB2144B0CC00432DC2 /* Pachyderm.framework */; };
D61099BB2144B0CC00432DC2 /* PachydermTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61099BA2144B0CC00432DC2 /* PachydermTests.swift */; }; D61099BB2144B0CC00432DC2 /* PachydermTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61099BA2144B0CC00432DC2 /* PachydermTests.swift */; };
@ -287,6 +288,7 @@
D60A548B21ED515800F1F87C /* GMImagePicker.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GMImagePicker.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D60A548B21ED515800F1F87C /* GMImagePicker.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GMImagePicker.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D60A548D21ED515800F1F87C /* GMImagePicker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GMImagePicker.h; sourceTree = "<group>"; }; D60A548D21ED515800F1F87C /* GMImagePicker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GMImagePicker.h; sourceTree = "<group>"; };
D60A548E21ED515800F1F87C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; D60A548E21ED515800F1F87C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D60BAFB72383921D00EED893 /* StatusCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCell.swift; sourceTree = "<group>"; };
D60C07E321E8176B0057FAA8 /* ComposeMediaView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ComposeMediaView.xib; sourceTree = "<group>"; }; D60C07E321E8176B0057FAA8 /* ComposeMediaView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ComposeMediaView.xib; sourceTree = "<group>"; };
D61099AB2144B0CC00432DC2 /* Pachyderm.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pachyderm.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D61099AB2144B0CC00432DC2 /* Pachyderm.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pachyderm.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D61099AD2144B0CC00432DC2 /* Pachyderm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Pachyderm.h; sourceTree = "<group>"; }; D61099AD2144B0CC00432DC2 /* Pachyderm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Pachyderm.h; sourceTree = "<group>"; };
@ -831,6 +833,7 @@
D6BED173212667E900F02DA0 /* StatusTableViewCell.swift */, D6BED173212667E900F02DA0 /* StatusTableViewCell.swift */,
D663625C2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib */, D663625C2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib */,
D663625E2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift */, D663625E2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift */,
D60BAFB72383921D00EED893 /* StatusCell.swift */,
); );
path = Status; path = Status;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1597,6 +1600,7 @@
D679C09F215850EF00DA27FE /* XCBActions.swift in Sources */, D679C09F215850EF00DA27FE /* XCBActions.swift in Sources */,
D6DD353F22F502EC00A9563A /* Preferences+Notification.swift in Sources */, D6DD353F22F502EC00A9563A /* Preferences+Notification.swift in Sources */,
D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */, D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */,
D60BAFB82383921D00EED893 /* StatusCell.swift in Sources */,
D6AEBB4523216AF800E5038B /* FollowAccountActivity.swift in Sources */, D6AEBB4523216AF800E5038B /* FollowAccountActivity.swift in Sources */,
D6538945214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift in Sources */, D6538945214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift in Sources */,
D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */, D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */,

View File

@ -12,6 +12,9 @@ import Pachyderm
class ConversationTableViewController: EnhancedTableViewController { class ConversationTableViewController: EnhancedTableViewController {
static let showPostsImage = UIImage(systemName: "eye.fill")!
static let hidePostsImage = UIImage(systemName: "eye.slash.fill")!
var mainStatusID: String! var mainStatusID: String!
var statusIDs: [String] = [] { var statusIDs: [String] = [] {
didSet { didSet {
@ -21,6 +24,9 @@ class ConversationTableViewController: EnhancedTableViewController {
} }
} }
var showStatusesAutomatically = false
var visibilityBarButtonItem: UIBarButtonItem!
init(for mainStatusID: String) { init(for mainStatusID: String) {
self.mainStatusID = mainStatusID self.mainStatusID = mainStatusID
@ -42,6 +48,9 @@ class ConversationTableViewController: EnhancedTableViewController {
tableView.prefetchDataSource = self tableView.prefetchDataSource = self
visibilityBarButtonItem = UIBarButtonItem(image: ConversationTableViewController.showPostsImage, style: .plain, target: self, action: #selector(toggleVisibilityButtonPressed))
navigationItem.rightBarButtonItem = visibilityBarButtonItem
statusIDs = [mainStatusID] statusIDs = [mainStatusID]
guard let mainStatus = MastodonCache.status(for: mainStatusID) else { fatalError("Missing cached status \(mainStatusID!)") } guard let mainStatus = MastodonCache.status(for: mainStatusID) else { fatalError("Missing cached status \(mainStatusID!)") }
@ -89,11 +98,13 @@ class ConversationTableViewController: EnhancedTableViewController {
if statusID == mainStatusID { if statusID == mainStatusID {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "mainStatusCell", for: indexPath) as? ConversationMainStatusTableViewCell else { fatalError() } guard let cell = tableView.dequeueReusableCell(withIdentifier: "mainStatusCell", for: indexPath) as? ConversationMainStatusTableViewCell else { fatalError() }
cell.selectionStyle = .none cell.selectionStyle = .none
cell.showStatusAutomatically = showStatusesAutomatically
cell.updateUI(statusID: statusID) cell.updateUI(statusID: statusID)
cell.delegate = self cell.delegate = self
return cell return cell
} else { } else {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? StatusTableViewCell else { fatalError() } guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? StatusTableViewCell else { fatalError() }
cell.showStatusAutomatically = showStatusesAutomatically
cell.updateUI(statusID: statusID) cell.updateUI(statusID: statusID)
cell.delegate = self cell.delegate = self
return cell return cell
@ -116,6 +127,24 @@ class ConversationTableViewController: EnhancedTableViewController {
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
return (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.trailingSwipeActionsConfiguration() return (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.trailingSwipeActionsConfiguration()
} }
@objc func toggleVisibilityButtonPressed() {
showStatusesAutomatically = !showStatusesAutomatically
for cell in tableView.visibleCells {
guard var cell = cell as? UITableViewCell & StatusCell,
cell.collapsible else { continue }
cell.showStatusAutomatically = showStatusesAutomatically
cell.setCollapsed(!showStatusesAutomatically, animated: false)
}
statusCollapsedStateChanged()
if showStatusesAutomatically {
visibilityBarButtonItem.image = ConversationTableViewController.hidePostsImage
} else {
visibilityBarButtonItem.image = ConversationTableViewController.showPostsImage
}
}
} }

View File

@ -10,7 +10,7 @@ import UIKit
import Combine import Combine
import Pachyderm import Pachyderm
class ConversationMainStatusTableViewCell: UITableViewCell { class ConversationMainStatusTableViewCell: UITableViewCell, StatusCell {
static let dateFormatter: DateFormatter = { static let dateFormatter: DateFormatter = {
let formatter = DateFormatter() let formatter = DateFormatter()
@ -69,6 +69,8 @@ class ConversationMainStatusTableViewCell: UITableViewCell {
} }
var collapsed = false var collapsed = false
var showStatusAutomatically = false
var avatarURL: URL? var avatarURL: URL?
var statusUpdater: Cancellable? var statusUpdater: Cancellable?
@ -136,9 +138,15 @@ class ConversationMainStatusTableViewCell: UITableViewCell {
contentLabel.statusID = statusID contentLabel.statusID = statusID
collapsible = !status.spoilerText.isEmpty collapsible = !status.spoilerText.isEmpty
setCollapsed(collapsible, animated: false) var shouldCollapse = collapsible
contentWarningLabel.text = status.spoilerText contentWarningLabel.text = status.spoilerText
contentWarningLabel.isHidden = status.spoilerText.isEmpty contentWarningLabel.isHidden = status.spoilerText.isEmpty
if collapsible && showStatusAutomatically {
shouldCollapse = false
}
setCollapsed(shouldCollapse, animated: false)
} }
private func updateStatusState(status: Status) { private func updateStatusState(status: Status) {
@ -189,6 +197,7 @@ class ConversationMainStatusTableViewCell: UITableViewCell {
ImageCache.avatars.cancel(url) ImageCache.avatars.cancel(url)
} }
attachmentsView.subviews.forEach { $0.removeFromSuperview() } attachmentsView.subviews.forEach { $0.removeFromSuperview() }
showStatusAutomatically = false
} }
@objc func accountPressed() { @objc func accountPressed() {

View File

@ -0,0 +1,16 @@
//
// StatusCell.swift
// Tusker
//
// Created by Shadowfacts on 11/18/19.
// Copyright © 2019 Shadowfacts. All rights reserved.
//
import UIKit
protocol StatusCell {
var collapsible: Bool { get }
var showStatusAutomatically: Bool { get set }
func setCollapsed(_ collapsed: Bool, animated: Bool)
}

View File

@ -14,7 +14,7 @@ protocol StatusTableViewCellDelegate: TuskerNavigationDelegate {
func statusCollapsedStateChanged() func statusCollapsedStateChanged()
} }
class StatusTableViewCell: UITableViewCell { class StatusTableViewCell: UITableViewCell, StatusCell {
static let relativeDateFormatter: RelativeDateTimeFormatter = { static let relativeDateFormatter: RelativeDateTimeFormatter = {
let formatter = RelativeDateTimeFormatter() let formatter = RelativeDateTimeFormatter()
@ -68,6 +68,8 @@ class StatusTableViewCell: UITableViewCell {
} }
var collapsed = false var collapsed = false
var showStatusAutomatically = false
var avatarURL: URL? var avatarURL: URL?
var updateTimestampWorkItem: DispatchWorkItem? var updateTimestampWorkItem: DispatchWorkItem?
var attachmentDataTasks: [URLSessionDataTask] = [] var attachmentDataTasks: [URLSessionDataTask] = []
@ -149,17 +151,23 @@ class StatusTableViewCell: UITableViewCell {
contentLabel.statusID = status.id contentLabel.statusID = status.id
collapsible = !status.spoilerText.isEmpty collapsible = !status.spoilerText.isEmpty
setCollapsed(collapsible, animated: false) var shouldCollapse = collapsible
contentWarningLabel.text = status.spoilerText contentWarningLabel.text = status.spoilerText
contentWarningLabel.isHidden = status.spoilerText.isEmpty contentWarningLabel.isHidden = status.spoilerText.isEmpty
if !collapsed, if !shouldCollapse,
let text = contentLabel.text, let text = contentLabel.text,
text.count > 500 { text.count > 500 {
collapsible = true collapsible = true
setCollapsed(true, animated: false) shouldCollapse = true
} }
if collapsible && showStatusAutomatically {
shouldCollapse = false
}
setCollapsed(shouldCollapse, animated: false)
let pinned = status.pinned ?? false let pinned = status.pinned ?? false
pinImageView.isHidden = !(pinned && showPinned) pinImageView.isHidden = !(pinned && showPinned)
timestampLabel.isHidden = !pinImageView.isHidden timestampLabel.isHidden = !pinImageView.isHidden
@ -240,6 +248,7 @@ class StatusTableViewCell: UITableViewCell {
updateTimestampWorkItem?.cancel() updateTimestampWorkItem?.cancel()
updateTimestampWorkItem = nil updateTimestampWorkItem = nil
attachmentsView.attachmentViews.allObjects.forEach { $0.removeFromSuperview() } attachmentsView.attachmentViews.allObjects.forEach { $0.removeFromSuperview() }
showStatusAutomatically = false
showPinned = false showPinned = false
} }