Compare commits

..

No commits in common. "06442b5629a5d673f57c8f729effc8666c958962" and "24a1e7ceb99d4e9c0b47fe15f806d63d38bbdbb4" have entirely different histories.

15 changed files with 92 additions and 167 deletions

View File

@ -12,18 +12,12 @@ public class NotificationGroup {
public let notificationIDs: [String]
public let id: String
public let kind: Notification.Kind
public let statusState: StatusState?
init?(notifications: [Notification]) {
guard !notifications.isEmpty else { return nil }
self.notificationIDs = notifications.map { $0.id }
self.id = notifications.first!.id
self.kind = notifications.first!.kind
if kind == .mention {
self.statusState = .unknown
} else {
self.statusState = nil
}
}
public static func createGroups(notifications: [Notification], only allowedTypes: [Notification.Kind]) -> [NotificationGroup] {

View File

@ -1,40 +0,0 @@
//
// StatusState.swift
// Pachyderm
//
// Created by Shadowfacts on 11/24/19.
// Copyright © 2019 Shadowfacts. All rights reserved.
//
import Foundation
public class StatusState: Equatable, Hashable {
public var collapsible: Bool?
public var collapsed: Bool?
public var unknown: Bool {
collapsible == nil || collapsed == nil
}
public init(collapsible: Bool?, collapsed: Bool?) {
self.collapsible = collapsible
self.collapsed = collapsed
}
public func copy() -> StatusState {
return StatusState(collapsible: self.collapsible, collapsed: self.collapsed)
}
public func hash(into hasher: inout Hasher) {
hasher.combine(collapsible)
hasher.combine(collapsed)
}
public static var unknown: StatusState {
StatusState(collapsible: nil, collapsed: nil)
}
public static func == (lhs: StatusState, rhs: StatusState) -> Bool {
lhs.collapsible == rhs.collapsible && lhs.collapsed == rhs.collapsed
}
}

View File

@ -90,7 +90,6 @@
D6333B372137838300CE884A /* AttributedString+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B362137838300CE884A /* AttributedString+Helpers.swift */; };
D6333B772138D94E00CE884A /* ComposeMediaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B762138D94E00CE884A /* ComposeMediaView.swift */; };
D6333B792139AEFD00CE884A /* Date+TimeAgo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B782139AEFD00CE884A /* Date+TimeAgo.swift */; };
D63569E023908A8D003DD353 /* StatusState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60A4FFB238B726A008AC647 /* StatusState.swift */; };
D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63661BF2381C144004B9E16 /* PreferencesNavigationController.swift */; };
D640D76922BAF5E6004FBE69 /* DomainBlocks.plist in Resources */ = {isa = PBXBuildFile; fileRef = D640D76822BAF5E6004FBE69 /* DomainBlocks.plist */; };
D641C773213CAA25004B4513 /* NotificationsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D641C772213CAA25004B4513 /* NotificationsTableViewController.swift */; };
@ -286,7 +285,6 @@
04DACE8D212CC7CC009840C4 /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = "<group>"; };
04ED00B021481ED800567C53 /* SteppedProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SteppedProgressView.swift; sourceTree = "<group>"; };
D6028B9A2150811100F223B9 /* MastodonCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonCache.swift; sourceTree = "<group>"; };
D60A4FFB238B726A008AC647 /* StatusState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusState.swift; sourceTree = "<group>"; };
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>"; };
D60A548E21ED515800F1F87C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -1002,7 +1000,6 @@
D6A3BC7223218C6E00FD64D5 /* Utilities */ = {
isa = PBXGroup;
children = (
D60A4FFB238B726A008AC647 /* StatusState.swift */,
D6E6F26221603F8B006A8599 /* CharacterCounter.swift */,
D6A3BC7323218C6E00FD64D5 /* TimelineSegment.swift */,
D6A3BC7823218E9200FD64D5 /* NotificationGroup.swift */,
@ -1537,7 +1534,6 @@
D61099F5214568C300432DC2 /* Notification.swift in Sources */,
D61099EF214566C000432DC2 /* Instance.swift in Sources */,
D61099D22144B2E600432DC2 /* Body.swift in Sources */,
D63569E023908A8D003DD353 /* StatusState.swift in Sources */,
D6109A0121456B0800432DC2 /* Hashtag.swift in Sources */,
D61099FD21456A1D00432DC2 /* SearchResults.swift in Sources */,
D61099F12145686D00432DC2 /* List.swift in Sources */,

View File

@ -15,9 +15,8 @@ class ConversationTableViewController: EnhancedTableViewController {
static let showPostsImage = UIImage(systemName: "eye.fill")!
static let hidePostsImage = UIImage(systemName: "eye.slash.fill")!
let mainStatusID: String
let mainStatusState: StatusState
var statuses: [(id: String, state: StatusState)] = [] {
var mainStatusID: String!
var statusIDs: [String] = [] {
didSet {
DispatchQueue.main.async {
self.tableView.reloadData()
@ -28,9 +27,8 @@ class ConversationTableViewController: EnhancedTableViewController {
var showStatusesAutomatically = false
var visibilityBarButtonItem: UIBarButtonItem!
init(for mainStatusID: String, state: StatusState = .unknown) {
init(for mainStatusID: String) {
self.mainStatusID = mainStatusID
self.mainStatusState = state
super.init(style: .plain)
}
@ -53,9 +51,9 @@ class ConversationTableViewController: EnhancedTableViewController {
visibilityBarButtonItem = UIBarButtonItem(image: ConversationTableViewController.showPostsImage, style: .plain, target: self, action: #selector(toggleVisibilityButtonPressed))
navigationItem.rightBarButtonItem = visibilityBarButtonItem
statuses = [(mainStatusID, mainStatusState)]
guard let mainStatus = MastodonCache.status(for: mainStatusID) else { fatalError("Missing cached status \(mainStatusID)") }
statusIDs = [mainStatusID]
guard let mainStatus = MastodonCache.status(for: mainStatusID) else { fatalError("Missing cached status \(mainStatusID!)") }
let request = Status.getContext(mainStatus)
MastodonController.client.run(request) { response in
@ -63,8 +61,8 @@ class ConversationTableViewController: EnhancedTableViewController {
let parents = self.getDirectParents(of: mainStatus, from: context.ancestors)
MastodonCache.addAll(statuses: parents)
MastodonCache.addAll(statuses: context.descendants)
self.statuses = parents.map { ($0.id, .unknown) } + self.statuses + context.descendants.map { ($0.id, .unknown) }
let indexPath = IndexPath(row: parents.count, section: 0)
self.statusIDs = parents.map { $0.id } + [self.mainStatusID] + context.descendants.map { $0.id }
let indexPath = IndexPath(row: self.statusIDs.firstIndex(of: self.mainStatusID)!, section: 0)
DispatchQueue.main.async {
self.tableView.scrollToRow(at: indexPath, at: .middle, animated: false)
}
@ -91,30 +89,30 @@ class ConversationTableViewController: EnhancedTableViewController {
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return statuses.count
return statusIDs.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let (id, state) = statuses[indexPath.row]
let statusID = statusIDs[indexPath.row]
if id == mainStatusID {
if statusID == mainStatusID {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "mainStatusCell", for: indexPath) as? ConversationMainStatusTableViewCell else { fatalError() }
cell.selectionStyle = .none
cell.showStatusAutomatically = showStatusesAutomatically
cell.updateUI(statusID: id, state: state)
cell.updateUI(statusID: statusID)
cell.delegate = self
return cell
} else {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? TimelineStatusTableViewCell else { fatalError() }
cell.showStatusAutomatically = showStatusesAutomatically
cell.updateUI(statusID: id, state: state)
cell.updateUI(statusID: statusID)
cell.delegate = self
return cell
}
}
override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
let statusID = statuses[indexPath.row].id
let statusID = statusIDs[indexPath.row]
return statusID == mainStatusID ? nil : indexPath
}
@ -133,21 +131,14 @@ class ConversationTableViewController: EnhancedTableViewController {
@objc func toggleVisibilityButtonPressed() {
showStatusesAutomatically = !showStatusesAutomatically
for (_, state) in statuses where state.collapsible == true {
state.collapsed = !showStatusesAutomatically
}
for cell in tableView.visibleCells {
guard let cell = cell as? BaseStatusTableViewCell,
cell.collapsible else { continue }
cell.showStatusAutomatically = showStatusesAutomatically
cell.setCollapsed(!showStatusesAutomatically, animated: false)
}
statusCollapsedStateChanged()
// recalculate cell heights
tableView.beginUpdates()
tableView.endUpdates()
if showStatusesAutomatically {
visibilityBarButtonItem.image = ConversationTableViewController.hidePostsImage
} else {
@ -158,7 +149,7 @@ class ConversationTableViewController: EnhancedTableViewController {
}
extension ConversationTableViewController: StatusTableViewCellDelegate {
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
func statusCollapsedStateChanged() {
// causes the table view to recalculate the cell heights
tableView.beginUpdates()
tableView.endUpdates()
@ -168,7 +159,7 @@ extension ConversationTableViewController: StatusTableViewCellDelegate {
extension ConversationTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths {
guard let status = MastodonCache.status(for: statuses[indexPath.row].id) else { continue }
guard let status = MastodonCache.status(for: statusIDs[indexPath.row]) else { continue }
ImageCache.avatars.get(status.account.avatar, completion: nil)
for attachment in status.attachments {
ImageCache.attachments.get(attachment.url, completion: nil)
@ -178,7 +169,7 @@ extension ConversationTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths {
guard let status = MastodonCache.status(for: statuses[indexPath.row].id) else { continue }
guard let status = MastodonCache.status(for: statusIDs[indexPath.row]) else { continue }
ImageCache.avatars.cancel(status.account.avatar)
for attachment in status.attachments {
ImageCache.attachments.cancel(attachment.url)

View File

@ -71,6 +71,16 @@ class LargeImageViewController: UIViewController, UIScrollViewDelegate {
modalPresentationStyle = .fullScreen
}
// init(gifData: Data?, description: String?, sourceFrame: CGRect, sourceCornerRadius: CGFloat, router: AppRouter) {
// self.router = router
// self.gifData = gifData
// self.imageDescription = description
// self.originFrame = sourceFrame
// self.originCornerRadius = sourceCornerRadius
//
// super.init(nibName: "LargeImageViewController", bundle: nil)
// }
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@ -162,9 +172,9 @@ class LargeImageViewController: UIViewController, UIScrollViewDelegate {
let prevZoomScale = self.prevZoomScale ?? scrollView.minimumZoomScale
if scrollView.zoomScale <= scrollView.minimumZoomScale {
setControlsVisible(true, animated: true)
controlsVisible = true
} else if scrollView.zoomScale > prevZoomScale {
setControlsVisible(false, animated: true)
controlsVisible = false
}
self.prevZoomScale = scrollView.zoomScale
}

View File

@ -91,7 +91,7 @@ class NotificationsTableViewController: EnhancedTableViewController {
let cell = tableView.dequeueReusableCell(withIdentifier: statusCell, for: indexPath) as? TimelineStatusTableViewCell else {
fatalError()
}
cell.updateUI(statusID: notification.status!.id, state: group.statusState!)
cell.updateUI(statusID: notification.status!.id)
cell.delegate = self
return cell
@ -212,7 +212,7 @@ class NotificationsTableViewController: EnhancedTableViewController {
}
extension NotificationsTableViewController: StatusTableViewCellDelegate {
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
func statusCollapsedStateChanged() {
// causes the table view to recalculate the cell heights
tableView.beginUpdates()
tableView.endUpdates()

View File

@ -22,14 +22,14 @@ class ProfileTableViewController: EnhancedTableViewController {
}
}
var pinnedStatuses: [(id: String, state: StatusState)] = [] {
var pinnedStatusIDs: [String] = [] {
didSet {
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
var timelineSegments: [[(id: String, state: StatusState)]] = [] {
var timelineSegments: [TimelineSegment<Status>] = [] {
didSet {
DispatchQueue.main.async {
self.tableView.reloadData()
@ -109,14 +109,14 @@ class ProfileTableViewController: EnhancedTableViewController {
guard case let .success(statuses, _) = response else { fatalError() }
MastodonCache.addAll(statuses: statuses)
self.pinnedStatuses = statuses.map { ($0.id, .unknown) }
self.pinnedStatusIDs = statuses.map { $0.id }
}
getStatuses() { response in
guard case let .success(statuses, pagination) = response else { fatalError() }
MastodonCache.addAll(statuses: statuses)
self.timelineSegments.append(statuses.map { ($0.id, .unknown) })
self.timelineSegments.append(TimelineSegment(objects: statuses))
self.older = pagination?.older
self.newer = pagination?.newer
@ -150,7 +150,7 @@ class ProfileTableViewController: EnhancedTableViewController {
if section == 0 {
return accountID == nil || MastodonCache.account(for: accountID) == nil ? 0 : 1
} else if section == 1 {
return pinnedStatuses.count
return pinnedStatusIDs.count
} else {
return timelineSegments[section - 2].count
}
@ -166,15 +166,15 @@ class ProfileTableViewController: EnhancedTableViewController {
return cell
case 1:
guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? TimelineStatusTableViewCell else { fatalError() }
let (id, state) = pinnedStatuses[indexPath.row]
let statusID = pinnedStatusIDs[indexPath.row]
cell.showPinned = true
cell.updateUI(statusID: id, state: state)
cell.updateUI(statusID: statusID)
cell.delegate = self
return cell
default:
guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? TimelineStatusTableViewCell else { fatalError() }
let (id, state) = timelineSegments[indexPath.section - 2][indexPath.row]
cell.updateUI(statusID: id, state: state)
let statusID = timelineSegments[indexPath.section - 2][indexPath.row]
cell.updateUI(statusID: statusID)
cell.delegate = self
return cell
}
@ -188,7 +188,7 @@ class ProfileTableViewController: EnhancedTableViewController {
guard case let .success(newStatuses, pagination) = response else { fatalError() }
MastodonCache.addAll(statuses: newStatuses)
self.timelineSegments[indexPath.section - 2].append(contentsOf: newStatuses.map { ($0.id, .unknown) })
self.timelineSegments[indexPath.section - 2].append(objects: newStatuses)
self.older = pagination?.older
}
@ -214,7 +214,7 @@ class ProfileTableViewController: EnhancedTableViewController {
guard case let .success(newStatuses, pagination) = response else { fatalError() }
MastodonCache.addAll(statuses: newStatuses)
self.timelineSegments[0].insert(contentsOf: newStatuses.map { ($0.id, .unknown) }, at: 0)
self.timelineSegments[0].insertAtBeginning(objects: newStatuses)
self.newer = pagination?.newer
@ -231,7 +231,7 @@ class ProfileTableViewController: EnhancedTableViewController {
}
extension ProfileTableViewController: StatusTableViewCellDelegate {
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
func statusCollapsedStateChanged() {
// causes the table view to recalculate the cell heights
tableView.beginUpdates()
tableView.endUpdates()
@ -270,7 +270,7 @@ extension ProfileTableViewController: ProfileHeaderTableViewCellDelegate {
extension ProfileTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths where indexPath.section > 1 {
let statusID = timelineSegments[indexPath.section - 2][indexPath.row].id
let statusID = timelineSegments[indexPath.section - 2][indexPath.row]
guard let status = MastodonCache.status(for: statusID) else { continue }
ImageCache.avatars.get(status.account.avatar, completion: nil)
for attachment in status.attachments {
@ -281,7 +281,7 @@ extension ProfileTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths where indexPath.section > 1 {
let statusID = timelineSegments[indexPath.section - 2][indexPath.row].id
let statusID = timelineSegments[indexPath.section - 2][indexPath.row]
guard let status = MastodonCache.status(for: statusID) else { continue }
ImageCache.avatars.cancel(status.account.avatar)
for attachment in status.attachments {

View File

@ -54,9 +54,9 @@ class SearchTableViewController: EnhancedTableViewController {
cell.updateUI(hashtag: tag)
cell.delegate = self
return cell
case let .status(id, state):
case let .status(id):
let cell = tableView.dequeueReusableCell(withIdentifier: statusCell, for: indexPath) as! TimelineStatusTableViewCell
cell.updateUI(statusID: id, state: state)
cell.updateUI(statusID: id)
cell.delegate = self
return cell
}
@ -113,16 +113,16 @@ class SearchTableViewController: EnhancedTableViewController {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
if !results.accounts.isEmpty {
snapshot.appendSections([.accounts])
snapshot.appendItems(results.accounts.map { .account($0.id) }, toSection: .accounts)
snapshot.appendItems(results.accounts.map { Item.account($0.id) }, toSection: .accounts)
MastodonCache.addAll(accounts: results.accounts)
}
if !results.hashtags.isEmpty {
snapshot.appendSections([.hashtags])
snapshot.appendItems(results.hashtags.map { .hashtag($0) }, toSection: .hashtags)
snapshot.appendItems(results.hashtags.map { Item.hashtag($0) }, toSection: .hashtags)
}
if !results.statuses.isEmpty {
snapshot.appendSections([.statuses])
snapshot.appendItems(results.statuses.map { .status($0.id, .unknown) }, toSection: .statuses)
snapshot.appendItems(results.statuses.map { Item.status($0.id) }, toSection: .statuses)
MastodonCache.addAll(statuses: results.statuses)
MastodonCache.addAll(accounts: results.statuses.map { $0.account })
}
@ -152,7 +152,7 @@ extension SearchTableViewController {
enum Item: Hashable {
case account(String)
case hashtag(Hashtag)
case status(String, StatusState)
case status(String)
}
class DataSource: UITableViewDiffableDataSource<Section, Item> {
@ -176,7 +176,7 @@ extension SearchTableViewController: UISearchBarDelegate {
}
extension SearchTableViewController: StatusTableViewCellDelegate {
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
func statusCollapsedStateChanged() {
tableView.beginUpdates()
tableView.endUpdates()
}

View File

@ -16,7 +16,6 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
let actionType: ActionType
let statusID: String
var statusState: StatusState
var accountIDs: [String]? {
didSet {
tableView.reloadData()
@ -33,10 +32,9 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
- Parameter statusID The ID of the status to show.
- Parameter accountIDs The accounts that will be shown. If `nil` is passed, a request will be performed to load the accounts.
*/
init(actionType: ActionType, statusID: String, statusState: StatusState, accountIDs: [String]?) {
init(actionType: ActionType, statusID: String, accountIDs: [String]?) {
self.actionType = actionType
self.statusID = statusID
self.statusState = statusState
self.accountIDs = accountIDs
super.init(style: .grouped)
@ -111,7 +109,7 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
switch indexPath.section {
case 0:
guard let cell = tableView.dequeueReusableCell(withIdentifier: statusCell, for: indexPath) as? TimelineStatusTableViewCell else { fatalError() }
cell.updateUI(statusID: statusID, state: statusState)
cell.updateUI(statusID: statusID)
cell.delegate = self
return cell
case 1:
@ -137,7 +135,7 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
}
extension StatusActionAccountListTableViewController: StatusTableViewCellDelegate {
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
func statusCollapsedStateChanged() {
// causes the table view to recalculate the cell heights
tableView.beginUpdates()
tableView.endUpdates()

View File

@ -26,7 +26,7 @@ class TimelineTableViewController: EnhancedTableViewController {
var timeline: Timeline!
var timelineSegments: [[(id: String, state: StatusState)]] = [] {
var timelineSegments: [TimelineSegment<Status>] = [] {
didSet {
DispatchQueue.main.async {
self.tableView.reloadData()
@ -56,7 +56,7 @@ class TimelineTableViewController: EnhancedTableViewController {
}
func statusID(for indexPath: IndexPath) -> String {
return timelineSegments[indexPath.section][indexPath.row].id
return timelineSegments[indexPath.section][indexPath.row]
}
override func viewDidLoad() {
@ -74,7 +74,7 @@ class TimelineTableViewController: EnhancedTableViewController {
MastodonController.client.run(request) { response in
guard case let .success(statuses, pagination) = response else { fatalError() }
MastodonCache.addAll(statuses: statuses)
self.timelineSegments.insert(statuses.map { ($0.id, .unknown) }, at: 0)
self.timelineSegments.insert(TimelineSegment(objects: statuses), at: 0)
self.newer = pagination?.newer
self.older = pagination?.older
}
@ -94,8 +94,7 @@ class TimelineTableViewController: EnhancedTableViewController {
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? TimelineStatusTableViewCell else { fatalError() }
let (id, state) = timelineSegments[indexPath.section][indexPath.row]
cell.updateUI(statusID: id, state: state)
cell.updateUI(statusID: statusID(for: indexPath))
cell.delegate = self
return cell
@ -113,7 +112,7 @@ class TimelineTableViewController: EnhancedTableViewController {
guard case let .success(newStatuses, pagination) = response else { fatalError() }
self.older = pagination?.older
MastodonCache.addAll(statuses: newStatuses)
self.timelineSegments[self.timelineSegments.count - 1].append(contentsOf: newStatuses.map { ($0.id, .unknown) })
self.timelineSegments[self.timelineSegments.count - 1].append(objects: newStatuses)
}
}
}
@ -138,7 +137,7 @@ class TimelineTableViewController: EnhancedTableViewController {
guard case let .success(newStatuses, pagination) = response else { fatalError() }
self.newer = pagination?.newer
MastodonCache.addAll(statuses: newStatuses)
self.timelineSegments[0].insert(contentsOf: newStatuses.map { ($0.id, .unknown) }, at: 0)
self.timelineSegments[0].insertAtBeginning(objects: newStatuses)
DispatchQueue.main.async {
self.refreshControl?.endRefreshing()
@ -155,7 +154,7 @@ class TimelineTableViewController: EnhancedTableViewController {
}
extension TimelineTableViewController: StatusTableViewCellDelegate {
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
func statusCollapsedStateChanged() {
// causes the table view to recalculate the cell heights
tableView.beginUpdates()
tableView.endUpdates()

View File

@ -24,8 +24,6 @@ protocol TuskerNavigationDelegate {
func selected(status statusID: String)
func selected(status statusID: String, state: StatusState)
func compose()
func reply(to statusID: String)
@ -48,7 +46,7 @@ protocol TuskerNavigationDelegate {
func showFollowedByList(accountIDs: [String])
func statusActionAccountList(action: StatusActionAccountListTableViewController.ActionType, statusID: String, statusState state: StatusState, accountIDs: [String]?) -> StatusActionAccountListTableViewController
func statusActionAccountList(action: StatusActionAccountListTableViewController.ActionType, statusID: String, accountIDs: [String]?) -> StatusActionAccountListTableViewController
}
extension TuskerNavigationDelegate where Self: UIViewController {
@ -98,18 +96,13 @@ extension TuskerNavigationDelegate where Self: UIViewController {
}
func selected(status statusID: String) {
self.selected(status: statusID, state: .unknown)
}
func selected(status statusID: String, state: StatusState) {
// todo: is this necessary? should the conversation main status cell prevent this
// don't open if the conversation is the same as the current one
if let conversationController = self as? ConversationTableViewController,
conversationController.mainStatusID == statusID {
return
}
show(ConversationTableViewController(for: statusID, state: state), sender: self)
show(ConversationTableViewController(for: statusID), sender: self)
}
func compose() {
@ -202,8 +195,8 @@ extension TuskerNavigationDelegate where Self: UIViewController {
show(vc, sender: self)
}
func statusActionAccountList(action: StatusActionAccountListTableViewController.ActionType, statusID: String, statusState state: StatusState, accountIDs: [String]?) -> StatusActionAccountListTableViewController {
return StatusActionAccountListTableViewController(actionType: action, statusID: statusID, statusState: state, accountIDs: accountIDs)
func statusActionAccountList(action: StatusActionAccountListTableViewController.ActionType, statusID: String, accountIDs: [String]?) -> StatusActionAccountListTableViewController {
return StatusActionAccountListTableViewController(actionType: action, statusID: statusID, accountIDs: accountIDs)
}
}

View File

@ -165,7 +165,7 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
default:
fatalError()
}
let vc = delegate.statusActionAccountList(action: action, statusID: statusID, statusState: .unknown, accountIDs: accountIDs)
let vc = delegate.statusActionAccountList(action: action, statusID: statusID, accountIDs: accountIDs)
delegate.show(vc)
}
}
@ -187,7 +187,7 @@ extension ActionNotificationGroupTableViewCell: MenuPreviewProvider {
default:
fatalError()
}
return self.delegate?.statusActionAccountList(action: action, statusID: self.statusID, statusState: .unknown, accountIDs: accountIDs)
return self.delegate?.statusActionAccountList(action: action, statusID: self.statusID, accountIDs: accountIDs)
}, actions: {
return []
})

View File

@ -11,7 +11,7 @@ import Pachyderm
import Combine
protocol StatusTableViewCellDelegate: TuskerNavigationDelegate {
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell)
func statusCollapsedStateChanged()
}
class BaseStatusTableViewCell: UITableViewCell {
@ -48,18 +48,12 @@ class BaseStatusTableViewCell: UITableViewCell {
}
}
var statusState: StatusState!
var collapsible = false {
didSet {
collapseButton.isHidden = !collapsible
statusState?.collapsible = collapsible
}
}
var collapsed = false {
didSet {
statusState?.collapsed = collapsed
}
}
var collapsed = false
var showStatusAutomatically = false
var avatarURL: URL?
@ -105,12 +99,11 @@ class BaseStatusTableViewCell: UITableViewCell {
.sink(receiveValue: updateUI(account:))
}
func updateUI(statusID: String, state: StatusState) {
func updateUI(statusID: String) {
guard let status = MastodonCache.status(for: statusID) else {
fatalError("Missing cached status")
}
self.statusID = statusID
self.statusState = state
let account = status.account
self.accountID = account.id
@ -126,29 +119,20 @@ class BaseStatusTableViewCell: UITableViewCell {
contentLabel.statusID = statusID
collapsible = !status.spoilerText.isEmpty
var shouldCollapse = collapsible
contentWarningLabel.text = status.spoilerText
contentWarningLabel.isHidden = status.spoilerText.isEmpty
if state.unknown {
collapsible = !status.spoilerText.isEmpty
var shouldCollapse = collapsible
if !shouldCollapse,
let text = contentLabel.text,
text.count > 500 {
collapsible = true
shouldCollapse = true
}
if collapsible && showStatusAutomatically {
shouldCollapse = false
}
setCollapsed(shouldCollapse, animated: false)
state.collapsible = collapsible
state.collapsed = shouldCollapse
} else {
collapsible = state.collapsible!
setCollapsed(state.collapsed!, animated: false)
if !shouldCollapse,
let text = contentLabel.text,
text.count > 500 {
collapsible = true
shouldCollapse = true
}
if collapsible && showStatusAutomatically {
shouldCollapse = false
}
setCollapsed(shouldCollapse, animated: false)
}
func updateStatusState(status: Status) {
@ -198,7 +182,7 @@ class BaseStatusTableViewCell: UITableViewCell {
@IBAction func collapseButtonPressed() {
setCollapsed(!collapsed, animated: true)
delegate?.statusCellCollapsedStateChanged(self)
delegate?.statusCollapsedStateChanged()
}
func setCollapsed(_ collapsed: Bool, animated: Bool) {

View File

@ -36,8 +36,8 @@ class ConversationMainStatusTableViewCell: BaseStatusTableViewCell {
accessibilityElements = [profileAccessibilityElement!, contentWarningLabel!, collapseButton!, contentLabel!, totalFavoritesButton!, totalReblogsButton!, timestampAndClientLabel!, replyButton!, favoriteButton!, reblogButton!, moreButton!]
}
override func updateUI(statusID: String, state: StatusState) {
super.updateUI(statusID: statusID, state: state)
override func updateUI(statusID: String) {
super.updateUI(statusID: statusID)
guard let status = MastodonCache.status(for: statusID) else { fatalError() }
var timestampAndClientText = ConversationMainStatusTableViewCell.dateFormatter.string(from: status.createdAt)
@ -70,7 +70,7 @@ class ConversationMainStatusTableViewCell: BaseStatusTableViewCell {
@IBAction func totalFavoritesPressed() {
if let delegate = delegate {
// accounts aren't known, pass nil so the VC will load them
let vc = delegate.statusActionAccountList(action: .favorite, statusID: statusID, statusState: statusState.copy(), accountIDs: nil)
let vc = delegate.statusActionAccountList(action: .favorite, statusID: statusID, accountIDs: nil)
vc.showInacurateCountWarning = true
delegate.show(vc)
}
@ -79,7 +79,7 @@ class ConversationMainStatusTableViewCell: BaseStatusTableViewCell {
@IBAction func totalReblogsPressed() {
if let delegate = delegate {
// accounts aren't known, pass nil so the VC will load them
let vc = delegate.statusActionAccountList(action: .reblog, statusID: statusID, statusState: statusState.copy(), accountIDs: nil)
let vc = delegate.statusActionAccountList(action: .reblog, statusID: statusID, accountIDs: nil)
vc.showInacurateCountWarning = true
delegate.show(vc)
}

View File

@ -48,7 +48,7 @@ class TimelineStatusTableViewCell: BaseStatusTableViewCell {
.sink(receiveValue: updateRebloggerLabel(reblogger:))
}
override func updateUI(statusID: String, state: StatusState) {
override func updateUI(statusID: String) {
guard var status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID)") }
let realStatusID: String
@ -66,7 +66,7 @@ class TimelineStatusTableViewCell: BaseStatusTableViewCell {
realStatusID = statusID
}
super.updateUI(statusID: realStatusID, state: state)
super.updateUI(statusID: realStatusID)
updateTimestamp()
@ -123,7 +123,7 @@ class TimelineStatusTableViewCell: BaseStatusTableViewCell {
super.setSelected(selected, animated: animated)
if selected {
delegate?.selected(status: statusID, state: statusState.copy())
delegate?.selected(status: statusID)
}
}
@ -134,7 +134,7 @@ class TimelineStatusTableViewCell: BaseStatusTableViewCell {
override func getStatusCellPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> BaseStatusTableViewCell.PreviewProviders? {
return (
content: { ConversationTableViewController(for: self.statusID, state: self.statusState.copy()) },
content: { ConversationTableViewController(for: self.statusID) },
actions: { self.actionsForStatus(statusID: self.statusID) }
)
}