Commit ac3aec8b authored by Kateryna Kostiuk's avatar Kateryna Kostiuk Committed by Andreas Traczyk

database: replace realm

This patch remove realm from conversation service, and use DBManager
for messages storage management.

Change-Id: I5bdb14ef54d587e9250686626fddec4d1e57aee4
Reviewed-by: Andreas Traczyk's avatarAndreas Traczyk <andreas.traczyk@savoirfairelinux.com>
parent 29385d27
......@@ -90,8 +90,8 @@
0E2D5F551F9145F200D574BF /* LinkNewDeviceCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E2D5F541F9145F200D574BF /* LinkNewDeviceCell.xib */; };
0E403F811F7D797300C80BC2 /* MessageCellGenerated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E403F801F7D797300C80BC2 /* MessageCellGenerated.swift */; };
0E403F831F7D79B000C80BC2 /* MessageCellGenerated.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E403F821F7D79B000C80BC2 /* MessageCellGenerated.xib */; };
0E570CB81FD5FD5A00A471B9 /* ConversationModel1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E570CB71FD5FD5A00A471B9 /* ConversationModel1.swift */; };
0E6949791FA7E71C0029B60A /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6949781FA7E71C0029B60A /* BaseViewController.swift */; };
0E983E6E1FC77C3E0082103E /* ConversationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E983E6D1FC77C3E0082103E /* ConversationModel.swift */; };
0E9D84491FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */; };
0E9D844B1FA7DBAA00C561EB /* ContactRequestTabBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9D844A1FA7DBAA00C561EB /* ContactRequestTabBarItem.swift */; };
0EB1A5CF1F8EBE03009923E2 /* DeviceCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0EB1A5CE1F8EBE03009923E2 /* DeviceCell.xib */; };
......@@ -107,6 +107,7 @@
0EE1B54E1F75ACDE00BA98EE /* CNContactVCardSerialization+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EE1B54D1F75ACDE00BA98EE /* CNContactVCardSerialization+Helpers.swift */; };
0EE1B5501F75AD4700BA98EE /* VCardUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EE1B54F1F75AD4700BA98EE /* VCardUtils.swift */; };
0EEFBA3C1F83DA21000EDBAD /* libsecp256k1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0EEFBA3B1F83DA21000EDBAD /* libsecp256k1.a */; };
0EF78DE31FD0AE3000FC6966 /* ConversationsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF78DE21FD0AE3000FC6966 /* ConversationsManager.swift */; };
1A0C4EDA1F1D4B1B00550433 /* WelcomeViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1A0C4ED91F1D4B1B00550433 /* WelcomeViewController.storyboard */; };
1A0C4EDC1F1D4B7E00550433 /* WelcomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0C4EDB1F1D4B7E00550433 /* WelcomeViewController.swift */; };
1A0C4EE31F1D673600550433 /* InjectionBag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0C4EE21F1D673600550433 /* InjectionBag.swift */; };
......@@ -142,7 +143,6 @@
1A2D18C31F29180700B2C785 /* AccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2D18BB1F29180700B2C785 /* AccountModel.swift */; };
1A2D18C41F29180700B2C785 /* ConfigKeyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2D18BC1F29180700B2C785 /* ConfigKeyModel.swift */; };
1A2D18C51F29180700B2C785 /* ContactModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2D18BD1F29180700B2C785 /* ContactModel.swift */; };
1A2D18C61F29180700B2C785 /* ConversationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2D18BE1F29180700B2C785 /* ConversationModel.swift */; };
1A2D18C71F29180700B2C785 /* DeviceModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2D18BF1F29180700B2C785 /* DeviceModel.swift */; };
1A2D18D11F29182500B2C785 /* ConversationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2D18CC1F29182500B2C785 /* ConversationViewController.swift */; };
1A2D18D81F2918EE00B2C785 /* MeDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2D18D71F2918EE00B2C785 /* MeDetailViewController.swift */; };
......@@ -335,8 +335,8 @@
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>"; };
0E403F821F7D79B000C80BC2 /* MessageCellGenerated.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MessageCellGenerated.xib; sourceTree = "<group>"; };
0E570CB71FD5FD5A00A471B9 /* ConversationModel1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationModel1.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>"; };
0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatTabBarItemViewModel.swift; sourceTree = "<group>"; };
0E9D844A1FA7DBAA00C561EB /* ContactRequestTabBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactRequestTabBarItem.swift; sourceTree = "<group>"; };
0EB1A5CE1F8EBE03009923E2 /* DeviceCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DeviceCell.xib; sourceTree = "<group>"; };
......@@ -352,6 +352,7 @@
0EE1B54D1F75ACDE00BA98EE /* CNContactVCardSerialization+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CNContactVCardSerialization+Helpers.swift"; sourceTree = "<group>"; };
0EE1B54F1F75AD4700BA98EE /* VCardUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VCardUtils.swift; sourceTree = "<group>"; };
0EEFBA3B1F83DA21000EDBAD /* libsecp256k1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecp256k1.a; path = ../DEPS/arm64/lib/libsecp256k1.a; sourceTree = "<group>"; };
0EF78DE21FD0AE3000FC6966 /* ConversationsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationsManager.swift; sourceTree = "<group>"; };
1A0C4ED91F1D4B1B00550433 /* WelcomeViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = WelcomeViewController.storyboard; path = Welcome/WelcomeViewController.storyboard; sourceTree = "<group>"; };
1A0C4EDB1F1D4B7E00550433 /* WelcomeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WelcomeViewController.swift; path = Welcome/WelcomeViewController.swift; sourceTree = "<group>"; };
1A0C4EE21F1D673600550433 /* InjectionBag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InjectionBag.swift; sourceTree = "<group>"; };
......@@ -387,7 +388,6 @@
1A2D18BB1F29180700B2C785 /* AccountModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountModel.swift; sourceTree = "<group>"; };
1A2D18BC1F29180700B2C785 /* ConfigKeyModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigKeyModel.swift; sourceTree = "<group>"; };
1A2D18BD1F29180700B2C785 /* ContactModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactModel.swift; sourceTree = "<group>"; };
1A2D18BE1F29180700B2C785 /* ConversationModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConversationModel.swift; sourceTree = "<group>"; };
1A2D18BF1F29180700B2C785 /* DeviceModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceModel.swift; sourceTree = "<group>"; };
1A2D18CC1F29182500B2C785 /* ConversationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConversationViewController.swift; sourceTree = "<group>"; };
1A2D18D71F2918EE00B2C785 /* MeDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MeDetailViewController.swift; sourceTree = "<group>"; };
......@@ -630,6 +630,7 @@
62A88D361F6C2ED400F8AB18 /* PresenceAdapterDelegate.swift */,
62A88D3A1F6C3ACC00F8AB18 /* PresenceService.swift */,
62DFAB2D1F9FF0D0002D6F9C /* NetworkService.swift */,
0EF78DE21FD0AE3000FC6966 /* ConversationsManager.swift */,
);
path = Services;
sourceTree = "<group>";
......@@ -1059,9 +1060,8 @@
1A2D18BB1F29180700B2C785 /* AccountModel.swift */,
1A2D18BC1F29180700B2C785 /* ConfigKeyModel.swift */,
1A2D18BD1F29180700B2C785 /* ContactModel.swift */,
1A2D18BE1F29180700B2C785 /* ConversationModel.swift */,
1A2D18BF1F29180700B2C785 /* DeviceModel.swift */,
0E570CB71FD5FD5A00A471B9 /* ConversationModel1.swift */,
0E983E6D1FC77C3E0082103E /* ConversationModel.swift */,
);
path = Models;
sourceTree = "<group>";
......@@ -1434,6 +1434,7 @@
1A5DC03F1F35678D0075E8EF /* ContactRequestsViewController.swift in Sources */,
1A20418B1F1EA58A00C08435 /* ViewModelBased.swift in Sources */,
1A5DC01E1F355DA70075E8EF /* ContactsAdapterDelegate.swift in Sources */,
0E983E6E1FC77C3E0082103E /* ConversationModel.swift in Sources */,
1A20418D1F1EABCC00C08435 /* StateableResponsive.swift in Sources */,
1A0C4EE51F1D67DF00550433 /* WalkthroughCoordinator.swift in Sources */,
1A2D18DD1F29192D00B2C785 /* MessableBubble.swift in Sources */,
......@@ -1449,7 +1450,6 @@
0E0FF1B51FC3947B003898C2 /* DBManager.swift in Sources */,
1A2D18E51F29197100B2C785 /* MessageAccessoryView.swift in Sources */,
0E0FF1B91FC398C5003898C2 /* InteractionDataHelper.swift in Sources */,
1A2D18C61F29180700B2C785 /* ConversationModel.swift in Sources */,
0EE1B54E1F75ACDE00BA98EE /* CNContactVCardSerialization+Helpers.swift in Sources */,
0E0FF1AA1FC3843E003898C2 /* RingDB.swift in Sources */,
56308BA71EA00E5700660275 /* NameRegistrationResponse.m in Sources */,
......@@ -1492,7 +1492,6 @@
0ED2B6FE1F96A16C001572F0 /* LinkNewDeviceViewModel.swift in Sources */,
1A3D28A91F0EBF0200B524EE /* UIView+Ring.swift in Sources */,
1A2041881F1EA1EA00C08435 /* CreateAccountViewModel.swift in Sources */,
0E570CB81FD5FD5A00A471B9 /* ConversationModel1.swift in Sources */,
62E55B6D1F758E6F00D3FEF4 /* String+Helpers.swift in Sources */,
1ABE07D21F0D8FE800D36361 /* Images.swift in Sources */,
0273C3081E0C68BF00CF00BA /* DesignableButton.swift in Sources */,
......@@ -1503,6 +1502,7 @@
56BBC9BC1ED7161200CDAF8B /* Date+Helpers.swift in Sources */,
564C44621E943DE6000F92B1 /* NameService.swift in Sources */,
1A5DC02C1F3565250075E8EF /* MeViewController.swift in Sources */,
0EF78DE31FD0AE3000FC6966 /* ConversationsManager.swift in Sources */,
1A2041801F1E903B00C08435 /* CreateProfileViewController.swift in Sources */,
0E0FF1B71FC398B3003898C2 /* ConversationDataHepler.swift in Sources */,
62DFAB2E1F9FF0D0002D6F9C /* NetworkService.swift in Sources */,
......
......@@ -21,7 +21,6 @@
*/
import UIKit
import RealmSwift
import SwiftyBeaver
import RxSwift
import Chameleon
......@@ -38,6 +37,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
private let contactsService = ContactsService(withContactsAdapter: ContactsAdapter())
private let presenceService = PresenceService(withPresenceAdapter: PresenceAdapter())
private let networkService = NetworkService()
private var conversationManager: ConversationsManager?
public lazy var injectionBag: InjectionBag = {
return InjectionBag(withDaemonService: self.daemonService,
......@@ -80,18 +80,23 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// load accounts during splashscreen
// and ask the AppCoordinator to handle the first screen once loading is finished
self.conversationManager = ConversationsManager(with: self.conversationsService, accountsService: self.accountService)
self.startDB()
self.accountService.loadAccounts().subscribe { [unowned self] (_) in
if let currentAccount = self.accountService.currentAccount {
self.contactsService.loadContacts(withAccount: currentAccount)
self.contactsService.loadContactRequests(withAccount: currentAccount)
self.presenceService.subscribeBuddies(withAccount: currentAccount, withContacts: self.contactsService.contacts.value)
if let ringID = AccountModelHelper(withAccount: currentAccount).ringId {
self.conversationManager?
.prepareConversationsForAccount(accountId: currentAccount.id, accountUri: ringID)
}
}
}.disposed(by: self.disposeBag)
self.window?.rootViewController = self.appCoordinator.rootViewController
self.window?.makeKeyAndVisible()
self.appCoordinator.start()
self.startDB()
return true
}
......
......@@ -84,6 +84,7 @@ enum DBBridgingError: Error {
case getConversationFailed
case updateMessageStatusFailed
case deleteConversationFailed
case getProfileFailed
}
enum InteractionType: String {
......@@ -127,8 +128,7 @@ class DBManager {
//use transaction to lock access to db from other threads while the following queries are executed
try dataBase.transaction {
//profile for account should be creating when creating account
guard let accountProfile = try self?.getProfile(for: accountUri, createIfNotExists: false) else {
guard let accountProfile = try self?.getProfile(for: accountUri, createIfNotExists: true) else {
throw DBBridgingError.saveMessageFailed
}
......@@ -168,7 +168,7 @@ class DBManager {
}
}
func getConversationsObservable(for accountID: String, accountURI: String) -> Observable<[ConversationModel1]> {
func getConversationsObservable(for accountID: String, accountURI: String) -> Observable<[ConversationModel]> {
return Observable.create { observable in
......@@ -205,7 +205,6 @@ class DBManager {
func setMessagesAsRead(messagesIDs: [Int64], withStatus status: MessageStatus) -> Completable {
return Completable.create { [unowned self] completable in
var success = true
for messageId in messagesIDs {
if !self.interactionHepler
......@@ -268,11 +267,25 @@ class DBManager {
}
}
func profileObservable(for profileUri: String, createIfNotExists: Bool) -> Observable<Profile> {
return Observable.create { observable in
do {
if let profile = try self.getProfile(for: profileUri, createIfNotExists: createIfNotExists) {
observable.onNext(profile)
observable.on(.completed)
}
} catch {
observable.on(.error(DBBridgingError.getProfileFailed))
}
return Disposables.create { }
}
}
// MARK: Private functions
private func buildConversationsForAccount(accountUri: String, accountID: String) throws -> [ConversationModel1] {
private func buildConversationsForAccount(accountUri: String, accountID: String) throws -> [ConversationModel] {
var conversationsToReturn = [ConversationModel1]()
var conversationsToReturn = [ConversationModel]()
guard let accountProfile = try self.getProfile(for: accountUri, createIfNotExists: false) else {
throw DBBridgingError.getConversationFailed
......@@ -295,9 +308,9 @@ class DBManager {
guard let participantProfile = try self.profileHepler.selectProfile(profileId: participant) else {
throw DBBridgingError.getConversationFailed
}
let conversationModel1 = ConversationModel1(withRecipientRingId: participantProfile.uri,
accountId: accountID)
conversationModel1.participantProfile = participantProfile
let conversationModel = ConversationModel(withRecipientRingId: participantProfile.uri,
accountId: accountID, accountUri: accountUri)
conversationModel.participantProfile = participantProfile
var messages = [MessageModel]()
guard let interactions = try self.interactionHepler
.selectInteractionsForConversationWithAccount(conversationID: conversationID,
......@@ -306,13 +319,17 @@ class DBManager {
throw DBBridgingError.getConversationFailed
}
for interaction in interactions {
if let message = self.convertToMessage(interaction: interaction, profile: participantProfile) {
var author = accountProfile.uri
if interaction.authorID == participantProfile.id {
author = participantProfile.uri
}
if let message = self.convertToMessage(interaction: interaction, author: author) {
messages.append(message)
}
}
conversationModel1.messages = messages
conversationsToReturn.append(conversationModel1)
conversationModel.messages = messages
conversationsToReturn.append(conversationModel)
}
return conversationsToReturn
}
......@@ -357,16 +374,17 @@ class DBManager {
}
}
private func convertToMessage(interaction: Interaction, profile: Profile) -> MessageModel? {
private func convertToMessage(interaction: Interaction, author: String) -> MessageModel? {
let date = Date(timeIntervalSince1970: TimeInterval(interaction.timestamp))
let message = MessageModel(withId: interaction.daemonID,
receivedDate: date,
content: interaction.body,
author: profile.uri)
author: author)
message.isGenerated = self.isGenerated(message: message)
if let status: InteractionStatus = InteractionStatus(rawValue: interaction.status) {
message.status = status.toMessageStatus()
}
message.messageId = interaction.id
return message
}
......@@ -378,7 +396,7 @@ class DBManager {
let interaction = Interaction(defaultID, accountProfileID, authorProfileID,
conversationID, Int64(timeInterval),
message.content, InteractionType.text.rawValue,
InteractionStatus.unknown.rawValue, message.id)
InteractionStatus.unknown.rawValue, message.daemonId)
return self.interactionHepler.insert(item: interaction)
}
......
......@@ -93,7 +93,10 @@ class ContactRequestsViewModel: Stateable, ViewModel {
withContent: GeneratedMessageType.contactRequestAccepted.rawValue,
byAuthor: accountHelper.ringId!,
toConversationWith: item.contactRequest.ringId,
currentAccountId: (self.accountsService.currentAccount?.id)!, generated: true)
toAccountId: (self.accountsService.currentAccount?.id)!,
toAccountUri: accountHelper.ringId!,
generated: true,
shouldRefreshConversations: true)
.subscribe(onCompleted: { [unowned self] in
self.log.debug("Message saved")
})
......@@ -155,7 +158,7 @@ class ContactRequestsViewModel: Stateable, ViewModel {
let conversationViewModel = ConversationViewModel(with: self.injectionBag)
let conversation = self.conversationService.findConversation(withRingId: ringId,
withAccountId: (accountsService.currentAccount?.id)!)
conversationViewModel.conversation = conversation
conversationViewModel.conversation = Variable<ConversationModel>(conversation!)
self.stateSubject.onNext(ConversationsState.conversationDetail(conversationViewModel: conversationViewModel))
}
}
......@@ -151,7 +151,7 @@ class ConversationViewController: UIViewController, UITextFieldDelegate, Storybo
self.tableView.register(cellType: MessageCellGenerated.self)
//Bind the TableView to the ViewModel
self.viewModel.messages.subscribe(onNext: { [weak self] (messageViewModels) in
self.viewModel.messages.asObservable().subscribe(onNext: { [weak self] (messageViewModels) in
self?.messageViewModels = messageViewModels
self?.computeSequencing()
self?.tableView.reloadData()
......@@ -452,7 +452,7 @@ class ConversationViewController: UIViewController, UITextFieldDelegate, Storybo
if scanner.scanHexInt64(&index) {
fallbackAvatar.isHidden = false
fallbackAvatar.backgroundColor = avatarColors[Int(index)]
if viewModel.conversation.recipientRingId != name {
if viewModel.conversation.value.recipientRingId != name {
fallbackAvatar.text = name.prefixString().capitalized
}
}
......@@ -468,7 +468,7 @@ class ConversationViewController: UIViewController, UITextFieldDelegate, Storybo
viewModel.userName.asObservable()
.observeOn(MainScheduler.instance)
.filter({ [weak self] userName in
return userName != self?.viewModel.conversation.recipientRingId
return userName != self?.viewModel.conversation.value.recipientRingId
})
.map { value in value.prefixString().capitalized }
.bind(to: fallbackAvatar.rx.text)
......
......@@ -21,7 +21,6 @@
import UIKit
import RxSwift
import RealmSwift
import SwiftyBeaver
class ConversationViewModel: ViewModel {
......@@ -51,25 +50,34 @@ class ConversationViewModel: ViewModel {
hourFormatter.dateFormat = "HH:mm"
}
var conversation: ConversationModel! {
var conversation: Variable<ConversationModel>! {
didSet {
//Create observable from sorted conversations and flatMap them to view models
self.messages = self.conversationsService.conversations.map({ [unowned self] conversations in
return conversations.filter({ conv in
let recipient1 = conv.recipientRingId
let recipient2 = self.conversation.recipientRingId
if recipient1 == recipient2 {
return true
}
return false
}).flatMap({ conversation in
conversation.messages.map({ [unowned self] message in
return MessageViewModel(withInjectionBag: self.injectionBag, withMessage: message)
let contactRingId = self.conversation.value.recipientRingId
self.conversationsService
.conversationsForCurrentAccount
.map({ [unowned self] conversations in
return conversations.filter({ conv in
let recipient1 = conv.recipientRingId
let recipient2 = contactRingId
if recipient1 == recipient2 {
return true
}
return false
}).map({ [weak self] conversation -> (ConversationModel) in
self?.conversation.value = conversation
return conversation
})
.flatMap({ conversation in
conversation.messages.map({ [unowned self] message in
return MessageViewModel(withInjectionBag: self.injectionBag, withMessage: message)
})
})
})
}).observeOn(MainScheduler.instance)
let contactRingId = self.conversation.recipientRingId
.observeOn(MainScheduler.instance)
.subscribe(onNext: { messageViewModel in
self.messages.value = messageViewModel
}).disposed(by: self.disposeBag)
let contact = self.contactsService.contact(withRingId: contactRingId)
......@@ -115,13 +123,11 @@ class ConversationViewModel: ViewModel {
self.userName.value = contactUserName
} else {
let recipientRingId = self.conversation.recipientRingId
// Return an observer for the username lookup
self.nameService.usernameLookupStatus
.filter({ lookupNameResponse in
return lookupNameResponse.address != nil &&
lookupNameResponse.address == recipientRingId
lookupNameResponse.address == contactRingId
}).subscribe(onNext: { [unowned self] lookupNameResponse in
if let name = lookupNameResponse.name, !name.isEmpty {
self.userName.value = name
......@@ -131,19 +137,11 @@ class ConversationViewModel: ViewModel {
}
}).disposed(by: disposeBag)
self.nameService.lookupAddress(withAccount: "", nameserver: "", address: self.conversation.recipientRingId)
self.nameService.lookupAddress(withAccount: "", nameserver: "", address: contactRingId)
}
}
}
private lazy var realm: Realm = {
guard let realm = try? Realm() else {
fatalError("Enable to instantiate Realm")
}
return realm
}()
//Displays the entire date ( for messages received before the current week )
private let dateFormatter = DateFormatter()
......@@ -152,7 +150,7 @@ class ConversationViewModel: ViewModel {
private let disposeBag = DisposeBag()
var messages: Observable<[MessageViewModel]>!
var messages = Variable([MessageViewModel]())
var userName = Variable<String>("")
......@@ -171,7 +169,8 @@ class ConversationViewModel: ViewModel {
}
var lastMessage: String {
if let lastMessage = conversation.messages.last?.content {
let messages = self.messages.value
if let lastMessage = messages.last?.content {
return lastMessage
} else {
return ""
......@@ -180,7 +179,7 @@ class ConversationViewModel: ViewModel {
var lastMessageReceivedDate: String {
guard let lastMessageDate = self.conversation.messages.last?.receivedDate else {
guard let lastMessageDate = self.conversation.value.messages.last?.receivedDate else {
return ""
}
......@@ -214,44 +213,36 @@ class ConversationViewModel: ViewModel {
}
var hideDate: Bool {
return self.conversation.messages.isEmpty
return self.conversation.value.messages.isEmpty
}
func sendMessage(withContent content: String) {
// send a contact request if this is the first message (implicitly not a contact)
if self.conversation.messages.isEmpty {
if self.conversation.value.messages.isEmpty {
self.sendContactRequest()
}
self.conversationsService
.sendMessage(withContent: content,
from: accountService.currentAccount!,
to: self.conversation.recipientRingId)
to: self.conversation.value.recipientRingId)
.subscribe(onCompleted: { [unowned self] in
self.log.debug("Message sent")
}).disposed(by: self.disposeBag)
}
fileprivate func saveMessage(withId messageId: String,
withContent content: String,
byAuthor author: String,
toConversationWith account: String,
generated: Bool) {
self.conversationsService
.saveMessage(withId: messageId,
withContent: content,
byAuthor: author,
toConversationWith: account,
currentAccountId: (accountService.currentAccount?.id)!, generated: generated)
.subscribe(onCompleted: { [unowned self] in
self.log.debug("Message saved")
})
.disposed(by: disposeBag)
}
func setMessagesAsRead() {
guard let account = self.accountService.currentAccount else {
return
}
guard let ringId = AccountModelHelper(withAccount: account).ringId else {
return
}
self.conversationsService
.setMessagesAsRead(forConversation: self.conversation)
.setMessagesAsRead(forConversation: self.conversation.value,
accountId: account.id,
accountURI: ringId)
.subscribe(onCompleted: { [unowned self] in
self.log.debug("Message set as read")
}).disposed(by: disposeBag)
......@@ -259,7 +250,7 @@ class ConversationViewModel: ViewModel {
fileprivate var unreadMessagesCount: Int {
let accountHelper = AccountModelHelper(withAccount: self.accountService.currentAccount!)
let unreadMessages = self.conversation.messages
let unreadMessages = self.conversation.value.messages
.filter({ message in
return message.status != .read && message.author != accountHelper.ringId!
})
......@@ -267,31 +258,35 @@ class ConversationViewModel: ViewModel {
}
func sendContactRequest() {
let contactExists = self.contactsService.contact(withRingId: self.conversation.recipientRingId) != nil ? true : false
VCardUtils.loadVCard(named: VCardFiles.myProfile.rawValue, inFolder: VCardFolders.profile.rawValue)
let contactExists = self.contactsService.contact(withRingId: self.conversation.value.recipientRingId) != nil ? true : false
VCardUtils.loadVCard(named: VCardFiles.myProfile.rawValue,
inFolder: VCardFolders.profile.rawValue)
.subscribe(onSuccess: { [unowned self] (card) in
self.contactsService.sendContactRequest(toContactRingId: self.conversation.recipientRingId, vCard: card, withAccount: self.accountService.currentAccount!)
.subscribe(onCompleted: {
self.contactsService.sendContactRequest(toContactRingId: self.conversation.value.recipientRingId, vCard: card, withAccount: self.accountService.currentAccount!)
.subscribe(onCompleted: { [unowned self] in
if !contactExists {
self.generateMessage(ofType: GeneratedMessageType.sendContactRequest)
}
self.log.info("contact request sent")
}, onError: { [unowned self] (error) in
self.log.info(error)
}).disposed(by: self.disposeBag)
}, onError: { [unowned self] _ in
self.contactsService.sendContactRequest(toContactRingId: self.conversation.recipientRingId, vCard: nil, withAccount: self.accountService.currentAccount!)
.subscribe(onCompleted: {
}) { [unowned self] error in
self.contactsService.sendContactRequest(toContactRingId: self.conversation.value.recipientRingId, vCard: nil, withAccount: self.accountService.currentAccount!)
.subscribe(onCompleted: { [unowned self] in
if !contactExists {
self.generateMessage(ofType: GeneratedMessageType.sendContactRequest)
}
self.log.info("contact request sent")
}, onError: { [unowned self] (error) in
self.log.info(error)
}).disposed(by: self.disposeBag)
}).disposed(by: self.disposeBag)
}.disposed(by: self.disposeBag)
}
func generateMessage(ofType messageType: GeneratedMessageType) {
self.conversationsService.generateMessage(ofType: messageType,
forRindId: self.conversation.recipientRingId,
forRindId: self.conversation.value.recipientRingId,
forAccount: self.accountService.currentAccount!)
}
}
......@@ -69,7 +69,7 @@ class MessageViewModel {
let account = self.accountService.getAccount(fromAccountId: messageUpdateEvent.getEventInput(.id)!)
let accountHelper = AccountModelHelper(withAccount: account!)
return messageUpdateEvent.eventType == ServiceEventType.messageStateChanged &&
messageUpdateEvent.getEventInput(.messageId) == self.message.id &&
messageUpdateEvent.getEventInput(.messageId) == self.message.daemonId &&
accountHelper.ringId == self.message.author
})
.subscribe(onNext: { [unowned self] messageUpdateEvent in
......@@ -89,7 +89,7 @@ class MessageViewModel {
}
var id: UInt64 {
return UInt64(self.message.id)!
return UInt64(self.message.daemonId)!
}
var status = BehaviorSubject<MessageStatus>(value: .unknown)
......
......@@ -159,7 +159,7 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
if scanner.scanHexInt64(&index) {
cell.fallbackAvatar.isHidden = false
cell.fallbackAvatar.backgroundColor = avatarColors[Int(index)]
if item.conversation.recipientRingId != name {
if item.conversation.value.recipientRingId != name {
cell.fallbackAvatar.text = name.prefixString().capitalized
}
}
......@@ -167,7 +167,7 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
item.userName.asObservable()
.observeOn(MainScheduler.instance)
.filter({ [weak item] userName in
return userName != item?.conversation.recipientRingId
return userName != item?.conversation.value.recipientRingId
})
.map { value in value.prefixString().capitalized }
.bind(to: cell.fallbackAvatar.rx.text)