Skip to content

Commit

Permalink
Implement ViewStore (#96)
Browse files Browse the repository at this point in the history
* viewstore and withviewstore implementation

* update environment examples

* remove deprecated api

* [ci enable] [run test] [upload] remove print
  • Loading branch information
adityadaniel authored Aug 7, 2023
1 parent 2dc7bb1 commit 57a73bd
Show file tree
Hide file tree
Showing 14 changed files with 3,186 additions and 17 deletions.
8 changes: 8 additions & 0 deletions Examples/Examples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
1D6402F9284DA71E00C4F882 /* NeverEqualVC+Reducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6402F7284DA71E00C4F882 /* NeverEqualVC+Reducer.swift */; };
1D6402FA284DA71E00C4F882 /* NeverEqualVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6402F8284DA71E00C4F882 /* NeverEqualVC.swift */; };
1D6402FC284DA73400C4F882 /* NeverEqualReducerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6402FB284DA73400C4F882 /* NeverEqualReducerTests.swift */; };
22E337FA2A6FAED6001BC3EF /* BasicUsageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22E337F92A6FAED6001BC3EF /* BasicUsageView.swift */; };
22E337FC2A70F60D001BC3EF /* EnvironmentRouteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22E337FB2A70F60D001BC3EF /* EnvironmentRouteView.swift */; };
9C82D5B228EFE16200E623DF /* TimerVC+Reducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C82D5B028EFE13800E623DF /* TimerVC+Reducer.swift */; };
9C82D5B328EFE16200E623DF /* TimerVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C82D5B128EFE13800E623DF /* TimerVC.swift */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -95,6 +97,8 @@
1D6402F7284DA71E00C4F882 /* NeverEqualVC+Reducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NeverEqualVC+Reducer.swift"; sourceTree = "<group>"; };
1D6402F8284DA71E00C4F882 /* NeverEqualVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeverEqualVC.swift; sourceTree = "<group>"; };
1D6402FB284DA73400C4F882 /* NeverEqualReducerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeverEqualReducerTests.swift; sourceTree = "<group>"; };
22E337F92A6FAED6001BC3EF /* BasicUsageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicUsageView.swift; sourceTree = "<group>"; };
22E337FB2A70F60D001BC3EF /* EnvironmentRouteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnvironmentRouteView.swift; sourceTree = "<group>"; };
9C82D5B028EFE13800E623DF /* TimerVC+Reducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TimerVC+Reducer.swift"; sourceTree = "<group>"; };
9C82D5B128EFE13800E623DF /* TimerVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimerVC.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -209,6 +213,7 @@
children = (
1D43C2C02833CBA7009C1A8B /* BasicUsageVC.swift */,
1D3CEFCB283E49F300A5105A /* BasicUsage+Reducer.swift */,
22E337F92A6FAED6001BC3EF /* BasicUsageView.swift */,
);
path = "1-BasicUsage";
sourceTree = "<group>";
Expand All @@ -220,6 +225,7 @@
1D6402C92848D69300C4F882 /* EnvironmentDemoVC.swift */,
1D6402D02849855B00C4F882 /* EnvironmentDemoVC+Reducer.swift */,
1D6402D2284985B700C4F882 /* EnvironmentVC+Mock.swift */,
22E337FB2A70F60D001BC3EF /* EnvironmentRouteView.swift */,
);
path = "2-Environment";
sourceTree = "<group>";
Expand Down Expand Up @@ -414,6 +420,8 @@
buildActionMask = 2147483647;
files = (
9C82D5B228EFE16200E623DF /* TimerVC+Reducer.swift in Sources */,
22E337FA2A6FAED6001BC3EF /* BasicUsageView.swift in Sources */,
22E337FC2A70F60D001BC3EF /* EnvironmentRouteView.swift in Sources */,
9C82D5B328EFE16200E623DF /* TimerVC.swift in Sources */,
1D6402D12849855B00C4F882 /* EnvironmentDemoVC+Reducer.swift in Sources */,
1D43C2902833C36C009C1A8B /* RouteVC.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"repositoryURL": "https://github.com/pointfreeco/combine-schedulers",
"state": {
"branch": null,
"revision": "882ac01eb7ef9e36d4467eb4b1151e74fcef85ab",
"version": "0.9.1"
"revision": "ec62f32d21584214a4b27c8cee2b2ad70ab2c38a",
"version": "0.11.0"
}
},
{
Expand Down Expand Up @@ -51,8 +51,17 @@
"repositoryURL": "https://github.com/pointfreeco/swift-clocks",
"state": {
"branch": null,
"revision": "20b25ca0dd88ebfb9111ec937814ddc5a8880172",
"version": "0.2.0"
"revision": "0fbaebfc013715dab44d715a4d350ba37f297e4d",
"version": "0.4.0"
}
},
{
"package": "swift-concurrency-extras",
"repositoryURL": "https://github.com/pointfreeco/swift-concurrency-extras",
"state": {
"branch": null,
"revision": "479750bd98fac2e813fffcf2af0728b5b0085795",
"version": "0.1.1"
}
},
{
Expand All @@ -66,20 +75,20 @@
},
{
"package": "swift-dependencies",
"repositoryURL": "https://github.com/TokoFree/swift-dependencies",
"repositoryURL": "https://github.com/pointfreeco/swift-dependencies",
"state": {
"branch": "rxswift-compatible-scheduler",
"revision": "6df2e8576a9433cfd8841697b86be20aa804e37c",
"version": null
"branch": null,
"revision": "16fd42ae04c6e7f74a6a86395d04722c641cccee",
"version": "0.6.0"
}
},
{
"package": "xctest-dynamic-overlay",
"repositoryURL": "https://github.com/pointfreeco/xctest-dynamic-overlay",
"state": {
"branch": null,
"revision": "ab8c9f45843694dd16be4297e6d44c0634fd9913",
"version": "0.8.4"
"revision": "50843cbb8551db836adec2290bb4bc6bac5c1865",
"version": "0.9.0"
}
}
]
Expand Down
62 changes: 62 additions & 0 deletions Examples/Examples/1-BasicUsage/BasicUsageView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// BasicUsageView.swift
// Examples
//
// Created by daniel.istyana on 25/07/23.
//

import SwiftUI
import RxComposableArchitecture

struct BasicUsageView: View {
let store: StoreOf<Basic>

var body: some View {
WithViewStore(self.store) { viewStore in
VStack {
Text("This is a demo for Basic usage State, Action, Reducer, and how to bind it to the UI using SwiftUI")
.padding()
Spacer()
HStack(spacing: 48) {
Button {
viewStore.send(.didTapPlus)
} label: {
Label {
Text("+")
.font(.title3)
} icon: {
Image(systemName: "plus")
}
.labelStyle(.titleOnly)

}

Text("\(viewStore.number)")
.font(.largeTitle)


Button {
viewStore.send(.didTapMinus)
} label: {
Label {
Text("-")
.font(.title3)
} icon: {
Image(systemName: "plus")
}
.labelStyle(.titleOnly)

}
}
Spacer()
}

}
}
}

struct BasicUsageView_Previews: PreviewProvider {
static var previews: some View {
BasicUsageView(store: Store(initialState: Basic.State(number: 0), reducer: Basic()))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ struct Environment: ReducerProtocol {
var alertMessage: String?
var uuidString: String = "NONE"
var currentDate: Date?

var isShowingAlert: Bool {
self.alertMessage != nil
}
}

enum Action: Equatable {
Expand Down
154 changes: 154 additions & 0 deletions Examples/Examples/2-Environment/EnvironmentRouteView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
//
// EnvironmentRouteView.swift
// Examples
//
// Created by daniel.istyana on 26/07/23.
//

import RxComposableArchitecture
import SwiftUI

struct EnvironmentRouteView: View {
var body: some View {
List(EnvironmentRouteVC.Route.allCases, id: \.self) { route in
NavigationLink(route.rawValue) {
switch route {
case .live:
EnvironmentDemoView(
store: Store(
initialState: Environment.State(),
reducer: Environment()
.dependency(\.envVCEnvironment, .live)
)
)
case .mockSuccess:
EnvironmentDemoView(
store: Store(
initialState: Environment.State(),
reducer: Environment()
.dependency(\.envVCEnvironment, .mockSuccess)
)
)
case .mockFailed:
EnvironmentDemoView(
store: Store(
initialState: Environment.State(),
reducer: Environment()
.dependency(\.envVCEnvironment, .mockFailed)
)
)
case .mockRandom:
EnvironmentDemoView(
store: Store(
initialState: Environment.State(),
reducer: Environment()
.dependency(\.envVCEnvironment, .mockRandom)
)
)
}
}
}
.navigationTitle("Environment")
}
}

struct EnvironmentDemoView: View {
let store: StoreOf<Environment>
var body: some View {
WithViewStore(self.store) { viewStore in
VStack {
Text("In this example, you will learn how to use Environment. You'll also learn how to use side effect (such as networking and analytics) Because we can initialize the environment in init, you can easily swap the environment from the EnvironmentRoute.swift. You can try to change from .live to .mock")

HStack {
Text(viewStore.text)
.font(.title3)

if viewStore.isLoading {
Spacer()
ProgressView()
} else {
Spacer()
}
}
.padding(.top)

Button {
viewStore.send(.refresh)
} label: {
Text("Reload")
.font(.largeTitle)
}

RoundedRectangle(cornerRadius: 8)
.frame(height: 3)

if let date = viewStore.currentDate {
HStack {
Text(DateFormatter.convertToString(date: date))
.font(.title3)
Spacer()
}
}

Button {
viewStore.send(.getCurrentDate)
} label: {
Text("Get New Date")
.font(.largeTitle)
}


.frame(height: 3)

if viewStore.uuidString.isEmpty {
HStack {
Text("None")
.font(.title3)
Spacer()
}
} else {
HStack {
Text(viewStore.uuidString)
Spacer()
}
}

Button {
viewStore.send(.generateUUID)
} label: {
Text("Get New UUID")
.font(.largeTitle)
}
}
.alert(
isPresented: viewStore.binding(
get: \.isShowingAlert,
send: { _ in Environment.Action.dismissAlert }
), content: {
Alert(title: Text("Test"), message: Text("Test"))
}
)
.padding()
}
}
}

struct EnvironmentRouteView_Previews: PreviewProvider {
static var previews: some View {
EnvironmentDemoView(
store: Store(
initialState: Environment.State(),
reducer: Environment()
)
)
}
}

extension DateFormatter {
static func convertToString(date: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .full
dateFormatter.timeStyle = .full
return dateFormatter.string(from: date)
}
}
Loading

0 comments on commit 57a73bd

Please sign in to comment.