Skip to content

Commit

Permalink
Add Dependency in Feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
sergdort committed Jun 13, 2021
1 parent 31083d2 commit d03e9ec
Show file tree
Hide file tree
Showing 26 changed files with 796 additions and 680 deletions.
23 changes: 21 additions & 2 deletions CombineFeedback.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
252BF08422BAE05700BC4265 /* SignIn.swift in Sources */ = {isa = PBXBuildFile; fileRef = 252BF08322BAE05700BC4265 /* SignIn.swift */; };
253D324122B185FA002F3B7F /* ViewContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 253D323F22B1858C002F3B7F /* ViewContext.swift */; };
254B4DB726755AE200653BB8 /* StoreBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 254B4DB626755AE200653BB8 /* StoreBox.swift */; };
254B4DBA2676650000653BB8 /* CombineSchedulers in Frameworks */ = {isa = PBXBuildFile; productRef = 254B4DB92676650000653BB8 /* CombineSchedulers */; };
25C57B2C22BC2C33007CB4D6 /* Activity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25C57B2B22BC2C33007CB4D6 /* Activity.swift */; };
25EBC08C23FD61B100719826 /* Reducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585CD878239AC7D3004BE9CC /* Reducer.swift */; };
25F23C2922CA984E00894863 /* TrafficLight.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F23C2822CA984E00894863 /* TrafficLight.swift */; };
Expand Down Expand Up @@ -195,6 +196,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
254B4DBA2676650000653BB8 /* CombineSchedulers in Frameworks */,
5822A2302434FEB400270514 /* CasePaths in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -307,8 +309,8 @@
5800FFAB22A89C08005A860B /* FlatMapLatest.swift */,
58751A9523EC823C00EEF398 /* Atomic.swift */,
5800FFAC22A89C08005A860B /* System.swift */,
5800FF9422A89BE6005A860B /* Info.plist */,
585CD878239AC7D3004BE9CC /* Reducer.swift */,
5800FF9422A89BE6005A860B /* Info.plist */,
);
path = CombineFeedback;
sourceTree = "<group>";
Expand Down Expand Up @@ -522,6 +524,7 @@
name = CombineFeedback;
packageProductDependencies = (
5822A22F2434FEB400270514 /* CasePaths */,
254B4DB92676650000653BB8 /* CombineSchedulers */,
);
productName = CombineFeedback;
productReference = 5800FF9022A89BE6005A860B /* CombineFeedback.framework */;
Expand Down Expand Up @@ -669,6 +672,7 @@
mainGroup = 5800FF8622A89BE6005A860B;
packageReferences = (
5822A22E2434FEB400270514 /* XCRemoteSwiftPackageReference "swift-case-paths" */,
254B4DB82676650000653BB8 /* XCRemoteSwiftPackageReference "combine-schedulers" */,
);
productRefGroup = 5800FF9122A89BE6005A860B /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -1165,6 +1169,7 @@
DEVELOPMENT_TEAM = 3JZ7RUJD4Q;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = Example/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -1186,6 +1191,7 @@
DEVELOPMENT_TEAM = 3JZ7RUJD4Q;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = Example/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -1306,17 +1312,30 @@
/* End XCConfigurationList section */

/* Begin XCRemoteSwiftPackageReference section */
254B4DB82676650000653BB8 /* XCRemoteSwiftPackageReference "combine-schedulers" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/pointfreeco/combine-schedulers.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 0.5.0;
};
};
5822A22E2434FEB400270514 /* XCRemoteSwiftPackageReference "swift-case-paths" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "[email protected]:pointfreeco/swift-case-paths.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 0.1.0;
minimumVersion = 0.2.0;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
254B4DB92676650000653BB8 /* CombineSchedulers */ = {
isa = XCSwiftPackageProductDependency;
package = 254B4DB82676650000653BB8 /* XCRemoteSwiftPackageReference "combine-schedulers" */;
productName = CombineSchedulers;
};
5822A22F2434FEB400270514 /* CasePaths */ = {
isa = XCSwiftPackageProductDependency;
package = 5822A22E2434FEB400270514 /* XCRemoteSwiftPackageReference "swift-case-paths" */;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
{
"object": {
"pins": [
{
"package": "combine-schedulers",
"repositoryURL": "https://github.com/pointfreeco/combine-schedulers.git",
"state": {
"branch": null,
"revision": "c37e5ae8012fb654af776cc556ff8ae64398c841",
"version": "0.5.0"
}
},
{
"package": "swift-case-paths",
"repositoryURL": "[email protected]:pointfreeco/swift-case-paths.git",
"state": {
"branch": null,
"revision": "a9c1e05518b6d95cf5844d823020376f2b6ff842",
"revision": "a313f0cc10e07bb5ce7e2ff5da600cce7efa8e8a",
"version": "0.2.0"
}
},
{
"package": "xctest-dynamic-overlay",
"repositoryURL": "https://github.com/pointfreeco/xctest-dynamic-overlay",
"state": {
"branch": null,
"revision": "603974e3909ad4b48ba04aad7e0ceee4f077a518",
"version": "0.1.0"
}
}
Expand Down
3 changes: 2 additions & 1 deletion Example/CounterExample/Counter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ extension Counter {
super.init(
initial: State(),
feedbacks: [],
reducer: Counter.reducer()
reducer: Counter.reducer(),
dependency: ()
)
}
}
Expand Down
13 changes: 7 additions & 6 deletions Example/MoviesExample/Movies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extension Movies {
movies: [],
status: .loading
)
var feedbacks: [Feedback<State, Event>] {
var feedbacks: [Feedback<State, Event, Void>] {
if #available(iOS 15.0, *) {
return [
ViewModel.whenLoadingIOS15()
Expand All @@ -27,12 +27,13 @@ extension Movies {
super.init(
initial: initial,
feedbacks: [ViewModel.whenLoading()],
reducer: Movies.reducer()
reducer: Movies.reducer(),
dependency: ()
)
}

private static func whenLoading() -> Feedback<State, Event> {
.lensing(state: { $0.nextPage }) { page in
private static func whenLoading() -> Feedback<State, Event, Void> {
.lensing(state: { $0.nextPage }) { page, _ in
URLSession.shared
.fetchMovies(page: page)
.map(Event.didLoad)
Expand All @@ -42,8 +43,8 @@ extension Movies {
}

@available(iOS 15.0, *)
private static func whenLoadingIOS15() -> Feedback<State, Event> {
.lensing(state: \.nextPage) { page in
private static func whenLoadingIOS15() -> Feedback<State, Event, Void> {
.lensing(state: \.nextPage) { page, _ in
do {
return Event.didLoad(try await URLSession.shared.movies(page: page))
} catch {
Expand Down
3 changes: 2 additions & 1 deletion Example/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
signInFeedback,
trafficLightFeedback
],
reducer: appReducer
reducer: appReducer,
dependency: AppDependency()
)
)
)
Expand Down
15 changes: 8 additions & 7 deletions Example/SignIn/SignIn.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ extension SignIn {
ViewModel.whenChangingUserName(api: GithubAPI()),
ViewModel.whenSubmitting(api: GithubAPI())
],
reducer: SignIn.reducer()
reducer: SignIn.reducer(),
dependency: ()
)
}

static func whenChangingUserName(api: GithubAPI) -> Feedback<State, Event> {
return Feedback.custom { state, consumer in
static func whenChangingUserName(api: GithubAPI) -> Feedback<State, Event, Void> {
return Feedback.custom { state, consumer, _ in
state
.map {
$0.0.userName
Expand All @@ -37,14 +38,14 @@ extension SignIn {
}
}

static func whenSubmitting(api: GithubAPI) -> Feedback<State, Event> {
return .middleware { (state) -> AnyPublisher<Event, Never> in
static func whenSubmitting(api: GithubAPI) -> Feedback<State, Event, Void> {
return .middleware { (state, _) -> AnyPublisher<Event, Never> in
guard state.status.isSubmitting else {
return Empty().eraseToAnyPublisher()
}

return api
.singIn(username: state.userName, email: state.email, password: state.password)
.signIn(username: state.userName, email: state.email, password: state.password)
.map(Event.didSignIn)
.eraseToAnyPublisher()
}
Expand Down Expand Up @@ -153,7 +154,7 @@ final class GithubAPI {
.eraseToAnyPublisher()
}

func singIn(username: String, email: String, password: String) -> AnyPublisher<Bool, Never> {
func signIn(username: String, email: String, password: String) -> AnyPublisher<Bool, Never> {
// Fake implementation
return Result.Publisher(true)
.delay(for: 0.3, scheduler: DispatchQueue.main)
Expand Down
132 changes: 68 additions & 64 deletions Example/SingleStoreExample/Movies/MoviesState.swift
Original file line number Diff line number Diff line change
@@ -1,81 +1,85 @@
import Foundation
import CombineFeedback
import Combine

enum Movies {
struct State: Equatable {
var batch: Results
var movies: [Movie]
var status: Status
struct Dependencies {
var movies: (Int) async throws -> Results
var fetchMovies: (Int) -> AnyPublisher<Results, NSError>
}

var nextPage: Int? {
switch status {
case .loading:
return batch.page + 1
case .failed:
return nil
case .idle:
return nil
}
}
struct State: Equatable {
var batch: Results
var movies: [Movie]
var status: Status

var error: NSError? {
switch status {
case .failed(let error):
return error
default:
return nil
}
}
var nextPage: Int? {
switch status {
case .loading:
return batch.page + 1
case .failed:
return nil
case .idle:
return nil
}
}

enum Status: Equatable {
case idle
case loading
case failed(NSError)
}
var error: NSError? {
switch status {
case .failed(let error):
return error
default:
return nil
}
}

enum Event {
case didLoad(Results)
case didFail(NSError)
case retry
case fetchNext
enum Status: Equatable {
case idle
case loading
case failed(NSError)
}
}

static func reducer() -> Reducer<State, Event> {
.init { state, event in
switch event {
case .didLoad(let batch):
state.movies += batch.results
state.status = .idle
state.batch = batch
case .didFail(let error):
state.status = .failed(error)
case .retry:
state.status = .loading
case .fetchNext:
state.status = .loading
}
}
enum Event {
case didLoad(Results)
case didFail(NSError)
case retry
case fetchNext
}

static func reducer() -> Reducer<State, Event> {
.init { state, event in
switch event {
case .didLoad(let batch):
state.movies += batch.results
state.status = .idle
state.batch = batch
case .didFail(let error):
state.status = .failed(error)
case .retry:
state.status = .loading
case .fetchNext:
state.status = .loading
}
}
}

static var feedback: Feedback<State, Event> {
if #available(iOS 15.0, *) {
return .lensing(state: \.nextPage) { page in
do {
return Event.didLoad(try await URLSession.shared.movies(page: page))
} catch {
return Event.didFail(error as NSError)
}
}
} else {
return .lensing(state: { $0.nextPage }) { page in
URLSession.shared
.fetchMovies(page: page)
.map(Event.didLoad)
.replaceError(replace: Event.didFail)
.receive(on: DispatchQueue.main)
static var feedback: Feedback<State, Event, Dependencies> {
if #available(iOS 15.0, *) {
return .lensing(state: \.nextPage) { page, dependency in
do {
return Event.didLoad(try await URLSession.shared.movies(page: page))
} catch {
return Event.didFail(error as NSError)
}
}
} else {
return .lensing(state: { $0.nextPage }) { page, dependency in
dependency.fetchMovies(page)
.map(Event.didLoad)
.replaceError(replace: Event.didFail)
.receive(on: DispatchQueue.main)
}
}

}
}
Loading

0 comments on commit d03e9ec

Please sign in to comment.