IceCubesApp/Packages/Account/Sources/Account/AccountsList/AccountsListViewModel.swift

150 lines
5.6 KiB
Swift
Raw Normal View History

2022-12-23 17:47:19 +00:00
import Models
import Network
import Observation
2024-02-02 17:26:24 +00:00
import OSLog
2024-02-14 11:48:14 +00:00
import SwiftUI
2022-12-23 17:47:19 +00:00
2022-12-24 12:41:25 +00:00
public enum AccountsListMode {
case following(accountId: String), followers(accountId: String)
case favoritedBy(statusId: String), rebloggedBy(statusId: String)
case accountsList(accounts: [Account])
2023-01-22 05:38:30 +00:00
var title: LocalizedStringKey {
2022-12-24 12:41:25 +00:00
switch self {
case .following:
2023-09-16 12:15:03 +00:00
"account.following"
2022-12-24 12:41:25 +00:00
case .followers:
2023-09-16 12:15:03 +00:00
"account.followers"
case .favoritedBy:
2023-09-16 12:15:03 +00:00
"account.favorited-by"
2022-12-24 12:41:25 +00:00
case .rebloggedBy:
2023-09-16 12:15:03 +00:00
"account.boosted-by"
case .accountsList:
2023-09-16 12:15:03 +00:00
""
2022-12-24 12:41:25 +00:00
}
}
2022-12-23 17:47:19 +00:00
}
@MainActor
@Observable class AccountsListViewModel {
2022-12-23 17:47:19 +00:00
var client: Client?
2023-01-17 10:36:01 +00:00
2022-12-23 17:47:19 +00:00
let mode: AccountsListMode
2023-01-17 10:36:01 +00:00
2022-12-23 17:47:19 +00:00
public enum State {
public enum PagingState {
case hasNextPage, none
2022-12-23 17:47:19 +00:00
}
2023-01-17 10:36:01 +00:00
2022-12-23 17:47:19 +00:00
case loading
case display(accounts: [Account],
relationships: [Relationship],
2022-12-23 17:47:19 +00:00
nextPageState: PagingState)
case error(error: Error)
}
2023-01-17 10:36:01 +00:00
2022-12-23 17:47:19 +00:00
private var accounts: [Account] = []
private var relationships: [Relationship] = []
2023-01-17 10:36:01 +00:00
var state = State.loading
var totalCount: Int?
2024-01-09 12:28:51 +00:00
var accountId: String?
2024-02-14 11:48:14 +00:00
2024-01-09 12:28:51 +00:00
var searchQuery: String = ""
2023-01-17 10:36:01 +00:00
private var nextPageId: String?
2023-01-17 10:36:01 +00:00
2022-12-24 12:41:25 +00:00
init(mode: AccountsListMode) {
2022-12-23 17:47:19 +00:00
self.mode = mode
}
2023-01-17 10:36:01 +00:00
2022-12-23 17:47:19 +00:00
func fetch() async {
guard let client else { return }
do {
state = .loading
let link: LinkHandler?
2022-12-23 17:47:19 +00:00
switch mode {
2022-12-24 12:41:25 +00:00
case let .followers(accountId):
let account: Account = try await client.get(endpoint: Accounts.accounts(id: accountId))
totalCount = account.followersCount
(accounts, link) = try await client.getWithLink(endpoint: Accounts.followers(id: accountId,
2022-12-24 12:41:25 +00:00
maxId: nil))
case let .following(accountId):
2024-01-09 12:28:51 +00:00
self.accountId = accountId
let account: Account = try await client.get(endpoint: Accounts.accounts(id: accountId))
totalCount = account.followingCount
(accounts, link) = try await client.getWithLink(endpoint: Accounts.following(id: accountId,
2022-12-24 12:41:25 +00:00
maxId: nil))
case let .rebloggedBy(statusId):
(accounts, link) = try await client.getWithLink(endpoint: Statuses.rebloggedBy(id: statusId,
maxId: nil))
case let .favoritedBy(statusId):
(accounts, link) = try await client.getWithLink(endpoint: Statuses.favoritedBy(id: statusId,
maxId: nil))
case let .accountsList(accounts):
self.accounts = accounts
link = nil
2022-12-23 17:47:19 +00:00
}
nextPageId = link?.maxId
2022-12-23 17:47:19 +00:00
relationships = try await client.get(endpoint:
2023-09-16 12:15:03 +00:00
Accounts.relationships(ids: accounts.map(\.id)))
2022-12-23 17:47:19 +00:00
state = .display(accounts: accounts,
relationships: relationships,
2022-12-24 14:09:17 +00:00
nextPageState: link?.maxId != nil ? .hasNextPage : .none)
2023-01-17 10:36:01 +00:00
} catch {}
2022-12-23 17:47:19 +00:00
}
2023-01-17 10:36:01 +00:00
func fetchNextPage() async throws {
guard let client, let nextPageId else { return }
let newAccounts: [Account]
let link: LinkHandler?
switch mode {
case let .followers(accountId):
(newAccounts, link) = try await client.getWithLink(endpoint: Accounts.followers(id: accountId,
maxId: nextPageId))
case let .following(accountId):
(newAccounts, link) = try await client.getWithLink(endpoint: Accounts.following(id: accountId,
maxId: nextPageId))
case let .rebloggedBy(statusId):
(newAccounts, link) = try await client.getWithLink(endpoint: Statuses.rebloggedBy(id: statusId,
2022-12-24 12:41:25 +00:00
maxId: nextPageId))
case let .favoritedBy(statusId):
(newAccounts, link) = try await client.getWithLink(endpoint: Statuses.favoritedBy(id: statusId,
2022-12-24 12:41:25 +00:00
maxId: nextPageId))
case .accountsList:
newAccounts = []
link = nil
2022-12-23 17:47:19 +00:00
}
accounts.append(contentsOf: newAccounts)
let newRelationships: [Relationship] =
try await client.get(endpoint: Accounts.relationships(ids: newAccounts.map(\.id)))
relationships.append(contentsOf: newRelationships)
self.nextPageId = link?.maxId
state = .display(accounts: accounts,
relationships: relationships,
nextPageState: link?.maxId != nil ? .hasNextPage : .none)
2022-12-23 17:47:19 +00:00
}
2024-02-14 11:48:14 +00:00
2024-01-09 12:28:51 +00:00
func search() async {
guard let client, !searchQuery.isEmpty else { return }
do {
state = .loading
try await Task.sleep(for: .milliseconds(250))
var results: SearchResults = try await client.get(endpoint: Search.search(query: searchQuery,
type: "accounts",
offset: nil,
following: true),
forceVersion: .v2)
let relationships: [Relationship] =
try await client.get(endpoint: Accounts.relationships(ids: results.accounts.map(\.id)))
results.relationships = relationships
withAnimation {
state = .display(accounts: results.accounts,
relationships: relationships,
nextPageState: .none)
}
2024-02-14 11:48:14 +00:00
} catch {}
2024-01-09 12:28:51 +00:00
}
2022-12-23 17:47:19 +00:00
}