forked from shadowfacts/Tusker
Add Trending Posts
This commit is contained in:
parent
e49859e5ea
commit
240ccf23a4
|
@ -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,
|
||||||
|
|
|
@ -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 */,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>()
|
||||||
|
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue