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

Highlight my contact on the list

parent d0f0e6e0
No related branches found
No related tags found
2 merge requests!102Release 1.0.0,!75Messenger example - contacts list
This commit is part of merge request !75. Comments created here will be created in the context of that merge request.
...@@ -120,6 +120,8 @@ let package = Package( ...@@ -120,6 +120,8 @@ let package = Package(
.target(name: "ContactFeature"), .target(name: "ContactFeature"),
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"), .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
.product(name: "ComposablePresentation", package: "swift-composable-presentation"), .product(name: "ComposablePresentation", package: "swift-composable-presentation"),
.product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
.product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
.product(name: "XXModels", package: "client-ios-db"), .product(name: "XXModels", package: "client-ios-db"),
], ],
swiftSettings: swiftSettings swiftSettings: swiftSettings
......
...@@ -66,6 +66,7 @@ extension AppEnvironment { ...@@ -66,6 +66,7 @@ extension AppEnvironment {
}, },
contacts: { contacts: {
ContactsEnvironment( ContactsEnvironment(
messenger: messenger,
db: dbManager.getDB, db: dbManager.getDB,
mainQueue: mainQueue, mainQueue: mainQueue,
bgQueue: bgQueue, bgQueue: bgQueue,
......
...@@ -4,17 +4,22 @@ import ComposablePresentation ...@@ -4,17 +4,22 @@ import ComposablePresentation
import ContactFeature import ContactFeature
import Foundation import Foundation
import XCTestDynamicOverlay import XCTestDynamicOverlay
import XXClient
import XXMessengerClient
import XXModels import XXModels
public struct ContactsState: Equatable { public struct ContactsState: Equatable {
public init( public init(
contacts: IdentifiedArrayOf<Contact> = [], myId: Data? = nil,
contacts: IdentifiedArrayOf<XXModels.Contact> = [],
contact: ContactState? = nil contact: ContactState? = nil
) { ) {
self.myId = myId
self.contacts = contacts self.contacts = contacts
self.contact = contact self.contact = contact
} }
public var myId: Data?
public var contacts: IdentifiedArrayOf<XXModels.Contact> public var contacts: IdentifiedArrayOf<XXModels.Contact>
public var contact: ContactState? public var contact: ContactState?
} }
...@@ -29,17 +34,20 @@ public enum ContactsAction: Equatable { ...@@ -29,17 +34,20 @@ public enum ContactsAction: Equatable {
public struct ContactsEnvironment { public struct ContactsEnvironment {
public init( public init(
messenger: Messenger,
db: DBManagerGetDB, db: DBManagerGetDB,
mainQueue: AnySchedulerOf<DispatchQueue>, mainQueue: AnySchedulerOf<DispatchQueue>,
bgQueue: AnySchedulerOf<DispatchQueue>, bgQueue: AnySchedulerOf<DispatchQueue>,
contact: @escaping () -> ContactEnvironment contact: @escaping () -> ContactEnvironment
) { ) {
self.messenger = messenger
self.db = db self.db = db
self.mainQueue = mainQueue self.mainQueue = mainQueue
self.bgQueue = bgQueue self.bgQueue = bgQueue
self.contact = contact self.contact = contact
} }
public var messenger: Messenger
public var db: DBManagerGetDB public var db: DBManagerGetDB
public var mainQueue: AnySchedulerOf<DispatchQueue> public var mainQueue: AnySchedulerOf<DispatchQueue>
public var bgQueue: AnySchedulerOf<DispatchQueue> public var bgQueue: AnySchedulerOf<DispatchQueue>
...@@ -49,6 +57,7 @@ public struct ContactsEnvironment { ...@@ -49,6 +57,7 @@ public struct ContactsEnvironment {
#if DEBUG #if DEBUG
extension ContactsEnvironment { extension ContactsEnvironment {
public static let unimplemented = ContactsEnvironment( public static let unimplemented = ContactsEnvironment(
messenger: .unimplemented,
db: .unimplemented, db: .unimplemented,
mainQueue: .unimplemented, mainQueue: .unimplemented,
bgQueue: .unimplemented, bgQueue: .unimplemented,
...@@ -61,6 +70,7 @@ public let contactsReducer = Reducer<ContactsState, ContactsAction, ContactsEnvi ...@@ -61,6 +70,7 @@ public let contactsReducer = Reducer<ContactsState, ContactsAction, ContactsEnvi
{ state, action, env in { state, action, env in
switch action { switch action {
case .start: case .start:
state.myId = try? env.messenger.e2e.tryGet().getContact().getId()
return Effect return Effect
.catching { try env.db() } .catching { try env.db() }
.flatMap { $0.fetchContactsPublisher(.init()) } .flatMap { $0.fetchContactsPublisher(.init()) }
...@@ -70,7 +80,11 @@ public let contactsReducer = Reducer<ContactsState, ContactsAction, ContactsEnvi ...@@ -70,7 +80,11 @@ public let contactsReducer = Reducer<ContactsState, ContactsAction, ContactsEnvi
.receive(on: env.mainQueue) .receive(on: env.mainQueue)
.eraseToEffect() .eraseToEffect()
case .didFetchContacts(let contacts): case .didFetchContacts(var contacts):
if let myId = state.myId,
let myIndex = contacts.firstIndex(where: { $0.id == myId }) {
contacts.move(fromOffsets: [myIndex], toOffset: contacts.startIndex)
}
state.contacts = IdentifiedArray(uniqueElements: contacts) state.contacts = IdentifiedArray(uniqueElements: contacts)
return .none return .none
......
...@@ -13,9 +13,11 @@ public struct ContactsView: View { ...@@ -13,9 +13,11 @@ public struct ContactsView: View {
let store: Store<ContactsState, ContactsAction> let store: Store<ContactsState, ContactsAction>
struct ViewState: Equatable { struct ViewState: Equatable {
var myId: Data?
var contacts: IdentifiedArrayOf<XXModels.Contact> var contacts: IdentifiedArrayOf<XXModels.Contact>
init(state: ContactsState) { init(state: ContactsState) {
myId = state.myId
contacts = state.contacts contacts = state.contacts
} }
} }
...@@ -24,6 +26,19 @@ public struct ContactsView: View { ...@@ -24,6 +26,19 @@ public struct ContactsView: View {
WithViewStore(store.scope(state: ViewState.init)) { viewStore in WithViewStore(store.scope(state: ViewState.init)) { viewStore in
Form { Form {
ForEach(viewStore.contacts) { contact in ForEach(viewStore.contacts) { contact in
if contact.id == viewStore.myId {
Section {
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)
} header: {
Text("My contact")
}
} else {
Section { Section {
Button { Button {
viewStore.send(.contactSelected(contact)) viewStore.send(.contactSelected(contact))
...@@ -44,6 +59,7 @@ public struct ContactsView: View { ...@@ -44,6 +59,7 @@ public struct ContactsView: View {
} }
} }
} }
}
.navigationTitle("Contacts") .navigationTitle("Contacts")
.task { viewStore.send(.start) } .task { viewStore.send(.start) }
.background(NavigationLinkWithStore( .background(NavigationLinkWithStore(
......
...@@ -3,6 +3,8 @@ import ComposableArchitecture ...@@ -3,6 +3,8 @@ import ComposableArchitecture
import ContactFeature import ContactFeature
import CustomDump import CustomDump
import XCTest import XCTest
import XXClient
import XXMessengerClient
import XXModels import XXModels
@testable import ContactsFeature @testable import ContactsFeature
...@@ -14,11 +16,21 @@ final class ContactsFeatureTests: XCTestCase { ...@@ -14,11 +16,21 @@ final class ContactsFeatureTests: XCTestCase {
environment: .unimplemented environment: .unimplemented
) )
let myId = "2".data(using: .utf8)!
var didFetchContacts: [XXModels.Contact.Query] = [] var didFetchContacts: [XXModels.Contact.Query] = []
let contactsPublisher = PassthroughSubject<[XXModels.Contact], Error>() let contactsPublisher = PassthroughSubject<[XXModels.Contact], Error>()
store.environment.mainQueue = .immediate store.environment.mainQueue = .immediate
store.environment.bgQueue = .immediate store.environment.bgQueue = .immediate
store.environment.messenger.e2e.get = {
var e2e: E2E = .unimplemented
e2e.getContact.run = {
var contact: XXClient.Contact = .unimplemented(Data())
contact.getIdFromContact.run = { _ in myId }
return contact
}
return e2e
}
store.environment.db.run = { store.environment.db.run = {
var db: Database = .failing var db: Database = .failing
db.fetchContactsPublisher.run = { query in db.fetchContactsPublisher.run = { query in
...@@ -28,7 +40,9 @@ final class ContactsFeatureTests: XCTestCase { ...@@ -28,7 +40,9 @@ final class ContactsFeatureTests: XCTestCase {
return db return db
} }
store.send(.start) store.send(.start) {
$0.myId = myId
}
XCTAssertNoDifference(didFetchContacts, [XXModels.Contact.Query()]) XCTAssertNoDifference(didFetchContacts, [XXModels.Contact.Query()])
...@@ -40,7 +54,11 @@ final class ContactsFeatureTests: XCTestCase { ...@@ -40,7 +54,11 @@ final class ContactsFeatureTests: XCTestCase {
contactsPublisher.send(contacts) contactsPublisher.send(contacts)
store.receive(.didFetchContacts(contacts)) { store.receive(.didFetchContacts(contacts)) {
$0.contacts = IdentifiedArray(uniqueElements: contacts) $0.contacts = IdentifiedArray(uniqueElements: [
contacts[1],
contacts[0],
contacts[2],
])
} }
contactsPublisher.send(completion: .finished) contactsPublisher.send(completion: .finished)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment