UI: Message read indicator is Avatar
Changes the message read indicator from a green
dot to the avatar of the user that read the
message
Change-Id: Iea0e03968ae822201d1ab15b44b3700b0de6f85e
Gitlab: #72
diff --git a/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift b/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift
index 5a2df23..1ac05c7 100644
--- a/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift
+++ b/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift
@@ -5,6 +5,7 @@
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
* Author: Quentin Muret <quentin.muret@savoirfairelinux.com>
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
+ * Author: Raphaël Brulé <raphael.brule@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
@@ -411,11 +412,19 @@
.bind(to: self.failedStatusLabel.rx.isHidden)
.disposed(by: self.disposeBag)
if self.messageReadIndicator != nil {
- item.displayReadIndicator.asObservable()
- .observeOn(MainScheduler.instance)
- .map {value in return !value}
- .bind(to: self.messageReadIndicator!.rx.isHidden)
- .disposed(by: self.disposeBag)
+ Observable<(Data?, String, Bool)>.combineLatest(conversationViewModel.profileImageData.asObservable(),
+ conversationViewModel.bestName.asObservable(),
+ item.displayReadIndicator.asObservable()) { ($0, $1, $2) }
+ .observeOn(MainScheduler.instance)
+ .startWith((conversationViewModel.profileImageData.value, conversationViewModel.userName.value, item.displayReadIndicator.value))
+ .subscribe({ [weak self] profileData -> Void in
+ guard let bestName = profileData.element?.1 else { return }
+ self?.messageReadIndicator?.subviews.forEach({ $0.removeFromSuperview() })
+ if let displayReadIndicator = profileData.element?.2, displayReadIndicator {
+ self?.messageReadIndicator?.addSubview(AvatarView(profileImageData: profileData.element?.0, username: bestName, size: 12))
+ }
+ })
+ .disposed(by: self.disposeBag)
}
}
} else if item.bubblePosition() == .received {
diff --git a/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCellSent.xib b/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCellSent.xib
index a833b39..2d7e7bb 100644
--- a/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCellSent.xib
+++ b/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCellSent.xib
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina6_5" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@@ -17,7 +17,7 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hdz-AQ-xHI" userLabel="Bottom Corner">
- <rect key="frame" x="469" y="20.666666666666671" width="25" height="18.333333333333329"/>
+ <rect key="frame" x="467" y="20.666666666666671" width="25" height="18.333333333333329"/>
<color key="backgroundColor" red="1" green="0.5" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="25" id="wlh-ar-Nsv"/>
@@ -29,7 +29,7 @@
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="EMh-bG-ilg" userLabel="Top Corner">
- <rect key="frame" x="469" y="8.0000000000000018" width="25" height="18.666666666666671"/>
+ <rect key="frame" x="467" y="8.0000000000000018" width="25" height="18.666666666666671"/>
<color key="backgroundColor" red="1" green="0.0" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="25" id="zaa-Rn-ziw"/>
@@ -42,7 +42,7 @@
</userDefinedRuntimeAttributes>
</view>
<view clipsSubviews="YES" contentMode="scaleToFill" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="kZJ-Ay-LTR" customClass="MessageBubble" customModule="Ring" customModuleProvider="target">
- <rect key="frame" x="274.66666666666669" y="8" width="219.33333333333331" height="31"/>
+ <rect key="frame" x="272.66666666666669" y="8" width="219.33333333333331" height="31"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label Label Label Label" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lyR-7c-S2k" customClass="ActiveLabel" customModule="ActiveLabel">
<rect key="frame" x="14" y="7" width="191.33333333333334" height="17"/>
@@ -87,20 +87,19 @@
<nil key="highlightedColor"/>
</label>
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="78h-fZ-7yf" userLabel="Sending Indicator">
- <rect key="frame" x="246.66666666666663" y="13.666666666666664" width="20" height="20"/>
+ <rect key="frame" x="244.66666666666666" y="13.666666666666664" width="19.999999999999972" height="20"/>
</activityIndicatorView>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Failed" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="P5a-HI-uhr" userLabel="Failed Status Label">
- <rect key="frame" x="224.33333333333334" y="13.999999999999998" width="42.333333333333343" height="19.333333333333329"/>
+ <rect key="frame" x="222.33333333333334" y="13.999999999999998" width="42.333333333333343" height="19.333333333333329"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.94117647058823528" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nk1-r0-5jJ">
- <rect key="frame" x="498" y="31" width="8" height="8"/>
- <color key="backgroundColor" systemColor="systemGreenColor" red="0.20392156859999999" green="0.78039215689999997" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <rect key="frame" x="494" y="27" width="12" height="12"/>
<constraints>
- <constraint firstAttribute="width" constant="8" id="IKx-gD-ktV"/>
- <constraint firstAttribute="height" constant="8" id="Kmy-bf-VRp"/>
+ <constraint firstAttribute="width" constant="12" id="IKx-gD-ktV"/>
+ <constraint firstAttribute="height" constant="12" id="Kmy-bf-VRp"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
@@ -115,7 +114,7 @@
<constraint firstAttribute="trailing" secondItem="nk1-r0-5jJ" secondAttribute="trailing" constant="4" id="1g3-Kl-0eG"/>
<constraint firstItem="h8N-aw-5lV" firstAttribute="leading" secondItem="ogn-wv-fZy" secondAttribute="trailing" constant="16" id="1jW-JR-t5r"/>
<constraint firstItem="78h-fZ-7yf" firstAttribute="trailing" secondItem="kZJ-Ay-LTR" secondAttribute="leading" constant="-8" id="4ME-jl-Uol"/>
- <constraint firstItem="nk1-r0-5jJ" firstAttribute="leading" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" constant="4" id="4ht-GX-AOD"/>
+ <constraint firstItem="nk1-r0-5jJ" firstAttribute="leading" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" constant="2" id="4ht-GX-AOD"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" priority="1" constant="64" id="99Y-bR-Ioq"/>
<constraint firstItem="kZJ-Ay-LTR" firstAttribute="bottom" secondItem="nk1-r0-5jJ" secondAttribute="bottom" id="AHa-wE-zfg"/>
<constraint firstItem="kZJ-Ay-LTR" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" priority="1" constant="16" id="Eso-cy-OYs"/>
@@ -125,7 +124,7 @@
<constraint firstItem="EMh-bG-ilg" firstAttribute="trailing" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" id="MY3-Aj-94K"/>
<constraint firstItem="EMh-bG-ilg" firstAttribute="height" secondItem="kZJ-Ay-LTR" secondAttribute="height" multiplier="0.5" constant="3" id="O7u-JI-koA"/>
<constraint firstItem="ogn-wv-fZy" firstAttribute="centerX" secondItem="H2p-sc-9uM" secondAttribute="centerX" id="RaG-SO-xFo"/>
- <constraint firstAttribute="trailing" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" constant="16" id="TCY-7X-mFs"/>
+ <constraint firstAttribute="trailing" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" constant="18" id="TCY-7X-mFs"/>
<constraint firstItem="P5a-HI-uhr" firstAttribute="centerY" secondItem="kZJ-Ay-LTR" secondAttribute="centerY" id="XNX-Nd-gDE"/>
<constraint firstItem="h8N-aw-5lV" firstAttribute="centerY" secondItem="ogn-wv-fZy" secondAttribute="centerY" id="Xdu-7c-MbP"/>
<constraint firstItem="2U4-l3-KET" firstAttribute="trailing" secondItem="ogn-wv-fZy" secondAttribute="leading" constant="-16" id="Xw6-H2-byY"/>
diff --git a/Ring/Ring/Features/Conversations/Conversation/MessageViewModel.swift b/Ring/Ring/Features/Conversations/Conversation/MessageViewModel.swift
index 86c55b7..8d4dc23 100644
--- a/Ring/Ring/Features/Conversations/Conversation/MessageViewModel.swift
+++ b/Ring/Ring/Features/Conversations/Conversation/MessageViewModel.swift
@@ -4,6 +4,7 @@
* Author: Silbino Gonçalves Matado <silbino.gmatado@savoirfairelinux.com>
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
+ * Author: Raphaël Brulé <raphael.brule@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
@@ -21,6 +22,7 @@
*/
import RxSwift
+import RxCocoa
import SwiftyBeaver
import MobileCoreServices
@@ -72,7 +74,7 @@
self.initialTransferStatus = message.transferStatus
self.timeStringShown = nil
self.status.onNext(message.status)
- self.displayReadIndicator.onNext(isLastDisplayed)
+ self.displayReadIndicator.accept(isLastDisplayed)
if isTransfer {
if let transferId = daemonId,
@@ -132,10 +134,10 @@
.subscribe(onNext: { [weak self] messageUpdateEvent in
if let oldMessage: Int64 = messageUpdateEvent.getEventInput(.oldDisplayedMessage),
oldMessage == self?.message.messageId {
- self?.displayReadIndicator.onNext(false)
+ self?.displayReadIndicator.accept(false)
} else if let newMessage: Int64 = messageUpdateEvent.getEventInput(.newDisplayedMessage),
newMessage == self?.message.messageId {
- self?.displayReadIndicator.onNext(true)
+ self?.displayReadIndicator.accept(true)
}
})
.disposed(by: self.disposeBag)
@@ -180,7 +182,7 @@
}
var status = BehaviorSubject<MessageStatus>(value: .unknown)
- var displayReadIndicator = BehaviorSubject<Bool>(value: false)
+ var displayReadIndicator = BehaviorRelay<Bool>(value: false)
var transferStatus = BehaviorSubject<DataTransferStatus>(value: .unknown)
var lastTransferStatus: DataTransferStatus = .unknown