Skip to content

Commit

Permalink
Demo form controls
Browse files Browse the repository at this point in the history
  • Loading branch information
willbrandin committed Jan 12, 2023
1 parent da33775 commit 2cd48b8
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 26 deletions.
16 changes: 16 additions & 0 deletions Examples/CustomTcaAlert.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@
D2A11A32297082950002E8FD /* AlertDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A11A31297082950002E8FD /* AlertDemoView.swift */; };
D2A11A33297082A40002E8FD /* AlertDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A11A31297082950002E8FD /* AlertDemoView.swift */; };
D2A11A34297082A40002E8FD /* AlertDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A11A31297082950002E8FD /* AlertDemoView.swift */; };
D2BB9510297094A0007CCC6D /* DemoReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BB950F297094A0007CCC6D /* DemoReducer.swift */; };
D2BB9511297094A0007CCC6D /* DemoReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BB950F297094A0007CCC6D /* DemoReducer.swift */; };
D2BB9512297094A0007CCC6D /* DemoReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BB950F297094A0007CCC6D /* DemoReducer.swift */; };
D2BB9514297094C6007CCC6D /* DemoFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BB9513297094C6007CCC6D /* DemoFormView.swift */; };
D2BB9515297094C6007CCC6D /* DemoFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BB9513297094C6007CCC6D /* DemoFormView.swift */; };
D2BB9516297094C6007CCC6D /* DemoFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BB9513297094C6007CCC6D /* DemoFormView.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -42,6 +48,8 @@
D2A11A2429707CE10002E8FD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
D2A11A2729707CE10002E8FD /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
D2A11A31297082950002E8FD /* AlertDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertDemoView.swift; sourceTree = "<group>"; };
D2BB950F297094A0007CCC6D /* DemoReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoReducer.swift; sourceTree = "<group>"; };
D2BB9513297094C6007CCC6D /* DemoFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoFormView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -163,6 +171,8 @@
isa = PBXGroup;
children = (
D2A11A31297082950002E8FD /* AlertDemoView.swift */,
D2BB950F297094A0007CCC6D /* DemoReducer.swift */,
D2BB9513297094C6007CCC6D /* DemoFormView.swift */,
);
path = Shared;
sourceTree = "<group>";
Expand Down Expand Up @@ -313,6 +323,8 @@
buildActionMask = 2147483647;
files = (
D2A11A32297082950002E8FD /* AlertDemoView.swift in Sources */,
D2BB9514297094C6007CCC6D /* DemoFormView.swift in Sources */,
D2BB9510297094A0007CCC6D /* DemoReducer.swift in Sources */,
D2A119D3297078320002E8FD /* CustomTcaAlertApp.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -322,6 +334,8 @@
buildActionMask = 2147483647;
files = (
D2A11A33297082A40002E8FD /* AlertDemoView.swift in Sources */,
D2BB9515297094C6007CCC6D /* DemoFormView.swift in Sources */,
D2BB9511297094A0007CCC6D /* DemoReducer.swift in Sources */,
D2A11A0B29707C410002E8FD /* CustomAlertTVDemoApp.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -331,6 +345,8 @@
buildActionMask = 2147483647;
files = (
D2A11A34297082A40002E8FD /* AlertDemoView.swift in Sources */,
D2BB9516297094C6007CCC6D /* DemoFormView.swift in Sources */,
D2BB9512297094A0007CCC6D /* DemoReducer.swift in Sources */,
D2A11A2129707CE00002E8FD /* CustomAlertWatchDemoApp.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
40 changes: 21 additions & 19 deletions Examples/Shared/AlertDemoView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,37 @@ import SwiftUI
import TCACustomAlert

struct AlertDemoView: View {
private struct AlertDemoReducer: ReducerProtocol {
struct State: Equatable {
var alert: CustomTcaAlert.State = .init()
}

enum Action: Equatable {
case alert(CustomTcaAlert.Action)
}

var body: some ReducerProtocol<State, Action> {
Scope(state: \.alert, action: /Action.alert) {
CustomTcaAlert()
}
}
}

private let store = Store(
initialState: .init(),
reducer: AlertDemoReducer()
reducer: AlertDemoReducer()._printChanges()
)

var body: some View {
WithViewStore(store) { viewStore in
VStack {
Button("Present", action: { viewStore.send(.alert(.present)) })
ZStack {
FormView(
store: self.store.scope(
state: \.form,
action: AlertDemoReducer.Action.form
)
)

VStack {
Spacer()
HStack {
Spacer()
Button("Present", action: { viewStore.send(.alert(.present)) })
.padding()
Spacer()
}
.background(.thinMaterial)
}
.frame(maxWidth: .infinity)
}
.customTcaAlert(
store.scope(
state: \.alert,
state: \.alertState,
action: AlertDemoReducer.Action.alert
),
content: {
Expand Down
92 changes: 92 additions & 0 deletions Examples/Shared/DemoFormView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import ComposableArchitecture
import SwiftUI

struct FormView: View {
let store: StoreOf<AlertDemoReducer.Form>

var body: some View {
WithViewStore(store) { formViewStore in
Form {
Section {
Text("Scrim Settings")
Toggle("Dismiss on Scrim Tap", isOn: formViewStore.binding(\.$dismissOnScrimTap))
HStack {
Text("Opacity: \(formViewStore.scrimPercentage)")
Slider(
value: formViewStore.binding(\.$scrimOpacity),
in: 0.1...1,
step: 0.1
)
}
}

Section {
Text("Alert presentation starting position")
HStack {
Text("X: \(Int(formViewStore.alertStartX))")
.frame(width: 80, alignment: .leading)
Slider(
value: formViewStore.binding(\.$alertStartX),
in: -1000...1000,
step: 100
)
}
HStack {
Text("Y: \(Int(formViewStore.alertStartY))")
.frame(width: 80, alignment: .leading)
Slider(
value: formViewStore.binding(\.$alertStartY),
in: -1000...1000,
step: 100
)
}
}

Section {
Text("Alert presented position")
HStack {
Text("X: \(Int(formViewStore.alertPresentedX))")
.frame(width: 80, alignment: .leading)

Slider(
value: formViewStore.binding(\.$alertPresentedX),
in: -300...300,
step: 100
)
}
HStack {
Text("Y: \(Int(formViewStore.alertPresentedY))")
.frame(width: 80, alignment: .leading)
Slider(
value: formViewStore.binding(\.$alertPresentedY),
in: -300...300,
step: 100
)
}
}

Section {
Text("Alert dismissal ending position")
HStack {
Text("X: \(Int(formViewStore.alertEndX))")
.frame(width: 80, alignment: .leading)
Slider(
value: formViewStore.binding(\.$alertEndX),
in: -1000...1000,
step: 100
)
}
HStack {
Text("Y: \(Int(formViewStore.alertEndY))")
.frame(width: 80, alignment: .leading)
Slider(
value: formViewStore.binding(\.$alertEndY),
in: -1000...1000,
step: 100
)
}
}
}
}
}
}
78 changes: 78 additions & 0 deletions Examples/Shared/DemoReducer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import ComposableArchitecture
import SwiftUI
import TCACustomAlert

struct AlertDemoReducer: ReducerProtocol {

struct State: Equatable {

var alertState: CustomTcaAlert.State = .init()

var form: Form.State {
get {
.init(
dismissOnScrimTap: alertState.dismissOnScrimTap,
scrimOpacity: alertState.endScrimOpacity,
alertStartY: alertState.alertStartPosition.height,
alertStartX: alertState.alertStartPosition.width,
alertPresentedY: alertState.alertPresentedPosition.height,
alertPresentedX: alertState.alertPresentedPosition.width,
alertEndY: alertState.alertEndPosition.height,
alertEndX: alertState.alertEndPosition.width
)
}
set {
self.alertState.dismissOnScrimTap = newValue.dismissOnScrimTap
self.alertState.endScrimOpacity = newValue.scrimOpacity
self.alertState.alertStartPosition = .init(width: newValue.alertStartX, height: newValue.alertStartY)
self.alertState.alertPresentedPosition = .init(width: newValue.alertPresentedX, height: newValue.alertPresentedY)
self.alertState.alertEndPosition = .init(width: newValue.alertEndX, height: newValue.alertEndY)

}
}
}

enum Action: Equatable {
case alert(CustomTcaAlert.Action)
case form(Form.Action)
}

var body: some ReducerProtocol<State, Action> {
Scope(state: \.form, action: /Action.form) {
Form()
}

Scope(state: \.alertState, action: /Action.alert) {
CustomTcaAlert()
}
}

struct Form: ReducerProtocol {
struct State: Equatable {
@BindableState var dismissOnScrimTap = true
@BindableState var scrimOpacity = 0.6

@BindableState var alertStartY: CGFloat = 500
@BindableState var alertStartX: CGFloat = 500

@BindableState var alertPresentedY: CGFloat = 0
@BindableState var alertPresentedX: CGFloat = 0

@BindableState var alertEndY: CGFloat = -500
@BindableState var alertEndX: CGFloat = -500

var scrimPercentage: String {
// Simple formatting for this use case.
String(format: "%.f%%", scrimOpacity * 100)
}
}

enum Action: Equatable, BindableAction {
case binding(BindingAction<State>)
}

var body: some ReducerProtocol<State, Action> {
BindingReducer()
}
}
}
17 changes: 10 additions & 7 deletions Sources/TCACustomAlert/CustomAlert.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,25 @@ public struct CustomTcaAlert: ReducerProtocol {
public struct State: Equatable {
/// X, Y postion where the alert will appear from.
/// Defaults to bottom of the screen.
public let alertStartPosition: CGSize
public var alertStartPosition: CGSize
/// X, Y position where the alert will be when shown to the user.
/// Defaults to center of the screen.
public let alertPresentedPosition: CGSize
public var alertPresentedPosition: CGSize
/// X, Y position where the alert will dismiss towards.
/// Defaults to top of screen.
public let alertEndPosition: CGSize
public var alertEndPosition: CGSize
/// Opacity of the scrim view behind the modal.
/// Defaults to 60%.
public let endScrimOpacity: CGFloat
/// Boolean reflecting if the alert is currently presented.
public internal(set) var isPresented: Bool
public var endScrimOpacity: CGFloat
/// Boolean reflecting if tapping the scrim view will dismiss the alert.
/// Defaults to `true`.
/// Dismissal requires sending ``RealtimeAlert.Action.dismiss`` into the reducer.
public let dismissOnScrimTap: Bool
public var dismissOnScrimTap: Bool
/// Boolean reflecting if the alert is currently presented.
public internal(set) var isPresented: Bool

// Animated propertes should not be available outside
// the scope of the Reducer

internal var modalOffset: CGSize
internal var modalOpacity: CGFloat
Expand Down

0 comments on commit 2cd48b8

Please sign in to comment.