Commit 6f9ee90f authored by Kateryna Kostiuk's avatar Kateryna Kostiuk Committed by Andreas Traczyk

contact request: add manager

This patch introduce manager to control conversations related to contact
request interactions

Change-Id: I4e841feb052d014d06bc3f272a1f038b84b086ce
Reviewed-by: Andreas Traczyk's avatarAndreas Traczyk <andreas.traczyk@savoirfairelinux.com>
parent f24f7157
...@@ -90,6 +90,7 @@ ...@@ -90,6 +90,7 @@
0E2D5F551F9145F200D574BF /* LinkNewDeviceCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E2D5F541F9145F200D574BF /* LinkNewDeviceCell.xib */; }; 0E2D5F551F9145F200D574BF /* LinkNewDeviceCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E2D5F541F9145F200D574BF /* LinkNewDeviceCell.xib */; };
0E403F811F7D797300C80BC2 /* MessageCellGenerated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E403F801F7D797300C80BC2 /* MessageCellGenerated.swift */; }; 0E403F811F7D797300C80BC2 /* MessageCellGenerated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E403F801F7D797300C80BC2 /* MessageCellGenerated.swift */; };
0E403F831F7D79B000C80BC2 /* MessageCellGenerated.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E403F821F7D79B000C80BC2 /* MessageCellGenerated.xib */; }; 0E403F831F7D79B000C80BC2 /* MessageCellGenerated.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E403F821F7D79B000C80BC2 /* MessageCellGenerated.xib */; };
0E48F9D31FDF150700D6CC08 /* ContactRequestManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E48F9D21FDF150700D6CC08 /* ContactRequestManager.swift */; };
0E6949791FA7E71C0029B60A /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6949781FA7E71C0029B60A /* BaseViewController.swift */; }; 0E6949791FA7E71C0029B60A /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6949781FA7E71C0029B60A /* BaseViewController.swift */; };
0E983E6E1FC77C3E0082103E /* ConversationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E983E6D1FC77C3E0082103E /* ConversationModel.swift */; }; 0E983E6E1FC77C3E0082103E /* ConversationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E983E6D1FC77C3E0082103E /* ConversationModel.swift */; };
0E9D84491FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */; }; 0E9D84491FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */; };
...@@ -335,6 +336,7 @@ ...@@ -335,6 +336,7 @@
0E2D5F541F9145F200D574BF /* LinkNewDeviceCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LinkNewDeviceCell.xib; sourceTree = "<group>"; }; 0E2D5F541F9145F200D574BF /* LinkNewDeviceCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LinkNewDeviceCell.xib; sourceTree = "<group>"; };
0E403F801F7D797300C80BC2 /* MessageCellGenerated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageCellGenerated.swift; sourceTree = "<group>"; }; 0E403F801F7D797300C80BC2 /* MessageCellGenerated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageCellGenerated.swift; sourceTree = "<group>"; };
0E403F821F7D79B000C80BC2 /* MessageCellGenerated.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MessageCellGenerated.xib; sourceTree = "<group>"; }; 0E403F821F7D79B000C80BC2 /* MessageCellGenerated.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MessageCellGenerated.xib; sourceTree = "<group>"; };
0E48F9D21FDF150700D6CC08 /* ContactRequestManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactRequestManager.swift; sourceTree = "<group>"; };
0E6949781FA7E71C0029B60A /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = "<group>"; }; 0E6949781FA7E71C0029B60A /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = "<group>"; };
0E983E6D1FC77C3E0082103E /* ConversationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationModel.swift; sourceTree = "<group>"; }; 0E983E6D1FC77C3E0082103E /* ConversationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationModel.swift; sourceTree = "<group>"; };
0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatTabBarItemViewModel.swift; sourceTree = "<group>"; }; 0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatTabBarItemViewModel.swift; sourceTree = "<group>"; };
...@@ -677,6 +679,7 @@ ...@@ -677,6 +679,7 @@
62A88D3A1F6C3ACC00F8AB18 /* PresenceService.swift */, 62A88D3A1F6C3ACC00F8AB18 /* PresenceService.swift */,
62DFAB2D1F9FF0D0002D6F9C /* NetworkService.swift */, 62DFAB2D1F9FF0D0002D6F9C /* NetworkService.swift */,
0EF78DE21FD0AE3000FC6966 /* ConversationsManager.swift */, 0EF78DE21FD0AE3000FC6966 /* ConversationsManager.swift */,
0E48F9D21FDF150700D6CC08 /* ContactRequestManager.swift */,
); );
path = Services; path = Services;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -1553,6 +1556,7 @@ ...@@ -1553,6 +1556,7 @@
56AC650E1E85694D00EA1AA9 /* DesignableTextField.swift in Sources */, 56AC650E1E85694D00EA1AA9 /* DesignableTextField.swift in Sources */,
1A2D189A1F2642C000B2C785 /* NotificationCenter+Ring.swift in Sources */, 1A2D189A1F2642C000B2C785 /* NotificationCenter+Ring.swift in Sources */,
1A2D18FC1F292DAD00B2C785 /* ConversationCell.swift in Sources */, 1A2D18FC1F292DAD00B2C785 /* ConversationCell.swift in Sources */,
0E48F9D31FDF150700D6CC08 /* ContactRequestManager.swift in Sources */,
1A5DC0371F35675E0075E8EF /* ContactRequestCell.swift in Sources */, 1A5DC0371F35675E0075E8EF /* ContactRequestCell.swift in Sources */,
1A20417C1F1E56FF00C08435 /* WelcomeViewModel.swift in Sources */, 1A20417C1F1E56FF00C08435 /* WelcomeViewModel.swift in Sources */,
1A5DC03D1F35678D0075E8EF /* ContactRequestItem.swift in Sources */, 1A5DC03D1F35678D0075E8EF /* ContactRequestItem.swift in Sources */,
......
...@@ -38,6 +38,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { ...@@ -38,6 +38,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
private let presenceService = PresenceService(withPresenceAdapter: PresenceAdapter()) private let presenceService = PresenceService(withPresenceAdapter: PresenceAdapter())
private let networkService = NetworkService() private let networkService = NetworkService()
private var conversationManager: ConversationsManager? private var conversationManager: ConversationsManager?
private var contactRequestManager: ContactRequestManager?
public lazy var injectionBag: InjectionBag = { public lazy var injectionBag: InjectionBag = {
return InjectionBag(withDaemonService: self.daemonService, return InjectionBag(withDaemonService: self.daemonService,
...@@ -78,6 +79,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { ...@@ -78,6 +79,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
Chameleon.setGlobalThemeUsingPrimaryColor(UIColor.ringMain, withSecondaryColor: UIColor.ringSecondary, andContentStyle: .light) Chameleon.setGlobalThemeUsingPrimaryColor(UIColor.ringMain, withSecondaryColor: UIColor.ringSecondary, andContentStyle: .light)
Chameleon.setRingThemeUsingPrimaryColor(UIColor.ringMain, withSecondaryColor: UIColor.ringSecondary, andContentStyle: .light) Chameleon.setRingThemeUsingPrimaryColor(UIColor.ringMain, withSecondaryColor: UIColor.ringSecondary, andContentStyle: .light)
self.contactRequestManager = ContactRequestManager(accountService: self.accountService, contactService: self.contactsService, conversationService: self.conversationsService)
// load accounts during splashscreen // load accounts during splashscreen
// and ask the AppCoordinator to handle the first screen once loading is finished // and ask the AppCoordinator to handle the first screen once loading is finished
self.conversationManager = ConversationsManager(with: self.conversationsService, accountsService: self.accountService) self.conversationManager = ConversationsManager(with: self.conversationsService, accountsService: self.accountService)
......
...@@ -304,4 +304,36 @@ final class InteractionDataHelper { ...@@ -304,4 +304,36 @@ final class InteractionDataHelper {
return false return false
} }
} }
func insertIfNotExist(item: Interaction) -> Bool {
guard let dataBase = RingDB.instance.ringDB else {
return false
}
let querySelect = table.filter(accountId == item.accountID &&
conversationId == item.conversationID &&
body == item.body &&
type == item.type)
let queryInsert = table.insert(accountId <- item.accountID,
authorId <- item.authorID,
conversationId <- item.conversationID,
timestamp <- item.timestamp,
body <- item.body,
type <- item.type,
status <- item.status,
daemonId <- item.daemonID)
do {
let rows = try dataBase.scalar(querySelect.count)
if rows == 0 {
let row = try dataBase.run(queryInsert)
guard row > 0 else {
return false
}
return true
}
} catch {
return false
}
return false
}
} }
...@@ -112,7 +112,7 @@ class DBManager { ...@@ -112,7 +112,7 @@ class DBManager {
try interactionHepler.createTable() try interactionHepler.createTable()
} }
func saveMessage(for accountUri: String, with contactUri: String, message: MessageModel, incoming: Bool) -> Completable { func saveMessage(for accountUri: String, with contactUri: String, message: MessageModel, incoming: Bool, interactionType: InteractionType) -> Completable {
//create completable which will be executed on background thread //create completable which will be executed on background thread
return Completable.create { [weak self] completable in return Completable.create { [weak self] completable in
...@@ -150,8 +150,17 @@ class DBManager { ...@@ -150,8 +150,17 @@ class DBManager {
guard let conversationID = conversationsID.first else { guard let conversationID = conversationsID.first else {
throw DBBridgingError.saveMessageFailed throw DBBridgingError.saveMessageFailed
} }
var result: Bool?
switch interactionType {
case .text:
// for now we have only one conversation between two persons(with group chat could be many) // for now we have only one conversation between two persons(with group chat could be many)
if let success = self?.addMessageTo(conversation: conversationID, account: accountProfile.id, author: author, message: message), success { result = self?.addMessageTo(conversation: conversationID, account: accountProfile.id, author: author, message: message)
case .contact:
result = self?.addInteractionContactTo(conversation: conversationID, account: accountProfile.id, author: author, message: message)
default:
result = nil
}
if let success = result, success {
completable(.completed) completable(.completed)
} else { } else {
completable(.error(DBBridgingError.saveMessageFailed)) completable(.error(DBBridgingError.saveMessageFailed))
...@@ -357,27 +366,20 @@ class DBManager { ...@@ -357,27 +366,20 @@ class DBManager {
return participants.first return participants.first
} }
private func isGenerated(message: MessageModel) -> Bool {
switch message.content {
case GeneratedMessageType.contactRequestAccepted.rawValue:
return true
case GeneratedMessageType.receivedContactRequest.rawValue:
return true
case GeneratedMessageType.sendContactRequest.rawValue:
return true
default:
return false
}
}
private func convertToMessage(interaction: Interaction, author: String) -> MessageModel? { private func convertToMessage(interaction: Interaction, author: String) -> MessageModel? {
if interaction.type != InteractionType.text.rawValue &&
interaction.type != InteractionType.contact.rawValue {
return nil
}
let date = Date(timeIntervalSince1970: TimeInterval(interaction.timestamp)) let date = Date(timeIntervalSince1970: TimeInterval(interaction.timestamp))
let message = MessageModel(withId: interaction.daemonID, let message = MessageModel(withId: interaction.daemonID,
receivedDate: date, receivedDate: date,
content: interaction.body, content: interaction.body,
author: author, author: author,
incoming: interaction.incoming) incoming: interaction.incoming)
message.isGenerated = self.isGenerated(message: message) if interaction.type == InteractionType.contact.rawValue {
message.isGenerated = true
}
if let status: InteractionStatus = InteractionStatus(rawValue: interaction.status) { if let status: InteractionStatus = InteractionStatus(rawValue: interaction.status) {
message.status = status.toMessageStatus() message.status = status.toMessageStatus()
} }
...@@ -393,10 +395,24 @@ class DBManager { ...@@ -393,10 +395,24 @@ class DBManager {
let interaction = Interaction(defaultID, accountProfileID, authorProfileID, let interaction = Interaction(defaultID, accountProfileID, authorProfileID,
conversationID, Int64(timeInterval), conversationID, Int64(timeInterval),
message.content, InteractionType.text.rawValue, message.content, InteractionType.text.rawValue,
InteractionStatus.unknown.rawValue, message.daemonId, message.incoming ) InteractionStatus.unknown.rawValue, message.daemonId,
message.incoming)
return self.interactionHepler.insert(item: interaction) return self.interactionHepler.insert(item: interaction)
} }
private func addInteractionContactTo(conversation conversationID: Int64,
account accountProfileID: Int64,
author authorProfileID: Int64,
message: MessageModel) -> Bool {
let timeInterval = message.receivedDate.timeIntervalSince1970
let interaction = Interaction(defaultID, accountProfileID, authorProfileID,
conversationID, Int64(timeInterval),
message.content, InteractionType.contact.rawValue,
InteractionStatus.read.rawValue, message.daemonId,
message.incoming)
return self.interactionHepler.insertIfNotExist(item: interaction)
}
private func getProfile(for profileUri: String, createIfNotExists: Bool) throws -> Profile? { private func getProfile(for profileUri: String, createIfNotExists: Bool) throws -> Profile? {
if let profile = try self.profileHepler.selectProfile(accountURI: profileUri) { if let profile = try self.profileHepler.selectProfile(accountURI: profileUri) {
return profile return profile
......
...@@ -49,17 +49,6 @@ class ContactRequestsViewModel: Stateable, ViewModel { ...@@ -49,17 +49,6 @@ class ContactRequestsViewModel: Stateable, ViewModel {
self.presenceService = injectionBag.presenceService self.presenceService = injectionBag.presenceService
self.injectionBag = injectionBag self.injectionBag = injectionBag
self.contactsService.contactRequests
.asObservable()
.subscribe(onNext: {[unowned self] contactRequests in
guard let account = self.accountsService.currentAccount else { return }
guard let ringId = contactRequests.last?.ringId else { return }
self.conversationService.generateMessage(ofType: GeneratedMessageType.receivedContactRequest,
forRindId: ringId,
forAccount: account)
})
.disposed(by: self.disposeBag)
} }
lazy var contactRequestItems: Observable<[ContactRequestItem]> = { lazy var contactRequestItems: Observable<[ContactRequestItem]> = {
...@@ -87,25 +76,6 @@ class ContactRequestsViewModel: Stateable, ViewModel { ...@@ -87,25 +76,6 @@ class ContactRequestsViewModel: Stateable, ViewModel {
func accept(withItem item: ContactRequestItem) -> Observable<Void> { func accept(withItem item: ContactRequestItem) -> Observable<Void> {
let acceptCompleted = self.contactsService.accept(contactRequest: item.contactRequest, withAccount: self.accountsService.currentAccount!) let acceptCompleted = self.contactsService.accept(contactRequest: item.contactRequest, withAccount: self.accountsService.currentAccount!)
let accountHelper = AccountModelHelper(withAccount: self.accountsService.currentAccount!)
let message = MessageModel(withId: "",
receivedDate: Date(),
content: GeneratedMessageType.contactRequestAccepted.rawValue,
author: accountHelper.ringId!,
incoming: true)
message.isGenerated = true
self.conversationService.saveMessage(message: message,
toConversationWith: item.contactRequest.ringId,
toAccountId: (self.accountsService.currentAccount?.id)!,
toAccountUri: accountHelper.ringId!,
shouldRefreshConversations: true)
.subscribe(onCompleted: { [unowned self] in
self.log.debug("Message saved")
})
.disposed(by: disposeBag)
self.presenceService.subscribeBuddy(withAccountId: (self.accountsService.currentAccount?.id)!, self.presenceService.subscribeBuddy(withAccountId: (self.accountsService.currentAccount?.id)!,
withUri: item.contactRequest.ringId, withUri: item.contactRequest.ringId,
withFlag: true) withFlag: true)
......
...@@ -100,9 +100,7 @@ class ConversationViewModel: ViewModel { ...@@ -100,9 +100,7 @@ class ConversationViewModel: ViewModel {
.subscribe(onNext: { [unowned self] cont in .subscribe(onNext: { [unowned self] cont in
self.inviteButtonIsAvailable.onNext(!cont.confirmed) self.inviteButtonIsAvailable.onNext(!cont.confirmed)
if cont.confirmed {
self.generateMessage(ofType: GeneratedMessageType.contactRequestAccepted)
}
}).disposed(by: self.disposeBag) }).disposed(by: self.disposeBag)
// subscribe to presence updates for the conversation's associated contact // subscribe to presence updates for the conversation's associated contact
...@@ -264,15 +262,11 @@ class ConversationViewModel: ViewModel { ...@@ -264,15 +262,11 @@ class ConversationViewModel: ViewModel {
} }
func sendContactRequest() { func sendContactRequest() {
let contactExists = self.contactsService.contact(withRingId: self.conversation.value.recipientRingId) != nil ? true : false
VCardUtils.loadVCard(named: VCardFiles.myProfile.rawValue, VCardUtils.loadVCard(named: VCardFiles.myProfile.rawValue,
inFolder: VCardFolders.profile.rawValue) inFolder: VCardFolders.profile.rawValue)
.subscribe(onSuccess: { [unowned self] (card) in .subscribe(onSuccess: { [unowned self] (card) in
self.contactsService.sendContactRequest(toContactRingId: self.conversation.value.recipientRingId, vCard: card, withAccount: self.accountService.currentAccount!) self.contactsService.sendContactRequest(toContactRingId: self.conversation.value.recipientRingId, vCard: card, withAccount: self.accountService.currentAccount!)
.subscribe(onCompleted: { [unowned self] in .subscribe(onCompleted: { [unowned self] in
if !contactExists {
self.generateMessage(ofType: GeneratedMessageType.sendContactRequest)
}
self.log.info("contact request sent") self.log.info("contact request sent")
}, onError: { [unowned self] (error) in }, onError: { [unowned self] (error) in
self.log.info(error) self.log.info(error)
...@@ -280,9 +274,6 @@ class ConversationViewModel: ViewModel { ...@@ -280,9 +274,6 @@ class ConversationViewModel: ViewModel {
}) { [unowned self] error in }) { [unowned self] error in
self.contactsService.sendContactRequest(toContactRingId: self.conversation.value.recipientRingId, vCard: nil, withAccount: self.accountService.currentAccount!) self.contactsService.sendContactRequest(toContactRingId: self.conversation.value.recipientRingId, vCard: nil, withAccount: self.accountService.currentAccount!)
.subscribe(onCompleted: { [unowned self] in .subscribe(onCompleted: { [unowned self] in
if !contactExists {
self.generateMessage(ofType: GeneratedMessageType.sendContactRequest)
}
self.log.info("contact request sent") self.log.info("contact request sent")
}, onError: { [unowned self] (error) in }, onError: { [unowned self] (error) in
self.log.info(error) self.log.info(error)
...@@ -290,9 +281,4 @@ class ConversationViewModel: ViewModel { ...@@ -290,9 +281,4 @@ class ConversationViewModel: ViewModel {
}.disposed(by: self.disposeBag) }.disposed(by: self.disposeBag)
} }
func generateMessage(ofType messageType: GeneratedMessageType) {
self.conversationsService.generateMessage(ofType: messageType,
forRindId: self.conversation.value.recipientRingId,
forAccount: self.accountService.currentAccount!)
}
} }
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import Foundation
import RxSwift
class ContactRequestManager {
let accountService: AccountsService
let contactService: ContactsService
let conversationService: ConversationsService
let disposeBag = DisposeBag()
init(accountService: AccountsService, contactService: ContactsService, conversationService: ConversationsService) {
self.accountService = accountService
self.contactService = contactService
self.conversationService = conversationService
self.subscribeToContactEvents()
}
private func subscribeToContactEvents() {
self.contactService
.sharedResponseStream
.subscribe(onNext: { [unowned self] contactRequestEvent in
guard let accountID: String = contactRequestEvent.getEventInput(.accountId) else {
return
}
guard let contactRingId: String = contactRequestEvent.getEventInput(.uri) else {
return
}
guard let account = self.accountService.getAccount(fromAccountId: accountID) else {
return
}
guard let ringId = AccountModelHelper(withAccount: account).ringId else {
return
}
var shouldUpdateConversations = false
if let currentAccount = self.accountService.currentAccount {
if let currentrRingId = AccountModelHelper(withAccount: currentAccount).ringId, currentrRingId == ringId {
shouldUpdateConversations = true
}
}
var type: GeneratedMessageType
var date = Date()
if let receivedDate: Date = contactRequestEvent.getEventInput(.date) {
date = receivedDate
}
switch contactRequestEvent.eventType {
case ServiceEventType.contactAdded:
guard let contactConfirmed: Bool = contactRequestEvent.getEventInput(.state) else {
return
}
if !contactConfirmed {
return
}
type = GeneratedMessageType.contactRequestAccepted
case ServiceEventType.contactRequestSended:
type = GeneratedMessageType.sendContactRequest
case ServiceEventType.contactRequestReceived:
type = GeneratedMessageType.receivedContactRequest
default:
return
}
self.conversationService.generateMessage(ofType: type,
contactRingId: contactRingId,
accountRingId: ringId,
accountId: account.id,
date: date,
shouldUpdateConversation: shouldUpdateConversations)
})
.disposed(by: disposeBag)
}
}
...@@ -34,14 +34,20 @@ class ContactsService { ...@@ -34,14 +34,20 @@ class ContactsService {
fileprivate let contactsAdapter: ContactsAdapter fileprivate let contactsAdapter: ContactsAdapter
fileprivate let log = SwiftyBeaver.self fileprivate let log = SwiftyBeaver.self
fileprivate let disposeBag = DisposeBag()
let contactRequests = Variable([ContactRequestModel]()) let contactRequests = Variable([ContactRequestModel]())
let contacts = Variable([ContactModel]()) let contacts = Variable([ContactModel]())
let contactStatus = PublishSubject<ContactModel>() let contactStatus = PublishSubject<ContactModel>()
fileprivate let responseStream = PublishSubject<ServiceEvent>()
var sharedResponseStream: Observable<ServiceEvent>
init(withContactsAdapter contactsAdapter: ContactsAdapter) { init(withContactsAdapter contactsAdapter: ContactsAdapter) {
self.contactsAdapter = contactsAdapter self.contactsAdapter = contactsAdapter
self.responseStream.disposed(by: disposeBag)
self.sharedResponseStream = responseStream.share()
ContactsAdapter.delegate = self ContactsAdapter.delegate = self
} }
...@@ -98,6 +104,11 @@ class ContactsService { ...@@ -98,6 +104,11 @@ class ContactsService {
let success = self.contactsAdapter.acceptTrustRequest(fromContact: contactRequest.ringId, let success = self.contactsAdapter.acceptTrustRequest(fromContact: contactRequest.ringId,
withAccountId: account.id) withAccountId: account.id)
if success { if success {
var event = ServiceEvent(withEventType: .contactAdded)
event.addEventInput(.accountId, value: account.id)
event.addEventInput(.state, value: true)
event.addEventInput(.uri, value: contactRequest.ringId)
self.responseStream.onNext(event)
observable.on(.completed) observable.on(.completed)
} else { } else {
observable.on(.error(ContactServiceError.acceptTrustRequestFailed)) observable.on(.error(ContactServiceError.acceptTrustRequestFailed))
...@@ -133,6 +144,10 @@ class ContactsService { ...@@ -133,6 +144,10 @@ class ContactsService {
payload = try CNContactVCardSerialization.dataWithImageAndUUID(from: vCard, andImageCompression: 40000) payload = try CNContactVCardSerialization.dataWithImageAndUUID(from: vCard, andImageCompression: 40000)
} }
self.contactsAdapter.sendTrustRequest(toContact: ringId, payload: payload, withAccountId: account.id) self.contactsAdapter.sendTrustRequest(toContact: ringId, payload: payload, withAccountId: account.id)
var event = ServiceEvent(withEventType: .contactRequestSended)
event.addEventInput(.accountId, value: account.id)
event.addEventInput(.uri, value: ringId)
self.responseStream.onNext(event)
completable(.completed) completable(.completed)
} catch { } catch {
completable(.error(ContactServiceError.vCardSerializationFailed)) completable(.error(ContactServiceError.vCardSerializationFailed))
...@@ -204,6 +219,11 @@ extension ContactsService: ContactsAdapterDelegate { ...@@ -204,6 +219,11 @@ extension ContactsService: ContactsAdapterDelegate {
receivedDate: receivedDate, receivedDate: receivedDate,
accountId: accountId) accountId: accountId)
self.contactRequests.value.append(contactRequest) self.contactRequests.value.append(contactRequest)
var event = ServiceEvent(withEventType: .contactRequestReceived)
event.addEventInput(.accountId, value: accountId)
event.addEventInput(.uri, value: senderAccount)
event.addEventInput(.date, value: receivedDate)
self.responseStream.onNext(event)
} else { } else {
// If the contact request already exists, update it's relevant data // If the contact request already exists, update it's relevant data
if let contactRequest = self.contactRequest(withRingId: senderAccount) { if let contactRequest = self.contactRequest(withRingId: senderAccount) {
...@@ -223,6 +243,13 @@ extension ContactsService: ContactsAdapterDelegate { ...@@ -223,6 +243,13 @@ extension ContactsService: ContactsAdapterDelegate {
if contact.confirmed != confirmed { if contact.confirmed != confirmed {
contact.confirmed = confirmed contact.confirmed = confirmed
self.contactStatus.onNext(contact) self.contactStatus.onNext(contact)
if confirmed {
var event = ServiceEvent(withEventType: .contactAdded)
event.addEventInput(.state, value: confirmed)
event.addEventInput(.accountId, value: accountId)
event.addEventInput(.uri, value: uri)
self.responseStream.onNext(event)
}
} }
} }
//sync contacts with daemon contacts //sync contacts with daemon contacts
......
...@@ -149,7 +149,8 @@ class ConversationsService { ...@@ -149,7 +149,8 @@ class ConversationsService {
self.dbManager.saveMessage(for: toAccountUri, self.dbManager.saveMessage(for: toAccountUri,
with: recipientRingId, with: recipientRingId,
message: message, message: message,
incoming: message.incoming) incoming: message