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
......@@ -120,6 +120,8 @@ let package = Package(
.target(name: "ContactFeature"),
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
.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"),
],
swiftSettings: swiftSettings
......
......@@ -66,6 +66,7 @@ extension AppEnvironment {
},
contacts: {
ContactsEnvironment(
messenger: messenger,
db: dbManager.getDB,
mainQueue: mainQueue,
bgQueue: bgQueue,
......
......@@ -4,17 +4,22 @@ import ComposablePresentation
import ContactFeature
import Foundation
import XCTestDynamicOverlay
import XXClient
import XXMessengerClient
import XXModels
public struct ContactsState: Equatable {
public init(
contacts: IdentifiedArrayOf<Contact> = [],
myId: Data? = nil,
contacts: IdentifiedArrayOf<XXModels.Contact> = [],
contact: ContactState? = nil
) {
self.myId = myId
self.contacts = contacts
self.contact = contact
}
public var myId: Data?
public var contacts: IdentifiedArrayOf<XXModels.Contact>
public var contact: ContactState?
}
......@@ -29,17 +34,20 @@ public enum ContactsAction: Equatable {
public struct ContactsEnvironment {
public init(
messenger: Messenger,
db: DBManagerGetDB,
mainQueue: AnySchedulerOf<DispatchQueue>,
bgQueue: AnySchedulerOf<DispatchQueue>,
contact: @escaping () -> ContactEnvironment
) {
self.messenger = messenger
self.db = db
self.mainQueue = mainQueue
self.bgQueue = bgQueue
self.contact = contact
}
public var messenger: Messenger
public var db: DBManagerGetDB
public var mainQueue: AnySchedulerOf<DispatchQueue>
public var bgQueue: AnySchedulerOf<DispatchQueue>
......@@ -49,6 +57,7 @@ public struct ContactsEnvironment {
#if DEBUG
extension ContactsEnvironment {
public static let unimplemented = ContactsEnvironment(
messenger: .unimplemented,
db: .unimplemented,
mainQueue: .unimplemented,
bgQueue: .unimplemented,
......@@ -61,6 +70,7 @@ public let contactsReducer = Reducer<ContactsState, ContactsAction, ContactsEnvi
{ state, action, env in
switch action {
case .start:
state.myId = try? env.messenger.e2e.tryGet().getContact().getId()
return Effect
.catching { try env.db() }
.flatMap { $0.fetchContactsPublisher(.init()) }
......@@ -70,7 +80,11 @@ public let contactsReducer = Reducer<ContactsState, ContactsAction, ContactsEnvi
.receive(on: env.mainQueue)
.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)
return .none
......
......@@ -13,9 +13,11 @@ public struct ContactsView: View {
let store: Store<ContactsState, ContactsAction>
struct ViewState: Equatable {
var myId: Data?
var contacts: IdentifiedArrayOf<XXModels.Contact>
init(state: ContactsState) {
myId = state.myId
contacts = state.contacts
}
}
......@@ -24,23 +26,37 @@ public struct ContactsView: View {
WithViewStore(store.scope(state: ViewState.init)) { viewStore in
Form {
ForEach(viewStore.contacts) { contact in
Section {
Button {
viewStore.send(.contactSelected(contact))
} label: {
HStack {
VStack(alignment: .leading, spacing: 8) {
Label(contact.username ?? "", systemImage: "person")
Label(contact.email ?? "", systemImage: "envelope")
Label(contact.phone ?? "", systemImage: "phone")
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 {
Button {
viewStore.send(.contactSelected(contact))
} 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")
}
.font(.callout)
.tint(Color.primary)
Spacer()
Image(systemName: "chevron.forward")
}
ContactAuthStatusView(contact.authStatus)
}
ContactAuthStatusView(contact.authStatus)
}
}
}
......
......@@ -3,6 +3,8 @@ import ComposableArchitecture
import ContactFeature
import CustomDump
import XCTest
import XXClient
import XXMessengerClient
import XXModels
@testable import ContactsFeature
......@@ -14,11 +16,21 @@ final class ContactsFeatureTests: XCTestCase {
environment: .unimplemented
)
let myId = "2".data(using: .utf8)!
var didFetchContacts: [XXModels.Contact.Query] = []
let contactsPublisher = PassthroughSubject<[XXModels.Contact], Error>()
store.environment.mainQueue = .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 = {
var db: Database = .failing
db.fetchContactsPublisher.run = { query in
......@@ -28,7 +40,9 @@ final class ContactsFeatureTests: XCTestCase {
return db
}
store.send(.start)
store.send(.start) {
$0.myId = myId
}
XCTAssertNoDifference(didFetchContacts, [XXModels.Contact.Query()])
......@@ -40,7 +54,11 @@ final class ContactsFeatureTests: XCTestCase {
contactsPublisher.send(contacts)
store.receive(.didFetchContacts(contacts)) {
$0.contacts = IdentifiedArray(uniqueElements: contacts)
$0.contacts = IdentifiedArray(uniqueElements: [
contacts[1],
contacts[0],
contacts[2],
])
}
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