Account: Added filter for accounts status

This commit is contained in:
Thomas Ricouard 2023-01-01 08:22:39 +01:00
parent a06386c1da
commit a592341768
5 changed files with 58 additions and 23 deletions

View file

@ -41,19 +41,15 @@ public struct AccountDetailView: View {
featuredTagsView featuredTagsView
.offset(y: -36) .offset(y: -36)
Group { Group {
if isCurrentUser { Picker("", selection: $viewModel.selectedTab) {
Picker("", selection: $viewModel.selectedTab) { ForEach(isCurrentUser ? AccountDetailViewModel.Tab.currentAccountTabs : AccountDetailViewModel.Tab.accountTabs,
ForEach(AccountDetailViewModel.Tab.allCases, id: \.self) { tab in id: \.self) { tab in
Text(tab.title).tag(tab) Text(tab.title).tag(tab)
}
} }
.pickerStyle(.segmented)
.padding(.horizontal, DS.Constants.layoutPadding)
.offset(y: -20)
} else {
Divider()
.offset(y: -20)
} }
.pickerStyle(.segmented)
.padding(.horizontal, DS.Constants.layoutPadding)
.offset(y: -20)
} }
.id("status") .id("status")

View file

@ -14,14 +14,24 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
case loading, data(account: Account), error(error: Error) case loading, data(account: Account), error(error: Error)
} }
enum Tab: Int, CaseIterable { enum Tab: Int {
case statuses, favourites, followedTags case statuses, favourites, followedTags, postsAndReplies, media
static var currentAccountTabs: [Tab] {
[.statuses, .favourites, .followedTags]
}
static var accountTabs: [Tab] {
[.statuses, .postsAndReplies, .media]
}
var title: String { var title: String {
switch self { switch self {
case .statuses: return "Posts" case .statuses: return "Posts"
case .favourites: return "Favourites" case .favourites: return "Favourites"
case .followedTags: return "Followed Tags" case .followedTags: return "Followed Tags"
case .postsAndReplies: return "Posts & Replies"
case .media: return "Media"
} }
} }
} }
@ -55,11 +65,20 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
@Published var familliarFollowers: [Account] = [] @Published var familliarFollowers: [Account] = []
@Published var selectedTab = Tab.statuses { @Published var selectedTab = Tab.statuses {
didSet { didSet {
reloadTabState() switch selectedTab {
case .statuses, .postsAndReplies, .media:
tabTask?.cancel()
tabTask = Task {
await fetchStatuses()
}
default:
reloadTabState()
}
} }
} }
private var account: Account? private var account: Account?
private var tabTask: Task<Void, Never>?
private(set) var statuses: [Status] = [] private(set) var statuses: [Status] = []
@ -109,7 +128,12 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
guard let client else { return } guard let client else { return }
do { do {
tabState = .statuses(statusesState: .loading) tabState = .statuses(statusesState: .loading)
statuses = try await client.get(endpoint: Accounts.statuses(id: accountId, sinceId: nil, tag: nil)) statuses =
try await client.get(endpoint: Accounts.statuses(id: accountId,
sinceId: nil,
tag: nil,
onlyMedia: selectedTab == .media ? true : nil,
excludeReplies: selectedTab == .statuses && !isCurrentUser ? true : nil))
if isCurrentUser { if isCurrentUser {
(favourites, favouritesNextPage) = try await client.getWithLink(endpoint: Accounts.favourites(sinceId: nil)) (favourites, favouritesNextPage) = try await client.getWithLink(endpoint: Accounts.favourites(sinceId: nil))
} }
@ -123,10 +147,15 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
guard let client else { return } guard let client else { return }
do { do {
switch selectedTab { switch selectedTab {
case .statuses: case .statuses, .postsAndReplies, .media:
guard let lastId = statuses.last?.id else { return } guard let lastId = statuses.last?.id else { return }
tabState = .statuses(statusesState: .display(statuses: statuses, nextPageState: .loadingNextPage)) tabState = .statuses(statusesState: .display(statuses: statuses, nextPageState: .loadingNextPage))
let newStatuses: [Status] = try await client.get(endpoint: Accounts.statuses(id: accountId, sinceId: lastId, tag: nil)) let newStatuses: [Status] =
try await client.get(endpoint: Accounts.statuses(id: accountId,
sinceId: lastId,
tag: nil,
onlyMedia: selectedTab == .media ? true : nil,
excludeReplies: selectedTab == .statuses && !isCurrentUser ? true : nil))
statuses.append(contentsOf: newStatuses) statuses.append(contentsOf: newStatuses)
tabState = .statuses(statusesState: .display(statuses: statuses, tabState = .statuses(statusesState: .display(statuses: statuses,
nextPageState: newStatuses.count < 20 ? .none : .hasNextPage)) nextPageState: newStatuses.count < 20 ? .none : .hasNextPage))
@ -164,7 +193,7 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
private func reloadTabState() { private func reloadTabState() {
switch selectedTab { switch selectedTab {
case .statuses: case .statuses, .postsAndReplies, .media:
tabState = .statuses(statusesState: .display(statuses: statuses, nextPageState: statuses.count < 20 ? .none : .hasNextPage)) tabState = .statuses(statusesState: .display(statuses: statuses, nextPageState: statuses.count < 20 ? .none : .hasNextPage))
case .favourites: case .favourites:
tabState = .statuses(statusesState: .display(statuses: favourites, tabState = .statuses(statusesState: .display(statuses: favourites,

View file

@ -6,7 +6,7 @@ public enum Accounts: Endpoint {
case followedTags case followedTags
case featuredTags(id: String) case featuredTags(id: String)
case verifyCredentials case verifyCredentials
case statuses(id: String, sinceId: String?, tag: String?) case statuses(id: String, sinceId: String?, tag: String?, onlyMedia: Bool?, excludeReplies: Bool?)
case relationships(ids: [String]) case relationships(ids: [String])
case follow(id: String) case follow(id: String)
case unfollow(id: String) case unfollow(id: String)
@ -27,7 +27,7 @@ public enum Accounts: Endpoint {
return "accounts/\(id)/featured_tags" return "accounts/\(id)/featured_tags"
case .verifyCredentials: case .verifyCredentials:
return "accounts/verify_credentials" return "accounts/verify_credentials"
case .statuses(let id, _, _): case .statuses(let id, _, _, _, _):
return "accounts/\(id)/statuses" return "accounts/\(id)/statuses"
case .relationships: case .relationships:
return "accounts/relationships" return "accounts/relationships"
@ -48,7 +48,7 @@ public enum Accounts: Endpoint {
public func queryItems() -> [URLQueryItem]? { public func queryItems() -> [URLQueryItem]? {
switch self { switch self {
case .statuses(_, let sinceId, let tag): case .statuses(_, let sinceId, let tag, let onlyMedia, let excludeReplies):
var params: [URLQueryItem] = [] var params: [URLQueryItem] = []
if let tag { if let tag {
params.append(.init(name: "tagged", value: tag)) params.append(.init(name: "tagged", value: tag))
@ -56,6 +56,12 @@ public enum Accounts: Endpoint {
if let sinceId { if let sinceId {
params.append(.init(name: "max_id", value: sinceId)) params.append(.init(name: "max_id", value: sinceId))
} }
if let onlyMedia {
params.append(.init(name: "only_media", value: onlyMedia ? "true" : "false"))
}
if let excludeReplies {
params.append(.init(name: "exclude_replies", value: excludeReplies ? "true" : "fals"))
}
return params return params
case let .relationships(ids): case let .relationships(ids):
return ids.map { return ids.map {

View file

@ -47,7 +47,7 @@ public enum TimelineFilter: Hashable, Equatable {
case .home: return Timelines.home(sinceId: sinceId, maxId: maxId, minId: minId) case .home: return Timelines.home(sinceId: sinceId, maxId: maxId, minId: minId)
case let .hashtag(tag, accountId): case let .hashtag(tag, accountId):
if let accountId { if let accountId {
return Accounts.statuses(id: accountId, sinceId: nil, tag: tag) return Accounts.statuses(id: accountId, sinceId: nil, tag: tag, onlyMedia: nil, excludeReplies: nil)
} else { } else {
return Timelines.hashtag(tag: tag, maxId: maxId) return Timelines.hashtag(tag: tag, maxId: maxId)
} }

View file

@ -20,7 +20,7 @@ For contributors and myself, here is a todo list of features that could be added
- [ ] Editor: Post image alts - [ ] Editor: Post image alts
- [ ] Editor: Add / Edit polls - [ ] Editor: Add / Edit polls
- [ ] Editor: Support video types - [ ] Editor: Support video types
- [ ] Editor: Open camera - [ ] Editor: Add photos from camera
- [X] Editor: Autocomplete for mentions / hashtags - [X] Editor: Autocomplete for mentions / hashtags
- [ ] Better settings tab - [ ] Better settings tab
- [ ] Edit profile - [ ] Edit profile
@ -30,6 +30,10 @@ For contributors and myself, here is a todo list of features that could be added
- [ ] Open remote status locally - [ ] Open remote status locally
- [ ] More context menu everywhere - [ ] More context menu everywhere
- [ ] Support pinned posts - [ ] Support pinned posts
- [ ] Support IceCubesApp://any mastodon links
- [ ] Add a share sheet
- [ ] Proper iPad support
- [ ] macOS support
IceCubesApp is an open source application for accessing the decentralized social network Mastodon! It's built entirely in SwiftUI, making it fast, lightweight, and easy to use. IceCubesApp is an open source application for accessing the decentralized social network Mastodon! It's built entirely in SwiftUI, making it fast, lightweight, and easy to use.