From 4a95ccccdb8e1cbbc6e4b67d47f80dc69d1b0742 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Tue, 10 May 2022 23:37:05 -0400 Subject: [PATCH] Show expand thread indicator when there are additional replies to an intermediate post in thread authored by a single person --- .../ConversationTableViewController.swift | 17 ++++---- .../ExpandThreadTableViewCell.swift | 41 +++++++++++++------ .../ExpandThreadTableViewCell.xib | 5 ++- Tusker/en.lproj/Localizable.stringsdict | 16 ++++++++ 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/Tusker/Screens/Conversation/ConversationTableViewController.swift b/Tusker/Screens/Conversation/ConversationTableViewController.swift index 7755837b..fad765e3 100644 --- a/Tusker/Screens/Conversation/ConversationTableViewController.swift +++ b/Tusker/Screens/Conversation/ConversationTableViewController.swift @@ -115,9 +115,9 @@ class ConversationTableViewController: EnhancedTableViewController { return cell - case let .expandThread(childThreads: childThreads): + case let .expandThread(childThreads: childThreads, inline: inline): let cell = tableView.dequeueReusableCell(withIdentifier: "expandThreadCell", for: indexPath) as! ExpandThreadTableViewCell - cell.updateUI(childThreads: childThreads) + cell.updateUI(childThreads: childThreads, inline: inline) return cell } }) @@ -314,8 +314,10 @@ class ConversationTableViewController: EnhancedTableViewController { let sameAuthorStatuses = currentNode.children.filter({ $0.status.account.id == node.status.account.id }) if sameAuthorStatuses.count == 1 { next = sameAuthorStatuses[0] + let nonSameAuthorChildren = currentNode.children.filter { $0.status.id != sameAuthorStatuses[0].status.id } + snapshot.appendItems([.expandThread(childThreads: nonSameAuthorChildren, inline: true)]) } else { - snapshot.appendItems([.expandThread(childThreads: currentNode.children)]) + snapshot.appendItems([.expandThread(childThreads: currentNode.children, inline: false)]) break } } @@ -399,14 +401,14 @@ extension ConversationTableViewController { } enum Item: Hashable { case status(id: String, state: StatusState) - case expandThread(childThreads: [ConversationNode]) + case expandThread(childThreads: [ConversationNode], inline: Bool) static func == (lhs: Item, rhs: Item) -> Bool { switch (lhs, rhs) { case let (.status(id: a, state: _), .status(id: b, state: _)): return a == b - case let (.expandThread(childThreads: a), .expandThread(childThreads: b)): - return zip(a, b).allSatisfy { $0.status.id == $1.status.id } + case let (.expandThread(childThreads: a, inline: aInline), .expandThread(childThreads: b, inline: bInline)): + return zip(a, b).allSatisfy { $0.status.id == $1.status.id } && aInline == bInline default: return false } @@ -417,9 +419,10 @@ extension ConversationTableViewController { case let .status(id: id, state: _): hasher.combine("status") hasher.combine(id) - case let .expandThread(childThreads: children): + case let .expandThread(childThreads: children, inline: inline): hasher.combine("expandThread") hasher.combine(children.map(\.status.id)) + hasher.combine(inline) } } } diff --git a/Tusker/Screens/Conversation/ExpandThreadTableViewCell.swift b/Tusker/Screens/Conversation/ExpandThreadTableViewCell.swift index e3d44ba7..dac30d91 100644 --- a/Tusker/Screens/Conversation/ExpandThreadTableViewCell.swift +++ b/Tusker/Screens/Conversation/ExpandThreadTableViewCell.swift @@ -10,34 +10,49 @@ import UIKit class ExpandThreadTableViewCell: UITableViewCell { + @IBOutlet weak var stackViewLeadingConstraint: NSLayoutConstraint! @IBOutlet weak var avatarContainerView: UIView! @IBOutlet weak var avatarContainerWidthConstraint: NSLayoutConstraint! @IBOutlet weak var replyCountLabel: UILabel! - var avatarImageViews: [UIImageView] = [] + private var threadLinkView: UIView! + private var threadLinkViewFullHeightConstraint: NSLayoutConstraint! + private var threadLinkViewShortHeightConstraint: NSLayoutConstraint! + private var avatarImageViews: [UIImageView] = [] private var avatarRequests: [ImageCache.Request] = [] override func awakeFromNib() { super.awakeFromNib() - let prevThreadLinkView = UIView() - prevThreadLinkView.translatesAutoresizingMaskIntoConstraints = false - prevThreadLinkView.backgroundColor = tintColor.withAlphaComponent(0.5) - prevThreadLinkView.layer.cornerRadius = 2.5 - prevThreadLinkView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner] - contentView.addSubview(prevThreadLinkView) + threadLinkView = UIView() + threadLinkView.translatesAutoresizingMaskIntoConstraints = false + threadLinkView.backgroundColor = tintColor.withAlphaComponent(0.5) + threadLinkView.layer.cornerRadius = 2.5 + addSubview(threadLinkView) + threadLinkViewFullHeightConstraint = threadLinkView.bottomAnchor.constraint(equalTo: bottomAnchor) + threadLinkViewShortHeightConstraint = threadLinkView.bottomAnchor.constraint(equalTo: avatarContainerView.topAnchor, constant: -2) NSLayoutConstraint.activate([ - prevThreadLinkView.widthAnchor.constraint(equalToConstant: 5), - prevThreadLinkView.centerXAnchor.constraint(equalTo: leadingAnchor, constant: 16 + 25), - prevThreadLinkView.topAnchor.constraint(equalTo: topAnchor), - prevThreadLinkView.bottomAnchor.constraint(equalTo: avatarContainerView.topAnchor, constant: -2), + threadLinkView.widthAnchor.constraint(equalToConstant: 5), + threadLinkView.centerXAnchor.constraint(equalTo: leadingAnchor, constant: 25 + 16 /* system spacing */), + threadLinkView.topAnchor.constraint(equalTo: topAnchor), + threadLinkViewFullHeightConstraint, ]) NotificationCenter.default.addObserver(self, selector: #selector(preferencesChanged), name: .preferencesChanged, object: nil) } - func updateUI(childThreads: [ConversationNode]) { - let format = NSLocalizedString("expand threads count", comment: "expand conversation threads button label") + func updateUI(childThreads: [ConversationNode], inline: Bool) { + stackViewLeadingConstraint.constant = inline ? 50 + 4 : 0 + threadLinkView.layer.maskedCorners = inline ? [] : [.layerMinXMaxYCorner, .layerMaxXMaxYCorner] + threadLinkViewFullHeightConstraint.isActive = inline + threadLinkViewShortHeightConstraint.isActive = !inline + + let format: String + if inline { + format = NSLocalizedString("expand threads inline count", comment: "expnad converstaion threads inline button label") + } else { + format = NSLocalizedString("expand threads count", comment: "expand conversation threads button label") + } replyCountLabel.text = String.localizedStringWithFormat(format, childThreads.count) let accounts = childThreads.map(\.status.account).uniques().prefix(3) diff --git a/Tusker/Screens/Conversation/ExpandThreadTableViewCell.xib b/Tusker/Screens/Conversation/ExpandThreadTableViewCell.xib index bb5d64d6..f84d4513 100644 --- a/Tusker/Screens/Conversation/ExpandThreadTableViewCell.xib +++ b/Tusker/Screens/Conversation/ExpandThreadTableViewCell.xib @@ -1,9 +1,9 @@ - + - + @@ -62,6 +62,7 @@ + diff --git a/Tusker/en.lproj/Localizable.stringsdict b/Tusker/en.lproj/Localizable.stringsdict index d00bd7f7..094e4474 100644 --- a/Tusker/en.lproj/Localizable.stringsdict +++ b/Tusker/en.lproj/Localizable.stringsdict @@ -61,6 +61,22 @@ %u replies + expand threads inline count + + NSStringLocalizedFormatKey + %#@replies@ + replies + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + u + one + 1 more reply + other + %u more replies + + favorites count NSStringLocalizedFormatKey