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

Fetch db contacts

parent 42d12de2
No related branches found
No related tags found
2 merge requests!102Release 1.0.0,!75Messenger example - contacts list
......@@ -50,7 +50,11 @@ extension AppEnvironment {
)
},
contacts: {
ContactsEnvironment()
ContactsEnvironment(
db: dbManager.getDB,
mainQueue: mainQueue,
bgQueue: bgQueue
)
},
userSearch: {
UserSearchEnvironment(
......
import AppCore
import ComposableArchitecture
import Foundation
import XCTestDynamicOverlay
import XXModels
public struct ContactsState: Equatable {
public init() {}
public init(
contacts: IdentifiedArrayOf<Contact> = []
) {
self.contacts = contacts
}
public var contacts: IdentifiedArrayOf<XXModels.Contact>
}
public enum ContactsAction: Equatable {
case start
case didFetchContacts([XXModels.Contact])
}
public struct ContactsEnvironment {
public init() {}
public init(
db: DBManagerGetDB,
mainQueue: AnySchedulerOf<DispatchQueue>,
bgQueue: AnySchedulerOf<DispatchQueue>
) {
self.db = db
self.mainQueue = mainQueue
self.bgQueue = bgQueue
}
public var db: DBManagerGetDB
public var mainQueue: AnySchedulerOf<DispatchQueue>
public var bgQueue: AnySchedulerOf<DispatchQueue>
}
#if DEBUG
extension ContactsEnvironment {
public static let unimplemented = ContactsEnvironment()
public static let unimplemented = ContactsEnvironment(
db: .unimplemented,
mainQueue: .unimplemented,
bgQueue: .unimplemented
)
}
#endif
......@@ -23,6 +49,17 @@ public let contactsReducer = Reducer<ContactsState, ContactsAction, ContactsEnvi
{ state, action, env in
switch action {
case .start:
return Effect
.catching { try env.db() }
.flatMap { $0.fetchContactsPublisher(.init()) }
.assertNoFailure()
.map(ContactsAction.didFetchContacts)
.subscribe(on: env.bgQueue)
.receive(on: env.mainQueue)
.eraseToEffect()
case .didFetchContacts(let contacts):
state.contacts = IdentifiedArray(uniqueElements: contacts)
return .none
}
}
import AppCore
import ComposableArchitecture
import SwiftUI
import XXModels
public struct ContactsView: View {
public init(store: Store<ContactsState, ContactsAction>) {
......@@ -9,13 +11,36 @@ public struct ContactsView: View {
let store: Store<ContactsState, ContactsAction>
struct ViewState: Equatable {
init(state: ContactsState) {}
var contacts: IdentifiedArrayOf<XXModels.Contact>
init(state: ContactsState) {
contacts = state.contacts
}
}
public var body: some View {
WithViewStore(store.scope(state: ViewState.init)) { viewStore in
Form {
ForEach(viewStore.contacts) { contact in
Section {
Button {
// TODO:
} label: {
HStack {
VStack(alignment: .leading, spacing: 8) {
Label(contact.username ?? "", systemImage: "person")
Label(contact.email ?? "", systemImage: "envelope")
Label(contact.phone ?? "", systemImage: "phone")
}
.font(.callout)
.tint(Color.primary)
Spacer()
Image(systemName: "chevron.forward")
}
}
ContactAuthStatusView(contact.authStatus)
}
}
}
.navigationTitle("Contacts")
.task { viewStore.send(.start) }
......@@ -28,7 +53,25 @@ public struct ContactsView_Previews: PreviewProvider {
public static var previews: some View {
NavigationView {
ContactsView(store: Store(
initialState: ContactsState(),
initialState: ContactsState(
contacts: [
.init(
id: "1".data(using: .utf8)!,
username: "John Doe",
email: "john@doe.com",
phone: "+1234567890",
authStatus: .friend
),
.init(
id: "2".data(using: .utf8)!,
username: "Alice Unknown",
authStatus: .requested
),
.init(
id: "3".data(using: .utf8)!
),
]
),
reducer: .empty,
environment: ()
))
......
import Combine
import ComposableArchitecture
import CustomDump
import XCTest
import XXModels
@testable import ContactsFeature
final class ContactsFeatureTests: XCTestCase {
......@@ -10,6 +13,35 @@ final class ContactsFeatureTests: XCTestCase {
environment: .unimplemented
)
var didFetchContacts: [XXModels.Contact.Query] = []
let contactsPublisher = PassthroughSubject<[XXModels.Contact], Error>()
store.environment.mainQueue = .immediate
store.environment.bgQueue = .immediate
store.environment.db.run = {
var db: Database = .failing
db.fetchContactsPublisher.run = { query in
didFetchContacts.append(query)
return contactsPublisher.eraseToAnyPublisher()
}
return db
}
store.send(.start)
XCTAssertNoDifference(didFetchContacts, [XXModels.Contact.Query()])
let contacts: [XXModels.Contact] = [
.init(id: "1".data(using: .utf8)!),
.init(id: "2".data(using: .utf8)!),
.init(id: "3".data(using: .utf8)!),
]
contactsPublisher.send(contacts)
store.receive(.didFetchContacts(contacts)) {
$0.contacts = IdentifiedArray(uniqueElements: contacts)
}
contactsPublisher.send(completion: .finished)
}
}
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