Compare commits

..

No commits in common. "8deb502140edbe738f86235f323d80dbb92869f6" and "71fa3910a162d0da4fcabdb3d066148c09803b40" have entirely different histories.

9 changed files with 26 additions and 150 deletions

View File

@ -222,7 +222,6 @@
D690797324A4EF9700023A34 /* UIBezierPath+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D690797224A4EF9700023A34 /* UIBezierPath+Helpers.swift */; };
D691771129A2B76A0054D7EF /* MainActor+Unsafe.swift in Sources */ = {isa = PBXBuildFile; fileRef = D691771029A2B76A0054D7EF /* MainActor+Unsafe.swift */; };
D691771529A6FCAB0054D7EF /* StateRestorableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D691771429A6FCAB0054D7EF /* StateRestorableViewController.swift */; };
D691771729A710520054D7EF /* ProfileNoContentCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D691771629A710520054D7EF /* ProfileNoContentCollectionViewCell.swift */; };
D693A72825CF282E003A14E2 /* TrendingHashtagsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D693A72725CF282E003A14E2 /* TrendingHashtagsViewController.swift */; };
D693A72A25CF8C1E003A14E2 /* ProfileDirectoryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D693A72925CF8C1E003A14E2 /* ProfileDirectoryViewController.swift */; };
D693A72F25CF91C6003A14E2 /* FeaturedProfileCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D693A72D25CF91C6003A14E2 /* FeaturedProfileCollectionViewCell.swift */; };
@ -640,7 +639,6 @@
D690797224A4EF9700023A34 /* UIBezierPath+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIBezierPath+Helpers.swift"; sourceTree = "<group>"; };
D691771029A2B76A0054D7EF /* MainActor+Unsafe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainActor+Unsafe.swift"; sourceTree = "<group>"; };
D691771429A6FCAB0054D7EF /* StateRestorableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRestorableViewController.swift; sourceTree = "<group>"; };
D691771629A710520054D7EF /* ProfileNoContentCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileNoContentCollectionViewCell.swift; sourceTree = "<group>"; };
D693A72725CF282E003A14E2 /* TrendingHashtagsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingHashtagsViewController.swift; sourceTree = "<group>"; };
D693A72925CF8C1E003A14E2 /* ProfileDirectoryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileDirectoryViewController.swift; sourceTree = "<group>"; };
D693A72D25CF91C6003A14E2 /* FeaturedProfileCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeaturedProfileCollectionViewCell.swift; sourceTree = "<group>"; };
@ -1098,7 +1096,6 @@
D61DC84C28F500D200B82C6E /* ProfileViewController.swift */,
D61ABEF728EFC3F900B29151 /* ProfileStatusesViewController.swift */,
D61DC84A28F4FD2000B82C6E /* ProfileHeaderCollectionViewCell.swift */,
D691771629A710520054D7EF /* ProfileNoContentCollectionViewCell.swift */,
);
path = Profile;
sourceTree = "<group>";
@ -1972,7 +1969,6 @@
0427033A22B31269000D31B6 /* AdvancedPrefsView.swift in Sources */,
D6C3F4F5298ED0890009FCFF /* LocalPredicateStatusesViewController.swift in Sources */,
D662AEEF263A3B880082A153 /* PollFinishedTableViewCell.swift in Sources */,
D691771729A710520054D7EF /* ProfileNoContentCollectionViewCell.swift in Sources */,
D626493C23C1000300612E6E /* AlbumTableViewCell.swift in Sources */,
D62275A624F1C81800B82A16 /* ComposeReplyView.swift in Sources */,
D60E2F292442372B005F8713 /* AccountMO.swift in Sources */,

View File

@ -9,9 +9,8 @@
import UIKit
import Pachyderm
class ConversationCollectionViewController: UIViewController, CollectionViewController, RefreshableViewController {
class ConversationCollectionViewController: UIViewController, CollectionViewController {
private unowned let conversationViewController: ConversationViewController
private let mastodonController: MastodonController
private let mainStatusID: String
private let mainStatusState: CollapseState
@ -23,12 +22,11 @@ class ConversationCollectionViewController: UIViewController, CollectionViewCont
}
private var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
init(for mainStatusID: String, state: CollapseState, conversationViewController: ConversationViewController) {
init(for mainStatusID: String, state: CollapseState, mastodonController: MastodonController) {
self.mainStatusID = mainStatusID
self.mainStatusState = state
self.statusIDToScrollToOnLoad = mainStatusID
self.conversationViewController = conversationViewController
self.mastodonController = conversationViewController.mastodonController
self.mastodonController = mastodonController
super.init(nibName: nil, bundle: nil)
}
@ -70,11 +68,6 @@ class ConversationCollectionViewController: UIViewController, CollectionViewCont
collectionView.dragDelegate = self
collectionView.allowsFocus = true
#if !targetEnvironment(macCatalyst)
collectionView.refreshControl = UIRefreshControl()
collectionView.refreshControl!.addTarget(self, action: #selector(refresh), for: .valueChanged)
#endif
dataSource = createDataSource()
}
@ -139,10 +132,9 @@ class ConversationCollectionViewController: UIViewController, CollectionViewCont
}
func addTree(_ tree: ConversationTree, mainStatus: StatusMO) {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.ancestors, .mainStatus])
var snapshot = dataSource.snapshot()
snapshot.deleteItems([.loadingIndicator])
let mainStatusItem = Item.status(id: mainStatusID, node: tree.mainStatus, state: mainStatusState, prevLink: mainStatus.inReplyToID != nil, nextLink: false)
snapshot.appendItems([mainStatusItem], toSection: .mainStatus)
let parentItems = tree.ancestors.enumerated().map { index, node in
Item.status(id: node.status.id, node: node, state: .unknown, prevLink: index > 0, nextLink: true)
}
@ -248,15 +240,6 @@ class ConversationCollectionViewController: UIViewController, CollectionViewCont
}
}
@objc func refresh() {
Task {
await conversationViewController.refreshContext()
#if !targetEnvironment(macCatalyst)
self.collectionView.refreshControl!.endRefreshing()
#endif
}
}
}
extension ConversationCollectionViewController {

View File

@ -227,7 +227,7 @@ class ConversationViewController: UIViewController {
}
private func mainStatusLoaded(_ mainStatus: StatusMO) {
let vc = ConversationCollectionViewController(for: mainStatus.id, state: mainStatusState, conversationViewController: self)
let vc = ConversationCollectionViewController(for: mainStatus.id, state: mainStatusState, mastodonController: mastodonController)
vc.statusIDToScrollToOnLoad = statusIDToScrollToOnLoad ?? mainStatus.id
vc.showStatusesAutomatically = showStatusesAutomatically
vc.addMainStatus(mainStatus)
@ -290,15 +290,6 @@ class ConversationViewController: UIViewController {
}
}
func refreshContext() async {
guard case .localID(let id) = mode,
let status = mastodonController.persistentContainer.status(for: id),
case .displaying(_) = state else {
return
}
await loadTree(for: status)
}
private func showMainStatusNotFound() {
let notFoundView = StatusNotFoundView(frame: .zero)
notFoundView.translatesAutoresizingMaskIntoConstraints = false

View File

@ -1,81 +0,0 @@
//
// ProfileNoContentCollectionViewCell.swift
// Tusker
//
// Created by Shadowfacts on 2/22/23.
// Copyright © 2023 Shadowfacts. All rights reserved.
//
import UIKit
class ProfileNoContentCollectionViewCell: UICollectionViewListCell {
weak var delegate: TuskerNavigationDelegate?
private var accountURL: URL?
private var button: UIButton!
override init(frame: CGRect) {
super.init(frame: frame)
let title = UILabel()
title.text = "There's nothing here"
title.adjustsFontForContentSizeCategory = true
title.font = .preferredFont(forTextStyle: .headline)
title.numberOfLines = 0
title.textAlignment = .center
title.textColor = .secondaryLabel
let body = UILabel()
body.text = "Your instance may not show all of the posts from accounts on other instances."
body.adjustsFontForContentSizeCategory = true
body.font = .preferredFont(forTextStyle: .body)
body.numberOfLines = 0
body.textAlignment = .center
body.textColor = .secondaryLabel
button = UIButton(configuration: .plain(), primaryAction: UIAction(handler: { [unowned self] _ in
if let delegate = self.delegate,
let accountURL = self.accountURL {
delegate.selected(url: accountURL)
}
}))
let stack = UIStackView(arrangedSubviews: [
title,
body,
button,
])
stack.axis = .vertical
stack.alignment = .center
stack.spacing = 4
stack.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(stack)
NSLayoutConstraint.activate([
stack.leadingAnchor.constraint(equalToSystemSpacingAfter: contentView.leadingAnchor, multiplier: 1),
contentView.trailingAnchor.constraint(equalToSystemSpacingAfter: stack.trailingAnchor, multiplier: 1),
stack.topAnchor.constraint(equalToSystemSpacingBelow: contentView.topAnchor, multiplier: 1),
contentView.bottomAnchor.constraint(equalToSystemSpacingBelow: stack.bottomAnchor, multiplier: 1),
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateUI(accountURL: URL) {
self.accountURL = accountURL
var title: AttributedString = "View on "
var host = AttributedString(accountURL.host!)
host.font = .preferredFont(forTextStyle: .body).withTraits(.traitBold)
title += host
var config = UIButton.Configuration.plain()
config.attributedTitle = title
config.image = UIImage(systemName: "safari")
config.imagePadding = 4
button.configuration = config
}
}

View File

@ -159,10 +159,6 @@ class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionVie
}
let zeroHeightCell = UICollectionView.CellRegistration<ZeroHeightCollectionViewCell, Void> { _, _, _ in
}
let noContentCell = UICollectionView.CellRegistration<ProfileNoContentCollectionViewCell, URL> { [unowned self] cell, _, item in
cell.delegate = self
cell.updateUI(accountURL: item)
}
return UICollectionViewDiffableDataSource(collectionView: collectionView) { [unowned self] collectionView, indexPath, itemIdentifier in
switch itemIdentifier {
case .header(let id):
@ -201,8 +197,6 @@ class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionVie
return loadingIndicatorCell(for: indexPath)
case .confirmLoadMore:
return confirmLoadMoreCell(for: indexPath)
case .noContent(let accountURL):
return collectionView.dequeueConfiguredReusableCell(using: noContentCell, for: indexPath, item: accountURL)
}
}
}
@ -231,7 +225,7 @@ class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionVie
guard isViewLoaded,
let accountID,
state == .unloaded,
let account = mastodonController.persistentContainer.account(for: accountID) else {
mastodonController.persistentContainer.account(for: accountID) != nil else {
return
}
@ -252,14 +246,6 @@ class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionVie
await controller.loadInitial()
await tryLoadPinned()
var newSnapshot = dataSource.snapshot()
if newSnapshot.numberOfItems(inSection: .pinned) == 0,
newSnapshot.numberOfItems(inSection: .statuses) == 0,
account.url.host != mastodonController.instanceURL.host {
newSnapshot.appendItems([.noContent(accountURL: account.url)], toSection: .pinned)
await apply(newSnapshot, animatingDifferences: true)
}
state = .loaded
// remove any content inset that was added when switching pages to this VC
@ -424,7 +410,6 @@ extension ProfileStatusesViewController {
case status(id: String, collapseState: CollapseState, filterState: FilterState, pinned: Bool)
case loadingIndicator
case confirmLoadMore
case noContent(accountURL: URL)
static func fromTimelineItem(_ item: String) -> Self {
return .status(id: item, collapseState: .unknown, filterState: .unknown, pinned: false)
@ -440,8 +425,6 @@ extension ProfileStatusesViewController {
return true
case (.confirmLoadMore, .confirmLoadMore):
return true
case (.noContent(let a), .noContent(let b)):
return a == b
default:
return false
}
@ -460,15 +443,12 @@ extension ProfileStatusesViewController {
hasher.combine(2)
case .confirmLoadMore:
hasher.combine(3)
case .noContent(let accountURL):
hasher.combine(4)
hasher.combine(accountURL)
}
}
var hideSeparators: Bool {
switch self {
case .loadingIndicator, .confirmLoadMore, .noContent(_):
case .loadingIndicator, .confirmLoadMore:
return true
default:
return false

View File

@ -17,7 +17,8 @@ class StatusActionAccountListCollectionViewController: UIViewController, Collect
private let actionType: StatusActionAccountListViewController.ActionType
private let mastodonController: MastodonController
private var needsInaccurateCountWarning = false
/// If `true`, a warning will be shown below the account list describing that the total favs/reblogs may be innacurate.
var showInacurateCountWarning = false
var collectionView: UICollectionView! {
view as? UICollectionView
@ -63,7 +64,7 @@ class StatusActionAccountListCollectionViewController: UIViewController, Collect
switch dataSource.sectionIdentifier(for: sectionIndex)! {
case .status:
var config = UICollectionLayoutListConfiguration(appearance: .grouped)
config.footerMode = self.needsInaccurateCountWarning ? .supplementary : .none
config.footerMode = self.showInacurateCountWarning ? .supplementary : .none
config.backgroundColor = .appGroupedBackground
config.leadingSwipeActionsConfigurationProvider = { [unowned self] in
(collectionView.cellForItem(at: $0) as? TimelineStatusCollectionViewCell)?.leadingSwipeActions()
@ -148,11 +149,9 @@ class StatusActionAccountListCollectionViewController: UIViewController, Collect
}
}
func addStatus(_ status: StatusMO, state: CollapseState, showInaccurateCountWarning: Bool) {
func addStatus(_ status: StatusMO, state: CollapseState) {
loadViewIfNeeded()
needsInaccurateCountWarning = showInaccurateCountWarning && status.url?.host != mastodonController.instanceURL.host
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.status, .accounts])
snapshot.appendItems([.status(status.id, state)], toSection: .status)

View File

@ -18,7 +18,13 @@ class StatusActionAccountListViewController: UIViewController {
private var accountIDs: [String]?
/// If `true`, a warning will be shown below the account list describing that the total favs/reblogs may be innacurate.
var showInaccurateCountWarning = false
var showInacurateCountWarning = false {
didSet {
if case .displaying(let vc) = state {
vc.showInacurateCountWarning = showInacurateCountWarning
}
}
}
private var state: State = .unloaded {
didSet {
@ -141,7 +147,8 @@ class StatusActionAccountListViewController: UIViewController {
private func statusLoaded(_ status: StatusMO) async {
let vc = StatusActionAccountListCollectionViewController(statusID: statusID, actionType: actionType, mastodonController: mastodonController)
vc.addStatus(status, state: statusState, showInaccurateCountWarning: showInaccurateCountWarning)
vc.addStatus(status, state: statusState)
vc.showInacurateCountWarning = showInacurateCountWarning
if let accountIDs {
vc.setAccounts(accountIDs, animated: false)
}

View File

@ -274,7 +274,7 @@ extension ActionNotificationGroupTableViewCell: SelectableTableViewCell {
fatalError()
}
let vc = StatusActionAccountListViewController(actionType: action, statusID: statusID, statusState: .unknown, accountIDs: accountIDs, mastodonController: mastodonController)
vc.showInaccurateCountWarning = false
vc.showInacurateCountWarning = false
delegate.show(vc)
}
}
@ -294,7 +294,7 @@ extension ActionNotificationGroupTableViewCell: MenuPreviewProvider {
fatalError()
}
let vc = StatusActionAccountListViewController(actionType: action, statusID: self.statusID, statusState: .unknown, accountIDs: accountIDs, mastodonController: self.mastodonController)
vc.showInaccurateCountWarning = false
vc.showInacurateCountWarning = false
return vc
}, actions: {
return []

View File

@ -417,7 +417,8 @@ class ConversationMainStatusCollectionViewCell: UICollectionViewListCell, Status
return
}
let vc = StatusActionAccountListViewController(actionType: .favorite, statusID: statusID, statusState: statusState.copy(), accountIDs: nil, mastodonController: mastodonController)
vc.showInaccurateCountWarning = true
// TODO: only show warning if the instance isn't the logged in one
vc.showInacurateCountWarning = true
delegate.show(vc)
}
@ -426,7 +427,7 @@ class ConversationMainStatusCollectionViewCell: UICollectionViewListCell, Status
return
}
let vc = StatusActionAccountListViewController(actionType: .reblog, statusID: statusID, statusState: statusState.copy(), accountIDs: nil, mastodonController: mastodonController)
vc.showInaccurateCountWarning = true
vc.showInacurateCountWarning = true
delegate.show(vc)
}