Commit 40bf3d2c authored by Kateryna Kostiuk's avatar Kateryna Kostiuk

support sip account

Change-Id: I1af53252c214742bc23093c90a36ad4f4d09b9f7
parent 32ec4d2d
This diff is collapsed.
......@@ -27,6 +27,7 @@ import SwiftyBeaver
struct AccountModelHelper {
fileprivate static let ringIdPrefix = "ring:"
fileprivate static let sipIdPrefix = "sip:"
fileprivate var account: AccountModel
......@@ -145,6 +146,34 @@ struct AccountModelHelper {
}
}
public var uri: String? {
if self.account.type == AccountType.sip {
let name = self.account.details!
.get(withConfigKeyModel: ConfigKeyModel.init(withKey: .accountUsername))
let server = self.account.details!
.get(withConfigKeyModel: ConfigKeyModel.init(withKey: .accountHostname))
let port = self.account.details!
.get(withConfigKeyModel: ConfigKeyModel.init(withKey: .localPort))
var uri: String
if !name.isEmpty {
uri = AccountModelHelper.sipIdPrefix + name
if !server.isEmpty {
uri += "@" + server
if !port.isEmpty {
uri += ":" + port
}
return uri
} else {
return uri
}
}
return nil
} else {
guard let ringId = self.ringId else {return nil}
return AccountModelHelper.ringIdPrefix.appending(ringId)
}
}
public var havePassword: Bool {
let noPassword: String = self.account.details?.get(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.archiveHasPassword)) ?? "false"
return noPassword == "true" ? true : false
......
......@@ -32,24 +32,6 @@ enum VCardFiles: String {
case myProfile
}
class VCardUtils {
class func saveVCard(vCard: CNContact, withName name: String, inFolder folder: String) -> Observable<Void> {
return Observable.create { observable in
if let directoryURL = VCardUtils.getFilePath(forFile: name, inFolder: folder, createIfNotExists: true) {
do {
let data = try CNContactVCardSerialization.dataWithImageAndUUID(from: vCard, andImageCompression: nil)
try data.write(to: directoryURL)
observable.on(.completed)
} catch {
observable.on(.error(ContactServiceError.saveVCardFailed))
}
} else {
observable.on(.error(ContactServiceError.saveVCardFailed))
}
return Disposables.create { }
}
}
class func loadVCard(named name: String, inFolder folder: String, contactService: ContactsService? = nil) -> Single<CNContact> {
return Single.create(subscribe: { single in
if let contactRequest = contactService?.contactRequest(withRingId: name) {
......
......@@ -25,8 +25,9 @@ import UIKit
import SwiftyBeaver
import RxSwift
import Chameleon
import Contacts
//import Contacts
import PushKit
import ContactsUI
// swiftlint:disable identifier_name
......@@ -162,14 +163,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
self.log.error("Can't get current account!")
return
}
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)
}
self.reloadDataFor(account: currentAccount)
if self.accountService.proxyEnabled() {
self.registerVoipNotifications()
......@@ -203,10 +196,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
self.contactsService.loadContacts(withAccount: account)
self.contactsService.loadContactRequests(withAccount: account)
self.presenceService.subscribeBuddies(withAccount: account, withContacts: self.contactsService.contacts.value)
if let ringID = AccountModelHelper(withAccount: account).ringId {
self.conversationManager?
.prepareConversationsForAccount(accountId: account.id, accountUri: ringID)
}
self.conversationManager?
.prepareConversationsForAccount(accountId: account.id)
}
func applicationDidEnterBackground(_ application: UIApplication) {
......
......@@ -50,6 +50,9 @@
- (void)setAccountDetails:(NSString *)accountID
details:(NSDictionary *)details;
- (void)setAccountCredentials:(NSString *)accountID
credentials:(NSArray *)credentials;
- (void)setAccountActive:(NSString *)accountID
active:(bool)active;
......
......@@ -109,6 +109,11 @@ static id <AccountAdapterDelegate> _delegate;
setAccountDetails(std::string([accountID UTF8String]),[Utils dictionnaryToMap:details]);
}
- (void)setAccountCredentials:(NSString *)accountID
credentials:(NSArray*) credentials {
setCredentials(std::string([accountID UTF8String]), [Utils arrayOfDictionnarisToVectorOfMap:credentials]);
}
- (void)setAccountActive:(NSString *)accountID
active:(bool)active {
setAccountActive(std::string([accountID UTF8String]), active);
......
......@@ -38,5 +38,6 @@
- (NSArray<NSString*>*)calls;
- (void) sendTextMessageWithCallID:(NSString*)callId message:(NSDictionary*)message accountId:(NSString*)accountId sMixed:(bool)isMixed;
- (BOOL) muteMedia:(NSString*)callId mediaType:(NSString*)media muted:(bool)muted;
- (void) playDTMF:(NSString*)code;
@end
......@@ -155,6 +155,10 @@ static id <CallsAdapterDelegate> _delegate;
return unhold(std::string([callId UTF8String]));
}
- (void) playDTMF:(NSString*)code {
playDTMF(std::string([code UTF8String]));
}
- (NSString*)placeCallWithAccountId:(NSString*)accountId toRingId:(NSString*)ringId details:(NSDictionary*)details {
std::string callId;
callId = placeCall(std::string([accountId UTF8String]), std::string([ringId UTF8String]), [Utils dictionnaryToMap:details]);
......
......@@ -36,7 +36,9 @@
#import "VideoAdapter.h"
#import "AudioAdapter.h"
#import <CommonCrypto/CommonCrypto.h>
#import <Contacts/Contacts.h>
//#import <Contacts/Contacts.h>
#import <ContactsUI/ContactsUI.h>
#import <UserNotifications/UserNotifications.h>
#import "CallsAdapter.h"
#import <PushKit/PushKit.h>
#import <UserNotifications/UserNotifications.h>
......
......@@ -34,6 +34,5 @@
+ (NSArray*)vectorOfMapsToArray:(const std::vector<std::map<std::string, std::string>>&)vectorOfMaps;
+ (NSData*)dataFromVectorOfUInt8:(std::vector<uint8_t>)vectorOfUInt8;
+ (std::vector<uint8_t>)vectorOfUInt8FromData:(NSData*)data;
+ (std::vector<std::map<std::string, std::string>>)arrayOfDictionnarisToVectorOfMap:(NSArray*)dictionaries;
@end
......@@ -52,10 +52,24 @@
resMap.insert(std::pair<std::string, std::string>(
std::string([key UTF8String]),
std::string([[dict objectForKey:key] UTF8String])));
return resMap;
}
+ (std::vector<std::map<std::string, std::string>>)arrayOfDictionnarisToVectorOfMap:(NSArray*)dictionaries {
std::vector<std::map<std::string, std::string>> resVector;
for (NSDictionary* dictionary in dictionaries) {
std::map<std::string, std::string> resMap;
for (id key in dictionary) {
resMap.insert(std::pair<std::string,
std::string>(
std::string([key UTF8String]),
std::string([[dictionary objectForKey:key] UTF8String])));
}
resVector.push_back(resMap);
}
return resVector;
}
+ (NSArray*)vectorOfMapsToArray:
(const std::vector<std::map<std::string, std::string>>&)vectorOfMaps {
NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity:vectorOfMaps.size()];
......@@ -88,7 +102,6 @@
for ( int i = 0; i < data.length; i++ ) {
vector.push_back(bytes[i]);
}
return vector;
}
......
......@@ -32,6 +32,7 @@ class ButtonsContainerView: UIView, NibLoadable {
@IBOutlet weak var muteAudioButton: UIButton!
@IBOutlet weak var muteVideoButton: UIButton!
@IBOutlet weak var pauseCallButton: UIButton!
@IBOutlet weak var dialpadButton: UIButton!
@IBOutlet weak var switchSpeakerButton: UIButton!
@IBOutlet weak var cancelButton: UIButton!
@IBOutlet weak var spaceButton: UIButton!
......@@ -90,6 +91,7 @@ class ButtonsContainerView: UIView, NibLoadable {
muteAudioButton.isHidden = true
muteVideoButton.isHidden = true
pauseCallButton.isHidden = true
dialpadButton.isHidden = true
switchSpeakerButton.isHidden = true
cancelButton.isHidden = false
}
......@@ -102,6 +104,9 @@ class ButtonsContainerView: UIView, NibLoadable {
if self.viewModel?.isAudioOnly ?? false {
muteVideoButton.isHidden = true
spaceButton.isHidden = true
if self.viewModel?.isSipCall ?? false {
dialpadButton.isHidden = false
}
} else {
muteVideoButton.isHidden = false
}
......@@ -118,6 +123,9 @@ class ButtonsContainerView: UIView, NibLoadable {
if self.viewModel?.isAudioOnly ?? false {
muteVideoButton.isHidden = true
spaceButton.isHidden = true
if self.viewModel?.isSipCall ?? false {
dialpadButton.isHidden = false
}
} else {
muteVideoButton.isHidden = false
}
......
......@@ -20,6 +20,7 @@
<outlet property="container" destination="a9g-pf-bHy" id="6bw-CB-5qN"/>
<outlet property="containerHeightConstraint" destination="Gjk-7U-rEe" id="G5G-Uh-zRV"/>
<outlet property="containerView" destination="iN0-l3-epB" id="mcP-kY-dVO"/>
<outlet property="dialpadButton" destination="izN-w3-Pc8" id="JWv-ys-ugD"/>
<outlet property="muteAudioButton" destination="tXL-FB-O0X" id="6Bh-x3-veQ"/>
<outlet property="muteVideoButton" destination="W7F-nH-kda" id="MWK-JU-544"/>
<outlet property="pauseCallButton" destination="MPk-dB-dhR" id="W4G-AB-WFw"/>
......@@ -159,10 +160,31 @@
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="izN-w3-Pc8">
<rect key="frame" x="345" y="0.0" width="50" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="PII-PT-xhP"/>
<constraint firstAttribute="width" constant="50" id="wje-Ic-6hu"/>
</constraints>
<color key="tintColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" image="dialpad"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="boolean" keyPath="roundedCorners" value="YES"/>
<userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
<real key="value" value="2"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="borderColor">
<color key="value" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
<real key="value" value="25"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="width" priority="250" constant="200" id="ZuV-LV-CYZ"/>
<constraint firstAttribute="width" priority="250" constant="230" id="ZuV-LV-CYZ"/>
<constraint firstAttribute="height" constant="50" id="gaC-GZ-ftw"/>
</constraints>
</stackView>
......@@ -217,6 +239,7 @@
</objects>
<resources>
<image name="audio_running" width="48" height="48"/>
<image name="dialpad" width="75" height="75"/>
<image name="disable_speakerphone" width="48" height="48"/>
<image name="pause_call" width="48" height="48"/>
<image name="stop_call" width="48" height="48"/>
......
......@@ -33,17 +33,19 @@ class ButtonsContainerViewModel {
let callID: String
let disposeBag = DisposeBag()
var isAudioOnly: Bool
var isSipCall: Bool
let avalaibleCallOptions = BehaviorSubject<CallOptions>(value: .none)
lazy var observableCallOptions: Observable<CallOptions> = { [unowned self] in
return self.avalaibleCallOptions.asObservable()
}()
init(isAudioOnly: Bool, with callService: CallsService, audioService: AudioService, callID: String) {
init(isAudioOnly: Bool, with callService: CallsService, audioService: AudioService, callID: String, isSipCall: Bool) {
self.callService = callService
self.audioService = audioService
self.callID = callID
self.isAudioOnly = isAudioOnly
self.isSipCall = isSipCall
checkCallOptions()
}
......
......@@ -369,6 +369,6 @@
<resources>
<image name="ic_contact_picture" width="512" height="512"/>
<image name="left_arrow" width="138.24000549316406" height="138.24000549316406"/>
<image name="switch_camera" width="100" height="100"/>
<image name="switch_camera" width="75" height="75"/>
</resources>
</document>
......@@ -187,6 +187,15 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
self?.removeFromScreen()
}).disposed(by: self.disposeBag)
self.buttonsContainer.dialpadButton.rx.tap
.subscribe(onNext: { [weak self] in
// guard let bag = self?.viewModel.injectionBag else {return}
// let dialpadViewController = DialpadViewController.instantiate(with: bag)
// dialpadViewController.viewModel.inCallDialpad = true
// self?.present(dialpadViewController, animated: true, completion: nil)
self?.viewModel.showDialpad()
}).disposed(by: self.disposeBag)
self.buttonsContainer.muteAudioButton.rx.tap
.subscribe(onNext: { [weak self] in
self?.viewModel.toggleMuteAudio()
......
......@@ -51,20 +51,32 @@ class CallViewModel: Stateable, ViewModel {
guard let call = self.call else {
return
}
guard let account = self.accountService.currentAccount else {return}
isHeadsetConnected = self.audioService.isHeadsetConnected.value
isAudioOnly = call.isAudioOnly
containerViewModel = ButtonsContainerViewModel(isAudioOnly: self.isAudioOnly, with: self.callService, audioService: self.audioService, callID: call.callId)
let type = account.type == AccountType.sip
containerViewModel =
ButtonsContainerViewModel(isAudioOnly: self.isAudioOnly,
with: self.callService,
audioService: self.audioService,
callID: call.callId,
isSipCall: type)
}
}
// data for ViewController binding
lazy var contactImageData: Observable<Data?>? = {
guard let call = self.call, let account = self.accountService.currentAccount else {
guard let call = self.call,
let account = self.accountService.getAccount(fromAccountId: call.accountId) else {
return nil
}
return self.profileService.getProfile(ringId: call.participantRingId,
let type = account.type == AccountType.sip ? URIType.sip : URIType.ring
guard let uriString = JamiURI.init(schema: type,
infoHach: call.participantUri,
account: account).uriString else {return nil}
return self.profileService.getProfile(uri: uriString,
createIfNotexists: true, accountId: account.id)
.filter({ profile in
guard let photo = profile.photo else {
......@@ -288,6 +300,7 @@ class CallViewModel: Stateable, ViewModel {
}()
var containerViewModel: ButtonsContainerViewModel?
let injectionBag: InjectionBag
required init(with injectionBag: InjectionBag) {
self.callService = injectionBag.callService
......@@ -296,6 +309,7 @@ class CallViewModel: Stateable, ViewModel {
self.videoService = injectionBag.videoService
self.audioService = injectionBag.audioService
self.profileService = injectionBag.profileService
self.injectionBag = injectionBag
callService.currentCall.filter({ [weak self] call in
return call.callId == self?.call?.callId
......@@ -416,4 +430,8 @@ class CallViewModel: Stateable, ViewModel {
videoService.setCameraOrientation(orientation: orientation,
callID: self.call?.callId)
}
func showDialpad() {
self.stateSubject.onNext(ConversationState.showDialpad(inCall: true))
}
}
......@@ -35,6 +35,7 @@ internal enum Asset {
internal static let conversationIcon = ImageAsset(name: "conversation_icon")
internal static let cross = ImageAsset(name: "cross")
internal static let device = ImageAsset(name: "device")
internal static let dialpad = ImageAsset(name: "dialpad")
internal static let disableSpeakerphone = ImageAsset(name: "disable_speakerphone")
internal static let doneIcon = ImageAsset(name: "done_icon")
internal static let downloadIcon = ImageAsset(name: "download_icon")
......@@ -42,11 +43,14 @@ internal enum Asset {
internal static let fallbackAvatar = ImageAsset(name: "fallback_avatar")
internal static let icContactPicture = ImageAsset(name: "ic_contact_picture")
internal static let icConversationRemove = ImageAsset(name: "ic_conversation_remove")
internal static let icHideInput = ImageAsset(name: "ic_hide_input")
internal static let icShowInput = ImageAsset(name: "ic_show_input")
internal static let infoArrow = ImageAsset(name: "info_arrow")
internal static let jamiIcon = ImageAsset(name: "jamiIcon")
internal static let leftArrow = ImageAsset(name: "left_arrow")
internal static let moreSettings = ImageAsset(name: "more_settings")
internal static let pauseCall = ImageAsset(name: "pause_call")
internal static let phoneBook = ImageAsset(name: "phone_book")
internal static let qrCode = ImageAsset(name: "qr_code")
internal static let qrCodeScan = ImageAsset(name: "qr_code_scan")
internal static let revokeDevice = ImageAsset(name: "revoke_device")
......
......@@ -12,6 +12,41 @@ import Foundation
// swiftlint:disable nesting type_body_length type_name
internal enum L10n {
internal enum Account {
/// Account Status
internal static let accountStatus = L10n.tr("Localizable", "account.accountStatus")
/// Create Sip Account
internal static let createSipAccount = L10n.tr("Localizable", "account.createSipAccount")
/// Enable Account
internal static let enableAccount = L10n.tr("Localizable", "account.enableAccount")
/// Enter Password
internal static let passwordLabel = L10n.tr("Localizable", "account.passwordLabel")
/// Port
internal static let port = L10n.tr("Localizable", "account.port")
/// Enter Port Number
internal static let portLabel = L10n.tr("Localizable", "account.portLabel")
/// Enter Address
internal static let serverLabel = L10n.tr("Localizable", "account.serverLabel")
/// Password
internal static let sipPassword = L10n.tr("Localizable", "account.sipPassword")
/// SIP Server
internal static let sipServer = L10n.tr("Localizable", "account.sipServer")
/// User Name
internal static let sipUsername = L10n.tr("Localizable", "account.sipUsername")
/// Connecting
internal static let statusConnecting = L10n.tr("Localizable", "account.statusConnecting")
/// Connection Error
internal static let statusConnectionerror = L10n.tr("Localizable", "account.statusConnectionerror")
/// Offline
internal static let statusOffline = L10n.tr("Localizable", "account.statusOffline")
/// Online
internal static let statusOnline = L10n.tr("Localizable", "account.statusOnline")
/// Unknown
internal static let statusUnknown = L10n.tr("Localizable", "account.statusUnknown")
/// Enter Username
internal static let usernameLabel = L10n.tr("Localizable", "account.usernameLabel")
}
internal enum AccountPage {
/// Block List
internal static let blockedContacts = L10n.tr("Localizable", "accountPage.blockedContacts")
......@@ -80,6 +115,8 @@ internal enum L10n {
}
internal enum Actions {
/// Back
internal static let backAction = L10n.tr("Localizable", "actions.backAction")
/// Block
internal static let blockAction = L10n.tr("Localizable", "actions.blockAction")
/// Cancel
......@@ -350,6 +387,8 @@ internal enum L10n {
internal static let noConversation = L10n.tr("Localizable", "smartlist.noConversation")
/// No network connectivity
internal static let noNetworkConnectivity = L10n.tr("Localizable", "smartlist.noNetworkConnectivity")
/// Selected contact does not have any number
internal static let noNumber = L10n.tr("Localizable", "smartlist.noNumber")
/// No results
internal static let noResults = L10n.tr("Localizable", "smartlist.noResults")
/// Search Result
......@@ -358,6 +397,8 @@ internal enum L10n {
internal static let searchBarPlaceholder = L10n.tr("Localizable", "smartlist.searchBarPlaceholder")
/// Searching...
internal static let searching = L10n.tr("Localizable", "smartlist.searching")
/// Select one of the numbers
internal static let selectOneNumber = L10n.tr("Localizable", "smartlist.selectOneNumber")
/// Yesterday
internal static let yesterday = L10n.tr("Localizable", "smartlist.yesterday")
}
......
......@@ -41,26 +41,43 @@ class ContactViewModel: ViewModel, Stateable {
private let accountService: AccountsService
private let conversationService: ConversationsService
private let nameService: NameService
var tableSection = Observable<[SectionModel<String, ContactActions>]>
.just([SectionModel(model: "ProfileInfoCell",
items:
[ ContactActions(title: L10n.ContactPage.startAudioCall, image: Asset.callButton),
ContactActions(title: L10n.ContactPage.startVideoCall, image: Asset.videoRunning),
ContactActions(title: L10n.ContactPage.sendMessage, image: Asset.conversationIcon)])])
lazy var tableSection : Observable<[SectionModel<String, ContactActions>]> = {
let jamiSettings =
[SectionModel(model: "ProfileInfoCell",
items:
[ ContactActions(title: L10n.ContactPage.startAudioCall, image: Asset.callButton),
ContactActions(title: L10n.ContactPage.startVideoCall, image: Asset.videoRunning),
ContactActions(title: L10n.ContactPage.sendMessage, image: Asset.conversationIcon)])]
let sipSettings =
[SectionModel(model: "ProfileInfoCell",
items:
[ ContactActions(title: L10n.ContactPage.startAudioCall, image: Asset.callButton)])]
guard let account = self.accountService.currentAccount,
account.type == AccountType.ring else {
return Observable<[SectionModel<String, ContactActions>]>
.just(sipSettings)
}
return Observable<[SectionModel<String, ContactActions>]>
.just(jamiSettings)
}()
var conversation: ConversationModel! {
didSet {
if let profile = conversation.participantProfile, let alias = profile.alias, !alias.isEmpty {
self.displayName.value = alias
}
if let contact = self.contactService.contact(withRingId: conversation.recipientRingId),
guard let account = self.accountService
.getAccount(fromAccountId: conversation.accountId) else {return}
if let contact = self.contactService.contact(withUri: conversation.participantUri),
let name = contact.userName {
self.userName.value = name
} else {
self.userName.value = conversation.recipientRingId
self.userName.value = conversation.hash
}
if account.type == AccountType.ring {
self.nameService.usernameLookupStatus
.filter({ [unowned self] lookupNameResponse in
return lookupNameResponse.address != nil &&
lookupNameResponse.address == self.conversation.recipientRingId
lookupNameResponse.address == self.conversation.participantUri
}).subscribe(onNext: { [unowned self] lookupNameResponse in
if let name = lookupNameResponse.name, !name.isEmpty {
self.userName.value = name
......@@ -68,24 +85,31 @@ class ContactViewModel: ViewModel, Stateable {
self.userName.value = address
}
}).disposed(by: disposeBag)
self.nameService.lookupAddress(withAccount: "", nameserver: "", address: conversation.recipientRingId)
self.nameService.lookupAddress(withAccount: "", nameserver: "", address: conversation.hash)
}
// add option block contact and clear conversation if contact exists
if self.contactService.contact(withRingId: conversation.recipientRingId) != nil {
self.tableSection = Observable<[SectionModel<String, ContactActions>]>
.just([SectionModel(model: "ProfileInfoCell",
items:
[ ContactActions(title: L10n.ContactPage.startAudioCall, image: Asset.callButton),
ContactActions(title: L10n.ContactPage.startVideoCall, image: Asset.videoRunning),
ContactActions(title: L10n.ContactPage.sendMessage, image: Asset.conversationIcon),
ContactActions(title: L10n.ContactPage.clearConversation, image: Asset.clearConversation),
ContactActions(title: L10n.ContactPage.removeConversation, image: Asset.icConversationRemove),
ContactActions(title: L10n.ContactPage.blockContact, image: Asset.blockIcon)])])
if self.contactService.contact(withUri: conversation.participantUri) != nil {
if account.type == AccountType.ring {
self.tableSection = Observable<[SectionModel<String, ContactActions>]>
.just([SectionModel(model: "ProfileInfoCell",
items:
[ ContactActions(title: L10n.ContactPage.startAudioCall, image: Asset.callButton),
ContactActions(title: L10n.ContactPage.startVideoCall, image: Asset.videoRunning),
ContactActions(title: L10n.ContactPage.sendMessage, image: Asset.conversationIcon),
ContactActions(title: L10n.ContactPage.clearConversation, image: Asset.clearConversation),
ContactActions(title: L10n.ContactPage.removeConversation, image: Asset.icConversationRemove),
ContactActions(title: L10n.ContactPage.blockContact, image: Asset.blockIcon)])])
} else {
self.tableSection = Observable<[SectionModel<String, ContactActions>]>
.just([SectionModel(model: "ProfileInfoCell",
items:
[ ContactActions(title: L10n.ContactPage.startAudioCall, image: Asset.callButton),
ContactActions(title: L10n.ContactPage.clearConversation, image: Asset.clearConversation),
ContactActions(title: L10n.ContactPage.removeConversation, image: Asset.icConversationRemove)])])
}
}
self.contactService
.getContactRequestVCard(forContactWithRingId: conversation.recipientRingId)
.getContactRequestVCard(forContactWithRingId: conversation.participantUri)
.subscribe(onSuccess: { [unowned self] vCard in
if !VCardUtils.getName(from: vCard).isEmpty {
self.displayName.value = VCardUtils.getName(from: vCard)
......@@ -96,7 +120,7 @@ class ContactViewModel: ViewModel, Stateable {
self.profileImageData.value = imageData
})
.disposed(by: self.disposeBag)
self.profileService.getProfile(ringId: conversation.recipientRingId,
self.profileService.getProfile(uri: conversation.participantUri,
createIfNotexists: false,
accountId: conversation.accountId)
.subscribe(onNext: { [unowned self] profile in
......@@ -131,38 +155,38 @@ class ContactViewModel: ViewModel, Stateable {
}
func startCall() {
self.stateSubject.onNext(ConversationState
.startCall(contactRingId: conversation.recipientRingId,
.startCall(contactRingId: conversation.participantUri,
userName: self.userName.value))
}
func startAudioCall() {
self.stateSubject.onNext(ConversationState
.startAudioCall(contactRingId: conversation.recipientRingId,
.startAudioCall(contactRingId: conversation.participantUri,
userName: self.userName.value))
}
func deleteConversation() {
self.conversationService
.clearHistory(conversation: conversation,
keepConversation: false)
keepConversation: false)
}
func clearConversation() {
self.conversationService
.clearHistory(conversation: conversation,
keepConversation: true)
keepConversation: true)
}
func blockContact() {
let contactRingId = conversation.recipientRingId
let contactRingId = conversation.participantUri
let accountId = conversation.accountId
let removeCompleted = self.contactService.removeContact(withRingId: contactRingId,
let removeCompleted = self.contactService.removeContact(withUri: contactRingId,
ban: true,
withAccountId: accountId)
removeCompleted.asObservable()
.subscribe(onCompleted: { [unowned self] in
self.conversationService
.clearHistory(conversation: self.conversation,
keepConversation: false)
keepConversation: false)
}).disposed(by: self.disposeBag)
}
}
......@@ -247,7 +247,7 @@ class DBManager {
throw DataAccessError.datastoreConnectionError
}
try dataBase.transaction {
let author: String? = incoming ? self!.ringUri(from: contactUri) : nil
let author: String? = incoming ? contactUri : nil
guard let conversationID = try self?.getConversationsFor(contactUri: contactUri,
createIfNotExists: true,
dataBase: dataBase) else {
......@@ -308,6 +308,17 @@ class DBManager {
}
}