meow/Meow/Sources/Facts/FactsFeature.swift

79 lines
2.1 KiB
Swift

//
// FactsFeature.swift
// Meow
//
import Foundation
import Core
import CatFactsKit
import ComposableArchitecture
/// Handles the logic for fetching and displaying a `List` of cat facts from a remote API.
@Reducer
public struct FactsFeature {
@ObservationIgnored
@Dependency(\.clientFactory) var clientFactory
@ObservableState
public struct State {
public var baseURL: URL
public var mode: Mode = .notLoaded
public init(baseURL: URL = URL(string: "https://invalid.barf")!, mode: Mode = .notLoaded) {
self.baseURL = baseURL
}
}
public enum Mode {
case notLoaded
case loading
case loaded(facts: [String])
case error(Error)
}
public enum Action {
case viewAppeared
case pulledToRefresh
case fetchNeeded
case receivedFacts([String])
case receivedError(Error)
}
// MARK: - Public functionality
public init() { }
public var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .viewAppeared:
switch state.mode {
case .loaded:
return .none
default:
state.mode = .loading
return .send(.fetchNeeded)
}
case .pulledToRefresh:
return .send(.fetchNeeded)
case .fetchNeeded:
let client = clientFactory.createClient(baseURL: state.baseURL)
return .run { send in
do {
let results = try await client.getFacts(count: 5)
await send(.receivedFacts(results))
} catch {
await send(.receivedError(error))
}
}
case let .receivedFacts(facts):
state.mode = .loaded(facts: facts)
return .none
case let .receivedError(error):
state.mode = .error(error)
return .none
}
}
}
}