Skip to content
Snippets Groups Projects
Commit 172ddcad authored by Dariusz Rybicki's avatar Dariusz Rybicki
Browse files

Implement entering new group name

parent bdc31076
No related branches found
No related tags found
2 merge requests!153Release 1.1.0,!149[Messenger example] create new group
...@@ -6,23 +6,34 @@ import XXModels ...@@ -6,23 +6,34 @@ import XXModels
public struct NewGroupComponent: ReducerProtocol { public struct NewGroupComponent: ReducerProtocol {
public struct State: Equatable { public struct State: Equatable {
public enum Field: String, Hashable {
case name
}
public init( public init(
contacts: IdentifiedArrayOf<XXModels.Contact> = [], contacts: IdentifiedArrayOf<XXModels.Contact> = [],
members: IdentifiedArrayOf<XXModels.Contact> = [] members: IdentifiedArrayOf<XXModels.Contact> = [],
name: String = "",
focusedField: Field? = nil
) { ) {
self.contacts = contacts self.contacts = contacts
self.members = members self.members = members
self.name = name
self.focusedField = focusedField
} }
public var contacts: IdentifiedArrayOf<XXModels.Contact> public var contacts: IdentifiedArrayOf<XXModels.Contact>
public var members: IdentifiedArrayOf<XXModels.Contact> public var members: IdentifiedArrayOf<XXModels.Contact>
@BindableState public var name: String
@BindableState public var focusedField: Field?
} }
public enum Action: Equatable { public enum Action: Equatable, BindableAction {
case start case start
case didFetchContacts([XXModels.Contact]) case didFetchContacts([XXModels.Contact])
case didSelectContact(XXModels.Contact) case didSelectContact(XXModels.Contact)
case didFinish case didFinish
case binding(BindingAction<State>)
} }
public init() {} public init() {}
...@@ -32,34 +43,40 @@ public struct NewGroupComponent: ReducerProtocol { ...@@ -32,34 +43,40 @@ public struct NewGroupComponent: ReducerProtocol {
@Dependency(\.app.mainQueue) var mainQueue: AnySchedulerOf<DispatchQueue> @Dependency(\.app.mainQueue) var mainQueue: AnySchedulerOf<DispatchQueue>
@Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue> @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
public func reduce(into state: inout State, action: Action) -> EffectTask<Action> { public var body: some ReducerProtocol<State, Action> {
switch action { BindingReducer()
case .start: Reduce { state, action in
let myId = try? messenger.e2e.tryGet().getContact().getId() switch action {
return Effect case .start:
.catching { try db() } let myId = try? messenger.e2e.tryGet().getContact().getId()
.flatMap { $0.fetchContactsPublisher(.init()) } return Effect
.assertNoFailure() .catching { try db() }
.map { $0.filter { $0.id != myId } } .flatMap { $0.fetchContactsPublisher(.init()) }
.map(Action.didFetchContacts) .assertNoFailure()
.subscribe(on: bgQueue) .map { $0.filter { $0.id != myId } }
.receive(on: mainQueue) .map(Action.didFetchContacts)
.eraseToEffect() .subscribe(on: bgQueue)
.receive(on: mainQueue)
.eraseToEffect()
case .didFetchContacts(let contacts): case .didFetchContacts(let contacts):
state.contacts = IdentifiedArray(uniqueElements: contacts) state.contacts = IdentifiedArray(uniqueElements: contacts)
return .none return .none
case .didSelectContact(let contact): case .didSelectContact(let contact):
if state.members.contains(contact) { if state.members.contains(contact) {
state.members.remove(contact) state.members.remove(contact)
} else { } else {
state.members.append(contact) state.members.append(contact)
} }
return .none return .none
case .didFinish: case .didFinish:
return .none return .none
case .binding(_):
return .none
}
} }
} }
} }
...@@ -12,15 +12,20 @@ public struct NewGroupView: View { ...@@ -12,15 +12,20 @@ public struct NewGroupView: View {
} }
let store: StoreOf<Component> let store: StoreOf<Component>
@FocusState var focusedField: Component.State.Field?
struct ViewState: Equatable { struct ViewState: Equatable {
init(state: Component.State) { init(state: Component.State) {
contacts = state.contacts contacts = state.contacts
members = state.members members = state.members
name = state.name
focusedField = state.focusedField
} }
var contacts: IdentifiedArrayOf<XXModels.Contact> var contacts: IdentifiedArrayOf<XXModels.Contact>
var members: IdentifiedArrayOf<XXModels.Contact> var members: IdentifiedArrayOf<XXModels.Contact>
var name: String
var focusedField: Component.State.Field?
} }
public var body: some View { public var body: some View {
...@@ -28,10 +33,13 @@ public struct NewGroupView: View { ...@@ -28,10 +33,13 @@ public struct NewGroupView: View {
Form { Form {
Section { Section {
membersView(viewStore) membersView(viewStore)
nameView(viewStore)
} }
} }
.navigationTitle("New Group") .navigationTitle("New Group")
.task { viewStore.send(.start) } .task { viewStore.send(.start) }
.onChange(of: viewStore.focusedField) { focusedField = $0 }
.onChange(of: focusedField) { viewStore.send(.set(\.$focusedField, $0)) }
} }
} }
...@@ -54,6 +62,14 @@ public struct NewGroupView: View { ...@@ -54,6 +62,14 @@ public struct NewGroupView: View {
} }
} }
} }
func nameView(_ viewStore: ViewStore) -> some View {
TextField("Group name", text: viewStore.binding(
get: \.name,
send: { .set(\.$name, $0) }
))
.focused($focusedField, equals: .name)
}
} }
#if DEBUG #if DEBUG
......
...@@ -97,6 +97,25 @@ final class NewGroupComponentTests: XCTestCase { ...@@ -97,6 +97,25 @@ final class NewGroupComponentTests: XCTestCase {
} }
} }
func testEnterGroupName() {
let store = TestStore(
initialState: NewGroupComponent.State(),
reducer: NewGroupComponent()
)
store.send(.binding(.set(\.$focusedField, .name))) {
$0.focusedField = .name
}
store.send(.binding(.set(\.$name, "My New Group"))) {
$0.name = "My New Group"
}
store.send(.binding(.set(\.$focusedField, nil))) {
$0.focusedField = nil
}
}
func testFinish() { func testFinish() {
let store = TestStore( let store = TestStore(
initialState: NewGroupComponent.State(), initialState: NewGroupComponent.State(),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment