From ec75906bc18cc368efa48a707789d3a68bf0a5ae Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 4 Feb 2023 13:21:58 -0500 Subject: [PATCH] Add favorites screen Closes #327 --- .../Pachyderm/Sources/Pachyderm/Client.swift | 6 +++-- Tusker.xcodeproj/project.pbxproj | 4 +++ .../Explore/ExploreViewController.swift | 14 +++++++++- .../FavoritesViewController.swift | 27 +++++++++++++++++++ .../Main/MainSidebarViewController.swift | 9 +++++-- .../Main/MainSplitViewController.swift | 8 ++++-- 6 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 Tusker/Screens/Local Predicate Statuses List/FavoritesViewController.swift diff --git a/Packages/Pachyderm/Sources/Pachyderm/Client.swift b/Packages/Pachyderm/Sources/Pachyderm/Client.swift index b7a0a932..57422227 100644 --- a/Packages/Pachyderm/Sources/Pachyderm/Client.swift +++ b/Packages/Pachyderm/Sources/Pachyderm/Client.swift @@ -199,8 +199,10 @@ public class Client { return Request(method: .get, path: "/api/v1/accounts/verify_credentials") } - public static func getFavourites() -> Request<[Status]> { - return Request<[Status]>(method: .get, path: "/api/v1/favourites") + public static func getFavourites(range: RequestRange = .default) -> Request<[Status]> { + var request = Request<[Status]>(method: .get, path: "/api/v1/favourites") + request.range = range + return request } public static func getRelationships(accounts: [String]? = nil) -> Request<[Relationship]> { diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index f6da57a7..6b7c1f12 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -296,6 +296,7 @@ D6C143DA253510F4007DC240 /* ComposeEmojiTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C143D9253510F4007DC240 /* ComposeEmojiTextField.swift */; }; D6C1B2082545D1EC00DAAA66 /* StatusCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C1B2072545D1EC00DAAA66 /* StatusCardView.swift */; }; D6C3F4F5298ED0890009FCFF /* LocalPredicateStatusesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C3F4F4298ED0890009FCFF /* LocalPredicateStatusesViewController.swift */; }; + D6C3F4F7298ED7F70009FCFF /* FavoritesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C3F4F6298ED7F70009FCFF /* FavoritesViewController.swift */; }; D6C693EF216192C2007D6A6D /* TuskerNavigationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */; }; D6C693FC2162FE6F007D6A6D /* LoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C693FB2162FE6F007D6A6D /* LoadingViewController.swift */; }; D6C693FE2162FEEA007D6A6D /* UIViewController+Children.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C693FD2162FEEA007D6A6D /* UIViewController+Children.swift */; }; @@ -704,6 +705,7 @@ D6C143D9253510F4007DC240 /* ComposeEmojiTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeEmojiTextField.swift; sourceTree = ""; }; D6C1B2072545D1EC00DAAA66 /* StatusCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCardView.swift; sourceTree = ""; }; D6C3F4F4298ED0890009FCFF /* LocalPredicateStatusesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalPredicateStatusesViewController.swift; sourceTree = ""; }; + D6C3F4F6298ED7F70009FCFF /* FavoritesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesViewController.swift; sourceTree = ""; }; D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TuskerNavigationDelegate.swift; sourceTree = ""; }; D6C693FB2162FE6F007D6A6D /* LoadingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingViewController.swift; sourceTree = ""; }; D6C693FD2162FEEA007D6A6D /* UIViewController+Children.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Children.swift"; sourceTree = ""; }; @@ -944,6 +946,7 @@ children = ( D6C3F4F4298ED0890009FCFF /* LocalPredicateStatusesViewController.swift */, D6DD8FFE2984D327002AD3FD /* BookmarksViewController.swift */, + D6C3F4F6298ED7F70009FCFF /* FavoritesViewController.swift */, ); path = "Local Predicate Statuses List"; sourceTree = ""; @@ -2155,6 +2158,7 @@ D6D706A72948D4D0000827ED /* TimlineState.swift in Sources */, D66C900B28DAB7FD00217BF2 /* TimelineViewController.swift in Sources */, D61F758D2933C69C00C0B37F /* StatusUpdatedNotificationTableViewCell.swift in Sources */, + D6C3F4F7298ED7F70009FCFF /* FavoritesViewController.swift in Sources */, D6AEBB432321685E00E5038B /* OpenInSafariActivity.swift in Sources */, D6C693FE2162FEEA007D6A6D /* UIViewController+Children.swift in Sources */, D61A45EA28DF51EE002BE511 /* TimelineLikeCollectionViewController.swift in Sources */, diff --git a/Tusker/Screens/Explore/ExploreViewController.swift b/Tusker/Screens/Explore/ExploreViewController.swift index 7e3925a1..4b1b37b2 100644 --- a/Tusker/Screens/Explore/ExploreViewController.swift +++ b/Tusker/Screens/Explore/ExploreViewController.swift @@ -154,7 +154,7 @@ class ExploreViewController: UIViewController, UICollectionViewDelegate, Collect private func applyInitialSnapshot() { var snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections(Section.allCases.filter { $0 != .discover }) - snapshot.appendItems([.bookmarks], toSection: .bookmarks) + snapshot.appendItems([.bookmarks, .favorites], toSection: .bookmarks) if mastodonController.instanceFeatures.trends, !Preferences.shared.hideDiscover { addDiscoverSection(to: &snapshot) @@ -336,6 +336,9 @@ class ExploreViewController: UIViewController, UICollectionViewDelegate, Collect case .bookmarks: show(BookmarksViewController(mastodonController: mastodonController), sender: nil) + case .favorites: + show(FavoritesViewController(mastodonController: mastodonController), sender: nil) + case .trendingStatuses: show(TrendingStatusesViewController(mastodonController: mastodonController), sender: nil) @@ -408,6 +411,7 @@ extension ExploreViewController { enum Item: Hashable { case bookmarks + case favorites case trendingStatuses case trendingTags case trendingLinks @@ -423,6 +427,8 @@ extension ExploreViewController { switch self { case .bookmarks: return NSLocalizedString("Bookmarks", comment: "bookmarks nav item title") + case .favorites: + return NSLocalizedString("Favorites", comment: "favorites nav item title") case .trendingStatuses: return NSLocalizedString("Trending Posts", comment: "trending statuses nav item title") case .trendingTags: @@ -451,6 +457,8 @@ extension ExploreViewController { switch self { case .bookmarks: name = "bookmark.fill" + case .favorites: + name = "star.fill" case .trendingStatuses: name = "doc.text.image" case .trendingTags: @@ -477,6 +485,8 @@ extension ExploreViewController { switch (lhs, rhs) { case (.bookmarks, .bookmarks): return true + case (.favorites, .favorites): + return true case (.trendingStatuses, .trendingStatuses): return true case (.trendingTags, .trendingTags): @@ -506,6 +516,8 @@ extension ExploreViewController { switch self { case .bookmarks: hasher.combine("bookmarks") + case .favorites: + hasher.combine("favorites") case .trendingStatuses: hasher.combine("trendingStatuses") case .trendingTags: diff --git a/Tusker/Screens/Local Predicate Statuses List/FavoritesViewController.swift b/Tusker/Screens/Local Predicate Statuses List/FavoritesViewController.swift new file mode 100644 index 00000000..b257bebb --- /dev/null +++ b/Tusker/Screens/Local Predicate Statuses List/FavoritesViewController.swift @@ -0,0 +1,27 @@ +// +// FavoritesViewController.swift +// Tusker +// +// Created by Shadowfacts on 2/4/23. +// Copyright © 2023 Shadowfacts. All rights reserved. +// + +import UIKit +import Pachyderm + +class FavoritesViewController: LocalPredicateStatusesViewController { + + init(mastodonController: MastodonController) { + super.init( + predicate: \.favourited, + predicateTitle: "Favorites", + request: { Client.getFavourites(range: $0) }, + mastodonController: mastodonController + ) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} diff --git a/Tusker/Screens/Main/MainSidebarViewController.swift b/Tusker/Screens/Main/MainSidebarViewController.swift index b87b7e44..7d91ff59 100644 --- a/Tusker/Screens/Main/MainSidebarViewController.swift +++ b/Tusker/Screens/Main/MainSidebarViewController.swift @@ -41,7 +41,7 @@ class MainSidebarViewController: UIViewController { } var exploreTabItems: [Item] { - var items: [Item] = [.explore, .bookmarks, .profileDirectory] + var items: [Item] = [.explore, .bookmarks, .favorites, .profileDirectory] let snapshot = dataSource.snapshot() for case let .list(list) in snapshot.itemIdentifiers(inSection: .lists) { items.append(.list(list)) @@ -172,6 +172,7 @@ class MainSidebarViewController: UIViewController { .tab(.notifications), .explore, .bookmarks, + .favorites, .tab(.myProfile) ], toSection: .tabs) snapshot.appendItems([ @@ -384,7 +385,7 @@ extension MainSidebarViewController { } enum Item: Hashable { case tab(MainTabBarViewController.Tab) - case explore, bookmarks + case explore, bookmarks, favorites case discoverHeader, profileDirectory case listsHeader, list(List), addList case savedHashtagsHeader, savedHashtag(Hashtag), addSavedHashtag @@ -398,6 +399,8 @@ extension MainSidebarViewController { return "Explore" case .bookmarks: return "Bookmarks" + case .favorites: + return "Favorites" case .discoverHeader: return "Discover" case .profileDirectory: @@ -431,6 +434,8 @@ extension MainSidebarViewController { return "magnifyingglass" case .bookmarks: return "bookmark" + case .favorites: + return "star" case .profileDirectory: return "person.2.fill" case .list(_): diff --git a/Tusker/Screens/Main/MainSplitViewController.swift b/Tusker/Screens/Main/MainSplitViewController.swift index 013845be..c57e041f 100644 --- a/Tusker/Screens/Main/MainSplitViewController.swift +++ b/Tusker/Screens/Main/MainSplitViewController.swift @@ -232,9 +232,9 @@ extension MainSplitViewController: UISplitViewControllerDelegate { tabBarViewController.select(tab: .explore) - case .bookmarks, .profileDirectory, .list(_), .savedHashtag(_), .savedInstance(_): + case .bookmarks, .favorites, .profileDirectory, .list(_), .savedHashtag(_), .savedInstance(_): tabBarViewController.select(tab: .explore) - // Make sure the Explore VC doesn't show it's search bar when it appears, in case the user was previously + // Make sure the Explore VC doesn't show its search bar when it appears, in case the user was previously // in compact mode and performing a search. let exploreNav = tabBarViewController.viewController(for: .explore) as! UINavigationController let explore = exploreNav.viewControllers.first as! ExploreViewController @@ -305,6 +305,8 @@ extension MainSplitViewController: UISplitViewControllerDelegate { switch tabNavigationStack[1] { case is BookmarksViewController: exploreItem = .bookmarks + case is FavoritesViewController: + exploreItem = .favorites case let listVC as ListTimelineViewController: exploreItem = .list(listVC.list) case let hashtagVC as HashtagTimelineViewController: @@ -380,6 +382,8 @@ fileprivate extension MainSidebarViewController.Item { return SearchViewController(mastodonController: mastodonController) case .bookmarks: return BookmarksViewController(mastodonController: mastodonController) + case .favorites: + return FavoritesViewController(mastodonController: mastodonController) case .profileDirectory: return ProfileDirectoryViewController(mastodonController: mastodonController) case let .list(list):