forked from shadowfacts/Tusker
Switch hashtag/instance/list timelines to use new collection view impl
This commit is contained in:
parent
658c08010d
commit
b1d83f2746
|
@ -9,7 +9,7 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
import Pachyderm
|
import Pachyderm
|
||||||
|
|
||||||
class ListTimelineViewController: TimelineTableViewController {
|
class ListTimelineViewController: TimelineViewController {
|
||||||
|
|
||||||
let list: List
|
let list: List
|
||||||
|
|
||||||
|
@ -57,8 +57,11 @@ class ListTimelineViewController: TimelineTableViewController {
|
||||||
@objc func editListDoneButtonPressed() {
|
@objc func editListDoneButtonPressed() {
|
||||||
dismiss(animated: true)
|
dismiss(animated: true)
|
||||||
|
|
||||||
// todo: show loading indicator
|
// TODO: only reload if there were changes
|
||||||
reloadInitial()
|
Task {
|
||||||
|
applyInitialSnapshot()
|
||||||
|
await controller.loadInitial()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
import Pachyderm
|
import Pachyderm
|
||||||
|
|
||||||
class HashtagTimelineViewController: TimelineTableViewController {
|
class HashtagTimelineViewController: TimelineViewController {
|
||||||
|
|
||||||
let hashtag: Hashtag
|
let hashtag: Hashtag
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,14 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import Pachyderm
|
||||||
|
|
||||||
protocol InstanceTimelineViewControllerDelegate: AnyObject {
|
protocol InstanceTimelineViewControllerDelegate: AnyObject {
|
||||||
func didSaveInstance(url: URL)
|
func didSaveInstance(url: URL)
|
||||||
func didUnsaveInstance(url: URL)
|
func didUnsaveInstance(url: URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
class InstanceTimelineViewController: TimelineTableViewController {
|
class InstanceTimelineViewController: TimelineViewController {
|
||||||
|
|
||||||
weak var delegate: InstanceTimelineViewControllerDelegate?
|
weak var delegate: InstanceTimelineViewControllerDelegate?
|
||||||
|
|
||||||
|
@ -68,19 +69,15 @@ class InstanceTimelineViewController: TimelineTableViewController {
|
||||||
toggleSaveButton.title = toggleSaveButtonTitle
|
toggleSaveButton.title = toggleSaveButtonTitle
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Table view data source
|
override func configureStatusCell(_ cell: TimelineStatusCollectionViewCell, id: String, state: StatusState) {
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
||||||
let cell = super.tableView(tableView, cellForRowAt: indexPath) as! TimelineStatusTableViewCell
|
|
||||||
cell.delegate = browsingEnabled ? self : nil
|
cell.delegate = browsingEnabled ? self : nil
|
||||||
return cell
|
cell.overrideMastodonController = mastodonController
|
||||||
|
cell.updateUI(statusID: id, state: state)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Table view delegate
|
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
|
||||||
guard browsingEnabled else { return }
|
guard browsingEnabled else { return }
|
||||||
super.tableView(tableView, didSelectRowAt: indexPath)
|
super.collectionView(collectionView, didSelectItemAt: indexPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Interaction
|
// MARK: - Interaction
|
||||||
|
|
|
@ -34,6 +34,7 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro
|
||||||
|
|
||||||
self.controller = TimelineLikeController(delegate: self)
|
self.controller = TimelineLikeController(delegate: self)
|
||||||
|
|
||||||
|
self.navigationItem.title = timeline.title
|
||||||
addKeyCommand(MenuController.refreshCommand(discoverabilityTitle: "Refresh Timeline"))
|
addKeyCommand(MenuController.refreshCommand(discoverabilityTitle: "Refresh Timeline"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,10 +85,15 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// separate method because InstanceTimelineViewController needs to be able to customize it
|
||||||
|
func configureStatusCell(_ cell: TimelineStatusCollectionViewCell, id: String, state: StatusState) {
|
||||||
|
cell.delegate = self
|
||||||
|
cell.updateUI(statusID: id, state: state)
|
||||||
|
}
|
||||||
|
|
||||||
private func createDataSource() -> UICollectionViewDiffableDataSource<Section, Item> {
|
private func createDataSource() -> UICollectionViewDiffableDataSource<Section, Item> {
|
||||||
let statusCell = UICollectionView.CellRegistration<TimelineStatusCollectionViewCell, (String, StatusState)> { [unowned self] cell, indexPath, item in
|
let statusCell = UICollectionView.CellRegistration<TimelineStatusCollectionViewCell, (String, StatusState)> { [unowned self] cell, indexPath, item in
|
||||||
cell.delegate = self
|
self.configureStatusCell(cell, id: item.0, state: item.1)
|
||||||
cell.updateUI(statusID: item.0, state: item.1)
|
|
||||||
}
|
}
|
||||||
let timelineDescriptionCell = UICollectionView.CellRegistration<PublicTimelineDescriptionCollectionViewCell, Item> { [unowned self] cell, indexPath, item in
|
let timelineDescriptionCell = UICollectionView.CellRegistration<PublicTimelineDescriptionCollectionViewCell, Item> { [unowned self] cell, indexPath, item in
|
||||||
guard case .public(let local) = timeline else {
|
guard case .public(let local) = timeline else {
|
||||||
|
@ -114,15 +120,16 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func applyInitialSnapshot() {
|
// non-private, because ListTimelineViewController needs to be able to reload it from scratch
|
||||||
|
func applyInitialSnapshot() {
|
||||||
|
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
|
||||||
if case .public(let local) = timeline,
|
if case .public(let local) = timeline,
|
||||||
(local && !Preferences.shared.hasShownLocalTimelineDescription) ||
|
(local && !Preferences.shared.hasShownLocalTimelineDescription) ||
|
||||||
(!local && !Preferences.shared.hasShownFederatedTimelineDescription) {
|
(!local && !Preferences.shared.hasShownFederatedTimelineDescription) {
|
||||||
var snapshot = dataSource.snapshot()
|
|
||||||
snapshot.appendSections([.header])
|
snapshot.appendSections([.header])
|
||||||
snapshot.appendItems([.publicTimelineDescription], toSection: .header)
|
snapshot.appendItems([.publicTimelineDescription], toSection: .header)
|
||||||
dataSource.apply(snapshot, animatingDifferences: false)
|
|
||||||
}
|
}
|
||||||
|
dataSource.apply(snapshot, animatingDifferences: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
|
|
|
@ -51,7 +51,7 @@ actor TimelineLikeController<Item> {
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadInitial() async {
|
func loadInitial() async {
|
||||||
guard state == .notLoadedInitial else {
|
guard state == .notLoadedInitial || state == .idle else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let token = LoadAttemptToken()
|
let token = LoadAttemptToken()
|
||||||
|
@ -175,14 +175,14 @@ actor TimelineLikeController<Item> {
|
||||||
switch self {
|
switch self {
|
||||||
case .notLoadedInitial:
|
case .notLoadedInitial:
|
||||||
switch to {
|
switch to {
|
||||||
case .loadingInitial(_, hasAddedLoadingIndicator: _):
|
case .loadingInitial(_, _):
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case .idle:
|
case .idle:
|
||||||
switch to {
|
switch to {
|
||||||
case .loadingNewer(_), .loadingOlder(_, _):
|
case .loadingInitial(_, _), .loadingNewer(_), .loadingOlder(_, _):
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -30,6 +30,7 @@ protocol StatusCollectionViewCell: UICollectionViewCell, AttachmentViewDelegate
|
||||||
var moreButton: UIButton { get }
|
var moreButton: UIButton { get }
|
||||||
|
|
||||||
var delegate: StatusCollectionViewCellDelegate? { get }
|
var delegate: StatusCollectionViewCellDelegate? { get }
|
||||||
|
var mastodonController: MastodonController! { get }
|
||||||
|
|
||||||
var showStatusAutomatically: Bool { get }
|
var showStatusAutomatically: Bool { get }
|
||||||
var showReplyIndicator: Bool { get }
|
var showReplyIndicator: Bool { get }
|
||||||
|
@ -75,8 +76,6 @@ extension StatusCollectionViewCell {
|
||||||
}
|
}
|
||||||
|
|
||||||
func doUpdateUI(status: StatusMO) {
|
func doUpdateUI(status: StatusMO) {
|
||||||
precondition(delegate != nil, "StatusCollectionViewCell must have delegate")
|
|
||||||
|
|
||||||
statusID = status.id
|
statusID = status.id
|
||||||
accountID = status.account.id
|
accountID = status.account.id
|
||||||
|
|
||||||
|
|
|
@ -227,6 +227,8 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
|
||||||
private var mainContainerBottomToActionsConstraint: NSLayoutConstraint!
|
private var mainContainerBottomToActionsConstraint: NSLayoutConstraint!
|
||||||
private var mainContainerBottomToSelfConstraint: NSLayoutConstraint!
|
private var mainContainerBottomToSelfConstraint: NSLayoutConstraint!
|
||||||
|
|
||||||
|
weak var overrideMastodonController: MastodonController?
|
||||||
|
var mastodonController: MastodonController! { overrideMastodonController ?? delegate?.apiController }
|
||||||
weak var delegate: StatusCollectionViewCellDelegate?
|
weak var delegate: StatusCollectionViewCellDelegate?
|
||||||
var showStatusAutomatically: Bool {
|
var showStatusAutomatically: Bool {
|
||||||
// TODO: needed once conversation controller refactored
|
// TODO: needed once conversation controller refactored
|
||||||
|
|
Loading…
Reference in New Issue