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