-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from GoodRequest/swiftui
feat: GoodNetworking + SwiftUI dynamic wrappers
- Loading branch information
Showing
19 changed files
with
535 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// | ||
// AFErrorExtensions.swift | ||
// GoodNetworking | ||
// | ||
// Created by Filip Šašala on 03/01/2024. | ||
// | ||
|
||
import Alamofire | ||
|
||
extension AFError: Equatable { | ||
|
||
public static func == (lhs: AFError, rhs: AFError) -> Bool { | ||
false // every AFError is unique | ||
} | ||
|
||
} |
2 changes: 1 addition & 1 deletion
2
Sources/GoodNetworking/ArrayEncoding.swift → ...Networking/Extensions/ArrayEncoding.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
// | ||
// ArrayEncoding.swift | ||
// | ||
// GoodNetworking | ||
// | ||
// Created by Andrej Jasso on 18/10/2023. | ||
// | ||
|
2 changes: 1 addition & 1 deletion
2
...es/GoodNetworking/CodableExtensions.swift → ...orking/Extensions/CodableExtensions.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
// | ||
// CodableExtensions.swift | ||
// | ||
// GoodNetworking | ||
// | ||
// Created by Dominik Pethö on 11/9/18. | ||
// | ||
|
2 changes: 1 addition & 1 deletion
2
...oodNetworking/DataRequestExtensions.swift → ...ng/Extensions/DataRequestExtensions.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
// | ||
// DataRequestExtensions.swift | ||
// | ||
// GoodNetworking | ||
// | ||
// Created by Dominik Pethö on 4/30/19. | ||
// | ||
|
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
// | ||
// GRImageDownloader.swift | ||
// | ||
// GoodNetworking | ||
// | ||
// Created by Andrej Jasso on 24/05/2022. | ||
// | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// | ||
// Query.swift | ||
// GoodNetworking | ||
// | ||
// Created by Filip Šašala on 10/12/2023. | ||
// | ||
|
||
import Alamofire | ||
import Combine | ||
import Foundation | ||
|
||
#if canImport(GoodStructs) | ||
import GoodStructs | ||
public typealias Response<R> = GoodStructs.GRResult<R, AFError> | ||
#else | ||
public typealias Response<R> = Swift.Result<R, AFError> | ||
#endif | ||
|
||
public protocol Query: EndpointBindable, Encodable, Equatable { | ||
|
||
associatedtype Result: Decodable | ||
|
||
var result: Response<Result>? { get set } | ||
|
||
} | ||
|
||
extension Query { | ||
|
||
internal func dataTaskPublisher(using session: NetworkSession) -> AnyPublisher<Response<Result>, Never> { | ||
return session.request(endpoint: Self.endpoint(self)) | ||
.goodify(type: Result.self) | ||
.receive(on: DispatchQueue.main) | ||
.map { .success($0) } | ||
.catch { Just(.failure($0)) } | ||
#if canImport(GoodStructs) | ||
.prepend(.loading) | ||
#endif | ||
.eraseToAnyPublisher() | ||
} | ||
|
||
} | ||
|
||
extension Query { | ||
|
||
public static func ==(lhs: any Query, rhs: any Query) -> Bool { | ||
false // every query is unique | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// | ||
// Resource.swift | ||
// GoodNetworking | ||
// | ||
// Created by Filip Šašala on 04/01/2024. | ||
// | ||
|
||
import Alamofire | ||
import Combine | ||
import Foundation | ||
|
||
public protocol Resource: EndpointBindable, Codable, Hashable { | ||
|
||
static var placeholder: Self { get } | ||
|
||
} | ||
|
||
extension Resource { | ||
|
||
internal func dataTaskPublisher( | ||
using session: NetworkSession | ||
) -> AnyPublisher<ResourceState<Self>, Never> { | ||
session.request(endpoint: Self.endpoint(self)) | ||
.goodify(type: Self.self) | ||
.receive(on: DispatchQueue.main) | ||
.map { .available($0) } | ||
.catch { Just(.stale(self, $0)).eraseToAnyPublisher() } | ||
.prepend(.uploading(self)) | ||
.eraseToAnyPublisher() | ||
} | ||
|
||
} | ||
|
||
public enum ResourceState<R: Resource>: Equatable { | ||
|
||
case unavailable | ||
case loading | ||
|
||
case available(R) | ||
case pending(R) | ||
case uploading(R) | ||
case stale(R, AFError) | ||
|
||
public var isAvailable: Bool { | ||
switch self { | ||
case .unavailable, .loading: | ||
return false | ||
|
||
default: | ||
return true | ||
} | ||
} | ||
|
||
public var resource: R? { | ||
switch self { | ||
case .unavailable, .loading: | ||
return nil | ||
|
||
case .available(let resource), .pending(let resource), .uploading(let resource): | ||
return resource | ||
|
||
case .stale(let resource, _): | ||
return resource | ||
} | ||
} | ||
|
||
public var unwrapped: R { | ||
guard let resource else { preconditionFailure("Accessing unavailable resource") } | ||
return resource | ||
} | ||
|
||
} |
2 changes: 1 addition & 1 deletion
2
Sources/GoodNetworking/GRSessionLogger.swift → ...dNetworking/Session/GRSessionLogger.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
// | ||
// GRSessionLogger.swift | ||
// | ||
// GoodNetworking | ||
// | ||
// Created by Andrej Jasso on 24/05/2022. | ||
// | ||
|
8 changes: 4 additions & 4 deletions
8
Sources/GoodNetworking/NetworkSession.swift → ...odNetworking/Session/NetworkSession.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 3 additions & 3 deletions
6
...working/NetworkSessionConfiguration.swift → ...Session/NetworkSessionConfiguration.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// | ||
// Fetch.swift | ||
// GoodNetworking | ||
// | ||
// Created by Filip Šašala on 08/12/2023. | ||
// | ||
|
||
import Alamofire | ||
import Combine | ||
import SwiftUI | ||
|
||
/// Fetches data from remote endpoint immediately after initialization. | ||
/// | ||
/// Example usage: | ||
/// ```swift | ||
/// @Fetch private var userData = UserDataRequest() | ||
/// | ||
/// switch data.result { | ||
/// case .none, .loading: | ||
/// ProgressView() | ||
/// case .success(let userResponse): | ||
/// Text(userResponse.name) | ||
/// case .failure(let error): | ||
/// Text(error.localizedDescription) | ||
/// } | ||
/// ``` | ||
@propertyWrapper public struct Fetch<Q: Query>: DynamicProperty { | ||
|
||
@ObservedObject @Observable private var observableQuery: Q | ||
@ObservedObject @Observable private var dataTask: AnyCancellable? | ||
|
||
private let session: NetworkSession | ||
|
||
public var wrappedValue: Q { | ||
get { observableQuery } | ||
nonmutating set { | ||
let oldValue = observableQuery | ||
guard newValue != oldValue else { return } | ||
|
||
observableQuery = newValue | ||
|
||
dataTask?.cancel() | ||
dataTask = nil | ||
dataTask = makeDataTask(from: newValue) | ||
} | ||
} | ||
|
||
public init(wrappedValue: Q, session: NetworkSession = .default) { | ||
self.session = session | ||
|
||
self._observableQuery = ObservedObject(wrappedValue: Observable(wrappedValue)) | ||
self._dataTask = ObservedObject(wrappedValue: Observable(nil)) | ||
|
||
self.dataTask = makeDataTask(from: wrappedValue) | ||
} | ||
|
||
private func makeDataTask(from query: Q) -> AnyCancellable { | ||
query.dataTaskPublisher(using: session) | ||
.sink { [self] in observableQuery.result = $0 } | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// | ||
// Observable.swift | ||
// GoodNetworking | ||
// | ||
// Created by Filip Šašala on 10/12/2023. | ||
// | ||
|
||
import Combine | ||
|
||
@propertyWrapper public final class Observable<T>: ObservableObject { | ||
|
||
@Published public var wrappedValue: T | ||
|
||
public init(_ wrappedValue: T) { | ||
self.wrappedValue = wrappedValue | ||
} | ||
|
||
} |
Oops, something went wrong.