build: upgrade dependencies

Change-Id: I0d33de98d0ca41a3b7e6ec86832007b527a6314f
diff --git a/Ring/Cartfile b/Ring/Cartfile
index a29b662..b8b06ed 100644
--- a/Ring/Cartfile
+++ b/Ring/Cartfile
@@ -1,9 +1,9 @@
-github "RxSwiftCommunity/RxRealm" ~> 0.7
-github "RxSwiftCommunity/RxDataSources" ~> 3.0
-github "pkluz/PKHUD" ~> 5.0
-github "AliSoftware/Reusable" ~> 4.0
-github "SwiftyBeaver/SwiftyBeaver" ~> 1.0
+github "RxSwiftCommunity/RxRealm"
+github "RxSwiftCommunity/RxDataSources"
+github "pkluz/PKHUD"
+github "AliSoftware/Reusable"
+github "SwiftyBeaver/SwiftyBeaver"
 github "andreamazz/AMPopTip"
 github "ashleymills/Reachability.swift"
-github "stephencelis/SQLite.swift" ~> 0.11.4
+github "stephencelis/SQLite.swift"
 github "gskbyte/GSKStretchyHeaderView"
diff --git a/Ring/Cartfile.resolved b/Ring/Cartfile.resolved
index f1ecc8b..ffb71a3 100644
--- a/Ring/Cartfile.resolved
+++ b/Ring/Cartfile.resolved
@@ -1,11 +1,11 @@
 github "AliSoftware/Reusable" "4.1.1"
-github "ReactiveX/RxSwift" "4.5.0"
-github "RxSwiftCommunity/RxDataSources" "3.1.0"
-github "RxSwiftCommunity/RxRealm" "0.7.7"
-github "SwiftyBeaver/SwiftyBeaver" "1.9.1"
+github "ReactiveX/RxSwift" "5.1.1"
+github "RxSwiftCommunity/RxDataSources" "4.0.1"
+github "RxSwiftCommunity/RxRealm" "3.1.0"
+github "SwiftyBeaver/SwiftyBeaver" "1.9.2"
 github "andreamazz/AMPopTip" "4.5.0"
-github "ashleymills/Reachability.swift" "v5.0.0"
+github "ashleymills/Reachability.swift" "v5.1.0"
 github "gskbyte/GSKStretchyHeaderView" "1.0.4"
-github "pkluz/PKHUD" "5.3.0"
-github "realm/realm-cocoa" "v3.21.0"
-github "stephencelis/SQLite.swift" "0.11.6"
+github "pkluz/PKHUD" "5.4.0"
+github "realm/realm-cocoa" "v5.5.0"
+github "stephencelis/SQLite.swift" "0.12.2"
diff --git a/Ring/Ring.xcodeproj/project.pbxproj b/Ring/Ring.xcodeproj/project.pbxproj
index 303fa43..a5947a4 100644
--- a/Ring/Ring.xcodeproj/project.pbxproj
+++ b/Ring/Ring.xcodeproj/project.pbxproj
@@ -258,6 +258,7 @@
 		2662FC7D246B78E800FA7782 /* IncognitoSmartListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2662FC7C246B78E800FA7782 /* IncognitoSmartListViewController.swift */; };
 		2662FC7F246B790400FA7782 /* IncognitoSmartListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2662FC7E246B790400FA7782 /* IncognitoSmartListViewModel.swift */; };
 		2662FC81246B793500FA7782 /* IncognitoSmartListViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2662FC80246B793500FA7782 /* IncognitoSmartListViewController.storyboard */; };
+		266C1DBB2539F3A300978E87 /* RxRelay.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 266C1DB82539F3A300978E87 /* RxRelay.framework */; };
 		2673D62A25261DD9000C56CB /* ConferenceMenuItemsManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2673D62925261DD9000C56CB /* ConferenceMenuItemsManagerTest.swift */; };
 		2673D62E252624AB000C56CB /* ConferenceMenuItemsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2673D62D252624AB000C56CB /* ConferenceMenuItemsManager.swift */; };
 		2673D630252657B0000C56CB /* ConferenceLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2673D62F252657B0000C56CB /* ConferenceLayout.swift */; };
@@ -666,6 +667,7 @@
 		2662FC7C246B78E800FA7782 /* IncognitoSmartListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = IncognitoSmartListViewController.swift; path = Ring/Features/Conversations/SmartList/IncognitoSmartListViewController.swift; sourceTree = SOURCE_ROOT; };
 		2662FC7E246B790400FA7782 /* IncognitoSmartListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = IncognitoSmartListViewModel.swift; path = Ring/Features/Conversations/SmartList/IncognitoSmartListViewModel.swift; sourceTree = SOURCE_ROOT; };
 		2662FC80246B793500FA7782 /* IncognitoSmartListViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = IncognitoSmartListViewController.storyboard; path = Ring/Features/Conversations/SmartList/IncognitoSmartListViewController.storyboard; sourceTree = SOURCE_ROOT; };
+		266C1DB82539F3A300978E87 /* RxRelay.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxRelay.framework; path = Carthage/Build/iOS/RxRelay.framework; sourceTree = "<group>"; };
 		2673D62925261DD9000C56CB /* ConferenceMenuItemsManagerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConferenceMenuItemsManagerTest.swift; sourceTree = "<group>"; };
 		2673D62D252624AB000C56CB /* ConferenceMenuItemsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConferenceMenuItemsManager.swift; sourceTree = "<group>"; };
 		2673D62F252657B0000C56CB /* ConferenceLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConferenceLayout.swift; sourceTree = "<group>"; };
@@ -821,6 +823,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				266C1DBB2539F3A300978E87 /* RxRelay.framework in Frameworks */,
 				649AD3C324B4CFC700A0236D /* libsqlite3.tbd in Frameworks */,
 				649AD3C624B4CFD500A0236D /* libxml2.tbd in Frameworks */,
 				04399A981D1C2F6100E99CD9 /* libz.tbd in Frameworks */,
@@ -931,6 +934,7 @@
 		02AED8171DD4C4B000F740BA /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				266C1DB82539F3A300978E87 /* RxRelay.framework */,
 				6452144724B4ACDE007203D5 /* libsqlite3.tbd */,
 				6452144524B4ACC8007203D5 /* libxml2.tbd */,
 				6452144324B4ACA7007203D5 /* CoreLocation.framework */,
@@ -2105,6 +2109,7 @@
 				"$(SRCROOT)/Carthage/Build/iOS/Differentiator.framework",
 				"$(SRCROOT)/Carthage/Build/iOS/SQLite.framework",
 				"$(SRCROOT)/Carthage/Build/iOS/GSKStretchyHeaderView.framework",
+				"$(SRCROOT)/Carthage/Build/iOS/RxRelay.framework",
 			);
 			name = "⚙️ Copy Frameworks";
 			outputPaths = (
@@ -2121,6 +2126,7 @@
 				"$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/Differentiator.framework",
 				"$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/SQLite.framework",
 				"$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/GSKStretchyHeaderView.framework",
+				"$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/RxRelay.framework",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
diff --git a/Ring/Ring/Calls/CallViewModel.swift b/Ring/Ring/Calls/CallViewModel.swift
index 6c6c4f6..9bdac8d 100644
--- a/Ring/Ring/Calls/CallViewModel.swift
+++ b/Ring/Ring/Calls/CallViewModel.swift
@@ -21,10 +21,10 @@
  */
 
 import RxSwift
+import RxRelay
 import SwiftyBeaver
 import Contacts
 import RxCocoa
-// swiftlint:disable type_body_length
 class CallViewModel: Stateable, ViewModel {
 
     //stateable
@@ -48,15 +48,15 @@
     var isHeadsetConnected = false
     var isAudioOnly = false
 
-    private lazy var currentCallVariable: Variable<CallModel> = {
-        Variable<CallModel>(self.call ?? CallModel())
+    private lazy var currentCallVariable: BehaviorRelay<CallModel> = {
+        BehaviorRelay<CallModel>(value: self.call ?? CallModel())
     }()
     lazy var currentCall: Observable<CallModel> = {
         currentCallVariable.asObservable()
     }()
     private var callDisposeBag = DisposeBag()
 
-    var conferenceMode: Variable<Bool> = Variable<Bool>(false)
+    var conferenceMode: BehaviorRelay<Bool> = BehaviorRelay<Bool>(value: false)
 
     var call: CallModel? {
         didSet {
@@ -73,7 +73,7 @@
                 .share()
                 .startWith(call)
                 .subscribe(onNext: { [weak self] call in
-                    self?.currentCallVariable.value = call
+                    self?.currentCallVariable.accept(call)
                 })
                 .disposed(by: self.callDisposeBag)
             // do other initializong only once
@@ -99,7 +99,7 @@
                     let conferenceCreated = conf.state == ConferenceState.conferenceCreated.rawValue
                     self?.rendererId = conferenceCreated ? conf.conferenceID : self!.call!.callId
                     self?.containerViewModel?.isConference = conferenceCreated
-                    self?.conferenceMode.value = conferenceCreated
+                    self?.conferenceMode.accept(conferenceCreated)
                 })
                 .disposed(by: self.disposeBag)
             self.rendererId = call.callId
@@ -217,7 +217,7 @@
     }()
 
     lazy var callDuration: Driver<String> = {
-        let timer = Observable<Int>.interval(1.0, scheduler: MainScheduler.instance)
+        let timer = Observable<Int>.interval(Durations.oneSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .takeUntil(currentCall
                 .filter { call in
                     !call.isExists()
@@ -547,7 +547,7 @@
             return
         }
         let conversationViewModel = ConversationViewModel(with: self.injectionBag)
-        conversationViewModel.conversation = Variable<ConversationModel>(conversation)
+        conversationViewModel.conversation = BehaviorRelay<ConversationModel>(value: conversation)
         self.stateSubject.onNext(ConversationState.fromCallToConversation(conversation: conversationViewModel))
     }
 
diff --git a/Ring/Ring/Calls/Conference/ContactPickerSection.swift b/Ring/Ring/Calls/Conference/ContactPickerSection.swift
index 7e23a2c..8178b8e 100644
--- a/Ring/Ring/Calls/Conference/ContactPickerSection.swift
+++ b/Ring/Ring/Calls/Conference/ContactPickerSection.swift
@@ -20,6 +20,7 @@
 
 import RxDataSources
 import RxSwift
+import RxCocoa
 
 struct Contact {
     var uri: String
@@ -27,7 +28,7 @@
     var registeredName: String
     var hash: String
 
-    lazy var presenceStatus: Variable<Bool>?  = {
+    lazy var presenceStatus: BehaviorRelay<Bool>?  = {
          self.presenceService
             .contactPresence[self.hash]
     }()
diff --git a/Ring/Ring/Calls/Conference/ContactPickerViewController.swift b/Ring/Ring/Calls/Conference/ContactPickerViewController.swift
index 2136863..13cc51d 100644
--- a/Ring/Ring/Calls/Conference/ContactPickerViewController.swift
+++ b/Ring/Ring/Calls/Conference/ContactPickerViewController.swift
@@ -193,7 +193,7 @@
         self.searchBar.tintColor = UIColor.jamiMain
         self.searchBar.placeholder = L10n.Smartlist.searchBarPlaceholder
         self.searchBar.rx.text.orEmpty
-            .throttle(0.5, scheduler: MainScheduler.instance)
+            .throttle(Durations.halfSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .distinctUntilChanged()
             .bind(to: self.viewModel.search)
             .disposed(by: disposeBag)
@@ -226,9 +226,10 @@
             dismissGR.delegate = self
             self.searchBar.addGestureRecognizer(dismissGR)
             self.rowSelectionHandler = { [weak self] row in
-                guard let contactToAdd: ConferencableItem = try? self?.tableView.rx.model(at: row) else { return }
-                self?.viewModel.contactSelected(contacts: [contactToAdd])
-                self?.removeView()
+                guard let self = self else { return }
+                guard let contactToAdd: ConferencableItem = try? self.tableView.rx.model(at: row) else { return }
+                self.viewModel.contactSelected(contacts: [contactToAdd])
+                self.removeView()
             }
         case .forConversation:
             self.searchBar.backgroundImage = UIImage()
@@ -240,7 +241,8 @@
                     let paths = self?.tableView.indexPathsForSelectedRows
                     var contacts = [ConferencableItem]()
                     paths?.forEach({ (path) in
-                        if let contactToAdd: ConferencableItem = try? self?.tableView.rx.model(at: path) {
+                        guard let self = self else { return }
+                        if let contactToAdd: ConferencableItem = try? self.tableView.rx.model(at: path) {
                             contacts.append(contactToAdd)
                         }
                     })
diff --git a/Ring/Ring/Constants/Durations.swift b/Ring/Ring/Constants/Durations.swift
index 000ee1e..00f8d4e 100644
--- a/Ring/Ring/Constants/Durations.swift
+++ b/Ring/Ring/Constants/Durations.swift
@@ -19,17 +19,40 @@
  */
 
 import Foundation
+import RxSwift
 
 public enum Durations {
     case textFieldThrottlingDuration
     case alertFlashDuration
+    case switchThrottlingDuration
+    case oneSecond
+    case halfSecond
+    case threeSeconds
+    case tenSeconds
+    case sixtySeconds
 
     var value: Double {
         switch self {
-        case .textFieldThrottlingDuration:
+        case .textFieldThrottlingDuration, .halfSecond:
             return 0.5
-        case .alertFlashDuration:
+        case .alertFlashDuration, .oneSecond:
             return 1.0
+        case .switchThrottlingDuration:
+            return 0.2
+        case .threeSeconds:
+            return 3
+        case .tenSeconds:
+            return 10
+        case .sixtySeconds:
+            return 60
         }
     }
+
+    var milliseconds: Int {
+        return Int(self.value * 1000)
+    }
+
+    func toTimeInterval() -> RxTimeInterval {
+        return RxTimeInterval.milliseconds(milliseconds)
+    }
 }
diff --git a/Ring/Ring/Contact/ContactViewModel.swift b/Ring/Ring/Contact/ContactViewModel.swift
index 955446e..b50197a 100644
--- a/Ring/Ring/Contact/ContactViewModel.swift
+++ b/Ring/Ring/Contact/ContactViewModel.swift
@@ -63,15 +63,15 @@
     var conversation: ConversationModel! {
         didSet {
             if let profile = conversation.participantProfile, let alias = profile.alias, !alias.isEmpty {
-                self.displayName.value = alias
+                self.displayName.accept(alias)
             }
             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
+                self.userName.accept(name)
             } else {
-                self.userName.value = conversation.hash
+                self.userName.accept(conversation.hash)
             }
             if account.type == AccountType.ring && self.userName.value == conversation.hash {
                 self.nameService.usernameLookupStatus
@@ -81,9 +81,9 @@
                     })
                     .subscribe(onNext: { [weak self] lookupNameResponse in
                         if let name = lookupNameResponse.name, !name.isEmpty {
-                            self?.userName.value = name
+                            self?.userName.accept(name)
                         } else if let address = lookupNameResponse.address {
-                            self?.userName.value = address
+                            self?.userName.accept(address)
                         }
                     })
                     .disposed(by: disposeBag)
@@ -115,12 +115,12 @@
                 .subscribe(onSuccess: { [weak self] vCard in
                     guard let self = self else { return }
                     if !VCardUtils.getName(from: vCard).isEmpty {
-                        self.displayName.value = VCardUtils.getName(from: vCard)
+                        self.displayName.accept(VCardUtils.getName(from: vCard))
                     }
                     guard let imageData = vCard.imageData else {
                         return
                     }
-                    self.profileImageData.value = imageData
+                    self.profileImageData.accept(imageData)
                 })
                 .disposed(by: self.disposeBag)
             self.profileService.getProfile(uri: conversation.participantUri,
@@ -129,18 +129,18 @@
                 .subscribe(onNext: { [weak self] profile in
                     guard let self = self else { return }
                     if let alias = profile.alias, !alias.isEmpty {
-                        self.displayName.value = alias
+                        self.displayName.accept(alias)
                     }
                     if let photo = profile.photo,
                         let data = NSData(base64Encoded: photo, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data? {
-                        self.profileImageData.value = data
+                        self.profileImageData.accept(data)
                     }
                 })
                 .disposed(by: disposeBag)
         }
     }
-    var userName = Variable<String>("")
-    var displayName = Variable<String>("")
+    var userName = BehaviorRelay<String>(value: "")
+    var displayName = BehaviorRelay<String>(value: "")
     lazy var titleName: Observable<String> = {
         return Observable.combineLatest(userName.asObservable(),
                                         displayName.asObservable()) {(userName, displayname) in
@@ -150,7 +150,7 @@
                                             return displayname
         }
     }()
-    var profileImageData = Variable<Data?>(nil)
+    var profileImageData = BehaviorRelay<Data?>(value: nil)
 
     required init (with injectionBag: InjectionBag) {
         self.contactService = injectionBag.contactsService
diff --git a/Ring/Ring/Features/ContactRequests/ContactRequestItem.swift b/Ring/Ring/Features/ContactRequests/ContactRequestItem.swift
index 39e2e11..20439a1 100644
--- a/Ring/Ring/Features/ContactRequests/ContactRequestItem.swift
+++ b/Ring/Ring/Features/ContactRequests/ContactRequestItem.swift
@@ -19,6 +19,7 @@
  */
 
 import RxSwift
+import RxCocoa
 import Contacts
 import SwiftyBeaver
 
@@ -26,9 +27,9 @@
 
     let contactRequest: ContactRequestModel
 
-    let userName = Variable("")
-    let profileName = Variable("")
-    let profileImageData = Variable<Data?>(nil)
+    let userName = BehaviorRelay(value: "")
+    let profileName = BehaviorRelay(value: "")
+    let profileImageData = BehaviorRelay<Data?>(value: nil)
     lazy var bestName: Observable<String> = {
         return Observable
             .combineLatest(userName.asObservable(),
@@ -45,9 +46,9 @@
     init(withContactRequest contactRequest: ContactRequestModel, profileService: ProfilesService,
          contactService: ContactsService) {
         self.contactRequest = contactRequest
-        self.userName.value = contactRequest.ringId
-        self.profileImageData.value = self.contactRequest.vCard?.imageData
-        self.profileName.value = VCardUtils.getName(from: self.contactRequest.vCard)
+        self.userName.accept(contactRequest.ringId)
+        self.profileImageData.accept(self.contactRequest.vCard?.imageData)
+        self.profileName.accept(VCardUtils.getName(from: self.contactRequest.vCard))
         guard let uri = JamiURI(schema: URIType.ring,
                                 infoHach: contactRequest.ringId)
             .uriString else { return }
@@ -58,10 +59,10 @@
                 if let photo = profile.photo, !photo.isEmpty,
                     let data = NSData(base64Encoded: photo,
                                       options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data? {
-                    self?.profileImageData.value = data
+                    self?.profileImageData.accept(data)
                 }
                 if let name = profile.alias, !name.isEmpty {
-                    self?.profileName.value = name
+                    self?.profileName.accept(name)
                 }
             })
             .disposed(by: self.disposeBag)
diff --git a/Ring/Ring/Features/ContactRequests/ContactRequestsViewModel.swift b/Ring/Ring/Features/ContactRequests/ContactRequestsViewModel.swift
index bcde4be..975010e 100644
--- a/Ring/Ring/Features/ContactRequests/ContactRequestsViewModel.swift
+++ b/Ring/Ring/Features/ContactRequests/ContactRequestsViewModel.swift
@@ -19,6 +19,7 @@
  */
 
 import RxSwift
+import RxCocoa
 import Contacts
 import SwiftyBeaver
 
@@ -121,9 +122,9 @@
             })
             .subscribe(onNext: { lookupNameResponse in
                 if lookupNameResponse.state == .found && !lookupNameResponse.name.isEmpty {
-                    item.userName.value = lookupNameResponse.name
+                    item.userName.accept(lookupNameResponse.name)
                 } else {
-                    item.userName.value = lookupNameResponse.address
+                    item.userName.accept(lookupNameResponse.address)
                 }
             })
             .disposed(by: self.disposeBag)
@@ -147,7 +148,7 @@
         guard let conversation = self.conversationService.findConversation(withUri: uri, withAccountId: account.id) else {
             return
         }
-        conversationViewModel.conversation = Variable<ConversationModel>(conversation)
+        conversationViewModel.conversation = BehaviorRelay<ConversationModel>(value: conversation)
         self.stateSubject.onNext(ConversationState.conversationDetail(conversationViewModel: conversationViewModel))
     }
 }
diff --git a/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift b/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift
index 45e187e..c54f98c 100644
--- a/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift
+++ b/Ring/Ring/Features/Conversations/Conversation/Cells/MessageCell.swift
@@ -71,7 +71,7 @@
 
     var disposeBag = DisposeBag()
 
-    var playerHeight = Variable<CGFloat>(0)
+    var playerHeight = BehaviorRelay<CGFloat>(value: 0)
 
     private(set) var messageId: Int64?
     private var isCopyable: Bool = false
@@ -109,7 +109,7 @@
         self.playerView?.removeFromSuperview()
         self.composingMsg.removeFromSuperview()
         self.transferImageView.image = nil
-        self.playerHeight.value = 0
+        self.playerHeight.accept(0)
         self.disposeBag = DisposeBag()
         openPreview.accept(false)
         self.messageLabel?.removeURLHandler()
@@ -432,7 +432,7 @@
         self.transferImageView.removeFromSuperview()
         self.playerView?.removeFromSuperview()
         self.composingMsg.removeFromSuperview()
-        self.playerHeight.value = 0
+        self.playerHeight.accept(0)
         self.bubbleViewMask?.isHidden = true
 
         guard let item = items?[indexPath.row] else { return }
@@ -639,7 +639,7 @@
         guard (self.playerView?.superview) != nil else {
             return
         }
-        playerHeight.value = height
+        playerHeight.accept(height)
     }
 
     func getMaxDimensionForTransfer() -> CGFloat {
@@ -698,7 +698,7 @@
                 self.transferProgressView.progress = 0
                 self.transferProgressView.target = 100
                 self.transferProgressView.currentProgress = 0
-                self.transferProgressView.status.value = message.initialTransferStatus
+                self.transferProgressView.status.accept(message.initialTransferStatus)
                 self.bubble.addSubview(self.transferProgressView)
             }
         }
diff --git a/Ring/Ring/Features/Conversations/Conversation/ConversationViewController.swift b/Ring/Ring/Features/Conversations/Conversation/ConversationViewController.swift
index ab346a3..1cd9a5f 100644
--- a/Ring/Ring/Features/Conversations/Conversation/ConversationViewController.swift
+++ b/Ring/Ring/Features/Conversations/Conversation/ConversationViewController.swift
@@ -484,7 +484,7 @@
         let tapGesture = UITapGestureRecognizer()
         titleView.addGestureRecognizer(tapGesture)
         tapGesture.rx.event
-            .throttle(RxTimeInterval(2), scheduler: MainScheduler.instance)
+            .throttle(Durations.switchThrottlingDuration.toTimeInterval(), scheduler: MainScheduler.instance)
             .bind(onNext: { [weak self] _ in
                 self?.contactTapped()
             })
@@ -547,7 +547,7 @@
         //set navigation buttons - call and send contact request
         let inviteItem = UIBarButtonItem()
         inviteItem.image = UIImage(named: "add_person")
-        inviteItem.rx.tap.throttle(0.5, scheduler: MainScheduler.instance)
+        inviteItem.rx.tap.throttle(Durations.halfSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .subscribe(onNext: { [weak self] in
                 self?.inviteItemTapped()
             })
@@ -560,7 +560,7 @@
         // call button
         let audioCallItem = UIBarButtonItem()
         audioCallItem.image = UIImage(asset: Asset.callButton)
-        audioCallItem.rx.tap.throttle(0.5, scheduler: MainScheduler.instance)
+        audioCallItem.rx.tap.throttle(Durations.halfSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .subscribe(onNext: { [weak self] in
                 self?.placeAudioOnlyCall()
             })
@@ -568,7 +568,7 @@
 
         let videoCallItem = UIBarButtonItem()
         videoCallItem.image = UIImage(asset: Asset.videoRunning)
-        videoCallItem.rx.tap.throttle(0.5, scheduler: MainScheduler.instance)
+        videoCallItem.rx.tap.throttle(Durations.halfSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .subscribe(onNext: { [weak self] in
                 self?.placeCall()
             })
@@ -617,7 +617,7 @@
             })
             .disposed(by: disposeBag)
         currentCallButton.rx.tap
-            .throttle(0.5, scheduler: MainScheduler.instance)
+            .throttle(Durations.halfSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .subscribe(onNext: { [weak self] in
                 self?.viewModel.openCall()
             })
diff --git a/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift b/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift
index eeeb088..5ac216b 100644
--- a/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift
+++ b/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift
@@ -24,6 +24,7 @@
 
 import UIKit
 import RxSwift
+import RxCocoa
 import SwiftyBeaver
 
 // swiftlint:disable file_length
@@ -47,7 +48,7 @@
 
     private let disposeBag = DisposeBag()
 
-    var messages = Variable([MessageViewModel]())
+    var messages = BehaviorRelay(value: [MessageViewModel]())
 
     private var players = [String: PlayerViewModel]()
 
@@ -90,8 +91,8 @@
 
     var isAccountSip: Bool = false
 
-    var displayName = Variable<String?>(nil)
-    var userName = Variable<String>("")
+    var displayName = BehaviorRelay<String?>(value: nil)
+    var userName = BehaviorRelay<String>(value: "")
     lazy var bestName: Observable<String> = {
         return Observable
             .combineLatest(userName.asObservable(),
@@ -103,13 +104,13 @@
     }()
 
     /// My contact's profile's image data
-    var profileImageData = Variable<Data?>(nil)
+    var profileImageData = BehaviorRelay<Data?>(value: nil)
     /// My profile's image data
     var myOwnProfileImageData: Data?
 
     var inviteButtonIsAvailable = BehaviorSubject(value: true)
 
-    var contactPresence = Variable<Bool>(false)
+    var contactPresence = BehaviorRelay<Bool>(value: false)
 
     required init(with injectionBag: InjectionBag) {
         self.injectionBag = injectionBag
@@ -125,26 +126,26 @@
     }
 
     private func setConversation(_ conversation: ConversationModel) {
-        self.conversation = Variable<ConversationModel>(conversation)
+        self.conversation = BehaviorRelay<ConversationModel>(value: conversation)
     }
 
     convenience init(with injectionBag: InjectionBag, conversation: ConversationModel, user: JamiSearchViewModel.UserSearchModel) {
         self.init(with: injectionBag)
-        self.userName.value = user.username
-        self.displayName.value = user.firstName + " " + user.lastName
-        self.profileImageData.value = user.profilePicture
+        self.userName.accept(user.username)
+        self.displayName.accept(user.firstName + " " + user.lastName)
+        self.profileImageData.accept(user.profilePicture)
         self.setConversation(conversation) // required to trigger the didSet
     }
 
-    var conversation: Variable<ConversationModel>! {
+    var conversation: BehaviorRelay<ConversationModel>! {
         didSet {
 
             if self.isJamsAccount { // fixes image and displayname not showing when adding contact for first time
                 if let profile = self.contactsService.getProfile(uri: self.contactUri, accountId: self.conversation.value.accountId),
                     let alias = profile.alias, let photo = profile.photo {
-                    self.displayName.value = alias
+                    self.displayName.accept(alias)
                     if let data = NSData(base64Encoded: photo, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data? {
-                        self.profileImageData.value = data
+                        self.profileImageData.accept(data)
                     }
                 }
             }
@@ -162,7 +163,7 @@
 
             if let account = self.accountService.getAccount(fromAccountId: self.conversation.value.accountId),
                 account.type == AccountType.sip {
-                self.userName.value = self.conversation.value.hash
+                self.userName.accept(self.conversation.value.hash)
                 self.isAccountSip = true
                 return
             }
@@ -179,9 +180,9 @@
 
             if !self.isJamsAccount || contact != nil {
                 if let contactUserName = contact?.userName {
-                    self.userName.value = contactUserName
+                    self.userName.accept(contactUserName)
                 } else if self.userName.value.isEmpty {
-                    self.userName.value = self.conversation.value.hash
+                    self.userName.accept(self.conversation.value.hash)
 
                     self.subscribeUserServiceLookupStatus()
                     self.nameService.lookupAddress(withAccount: self.conversation.value.accountId, nameserver: "", address: self.conversation.value.hash)
@@ -314,7 +315,9 @@
             .disposed(by: disposeBag)
         let message = self.messages.value.filter { $0.messageId == messageId }.first
         message?.removeFile(conversationID: self.conversation.value.conversationId, accountId: account.id)
-        self.messages.value.removeAll(where: { $0.messageId == messageId })
+        var values = self.messages.value
+        values.removeAll(where: { $0.messageId == messageId })
+        self.messages.accept(values)
     }
 
     func sendContactRequest() {
@@ -412,12 +415,12 @@
             })
             .map({ call in
                 let callIsValid = self.callIsValid(call: call)
-                self.currentCallId.value = callIsValid ? call.callId : ""
+                self.currentCallId.accept(callIsValid ? call.callId : "")
                 return callIsValid
             })
         }()
 
-    let currentCallId = Variable<String>("")
+    let currentCallId = BehaviorRelay<String>(value: "")
 
     func callIsValid (call: CallModel) -> Bool {
         return call.stateValue == CallState.hold.rawValue ||
@@ -463,7 +466,7 @@
         let composingIndicator = MessageViewModel(withInjectionBag: self.injectionBag, withMessage: msgModel, isLastDisplayed: false)
         composingIndicator.isComposingIndicator = true
         messagesValue.append(composingIndicator)
-        self.messages.value = messagesValue
+        self.messages.accept(messagesValue)
     }
 
     var composingMessage: Bool = false
@@ -478,7 +481,7 @@
         let conversationsMsg = messagesValue.filter { (messageModel) -> Bool in
             !messageModel.isComposingIndicator
         }
-        self.messages.value = conversationsMsg
+        self.messages.accept(conversationsMsg)
     }
 
     func isLastDisplayed(messageId: Int64) -> Bool {
@@ -506,7 +509,7 @@
                         return recipient1 == recipient2
                     })
                     .map({ [weak self] conversation -> (ConversationModel) in
-                        self?.conversation.value = conversation
+                        self?.conversation.accept(conversation)
                         return conversation
                     })
                     .flatMap({ conversation in
@@ -539,7 +542,7 @@
                     composingIndicator.isComposingIndicator = true
                     msg.append(composingIndicator)
                 }
-                self.messages.value = msg
+                self.messages.accept(msg)
             })
             .disposed(by: self.disposeBag)
     }
@@ -565,8 +568,8 @@
                     self?.log.warning("vCard for ringId: \(String(describing: self?.contactUri)) has no image")
                     return
                 }
-                self?.profileImageData.value = imageData
-                self?.displayName.value = VCardUtils.getName(from: vCard)
+                self?.profileImageData.accept(imageData)
+                self?.displayName.accept(VCardUtils.getName(from: vCard))
             })
             .disposed(by: self.disposeBag)
     }
@@ -577,10 +580,10 @@
                         createIfNotexists: false,
                         accountId: self.conversation.value.accountId)
             .subscribe(onNext: { [weak self] profile in
-                self?.displayName.value = profile.alias
+                self?.displayName.accept(profile.alias)
                 if let photo = profile.photo,
                     let data = NSData(base64Encoded: photo, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data? {
-                    self?.profileImageData.value = data
+                    self?.profileImageData.accept(data)
                 }
             })
             .disposed(by: disposeBag)
@@ -605,7 +608,7 @@
         if let contactPresence = self.presenceService.contactPresence[self.conversation.value.hash] {
             self.contactPresence = contactPresence
         } else {
-            self.contactPresence.value = false
+            self.contactPresence.accept(false)
             self.presenceService
                 .sharedResponseStream
                 .filter({ [weak self] serviceEvent in
@@ -625,7 +628,7 @@
             .contactPresence[self.conversation.value.hash] {
             self.contactPresence = contactPresence
         } else {
-            self.contactPresence.value = false
+            self.contactPresence.accept(false)
         }
     }
 
@@ -642,10 +645,10 @@
             })
             .subscribe(onNext: { [weak self] lookupNameResponse in
                 if let name = lookupNameResponse.name, !name.isEmpty {
-                    self?.userName.value = name
+                    self?.userName.accept(name)
                     contact?.userName = name
                 } else if let address = lookupNameResponse.address {
-                    self?.userName.value = address
+                    self?.userName.accept(address)
                 }
             })
             .disposed(by: disposeBag)
diff --git a/Ring/Ring/Features/Conversations/Conversation/MessageAccessoryView.swift b/Ring/Ring/Features/Conversations/Conversation/MessageAccessoryView.swift
index 63e6dc4..8b35108 100644
--- a/Ring/Ring/Features/Conversations/Conversation/MessageAccessoryView.swift
+++ b/Ring/Ring/Features/Conversations/Conversation/MessageAccessoryView.swift
@@ -22,6 +22,7 @@
 import UIKit
 import Reusable
 import RxSwift
+import RxRelay
 
 protocol MessageAccessoryViewDelegate: class {
     func setIsComposing(isComposing: Bool)
@@ -37,8 +38,8 @@
     @IBOutlet weak var emojisButtonTrailingConstraint: NSLayoutConstraint!
     @IBOutlet weak var sendButtonLeftConstraint: NSLayoutConstraint!
     @IBOutlet weak var textViewHeightConstraints: NSLayoutConstraint!
-    var messageTextViewHeight = Variable<CGFloat>(0.00)
-    var messageTextViewContent = Variable<String>("")
+    var messageTextViewHeight = BehaviorRelay<CGFloat>(value: 0.00)
+    var messageTextViewContent = BehaviorRelay<String>(value: "")
     weak var delegate: MessageAccessoryViewDelegate?
 
     var blurEffect: UIVisualEffectView?
@@ -93,11 +94,11 @@
                 self.layoutIfNeeded()
             }
         }
-        self.messageTextViewHeight.value = height
+        self.messageTextViewHeight.accept(height)
     }
 
     func textViewDidChange(_ textView: UITextView) {
-        self.messageTextViewContent.value = textView.text
+        self.messageTextViewContent.accept(textView.text)
     }
 
     func editingChanges() {
diff --git a/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift b/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift
index ef5f152..d6057b9 100644
--- a/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift
+++ b/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift
@@ -21,6 +21,7 @@
 
 import Foundation
 import RxSwift
+import RxCocoa
 
 /// This Coordinator drives the conversation navigation (Smartlist / Conversation detail)
 class ConversationsCoordinator: Coordinator, StateableResponsive, ConversationNavigation {
@@ -232,7 +233,7 @@
             return
         }
         let conversationViewModel = ConversationViewModel(with: self.injectionBag)
-        conversationViewModel.conversation = Variable<ConversationModel>(conversation)
+        conversationViewModel.conversation = BehaviorRelay<ConversationModel>(value: conversation)
         self.pushConversation(withConversationViewModel: conversationViewModel)
     }
 
diff --git a/Ring/Ring/Features/Conversations/SendFile/SendFileViewController.swift b/Ring/Ring/Features/Conversations/SendFile/SendFileViewController.swift
index 9104d6f..464402b 100644
--- a/Ring/Ring/Features/Conversations/SendFile/SendFileViewController.swift
+++ b/Ring/Ring/Features/Conversations/SendFile/SendFileViewController.swift
@@ -55,7 +55,7 @@
         self.viewModel.userStartSeeking()
         progressSlider.rx.value
         .subscribe(onNext: { [weak self] (value) in
-            self?.viewModel.seekTimeVariable.value = Float(value)
+            self?.viewModel.seekTimeVariable.accept(Float(value))
         })
         .disposed(by: self.sliderDisposeBag)
     }
diff --git a/Ring/Ring/Features/Conversations/SendFile/SendFileViewModel.swift b/Ring/Ring/Features/Conversations/SendFile/SendFileViewModel.swift
index 749b815..3e6f972 100644
--- a/Ring/Ring/Features/Conversations/SendFile/SendFileViewModel.swift
+++ b/Ring/Ring/Features/Conversations/SendFile/SendFileViewModel.swift
@@ -36,7 +36,7 @@
     lazy var state: Observable<State> = {
         return self.stateSubject.asObservable()
     }()
-    private let recordingState = Variable<RecordingState>(.initial)
+    private let recordingState = BehaviorRelay<RecordingState>(value: .initial)
 
     lazy var hideVideoControls: Observable<Bool> = {
         Observable.just(audioOnly)
@@ -83,7 +83,7 @@
     lazy var recordDuration: Driver<String> = {
         let emptyString = Observable.just("")
         let durationTimer = Observable<Int>
-            .interval(1.0, scheduler: MainScheduler.instance)
+            .interval(Durations.oneSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .takeUntil(self.recordingState
                 .asObservable()
                 .filter { state in
@@ -168,7 +168,7 @@
             .startLocalRecorder(audioOnly: audioOnly, path: url.path) else {
                 return
         }
-        recordingState.value = .recording
+        recordingState.accept(.recording)
         fileName = name
     }
 
@@ -182,7 +182,7 @@
 
     func stopRecording() {
         self.videoService.stopLocalRecorder(path: fileName)
-        recordingState.value = .recorded
+        recordingState.accept(.recorded)
         //create player after delay so recording could be finished
         DispatchQueue.main.asyncAfter(deadline: (.now() + 1)) { [weak self] in
             self?.createPlayer()
@@ -209,7 +209,7 @@
                                           peerInfoHash: self.conversation.hash,
                                           localIdentifier: nil)
         self.videoService.videRecordingFinished()
-        self.recordingState.value = .sent
+        self.recordingState.accept(.sent)
     }
 
     func cancel() {
@@ -219,7 +219,7 @@
         player?.closePlayer()
         self.player = nil
         self.videoService.videRecordingFinished()
-        recordingState.value = .sent
+        recordingState.accept(.sent)
         if fileName.isEmpty {
             return
         }
@@ -233,15 +233,15 @@
     //player
     var player: PlayerViewModel?
 
-    var playerDuration = Variable<Float>(0)
+    var playerDuration = BehaviorRelay<Float>(value: 0)
     var playerPosition = PublishSubject<Float>()
 
-    var seekTimeVariable = Variable<Float>(0) //player position set by user
+    var seekTimeVariable = BehaviorRelay<Float>(value: 0) //player position set by user
     let playBackFrame = PublishSubject<UIImage?>()
 
-    var pause = Variable<Bool>(true)
-    var audioMuted = Variable<Bool>(true)
-    var playerReady = Variable<Bool>(false)
+    var pause = BehaviorRelay<Bool>(value: true)
+    var audioMuted = BehaviorRelay<Bool>(value: true)
+    var playerReady = BehaviorRelay<Bool>(value: false)
     var playBackDisposeBag = DisposeBag()
 }
 
@@ -277,7 +277,7 @@
             })
             .take(1)
             .subscribe(onNext: { [weak self] ready in
-                self?.playerReady.value = ready
+                self?.playerReady.accept(ready)
                 self?.playBackDisposeBag = DisposeBag()
                 self?.subscribePlayerControls()
             })
@@ -287,19 +287,19 @@
     func subscribePlayerControls() {
         player?.audioMuted.asObservable()
             .subscribe(onNext: { [weak self] muted in
-                self?.audioMuted.value = muted
+                self?.audioMuted.accept(muted)
             })
             .disposed(by: playBackDisposeBag)
 
         player?.pause.asObservable()
             .subscribe(onNext: { [weak self] pause in
-                self?.pause.value = pause
+                self?.pause.accept(pause)
             })
             .disposed(by: playBackDisposeBag)
 
         player?.playerDuration.asObservable()
             .subscribe(onNext: { [weak self] duration in
-                self?.playerDuration.value = duration
+                self?.playerDuration.accept(duration)
             })
             .disposed(by: playBackDisposeBag)
 
@@ -317,7 +317,7 @@
 
         seekTimeVariable.asObservable()
             .subscribe(onNext: { [weak self](position) in
-                self?.player?.seekTimeVariable.value = position
+                self?.player?.seekTimeVariable.accept(position)
             })
             .disposed(by: playBackDisposeBag)
     }
diff --git a/Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewModel.swift b/Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewModel.swift
index ed8ebde..6f0b295 100644
--- a/Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewModel.swift
+++ b/Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewModel.swift
@@ -68,11 +68,11 @@
     }
 
     func conversationFound(conversation: ConversationViewModel?, name: String) {
-        contactFoundConversation.value = conversation
+        contactFoundConversation.accept(conversation)
         lookupName.accept(name)
     }
 
-    private var contactFoundConversation = Variable<ConversationViewModel?>(nil)
+    private var contactFoundConversation = BehaviorRelay<ConversationViewModel?>(value: nil)
 
     func showConversation (withConversationViewModel conversationViewModel: ConversationViewModel) {
     }
diff --git a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift
index 65bfb3c..a61b473 100644
--- a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift
+++ b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift
@@ -182,18 +182,18 @@
         generalSettingsButton.setImage(imageSettings, for: .normal)
         generalSettingsButton.contentMode = .scaleAspectFill
         let settingsButtonItem = UIBarButtonItem(customView: generalSettingsButton)
-        generalSettingsButton.rx.tap.throttle(0.5, scheduler: MainScheduler.instance)
+        generalSettingsButton.rx.tap.throttle(Durations.halfSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .subscribe(onNext: { [weak self] in
                 self?.viewModel.showGeneralSettings()
             })
             .disposed(by: self.disposeBag)
-        qrScanButton.rx.tap.throttle(0.5, scheduler: MainScheduler.instance)
+        qrScanButton.rx.tap.throttle(Durations.halfSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .subscribe(onNext: { [weak self] in
                 self?.openScan()
             })
             .disposed(by: self.disposeBag)
 
-        phoneBookButton.rx.tap.throttle(0.5, scheduler: MainScheduler.instance)
+        phoneBookButton.rx.tap.throttle(Durations.halfSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .subscribe(onNext: { [weak self] in
                 guard let self = self else { return }
                 self.contactPicker.delegate = self
@@ -250,7 +250,7 @@
                 .widthAnchor
                 .constraint(equalToConstant: 80).isActive = true
         accountButton.rx.tap
-            .throttle(0.5, scheduler: MainScheduler.instance)
+            .throttle(Durations.halfSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .subscribe(onNext: { [weak self] in
                 self?.openAccountsList()
             })
@@ -315,7 +315,7 @@
         toolbar.items = [flexibleBarButton, addBarButton]
         accountPickerTextView.inputAccessoryView = toolbar
         addAccountButton.rx.tap
-            .throttle(0.5, scheduler: MainScheduler.instance)
+            .throttle(Durations.halfSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .subscribe(onNext: { [weak self] in
                 self?.startAccountCreation()
             })
diff --git a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewModel.swift b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewModel.swift
index 3eaf6d5..382229d 100644
--- a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewModel.swift
+++ b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewModel.swift
@@ -22,6 +22,7 @@
  */
 
 import RxSwift
+import RxCocoa
 import SwiftyBeaver
 
 class SmartlistViewModel: Stateable, ViewModel, FilterConversationDataSource {
@@ -50,7 +51,7 @@
 
     var searching = PublishSubject<Bool>()
 
-    private var contactFoundConversation = Variable<ConversationViewModel?>(nil)
+    private var contactFoundConversation = BehaviorRelay<ConversationViewModel?>(value: nil)
 
     lazy var hideNoConversationsMessage: Observable<Bool> = {
         return Observable<Bool>
@@ -161,7 +162,7 @@
                             self.conversationViewModels.append(contactFound)
                         } else {
                             conversationViewModel = ConversationViewModel(with: self.injectionBag)
-                            conversationViewModel?.conversation = Variable<ConversationModel>(conversationModel)
+                            conversationViewModel?.conversation = BehaviorRelay<ConversationModel>(value: conversationModel)
                             if let conversation = conversationViewModel {
                                 self.conversationViewModels
                                     .append(conversation)
@@ -232,7 +233,7 @@
 
     /// For FilterConversationDataSource protocol
     func conversationFound(conversation: ConversationViewModel?, name: String) {
-        contactFoundConversation.value = conversation
+        contactFoundConversation.accept(conversation)
     }
 
     func delete(conversationViewModel: ConversationViewModel) {
@@ -318,7 +319,7 @@
                                              accountId: account.id,
                                              hash: number)
         let newConversation = ConversationViewModel(with: self.injectionBag)
-        newConversation.conversation = Variable<ConversationModel>(conversation)
+        newConversation.conversation = BehaviorRelay<ConversationModel>(value: conversation)
         self.stateSubject
             .onNext(ConversationState
                 .conversationDetail(conversationViewModel:
diff --git a/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchView.swift b/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchView.swift
index d1fc7fa..11f4d46 100644
--- a/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchView.swift
+++ b/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchView.swift
@@ -125,7 +125,7 @@
 
     private func configureSearchBar() {
         self.searchBar.rx.text.orEmpty
-            .debounce(Durations.textFieldThrottlingDuration.value, scheduler: MainScheduler.instance)
+            .debounce(Durations.textFieldThrottlingDuration.toTimeInterval(), scheduler: MainScheduler.instance)
             .bind(to: self.viewModel.searchBarText)
             .disposed(by: disposeBag)
 
diff --git a/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchViewModel.swift b/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchViewModel.swift
index 73264df..0c93af1 100644
--- a/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchViewModel.swift
+++ b/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchViewModel.swift
@@ -71,10 +71,10 @@
     }()
 
     private var contactFoundConversation = BehaviorRelay<ConversationViewModel?>(value: nil)
-    private var filteredResults = Variable([ConversationViewModel]())
+    private var filteredResults = BehaviorRelay(value: [ConversationViewModel]())
     private let jamsResults = BehaviorRelay<[ConversationViewModel]>(value: [])
 
-    let searchBarText = Variable<String>("")
+    let searchBarText = BehaviorRelay<String>(value: "")
     var isSearching: Observable<Bool>!
     var searchStatus = PublishSubject<String>()
     let dataSource: FilterConversationDataSource
@@ -124,9 +124,9 @@
                         let conversation = ConversationModel(withParticipantUri: uri, accountId: account.id)
                         let newConversation = ConversationViewModel(with: injectionBag)
                         if lookupResponse.name == self.searchBarText.value {
-                            newConversation.userName.value = lookupResponse.name
+                            newConversation.userName.accept(lookupResponse.name)
                         }
-                        newConversation.conversation = Variable<ConversationModel>(conversation)
+                        newConversation.conversation = BehaviorRelay<ConversationModel>(value: conversation)
                         self.contactFoundConversation.accept(newConversation)
                         self.dataSource.conversationFound(conversation: newConversation, name: self.searchBarText.value)
                     }
@@ -200,7 +200,7 @@
         self.contactFoundConversation.accept(nil)
         self.jamsResults.accept([])
         self.dataSource.conversationFound(conversation: nil, name: "")
-        self.filteredResults.value.removeAll()
+        self.filteredResults.accept([])
         self.searchStatus.onNext("")
 
         if text.isEmpty { return }
@@ -217,7 +217,7 @@
                 })
 
         if !filteredConversations.isEmpty {
-            self.filteredResults.value = filteredConversations
+            self.filteredResults.accept(filteredConversations)
         }
 
         if self.accountsService.isJams(for: currentAccount.id) {
@@ -232,7 +232,7 @@
                                                  accountId: currentAccount.id,
                                                  hash: text)
             let newConversation = ConversationViewModel(with: self.injectionBag)
-            newConversation.conversation = Variable<ConversationModel>(conversation)
+            newConversation.conversation = BehaviorRelay<ConversationModel>(value: conversation)
             self.contactFoundConversation.accept(newConversation)
             self.dataSource.conversationFound(conversation: newConversation, name: self.searchBarText.value)
             return
@@ -249,7 +249,7 @@
             let conversation = ConversationModel(withParticipantUri: uri,
                                                  accountId: currentAccount.id)
             let newConversation = ConversationViewModel(with: self.injectionBag)
-            newConversation.conversation = Variable<ConversationModel>(conversation)
+            newConversation.conversation = BehaviorRelay<ConversationModel>(value: conversation)
             self.contactFoundConversation.accept(newConversation)
             self.dataSource.conversationFound(conversation: newConversation, name: self.searchBarText.value)
         }
diff --git a/Ring/Ring/Features/Conversations/views/PlayerView.swift b/Ring/Ring/Features/Conversations/views/PlayerView.swift
index b90921b..5f4af02 100644
--- a/Ring/Ring/Features/Conversations/views/PlayerView.swift
+++ b/Ring/Ring/Features/Conversations/views/PlayerView.swift
@@ -89,7 +89,7 @@
         self.viewModel.userStartSeeking()
         progressSlider.rx.value
             .subscribe(onNext: { [weak self] (value) in
-                self?.viewModel.seekTimeVariable.value = Float(value)
+                self?.viewModel.seekTimeVariable.accept(Float(value))
             })
             .disposed(by: self.sliderDisposeBag)
     }
diff --git a/Ring/Ring/Features/Conversations/views/PlayerViewModel.swift b/Ring/Ring/Features/Conversations/views/PlayerViewModel.swift
index b461797..02382ec 100644
--- a/Ring/Ring/Features/Conversations/views/PlayerViewModel.swift
+++ b/Ring/Ring/Features/Conversations/views/PlayerViewModel.swift
@@ -26,15 +26,15 @@
 }
 
 class PlayerViewModel {
-    var hasVideo = Variable<Bool>(true)
-    var playerDuration = Variable<Float>(0)
+    var hasVideo = BehaviorRelay<Bool>(value: true)
+    var playerDuration = BehaviorRelay<Float>(value: 0)
     var playerPosition = PublishSubject<Float>()
-    let seekTimeVariable = Variable<Float>(0)
+    let seekTimeVariable = BehaviorRelay<Float>(value: 0)
     let playBackFrame = PublishSubject<UIImage?>()
 
-    let pause = Variable<Bool>(true)
-    let audioMuted = Variable<Bool>(true)
-    let playerReady = Variable<Bool>(false)
+    let pause = BehaviorRelay<Bool>(value: true)
+    let audioMuted = BehaviorRelay<Bool>(value: true)
+    let playerReady = BehaviorRelay<Bool>(value: false)
     weak var delegate: PlayerDelegate?
 
     var firstFrame: UIImage?
@@ -53,18 +53,18 @@
     }
 
     func createPlayer() {
-        self.playerReady.value = false
+        self.playerReady.accept(false)
         let fname = "file://" + filePath
         if !self.playerId.isEmpty {
             if let frame = firstFrame {
                 self.playBackFrame.onNext(frame)
             }
-            self.playerReady.value = true
+            self.playerReady.accept(true)
             return
         }
         invalidateTimer()
         self.playerId = self.videoService.createPlayer(path: fname)
-        self.pause.value = true
+        self.pause.accept(true)
         self.playerPosition.onNext(0)
         // subscribe for frame playback
         //get first frame, pause player and seek back to first frame
@@ -80,7 +80,7 @@
             self?.muteAudio()
             self?.seekToTime(time: 0)
             self?.startTimer()
-            self?.playerReady.value = true
+            self?.playerReady.accept(true)
             if let image = renderer?.data {
                 DispatchQueue.main.async {
                     self?.delegate?.extractedVideoFrame(with: image.size.height)
@@ -111,16 +111,16 @@
                         }
                         return
                 }
-                self?.playerDuration.value = duration
-                self?.hasVideo.value = player.hasVideo
+                self?.playerDuration.accept(duration)
+                self?.hasVideo.accept(player.hasVideo)
                 if !player.hasVideo {
                     self?.startTimer()
-                    self?.audioMuted.value = false
-                    self?.playerReady.value = true
+                    self?.audioMuted.accept(false)
+                    self?.playerReady.accept(true)
                     return
                 }
                 // mute audio so it is not played when extracting first frame
-                self?.audioMuted.value = true
+                self?.audioMuted.accept(true)
                 self?.videoService.mutePlayerAudio(playerId: player.playerId,
                                                    mute: self?.audioMuted.value ?? true)
                 //unpause player to get first video frame
@@ -134,14 +134,14 @@
         if pause.value {
             return
         }
-        pause.value = true
+        pause.accept(true)
         videoService.pausePlayer(playerId: playerId, pause: pause.value)
     }
 
     func userStopSeeking() {
         let time = Int(self.playerDuration.value * seekTimeVariable.value)
         self.videoService.seekToTime(time: time, playerId: playerId)
-        pause.value = false
+        pause.accept(false)
         videoService.pausePlayer(playerId: playerId, pause: pause.value)
         startTimer()
     }
@@ -165,12 +165,12 @@
     }
 
     func toglePause() {
-        pause.value.toggle()
+        pause.accept(!pause.value)
         videoService.pausePlayer(playerId: playerId, pause: pause.value)
     }
 
     func muteAudio() {
-        audioMuted.value.toggle()
+        audioMuted.accept(!audioMuted.value)
         videoService.mutePlayerAudio(playerId: playerId, mute: audioMuted.value)
     }
 
@@ -194,7 +194,7 @@
         self.playerPosition.onNext(progress)
         // if new time less than previous file is finished
         if time < currentTime {
-            pause.value = true
+            pause.accept(true)
             if let image = self.firstFrame {
                 self.playBackFrame.onNext(image)
             }
diff --git a/Ring/Ring/Features/Me/LinkNewDeviceViewModel.swift b/Ring/Ring/Features/Me/LinkNewDeviceViewModel.swift
index 13c0332..38d729d 100644
--- a/Ring/Ring/Features/Me/LinkNewDeviceViewModel.swift
+++ b/Ring/Ring/Features/Me/LinkNewDeviceViewModel.swift
@@ -20,6 +20,7 @@
 
 import Foundation
 import RxSwift
+import RxCocoa
 import RxDataSources
 
 enum ExportAccountResponse: Int {
@@ -79,7 +80,7 @@
         return self.stateSubject.asObservable()
     }()
 
-    private let generatingState = Variable(GeneratingPinState.initial)
+    private let generatingState = BehaviorRelay(value: GeneratingPinState.initial)
     lazy var observableState: Observable <GeneratingPinState> = {
         return self.generatingState.asObservable()
     }()
@@ -103,9 +104,9 @@
     }
 
     func linkDevice(with password: String?) {
-        self.generatingState.value = GeneratingPinState.generatingPin
+        self.generatingState.accept(GeneratingPinState.generatingPin)
         guard let password = password else {
-            self.generatingState.value = GeneratingPinState.error(error: PinError.passwordError)
+            self.generatingState.accept(GeneratingPinState.error(error: PinError.passwordError))
             return
         }
         self.accountService.exportOnRing(withPassword: password)
@@ -121,30 +122,30 @@
                                 switch state {
                                 case ExportAccountResponse.success.rawValue:
                                     if let pin: String = exportComplitedEvent.getEventInput(.pin) {
-                                        self.generatingState.value = GeneratingPinState.success(pin: pin)
+                                        self.generatingState.accept(GeneratingPinState.success(pin: pin))
                                     } else {
-                                        self.generatingState.value = GeneratingPinState.error(error: PinError.defaultError)
+                                        self.generatingState.accept(GeneratingPinState.error(error: PinError.defaultError))
                                     }
                                 case ExportAccountResponse.wrongPassword.rawValue:
-                                    self.generatingState.value = GeneratingPinState.error(error: PinError.passwordError)
+                                    self.generatingState.accept(GeneratingPinState.error(error: PinError.passwordError))
                                 case ExportAccountResponse.networkProblem.rawValue:
-                                    self.generatingState.value = GeneratingPinState.error(error: PinError.networkError)
+                                    self.generatingState.accept(GeneratingPinState.error(error: PinError.networkError))
                                 default:
-                                    self.generatingState.value = GeneratingPinState.error(error: PinError.defaultError)
+                                    self.generatingState.accept(GeneratingPinState.error(error: PinError.defaultError))
                                 }
                             }
                         })
                         .disposed(by: self.disposeBag)
                 } else {
-                    self.generatingState.value = GeneratingPinState.error(error: PinError.defaultError)
+                    self.generatingState.accept(GeneratingPinState.error(error: PinError.defaultError))
                 }
             }, onError: { error in
-                self.generatingState.value = GeneratingPinState.error(error: PinError.passwordError)
+                self.generatingState.accept(GeneratingPinState.error(error: PinError.passwordError))
             })
             .disposed(by: self.disposeBag)
     }
 
     func refresh() {
-        self.generatingState.value = GeneratingPinState.initial
+        self.generatingState.accept(GeneratingPinState.initial)
     }
 }
diff --git a/Ring/Ring/Features/Me/Me/BlockListViewModel.swift b/Ring/Ring/Features/Me/Me/BlockListViewModel.swift
index bc22400..9cd6b7a 100644
--- a/Ring/Ring/Features/Me/Me/BlockListViewModel.swift
+++ b/Ring/Ring/Features/Me/Me/BlockListViewModel.swift
@@ -20,6 +20,7 @@
 
 import Reusable
 import RxSwift
+import RxRelay
 
 class BlockListViewModel: ViewModel {
 
@@ -48,7 +49,7 @@
         })
     }()
 
-    lazy var contacts: Variable<[ContactModel]> = {
+    lazy var contacts: BehaviorRelay<[ContactModel]> = {
         return self.contactService.contacts
     }()
 
diff --git a/Ring/Ring/Features/Me/Me/MeViewController.swift b/Ring/Ring/Features/Me/Me/MeViewController.swift
index 64d9559..ba9649e 100644
--- a/Ring/Ring/Features/Me/Me/MeViewController.swift
+++ b/Ring/Ring/Features/Me/Me/MeViewController.swift
@@ -129,12 +129,12 @@
             .disposed(by: self.disposeBag)
         let infoItem = UIBarButtonItem(customView: infoButton)
         let qrCodeButtonItem = UIBarButtonItem(customView: qrCodeButton)
-        infoButton.rx.tap.throttle(0.5, scheduler: MainScheduler.instance)
+        infoButton.rx.tap.throttle(Durations.halfSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .subscribe(onNext: { [weak self] in
                 self?.infoItemTapped()
             })
             .disposed(by: self.disposeBag)
-        qrCodeButton.rx.tap.throttle(0.5, scheduler: MainScheduler.instance)
+        qrCodeButton.rx.tap.throttle(Durations.halfSecond.toTimeInterval(), scheduler: MainScheduler.instance)
             .subscribe(onNext: { [weak self] in
                 self?.qrCodeItemTapped()
             })
@@ -319,7 +319,7 @@
                         .disposed(by: cell.disposeBag)
                     switchView.rx
                         .isOn.changed
-                        .debounce(0.2, scheduler: MainScheduler.instance)
+                        .debounce(Durations.switchThrottlingDuration.toTimeInterval(), scheduler: MainScheduler.instance)
                         .distinctUntilChanged()
                         .asObservable()
                         .subscribe(onNext: {[weak self] enable in
@@ -497,7 +497,7 @@
                     switchView.setOn(self.viewModel.notificationsEnabled, animated: false)
                     switchView.rx
                         .isOn.changed
-                        .debounce(0.2, scheduler: MainScheduler.instance)
+                        .debounce(Durations.switchThrottlingDuration.toTimeInterval(), scheduler: MainScheduler.instance)
                         .distinctUntilChanged()
                         .asObservable()
                         .subscribe(onNext: {[weak self] value in
@@ -521,7 +521,7 @@
                         .disposed(by: cell.disposeBag)
                     switchView.rx
                         .isOn.changed
-                        .debounce(0.2, scheduler: MainScheduler.instance)
+                        .debounce(Durations.switchThrottlingDuration.toTimeInterval(), scheduler: MainScheduler.instance)
                         .distinctUntilChanged()
                         .asObservable()
                         .subscribe(onNext: {[weak self] enable in
@@ -622,7 +622,7 @@
                         .disposed(by: cell.disposeBag)
                     switchView.rx
                         .isOn.changed
-                        .debounce(0.2, scheduler: MainScheduler.instance)
+                        .debounce(Durations.switchThrottlingDuration.toTimeInterval(), scheduler: MainScheduler.instance)
                         .distinctUntilChanged()
                         .asObservable()
                         .subscribe(onNext: {[weak self] enable in
@@ -746,7 +746,7 @@
                 .disposed(by: cell.disposeBag)
             text.rx.text.orEmpty.distinctUntilChanged()
                 .bind { [weak self, weak rightButton] newText in
-                    self?.viewModel.sipPassword.value = newText
+                    self?.viewModel.sipPassword.accept(newText)
                     rightButton?.isHidden = newText.isEmpty
                     rightButton?.isEnabled = !newText.isEmpty
                 }
diff --git a/Ring/Ring/Features/Me/Me/MeViewModel.swift b/Ring/Ring/Features/Me/Me/MeViewModel.swift
index 80283a5..2d0c25c 100644
--- a/Ring/Ring/Features/Me/Me/MeViewModel.swift
+++ b/Ring/Ring/Features/Me/Me/MeViewModel.swift
@@ -51,7 +51,7 @@
         case sipServer(value: String)
         case port(value: String)
         case proxyServer(value: String)
-        case accountState(state: Variable<String>)
+        case accountState(state: BehaviorRelay<String>)
         case enableAccount
         case changePassword
         case boothMode
@@ -114,7 +114,7 @@
 
      // MARK: - configure table sections
 
-    var showActionState = Variable<ActionsState>(.noAction)
+    var showActionState = BehaviorRelay<ActionsState>(value: .noAction)
 
     func getRingId() -> String? {
         if let uri = self.accountService.currentAccount?.details?.get(withConfigKeyModel: ConfigKeyModel(withKey: .accountUsername)) {
@@ -178,8 +178,8 @@
                                             .ordinary(label: L10n.AccountPage.removeAccountTitle)]))
     }()
 
-    lazy var accountStatus: Variable<String> = {
-        let accStatus = Variable<String>("")
+    lazy var accountStatus: BehaviorRelay<String> = {
+        let accStatus = BehaviorRelay<String>(value: "")
         Observable
             .combineLatest(accountState,
                            accountEnabled.asObservable()) { (state, enabled) -> String in
@@ -201,7 +201,7 @@
                             }
             }
             .subscribe(onNext: { status in
-                accStatus.value = status
+                accStatus.accept(status)
             })
             .disposed(by: self.disposeBag)
         return accStatus
@@ -251,7 +251,7 @@
         }
     }()
 
-    let isAccountSip = Variable<Bool>(false)
+    let isAccountSip = BehaviorRelay<Bool>(value: false)
     var sipInfoUpdated = BehaviorSubject<Bool>(value: true)
 
     lazy var otherSipSettings: Observable<SettingsSection> = {
@@ -278,11 +278,11 @@
                 server = details.get(withConfigKeyModel: ConfigKeyModel.init(withKey: .accountHostname))
                 port = details.get(withConfigKeyModel: ConfigKeyModel.init(withKey: .localPort))
                 proxyServer = details.get(withConfigKeyModel: ConfigKeyModel.init(withKey: .accountRouteSet))
-                self.sipUsername.value = username
-                self.sipPassword.value = password
-                self.sipServer.value = server
-                self.port.value = port
-                self.proxyServer.value = proxyServer
+                self.sipUsername.accept(username)
+                self.sipPassword.accept(password)
+                self.sipServer.accept(server)
+                self.port.accept(port)
+                self.proxyServer.accept(proxyServer)
             }
             //isIP2IP
             if server.isEmpty {
@@ -318,7 +318,7 @@
             })
             .disposed(by: self.disposeBag)
         if let account = self.accountService.currentAccount {
-            self.isAccountSip.value = account.type == AccountType.sip
+            self.isAccountSip.accept(account.type == AccountType.sip)
         }
         return Observable.combineLatest(jamiSettings, sipSettings,
                                         isAccountSip.asObservable()) {(jami, sip, isSip) in
@@ -341,7 +341,7 @@
         tempBag = DisposeBag()
         self.currentAccountState.onNext(account.status)
         self.secureTextEntry.onNext(true)
-        self.accountEnabled.value = account.enabled
+        self.accountEnabled.accept(account.enabled)
         // subscribe for updating status for current account
         self.accountService.sharedResponseStream
             .filter({ serviceEvent in
@@ -359,7 +359,7 @@
                 self.currentAccountState.onNext(accountState)
             })
             .disposed(by: self.tempBag)
-        self.isAccountSip.value = account.type == AccountType.sip
+        self.isAccountSip.accept(account.type == AccountType.sip)
         if account.type == AccountType.sip {
             sipInfoUpdated.onNext(true)
             return
@@ -449,7 +449,7 @@
 
     func registerUsername(username: String, password: String) {
         guard let accountId = self.accountService.currentAccount?.id else {
-            self.showActionState.value = .hideLoading
+            self.showActionState.accept(.hideLoading)
             return
         }
 
@@ -463,12 +463,12 @@
                         self.currentAccountUserName
                             .onNext(self.userNameForAccount(account: account))
                     }
-                    self.showActionState.value = .usernameRegistered
+                    self.showActionState.accept(.usernameRegistered)
                 } else {
-                    self.showActionState.value = .usernameRegistrationFailed(errorMessage: L10n.AccountPage.usernameRegistrationFailed)
+                    self.showActionState.accept(.usernameRegistrationFailed(errorMessage: L10n.AccountPage.usernameRegistrationFailed))
                 }
             }, onError: { _ in
-                self.showActionState.value = .usernameRegistrationFailed(errorMessage: L10n.AccountPage.usernameRegistrationFailed)
+                self.showActionState.accept(.usernameRegistrationFailed(errorMessage: L10n.AccountPage.usernameRegistrationFailed))
             })
             .disposed(by: self.disposeBag)
     }
@@ -499,7 +499,7 @@
 
     func revokeDevice(deviceId: String, accountPassword password: String) {
         guard let accountId = self.accountService.currentAccount?.id else {
-            self.showActionState.value = .hideLoading
+            self.showActionState.accept(.hideLoading)
             return
         }
         self.accountService.sharedResponseStream
@@ -512,13 +512,13 @@
                     let deviceID: String = deviceEvent.getEventInput(.deviceId) {
                     switch state {
                     case DeviceRevocationState.success.rawValue:
-                        self.showActionState.value = .deviceRevokedWithSuccess(deviceId: deviceID)
+                        self.showActionState.accept(.deviceRevokedWithSuccess(deviceId: deviceID))
                     case DeviceRevocationState.wrongPassword.rawValue:
-                        self.showActionState.value = .deviceRevokationError(deviceId:deviceID, errorMessage: L10n.AccountPage.deviceRevocationWrongPassword)
+                        self.showActionState.accept(.deviceRevokationError(deviceId:deviceID, errorMessage: L10n.AccountPage.deviceRevocationWrongPassword))
                     case DeviceRevocationState.unknownDevice.rawValue:
-                        self.showActionState.value = .deviceRevokationError(deviceId:deviceID, errorMessage: L10n.AccountPage.deviceRevocationUnknownDevice)
+                        self.showActionState.accept(.deviceRevokationError(deviceId:deviceID, errorMessage: L10n.AccountPage.deviceRevocationUnknownDevice))
                     default:
-                        self.showActionState.value = .deviceRevokationError(deviceId:deviceID, errorMessage: L10n.AccountPage.deviceRevocationError)
+                        self.showActionState.accept(.deviceRevokationError(deviceId:deviceID, errorMessage: L10n.AccountPage.deviceRevocationError))
                     }
                 }
             })
@@ -660,13 +660,13 @@
 
     private var _notificationsEnabled: Bool = true
 
-    lazy var notificationsPermitted: Variable<Bool> = {
-        let variable = Variable<Bool>(LocalNotificationsHelper.isEnabled())
+    lazy var notificationsPermitted: BehaviorRelay<Bool> = {
+        let variable = BehaviorRelay<Bool>(value: LocalNotificationsHelper.isEnabled())
         UserDefaults.standard.rx
             .observe(Bool.self, enbleNotificationsKey)
             .subscribe(onNext: { enable in
                 if let enable = enable {
-                    variable.value = enable
+                    variable.accept(enable)
                 }
             })
             .disposed(by: self.disposeBag)
@@ -719,24 +719,24 @@
         self.stateSubject.onNext(MeState.needAccountMigration(accountId: allAccounts[1].id))
     }
 
-    lazy var accountEnabled: Variable<Bool> = {
+    lazy var accountEnabled: BehaviorRelay<Bool> = {
         if let account = self.accountService.currentAccount,
             let details = account.details {
             let enable = details.get(withConfigKeyModel:
                 ConfigKeyModel.init(withKey: .accountEnable)).boolValue
-            return Variable<Bool>(enable)
+            return BehaviorRelay<Bool>(value: enable)
         }
-        return Variable<Bool>(true)
+        return BehaviorRelay<Bool>(value: true)
     }()
 
-    lazy var peerDiscoveryEnabled: Variable<Bool> = {
+    lazy var peerDiscoveryEnabled: BehaviorRelay<Bool> = {
         if let account = self.accountService.currentAccount,
             let details = account.details {
             let enable = details.get(withConfigKeyModel:
                 ConfigKeyModel.init(withKey: .dhtPeerDiscovery)).boolValue
-            return Variable<Bool>(enable)
+            return BehaviorRelay<Bool>(value: enable)
         }
-        return Variable<Bool>(true)
+        return BehaviorRelay<Bool>(value: true)
     }()
 
     lazy var keepAliveEnabled: BehaviorRelay<Bool> = {
@@ -753,14 +753,14 @@
         if self.accountEnabled.value == enable { return }
         guard let account = self.accountService.currentAccount else { return }
         self.accountService.enableAccount(enable: enable, accountId: account.id)
-        accountEnabled.value = enable
+        accountEnabled.accept(enable)
     }
 
     func enablePeerDiscovery(enable: Bool) {
         guard self.peerDiscoveryEnabled.value != enable,
             let account = self.accountService.currentAccount else { return }
         self.accountService.enablePeerDiscovery(enable: enable, accountId: account.id)
-        peerDiscoveryEnabled.value = enable
+        peerDiscoveryEnabled.accept(enable)
     }
 
     func enableKeepAlive(enable: Bool) {
@@ -771,11 +771,11 @@
     }
 
     // MARK: Sip Credentials
-    let sipUsername = Variable<String>("")
-    let sipPassword = Variable<String>("")
-    let sipServer = Variable<String>("")
-    let port = Variable<String>("")
-    let proxyServer = Variable<String>("")
+    let sipUsername = BehaviorRelay<String>(value: "")
+    let sipPassword = BehaviorRelay<String>(value: "")
+    let sipServer = BehaviorRelay<String>(value: "")
+    let port = BehaviorRelay<String>(value: "")
+    let proxyServer = BehaviorRelay<String>(value: "")
 
     func updateSipSettings() {
         guard let account = self.accountService.currentAccount, let details = account.details, let credentials = account.credentialDetails.first else { return }
diff --git a/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewController.swift b/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewController.swift
index 176cdd5..6e15130 100644
--- a/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewController.swift
+++ b/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewController.swift
@@ -305,7 +305,15 @@
             })
             .disposed(by: self.disposeBag)
         self.notificationsSwitch.rx.isOn.bind(to: self.viewModel.notificationSwitch).disposed(by: self.disposeBag)
-        self.usernameTextField.rx.text.orEmpty.throttle(3, scheduler: MainScheduler.instance).distinctUntilChanged().bind(to: self.viewModel.username).disposed(by: self.disposeBag)
+        self.usernameTextField
+            .rx
+            .text
+            .orEmpty
+            .throttle(Durations.threeSeconds.toTimeInterval(),
+                      scheduler: MainScheduler.instance)
+            .distinctUntilChanged()
+            .bind(to: self.viewModel.username)
+            .disposed(by: self.disposeBag)
         self.passwordTextField.rx.text.orEmpty.bind(to: self.viewModel.password).disposed(by: self.disposeBag)
         self.confirmPasswordTextField.rx.text.orEmpty.bind(to: self.viewModel.confirmPassword).disposed(by: self.disposeBag)
 
diff --git a/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewModel.swift b/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewModel.swift
index 97bcc3d..7ef494f 100644
--- a/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewModel.swift
+++ b/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewModel.swift
@@ -21,6 +21,7 @@
 
 import Foundation
 import RxSwift
+import RxRelay
 
 enum PasswordValidationState {
     case validated
@@ -198,15 +199,15 @@
     private let nameService: NameService
 
     // MARK: - Rx Variables for UI binding
-    private let accountCreationState = Variable<AccountCreationState>(.unknown)
+    private let accountCreationState = BehaviorRelay<AccountCreationState>(value: .unknown)
     lazy var createState: Observable<AccountCreationState> = {
         return self.accountCreationState.asObservable()
     }()
-    let username = Variable<String>("")
-    let password = Variable<String>("")
-    let confirmPassword = Variable<String>("")
-    let registerUsername = Variable<Bool>(true)
-    let notificationSwitch = Variable<Bool>(true)
+    let username = BehaviorRelay<String>(value: "")
+    let password = BehaviorRelay<String>(value: "")
+    let confirmPassword = BehaviorRelay<String>(value: "")
+    let registerUsername = BehaviorRelay<Bool>(value: true)
+    let notificationSwitch = BehaviorRelay<Bool>(value: true)
     lazy var passwordValidationState: Observable<PasswordValidationState> = {
         return Observable.combineLatest(self.password.asObservable(), self.confirmPassword.asObservable())
         { (password: String, confirmPassword: String) -> PasswordValidationState in
@@ -225,7 +226,7 @@
             return .validated
         }
     }()
-    lazy var usernameValidationState = Variable<UsernameValidationState>(.unknown)
+    lazy var usernameValidationState = BehaviorRelay<UsernameValidationState>(value: .unknown)
     lazy var canAskForAccountCreation: Observable<Bool> = {
         return Observable.combineLatest(self.passwordValidationState.asObservable(),
                                         self.usernameValidationState.asObservable(),
@@ -268,20 +269,20 @@
             .subscribe(onNext: { [weak self] (status) in
                 switch status {
                 case .lookingUp:
-                    self?.usernameValidationState.value = .lookingForAvailibility(message: L10n.CreateAccount.lookingForUsernameAvailability)
+                    self?.usernameValidationState.accept(.lookingForAvailibility(message: L10n.CreateAccount.lookingForUsernameAvailability))
                 case .invalid:
-                    self?.usernameValidationState.value = .invalid(message: L10n.CreateAccount.invalidUsername)
+                    self?.usernameValidationState.accept(.invalid(message: L10n.CreateAccount.invalidUsername))
                 case .alreadyTaken:
-                    self?.usernameValidationState.value = .unavailable(message: L10n.CreateAccount.usernameAlreadyTaken)
+                    self?.usernameValidationState.accept(.unavailable(message: L10n.CreateAccount.usernameAlreadyTaken))
                 default:
-                    self?.usernameValidationState.value = .available
+                    self?.usernameValidationState.accept(.available)
                 }
             })
             .disposed(by: self.disposeBag)
     }
 
     func createAccount() {
-        self.accountCreationState.value = .started
+        self.accountCreationState.accept(.started)
 
         let username = self.username.value
         let password = self.password.value
@@ -293,7 +294,7 @@
             .subscribe(onNext: { [weak self] (account) in
                 guard let self = self else { return }
                 if username.isEmpty {
-                    self.accountCreationState.value = .success
+                    self.accountCreationState.accept(.success)
                     DispatchQueue.main.async {
                         self.stateSubject.onNext(WalkthroughState.accountCreated)
                     }
@@ -304,16 +305,16 @@
                                                                          name: username)
                     .subscribe(onNext: { registered in
                         if registered {
-                            self.accountCreationState.value = .success
+                            self.accountCreationState.accept(.success)
                             DispatchQueue.main.async {
                                 self.stateSubject
                                     .onNext(WalkthroughState.accountCreated)
                             }
                         } else {
-                            self.accountCreationState.value = .nameNotRegistered
+                            self.accountCreationState.accept(.nameNotRegistered)
                         }
                     }, onError: { _ in
-                        self.accountCreationState.value = .nameNotRegistered
+                        self.accountCreationState.accept(.nameNotRegistered)
                     })
                 DispatchQueue.main
                     .asyncAfter(deadline: .now() + 6) {
@@ -321,14 +322,14 @@
                         if self.accountCreationState.value.isCompleted {
                             return
                         }
-                        self.accountCreationState.value = .timeOut
+                        self.accountCreationState.accept(.timeOut)
                     }
                 }, onError: { [weak self] (error) in
                     guard let self = self else { return }
                     if let error = error as? AccountCreationError {
-                        self.accountCreationState.value = .error(error: error)
+                        self.accountCreationState.accept(.error(error: error))
                     } else {
-                        self.accountCreationState.value = .error(error: AccountCreationError.unknown)
+                        self.accountCreationState.accept(.error(error: AccountCreationError.unknown))
                     }
             })
             .disposed(by: self.disposeBag)
diff --git a/Ring/Ring/Features/Walkthrough/CreateProfile/CreateProfileViewModel.swift b/Ring/Ring/Features/Walkthrough/CreateProfile/CreateProfileViewModel.swift
index 30a0231..10b2db9 100644
--- a/Ring/Ring/Features/Walkthrough/CreateProfile/CreateProfileViewModel.swift
+++ b/Ring/Ring/Features/Walkthrough/CreateProfile/CreateProfileViewModel.swift
@@ -21,6 +21,7 @@
 
 import Foundation
 import RxSwift
+import RxRelay
 
 class CreateProfileViewModel: Stateable, ViewModel {
 
@@ -29,8 +30,8 @@
     lazy var state: Observable<State> = {
         return self.stateSubject.asObservable()
     }()
-    var profileName = Variable<String>("")
-    var profilePhoto = Variable<UIImage?>(nil)
+    var profileName = BehaviorRelay<String>(value: "")
+    var profilePhoto = BehaviorRelay<UIImage?>(value: nil)
 
     lazy var profileExists: Observable<Bool>  = {
 
diff --git a/Ring/Ring/Features/Walkthrough/CreateSipAccount/CreateSipAccountViewController.swift b/Ring/Ring/Features/Walkthrough/CreateSipAccount/CreateSipAccountViewController.swift
index 8741dec..a0ca91b 100644
--- a/Ring/Ring/Features/Walkthrough/CreateSipAccount/CreateSipAccountViewController.swift
+++ b/Ring/Ring/Features/Walkthrough/CreateSipAccount/CreateSipAccountViewController.swift
@@ -145,7 +145,15 @@
     }
 
     func buindViewToViewModel() {
-        self.userNameTextField.rx.text.orEmpty.throttle(3, scheduler: MainScheduler.instance).distinctUntilChanged().bind(to: self.viewModel.userName).disposed(by: self.disposeBag)
+        self.userNameTextField
+            .rx
+            .text
+            .orEmpty
+            .throttle(Durations.threeSeconds.toTimeInterval(),
+                      scheduler: MainScheduler.instance)
+            .distinctUntilChanged()
+            .bind(to: self.viewModel.userName)
+            .disposed(by: self.disposeBag)
         self.passwordTextField.rx.text.orEmpty.bind(to: self.viewModel.password).disposed(by: self.disposeBag)
         self.serverTextField.rx.text.orEmpty.bind(to: self.viewModel.sipServer).disposed(by: self.disposeBag)
         self.portTextField.rx.text.orEmpty
diff --git a/Ring/Ring/Features/Walkthrough/CreateSipAccount/CreateSipAccountViewModel.swift b/Ring/Ring/Features/Walkthrough/CreateSipAccount/CreateSipAccountViewModel.swift
index 9b13f62..209ae4f 100644
--- a/Ring/Ring/Features/Walkthrough/CreateSipAccount/CreateSipAccountViewModel.swift
+++ b/Ring/Ring/Features/Walkthrough/CreateSipAccount/CreateSipAccountViewModel.swift
@@ -28,10 +28,10 @@
         return self.stateSubject.asObservable()
     }()
 
-    var userName = Variable<String>("")
-    var password = Variable<String>("")
-    var sipServer = Variable<String>("")
-    var port = Variable<String>("")
+    var userName = BehaviorRelay<String>(value: "")
+    var password = BehaviorRelay<String>(value: "")
+    var sipServer = BehaviorRelay<String>(value: "")
+    var port = BehaviorRelay<String>(value: "")
     private let accountsService: AccountsService
 
     required init(with injectionBag: InjectionBag) {
diff --git a/Ring/Ring/Features/Walkthrough/LinkDevice/LinkDeviceViewModel.swift b/Ring/Ring/Features/Walkthrough/LinkDevice/LinkDeviceViewModel.swift
index 299144e..dba4f53 100644
--- a/Ring/Ring/Features/Walkthrough/LinkDevice/LinkDeviceViewModel.swift
+++ b/Ring/Ring/Features/Walkthrough/LinkDevice/LinkDeviceViewModel.swift
@@ -20,6 +20,7 @@
 
 import Foundation
 import RxSwift
+import RxCocoa
 
 class LinkDeviceViewModel: Stateable, ViewModel {
 
@@ -30,7 +31,7 @@
     }()
     private let accountService: AccountsService
     private let contactService: ContactsService
-    private let accountCreationState = Variable<AccountCreationState>(.unknown)
+    private let accountCreationState = BehaviorRelay<AccountCreationState>(value: .unknown)
     let enableNotificationsTitle = L10n.CreateAccount.enableNotifications
     lazy var createState: Observable<AccountCreationState> = {
         return self.accountCreationState.asObservable()
@@ -42,9 +43,9 @@
         })
     }()
 
-    let pin = Variable<String>("")
-    let password = Variable<String>("")
-    let notificationSwitch = Variable<Bool>(true)
+    let pin = BehaviorRelay<String>(value: "")
+    let password = BehaviorRelay<String>(value: "")
+    let notificationSwitch = BehaviorRelay<Bool>(value: true)
     let disposeBag = DisposeBag()
 
     required init (with injectionBag: InjectionBag) {
@@ -53,15 +54,15 @@
     }
 
     func linkDevice () {
-        self.accountCreationState.value = .started
+        self.accountCreationState.accept(.started)
         self.accountService
             .linkToRingAccount(withPin: self.pin.value,
                                password: self.password.value,
                                enable: self.notificationSwitch.value)
             .subscribe(onNext: { [weak self] (account) in
                 guard let self = self else { return }
-                self.accountCreationState.value = .success
-                Observable<Int>.timer(Durations.alertFlashDuration.value,
+                self.accountCreationState.accept(.success)
+                Observable<Int>.timer(Durations.alertFlashDuration.toTimeInterval(),
                                       period: nil,
                                       scheduler: MainScheduler.instance)
                     .subscribe(onNext: { [weak self] (_) in
@@ -76,9 +77,9 @@
                     .disposed(by: self.disposeBag)
                 }, onError: { [weak self] (error) in
                     if let error = error as? AccountCreationError {
-                        self?.accountCreationState.value = .error(error: error)
+                        self?.accountCreationState.accept(.error(error: error))
                     } else {
-                        self?.accountCreationState.value = .error(error: AccountCreationError.unknown)
+                        self?.accountCreationState.accept(.error(error: AccountCreationError.unknown))
                     }
             })
             .disposed(by: self.disposeBag)
diff --git a/Ring/Ring/Features/Walkthrough/LinkToAccountManager/LinkToAccountManagerViewController.swift b/Ring/Ring/Features/Walkthrough/LinkToAccountManager/LinkToAccountManagerViewController.swift
index 0575ca1..0840e36 100644
--- a/Ring/Ring/Features/Walkthrough/LinkToAccountManager/LinkToAccountManagerViewController.swift
+++ b/Ring/Ring/Features/Walkthrough/LinkToAccountManager/LinkToAccountManagerViewController.swift
@@ -87,7 +87,7 @@
 
     func bindViewToViewModel() {
         self.userNameTextField.rx.text.orEmpty
-            .throttle(3, scheduler: MainScheduler.instance)
+            .throttle(Durations.threeSeconds.toTimeInterval(), scheduler: MainScheduler.instance)
             .distinctUntilChanged()
             .bind(to: self.viewModel.userName)
             .disposed(by: self.disposeBag)
diff --git a/Ring/Ring/Features/Walkthrough/LinkToAccountManager/LinkToAccountManagerViewModel.swift b/Ring/Ring/Features/Walkthrough/LinkToAccountManager/LinkToAccountManagerViewModel.swift
index 9c7b759..fb9f192 100644
--- a/Ring/Ring/Features/Walkthrough/LinkToAccountManager/LinkToAccountManagerViewModel.swift
+++ b/Ring/Ring/Features/Walkthrough/LinkToAccountManager/LinkToAccountManagerViewModel.swift
@@ -28,13 +28,13 @@
         return self.stateSubject.asObservable()
     }()
 
-    var userName = Variable<String>("")
-    var password = Variable<String>("")
-    var manager = Variable<String>("")
-    let notificationSwitch = Variable<Bool>(true)
+    var userName = BehaviorRelay<String>(value: "")
+    var password = BehaviorRelay<String>(value: "")
+    var manager = BehaviorRelay<String>(value: "")
+    let notificationSwitch = BehaviorRelay<Bool>(value: true)
     private let accountsService: AccountsService
     private let disposeBag = DisposeBag()
-    private let accountCreationState = Variable<AccountCreationState>(.unknown)
+    private let accountCreationState = BehaviorRelay<AccountCreationState>(value: .unknown)
     lazy var createState: Observable<AccountCreationState> = {
         return self.accountCreationState.asObservable()
     }()
@@ -54,7 +54,7 @@
     }
 
     func linkToAccountManager() {
-        self.accountCreationState.value = .started
+        self.accountCreationState.accept(.started)
         self.accountsService
             .connectToAccountManager(username: userName.value,
                                      password: password.value,
@@ -62,16 +62,16 @@
                                      emableNotifications: self.notificationSwitch.value)
             .subscribe(onNext: { [weak self] (_) in
                 guard let self = self else { return }
-                self.accountCreationState.value = .success
+                self.accountCreationState.accept(.success)
                 self.enablePushNotifications(enable: self.notificationSwitch.value)
                 DispatchQueue.main.async {
                     self.stateSubject.onNext(WalkthroughState.profileCreated)
                 }
                 }, onError: { [weak self] (error) in
                     if let error = error as? AccountCreationError {
-                        self?.accountCreationState.value = .error(error: error)
+                        self?.accountCreationState.accept(.error(error: error))
                     } else {
-                        self?.accountCreationState.value = .error(error: AccountCreationError.wrongCredentials)
+                        self?.accountCreationState.accept(.error(error: AccountCreationError.wrongCredentials))
                     }
             })
             .disposed(by: self.disposeBag)
diff --git a/Ring/Ring/Features/Walkthrough/Welcome/WelcomeViewController.swift b/Ring/Ring/Features/Walkthrough/Welcome/WelcomeViewController.swift
index 782441b..cddc7cd 100644
--- a/Ring/Ring/Features/Walkthrough/Welcome/WelcomeViewController.swift
+++ b/Ring/Ring/Features/Walkthrough/Welcome/WelcomeViewController.swift
@@ -75,7 +75,7 @@
             cancelButton.setTitle(L10n.Actions.cancelAction, for: .normal)
             cancelButton.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
             let buttonItem = UIBarButtonItem(customView: cancelButton)
-            cancelButton.rx.tap.throttle(0.5, scheduler: MainScheduler.instance)
+            cancelButton.rx.tap.throttle(Durations.halfSecond.toTimeInterval(), scheduler: MainScheduler.instance)
                 .subscribe(onNext: { [weak self] in
                     self?.viewModel.cancelWalkthrough()
                 })
diff --git a/Ring/Ring/GeneralSettings/GeneralSettingsViewModel.swift b/Ring/Ring/GeneralSettings/GeneralSettingsViewModel.swift
index dbbac04..518b7c6 100644
--- a/Ring/Ring/GeneralSettings/GeneralSettingsViewModel.swift
+++ b/Ring/Ring/GeneralSettings/GeneralSettingsViewModel.swift
@@ -20,6 +20,7 @@
 
 import UIKit
 import RxSwift
+import RxCocoa
 import RxDataSources
 
 let hardareAccelerationKey = "HARDWARE_ACCELERATION_KEY"
@@ -55,7 +56,7 @@
                 [.hardwareAcceleration])])
     }()
 
-    var hardwareAccelerationEnabled: Variable<Bool>
+    var hardwareAccelerationEnabled: BehaviorRelay<Bool>
 
     let videoService: VideoService
 
@@ -67,7 +68,7 @@
         if accelerationEnabled != accelerationEnabledSettings {
             injectionBag.videoService.setHardwareAccelerated(withState: accelerationEnabled)
         }
-        hardwareAccelerationEnabled = Variable<Bool>(accelerationEnabled)
+        hardwareAccelerationEnabled = BehaviorRelay<Bool>(value: accelerationEnabled)
     }
 
     func togleHardwareAcceleration(enable: Bool) {
@@ -76,7 +77,7 @@
         }
         self.videoService.setHardwareAccelerated(withState: enable)
         UserDefaults.standard.set(enable, forKey: hardareAccelerationKey)
-        hardwareAccelerationEnabled.value = enable
+        hardwareAccelerationEnabled.accept(enable)
     }
 
     func hardwareAccelerationEnabledSettings() -> Bool {
diff --git a/Ring/Ring/QRCode/ScanViewModel.swift b/Ring/Ring/QRCode/ScanViewModel.swift
index a104ea9..6e07188 100644
--- a/Ring/Ring/QRCode/ScanViewModel.swift
+++ b/Ring/Ring/QRCode/ScanViewModel.swift
@@ -20,6 +20,7 @@
 
 import UIKit
 import RxSwift
+import RxCocoa
 
 class ScanViewModel: ViewModel, Stateable {
 
@@ -44,7 +45,7 @@
                                                                               infoHach: recipientRingId),
                                              accountId: currentAccount.id)
         let newConversation = ConversationViewModel(with: self.injectionBag)
-        newConversation.conversation = Variable<ConversationModel>(conversation)
+        newConversation.conversation = BehaviorRelay<ConversationModel>(value: conversation)
         self.showConversation(withConversationViewModel: newConversation)
     }
 
diff --git a/Ring/Ring/Services/AccountsService.swift b/Ring/Ring/Services/AccountsService.swift
index 5baf6ed..c05e330 100644
--- a/Ring/Ring/Services/AccountsService.swift
+++ b/Ring/Ring/Services/AccountsService.swift
@@ -111,7 +111,7 @@
         }
     }
 
-    var accountsObservable = Variable<[AccountModel]>([AccountModel]())
+    var accountsObservable = BehaviorRelay<[AccountModel]>(value: [AccountModel]())
 
     let currentAccountChanged = PublishSubject<AccountModel?>()
     let currentWillChange = PublishSubject<AccountModel?>()
@@ -188,7 +188,7 @@
             }
         }
         reloadAccounts()
-        accountsObservable.value = self.accountList
+        accountsObservable.accept(self.accountList)
         if selectedAccount != nil {
             let currentAccount = self.accountList.filter({ account in
                 return account == selectedAccount
@@ -471,24 +471,24 @@
     }
 
     func connectToAccountManager(username: String, password: String, serverUri: String, emableNotifications: Bool) -> Observable<AccountModel> {
-        let accountState = Variable<ConnectAccountState>(ConnectAccountState.initializinzg)
-        let newAccountId = Variable<String>("")
+        let accountState = BehaviorRelay<ConnectAccountState>(value: ConnectAccountState.initializinzg)
+        let newAccountId = BehaviorRelay<String>(value: "")
         self.sharedResponseStream
             .subscribe(onNext: { (event) in
                 if event.getEventInput(ServiceEventInput.registrationState) == Initializing {
                     return
                 }
                 if event.getEventInput(ServiceEventInput.registrationState) == ErrorNetwork {
-                    accountState.value = ConnectAccountState.networkError
-                    newAccountId.value = ""
+                    accountState.accept(ConnectAccountState.networkError)
+                    newAccountId.accept("")
                 } else if event.eventType == ServiceEventType.registrationStateChanged,
                     event.getEventInput(ServiceEventInput.registrationState) == Registered {
-                    accountState.value = ConnectAccountState.created
+                    accountState.accept(ConnectAccountState.created)
                 } else if event.getEventInput(ServiceEventInput.registrationState) == ErrorGeneric ||
                     event.getEventInput(ServiceEventInput.registrationState) == ErrorAuth ||
                     event.getEventInput(ServiceEventInput.registrationState) == ErrorNeedMigration {
-                    accountState.value = ConnectAccountState.error
-                    newAccountId.value = ""
+                    accountState.accept(ConnectAccountState.error)
+                    newAccountId.accept("")
                 }
             }, onError: { (_) in
             })
@@ -530,7 +530,7 @@
                 guard let accountId = self.accountAdapter.addAccount(ringDetails) else {
                     throw AccountCreationError.wrongCredentials
                 }
-                newAccountId.value = accountId
+                newAccountId.accept(accountId)
             } catch {
             }
         }
@@ -901,8 +901,8 @@
         return proxyEnabled
     }
 
-    func proxyEnabled(accountID: String) -> Variable<Bool> {
-        let variable = Variable<Bool>(getCurrentProxyState(accountID: accountID))
+    func proxyEnabled(accountID: String) -> BehaviorRelay<Bool> {
+        let variable = BehaviorRelay<Bool>(value: getCurrentProxyState(accountID: accountID))
         self.sharedResponseStream
             .filter({ event -> Bool in
                 if let accountId: String = event.getEventInput(.accountId) {
@@ -913,7 +913,7 @@
             })
             .subscribe(onNext: { (event) in
                 if let state: Bool = event.getEventInput(.state) {
-                    variable.value = state
+                    variable.accept(state)
                 }
             })
             .disposed(by: self.disposeBag)
diff --git a/Ring/Ring/Services/AudioService.swift b/Ring/Ring/Services/AudioService.swift
index 7ab0eff..12e372d 100644
--- a/Ring/Ring/Services/AudioService.swift
+++ b/Ring/Ring/Services/AudioService.swift
@@ -21,6 +21,7 @@
 import Foundation
 import SwiftyBeaver
 import RxSwift
+import RxRelay
 
 enum OutputPortType: Int {
     case builtinspk = 0
@@ -35,8 +36,8 @@
 
     private let audioAdapter: AudioAdapter
 
-    var isHeadsetConnected = Variable<Bool>(false)
-    var isOutputToSpeaker = Variable<Bool>(true)
+    var isHeadsetConnected = BehaviorRelay<Bool>(value: false)
+    var isOutputToSpeaker = BehaviorRelay<Bool>(value: true)
 
     var enableSwitchAudio: Observable<Bool> {
         return self.isHeadsetConnected.asObservable()
@@ -62,7 +63,7 @@
     func connectAudioSignal() {
         let bluetoothConnected = bluetoothAudioConnected()
         let headphonesConnected = headphoneAudioConnected()
-        isHeadsetConnected.value = bluetoothConnected || headphonesConnected
+        isHeadsetConnected.accept(bluetoothConnected || headphonesConnected)
 
         // Listen for audio route changes
         NotificationCenter.default.addObserver(
@@ -75,7 +76,7 @@
     func overrideAudioRoute() {
         let bluetoothConnected = bluetoothAudioConnected()
         let headphonesConnected = headphoneAudioConnected()
-        isHeadsetConnected.value = bluetoothConnected || headphonesConnected
+        isHeadsetConnected.accept(bluetoothConnected || headphonesConnected)
         if bluetoothConnected {
             setAudioOutputDevice(port: OutputPortType.bluetooth)
             return
@@ -105,17 +106,17 @@
     }
 
     func overrideToSpeaker() {
-        isOutputToSpeaker.value = true
+        isOutputToSpeaker.accept(true)
         setAudioOutputDevice(port: OutputPortType.builtinspk)
     }
 
     func overrideToReceiver() {
-        isOutputToSpeaker.value = false
+        isOutputToSpeaker.accept(false)
         setAudioOutputDevice(port: OutputPortType.receiver)
     }
 
     func setDefaultOutput(toSpeaker: Bool, override: Bool = false) {
-        isOutputToSpeaker.value = toSpeaker
+        isOutputToSpeaker.accept(toSpeaker)
         if override {
             overrideAudioRoute()
         }
diff --git a/Ring/Ring/Services/CallsService.swift b/Ring/Ring/Services/CallsService.swift
index 90e0c58..be5cdcf 100644
--- a/Ring/Ring/Services/CallsService.swift
+++ b/Ring/Ring/Services/CallsService.swift
@@ -20,6 +20,7 @@
  */
 
 import RxSwift
+import RxRelay
 import SwiftyBeaver
 import Contacts
 
@@ -53,13 +54,13 @@
     private let callsAdapter: CallsAdapter
     private let log = SwiftyBeaver.self
 
-    var calls = Variable<[String: CallModel]>([String: CallModel]())
+    var calls = BehaviorRelay<[String: CallModel]>(value: [String: CallModel]())
     var pendingConferences = [String: Set<String>]()
 
     private let ringVCardMIMEType = "x-ring/ring.profile.vcard;"
 
     let currentCallsEvents = ReplaySubject<CallModel>.create(bufferSize: 1)
-    let newCall = Variable<CallModel>(CallModel(withCallId: "", callDetails: [:]))
+    let newCall = BehaviorRelay<CallModel>(value: CallModel(withCallId: "", callDetails: [:]))
     private let responseStream = PublishSubject<ServiceEvent>()
     var sharedResponseStream: Observable<ServiceEvent>
     private let newMessagesStream = PublishSubject<ServiceEvent>()
@@ -68,7 +69,7 @@
 
     typealias ConferenceUpdates = (conferenceID: String, state: String, calls: Set<String>)
 
-    let currentConferenceEvent: Variable<ConferenceUpdates> = Variable<ConferenceUpdates>(ConferenceUpdates("", "", Set<String>()))
+    let currentConferenceEvent: BehaviorRelay<ConferenceUpdates> = BehaviorRelay<ConferenceUpdates>(value: ConferenceUpdates("", "", Set<String>()))
     let inConferenceCalls = PublishSubject<CallModel>()
 
     init(withCallsAdapter callsAdapter: CallsAdapter, dbManager: DBManager) {
@@ -192,7 +193,7 @@
     func conferenceInfoUpdated(conference conferenceID: String, info: [[String: String]]) {
         let participants = self.arrayToConferenceParticipants(participants: info, onlyURIAndActive: false)
         self.conferenceInfos[conferenceID] = participants
-        currentConferenceEvent.value = ConferenceUpdates(conferenceID, ConferenceState.infoUpdated.rawValue, [""])
+        currentConferenceEvent.accept(ConferenceUpdates(conferenceID, ConferenceState.infoUpdated.rawValue, [""]))
     }
 
     func getConferenceParticipants(for conferenceId: String) -> [ConferenceParticipant]? {
@@ -339,8 +340,9 @@
                 call.participantsCallId.removeAll()
                 call.participantsCallId.insert(callId)
                 self.currentCallsEvents.onNext(call)
-                self.calls.value[callId] = call
-                self.calls.value = self.calls.value
+                var values = self.calls.value
+                values[callId] = call
+                self.calls.accept(values)
                 single(.success(call))
             } else {
                 single(.error(CallServiceError.placeCallFailed))
@@ -444,8 +446,9 @@
                 event.addEventInput(.callTime, value: time)
                 self.responseStream.onNext(event)
                 self.currentCallsEvents.onNext(finichedCall)
-                self.calls.value[callId] = nil
-                self.calls.value = self.calls.value
+                var values = self.calls.value
+                values[callId] = nil
+                self.calls.accept(values)
                 // clear pending conferences if need
                 if self.pendingConferences.keys.contains(callId) {
                     self.pendingConferences[callId] = nil
@@ -465,8 +468,9 @@
             }
             if call == nil {
                 call = CallModel(withCallId: callId, callDetails: callDictionary)
-                self.calls.value[callId] = call
-                self.calls.value = self.calls.value
+                var values = self.calls.value
+                values[callId] = call
+                self.calls.accept(values)
             } else {
                 call?.update(withDictionary: callDictionary)
             }
@@ -544,7 +548,7 @@
                 }
                 //Emit the call to the observers
                 guard let newCall = call else { return }
-                self.newCall.value = newCall
+                self.newCall.accept(newCall)
             } else {
                 self.refuse(callId: callId)
                     .subscribe(onCompleted: { [weak self] in
@@ -618,9 +622,10 @@
             callDetails[CallDetailKey.audioOnlyKey.rawValue] = self.call(callID: callId)?.isAudioOnly.toString()
             let conf = CallModel(withCallId: conferenceID, callDetails: callDetails)
             conf.participantsCallId = conferenceCalls
-            self.calls.value[conferenceID] = conf
-            self.calls.value = self.calls.value
-            currentConferenceEvent.value = ConferenceUpdates(conferenceID, ConferenceState.conferenceCreated.rawValue, conferenceCalls)
+            var value = self.calls.value
+            value[conferenceID] = conf
+            self.calls.accept(value)
+            currentConferenceEvent.accept(ConferenceUpdates(conferenceID, ConferenceState.conferenceCreated.rawValue, conferenceCalls))
         }
     }
 
@@ -632,16 +637,20 @@
         conferenceCalls.forEach { (callId) in
             guard let call = self.call(callID: callId) else { return }
             call.participantsCallId = conferenceCalls
-            self.calls.value[callId] = call
+            var values = self.calls.value
+            values[callId] = call
+            self.calls.accept(values)
         }
     }
 
     func conferenceRemoved(conference conferenceID: String) {
         guard let conference = self.call(callID: conferenceID) else { return }
         self.conferenceInfos[conferenceID] = nil
-        self.currentConferenceEvent.value = ConferenceUpdates(conferenceID, ConferenceState.infoUpdated.rawValue, [""])
-        self.currentConferenceEvent.value = ConferenceUpdates(conferenceID, ConferenceState.conferenceDestroyed.rawValue, conference.participantsCallId)
-        self.calls.value[conferenceID] = nil
+        self.currentConferenceEvent.accept(ConferenceUpdates(conferenceID, ConferenceState.infoUpdated.rawValue, [""]))
+        self.currentConferenceEvent.accept(ConferenceUpdates(conferenceID, ConferenceState.conferenceDestroyed.rawValue, conference.participantsCallId))
+        var values = self.calls.value
+        values[conferenceID] = nil
+        self.calls.accept(values)
      }
 
     func updateConferences(callId: String) {
diff --git a/Ring/Ring/Services/ContactsService.swift b/Ring/Ring/Services/ContactsService.swift
index da6aa73..b5b5b8e 100644
--- a/Ring/Ring/Services/ContactsService.swift
+++ b/Ring/Ring/Services/ContactsService.swift
@@ -21,6 +21,7 @@
 import Contacts
 import SwiftyBeaver
 import RxSwift
+import RxRelay
 
 enum ContactServiceError: Error {
     case acceptTrustRequestFailed
@@ -37,8 +38,8 @@
     private let log = SwiftyBeaver.self
     private let disposeBag = DisposeBag()
 
-    let contactRequests = Variable([ContactRequestModel]())
-    let contacts = Variable([ContactModel]())
+    let contactRequests = BehaviorRelay(value: [ContactRequestModel]())
+    let contacts = BehaviorRelay(value: [ContactModel]())
 
     let contactStatus = PublishSubject<ContactModel>()
 
@@ -89,10 +90,12 @@
         let contacts = profiles.map({ profile in
             return ContactModel(withUri: JamiURI.init(schema: URIType.sip, infoHach: profile.uri))
         })
-        self.contacts.value.removeAll()
+        self.contacts.accept([])
         for contact in contacts {
             if self.contacts.value.firstIndex(of: contact) == nil {
-                self.contacts.value.append(contact)
+                var values = self.contacts.value
+                values.append(contact)
+                self.contacts.accept(values)
                 self.log.debug("contact: \(String(describing: contact.userName))")
             }
         }
@@ -114,10 +117,12 @@
         if let contacts = contactsDictionaries?.map({ contactDict in
             return ContactModel(withDictionary: contactDict)
         }) {
-            self.contacts.value.removeAll()
+            self.contacts.accept([])
             for contact in contacts {
                 if self.contacts.value.firstIndex(of: contact) == nil {
-                    self.contacts.value.append(contact)
+                    var values = self.contacts.value
+                    values.append(contact)
+                    self.contacts.accept(values)
                     self.log.debug("contact: \(String(describing: contact.userName))")
                 }
             }
@@ -125,7 +130,7 @@
     }
 
     func loadContactRequests(withAccount accountId: String) {
-        self.contactRequests.value.removeAll()
+        self.contactRequests.accept([])
         //Load trust requests from daemon
         let trustRequestsDictionaries = self.contactsAdapter.trustRequests(withAccountId: accountId)
 
@@ -135,7 +140,9 @@
         }) {
             for contactRequest in contactRequests {
                 if self.contactRequest(withRingId: contactRequest.ringId) == nil {
-                    self.contactRequests.value.append(contactRequest)
+                    var values = self.contactRequests.value
+                    values.append(contactRequest)
+                    self.contactRequests.accept(values)
                 }
             }
         }
@@ -237,7 +244,9 @@
             guard let self = self else { return Disposables.create { } }
             self.contactsAdapter.addContact(withURI: contact.hash, accountId: account.id)
             if self.contact(withUri: contact.uriString ?? "") == nil {
-                self.contacts.value.append(contact)
+                var values = self.contacts.value
+                values.append(contact)
+                self.contacts.accept(values)
             }
             observable.on(.completed)
             return Disposables.create { }
@@ -267,7 +276,9 @@
         guard let index = self.contactRequests.value.firstIndex(where: { $0 === contactRequestToRemove }) else {
             return
         }
-        self.contactRequests.value.remove(at: index)
+        var values = self.contactRequests.value
+        values.remove(at: index)
+        self.contactRequests.accept(values)
     }
 
     func unbanContact(contact: ContactModel, account: AccountModel) {
@@ -280,7 +291,7 @@
                 event.addEventInput(.uri, value: contact.hash)
                 self.responseStream.onNext(event)
                 self.contactStatus.onNext(contact)
-                self.contacts.value = self.contacts.value
+                self.contacts.accept(self.contacts.value)
             })
             .disposed(by: self.disposeBag)
     }
@@ -301,7 +312,9 @@
                                                      vCard: vCard,
                                                      receivedDate: receivedDate,
                                                      accountId: accountId)
-            self.contactRequests.value.append(contactRequest)
+            var values = self.contactRequests.value
+            values.append(contactRequest)
+            self.contactRequests.accept(values)
             var event = ServiceEvent(withEventType: .contactRequestReceived)
             event.addEventInput(.accountId, value: accountId)
             event.addEventInput(.uri, value: senderAccount)
@@ -342,7 +355,9 @@
             }) {
                 for contact in contacts {
                     if self.contacts.value.firstIndex(of: contact) == nil {
-                        self.contacts.value.append(contact)
+                        var values = self.contacts.value
+                        values.append(contact)
+                        self.contacts.accept(values)
                         contactStatus.onNext(contact)
                     }
                 }
@@ -402,11 +417,11 @@
             for contact in self.contacts.value {
                 self.contactsAdapter.removeContact(withURI: contact.hash, accountId: accountId, ban: false)
             }
-            self.contacts.value.removeAll()
+            self.contacts.accept([])
             self.contactRequests.value.forEach { (request) in
                 self.contactsAdapter.discardTrustRequest(fromContact: request.ringId, withAccountId: accountId)
             }
-            self.contactRequests.value.removeAll()
+            self.contactRequests.accept([])
             self.dbManager
                 .clearAllHistoryFor(accountId: accountId)
                 .subscribe()
diff --git a/Ring/Ring/Services/ConversationsService.swift b/Ring/Ring/Services/ConversationsService.swift
index aea3839..b80d9cb 100644
--- a/Ring/Ring/Services/ConversationsService.swift
+++ b/Ring/Ring/Services/ConversationsService.swift
@@ -21,6 +21,7 @@
  */
 
 import RxSwift
+import RxRelay
 import SwiftyBeaver
 
 // swiftlint:disable type_body_length
@@ -40,7 +41,7 @@
     private let responseStream = PublishSubject<ServiceEvent>()
     var sharedResponseStream: Observable<ServiceEvent>
 
-    var conversations = Variable([ConversationModel]())
+    var conversations = BehaviorRelay(value: [ConversationModel]())
 
     var messagesSemaphore = DispatchSemaphore(value: 1)
 
@@ -78,7 +79,7 @@
         dbManager.getConversationsObservable(for: accountId)
             .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
             .subscribe(onNext: { [weak self] conversationsModels in
-                self?.conversations.value = conversationsModels
+                self?.conversations.accept(conversationsModels)
                 if shouldUpdateMessagesStatus {
                     self?.updateMessagesStatus(accountId: accountId)
                 }
@@ -202,7 +203,7 @@
                         self.dbManager.getConversationsObservable(for: toAccountId)
                             .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
                             .subscribe(onNext: { [weak self] conversationsModels in
-                                self?.conversations.value = conversationsModels
+                                self?.conversations.accept(conversationsModels)
                             })
                             .disposed(by: (self.disposeBag))
                     }
@@ -259,7 +260,7 @@
                     self.dbManager.getConversationsObservable(for: accountId)
                         .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
                         .subscribe(onNext: { conversationsModels in
-                            self.conversations.value = conversationsModels
+                            self.conversations.accept(conversationsModels)
                         })
                         .disposed(by: (self.disposeBag))
                 }
@@ -310,7 +311,7 @@
                         .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
                         .subscribe(onNext: { conversationsModels in
                             if updateConversation {
-                                self.conversations.value = conversationsModels
+                                self.conversations.accept(conversationsModels)
                             }
                             let serviceEventType: ServiceEventType = .dataTransferMessageUpdated
                             var serviceEvent = ServiceEvent(withEventType: serviceEventType)
@@ -380,7 +381,7 @@
                     self.dbManager.getConversationsObservable(for: accountId)
                         .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
                         .subscribe(onNext: { [weak self] conversationsModels in
-                            self?.conversations.value = conversationsModels
+                            self?.conversations.accept(conversationsModels)
                         })
                         .disposed(by: (self.disposeBag))
                     completable(.completed)
@@ -418,7 +419,7 @@
                     .getConversationsObservable(for: conversation.accountId)
                     .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
                     .subscribe(onNext: { [weak self] conversationsModels in
-                        self?.conversations.value = conversationsModels
+                        self?.conversations.accept(conversationsModels)
                     })
                     .disposed(by: (self.disposeBag))
                 }, onError: { error in
@@ -615,7 +616,7 @@
                         self.dbManager.getConversationsObservable(for: accountId)
                             .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
                             .subscribe(onNext: { [weak self] conversationsModels in
-                                self?.conversations.value = conversationsModels
+                                self?.conversations.accept(conversationsModels)
                             })
                             .disposed(by: (self.disposeBag))
                     }
diff --git a/Ring/Ring/Services/LocationSharingService.swift b/Ring/Ring/Services/LocationSharingService.swift
index 5ccfb42..279f6de 100644
--- a/Ring/Ring/Services/LocationSharingService.swift
+++ b/Ring/Ring/Services/LocationSharingService.swift
@@ -160,7 +160,7 @@
 
     private func initialize() {
         self.currentLocation
-            .throttle(10, scheduler: MainScheduler.instance)
+            .throttle(Durations.tenSeconds.toTimeInterval(), scheduler: MainScheduler.instance)
             .subscribe(onNext: { [weak self] location in
                 guard let self = self, let location = location else { return }
                 self.doShareLocationAction(location)
@@ -321,7 +321,7 @@
 
     func startReceivingService() {
         self.stopReceivingService()
-        self.receivingService = Observable<Int>.interval(60, scheduler: MainScheduler.instance)
+        self.receivingService = Observable<Int>.interval(Durations.sixtySeconds.toTimeInterval(), scheduler: MainScheduler.instance)
             .subscribe({ [weak self] _ in
                 guard let self = self else { return }
 
diff --git a/Ring/Ring/Services/NetworkService.swift b/Ring/Ring/Services/NetworkService.swift
index 19ab22d..ae00cce 100644
--- a/Ring/Ring/Services/NetworkService.swift
+++ b/Ring/Ring/Services/NetworkService.swift
@@ -22,6 +22,7 @@
 import Reachability
 import SwiftyBeaver
 import RxSwift
+import RxRelay
 
 enum ConnectionType {
     case none
@@ -35,7 +36,7 @@
 
     let reachability: Reachability?
 
-    var connectionState = Variable<ConnectionType>(.none)
+    var connectionState = BehaviorRelay<ConnectionType>(value: .none)
 
     lazy var connectionStateObservable: Observable<ConnectionType> = {
         return self.connectionState.asObservable()
@@ -49,14 +50,14 @@
 
         reachability?.whenReachable = { reachability in
             if reachability.connection == .wifi {
-                self.connectionState.value = .wifi
+                self.connectionState.accept(.wifi)
             } else {
-                self.connectionState.value = .cellular
+                self.connectionState.accept(.cellular)
             }
         }
 
         reachability?.whenUnreachable = { _ in
-            self.connectionState.value = .none
+            self.connectionState.accept(.none)
         }
 
         do {
diff --git a/Ring/Ring/Services/PresenceService.swift b/Ring/Ring/Services/PresenceService.swift
index b3d5693..8c7c870 100644
--- a/Ring/Ring/Services/PresenceService.swift
+++ b/Ring/Ring/Services/PresenceService.swift
@@ -20,12 +20,13 @@
 
 import SwiftyBeaver
 import RxSwift
+import RxCocoa
 
 class PresenceService {
 
     private let presenceAdapter: PresenceAdapter
     private let log = SwiftyBeaver.self
-    var contactPresence: [String: Variable<Bool>]
+    var contactPresence: [String: BehaviorRelay<Bool>]
 
     private let responseStream = PublishSubject<ServiceEvent>()
     var sharedResponseStream: Observable<ServiceEvent>
@@ -33,7 +34,7 @@
     private let disposeBag = DisposeBag()
 
     init(withPresenceAdapter presenceAdapter: PresenceAdapter) {
-        self.contactPresence = [String: Variable<Bool>]()
+        self.contactPresence = [String: BehaviorRelay<Bool>]()
         self.presenceAdapter = presenceAdapter
         self.responseStream.disposed(by: disposeBag)
         self.sharedResponseStream = responseStream.share()
@@ -62,10 +63,10 @@
             return
         }
         if let presenceForContact = contactPresence[uri] {
-            presenceForContact.value = false
+            presenceForContact.accept(false)
             return
         }
-        let observableValue = Variable<Bool>(false)
+        let observableValue = BehaviorRelay<Bool>(value: false)
         contactPresence[uri] = observableValue
         var event = ServiceEvent(withEventType: .presenseSubscribed)
         event.addEventInput(.accountId, value: accountId)
@@ -81,10 +82,10 @@
                               withLineStatus lineStatus: String) {
         let value = status > 0 ? true : false
         if let presenceForContact = contactPresence[uri] {
-            presenceForContact.value = value
+            presenceForContact.accept(value)
             return
         }
-        let observableValue = Variable<Bool>(value)
+        let observableValue = BehaviorRelay<Bool>(value: value)
         contactPresence[uri] = observableValue
         log.debug("newBuddyNotification: uri=\(uri), status=\(status)")
     }
diff --git a/Ring/Ring/Services/VideoService.swift b/Ring/Ring/Services/VideoService.swift
index 799b434..a633d91 100644
--- a/Ring/Ring/Services/VideoService.swift
+++ b/Ring/Ring/Services/VideoService.swift
@@ -22,6 +22,7 @@
 import Foundation
 import SwiftyBeaver
 import RxSwift
+import RxRelay
 import UIKit
 import AVFoundation
 
@@ -71,7 +72,7 @@
         return orientation
     }
 
-    var permissionGranted = Variable<Bool>(false)
+    var permissionGranted = BehaviorRelay<Bool>(value: false)
 
     lazy var permissionGrantedObservable: Observable<Bool> = {
         return self.permissionGranted.asObservable()
@@ -138,18 +139,18 @@
     func checkPermission() {
         switch AVCaptureDevice.authorizationStatus(for: AVMediaType.video) {
         case .authorized:
-            self.permissionGranted.value = true
+            self.permissionGranted.accept(true)
         case .notDetermined:
             requestPermission()
         default:
-            self.permissionGranted.value = false
+            self.permissionGranted.accept(false)
         }
     }
 
     private func requestPermission() {
         sessionQueue.suspend()
         AVCaptureDevice.requestAccess(for: AVMediaType.video) { [weak self] granted in
-            self?.permissionGranted.value = granted
+            self?.permissionGranted.accept(granted)
             self?.sessionQueue.resume()
         }
     }
diff --git a/Ring/Ring/UI/ProgressView.swift b/Ring/Ring/UI/ProgressView.swift
index 2c29173..310e5dd 100644
--- a/Ring/Ring/UI/ProgressView.swift
+++ b/Ring/Ring/UI/ProgressView.swift
@@ -20,6 +20,7 @@
 
 import UIKit
 import RxSwift
+import RxCocoa
 
 class ProgressView: UIView {
     var maximumValue: CGFloat = 100
@@ -28,8 +29,8 @@
     var statusLabel = UILabel()
 
     var disposeBug = DisposeBag()
-    var status = Variable<DataTransferStatus>(.ongoing)
-    var progressVariable = Variable<CGFloat>(0)
+    var status = BehaviorRelay<DataTransferStatus>(value: .ongoing)
+    var progressVariable = BehaviorRelay<CGFloat>(value: 0)
     lazy var statusLabelValue: Observable<String> = {
         return Observable
             .merge( status.asObservable().map({ status in
@@ -64,7 +65,7 @@
             target = newProgress
             currentProgress += (target - currentProgress) * 0.1
             innerProgress = currentProgress * toAngleScaler
-            self.progressVariable.value = newProgress
+            self.progressVariable.accept(newProgress)
             setImage()
         }
     }