Skip to content
Snippets Groups Projects
Commit e7668d03 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk
Browse files

db: migrate to version 2

- save profiles as vCards
- move db inside account folder

Change-Id: I023b312f1589a98d489e8e99dbf4edab4903a98c
Gitlab: #71
parent 4a1c6a51
No related branches found
No related tags found
No related merge requests found
Showing
with 384 additions and 342 deletions
/*
* Copyright (C) 2017-2019 Savoir-faire Linux Inc.
* Copyright (C) 2017-2020 Savoir-faire Linux Inc.
*
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
......@@ -21,6 +21,25 @@
import SQLite
import SwiftyBeaver
//================================================================================
// jami files structure
//
// Jami Documents folder
// └──{ account_id }
// ├── config.yml
// ├── contacts
// ├── archive.gz
// ├── incomingTrustRequests
// ├── knownDevicesNames
// ├── { account_id }.db < --conversations and interactions database
// ├── profile.vcf < --account vcard
// ├── profiles < --account contact vcards
// │ │──{ contact_uri }.vcf
// │ └── ...
// ├── ring_device.crt
// └── ring_device.key
//================================================================================
enum DataAccessError: Error {
case datastoreConnectionError
case databaseMigrationError
......@@ -32,32 +51,18 @@ final class DBContainer {
private var connections = [String: Connection?]()
var connectionsSemaphore = DispatchSemaphore(value: 1)
private let log = SwiftyBeaver.self
private let jamiDBName = "ring.db"
private let path: String?
private let dbVersion = 1
private let dbVersions = [1, 2]
init() {
path = NSSearchPathForDirectoriesInDomains(
let documentsPath = {
return NSSearchPathForDirectoriesInDomains(
.documentDirectory, .userDomainMask, true
).first
}
func getJamiDB() -> Connection? {
if jamiDB != nil {
return jamiDB
}
guard let dbPath = path else { return nil }
do {
jamiDB = try Connection("\(dbPath)/" + jamiDBName)
} catch {
jamiDB = nil
log.error("Unable to open database")
}
return jamiDB
}
}()
func removeJamiDB() {
self.removeDBNamed(dbName: jamiDBName)
func removeDBForAccount(account: String, removeFolder: Bool) {
connections[account] = nil
if !removeFolder { return }
self.removeAccountFolder(accountId: account)
}
func removeDBForAccount(account: String) {
......@@ -69,11 +74,11 @@ final class DBContainer {
if connections[account] != nil {
return connections[account] ?? nil
}
guard let dbPath = path else { return nil }
guard let dbPath = accountDbPath(accountId: account) else { return nil }
do {
self.connectionsSemaphore.wait()
connections[account] = try Connection("\(dbPath)/" + "\(account).db")
connections[account]??.userVersion = dbVersion
connections[account] = try Connection(dbPath)
connections[account]??.userVersion = dbVersions.last
self.connectionsSemaphore.signal()
return connections[account] ?? nil
} catch {
......@@ -83,24 +88,84 @@ final class DBContainer {
}
}
func isDBExistsFor(account: String) -> Bool {
guard let dbPath = path else { return false }
let url = NSURL(fileURLWithPath: dbPath)
if let pathComponent = url.appendingPathComponent("/" + "\(account).db") {
let filePath = pathComponent.path
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath) {
return false
} else {
return true
}
} else {
// MARK: paths
private func accountFolderPath(accountId: String) -> String? {
guard let documents = documentsPath else { return nil }
return documents + "/" + "\(accountId)" + "/"
}
private func accountDbPath(accountId: String) -> String? {
guard let accountFolder = accountFolderPath(accountId: accountId) else { return nil }
return accountFolder + "\(accountId).db"
}
func contactsPath(accountId: String, createIfNotExists: Bool) -> String? {
guard let accountFolder = accountFolderPath(accountId: accountId) else { return nil }
let profilesFolder = accountFolder + "profiles/"
let fileManager = FileManager.default
if fileManager.fileExists(atPath: profilesFolder) { return profilesFolder }
if !createIfNotExists { return nil }
do {
try fileManager.createDirectory(atPath: profilesFolder,
withIntermediateDirectories: true,
attributes: nil)
} catch {
return nil
}
return fileManager.fileExists(atPath: profilesFolder) ? profilesFolder : nil
}
private func isDbExists(accountId: String) -> Bool {
guard let path = accountDbPath(accountId: accountId) else { return false }
return isFileExists(path: path)
}
private func isFileExists(path: String) -> Bool {
if path.isEmpty {
return false
}
let fileManager = FileManager.default
return fileManager.fileExists(atPath: path)
}
func contactProfilePath(accountId: String, profileURI: String, createifNotExists: Bool) -> String? {
guard let profilesFolder = contactsPath(accountId: accountId,
createIfNotExists: createifNotExists) else { return nil }
return profilesFolder + "\(profileURI.toBase64()).vcf"
}
func accountProfilePath(accountId: String) -> String? {
guard let accountFolder = accountFolderPath(accountId: accountId) else { return nil }
return accountFolder + "profile.vcf"
}
func isAccountProfileExists(accountId: String) -> Bool {
guard let path = accountProfilePath(accountId: accountId) else { return false }
return isFileExists(path: path)
}
func isContactProfileExists(accountId: String, profileURI: String) -> Bool {
guard let path = contactProfilePath(accountId: accountId, profileURI: profileURI, createifNotExists: false) else { return false }
return isFileExists(path: path)
}
func isMigrationToDBv2Needed(for accountId: String) -> Bool {
if !isDbExists(accountId: accountId) { return true }
guard let dbase = self.forAccount(account: accountId) else {
return true
}
let table = Table("profiles")
do {
try _ = dbase.scalar(table.exists)
return true
} catch {
return false
}
}
private func removeDBNamed(dbName: String) {
guard let dbPath = path else { return }
guard let dbPath = documentsPath else { return }
let url = NSURL(fileURLWithPath: dbPath)
guard let pathComponent = url
.appendingPathComponent("/" + dbName) else {
......@@ -116,6 +181,50 @@ final class DBContainer {
print("Error on delete old database!!!")
}
}
func createAccountfolder(for accountId: String) {
guard let accountFolder = accountFolderPath(accountId: accountId) else { return }
let fileManager = FileManager.default
if fileManager.fileExists(atPath: accountFolder) { return }
do {
try fileManager.createDirectory(atPath: accountFolder,
withIntermediateDirectories: true,
attributes: nil)
} catch {
return
}
}
func copyDbToAccountFolder(for accountId: String) -> Bool {
if isDbExists(accountId: accountId) { return true }
guard let dbPath = documentsPath else { return false }
let url = NSURL(fileURLWithPath: dbPath)
guard let oldPath = url.appendingPathComponent("/" + "\(accountId).db") else { return false }
guard let newPath = accountDbPath(accountId: accountId) else { return false }
let fileManager = FileManager.default
do {
try fileManager.copyItem(atPath: oldPath.path, toPath: newPath)
return fileManager.fileExists(atPath: newPath)
} catch _ as NSError {
return false
}
}
func removeContacts(accountId: String) {
guard let contacts = self.contactsPath(accountId: accountId, createIfNotExists: false) else { return }
let fileManager = FileManager.default
do {
try fileManager.removeItem(atPath: contacts)
} catch _ as NSError {}
}
func removeAccountFolder(accountId: String) {
guard let account = self.accountFolderPath(accountId: accountId) else { return }
let fileManager = FileManager.default
do {
try fileManager.removeItem(atPath: account)
} catch _ as NSError {}
}
}
extension Connection {
......
......@@ -37,132 +37,33 @@ final class ProfileDataHelper {
let type = Expression<String>("type")
private let log = SwiftyBeaver.self
//migrate from legacy db
let id = Expression<Int64>("id")
func getLegacyProfileID(profileURI: String, dataBase: Connection) throws -> Int64? {
let query = contactsProfileTable.filter(uri == profileURI)
let items = try dataBase.prepare(query)
for item in items {
return item[id]
}
return nil
}
func getLegacyProfiles(accountURI: String,
accountId: String,
database: Connection) throws -> [Int64: String] {
let query = contactsProfileTable.filter(accountId != uri && accountURI != uri)
let items = try database.prepare(query)
var profiles = [Int64: String]()
for item in items {
profiles[item[id]] = item[uri]
}
return profiles
}
func migrateToDBForAccount (from oldDB: Connection,
to newDB: Connection,
jamiId: String,
accountId: String) throws {
// migrate account profile
// get account profile, it should be only one
let accountQuery = contactsProfileTable.filter(uri == jamiId)
let items = try oldDB.prepare(accountQuery)
for item in items {
let query = accountProfileTable.insert(alias <- item[alias],
photo <- item[photo])
try newDB.run(query)
}
//migrate contacts rofiles
let contactQuery = contactsProfileTable.filter((uri != jamiId) && (uri != accountId))
let rows = try oldDB.prepare(contactQuery)
for row in rows {
let query = contactsProfileTable.insert(uri <- "ring:" + row[uri],
alias <- row[alias],
photo <- row[photo],
type <- row[type])
try newDB.run(query)
}
}
func createAccountTable(accountDb: Connection) {
func dropAccountTable(accountDb: Connection) {
do {
try accountDb.run(accountProfileTable.create(ifNotExists: true) { table in
table.column(alias)
table.column(photo)
})
} catch _ {
print("Table already exists")
try accountDb.run(accountProfileTable.drop(ifExists: true))
} catch {
debugPrint(error)
}
}
func updateAccountProfile(accountAlias: String?, accountPhoto: String?, dataBase: Connection) -> Bool {
func dropProfileTable(accountDb: Connection) {
do {
if try dataBase.pluck(accountProfileTable) != nil {
try dataBase.run(accountProfileTable.update(alias <- accountAlias,
photo <- accountPhoto))
} else {
try dataBase.run(accountProfileTable.insert(alias <- accountAlias,
photo <- accountPhoto))
}
return true
try accountDb.run(contactsProfileTable.drop(ifExists: true))
} catch {
return false
debugPrint(error)
}
}
func getAccountProfile(dataBase: Connection) -> AccountProfile? {
func getAccountProfile(dataBase: Connection) -> Profile? {
do {
guard let row = try dataBase.pluck(accountProfileTable) else { return nil}
return (row[alias], row[photo])
// account profile saved in db does not have uri and type,
// return default values that need to be updated by function caller
return Profile("", row[alias], row[photo], ProfileType.ring.rawValue)
} catch {
return nil
}
}
func createContactsTable(accountDb: Connection) {
do {
try accountDb.run(contactsProfileTable.create(ifNotExists: true) { table in
table.column(uri, unique: true)
table.column(alias)
table.column(photo)
table.column(type)
})
try accountDb.run(contactsProfileTable.createIndex(uri))
} catch _ {
print("Table already exists")
}
}
func insert(item: Profile, dataBase: Connection) -> Bool {
let query = contactsProfileTable.insert(uri <- item.uri,
alias <- item.alias,
photo <- item.photo,
type <- item.type)
do {
let rowId = try dataBase.run(query)
guard rowId > 0 else {
return false
}
return true
} catch _ {
return false
}
}
func delete(item: Profile, dataBase: Connection) -> Bool {
let profileUri = item.uri
let query = contactsProfileTable.filter(uri == profileUri)
do {
let deletedRows = try dataBase.run(query.delete())
guard deletedRows == 1 else {
return false
}
return true
} catch _ {
return false
}
}
func selectAll(dataBase: Connection) throws -> [Profile]? {
var profiles = [Profile]()
let items = try dataBase.prepare(contactsProfileTable)
......@@ -172,46 +73,4 @@ final class ProfileDataHelper {
}
return profiles
}
func selectProfile(profileURI: String, dataBase: Connection) throws -> Profile? {
let query = contactsProfileTable.filter(uri == profileURI)
let items = try dataBase.prepare(query)
// for one URI we should have only one profile
for item in items {
return Profile(uri: item[uri], alias: item[alias],
photo: item[photo], type: item[type])
}
return nil
}
func insertOrUpdateProfile(item: Profile, dataBase: Connection) throws {
try dataBase.transaction {
let selectQuery = contactsProfileTable.filter(uri == item.uri)
let rows = try dataBase.run(selectQuery.update(alias <- item.alias,
photo <- item.photo))
if rows > 0 {
return
}
let insertQuery = contactsProfileTable.insert(uri <- item.uri,
alias <- item.alias,
photo <- item.photo,
type <- item.type)
let rowId = try dataBase.run(insertQuery)
guard rowId > 0 else {
throw DataAccessError.databaseError
}
}
}
func deleteAll(dataBase: Connection) -> Bool {
do {
if try dataBase.run(contactsProfileTable.delete()) > 0 {
return true
} else {
return false
}
} catch {
return false
}
}
}
This diff is collapsed.
......@@ -57,7 +57,7 @@ class EditProfileViewModel {
})
}()
var profileForCurrentAccount = PublishSubject<AccountProfile>()
var profileForCurrentAccount = PublishSubject<Profile>()
lazy var profileName: Observable<String?> = { [unowned self] in
return profileForCurrentAccount.share()
......@@ -107,9 +107,11 @@ class EditProfileViewModel {
details.set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.displayName), withValue: self.name)
account.details = details
self.accountService.setAccountDetails(forAccountId: account.id, withDetails: details)
let accountUri = AccountModelHelper.init(withAccount: account).uri ?? ""
self.profileService.updateAccountProfile(accountId: account.id,
alias: self.name,
photo: photo)
alias: self.name,
photo: photo, accountURI: accountUri)
}
func updateImage(_ image: UIImage) {
......
......@@ -30,8 +30,8 @@ enum VCardFields: String {
case photoJPEG = "PHOTO;ENCODING=BASE64;TYPE=JPEG:"
case photoPNG = "PHOTO;ENCODING=BASE64;TYPE=PNG:"
case end = "END:VCARD"
case name = "N:"
case fullName = "FN:"
case telephone = "TEL;other:"
}
extension CNContactVCardSerialization {
......@@ -42,11 +42,12 @@ extension CNContactVCardSerialization {
let beginString = VCardFields.begin.rawValue + "\n"
let entryUIDString = VCardFields.uid.rawValue + contact.identifier + "\n"
let name = contact.familyName.trimmingCharacters(in: .whitespacesAndNewlines)
let firstnameString = VCardFields.name.rawValue + name + "\n"
let phone = contact.phoneNumbers.isEmpty ? "" : contact.phoneNumbers[0].value.stringValue
let telephoneString = VCardFields.telephone.rawValue + phone + "\n"
let fullNameString = VCardFields.fullName.rawValue + name + "\n"
let endString = VCardFields.end.rawValue
var vCardString = beginString + entryUIDString + firstnameString + fullNameString + endString
var vCardString = beginString + entryUIDString + fullNameString + telephoneString + endString
// if contact have an image add it to vCard data
guard var image = contact.imageData else {
......@@ -96,6 +97,7 @@ extension CNContactVCardSerialization {
let vcard = CNMutableContact()
let name = String(nameRow.suffix(nameRow.count - 3))
vcard.familyName = name
vcard.phoneNumbers = vCard.phoneNumbers
vcard.imageData = vCard.imageData
return vcard
}
......
......@@ -131,4 +131,8 @@ extension String {
}
return fileIsImage
}
func toBase64() -> String {
return Data(self.utf8).base64EncodedString()
}
}
......@@ -55,7 +55,7 @@ class ContactRequestItem {
createIfNotexists: false,
accountId: contactRequest.accountId)
.subscribe(onNext: { [weak self] profile in
if let photo = profile.photo,
if let photo = profile.photo, !photo.isEmpty,
let data = NSData(base64Encoded: photo,
options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data? {
self?.profileImageData.value = data
......
......@@ -24,7 +24,7 @@ import RxCocoa
struct AccountItem {
let account: AccountModel
let profileObservable: Observable<AccountProfile>
let profileObservable: Observable<Profile>
}
final class AccountPickerAdapter: NSObject, UIPickerViewDataSource, UIPickerViewDelegate, RxPickerViewDataSourceType, SectionedViewDataSourceType {
......
......@@ -90,7 +90,7 @@ class SmartlistViewModel: Stateable, ViewModel, FilterConversationDataSource {
}
let injectionBag: InjectionBag
//Values need to be updated when selected account changed
var profileImageForCurrentAccount = PublishSubject<AccountProfile>()
var profileImageForCurrentAccount = PublishSubject<Profile>()
lazy var profileImage: Observable<UIImage> = { [unowned self] in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01, execute: {
......
......@@ -202,14 +202,12 @@ class AccountsService: AccountAdapterDelegate {
fileprivate func loadDatabases() -> Bool {
for account in accountList {
if dbManager.isNeedMigrationToAccountDB(accountId: account.id) {
do {
if let jamiId = AccountModelHelper
.init(withAccount: account).ringId {
try dbManager.migrateToAccountDB(accountId: account.id,
jamiId: jamiId)
}
} catch { return false}
if dbManager.isMigrationToDBv2Needed(accountId: account.id) {
if let accountURI = AccountModelHelper
.init(withAccount: account).uri {
if !dbManager.migrateToDbVersion2(accountId: account.id,
accountURI: accountURI) { return false }
}
} else {
do {
// return false if could not open database connection
......@@ -300,7 +298,7 @@ class AccountsService: AccountAdapterDelegate {
return true
}
func getAccountProfile(accountId: String) -> AccountProfile? {
func getAccountProfile(accountId: String) -> Profile? {
return self.dbManager.accountProfile(for: accountId)
}
......@@ -361,7 +359,9 @@ class AccountsService: AccountAdapterDelegate {
if try !self.dbManager.createDatabaseForAccount(accountId: accountModel.id) {
throw AddAccountError.unknownError
}
_ = self.dbManager.saveAccountProfile(alias: nil, photo: nil, accountId: accountModel.id)
let uri = JamiURI(schema: URIType.ring, infoHach: accountModel.jamiId)
let uriString = uri.uriString ?? ""
_ = self.dbManager.saveAccountProfile(alias: nil, photo: nil, accountId: accountModel.id, accountURI: uriString)
self.loadAccountsFromDaemon()
return accountModel
}.take(1)
......@@ -385,12 +385,13 @@ class AccountsService: AccountAdapterDelegate {
accountDetails.updateValue(password, forKey: ConfigKey.localPort.rawValue)
}
guard let account = self.accountAdapter.addAccount(accountDetails) else {return false}
_ = try self.dbManager.createDatabaseForAccount(accountId: account)
_ = self.dbManager.saveAccountProfile(alias: nil, photo: nil, accountId: account)
_ = try self.dbManager.createDatabaseForAccount(accountId: account, createFolder: true)
self.loadAccountsFromDaemon()
let newAccount = self.getAccount(fromAccountId: account)
guard let newAccount = self.getAccount(fromAccountId: account) else { return false }
self.currentAccount = newAccount
UserDefaults.standard.set(account, forKey: self.selectedAccountID)
let accountUri = AccountModelHelper.init(withAccount: newAccount).uri ?? ""
_ = self.dbManager.saveAccountProfile(alias: nil, photo: nil, accountId: account, accountURI: accountUri)
return true
} catch {
return false
......@@ -440,7 +441,9 @@ class AccountsService: AccountAdapterDelegate {
if try !self.dbManager.createDatabaseForAccount(accountId: accountModel.id) {
throw AddAccountError.unknownError
}
_ = self.dbManager.saveAccountProfile(alias: nil, photo: nil, accountId: accountModel.id)
let uri = JamiURI(schema: URIType.ring, infoHach: accountModel.jamiId)
let uriString = uri.uriString ?? ""
_ = self.dbManager.saveAccountProfile(alias: nil, photo: nil, accountId: accountModel.id, accountURI: uriString)
self.loadAccountsFromDaemon()
return accountModel
}.take(1)
......@@ -781,11 +784,12 @@ class AccountsService: AccountAdapterDelegate {
}
func removeAccount(id: String) {
if self.getAccount(fromAccountId: id) == nil {return}
guard let account = self.getAccount(fromAccountId: id) else {return}
let shouldRemoveFolder = AccountModelHelper.init(withAccount: account).isAccountSip()
self.accountAdapter.removeAccount(id)
self.loadAccountsFromDaemon()
if self.getAccount(fromAccountId: id) == nil {
self.dbManager.removeDBForAccount(accountId: id)
self.dbManager.removeDBForAccount(accountId: id, removeFolder: shouldRemoveFolder)
guard let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
return
}
......@@ -875,7 +879,11 @@ class AccountsService: AccountAdapterDelegate {
}
let accountDetails = getAccountDetails(fromAccountId: account)
let displayName: String? = accountDetails.get(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.displayName))
_ = self.dbManager.saveAccountProfile(alias: displayName, photo: photo, accountId: account)
guard let accountToUpdate = self.getAccount(fromAccountId: account),
let accountURI = AccountModelHelper
.init(withAccount: accountToUpdate).uri else {return}
_ = self.dbManager.saveAccountProfile(alias: displayName, photo: photo, accountId: account, accountURI: accountURI)
}
// MARK: Push Notifications
......
......@@ -328,25 +328,12 @@ class CallsService: CallsAdapterDelegate {
if accountID.isEmpty || callID.isEmpty {
return
}
guard let accountProfile = self.dbManager.accountProfile(for: accountID) else {return}
let vCard = CNMutableContact()
var cardChanged = false
if let name = accountProfile.alias {
vCard.familyName = name
cardChanged = true
}
if let photo = accountProfile.photo {
vCard.imageData = NSData(base64Encoded: photo,
options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data?
cardChanged = true
}
if cardChanged {
DispatchQueue.main.async { [unowned self] in
VCardUtils.sendVCard(card: vCard,
callID: callID,
accountID: accountID,
sender: self)
}
guard let vCard = self.dbManager.accountVCard(for: accountID) else {return}
DispatchQueue.main.async { [unowned self] in
VCardUtils.sendVCard(card: vCard,
callID: callID,
accountID: accountID,
sender: self)
}
}
......
......@@ -85,7 +85,7 @@ class ContactsService {
func loadSipContacts(withAccount account: AccountModel) {
guard let profiles = self.dbManager
.getProfilesForAccount(accountID: account.id) else {return}
.getProfilesForAccount(accountId: account.id) else {return}
let contacts = profiles.map({ profile in
return ContactModel(withUri: JamiURI.init(schema: URIType.sip, infoHach: profile.uri))
})
......@@ -151,8 +151,10 @@ class ContactsService {
stringImage = image.base64EncodedString()
}
let name = VCardUtils.getName(from: contactRequest.vCard)
let uri = JamiURI(schema: URIType.ring, infoHach: contactRequest.ringId)
let uriString = uri.uriString ?? contactRequest.ringId
_ = self.dbManager
.createOrUpdateRingProfile(profileUri: contactRequest.ringId,
.createOrUpdateRingProfile(profileUri: uriString,
alias: name,
image: stringImage,
accountId: account.id)
......@@ -375,7 +377,7 @@ extension ContactsService: ContactsAdapterDelegate {
func getProfile(uri: String, accountId: String) -> Profile? {
do {
return try self.dbManager.getProfile(for: uri, createIfNotExists: false, accounId: accountId)
return try self.dbManager.getProfile(for: uri, createIfNotExists: false, accountId: accountId)
} catch {
return nil
}
......
......@@ -46,7 +46,7 @@ class ProfilesService {
fileprivate let log = SwiftyBeaver.self
var profiles = [String: ReplaySubject<Profile>]()
var accountProfiles = [String: ReplaySubject<AccountProfile>]()
var accountProfiles = [String: ReplaySubject<Profile>]()
let dbManager: DBManager
......@@ -69,7 +69,10 @@ class ProfilesService {
guard let accountId = notification.userInfo?[ProfileNotificationsKeys.accountId.rawValue] as? String else {
return
}
self.triggerProfileSignal(uri: ringId, createIfNotexists: false, accountId: accountId)
let uri = JamiURI(schema: URIType.ring, infoHach: ringId)
let uriString = uri.uriString ?? ringId
self.triggerProfileSignal(uri: uriString, createIfNotexists: false, accountId: accountId)
}
// swiftlint:disable cyclomatic_complexity
......@@ -197,13 +200,12 @@ class ProfilesService {
}
// MARK: account profile
typealias AccountProfile = (alias: String?, photo: String?)
extension ProfilesService {
func getAccountProfile(accountId: String) -> Observable<AccountProfile> {
func getAccountProfile(accountId: String) -> Observable<Profile> {
if let profile = self.accountProfiles[accountId] {
return profile.asObservable().share()
}
let profileObservable = ReplaySubject<AccountProfile>.create(bufferSize: 1)
let profileObservable = ReplaySubject<Profile>.create(bufferSize: 1)
self.accountProfiles[accountId] = profileObservable
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
self?.triggerAccountProfileSignal(accountId: accountId)
......@@ -222,10 +224,10 @@ extension ProfilesService {
}).disposed(by: self.disposeBag)
}
func updateAccountProfile(accountId: String, alias: String?, photo: String?) {
func updateAccountProfile(accountId: String, alias: String?, photo: String?, accountURI: String) {
if self.dbManager
.saveAccountProfile(alias: alias, photo: photo,
accountId: accountId) {
accountId: accountId, accountURI: accountURI) {
self.triggerAccountProfileSignal(accountId: accountId)
}
}
......
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