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

Implement new group members selection

parent 3f7726d3
No related branches found
No related tags found
2 merge requests!153Release 1.1.0,!149[Messenger example] create new group
import AppCore
import ComposableArchitecture
import Foundation
import XXMessengerClient
import XXModels
public struct NewGroupComponent: ReducerProtocol {
public struct State: Equatable {
public init(
contacts: IdentifiedArrayOf<XXModels.Contact> = []
contacts: IdentifiedArrayOf<XXModels.Contact> = [],
members: IdentifiedArrayOf<XXModels.Contact> = []
) {
self.contacts = contacts
self.members = members
}
public var contacts: IdentifiedArrayOf<XXModels.Contact>
public var members: IdentifiedArrayOf<XXModels.Contact>
}
public enum Action: Equatable {
case start
case didFetchContacts([XXModels.Contact])
case didSelectContact(XXModels.Contact)
case didFinish
}
public init() {}
@Dependency(\.app.messenger) var messenger: Messenger
@Dependency(\.app.dbManager.getDB) var db: DBManagerGetDB
@Dependency(\.app.mainQueue) var mainQueue: AnySchedulerOf<DispatchQueue>
@Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
......@@ -29,10 +35,12 @@ public struct NewGroupComponent: ReducerProtocol {
public func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
switch action {
case .start:
let myId = try? messenger.e2e.tryGet().getContact().getId()
return Effect
.catching { try db() }
.flatMap { $0.fetchContactsPublisher(.init()) }
.assertNoFailure()
.map { $0.filter { $0.id != myId } }
.map(Action.didFetchContacts)
.subscribe(on: bgQueue)
.receive(on: mainQueue)
......@@ -42,6 +50,14 @@ public struct NewGroupComponent: ReducerProtocol {
state.contacts = IdentifiedArray(uniqueElements: contacts)
return .none
case .didSelectContact(let contact):
if state.members.contains(contact) {
state.members.remove(contact)
} else {
state.members.append(contact)
}
return .none
case .didFinish:
return .none
}
......
......@@ -5,6 +5,7 @@ import XXModels
public struct NewGroupView: View {
public typealias Component = NewGroupComponent
typealias ViewStore = ComposableArchitecture.ViewStore<ViewState, Component.Action>
public init(store: StoreOf<Component>) {
self.store = store
......@@ -13,18 +14,46 @@ public struct NewGroupView: View {
let store: StoreOf<Component>
struct ViewState: Equatable {
init(state: Component.State) {}
init(state: Component.State) {
contacts = state.contacts
members = state.members
}
var contacts: IdentifiedArrayOf<XXModels.Contact>
var members: IdentifiedArrayOf<XXModels.Contact>
}
public var body: some View {
WithViewStore(store, observe: ViewState.init) { viewStore in
Form {
Section {
membersView(viewStore)
}
}
.navigationTitle("New Group")
.task { viewStore.send(.start) }
}
}
func membersView(_ viewStore: ViewStore) -> some View {
NavigationLink("Members (\(viewStore.members.count))") {
Form {
ForEach(viewStore.contacts) { contact in
Button {
viewStore.send(.didSelectContact(contact))
} label: {
HStack {
Text(contact.username ?? "")
Spacer()
if viewStore.members.contains(contact) {
Image(systemName: "checkmark")
}
}
}
}
}
}
}
}
#if DEBUG
......
......@@ -2,6 +2,8 @@ import Combine
import ComposableArchitecture
import CustomDump
import XCTest
import XXClient
import XXMessengerClient
import XXModels
@testable import NewGroupFeature
......@@ -30,6 +32,15 @@ final class NewGroupComponentTests: XCTestCase {
store.dependencies.app.mainQueue = .immediate
store.dependencies.app.bgQueue = .immediate
store.dependencies.app.messenger.e2e.get = {
var e2e: E2E = .unimplemented
e2e.getContact.run = {
var contact = XXClient.Contact.unimplemented("my-contact-data".data(using: .utf8)!)
contact.getIdFromContact.run = { _ in "my-contact-id".data(using: .utf8)! }
return contact
}
return e2e
}
store.dependencies.app.dbManager.getDB.run = {
var db: Database = .unimplemented
db.fetchContactsPublisher.run = { query in
......@@ -59,6 +70,33 @@ final class NewGroupComponentTests: XCTestCase {
contactsSubject.send(completion: .finished)
}
func testSelectMembers() {
let contacts: [XXModels.Contact] = [
.init(id: "contact-1-id".data(using: .utf8)!),
.init(id: "contact-2-id".data(using: .utf8)!),
.init(id: "contact-3-id".data(using: .utf8)!),
]
let store = TestStore(
initialState: NewGroupComponent.State(
contacts: IdentifiedArray(uniqueElements: contacts)
),
reducer: NewGroupComponent()
)
store.send(.didSelectContact(contacts[0])) {
$0.members = IdentifiedArray(uniqueElements: [contacts[0]])
}
store.send(.didSelectContact(contacts[1])) {
$0.members = IdentifiedArray(uniqueElements: [contacts[0], contacts[1]])
}
store.send(.didSelectContact(contacts[0])) {
$0.members = IdentifiedArray(uniqueElements: [contacts[1]])
}
}
func testFinish() {
let store = TestStore(
initialState: NewGroupComponent.State(),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment