From 719b1b8026008cc0cf20ed4c2ca6d570a6212fd4 Mon Sep 17 00:00:00 2001
From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
Date: Fri, 20 Oct 2017 17:40:32 -0400
Subject: [PATCH] fix: correct cell subscription disposal

- Adds DisposeBags for cells and uses them to dispose of their
  subscriptions.

- Prevents status indicators from showing for the generated message
  cell type.

Change-Id: I930865e02b628a0f749683456d14184dd9189dc2
Reviewed-by: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
---
 .../Conversation/Cells/MessageCell.swift           |  6 +++++-
 .../Conversation/ConversationViewController.swift  | 14 ++++++++------
 .../SmartList/Cells/ConversationCell.swift         |  6 ++++++
 .../SmartList/SmartlistViewController.swift        |  8 ++++----
 Ring/Ring/Features/Me/Me/LinkNewDeviceCell.swift   |  6 +++++-
 5 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift b/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift
index 49d789c05..3b0576107 100644
--- a/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift
+++ b/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift
@@ -39,5 +39,9 @@ class MessageCell: UITableViewCell, NibReusable {
     @IBOutlet weak var profileImage: UIImageView!
     @IBOutlet weak var fallbackAvatar: UILabel!
 
-    let disposeBag = DisposeBag()
+    var disposeBag = DisposeBag()
+
+    override func prepareForReuse() {
+        self.disposeBag = DisposeBag()
+    }
 }
diff --git a/Ring/Ring/Features/Conversations/Conversation/ConversationViewController.swift b/Ring/Ring/Features/Conversations/Conversation/ConversationViewController.swift
index fe7fc2fb4..b5caefaa1 100644
--- a/Ring/Ring/Features/Conversations/Conversation/ConversationViewController.swift
+++ b/Ring/Ring/Features/Conversations/Conversation/ConversationViewController.swift
@@ -93,7 +93,6 @@ class ConversationViewController: UIViewController, UITextFieldDelegate, Storybo
                 return defaultAvatarColor
             }
 
-
         self.tableView.contentInset.bottom = messageAccessoryView.frame.size.height
         self.tableView.scrollIndicatorInsets.bottom = messageAccessoryView.frame.size.height
 
@@ -402,17 +401,20 @@ class ConversationViewController: UIViewController, UITextFieldDelegate, Storybo
             cell.bubbleBottomConstraint.constant = 16
         }
 
-        if messageVM.bubblePosition() == .sent {
+        if messageVM.bubblePosition() == .generated {
+            cell.failedStatusLabel.isHidden = true
+            cell.sendingIndicator.stopAnimating()
+        } else if messageVM.bubblePosition() == .sent {
             messageVM.status.asObservable()
                 .observeOn(MainScheduler.instance)
                 .map { value in value == MessageStatus.sending ? true : false }
                 .bind(to: cell.sendingIndicator.rx.isAnimating)
-                .disposed(by: disposeBag)
+                .disposed(by: cell.disposeBag)
             messageVM.status.asObservable()
                 .observeOn(MainScheduler.instance)
                 .map { value in value == MessageStatus.failure ? false : true }
                 .bind(to: cell.failedStatusLabel.rx.isHidden)
-                .disposed(by: disposeBag)
+                .disposed(by: cell.disposeBag)
         } else {
             // avatar
             guard let fallbackAvatar = cell.fallbackAvatar else {
@@ -429,14 +431,14 @@ class ConversationViewController: UIViewController, UITextFieldDelegate, Storybo
                     .observeOn(MainScheduler.instance)
                     .map { value in value.prefixString().capitalized }
                     .bind(to: fallbackAvatar.rx.text)
-                    .disposed(by: disposeBag)
+                    .disposed(by: cell.disposeBag)
 
                 // Set placeholder avatar to backgroundColorObservable
                 self.backgroundColorObservable
                     .subscribe(onNext: { backgroundColor in
                         fallbackAvatar.backgroundColor = backgroundColor
                     })
-                    .disposed(by: disposeBag)
+                    .disposed(by: cell.disposeBag)
 
                 // Set image if any
                 cell.profileImage?.image = nil
diff --git a/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.swift b/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.swift
index 69fc315c0..77434e58b 100644
--- a/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.swift
+++ b/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.swift
@@ -52,4 +52,10 @@ class ConversationCell: UITableViewCell, NibReusable {
         self.presenceIndicator.backgroundColor = presenceBGColor
         self.fallbackAvatar.backgroundColor = fallbackAvatarBGColor
     }
+
+    var disposeBag = DisposeBag()
+
+    override func prepareForReuse() {
+        self.disposeBag = DisposeBag()
+    }
 }
diff --git a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift
index da9719ea6..52cf2121e 100644
--- a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift
+++ b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift
@@ -125,14 +125,14 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
                 item.userName.asObservable()
                     .observeOn(MainScheduler.instance)
                     .bind(to: cell.nameLabel.rx.text)
-                    .disposed(by: self.disposeBag)
+                    .disposed(by: cell.disposeBag)
 
                 // Avatar placeholder initial
                 item.userName.asObservable()
                     .observeOn(MainScheduler.instance)
                     .map { value in value.prefixString().capitalized }
                     .bind(to: cell.fallbackAvatar.rx.text)
-                    .disposed(by: self.disposeBag)
+                    .disposed(by: cell.disposeBag)
 
                 // UIColor that observes "best Id" prefix
                 self.backgroundColorObservable = item.userName.asObservable()
@@ -151,7 +151,7 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
                     .subscribe(onNext: { backgroundColor in
                         cell.fallbackAvatar.backgroundColor = backgroundColor
                     })
-                    .disposed(by: self.disposeBag)
+                    .disposed(by: cell.disposeBag)
 
                 // Set image if any
                 cell.fallbackAvatar.isHidden = false
@@ -172,7 +172,7 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
                     .observeOn(MainScheduler.instance)
                     .map { value in !value }
                     .bind(to: cell.presenceIndicator.rx.isHidden)
-                    .disposed(by: self.disposeBag)
+                    .disposed(by: cell.disposeBag)
 
                 return cell
         }
diff --git a/Ring/Ring/Features/Me/Me/LinkNewDeviceCell.swift b/Ring/Ring/Features/Me/Me/LinkNewDeviceCell.swift
index 6ecb75f4b..745fe0a01 100644
--- a/Ring/Ring/Features/Me/Me/LinkNewDeviceCell.swift
+++ b/Ring/Ring/Features/Me/Me/LinkNewDeviceCell.swift
@@ -25,5 +25,9 @@ import RxSwift
 class LinkNewDeviceCell: UITableViewCell, NibReusable {
 
     @IBOutlet weak var addDeviceButton: UIButton!
-    let disposeBag = DisposeBag()
+    var disposeBag = DisposeBag()
+
+    override func prepareForReuse() {
+        self.disposeBag = DisposeBag()
+    }
 }
-- 
GitLab