Commit 7c6f41c8 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk Committed by Andreas Traczyk

fix: display avatar

This patch adds next fixes:
- update avatar when a new data received
- fix sending vcard on outgoing call
- clean labels text on call screen

Change-Id: I47b469a156e9b46ff38fdd4362309b2bbc2172e5
parent 829c8de0
......@@ -95,8 +95,8 @@
<userDefinedRuntimeAttribute type="boolean" keyPath="roundedCorners" value="YES"/>
</userDefinedRuntimeAttributes>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fac-lR-4on">
<rect key="frame" x="20" y="150" width="55" height="40"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fac-lR-4on">
<rect key="frame" x="20" y="150" width="0.0" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="uWM-mZ-BSi"/>
</constraints>
......@@ -104,8 +104,8 @@
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cgd-Wa-clf">
<rect key="frame" x="110" y="88" width="51.5" height="24"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cgd-Wa-clf">
<rect key="frame" x="110" y="100" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="20"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
......
......@@ -27,11 +27,43 @@ class ContactRequestItem {
let contactRequest: ContactRequestModel
let userName = Variable("")
let profileImageData: Data?
let profileImageData = Variable<Data?>(nil)
let disposeBag = DisposeBag()
init(withContactRequest contactRequest: ContactRequestModel) {
init(withContactRequest contactRequest: ContactRequestModel, callService: CallsService,
contactService: ContactsService) {
self.contactRequest = contactRequest
self.userName.value = contactRequest.ringId
self.profileImageData = self.contactRequest.vCard?.imageData
self.profileImageData.value = self.contactRequest.vCard?.imageData
contactService.getProfileForUri(uri: contactRequest.ringId)
.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? {
self.profileImageData.value = data
}
})
.disposed(by: self.disposeBag)
})
.disposed(by: self.disposeBag)
}
}
......@@ -126,12 +126,20 @@ class ContactRequestsViewController: UIViewController, StoryboardBased, ViewMode
// Set image if any
cell.fallbackAvatar.isHidden = false
cell.profileImageView.image = nil
if let imageData = item.profileImageData {
if let image = UIImage(data: imageData) {
cell.profileImageView.image = image
cell.fallbackAvatar.isHidden = true
}
}
item.profileImageData.asObservable()
.observeOn(MainScheduler.instance)
.subscribe(onNext: { data in
if let imageData = data {
if let image = UIImage(data: imageData) {
cell.profileImageView.image = image
cell.fallbackAvatar.isHidden = true
}
} else {
cell.fallbackAvatar.isHidden = false
cell.profileImageView.image = nil
}
}).disposed(by: cell.disposeBag)
//Accept button
cell.acceptButton.backgroundColor = UIColor.clear
......
......@@ -35,6 +35,7 @@ class ContactRequestsViewModel: Stateable, ViewModel {
let conversationService: ConversationsService
let nameService: NameService
let presenceService: PresenceService
let callsService: CallsService
fileprivate let disposeBag = DisposeBag()
fileprivate let log = SwiftyBeaver.self
......@@ -47,6 +48,7 @@ class ContactRequestsViewModel: Stateable, ViewModel {
self.conversationService = injectionBag.conversationsService
self.nameService = injectionBag.nameService
self.presenceService = injectionBag.presenceService
self.callsService = injectionBag.callService
self.injectionBag = injectionBag
}
......@@ -59,7 +61,9 @@ class ContactRequestsViewModel: Stateable, ViewModel {
.filter { $0.accountId == self.accountsService.currentAccount?.id }
.sorted { $0.receivedDate > $1.receivedDate }
.map { contactRequest in
let item = ContactRequestItem(withContactRequest: contactRequest)
let item = ContactRequestItem(withContactRequest: contactRequest,
callService: self.callsService,
contactService: self.contactsService)
self.lookupUserName(withItem: item)
return item
}
......
......@@ -90,7 +90,7 @@ class ConversationViewController: UIViewController, UITextFieldDelegate, Storybo
self.updateBottomOffset()
}
func setupNavTitle(displayName: String? = nil, username: String?) {
func setupNavTitle(profileImageData: Data?, displayName: String? = nil, username: String?) {
let imageSize = CGFloat(36.0)
let imageOffsetY = CGFloat(5.0)
let infoPadding = CGFloat(8.0)
......@@ -110,13 +110,14 @@ class ConversationViewController: UIViewController, UITextFieldDelegate, Storybo
let profileImageView = UIImageView(frame: CGRect(x: 0, y: imageOffsetY, width: imageSize, height: imageSize))
profileImageView.frame = CGRect.init(x: 0, y: 0, width: imageSize, height: imageSize)
profileImageView.center = CGPoint.init(x: imageSize / 2, y: titleView.center.y)
if let imageData = viewModel.profileImageData, let image = UIImage(data: imageData) {
if let imageData = profileImageData, let image = UIImage(data: imageData) {
self.log.debug("standard avatar")
(profileImageView as UIImageView).image = image.circleMasked
titleView.addSubview(profileImageView)
} else {
// use fallback avatars
let name = viewModel.userName.value
let name = self.viewModel.userName.value
let scanner = Scanner(string: name.toMD5HexString().prefixString())
var index: UInt64 = 0
if scanner.scanHexInt64(&index) {
......@@ -148,14 +149,13 @@ class ConversationViewController: UIViewController, UITextFieldDelegate, Storybo
}
}
if displayName != nil {
if let name = displayName, !name.isEmpty {
let dnlabel: UILabel = UILabel.init(frame: CGRect.init(x: imageSize + infoPadding, y: 4, width: maxNameLength, height: 20))
dnlabel.text = displayName
dnlabel.text = name
dnlabel.font = UIFont.systemFont(ofSize: nameSize)
dnlabel.textColor = UIColor.white
dnlabel.textAlignment = .left
titleView.addSubview(dnlabel)
userNameYOffset = 20.0
nameSize = 14.0
}
......@@ -168,22 +168,27 @@ class ConversationViewController: UIViewController, UITextFieldDelegate, Storybo
titleView.addSubview(unlabel)
self.navigationItem.titleView = titleView
}
func setupUI() {
if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad {
self.viewModel.userName.asObservable().bind(to: self.navigationItem.rx.title).disposed(by: disposeBag)
} else {
self.setupNavTitle(displayName: self.viewModel.displayName.value, username: self.viewModel.userName.value)
Observable<(String, String?)>.combineLatest(self.viewModel.userName.asObservable(),
self.viewModel.displayName.asObservable()) { username, displayName in
return (username, displayName)
self.setupNavTitle(profileImageData: self.viewModel.profileImageData.value,
displayName: self.viewModel.displayName.value,
username: self.viewModel.userName.value)
Observable<(Data?, String?, String)>.combineLatest(self.viewModel.profileImageData.asObservable(),
self.viewModel.displayName.asObservable(),
self.viewModel.userName.asObservable()) { profileImage, displayName, username in
return (profileImage, displayName, username)
}
.observeOn(MainScheduler.instance)
.subscribe({ [weak self] names -> Void in
self?.setupNavTitle(displayName: names.element?.1,
username: names.element?.0)
.subscribe({ [weak self] profileData -> Void in
self?.setupNavTitle(profileImageData: profileData.element?.0,
displayName: profileData.element?.1,
username: profileData.element?.2)
return
})
.disposed(by: self.disposeBag)
......@@ -656,14 +661,19 @@ class ConversationViewController: UIViewController, UITextFieldDelegate, Storybo
// Set image if any
cell.profileImage?.image = nil
if let imageData = viewModel.profileImageData {
if let image = UIImage(data: imageData) {
cell.profileImage?.image = image
fallbackAvatar.isHidden = true
}
} else {
fallbackAvatar.isHidden = false
}
self.viewModel.profileImageData.asObservable()
.observeOn(MainScheduler.instance)
.subscribe(onNext: { data in
if let imageData = data {
if let image = UIImage(data: imageData) {
cell.profileImage?.image = image
fallbackAvatar.isHidden = true
}
} else {
cell.profileImage?.image = nil
fallbackAvatar.isHidden = false
}
}).disposed(by: cell.disposeBag)
}
}
}
......
......@@ -36,6 +36,7 @@ class ConversationViewModel: Stateable, ViewModel {
private let nameService: NameService
private let contactsService: ContactsService
private let presenceService: PresenceService
private let callsService: CallsService
private let injectionBag: InjectionBag
private let stateSubject = PublishSubject<State>()
......@@ -50,6 +51,7 @@ class ConversationViewModel: Stateable, ViewModel {
self.nameService = injectionBag.nameService
self.contactsService = injectionBag.contactsService
self.presenceService = injectionBag.presenceService
self.callsService = injectionBag.callService
dateFormatter.dateStyle = .medium
hourFormatter.dateFormat = "HH:mm"
......@@ -89,7 +91,7 @@ class ConversationViewModel: Stateable, ViewModel {
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 = data
self.profileImageData.value = data
}
} else {
self.contactsService.loadVCard(forContactWithRingId: contactRingId)
......@@ -98,7 +100,7 @@ class ConversationViewModel: Stateable, ViewModel {
self.log.warning("vCard for ringId: \(contactRingId) has no image")
return
}
self.profileImageData = imageData
self.profileImageData.value = imageData
self.displayName.value = VCardUtils.getName(from: vCard)
})
.disposed(by: self.disposeBag)
......@@ -141,6 +143,27 @@ 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
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)
if let contactUserName = contact?.userName {
self.userName.value = contactUserName
} else {
......@@ -178,7 +201,7 @@ class ConversationViewModel: Stateable, ViewModel {
var userName = Variable<String>("")
var profileImageData: Data?
var profileImageData = Variable<Data?>(nil)
var inviteButtonIsAvailable = BehaviorSubject(value: true)
......
......@@ -204,12 +204,20 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
// Set image if any
cell.fallbackAvatar.isHidden = false
cell.profileImage.image = nil
if let imageData = item.profileImageData {
if let image = UIImage(data: imageData) {
cell.profileImage.image = image
cell.fallbackAvatar.isHidden = true
}
}
item.profileImageData.asObservable()
.observeOn(MainScheduler.instance)
.subscribe(onNext: { data in
if let imageData = data {
if let image = UIImage(data: imageData) {
cell.profileImage.image = image
cell.fallbackAvatar.isHidden = true
}
} else {
cell.fallbackAvatar.isHidden = false
cell.profileImage.image = nil
}
}).disposed(by: cell.disposeBag)
cell.newMessagesLabel.text = item.unreadMessages
cell.lastMessageDateLabel.text = item.lastMessageReceivedDate
......
......@@ -144,6 +144,7 @@ class CallsService: CallsAdapterDelegate {
callDetails[CallDetailKey.audioOnlyKey.rawValue] = isAudioOnly.toString()
let call = CallModel(withCallId: ringId, callDetails: callDetails)
call.state = .connecting
call.callType = .outgoing
return Single<CallModel>.create(subscribe: { [unowned self] single in
if let callId = self.callsAdapter.placeCall(withAccountId: account.id,
toRingId: "ring:\(ringId)",
......
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