From 0e7dbe05881fd87a68a48e080da49ffbcc8ac231 Mon Sep 17 00:00:00 2001
From: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
Date: Tue, 12 May 2020 20:26:54 -0400
Subject: [PATCH] account: add booth mode

Change-Id: I43a7fc03b4b1fb6368569d35c6df7f6cc17bc5d5
---
 Ring/Ring.xcodeproj/project.pbxproj           |  52 +++-
 Ring/Ring/Account/AccountModelHelper.swift    |   2 +-
 Ring/Ring/AppDelegate.swift                   |   5 +-
 .../Bridging/AccountCreation/AccountAdapter.h |   4 +
 .../AccountCreation/AccountAdapter.mm         |  11 +
 Ring/Ring/Calls/CallViewController.swift      |   5 +-
 Ring/Ring/Calls/CallViewModel.swift           |  18 ++
 .../ContactPickerViewController.swift         |  16 +-
 Ring/Ring/Constants/Generated/Strings.swift   |  40 ++-
 Ring/Ring/Coordinators/AppCoordinator.swift   |   7 +
 .../DBHelpers/ConversationDataHepler.swift    |  12 +
 .../DBHelpers/InteractionDataHelper.swift     |  12 +
 .../DBHelpers/ProfileDataHelper.swift         |  12 +
 Ring/Ring/Database/DBManager.swift            |  28 +++
 .../ContactRequestsViewModel.swift            |   4 +-
 .../Conversation/ConversationViewModel.swift  |  40 ++-
 .../ConversationsCoordinator.swift            |  14 +-
 .../SmartList/Cells/ConversationCell.swift    |  28 ++-
 .../Cells/IncognitoSmartListCell.swift        |  23 ++
 .../Cells/IncognitoSmartListCell.xib          |  49 ++++
 .../SmartList/Cells/SmartListCell.swift       |  22 ++
 ...ConversationCell.xib => SmartListCell.xib} |  16 +-
 ...ncognitoSmartListViewController.storyboard | 231 ++++++++++++++++++
 .../IncognitoSmartListViewController.swift    | 204 ++++++++++++++++
 .../IncognitoSmartListViewModel.swift         | 115 +++++++++
 .../SmartlistViewController.storyboard        |  11 +-
 .../SmartList/SmartlistViewController.swift   | 116 ++-------
 .../SmartList/SmartlistViewModel.swift        | 134 ++--------
 .../views/ConfirmationAlert.swift             |  97 ++++++++
 .../views/JamiSearchView/JamiSearchView.swift | 172 +++++++++++++
 .../JamiSearchView/JamiSearchViewModel.swift  | 176 +++++++++++++
 .../Features/Me/LinkNewDeviceViewModel.swift  |   2 +-
 .../Features/Me/Me/MeViewController.swift     | 173 ++++++++++++-
 Ring/Ring/Features/Me/Me/MeViewModel.swift    |  36 ++-
 Ring/Ring/Features/Me/MeCoordinator.swift     |   9 +
 .../MigrateAccountViewModel.swift             |   2 +-
 .../Protocols/ConversationNavigation.swift    |   8 +
 .../Resources/en.lproj/Localizable.strings    |  15 ++
 Ring/Ring/Services/AccountsService.swift      |  44 +++-
 Ring/Ring/Services/ContactsService.swift      |  30 ++-
 Ring/Ring/Services/ConversationsManager.swift |  12 +
 .../GeneratedInteractionsManager.swift        |   7 +
 Ring/Ring/Services/PresenceService.swift      |  13 +
 Ring/Ring/Services/ServiceEvent.swift         |   1 +
 44 files changed, 1746 insertions(+), 282 deletions(-)
 create mode 100644 Ring/Ring/Features/Conversations/SmartList/Cells/IncognitoSmartListCell.swift
 create mode 100644 Ring/Ring/Features/Conversations/SmartList/Cells/IncognitoSmartListCell.xib
 create mode 100644 Ring/Ring/Features/Conversations/SmartList/Cells/SmartListCell.swift
 rename Ring/Ring/Features/Conversations/SmartList/Cells/{ConversationCell.xib => SmartListCell.xib} (95%)
 create mode 100644 Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewController.storyboard
 create mode 100644 Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewController.swift
 create mode 100644 Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewModel.swift
 create mode 100644 Ring/Ring/Features/Conversations/views/ConfirmationAlert.swift
 create mode 100644 Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchView.swift
 create mode 100644 Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchViewModel.swift

diff --git a/Ring/Ring.xcodeproj/project.pbxproj b/Ring/Ring.xcodeproj/project.pbxproj
index 642cad9da..e713d1244 100644
--- a/Ring/Ring.xcodeproj/project.pbxproj
+++ b/Ring/Ring.xcodeproj/project.pbxproj
@@ -221,7 +221,7 @@
 		1A2D18F71F292D7200B2C785 /* MessageCellSent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2D18F31F292D7200B2C785 /* MessageCellSent.swift */; };
 		1A2D18F81F292D7200B2C785 /* MessageCellSent.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1A2D18F41F292D7200B2C785 /* MessageCellSent.xib */; };
 		1A2D18FC1F292DAD00B2C785 /* ConversationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2D18FA1F292DAD00B2C785 /* ConversationCell.swift */; };
-		1A2D18FD1F292DAD00B2C785 /* ConversationCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1A2D18FB1F292DAD00B2C785 /* ConversationCell.xib */; };
+		1A2D18FD1F292DAD00B2C785 /* SmartListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1A2D18FB1F292DAD00B2C785 /* SmartListCell.xib */; };
 		1A2D18FF1F29352D00B2C785 /* MeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2D18FE1F29352D00B2C785 /* MeViewModel.swift */; };
 		1A2D19011F29353A00B2C785 /* MeDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2D19001F29353A00B2C785 /* MeDetailViewModel.swift */; };
 		1A3D28A71F0EB9DB00B524EE /* Bool+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A3D28A61F0EB9DB00B524EE /* Bool+String.swift */; };
@@ -247,6 +247,15 @@
 		1ABE07DC1F0D915100D36361 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1ABE07DA1F0D915100D36361 /* Localizable.strings */; };
 		1ABE07DF1F0D91A800D36361 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1ABE07DD1F0D91A800D36361 /* LaunchScreen.storyboard */; };
 		1ABE07E21F0D924700D36361 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ABE07E11F0D924700D36361 /* Strings.swift */; };
+		263B7158246D9390007044C4 /* SmartListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 263B7157246D9390007044C4 /* SmartListCell.swift */; };
+		263B715A246D9556007044C4 /* IncognitoSmartListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 263B7159246D9556007044C4 /* IncognitoSmartListCell.swift */; };
+		263B715C246D96E5007044C4 /* IncognitoSmartListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 263B715B246D96E5007044C4 /* IncognitoSmartListCell.xib */; };
+		2662FC79246B1E1700FA7782 /* JamiSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2662FC78246B1E1700FA7782 /* JamiSearchView.swift */; };
+		2662FC7B246B216B00FA7782 /* JamiSearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2662FC7A246B216B00FA7782 /* JamiSearchViewModel.swift */; };
+		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 */; };
+		268AA5C12472D42700B654A0 /* ConfirmationAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 268AA5C02472D42700B654A0 /* ConfirmationAlert.swift */; };
 		4430A66B236CBA7D00747177 /* ContactPickerSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4430A66A236CBA7D00747177 /* ContactPickerSection.swift */; };
 		4430A66D236CBC5900747177 /* ContactPickerViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4430A66C236CBC5900747177 /* ContactPickerViewController.storyboard */; };
 		4430A66F236CBC6900747177 /* ContactPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4430A66E236CBC6900747177 /* ContactPickerViewController.swift */; };
@@ -562,7 +571,7 @@
 		1A2D18F31F292D7200B2C785 /* MessageCellSent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageCellSent.swift; sourceTree = "<group>"; };
 		1A2D18F41F292D7200B2C785 /* MessageCellSent.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MessageCellSent.xib; sourceTree = "<group>"; };
 		1A2D18FA1F292DAD00B2C785 /* ConversationCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConversationCell.swift; sourceTree = "<group>"; };
-		1A2D18FB1F292DAD00B2C785 /* ConversationCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ConversationCell.xib; sourceTree = "<group>"; };
+		1A2D18FB1F292DAD00B2C785 /* SmartListCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SmartListCell.xib; sourceTree = "<group>"; };
 		1A2D18FE1F29352D00B2C785 /* MeViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MeViewModel.swift; sourceTree = "<group>"; };
 		1A2D19001F29353A00B2C785 /* MeDetailViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MeDetailViewModel.swift; sourceTree = "<group>"; };
 		1A3CA32A1F102BB700283748 /* Chameleon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Chameleon.framework; path = Carthage/Build/iOS/Chameleon.framework; sourceTree = "<group>"; };
@@ -592,6 +601,15 @@
 		1ABE07DD1F0D91A800D36361 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = Resources/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		1ABE07E11F0D924700D36361 /* Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
 		26376721245315E600CDC51F /* Debug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Debug.entitlements; sourceTree = "<group>"; };
+		263B7157246D9390007044C4 /* SmartListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmartListCell.swift; sourceTree = "<group>"; };
+		263B7159246D9556007044C4 /* IncognitoSmartListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncognitoSmartListCell.swift; sourceTree = "<group>"; };
+		263B715B246D96E5007044C4 /* IncognitoSmartListCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IncognitoSmartListCell.xib; sourceTree = "<group>"; };
+		2662FC78246B1E1700FA7782 /* JamiSearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JamiSearchView.swift; sourceTree = "<group>"; };
+		2662FC7A246B216B00FA7782 /* JamiSearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JamiSearchViewModel.swift; sourceTree = "<group>"; };
+		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; };
+		268AA5C02472D42700B654A0 /* ConfirmationAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationAlert.swift; sourceTree = "<group>"; };
 		4430A66A236CBA7D00747177 /* ContactPickerSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactPickerSection.swift; sourceTree = "<group>"; };
 		4430A66C236CBC5900747177 /* ContactPickerViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = ContactPickerViewController.storyboard; sourceTree = "<group>"; };
 		4430A66E236CBC6900747177 /* ContactPickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactPickerViewController.swift; sourceTree = "<group>"; };
@@ -1194,9 +1212,11 @@
 		0E5806F123BE42C8007D1F5D /* views */ = {
 			isa = PBXGroup;
 			children = (
+				2662FC77246B1DD600FA7782 /* JamiSearchView */,
 				0E5806F223BE42EC007D1F5D /* PlayerView.swift */,
 				0E5806F423BE4307007D1F5D /* PlayerViewModel.swift */,
 				0E5806F623BE4325007D1F5D /* PlayerView.xib */,
+				268AA5C02472D42700B654A0 /* ConfirmationAlert.swift */,
 			);
 			path = views;
 			sourceTree = "<group>";
@@ -1427,6 +1447,9 @@
 				1A5DC02F1F3565AE0075E8EF /* SmartlistViewController.swift */,
 				1A2D18B51F29164700B2C785 /* SmartlistViewModel.swift */,
 				1A5DC0311F3566140075E8EF /* ConversationSection.swift */,
+				2662FC7C246B78E800FA7782 /* IncognitoSmartListViewController.swift */,
+				2662FC7E246B790400FA7782 /* IncognitoSmartListViewModel.swift */,
+				2662FC80246B793500FA7782 /* IncognitoSmartListViewController.storyboard */,
 			);
 			path = Smartlist;
 			sourceTree = "<group>";
@@ -1510,9 +1533,12 @@
 			children = (
 				0E6F544E223C0ED600ECC3CE /* AccountPickerAdapter.swift */,
 				1A2D18FA1F292DAD00B2C785 /* ConversationCell.swift */,
-				1A2D18FB1F292DAD00B2C785 /* ConversationCell.xib */,
+				1A2D18FB1F292DAD00B2C785 /* SmartListCell.xib */,
 				0E6F5450223C3C4F00ECC3CE /* AccountItemView.xib */,
 				0E6F5452223C3C7500ECC3CE /* AccountItemView.swift */,
+				263B7157246D9390007044C4 /* SmartListCell.swift */,
+				263B7159246D9556007044C4 /* IncognitoSmartListCell.swift */,
+				263B715B246D96E5007044C4 /* IncognitoSmartListCell.xib */,
 			);
 			name = Cells;
 			path = ../SmartList/Cells;
@@ -1561,6 +1587,15 @@
 			path = Resources;
 			sourceTree = "<group>";
 		};
+		2662FC77246B1DD600FA7782 /* JamiSearchView */ = {
+			isa = PBXGroup;
+			children = (
+				2662FC78246B1E1700FA7782 /* JamiSearchView.swift */,
+				2662FC7A246B216B00FA7782 /* JamiSearchViewModel.swift */,
+			);
+			path = JamiSearchView;
+			sourceTree = "<group>";
+		};
 		4430A669236CB9F600747177 /* Conference */ = {
 			isa = PBXGroup;
 			children = (
@@ -1833,7 +1868,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				0E6F545622403ADE00ECC3CE /* CreateSipAccountViewController.storyboard in Resources */,
-				1A2D18FD1F292DAD00B2C785 /* ConversationCell.xib in Resources */,
+				1A2D18FD1F292DAD00B2C785 /* SmartListCell.xib in Resources */,
 				0E320D50224ADF840070B515 /* DialpadViewController.storyboard in Resources */,
 				1ABE07DC1F0D915100D36361 /* Localizable.strings in Resources */,
 				1A2D18E61F29197100B2C785 /* MessageAccessoryView.xib in Resources */,
@@ -1843,6 +1878,7 @@
 				0ED2B6FA1F96A075001572F0 /* LinkNewDeviceViewController.storyboard in Resources */,
 				1A2D18EF1F291A0100B2C785 /* MeDetailViewController.storyboard in Resources */,
 				623660AA20092081002598C1 /* src in Resources */,
+				263B715C246D96E5007044C4 /* IncognitoSmartListCell.xib in Resources */,
 				1A2D18B11F2915B600B2C785 /* SmartlistViewController.storyboard in Resources */,
 				0E403F831F7D79B000C80BC2 /* MessageCellGenerated.xib in Resources */,
 				0E6F5451223C3C4F00ECC3CE /* AccountItemView.xib in Resources */,
@@ -1858,6 +1894,7 @@
 				6613A612214AFF4700B497D1 /* ScanViewController.storyboard in Resources */,
 				1A20417E1F1E8DDA00C08435 /* CreateProfileViewController.storyboard in Resources */,
 				1ABE07DF1F0D91A800D36361 /* LaunchScreen.storyboard in Resources */,
+				2662FC81246B793500FA7782 /* IncognitoSmartListViewController.storyboard in Resources */,
 				1A5DC0381F35675E0075E8EF /* ContactRequestCell.xib in Resources */,
 				0ECA56812433948E0055D31E /* MigrateAccountViewController.storyboard in Resources */,
 				1A0C4EDA1F1D4B1B00550433 /* WelcomeViewController.storyboard in Resources */,
@@ -1987,6 +2024,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				557086521E8ADB9D001A7CE4 /* SystemAdapter.mm in Sources */,
+				263B7158246D9390007044C4 /* SmartListCell.swift in Sources */,
 				0586C94B1F684DF600613517 /* UIImage+Helpers.swift in Sources */,
 				4430A671236CBC7A00747177 /* ContactPickerViewModel.swift in Sources */,
 				621231F91F880EDF009B86F0 /* UILabel+Ring.swift in Sources */,
@@ -2056,6 +2094,7 @@
 				0E0FF1B91FC398C5003898C2 /* InteractionDataHelper.swift in Sources */,
 				0E6F545822403B0300ECC3CE /* CreateSipAccountViewController.swift in Sources */,
 				0EE1B54E1F75ACDE00BA98EE /* CNContactVCardSerialization+Helpers.swift in Sources */,
+				268AA5C12472D42700B654A0 /* ConfirmationAlert.swift in Sources */,
 				0E0FF1AA1FC3843E003898C2 /* DBContainer.swift in Sources */,
 				56308BA71EA00E5700660275 /* NameRegistrationResponse.m in Sources */,
 				0ED2B6FC1F96A158001572F0 /* LinkNewDeviceViewController.swift in Sources */,
@@ -2063,8 +2102,10 @@
 				0E6F544D223BFE3E00ECC3CE /* DisposableCell.swift in Sources */,
 				0E9D84491FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift in Sources */,
 				621231FB1F8D6FEE009B86F0 /* MessageCell.swift in Sources */,
+				2662FC7D246B78E800FA7782 /* IncognitoSmartListViewController.swift in Sources */,
 				56AC650E1E85694D00EA1AA9 /* DesignableTextField.swift in Sources */,
 				1A2D189A1F2642C000B2C785 /* NotificationCenter+Ring.swift in Sources */,
+				2662FC79246B1E1700FA7782 /* JamiSearchView.swift in Sources */,
 				0E44B62F202B9DE40060F71B /* LocalNotificationsHelper.swift in Sources */,
 				0E6F545A22403B1D00ECC3CE /* CreateSipAccountViewModel.swift in Sources */,
 				1A2D18FC1F292DAD00B2C785 /* ConversationCell.swift in Sources */,
@@ -2098,6 +2139,8 @@
 				62AA15C31FFC39C80064A063 /* VideoAdapterDelegate.swift in Sources */,
 				04399AAE1D1C304300E99CD9 /* Utils.mm in Sources */,
 				56BBC9A31ED714DF00CDAF8B /* ConversationsService.swift in Sources */,
+				2662FC7B246B216B00FA7782 /* JamiSearchViewModel.swift in Sources */,
+				2662FC7F246B790400FA7782 /* IncognitoSmartListViewModel.swift in Sources */,
 				446FAF1D2373427100519C4F /* SendFileViewModel.swift in Sources */,
 				62AD584A2056DADF00AF0701 /* MessageCellDataTransferReceived.swift in Sources */,
 				0E0FF1AF1FC38CBC003898C2 /* ProfileDataHelper.swift in Sources */,
@@ -2133,6 +2176,7 @@
 				564C44621E943DE6000F92B1 /* NameService.swift in Sources */,
 				1A5DC02C1F3565250075E8EF /* MeViewController.swift in Sources */,
 				0EF78DE31FD0AE3000FC6966 /* ConversationsManager.swift in Sources */,
+				263B715A246D9556007044C4 /* IncognitoSmartListCell.swift in Sources */,
 				66266FC021557D2F002757A6 /* ScanViewModel.swift in Sources */,
 				0E5A668322F0B1F100AA6820 /* ProgressView.swift in Sources */,
 				0E96ED79225D06480016C07D /* GeneralSettingsViewModel.swift in Sources */,
diff --git a/Ring/Ring/Account/AccountModelHelper.swift b/Ring/Ring/Account/AccountModelHelper.swift
index 20b9af6cb..8e5c153e9 100644
--- a/Ring/Ring/Account/AccountModelHelper.swift
+++ b/Ring/Ring/Account/AccountModelHelper.swift
@@ -181,7 +181,7 @@ struct AccountModelHelper {
         }
     }
 
-    public var havePassword: Bool {
+    public var hasPassword: Bool {
         let noPassword: String = self.account.details?.get(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.archiveHasPassword)) ?? "false"
         return noPassword == "true" ? true : false
     }
diff --git a/Ring/Ring/AppDelegate.swift b/Ring/Ring/AppDelegate.swift
index 79bd69153..f30469ca7 100644
--- a/Ring/Ring/AppDelegate.swift
+++ b/Ring/Ring/AppDelegate.swift
@@ -211,7 +211,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
 
     func reloadDataFor(account: AccountModel) {
         self.contactsService.loadContacts(withAccount: account)
-        self.contactsService.loadContactRequests(withAccount: account)
+        self.contactsService.loadContactRequests(withAccount: account.id)
         self.presenceService.subscribeBuddies(withAccount: account.id, withContacts: self.contactsService.contacts.value, subscribe: true)
         self.conversationManager?
                 .prepareConversationsForAccount(accountId: account.id)
@@ -424,6 +424,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
     func application(_ application: UIApplication,
                      continue userActivity: NSUserActivity,
                      restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
+        if self.accountService.boothMode() {
+            return false
+        }
         guard let handle = userActivity.startCallHandle else {
             return false
         }
diff --git a/Ring/Ring/Bridging/AccountCreation/AccountAdapter.h b/Ring/Ring/Bridging/AccountCreation/AccountAdapter.h
index 94142dbf8..56ceeca02 100644
--- a/Ring/Ring/Bridging/AccountCreation/AccountAdapter.h
+++ b/Ring/Ring/Bridging/AccountCreation/AccountAdapter.h
@@ -77,5 +77,9 @@
 
 - (void)pushNotificationReceived:(NSString *) from message:(NSDictionary*) data;
 - (void)setPushNotificationToken: (NSString *) token;
+- (BOOL)passwordIsValid:(NSString *)accountId password:(NSString *)password;
+- (BOOL)changeAccountPassword:(NSString *)accountId
+                  oldPassword:(NSString *)oldpassword
+                  newPassword:(NSString *)newPassword;
 
 @end
diff --git a/Ring/Ring/Bridging/AccountCreation/AccountAdapter.mm b/Ring/Ring/Bridging/AccountCreation/AccountAdapter.mm
index 1442db3e1..715cafda1 100644
--- a/Ring/Ring/Bridging/AccountCreation/AccountAdapter.mm
+++ b/Ring/Ring/Bridging/AccountCreation/AccountAdapter.mm
@@ -197,5 +197,16 @@ static id <AccountAdapterDelegate> _delegate;
 - (void)setPushNotificationToken: (NSString*)token {
     setPushNotificationToken(std::string([token UTF8String]));
 }
+- (BOOL)passwordIsValid:(NSString *)accountId password:(NSString *)password {
+    return isPasswordValid(std::string([accountId UTF8String]), std::string([password UTF8String]));
+}
+
+- (BOOL)changeAccountPassword:(NSString *)accountId
+                  oldPassword:(NSString *)oldpassword
+                  newPassword:(NSString *)newPassword {
+    return changeAccountPassword(std::string([accountId UTF8String]),
+                                 std::string([oldpassword UTF8String]),
+                                 std::string([newPassword UTF8String]));
+}
 
 @end
diff --git a/Ring/Ring/Calls/CallViewController.swift b/Ring/Ring/Calls/CallViewController.swift
index cd0435fed..64b2dca1b 100644
--- a/Ring/Ring/Calls/CallViewController.swift
+++ b/Ring/Ring/Calls/CallViewController.swift
@@ -137,6 +137,9 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
                 self.setAvatarView(!self.avatarView.isHidden)
                 self.callPulse.layer.cornerRadius = (self.profileImageViewWidthConstraint.constant - 20) * 0.5
             }).disposed(by: self.disposeBag)
+        sendMessageButton.isHidden = self.viewModel.isBoothMode()
+        sendMessageButton.isEnabled = !self.viewModel.isBoothMode()
+        buttonsStackView.isHidden = self.viewModel.isBoothMode()
     }
 
     @IBAction func addParticipant(_ sender: Any) {
@@ -542,7 +545,7 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
     func removeFromScreen() {
         UIDevice.current.isProximityMonitoringEnabled = false
         UIApplication.shared.isIdleTimerDisabled = false
-        self.viewModel.showConversations()
+        self.viewModel.callFinished()
         self.dismiss(animated: false)
     }
 
diff --git a/Ring/Ring/Calls/CallViewModel.swift b/Ring/Ring/Calls/CallViewModel.swift
index 4d5601861..ff31a28e7 100644
--- a/Ring/Ring/Calls/CallViewModel.swift
+++ b/Ring/Ring/Calls/CallViewModel.swift
@@ -459,6 +459,9 @@ class CallViewModel: Stateable, ViewModel {
             .subscribe(onSuccess: { [weak self] callModel in
                 callModel.callUUID = UUID()
                 self?.call = callModel
+                if self?.isBoothMode() ?? false {
+                    return
+                }
                 self?.callsProvider
                     .startCall(account: account, call: callModel)
             }).disposed(by: self.disposeBag)
@@ -543,4 +546,19 @@ class CallViewModel: Stateable, ViewModel {
         conversationViewModel.conversation = Variable<ConversationModel>(conversation)
         self.stateSubject.onNext(ConversationState.fromCallToConversation(conversation: conversationViewModel))
     }
+
+    func isBoothMode() -> Bool {
+        return self.accountService.boothMode()
+    }
+
+    func callFinished() {
+        guard let accountId = self.call?.accountId else {
+            return
+        }
+        if self.isBoothMode() {
+            self.contactsService.removeAllContacts(for: accountId)
+            return
+        }
+        self.showConversations()
+    }
 }
diff --git a/Ring/Ring/Calls/Conference/ContactPickerViewController.swift b/Ring/Ring/Calls/Conference/ContactPickerViewController.swift
index 7272ea071..97127886a 100644
--- a/Ring/Ring/Calls/Conference/ContactPickerViewController.swift
+++ b/Ring/Ring/Calls/Conference/ContactPickerViewController.swift
@@ -94,14 +94,14 @@ class ContactPickerViewController: UIViewController, StoryboardBased, ViewModelB
                 indexPath: IndexPath,
                 contactItem: ContactPickerSection.Item) in
 
-                let cell = tableView.dequeueReusableCell(for: indexPath, cellType: ConversationCell.self)
+                let cell = tableView.dequeueReusableCell(for: indexPath, cellType: SmartListCell.self)
                 if contactItem.contacts.count < 1 {
                     return cell
                 }
-                cell.newMessagesIndicator.isHidden = true
-                cell.newMessagesLabel.isHidden = true
-                cell.lastMessageDateLabel.isHidden = true
-                cell.presenceIndicator.isHidden = true
+                cell.newMessagesIndicator?.isHidden = true
+                cell.newMessagesLabel?.isHidden = true
+                cell.lastMessageDateLabel?.isHidden = true
+                cell.presenceIndicator?.isHidden = true
                 if contactItem.contacts.count > 1 {
                     cell.avatarView.isHidden = true
                     var name = ""
@@ -119,7 +119,7 @@ class ContactPickerViewController: UIViewController, StoryboardBased, ViewModelB
 
                 var contact = contactItem.contacts.first!
                 cell.nameLabel.text = contact.firstLine
-                cell.lastMessagePreviewLabel.text = contact.secondLine
+                cell.lastMessagePreviewLabel?.text = contact.secondLine
 
                 var imageData: Data?
                 if let contactProfile = contact.profile, let photo = contactProfile.photo,
@@ -138,7 +138,7 @@ class ContactPickerViewController: UIViewController, StoryboardBased, ViewModelB
                     .observeOn(MainScheduler.instance)
                     .startWith(status.value)
                     .subscribe(onNext: { precence in
-                        cell.presenceIndicator.isHidden = !precence
+                        cell.presenceIndicator?.isHidden = !precence
                     })
                     .disposed(by: cell.disposeBag)
                 return cell
@@ -155,7 +155,7 @@ class ContactPickerViewController: UIViewController, StoryboardBased, ViewModelB
     func setupTableViews() {
         self.tableView.rowHeight = 64.0
         self.tableView.delegate = self
-        self.tableView.register(cellType: ConversationCell.self)
+        self.tableView.register(cellType: SmartListCell.self)
         self.tableView.rx.itemSelected.subscribe(onNext: { [unowned self] indexPath in
             if let contactToAdd: ConferencableItem = try? self.tableView.rx.model(at: indexPath) {
                 self.viewModel.addContactToConference(contact: contactToAdd)
diff --git a/Ring/Ring/Constants/Generated/Strings.swift b/Ring/Ring/Constants/Generated/Strings.swift
index 14f5e5308..de185106d 100644
--- a/Ring/Ring/Constants/Generated/Strings.swift
+++ b/Ring/Ring/Constants/Generated/Strings.swift
@@ -52,14 +52,24 @@ internal enum L10n {
   }
 
   internal enum AccountPage {
-    /// Block List
+    /// Blocked contacts
     internal static let blockedContacts = L10n.tr("Localizable", "accountPage.blockedContacts")
+    /// After enabling booth mode all your conversations will be removed.
+    internal static let boothModeAlertMessage = L10n.tr("Localizable", "accountPage.boothModeAlertMessage")
+    /// In booth mode conversation history not saved and jami functionality limited by making outgoing calls. When you enable booth mode all your conversations will be removed.
+    internal static let boothModeExplanation = L10n.tr("Localizable", "accountPage.boothModeExplanation")
+    /// Change password
+    internal static let changePassword = L10n.tr("Localizable", "accountPage.changePassword")
+    /// Password incorrect
+    internal static let changePasswordError = L10n.tr("Localizable", "accountPage.changePasswordError")
     /// Contact me using "%s" on the Jami distributed communication platform: https://jami.net
     internal static func contactMeOnJamiContant(_ p1: UnsafePointer<CChar>) -> String {
       return L10n.tr("Localizable", "accountPage.contactMeOnJamiContant", p1)
     }
     /// Contact me on Jami!
     internal static let contactMeOnJamiTitle = L10n.tr("Localizable", "accountPage.contactMeOnJamiTitle")
+    /// Create password
+    internal static let createPassword = L10n.tr("Localizable", "accountPage.createPassword")
     /// Account Details
     internal static let credentialsHeader = L10n.tr("Localizable", "accountPage.credentialsHeader")
     /// Device revocation error
@@ -78,6 +88,12 @@ internal enum L10n {
     internal static let deviceRevoked = L10n.tr("Localizable", "accountPage.deviceRevoked")
     /// Devices
     internal static let devicesListHeader = L10n.tr("Localizable", "accountPage.devicesListHeader")
+    /// Disable Booth Mode
+    internal static let disableBoothMode = L10n.tr("Localizable", "accountPage.disableBoothMode")
+    /// Pleace provide your account password
+    internal static let disableBoothModeExplanation = L10n.tr("Localizable", "accountPage.disableBoothModeExplanation")
+    /// Enable Booth Mode
+    internal static let enableBoothMode = L10n.tr("Localizable", "accountPage.enableBoothMode")
     /// Enable Notifications
     internal static let enableNotifications = L10n.tr("Localizable", "accountPage.enableNotifications")
     /// Enable Proxy
@@ -86,8 +102,16 @@ internal enum L10n {
     internal static let linkDeviceTitle = L10n.tr("Localizable", "accountPage.linkDeviceTitle")
     /// Name
     internal static let namePlaceholder = L10n.tr("Localizable", "accountPage.namePlaceholder")
+    /// Confirm new password
+    internal static let newPasswordConfirmPlaceholder = L10n.tr("Localizable", "accountPage.newPasswordConfirmPlaceholder")
+    /// Enter new password
+    internal static let newPasswordPlaceholder = L10n.tr("Localizable", "accountPage.newPasswordPlaceholder")
+    /// To enable Booth mode you need to create account password first.
+    internal static let noBoothMode = L10n.tr("Localizable", "accountPage.noBoothMode")
     /// Your device won't receive notifications when proxy is disabled
     internal static let noProxyExplanationLabel = L10n.tr("Localizable", "accountPage.noProxyExplanationLabel")
+    /// Enter old password
+    internal static let oldPasswordPlaceholder = L10n.tr("Localizable", "accountPage.oldPasswordPlaceholder")
     /// Other
     internal static let other = L10n.tr("Localizable", "accountPage.other")
     /// Enter account password
@@ -151,6 +175,12 @@ internal enum L10n {
     internal static let clearAction = L10n.tr("Localizable", "actions.clearAction")
     /// Delete
     internal static let deleteAction = L10n.tr("Localizable", "actions.deleteAction")
+    /// Done
+    internal static let doneAction = L10n.tr("Localizable", "actions.doneAction")
+    ///   Audio Call
+    internal static let startAudioCall = L10n.tr("Localizable", "actions.startAudioCall")
+    ///   Video Call
+    internal static let startVideoCall = L10n.tr("Localizable", "actions.startVideoCall")
   }
 
   internal enum Alerts {
@@ -206,6 +236,14 @@ internal enum L10n {
     internal static let profileTakePhoto = L10n.tr("Localizable", "alerts.profileTakePhoto")
     /// Upload photo
     internal static let profileUploadPhoto = L10n.tr("Localizable", "alerts.profileUploadPhoto")
+    /// Record an audio message
+    internal static let recordAudioMessage = L10n.tr("Localizable", "alerts.recordAudioMessage")
+    /// Record a video message
+    internal static let recordVideoMessage = L10n.tr("Localizable", "alerts.recordVideoMessage")
+    /// Upload file
+    internal static let uploadFile = L10n.tr("Localizable", "alerts.uploadFile")
+    /// Upload photo or movie
+    internal static let uploadPhoto = L10n.tr("Localizable", "alerts.uploadPhoto")
   }
 
   internal enum BlockListPage {
diff --git a/Ring/Ring/Coordinators/AppCoordinator.swift b/Ring/Ring/Coordinators/AppCoordinator.swift
index 56819a918..567f4efc8 100644
--- a/Ring/Ring/Coordinators/AppCoordinator.swift
+++ b/Ring/Ring/Coordinators/AppCoordinator.swift
@@ -35,6 +35,7 @@ public enum AppState: State {
     case allSet
     case accountRemoved
     case needAccountMigration(accountId: String)
+    case accountModeSwitched
 }
 
 public enum VCType: String {
@@ -93,6 +94,8 @@ final class AppCoordinator: Coordinator, StateableResponsive {
                 self.accountRemoved()
             case .needAccountMigration(let accountId):
                 self.migrateAccount(accountId: accountId)
+            case .accountModeSwitched:
+                self.switchAccountMode()
             }
         }).disposed(by: self.disposeBag)
     }
@@ -108,6 +111,10 @@ final class AppCoordinator: Coordinator, StateableResponsive {
     func accountRemoved() {
         self.tabBarViewController.selectedIndex = 0
     }
+    func switchAccountMode() {
+        self.childCoordinators[0].start()
+        self.tabBarViewController.selectedIndex = 0
+    }
 
     func migrateAccount(accountId: String) {
         let migratonController = MigrateAccountViewController.instantiate(with: self.injectionBag)
diff --git a/Ring/Ring/Database/DBHelpers/ConversationDataHepler.swift b/Ring/Ring/Database/DBHelpers/ConversationDataHepler.swift
index 5177aa0a7..406d96c3e 100644
--- a/Ring/Ring/Database/DBHelpers/ConversationDataHepler.swift
+++ b/Ring/Ring/Database/DBHelpers/ConversationDataHepler.swift
@@ -132,4 +132,16 @@ final class ConversationDataHelper {
             return false
         }
     }
+
+    func deleteAll(dataBase: Connection) -> Bool {
+        do {
+            if try dataBase.run(table.delete()) > 0 {
+                return true
+            } else {
+                return false
+            }
+        } catch {
+            return false
+        }
+    }
 }
diff --git a/Ring/Ring/Database/DBHelpers/InteractionDataHelper.swift b/Ring/Ring/Database/DBHelpers/InteractionDataHelper.swift
index 8d57bc8ab..6cd723a9a 100644
--- a/Ring/Ring/Database/DBHelpers/InteractionDataHelper.swift
+++ b/Ring/Ring/Database/DBHelpers/InteractionDataHelper.swift
@@ -299,6 +299,18 @@ final class InteractionDataHelper {
         }
     }
 
+    func deleteAll(dataBase: Connection) -> Bool {
+        do {
+            if try dataBase.run(table.delete()) > 0 {
+                return true
+            } else {
+                return false
+            }
+        } catch {
+            return false
+        }
+    }
+
     func insertIfNotExist(item: Interaction, dataBase: Connection) -> Int64? {
         let querySelect = table.filter(conversation == item.conversation &&
             body == item.body &&
diff --git a/Ring/Ring/Database/DBHelpers/ProfileDataHelper.swift b/Ring/Ring/Database/DBHelpers/ProfileDataHelper.swift
index 2118f85c7..4387db61c 100644
--- a/Ring/Ring/Database/DBHelpers/ProfileDataHelper.swift
+++ b/Ring/Ring/Database/DBHelpers/ProfileDataHelper.swift
@@ -202,4 +202,16 @@ final class ProfileDataHelper {
             }
         }
     }
+
+    func deleteAll(dataBase: Connection) -> Bool {
+        do {
+            if try dataBase.run(contactsProfileTable.delete()) > 0 {
+                return true
+            } else {
+                return false
+            }
+        } catch {
+            return false
+        }
+    }
 }
diff --git a/Ring/Ring/Database/DBManager.swift b/Ring/Ring/Database/DBManager.swift
index 5355819dd..ad937d100 100644
--- a/Ring/Ring/Database/DBManager.swift
+++ b/Ring/Ring/Database/DBManager.swift
@@ -393,6 +393,34 @@ class DBManager {
         }
     }
 
+    func clearAllHistoryFor(accountId: String) -> Completable {
+        return Completable.create { [unowned self] completable in
+            do {
+                guard let dataBase = self.dbConnections.forAccount(account: accountId) else {
+                    throw DBBridgingError.deleteConversationFailed
+                }
+                try dataBase.transaction {
+                    if !self.interactionHepler
+                        .deleteAll(dataBase: dataBase) {
+                        completable(.error(DBBridgingError.deleteConversationFailed))
+                    }
+                    if !self.conversationHelper
+                        .deleteAll(dataBase: dataBase) {
+                        completable(.error(DBBridgingError.deleteConversationFailed))
+                    }
+                    if !self.profileHepler
+                        .deleteAll(dataBase: dataBase) {
+                        completable(.error(DBBridgingError.deleteConversationFailed))
+                    }
+                    completable(.completed)
+                }
+            } catch {
+                completable(.error(DBBridgingError.deleteConversationFailed))
+            }
+            return Disposables.create { }
+        }
+   }
+
     func clearHistoryFor(accountId: String,
                          and participantUri: String,
                          keepConversation: Bool) -> Completable {
diff --git a/Ring/Ring/Features/ContactRequests/ContactRequestsViewModel.swift b/Ring/Ring/Features/ContactRequests/ContactRequestsViewModel.swift
index 43e1cb94c..89bf4dfea 100644
--- a/Ring/Ring/Features/ContactRequests/ContactRequestsViewModel.swift
+++ b/Ring/Ring/Features/ContactRequests/ContactRequestsViewModel.swift
@@ -91,12 +91,12 @@ class ContactRequestsViewModel: Stateable, ViewModel {
     }
 
     func discard(withItem item: ContactRequestItem) -> Observable<Void> {
-        return self.contactsService.discard(contactRequest: item.contactRequest,
+        return self.contactsService.discard(from: item.contactRequest.ringId,
                                             withAccountId: item.contactRequest.accountId)
     }
 
     func ban(withItem item: ContactRequestItem) -> Observable<Void> {
-        let discardCompleted = self.contactsService.discard(contactRequest: item.contactRequest,
+        let discardCompleted = self.contactsService.discard(from: item.contactRequest.ringId,
                                                             withAccountId: item.contactRequest.accountId)
         guard let uri = JamiURI.init(schema: URIType.ring,
                                      infoHach: item.contactRequest.ringId)
diff --git a/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift b/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift
index 1e0959673..e5a2a19b0 100644
--- a/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift
+++ b/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift
@@ -155,13 +155,13 @@ class ConversationViewModel: Stateable, ViewModel {
 
             self.contactsService
                 .getContactRequestVCard(forContactWithRingId: self.conversation.value.hash)
-                .subscribe(onSuccess: { vCard in
+                .subscribe(onSuccess: { [weak self] vCard in
                     guard let imageData = vCard.imageData else {
-                        self.log.warning("vCard for ringId: \(contactUri) has no image")
+                        self?.log.warning("vCard for ringId: \(contactUri) has no image")
                         return
                     }
-                    self.profileImageData.value = imageData
-                    self.displayName.value = VCardUtils.getName(from: vCard)
+                    self?.profileImageData.value = imageData
+                    self?.displayName.value = VCardUtils.getName(from: vCard)
                 })
                 .disposed(by: self.disposeBag)
 
@@ -202,8 +202,18 @@ class ConversationViewModel: Stateable, ViewModel {
                 .contactPresence[self.conversation.value.hash] {
                 self.contactPresence = contactPresence
             } else {
-                self.log.warning("Contact presence unknown for: \(contactUri)")
                 self.contactPresence.value = false
+                presenceService.sharedResponseStream
+                    .filter({ [weak self] serviceEvent in
+                        guard let uri: String = serviceEvent
+                            .getEventInput(ServiceEventInput.uri),
+                            let accountID: String = serviceEvent
+                                .getEventInput(ServiceEventInput.accountId) else {return false}
+                        return uri == self?.conversation.value.hash &&
+                            accountID == self?.conversation.value.accountId
+                    }).subscribe(onNext: { [weak self] _ in
+                        self?.subscribePresence()
+                    }).disposed(by: self.disposeBag)
             }
 
             if let contactUserName = contact?.userName {
@@ -212,10 +222,10 @@ class ConversationViewModel: Stateable, ViewModel {
                 self.userName.value = self.conversation.value.hash
                 // Return an observer for the username lookup
                 self.nameService.usernameLookupStatus
-                    .filter({ lookupNameResponse in
+                    .filter({ [weak self] lookupNameResponse in
                         return lookupNameResponse.address != nil &&
                             (lookupNameResponse.address == contactUri ||
-                        lookupNameResponse.address == self.conversation.value.hash)
+                        lookupNameResponse.address == self?.conversation.value.hash)
                     }).subscribe(onNext: { [weak self] lookupNameResponse in
                         if let name = lookupNameResponse.name, !name.isEmpty {
                             self?.userName.value = name
@@ -238,6 +248,15 @@ class ConversationViewModel: Stateable, ViewModel {
         }
     }
 
+    func subscribePresence() {
+        if let contactPresence = self.presenceService
+            .contactPresence[self.conversation.value.hash] {
+            self.contactPresence = contactPresence
+        } else {
+            self.contactPresence.value = false
+        }
+    }
+
     //Displays the entire date ( for messages received before the current week )
     private let dateFormatter = DateFormatter()
 
@@ -412,6 +431,9 @@ class ConversationViewModel: Stateable, ViewModel {
                 }, onError: { [weak self] (error) in
                     self?.log.info(error)
             }).disposed(by: self.disposeBag)
+        self.presenceService.subscribeBuddy(withAccountId: currentAccount.id,
+                                            withUri: self.conversation.value.hash,
+                                            withFlag: true)
     }
 
     func block() {
@@ -422,7 +444,7 @@ class ConversationViewModel: Stateable, ViewModel {
                                                                  ban: true,
                                                                  withAccountId: accountId)
         if let contactRequest = self.contactsService.contactRequest(withRingId: contactRingId) {
-            let discardCompleted = self.contactsService.discard(contactRequest: contactRequest,
+            let discardCompleted = self.contactsService.discard(from: contactRequest.ringId,
                                                                 withAccountId: accountId)
             blockComplete = Observable<Void>.zip(discardCompleted, removeCompleted) { _, _ in
                 return
@@ -443,7 +465,7 @@ class ConversationViewModel: Stateable, ViewModel {
 
     func ban(withItem item: ContactRequestItem) -> Observable<Void> {
         let accountId = item.contactRequest.accountId
-        let discardCompleted = self.contactsService.discard(contactRequest: item.contactRequest,
+        let discardCompleted = self.contactsService.discard(from: item.contactRequest.ringId,
                                                             withAccountId: accountId)
         let removeCompleted = self.contactsService.removeContact(withUri: item.contactRequest.ringId,
                                                                  ban: true,
diff --git a/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift b/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift
index ff120c130..bbbbabef4 100644
--- a/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift
+++ b/Ring/Ring/Features/Conversations/ConversationsCoordinator.swift
@@ -96,6 +96,11 @@ class ConversationsCoordinator: Coordinator, StateableResponsive, ConversationNa
         guard let account = self.accountService
             .getAccount(fromAccountId: call.accountId),
             !call.callId.isEmpty else {return}
+        if self.accountService.boothMode() {
+            self.callService.refuse(callId: call.callId)
+                .subscribe().disposed(by: self.disposeBag)
+            return
+        }
         guard let topController = getTopController(),
             !topController.isKind(of: (CallViewController).self) else {
                 return
@@ -213,7 +218,14 @@ class ConversationsCoordinator: Coordinator, StateableResponsive, ConversationNa
         self.pushConversation(withConversationViewModel: conversationViewModel)
     }
 
-    func start () {
+    func start() {
+        self.navigationViewController.viewControllers.removeAll()
+        let boothMode = self.accountService.boothMode()
+        if boothMode {
+            let smartListViewController = IncognitoSmartListViewController.instantiate(with: self.injectionBag)
+            self.present(viewController: smartListViewController, withStyle: .show, withAnimation: true, withStateable: smartListViewController.viewModel)
+            return
+        }
         let smartListViewController = SmartlistViewController.instantiate(with: self.injectionBag)
         self.present(viewController: smartListViewController, withStyle: .show, withAnimation: true, withStateable: smartListViewController.viewModel)
     }
diff --git a/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.swift b/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.swift
index e2f4ddd11..1c6c8e091 100644
--- a/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.swift
+++ b/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.swift
@@ -28,11 +28,13 @@ class ConversationCell: UITableViewCell, NibReusable {
 
     @IBOutlet weak var avatarView: UIView!
     @IBOutlet weak var nameLabel: UILabel!
-    @IBOutlet weak var newMessagesIndicator: UIView!
-    @IBOutlet weak var newMessagesLabel: UILabel!
-    @IBOutlet weak var lastMessageDateLabel: UILabel!
-    @IBOutlet weak var lastMessagePreviewLabel: UILabel!
-    @IBOutlet weak var presenceIndicator: UIView!
+    @IBOutlet weak var newMessagesIndicator: UIView?
+    @IBOutlet weak var newMessagesLabel: UILabel?
+    @IBOutlet weak var lastMessageDateLabel: UILabel?
+    @IBOutlet weak var lastMessagePreviewLabel: UILabel?
+    @IBOutlet weak var presenceIndicator: UIView?
+
+    var avatarSize: CGFloat { return 40 }
 
     override func setSelected(_ selected: Bool, animated: Bool) {
         self.backgroundColor = UIColor.jamiUITableViewCellSelection
@@ -76,21 +78,23 @@ class ConversationCell: UITableViewCell, NibReusable {
                     .addSubview(
                         AvatarView(profileImageData: profileData.element?.0,
                                    username: data,
-                                   size: 40))
+                                   size: self?.avatarSize ?? 40))
                 return
             })
             .disposed(by: self.disposeBag)
 
         // unread messages
-        self.newMessagesLabel.text = item.unreadMessages
-        self.newMessagesIndicator.isHidden = item.hideNewMessagesLabel
+        self.newMessagesLabel?.text = item.unreadMessages
+        self.newMessagesIndicator?.isHidden = item.hideNewMessagesLabel
 
         // presence
+        if self.presenceIndicator != nil {
         item.contactPresence.asObservable()
             .observeOn(MainScheduler.instance)
             .map { value in !value }
-            .bind(to: self.presenceIndicator.rx.isHidden)
+            .bind(to: self.presenceIndicator!.rx.isHidden)
             .disposed(by: self.disposeBag)
+            }
 
         // username
         item.bestName.asObservable()
@@ -100,11 +104,11 @@ class ConversationCell: UITableViewCell, NibReusable {
         self.nameLabel.lineBreakMode = .byTruncatingTail
 
         // last message date
-        self.lastMessageDateLabel.text = item.lastMessageReceivedDate
+        self.lastMessageDateLabel?.text = item.lastMessageReceivedDate
 
         // last message preview
-        self.lastMessagePreviewLabel.text = item.lastMessage
-        self.lastMessagePreviewLabel.lineBreakMode = .byTruncatingTail
+        self.lastMessagePreviewLabel?.text = item.lastMessage
+        self.lastMessagePreviewLabel?.lineBreakMode = .byTruncatingTail
 
         self.selectionStyle = .none
     }
diff --git a/Ring/Ring/Features/Conversations/SmartList/Cells/IncognitoSmartListCell.swift b/Ring/Ring/Features/Conversations/SmartList/Cells/IncognitoSmartListCell.swift
new file mode 100644
index 000000000..b7357ec87
--- /dev/null
+++ b/Ring/Ring/Features/Conversations/SmartList/Cells/IncognitoSmartListCell.swift
@@ -0,0 +1,23 @@
+/*
+*  Copyright (C) 2020 Savoir-faire Linux Inc.
+*
+*  Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+*/
+
+class IncognitoSmartListCell: ConversationCell {
+    override var avatarSize: CGFloat { return 80 }
+}
diff --git a/Ring/Ring/Features/Conversations/SmartList/Cells/IncognitoSmartListCell.xib b/Ring/Ring/Features/Conversations/SmartList/Cells/IncognitoSmartListCell.xib
new file mode 100644
index 000000000..93f1729e5
--- /dev/null
+++ b/Ring/Ring/Features/Conversations/SmartList/Cells/IncognitoSmartListCell.xib
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="150" id="1LM-2m-16A" customClass="IncognitoSmartListCell" customModule="Ring" customModuleProvider="target">
+            <rect key="frame" x="0.0" y="0.0" width="414" height="150"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="1LM-2m-16A" id="dGp-y2-lQ3">
+                <rect key="frame" x="0.0" y="0.0" width="414" height="150"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4Fr-fc-JfP" userLabel="Avatar View">
+                        <rect key="frame" x="167" y="20" width="80" height="80"/>
+                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="80" id="iSv-Ly-cn7"/>
+                            <constraint firstAttribute="height" constant="80" id="mQv-lf-YGw"/>
+                        </constraints>
+                    </view>
+                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="c3C-hG-z8X">
+                        <rect key="frame" x="207" y="110" width="0.0" height="30"/>
+                        <fontDescription key="fontDescription" type="system" weight="light" pointSize="20"/>
+                        <nil key="textColor"/>
+                        <nil key="highlightedColor"/>
+                    </label>
+                </subviews>
+                <constraints>
+                    <constraint firstItem="4Fr-fc-JfP" firstAttribute="top" secondItem="dGp-y2-lQ3" secondAttribute="top" constant="20" id="1nI-Wm-UXW"/>
+                    <constraint firstItem="c3C-hG-z8X" firstAttribute="top" secondItem="4Fr-fc-JfP" secondAttribute="bottom" constant="10" id="Vv1-sF-jKg"/>
+                    <constraint firstItem="4Fr-fc-JfP" firstAttribute="centerX" secondItem="dGp-y2-lQ3" secondAttribute="centerX" id="egs-ar-EXo"/>
+                    <constraint firstItem="c3C-hG-z8X" firstAttribute="centerX" secondItem="dGp-y2-lQ3" secondAttribute="centerX" id="iHj-r4-1Yn"/>
+                    <constraint firstAttribute="bottom" secondItem="c3C-hG-z8X" secondAttribute="bottom" constant="10" id="wAQ-Fs-WEW"/>
+                </constraints>
+            </tableViewCellContentView>
+            <connections>
+                <outlet property="avatarView" destination="4Fr-fc-JfP" id="HGs-MF-iXG"/>
+                <outlet property="nameLabel" destination="c3C-hG-z8X" id="AZC-rO-J23"/>
+            </connections>
+            <point key="canvasLocation" x="9" y="-89"/>
+        </tableViewCell>
+    </objects>
+</document>
diff --git a/Ring/Ring/Features/Conversations/SmartList/Cells/SmartListCell.swift b/Ring/Ring/Features/Conversations/SmartList/Cells/SmartListCell.swift
new file mode 100644
index 000000000..0a839bea1
--- /dev/null
+++ b/Ring/Ring/Features/Conversations/SmartList/Cells/SmartListCell.swift
@@ -0,0 +1,22 @@
+/*
+*  Copyright (C) 2020 Savoir-faire Linux Inc.
+*
+*  Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+*/
+
+class SmartListCell: ConversationCell {
+}
diff --git a/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.xib b/Ring/Ring/Features/Conversations/SmartList/Cells/SmartListCell.xib
similarity index 95%
rename from Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.xib
rename to Ring/Ring/Features/Conversations/SmartList/Cells/SmartListCell.xib
index 37b692c86..d08b5aad8 100644
--- a/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.xib
+++ b/Ring/Ring/Features/Conversations/SmartList/Cells/SmartListCell.xib
@@ -1,21 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
-    <device id="retina4_7" orientation="portrait">
-        <adaptation id="fullscreen"/>
-    </device>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="76" id="KGk-i7-Jjw" customClass="ConversationCell" customModule="Ring" customModuleProvider="target">
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="76" id="KGk-i7-Jjw" customClass="SmartListCell" customModule="Ring" customModuleProvider="target">
             <rect key="frame" x="0.0" y="0.0" width="358" height="76"/>
             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
             <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
-                <rect key="frame" x="0.0" y="0.0" width="358" height="75.5"/>
+                <rect key="frame" x="0.0" y="0.0" width="358" height="76"/>
                 <autoresizingMask key="autoresizingMask"/>
                 <subviews>
                     <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="KC4-sG-yj8" userLabel="Avatar View">
@@ -33,13 +31,13 @@
                         <nil key="highlightedColor"/>
                     </label>
                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2fJ-Wf-1e0">
-                        <rect key="frame" x="60" y="8" width="278" height="55.5"/>
+                        <rect key="frame" x="60" y="8" width="278" height="56"/>
                         <fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
                         <nil key="textColor"/>
                         <nil key="highlightedColor"/>
                     </label>
                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eug-ak-r49">
-                        <rect key="frame" x="60" y="67.5" width="278" height="0.0"/>
+                        <rect key="frame" x="60" y="68" width="278" height="0.0"/>
                         <fontDescription key="fontDescription" type="system" pointSize="14"/>
                         <nil key="textColor"/>
                         <nil key="highlightedColor"/>
diff --git a/Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewController.storyboard b/Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewController.storyboard
new file mode 100644
index 000000000..459e12ef8
--- /dev/null
+++ b/Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewController.storyboard
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="VQC-aV-7oi">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--Incognito Smart List View Controller-->
+        <scene sceneID="ddP-29-OKS">
+            <objects>
+                <viewController hidesBottomBarWhenPushed="YES" id="VQC-aV-7oi" customClass="IncognitoSmartListViewController" customModule="Ring" customModuleProvider="target" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="Lsh-nl-RJT">
+                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" translatesAutoresizingMaskIntoConstraints="NO" id="XVO-MU-jo2">
+                                <rect key="frame" x="0.0" y="44" width="414" height="852"/>
+                                <subviews>
+                                    <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="Snl-Rn-2k3">
+                                        <rect key="frame" x="0.0" y="0.0" width="414" height="236"/>
+                                        <subviews>
+                                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="byS-Ap-EAU">
+                                                <rect key="frame" x="0.0" y="0.0" width="414" height="40"/>
+                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="40" id="hRo-xA-uvQ"/>
+                                                </constraints>
+                                            </view>
+                                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="jamiIcon" translatesAutoresizingMaskIntoConstraints="NO" id="thK-sI-jCE">
+                                                <rect key="frame" x="0.0" y="40" width="414" height="105"/>
+                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="105" id="wJk-Kp-hds"/>
+                                                </constraints>
+                                            </imageView>
+                                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Gt-Rt-p98">
+                                                <rect key="frame" x="0.0" y="145" width="414" height="35"/>
+                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="35" id="roG-sR-QtB"/>
+                                                </constraints>
+                                            </view>
+                                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qeo-Fd-n47" userLabel="Network Alert View">
+                                                <rect key="frame" x="0.0" y="180" width="414" height="56"/>
+                                                <subviews>
+                                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="KdJ-ct-8fq" userLabel="Alert Labels View">
+                                                        <rect key="frame" x="190.5" y="0.0" width="33" height="56"/>
+                                                        <subviews>
+                                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="X9t-3C-1Cp" userLabel="Network Alert Label">
+                                                                <rect key="frame" x="-2" y="19" width="37.5" height="18"/>
+                                                                <fontDescription key="fontDescription" type="system" pointSize="15"/>
+                                                                <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                                                                <nil key="highlightedColor"/>
+                                                            </label>
+                                                        </subviews>
+                                                        <constraints>
+                                                            <constraint firstItem="X9t-3C-1Cp" firstAttribute="width" secondItem="KdJ-ct-8fq" secondAttribute="width" multiplier="1.13636" id="GvM-sR-tIj"/>
+                                                            <constraint firstItem="X9t-3C-1Cp" firstAttribute="centerX" secondItem="KdJ-ct-8fq" secondAttribute="centerX" id="JP1-Ha-1s8"/>
+                                                            <constraint firstAttribute="height" constant="56" id="axB-4g-Day"/>
+                                                            <constraint firstItem="X9t-3C-1Cp" firstAttribute="centerY" secondItem="KdJ-ct-8fq" secondAttribute="centerY" id="w27-o3-a8S"/>
+                                                        </constraints>
+                                                    </view>
+                                                </subviews>
+                                                <color key="backgroundColor" red="0.94117647059999998" green="0.43921568630000002" blue="0.43921568630000002" alpha="1" colorSpace="calibratedRGB"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="56" id="F1g-wg-LFx"/>
+                                                    <constraint firstItem="KdJ-ct-8fq" firstAttribute="centerY" secondItem="qeo-Fd-n47" secondAttribute="centerY" id="mdH-co-Kac"/>
+                                                    <constraint firstItem="KdJ-ct-8fq" firstAttribute="centerX" secondItem="qeo-Fd-n47" secondAttribute="centerX" priority="750" id="pCf-7n-IeF"/>
+                                                </constraints>
+                                            </view>
+                                        </subviews>
+                                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                        <constraints>
+                                            <constraint firstAttribute="trailing" secondItem="qeo-Fd-n47" secondAttribute="trailing" id="6ct-Kx-hXb"/>
+                                            <constraint firstItem="qeo-Fd-n47" firstAttribute="leading" secondItem="Snl-Rn-2k3" secondAttribute="leading" id="nP8-db-kad"/>
+                                        </constraints>
+                                    </stackView>
+                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="RC3-OR-Sdo">
+                                        <rect key="frame" x="0.0" y="236" width="414" height="56"/>
+                                        <subviews>
+                                            <searchBar contentMode="redraw" id="rXO-wH-W8B">
+                                                <rect key="frame" x="0.0" y="0.0" width="414" height="56"/>
+                                                <autoresizingMask key="autoresizingMask" widthSizable="YES"/>
+                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                                <textInputTraits key="textInputTraits"/>
+                                            </searchBar>
+                                        </subviews>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="56" id="i5V-8X-L7Z"/>
+                                        </constraints>
+                                    </view>
+                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Yfv-j3-kOe">
+                                        <rect key="frame" x="0.0" y="292" width="414" height="499"/>
+                                        <subviews>
+                                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="MK3-LU-grM">
+                                                <rect key="frame" x="0.0" y="0.0" width="414" height="499"/>
+                                                <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+                                                <stackView key="tableFooterView" opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="15" id="j2Q-e4-mDm">
+                                                    <rect key="frame" x="0.0" y="0.0" width="414" height="44"/>
+                                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                                                    <subviews>
+                                                        <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Syd-wf-zvr">
+                                                            <rect key="frame" x="0.0" y="0.0" width="199.5" height="44"/>
+                                                            <subviews>
+                                                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="KVW-Ib-pta">
+                                                                    <rect key="frame" x="0.0" y="0.0" width="15" height="44"/>
+                                                                    <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+                                                                    <constraints>
+                                                                        <constraint firstAttribute="width" constant="15" id="Ia9-pu-KkS"/>
+                                                                    </constraints>
+                                                                </view>
+                                                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Z1C-QN-Ish" customClass="DesignableButton" customModule="Ring" customModuleProvider="target">
+                                                                    <rect key="frame" x="15" y="0.0" width="184.5" height="44"/>
+                                                                    <fontDescription key="fontDescription" type="system" weight="light" pointSize="19"/>
+                                                                    <color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                                                    <state key="normal" title="   Video Call" image="video_running">
+                                                                        <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                                                    </state>
+                                                                    <userDefinedRuntimeAttributes>
+                                                                        <userDefinedRuntimeAttribute type="boolean" keyPath="roundedCorners" value="YES"/>
+                                                                    </userDefinedRuntimeAttributes>
+                                                                </button>
+                                                            </subviews>
+                                                        </stackView>
+                                                        <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Z0k-xY-9Qd">
+                                                            <rect key="frame" x="214.5" y="0.0" width="199.5" height="44"/>
+                                                            <subviews>
+                                                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5PU-M8-7lD" customClass="DesignableButton" customModule="Ring" customModuleProvider="target">
+                                                                    <rect key="frame" x="0.0" y="0.0" width="184.5" height="44"/>
+                                                                    <fontDescription key="fontDescription" type="system" weight="light" pointSize="19"/>
+                                                                    <color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                                                    <state key="normal" title="   Audio Call" image="call_button">
+                                                                        <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                                                    </state>
+                                                                    <userDefinedRuntimeAttributes>
+                                                                        <userDefinedRuntimeAttribute type="boolean" keyPath="roundedCorners" value="YES"/>
+                                                                    </userDefinedRuntimeAttributes>
+                                                                </button>
+                                                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="b0i-TS-FoA">
+                                                                    <rect key="frame" x="184.5" y="0.0" width="15" height="44"/>
+                                                                    <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+                                                                    <constraints>
+                                                                        <constraint firstAttribute="width" constant="15" id="tMR-m6-i2R"/>
+                                                                    </constraints>
+                                                                </view>
+                                                            </subviews>
+                                                        </stackView>
+                                                    </subviews>
+                                                </stackView>
+                                            </tableView>
+                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ub7-pM-ati">
+                                                <rect key="frame" x="187.5" y="0.0" width="39.5" height="19.5"/>
+                                                <fontDescription key="fontDescription" style="UICTFontTextStyleCallout"/>
+                                                <nil key="textColor"/>
+                                                <nil key="highlightedColor"/>
+                                            </label>
+                                        </subviews>
+                                        <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+                                        <constraints>
+                                            <constraint firstItem="Ub7-pM-ati" firstAttribute="top" secondItem="MK3-LU-grM" secondAttribute="top" id="BZv-Hr-4Rb"/>
+                                            <constraint firstItem="MK3-LU-grM" firstAttribute="top" secondItem="Yfv-j3-kOe" secondAttribute="top" id="Huf-lP-gNy"/>
+                                            <constraint firstItem="Ub7-pM-ati" firstAttribute="centerX" secondItem="Yfv-j3-kOe" secondAttribute="centerX" id="bYV-2e-sgt"/>
+                                            <constraint firstAttribute="bottom" secondItem="MK3-LU-grM" secondAttribute="bottom" id="fTV-NI-0xg"/>
+                                        </constraints>
+                                    </view>
+                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="gvx-Bj-xi3">
+                                        <rect key="frame" x="0.0" y="791" width="414" height="41"/>
+                                        <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="41" id="YSq-hX-dDN"/>
+                                        </constraints>
+                                        <fontDescription key="fontDescription" type="system" weight="light" pointSize="22"/>
+                                    </button>
+                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3Uk-bD-yCE">
+                                        <rect key="frame" x="0.0" y="832" width="414" height="20"/>
+                                        <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="20" id="3Ui-l5-o0o"/>
+                                        </constraints>
+                                    </view>
+                                </subviews>
+                                <constraints>
+                                    <constraint firstAttribute="trailing" secondItem="RC3-OR-Sdo" secondAttribute="trailing" id="3Ha-ZA-evo"/>
+                                    <constraint firstItem="Yfv-j3-kOe" firstAttribute="top" secondItem="RC3-OR-Sdo" secondAttribute="bottom" id="FQl-vD-D1e"/>
+                                    <constraint firstItem="RC3-OR-Sdo" firstAttribute="leading" secondItem="XVO-MU-jo2" secondAttribute="leading" id="blv-zx-TKT"/>
+                                    <constraint firstItem="RC3-OR-Sdo" firstAttribute="top" secondItem="Snl-Rn-2k3" secondAttribute="bottom" id="uPc-9e-hq4"/>
+                                </constraints>
+                            </stackView>
+                        </subviews>
+                        <constraints>
+                            <constraint firstItem="MK3-LU-grM" firstAttribute="leading" secondItem="Jq5-jG-gOI" secondAttribute="leading" id="3kE-pp-Qn5"/>
+                            <constraint firstItem="XVO-MU-jo2" firstAttribute="trailing" secondItem="Lsh-nl-RJT" secondAttribute="trailing" id="6sJ-Co-Dgz"/>
+                            <constraint firstItem="Jq5-jG-gOI" firstAttribute="trailing" secondItem="MK3-LU-grM" secondAttribute="trailing" id="Ng1-ld-WkW"/>
+                            <constraint firstAttribute="bottom" secondItem="XVO-MU-jo2" secondAttribute="bottom" id="gDO-q2-aT0"/>
+                            <constraint firstItem="Jq5-jG-gOI" firstAttribute="top" secondItem="XVO-MU-jo2" secondAttribute="top" id="uT3-xA-kDy"/>
+                            <constraint firstItem="XVO-MU-jo2" firstAttribute="leading" secondItem="Lsh-nl-RJT" secondAttribute="leading" id="y8D-R2-hpu"/>
+                        </constraints>
+                        <viewLayoutGuide key="safeArea" id="Jq5-jG-gOI"/>
+                    </view>
+                    <connections>
+                        <outlet property="boothSwitch" destination="gvx-Bj-xi3" id="SSi-NS-vkg"/>
+                        <outlet property="logoView" destination="Snl-Rn-2k3" id="0xv-XO-JFo"/>
+                        <outlet property="networkAlertLabel" destination="X9t-3C-1Cp" id="ruo-Cn-5ax"/>
+                        <outlet property="networkAlertView" destination="qeo-Fd-n47" id="C8H-FJ-Co6"/>
+                        <outlet property="placeAudioCall" destination="5PU-M8-7lD" id="DuF-do-s0o"/>
+                        <outlet property="placeVideoCall" destination="Z1C-QN-Ish" id="EGx-dE-zBT"/>
+                        <outlet property="searchBarShadow" destination="RC3-OR-Sdo" id="oCc-BH-udN"/>
+                        <outlet property="searchView" destination="46f-Ue-tcu" id="cja-31-Vaz"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="mvQ-Si-Of0" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+                <customObject id="46f-Ue-tcu" customClass="JamiSearchView" customModule="Ring" customModuleProvider="target">
+                    <connections>
+                        <outlet property="searchBar" destination="rXO-wH-W8B" id="r63-1p-hRj"/>
+                        <outlet property="searchResultsTableView" destination="MK3-LU-grM" id="7Lz-ew-QeT"/>
+                        <outlet property="searchingLabel" destination="Ub7-pM-ati" id="R9B-4d-mA5"/>
+                    </connections>
+                </customObject>
+            </objects>
+            <point key="canvasLocation" x="137.68115942028987" y="91.741071428571431"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="call_button" width="29" height="29"/>
+        <image name="jamiIcon" width="100" height="95"/>
+        <image name="video_running" width="29" height="29"/>
+    </resources>
+</document>
diff --git a/Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewController.swift b/Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewController.swift
new file mode 100644
index 000000000..598a083b0
--- /dev/null
+++ b/Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewController.swift
@@ -0,0 +1,204 @@
+/*
+*  Copyright (C) 2020 Savoir-faire Linux Inc.
+*
+*  Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+*/
+
+import UIKit
+import RxSwift
+import RxDataSources
+import RxCocoa
+import Reusable
+import PKHUD
+
+class IncognitoSmartListViewController: UIViewController, StoryboardBased, ViewModelBased {
+
+    @IBOutlet weak var searchView: JamiSearchView!
+
+    @IBOutlet weak var placeVideoCall: DesignableButton!
+    @IBOutlet weak var placeAudioCall: DesignableButton!
+    @IBOutlet weak var logoView: UIStackView!
+    @IBOutlet weak var boothSwitch: UIButton!
+    @IBOutlet weak var networkAlertLabel: UILabel!
+    @IBOutlet weak var networkAlertView: UIView!
+    @IBOutlet weak var searchBarShadow: UIView!
+
+    var viewModel: IncognitoSmartListViewModel!
+    fileprivate let disposeBag = DisposeBag()
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        self.configureRingNavigationBar()
+        self.setupSearchBar()
+        searchView.configure(with: viewModel.injectionBag, source: viewModel, isIncognito: true)
+        self.setupUI()
+        self.applyL10n()
+
+        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(withNotification:)), name: UIResponder.keyboardDidShowNotification, object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(withNotification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
+        self.tabBarController?.tabBar.isHidden = true
+        self.tabBarController?.tabBar.layer.zPosition = -1
+        NotificationCenter.default.rx
+            .notification(UIDevice.orientationDidChangeNotification)
+            .observeOn(MainScheduler.instance)
+            .subscribe(onNext: {[weak self](_) in
+                self?.placeVideoCall.updateGradientFrame()
+                self?.placeAudioCall.updateGradientFrame()
+            }).disposed(by: self.disposeBag)
+    }
+
+    override func viewWillAppear(_ animated: Bool) {
+        super.viewWillAppear(animated)
+        self.navigationController?.setNavigationBarHidden(true, animated: animated)
+    }
+
+    override func viewWillDisappear(_ animated: Bool) {
+        super.viewWillDisappear(animated)
+        self.navigationController?.setNavigationBarHidden(false, animated: animated)
+    }
+
+    func applyL10n() {
+        self.navigationItem.title = ""
+        self.networkAlertLabel.text = L10n.Smartlist.noNetworkConnectivity
+        boothSwitch.setTitle(L10n.AccountPage.disableBoothMode, for: .normal)
+        placeAudioCall.setTitle(L10n.Actions.startAudioCall, for: .normal)
+        placeVideoCall.setTitle(L10n.Actions.startVideoCall, for: .normal)
+    }
+
+    func setupUI() {
+        view.backgroundColor = UIColor.jamiBackgroundSecondaryColor
+        self.placeVideoCall.applyGradient(with: [UIColor.jamiButtonLight, UIColor.jamiButtonDark], gradient: .horizontal)
+        self.placeAudioCall.applyGradient(with: [UIColor.jamiButtonLight, UIColor.jamiButtonDark], gradient: .horizontal)
+        self.boothSwitch.setTitleColor(.jamiTextSecondary, for: .normal)
+        self.searchView.editSearch
+            .subscribe(onNext: {[weak self] (editing) in
+                self?.logoView.isHidden = editing
+                self?.boothSwitch.isHidden = editing
+            }).disposed(by: disposeBag)
+
+        self.placeVideoCall.rx.tap
+            .subscribe(onNext: { [weak self] in
+                self?.viewModel.startCall(audioOnly: false)
+        }).disposed(by: self.disposeBag)
+
+        self.placeAudioCall.rx.tap
+            .subscribe(onNext: { [weak self] in
+                self?.viewModel.startCall(audioOnly: true)
+        }).disposed(by: self.disposeBag)
+        self.boothSwitch.rx.tap
+            .subscribe(onNext: { [weak self] in
+                self?.confirmBoothModeAlert()
+            }).disposed(by: self.disposeBag)
+        let isHidden = self.viewModel.networkConnectionState() == .none ? false : true
+        self.networkAlertView.isHidden = isHidden
+        self.viewModel.connectionState
+            .subscribe(onNext: { [weak self] connectionState in
+                let isHidden = connectionState == .none ? false : true
+                self?.networkAlertView.isHidden = isHidden
+            })
+            .disposed(by: self.disposeBag)
+    }
+
+    @objc func keyboardWillShow(withNotification notification: Notification) {
+        guard let userInfo: Dictionary = notification.userInfo else {return}
+        guard let keyboardFrame: NSValue = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
+        let keyboardRectangle = keyboardFrame.cgRectValue
+        let keyboardHeight = keyboardRectangle.height
+        guard let tabBarHeight = (self.tabBarController?.tabBar.frame.size.height) else {
+            return
+        }
+        self.searchView.searchResultsTableView.contentInset.bottom = keyboardHeight - tabBarHeight
+        self.searchView.searchResultsTableView.scrollIndicatorInsets.bottom = keyboardHeight - tabBarHeight
+    }
+
+    @objc func keyboardWillHide(withNotification notification: Notification) {
+        self.searchView.searchResultsTableView.contentInset.bottom = 0
+        self.searchView.searchResultsTableView.scrollIndicatorInsets.bottom = 0
+    }
+
+    func setupSearchBar() {
+        searchBarShadow.backgroundColor = UIColor.jamiBackgroundSecondaryColor
+        searchBarShadow.layer.shadowColor = UIColor.jamiNavigationBarShadow.cgColor
+        searchBarShadow.layer.shadowOffset = CGSize(width: 0.0, height: 1.5)
+        searchBarShadow.layer.shadowOpacity = 0.2
+        searchBarShadow.layer.shadowRadius = 3
+        searchBarShadow.layer.masksToBounds = false
+        searchBarShadow.superview?.bringSubviewToFront(searchBarShadow)
+
+        if #available(iOS 13.0, *) {
+            let visualEffectView   = UIVisualEffectView(effect: UIBlurEffect(style: .systemChromeMaterial))
+            visualEffectView.frame = searchBarShadow.bounds
+            visualEffectView.isUserInteractionEnabled = false
+            searchBarShadow.insertSubview(visualEffectView, at: 0)
+            visualEffectView.translatesAutoresizingMaskIntoConstraints = false
+            visualEffectView.widthAnchor.constraint(equalTo: self.view.widthAnchor, constant: 0).isActive = true
+            visualEffectView.trailingAnchor.constraint(equalTo: searchBarShadow.trailingAnchor, constant: 0).isActive = true
+            visualEffectView.leadingAnchor.constraint(equalTo: searchBarShadow.leadingAnchor, constant: 0).isActive = true
+            visualEffectView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true
+            visualEffectView.bottomAnchor.constraint(equalTo: searchBarShadow.bottomAnchor, constant: 0).isActive = true
+        } else {
+            let visualEffectView   = UIVisualEffectView(effect: UIBlurEffect(style: .light))
+            visualEffectView.frame = searchBarShadow.bounds
+            visualEffectView.isUserInteractionEnabled = false
+            let background = UIView()
+            background.frame = searchBarShadow.bounds
+            background.backgroundColor = UIColor(red: 245, green: 245, blue: 245, alpha: 1.0)
+            background.alpha = 0.7
+            searchBarShadow.insertSubview(background, at: 0)
+            searchBarShadow.insertSubview(visualEffectView, at: 0)
+            background.translatesAutoresizingMaskIntoConstraints = false
+            visualEffectView.translatesAutoresizingMaskIntoConstraints = false
+            visualEffectView.widthAnchor.constraint(equalTo: self.view.widthAnchor, constant: 0).isActive = true
+            background.widthAnchor.constraint(equalTo: self.view.widthAnchor, constant: 0).isActive = true
+            visualEffectView.trailingAnchor.constraint(equalTo: searchBarShadow.trailingAnchor, constant: 0).isActive = true
+            background.trailingAnchor.constraint(equalTo: searchBarShadow.trailingAnchor, constant: 0).isActive = true
+            visualEffectView.leadingAnchor.constraint(equalTo: searchBarShadow.leadingAnchor, constant: 0).isActive = true
+            background.leadingAnchor.constraint(equalTo: searchBarShadow.leadingAnchor, constant: 0).isActive = true
+            visualEffectView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true
+            background.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true
+            visualEffectView.bottomAnchor.constraint(equalTo: searchBarShadow.bottomAnchor, constant: 0).isActive = true
+            background.bottomAnchor.constraint(equalTo: searchBarShadow.bottomAnchor, constant: 0).isActive = true
+        }
+        logoView.superview?.bringSubviewToFront(logoView)
+    }
+
+    let boothConfirmation = ConfirmationAlert()
+
+    func confirmBoothModeAlert() {
+        boothConfirmation.configure(title: L10n.AccountPage.disableBoothMode,
+                                           msg: "",
+                                           enable: false, presenter: self,
+                                           disposeBag: self.disposeBag)
+    }
+}
+
+extension IncognitoSmartListViewController: BoothModeConfirmationPresenter {
+    func enableBoothMode(enable: Bool, password: String) -> Bool {
+          return self.viewModel.enableBoothMode(enable: enable, password: password)
+      }
+
+      func switchBoothModeState(state: Bool) {
+      }
+
+      internal func stopLoadingView() {
+          HUD.hide(animated: false)
+      }
+
+      internal func showLoadingViewWithoutText() {
+          HUD.show(.labeledProgress(title: "", subtitle: nil))
+      }
+}
diff --git a/Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewModel.swift b/Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewModel.swift
new file mode 100644
index 000000000..d66a1f761
--- /dev/null
+++ b/Ring/Ring/Features/Conversations/SmartList/IncognitoSmartListViewModel.swift
@@ -0,0 +1,115 @@
+/*
+*  Copyright (C) 2020 Savoir-faire Linux Inc.
+*
+*  Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+*/
+
+import RxSwift
+import RxCocoa
+
+class IncognitoSmartListViewModel: Stateable, ViewModel, FilterConversationDataSource {
+
+    // MARK: - Rx Stateable
+    private let stateSubject = PublishSubject<State>()
+    lazy var state: Observable<State> = {
+        return self.stateSubject.asObservable()
+    }()
+
+    fileprivate let disposeBag = DisposeBag()
+
+    //Services
+    fileprivate let accountService: AccountsService
+    fileprivate let networkService: NetworkService
+    fileprivate let contactService: ContactsService
+    let conversationService: ConversationsService
+
+    lazy var currentAccount: AccountModel? = {
+        return self.accountService.currentAccount
+    }()
+
+    fileprivate var lookupName = BehaviorRelay<String?>(value: "")
+
+    var searching = PublishSubject<Bool>()
+
+    var connectionState = PublishSubject<ConnectionType>()
+    var conversationViewModels = [ConversationViewModel]()
+
+    func networkConnectionState() -> ConnectionType {
+        return self.networkService.connectionState.value
+    }
+    let injectionBag: InjectionBag
+
+    required init(with injectionBag: InjectionBag) {
+        self.accountService = injectionBag.accountService
+        self.networkService = injectionBag.networkService
+        self.contactService = injectionBag.contactsService
+        self.conversationService = injectionBag.conversationsService
+        self.injectionBag = injectionBag
+        self.networkService.connectionStateObservable
+            .subscribe(onNext: { [weak self] value in
+                self?.connectionState.onNext(value)
+            })
+            .disposed(by: self.disposeBag)
+    }
+
+    func conversationFound(conversation: ConversationViewModel?, name: String) {
+        contactFoundConversation.value = conversation
+        lookupName.accept(name)
+    }
+    fileprivate var contactFoundConversation = Variable<ConversationViewModel?>(nil)
+
+    func showConversation (withConversationViewModel conversationViewModel: ConversationViewModel) {
+    }
+
+    func enableBoothMode(enable: Bool, password: String) -> Bool {
+        guard let accountId = self.accountService.currentAccount?.id else {
+            return false
+        }
+        let result = self.accountService.setBoothMode(forAccount: accountId, enable: enable, password: password)
+        if !result {
+            return false
+        }
+        self.contactService.removeAllContacts(for: accountId)
+        self.conversationService
+        .getConversationsForAccount(accountId: accountId)
+        .subscribe()
+        .disposed(by: self.disposeBag)
+        self.stateSubject.onNext(ConversationState.accountModeChanged)
+        return true
+    }
+
+    func startCall(audioOnly: Bool) {
+        guard let currentAccount = self.accountService.currentAccount,
+            let conversation = self.contactFoundConversation.value?.conversation.value else {
+                return
+        }
+        let username: String = lookupName.value ?? ""
+        self.contactService
+            .sendContactRequest(toContactRingId: self.contactFoundConversation.value!.conversation.value.hash,
+                                withAccount: currentAccount)
+            .subscribe(onCompleted: { [weak self, weak conversation] in
+                guard let self = self, let conversation = conversation else {
+                    return
+                }
+                if audioOnly {
+                    self.stateSubject.onNext(ConversationState.startAudioCall(contactRingId: conversation.hash, userName: username))
+                    return
+                }
+                self.stateSubject.onNext(ConversationState.startCall(contactRingId: conversation.hash, userName: username))
+            }).disposed(by: self.disposeBag)
+    }
+}
diff --git a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.storyboard b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.storyboard
index e3d4df286..ae85950f3 100644
--- a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.storyboard
+++ b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.storyboard
@@ -233,16 +233,21 @@
                         <outlet property="phoneBookButton" destination="RSG-bY-flb" id="Yjw-Va-7c1"/>
                         <outlet property="qrScanButton" destination="Eta-uf-Ija" id="Hh0-vy-8EK"/>
                         <outlet property="scanButtonLeadingConstraint" destination="O7M-He-7UH" id="cvF-Wd-TJT"/>
-                        <outlet property="searchBar" destination="xPr-nI-I35" id="Y3U-rV-yfc"/>
                         <outlet property="searchBarShadow" destination="DKd-eF-L6f" id="CKZ-ws-ag1"/>
-                        <outlet property="searchResultsTableView" destination="opE-y7-3Rm" id="F3g-9d-IQt"/>
-                        <outlet property="searchTableViewLabel" destination="HGv-QU-VSD" id="cVs-pr-n1f"/>
+                        <outlet property="searchView" destination="Y4B-5f-ij4" id="FtS-9R-atZ"/>
                         <outlet property="settingsButton" destination="iaz-fd-fEz" id="R2O-R8-BDk"/>
                         <outlet property="tableTopConstraint" destination="TVk-tz-qtF" id="lIj-Yu-ZL7"/>
                         <outlet property="tableView" destination="HFM-G6-hMN" id="Gci-vk-ijr"/>
                     </connections>
                 </viewController>
                 <placeholder placeholderIdentifier="IBFirstResponder" id="JSt-CJ-9Vq" userLabel="First Responder" sceneMemberID="firstResponder"/>
+                <customObject id="Y4B-5f-ij4" customClass="JamiSearchView" customModule="Ring" customModuleProvider="target">
+                    <connections>
+                        <outlet property="searchBar" destination="xPr-nI-I35" id="M1f-Qz-kHV"/>
+                        <outlet property="searchResultsTableView" destination="opE-y7-3Rm" id="cMo-3b-5FA"/>
+                        <outlet property="searchingLabel" destination="HGv-QU-VSD" id="WnL-0s-Szs"/>
+                    </connections>
+                </customObject>
             </objects>
             <point key="canvasLocation" x="-108" y="-1208.5457271364319"/>
         </scene>
diff --git a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift
index 6a0a9f628..0f4c30bdc 100644
--- a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift
+++ b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift
@@ -30,7 +30,7 @@ import ContactsUI
 import QuartzCore
 
 //Constants
-private struct SmartlistConstants {
+struct SmartlistConstants {
     static let smartlistRowHeight: CGFloat = 64.0
     static let tableHeaderViewHeight: CGFloat = 142.0
     static let firstSectionHeightForHeader: CGFloat = 51.0
@@ -40,7 +40,6 @@ private struct SmartlistConstants {
 }
 
 // swiftlint:disable type_body_length
-// swiftlint:disable file_length
 class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased {
 
     private let log = SwiftyBeaver.self
@@ -48,11 +47,8 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
     // MARK: outlets
     @IBOutlet weak var tableView: UITableView!
     @IBOutlet weak var conversationsTableView: UITableView!
-    @IBOutlet weak var searchResultsTableView: UITableView!
-    @IBOutlet weak var searchBar: UISearchBar!
     @IBOutlet weak var noConversationsView: UIView!
     @IBOutlet weak var noConversationLabel: UILabel!
-    @IBOutlet weak var searchTableViewLabel: UILabel!
     @IBOutlet weak var networkAlertLabel: UILabel!
     @IBOutlet weak var cellularAlertLabel: UILabel!
     @IBOutlet weak var networkAlertViewTopConstraint: NSLayoutConstraint!
@@ -65,6 +61,7 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
     @IBOutlet weak var phoneBookButton: UIButton!
     @IBOutlet weak var scanButtonLeadingConstraint: NSLayoutConstraint!
     @IBOutlet weak var networkAlertView: UIView!
+    @IBOutlet weak var searchView: JamiSearchView!
 
     // account selection
     var accounPicker = UIPickerView()
@@ -85,8 +82,9 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
 
     override func viewDidLoad() {
         super.viewDidLoad()
+        searchView.configure(with: viewModel.injectionBag, source: viewModel, isIncognito: false)
         self.setupDataSources()
-        self.setupTableViews()
+        self.setupTableView()
         self.setupSearchBar()
         self.setupUI()
         self.applyL10n()
@@ -100,6 +98,9 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
          */
         NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(withNotification:)), name: UIResponder.keyboardDidShowNotification, object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(withNotification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
+        self.tabBarController?.tabBar.isHidden = false
+        self.tabBarController?.tabBar.layer.zPosition = -0
+        self.extendedLayoutIncludesOpaqueBars = true
     }
 
     @objc func dismissKeyboard() {
@@ -120,12 +121,14 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
             .titleTextAttributes = [NSAttributedString.Key.font: UIFont(name: "HelveticaNeue-Light", size: 25)!,
                                     NSAttributedString.Key.foregroundColor: UIColor.jamiMain]
         self.viewModel.closeAllPlayers()
+        self.tabBarController?.tabBar.isHidden = false
+        self.tabBarController?.tabBar.layer.zPosition = -0
+        self.navigationController?.setNavigationBarHidden(false, animated: animated)
     }
 
     func applyL10n() {
         self.navigationItem.title = L10n.Global.homeTabBarTitle
         noConversationLabel.text = L10n.Smartlist.noConversation
-        self.searchBar.placeholder = L10n.Smartlist.searchBarPlaceholder
         self.networkAlertLabel.text = L10n.Smartlist.noNetworkConnectivity
         self.cellularAlertLabel.text = L10n.Smartlist.cellularAccess
     }
@@ -134,11 +137,9 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
     func setupUI() {
         view.backgroundColor = UIColor.jamiBackgroundColor
         conversationsTableView.backgroundColor = UIColor.jamiBackgroundColor
-        searchResultsTableView.backgroundColor = UIColor.jamiBackgroundColor
         noConversationsView.backgroundColor = UIColor.jamiBackgroundColor
         noConversationLabel.backgroundColor = UIColor.jamiBackgroundColor
         noConversationLabel.textColor = UIColor.jamiLabelColor
-        searchTableViewLabel.textColor = UIColor.jamiLabelColor
         dialpadButtonShadow.backgroundColor = UIColor.jamiBackgroundSecondaryColor
         dialpadButtonShadow.layer.shadowColor = UIColor.jamiLabelColor.cgColor
         dialpadButtonShadow.layer.shadowOffset =  CGSize.zero
@@ -153,7 +154,7 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
         tableTopConstraint.constant = !isHidden ?  -(SmartlistConstants.tableViewOffset - SmartlistConstants.networkAllerHeight) : -SmartlistConstants.tableViewOffset
         self.networkAlertView.isHidden = isHidden
         self.viewModel.connectionState
-            .subscribe(onNext: { connectionState in
+            .subscribe(onNext: { [weak self] connectionState in
                 let newAlertHeight = connectionState == .none ? 0.0 : -SmartlistConstants.networkAllerHeight
                 let newTableViewTop = connectionState == .none ? -(SmartlistConstants.tableViewOffset - SmartlistConstants.networkAllerHeight) : -SmartlistConstants.tableViewOffset
                 let isHidden = connectionState == .none ? false : true
@@ -162,7 +163,7 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
                     self?.tableTopConstraint.constant = CGFloat(newTableViewTop)
                     self?.view.layoutIfNeeded()
                 }
-                self.networkAlertView.isHidden = isHidden
+                self?.networkAlertView.isHidden = isHidden
             })
             .disposed(by: self.disposeBag)
 
@@ -257,7 +258,6 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
             })
             .disposed(by: self.disposeBag)
         self.conversationsTableView.tableFooterView = UIView()
-        self.searchResultsTableView.tableFooterView = UIView()
     }
 
     func confugureAccountPicker() {
@@ -275,7 +275,8 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
         }
         self.viewModel.currentAccountChanged
             .observeOn(MainScheduler.instance)
-            .subscribe(onNext: { [unowned self] currentAccount in
+            .subscribe(onNext: { [weak self] currentAccount in
+                guard let self = self else { return }
                 if let account = currentAccount,
                     let row = self.accountsAdapter.rowForAccountId(account: account) {
                     self.accounPicker.selectRow(row, inComponent: 0, animated: true)
@@ -325,17 +326,17 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
         }
 
         self.conversationsTableView.contentInset.bottom = keyboardHeight - tabBarHeight
-        self.searchResultsTableView.contentInset.bottom = keyboardHeight - tabBarHeight
+        self.searchView.searchResultsTableView.contentInset.bottom = keyboardHeight - tabBarHeight
         self.conversationsTableView.scrollIndicatorInsets.bottom = keyboardHeight - tabBarHeight
-        self.searchResultsTableView.scrollIndicatorInsets.bottom = keyboardHeight - tabBarHeight
+        self.searchView.searchResultsTableView.scrollIndicatorInsets.bottom = keyboardHeight - tabBarHeight
     }
 
     @objc func keyboardWillHide(withNotification notification: Notification) {
         self.conversationsTableView.contentInset.bottom = 0
-        self.searchResultsTableView.contentInset.bottom = 0
+        self.searchView.searchResultsTableView.contentInset.bottom = 0
 
         self.conversationsTableView.scrollIndicatorInsets.bottom = 0
-        self.searchResultsTableView.scrollIndicatorInsets.bottom = 0
+        self.searchView.searchResultsTableView.scrollIndicatorInsets.bottom = 0
     }
 
     func setupDataSources() {
@@ -347,15 +348,13 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
                     indexPath: IndexPath,
                     conversationItem: ConversationSection.Item) in
 
-                let cell = tableView.dequeueReusableCell(for: indexPath, cellType: ConversationCell.self)
+                let cell = tableView.dequeueReusableCell(for: indexPath, cellType: SmartListCell.self)
                 cell.configureFromItem(conversationItem)
                 return cell
         }
 
         //Create DataSources for conversations and filtered conversations
         let conversationsDataSource = RxTableViewSectionedReloadDataSource<ConversationSection>(configureCell: configureCell)
-        let searchResultsDatasource = RxTableViewSectionedReloadDataSource<ConversationSection>(configureCell: configureCell)
-
         //Allows to delete
         conversationsDataSource.canEditRowAtIndexPath = { _, _  in
             return true
@@ -365,58 +364,24 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
         self.viewModel.conversations
             .bind(to: self.conversationsTableView.rx.items(dataSource: conversationsDataSource))
             .disposed(by: disposeBag)
-
-        self.viewModel.searchResults
-            .bind(to: self.searchResultsTableView.rx.items(dataSource: searchResultsDatasource))
-            .disposed(by: disposeBag)
-
-        //Set header titles
-        searchResultsDatasource.titleForHeaderInSection = { dataSource, index in
-            return dataSource.sectionModels[index].header
-        }
     }
 
-    func setupTableViews() {
+    func setupTableView() {
         //Set row height
         self.conversationsTableView.rowHeight = SmartlistConstants.smartlistRowHeight
-        self.searchResultsTableView.rowHeight = SmartlistConstants.smartlistRowHeight
 
         //Register Cell
-        self.conversationsTableView.register(cellType: ConversationCell.self)
-        self.searchResultsTableView.register(cellType: ConversationCell.self)
-
-        //Bind to ViewModel to show or hide the filtered results
-        self.viewModel.isSearching.subscribe(onNext: { [unowned self] (isSearching) in
-            self.searchResultsTableView.isHidden = !isSearching
-            self.searchTableViewLabel.isHidden = !isSearching
-        }).disposed(by: disposeBag)
-
+        self.conversationsTableView.register(cellType: SmartListCell.self)
         //Deselect the rows
         self.conversationsTableView.rx.itemSelected.subscribe(onNext: { [unowned self] indexPath in
             self.conversationsTableView.deselectRow(at: indexPath, animated: true)
         }).disposed(by: disposeBag)
 
-        self.searchResultsTableView.rx.itemSelected.subscribe(onNext: { [unowned self] indexPath in
-            self.searchResultsTableView.deselectRow(at: indexPath, animated: true)
-        }).disposed(by: disposeBag)
-
-        //Bind the search status label
-        self.viewModel.searchStatus
-            .observeOn(MainScheduler.instance)
-            .bind(to: self.searchTableViewLabel.rx.text)
-            .disposed(by: disposeBag)
-
-        self.searchResultsTableView.rx.setDelegate(self).disposed(by: disposeBag)
         self.conversationsTableView.rx.setDelegate(self).disposed(by: disposeBag)
     }
 
     func setupSearchBar() {
-        self.searchBar.returnKeyType = .done
-        self.searchBar.autocapitalizationType = .none
-        self.searchBar.tintColor = UIColor.jamiMain
-        searchBar.backgroundImage = UIImage()
         searchBarShadow.backgroundColor = UIColor.clear
-        searchBar.backgroundColor = UIColor.clear
         self.searchBarShadow.layer.shadowColor = UIColor.jamiNavigationBarShadow.cgColor
         self.searchBarShadow.layer.shadowOffset = CGSize(width: 0.0, height: 1.5)
         self.searchBarShadow.layer.shadowOpacity = 0.2
@@ -458,40 +423,11 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
             visualEffectView.bottomAnchor.constraint(equalTo: self.searchBarShadow.bottomAnchor, constant: 0).isActive = true
             background.bottomAnchor.constraint(equalTo: self.searchBarShadow.bottomAnchor, constant: 0).isActive = true
         }
-
-        //Bind the SearchBar to the ViewModel
-        self.searchBar.rx.text.orEmpty
-            .debounce(Durations.textFieldThrottlingDuration.value, scheduler: MainScheduler.instance)
-            .bind(to: self.viewModel.searchBarText)
-            .disposed(by: disposeBag)
-
-        //Show Cancel button
-        self.searchBar.rx.textDidBeginEditing.subscribe(onNext: { [unowned self] in
-            self.scanButtonLeadingConstraint.constant = -40
-            self.searchBar.setShowsCancelButton(true, animated: false)
-        }).disposed(by: disposeBag)
-
-        //Hide Cancel button
-        self.searchBar.rx.textDidEndEditing.subscribe(onNext: { [unowned self] in
-            self.scanButtonLeadingConstraint.constant = 10
-            self.searchBar.setShowsCancelButton(false, animated: false)
+        self.searchView.editSearch
+            .subscribe(onNext: {[weak self] (editing) in
+            self?.scanButtonLeadingConstraint.constant = editing ? -40 : 10
+            self?.viewModel.searching.onNext(editing)
         }).disposed(by: disposeBag)
-
-        //Cancel button event
-        self.searchBar.rx.cancelButtonClicked.subscribe(onNext: { [unowned self] in
-            self.cancelSearch()
-        }).disposed(by: disposeBag)
-
-        //Search button event
-        self.searchBar.rx.searchButtonClicked.subscribe(onNext: { [unowned self] in
-            self.searchBar.resignFirstResponder()
-        }).disposed(by: disposeBag)
-    }
-
-    func cancelSearch() {
-        self.searchBar.text = ""
-        self.searchBar.resignFirstResponder()
-        self.searchResultsTableView.isHidden = true
     }
 
     func startAccountCreation() {
@@ -500,7 +436,7 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
     }
 
     func openAccountsList() {
-        if searchBar.isFirstResponder {
+        if searchView.searchBar.isFirstResponder {
             return
         }
         if accountPickerTextView.isFirstResponder {
diff --git a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewModel.swift b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewModel.swift
index f25fd8412..8a1cd465e 100644
--- a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewModel.swift
+++ b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewModel.swift
@@ -24,7 +24,7 @@
 import RxSwift
 import SwiftyBeaver
 
-class SmartlistViewModel: Stateable, ViewModel {
+class SmartlistViewModel: Stateable, ViewModel, FilterConversationDataSource {
 
     private let log = SwiftyBeaver.self
 
@@ -46,33 +46,21 @@ class SmartlistViewModel: Stateable, ViewModel {
     fileprivate let profileService: ProfilesService
     fileprivate let callService: CallsService
 
-    let searchBarText = Variable<String>("")
-    var isSearching: Observable<Bool>!
     lazy var currentAccount: AccountModel? = {
         return self.accountsService.currentAccount
     }()
-    lazy var searchResults: Observable<[ConversationSection]> = {
-        return Observable<[ConversationSection]>
-            .combineLatest(self.contactFoundConversation
-                .asObservable(),
-                           self.filteredResults.asObservable(),
-                           resultSelector: { contactFoundConversation, filteredResults in
-
-                            var sections = [ConversationSection]()
-                            if !filteredResults.isEmpty {
-                                sections.append(ConversationSection(header: L10n.Smartlist.conversations, items: filteredResults))
-                            } else if contactFoundConversation != nil {
-                                sections.append(ConversationSection(header: L10n.Smartlist.results, items: [contactFoundConversation!]))
-                            }
 
-                            return sections
-            }).observeOn(MainScheduler.instance)
-    }()
+    var searching = PublishSubject<Bool>()
+
+    fileprivate var contactFoundConversation = Variable<ConversationViewModel?>(nil)
+
     lazy var hideNoConversationsMessage: Observable<Bool> = {
         return Observable<Bool>
-            .combineLatest(self.conversations, self.searchBarText.asObservable(),
-                           resultSelector: {(conversations, searchBarText) -> Bool in
-                            if !searchBarText.isEmpty {return true}
+            .combineLatest(self.conversations,
+                           self.searching.asObservable()
+                            .startWith(false),
+                           resultSelector: {(conversations, searching) -> Bool in
+                            if searching {return true}
                             if let convf = conversations.first {
                                 return !convf.items.isEmpty
                             }
@@ -80,13 +68,13 @@ class SmartlistViewModel: Stateable, ViewModel {
             }).observeOn(MainScheduler.instance)
     }()
 
-    var searchStatus = PublishSubject<String>()
     var connectionState = PublishSubject<ConnectionType>()
     lazy var accounts: Observable<[AccountItem]> = {
         return self.accountsService
             .accountsObservable.asObservable()
-            .map({ accountsModels in
+            .map({ [weak self] accountsModels in
             var items = [AccountItem]()
+            guard let self = self else { return items }
             for account in accountsModels {
                 items.append(AccountItem(account: account,
                                          profileObservable: self.profileService.getAccountProfile(accountId: account.id)))
@@ -95,8 +83,6 @@ class SmartlistViewModel: Stateable, ViewModel {
         })
     }()
 
-    fileprivate var filteredResults = Variable([ConversationViewModel]())
-    fileprivate var contactFoundConversation = Variable<ConversationViewModel?>(nil)
     var conversationViewModels = [ConversationViewModel]()
 
     func networkConnectionState() -> ConnectionType {
@@ -232,102 +218,10 @@ class SmartlistViewModel: Stateable, ViewModel {
                 self.connectionState.onNext(value)
             })
             .disposed(by: self.disposeBag)
-
-        //Observes if the user is searching
-        self.isSearching = searchBarText.asObservable()
-            .map({ text in
-            return !text.isEmpty
-        }).observeOn(MainScheduler.instance)
-
-        //Observes search bar text
-        searchBarText.asObservable()
-            .observeOn(MainScheduler.instance)
-            .subscribe(onNext: { [unowned self] text in
-            self.search(withText: text)
-        }).disposed(by: disposeBag)
-
-        //Observe username lookup
-        self.nameService.usernameLookupStatus
-            .observeOn(MainScheduler.instance)
-            .subscribe(onNext: { [unowned self, unowned injectionBag] usernameLookupStatus in
-                if usernameLookupStatus.state == .found &&
-                    (usernameLookupStatus.name == self.searchBarText.value
-                        || usernameLookupStatus.address == self.searchBarText.value) {
-                    if let conversation = self.conversationViewModels.filter({ conversationViewModel in
-                        conversationViewModel.conversation.value.participantUri == usernameLookupStatus.address || conversationViewModel.conversation.value.hash == usernameLookupStatus.address
-                    }).first {
-                        self.contactFoundConversation.value = conversation
-                    } else {
-                        if self.contactFoundConversation.value?.conversation.value
-                            .participantUri != usernameLookupStatus.address && self.contactFoundConversation.value?.conversation.value
-                                .hash != usernameLookupStatus.address {
-                            if let account = self.accountsService.currentAccount {
-                                let uri = JamiURI.init(schema: URIType.ring, infoHach: usernameLookupStatus.address)
-                                //Create new converation
-                                let conversation = ConversationModel(withParticipantUri: uri, accountId: account.id)
-                                let newConversation = ConversationViewModel(with: injectionBag)
-                                newConversation.conversation = Variable<ConversationModel>(conversation)
-                                self.contactFoundConversation.value = newConversation
-                            }
-                        }
-                    }
-                    self.searchStatus.onNext("")
-                } else {
-                    if self.filteredResults.value.isEmpty
-                        && self.contactFoundConversation.value == nil {
-                        self.searchStatus.onNext(L10n.Smartlist.noResults)
-                    } else {
-                        self.searchStatus.onNext("")
-                    }
-                }
-            }).disposed(by: disposeBag)
     }
 
-    fileprivate func search(withText text: String) {
-        guard let currentAccount = self.accountsService.currentAccount else { return }
-
-        self.contactFoundConversation.value = nil
-        self.filteredResults.value.removeAll()
-        self.searchStatus.onNext("")
-
-        if text.isEmpty {return}
-
-        //Filter conversations
-        let filteredConversations = self.conversationViewModels
-            .filter({conversationViewModel in
-                conversationViewModel.conversation.value.participantUri == text
-                || conversationViewModel.conversation.value.hash == text
-            })
-
-        if !filteredConversations.isEmpty {
-            self.filteredResults.value = filteredConversations
-        }
-
-        if currentAccount.type == AccountType.sip {
-            let uri = JamiURI.init(schema: URIType.sip, infoHach: text, account: currentAccount)
-            let conversation = ConversationModel(withParticipantUri: uri,
-                                                 accountId: currentAccount.id,
-                                                 hash: text)
-            let newConversation = ConversationViewModel(with: self.injectionBag)
-            newConversation.conversation = Variable<ConversationModel>(conversation)
-            self.contactFoundConversation.value = newConversation
-            return
-        }
-
-        if !text.isSHA1() {
-            self.nameService.lookupName(withAccount: currentAccount.id, nameserver: "", name: text)
-            self.searchStatus.onNext(L10n.Smartlist.searching)
-            return
-        }
-
-        if self.contactFoundConversation.value?.conversation.value.participantUri != text && self.contactFoundConversation.value?.conversation.value.hash != text {
-            let uri = JamiURI.init(schema: URIType.ring, infoHach: text)
-            let conversation = ConversationModel(withParticipantUri: uri,
-                                                 accountId: currentAccount.id)
-            let newConversation = ConversationViewModel(with: self.injectionBag)
-            newConversation.conversation = Variable<ConversationModel>(conversation)
-            self.contactFoundConversation.value = newConversation
-        }
+    func conversationFound(conversation: ConversationViewModel?, name: String) {
+        contactFoundConversation.value = conversation
     }
 
     func delete(conversationViewModel: ConversationViewModel) {
diff --git a/Ring/Ring/Features/Conversations/views/ConfirmationAlert.swift b/Ring/Ring/Features/Conversations/views/ConfirmationAlert.swift
new file mode 100644
index 000000000..dd228efeb
--- /dev/null
+++ b/Ring/Ring/Features/Conversations/views/ConfirmationAlert.swift
@@ -0,0 +1,97 @@
+/*
+*  Copyright (C) 2020 Savoir-faire Linux Inc.
+*
+*  Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ */
+
+import RxSwift
+
+protocol BoothModeConfirmationPresenter: UIViewController {
+    func showLoadingViewWithoutText()
+    func stopLoadingView()
+    func enableBoothMode(enable: Bool, password: String) -> Bool
+    func switchBoothModeState(state: Bool)
+}
+
+class ConfirmationAlert {
+    var alert = UIAlertController()
+    func configure(title: String,
+                   msg: String,
+                   enable: Bool,
+                   presenter: BoothModeConfirmationPresenter,
+                   disposeBag: DisposeBag) {
+        alert = UIAlertController(title: title,
+                                      message: msg,
+                                      preferredStyle: .alert)
+        let actionCancel = UIAlertAction(title: L10n.Actions.cancelAction,
+                                         style: .cancel) { [weak presenter] _ in
+                                            presenter?.switchBoothModeState(state: !enable)
+        }
+        let actionConfirm = UIAlertAction(title: L10n.Actions.doneAction,
+                                          style: .default) { [weak presenter, weak self] _ in
+                                            presenter?.showLoadingViewWithoutText()
+                                            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
+                                                presenter?.stopLoadingView()
+                                                if let textFields = self?.alert.textFields,
+                                                    !textFields.isEmpty,
+                                                    let text = textFields[0].text,
+                                                    !text.isEmpty {
+                                                    let result = presenter?.enableBoothMode(enable: enable, password: text)
+                                                    if result ?? true {
+                                                        return
+                                                    }
+                                                    presenter?.switchBoothModeState(state: !enable)
+                                                    guard let self = self else {
+                                                        return
+                                                    }
+                                                    presenter?.present(self.alert, animated: true, completion: nil)
+                                                    textFields[1].text = L10n.AccountPage.changePasswordError
+                                                    textFields[1].textColor = UIColor.red
+                                                }
+                                            }
+        }
+        alert.addAction(actionCancel)
+        alert.addAction(actionConfirm)
+        alert.addTextField {(textField) in
+            textField.placeholder = L10n.Account.passwordLabel
+            textField.isSecureTextEntry = true
+        }
+        alert.addTextField {(textField) in
+            textField.text = ""
+            textField.isUserInteractionEnabled = false
+            textField.textColor = UIColor.jamiLabelColor
+            textField.textAlignment = .center
+            textField.borderStyle = .none
+            textField.backgroundColor = UIColor.clear
+            textField.font =  UIFont.systemFont(ofSize: 11, weight: .thin)
+            textField.text = L10n.AccountPage.passwordPlaceholder
+        }
+
+        if let textFields = alert.textFields {
+            textFields[0].rx.text.map({text in
+                if let text = text {
+                    return !text.isEmpty
+                }
+                return false
+            }).bind(to: actionConfirm.rx.isEnabled)
+                .disposed(by: disposeBag)
+        }
+        presenter.present(alert, animated: true, completion: nil)
+        alert.textFields?[1].superview?.backgroundColor = .clear
+        alert.textFields?[1].superview?.superview?.subviews[0].removeFromSuperview()
+    }
+}
diff --git a/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchView.swift b/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchView.swift
new file mode 100644
index 000000000..d43c3e576
--- /dev/null
+++ b/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchView.swift
@@ -0,0 +1,172 @@
+/*
+*  Copyright (C) 2020 Savoir-faire Linux Inc.
+*
+*  Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+*/
+
+import UIKit
+import RxSwift
+import RxDataSources
+import RxCocoa
+import Reusable
+
+class JamiSearchView: NSObject, UITableViewDelegate {
+    @IBOutlet weak var searchBar: UISearchBar!
+    @IBOutlet weak var searchingLabel: UILabel!
+    @IBOutlet weak var searchResultsTableView: UITableView!
+
+    fileprivate var viewModel: JamiSearchViewModel!
+    fileprivate let disposeBag = DisposeBag()
+    var editSearch = PublishSubject<Bool>()
+    var isIncognito = false
+
+    let incognitoCellHeight: CGFloat = 150
+    let incognitoHeaderHeight: CGFloat = 0
+
+    func configure(with injectionBag: InjectionBag, source: FilterConversationDataSource, isIncognito: Bool) {
+        viewModel = JamiSearchViewModel(with: injectionBag, source: source)
+        self.isIncognito = isIncognito
+        setUpView()
+    }
+
+    private func setUpView() {
+        configureSearchResult()
+        configureSearchBar()
+    }
+    private func cancelSearch() {
+        self.searchBar.text = ""
+        self.searchBar.resignFirstResponder()
+        self.searchResultsTableView.isHidden = true
+    }
+
+    private func configureSearchResult() {
+        let cellType = isIncognito ? IncognitoSmartListCell.self : SmartListCell.self
+        searchResultsTableView.register(cellType: cellType)
+
+        searchResultsTableView.rowHeight = isIncognito ? incognitoCellHeight : SmartlistConstants.smartlistRowHeight
+        searchResultsTableView.backgroundColor = UIColor.jamiBackgroundColor
+        if !isIncognito {
+            searchResultsTableView.tableFooterView = UIView()
+        }
+        searchResultsTableView.rx.setDelegate(self).disposed(by: disposeBag)
+        let configureCell: (TableViewSectionedDataSource, UITableView, IndexPath, ConversationSection.Item)
+            -> UITableViewCell = {
+                (   dataSource: TableViewSectionedDataSource<ConversationSection>,
+                tableView: UITableView,
+                indexPath: IndexPath,
+                conversationItem: ConversationSection.Item) in
+
+                let cell = self.isIncognito ?
+                    tableView.dequeueReusableCell(for: indexPath,
+                                                  cellType: IncognitoSmartListCell.self) :
+                    tableView.dequeueReusableCell(for: indexPath,
+                                                  cellType: SmartListCell.self)
+                cell.configureFromItem(conversationItem)
+                return cell
+        }
+        let searchResultsDatasource = RxTableViewSectionedReloadDataSource<ConversationSection>(configureCell: configureCell)
+        viewModel.searchResults.map { (conversations) -> Bool in
+            return conversations.isEmpty
+        }.subscribe(onNext: { [weak self] (hideFooterView) in
+            self?.searchResultsTableView.tableFooterView?.isHidden = hideFooterView
+        }).disposed(by: disposeBag)
+
+        self.viewModel.searchResults
+            .bind(to: self.searchResultsTableView.rx.items(dataSource: searchResultsDatasource))
+            .disposed(by: disposeBag)
+        searchResultsTableView.rx.itemSelected.subscribe(onNext: { [weak self] indexPath in
+            self?.searchResultsTableView.deselectRow(at: indexPath, animated: true)
+        }).disposed(by: disposeBag)
+        searchResultsDatasource.titleForHeaderInSection = { dataSource, index in
+            return dataSource.sectionModels[index].header
+        }
+        //search status label
+        self.viewModel.searchStatus
+            .observeOn(MainScheduler.instance)
+            .bind(to: self.searchingLabel.rx.text)
+            .disposed(by: disposeBag)
+        searchingLabel.textColor = UIColor.jamiLabelColor
+
+        self.viewModel.isSearching.subscribe(onNext: { [weak self] (isSearching) in
+            self?.searchResultsTableView.isHidden = !isSearching
+            self?.searchingLabel.isHidden = !isSearching
+        }).disposed(by: disposeBag)
+    }
+
+    private func configureSearchBar() {
+        self.searchBar.rx.text.orEmpty
+            .debounce(Durations.textFieldThrottlingDuration.value, scheduler: MainScheduler.instance)
+            .bind(to: self.viewModel.searchBarText)
+            .disposed(by: disposeBag)
+
+        //Show Cancel button
+        self.searchBar.rx.textDidBeginEditing
+            .subscribe(onNext: { [weak self] in
+                self?.editSearch.onNext(true)
+                self?.searchBar.setShowsCancelButton(true, animated: false)
+            }).disposed(by: disposeBag)
+
+        //Hide Cancel button
+        self.searchBar.rx.textDidEndEditing
+            .subscribe(onNext: { [weak self] in
+                guard let self = self else { return }
+                self.searchBar.setShowsCancelButton(false, animated: false)
+                if self.isIncognito && !(self.searchBar.text?.isEmpty ?? true) {
+                    return
+                }
+                self.editSearch.onNext(false)
+            }).disposed(by: disposeBag)
+
+        //Cancel button event
+        self.searchBar.rx.cancelButtonClicked
+            .subscribe(onNext: { [weak self] in
+                self?.cancelSearch()
+            }).disposed(by: disposeBag)
+
+        //Search button event
+        self.searchBar.rx.searchButtonClicked
+            .subscribe(onNext: { [weak self] in
+                self?.searchBar.resignFirstResponder()
+            }).disposed(by: disposeBag)
+
+        searchBar.returnKeyType = .done
+        searchBar.autocapitalizationType = .none
+        searchBar.tintColor = UIColor.jamiMain
+        searchBar.placeholder = L10n.Smartlist.searchBarPlaceholder
+        searchBar.searchBarStyle = .minimal
+        searchBar.backgroundImage = UIImage()
+        searchBar.placeholder = L10n.Smartlist.searchBarPlaceholder
+        searchBar.backgroundColor = UIColor.clear
+    }
+
+// MARK: UITableViewDelegate
+
+    func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
+        guard let headerView = view as? UITableViewHeaderFooterView else { return }
+        headerView.tintColor = .clear
+    }
+
+    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
+        return isIncognito ? incognitoHeaderHeight : SmartlistConstants.tableHeaderViewHeight
+    }
+
+    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        if let convToShow: ConversationViewModel = try? tableView.rx.model(at: indexPath) {
+            self.viewModel.showConversation(conversation: convToShow)
+        }
+    }
+}
diff --git a/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchViewModel.swift b/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchViewModel.swift
new file mode 100644
index 000000000..74493b353
--- /dev/null
+++ b/Ring/Ring/Features/Conversations/views/JamiSearchView/JamiSearchViewModel.swift
@@ -0,0 +1,176 @@
+/*
+*  Copyright (C) 2020 Savoir-faire Linux Inc.
+*
+*  Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+*/
+
+import Foundation
+import RxSwift
+import RxCocoa
+
+protocol FilterConversationDataSource {
+    var conversationViewModels: [ConversationViewModel] { get set }
+    func conversationFound(conversation: ConversationViewModel?, name: String)
+    func showConversation(withConversationViewModel conversationViewModel: ConversationViewModel)
+}
+
+class JamiSearchViewModel {
+
+    //Services
+    fileprivate let nameService: NameService
+    fileprivate let accountsService: AccountsService
+    fileprivate let injectionBag: InjectionBag
+
+    fileprivate let disposeBag = DisposeBag()
+
+    lazy var searchResults: Observable<[ConversationSection]> = {
+        return Observable<[ConversationSection]>
+            .combineLatest(self.contactFoundConversation
+                .asObservable(),
+                           self.filteredResults.asObservable(),
+                           resultSelector: { contactFoundConversation, filteredResults in
+                            var sections = [ConversationSection]()
+                            if !filteredResults.isEmpty {
+                                sections.append(ConversationSection(header: L10n.Smartlist.conversations, items: filteredResults))
+                            } else if contactFoundConversation != nil {
+                                sections.append(ConversationSection(header: L10n.Smartlist.results, items: [contactFoundConversation!]))
+                            }
+                            return sections
+            }).observeOn(MainScheduler.instance)
+    }()
+
+    fileprivate var contactFoundConversation = BehaviorRelay<ConversationViewModel?>(value: nil)
+    fileprivate var filteredResults = Variable([ConversationViewModel]())
+
+    let searchBarText = Variable<String>("")
+    var isSearching: Observable<Bool>!
+    var searchStatus = PublishSubject<String>()
+    let dataSource: FilterConversationDataSource
+
+    init(with injectionBag: InjectionBag, source: FilterConversationDataSource) {
+        self.nameService = injectionBag.nameService
+        self.accountsService = injectionBag.accountService
+        self.injectionBag = injectionBag
+        dataSource = source
+
+        //Observes if the user is searching
+        self.isSearching = searchBarText.asObservable()
+            .map({ text in
+            return !text.isEmpty
+        }).observeOn(MainScheduler.instance)
+
+        //Observes search bar text
+        searchBarText.asObservable()
+            .observeOn(MainScheduler.instance)
+            .distinctUntilChanged()
+            .subscribe(onNext: { [weak self] text in
+            self?.search(withText: text)
+        }).disposed(by: disposeBag)
+
+        //Observe username lookup
+        self.nameService.usernameLookupStatus
+            .observeOn(MainScheduler.instance)
+            .subscribe(onNext: { [unowned self, unowned injectionBag] usernameLookupStatus in
+                if usernameLookupStatus.state == .found &&
+                    (usernameLookupStatus.name == self.searchBarText.value
+                        || usernameLookupStatus.address == self.searchBarText.value) {
+                    if let conversation = self.dataSource.conversationViewModels.filter({ conversationViewModel in
+                        conversationViewModel.conversation.value.participantUri == usernameLookupStatus.address || conversationViewModel.conversation.value.hash == usernameLookupStatus.address
+                    }).first {
+                        self.contactFoundConversation.accept(conversation)
+                        self.dataSource.conversationFound(conversation: conversation, name: self.searchBarText.value)
+                    } else {
+                        if self.contactFoundConversation.value?.conversation.value
+                            .participantUri != usernameLookupStatus.address && self.contactFoundConversation.value?.conversation.value
+                                .hash != usernameLookupStatus.address {
+                            if let account = self.accountsService.currentAccount {
+                                let uri = JamiURI.init(schema: URIType.ring, infoHach: usernameLookupStatus.address)
+                                //Create new converation
+                                let conversation = ConversationModel(withParticipantUri: uri, accountId: account.id)
+                                let newConversation = ConversationViewModel(with: injectionBag)
+                                newConversation.conversation = Variable<ConversationModel>(conversation)
+                                self.contactFoundConversation.accept(newConversation)
+                                self.dataSource.conversationFound(conversation: newConversation, name: self.searchBarText.value)
+                            }
+                        }
+                    }
+                    self.searchStatus.onNext("")
+                } else {
+                    if self.filteredResults.value.isEmpty
+                        && self.contactFoundConversation.value == nil {
+                        self.searchStatus.onNext(L10n.Smartlist.noResults)
+                    } else {
+                        self.searchStatus.onNext("")
+                    }
+                }
+            }).disposed(by: disposeBag)
+    }
+
+    fileprivate func search(withText text: String) {
+        guard let currentAccount = self.accountsService.currentAccount else { return }
+
+        self.contactFoundConversation.accept(nil)
+        self.dataSource.conversationFound(conversation: nil, name: "")
+        self.filteredResults.value.removeAll()
+        self.searchStatus.onNext("")
+
+        if text.isEmpty {return}
+
+        //Filter conversations
+        let filteredConversations = self.dataSource.conversationViewModels
+            .filter({conversationViewModel in
+                conversationViewModel.conversation.value.participantUri == text
+                || conversationViewModel.conversation.value.hash == text
+            })
+
+        if !filteredConversations.isEmpty {
+            self.filteredResults.value = filteredConversations
+        }
+
+        if currentAccount.type == AccountType.sip {
+            let uri = JamiURI.init(schema: URIType.sip, infoHach: text, account: currentAccount)
+            let conversation = ConversationModel(withParticipantUri: uri,
+                                                 accountId: currentAccount.id,
+                                                 hash: text)
+            let newConversation = ConversationViewModel(with: self.injectionBag)
+            newConversation.conversation = Variable<ConversationModel>(conversation)
+            self.contactFoundConversation.accept(newConversation)
+            self.dataSource.conversationFound(conversation: newConversation, name: self.searchBarText.value)
+            return
+        }
+
+        if !text.isSHA1() {
+            self.nameService.lookupName(withAccount: currentAccount.id, nameserver: "", name: text)
+            self.searchStatus.onNext(L10n.Smartlist.searching)
+            return
+        }
+
+        if self.contactFoundConversation.value?.conversation.value.participantUri != text && self.contactFoundConversation.value?.conversation.value.hash != text {
+            let uri = JamiURI.init(schema: URIType.ring, infoHach: text)
+            let conversation = ConversationModel(withParticipantUri: uri,
+                                                 accountId: currentAccount.id)
+            let newConversation = ConversationViewModel(with: self.injectionBag)
+            newConversation.conversation = Variable<ConversationModel>(conversation)
+            self.contactFoundConversation.accept(newConversation)
+            self.dataSource.conversationFound(conversation: newConversation, name: self.searchBarText.value)
+        }
+    }
+
+    func showConversation(conversation: ConversationViewModel) {
+        dataSource.showConversation(withConversationViewModel: conversation)
+    }
+}
diff --git a/Ring/Ring/Features/Me/LinkNewDeviceViewModel.swift b/Ring/Ring/Features/Me/LinkNewDeviceViewModel.swift
index e4e217bd6..88f76c4e7 100644
--- a/Ring/Ring/Features/Me/LinkNewDeviceViewModel.swift
+++ b/Ring/Ring/Features/Me/LinkNewDeviceViewModel.swift
@@ -86,7 +86,7 @@ class LinkNewDeviceViewModel: ViewModel, Stateable {
 
     lazy var hasPassord: Bool = {
         guard let currentAccount = self.accountService.currentAccount else {return true}
-        return AccountModelHelper(withAccount: currentAccount).havePassword
+        return AccountModelHelper(withAccount: currentAccount).hasPassword
     }()
 
     let accountService: AccountsService
diff --git a/Ring/Ring/Features/Me/Me/MeViewController.swift b/Ring/Ring/Features/Me/Me/MeViewController.swift
index fed5ae63f..1719a21ed 100644
--- a/Ring/Ring/Features/Me/Me/MeViewController.swift
+++ b/Ring/Ring/Features/Me/Me/MeViewController.swift
@@ -174,10 +174,6 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
         self.viewModel.showBlockedContacts()
     }
 
-    private func stopLoadingView() {
-        HUD.hide(animated: false)
-    }
-
     private func showLoadingView() {
         HUD.show(.labeledProgress(title: L10n.AccountPage.deviceRevocationProgress, subtitle: nil))
     }
@@ -421,7 +417,24 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
                         self?.shareAccountInfo()
                     }).disposed(by: cell.disposeBag)
                     return cell
-
+                case .changePassword:
+                    let cell = DisposableCell()
+                    cell.backgroundColor = UIColor.jamiBackgroundColor
+                    let title =  self.viewModel.hasPassword() ?
+                        L10n.AccountPage.changePassword : L10n.AccountPage.createPassword
+                    cell.textLabel?.text = title
+                    cell.textLabel?.textColor = UIColor.jamiMain
+                    cell.textLabel?.textAlignment = .center
+                    cell.sizeToFit()
+                    cell.selectionStyle = .none
+                    let button = UIButton.init(frame: cell.frame)
+                    let size = CGSize(width: self.view.frame.width, height: button.frame.height)
+                    button.frame.size = size
+                    cell.addSubview(button)
+                    button.rx.tap.subscribe(onNext: { [weak self] in
+                        self?.changePassword(title: title)
+                    }).disposed(by: cell.disposeBag)
+                    return cell
                 case .notifications:
                     let cell = DisposableCell()
                     cell.backgroundColor = UIColor.jamiBackgroundColor
@@ -483,6 +496,40 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
                                                    cell.detailTextLabel?.text = status
                                                }).disposed(by: cell.disposeBag)
                     return cell
+                case .boothMode:
+                    let cell = DisposableCell(style: .subtitle, reuseIdentifier: self.jamiIDCell)
+                    cell.backgroundColor = UIColor.jamiBackgroundColor
+                    cell.textLabel?.text = L10n.AccountPage.enableBoothMode
+                    cell.textLabel?.sizeToFit()
+                    let switchView = UISwitch()
+                    cell.selectionStyle = .none
+                    cell.accessoryType = UITableViewCell.AccessoryType.disclosureIndicator
+                    cell.accessoryView = switchView
+                    cell.detailTextLabel?.text = self.viewModel.hasPassword() ?
+                        L10n.AccountPage.boothModeExplanation : L10n.AccountPage.noBoothMode
+                    cell.detailTextLabel?.lineBreakMode = .byWordWrapping
+                    cell.detailTextLabel?.numberOfLines = 0
+                    cell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .footnote)
+                    cell.sizeToFit()
+                    cell.layoutIfNeeded()
+                    self.viewModel.switchBoothModeState
+                        .observeOn(MainScheduler.instance)
+                        .bind(to: switchView.rx.value)
+                        .disposed(by: self.disposeBag)
+                    switchView.rx
+                    .isOn.changed
+                    .subscribe(onNext: {[weak self] enable in
+                        if !enable {
+                            return
+                        }
+                        self?.viewModel.switchBoothModeState.onNext(enable)
+                        self?.confirmBoothModeAlert()
+                    }).disposed(by: self.disposeBag)
+                    cell.isUserInteractionEnabled = self.viewModel.hasPassword()
+                    cell.textLabel?.isEnabled = self.viewModel.hasPassword()
+                    cell.detailTextLabel?.isEnabled = self.viewModel.hasPassword()
+                    switchView.isEnabled = self.viewModel.hasPassword()
+                    return cell
                 case .enableAccount:
                     let cell = DisposableCell()
                     cell.backgroundColor = UIColor.jamiBackgroundColor
@@ -695,6 +742,100 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
         self.viewModel.updateSipSettings()
     }
 
+    let boothConfirmation = ConfirmationAlert()
+
+    func confirmBoothModeAlert() {
+        boothConfirmation.configure(title: L10n.AccountPage.enableBoothMode,
+                                    msg: L10n.AccountPage.boothModeAlertMessage,
+                                    enable: true, presenter: self,
+                                    disposeBag: self.disposeBag)
+    }
+
+    func changePassword(title: String) {
+        let controller = UIAlertController(title: title,
+                                           message: nil,
+                                           preferredStyle: .alert)
+        let actionCancel = UIAlertAction(title: L10n.Actions.cancelAction,
+                                         style: .cancel)
+        let actionChange = UIAlertAction(title: L10n.Actions.doneAction,
+                                         style: .default) { [weak self] _ in
+                                            guard let textFields = controller.textFields else {
+                                                return
+                                            }
+                                            self?.showLoadingViewWithoutText()
+                                            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
+                                                if textFields.count == 2, let password = textFields[1].text {
+                                                    _ = self?.viewModel
+                                                        .changePassword(oldPassword: "",
+                                                                        newPassword: password)
+                                                    self?.stopLoadingView()
+                                                } else if textFields.count == 4,
+                                                    let oldPassword = textFields[0].text, !oldPassword.isEmpty,
+                                                    let password = textFields[2].text {
+                                                    let result = self?.viewModel.changePassword(oldPassword: oldPassword, newPassword: password)
+                                                    if result ?? true {
+                                                        self?.stopLoadingView()
+                                                        return
+                                                    }
+                                                    self?.present(controller, animated: true, completion: nil)
+                                                    textFields[1].text = L10n.AccountPage.changePasswordError
+                                                    self?.stopLoadingView()
+                                                }
+                                            }
+        }
+        controller.addAction(actionCancel)
+        controller.addAction(actionChange)
+        if self.viewModel.hasPassword() {
+            controller.addTextField {(textField) in
+                textField.placeholder = L10n.AccountPage.oldPasswordPlaceholder
+                textField.isSecureTextEntry = true
+            }
+            controller.addTextField {(textField) in
+                textField.text = ""
+                textField.isUserInteractionEnabled = false
+                textField.textColor = UIColor.red
+                textField.textAlignment = .center
+                textField.borderStyle = .none
+                textField.backgroundColor = UIColor.clear
+                textField.font =  UIFont.systemFont(ofSize: 11, weight: .thin)
+            }
+        }
+
+        controller.addTextField {(textField) in
+            textField.placeholder = L10n.AccountPage.newPasswordPlaceholder
+            textField.isSecureTextEntry = true
+        }
+
+        controller.addTextField {(textField) in
+            textField.placeholder = L10n.AccountPage.newPasswordConfirmPlaceholder
+            textField.isSecureTextEntry = true
+        }
+
+        if let textFields = controller.textFields {
+            if textFields.count == 4 {
+                Observable
+                    .combineLatest(textFields[3].rx.text,
+                                   textFields[2].rx.text) {(text1, text2) -> Bool in
+                                    return text1 == text2 }
+                    .bind(to: actionChange.rx.isEnabled)
+                    .disposed(by: self.disposeBag)
+            } else {
+                Observable
+                    .combineLatest(textFields[0].rx.text,
+                                   textFields[1].rx.text) {(text1, text2) -> Bool in
+                                    return text1 == text2 }
+                    .bind(to: actionChange.rx.isEnabled)
+                    .disposed(by: self.disposeBag)
+            }
+        }
+        self.present(controller, animated: true, completion: nil)
+        if self.viewModel.hasPassword() {
+            //remove border around text view
+            controller.textFields?[1].superview?.backgroundColor = .clear
+            controller.textFields?[1].superview?.superview?.subviews[0].removeFromSuperview()
+        }
+    }
+
     var nameRegistrationBag = DisposeBag()
 
     func registerUsername() {
@@ -740,7 +881,7 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
             textField.font =  UIFont.systemFont(ofSize: 11, weight: .thin)
         }
         //password text field
-        if self.viewModel.havePassord() {
+        if self.viewModel.hasPassword() {
             controller.addTextField {(textField) in
                 textField.placeholder = L10n.AccountPage.passwordPlaceholder
                 textField.isSecureTextEntry = true
@@ -835,7 +976,7 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
         alert.addAction(actionCancel)
         alert.addAction(actionConfirm)
 
-        if self.viewModel.havePassord() {
+        if self.viewModel.hasPassword() {
             alert.addTextField {(textField) in
                 textField.placeholder = L10n.AccountPage.revokeDevicePlaceholder
                 textField.isSecureTextEntry = true
@@ -930,3 +1071,21 @@ extension MeViewController: UITableViewDelegate {
         self.settingsTable.setContentOffset(contentOffset, animated: true)
     }
 }
+
+extension MeViewController: BoothModeConfirmationPresenter {
+    func enableBoothMode(enable: Bool, password: String) -> Bool {
+          return self.viewModel.enableBoothMode(enable: enable, password: password)
+      }
+
+      func switchBoothModeState(state: Bool) {
+          self.viewModel.switchBoothModeState.onNext(state)
+      }
+
+      internal func stopLoadingView() {
+          HUD.hide(animated: false)
+      }
+
+      internal func showLoadingViewWithoutText() {
+          HUD.show(.labeledProgress(title: "", subtitle: nil))
+      }
+}
diff --git a/Ring/Ring/Features/Me/Me/MeViewModel.swift b/Ring/Ring/Features/Me/Me/MeViewModel.swift
index fdea56e2c..dec3a49ca 100644
--- a/Ring/Ring/Features/Me/Me/MeViewModel.swift
+++ b/Ring/Ring/Features/Me/Me/MeViewModel.swift
@@ -53,6 +53,8 @@ enum SettingsSection: SectionModelType {
         case proxyServer(value: String)
         case accountState(state: Variable<String>)
         case enableAccount
+        case changePassword
+        case boothMode
     }
 
     var items: [SectionRow] {
@@ -105,6 +107,8 @@ class MeViewModel: ViewModel, Stateable {
 
     let accountService: AccountsService
     let nameService: NameService
+    let contactService: ContactsService
+    let presenceService: PresenceService
 
      // MARK: - configure table sections
 
@@ -211,12 +215,14 @@ class MeViewModel: ViewModel, Stateable {
                                                            .blockedList,
                                                            .accountState(state: self.accountStatus),
                                                            .enableAccount,
+                                                           .changePassword,
+                                                           .boothMode,
                                                            .removeAccount]))
     }()
 
-    func havePassord() -> Bool {
+    func hasPassword() -> Bool {
         guard let currentAccount = self.accountService.currentAccount else {return true}
-        return AccountModelHelper(withAccount: currentAccount).havePassword
+        return AccountModelHelper(withAccount: currentAccount).hasPassword
     }
 
     lazy var jamiSettings: Observable<[SettingsSection]> = {
@@ -308,6 +314,8 @@ class MeViewModel: ViewModel, Stateable {
     required init (with injectionBag: InjectionBag) {
         self.accountService = injectionBag.accountService
         self.nameService = injectionBag.nameService
+        self.contactService = injectionBag.contactsService
+        self.presenceService = injectionBag.presenceService
         self.secureTextEntry.onNext(true)
     }
 
@@ -436,6 +444,30 @@ class MeViewModel: ViewModel, Stateable {
             }).disposed(by: self.disposeBag)
     }
 
+    func changePassword(oldPassword: String, newPassword: String) -> Bool {
+        guard let accountId = self.accountService.currentAccount?.id else {
+            return false
+        }
+        return self.accountService
+            .changePassword(forAccount: accountId, password: oldPassword, newPassword: newPassword)
+    }
+
+    var switchBoothModeState = PublishSubject<Bool>()
+
+    func enableBoothMode(enable: Bool, password: String) -> Bool {
+        guard let accountId = self.accountService.currentAccount?.id else {
+            return false
+        }
+        let result = self.accountService.setBoothMode(forAccount: accountId, enable: enable, password: password)
+        if !result {
+            return false
+        }
+        self.stateSubject.onNext(MeState.accountModeChanged)
+        self.presenceService.subscribeBuddies(withAccount: accountId, withContacts: self.contactService.contacts.value, subscribe: false)
+        self.contactService.removeAllContacts(for: accountId)
+        return true
+    }
+
     func revokeDevice(deviceId: String, accountPassword password: String) {
         guard let accountId = self.accountService.currentAccount?.id else {
             self.showActionState.value = .hideLoading
diff --git a/Ring/Ring/Features/Me/MeCoordinator.swift b/Ring/Ring/Features/Me/MeCoordinator.swift
index 806f3e909..f0cdcd357 100644
--- a/Ring/Ring/Features/Me/MeCoordinator.swift
+++ b/Ring/Ring/Features/Me/MeCoordinator.swift
@@ -31,6 +31,7 @@ public enum MeState: State {
     case blockedContacts
     case needToOnboard
     case accountRemoved
+    case accountModeChanged
     case needAccountMigration(accountId: String)
 }
 
@@ -71,6 +72,8 @@ class MeCoordinator: Coordinator, StateableResponsive {
                 self.needToOnboard()
             case .accountRemoved:
                 self.accountRemoved()
+            case .accountModeChanged:
+                self.accountModeChanged()
             case .needAccountMigration(let accountId):
                 self.migrateAccount(accountId: accountId)
             }
@@ -83,6 +86,12 @@ class MeCoordinator: Coordinator, StateableResponsive {
         }
     }
 
+    func accountModeChanged() {
+        if let parent = self.parentCoordinator as? AppCoordinator {
+            parent.stateSubject.onNext(AppState.accountModeSwitched)
+        }
+    }
+
     func migrateAccount(accountId: String) {
         if let parent = self.parentCoordinator as? AppCoordinator {
             parent.stateSubject.onNext(AppState.needAccountMigration(accountId: accountId))
diff --git a/Ring/Ring/MigrateAccount/MigrateAccountViewModel.swift b/Ring/Ring/MigrateAccount/MigrateAccountViewModel.swift
index e9f1b9447..9e1eb979d 100644
--- a/Ring/Ring/MigrateAccount/MigrateAccountViewModel.swift
+++ b/Ring/Ring/MigrateAccount/MigrateAccountViewModel.swift
@@ -121,7 +121,7 @@ class MigrateAccountViewModel: Stateable, ViewModel {
     func accountHasPassword() -> Bool {
         guard let account = self.accountService
             .getAccount(fromAccountId: registeredNamesKey) else {return true}
-        return AccountModelHelper(withAccount: account).havePassword
+        return AccountModelHelper(withAccount: account).hasPassword
     }
 
     // MARK: - Actions
diff --git a/Ring/Ring/Protocols/ConversationNavigation.swift b/Ring/Ring/Protocols/ConversationNavigation.swift
index 36bc4cbd1..055554a38 100644
--- a/Ring/Ring/Protocols/ConversationNavigation.swift
+++ b/Ring/Ring/Protocols/ConversationNavigation.swift
@@ -35,6 +35,7 @@ enum ConversationState: State {
     case showContactPicker(callID: String)
     case fromCallToConversation(conversation: ConversationViewModel)
     case needAccountMigration(accountId: String)
+    case accountModeChanged
 }
 
 protocol ConversationNavigation: class {
@@ -68,6 +69,8 @@ extension ConversationNavigation where Self: Coordinator, Self: StateableRespons
                 self.presentCallController(call: call)
             case .needAccountMigration(let accountId):
                 self.migrateAccount(accountId: accountId)
+            case .accountModeChanged:
+                self.accountModeChanged()
             default:
                 break
             }
@@ -79,6 +82,11 @@ extension ConversationNavigation where Self: Coordinator, Self: StateableRespons
             parent.stateSubject.onNext(AppState.needAccountMigration(accountId: accountId))
         }
     }
+    func accountModeChanged() {
+        if let parent = self.parentCoordinator as? AppCoordinator {
+            parent.stateSubject.onNext(AppState.accountModeSwitched)
+        }
+    }
 
     func openRecordFile(conversation: ConversationModel, audioOnly: Bool) {
         let recordFileViewController = SendFileViewController.instantiate(with: self.injectionBag)
diff --git a/Ring/Ring/Resources/en.lproj/Localizable.strings b/Ring/Ring/Resources/en.lproj/Localizable.strings
index 8f3591f83..62ac32878 100644
--- a/Ring/Ring/Resources/en.lproj/Localizable.strings
+++ b/Ring/Ring/Resources/en.lproj/Localizable.strings
@@ -144,9 +144,12 @@
 "actions.cancelAction" = "Cancel";
 "actions.clearAction" = "Clear";
 "actions.backAction" = "Back";
+"actions.doneAction" = "Done";
 "alerts.incomingCallAllertTitle" = "Incoming call from ";
 "alerts.incomingCallButtonAccept" = "Accept";
 "alerts.incomingCallButtonIgnore" = "Ignore";
+"actions.startAudioCall" = "  Audio Call";
+"actions.startVideoCall" = "  Video Call";
 
 //Calls
 "calls.callItemTitle" = "Call";
@@ -203,6 +206,18 @@
 "accountPage.usernameRegistering" = "Registering";
 "accountPage.usernameRegisterAction" = "Register";
 "accountPage.usernameRegistrationFailed" = "Registration failed. Please check password.";
+"accountPage.createPassword" = "Create password";
+"accountPage.changePassword" = "Change password";
+"accountPage.oldPasswordPlaceholder" = "Enter old password";
+"accountPage.newPasswordPlaceholder" = "Enter new password";
+"accountPage.newPasswordConfirmPlaceholder" = "Confirm new password";
+"accountPage.changePasswordError" = "Password incorrect";
+"accountPage.enableBoothMode" = "Enable Booth Mode";
+"accountPage.disableBoothMode" = "Disable Booth Mode";
+"accountPage.disableBoothModeExplanation" = "Pleace provide your account password";
+"accountPage.boothModeExplanation" = "In booth mode conversation history not saved and jami functionality limited by making outgoing calls. When you enable booth mode all your conversations will be removed.";
+"accountPage.noBoothMode" = "To enable Booth mode you need to create account password first.";
+"accountPage.boothModeAlertMessage" = "After enabling booth mode all your conversations will be removed.";
 
 //Account
 "account.sipUsername" = "User Name";
diff --git a/Ring/Ring/Services/AccountsService.swift b/Ring/Ring/Services/AccountsService.swift
index 0f29ec745..60c9bc467 100644
--- a/Ring/Ring/Services/AccountsService.swift
+++ b/Ring/Ring/Services/AccountsService.swift
@@ -66,6 +66,7 @@ class AccountsService: AccountAdapterDelegate {
     private let log = SwiftyBeaver.self
 
     let selectedAccountID = "SELECTED_ACCOUNT_ID"
+    let boothModeEnabled = "BOOTH_MODE_ENABLED"
 
     /**
      Used to register the service to daemon events, injected by constructor.
@@ -153,8 +154,8 @@ class AccountsService: AccountAdapterDelegate {
                 if index != 0 {
                     self.accountList.remove(at: index)
                     self.accountList.insert(currentAccount, at: 0)
-                    currentAccountChanged.onNext(currentAccount)
                 }
+                currentAccountChanged.onNext(currentAccount)
             } else {
                 self.accountList.append(newAccount)
                 currentAccountChanged.onNext(currentAccount)
@@ -265,6 +266,40 @@ class AccountsService: AccountAdapterDelegate {
         }
     }
 
+    func boothMode() -> Bool {
+        return UserDefaults.standard.bool(forKey: boothModeEnabled)
+    }
+
+    func setBoothMode(forAccount accountId: String, enable: Bool, password: String) -> Bool {
+        let enabled = UserDefaults.standard.bool(forKey: boothModeEnabled)
+        if enabled == enable {
+            return true
+        }
+        if !accountAdapter.passwordIsValid(accountId, password: password) {
+            return false
+        }
+        UserDefaults.standard.set(enable, forKey: boothModeEnabled)
+        let details = self.getAccountDetails(fromAccountId: accountId)
+        details
+            .set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.dhtPublicIn),
+                 withValue: (!enable).toString())
+        setAccountDetails(forAccountId: accountId, withDetails: details)
+        return true
+    }
+
+    func changePassword(forAccount accountId: String, password: String, newPassword: String) -> Bool {
+        let result = accountAdapter.changeAccountPassword(accountId, oldPassword: password, newPassword: newPassword)
+        if !result {
+            return false
+        }
+        let details = self.getAccountDetails(fromAccountId: accountId)
+        details
+        .set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.archiveHasPassword),
+             withValue: (!newPassword.isEmpty).toString())
+        setAccountDetails(forAccountId: accountId, withDetails: details)
+        return true
+    }
+
     func getAccountProfile(accountId: String) -> AccountProfile? {
         return self.dbManager.accountProfile(for: accountId)
     }
@@ -489,6 +524,8 @@ class AccountsService: AccountAdapterDelegate {
         let filename = ""
         if details
             .get(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.ringtonePath)) == filename &&
+            details
+                .get(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.ringtoneEnabled)) == "false" &&
             details
                 .get(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.dhtPeerDiscovery)) == "false" &&
             details
@@ -501,8 +538,11 @@ class AccountsService: AccountAdapterDelegate {
             .set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.ringtonePath),
                  withValue: filename)
         details
-            .set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.dhtPeerDiscovery),
+            .set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.ringtoneEnabled),
                  withValue: "false")
+        details
+        .set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.dhtPeerDiscovery),
+             withValue: "false")
         details
             .set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.accountPeerDiscovery),
                  withValue: "false")
diff --git a/Ring/Ring/Services/ContactsService.swift b/Ring/Ring/Services/ContactsService.swift
index afe3d6430..7a9abbc21 100644
--- a/Ring/Ring/Services/ContactsService.swift
+++ b/Ring/Ring/Services/ContactsService.swift
@@ -124,14 +124,14 @@ class ContactsService {
         }
     }
 
-    func loadContactRequests(withAccount account: AccountModel) {
+    func loadContactRequests(withAccount accountId: String) {
         self.contactRequests.value.removeAll()
         //Load trust requests from daemon
-        let trustRequestsDictionaries = self.contactsAdapter.trustRequests(withAccountId: account.id)
+        let trustRequestsDictionaries = self.contactsAdapter.trustRequests(withAccountId: accountId)
 
         //Create contact requests from daemon trust requests
         if let contactRequests = trustRequestsDictionaries?.map({ dictionary in
-            return ContactRequestModel(withDictionary: dictionary, accountId: account.id)
+            return ContactRequestModel(withDictionary: dictionary, accountId: accountId)
         }) {
             for contactRequest in contactRequests {
                 if self.contactRequest(withRingId: contactRequest.ringId) == nil {
@@ -173,18 +173,18 @@ class ContactsService {
         }
     }
 
-    func discard(contactRequest: ContactRequestModel, withAccountId accountId: String) -> Observable<Void> {
+    func discard(from jamiId: String, withAccountId accountId: String) -> Observable<Void> {
         return Observable.create { [unowned self] observable in
-            let success = self.contactsAdapter.discardTrustRequest(fromContact: contactRequest.ringId,
+            let success = self.contactsAdapter.discardTrustRequest(fromContact: jamiId,
                                                                    withAccountId: accountId)
 
             //Update the Contact request list
-            self.removeContactRequest(withRingId: contactRequest.ringId)
+            self.removeContactRequest(withRingId: jamiId)
 
             if success {
                 var event = ServiceEvent(withEventType: .contactRequestDiscarded)
                 event.addEventInput(.accountId, value: accountId)
-                event.addEventInput(.uri, value: contactRequest.ringId)
+                event.addEventInput(.uri, value: jamiId)
                 self.responseStream.onNext(event)
                 observable.on(.completed)
             } else {
@@ -380,4 +380,20 @@ extension ContactsService: ContactsAdapterDelegate {
             return nil
         }
     }
+
+    func removeAllContacts(for accountId: String) {
+        DispatchQueue.global(qos: .background).async {
+            for contact in self.contacts.value {
+                self.contactsAdapter.removeContact(withURI: contact.hash, accountId: accountId, ban: false)
+            }
+            self.contacts.value.removeAll()
+            self.contactRequests.value.forEach { (request) in
+                self.contactsAdapter.discardTrustRequest(fromContact: request.ringId, withAccountId: accountId)
+            }
+            self.contactRequests.value.removeAll()
+            self.dbManager
+                .clearAllHistoryFor(accountId: accountId)
+                .subscribe().disposed(by: self.disposeBag)
+        }
+    }
 }
diff --git a/Ring/Ring/Services/ConversationsManager.swift b/Ring/Ring/Services/ConversationsManager.swift
index d5b9c3e51..11041a06e 100644
--- a/Ring/Ring/Services/ConversationsManager.swift
+++ b/Ring/Ring/Services/ConversationsManager.swift
@@ -54,6 +54,9 @@ class ConversationsManager: MessagesAdapterDelegate {
             return  event.eventType == ServiceEventType.newIncomingMessage
         })
             .subscribe(onNext: { [unowned self] event in
+                if self.accountsService.boothMode() {
+                    return
+                }
                 guard let accountId: String = event.getEventInput(ServiceEventInput.accountId),
                     let messageContent: String = event.getEventInput(ServiceEventInput.content),
                     let peerUri: String = event.getEventInput(ServiceEventInput.peerUri)
@@ -70,6 +73,9 @@ class ConversationsManager: MessagesAdapterDelegate {
             return  event.eventType == ServiceEventType.newOutgoingMessage
         })
             .subscribe(onNext: { [unowned self] event in
+                if self.accountsService.boothMode() {
+                    return
+                }
                 guard let accountId: String = event.getEventInput(ServiceEventInput.accountId),
                     let messageContent: String = event.getEventInput(ServiceEventInput.content),
                     let peerUri: String = event.getEventInput(ServiceEventInput.peerUri),
@@ -97,6 +103,9 @@ class ConversationsManager: MessagesAdapterDelegate {
                     event.eventType == ServiceEventType.dataTransferChanged
             })
             .subscribe(onNext: { [unowned self] event in
+                if self.accountsService.boothMode() {
+                    return
+                }
                 guard   let transferId: UInt64 = event.getEventInput(ServiceEventInput.transferId),
                     let transferInfo = self.dataTransferService.getTransferInfo(withId: transferId),
                     let currentAccount = self.accountsService.currentAccount else {
@@ -161,6 +170,9 @@ class ConversationsManager: MessagesAdapterDelegate {
     func didReceiveMessage(_ message: [String: String], from senderAccount: String,
                            messageId: String,
                            to receiverAccountId: String) {
+        if self.accountsService.boothMode() {
+            return
+        }
         guard let content = message[textPlainMIMEType] else {
             return
         }
diff --git a/Ring/Ring/Services/GeneratedInteractionsManager.swift b/Ring/Ring/Services/GeneratedInteractionsManager.swift
index 964d1956e..61b6e965d 100644
--- a/Ring/Ring/Services/GeneratedInteractionsManager.swift
+++ b/Ring/Ring/Services/GeneratedInteractionsManager.swift
@@ -38,10 +38,14 @@ class GeneratedInteractionsManager {
         self.subscribeToCallEvents()
     }
 
+    // swiftlint:disable cyclomatic_complexity
     private func subscribeToContactEvents() {
         self.contactService
             .sharedResponseStream
             .subscribe(onNext: { [unowned self] contactRequestEvent in
+                if self.accountService.boothMode() {
+                    return
+                }
                 guard let accountID: String = contactRequestEvent.getEventInput(.accountId) else {
                     return
                 }
@@ -108,6 +112,9 @@ class GeneratedInteractionsManager {
         self.callService
             .sharedResponseStream
             .subscribe(onNext: { [unowned self] callEvent in
+                if self.accountService.boothMode() {
+                    return
+                }
                 guard let accountID: String = callEvent.getEventInput(.accountId) else {
                     return
                 }
diff --git a/Ring/Ring/Services/PresenceService.swift b/Ring/Ring/Services/PresenceService.swift
index 1eee5762a..25fdc5a43 100644
--- a/Ring/Ring/Services/PresenceService.swift
+++ b/Ring/Ring/Services/PresenceService.swift
@@ -27,11 +27,16 @@ class PresenceService {
     fileprivate let log = SwiftyBeaver.self
     var contactPresence: [String: Variable<Bool>]
 
+    fileprivate let responseStream = PublishSubject<ServiceEvent>()
+    var sharedResponseStream: Observable<ServiceEvent>
+
     fileprivate let disposeBag = DisposeBag()
 
     init(withPresenceAdapter presenceAdapter: PresenceAdapter) {
         self.contactPresence = [String: Variable<Bool>]()
         self.presenceAdapter = presenceAdapter
+        self.responseStream.disposed(by: disposeBag)
+        self.sharedResponseStream = responseStream.share()
         PresenceAdapter.delegate = self
     }
 
@@ -49,12 +54,20 @@ class PresenceService {
                         withUri uri: String,
                         withFlag flag: Bool) {
         presenceAdapter.subscribeBuddy(withURI: uri, withAccountId: accountId, withFlag: flag)
+        if !flag {
+            contactPresence[uri] = nil
+            return
+        }
         if let presenceForContact = contactPresence[uri] {
             presenceForContact.value = false
             return
         }
         let observableValue = Variable<Bool>(false)
         contactPresence[uri] = observableValue
+        var event = ServiceEvent(withEventType: .presenseSubscribed)
+        event.addEventInput(.accountId, value: accountId)
+        event.addEventInput(.uri, value: uri)
+        self.responseStream.onNext(event)
     }
 }
 
diff --git a/Ring/Ring/Services/ServiceEvent.swift b/Ring/Ring/Services/ServiceEvent.swift
index 8be118dd7..eb7132cf1 100644
--- a/Ring/Ring/Services/ServiceEvent.swift
+++ b/Ring/Ring/Services/ServiceEvent.swift
@@ -51,6 +51,7 @@ enum ServiceEventType {
     case messageTypingIndicator
     case migrationEnded
     case lastDisplayedMessageUpdated
+    case presenseSubscribed
 }
 
 /**
-- 
GitLab