mirror of
https://github.com/VernissageApp/Vernissage.git
synced 2024-12-27 09:23:45 +01:00
Add favourites/bookmarks to profile
This commit is contained in:
parent
92c0bf75ce
commit
4358ed6a38
@ -133,4 +133,30 @@ public extension MastodonClientAuthenticated {
|
||||
|
||||
return try await downloadJson([Account].self, request: request)
|
||||
}
|
||||
|
||||
func favourites(maxId: EntityId? = nil,
|
||||
sinceId: EntityId? = nil,
|
||||
minId: EntityId? = nil,
|
||||
limit: Int? = nil) async throws -> [Status] {
|
||||
let request = try Self.request(
|
||||
for: baseURL,
|
||||
target: Mastodon.Favourites.favourites(maxId, sinceId, minId, limit),
|
||||
withBearerToken: token
|
||||
)
|
||||
|
||||
return try await downloadJson([Status].self, request: request)
|
||||
}
|
||||
|
||||
func bookmarks(maxId: EntityId? = nil,
|
||||
sinceId: EntityId? = nil,
|
||||
minId: EntityId? = nil,
|
||||
limit: Int? = nil) async throws -> [Status] {
|
||||
let request = try Self.request(
|
||||
for: baseURL,
|
||||
target: Mastodon.Bookmarks.bookmarks(maxId, sinceId, minId, limit),
|
||||
withBearerToken: token
|
||||
)
|
||||
|
||||
return try await downloadJson([Status].self, request: request)
|
||||
}
|
||||
}
|
||||
|
74
MastodonKit/Sources/MastodonKit/Targets/Bookmarks.swift
Normal file
74
MastodonKit/Sources/MastodonKit/Targets/Bookmarks.swift
Normal file
@ -0,0 +1,74 @@
|
||||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2022 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Mastodon {
|
||||
public enum Bookmarks {
|
||||
case bookmarks(MaxId?, SinceId?, MinId?, Limit?)
|
||||
}
|
||||
}
|
||||
|
||||
extension Mastodon.Bookmarks: TargetType {
|
||||
fileprivate var apiPath: String { return "/api/v1/bookmarks" }
|
||||
|
||||
/// The path to be appended to `baseURL` to form the full `URL`.
|
||||
public var path: String {
|
||||
switch self {
|
||||
case .bookmarks(_, _, _, _):
|
||||
return "\(apiPath)"
|
||||
}
|
||||
}
|
||||
|
||||
/// The HTTP method used in the request.
|
||||
public var method: Method {
|
||||
switch self {
|
||||
case .bookmarks:
|
||||
return .get
|
||||
}
|
||||
}
|
||||
|
||||
/// The parameters to be incoded in the request.
|
||||
public var queryItems: [(String, String)]? {
|
||||
var params: [(String, String)] = []
|
||||
|
||||
var maxId: MaxId? = nil
|
||||
var sinceId: SinceId? = nil
|
||||
var minId: MinId? = nil
|
||||
var limit: Limit? = nil
|
||||
|
||||
switch self {
|
||||
case .bookmarks(let _maxId, let _sinceId, let _minId, let _limit):
|
||||
maxId = _maxId
|
||||
sinceId = _sinceId
|
||||
minId = _minId
|
||||
limit = _limit
|
||||
}
|
||||
|
||||
if let maxId {
|
||||
params.append(("max_id", maxId))
|
||||
}
|
||||
if let sinceId {
|
||||
params.append(("since_id", sinceId))
|
||||
}
|
||||
if let minId {
|
||||
params.append(("min_id", minId))
|
||||
}
|
||||
if let limit {
|
||||
params.append(("limit", "\(limit)"))
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
public var headers: [String: String]? {
|
||||
[:].contentTypeApplicationJson
|
||||
}
|
||||
|
||||
public var httpBody: Data? {
|
||||
nil
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ import Foundation
|
||||
|
||||
extension Mastodon {
|
||||
public enum Favourites {
|
||||
case favourites
|
||||
case favourites(MaxId?, SinceId?, MinId?, Limit?)
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ extension Mastodon.Favourites: TargetType {
|
||||
/// The path to be appended to `baseURL` to form the full `URL`.
|
||||
public var path: String {
|
||||
switch self {
|
||||
case .favourites:
|
||||
case .favourites(_, _, _, _):
|
||||
return "\(apiPath)"
|
||||
}
|
||||
}
|
||||
@ -33,10 +33,35 @@ extension Mastodon.Favourites: TargetType {
|
||||
|
||||
/// The parameters to be incoded in the request.
|
||||
public var queryItems: [(String, String)]? {
|
||||
var params: [(String, String)] = []
|
||||
|
||||
var maxId: MaxId? = nil
|
||||
var sinceId: SinceId? = nil
|
||||
var minId: MinId? = nil
|
||||
var limit: Limit? = nil
|
||||
|
||||
switch self {
|
||||
case .favourites:
|
||||
return nil
|
||||
case .favourites(let _maxId, let _sinceId, let _minId, let _limit):
|
||||
maxId = _maxId
|
||||
sinceId = _sinceId
|
||||
minId = _minId
|
||||
limit = _limit
|
||||
}
|
||||
|
||||
if let maxId {
|
||||
params.append(("max_id", maxId))
|
||||
}
|
||||
if let sinceId {
|
||||
params.append(("since_id", sinceId))
|
||||
}
|
||||
if let minId {
|
||||
params.append(("min_id", minId))
|
||||
}
|
||||
if let limit {
|
||||
params.append(("limit", "\(limit)"))
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
public var headers: [String: String]? {
|
||||
|
@ -69,9 +69,8 @@
|
||||
F88C2478295C37BB0006098B /* Vernissage.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */; };
|
||||
F88C2482295C3A4F0006098B /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88C2481295C3A4F0006098B /* StatusView.swift */; };
|
||||
F88C2486295C48030006098B /* HTMLFotmattedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88C2485295C48030006098B /* HTMLFotmattedText.swift */; };
|
||||
F88E4D42297E69FD0057491A /* StatusesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D41297E69FD0057491A /* StatusesView.swift */; };
|
||||
F88FAD21295F3944009B20C9 /* HomeFeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD20295F3944009B20C9 /* HomeFeedView.swift */; };
|
||||
F88FAD23295F3FC4009B20C9 /* TimelineFeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD22295F3FC4009B20C9 /* TimelineFeedView.swift */; };
|
||||
F88FAD25295F3FF7009B20C9 /* FederatedFeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD24295F3FF7009B20C9 /* FederatedFeedView.swift */; };
|
||||
F88FAD27295F400E009B20C9 /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD26295F400E009B20C9 /* NotificationsView.swift */; };
|
||||
F88FAD2A295F43B8009B20C9 /* AccountData+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD28295F43B8009B20C9 /* AccountData+CoreDataClass.swift */; };
|
||||
F88FAD2B295F43B8009B20C9 /* AccountData+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD29295F43B8009B20C9 /* AccountData+CoreDataProperties.swift */; };
|
||||
@ -168,9 +167,8 @@
|
||||
F88C2477295C37BB0006098B /* Vernissage.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Vernissage.xcdatamodel; sourceTree = "<group>"; };
|
||||
F88C2481295C3A4F0006098B /* StatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusView.swift; sourceTree = "<group>"; };
|
||||
F88C2485295C48030006098B /* HTMLFotmattedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTMLFotmattedText.swift; sourceTree = "<group>"; };
|
||||
F88E4D41297E69FD0057491A /* StatusesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusesView.swift; sourceTree = "<group>"; };
|
||||
F88FAD20295F3944009B20C9 /* HomeFeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeFeedView.swift; sourceTree = "<group>"; };
|
||||
F88FAD22295F3FC4009B20C9 /* TimelineFeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineFeedView.swift; sourceTree = "<group>"; };
|
||||
F88FAD24295F3FF7009B20C9 /* FederatedFeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FederatedFeedView.swift; sourceTree = "<group>"; };
|
||||
F88FAD26295F400E009B20C9 /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = "<group>"; };
|
||||
F88FAD28295F43B8009B20C9 /* AccountData+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountData+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
F88FAD29295F43B8009B20C9 /* AccountData+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountData+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
@ -251,8 +249,6 @@
|
||||
F88C2481295C3A4F0006098B /* StatusView.swift */,
|
||||
F88C246D295C37B80006098B /* MainView.swift */,
|
||||
F88FAD20295F3944009B20C9 /* HomeFeedView.swift */,
|
||||
F88FAD22295F3FC4009B20C9 /* TimelineFeedView.swift */,
|
||||
F88FAD24295F3FF7009B20C9 /* FederatedFeedView.swift */,
|
||||
F88FAD26295F400E009B20C9 /* NotificationsView.swift */,
|
||||
F866F6A629604629002E8F88 /* SignInView.swift */,
|
||||
F8A93D7D2965FD89001D8331 /* UserProfileView.swift */,
|
||||
@ -260,6 +256,7 @@
|
||||
F897978E29684BCB00B22335 /* LoadingView.swift */,
|
||||
F88ABD9329687CA4004EF61E /* ComposeView.swift */,
|
||||
F89A46DB296EAACE0062125F /* SettingsView.swift */,
|
||||
F88E4D41297E69FD0057491A /* StatusesView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
@ -584,7 +581,6 @@
|
||||
F897978A2968314A00B22335 /* LoadingIndicator.swift in Sources */,
|
||||
F8210DE52966E160001D9973 /* Color+SystemColors.swift in Sources */,
|
||||
F85DBF93296760790069BF89 /* CacheAvatarService.swift in Sources */,
|
||||
F88FAD23295F3FC4009B20C9 /* TimelineFeedView.swift in Sources */,
|
||||
F88FAD2B295F43B8009B20C9 /* AccountData+CoreDataProperties.swift in Sources */,
|
||||
F85D4975296407F100751DF7 /* HomeTimelineService.swift in Sources */,
|
||||
F80048062961850500E6868A /* StatusData+CoreDataProperties.swift in Sources */,
|
||||
@ -601,6 +597,7 @@
|
||||
F85D498329642FAC00751DF7 /* AttachmentData+Comperable.swift in Sources */,
|
||||
F85D497B29640C8200751DF7 /* UsernameRow.swift in Sources */,
|
||||
F89D6C4429718092001DA3D4 /* AccentsSection.swift in Sources */,
|
||||
F88E4D42297E69FD0057491A /* StatusesView.swift in Sources */,
|
||||
F85D497929640B9D00751DF7 /* ImagesCarousel.swift in Sources */,
|
||||
F89D6C3F29716E41001DA3D4 /* Theme.swift in Sources */,
|
||||
F8CC95CE2970761D00C9C2AC /* TintColor.swift in Sources */,
|
||||
@ -644,7 +641,6 @@
|
||||
F88C246C295C37B80006098B /* VernissageApp.swift in Sources */,
|
||||
F802884F297AEED5000BDD51 /* DatabaseError.swift in Sources */,
|
||||
F85D4971296402DC00751DF7 /* AuthorizationService.swift in Sources */,
|
||||
F88FAD25295F3FF7009B20C9 /* FederatedFeedView.swift in Sources */,
|
||||
F88FAD32295F5029009B20C9 /* RemoteFileService.swift in Sources */,
|
||||
F88FAD27295F400E009B20C9 /* NotificationsView.swift in Sources */,
|
||||
F86B7216296BFFDA00EE59EC /* UserProfileStatuses.swift in Sources */,
|
||||
|
@ -122,4 +122,30 @@ public class AccountService {
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.following(for: accountId, page: page)
|
||||
}
|
||||
|
||||
public func favourites(accountData: AccountData?,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.favourites(maxId: maxId, sinceId: sinceId, minId: minId, limit: limit)
|
||||
}
|
||||
|
||||
public func bookmarks(accountData: AccountData?,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.bookmarks(maxId: maxId, sinceId: sinceId, minId: minId, limit: limit)
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2022 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct FederatedFeedView: View {
|
||||
var body: some View {
|
||||
Text("Federated feed")
|
||||
}
|
||||
}
|
@ -67,10 +67,10 @@ struct MainView: View {
|
||||
HomeFeedView(accountId: applicationState.accountData?.id ?? String.empty())
|
||||
.id(applicationState.accountData?.id ?? String.empty())
|
||||
case .local:
|
||||
TimelineFeedView(accountId: applicationState.accountData?.id ?? String.empty(), isLocalOnly: true)
|
||||
StatusesView(accountId: applicationState.accountData?.id ?? String.empty(), listType: .local)
|
||||
.id(applicationState.accountData?.id ?? String.empty())
|
||||
case .federated:
|
||||
TimelineFeedView(accountId: applicationState.accountData?.id ?? String.empty(), isLocalOnly: false)
|
||||
StatusesView(accountId: applicationState.accountData?.id ?? String.empty(), listType: .federated)
|
||||
.id(applicationState.accountData?.id ?? String.empty())
|
||||
case .profile:
|
||||
if let accountData = self.applicationState.accountData {
|
||||
|
@ -5,11 +5,19 @@
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import MastodonKit
|
||||
|
||||
struct TimelineFeedView: View {
|
||||
struct StatusesView: View {
|
||||
public enum ListType {
|
||||
case local
|
||||
case federated
|
||||
case favourites
|
||||
case bookmarks
|
||||
}
|
||||
|
||||
@EnvironmentObject private var applicationState: ApplicationState
|
||||
@State public var accountId: String
|
||||
@State public var isLocalOnly: Bool
|
||||
@State public var listType: ListType
|
||||
|
||||
@State private var allItemsLoaded = false
|
||||
@State private var firstLoadFinished = false
|
||||
@ -53,6 +61,7 @@ struct TimelineFeedView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarTitle(self.getTitle())
|
||||
.overlay(alignment: .center) {
|
||||
if firstLoadFinished == false {
|
||||
LoadingIndicator()
|
||||
@ -88,11 +97,7 @@ struct TimelineFeedView: View {
|
||||
return
|
||||
}
|
||||
|
||||
let statuses = try await PublicTimelineService.shared.getStatuses(
|
||||
accountData: self.applicationState.accountData,
|
||||
local: isLocalOnly,
|
||||
remote: !isLocalOnly,
|
||||
limit: self.defaultLimit)
|
||||
let statuses = try await self.loadFromApi()
|
||||
var inPlaceStatuses: [StatusViewModel] = []
|
||||
|
||||
for item in statuses {
|
||||
@ -109,12 +114,7 @@ struct TimelineFeedView: View {
|
||||
|
||||
private func loadMoreStatuses() async throws {
|
||||
if let lastStatusId = self.statusViewModels.last?.id {
|
||||
let previousStatuses = try await PublicTimelineService.shared.getStatuses(
|
||||
accountData: self.applicationState.accountData,
|
||||
local: isLocalOnly,
|
||||
remote: !isLocalOnly,
|
||||
maxId: lastStatusId,
|
||||
limit: self.defaultLimit)
|
||||
let previousStatuses = try await self.loadFromApi(maxId: lastStatusId)
|
||||
|
||||
if previousStatuses.count < self.defaultLimit {
|
||||
self.allItemsLoaded = true
|
||||
@ -131,12 +131,7 @@ struct TimelineFeedView: View {
|
||||
|
||||
private func loadTopStatuses() async throws {
|
||||
if let firstStatusId = self.statusViewModels.first?.id {
|
||||
let newestStatuses = try await PublicTimelineService.shared.getStatuses(
|
||||
accountData: self.applicationState.accountData,
|
||||
local: isLocalOnly,
|
||||
remote: !isLocalOnly,
|
||||
sinceId: firstStatusId,
|
||||
limit: self.defaultLimit)
|
||||
let newestStatuses = try await self.loadFromApi(sinceId: firstStatusId)
|
||||
|
||||
var inPlaceStatuses: [StatusViewModel] = []
|
||||
for item in newestStatuses {
|
||||
@ -146,4 +141,54 @@ struct TimelineFeedView: View {
|
||||
self.statusViewModels.insert(contentsOf: inPlaceStatuses, at: 0)
|
||||
}
|
||||
}
|
||||
|
||||
private func loadFromApi(maxId: String? = nil, sinceId: String? = nil, minId: String? = nil) async throws -> [Status] {
|
||||
switch self.listType {
|
||||
case .local:
|
||||
return try await PublicTimelineService.shared.getStatuses(
|
||||
accountData: self.applicationState.accountData,
|
||||
local: true,
|
||||
remote: false,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit)
|
||||
case .federated:
|
||||
return try await PublicTimelineService.shared.getStatuses(
|
||||
accountData: self.applicationState.accountData,
|
||||
local: false,
|
||||
remote: true,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit)
|
||||
case .favourites:
|
||||
return try await AccountService.shared.favourites(
|
||||
accountData: self.applicationState.accountData,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit)
|
||||
case .bookmarks:
|
||||
return try await AccountService.shared.bookmarks(
|
||||
accountData: self.applicationState.accountData,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit)
|
||||
}
|
||||
}
|
||||
|
||||
private func getTitle() -> String {
|
||||
switch self.listType {
|
||||
case .local:
|
||||
return "Local"
|
||||
case .federated:
|
||||
return "Federeted"
|
||||
case .favourites:
|
||||
return "Favourites"
|
||||
case .bookmarks:
|
||||
return "Bookmarks"
|
||||
}
|
||||
}
|
||||
}
|
@ -162,19 +162,15 @@ struct UserProfileHeader: View {
|
||||
Divider()
|
||||
}
|
||||
|
||||
Button {
|
||||
Task {
|
||||
// await onMuteAccount()
|
||||
}
|
||||
} label: {
|
||||
NavigationLink(destination: StatusesView(accountId: applicationState.accountData?.id ?? String.empty(), listType: .favourites)
|
||||
.environmentObject(applicationState)
|
||||
) {
|
||||
Label("Favourites", systemImage: "hand.thumbsup")
|
||||
}
|
||||
|
||||
Button {
|
||||
Task {
|
||||
// await onMuteAccount()
|
||||
}
|
||||
} label: {
|
||||
NavigationLink(destination: StatusesView(accountId: applicationState.accountData?.id ?? String.empty(), listType: .bookmarks)
|
||||
.environmentObject(applicationState)
|
||||
) {
|
||||
Label("Bookmarks", systemImage: "bookmark")
|
||||
}
|
||||
}, label: {
|
||||
|
Loading…
Reference in New Issue
Block a user