Commit 19c4ce68 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk Committed by Andreas Traczyk

vCard: add profile service

This patch introduce profile service. The service updates profiles
and post event s when new data is available.

Change-Id: I3e780cc3f19498379a49bacb20fa7faa2365705c
Reviewed-by: Andreas Traczyk's avatarAndreas Traczyk <andreas.traczyk@savoirfairelinux.com>
parent e26b621b
......@@ -135,6 +135,7 @@
0EB1A5CF1F8EBE03009923E2 /* DeviceCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0EB1A5CE1F8EBE03009923E2 /* DeviceCell.xib */; };
0EB1A5D11F8EBE23009923E2 /* DeviceCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB1A5D01F8EBE23009923E2 /* DeviceCell.swift */; };
0EB479951FA28A7300106AFD /* ButtonTransparentBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB479941FA28A7300106AFD /* ButtonTransparentBackground.swift */; };
0EBB72A92034F44200D88F46 /* ProfilesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBB72A82034F44200D88F46 /* ProfilesService.swift */; };
0EBCAA4E202E60F000E2A545 /* default.wav in Resources */ = {isa = PBXBuildFile; fileRef = 0EBCAA4D202E60F000E2A545 /* default.wav */; };
0ED2B6FA1F96A075001572F0 /* LinkNewDeviceViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0ED2B6F91F96A075001572F0 /* LinkNewDeviceViewController.storyboard */; };
0ED2B6FC1F96A158001572F0 /* LinkNewDeviceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED2B6FB1F96A158001572F0 /* LinkNewDeviceViewController.swift */; };
......@@ -416,6 +417,7 @@
0EB1A5CE1F8EBE03009923E2 /* DeviceCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DeviceCell.xib; sourceTree = "<group>"; };
0EB1A5D01F8EBE23009923E2 /* DeviceCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceCell.swift; sourceTree = "<group>"; };
0EB479941FA28A7300106AFD /* ButtonTransparentBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonTransparentBackground.swift; sourceTree = "<group>"; };
0EBB72A82034F44200D88F46 /* ProfilesService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfilesService.swift; sourceTree = "<group>"; };
0EBCAA4D202E60F000E2A545 /* default.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = default.wav; sourceTree = "<group>"; };
0ED2B6F91F96A075001572F0 /* LinkNewDeviceViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LinkNewDeviceViewController.storyboard; sourceTree = "<group>"; };
0ED2B6FB1F96A158001572F0 /* LinkNewDeviceViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinkNewDeviceViewController.swift; sourceTree = "<group>"; };
......@@ -771,6 +773,7 @@
62AA15C21FFC39C80064A063 /* VideoAdapterDelegate.swift */,
62AA15C91FFD3D7E0064A063 /* VideoService.swift */,
62AF685D201A61FF003AA9E8 /* AudioService.swift */,
0EBB72A82034F44200D88F46 /* ProfilesService.swift */,
);
path = Services;
sourceTree = "<group>";
......@@ -1762,6 +1765,7 @@
1A0C4EE51F1D67DF00550433 /* WalkthroughCoordinator.swift in Sources */,
1A2D18DD1F29192D00B2C785 /* MessableBubble.swift in Sources */,
1A5DC02E1F3565640075E8EF /* ConversationViewModel.swift in Sources */,
0EBB72A92034F44200D88F46 /* ProfilesService.swift in Sources */,
1A2D189C1F264AD900B2C785 /* UIViewController+Ring.swift in Sources */,
02C9B63F1E1D4E8C00F82F0C /* ServiceEvent.swift in Sources */,
62AA15BF1FFC36840064A063 /* VideoAdapter.mm in Sources */,
......
......@@ -40,6 +40,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
private let videoService = VideoService(withVideoAdapter: VideoAdapter())
private let audioService = AudioService(withAudioAdapter: AudioAdapter())
private let networkService = NetworkService()
private let profileService = ProfilesService()
private var conversationManager: ConversationsManager?
private var contactRequestManager: ContactRequestManager?
......@@ -55,7 +56,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
withNetworkService: self.networkService,
withCallService: self.callService,
withVideoService: self.videoService,
withAudioService: self.audioService)
withAudioService: self.audioService,
withProfileService: self.profileService)
}()
private lazy var appCoordinator: AppCoordinator = {
return AppCoordinator(with: self.injectionBag)
......
......@@ -158,7 +158,7 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
func setupBindings() {
self.viewModel.contactImageData.asObservable()
self.viewModel.contactImageData?.asObservable()
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] dataOrNil in
if let imageData = dataOrNil {
......
......@@ -37,6 +37,7 @@ class CallViewModel: Stateable, ViewModel {
fileprivate let accountService: AccountsService
fileprivate let videoService: VideoService
fileprivate let audioService: AudioService
fileprivate let profileService: ProfilesService
private let disposeBag = DisposeBag()
fileprivate let log = SwiftyBeaver.self
......@@ -49,30 +50,6 @@ class CallViewModel: Stateable, ViewModel {
guard let call = self.call else {
return
}
self.contactsService.getProfileForUri(uri: call.participantRingId)
.subscribe(onNext: { [unowned self] profile in
self.profileUpdated(profile: profile)
})
.disposed(by: self.disposeBag)
self.callService
.sharedResponseStream
.filter({ (event) in
if let uri: String = event.getEventInput(ServiceEventInput.uri) {
return event.eventType == ServiceEventType.profileUpdated
&& uri == call.participantRingId
}
return false
})
.subscribe(onNext: { [unowned self] _ in
self.contactsService.getProfileForUri(uri: call.participantRingId)
.subscribe(onNext: { profile in
self.profileUpdated(profile: profile)
})
.disposed(by: self.disposeBag)
})
.disposed(by: disposeBag)
isHeadsetConnected = self.audioService.isHeadsetConnected.value
isAudioOnly = call.isAudioOnly
......@@ -82,7 +59,22 @@ class CallViewModel: Stateable, ViewModel {
// data for ViewController binding
var contactImageData = Variable<Data?>(nil)
lazy var contactImageData: Observable<Data?>? = {
guard let call = self.call else {
return nil
}
return self.profileService.getProfile(ringId: call.participantRingId,
createIfNotexists: true)
.filter({ profile in
guard let photo = profile.photo else {
return false
}
return true
}).map({ profile in
return NSData(base64Encoded: profile.photo!,
options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data?
})
}()
lazy var incomingFrame: Observable<UIImage?> = {
return videoService.incomingVideoFrame.asObservable().map({ frame in
......@@ -277,6 +269,7 @@ class CallViewModel: Stateable, ViewModel {
self.accountService = injectionBag.accountService
self.videoService = injectionBag.videoService
self.audioService = injectionBag.audioService
self.profileService = injectionBag.profileService
}
static func formattedDurationFrom(interval: Int) -> String {
......@@ -321,17 +314,6 @@ class CallViewModel: Stateable, ViewModel {
}).disposed(by: self.disposeBag)
}
func profileUpdated(profile: Profile) {
guard let photo = profile.photo else {
return
}
guard let data = NSData(base64Encoded: photo,
options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data? else {
return
}
self.contactImageData.value = data
}
func respondOnTap() {
self.screenTapped.onNext(true)
}
......
......@@ -33,6 +33,7 @@ class InjectionBag {
let callService: CallsService
let videoService: VideoService
let audioService: AudioService
let profileService: ProfilesService
init (withDaemonService daemonService: DaemonService,
withAccountService accountService: AccountsService,
......@@ -43,7 +44,8 @@ class InjectionBag {
withNetworkService networkService: NetworkService,
withCallService callService: CallsService,
withVideoService videoService: VideoService,
withAudioService audioService: AudioService) {
withAudioService audioService: AudioService,
withProfileService profileService: ProfilesService) {
self.daemonService = daemonService
self.accountService = accountService
self.nameService = nameService
......@@ -54,6 +56,7 @@ class InjectionBag {
self.callService = callService
self.videoService = videoService
self.audioService = audioService
self.profileService = profileService
}
}
......@@ -30,40 +30,18 @@ class ContactRequestItem {
let profileImageData = Variable<Data?>(nil)
let disposeBag = DisposeBag()
init(withContactRequest contactRequest: ContactRequestModel, callService: CallsService,
init(withContactRequest contactRequest: ContactRequestModel, profileService: ProfilesService,
contactService: ContactsService) {
self.contactRequest = contactRequest
self.userName.value = contactRequest.ringId
self.profileImageData.value = self.contactRequest.vCard?.imageData
contactService.getProfileForUri(uri: contactRequest.ringId)
profileService.getProfile(ringId: contactRequest.ringId, createIfNotexists: false)
.subscribe(onNext: { [unowned self] profile in
if let photo = profile.photo,
let data = NSData(base64Encoded: photo, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data? {
self.profileImageData.value = data
}
})
.disposed(by: self.disposeBag)
callService
.sharedResponseStream
.filter({ (event) in
if let uri: String = event.getEventInput(ServiceEventInput.uri) {
return event.eventType == ServiceEventType.profileUpdated
&& uri == contactRequest.ringId
}
return false
})
.subscribe(onNext: { [unowned self] _ in
contactService.getProfileForUri(uri: contactRequest.ringId)
.subscribe(onNext: { profile in
if let photo = profile.photo,
let data = NSData(base64Encoded: photo, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data? {
let data = NSData(base64Encoded: photo,
options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data? {
self.profileImageData.value = data
}
})
.disposed(by: self.disposeBag)
})
.disposed(by: self.disposeBag)
}).disposed(by: self.disposeBag)
}
}
......@@ -35,7 +35,7 @@ class ContactRequestsViewModel: Stateable, ViewModel {
let conversationService: ConversationsService
let nameService: NameService
let presenceService: PresenceService
let callsService: CallsService
let profileService: ProfilesService
fileprivate let disposeBag = DisposeBag()
fileprivate let log = SwiftyBeaver.self
......@@ -48,7 +48,7 @@ class ContactRequestsViewModel: Stateable, ViewModel {
self.conversationService = injectionBag.conversationsService
self.nameService = injectionBag.nameService
self.presenceService = injectionBag.presenceService
self.callsService = injectionBag.callService
self.profileService = injectionBag.profileService
self.injectionBag = injectionBag
}
......@@ -62,7 +62,7 @@ class ContactRequestsViewModel: Stateable, ViewModel {
.sorted { $0.receivedDate > $1.receivedDate }
.map { contactRequest in
let item = ContactRequestItem(withContactRequest: contactRequest,
callService: self.callsService,
profileService: self.profileService,
contactService: self.contactsService)
self.lookupUserName(withItem: item)
return item
......
......@@ -36,7 +36,7 @@ class ConversationViewModel: Stateable, ViewModel {
private let nameService: NameService
private let contactsService: ContactsService
private let presenceService: PresenceService
private let callsService: CallsService
private let profileService: ProfilesService
private let injectionBag: InjectionBag
private let stateSubject = PublishSubject<State>()
......@@ -51,7 +51,7 @@ class ConversationViewModel: Stateable, ViewModel {
self.nameService = injectionBag.nameService
self.contactsService = injectionBag.contactsService
self.presenceService = injectionBag.presenceService
self.callsService = injectionBag.callService
self.profileService = injectionBag.profileService
dateFormatter.dateStyle = .medium
hourFormatter.dateFormat = "HH:mm"
......@@ -87,14 +87,7 @@ class ConversationViewModel: Stateable, ViewModel {
}).disposed(by: self.disposeBag)
let contact = self.contactsService.contact(withRingId: contactRingId)
if let profile = conversation.value.participantProfile, let photo = profile.photo {
self.displayName.value = profile.alias
if let data = NSData(base64Encoded: photo, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data? {
self.profileImageData.value = data
}
} else {
self.contactsService.loadVCard(forContactWithRingId: contactRingId)
self.contactsService.getContactRequestVCard(forContactWithRingId: contactRingId)
.subscribe(onSuccess: { vCard in
guard let imageData = vCard.imageData else {
self.log.warning("vCard for ringId: \(contactRingId) has no image")
......@@ -104,7 +97,6 @@ class ConversationViewModel: Stateable, ViewModel {
self.displayName.value = VCardUtils.getName(from: vCard)
})
.disposed(by: self.disposeBag)
}
// invite and block buttons
if let contact = contact {
......@@ -143,26 +135,15 @@ class ConversationViewModel: Stateable, ViewModel {
})
.disposed(by: disposeBag)
self.callsService
.sharedResponseStream
.filter({ (event) in
if let uri: String = event.getEventInput(ServiceEventInput.uri) {
return event.eventType == ServiceEventType.profileUpdated
&& uri == contactRingId
}
return false
})
.subscribe(onNext: { [unowned self] _ in
self.contactsService.getProfileForUri(uri: contactRingId)
.subscribe(onNext: { profile in
self.profileService.getProfile(ringId: contactRingId,
createIfNotexists: false)
.subscribe(onNext: { [unowned self] profile in
self.displayName.value = profile.alias
if let photo = profile.photo,
let data = NSData(base64Encoded: photo, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data? {
self.profileImageData.value = data
}
})
.disposed(by: self.disposeBag)
})
.disposed(by: disposeBag)
}).disposed(by: disposeBag)
if let contactUserName = contact?.userName {
self.userName.value = contactUserName
......
......@@ -41,11 +41,6 @@ enum MediaType: String, CustomStringConvertible {
}
}
struct Base64VCard {
var data: [Int: String] //The key is the number of vCard part
var partsReceived: Int
}
class CallsService: CallsAdapterDelegate {
fileprivate let disposeBag = DisposeBag()
......@@ -54,20 +49,13 @@ class CallsService: CallsAdapterDelegate {
fileprivate var calls = [String: CallModel]()
fileprivate var base64VCards = [Int: Base64VCard]() //The key is the vCard id
fileprivate let ringVCardMIMEType = "x-ring/ring.profile.vcard;"
let currentCall = ReplaySubject<CallModel>.create(bufferSize: 1)
let newCall = Variable<CallModel>(CallModel(withCallId: "", callDetails: [:]))
//let receivedVCard = PublishSubject<Profile>()
let dbManager = DBManager(profileHepler: ProfileDataHelper(), conversationHelper: ConversationDataHelper(), interactionHepler: InteractionDataHelper())
fileprivate let responseStream = PublishSubject<ServiceEvent>()
var sharedResponseStream: Observable<ServiceEvent>
init(withCallsAdapter callsAdapter: CallsAdapter) {
self.callsAdapter = callsAdapter
self.responseStream.disposed(by: disposeBag)
self.sharedResponseStream = responseStream.share()
CallsAdapter.delegate = self
NotificationCenter.default.addObserver(self, selector: #selector(self.refuseUnansweredCall(_:)),
name: NSNotification.Name(rawValue: NotificationName.refuseCallFromNotifications.rawValue),
......@@ -259,88 +247,13 @@ class CallsService: CallsAdapterDelegate {
}
}
// swiftlint:disable cyclomatic_complexity
func didReceiveMessage(withCallId callId: String, fromURI uri: String, message: [String: String]) {
if let vCardKey = message.keys.filter({ $0.hasPrefix(self.ringVCardMIMEType) }).first {
//Parse the key to get the number of parts and the current part number
let components = vCardKey.components(separatedBy: ",")
guard let partComponent = components.filter({$0.hasPrefix("part=")}).first else {
return
}
guard let ofComponent = components.filter({$0.hasPrefix("of=")}).first else {
return
}
guard let idComponent = components.filter({$0.hasPrefix("x-ring/ring.profile.vcard;id=")}).first else {
return
}
guard let part = Int(partComponent.components(separatedBy: "=")[1]) else {
return
}
guard let of = Int(ofComponent.components(separatedBy: "=")[1]) else {
return
}
guard let id = Int(idComponent.components(separatedBy: "=")[1]) else {
return
}
var numberOfReceivedChunk = 1
if var chunk = self.base64VCards[id] {
chunk.data[part] = message[vCardKey]
chunk.partsReceived += 1
numberOfReceivedChunk = chunk.partsReceived
self.base64VCards[id] = chunk
} else {
let partMessage = message[vCardKey]
let data: [Int: String] = [part: partMessage!]
let chunk = Base64VCard(data: data, partsReceived: numberOfReceivedChunk)
self.base64VCards[id] = chunk
}
//Emit the vCard when all data are appended
if of == numberOfReceivedChunk {
guard let vcard = self.base64VCards[id] else {
return
}
let vCardChunks = vcard.data
//Append data from sorted part numbers
var vCardData = Data()
for currentPartNumber in vCardChunks.keys.sorted() {
if let currentData = vCardChunks[currentPartNumber]?.data(using: String.Encoding.utf8) {
vCardData.append(currentData)
}
}
//Create the vCard, save and db and emite an event
do {
if let vCard = try CNContactVCardSerialization.contacts(with: vCardData).first {
let name = VCardUtils.getName(from: vCard)
var stringImage: String?
if let image = vCard.imageData {
stringImage = image.base64EncodedString()
}
let uri = uri.replacingOccurrences(of: "@ring.dht", with: "")
_ = self.dbManager
.createOrUpdateRingProfile(profileUri: uri,
alias: name,
image: stringImage,
status: ProfileStatus.untrasted)
var event = ServiceEvent(withEventType: .profileUpdated)
event.addEventInput(.uri, value: uri)
self.responseStream.onNext(event)
}
} catch {
self.log.error(error)
}
}
if message.keys.filter({ $0.hasPrefix(self.ringVCardMIMEType) }).first != nil {
var data = [String: Any]()
data[ProfileNotificationsKeys.ringID.rawValue] = uri
data[ProfileNotificationsKeys.message.rawValue] = message
NotificationCenter.default.post(name: NSNotification.Name(ProfileNotifications.messageReceived.rawValue), object: nil, userInfo: data)
}
}
// swiftlint:enable cyclomatic_complexity
......
......@@ -313,6 +313,21 @@ extension ContactsService: ContactsAdapterDelegate {
return vCard
}
func getContactRequestVCard(forContactWithRingId ringID: String) -> Single<CNContact> {
return Single.create(subscribe: { single in
if let contactRequest = self.contactRequest(withRingId: ringID) {
if let vCard = contactRequest.vCard {
single(.success(vCard))
} else {
single(.error(ContactServiceError.loadVCardFailed))
}
} else {
single(.error(ContactServiceError.loadVCardFailed))
}
return Disposables.create { }
})
}
func getProfileForUri(uri: String) ->Observable<Profile> {
return self.dbManager.profileObservable(for: uri, createIfNotExists: false)
.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
......
/*
* 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 RxSwift
import SwiftyBeaver
enum ProfileNotifications: String {
case messageReceived
}
enum ProfileNotificationsKeys: String {
case ringID
case message
}
struct Base64VCard {
var data: [Int: String] //The key is the number of vCard part
var partsReceived: Int
}
class ProfilesService {
fileprivate let ringVCardMIMEType = "x-ring/ring.profile.vcard;"
fileprivate var base64VCards = [Int: Base64VCard]()
fileprivate let log = SwiftyBeaver.self
var profiles = [String: ReplaySubject<Profile>]()
let dbManager = DBManager(profileHepler: ProfileDataHelper(),
conversationHelper: ConversationDataHelper(),
interactionHepler: InteractionDataHelper())
let disposeBag = DisposeBag()
init() {
NotificationCenter.default.addObserver(self, selector: #selector(self.messageReceived(_:)),
name: NSNotification.Name(rawValue: ProfileNotifications.messageReceived.rawValue),
object: nil)
}
// swiftlint:enable cyclomatic_complexity
@objc private func messageReceived(_ notification: NSNotification) {
guard let ringId = notification.userInfo?[ProfileNotificationsKeys.ringID.rawValue] as? String else {
return
}
guard let message = notification.userInfo?[ProfileNotificationsKeys.message.rawValue] as? [String: String] else {
return
}
if let vCardKey = message.keys.filter({ $0.hasPrefix(self.ringVCardMIMEType) }).first {
//Parse the key to get the number of parts and the current part number
let components = vCardKey.components(separatedBy: ",")
guard let partComponent = components.filter({$0.hasPrefix("part=")}).first else {
return
}
guard let ofComponent = components.filter({$0.hasPrefix("of=")}).first else {
return
}
guard let idComponent = components.filter({$0.hasPrefix("x-ring/ring.profile.vcard;id=")}).first else {
return
}
guard let part = Int(partComponent.components(separatedBy: "=")[1]) else {
return
}
guard let of = Int(ofComponent.components(separatedBy: "=")[1]) else {
return
}
guard let id = Int(idComponent.components(separatedBy: "=")[1]) else {
return
}
var numberOfReceivedChunk = 1
if var chunk = self.base64VCards[id] {
chunk.data[part] = message[vCardKey]
chunk.partsReceived += 1
numberOfReceivedChunk = chunk.partsReceived
self.base64VCards[id] = chunk
} else {
let partMessage = message[vCardKey]
let data: [Int: String] = [part: partMessage!]
let chunk = Base64VCard(data: data, partsReceived: numberOfReceivedChunk)
self.base64VCards[id] = chunk
}
//Build the vCard when all data are appended
if of == numberOfReceivedChunk {
self.buildVCardFromChunks(cardID: id, ringID: ringId)
}
}
}
private func buildVCardFromChunks(cardID: Int, ringID: String) {
guard let vcard = self.base64VCards[cardID] else {
return
}
let vCardChunks = vcard.data
//Append data from sorted part numbers
var vCardData = Data()
for currentPartNumber in vCardChunks.keys.sorted() {
if let currentData = vCardChunks[currentPartNumber]?.data(using: String.Encoding.utf8) {
vCardData.append(currentData)
}
}
//Create the vCard, save and db and emit a new event
do {
if let vCard = try CNContactVCardSerialization.contacts(with: vCardData).first {
let name = VCardUtils.getName(from: vCard)
var stringImage: String?
if let image = vCard.imageData {
stringImage = image.base64EncodedString()
}
let uri = ringID.replacingOccurrences(of: "@ring.dht", with: "")
_ = self.dbManager
.createOrUpdateRingProfile(profileUri: uri,
alias: name,
image: stringImage,
status: ProfileStatus.untrasted)
self.updateProfileFor(ringId: uri, createIfNotexists: false)
}
} catch {
self.log.error(error)
}
}
private func updateProfileFor(ringId: String, createIfNotexists: Bool) {
guard let profileObservable = self.profiles[ringId] else {
return
}
self.dbManager
.profileObservable(for: ringId, createIfNotExists: createIfNotexists)
.subscribe(onNext: {profile in
profileObservable.onNext(profile)
}).disposed(by: self.disposeBag)
}
func getProfile(ringId: String, createIfNotexists: Bool) -> Observable<Profile> {
if let profile = self.profiles[ringId] {
return profile.asObservable().share()
}
let profileObservable = ReplaySubject<Profile>.create(bufferSize: 1)
self.profiles[ringId] = profileObservable
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.updateProfileFor(ringId: ringId, createIfNotexists: createIfNotexists)
}
return profileObservable.share()
}
}
......@@ -36,7 +36,6 @@ enum ServiceEventType {
case contactRequestSended
case contactRequestReceived
case contactRequestDiscarded
case profileUpdated
case proxyEnabled
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment