Add Trending Posts

This commit is contained in:
Shadowfacts 2022-04-02 10:39:03 -04:00
parent e49859e5ea
commit 240ccf23a4
7 changed files with 130 additions and 14 deletions

View File

@ -368,7 +368,7 @@ public class Client {
} }
// MARK: - Instance // MARK: - Instance
public static func getTrends(limit: Int? = nil) -> Request<[Hashtag]> { public static func getTrendingHashtags(limit: Int? = nil) -> Request<[Hashtag]> {
let parameters: [Parameter] let parameters: [Parameter]
if let limit = limit { if let limit = limit {
parameters = ["limit" => limit] parameters = ["limit" => limit]
@ -378,6 +378,16 @@ public class Client {
return Request<[Hashtag]>(method: .get, path: "/api/v1/trends", queryParameters: parameters) return Request<[Hashtag]>(method: .get, path: "/api/v1/trends", queryParameters: parameters)
} }
public static func getTrendingStatuses(limit: Int? = nil) -> Request<[Status]> {
let parameters: [Parameter]
if let limit = limit {
parameters = ["limit" => limit]
} else {
parameters = []
}
return Request(method: .get, path: "/api/v1/trends/statuses", queryParameters: parameters)
}
public static func getFeaturedProfiles(local: Bool, order: DirectoryOrder, offset: Int? = nil, limit: Int? = nil) -> Request<[Account]> { public static func getFeaturedProfiles(local: Bool, order: DirectoryOrder, offset: Int? = nil, limit: Int? = nil) -> Request<[Account]> {
var parameters = [ var parameters = [
"order" => order.rawValue, "order" => order.rawValue,

View File

@ -71,6 +71,7 @@
D6109A11214607D500432DC2 /* Timeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6109A10214607D500432DC2 /* Timeline.swift */; }; D6109A11214607D500432DC2 /* Timeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6109A10214607D500432DC2 /* Timeline.swift */; };
D6114E0927F3EA3D0080E273 /* CrashReporterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6114E0827F3EA3D0080E273 /* CrashReporterViewController.swift */; }; D6114E0927F3EA3D0080E273 /* CrashReporterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6114E0827F3EA3D0080E273 /* CrashReporterViewController.swift */; };
D6114E0B27F3F6EA0080E273 /* Endpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6114E0A27F3F6EA0080E273 /* Endpoint.swift */; }; D6114E0B27F3F6EA0080E273 /* Endpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6114E0A27F3F6EA0080E273 /* Endpoint.swift */; };
D6114E0D27F7FEB30080E273 /* TrendingStatusesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6114E0C27F7FEB30080E273 /* TrendingStatusesViewController.swift */; };
D611C2CF232DC61100C86A49 /* HashtagTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D611C2CD232DC61100C86A49 /* HashtagTableViewCell.swift */; }; D611C2CF232DC61100C86A49 /* HashtagTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D611C2CD232DC61100C86A49 /* HashtagTableViewCell.swift */; };
D611C2D0232DC61100C86A49 /* HashtagTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D611C2CE232DC61100C86A49 /* HashtagTableViewCell.xib */; }; D611C2D0232DC61100C86A49 /* HashtagTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D611C2CE232DC61100C86A49 /* HashtagTableViewCell.xib */; };
D61AC1D3232E928600C54D2D /* InstanceSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61AC1D2232E928600C54D2D /* InstanceSelector.swift */; }; D61AC1D3232E928600C54D2D /* InstanceSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61AC1D2232E928600C54D2D /* InstanceSelector.swift */; };
@ -484,6 +485,7 @@
D6109A10214607D500432DC2 /* Timeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Timeline.swift; sourceTree = "<group>"; }; D6109A10214607D500432DC2 /* Timeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Timeline.swift; sourceTree = "<group>"; };
D6114E0827F3EA3D0080E273 /* CrashReporterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReporterViewController.swift; sourceTree = "<group>"; }; D6114E0827F3EA3D0080E273 /* CrashReporterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReporterViewController.swift; sourceTree = "<group>"; };
D6114E0A27F3F6EA0080E273 /* Endpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Endpoint.swift; sourceTree = "<group>"; }; D6114E0A27F3F6EA0080E273 /* Endpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Endpoint.swift; sourceTree = "<group>"; };
D6114E0C27F7FEB30080E273 /* TrendingStatusesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingStatusesViewController.swift; sourceTree = "<group>"; };
D611C2CD232DC61100C86A49 /* HashtagTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagTableViewCell.swift; sourceTree = "<group>"; }; D611C2CD232DC61100C86A49 /* HashtagTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagTableViewCell.swift; sourceTree = "<group>"; };
D611C2CE232DC61100C86A49 /* HashtagTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HashtagTableViewCell.xib; sourceTree = "<group>"; }; D611C2CE232DC61100C86A49 /* HashtagTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HashtagTableViewCell.xib; sourceTree = "<group>"; };
D61AC1D2232E928600C54D2D /* InstanceSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceSelector.swift; sourceTree = "<group>"; }; D61AC1D2232E928600C54D2D /* InstanceSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceSelector.swift; sourceTree = "<group>"; };
@ -1023,6 +1025,7 @@
D6945C3323AC6431005C403C /* AddSavedHashtagViewController.swift */, D6945C3323AC6431005C403C /* AddSavedHashtagViewController.swift */,
D6093F9A25BDD4B9004811E6 /* HashtagSearchResultsViewController.swift */, D6093F9A25BDD4B9004811E6 /* HashtagSearchResultsViewController.swift */,
D6945C3923AC75E2005C403C /* FindInstanceViewController.swift */, D6945C3923AC75E2005C403C /* FindInstanceViewController.swift */,
D6114E0C27F7FEB30080E273 /* TrendingStatusesViewController.swift */,
D693A72725CF282E003A14E2 /* TrendingHashtagsViewController.swift */, D693A72725CF282E003A14E2 /* TrendingHashtagsViewController.swift */,
D693A72925CF8C1E003A14E2 /* ProfileDirectoryViewController.swift */, D693A72925CF8C1E003A14E2 /* ProfileDirectoryViewController.swift */,
D693A72D25CF91C6003A14E2 /* FeaturedProfileCollectionViewCell.swift */, D693A72D25CF91C6003A14E2 /* FeaturedProfileCollectionViewCell.swift */,
@ -2194,6 +2197,7 @@
04ED00B121481ED800567C53 /* SteppedProgressView.swift in Sources */, 04ED00B121481ED800567C53 /* SteppedProgressView.swift in Sources */,
D677284C24ECBE9100C732D3 /* ComposeAvatarImageView.swift in Sources */, D677284C24ECBE9100C732D3 /* ComposeAvatarImageView.swift in Sources */,
D6A6C11B25B63CEE00298D0F /* MemoryCache.swift in Sources */, D6A6C11B25B63CEE00298D0F /* MemoryCache.swift in Sources */,
D6114E0D27F7FEB30080E273 /* TrendingStatusesViewController.swift in Sources */,
D6BC9DDA232D8BE5002CA326 /* SearchResultsViewController.swift in Sources */, D6BC9DDA232D8BE5002CA326 /* SearchResultsViewController.swift in Sources */,
D627FF7F217E95E000CC0648 /* DraftTableViewCell.swift in Sources */, D627FF7F217E95E000CC0648 /* DraftTableViewCell.swift in Sources */,
D6B17255254F88B800128392 /* OppositeCollapseKeywordsView.swift in Sources */, D6B17255254F88B800128392 /* OppositeCollapseKeywordsView.swift in Sources */,

View File

@ -346,7 +346,7 @@ struct ComposeAutocompleteHashtagsView: View {
let group = DispatchGroup() let group = DispatchGroup()
group.enter() group.enter()
trendingRequest = mastodonController.run(Client.getTrends()) { (response) in trendingRequest = mastodonController.run(Client.getTrendingHashtags()) { (response) in
defer { group.leave() } defer { group.leave() }
guard case let .success(trends, _) = response else { return } guard case let .success(trends, _) = response else { return }
trendingTags = trends trendingTags = trends

View File

@ -69,7 +69,7 @@ class AddSavedHashtagViewController: EnhancedTableViewController {
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
let request = Client.getTrends(limit: 10) let request = Client.getTrendingHashtags(limit: 10)
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>() var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()

View File

@ -155,7 +155,8 @@ class ExploreViewController: UIViewController, UICollectionViewDelegate {
private func addDiscoverSection(to snapshot: inout NSDiffableDataSourceSnapshot<Section, Item>) { private func addDiscoverSection(to snapshot: inout NSDiffableDataSourceSnapshot<Section, Item>) {
snapshot.insertSections([.discover], afterSection: .bookmarks) snapshot.insertSections([.discover], afterSection: .bookmarks)
snapshot.appendItems([.trendingTags, .profileDirectory], toSection: .discover) // todo: check version
snapshot.appendItems([.trendingStatuses, .trendingTags, .profileDirectory], toSection: .discover)
} }
private func ownInstanceLoaded(_ instance: Instance) { private func ownInstanceLoaded(_ instance: Instance) {
@ -293,6 +294,9 @@ class ExploreViewController: UIViewController, UICollectionViewDelegate {
case .bookmarks: case .bookmarks:
show(BookmarksTableViewController(mastodonController: mastodonController), sender: nil) show(BookmarksTableViewController(mastodonController: mastodonController), sender: nil)
case .trendingStatuses:
show(TrendingStatusesViewController(mastodonController: mastodonController), sender: nil)
case .trendingTags: case .trendingTags:
show(TrendingHashtagsViewController(mastodonController: mastodonController), sender: nil) show(TrendingHashtagsViewController(mastodonController: mastodonController), sender: nil)
@ -375,6 +379,7 @@ extension ExploreViewController {
enum Item: Hashable { enum Item: Hashable {
case bookmarks case bookmarks
case trendingStatuses
case trendingTags case trendingTags
case profileDirectory case profileDirectory
case list(List) case list(List)
@ -388,6 +393,8 @@ extension ExploreViewController {
switch self { switch self {
case .bookmarks: case .bookmarks:
return NSLocalizedString("Bookmarks", comment: "bookmarks nav item title") return NSLocalizedString("Bookmarks", comment: "bookmarks nav item title")
case .trendingStatuses:
return NSLocalizedString("Trending Posts", comment: "trending statuses nav item title")
case .trendingTags: case .trendingTags:
return NSLocalizedString("Trending Hashtags", comment: "trending hashtags nav item title") return NSLocalizedString("Trending Hashtags", comment: "trending hashtags nav item title")
case .profileDirectory: case .profileDirectory:
@ -412,6 +419,8 @@ extension ExploreViewController {
switch self { switch self {
case .bookmarks: case .bookmarks:
name = "bookmark.fill" name = "bookmark.fill"
case .trendingStatuses:
name = "doc.text.image"
case .trendingTags: case .trendingTags:
name = "arrow.up.arrow.down" name = "arrow.up.arrow.down"
case .profileDirectory: case .profileDirectory:
@ -434,6 +443,8 @@ extension ExploreViewController {
switch (lhs, rhs) { switch (lhs, rhs) {
case (.bookmarks, .bookmarks): case (.bookmarks, .bookmarks):
return true return true
case (.trendingStatuses, .trendingStatuses):
return true
case (.trendingTags, .trendingTags): case (.trendingTags, .trendingTags):
return true return true
case (.profileDirectory, .profileDirectory): case (.profileDirectory, .profileDirectory):
@ -459,6 +470,8 @@ extension ExploreViewController {
switch self { switch self {
case .bookmarks: case .bookmarks:
hasher.combine("bookmarks") hasher.combine("bookmarks")
case .trendingStatuses:
hasher.combine("trendingStatuses")
case .trendingTags: case .trendingTags:
hasher.combine("trendingTags") hasher.combine("trendingTags")
case .profileDirectory: case .profileDirectory:
@ -517,7 +530,7 @@ extension ExploreViewController: UICollectionViewDragDelegate {
case let .savedInstance(url): case let .savedInstance(url):
provider = NSItemProvider(object: url as NSURL) provider = NSItemProvider(object: url as NSURL)
// todo: should dragging public timelines into new windows be supported? // todo: should dragging public timelines into new windows be supported?
case .trendingTags, .profileDirectory, .addList, .addSavedHashtag, .findInstance: default:
return [] return []
} }
return [UIDragItem(itemProvider: provider)] return [UIDragItem(itemProvider: provider)]

View File

@ -48,19 +48,15 @@ class TrendingHashtagsViewController: EnhancedTableViewController {
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
let request = Client.getTrends(limit: 10) let request = Client.getTrendingHashtags(limit: 10)
mastodonController.run(request) { (response) in Task {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>() guard let (hashtags, _) = try? await mastodonController.run(request) else {
guard case let .success(hashtags, _) = response,
hashtags.count > 0 else {
self.dataSource.apply(snapshot)
return return
} }
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.trendingTags]) snapshot.appendSections([.trendingTags])
snapshot.appendItems(hashtags.map { .tag($0) }) snapshot.appendItems(hashtags.map { .tag($0) })
self.dataSource.apply(snapshot) dataSource.apply(snapshot)
} }
} }

View File

@ -0,0 +1,93 @@
//
// TrendingStatusesViewController.swift
// Tusker
//
// Created by Shadowfacts on 4/1/22.
// Copyright © 2022 Shadowfacts. All rights reserved.
//
import UIKit
import Pachyderm
class TrendingStatusesViewController: EnhancedTableViewController {
weak var mastodonController: MastodonController!
private var dataSource: UITableViewDiffableDataSource<Section, Item>!
init(mastodonController: MastodonController) {
self.mastodonController = mastodonController
super.init(style: .grouped)
dragEnabled = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
title = NSLocalizedString("Trending Posts", comment: "trending posts screen title")
tableView.register(UINib(nibName: "TimelineStatusTableViewCell", bundle: .main), forCellReuseIdentifier: "statusCell")
tableView.estimatedRowHeight = 144
dataSource = UITableViewDiffableDataSource(tableView: tableView, cellProvider: { tableView, indexPath, item in
let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as! TimelineStatusTableViewCell
cell.delegate = self
cell.updateUI(statusID: item.id, state: item.state)
return cell
})
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let request = Client.getTrendingStatuses()
Task {
guard let (statuses, _) = try? await mastodonController.run(request) else {
return
}
mastodonController.persistentContainer.addAll(statuses: statuses) {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.statuses])
snapshot.appendItems(statuses.map { Item(id: $0.id, state: .unknown) })
self.dataSource.apply(snapshot)
}
}
}
// MARK: - Table View Delegate
}
extension TrendingStatusesViewController {
enum Section {
case statuses
}
struct Item: Hashable {
let id: String
let state: StatusState
static func ==(lhs: Item, rhs: Item) -> Bool {
return lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
}
extension TrendingStatusesViewController: TuskerNavigationDelegate {
var apiController: MastodonController { mastodonController }
}
extension TrendingStatusesViewController: StatusTableViewCellDelegate {
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
tableView.beginUpdates()
tableView.endUpdates()
}
}