diff --git a/IceCubesApp/App/AppRouteur.swift b/IceCubesApp/App/AppRouteur.swift index 355b1141..a7caf055 100644 --- a/IceCubesApp/App/AppRouteur.swift +++ b/IceCubesApp/App/AppRouteur.swift @@ -8,7 +8,7 @@ extension View { self.navigationDestination(for: RouteurDestinations.self) { destination in switch destination { case let .accountDetail(id): - AccountView(accountId: id) + AccountDetailView(accountId: id) case let .statusDetail(id): StatusDetailView(statusId: id) } diff --git a/IceCubesApp/App/TimelineTabView.swift b/IceCubesApp/App/TimelineTabView.swift index 331014ea..9ed2662b 100644 --- a/IceCubesApp/App/TimelineTabView.swift +++ b/IceCubesApp/App/TimelineTabView.swift @@ -1,16 +1,25 @@ import SwiftUI import Timeline import Routeur +import Network struct TimelineTabView: View { let tab: String + + private let client: Client @StateObject private var routeurPath = RouterPath() + init(tab: String) { + self.tab = tab + self.client = .init(server: tab) + } + var body: some View { NavigationStack(path: $routeurPath.path) { - TimelineView(client: .init(server: tab)) + TimelineView() .withAppRouteur() } .environmentObject(routeurPath) + .environmentObject(client) } } diff --git a/Packages/Account/Sources/Account/AccountDetailView.swift b/Packages/Account/Sources/Account/AccountDetailView.swift new file mode 100644 index 00000000..dbcfbe27 --- /dev/null +++ b/Packages/Account/Sources/Account/AccountDetailView.swift @@ -0,0 +1,38 @@ +import SwiftUI +import Models +import Network + +public struct AccountDetailView: View { + @EnvironmentObject private var client: Client + @StateObject private var viewModel: AccountDetailViewModel + + public init(accountId: String) { + _viewModel = StateObject(wrappedValue: .init(accountId: accountId)) + } + + public var body: some View { + List { + switch viewModel.state { + case .loading: + loadingRow + case let .data(account): + Text("Account id \(account.id)") + Text("Account name \(account.displayName)") + case let .error(error): + Text("Error: \(error.localizedDescription)") + } + } + .task { + viewModel.client = client + await viewModel.fetchAccount() + } + } + + private var loadingRow: some View { + HStack { + Spacer() + ProgressView() + Spacer() + } + } +} diff --git a/Packages/Account/Sources/Account/AccountDetailViewModel.swift b/Packages/Account/Sources/Account/AccountDetailViewModel.swift new file mode 100644 index 00000000..968003dc --- /dev/null +++ b/Packages/Account/Sources/Account/AccountDetailViewModel.swift @@ -0,0 +1,27 @@ +import SwiftUI +import Network +import Models + +@MainActor +class AccountDetailViewModel: ObservableObject { + let accountId: String + var client: Client = .init(server: "") + + enum State { + case loading, data(account: Models.Account), error(error: Error) + } + + @Published var state: State = .loading + + init(accountId: String) { + self.accountId = accountId + } + + func fetchAccount() async { + do { + state = .data(account: try await client.fetch(endpoint: Network.Account.accounts(id: accountId))) + } catch { + state = .error(error: error) + } + } +} diff --git a/Packages/Account/Sources/Account/AccountView.swift b/Packages/Account/Sources/Account/AccountView.swift deleted file mode 100644 index d3f060fd..00000000 --- a/Packages/Account/Sources/Account/AccountView.swift +++ /dev/null @@ -1,14 +0,0 @@ -import SwiftUI -import Models - -public struct AccountView: View { - private let accountId: String - - public init(accountId: String) { - self.accountId = accountId - } - - public var body: some View { - Text("Account id \(accountId)") - } -} diff --git a/Packages/Network/Sources/Network/Endpoint/Account.swift b/Packages/Network/Sources/Network/Endpoint/Account.swift new file mode 100644 index 00000000..51cec0aa --- /dev/null +++ b/Packages/Network/Sources/Network/Endpoint/Account.swift @@ -0,0 +1,16 @@ +import Foundation + +public enum Account: Endpoint { + case accounts(id: String) + + public func path() -> String { + switch self { + case .accounts(let id): + return "accounts/\(id)" + } + } + + public func queryItems() -> [URLQueryItem]? { + nil + } +} diff --git a/Packages/Timeline/Sources/Timeline/TimelineView.swift b/Packages/Timeline/Sources/Timeline/TimelineView.swift index 1e18c74a..4ecb2380 100644 --- a/Packages/Timeline/Sources/Timeline/TimelineView.swift +++ b/Packages/Timeline/Sources/Timeline/TimelineView.swift @@ -2,12 +2,11 @@ import SwiftUI import Network public struct TimelineView: View { - @StateObject private var viewModel: TimelineViewModel + @EnvironmentObject private var client: Client + @StateObject private var viewModel = TimelineViewModel() @State private var didAppear = false - public init(client: Client) { - _viewModel = StateObject(wrappedValue: TimelineViewModel(client: client)) - } + public init() {} public var body: some View { List { @@ -37,6 +36,7 @@ public struct TimelineView: View { .navigationTitle("Public Timeline: \(viewModel.serverName)") .navigationBarTitleDisplayMode(.inline) .task { + viewModel.client = client if !didAppear { await viewModel.refreshTimeline() didAppear = true diff --git a/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift b/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift index afd2a494..f67be914 100644 --- a/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift +++ b/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift @@ -13,7 +13,7 @@ class TimelineViewModel: ObservableObject { case error(error: Error) } - private let client: Client + var client: Client = .init(server: "") private var statuses: [Status] = [] @Published var state: State = .loading @@ -21,11 +21,7 @@ class TimelineViewModel: ObservableObject { var serverName: String { client.server } - - init(client: Client) { - self.client = client - } - + func refreshTimeline() async { do { statuses = try await client.fetch(endpoint: Timeline.pub(sinceId: nil))