diff --git a/Package.swift b/Package.swift
index 14e5880804888513d778f51ee860c843bd3e3060..5a8a8e1d8fdc7f2e8887e4caa5d72b89b2449201 100644
--- a/Package.swift
+++ b/Package.swift
@@ -10,7 +10,6 @@ let package = Package(
   products: [
     .library(name: "App", targets: ["App"]),
     .library(name: "HUD", targets: ["HUD"]),
-    .library(name: "Theme", targets: ["Theme"]),
     .library(name: "Shared", targets: ["Shared"]),
     .library(name: "Models", targets: ["Models"]),
     .library(name: "XXLogger", targets: ["XXLogger"]),
@@ -28,7 +27,6 @@ let package = Package(
     .library(name: "CrashService", targets: ["CrashService"]),
     .library(name: "TermsFeature", targets: ["TermsFeature"]),
     .library(name: "Presentation", targets: ["Presentation"]),
-    .library(name: "ToastFeature", targets: ["ToastFeature"]),
     .library(name: "BackupFeature", targets: ["BackupFeature"]),
     .library(name: "LaunchFeature", targets: ["LaunchFeature"]),
     .library(name: "SearchFeature", targets: ["SearchFeature"]),
@@ -96,12 +94,15 @@ let package = Package(
     ),
     .package(
       path: "../elixxir-dapps-sdk-swift"
-      //            url: "https://git.xx.network/elixxir/elixxir-dapps-sdk-swift",
-      //            branch: "development"
+      //url: "https://git.xx.network/elixxir/elixxir-dapps-sdk-swift",
+      //branch: "development"
     ),
     .package(
       path: "../xxm-cloud-providers"
     ),
+    .package(
+      path: "../Router-PoC/Navigation"
+    ),
     .package(
       url: "https://git.xx.network/elixxir/client-ios-db.git",
       .upToNextMajor(from: "1.1.0")
@@ -139,7 +140,6 @@ let package = Package(
         .target(name: "MenuFeature"),
         .target(name: "PushFeature"),
         .target(name: "TermsFeature"),
-        .target(name: "ToastFeature"),
         .target(name: "CrashService"),
         .target(name: "BackupFeature"),
         .target(name: "SearchFeature"),
@@ -154,6 +154,7 @@ let package = Package(
         .target(name: "ReportingFeature"),
         .target(name: "OnboardingFeature"),
         .target(name: "ContactListFeature"),
+        .product(name: "Navigation", package: "Navigation"),
       ]
     ),
     .testTarget(
@@ -192,7 +193,6 @@ let package = Package(
     .target(
       name: "Permissions",
       dependencies: [
-        .target(name: "Theme"),
         .target(name: "Shared"),
         .target(name: "DependencyInjection"),
       ]
@@ -241,12 +241,6 @@ let package = Package(
         .target(name: "DependencyInjection"),
       ]
     ),
-    .target(
-      name: "ToastFeature",
-      dependencies: [
-        .target(name: "Shared"),
-      ]
-    ),
     .target(
       name: "CrashService",
       dependencies: [
@@ -257,7 +251,6 @@ let package = Package(
     .target(
       name: "Countries",
       dependencies: [
-        .target(name: "Theme"),
         .target(name: "Shared"),
         .target(name: "DependencyInjection"),
       ],
@@ -265,21 +258,6 @@ let package = Package(
         .process("Resources"),
       ]
     ),
-    .target(
-      name: "Theme",
-      dependencies: [
-        .target(name: "Defaults"),
-        .target(name: "DependencyInjection"),
-      ]
-    ),
-    .testTarget(
-      name: "ThemeTests",
-      dependencies: [
-        .target(name: "Theme"),
-        .product(name: "Quick", package: "Quick"),
-        .product(name: "Nimble", package: "Nimble"),
-      ]
-    ),
     .target(
       name: "DrawerFeature",
       dependencies: [
@@ -291,7 +269,6 @@ let package = Package(
     .target(
       name: "HUD",
       dependencies: [
-        .target(name: "Theme"),
         .target(name: "Shared"),
         .product(name: "SnapKit", package: "SnapKit"),
       ]
@@ -319,7 +296,6 @@ let package = Package(
     .target(
       name: "Presentation",
       dependencies: [
-        .target(name: "Theme"),
         .target(name: "Shared"),
         .product(name: "SnapKit", package: "SnapKit"),
       ]
@@ -378,7 +354,6 @@ let package = Package(
       name: "ChatFeature",
       dependencies: [
         .target(name: "HUD"),
-        .target(name: "Theme"),
         .target(name: "Shared"),
         .target(name: "Defaults"),
         .target(name: "Keychain"),
@@ -434,7 +409,6 @@ let package = Package(
       name: "LaunchFeature",
       dependencies: [
         .target(name: "HUD"),
-        .target(name: "Theme"),
         .target(name: "Shared"),
         .target(name: "Defaults"),
         .target(name: "PushFeature"),
@@ -454,7 +428,6 @@ let package = Package(
     .target(
       name: "TermsFeature",
       dependencies: [
-        .target(name: "Theme"),
         .target(name: "Shared"),
         .target(name: "Defaults"),
         .target(name: "Presentation"),
@@ -463,9 +436,7 @@ let package = Package(
     .target(
       name: "RequestsFeature",
       dependencies: [
-        .target(name: "Theme"),
         .target(name: "Shared"),
-        .target(name: "ToastFeature"),
         .target(name: "ContactFeature"),
         .target(name: "DependencyInjection"),
         .product(name: "DifferenceKit", package: "DifferenceKit"),
@@ -484,7 +455,6 @@ let package = Package(
       name: "ProfileFeature",
       dependencies: [
         .target(name: "HUD"),
-        .target(name: "Theme"),
         .target(name: "Shared"),
         .target(name: "Keychain"),
         .target(name: "Defaults"),
@@ -514,7 +484,6 @@ let package = Package(
     .target(
       name: "ChatListFeature",
       dependencies: [
-        .target(name: "Theme"),
         .target(name: "Shared"),
         .target(name: "Defaults"),
         .target(name: "MenuFeature"),
@@ -566,7 +535,6 @@ let package = Package(
     .target(
       name: "MenuFeature",
       dependencies: [
-        .target(name: "Theme"),
         .target(name: "Shared"),
         .target(name: "Defaults"),
         .target(name: "Presentation"),
@@ -598,7 +566,6 @@ let package = Package(
     .target(
       name: "ScanFeature",
       dependencies: [
-        .target(name: "Theme"),
         .target(name: "Shared"),
         .target(name: "Countries"),
         .target(name: "Permissions"),
@@ -621,7 +588,6 @@ let package = Package(
     .target(
       name: "ContactListFeature",
       dependencies: [
-        .target(name: "Theme"),
         .target(name: "Shared"),
         .target(name: "Presentation"),
         .target(name: "ContactFeature"),
@@ -642,7 +608,6 @@ let package = Package(
       name: "SettingsFeature",
       dependencies: [
         .target(name: "HUD"),
-        .target(name: "Theme"),
         .target(name: "Shared"),
         .target(name: "Defaults"),
         .target(name: "Keychain"),
diff --git a/Sources/App/AppDelegate.swift b/Sources/App/AppDelegate.swift
index c4d76fdeef07350ba48d3fb275c7101d0518926b..6ff2efd3a3207403d7bc1be03792a276cee9235e 100644
--- a/Sources/App/AppDelegate.swift
+++ b/Sources/App/AppDelegate.swift
@@ -1,12 +1,12 @@
 import UIKit
+import Navigation
 import BackgroundTasks
 
-import Theme
+import Shared
 import XXModels
 import XXLogger
 import Defaults
 import PushFeature
-import ToastFeature
 import LaunchFeature
 import CrashReporting
 import DependencyInjection
@@ -20,9 +20,9 @@ import CloudFilesICloud
 import CloudFilesDropbox
 
 public class AppDelegate: UIResponder, UIApplicationDelegate {
-  @Dependency private var pushRouter: PushRouter
-  @Dependency private var pushHandler: PushHandling
-  @Dependency private var crashReporter: CrashReporter
+  @Dependency var navigator: Navigator
+  @Dependency var pushHandler: PushHandling
+  @Dependency var crashReporter: CrashReporter
 
   @KeyObject(.hideAppList, defaultValue: false) var hideAppList: Bool
   @KeyObject(.recordingLogs, defaultValue: true) var recordingLogs: Bool
@@ -39,32 +39,15 @@ public class AppDelegate: UIResponder, UIApplicationDelegate {
     _ application: UIApplication,
     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
   ) -> Bool {
-#if DEBUG
-    DependencyRegistrator.registerForMock()
-#else
-    DependencyRegistrator.registerForLive()
-#endif
-
-    if recordingLogs {
-      XXLogger.start()
-    }
-
-    crashReporter.configure()
-    crashReporter.setEnabled(isCrashReportingEnabled)
-
     UNUserNotificationCenter.current().delegate = self
-
-    let window = Window()
-    let navController = UINavigationController(rootViewController: LaunchController())
-    window.rootViewController = StatusBarViewController(ToastViewController(navController))
-    window.backgroundColor = UIColor.white
-    window.makeKeyAndVisible()
-    self.window = window
-
-    DependencyInjection.Container.shared.register(
-      PushRouter.live(navigationController: navController)
-    )
-
+    DependencyRegistrator.registerDependencies()
+    setupCloudFilesManagers()
+    setupCrashReporting()
+    setupLogging()
+
+    window = UIWindow(frame: UIScreen.main.bounds)
+    window?.rootViewController = RootViewController(UINavigationController(rootViewController: LaunchController()))
+    window?.makeKeyAndVisible()
     return true
   }
 
@@ -172,21 +155,6 @@ public class AppDelegate: UIResponder, UIApplicationDelegate {
   }
 }
 
-func getUsernameFromInvitationDeepLink(_ url: URL) -> String? {
-  if let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
-     components.scheme == "https",
-     components.host == "elixxir.io",
-     components.path == "/connect",
-     let queryItem = components.queryItems?.first(where: { $0.name == "username" }),
-     let username = queryItem.value {
-    return username
-  }
-
-  return nil
-}
-
-// MARK: Notifications
-
 extension AppDelegate: UNUserNotificationCenterDelegate {
   public func userNotificationCenter(
     _ center: UNUserNotificationCenter,
@@ -194,7 +162,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
     withCompletionHandler completionHandler: @escaping () -> Void
   ) {
     let userInfo = response.notification.request.content.userInfo
-    pushHandler.handleAction(pushRouter, userInfo, completionHandler)
+    //pushHandler.handleAction(pushRouter, userInfo, completionHandler)
   }
 
   public func application(
@@ -212,3 +180,39 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
     pushHandler.registerToken(deviceToken)
   }
 }
+
+extension AppDelegate {
+  private func setupCrashReporting() {
+    crashReporter.configure()
+    crashReporter.setEnabled(isCrashReportingEnabled)
+  }
+
+  private func setupCloudFilesManagers() {
+    CloudFilesManager.all[.icloud] = .iCloud(fileName: "backup.xxm")
+    CloudFilesManager.all[.dropbox] = .dropbox(appKey: "ppx0de5f16p9aq2", path: "/backup/backup.xxm")
+    CloudFilesManager.all[.drive] = .drive(
+      apiKey: "AIzaSyCbI2yQ7pbuVSRvraqanjGcS9CDrjD7lNU",
+      clientId: "662236151640-herpu89qikpfs9m4kvbi9bs5fpdji5de.apps.googleusercontent.com",
+      fileName: "backup.xxm"
+    )
+  }
+
+  private func setupLogging() {
+    if recordingLogs {
+      XXLogger.start()
+    }
+  }
+}
+
+func getUsernameFromInvitationDeepLink(_ url: URL) -> String? {
+  if let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
+     components.scheme == "https",
+     components.host == "elixxir.io",
+     components.path == "/connect",
+     let queryItem = components.queryItems?.first(where: { $0.name == "username" }),
+     let username = queryItem.value {
+    return username
+  }
+
+  return nil
+}
diff --git a/Sources/App/DependencyRegistrator.swift b/Sources/App/DependencyRegistrator.swift
index 5fe201895d13401ece9994aab414f6ff5c0b7230..824b2ef6de0378d6cf41e14f566694469f6e9ca1 100644
--- a/Sources/App/DependencyRegistrator.swift
+++ b/Sources/App/DependencyRegistrator.swift
@@ -8,7 +8,6 @@ import MobileCoreServices
 // MARK: Isolated features
 
 import HUD
-import Theme
 import Bindings
 import XXLogger
 import Keychain
@@ -18,7 +17,6 @@ import Voxophone
 import Permissions
 import PushFeature
 import CrashService
-import ToastFeature
 import CrashReporting
 import NetworkMonitor
 import VersionChecking
@@ -44,11 +42,21 @@ import OnboardingFeature
 import ContactListFeature
 
 import XXClient
+import Navigation
 import KeychainAccess
+import Shared
 
 struct DependencyRegistrator {
   static private let container = DependencyInjection.Container.shared
 
+  static func registerDependencies() {
+    #if DEBUG
+    DependencyRegistrator.registerForMock()
+    #else
+    DependencyRegistrator.registerForLive()
+    #endif
+  }
+
   // MARK: MOCK
 
   static func registerForMock() {
@@ -103,9 +111,8 @@ struct DependencyRegistrator {
     // MARK: Isolated
 
     container.register(HUD())
-    container.register(ThemeController() as ThemeControlling)
     container.register(ToastController())
-    container.register(StatusBarController() as StatusBarStyleControlling)
+    container.register(StatusBarStylist())
 
     // MARK: Coordinators
 
diff --git a/Sources/ChatFeature/Controllers/GroupChatController.swift b/Sources/ChatFeature/Controllers/GroupChatController.swift
index 6080ba62c24a8096e3ec4d4ecaee1fbf20fcb89b..5bd1504ec4f4a91b30cc2303f0ebcfd097756dee 100644
--- a/Sources/ChatFeature/Controllers/GroupChatController.swift
+++ b/Sources/ChatFeature/Controllers/GroupChatController.swift
@@ -1,6 +1,5 @@
 import HUD
 import UIKit
-import Theme
 import Models
 import Shared
 import Combine
@@ -21,631 +20,631 @@ typealias OutgoingFailedGroupTextCell = CollectionCell<FlexibleSpace, StackMessa
 typealias OutgoingFailedGroupReplyCell = CollectionCell<FlexibleSpace, ReplyStackMessageView>
 
 public final class GroupChatController: UIViewController {
-    @Dependency private var hud: HUD
-    @Dependency private var database: Database
-    @Dependency private var coordinator: ChatCoordinating
-    @Dependency private var reportingStatus: ReportingStatus
-    @Dependency private var makeReportDrawer: MakeReportDrawer
-    @Dependency private var makeAppScreenshot: MakeAppScreenshot
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    private let members: MembersController
-    private var collectionView: UICollectionView!
-    lazy private var header = GroupHeaderView()
-    private let inputComponent: ChatInputView
-
-    private var animator: ManualAnimator?
-    private let viewModel: GroupChatViewModel
-    private let layoutDelegate = LayoutDelegate()
-    private var cancellables = Set<AnyCancellable>()
-    private let chatLayout = CollectionViewChatLayout()
-    private var sections = [ArraySection<ChatSection, Message>]()
-    private var currentInterfaceActions = SetActor<Set<InterfaceActions>, ReactionTypes>()
-
-    public override var canBecomeFirstResponder: Bool { true }
-    public override var inputAccessoryView: UIView? { inputComponent }
-
-    public init(_ info: GroupInfo) {
-        let viewModel = GroupChatViewModel(info)
-        self.viewModel = viewModel
-        self.members = .init(with: info.members)
-
-        self.inputComponent = ChatInputView(store: .init(
-            initialState: .init(canAddAttachments: false),
-            reducer: chatInputReducer,
-            environment: .init(
-                voxophone: try! DependencyInjection.Container.shared.resolve() as Voxophone,
-                sendAudio: { _ in },
-                didTapCamera: {},
-                didTapLibrary: {},
-                sendText: { viewModel.send($0) },
-                didTapAbortReply: { viewModel.abortReply() },
-                didTapMicrophone: { false }
-            )
-        ))
-
-        super.init(nibName: nil, bundle: nil)
-
-        let memberList = info.members.map {
-            Member(
-                title: ($0.nickname ?? $0.username) ?? "Fetching username...",
-                photo: $0.photo
-            )
-        }
-
-        header.setup(title: info.group.name, memberList: memberList)
+  @Dependency var hud: HUD
+  @Dependency var database: Database
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: ChatCoordinating
+  @Dependency var reportingStatus: ReportingStatus
+  @Dependency var makeReportDrawer: MakeReportDrawer
+  @Dependency var makeAppScreenshot: MakeAppScreenshot
+
+  private let members: MembersController
+  private var collectionView: UICollectionView!
+  lazy private var header = GroupHeaderView()
+  private let inputComponent: ChatInputView
+
+  private var animator: ManualAnimator?
+  private let viewModel: GroupChatViewModel
+  private let layoutDelegate = LayoutDelegate()
+  private var cancellables = Set<AnyCancellable>()
+  private let chatLayout = CollectionViewChatLayout()
+  private var sections = [ArraySection<ChatSection, Message>]()
+  private var currentInterfaceActions = SetActor<Set<InterfaceActions>, ReactionTypes>()
+
+  public override var canBecomeFirstResponder: Bool { true }
+  public override var inputAccessoryView: UIView? { inputComponent }
+
+  public init(_ info: GroupInfo) {
+    let viewModel = GroupChatViewModel(info)
+    self.viewModel = viewModel
+    self.members = .init(with: info.members)
+
+    self.inputComponent = ChatInputView(store: .init(
+      initialState: .init(canAddAttachments: false),
+      reducer: chatInputReducer,
+      environment: .init(
+        voxophone: try! DependencyInjection.Container.shared.resolve() as Voxophone,
+        sendAudio: { _ in },
+        didTapCamera: {},
+        didTapLibrary: {},
+        sendText: { viewModel.send($0) },
+        didTapAbortReply: { viewModel.abortReply() },
+        didTapMicrophone: { false }
+      )
+    ))
+
+    super.init(nibName: nil, bundle: nil)
+
+    let memberList = info.members.map {
+      Member(
+        title: ($0.nickname ?? $0.username) ?? "Fetching username...",
+        photo: $0.photo
+      )
     }
 
-    public required init?(coder: NSCoder) { nil }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar.customize(
-            backgroundColor: Asset.neutralWhite.color,
-            shadowColor: Asset.neutralDisabled.color
-        )
+    header.setup(title: info.group.name, memberList: memberList)
+  }
+
+  public required init?(coder: NSCoder) { nil }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar.customize(
+      backgroundColor: Asset.neutralWhite.color,
+      shadowColor: Asset.neutralDisabled.color
+    )
+  }
+
+  public override func viewDidAppear(_ animated: Bool) {
+    super.viewDidAppear(animated)
+    collectionView.collectionViewLayout.invalidateLayout()
+    becomeFirstResponder()
+  }
+
+  private var isFirstAppearance = true
+
+  public override func viewDidLayoutSubviews() {
+    super.viewDidLayoutSubviews()
+
+    if isFirstAppearance {
+      isFirstAppearance = false
+      let insets = UIEdgeInsets(
+        top: 0,
+        left: 0,
+        bottom: inputComponent.bounds.height - view.safeAreaInsets.bottom,
+        right: 0
+      )
+      collectionView.contentInset = insets
+      collectionView.scrollIndicatorInsets = insets
     }
-
-    public override func viewDidAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-        collectionView.collectionViewLayout.invalidateLayout()
-        becomeFirstResponder()
+  }
+
+  public override func viewWillDisappear(_ animated: Bool) {
+    super.viewWillDisappear(animated)
+    viewModel.readAll()
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+
+    setupNavigationBar()
+    setupCollectionView()
+    setupInputController()
+    setupBindings()
+
+    KeyboardListener.shared.add(delegate: self)
+  }
+
+  private func setupNavigationBar() {
+    let more = UIButton()
+    more.setImage(Asset.chatMore.image, for: .normal)
+    more.addTarget(self, action: #selector(didTapDots), for: .touchUpInside)
+
+    navigationItem.titleView = header
+    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: more)
+  }
+
+  private func setupCollectionView() {
+    chatLayout.configure(layoutDelegate)
+    collectionView = .init(on: view, with: chatLayout)
+    collectionView.register(IncomingGroupTextCell.self)
+    collectionView.register(OutgoingGroupTextCell.self)
+    collectionView.register(IncomingGroupReplyCell.self)
+    collectionView.register(OutgoingGroupReplyCell.self)
+    collectionView.register(OutgoingFailedGroupTextCell.self)
+    collectionView.register(OutgoingFailedGroupReplyCell.self)
+    collectionView.registerSectionHeader(SectionHeaderView.self)
+    collectionView.dataSource = self
+    collectionView.delegate = self
+  }
+
+  private func setupInputController() {
+    inputComponent.setMaxHeight { [weak self] in
+      guard let self = self else { return 150 }
+
+      let maxHeight = self.collectionView.frame.height
+      - self.collectionView.adjustedContentInset.top
+      - self.collectionView.adjustedContentInset.bottom
+      + self.inputComponent.bounds.height
+
+      return maxHeight * 0.9
     }
 
-    private var isFirstAppearance = true
-
-    public override func viewDidLayoutSubviews() {
-        super.viewDidLayoutSubviews()
-
-        if isFirstAppearance {
-            isFirstAppearance = false
-            let insets = UIEdgeInsets(
-                top: 0,
-                left: 0,
-                bottom: inputComponent.bounds.height - view.safeAreaInsets.bottom,
-                right: 0
-            )
-            collectionView.contentInset = insets
-            collectionView.scrollIndicatorInsets = insets
+    viewModel.replyPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] senderTitle, messageText in
+        inputComponent.setupReply(message: messageText, sender: senderTitle)
+      }
+      .store(in: &cancellables)
+  }
+
+  private func setupBindings() {
+    viewModel.routesPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        switch $0 {
+        case .waitingRound:
+          coordinator.toDrawer(makeWaitingRoundDrawer(), from: self)
+        case .webview(let urlString):
+          coordinator.toWebview(with: urlString, from: self)
+        }
+      }.store(in: &cancellables)
+
+    viewModel.hudPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [hud] in hud.update(with: $0) }
+      .store(in: &cancellables)
+
+    viewModel.reportPopupPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] contact in
+        presentReportDrawer(contact)
+      }.store(in: &cancellables)
+
+    viewModel.messages
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] sections in
+        func process() {
+          let changeSet = StagedChangeset(source: self.sections, target: sections).flattenIfPossible()
+          collectionView.reload(
+            using: changeSet,
+            interrupt: { changeSet in
+              guard !self.sections.isEmpty else { return true }
+              return false
+            }, onInterruptedReload: {
+              guard let lastSection = self.sections.last else { return }
+              let positionSnapshot = ChatLayoutPositionSnapshot(
+                indexPath: IndexPath(
+                  item: lastSection.elements.count - 1,
+                  section: self.sections.count - 1
+                ),
+                kind: .cell,
+                edge: .bottom
+              )
+
+              self.collectionView.reloadData()
+              self.chatLayout.restoreContentOffset(with: positionSnapshot)
+            },
+            completion: nil,
+            setData: { self.sections = $0 }
+          )
         }
-    }
-
-    public override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-        viewModel.readAll()
-    }
 
-    public override func viewDidLoad() {
-        super.viewDidLoad()
+        guard currentInterfaceActions.options.isEmpty else {
+          let reaction = SetActor<Set<InterfaceActions>, ReactionTypes>.Reaction(
+            type: .delayedUpdate,
+            action: .onEmpty,
+            executionType: .once,
+            actionBlock: { [weak self] in
+              guard let _ = self else { return }
+              process()
+            }
+          )
 
-        setupNavigationBar()
-        setupCollectionView()
-        setupInputController()
-        setupBindings()
+          currentInterfaceActions.add(reaction: reaction)
+          return
+        }
 
-        KeyboardListener.shared.add(delegate: self)
+        process()
+      }
+      .store(in: &cancellables)
+  }
+
+  @objc private func didTapDots() {
+    coordinator.toMembersList(members, from: self)
+  }
+
+  private func presentReportDrawer(_ contact: Contact) {
+    var config = MakeReportDrawer.Config()
+    config.onReport = { [weak self] in
+      guard let self = self else { return }
+      let screenshot = try! self.makeAppScreenshot()
+      self.viewModel.report(contact: contact, screenshot: screenshot) {
+        self.collectionView.reloadData()
+      }
     }
-
-    private func setupNavigationBar() {
-        let more = UIButton()
-        more.setImage(Asset.chatMore.image, for: .normal)
-        more.addTarget(self, action: #selector(didTapDots), for: .touchUpInside)
-
-        navigationItem.titleView = header
-        navigationItem.rightBarButtonItem = UIBarButtonItem(customView: more)
+    let drawer = makeReportDrawer(config)
+    coordinator.toDrawer(drawer, from: self)
+  }
+
+  private func makeWaitingRoundDrawer() -> UIViewController {
+    let text = DrawerText(
+      font: Fonts.Mulish.semiBold.font(size: 14.0),
+      text: Localized.Chat.RoundDrawer.title,
+      color: Asset.neutralWeak.color,
+      lineHeightMultiple: 1.35,
+      spacingAfter: 25
+    )
+
+    let button = DrawerCapsuleButton(model: .init(
+      title: Localized.Chat.RoundDrawer.action,
+      style: .brandColored
+    ))
+
+    let drawer = DrawerController(with: [text, button])
+
+    button.action
+      .receive(on: DispatchQueue.main)
+      .sink { [weak drawer] in
+        drawer?.dismiss(animated: true)
+      }.store(in: &drawer.cancellables)
+
+    return drawer
+  }
+
+  func scrollToBottom(completion: (() -> Void)? = nil) {
+    let contentOffsetAtBottom = CGPoint(
+      x: collectionView.contentOffset.x,
+      y: chatLayout.collectionViewContentSize.height
+      - collectionView.frame.height + collectionView.adjustedContentInset.bottom
+    )
+
+    guard contentOffsetAtBottom.y > collectionView.contentOffset.y else { completion?(); return }
+
+    let initialOffset = collectionView.contentOffset.y
+    let delta = contentOffsetAtBottom.y - initialOffset
+
+    if abs(delta) > chatLayout.visibleBounds.height {
+      animator = ManualAnimator()
+      animator?.animate(duration: TimeInterval(0.25), curve: .easeInOut) { [weak self] percentage in
+        guard let self = self else { return }
+
+        self.collectionView.contentOffset = CGPoint(x: self.collectionView.contentOffset.x, y: initialOffset + (delta * percentage))
+        if percentage == 1.0 {
+          self.animator = nil
+          let positionSnapshot = ChatLayoutPositionSnapshot(indexPath: IndexPath(item: 0, section: 0), kind: .footer, edge: .bottom)
+          self.chatLayout.restoreContentOffset(with: positionSnapshot)
+          self.currentInterfaceActions.options.remove(.scrollingToBottom)
+          completion?()
+        }
+      }
+    } else {
+      currentInterfaceActions.options.insert(.scrollingToBottom)
+      UIView.animate(withDuration: 0.25, animations: {
+        self.collectionView.setContentOffset(contentOffsetAtBottom, animated: true)
+      }, completion: { [weak self] _ in
+        self?.currentInterfaceActions.options.remove(.scrollingToBottom)
+        completion?()
+      })
     }
+  }
+}
 
-    private func setupCollectionView() {
-        chatLayout.configure(layoutDelegate)
-        collectionView = .init(on: view, with: chatLayout)
-        collectionView.register(IncomingGroupTextCell.self)
-        collectionView.register(OutgoingGroupTextCell.self)
-        collectionView.register(IncomingGroupReplyCell.self)
-        collectionView.register(OutgoingGroupReplyCell.self)
-        collectionView.register(OutgoingFailedGroupTextCell.self)
-        collectionView.register(OutgoingFailedGroupReplyCell.self)
-        collectionView.registerSectionHeader(SectionHeaderView.self)
-        collectionView.dataSource = self
-        collectionView.delegate = self
+extension GroupChatController: UICollectionViewDataSource {
+  public func numberOfSections(in collectionView: UICollectionView) -> Int {
+    sections.count
+  }
+
+  public func collectionView(_ collectionView: UICollectionView,
+                             viewForSupplementaryElementOfKind kind: String,
+                             at indexPath: IndexPath) -> UICollectionReusableView {
+    let sectionHeader: SectionHeaderView = collectionView.dequeueSupplementaryView(forIndexPath: indexPath)
+    sectionHeader.title.text = sections[indexPath.section].model.date.asDayOfMonth()
+    return sectionHeader
+  }
+
+  public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+    sections[section].elements.count
+  }
+
+  public func collectionView(
+    _ collectionView: UICollectionView,
+    cellForItemAt indexPath: IndexPath
+  ) -> UICollectionViewCell {
+
+    var item = sections[indexPath.section].elements[indexPath.item]
+    let canReply: () -> Bool = {
+      (item.status == .sent || item.status == .received) && item.networkId != nil
     }
 
-    private func setupInputController() {
-        inputComponent.setMaxHeight { [weak self] in
-            guard let self = self else { return 150 }
-
-            let maxHeight = self.collectionView.frame.height
-            - self.collectionView.adjustedContentInset.top
-            - self.collectionView.adjustedContentInset.bottom
-            + self.inputComponent.bounds.height
-
-            return maxHeight * 0.9
-        }
-
-        viewModel.replyPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] senderTitle, messageText in
-                inputComponent.setupReply(message: messageText, sender: senderTitle)
-            }
-            .store(in: &cancellables)
+    let performReply: () -> Void = { [weak self] in
+      self?.viewModel.didRequestReply(item)
     }
 
-    private func setupBindings() {
-        viewModel.routesPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                switch $0 {
-                case .waitingRound:
-                    coordinator.toDrawer(makeWaitingRoundDrawer(), from: self)
-                case .webview(let urlString):
-                    coordinator.toWebview(with: urlString, from: self)
-                }
-            }.store(in: &cancellables)
-
-        viewModel.hudPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [hud] in hud.update(with: $0) }
-            .store(in: &cancellables)
-
-        viewModel.reportPopupPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] contact in
-                presentReportDrawer(contact)
-            }.store(in: &cancellables)
-
-        viewModel.messages
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] sections in
-                func process() {
-                    let changeSet = StagedChangeset(source: self.sections, target: sections).flattenIfPossible()
-                    collectionView.reload(
-                        using: changeSet,
-                        interrupt: { changeSet in
-                            guard !self.sections.isEmpty else { return true }
-                            return false
-                        }, onInterruptedReload: {
-                            guard let lastSection = self.sections.last else { return }
-                            let positionSnapshot = ChatLayoutPositionSnapshot(
-                                indexPath: IndexPath(
-                                    item: lastSection.elements.count - 1,
-                                    section: self.sections.count - 1
-                                ),
-                                kind: .cell,
-                                edge: .bottom
-                            )
-
-                            self.collectionView.reloadData()
-                            self.chatLayout.restoreContentOffset(with: positionSnapshot)
-                        },
-                        completion: nil,
-                        setData: { self.sections = $0 }
-                    )
-                }
-
-                guard currentInterfaceActions.options.isEmpty else {
-                    let reaction = SetActor<Set<InterfaceActions>, ReactionTypes>.Reaction(
-                        type: .delayedUpdate,
-                        action: .onEmpty,
-                        executionType: .once,
-                        actionBlock: { [weak self] in
-                            guard let _ = self else { return }
-                            process()
-                        }
-                    )
-
-                    currentInterfaceActions.add(reaction: reaction)
-                    return
-                }
-
-                process()
-            }
-            .store(in: &cancellables)
-    }
+    let name: (Data) -> String = viewModel.getName(from:)
+    let showRound: (String?) -> Void = viewModel.showRoundFrom(_:)
+    let replyContent: (Data) -> (String, String) = viewModel.getReplyContent(for:)
 
-    @objc private func didTapDots() {
-        coordinator.toMembersList(members, from: self)
-    }
+    var isSenderBanned = false
 
-    private func presentReportDrawer(_ contact: Contact) {
-        var config = MakeReportDrawer.Config()
-        config.onReport = { [weak self] in
-            guard let self = self else { return }
-            let screenshot = try! self.makeAppScreenshot()
-            self.viewModel.report(contact: contact, screenshot: screenshot) {
-                self.collectionView.reloadData()
-            }
-        }
-        let drawer = makeReportDrawer(config)
-        coordinator.toDrawer(drawer, from: self)
+    if let sender = try? database.fetchContacts(.init(id: [item.senderId])).first {
+      isSenderBanned = sender.isBanned
     }
 
-    private func makeWaitingRoundDrawer() -> UIViewController {
-        let text = DrawerText(
-            font: Fonts.Mulish.semiBold.font(size: 14.0),
-            text: Localized.Chat.RoundDrawer.title,
-            color: Asset.neutralWeak.color,
-            lineHeightMultiple: 1.35,
-            spacingAfter: 25
+    if item.status == .received {
+      guard isSenderBanned == false else {
+        item.text = "This user has been banned"
+
+        let cell: IncomingGroupTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+        Bubbler.buildGroup(
+          bubble: cell.leftView,
+          with: item,
+          with: "Banned user"
         )
 
-        let button = DrawerCapsuleButton(model: .init(
-            title: Localized.Chat.RoundDrawer.action,
-            style: .brandColored
-        ))
+        cell.canReply = false
+        cell.performReply = {}
+        cell.leftView.didTapShowRound = {}
 
-        let drawer = DrawerController(with: [text, button])
+        return cell
+      }
 
-        button.action
-            .receive(on: DispatchQueue.main)
-            .sink { [weak drawer] in
-                drawer?.dismiss(animated: true)
-            }.store(in: &drawer.cancellables)
+      if let replyMessageId = item.replyMessageId {
+        let cell: IncomingGroupReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
 
-        return drawer
-    }
+        Bubbler.buildReplyGroup(
+          bubble: cell.leftView,
+          with: item,
+          reply: replyContent(replyMessageId),
+          sender: name(item.senderId)
+        )
 
-    func scrollToBottom(completion: (() -> Void)? = nil) {
-        let contentOffsetAtBottom = CGPoint(
-            x: collectionView.contentOffset.x,
-            y: chatLayout.collectionViewContentSize.height
-            - collectionView.frame.height + collectionView.adjustedContentInset.bottom
+        cell.canReply = canReply()
+        cell.performReply = performReply
+        cell.leftView.didTapShowRound = { showRound(item.roundURL) }
+
+        return cell
+      } else {
+        let cell: IncomingGroupTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+        Bubbler.buildGroup(
+          bubble: cell.leftView,
+          with: item,
+          with: name(item.senderId)
         )
 
-        guard contentOffsetAtBottom.y > collectionView.contentOffset.y else { completion?(); return }
+        cell.canReply = canReply()
+        cell.performReply = performReply
+        cell.leftView.didTapShowRound = { showRound(item.roundURL) }
+
+        return cell
+      }
+    } else if item.status == .sendingFailed {
+      if let replyMessageId = item.replyMessageId {
+        let cell: OutgoingFailedGroupReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+
+        Bubbler.buildReplyGroup(
+          bubble: cell.rightView,
+          with: item,
+          reply: replyContent(replyMessageId),
+          sender: name(item.senderId)
+        )
 
-        let initialOffset = collectionView.contentOffset.y
-        let delta = contentOffsetAtBottom.y - initialOffset
+        cell.canReply = canReply()
+        cell.performReply = performReply
 
-        if abs(delta) > chatLayout.visibleBounds.height {
-            animator = ManualAnimator()
-            animator?.animate(duration: TimeInterval(0.25), curve: .easeInOut) { [weak self] percentage in
-                guard let self = self else { return }
+        return cell
+      } else {
+        let cell: OutgoingFailedGroupTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
 
-                self.collectionView.contentOffset = CGPoint(x: self.collectionView.contentOffset.x, y: initialOffset + (delta * percentage))
-                if percentage == 1.0 {
-                    self.animator = nil
-                    let positionSnapshot = ChatLayoutPositionSnapshot(indexPath: IndexPath(item: 0, section: 0), kind: .footer, edge: .bottom)
-                    self.chatLayout.restoreContentOffset(with: positionSnapshot)
-                    self.currentInterfaceActions.options.remove(.scrollingToBottom)
-                    completion?()
-                }
-            }
-        } else {
-            currentInterfaceActions.options.insert(.scrollingToBottom)
-            UIView.animate(withDuration: 0.25, animations: {
-                self.collectionView.setContentOffset(contentOffsetAtBottom, animated: true)
-            }, completion: { [weak self] _ in
-                self?.currentInterfaceActions.options.remove(.scrollingToBottom)
-                completion?()
-            })
-        }
-    }
-}
+        Bubbler.buildGroup(
+          bubble: cell.rightView,
+          with: item,
+          with: name(item.senderId)
+        )
 
-extension GroupChatController: UICollectionViewDataSource {
-    public func numberOfSections(in collectionView: UICollectionView) -> Int {
-        sections.count
-    }
+        cell.canReply = canReply()
+        cell.performReply = performReply
 
-    public func collectionView(_ collectionView: UICollectionView,
-                               viewForSupplementaryElementOfKind kind: String,
-                               at indexPath: IndexPath) -> UICollectionReusableView {
-        let sectionHeader: SectionHeaderView = collectionView.dequeueSupplementaryView(forIndexPath: indexPath)
-        sectionHeader.title.text = sections[indexPath.section].model.date.asDayOfMonth()
-        return sectionHeader
-    }
+        return cell
+      }
+    } else if item.status == .sendingTimedOut {
+      if let replyMessageId = item.replyMessageId {
+        let cell: OutgoingFailedGroupReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
 
-    public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        sections[section].elements.count
-    }
+        Bubbler.buildReplyGroup(
+          bubble: cell.rightView,
+          with: item,
+          reply: replyContent(replyMessageId),
+          sender: name(item.senderId)
+        )
 
-    public func collectionView(
-        _ collectionView: UICollectionView,
-        cellForItemAt indexPath: IndexPath
-    ) -> UICollectionViewCell {
+        cell.canReply = false
+        cell.performReply = performReply
 
-        var item = sections[indexPath.section].elements[indexPath.item]
-        let canReply: () -> Bool = {
-            (item.status == .sent || item.status == .received) && item.networkId != nil
-        }
+        return cell
+      } else {
+        let cell: OutgoingFailedGroupTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
 
-        let performReply: () -> Void = { [weak self] in
-            self?.viewModel.didRequestReply(item)
-        }
+        Bubbler.buildGroup(
+          bubble: cell.rightView,
+          with: item,
+          with: name(item.senderId)
+        )
 
-        let name: (Data) -> String = viewModel.getName(from:)
-        let showRound: (String?) -> Void = viewModel.showRoundFrom(_:)
-        let replyContent: (Data) -> (String, String) = viewModel.getReplyContent(for:)
+        cell.canReply = false
+        cell.performReply = performReply
 
-        var isSenderBanned = false
+        return cell
+      }
+    } else {
+      if let replyMessageId = item.replyMessageId {
+        let cell: OutgoingGroupReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
 
-        if let sender = try? database.fetchContacts(.init(id: [item.senderId])).first {
-            isSenderBanned = sender.isBanned
-        }
+        Bubbler.buildReplyGroup(
+          bubble: cell.rightView,
+          with: item,
+          reply: replyContent(replyMessageId),
+          sender: name(item.senderId)
+        )
 
-        if item.status == .received {
-            guard isSenderBanned == false else {
-                item.text = "This user has been banned"
+        cell.canReply = canReply()
+        cell.performReply = performReply
+        cell.rightView.didTapShowRound = { showRound(item.roundURL) }
 
-                let cell: IncomingGroupTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-                Bubbler.buildGroup(
-                    bubble: cell.leftView,
-                    with: item,
-                    with: "Banned user"
-                )
+        return cell
+      } else {
+        let cell: OutgoingGroupTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
 
-                cell.canReply = false
-                cell.performReply = {}
-                cell.leftView.didTapShowRound = {}
+        Bubbler.buildGroup(
+          bubble: cell.rightView,
+          with: item,
+          with: name(item.senderId)
+        )
 
-                return cell
-            }
+        cell.canReply = canReply()
+        cell.performReply = performReply
+        cell.rightView.didTapShowRound = { showRound(item.roundURL) }
 
-            if let replyMessageId = item.replyMessageId {
-                let cell: IncomingGroupReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-                Bubbler.buildReplyGroup(
-                    bubble: cell.leftView,
-                    with: item,
-                    reply: replyContent(replyMessageId),
-                    sender: name(item.senderId)
-                )
-
-                cell.canReply = canReply()
-                cell.performReply = performReply
-                cell.leftView.didTapShowRound = { showRound(item.roundURL) }
-
-                return cell
-            } else {
-                let cell: IncomingGroupTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-                Bubbler.buildGroup(
-                    bubble: cell.leftView,
-                    with: item,
-                    with: name(item.senderId)
-                )
-
-                cell.canReply = canReply()
-                cell.performReply = performReply
-                cell.leftView.didTapShowRound = { showRound(item.roundURL) }
-
-                return cell
-            }
-        } else if item.status == .sendingFailed {
-            if let replyMessageId = item.replyMessageId {
-                let cell: OutgoingFailedGroupReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-                Bubbler.buildReplyGroup(
-                    bubble: cell.rightView,
-                    with: item,
-                    reply: replyContent(replyMessageId),
-                    sender: name(item.senderId)
-                )
-
-                cell.canReply = canReply()
-                cell.performReply = performReply
-
-                return cell
-            } else {
-                let cell: OutgoingFailedGroupTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-                Bubbler.buildGroup(
-                    bubble: cell.rightView,
-                    with: item,
-                    with: name(item.senderId)
-                )
-
-                cell.canReply = canReply()
-                cell.performReply = performReply
-
-                return cell
-            }
-        } else if item.status == .sendingTimedOut {
-          if let replyMessageId = item.replyMessageId {
-            let cell: OutgoingFailedGroupReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-            Bubbler.buildReplyGroup(
-              bubble: cell.rightView,
-              with: item,
-              reply: replyContent(replyMessageId),
-              sender: name(item.senderId)
-            )
-
-            cell.canReply = false
-            cell.performReply = performReply
-
-            return cell
-          } else {
-            let cell: OutgoingFailedGroupTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-            Bubbler.buildGroup(
-              bubble: cell.rightView,
-              with: item,
-              with: name(item.senderId)
-            )
-
-            cell.canReply = false
-            cell.performReply = performReply
-
-            return cell
-          }
-        } else {
-            if let replyMessageId = item.replyMessageId {
-                let cell: OutgoingGroupReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-                Bubbler.buildReplyGroup(
-                    bubble: cell.rightView,
-                    with: item,
-                    reply: replyContent(replyMessageId),
-                    sender: name(item.senderId)
-                )
-
-                cell.canReply = canReply()
-                cell.performReply = performReply
-                cell.rightView.didTapShowRound = { showRound(item.roundURL) }
-
-                return cell
-            } else {
-                let cell: OutgoingGroupTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-                Bubbler.buildGroup(
-                    bubble: cell.rightView,
-                    with: item,
-                    with: name(item.senderId)
-                )
-
-                cell.canReply = canReply()
-                cell.performReply = performReply
-                cell.rightView.didTapShowRound = { showRound(item.roundURL) }
-
-                return cell
-            }
-        }
+        return cell
+      }
     }
+  }
 }
 
 extension GroupChatController: KeyboardListenerDelegate {
-    fileprivate var isUserInitiatedScrolling: Bool {
-        return collectionView.isDragging || collectionView.isDecelerating
+  fileprivate var isUserInitiatedScrolling: Bool {
+    return collectionView.isDragging || collectionView.isDecelerating
+  }
+
+  func keyboardWillChangeFrame(info: KeyboardInfo) {
+    let keyWindow = UIApplication.shared.windows.filter { $0.isKeyWindow }.first
+
+    guard !currentInterfaceActions.options.contains(.changingFrameSize),
+          collectionView.contentInsetAdjustmentBehavior != .never,
+          let keyboardFrame = keyWindow?.convert(info.frameEnd, to: view),
+          collectionView.convert(collectionView.bounds, to: keyWindow).maxY > info.frameEnd.minY else {
+      return
     }
-
-    func keyboardWillChangeFrame(info: KeyboardInfo) {
-        let keyWindow = UIApplication.shared.windows.filter { $0.isKeyWindow }.first
-
-        guard !currentInterfaceActions.options.contains(.changingFrameSize),
-              collectionView.contentInsetAdjustmentBehavior != .never,
-              let keyboardFrame = keyWindow?.convert(info.frameEnd, to: view),
-              collectionView.convert(collectionView.bounds, to: keyWindow).maxY > info.frameEnd.minY else {
-                  return
-              }
-        currentInterfaceActions.options.insert(.changingKeyboardFrame)
-        let newBottomInset = collectionView.frame.minY + collectionView.frame.size.height - keyboardFrame.minY - collectionView.safeAreaInsets.bottom
-        if newBottomInset > 0,
-           collectionView.contentInset.bottom != newBottomInset {
-            let positionSnapshot = chatLayout.getContentOffsetSnapshot(from: .bottom)
-
-            currentInterfaceActions.options.insert(.changingContentInsets)
-            UIView.animate(withDuration: info.animationDuration, animations: {
-                self.collectionView.performBatchUpdates({
-                    self.collectionView.contentInset.bottom = newBottomInset
-                    self.collectionView.verticalScrollIndicatorInsets.bottom = newBottomInset
-                }, completion: nil)
-
-                if let positionSnapshot = positionSnapshot, !self.isUserInitiatedScrolling {
-                    self.chatLayout.restoreContentOffset(with: positionSnapshot)
-                }
-            }, completion: { _ in
-                self.currentInterfaceActions.options.remove(.changingContentInsets)
-            })
+    currentInterfaceActions.options.insert(.changingKeyboardFrame)
+    let newBottomInset = collectionView.frame.minY + collectionView.frame.size.height - keyboardFrame.minY - collectionView.safeAreaInsets.bottom
+    if newBottomInset > 0,
+       collectionView.contentInset.bottom != newBottomInset {
+      let positionSnapshot = chatLayout.getContentOffsetSnapshot(from: .bottom)
+
+      currentInterfaceActions.options.insert(.changingContentInsets)
+      UIView.animate(withDuration: info.animationDuration, animations: {
+        self.collectionView.performBatchUpdates({
+          self.collectionView.contentInset.bottom = newBottomInset
+          self.collectionView.verticalScrollIndicatorInsets.bottom = newBottomInset
+        }, completion: nil)
+
+        if let positionSnapshot = positionSnapshot, !self.isUserInitiatedScrolling {
+          self.chatLayout.restoreContentOffset(with: positionSnapshot)
         }
+      }, completion: { _ in
+        self.currentInterfaceActions.options.remove(.changingContentInsets)
+      })
     }
+  }
 
-    func keyboardDidChangeFrame(info: KeyboardInfo) {
-        guard currentInterfaceActions.options.contains(.changingKeyboardFrame) else { return }
-        currentInterfaceActions.options.remove(.changingKeyboardFrame)
-    }
+  func keyboardDidChangeFrame(info: KeyboardInfo) {
+    guard currentInterfaceActions.options.contains(.changingKeyboardFrame) else { return }
+    currentInterfaceActions.options.remove(.changingKeyboardFrame)
+  }
 }
 
 extension GroupChatController: UICollectionViewDelegate {
-    private func makeTargetedPreview(for configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
-        guard let identifier = configuration.identifier as? String,
-              let first = identifier.components(separatedBy: "|").first,
-              let last = identifier.components(separatedBy: "|").last,
-              let item = Int(first), let section = Int(last),
-              let cell = collectionView.cellForItem(at: IndexPath(item: item, section: section)) else {
-                  return nil
-              }
-
-        let parameters = UIPreviewParameters()
-        parameters.backgroundColor = .clear
-
-        if sections[section].elements[item].status == .received {
-            var leftView: UIView!
-
-            if let cell = cell as? IncomingGroupReplyCell {
-                leftView = cell.leftView
-            } else if let cell = cell as? IncomingGroupTextCell {
-                leftView = cell.leftView
-            }
+  private func makeTargetedPreview(for configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
+    guard let identifier = configuration.identifier as? String,
+          let first = identifier.components(separatedBy: "|").first,
+          let last = identifier.components(separatedBy: "|").last,
+          let item = Int(first), let section = Int(last),
+          let cell = collectionView.cellForItem(at: IndexPath(item: item, section: section)) else {
+      return nil
+    }
 
-            parameters.visiblePath = UIBezierPath(roundedRect: leftView.bounds, cornerRadius: 13)
-            return UITargetedPreview(view: leftView, parameters: parameters)
-        }
+    let parameters = UIPreviewParameters()
+    parameters.backgroundColor = .clear
 
-        var rightView: UIView!
+    if sections[section].elements[item].status == .received {
+      var leftView: UIView!
 
-        if let cell = cell as? OutgoingGroupTextCell {
-            rightView = cell.rightView
-        } else if let cell = cell as? OutgoingGroupReplyCell {
-            rightView = cell.rightView
-        }
+      if let cell = cell as? IncomingGroupReplyCell {
+        leftView = cell.leftView
+      } else if let cell = cell as? IncomingGroupTextCell {
+        leftView = cell.leftView
+      }
 
-        parameters.visiblePath = UIBezierPath(roundedRect: rightView.bounds, cornerRadius: 13)
-        return UITargetedPreview(view: rightView, parameters: parameters)
+      parameters.visiblePath = UIBezierPath(roundedRect: leftView.bounds, cornerRadius: 13)
+      return UITargetedPreview(view: leftView, parameters: parameters)
     }
 
-    public func collectionView(
-        _ collectionView: UICollectionView,
-        previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration
-    ) -> UITargetedPreview? {
-        makeTargetedPreview(for: configuration)
-    }
+    var rightView: UIView!
 
-    public func collectionView(
-        _ collectionView: UICollectionView,
-        previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration
-    ) -> UITargetedPreview? {
-        makeTargetedPreview(for: configuration)
+    if let cell = cell as? OutgoingGroupTextCell {
+      rightView = cell.rightView
+    } else if let cell = cell as? OutgoingGroupReplyCell {
+      rightView = cell.rightView
     }
 
-    public func collectionView(
-        _ collectionView: UICollectionView,
-        contextMenuConfigurationForItemAt indexPath: IndexPath,
-        point: CGPoint
-    ) -> UIContextMenuConfiguration? {
-        UIContextMenuConfiguration(
-            identifier: "\(indexPath.item)|\(indexPath.section)" as NSCopying,
-            previewProvider: nil
-        ) { [weak self] suggestedActions in
-
-            guard let self = self else { return nil }
-
-            let item = self.sections[indexPath.section].elements[indexPath.item]
-
-            let copy = UIAction(title: Localized.Chat.BubbleMenu.copy, state: .off) { _ in
-                UIPasteboard.general.string = item.text
-            }
-
-            let reply = UIAction(title: Localized.Chat.BubbleMenu.reply, state: .off) { [weak self] _ in
-                self?.viewModel.didRequestReply(item)
-            }
-
-            let delete = UIAction(title: Localized.Chat.BubbleMenu.delete, state: .off) { [weak self] _ in
-                self?.viewModel.didRequestDelete([item])
-            }
-
-            let report = UIAction(title: Localized.Chat.BubbleMenu.report, state: .off) { [weak self] _ in
-                self?.viewModel.didRequestReport(item)
-            }
-
-            let retry = UIAction(title: Localized.Chat.BubbleMenu.retry, state: .off) { [weak self] _ in
-                self?.viewModel.retry(item)
-            }
-
-            var children = [UIAction]()
-
-            if item.status == .sendingFailed {
-                children = [copy, retry, delete]
-            } else if item.status == .sending {
-                children = [copy]
-            } else {
-                children = [copy, reply, delete]
-
-                if self.reportingStatus.isEnabled() {
-                    children.append(report)
-                }
-            }
-
-            return UIMenu(title: "", children: children)
+    parameters.visiblePath = UIBezierPath(roundedRect: rightView.bounds, cornerRadius: 13)
+    return UITargetedPreview(view: rightView, parameters: parameters)
+  }
+
+  public func collectionView(
+    _ collectionView: UICollectionView,
+    previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration
+  ) -> UITargetedPreview? {
+    makeTargetedPreview(for: configuration)
+  }
+
+  public func collectionView(
+    _ collectionView: UICollectionView,
+    previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration
+  ) -> UITargetedPreview? {
+    makeTargetedPreview(for: configuration)
+  }
+
+  public func collectionView(
+    _ collectionView: UICollectionView,
+    contextMenuConfigurationForItemAt indexPath: IndexPath,
+    point: CGPoint
+  ) -> UIContextMenuConfiguration? {
+    UIContextMenuConfiguration(
+      identifier: "\(indexPath.item)|\(indexPath.section)" as NSCopying,
+      previewProvider: nil
+    ) { [weak self] suggestedActions in
+
+      guard let self = self else { return nil }
+
+      let item = self.sections[indexPath.section].elements[indexPath.item]
+
+      let copy = UIAction(title: Localized.Chat.BubbleMenu.copy, state: .off) { _ in
+        UIPasteboard.general.string = item.text
+      }
+
+      let reply = UIAction(title: Localized.Chat.BubbleMenu.reply, state: .off) { [weak self] _ in
+        self?.viewModel.didRequestReply(item)
+      }
+
+      let delete = UIAction(title: Localized.Chat.BubbleMenu.delete, state: .off) { [weak self] _ in
+        self?.viewModel.didRequestDelete([item])
+      }
+
+      let report = UIAction(title: Localized.Chat.BubbleMenu.report, state: .off) { [weak self] _ in
+        self?.viewModel.didRequestReport(item)
+      }
+
+      let retry = UIAction(title: Localized.Chat.BubbleMenu.retry, state: .off) { [weak self] _ in
+        self?.viewModel.retry(item)
+      }
+
+      var children = [UIAction]()
+
+      if item.status == .sendingFailed {
+        children = [copy, retry, delete]
+      } else if item.status == .sending {
+        children = [copy]
+      } else {
+        children = [copy, reply, delete]
+
+        if self.reportingStatus.isEnabled() {
+          children.append(report)
         }
+      }
+
+      return UIMenu(title: "", children: children)
     }
+  }
 }
diff --git a/Sources/ChatFeature/Controllers/SingleChatController.swift b/Sources/ChatFeature/Controllers/SingleChatController.swift
index 970539b33f9dc0ebf25c2fa1bad10ec97a6c20e4..5ad2e83d43be534ca156dcf58020818ef222ebf1 100644
--- a/Sources/ChatFeature/Controllers/SingleChatController.swift
+++ b/Sources/ChatFeature/Controllers/SingleChatController.swift
@@ -1,6 +1,5 @@
 import HUD
 import UIKit
-import Theme
 import Models
 import Shared
 import Combine
@@ -17,691 +16,691 @@ import DependencyInjection
 import ScrollViewController
 
 extension FlexibleSpace: CollectionCellContent {
-    func prepareForReuse() {}
+  func prepareForReuse() {}
 }
 
 extension Message: Differentiable {
-    public var differenceIdentifier: Int64 { id! }
+  public var differenceIdentifier: Int64 { id! }
 }
 
 public final class SingleChatController: UIViewController {
-    @Dependency private var hud: HUD
-    @Dependency private var logger: XXLogger
-    @Dependency private var voxophone: Voxophone
-    @Dependency private var coordinator: ChatCoordinating
-    @Dependency private var reportingStatus: ReportingStatus
-    @Dependency private var makeReportDrawer: MakeReportDrawer
-    @Dependency private var makeAppScreenshot: MakeAppScreenshot
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    lazy private var infoView = UIControl()
-    lazy private var nameLabel = UILabel()
-    lazy private var avatarView = AvatarView()
-
-    lazy private var moreButton = UIButton()
-    lazy private var screenView = ChatView()
-    lazy private var sheet = SheetController()
-
-    private let inputComponent: ChatInputView
-    private var collectionView: UICollectionView!
-
-    private var animator: ManualAnimator?
-    private let viewModel: SingleChatViewModel
-    private let layoutDelegate = LayoutDelegate()
-    private var cancellables = Set<AnyCancellable>()
-    private let chatLayout = CollectionViewChatLayout()
-    private var sections = [ArraySection<ChatSection, Message>]()
-    private var currentInterfaceActions: SetActor<Set<InterfaceActions>, ReactionTypes> = SetActor()
-
-    var fileURL: URL?
-
-    public override func loadView() { view = screenView }
-    public override var canBecomeFirstResponder: Bool { true }
-    public override var inputAccessoryView: UIView? { inputComponent }
-
-    public init(_ contact: Contact) {
-        let viewModel = SingleChatViewModel(contact)
-        self.viewModel = viewModel
-
-        self.inputComponent = ChatInputView(store: .init(
-            initialState: .init(canAddAttachments: true),
-            reducer: chatInputReducer,
-            environment: .init(
-                voxophone: try! DependencyInjection.Container.shared.resolve() as Voxophone,
-                sendAudio: { viewModel.didSendAudio(url: $0) },
-                didTapCamera: { viewModel.didTest(permission: .camera) },
-                didTapLibrary: { viewModel.didTest(permission: .library) },
-                sendText: { viewModel.send($0) },
-                didTapAbortReply: { viewModel.abortReply() },
-                didTapMicrophone: { viewModel.didTest(permission: .microphone) }
-            )
-        ))
-
-        super.init(nibName: nil, bundle: nil)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar.customize(
-            backgroundColor: Asset.neutralWhite.color,
-            shadowColor: Asset.neutralDisabled.color
-        )
-    }
-
-    public override func viewDidAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-        collectionView.collectionViewLayout.invalidateLayout()
-        becomeFirstResponder()
-        viewModel.viewDidAppear()
-    }
-
-    private var isFirstAppearance = true
-
-    public override func viewDidLayoutSubviews() {
-        super.viewDidLayoutSubviews()
-
-        if isFirstAppearance {
-            isFirstAppearance = false
-            let insets = UIEdgeInsets(
-                top: 0,
-                left: 0,
-                bottom: inputComponent.bounds.height - view.safeAreaInsets.bottom,
-                right: 0
-            )
-            collectionView.contentInset = insets
-            collectionView.scrollIndicatorInsets = insets
-        }
-    }
-
-    public override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-        viewModel.readAll()
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-
-        viewModel
-            .contactPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in setupNavigationBar(contact: $0) }
-            .store(in: &cancellables)
-
-        setupCollectionView()
-        setupInputController()
-        setupBindings()
-
-        KeyboardListener.shared.add(delegate: self)
-        screenView.bringSubviewToFront(screenView.snackBar)
-    }
-
-    // MARK: Private
-
-    private func setupCollectionView() {
-        chatLayout.configure(layoutDelegate)
-        collectionView = .init(on: screenView, with: chatLayout)
-        collectionView.delegate = self
-        collectionView.dataSource = self
-
-        collectionView.register(OutgoingTextCell.self)
-        collectionView.register(IncomingTextCell.self)
-        collectionView.register(IncomingAudioCell.self)
-        collectionView.register(OutgoingAudioCell.self)
-        collectionView.register(IncomingImageCell.self)
-        collectionView.register(IncomingReplyCell.self)
-        collectionView.register(OutgoingImageCell.self)
-        collectionView.register(OutgoingReplyCell.self)
-        collectionView.register(OutgoingFailedTextCell.self)
-        collectionView.register(OutgoingFailedReplyCell.self)
-
-        collectionView.registerSectionHeader(SectionHeaderView.self)
-    }
-
-    private func setupNavigationBar(contact: Contact) {
-        screenView.set(name: contact.nickname ?? contact.username!)
-        avatarView.snp.makeConstraints { $0.width.height.equalTo(35) }
-
-        let title = (contact.nickname ?? contact.username) ?? ""
-        avatarView.setupProfile(title: title, image: contact.photo, size: .small)
-
-        nameLabel.text = title
-        nameLabel.textColor = Asset.neutralActive.color
-        nameLabel.font = Fonts.Mulish.semiBold.font(size: 18.0)
-
-        moreButton.setImage(Asset.chatMore.image, for: .normal)
-        moreButton.addTarget(self, action: #selector(didTapDots), for: .touchUpInside)
-
-        infoView.addTarget(self, action: #selector(didTapInfo), for: .touchUpInside)
-
-        infoView.addSubview(avatarView)
-        infoView.addSubview(nameLabel)
-
-        avatarView.snp.makeConstraints {
-            $0.top.left.bottom.equalToSuperview()
+  @Dependency var hud: HUD
+  @Dependency var logger: XXLogger
+  @Dependency var voxophone: Voxophone
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: ChatCoordinating
+  @Dependency var reportingStatus: ReportingStatus
+  @Dependency var makeReportDrawer: MakeReportDrawer
+  @Dependency var makeAppScreenshot: MakeAppScreenshot
+
+  lazy private var infoView = UIControl()
+  lazy private var nameLabel = UILabel()
+  lazy private var avatarView = AvatarView()
+
+  lazy private var moreButton = UIButton()
+  lazy private var screenView = ChatView()
+  lazy private var sheet = SheetController()
+
+  private let inputComponent: ChatInputView
+  private var collectionView: UICollectionView!
+
+  private var animator: ManualAnimator?
+  private let viewModel: SingleChatViewModel
+  private let layoutDelegate = LayoutDelegate()
+  private var cancellables = Set<AnyCancellable>()
+  private let chatLayout = CollectionViewChatLayout()
+  private var sections = [ArraySection<ChatSection, Message>]()
+  private var currentInterfaceActions: SetActor<Set<InterfaceActions>, ReactionTypes> = SetActor()
+
+  var fileURL: URL?
+
+  public override func loadView() { view = screenView }
+  public override var canBecomeFirstResponder: Bool { true }
+  public override var inputAccessoryView: UIView? { inputComponent }
+
+  public init(_ contact: Contact) {
+    let viewModel = SingleChatViewModel(contact)
+    self.viewModel = viewModel
+
+    self.inputComponent = ChatInputView(store: .init(
+      initialState: .init(canAddAttachments: true),
+      reducer: chatInputReducer,
+      environment: .init(
+        voxophone: try! DependencyInjection.Container.shared.resolve() as Voxophone,
+        sendAudio: { viewModel.didSendAudio(url: $0) },
+        didTapCamera: { viewModel.didTest(permission: .camera) },
+        didTapLibrary: { viewModel.didTest(permission: .library) },
+        sendText: { viewModel.send($0) },
+        didTapAbortReply: { viewModel.abortReply() },
+        didTapMicrophone: { viewModel.didTest(permission: .microphone) }
+      )
+    ))
+
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar.customize(
+      backgroundColor: Asset.neutralWhite.color,
+      shadowColor: Asset.neutralDisabled.color
+    )
+  }
+
+  public override func viewDidAppear(_ animated: Bool) {
+    super.viewDidAppear(animated)
+    collectionView.collectionViewLayout.invalidateLayout()
+    becomeFirstResponder()
+    viewModel.viewDidAppear()
+  }
+
+  private var isFirstAppearance = true
+
+  public override func viewDidLayoutSubviews() {
+    super.viewDidLayoutSubviews()
+
+    if isFirstAppearance {
+      isFirstAppearance = false
+      let insets = UIEdgeInsets(
+        top: 0,
+        left: 0,
+        bottom: inputComponent.bounds.height - view.safeAreaInsets.bottom,
+        right: 0
+      )
+      collectionView.contentInset = insets
+      collectionView.scrollIndicatorInsets = insets
+    }
+  }
+
+  public override func viewWillDisappear(_ animated: Bool) {
+    super.viewWillDisappear(animated)
+    viewModel.readAll()
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+
+    viewModel
+      .contactPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in setupNavigationBar(contact: $0) }
+      .store(in: &cancellables)
+
+    setupCollectionView()
+    setupInputController()
+    setupBindings()
+
+    KeyboardListener.shared.add(delegate: self)
+    screenView.bringSubviewToFront(screenView.snackBar)
+  }
+
+  // MARK: Private
+
+  private func setupCollectionView() {
+    chatLayout.configure(layoutDelegate)
+    collectionView = .init(on: screenView, with: chatLayout)
+    collectionView.delegate = self
+    collectionView.dataSource = self
+
+    collectionView.register(OutgoingTextCell.self)
+    collectionView.register(IncomingTextCell.self)
+    collectionView.register(IncomingAudioCell.self)
+    collectionView.register(OutgoingAudioCell.self)
+    collectionView.register(IncomingImageCell.self)
+    collectionView.register(IncomingReplyCell.self)
+    collectionView.register(OutgoingImageCell.self)
+    collectionView.register(OutgoingReplyCell.self)
+    collectionView.register(OutgoingFailedTextCell.self)
+    collectionView.register(OutgoingFailedReplyCell.self)
+
+    collectionView.registerSectionHeader(SectionHeaderView.self)
+  }
+
+  private func setupNavigationBar(contact: Contact) {
+    screenView.set(name: contact.nickname ?? contact.username!)
+    avatarView.snp.makeConstraints { $0.width.height.equalTo(35) }
+
+    let title = (contact.nickname ?? contact.username) ?? ""
+    avatarView.setupProfile(title: title, image: contact.photo, size: .small)
+
+    nameLabel.text = title
+    nameLabel.textColor = Asset.neutralActive.color
+    nameLabel.font = Fonts.Mulish.semiBold.font(size: 18.0)
+
+    moreButton.setImage(Asset.chatMore.image, for: .normal)
+    moreButton.addTarget(self, action: #selector(didTapDots), for: .touchUpInside)
+
+    infoView.addTarget(self, action: #selector(didTapInfo), for: .touchUpInside)
+
+    infoView.addSubview(avatarView)
+    infoView.addSubview(nameLabel)
+
+    avatarView.snp.makeConstraints {
+      $0.top.left.bottom.equalToSuperview()
+    }
+
+    nameLabel.snp.makeConstraints {
+      $0.centerY.equalToSuperview()
+      $0.left.equalTo(avatarView.snp.right).offset(13)
+      $0.right.lessThanOrEqualToSuperview()
+    }
+
+    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: moreButton)
+    navigationItem.leftBarButtonItem = UIBarButtonItem(customView: infoView)
+    navigationItem.leftItemsSupplementBackButton = true
+  }
+
+  private func setupInputController() {
+    inputComponent.setMaxHeight { [weak self] in
+      guard let self = self else { return 150 }
+
+      let maxHeight = self.collectionView.frame.height
+      - self.collectionView.adjustedContentInset.top
+      - self.collectionView.adjustedContentInset.bottom
+      + self.inputComponent.bounds.height
+
+      return maxHeight * 0.9
+    }
+
+    viewModel.replyPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] senderTitle, messageText in
+        inputComponent.setupReply(message: messageText, sender: senderTitle)
+      }
+      .store(in: &cancellables)
+
+    viewModel.navigation
+      .receive(on: DispatchQueue.main)
+      .removeDuplicates()
+      .sink { [unowned self] in
+        switch $0 {
+        case .library:
+          coordinator.toLibrary(from: self)
+        case .camera:
+          coordinator.toCamera(from: self)
+        case .cameraPermission:
+          coordinator.toPermission(type: .camera, from: self)
+        case .microphonePermission:
+          coordinator.toPermission(type: .microphone, from: self)
+        case .libraryPermission:
+          coordinator.toPermission(type: .library, from: self)
+        case .webview(let urlString):
+          coordinator.toWebview(with: urlString, from: self)
+        case .waitingRound:
+          coordinator.toDrawer(makeWaitingRoundDrawer(), from: self)
+        case .none:
+          break
         }
 
-        nameLabel.snp.makeConstraints {
-            $0.centerY.equalToSuperview()
-            $0.left.equalTo(avatarView.snp.right).offset(13)
-            $0.right.lessThanOrEqualToSuperview()
+        viewModel.didNavigateSomewhere()
+      }.store(in: &cancellables)
+  }
+
+  private func setupBindings() {
+    viewModel.hud
+      .receive(on: DispatchQueue.main)
+      .sink { [hud] in hud.update(with: $0) }
+      .store(in: &cancellables)
+
+    sheet.actionPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        switch $0 {
+        case .clear:
+          presentDeleteAllDrawer()
+        case .details:
+          coordinator.toContact(viewModel.contact, from: self)
+        case .report:
+          presentReportDrawer()
         }
+      }.store(in: &cancellables)
 
-        navigationItem.rightBarButtonItem = UIBarButtonItem(customView: moreButton)
-        navigationItem.leftBarButtonItem = UIBarButtonItem(customView: infoView)
-        navigationItem.leftItemsSupplementBackButton = true
-    }
-
-    private func setupInputController() {
-        inputComponent.setMaxHeight { [weak self] in
-            guard let self = self else { return 150 }
+    viewModel
+      .shouldDisplayEmptyView
+      .removeDuplicates()
+      .sink { [unowned self] in
+        screenView.titleLabel.isHidden = !$0
 
-            let maxHeight = self.collectionView.frame.height
-            - self.collectionView.adjustedContentInset.top
-            - self.collectionView.adjustedContentInset.bottom
-            + self.inputComponent.bounds.height
-
-            return maxHeight * 0.9
+        if $0 == true {
+          screenView.bringSubviewToFront(screenView.titleLabel)
+        }
+      }.store(in: &cancellables)
+
+    viewModel.reportPopupPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        presentReportDrawer()
+      }.store(in: &cancellables)
+
+    viewModel.isOnline
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [weak screenView] in screenView?.displayNetworkIssue(!$0) }
+      .store(in: &cancellables)
+
+    viewModel.messages
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] sections in
+        func process() {
+          let changeSet = StagedChangeset(source: self.sections, target: sections).flattenIfPossible()
+          collectionView.reload(
+            using: changeSet,
+            interrupt: { changeSet in
+              guard !self.sections.isEmpty else { return true }
+              return false
+            }, onInterruptedReload: {
+              guard let lastSection = self.sections.last else { return }
+              let positionSnapshot = ChatLayoutPositionSnapshot(
+                indexPath: IndexPath(
+                  item: lastSection.elements.count - 1,
+                  section: self.sections.count - 1
+                ),
+                kind: .cell,
+                edge: .bottom
+              )
+
+              self.collectionView.reloadData()
+              self.chatLayout.restoreContentOffset(with: positionSnapshot)
+            },
+            completion: nil,
+            setData: { self.sections = $0 }
+          )
         }
 
-        viewModel.replyPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] senderTitle, messageText in
-                inputComponent.setupReply(message: messageText, sender: senderTitle)
-            }
-            .store(in: &cancellables)
-
-        viewModel.navigation
-            .receive(on: DispatchQueue.main)
-            .removeDuplicates()
-            .sink { [unowned self] in
-                switch $0 {
-                case .library:
-                    coordinator.toLibrary(from: self)
-                case .camera:
-                    coordinator.toCamera(from: self)
-                case .cameraPermission:
-                    coordinator.toPermission(type: .camera, from: self)
-                case .microphonePermission:
-                     coordinator.toPermission(type: .microphone, from: self)
-                case .libraryPermission:
-                    coordinator.toPermission(type: .library, from: self)
-                case .webview(let urlString):
-                    coordinator.toWebview(with: urlString, from: self)
-                case .waitingRound:
-                    coordinator.toDrawer(makeWaitingRoundDrawer(), from: self)
-                case .none:
-                    break
-                }
-
-                viewModel.didNavigateSomewhere()
-            }.store(in: &cancellables)
-    }
-
-    private func setupBindings() {
-        viewModel.hud
-            .receive(on: DispatchQueue.main)
-            .sink { [hud] in hud.update(with: $0) }
-            .store(in: &cancellables)
-
-        sheet.actionPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                switch $0 {
-                case .clear:
-                    presentDeleteAllDrawer()
-                case .details:
-                    coordinator.toContact(viewModel.contact, from: self)
-                case .report:
-                    presentReportDrawer()
-                }
-            }.store(in: &cancellables)
-
-        viewModel
-            .shouldDisplayEmptyView
-            .removeDuplicates()
-            .sink { [unowned self] in
-                screenView.titleLabel.isHidden = !$0
-
-                if $0 == true {
-                    screenView.bringSubviewToFront(screenView.titleLabel)
-                }
-            }.store(in: &cancellables)
-
-        viewModel.reportPopupPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                presentReportDrawer()
-            }.store(in: &cancellables)
-
-        viewModel.isOnline
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [weak screenView] in screenView?.displayNetworkIssue(!$0) }
-            .store(in: &cancellables)
-
-        viewModel.messages
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] sections in
-                func process() {
-                    let changeSet = StagedChangeset(source: self.sections, target: sections).flattenIfPossible()
-                    collectionView.reload(
-                        using: changeSet,
-                        interrupt: { changeSet in
-                            guard !self.sections.isEmpty else { return true }
-                            return false
-                        }, onInterruptedReload: {
-                            guard let lastSection = self.sections.last else { return }
-                            let positionSnapshot = ChatLayoutPositionSnapshot(
-                                indexPath: IndexPath(
-                                    item: lastSection.elements.count - 1,
-                                    section: self.sections.count - 1
-                                ),
-                                kind: .cell,
-                                edge: .bottom
-                            )
-
-                            self.collectionView.reloadData()
-                            self.chatLayout.restoreContentOffset(with: positionSnapshot)
-                        },
-                        completion: nil,
-                        setData: { self.sections = $0 }
-                    )
-                }
-
-                guard currentInterfaceActions.options.isEmpty else {
-                    let reaction = SetActor<Set<InterfaceActions>, ReactionTypes>.Reaction(
-                        type: .delayedUpdate,
-                        action: .onEmpty,
-                        executionType: .once,
-                        actionBlock: { [weak self] in
-                            guard let _ = self else { return }
-                            process()
-                        }
-                    )
-
-                    currentInterfaceActions.add(reaction: reaction)
-                    return
-                }
-
-                process()
+        guard currentInterfaceActions.options.isEmpty else {
+          let reaction = SetActor<Set<InterfaceActions>, ReactionTypes>.Reaction(
+            type: .delayedUpdate,
+            action: .onEmpty,
+            executionType: .once,
+            actionBlock: { [weak self] in
+              guard let _ = self else { return }
+              process()
             }
-            .store(in: &cancellables)
-    }
-
-    func scrollToBottom(completion: (() -> Void)? = nil) {
-        let contentOffsetAtBottom = CGPoint(
-            x: collectionView.contentOffset.x,
-            y: chatLayout.collectionViewContentSize.height
-            - collectionView.frame.height + collectionView.adjustedContentInset.bottom
-        )
-
-        guard contentOffsetAtBottom.y > collectionView.contentOffset.y else { completion?(); return }
-
-        let initialOffset = collectionView.contentOffset.y
-        let delta = contentOffsetAtBottom.y - initialOffset
-
-        if abs(delta) > chatLayout.visibleBounds.height {
-            animator = ManualAnimator()
-            animator?.animate(duration: TimeInterval(0.25), curve: .easeInOut) { [weak self] percentage in
-                guard let self = self else { return }
+          )
 
-                self.collectionView.contentOffset = CGPoint(x: self.collectionView.contentOffset.x, y: initialOffset + (delta * percentage))
-                if percentage == 1.0 {
-                    self.animator = nil
-                    let positionSnapshot = ChatLayoutPositionSnapshot(indexPath: IndexPath(item: 0, section: 0), kind: .footer, edge: .bottom)
-                    self.chatLayout.restoreContentOffset(with: positionSnapshot)
-                    self.currentInterfaceActions.options.remove(.scrollingToBottom)
-                    completion?()
-                }
-            }
-        } else {
-            currentInterfaceActions.options.insert(.scrollingToBottom)
-            UIView.animate(withDuration: 0.25, animations: {
-                self.collectionView.setContentOffset(contentOffsetAtBottom, animated: true)
-            }, completion: { [weak self] _ in
-                self?.currentInterfaceActions.options.remove(.scrollingToBottom)
-                completion?()
-            })
+          currentInterfaceActions.add(reaction: reaction)
+          return
         }
-    }
-
-    private func makeWaitingRoundDrawer() -> UIViewController {
-        let text = DrawerText(
-            font: Fonts.Mulish.semiBold.font(size: 14.0),
-            text: Localized.Chat.RoundDrawer.title,
-            color: Asset.neutralWeak.color,
-            lineHeightMultiple: 1.35,
-            spacingAfter: 25
-        )
-
-        let button = DrawerCapsuleButton(model: .init(
-            title: Localized.Chat.RoundDrawer.action,
-            style: .brandColored
-        ))
 
-        let drawer = DrawerController(with: [text, button])
-
-        button.action
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned drawer] in drawer.dismiss(animated: true) }
-            .store(in: &drawer.cancellables)
-
-        return drawer
-    }
-
-    private func presentReportDrawer() {
-        var config = MakeReportDrawer.Config()
-        config.onReport = { [weak self] in
-            guard let self = self else { return }
-            let screenshot = try! self.makeAppScreenshot()
-            self.viewModel.report(screenshot: screenshot) { success in
-                guard success else { return }
-                self.navigationController?.popViewController(animated: true)
-            }
+        process()
+      }
+      .store(in: &cancellables)
+  }
+
+  func scrollToBottom(completion: (() -> Void)? = nil) {
+    let contentOffsetAtBottom = CGPoint(
+      x: collectionView.contentOffset.x,
+      y: chatLayout.collectionViewContentSize.height
+      - collectionView.frame.height + collectionView.adjustedContentInset.bottom
+    )
+
+    guard contentOffsetAtBottom.y > collectionView.contentOffset.y else { completion?(); return }
+
+    let initialOffset = collectionView.contentOffset.y
+    let delta = contentOffsetAtBottom.y - initialOffset
+
+    if abs(delta) > chatLayout.visibleBounds.height {
+      animator = ManualAnimator()
+      animator?.animate(duration: TimeInterval(0.25), curve: .easeInOut) { [weak self] percentage in
+        guard let self = self else { return }
+
+        self.collectionView.contentOffset = CGPoint(x: self.collectionView.contentOffset.x, y: initialOffset + (delta * percentage))
+        if percentage == 1.0 {
+          self.animator = nil
+          let positionSnapshot = ChatLayoutPositionSnapshot(indexPath: IndexPath(item: 0, section: 0), kind: .footer, edge: .bottom)
+          self.chatLayout.restoreContentOffset(with: positionSnapshot)
+          self.currentInterfaceActions.options.remove(.scrollingToBottom)
+          completion?()
         }
-        let drawer = makeReportDrawer(config)
-        coordinator.toDrawer(drawer, from: self)
-    }
+      }
+    } else {
+      currentInterfaceActions.options.insert(.scrollingToBottom)
+      UIView.animate(withDuration: 0.25, animations: {
+        self.collectionView.setContentOffset(contentOffsetAtBottom, animated: true)
+      }, completion: { [weak self] _ in
+        self?.currentInterfaceActions.options.remove(.scrollingToBottom)
+        completion?()
+      })
+    }
+  }
+
+  private func makeWaitingRoundDrawer() -> UIViewController {
+    let text = DrawerText(
+      font: Fonts.Mulish.semiBold.font(size: 14.0),
+      text: Localized.Chat.RoundDrawer.title,
+      color: Asset.neutralWeak.color,
+      lineHeightMultiple: 1.35,
+      spacingAfter: 25
+    )
+
+    let button = DrawerCapsuleButton(model: .init(
+      title: Localized.Chat.RoundDrawer.action,
+      style: .brandColored
+    ))
+
+    let drawer = DrawerController(with: [text, button])
+
+    button.action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned drawer] in drawer.dismiss(animated: true) }
+      .store(in: &drawer.cancellables)
+
+    return drawer
+  }
+
+  private func presentReportDrawer() {
+    var config = MakeReportDrawer.Config()
+    config.onReport = { [weak self] in
+      guard let self = self else { return }
+      let screenshot = try! self.makeAppScreenshot()
+      self.viewModel.report(screenshot: screenshot) { success in
+        guard success else { return }
+        self.navigationController?.popViewController(animated: true)
+      }
+    }
+    let drawer = makeReportDrawer(config)
+    coordinator.toDrawer(drawer, from: self)
+  }
+
+  private func presentDeleteAllDrawer() {
+    let clearButton = CapsuleButton()
+    clearButton.setStyle(.red)
+    clearButton.setTitle(Localized.Chat.Clear.action, for: .normal)
+
+    let cancelButton = CapsuleButton()
+    cancelButton.setStyle(.seeThrough)
+    cancelButton.setTitle(Localized.Chat.Clear.cancel, for: .normal)
+
+    let drawer = DrawerController(with: [
+      DrawerImage(
+        image: Asset.drawerNegative.image
+      ),
+      DrawerText(
+        font: Fonts.Mulish.semiBold.font(size: 18.0),
+        text: Localized.Chat.Clear.title,
+        color: Asset.neutralActive.color
+      ),
+      DrawerText(
+        font: Fonts.Mulish.semiBold.font(size: 14.0),
+        text: Localized.Chat.Clear.subtitle,
+        color: Asset.neutralWeak.color,
+        lineHeightMultiple: 1.35,
+        spacingAfter: 25
+      ),
+      DrawerStack(
+        spacing: 20.0,
+        views: [clearButton, cancelButton]
+      )
+    ])
+
+    clearButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned drawer, weak self] in
+        drawer.dismiss(animated: true) {
+          self?.viewModel.didRequestDeleteAll()
+        }
+      }
+      .store(in: &drawer.cancellables)
 
-    private func presentDeleteAllDrawer() {
-        let clearButton = CapsuleButton()
-        clearButton.setStyle(.red)
-        clearButton.setTitle(Localized.Chat.Clear.action, for: .normal)
-
-        let cancelButton = CapsuleButton()
-        cancelButton.setStyle(.seeThrough)
-        cancelButton.setTitle(Localized.Chat.Clear.cancel, for: .normal)
-
-        let drawer = DrawerController(with: [
-            DrawerImage(
-                image: Asset.drawerNegative.image
-            ),
-            DrawerText(
-                font: Fonts.Mulish.semiBold.font(size: 18.0),
-                text: Localized.Chat.Clear.title,
-                color: Asset.neutralActive.color
-            ),
-            DrawerText(
-                font: Fonts.Mulish.semiBold.font(size: 14.0),
-                text: Localized.Chat.Clear.subtitle,
-                color: Asset.neutralWeak.color,
-                lineHeightMultiple: 1.35,
-                spacingAfter: 25
-            ),
-            DrawerStack(
-                spacing: 20.0,
-                views: [clearButton, cancelButton]
-            )
-        ])
-
-        clearButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned drawer, weak self] in
-                drawer.dismiss(animated: true) {
-                    self?.viewModel.didRequestDeleteAll()
-                }
-            }
-            .store(in: &drawer.cancellables)
+    cancelButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned drawer] in drawer.dismiss(animated: true) }
+      .store(in: &drawer.cancellables)
 
-        cancelButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned drawer] in drawer.dismiss(animated: true) }
-            .store(in: &drawer.cancellables)
+    coordinator.toDrawer(drawer, from: self)
+  }
 
-        coordinator.toDrawer(drawer, from: self)
-    }
+  private func previewItemAt(_ indexPath: IndexPath) {
+    let item = sections[indexPath.section].elements[indexPath.item]
+    guard let ftid = item.fileTransferId,
+          item.status != .receiving,
+          item.status != .receivingFailed else { return }
 
-    private func previewItemAt(_ indexPath: IndexPath) {
-        let item = sections[indexPath.section].elements[indexPath.item]
-        guard let ftid = item.fileTransferId,
-              item.status != .receiving,
-              item.status != .receivingFailed else { return }
-
-        let ft = viewModel.getFileTransferWith(id: ftid)
-        fileURL = FileManager.url(for: "\(ft.name).\(ft.type)")
-        coordinator.toPreview(from: self)
-    }
+    let ft = viewModel.getFileTransferWith(id: ftid)
+    fileURL = FileManager.url(for: "\(ft.name).\(ft.type)")
+    coordinator.toPreview(from: self)
+  }
 
-    // MARK: Selectors
+  // MARK: Selectors
 
-    @objc private func didTapDots() {
-        coordinator.toMenuSheet(sheet, from: self)
-    }
+  @objc private func didTapDots() {
+    coordinator.toMenuSheet(sheet, from: self)
+  }
 
-    @objc private func didTapInfo() {
-        coordinator.toContact(viewModel.contact, from: self)
-    }
+  @objc private func didTapInfo() {
+    coordinator.toContact(viewModel.contact, from: self)
+  }
 }
 
 extension SingleChatController: UICollectionViewDataSource {
-    public func numberOfSections(in collectionView: UICollectionView) -> Int {
-        sections.count
-    }
-
-    public func collectionView(
-        _ collectionView: UICollectionView,
-        viewForSupplementaryElementOfKind kind: String,
-        at indexPath: IndexPath
-    ) -> UICollectionReusableView {
-        let sectionHeader: SectionHeaderView = collectionView.dequeueSupplementaryView(forIndexPath: indexPath)
-        sectionHeader.title.text = sections[indexPath.section].model.date.asDayOfMonth()
-        return sectionHeader
-    }
-
-    public func collectionView(
-        _ collectionView: UICollectionView,
-        numberOfItemsInSection section: Int
-    ) -> Int {
-        sections[section].elements.count
-    }
-
-    public func collectionView(
-        _ collectionView: UICollectionView,
-        cellForItemAt indexPath: IndexPath
-    ) -> UICollectionViewCell {
-
-        let showRound: (String?) -> Void = viewModel.showRoundFrom(_:)
-        let item = sections[indexPath.section].elements[indexPath.item]
-        let replyContent: (Data) -> (String, String) = viewModel.getReplyContent(for:)
-        let performReply: () -> Void = { [weak self] in self?.viewModel.didRequestReply(item) }
-
-        let factory = CellFactory.combined(factories: [
-            .incomingImage(transfer: viewModel.getFileTransferWith(id:)),
-            .outgoingImage(transfer: viewModel.getFileTransferWith(id:)),
-            .incomingAudio(voxophone: voxophone, transfer: viewModel.getFileTransferWith(id:)),
-            .outgoingAudio(voxophone: voxophone, transfer: viewModel.getFileTransferWith(id:)),
-            .incomingText(performReply: performReply, showRound: showRound),
-            .outgoingText(performReply: performReply, showRound: showRound),
-            .outgoingFailedText(performReply: performReply),
-            .incomingReply(performReply: performReply, replyContent: replyContent, showRound: showRound),
-            .outgoingReply(performReply: performReply, replyContent: replyContent, showRound: showRound),
-            .outgoingFailedReply(performReply: performReply, replyContent: replyContent)
-        ])
-
-        return factory(item: item, collectionView: collectionView, indexPath: indexPath)
-    }
+  public func numberOfSections(in collectionView: UICollectionView) -> Int {
+    sections.count
+  }
+
+  public func collectionView(
+    _ collectionView: UICollectionView,
+    viewForSupplementaryElementOfKind kind: String,
+    at indexPath: IndexPath
+  ) -> UICollectionReusableView {
+    let sectionHeader: SectionHeaderView = collectionView.dequeueSupplementaryView(forIndexPath: indexPath)
+    sectionHeader.title.text = sections[indexPath.section].model.date.asDayOfMonth()
+    return sectionHeader
+  }
+
+  public func collectionView(
+    _ collectionView: UICollectionView,
+    numberOfItemsInSection section: Int
+  ) -> Int {
+    sections[section].elements.count
+  }
+
+  public func collectionView(
+    _ collectionView: UICollectionView,
+    cellForItemAt indexPath: IndexPath
+  ) -> UICollectionViewCell {
+
+    let showRound: (String?) -> Void = viewModel.showRoundFrom(_:)
+    let item = sections[indexPath.section].elements[indexPath.item]
+    let replyContent: (Data) -> (String, String) = viewModel.getReplyContent(for:)
+    let performReply: () -> Void = { [weak self] in self?.viewModel.didRequestReply(item) }
+
+    let factory = CellFactory.combined(factories: [
+      .incomingImage(transfer: viewModel.getFileTransferWith(id:)),
+      .outgoingImage(transfer: viewModel.getFileTransferWith(id:)),
+      .incomingAudio(voxophone: voxophone, transfer: viewModel.getFileTransferWith(id:)),
+      .outgoingAudio(voxophone: voxophone, transfer: viewModel.getFileTransferWith(id:)),
+      .incomingText(performReply: performReply, showRound: showRound),
+      .outgoingText(performReply: performReply, showRound: showRound),
+      .outgoingFailedText(performReply: performReply),
+      .incomingReply(performReply: performReply, replyContent: replyContent, showRound: showRound),
+      .outgoingReply(performReply: performReply, replyContent: replyContent, showRound: showRound),
+      .outgoingFailedReply(performReply: performReply, replyContent: replyContent)
+    ])
+
+    return factory(item: item, collectionView: collectionView, indexPath: indexPath)
+  }
 }
 
 extension SingleChatController: KeyboardListenerDelegate {
-    fileprivate var isUserInitiatedScrolling: Bool {
-        collectionView.isDragging || collectionView.isDecelerating
-    }
-
-    func keyboardWillChangeFrame(info: KeyboardInfo) {
-        let keyWindow = UIApplication.shared.windows.filter { $0.isKeyWindow }.first
+  fileprivate var isUserInitiatedScrolling: Bool {
+    collectionView.isDragging || collectionView.isDecelerating
+  }
 
-        guard let keyWindow = keyWindow else {
-            fatalError("[keyboardWillChangeFrame]: Couldn't get key window")
-        }
+  func keyboardWillChangeFrame(info: KeyboardInfo) {
+    let keyWindow = UIApplication.shared.windows.filter { $0.isKeyWindow }.first
 
-        let keyboardFrame = keyWindow.convert(info.frameEnd, to: view)
-
-        guard !currentInterfaceActions.options.contains(.changingFrameSize),
-              collectionView.contentInsetAdjustmentBehavior != .never,
-              collectionView.convert(collectionView.bounds, to: keyWindow).maxY > info.frameEnd.minY else { return }
-
-        currentInterfaceActions.options.insert(.changingKeyboardFrame)
-        let newBottomInset = collectionView.frame.minY + collectionView.frame.size.height - keyboardFrame.minY - collectionView.safeAreaInsets.bottom
-        if newBottomInset > 0,
-           collectionView.contentInset.bottom != newBottomInset {
-            let positionSnapshot = chatLayout.getContentOffsetSnapshot(from: .bottom)
-
-            currentInterfaceActions.options.insert(.changingContentInsets)
-            UIView.animate(withDuration: info.animationDuration, animations: {
-                self.collectionView.performBatchUpdates({
-                    self.collectionView.contentInset.bottom = newBottomInset
-                    self.collectionView.verticalScrollIndicatorInsets.bottom = newBottomInset
-                }, completion: nil)
-
-                if let positionSnapshot = positionSnapshot, !self.isUserInitiatedScrolling {
-                    self.chatLayout.restoreContentOffset(with: positionSnapshot)
-                }
-            }, completion: { _ in
-                self.currentInterfaceActions.options.remove(.changingContentInsets)
-            })
-        }
+    guard let keyWindow = keyWindow else {
+      fatalError("[keyboardWillChangeFrame]: Couldn't get key window")
     }
 
-    func keyboardDidChangeFrame(info: KeyboardInfo) {
-        guard currentInterfaceActions.options.contains(.changingKeyboardFrame) else { return }
-        currentInterfaceActions.options.remove(.changingKeyboardFrame)
-    }
-}
+    let keyboardFrame = keyWindow.convert(info.frameEnd, to: view)
 
-extension SingleChatController: UICollectionViewDelegate {
-    private func makeTargetedPreview(for configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
-        guard let identifier = configuration.identifier as? String,
-              let first = identifier.components(separatedBy: "|").first,
-              let last = identifier.components(separatedBy: "|").last,
-              let item = Int(first), let section = Int(last),
-              let cell = collectionView.cellForItem(at: IndexPath(item: item, section: section)) else {
-                  return nil
-              }
-
-        let parameters = UIPreviewParameters()
-        parameters.backgroundColor = .clear
-
-        let status = sections[section].elements[item].status
-
-        if status == .received || status == .receiving {
-            var leftView: UIView!
-
-            if let cell = cell as? IncomingReplyCell {
-                leftView = cell.leftView
-            } else if let cell = cell as? IncomingAudioCell {
-                leftView = cell.leftView
-            } else if let cell = cell as? IncomingTextCell {
-                leftView = cell.leftView
-            } else if let cell = cell as? IncomingImageCell {
-                leftView = cell.leftView
-            }
+    guard !currentInterfaceActions.options.contains(.changingFrameSize),
+          collectionView.contentInsetAdjustmentBehavior != .never,
+          collectionView.convert(collectionView.bounds, to: keyWindow).maxY > info.frameEnd.minY else { return }
 
-            parameters.visiblePath = UIBezierPath(roundedRect: leftView.bounds, cornerRadius: 13)
-            return UITargetedPreview(view: leftView, parameters: parameters)
-        }
+    currentInterfaceActions.options.insert(.changingKeyboardFrame)
+    let newBottomInset = collectionView.frame.minY + collectionView.frame.size.height - keyboardFrame.minY - collectionView.safeAreaInsets.bottom
+    if newBottomInset > 0,
+       collectionView.contentInset.bottom != newBottomInset {
+      let positionSnapshot = chatLayout.getContentOffsetSnapshot(from: .bottom)
 
-        var rightView: UIView!
-
-        if let cell = cell as? OutgoingTextCell {
-            rightView = cell.rightView
-        } else if let cell = cell as? OutgoingAudioCell {
-            rightView = cell.rightView
-        } else if let cell = cell as? OutgoingReplyCell {
-            rightView = cell.rightView
-        } else if let cell = cell as? OutgoingImageCell {
-            rightView = cell.rightView
-        } else if let cell = cell as? OutgoingFailedTextCell {
-            rightView = cell.rightView
-        } else if let cell = cell as? OutgoingFailedReplyCell {
-            rightView = cell.rightView
-        }
+      currentInterfaceActions.options.insert(.changingContentInsets)
+      UIView.animate(withDuration: info.animationDuration, animations: {
+        self.collectionView.performBatchUpdates({
+          self.collectionView.contentInset.bottom = newBottomInset
+          self.collectionView.verticalScrollIndicatorInsets.bottom = newBottomInset
+        }, completion: nil)
 
-        parameters.visiblePath = UIBezierPath(roundedRect: rightView.bounds, cornerRadius: 13)
-        return UITargetedPreview(view: rightView, parameters: parameters)
-    }
-
-    public func collectionView(
-        _ collectionView: UICollectionView,
-        previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration
-    ) -> UITargetedPreview? {
-        makeTargetedPreview(for: configuration)
+        if let positionSnapshot = positionSnapshot, !self.isUserInitiatedScrolling {
+          self.chatLayout.restoreContentOffset(with: positionSnapshot)
+        }
+      }, completion: { _ in
+        self.currentInterfaceActions.options.remove(.changingContentInsets)
+      })
     }
+  }
 
-    public func collectionView(
-        _ collectionView: UICollectionView,
-        previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration
-    ) -> UITargetedPreview? {
-        makeTargetedPreview(for: configuration)
-    }
+  func keyboardDidChangeFrame(info: KeyboardInfo) {
+    guard currentInterfaceActions.options.contains(.changingKeyboardFrame) else { return }
+    currentInterfaceActions.options.remove(.changingKeyboardFrame)
+  }
+}
 
-    public func collectionView(
-        _ collectionView: UICollectionView,
-        contextMenuConfigurationForItemAt indexPath: IndexPath,
-        point: CGPoint
-    ) -> UIContextMenuConfiguration? {
-        UIContextMenuConfiguration(
-            identifier: "\(indexPath.item)|\(indexPath.section)" as NSCopying,
-            previewProvider: nil
-        ) { [weak self] _ in
-
-            guard let self = self else { return nil }
-            let item = self.sections[indexPath.section].elements[indexPath.item]
-
-            var children = [
-                ActionFactory.build(from: item, action: .copy, closure: self.viewModel.didRequestCopy(_:)),
-                ActionFactory.build(from: item, action: .retry, closure: self.viewModel.didRequestRetry(_:)),
-                ActionFactory.build(from: item, action: .reply, closure: self.viewModel.didRequestReply(_:)),
-                ActionFactory.build(from: item, action: .delete, closure: self.viewModel.didRequestDeleteSingle(_:))
-            ]
-
-            if self.reportingStatus.isEnabled() {
-                children.append(
-                    ActionFactory.build(from: item, action: .report, closure: self.viewModel.didRequestReport(_:))
-                )
-            }
+extension SingleChatController: UICollectionViewDelegate {
+  private func makeTargetedPreview(for configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
+    guard let identifier = configuration.identifier as? String,
+          let first = identifier.components(separatedBy: "|").first,
+          let last = identifier.components(separatedBy: "|").last,
+          let item = Int(first), let section = Int(last),
+          let cell = collectionView.cellForItem(at: IndexPath(item: item, section: section)) else {
+      return nil
+    }
+
+    let parameters = UIPreviewParameters()
+    parameters.backgroundColor = .clear
+
+    let status = sections[section].elements[item].status
+
+    if status == .received || status == .receiving {
+      var leftView: UIView!
+
+      if let cell = cell as? IncomingReplyCell {
+        leftView = cell.leftView
+      } else if let cell = cell as? IncomingAudioCell {
+        leftView = cell.leftView
+      } else if let cell = cell as? IncomingTextCell {
+        leftView = cell.leftView
+      } else if let cell = cell as? IncomingImageCell {
+        leftView = cell.leftView
+      }
+
+      parameters.visiblePath = UIBezierPath(roundedRect: leftView.bounds, cornerRadius: 13)
+      return UITargetedPreview(view: leftView, parameters: parameters)
+    }
+
+    var rightView: UIView!
+
+    if let cell = cell as? OutgoingTextCell {
+      rightView = cell.rightView
+    } else if let cell = cell as? OutgoingAudioCell {
+      rightView = cell.rightView
+    } else if let cell = cell as? OutgoingReplyCell {
+      rightView = cell.rightView
+    } else if let cell = cell as? OutgoingImageCell {
+      rightView = cell.rightView
+    } else if let cell = cell as? OutgoingFailedTextCell {
+      rightView = cell.rightView
+    } else if let cell = cell as? OutgoingFailedReplyCell {
+      rightView = cell.rightView
+    }
+
+    parameters.visiblePath = UIBezierPath(roundedRect: rightView.bounds, cornerRadius: 13)
+    return UITargetedPreview(view: rightView, parameters: parameters)
+  }
+
+  public func collectionView(
+    _ collectionView: UICollectionView,
+    previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration
+  ) -> UITargetedPreview? {
+    makeTargetedPreview(for: configuration)
+  }
+
+  public func collectionView(
+    _ collectionView: UICollectionView,
+    previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration
+  ) -> UITargetedPreview? {
+    makeTargetedPreview(for: configuration)
+  }
+
+  public func collectionView(
+    _ collectionView: UICollectionView,
+    contextMenuConfigurationForItemAt indexPath: IndexPath,
+    point: CGPoint
+  ) -> UIContextMenuConfiguration? {
+    UIContextMenuConfiguration(
+      identifier: "\(indexPath.item)|\(indexPath.section)" as NSCopying,
+      previewProvider: nil
+    ) { [weak self] _ in
+
+      guard let self = self else { return nil }
+      let item = self.sections[indexPath.section].elements[indexPath.item]
+
+      var children = [
+        ActionFactory.build(from: item, action: .copy, closure: self.viewModel.didRequestCopy(_:)),
+        ActionFactory.build(from: item, action: .retry, closure: self.viewModel.didRequestRetry(_:)),
+        ActionFactory.build(from: item, action: .reply, closure: self.viewModel.didRequestReply(_:)),
+        ActionFactory.build(from: item, action: .delete, closure: self.viewModel.didRequestDeleteSingle(_:))
+      ]
+
+      if self.reportingStatus.isEnabled() {
+        children.append(
+          ActionFactory.build(from: item, action: .report, closure: self.viewModel.didRequestReport(_:))
+        )
+      }
 
-            return UIMenu(title: "", children: children.compactMap { $0 })
-        }
+      return UIMenu(title: "", children: children.compactMap { $0 })
     }
+  }
 
-    public func collectionView(
-        _ collectionView: UICollectionView,
-        didSelectItemAt indexPath: IndexPath
-    ) {
-        previewItemAt(indexPath)
-    }
+  public func collectionView(
+    _ collectionView: UICollectionView,
+    didSelectItemAt indexPath: IndexPath
+  ) {
+    previewItemAt(indexPath)
+  }
 }
 
 extension SingleChatController: UIImagePickerControllerDelegate {
-    public func imagePickerController(
-        _ picker: UIImagePickerController,
-        didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]
-    ) {
-        picker.delegate = nil
-        picker.dismiss(animated: true)
-        guard let image = info[.originalImage] as? UIImage else { return }
-
-        DispatchQueue.global().async { [weak self] in
-            self?.viewModel.didSend(image: image)
-        }
-    }
+  public func imagePickerController(
+    _ picker: UIImagePickerController,
+    didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]
+  ) {
+    picker.delegate = nil
+    picker.dismiss(animated: true)
+    guard let image = info[.originalImage] as? UIImage else { return }
+
+    DispatchQueue.global().async { [weak self] in
+      self?.viewModel.didSend(image: image)
+    }
+  }
 }
 
 extension SingleChatController: UINavigationControllerDelegate {}
 
 extension SingleChatController: QLPreviewControllerDataSource {
-    public func numberOfPreviewItems(in controller: QLPreviewController) -> Int { 1 }
+  public func numberOfPreviewItems(in controller: QLPreviewController) -> Int { 1 }
 
-    public func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
-        fileURL! as QLPreviewItem
-    }
+  public func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
+    fileURL! as QLPreviewItem
+  }
 }
 
 extension SingleChatController: QLPreviewControllerDelegate {
-    public func previewControllerDidDismiss(_ controller: QLPreviewController) {
-        fileURL = nil
-    }
+  public func previewControllerDidDismiss(_ controller: QLPreviewController) {
+    fileURL = nil
+  }
 }
diff --git a/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift b/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift
index 7e5bc8ea026b1f68378a3935594616a9a16ebee8..2265930fde064d351972af38bebd8c85ba9ab31e 100644
--- a/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift
+++ b/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift
@@ -6,7 +6,6 @@ import Combine
 import XXModels
 import Defaults
 import Foundation
-import ToastFeature
 import DifferenceKit
 import ReportingFeature
 import DependencyInjection
diff --git a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
index d06d88f7eb5c2e6917a891dab8d062cb2723bc02..58757d2f8b83412fd9a7482de7d7275b98bb16d2 100644
--- a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
+++ b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
@@ -9,7 +9,6 @@ import XXClient
 import Defaults
 import Foundation
 import Permissions
-import ToastFeature
 import DifferenceKit
 import ReportingFeature
 import DependencyInjection
diff --git a/Sources/ChatListFeature/Controller/ChatListController.swift b/Sources/ChatListFeature/Controller/ChatListController.swift
index 57e744a3b29d7ab15371624fe2ce0932e7f9d772..be41db769a23a3ef9e8215d2e240ffee932a7c33 100644
--- a/Sources/ChatListFeature/Controller/ChatListController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListController.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Theme
 import Models
 import Shared
 import Combine
@@ -8,229 +7,229 @@ import MenuFeature
 import DependencyInjection
 
 public final class ChatListController: UIViewController {
-    @Dependency private var coordinator: ChatListCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    lazy private var screenView = ChatListView()
-    lazy private var topLeftView = ChatListTopLeftNavView()
-    lazy private var topRightView = ChatListTopRightNavView()
-    lazy private var tableController = ChatListTableController(viewModel)
-    lazy private var searchTableController = ChatSearchTableController(viewModel)
-    private var collectionDataSource: UICollectionViewDiffableDataSource<SectionId, Contact>!
-
-    private let viewModel = ChatListViewModel()
-    private var cancellables = Set<AnyCancellable>()
-    private var drawerCancellables = Set<AnyCancellable>()
-
-    private var isEditingSearch = false {
-        didSet {
-            screenView.listContainerView
-                .showRecentsCollection(isEditingSearch ? false : shouldBeShowingRecents)
-        }
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: ChatListCoordinating
+
+  lazy private var screenView = ChatListView()
+  lazy private var topLeftView = ChatListTopLeftNavView()
+  lazy private var topRightView = ChatListTopRightNavView()
+  lazy private var tableController = ChatListTableController(viewModel)
+  lazy private var searchTableController = ChatSearchTableController(viewModel)
+  private var collectionDataSource: UICollectionViewDiffableDataSource<SectionId, Contact>!
+
+  private let viewModel = ChatListViewModel()
+  private var cancellables = Set<AnyCancellable>()
+  private var drawerCancellables = Set<AnyCancellable>()
+
+  private var isEditingSearch = false {
+    didSet {
+      screenView.listContainerView
+        .showRecentsCollection(isEditingSearch ? false : shouldBeShowingRecents)
     }
+  }
 
-    private var shouldBeShowingRecents = false {
-        didSet {
-            screenView.listContainerView
-                .showRecentsCollection(isEditingSearch ? false : shouldBeShowingRecents)
-        }
+  private var shouldBeShowingRecents = false {
+    didSet {
+      screenView.listContainerView
+        .showRecentsCollection(isEditingSearch ? false : shouldBeShowingRecents)
     }
-
-    public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
-        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
-        navigationItem.backButtonTitle = ""
+  }
+
+  public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
+    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
+    navigationItem.backButtonTitle = ""
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func loadView() {
+    view = screenView
+  }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar.customize(backgroundColor: Asset.neutralWhite.color)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupChatList()
+    setupBindings()
+    setupNavigationBar()
+    setupRecentContacts()
+  }
+
+  private func setupNavigationBar() {
+    navigationItem.leftBarButtonItem = UIBarButtonItem(customView: topLeftView)
+    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: topRightView)
+
+    topRightView.actionPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        switch $0 {
+        case .didTapSearch:
+          coordinator.toSearch(from: self)
+        case .didTapNewGroup:
+          coordinator.toNewGroup(from: self)
+        }
+      }.store(in: &cancellables)
+
+    viewModel.badgeCountPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in topLeftView.updateBadge($0) }
+      .store(in: &cancellables)
+
+    topLeftView.actionPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toSideMenu(from: self) }
+      .store(in: &cancellables)
+  }
+
+  private func setupChatList() {
+    addChild(tableController)
+    addChild(searchTableController)
+
+    screenView.listContainerView.addSubview(tableController.view)
+    screenView.searchListContainerView.addSubview(searchTableController.view)
+
+    tableController.view.snp.makeConstraints {
+      $0.top.equalTo(screenView.listContainerView.collectionContainerView.snp.bottom)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
     }
 
-    required init?(coder: NSCoder) { nil }
-
-    public override func loadView() {
-        view = screenView
+    searchTableController.view.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
     }
 
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar.customize(backgroundColor: Asset.neutralWhite.color)
+    tableController.didMove(toParent: self)
+    searchTableController.didMove(toParent: self)
+  }
+
+  private func setupRecentContacts() {
+    screenView
+      .listContainerView
+      .collectionView
+      .register(ChatListRecentContactCell.self)
+
+    collectionDataSource = UICollectionViewDiffableDataSource<SectionId, Contact>(
+      collectionView: screenView.listContainerView.collectionView
+    ) { collectionView, indexPath, contact in
+      let cell: ChatListRecentContactCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+      let title = (contact.nickname ?? contact.username) ?? ""
+      cell.setup(title: title, image: contact.photo)
+      return cell
     }
 
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupChatList()
-        setupBindings()
-        setupNavigationBar()
-        setupRecentContacts()
+    screenView.listContainerView.collectionView.delegate = self
+    screenView.listContainerView.collectionView.dataSource = collectionDataSource
+
+    viewModel.recentsPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        collectionDataSource.apply($0)
+        shouldBeShowingRecents = $0.numberOfItems > 0
+      }.store(in: &cancellables)
+  }
+
+  private func setupBindings() {
+    screenView.searchView
+      .rightPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toScan(from: self) }
+      .store(in: &cancellables)
+
+    screenView.searchView
+      .textPublisher
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] query in
+        viewModel.updateSearch(query: query)
+        screenView.searchListContainerView.emptyView.updateSearched(content: query)
+      }.store(in: &cancellables)
+
+    Publishers.CombineLatest(
+      viewModel.searchPublisher,
+      screenView.searchView.textPublisher.removeDuplicates()
+    )
+    .receive(on: DispatchQueue.main)
+    .sink { [unowned self] items, query in
+      guard query.isEmpty == false else {
+        screenView.searchListContainerView.isHidden = true
+        screenView.listContainerView.isHidden = false
+        screenView.bringSubviewToFront(screenView.listContainerView)
+        return
+      }
+
+      screenView.listContainerView.isHidden = true
+      screenView.searchListContainerView.isHidden = false
+
+      guard items.numberOfItems > 0 else {
+        screenView.searchListContainerView.emptyView.isHidden = false
+        screenView.bringSubviewToFront(screenView.searchListContainerView)
+        screenView.searchListContainerView.bringSubviewToFront(screenView.searchListContainerView.emptyView)
+        return
+      }
+
+      screenView.searchListContainerView.bringSubviewToFront(searchTableController.view)
+      screenView.searchListContainerView.emptyView.isHidden = true
     }
-
-    private func setupNavigationBar() {
-        navigationItem.leftBarButtonItem = UIBarButtonItem(customView: topLeftView)
-        navigationItem.rightBarButtonItem = UIBarButtonItem(customView: topRightView)
-
-        topRightView.actionPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                switch $0 {
-                case .didTapSearch:
-                    coordinator.toSearch(from: self)
-                case .didTapNewGroup:
-                    coordinator.toNewGroup(from: self)
-                }
-            }.store(in: &cancellables)
-
-        viewModel.badgeCountPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in topLeftView.updateBadge($0) }
-            .store(in: &cancellables)
-
-        topLeftView.actionPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toSideMenu(from: self) }
-            .store(in: &cancellables)
-   }
-
-    private func setupChatList() {
-        addChild(tableController)
-        addChild(searchTableController)
-
-        screenView.listContainerView.addSubview(tableController.view)
-        screenView.searchListContainerView.addSubview(searchTableController.view)
-
-        tableController.view.snp.makeConstraints {
-            $0.top.equalTo(screenView.listContainerView.collectionContainerView.snp.bottom)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
-
-        searchTableController.view.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
+    .store(in: &cancellables)
+
+    screenView.searchView
+      .isEditingPublisher
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in isEditingSearch = $0 }
+      .store(in: &cancellables)
+
+    viewModel.chatsPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        guard $0.isEmpty == false else {
+          screenView.listContainerView.bringSubviewToFront(screenView.listContainerView.emptyView)
+          screenView.listContainerView.emptyView.isHidden = false
+          return
         }
 
-        tableController.didMove(toParent: self)
-        searchTableController.didMove(toParent: self)
-    }
-
-    private func setupRecentContacts() {
-        screenView
-            .listContainerView
-            .collectionView
-            .register(ChatListRecentContactCell.self)
-
-        collectionDataSource = UICollectionViewDiffableDataSource<SectionId, Contact>(
-            collectionView: screenView.listContainerView.collectionView
-        ) { collectionView, indexPath, contact in
-            let cell: ChatListRecentContactCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-            let title = (contact.nickname ?? contact.username) ?? ""
-            cell.setup(title: title, image: contact.photo)
-            return cell
-        }
-
-        screenView.listContainerView.collectionView.delegate = self
-        screenView.listContainerView.collectionView.dataSource = collectionDataSource
-
-        viewModel.recentsPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                collectionDataSource.apply($0)
-                shouldBeShowingRecents = $0.numberOfItems > 0
-            }.store(in: &cancellables)
-    }
-
-    private func setupBindings() {
-        screenView.searchView
-            .rightPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toScan(from: self) }
-            .store(in: &cancellables)
-
-        screenView.searchView
-            .textPublisher
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] query in
-                viewModel.updateSearch(query: query)
-                screenView.searchListContainerView.emptyView.updateSearched(content: query)
-            }.store(in: &cancellables)
-
-        Publishers.CombineLatest(
-            viewModel.searchPublisher,
-            screenView.searchView.textPublisher.removeDuplicates()
-        )
-        .receive(on: DispatchQueue.main)
-            .sink { [unowned self] items, query in
-                guard query.isEmpty == false else {
-                    screenView.searchListContainerView.isHidden = true
-                    screenView.listContainerView.isHidden = false
-                    screenView.bringSubviewToFront(screenView.listContainerView)
-                    return
-                }
-
-                screenView.listContainerView.isHidden = true
-                screenView.searchListContainerView.isHidden = false
-
-                guard items.numberOfItems > 0 else {
-                    screenView.searchListContainerView.emptyView.isHidden = false
-                    screenView.bringSubviewToFront(screenView.searchListContainerView)
-                    screenView.searchListContainerView.bringSubviewToFront(screenView.searchListContainerView.emptyView)
-                    return
-                }
-
-                screenView.searchListContainerView.bringSubviewToFront(searchTableController.view)
-                screenView.searchListContainerView.emptyView.isHidden = true
-            }
-            .store(in: &cancellables)
-
-        screenView.searchView
-            .isEditingPublisher
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in isEditingSearch = $0 }
-            .store(in: &cancellables)
-
-        viewModel.chatsPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                guard $0.isEmpty == false else {
-                    screenView.listContainerView.bringSubviewToFront(screenView.listContainerView.emptyView)
-                    screenView.listContainerView.emptyView.isHidden = false
-                    return
-                }
-
-                screenView.listContainerView.bringSubviewToFront(tableController.view)
-                screenView.listContainerView.emptyView.isHidden = true
-            }
-            .store(in: &cancellables)
-
-        screenView.searchListContainerView
-            .emptyView.searchButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in coordinator.toSearch(from: self) }
-            .store(in: &cancellables)
-
-        screenView.listContainerView
-            .emptyView.contactsButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toContacts(from: self) }
-            .store(in: &cancellables)
-
-        viewModel.isOnline
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [weak screenView] connected in screenView?.showConnectingBanner(!connected) }
-            .store(in: &cancellables)
-    }
+        screenView.listContainerView.bringSubviewToFront(tableController.view)
+        screenView.listContainerView.emptyView.isHidden = true
+      }
+      .store(in: &cancellables)
+
+    screenView.searchListContainerView
+      .emptyView.searchButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in coordinator.toSearch(from: self) }
+      .store(in: &cancellables)
+
+    screenView.listContainerView
+      .emptyView.contactsButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toContacts(from: self) }
+      .store(in: &cancellables)
+
+    viewModel.isOnline
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [weak screenView] connected in screenView?.showConnectingBanner(!connected) }
+      .store(in: &cancellables)
+  }
 }
 
 extension ChatListController: UICollectionViewDelegate {
-    public func collectionView(
-        _ collectionView: UICollectionView,
-        didSelectItemAt indexPath: IndexPath
-    ) {
-        if let contact = collectionDataSource.itemIdentifier(for: indexPath) {
-            coordinator.toSingleChat(with: contact, from: self)
-        }
+  public func collectionView(
+    _ collectionView: UICollectionView,
+    didSelectItemAt indexPath: IndexPath
+  ) {
+    if let contact = collectionDataSource.itemIdentifier(for: indexPath) {
+      coordinator.toSingleChat(with: contact, from: self)
     }
+  }
 }
diff --git a/Sources/ContactFeature/Controllers/ContactController.swift b/Sources/ContactFeature/Controllers/ContactController.swift
index 30dd3f5e48444176c274a0f6f18502b12e172c17..d9c7f68fc87b0b4970ea138aa63dbf08e1d660dd 100644
--- a/Sources/ContactFeature/Controllers/ContactController.swift
+++ b/Sources/ContactFeature/Controllers/ContactController.swift
@@ -1,6 +1,5 @@
 import HUD
 import UIKit
-import Theme
 import Shared
 import Models
 import Combine
@@ -10,428 +9,428 @@ import DependencyInjection
 import ScrollViewController
 
 public final class ContactController: UIViewController {
-    @Dependency private var hud: HUD
-    @Dependency private var coordinator: ContactCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    lazy private var screenView = ContactView()
-    lazy private var scrollViewController = ScrollViewController()
-
-    private let viewModel: ContactViewModel
-    private var cancellables = Set<AnyCancellable>()
-    private var drawerCancellables = Set<AnyCancellable>()
-
-    public init(_ model: Contact) {
-        self.viewModel = ContactViewModel(model)
-        super.init(nibName: nil, bundle: nil)
+  @Dependency var hud: HUD
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: ContactCoordinating
+
+  lazy private var screenView = ContactView()
+  lazy private var scrollViewController = ScrollViewController()
+
+  private let viewModel: ContactViewModel
+  private var cancellables = Set<AnyCancellable>()
+  private var drawerCancellables = Set<AnyCancellable>()
+
+  public init(_ model: Contact) {
+    self.viewModel = ContactViewModel(model)
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    barStylist.styleSubject.send(.lightContent)
+    navigationController?.navigationBar
+      .customize(
+        backgroundColor: Asset.neutralBody.color,
+        tint: Asset.neutralWhite.color
+      )
+  }
+
+  public override func viewSafeAreaInsetsDidChange() {
+    super.viewSafeAreaInsetsDidChange()
+    screenView.updateTopOffset(-view.safeAreaInsets.top)
+    screenView.updateBottomOffset(view.safeAreaInsets.bottom)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupScrollView()
+    setupBindings()
+
+    screenView.didTapSend = { [weak self] in
+      guard let self = self else { return }
+      self.coordinator.toSingleChat(with: self.viewModel.contact, from: self)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        statusBarController.style.send(.lightContent)
-        navigationController?.navigationBar
-            .customize(
-                backgroundColor: Asset.neutralBody.color,
-                tint: Asset.neutralWhite.color
-            )
+    screenView.didTapInfo = { [weak self] in
+      self?.presentInfo(
+        title: Localized.Contact.SendMessage.Info.title,
+        subtitle: Localized.Contact.SendMessage.Info.subtitle,
+        urlString: "https://links.xx.network/cmix"
+      )
     }
 
-    public override func viewSafeAreaInsetsDidChange() {
-        super.viewSafeAreaInsetsDidChange()
-        screenView.updateTopOffset(-view.safeAreaInsets.top)
-        screenView.updateBottomOffset(view.safeAreaInsets.bottom)
-    }
-    
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupScrollView()
-        setupBindings()
-
-        screenView.didTapSend = { [weak self] in
-            guard let self = self else { return }
-            self.coordinator.toSingleChat(with: self.viewModel.contact, from: self)
+    screenView.set(status: viewModel.contact.authStatus)
+  }
+
+  private func setupScrollView() {
+    addChild(scrollViewController)
+    view.addSubview(scrollViewController.view)
+    scrollViewController.view.backgroundColor = Asset.neutralWhite.color
+    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.didMove(toParent: self)
+    scrollViewController.contentView = screenView
+    scrollViewController.scrollView.bounces = false
+  }
+
+  private func setupBindings() {
+    viewModel.hudPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [hud] in hud.update(with: $0) }
+      .store(in: &cancellables)
+
+    screenView.cardComponent.avatarView.editButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toPhotos(from: self) }
+      .store(in: &cancellables)
+
+    viewModel.statePublisher
+      .map(\.photo)
+      .compactMap { $0 }
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.cardComponent.image = $0 }
+      .store(in: &cancellables)
+
+    viewModel.statePublisher
+      .map(\.title)
+      .compactMap { $0 }
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.cardComponent.nameLabel.text = $0 }
+      .store(in: &cancellables)
+
+    viewModel.popPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in navigationController?.popViewController(animated: true) }
+      .store(in: &cancellables)
+
+    viewModel.popToRootPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in navigationController?.popToRootViewController(animated: true) }
+      .store(in: &cancellables)
+
+    viewModel.successPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.updateToSuccess() }
+      .store(in: &cancellables)
+
+    setupScannedBindings()
+    setupReceivedBindings()
+    setupConfirmedBindings()
+    setupInProgressBindings()
+    setupSuccessBindings()
+  }
+
+  private func setupSuccessBindings() {
+    screenView.successView.keepAdding
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in navigationController?.popViewController(animated: true) }
+      .store(in: &cancellables)
+
+    screenView.successView.sentRequests
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in coordinator.toRequests(from: self) }
+      .store(in: &cancellables)
+
+    viewModel.statePublisher
+      .map(\.username)
+      .removeDuplicates()
+      .combineLatest(
+        viewModel.statePublisher.map(\.email).removeDuplicates(),
+        viewModel.statePublisher.map(\.phone).removeDuplicates()
+      )
+      .sink { [unowned self] in
+        [Localized.Contact.username: $0.0,
+         Localized.Contact.email: $0.1,
+         Localized.Contact.phone: $0.2].forEach { pair in
+          guard let value = pair.value else { return }
+
+          let attributeView = AttributeComponent()
+          attributeView.set(
+            title: pair.key,
+            value: value
+          )
+
+          screenView.successView.stack.addArrangedSubview(attributeView)
         }
-        screenView.didTapInfo = { [weak self] in
-            self?.presentInfo(
-                title: Localized.Contact.SendMessage.Info.title,
-                subtitle: Localized.Contact.SendMessage.Info.subtitle,
-                urlString: "https://links.xx.network/cmix"
-            )
+      }.store(in: &cancellables)
+  }
+
+  private func setupScannedBindings() {
+    screenView.scannedView.add
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        coordinator.toNickname(
+          from: self,
+          prefilled: (viewModel.contact.nickname ?? viewModel.contact.username) ?? "",
+          viewModel.didTapRequest(with:)
+        )
+      }.store(in: &cancellables)
+  }
+
+  private func setupReceivedBindings() {
+    screenView.receivedView.accept
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        coordinator.toNickname(
+          from: self,
+          prefilled: (viewModel.contact.nickname ?? viewModel.contact.username) ?? "",
+          viewModel.didTapAccept(_:)
+        )
+      }.store(in: &cancellables)
+
+    screenView.receivedView.reject
+      .publisher(for: .touchUpInside)
+      .sink { [weak viewModel] in viewModel?.didTapReject() }
+      .store(in: &cancellables)
+  }
+
+  private func setupInProgressBindings() {
+    viewModel.statePublisher
+      .map(\.username)
+      .removeDuplicates()
+      .combineLatest(
+        viewModel.statePublisher.map(\.email).removeDuplicates(),
+        viewModel.statePublisher.map(\.phone).removeDuplicates()
+      )
+      .sink { [unowned self] in
+        [Localized.Contact.username: $0.0,
+         Localized.Contact.email: $0.1,
+         Localized.Contact.phone: $0.2].forEach { pair in
+          guard let value = pair.value else { return }
+
+          let attributeView = AttributeComponent()
+          attributeView.set(
+            title: pair.key,
+            value: value
+          )
+
+          screenView.inProgressView.stack.addArrangedSubview(attributeView)
         }
-
-        screenView.set(status: viewModel.contact.authStatus)
-    }
-
-    private func setupScrollView() {
-        addChild(scrollViewController)
-        view.addSubview(scrollViewController.view)
-        scrollViewController.view.backgroundColor = Asset.neutralWhite.color
-        scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
-        scrollViewController.didMove(toParent: self)
-        scrollViewController.contentView = screenView
-        scrollViewController.scrollView.bounces = false
-    }
-
-    private func setupBindings() {
-        viewModel.hudPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [hud] in hud.update(with: $0) }
-            .store(in: &cancellables)
-
-        screenView.cardComponent.avatarView.editButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toPhotos(from: self) }
-            .store(in: &cancellables)
-
-        viewModel.statePublisher
-            .map(\.photo)
-            .compactMap { $0 }
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.cardComponent.image = $0 }
-            .store(in: &cancellables)
-
-        viewModel.statePublisher
-            .map(\.title)
-            .compactMap { $0 }
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.cardComponent.nameLabel.text = $0 }
-            .store(in: &cancellables)
-
-        viewModel.popPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in navigationController?.popViewController(animated: true) }
-            .store(in: &cancellables)
-
-        viewModel.popToRootPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in navigationController?.popToRootViewController(animated: true) }
-            .store(in: &cancellables)
-
-        viewModel.successPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.updateToSuccess() }
-            .store(in: &cancellables)
-
-        setupScannedBindings()
-        setupReceivedBindings()
-        setupConfirmedBindings()
-        setupInProgressBindings()
-        setupSuccessBindings()
-    }
-
-    private func setupSuccessBindings() {
-        screenView.successView.keepAdding
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in navigationController?.popViewController(animated: true) }
-            .store(in: &cancellables)
-
-        screenView.successView.sentRequests
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in coordinator.toRequests(from: self) }
-            .store(in: &cancellables)
-
-        viewModel.statePublisher
-            .map(\.username)
-            .removeDuplicates()
-            .combineLatest(
-                viewModel.statePublisher.map(\.email).removeDuplicates(),
-                viewModel.statePublisher.map(\.phone).removeDuplicates()
+      }.store(in: &cancellables)
+
+    screenView.inProgressView.feedback
+      .button.publisher(for: .touchUpInside)
+      .sink { [weak viewModel] in viewModel?.didTapResend() }
+      .store(in: &cancellables)
+  }
+
+  private func setupConfirmedBindings() {
+    viewModel.statePublisher
+      .receive(on: DispatchQueue.main)
+      .map(\.nickname)
+      .removeDuplicates()
+      .combineLatest(
+        viewModel.statePublisher.map(\.username).removeDuplicates(),
+        viewModel.statePublisher.map(\.email).removeDuplicates(),
+        viewModel.statePublisher.map(\.phone).removeDuplicates()
+      )
+      .sink { [unowned self] in
+        screenView.confirmedView.stackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
+
+        let nicknameAttribute = AttributeComponent()
+        nicknameAttribute.set(title: Localized.Contact.nickname, value: $0.0, style: .requiredEditable)
+        screenView.confirmedView.stackView.insertArrangedSubview(nicknameAttribute, at: 0)
+
+        nicknameAttribute.actionButton.publisher(for: .touchUpInside)
+          .sink { [unowned self] in
+            coordinator.toNickname(
+              from: self,
+              prefilled: (viewModel.contact.nickname ?? viewModel.contact.username) ?? "",
+              viewModel.didUpdateNickname(_:)
             )
-            .sink { [unowned self] in
-                [Localized.Contact.username: $0.0,
-                 Localized.Contact.email: $0.1,
-                 Localized.Contact.phone: $0.2].forEach { pair in
-                    guard let value = pair.value else { return }
-
-                    let attributeView = AttributeComponent()
-                    attributeView.set(
-                        title: pair.key,
-                        value: value
-                    )
-
-                    screenView.successView.stack.addArrangedSubview(attributeView)
-                }
-            }.store(in: &cancellables)
-    }
-
-    private func setupScannedBindings() {
-        screenView.scannedView.add
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in
-                coordinator.toNickname(
-                    from: self,
-                    prefilled: (viewModel.contact.nickname ?? viewModel.contact.username) ?? "",
-                    viewModel.didTapRequest(with:)
-                )
-            }.store(in: &cancellables)
-    }
-
-    private func setupReceivedBindings() {
-        screenView.receivedView.accept
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in
-                coordinator.toNickname(
-                    from: self,
-                    prefilled: (viewModel.contact.nickname ?? viewModel.contact.username) ?? "",
-                    viewModel.didTapAccept(_:)
-                )
-            }.store(in: &cancellables)
-
-        screenView.receivedView.reject
-            .publisher(for: .touchUpInside)
-            .sink { [weak viewModel] in viewModel?.didTapReject() }
-            .store(in: &cancellables)
-    }
+          }
+          .store(in: &cancellables)
+
+        let usernameAttribute = AttributeComponent()
+        usernameAttribute.set(title: Localized.Contact.username, value: $0.1)
+        screenView.confirmedView.stackView.addArrangedSubview(usernameAttribute)
+
+        let emailAttribute = AttributeComponent()
+        emailAttribute.set(title: Localized.Contact.email, value: $0.2)
+        screenView.confirmedView.stackView.addArrangedSubview(emailAttribute)
+
+        let phoneAttribute = AttributeComponent()
+        phoneAttribute.set(title: Localized.Contact.phone, value: $0.3)
+        screenView.confirmedView.stackView.addArrangedSubview(phoneAttribute)
+
+        let deleteButton = RowButton()
+        deleteButton.setup(
+          title: Localized.Contact.Delete.Info.title,
+          icon: Asset.settingsDelete.image,
+          style: .delete,
+          separator: false
+        )
 
-    private func setupInProgressBindings() {
-        viewModel.statePublisher
-            .map(\.username)
-            .removeDuplicates()
-            .combineLatest(
-                viewModel.statePublisher.map(\.email).removeDuplicates(),
-                viewModel.statePublisher.map(\.phone).removeDuplicates()
-            )
-            .sink { [unowned self] in
-                [Localized.Contact.username: $0.0,
-                 Localized.Contact.email: $0.1,
-                 Localized.Contact.phone: $0.2].forEach { pair in
-                    guard let value = pair.value else { return }
-
-                    let attributeView = AttributeComponent()
-                    attributeView.set(
-                        title: pair.key,
-                        value: value
-                    )
-
-                    screenView.inProgressView.stack.addArrangedSubview(attributeView)
-                }
-            }.store(in: &cancellables)
-
-        screenView.inProgressView.feedback
-            .button.publisher(for: .touchUpInside)
-            .sink { [weak viewModel] in viewModel?.didTapResend() }
-            .store(in: &cancellables)
-    }
+        screenView.confirmedView.stackView.addArrangedSubview(deleteButton)
+
+        deleteButton.publisher(for: .touchUpInside)
+          .sink { [unowned self] in presentDeleteInfo() }
+          .store(in: &cancellables)
+      }.store(in: &cancellables)
+
+    screenView.confirmedView.clearButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in presentClearDrawer() }
+      .store(in: &cancellables)
+  }
+
+  private func presentClearDrawer() {
+    let clearButton = CapsuleButton()
+    clearButton.setStyle(.red)
+    clearButton.setTitle(Localized.Contact.Clear.action, for: .normal)
+
+    let cancelButton = CapsuleButton()
+    cancelButton.setStyle(.seeThrough)
+    cancelButton.setTitle(Localized.Contact.Clear.cancel, for: .normal)
+
+    let drawer = DrawerController(with: [
+      DrawerImage(
+        image: Asset.drawerNegative.image
+      ),
+      DrawerText(
+        font: Fonts.Mulish.semiBold.font(size: 18.0),
+        text: Localized.Contact.Clear.title,
+        color: Asset.neutralActive.color
+      ),
+      DrawerText(
+        font: Fonts.Mulish.semiBold.font(size: 14.0),
+        text: Localized.Contact.Clear.subtitle,
+        color: Asset.neutralWeak.color,
+        lineHeightMultiple: 1.35,
+        spacingAfter: 25
+      ),
+      DrawerStack(
+        spacing: 20.0,
+        views: [clearButton, cancelButton]
+      )
+    ])
+
+    clearButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didTapClear()
+        }
+      }.store(in: &drawerCancellables)
 
-    private func setupConfirmedBindings() {
-        viewModel.statePublisher
-            .receive(on: DispatchQueue.main)
-            .map(\.nickname)
-            .removeDuplicates()
-            .combineLatest(
-                viewModel.statePublisher.map(\.username).removeDuplicates(),
-                viewModel.statePublisher.map(\.email).removeDuplicates(),
-                viewModel.statePublisher.map(\.phone).removeDuplicates()
-            )
-            .sink { [unowned self] in
-                screenView.confirmedView.stackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
-
-                let nicknameAttribute = AttributeComponent()
-                nicknameAttribute.set(title: Localized.Contact.nickname, value: $0.0, style: .requiredEditable)
-                screenView.confirmedView.stackView.insertArrangedSubview(nicknameAttribute, at: 0)
-
-                nicknameAttribute.actionButton.publisher(for: .touchUpInside)
-                    .sink { [unowned self] in
-                        coordinator.toNickname(
-                            from: self,
-                            prefilled: (viewModel.contact.nickname ?? viewModel.contact.username) ?? "",
-                            viewModel.didUpdateNickname(_:)
-                        )
-                    }
-                    .store(in: &cancellables)
-
-                let usernameAttribute = AttributeComponent()
-                usernameAttribute.set(title: Localized.Contact.username, value: $0.1)
-                screenView.confirmedView.stackView.addArrangedSubview(usernameAttribute)
-
-                let emailAttribute = AttributeComponent()
-                emailAttribute.set(title: Localized.Contact.email, value: $0.2)
-                screenView.confirmedView.stackView.addArrangedSubview(emailAttribute)
-
-                let phoneAttribute = AttributeComponent()
-                phoneAttribute.set(title: Localized.Contact.phone, value: $0.3)
-                screenView.confirmedView.stackView.addArrangedSubview(phoneAttribute)
-
-                let deleteButton = RowButton()
-                deleteButton.setup(
-                    title: Localized.Contact.Delete.Info.title,
-                    icon: Asset.settingsDelete.image,
-                    style: .delete,
-                    separator: false
-                )
-
-                screenView.confirmedView.stackView.addArrangedSubview(deleteButton)
-
-                deleteButton.publisher(for: .touchUpInside)
-                    .sink { [unowned self] in presentDeleteInfo() }
-                    .store(in: &cancellables)
-            }.store(in: &cancellables)
-
-        screenView.confirmedView.clearButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in presentClearDrawer() }
-            .store(in: &cancellables)
-    }
+    cancelButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          self?.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-    private func presentClearDrawer() {
-        let clearButton = CapsuleButton()
-        clearButton.setStyle(.red)
-        clearButton.setTitle(Localized.Contact.Clear.action, for: .normal)
-
-        let cancelButton = CapsuleButton()
-        cancelButton.setStyle(.seeThrough)
-        cancelButton.setTitle(Localized.Contact.Clear.cancel, for: .normal)
-
-        let drawer = DrawerController(with: [
-            DrawerImage(
-                image: Asset.drawerNegative.image
-            ),
-            DrawerText(
-                font: Fonts.Mulish.semiBold.font(size: 18.0),
-                text: Localized.Contact.Clear.title,
-                color: Asset.neutralActive.color
-            ),
-            DrawerText(
-                font: Fonts.Mulish.semiBold.font(size: 14.0),
-                text: Localized.Contact.Clear.subtitle,
-                color: Asset.neutralWeak.color,
-                lineHeightMultiple: 1.35,
-                spacingAfter: 25
-            ),
-            DrawerStack(
-                spacing: 20.0,
-                views: [clearButton, cancelButton]
-            )
-        ])
-
-        clearButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                    self.viewModel.didTapClear()
-                }
-            }.store(in: &drawerCancellables)
-
-        cancelButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    self?.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+    coordinator.toDrawer(drawer, from: self)
+  }
 }
 
 extension ContactController: UIImagePickerControllerDelegate {
-    public func imagePickerController(
-        _ picker: UIImagePickerController,
-        didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]
-    ) {
-        var image: UIImage?
-
-        if let originalImage = info[.originalImage] as? UIImage {
-            image = originalImage
-        }
-
-        if let croppedImage = info[.editedImage] as? UIImage {
-            image = croppedImage
-        }
+  public func imagePickerController(
+    _ picker: UIImagePickerController,
+    didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]
+  ) {
+    var image: UIImage?
+
+    if let originalImage = info[.originalImage] as? UIImage {
+      image = originalImage
+    }
 
-        guard let image = image else {
-            picker.dismiss(animated: true)
-            return
-        }
+    if let croppedImage = info[.editedImage] as? UIImage {
+      image = croppedImage
+    }
 
-        picker.dismiss(animated: true)
-        viewModel.didChoosePhoto(image)
+    guard let image = image else {
+      picker.dismiss(animated: true)
+      return
     }
+
+    picker.dismiss(animated: true)
+    viewModel.didChoosePhoto(image)
+  }
 }
 
 extension ContactController: UINavigationControllerDelegate {}
 
 extension ContactController {
-    private func presentInfo(
-        title: String,
-        subtitle: String,
-        urlString: String = ""
-    ) {
-        let actionButton = CapsuleButton()
-        actionButton.set(
-            style: .seeThrough,
-            title: Localized.Settings.InfoDrawer.action
-        )
-
-        let drawer = DrawerController(with: [
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerLinkText(
-                text: subtitle,
-                urlString: urlString,
-                spacingAfter: 37
-            ),
-            DrawerStack(views: [
-                actionButton,
-                FlexibleSpace()
-            ])
-        ])
-
-        actionButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+  private func presentInfo(
+    title: String,
+    subtitle: String,
+    urlString: String = ""
+  ) {
+    let actionButton = CapsuleButton()
+    actionButton.set(
+      style: .seeThrough,
+      title: Localized.Settings.InfoDrawer.action
+    )
+
+    let drawer = DrawerController(with: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerLinkText(
+        text: subtitle,
+        urlString: urlString,
+        spacingAfter: 37
+      ),
+      DrawerStack(views: [
+        actionButton,
+        FlexibleSpace()
+      ])
+    ])
+
+    actionButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    coordinator.toDrawer(drawer, from: self)
+  }
+
+  private func presentDeleteInfo() {
+    let actionButton = DrawerCapsuleButton(model: .init(
+      title: Localized.Contact.Delete.Info.title,
+      style: .red
+    ))
+
+    let drawer = DrawerController(with: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: Localized.Contact.Delete.Drawer.title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerText(
+        text: Localized.Contact.Delete.Drawer.description(viewModel.contact.username ?? ""),
+        spacingAfter: 37,
+        customAttributes: [.font:  Fonts.Mulish.bold.font(size: 16.0)]
+      ),
+      actionButton
+    ])
+
+    actionButton.action
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didTapDelete()
+        }
+      }.store(in: &drawerCancellables)
 
-    private func presentDeleteInfo() {
-        let actionButton = DrawerCapsuleButton(model: .init(
-            title: Localized.Contact.Delete.Info.title,
-            style: .red
-        ))
-
-        let drawer = DrawerController(with: [
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: Localized.Contact.Delete.Drawer.title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerText(
-                text: Localized.Contact.Delete.Drawer.description(viewModel.contact.username ?? ""),
-                spacingAfter: 37,
-                customAttributes: [.font:  Fonts.Mulish.bold.font(size: 16.0)]
-            ),
-            actionButton
-        ])
-
-        actionButton.action
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                    self.viewModel.didTapDelete()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+    coordinator.toDrawer(drawer, from: self)
+  }
 }
diff --git a/Sources/ContactListFeature/Controllers/ContactListController.swift b/Sources/ContactListFeature/Controllers/ContactListController.swift
index 1e09b9377139e9428ddb539c6ace95164f26bb1c..d7f9094b833da623928d8c197ddd468239cbe091 100644
--- a/Sources/ContactListFeature/Controllers/ContactListController.swift
+++ b/Sources/ContactListFeature/Controllers/ContactListController.swift
@@ -1,135 +1,134 @@
 import UIKit
-import Theme
 import Shared
 import Combine
 import DependencyInjection
 
 public final class ContactListController: UIViewController {
-    @Dependency private var coordinator: ContactListCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    lazy private var screenView = ContactListView()
-    lazy private var tableController = ContactListTableController(viewModel)
-
-    private let viewModel = ContactListViewModel()
-    private var cancellables = Set<AnyCancellable>()
-
-    public override func loadView() {
-        view = screenView
-    }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar.customize(backgroundColor: Asset.neutralWhite.color)
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupNavigationBar()
-        setupTableView()
-        setupBindings()
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: ContactListCoordinating
+
+  lazy private var screenView = ContactListView()
+  lazy private var tableController = ContactListTableController(viewModel)
+
+  private let viewModel = ContactListViewModel()
+  private var cancellables = Set<AnyCancellable>()
+
+  public override func loadView() {
+    view = screenView
+  }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar.customize(backgroundColor: Asset.neutralWhite.color)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupNavigationBar()
+    setupTableView()
+    setupBindings()
+  }
+
+  private func setupNavigationBar() {
+    navigationItem.backButtonTitle = " "
+
+    let titleLabel = UILabel()
+    titleLabel.text = Localized.ContactList.title
+    titleLabel.textColor = Asset.neutralActive.color
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 18.0)
+
+    let menuButton = UIButton()
+    menuButton.tintColor = Asset.neutralDark.color
+    menuButton.setImage(Asset.chatListMenu.image, for: .normal)
+    menuButton.addTarget(self, action: #selector(didTapMenu), for: .touchUpInside)
+    menuButton.snp.makeConstraints { $0.width.equalTo(50) }
+
+    navigationItem.leftBarButtonItem = UIBarButtonItem(
+      customView: UIStackView(arrangedSubviews: [menuButton, titleLabel])
+    )
+
+    let search = UIButton()
+    search.tintColor = Asset.neutralActive.color
+    search.setImage(Asset.contactListSearch.image, for: .normal)
+    search.addTarget(self, action: #selector(didTapSearch), for: .touchUpInside)
+    search.accessibilityIdentifier = Localized.Accessibility.ContactList.search
+
+    let scanButton = UIButton()
+    scanButton.setImage(Asset.sharedScan.image, for: .normal)
+    scanButton.addTarget(self, action: #selector(didTapScan), for: .touchUpInside)
+
+    let rightStack = UIStackView()
+    rightStack.spacing = 15
+    rightStack.addArrangedSubview(scanButton)
+    rightStack.addArrangedSubview(search)
+
+    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: rightStack)
+
+    search.snp.makeConstraints { $0.width.equalTo(40) }
+  }
+
+  private func setupTableView() {
+    addChild(tableController)
+    screenView.addSubview(tableController.view)
+
+    tableController.view.snp.makeConstraints { make in
+      make.top.equalTo(screenView.topStackView.snp.bottom)
+      make.left.bottom.right.equalToSuperview()
     }
 
-    private func setupNavigationBar() {
-        navigationItem.backButtonTitle = " "
-
-        let titleLabel = UILabel()
-        titleLabel.text = Localized.ContactList.title
-        titleLabel.textColor = Asset.neutralActive.color
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 18.0)
-
-        let menuButton = UIButton()
-        menuButton.tintColor = Asset.neutralDark.color
-        menuButton.setImage(Asset.chatListMenu.image, for: .normal)
-        menuButton.addTarget(self, action: #selector(didTapMenu), for: .touchUpInside)
-        menuButton.snp.makeConstraints { $0.width.equalTo(50) }
-
-        navigationItem.leftBarButtonItem = UIBarButtonItem(
-            customView: UIStackView(arrangedSubviews: [menuButton, titleLabel])
-        )
-
-        let search = UIButton()
-        search.tintColor = Asset.neutralActive.color
-        search.setImage(Asset.contactListSearch.image, for: .normal)
-        search.addTarget(self, action: #selector(didTapSearch), for: .touchUpInside)
-        search.accessibilityIdentifier = Localized.Accessibility.ContactList.search
-
-        let scanButton = UIButton()
-        scanButton.setImage(Asset.sharedScan.image, for: .normal)
-        scanButton.addTarget(self, action: #selector(didTapScan), for: .touchUpInside)
-
-        let rightStack = UIStackView()
-        rightStack.spacing = 15
-        rightStack.addArrangedSubview(scanButton)
-        rightStack.addArrangedSubview(search)
-
-        navigationItem.rightBarButtonItem = UIBarButtonItem(customView: rightStack)
-
-        search.snp.makeConstraints { $0.width.equalTo(40) }
-    }
-
-    private func setupTableView() {
-        addChild(tableController)
-        screenView.addSubview(tableController.view)
-
-        tableController.view.snp.makeConstraints { make in
-            make.top.equalTo(screenView.topStackView.snp.bottom)
-            make.left.bottom.right.equalToSuperview()
+    tableController.didMove(toParent: self)
+  }
+
+  private func setupBindings() {
+    tableController.didTap
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toSingleChat(with: $0, from: self) }
+      .store(in: &cancellables)
+
+    screenView.requestsButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toRequests(from: self) }
+      .store(in: &cancellables)
+
+    screenView.newGroupButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toNewGroup(from: self) }
+      .store(in: &cancellables)
+
+    screenView.searchButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toSearch(from: self) }
+      .store(in: &cancellables)
+
+    viewModel.requestCount
+      .receive(on: DispatchQueue.main)
+      .sink { [weak screenView] in screenView?.requestsButton.updateNotification($0) }
+      .store(in: &cancellables)
+
+    viewModel.contacts
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.stackView.isHidden = !$0.isEmpty
+
+        if $0.isEmpty {
+          screenView.bringSubviewToFront(screenView.stackView)
         }
+      }.store(in: &cancellables)
+  }
 
-        tableController.didMove(toParent: self)
-    }
-
-    private func setupBindings() {
-        tableController.didTap
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toSingleChat(with: $0, from: self) }
-            .store(in: &cancellables)
-
-        screenView.requestsButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toRequests(from: self) }
-            .store(in: &cancellables)
-
-        screenView.newGroupButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toNewGroup(from: self) }
-            .store(in: &cancellables)
-
-        screenView.searchButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toSearch(from: self) }
-            .store(in: &cancellables)
-
-        viewModel.requestCount
-            .receive(on: DispatchQueue.main)
-            .sink { [weak screenView] in screenView?.requestsButton.updateNotification($0) }
-            .store(in: &cancellables)
-
-        viewModel.contacts
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                screenView.stackView.isHidden = !$0.isEmpty
-
-                if $0.isEmpty {
-                    screenView.bringSubviewToFront(screenView.stackView)
-                }
-            }.store(in: &cancellables)
-    }
-
-    @objc private func didTapSearch() {
-        coordinator.toSearch(from: self)
-    }
+  @objc private func didTapSearch() {
+    coordinator.toSearch(from: self)
+  }
 
-    @objc private func didTapScan() {
-        coordinator.toScan(from: self)
-    }
+  @objc private func didTapScan() {
+    coordinator.toScan(from: self)
+  }
 
-    @objc private func didTapMenu() {
-        coordinator.toSideMenu(from: self)
-    }
+  @objc private func didTapMenu() {
+    coordinator.toSideMenu(from: self)
+  }
 }
diff --git a/Sources/Countries/CountryListController.swift b/Sources/Countries/CountryListController.swift
index a11c0e5724696bc172f58cfdc7b4333288639b7f..633633f1a921be0183cd00effe2f3e73080105b6 100644
--- a/Sources/Countries/CountryListController.swift
+++ b/Sources/Countries/CountryListController.swift
@@ -1,93 +1,92 @@
 import os
-import Theme
 import UIKit
 import Shared
 import Combine
 import DependencyInjection
 
 public final class CountryListController: UIViewController {
-    @Dependency private var statusBarController: StatusBarStyleControlling
-    
-    lazy private var screenView = CountryListView()
-
-    private var didChoose: ((Country) -> Void)!
-    private let viewModel = CountryListViewModel()
-    private var cancellables = Set<AnyCancellable>()
-    private var dataSource: UITableViewDiffableDataSource<SectionId, Country>!
-
-    public init(_ didChoose: @escaping (Country) -> Void) {
-        self.didChoose = didChoose
-        super.init(nibName: nil, bundle: nil)
+  @Dependency var barStylist: StatusBarStylist
+
+  lazy private var screenView = CountryListView()
+
+  private var didChoose: ((Country) -> Void)!
+  private let viewModel = CountryListViewModel()
+  private var cancellables = Set<AnyCancellable>()
+  private var dataSource: UITableViewDiffableDataSource<SectionId, Country>!
+
+  public init(_ didChoose: @escaping (Country) -> Void) {
+    self.didChoose = didChoose
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    barStylist.styleSubject.send(.darkContent)
+
+    navigationController?.navigationBar.customize(
+      backgroundColor: Asset.neutralWhite.color,
+      shadowColor: Asset.neutralDisabled.color
+    )
+  }
+
+  public override func loadView() {
+    view = screenView
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    screenView.tableView.register(CountryListCell.self)
+    setupNavigationBar()
+    setupBindings()
+
+    viewModel.fetchCountryList()
+  }
+
+  private func setupNavigationBar() {
+    let title = UILabel()
+    title.text = Localized.Countries.title
+    title.textColor = Asset.neutralActive.color
+    title.font = Fonts.Mulish.semiBold.font(size: 18.0)
+
+    navigationItem.leftBarButtonItem = UIBarButtonItem(customView: title)
+    navigationItem.leftItemsSupplementBackButton = true
+  }
+
+  private func setupBindings() {
+    viewModel.countries
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in dataSource.apply($0, animatingDifferences: false) }
+      .store(in: &cancellables)
+
+    dataSource = UITableViewDiffableDataSource<SectionId, Country>(
+      tableView: screenView.tableView
+    ) { tableView, indexPath, country in
+      let cell: CountryListCell = tableView.dequeueReusableCell(forIndexPath: indexPath)
+      cell.flagLabel.text = country.flag
+      cell.nameLabel.text = country.name
+      cell.prefixLabel.text = country.prefix
+      return cell
     }
 
-    required init?(coder: NSCoder) { nil }
+    screenView.searchComponent
+      .textPublisher
+      .removeDuplicates()
+      .sink { [unowned self] in viewModel.didSearchFor($0) }
+      .store(in: &cancellables)
 
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        statusBarController.style.send(.darkContent)
+    screenView.tableView.delegate = self
+    screenView.tableView.dataSource = dataSource
+  }
 
-        navigationController?.navigationBar.customize(
-            backgroundColor: Asset.neutralWhite.color,
-            shadowColor: Asset.neutralDisabled.color
-        )
-    }
-
-    public override func loadView() {
-        view = screenView
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        screenView.tableView.register(CountryListCell.self)
-        setupNavigationBar()
-        setupBindings()
-
-        viewModel.fetchCountryList()
-    }
-    
-    private func setupNavigationBar() {
-        let title = UILabel()
-        title.text = Localized.Countries.title
-        title.textColor = Asset.neutralActive.color
-        title.font = Fonts.Mulish.semiBold.font(size: 18.0)
-
-        navigationItem.leftBarButtonItem = UIBarButtonItem(customView: title)
-        navigationItem.leftItemsSupplementBackButton = true
-    }
-
-    private func setupBindings() {
-        viewModel.countries
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in dataSource.apply($0, animatingDifferences: false) }
-            .store(in: &cancellables)
-
-        dataSource = UITableViewDiffableDataSource<SectionId, Country>(
-            tableView: screenView.tableView
-        ) { tableView, indexPath, country in
-            let cell: CountryListCell = tableView.dequeueReusableCell(forIndexPath: indexPath)
-            cell.flagLabel.text = country.flag
-            cell.nameLabel.text = country.name
-            cell.prefixLabel.text = country.prefix
-            return cell
-        }
-
-        screenView.searchComponent
-            .textPublisher
-            .removeDuplicates()
-            .sink { [unowned self] in viewModel.didSearchFor($0) }
-            .store(in: &cancellables)
-
-        screenView.tableView.delegate = self
-        screenView.tableView.dataSource = dataSource
-    }
-
-    public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        if let country = dataSource.itemIdentifier(for: indexPath) {
-            didChoose(country)
-            navigationController?.popViewController(animated: true)
-        }
+  public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+    if let country = dataSource.itemIdentifier(for: indexPath) {
+      didChoose(country)
+      navigationController?.popViewController(animated: true)
     }
+  }
 }
 
 extension CountryListController: UITableViewDelegate {}
diff --git a/Sources/Defaults/KeyObject.swift b/Sources/Defaults/KeyObject.swift
index 0ade4e83639f54a5181b4292936a2d9dee049f60..c864b9f9c9adcd70a62f5f8891fc8b71f9644a07 100644
--- a/Sources/Defaults/KeyObject.swift
+++ b/Sources/Defaults/KeyObject.swift
@@ -20,7 +20,6 @@ public enum Key: String {
 
     // MARK: General
 
-    case theme
     case acceptedTerms
 
     // MARK: Requests
diff --git a/Sources/HUD/HUD.swift b/Sources/HUD/HUD.swift
index 207f3473c9173a3a64c8636a8373d734d207807b..8850d8a2ee7a2e7be7fa7e20f36d0f8070973cb4 100644
--- a/Sources/HUD/HUD.swift
+++ b/Sources/HUD/HUD.swift
@@ -1,195 +1,194 @@
 import UIKit
-import Theme
 import Shared
 import Combine
 import SnapKit
 
 private enum Constants {
-    static let title = Localized.Hud.Error.title
-    static let action = Localized.Hud.Error.action
+  static let title = Localized.Hud.Error.title
+  static let action = Localized.Hud.Error.action
 }
 
 public enum HUDStatus: Equatable {
-    case none
-    case on
-    case onTitle(String)
-    case onAction(String)
-    case error(HUDError)
-
-    var isPresented: Bool {
-        switch self {
-        case .none:
-            return false
-        case .on, .error, .onTitle, .onAction:
-            return true
-        }
+  case none
+  case on
+  case onTitle(String)
+  case onAction(String)
+  case error(HUDError)
+
+  var isPresented: Bool {
+    switch self {
+    case .none:
+      return false
+    case .on, .error, .onTitle, .onAction:
+      return true
     }
+  }
 }
 
 public struct HUDError: Equatable {
-    var title: String
-    var content: String
-    var buttonTitle: String
-    var dismissable: Bool
-
-    public init(
-        content: String,
-        title: String? = nil,
-        buttonTitle: String? = nil,
-        dismissable: Bool = true
-    ) {
-        self.content = content
-        self.title = title ?? Constants.title
-        self.buttonTitle = buttonTitle ?? Constants.action
-        self.dismissable = dismissable
-    }
-
-    public init(with error: Error) {
-        self.title = Constants.title
-        self.buttonTitle = Constants.action
-        self.content = error.localizedDescription
-        self.dismissable = true
-    }
+  var title: String
+  var content: String
+  var buttonTitle: String
+  var dismissable: Bool
+
+  public init(
+    content: String,
+    title: String? = nil,
+    buttonTitle: String? = nil,
+    dismissable: Bool = true
+  ) {
+    self.content = content
+    self.title = title ?? Constants.title
+    self.buttonTitle = buttonTitle ?? Constants.action
+    self.dismissable = dismissable
+  }
+
+  public init(with error: Error) {
+    self.title = Constants.title
+    self.buttonTitle = Constants.action
+    self.content = error.localizedDescription
+    self.dismissable = true
+  }
 }
 
 public final class HUD {
-    private(set) var window: UIWindow?
-    private(set) var errorView: ErrorView?
-    private(set) var titleLabel: UILabel?
-    private(set) var animation: DotAnimation?
-    public var actionButton: CapsuleButton?
-    private var cancellables = Set<AnyCancellable>()
-
-    private var status: HUDStatus = .none {
-        didSet {
-            if oldValue.isPresented == true && status.isPresented == true {
-                self.errorView = nil
-                self.animation = nil
-                self.window = nil
-                self.actionButton = nil
-                self.titleLabel = nil
-
-                switch status {
-                case .on:
-                    animation = DotAnimation()
-
-                case .onTitle(let text):
-                    animation = DotAnimation()
-                    titleLabel = UILabel()
-                    titleLabel!.text = text
-
-                case .onAction(let title):
-                    animation = DotAnimation()
-                    actionButton = CapsuleButton()
-                    actionButton!.set(style: .seeThroughWhite, title: title)
-
-                case .error(let error):
-                    errorView = ErrorView(with: error)
-                case .none:
-                    break
-                }
-
-                showWindow()
-            }
-
-            if oldValue.isPresented == false && status.isPresented == true {
-                switch status {
-                case .on:
-                    animation = DotAnimation()
-
-                case .onTitle(let text):
-                    animation = DotAnimation()
-                    titleLabel = UILabel()
-                    titleLabel!.text = text
-
-                case .onAction(let title):
-                    animation = DotAnimation()
-                    actionButton = CapsuleButton()
-                    actionButton!.set(style: .seeThroughWhite, title: title)
-
-                case .error(let error):
-                    errorView = ErrorView(with: error)
-                case .none:
-                    break
-                }
-
-                showWindow()
-            }
-
-            if oldValue.isPresented == true && status.isPresented == false {
-                hideWindow()
-            }
+  private(set) var window: UIWindow?
+  private(set) var errorView: ErrorView?
+  private(set) var titleLabel: UILabel?
+  private(set) var animation: DotAnimation?
+  public var actionButton: CapsuleButton?
+  private var cancellables = Set<AnyCancellable>()
+
+  private var status: HUDStatus = .none {
+    didSet {
+      if oldValue.isPresented == true && status.isPresented == true {
+        self.errorView = nil
+        self.animation = nil
+        self.window = nil
+        self.actionButton = nil
+        self.titleLabel = nil
+
+        switch status {
+        case .on:
+          animation = DotAnimation()
+
+        case .onTitle(let text):
+          animation = DotAnimation()
+          titleLabel = UILabel()
+          titleLabel!.text = text
+
+        case .onAction(let title):
+          animation = DotAnimation()
+          actionButton = CapsuleButton()
+          actionButton!.set(style: .seeThroughWhite, title: title)
+
+        case .error(let error):
+          errorView = ErrorView(with: error)
+        case .none:
+          break
         }
-    }
 
-    public init() {}
+        showWindow()
+      }
 
-    public func update(with status: HUDStatus) {
-        self.status = status
-    }
+      if oldValue.isPresented == false && status.isPresented == true {
+        switch status {
+        case .on:
+          animation = DotAnimation()
 
-    private func showWindow() {
-        window = Window()
-        window?.backgroundColor = UIColor.black.withAlphaComponent(0.8)
-        window?.rootViewController = StatusBarViewController(nil)
+        case .onTitle(let text):
+          animation = DotAnimation()
+          titleLabel = UILabel()
+          titleLabel!.text = text
 
-        if let animation = animation {
-            window?.addSubview(animation)
-            animation.setColor(.white)
-            animation.snp.makeConstraints { $0.center.equalToSuperview() }
-        }
+        case .onAction(let title):
+          animation = DotAnimation()
+          actionButton = CapsuleButton()
+          actionButton!.set(style: .seeThroughWhite, title: title)
 
-        if let titleLabel = titleLabel {
-            window?.addSubview(titleLabel)
-            titleLabel.textAlignment = .center
-            titleLabel.numberOfLines = 0
-            titleLabel.snp.makeConstraints { make in
-                make.left.equalToSuperview().offset(18)
-                make.center.equalToSuperview().offset(50)
-                make.right.equalToSuperview().offset(-18)
-            }
+        case .error(let error):
+          errorView = ErrorView(with: error)
+        case .none:
+          break
         }
 
-        if let actionButton = actionButton {
-            window?.addSubview(actionButton)
-            actionButton.snp.makeConstraints {
-                $0.left.equalToSuperview().offset(18)
-                $0.right.equalToSuperview().offset(-18)
-                $0.bottom.equalToSuperview().offset(-50)
-            }
-        }
+        showWindow()
+      }
 
-        if let errorView = errorView {
-            window?.addSubview(errorView)
-            errorView.snp.makeConstraints { make in
-                make.left.equalToSuperview().offset(18)
-                make.center.equalToSuperview()
-                make.right.equalToSuperview().offset(-18)
-            }
-
-            errorView.button
-                .publisher(for: .touchUpInside)
-                .receive(on: DispatchQueue.main)
-                .sink { [unowned self] in hideWindow() }
-                .store(in: &cancellables)
-        }
+      if oldValue.isPresented == true && status.isPresented == false {
+        hideWindow()
+      }
+    }
+  }
+
+  public init() {}
 
-        window?.alpha = 0.0
-        window?.makeKeyAndVisible()
+  public func update(with status: HUDStatus) {
+    self.status = status
+  }
 
-        UIView.animate(withDuration: 0.3) { self.window?.alpha = 1.0 }
+  private func showWindow() {
+    window = UIWindow(frame: UIScreen.main.bounds)
+    window?.backgroundColor = UIColor.black.withAlphaComponent(0.8)
+    window?.rootViewController = RootViewController(nil)
+
+    if let animation = animation {
+      window?.addSubview(animation)
+      animation.setColor(.white)
+      animation.snp.makeConstraints { $0.center.equalToSuperview() }
     }
 
-    private func hideWindow() {
-        UIView.animate(withDuration: 0.3) {
-            self.window?.alpha = 0.0
-        } completion: { _ in
-            self.cancellables.removeAll()
-            self.errorView = nil
-            self.animation = nil
-            self.actionButton = nil
-            self.titleLabel = nil
-            self.window = nil
-        }
+    if let titleLabel = titleLabel {
+      window?.addSubview(titleLabel)
+      titleLabel.textAlignment = .center
+      titleLabel.numberOfLines = 0
+      titleLabel.snp.makeConstraints { make in
+        make.left.equalToSuperview().offset(18)
+        make.center.equalToSuperview().offset(50)
+        make.right.equalToSuperview().offset(-18)
+      }
+    }
+
+    if let actionButton = actionButton {
+      window?.addSubview(actionButton)
+      actionButton.snp.makeConstraints {
+        $0.left.equalToSuperview().offset(18)
+        $0.right.equalToSuperview().offset(-18)
+        $0.bottom.equalToSuperview().offset(-50)
+      }
+    }
+
+    if let errorView = errorView {
+      window?.addSubview(errorView)
+      errorView.snp.makeConstraints { make in
+        make.left.equalToSuperview().offset(18)
+        make.center.equalToSuperview()
+        make.right.equalToSuperview().offset(-18)
+      }
+
+      errorView.button
+        .publisher(for: .touchUpInside)
+        .receive(on: DispatchQueue.main)
+        .sink { [unowned self] in hideWindow() }
+        .store(in: &cancellables)
+    }
+
+    window?.alpha = 0.0
+    window?.makeKeyAndVisible()
+
+    UIView.animate(withDuration: 0.3) { self.window?.alpha = 1.0 }
+  }
+
+  private func hideWindow() {
+    UIView.animate(withDuration: 0.3) {
+      self.window?.alpha = 0.0
+    } completion: { _ in
+      self.cancellables.removeAll()
+      self.errorView = nil
+      self.animation = nil
+      self.actionButton = nil
+      self.titleLabel = nil
+      self.window = nil
     }
+  }
 }
diff --git a/Sources/LaunchFeature/LaunchController.swift b/Sources/LaunchFeature/LaunchController.swift
index 651da26c6449cc120fdc33c640aaac51cb07154c..fe5d10cbead95e6ca6433a600325cbceca1f13d7 100644
--- a/Sources/LaunchFeature/LaunchController.swift
+++ b/Sources/LaunchFeature/LaunchController.swift
@@ -7,156 +7,155 @@ import PushFeature
 import DependencyInjection
 
 public final class LaunchController: UIViewController {
-    @Dependency private var hud: HUD
-    @Dependency private var coordinator: LaunchCoordinating
-
-    @KeyObject(.acceptedTerms, defaultValue: false) var didAcceptTerms: Bool
-
-    lazy private var screenView = LaunchView()
-
-    private let blocker = UpdateBlocker()
-    private let viewModel = LaunchViewModel()
-    public var pendingPushRoute: PushRouter.Route?
-    private var cancellables = Set<AnyCancellable>()
-
-    public override func viewDidAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-        viewModel.viewDidAppear()
-    }
-
-    public override func loadView() {
-        view = screenView
-    }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationController?
-            .navigationBar
-            .customize(translucent: true)
+  @Dependency var hud: HUD
+  @Dependency var coordinator: LaunchCoordinating
+
+  @KeyObject(.acceptedTerms, defaultValue: false) var didAcceptTerms: Bool
+
+  lazy private var screenView = LaunchView()
+
+  private let viewModel = LaunchViewModel()
+  public var pendingPushRoute: PushRouter.Route?
+  private var cancellables = Set<AnyCancellable>()
+
+  public override func viewDidAppear(_ animated: Bool) {
+    super.viewDidAppear(animated)
+    viewModel.viewDidAppear()
+  }
+
+  public override func loadView() {
+    view = screenView
+  }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationController?
+      .navigationBar
+      .customize(translucent: true)
+  }
+
+  public override func viewDidLayoutSubviews() {
+    super.viewDidLayoutSubviews()
+    screenView.setupGradient()
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+
+    viewModel.hudPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [hud] in hud.update(with: $0) }
+      .store(in: &cancellables)
+
+    viewModel.routePublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        switch $0 {
+        case .chats:
+          guard didAcceptTerms == true else {
+            coordinator.toTerms(from: self)
+            return
+          }
+
+          if let pushRoute = pendingPushRoute {
+            switch pushRoute {
+            case .requests:
+              coordinator.toRequests(from: self)
+
+            case .search(username: let username):
+              coordinator.toSearch(searching: username, from: self)
+
+            case .groupChat(id: let groupId):
+              if let groupInfo = viewModel.getGroupInfoWith(groupId: groupId) {
+                coordinator.toGroupChat(with: groupInfo, from: self)
+                return
+              }
+              coordinator.toChats(from: self)
+
+            case .contactChat(id: let userId):
+              if let contact = viewModel.getContactWith(userId: userId) {
+                coordinator.toSingleChat(with: contact, from: self)
+                return
+              }
+              coordinator.toChats(from: self)
+            }
+
+            return
+          }
+
+          coordinator.toChats(from: self)
+
+        case .onboarding:
+          coordinator.toOnboarding(from: self)
+
+        case .update(let model):
+          offerUpdate(model: model)
+        }
+      }.store(in: &cancellables)
+  }
+
+  private func offerUpdate(model: Update) {
+    let drawerView = UIView()
+    drawerView.backgroundColor = Asset.neutralSecondary.color
+    drawerView.layer.cornerRadius = 5
+
+    let vStack = UIStackView()
+    vStack.axis = .vertical
+    vStack.spacing = 10
+    drawerView.addSubview(vStack)
+
+    vStack.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(18)
+      $0.left.equalToSuperview().offset(18)
+      $0.right.equalToSuperview().offset(-18)
+      $0.bottom.equalToSuperview().offset(-18)
     }
 
-    public override func viewDidLayoutSubviews() {
-        super.viewDidLayoutSubviews()
-        screenView.setupGradient()
+    let title = UILabel()
+    title.text = "App Update"
+    title.textAlignment = .center
+    title.textColor = Asset.neutralDark.color
+
+    let body = UILabel()
+    body.numberOfLines = 0
+    body.textAlignment = .center
+    body.textColor = Asset.neutralDark.color
+
+    let update = CapsuleButton()
+    update.publisher(for: .touchUpInside)
+      .sink { UIApplication.shared.open(.init(string: model.urlString)!, options: [:]) }
+      .store(in: &cancellables)
+
+    vStack.addArrangedSubview(title)
+    vStack.addArrangedSubview(body)
+    vStack.addArrangedSubview(update)
+
+    body.text = model.content
+    update.set(
+      style: model.actionStyle,
+      title: model.positiveActionTitle
+    )
+
+    if let negativeTitle = model.negativeActionTitle {
+      let negativeButton = CapsuleButton()
+      negativeButton.set(style: .simplestColoredRed, title: negativeTitle)
+
+      negativeButton.publisher(for: .touchUpInside)
+        .sink { [unowned self] in
+          blocker.hideWindow()
+          viewModel.continueWithInitialization()
+        }.store(in: &cancellables)
+
+      vStack.addArrangedSubview(negativeButton)
     }
 
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-
-        viewModel.hudPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [hud] in hud.update(with: $0) }
-            .store(in: &cancellables)
-
-        viewModel.routePublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                switch $0 {
-                case .chats:
-                    guard didAcceptTerms == true else {
-                        coordinator.toTerms(from: self)
-                        return
-                    }
-
-                    if let pushRoute = pendingPushRoute {
-                        switch pushRoute {
-                        case .requests:
-                            coordinator.toRequests(from: self)
-
-                        case .search(username: let username):
-                            coordinator.toSearch(searching: username, from: self)
-
-                        case .groupChat(id: let groupId):
-                            if let groupInfo = viewModel.getGroupInfoWith(groupId: groupId) {
-                                coordinator.toGroupChat(with: groupInfo, from: self)
-                                return
-                            }
-                            coordinator.toChats(from: self)
-
-                        case .contactChat(id: let userId):
-                            if let contact = viewModel.getContactWith(userId: userId) {
-                                coordinator.toSingleChat(with: contact, from: self)
-                                return
-                            }
-                            coordinator.toChats(from: self)
-                        }
-
-                        return
-                    }
-
-                    coordinator.toChats(from: self)
-
-                case .onboarding:
-                    coordinator.toOnboarding(from: self)
-
-                case .update(let model):
-                    offerUpdate(model: model)
-                }
-            }.store(in: &cancellables)
+    blocker.window?.addSubview(drawerView)
+    drawerView.snp.makeConstraints {
+      $0.left.equalToSuperview().offset(18)
+      $0.center.equalToSuperview()
+      $0.right.equalToSuperview().offset(-18)
     }
 
-    private func offerUpdate(model: Update) {
-        let drawerView = UIView()
-        drawerView.backgroundColor = Asset.neutralSecondary.color
-        drawerView.layer.cornerRadius = 5
-
-        let vStack = UIStackView()
-        vStack.axis = .vertical
-        vStack.spacing = 10
-        drawerView.addSubview(vStack)
-
-        vStack.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(18)
-            $0.left.equalToSuperview().offset(18)
-            $0.right.equalToSuperview().offset(-18)
-            $0.bottom.equalToSuperview().offset(-18)
-        }
-
-        let title = UILabel()
-        title.text = "App Update"
-        title.textAlignment = .center
-        title.textColor = Asset.neutralDark.color
-
-        let body = UILabel()
-        body.numberOfLines = 0
-        body.textAlignment = .center
-        body.textColor = Asset.neutralDark.color
-
-        let update = CapsuleButton()
-        update.publisher(for: .touchUpInside)
-            .sink { UIApplication.shared.open(.init(string: model.urlString)!, options: [:]) }
-            .store(in: &cancellables)
-
-        vStack.addArrangedSubview(title)
-        vStack.addArrangedSubview(body)
-        vStack.addArrangedSubview(update)
-
-        body.text = model.content
-        update.set(
-            style: model.actionStyle,
-            title: model.positiveActionTitle
-        )
-
-        if let negativeTitle = model.negativeActionTitle {
-            let negativeButton = CapsuleButton()
-            negativeButton.set(style: .simplestColoredRed, title: negativeTitle)
-
-            negativeButton.publisher(for: .touchUpInside)
-                .sink { [unowned self] in
-                    blocker.hideWindow()
-                    viewModel.continueWithInitialization()
-                }.store(in: &cancellables)
-
-            vStack.addArrangedSubview(negativeButton)
-        }
-
-        blocker.window?.addSubview(drawerView)
-        drawerView.snp.makeConstraints {
-            $0.left.equalToSuperview().offset(18)
-            $0.center.equalToSuperview()
-            $0.right.equalToSuperview().offset(-18)
-        }
-
-        blocker.showWindow()
-    }
+    blocker.showWindow()
+  }
 }
diff --git a/Sources/LaunchFeature/LaunchViewModel.swift b/Sources/LaunchFeature/LaunchViewModel.swift
index 66ba1a1e0323cb8145fa9f623f147733b2dd4294..8eda0596d6817bb246d86620f22c7190a18ab908 100644
--- a/Sources/LaunchFeature/LaunchViewModel.swift
+++ b/Sources/LaunchFeature/LaunchViewModel.swift
@@ -8,7 +8,6 @@ import XXLogger
 import Keychain
 import Foundation
 import Permissions
-import ToastFeature
 import BackupFeature
 import VersionChecking
 import ReportingFeature
diff --git a/Sources/LaunchFeature/UpdateBlocker.swift b/Sources/LaunchFeature/UpdateBlocker.swift
deleted file mode 100644
index 571c2a527a33e8411c320cbc7b25fdec6145d399..0000000000000000000000000000000000000000
--- a/Sources/LaunchFeature/UpdateBlocker.swift
+++ /dev/null
@@ -1,24 +0,0 @@
-import UIKit
-import Theme
-import Shared
-
-final class UpdateBlocker {
-    private(set) var window: Window? = Window()
-
-    func showWindow() {
-        window?.backgroundColor = UIColor.black.withAlphaComponent(0.5)
-        window?.rootViewController = StatusBarViewController(nil)
-        window?.alpha = 0.0
-        window?.makeKeyAndVisible()
-
-        UIView.animate(withDuration: 0.3) { self.window?.alpha = 1.0 }
-    }
-
-    func hideWindow() {
-        UIView.animate(withDuration: 0.3) {
-            self.window?.alpha = 0.0
-        } completion: { _ in
-            self.window = nil
-        }
-    }
-}
diff --git a/Sources/MenuFeature/Controllers/MenuController.swift b/Sources/MenuFeature/Controllers/MenuController.swift
index 93f1fcf4a328da1f73f077b8f0f8806ceee0c7f5..49b86d3a90686a2b460d0256a8ff040376486672 100644
--- a/Sources/MenuFeature/Controllers/MenuController.swift
+++ b/Sources/MenuFeature/Controllers/MenuController.swift
@@ -1,4 +1,3 @@
-import Theme
 import UIKit
 import Shared
 import Combine
@@ -6,230 +5,230 @@ import DrawerFeature
 import DependencyInjection
 
 public enum MenuItem {
-    case join
-    case scan
-    case chats
-    case share
-    case profile
-    case contacts
-    case requests
-    case settings
-    case dashboard
+  case join
+  case scan
+  case chats
+  case share
+  case profile
+  case contacts
+  case requests
+  case settings
+  case dashboard
 }
 
 public final class MenuController: UIViewController {
-    @Dependency private var coordinator: MenuCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    lazy private var screenView = MenuView()
-
-    private let previousItem: MenuItem
-    private let viewModel = MenuViewModel()
-    private let previousController: UIViewController
-    private var cancellables = Set<AnyCancellable>()
-    private var drawerCancellables = Set<AnyCancellable>()
-
-    public init(
-        _ previousItem: MenuItem,
-        _ previousController: UIViewController
-    ) {
-        self.previousItem = previousItem
-        self.previousController = previousController
-        super.init(nibName: nil, bundle: nil)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func loadView() {
-        view = screenView
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-
-        screenView.headerView.set(
-            username: viewModel.username,
-            image: viewModel.avatar
-        )
-
-        screenView.select(item: previousItem)
-        screenView.xxdkVersionLabel.text = "XXDK \(viewModel.xxdk)"
-        screenView.buildLabel.text = Localized.Menu.build(viewModel.build)
-        screenView.versionLabel.text = Localized.Menu.version(viewModel.version)
-        setupBindings()
-    }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        statusBarController.style.send(.lightContent)
-    }
-
-    public override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-        statusBarController.style.send(.darkContent)
-    }
-
-    private func setupBindings() {
-        screenView.headerView.scanButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                dismiss(animated: true) { [weak self] in
-                    guard let self = self, self.previousItem != .scan else { return }
-                    self.coordinator.toFlow(.scan, from: self.previousController)
-                }
-            }.store(in: &cancellables)
-
-        screenView.headerView.nameButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                dismiss(animated: true) { [weak self] in
-                    guard let self = self, self.previousItem != .profile else { return }
-                    self.coordinator.toFlow(.profile, from: self.previousController)
-                }
-            }.store(in: &cancellables)
-
-        screenView.scanButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                dismiss(animated: true) { [weak self] in
-                    guard let self = self, self.previousItem != .scan else { return }
-                    self.coordinator.toFlow(.scan, from: self.previousController)
-                }
-            }.store(in: &cancellables)
-
-        screenView.chatsButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                dismiss(animated: true) { [weak self] in
-                    guard let self = self, self.previousItem != .chats else { return }
-                    self.coordinator.toFlow(.chats, from: self.previousController)
-                }
-            }.store(in: &cancellables)
-
-        screenView.contactsButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                dismiss(animated: true) { [weak self] in
-                    guard let self = self, self.previousItem != .contacts else { return }
-                    self.coordinator.toFlow(.contacts, from: self.previousController)
-                }
-            }.store(in: &cancellables)
-
-        screenView.settingsButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                dismiss(animated: true) { [weak self] in
-                    guard let self = self, self.previousItem != .settings else { return }
-                    self.coordinator.toFlow(.settings, from: self.previousController)
-                }
-            }.store(in: &cancellables)
-
-        screenView.dashboardButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                dismiss(animated: true) { [weak self] in
-                    guard let self = self, self.previousItem != .dashboard else { return }
-                    self.presentDrawer(
-                        title: Localized.ChatList.Dashboard.title,
-                        subtitle: Localized.ChatList.Dashboard.subtitle,
-                        actionTitle: Localized.ChatList.Dashboard.open) {
-                            guard let url = URL(string: "https://dashboard.xx.network") else { return }
-                            UIApplication.shared.open(url, options: [:])
-                        }
-                }
-            }.store(in: &cancellables)
-
-        screenView.requestsButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                dismiss(animated: true) { [weak self] in
-                    guard let self = self, self.previousItem != .requests else { return }
-                    self.coordinator.toFlow(.requests, from: self.previousController)
-                }
-            }.store(in: &cancellables)
-
-        screenView.joinButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                dismiss(animated: true) { [weak self] in
-                    guard let self = self, self.previousItem != .join else { return }
-                    self.presentDrawer(
-                        title: Localized.ChatList.Join.title,
-                        subtitle: Localized.ChatList.Join.subtitle,
-                        actionTitle: Localized.ChatList.Dashboard.open) {
-                            guard let url = URL(string: "https://xx.network") else { return }
-                            UIApplication.shared.open(url, options: [:])
-                        }
-                }
-            }.store(in: &cancellables)
-
-        screenView.shareButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                dismiss(animated: true) { [weak self] in
-                    guard let self = self, self.previousItem != .share else { return }
-                    self.coordinator.toActivityController(
-                        with: [Localized.Menu.shareContent(self.viewModel.referralDeeplink)],
-                        from: self.previousController
-                    )
-                }
-            }.store(in: &cancellables)
-
-        viewModel.requestCount
-            .receive(on: DispatchQueue.main)
-            .sink { [weak screenView] in screenView?.requestsButton.updateNotification($0) }
-            .store(in: &cancellables)
-    }
-
-    private func presentDrawer(
-        title: String,
-        subtitle: String,
-        actionTitle: String,
-        action: @escaping () -> Void
-    ) {
-        let actionButton = DrawerCapsuleButton(model: .init(
-            title: actionTitle,
-            style: .red
-        ))
-
-        let drawer = DrawerController(with: [
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerText(
-                font: Fonts.Mulish.regular.font(size: 16.0),
-                text: subtitle,
-                color: Asset.neutralBody.color,
-                alignment: .left,
-                lineHeightMultiple: 1.1,
-                spacingAfter: 39
-            ),
-            actionButton
-        ])
-
-        actionButton.action.receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                    action()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: previousController)
-    }
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: MenuCoordinating
+
+  lazy private var screenView = MenuView()
+
+  private let previousItem: MenuItem
+  private let viewModel = MenuViewModel()
+  private let previousController: UIViewController
+  private var cancellables = Set<AnyCancellable>()
+  private var drawerCancellables = Set<AnyCancellable>()
+
+  public init(
+    _ previousItem: MenuItem,
+    _ previousController: UIViewController
+  ) {
+    self.previousItem = previousItem
+    self.previousController = previousController
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func loadView() {
+    view = screenView
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+
+    screenView.headerView.set(
+      username: viewModel.username,
+      image: viewModel.avatar
+    )
+
+    screenView.select(item: previousItem)
+    screenView.xxdkVersionLabel.text = "XXDK \(viewModel.xxdk)"
+    screenView.buildLabel.text = Localized.Menu.build(viewModel.build)
+    screenView.versionLabel.text = Localized.Menu.version(viewModel.version)
+    setupBindings()
+  }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    barStylist.styleSubject.send(.lightContent)
+  }
+
+  public override func viewWillDisappear(_ animated: Bool) {
+    super.viewWillDisappear(animated)
+    barStylist.styleSubject.send(.darkContent)
+  }
+
+  private func setupBindings() {
+    screenView.headerView.scanButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak self] in
+          guard let self = self, self.previousItem != .scan else { return }
+          self.coordinator.toFlow(.scan, from: self.previousController)
+        }
+      }.store(in: &cancellables)
+
+    screenView.headerView.nameButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak self] in
+          guard let self = self, self.previousItem != .profile else { return }
+          self.coordinator.toFlow(.profile, from: self.previousController)
+        }
+      }.store(in: &cancellables)
+
+    screenView.scanButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak self] in
+          guard let self = self, self.previousItem != .scan else { return }
+          self.coordinator.toFlow(.scan, from: self.previousController)
+        }
+      }.store(in: &cancellables)
+
+    screenView.chatsButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak self] in
+          guard let self = self, self.previousItem != .chats else { return }
+          self.coordinator.toFlow(.chats, from: self.previousController)
+        }
+      }.store(in: &cancellables)
+
+    screenView.contactsButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak self] in
+          guard let self = self, self.previousItem != .contacts else { return }
+          self.coordinator.toFlow(.contacts, from: self.previousController)
+        }
+      }.store(in: &cancellables)
+
+    screenView.settingsButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak self] in
+          guard let self = self, self.previousItem != .settings else { return }
+          self.coordinator.toFlow(.settings, from: self.previousController)
+        }
+      }.store(in: &cancellables)
+
+    screenView.dashboardButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak self] in
+          guard let self = self, self.previousItem != .dashboard else { return }
+          self.presentDrawer(
+            title: Localized.ChatList.Dashboard.title,
+            subtitle: Localized.ChatList.Dashboard.subtitle,
+            actionTitle: Localized.ChatList.Dashboard.open) {
+              guard let url = URL(string: "https://dashboard.xx.network") else { return }
+              UIApplication.shared.open(url, options: [:])
+            }
+        }
+      }.store(in: &cancellables)
+
+    screenView.requestsButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak self] in
+          guard let self = self, self.previousItem != .requests else { return }
+          self.coordinator.toFlow(.requests, from: self.previousController)
+        }
+      }.store(in: &cancellables)
+
+    screenView.joinButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak self] in
+          guard let self = self, self.previousItem != .join else { return }
+          self.presentDrawer(
+            title: Localized.ChatList.Join.title,
+            subtitle: Localized.ChatList.Join.subtitle,
+            actionTitle: Localized.ChatList.Dashboard.open) {
+              guard let url = URL(string: "https://xx.network") else { return }
+              UIApplication.shared.open(url, options: [:])
+            }
+        }
+      }.store(in: &cancellables)
+
+    screenView.shareButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak self] in
+          guard let self = self, self.previousItem != .share else { return }
+          self.coordinator.toActivityController(
+            with: [Localized.Menu.shareContent(self.viewModel.referralDeeplink)],
+            from: self.previousController
+          )
+        }
+      }.store(in: &cancellables)
+
+    viewModel.requestCount
+      .receive(on: DispatchQueue.main)
+      .sink { [weak screenView] in screenView?.requestsButton.updateNotification($0) }
+      .store(in: &cancellables)
+  }
+
+  private func presentDrawer(
+    title: String,
+    subtitle: String,
+    actionTitle: String,
+    action: @escaping () -> Void
+  ) {
+    let actionButton = DrawerCapsuleButton(model: .init(
+      title: actionTitle,
+      style: .red
+    ))
+
+    let drawer = DrawerController(with: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerText(
+        font: Fonts.Mulish.regular.font(size: 16.0),
+        text: subtitle,
+        color: Asset.neutralBody.color,
+        alignment: .left,
+        lineHeightMultiple: 1.1,
+        spacingAfter: 39
+      ),
+      actionButton
+    ])
+
+    actionButton.action.receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+          action()
+        }
+      }.store(in: &drawerCancellables)
+
+    coordinator.toDrawer(drawer, from: previousController)
+  }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingEmailConfirmationController.swift b/Sources/OnboardingFeature/Controllers/OnboardingEmailConfirmationController.swift
index 578a27dc5bdedfcd58ab9dbecfd1338c07bad324..b45a26fcc8e08e24c1232444434b632914edda51 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingEmailConfirmationController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingEmailConfirmationController.swift
@@ -1,152 +1,151 @@
 import HUD
-import DrawerFeature
-import Theme
 import UIKit
 import Shared
+import Models
 import Combine
+import DrawerFeature
 import DependencyInjection
 import ScrollViewController
-import Models
 
 public final class OnboardingEmailConfirmationController: UIViewController {
-    @Dependency private var hud: HUD
-    @Dependency private var coordinator: OnboardingCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    lazy private var screenView = OnboardingEmailConfirmationView()
-    lazy private var scrollViewController = ScrollViewController()
-
-    private var cancellables = Set<AnyCancellable>()
-    private let completion: (UIViewController) -> Void
-    private var drawerCancellables = Set<AnyCancellable>()
-    private let viewModel: OnboardingEmailConfirmationViewModel
-
-    public init(
-        _ confirmation: AttributeConfirmation,
-        _ completion: @escaping (UIViewController) -> Void
-    ) {
-        self.completion = completion
-        self.viewModel = OnboardingEmailConfirmationViewModel(confirmation)
-        super.init(nibName: nil, bundle: nil)
+  @Dependency var hud: HUD
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: OnboardingCoordinating
+
+  lazy private var screenView = OnboardingEmailConfirmationView()
+  lazy private var scrollViewController = ScrollViewController()
+
+  private var cancellables = Set<AnyCancellable>()
+  private let completion: (UIViewController) -> Void
+  private var drawerCancellables = Set<AnyCancellable>()
+  private let viewModel: OnboardingEmailConfirmationViewModel
+
+  public init(
+    _ confirmation: AttributeConfirmation,
+    _ completion: @escaping (UIViewController) -> Void
+  ) {
+    self.completion = completion
+    self.viewModel = OnboardingEmailConfirmationViewModel(confirmation)
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar.customize(translucent: true)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupScrollView()
+    setupBindings()
+
+    screenView.setupSubtitle(
+      Localized.Onboarding.EmailConfirmation.subtitle(viewModel.confirmation.content)
+    )
+
+    screenView.didTapInfo = { [weak self] in
+      self?.presentInfo(
+        title: Localized.Onboarding.EmailConfirmation.Info.title,
+        subtitle: Localized.Onboarding.EmailConfirmation.Info.subtitle
+      )
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar.customize(translucent: true)
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupScrollView()
-        setupBindings()
-
-        screenView.setupSubtitle(
-            Localized.Onboarding.EmailConfirmation.subtitle(viewModel.confirmation.content)
-        )
-
-        screenView.didTapInfo = { [weak self] in
-            self?.presentInfo(
-                title: Localized.Onboarding.EmailConfirmation.Info.title,
-                subtitle: Localized.Onboarding.EmailConfirmation.Info.subtitle
-            )
+  }
+
+  private func setupScrollView() {
+    addChild(scrollViewController)
+    view.addSubview(scrollViewController.view)
+    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.didMove(toParent: self)
+    scrollViewController.contentView = screenView
+    scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
+  }
+
+  private func setupBindings() {
+    viewModel.hud.receive(on: DispatchQueue.main)
+      .sink { [hud] in hud.update(with: $0) }
+      .store(in: &cancellables)
+
+    screenView.inputField.textPublisher
+      .sink { [unowned self] in viewModel.didInput($0) }
+      .store(in: &cancellables)
+
+    viewModel.state
+      .map(\.status)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.update(status: $0) }
+      .store(in: &cancellables)
+
+    screenView.nextButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in viewModel.didTapNext() }
+      .store(in: &cancellables)
+
+    viewModel.completionPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] _ in completion(self) }
+      .store(in: &cancellables)
+
+    screenView.resendButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in viewModel.didTapResend() }
+      .store(in: &cancellables)
+
+    viewModel.state
+      .map(\.resendDebouncer)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.resendButton.isEnabled = $0 == 0
+
+        if $0 == 0 {
+          screenView.resendButton.setTitle(Localized.Profile.Code.resend(""), for: .normal)
+        } else {
+          screenView.resendButton.setTitle(Localized.Profile.Code.resend("(\($0))"), for: .disabled)
         }
-    }
-
-    private func setupScrollView() {
-        addChild(scrollViewController)
-        view.addSubview(scrollViewController.view)
-        scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
-        scrollViewController.didMove(toParent: self)
-        scrollViewController.contentView = screenView
-        scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
-    }
-
-    private func setupBindings() {
-        viewModel.hud.receive(on: DispatchQueue.main)
-            .sink { [hud] in hud.update(with: $0) }
-            .store(in: &cancellables)
-
-        screenView.inputField.textPublisher
-            .sink { [unowned self] in viewModel.didInput($0) }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .map(\.status)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.update(status: $0) }
-            .store(in: &cancellables)
-
-        screenView.nextButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in viewModel.didTapNext() }
-            .store(in: &cancellables)
-
-        viewModel.completionPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] _ in completion(self) }
-            .store(in: &cancellables)
-
-        screenView.resendButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in viewModel.didTapResend() }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .map(\.resendDebouncer)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                screenView.resendButton.isEnabled = $0 == 0
-
-                if $0 == 0 {
-                    screenView.resendButton.setTitle(Localized.Profile.Code.resend(""), for: .normal)
-                } else {
-                    screenView.resendButton.setTitle(Localized.Profile.Code.resend("(\($0))"), for: .disabled)
-                }
-            }.store(in: &cancellables)
-    }
+      }.store(in: &cancellables)
+  }
+
+  private func presentInfo(title: String, subtitle: String) {
+    let actionButton = CapsuleButton()
+    actionButton.set(style: .seeThrough, title: Localized.Settings.InfoDrawer.action)
+
+    let drawer = DrawerController(with: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerText(
+        font: Fonts.Mulish.regular.font(size: 16.0),
+        text: subtitle,
+        color: Asset.neutralBody.color,
+        alignment: .left,
+        lineHeightMultiple: 1.1,
+        spacingAfter: 37
+      ),
+      DrawerStack(views: [
+        actionButton,
+        FlexibleSpace()
+      ])
+    ])
+
+    actionButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-    private func presentInfo(title: String, subtitle: String) {
-        let actionButton = CapsuleButton()
-        actionButton.set(style: .seeThrough, title: Localized.Settings.InfoDrawer.action)
-
-        let drawer = DrawerController(with: [
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerText(
-                font: Fonts.Mulish.regular.font(size: 16.0),
-                text: subtitle,
-                color: Asset.neutralBody.color,
-                alignment: .left,
-                lineHeightMultiple: 1.1,
-                spacingAfter: 37
-            ),
-            DrawerStack(views: [
-                actionButton,
-                FlexibleSpace()
-            ])
-        ])
-
-        actionButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+    coordinator.toDrawer(drawer, from: self)
+  }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift b/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
index 4ff185e789c7d3761e5be4d6aeabdcc8ef272b0b..b3ff6046b302a2ccb6eb1bc8d263fffe16030d17 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
@@ -1,140 +1,139 @@
 import HUD
-import DrawerFeature
-import Theme
 import UIKit
 import Shared
 import Combine
+import DrawerFeature
 import DependencyInjection
 import ScrollViewController
 
 public final class OnboardingEmailController: UIViewController {
-    @Dependency private var hud: HUD
-    @Dependency private var coordinator: OnboardingCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    lazy private var screenView = OnboardingEmailView()
-    lazy private var scrollViewController = ScrollViewController()
-
-    private var cancellables = Set<AnyCancellable>()
-    private let viewModel = OnboardingEmailViewModel()
-    private var drawerCancellables = Set<AnyCancellable>()
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar.customize(translucent: true)
+  @Dependency var hud: HUD
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: OnboardingCoordinating
+
+  lazy private var screenView = OnboardingEmailView()
+  lazy private var scrollViewController = ScrollViewController()
+
+  private var cancellables = Set<AnyCancellable>()
+  private let viewModel = OnboardingEmailViewModel()
+  private var drawerCancellables = Set<AnyCancellable>()
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar.customize(translucent: true)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    navigationItem.backButtonTitle = " "
+
+    setupScrollView()
+    setupBindings()
+
+    screenView.didTapInfo = { [weak self] in
+      self?.presentInfo(
+        title: Localized.Onboarding.Email.Info.title,
+        subtitle: Localized.Onboarding.Email.Info.subtitle,
+        urlString: "https://links.xx.network/ud"
+      )
     }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        navigationItem.backButtonTitle = " "
-
-        setupScrollView()
-        setupBindings()
-
-        screenView.didTapInfo = { [weak self] in
-            self?.presentInfo(
-                title: Localized.Onboarding.Email.Info.title,
-                subtitle: Localized.Onboarding.Email.Info.subtitle,
-                urlString: "https://links.xx.network/ud"
-            )
+  }
+
+  private func setupScrollView() {
+    addChild(scrollViewController)
+    view.addSubview(scrollViewController.view)
+    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.didMove(toParent: self)
+    scrollViewController.contentView = screenView
+    scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
+  }
+
+  private func setupBindings() {
+    viewModel.hud.receive(on: DispatchQueue.main)
+      .sink { [hud] in hud.update(with: $0) }
+      .store(in: &cancellables)
+
+    screenView.inputField.textPublisher
+      .sink { [unowned self] in viewModel.didInput($0) }
+      .store(in: &cancellables)
+
+    screenView.inputField.returnPublisher
+      .sink { [unowned self] in screenView.inputField.endEditing(true) }
+      .store(in: &cancellables)
+
+    viewModel.state
+      .map(\.confirmation)
+      .receive(on: DispatchQueue.main)
+      .compactMap { $0 }
+      .sink { [unowned self] in
+        viewModel.clearUp()
+        coordinator.toEmailConfirmation(with: $0, from: self) { controller in
+          let successModel = OnboardingSuccessModel(
+            title: Localized.Onboarding.Success.Email.title,
+            subtitle: nil,
+            nextController: self.coordinator.toPhone(from:)
+          )
+
+          self.coordinator.toSuccess(with: successModel, from: controller)
         }
-    }
-
-    private func setupScrollView() {
-        addChild(scrollViewController)
-        view.addSubview(scrollViewController.view)
-        scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
-        scrollViewController.didMove(toParent: self)
-        scrollViewController.contentView = screenView
-        scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
-    }
-
-    private func setupBindings() {
-        viewModel.hud.receive(on: DispatchQueue.main)
-            .sink { [hud] in hud.update(with: $0) }
-            .store(in: &cancellables)
-
-        screenView.inputField.textPublisher
-            .sink { [unowned self] in viewModel.didInput($0) }
-            .store(in: &cancellables)
-
-        screenView.inputField.returnPublisher
-            .sink { [unowned self] in screenView.inputField.endEditing(true) }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .map(\.confirmation)
-            .receive(on: DispatchQueue.main)
-            .compactMap { $0 }
-            .sink { [unowned self] in
-                viewModel.clearUp()
-                coordinator.toEmailConfirmation(with: $0, from: self) { controller in
-                    let successModel = OnboardingSuccessModel(
-                        title: Localized.Onboarding.Success.Email.title,
-                        subtitle: nil,
-                        nextController: self.coordinator.toPhone(from:)
-                    )
-
-                    self.coordinator.toSuccess(with: successModel, from: controller)
-                }
-            }.store(in: &cancellables)
-
-        viewModel.state
-            .map(\.status)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.update(status: $0) }
-            .store(in: &cancellables)
-
-        screenView.nextButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewModel.didTapNext() }
-            .store(in: &cancellables)
-
-        screenView.skipButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in coordinator.toPhone(from: self) }
-            .store(in: &cancellables)
-    }
+      }.store(in: &cancellables)
+
+    viewModel.state
+      .map(\.status)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.update(status: $0) }
+      .store(in: &cancellables)
+
+    screenView.nextButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewModel.didTapNext() }
+      .store(in: &cancellables)
+
+    screenView.skipButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in coordinator.toPhone(from: self) }
+      .store(in: &cancellables)
+  }
+
+  private func presentInfo(
+    title: String,
+    subtitle: String,
+    urlString: String = ""
+  ) {
+    let actionButton = CapsuleButton()
+    actionButton.set(
+      style: .seeThrough,
+      title: Localized.Settings.InfoDrawer.action
+    )
+
+    let drawer = DrawerController(with: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerLinkText(
+        text: subtitle,
+        urlString: urlString,
+        spacingAfter: 37
+      ),
+      DrawerStack(views: [
+        actionButton,
+        FlexibleSpace()
+      ])
+    ])
+
+    actionButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-    private func presentInfo(
-        title: String,
-        subtitle: String,
-        urlString: String = ""
-    ) {
-        let actionButton = CapsuleButton()
-        actionButton.set(
-            style: .seeThrough,
-            title: Localized.Settings.InfoDrawer.action
-        )
-
-        let drawer = DrawerController(with: [
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerLinkText(
-                text: subtitle,
-                urlString: urlString,
-                spacingAfter: 37
-            ),
-            DrawerStack(views: [
-                actionButton,
-                FlexibleSpace()
-            ])
-        ])
-
-        actionButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+    coordinator.toDrawer(drawer, from: self)
+  }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingPhoneConfirmationController.swift b/Sources/OnboardingFeature/Controllers/OnboardingPhoneConfirmationController.swift
index 6207a5a7c9b19b1a5184557eb45cd07bd8aeb21b..1fb93ad4f023b0e18fa8c1a52b8ffd3c30d759cc 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingPhoneConfirmationController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingPhoneConfirmationController.swift
@@ -1,152 +1,151 @@
 import HUD
-import DrawerFeature
-import Theme
 import UIKit
 import Shared
+import Models
 import Combine
+import DrawerFeature
 import DependencyInjection
 import ScrollViewController
-import Models
 
 public final class OnboardingPhoneConfirmationController: UIViewController {
-    @Dependency private var hud: HUD
-    @Dependency private var coordinator: OnboardingCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    lazy private var screenView = OnboardingPhoneConfirmationView()
-    lazy private var scrollViewController = ScrollViewController()
-
-    private var cancellables = Set<AnyCancellable>()
-    private let completion: (UIViewController) -> Void
-    private var drawerCancellables = Set<AnyCancellable>()
-    private let viewModel: OnboardingPhoneConfirmationViewModel
-
-    public init(
-        _ confirmation: AttributeConfirmation,
-        _ completion: @escaping (UIViewController) -> Void
-    ) {
-        self.completion = completion
-        self.viewModel = OnboardingPhoneConfirmationViewModel(confirmation)
-        super.init(nibName: nil, bundle: nil)
+  @Dependency var hud: HUD
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: OnboardingCoordinating
+
+  lazy private var screenView = OnboardingPhoneConfirmationView()
+  lazy private var scrollViewController = ScrollViewController()
+
+  private var cancellables = Set<AnyCancellable>()
+  private let completion: (UIViewController) -> Void
+  private var drawerCancellables = Set<AnyCancellable>()
+  private let viewModel: OnboardingPhoneConfirmationViewModel
+
+  public init(
+    _ confirmation: AttributeConfirmation,
+    _ completion: @escaping (UIViewController) -> Void
+  ) {
+    self.completion = completion
+    self.viewModel = OnboardingPhoneConfirmationViewModel(confirmation)
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar.customize(translucent: true)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupScrollView()
+    setupBindings()
+
+    screenView.setupSubtitle(
+      Localized.Onboarding.PhoneConfirmation.subtitle(viewModel.confirmation.content)
+    )
+
+    screenView.didTapInfo = { [weak self] in
+      self?.presentInfo(
+        title: Localized.Onboarding.PhoneConfirmation.Info.title,
+        subtitle: Localized.Onboarding.PhoneConfirmation.Info.subtitle
+      )
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar.customize(translucent: true)
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupScrollView()
-        setupBindings()
-
-        screenView.setupSubtitle(
-            Localized.Onboarding.PhoneConfirmation.subtitle(viewModel.confirmation.content)
-        )
-
-        screenView.didTapInfo = { [weak self] in
-            self?.presentInfo(
-                title: Localized.Onboarding.PhoneConfirmation.Info.title,
-                subtitle: Localized.Onboarding.PhoneConfirmation.Info.subtitle
-            )
+  }
+
+  private func setupScrollView() {
+    addChild(scrollViewController)
+    view.addSubview(scrollViewController.view)
+    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.didMove(toParent: self)
+    scrollViewController.contentView = screenView
+    scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
+  }
+
+  private func setupBindings() {
+    viewModel.hud.receive(on: DispatchQueue.main)
+      .sink { [hud] in hud.update(with: $0) }
+      .store(in: &cancellables)
+
+    screenView.inputField.textPublisher
+      .sink { [unowned self] in viewModel.didInput($0) }
+      .store(in: &cancellables)
+
+    viewModel.state
+      .map(\.status)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.update(status: $0) }
+      .store(in: &cancellables)
+
+    screenView.nextButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in viewModel.didTapNext() }
+      .store(in: &cancellables)
+
+    viewModel.completionPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] _ in completion(self) }
+      .store(in: &cancellables)
+
+    screenView.resendButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in viewModel.didTapResend() }
+      .store(in: &cancellables)
+
+    viewModel.state
+      .map(\.resendDebouncer)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.resendButton.isEnabled = $0 == 0
+
+        if $0 == 0 {
+          screenView.resendButton.setTitle(Localized.Profile.Code.resend(""), for: .normal)
+        } else {
+          screenView.resendButton.setTitle(Localized.Profile.Code.resend("(\($0))"), for: .disabled)
         }
-    }
-
-    private func setupScrollView() {
-        addChild(scrollViewController)
-        view.addSubview(scrollViewController.view)
-        scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
-        scrollViewController.didMove(toParent: self)
-        scrollViewController.contentView = screenView
-        scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
-    }
-
-    private func setupBindings() {
-        viewModel.hud.receive(on: DispatchQueue.main)
-            .sink { [hud] in hud.update(with: $0) }
-            .store(in: &cancellables)
-
-        screenView.inputField.textPublisher
-            .sink { [unowned self] in viewModel.didInput($0) }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .map(\.status)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.update(status: $0) }
-            .store(in: &cancellables)
-
-        screenView.nextButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in viewModel.didTapNext() }
-            .store(in: &cancellables)
-
-        viewModel.completionPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] _ in completion(self) }
-            .store(in: &cancellables)
-
-        screenView.resendButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in viewModel.didTapResend() }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .map(\.resendDebouncer)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                screenView.resendButton.isEnabled = $0 == 0
-
-                if $0 == 0 {
-                    screenView.resendButton.setTitle(Localized.Profile.Code.resend(""), for: .normal)
-                } else {
-                    screenView.resendButton.setTitle(Localized.Profile.Code.resend("(\($0))"), for: .disabled)
-                }
-            }.store(in: &cancellables)
-    }
+      }.store(in: &cancellables)
+  }
+
+  private func presentInfo(title: String, subtitle: String) {
+    let actionButton = CapsuleButton()
+    actionButton.set(style: .seeThrough, title: Localized.Settings.InfoDrawer.action)
+
+    let drawer = DrawerController(with: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerText(
+        font: Fonts.Mulish.regular.font(size: 16.0),
+        text: subtitle,
+        color: Asset.neutralBody.color,
+        alignment: .left,
+        lineHeightMultiple: 1.1,
+        spacingAfter: 37
+      ),
+      DrawerStack(views: [
+        actionButton,
+        FlexibleSpace()
+      ])
+    ])
+
+    actionButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-    private func presentInfo(title: String, subtitle: String) {
-        let actionButton = CapsuleButton()
-        actionButton.set(style: .seeThrough, title: Localized.Settings.InfoDrawer.action)
-
-        let drawer = DrawerController(with: [
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerText(
-                font: Fonts.Mulish.regular.font(size: 16.0),
-                text: subtitle,
-                color: Asset.neutralBody.color,
-                alignment: .left,
-                lineHeightMultiple: 1.1,
-                spacingAfter: 37
-            ),
-            DrawerStack(views: [
-                actionButton,
-                FlexibleSpace()
-            ])
-        ])
-
-        actionButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+    coordinator.toDrawer(drawer, from: self)
+  }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift b/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
index 4686825bbeba8c9e599602f7c62453c3f23cffee..e25481b405aabf394245fde4598a44d4a548cd3c 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
@@ -1,153 +1,152 @@
 import HUD
-import DrawerFeature
-import Theme
 import UIKit
 import Shared
 import Combine
+import DrawerFeature
 import DependencyInjection
 import ScrollViewController
 
 public final class OnboardingPhoneController: UIViewController {
-    @Dependency private var hud: HUD
-    @Dependency private var coordinator: OnboardingCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    lazy private var screenView = OnboardingPhoneView()
-    lazy private var scrollViewController = ScrollViewController()
-
-    private var cancellables = Set<AnyCancellable>()
-    private let viewModel = OnboardingPhoneViewModel()
-    private var drawerCancellables = Set<AnyCancellable>()
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar.customize(translucent: true)
+  @Dependency var hud: HUD
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: OnboardingCoordinating
+
+  lazy private var screenView = OnboardingPhoneView()
+  lazy private var scrollViewController = ScrollViewController()
+
+  private var cancellables = Set<AnyCancellable>()
+  private let viewModel = OnboardingPhoneViewModel()
+  private var drawerCancellables = Set<AnyCancellable>()
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar.customize(translucent: true)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    navigationItem.backButtonTitle = " "
+
+    setupScrollView()
+    setupBindings()
+
+    screenView.didTapInfo = { [weak self] in
+      self?.presentInfo(
+        title: Localized.Onboarding.Phone.Info.title,
+        subtitle: Localized.Onboarding.Phone.Info.subtitle,
+        urlString: "https://links.xx.network/ud"
+      )
     }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        navigationItem.backButtonTitle = " "
-
-        setupScrollView()
-        setupBindings()
-
-        screenView.didTapInfo = { [weak self] in
-            self?.presentInfo(
-                title: Localized.Onboarding.Phone.Info.title,
-                subtitle: Localized.Onboarding.Phone.Info.subtitle,
-                urlString: "https://links.xx.network/ud"
-            )
+  }
+
+  private func setupScrollView() {
+    addChild(scrollViewController)
+    view.addSubview(scrollViewController.view)
+    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.didMove(toParent: self)
+    scrollViewController.contentView = screenView
+    scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
+  }
+
+  private func setupBindings() {
+    viewModel.hud
+      .receive(on: DispatchQueue.main)
+      .sink { [hud] in hud.update(with: $0) }
+      .store(in: &cancellables)
+
+    screenView.inputField.textPublisher
+      .sink { [unowned self] in viewModel.didInput($0) }
+      .store(in: &cancellables)
+
+    screenView.inputField.returnPublisher
+      .sink { [unowned self] in screenView.inputField.endEditing(true) }
+      .store(in: &cancellables)
+
+    viewModel.state.map(\.status)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.update(status: $0) }
+      .store(in: &cancellables)
+
+    screenView.nextButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewModel.didTapNext() }
+      .store(in: &cancellables)
+
+    screenView.skipButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in coordinator.toChats(from: self) }
+      .store(in: &cancellables)
+
+    screenView.inputField.codePublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        coordinator.toCountries(from: self) { self.viewModel.didChooseCountry($0) }
+      }.store(in: &cancellables)
+
+    viewModel.state.map(\.confirmation)
+      .receive(on: DispatchQueue.main)
+      .compactMap { $0 }
+      .sink { [unowned self] in
+        viewModel.clearUp()
+        coordinator.toPhoneConfirmation(with: $0, from: self) { controller in
+          let successModel = OnboardingSuccessModel(
+            title: Localized.Onboarding.Success.Phone.title,
+            subtitle: nil,
+            nextController: self.coordinator.toChats(from:)
+          )
+
+          self.coordinator.toSuccess(with: successModel, from: controller)
         }
-    }
-
-    private func setupScrollView() {
-        addChild(scrollViewController)
-        view.addSubview(scrollViewController.view)
-        scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
-        scrollViewController.didMove(toParent: self)
-        scrollViewController.contentView = screenView
-        scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
-    }
-
-    private func setupBindings() {
-        viewModel.hud
-            .receive(on: DispatchQueue.main)
-            .sink { [hud] in hud.update(with: $0) }
-            .store(in: &cancellables)
-
-        screenView.inputField.textPublisher
-            .sink { [unowned self] in viewModel.didInput($0) }
-            .store(in: &cancellables)
-
-        screenView.inputField.returnPublisher
-            .sink { [unowned self] in screenView.inputField.endEditing(true) }
-            .store(in: &cancellables)
-
-        viewModel.state.map(\.status)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.update(status: $0) }
-            .store(in: &cancellables)
-
-        screenView.nextButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewModel.didTapNext() }
-            .store(in: &cancellables)
-
-        screenView.skipButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in coordinator.toChats(from: self) }
-            .store(in: &cancellables)
-
-        screenView.inputField.codePublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                coordinator.toCountries(from: self) { self.viewModel.didChooseCountry($0) }
-            }.store(in: &cancellables)
-
-        viewModel.state.map(\.confirmation)
-            .receive(on: DispatchQueue.main)
-            .compactMap { $0 }
-            .sink { [unowned self] in
-                viewModel.clearUp()
-                coordinator.toPhoneConfirmation(with: $0, from: self) { controller in
-                    let successModel = OnboardingSuccessModel(
-                        title: Localized.Onboarding.Success.Phone.title,
-                        subtitle: nil,
-                        nextController: self.coordinator.toChats(from:)
-                    )
-
-                    self.coordinator.toSuccess(with: successModel, from: controller)
-                }
-            }.store(in: &cancellables)
-
-        viewModel.state.map(\.country)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                screenView.inputField.set(prefix: $0.prefixWithFlag)
-                screenView.inputField.update(placeholder: $0.example)
-            }.store(in: &cancellables)
-    }
+      }.store(in: &cancellables)
+
+    viewModel.state.map(\.country)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.inputField.set(prefix: $0.prefixWithFlag)
+        screenView.inputField.update(placeholder: $0.example)
+      }.store(in: &cancellables)
+  }
+
+  private func presentInfo(
+    title: String,
+    subtitle: String,
+    urlString: String = ""
+  ) {
+    let actionButton = CapsuleButton()
+    actionButton.set(
+      style: .seeThrough,
+      title: Localized.Settings.InfoDrawer.action
+    )
+
+    let drawer = DrawerController(with: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerLinkText(
+        text: subtitle,
+        urlString: urlString,
+        spacingAfter: 37
+      ),
+      DrawerStack(views: [
+        actionButton,
+        FlexibleSpace()
+      ])
+    ])
+
+    actionButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-    private func presentInfo(
-        title: String,
-        subtitle: String,
-        urlString: String = ""
-    ) {
-        let actionButton = CapsuleButton()
-        actionButton.set(
-            style: .seeThrough,
-            title: Localized.Settings.InfoDrawer.action
-        )
-
-        let drawer = DrawerController(with: [
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerLinkText(
-                text: subtitle,
-                urlString: urlString,
-                spacingAfter: 37
-            ),
-            DrawerStack(views: [
-                actionButton,
-                FlexibleSpace()
-            ])
-        ])
-
-        actionButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+    coordinator.toDrawer(drawer, from: self)
+  }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift b/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
index 3fce498d995b7bbabaf62517313b1705c9996b1b..a902a8d2e68656aa4b920a55e8c11c0012abc87b 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
@@ -1,6 +1,5 @@
 import HUD
 import UIKit
-import Theme
 import Shared
 import Combine
 import DependencyInjection
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingSuccessController.swift b/Sources/OnboardingFeature/Controllers/OnboardingSuccessController.swift
index a260afa9a7c69369f0bf9a9510c851ebe2e20313..d072efad04cb9446f229614025c1adc515db9f2f 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingSuccessController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingSuccessController.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Theme
 import Models
 import Shared
 import Combine
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift b/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
index fd349efb4f4acfba8e6538e5892a1bf3025d5617..2b139fad43b2f00f23a2834289952673efbbfb0b 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
@@ -1,5 +1,4 @@
 import HUD
-import Theme
 import UIKit
 import Shared
 import Combine
@@ -8,131 +7,131 @@ import DependencyInjection
 import ScrollViewController
 
 public final class OnboardingUsernameController: UIViewController {
-    @Dependency private var hud: HUD
-    @Dependency private var coordinator: OnboardingCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    lazy private var screenView = OnboardingUsernameView()
-    lazy private var scrollViewController = ScrollViewController()
-
-    private var cancellables = Set<AnyCancellable>()
-    private let viewModel = OnboardingUsernameViewModel()
-    private var drawerCancellables = Set<AnyCancellable>()
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar.customize(translucent: true)
+  @Dependency var hud: HUD
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: OnboardingCoordinating
+
+  lazy private var screenView = OnboardingUsernameView()
+  lazy private var scrollViewController = ScrollViewController()
+
+  private var cancellables = Set<AnyCancellable>()
+  private let viewModel = OnboardingUsernameViewModel()
+  private var drawerCancellables = Set<AnyCancellable>()
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar.customize(translucent: true)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupScrollView()
+    setupBindings()
+
+    screenView.didTapInfo = { [weak self] in
+      self?.presentInfo(
+        title: Localized.Onboarding.Username.Info.title,
+        subtitle: Localized.Onboarding.Username.Info.subtitle,
+        urlString: "https://links.xx.network/ud"
+      )
     }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupScrollView()
-        setupBindings()
-
-        screenView.didTapInfo = { [weak self] in
-            self?.presentInfo(
-                title: Localized.Onboarding.Username.Info.title,
-                subtitle: Localized.Onboarding.Username.Info.subtitle,
-                urlString: "https://links.xx.network/ud"
-            )
+  }
+
+  private func setupScrollView() {
+    scrollViewController.scrollView.backgroundColor = .white
+
+    addChild(scrollViewController)
+    view.addSubview(scrollViewController.view)
+    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.didMove(toParent: self)
+    scrollViewController.contentView = screenView
+  }
+
+  private func setupBindings() {
+    viewModel.hud
+      .receive(on: DispatchQueue.main)
+      .sink { [hud] in hud.update(with: $0) }
+      .store(in: &cancellables)
+
+    screenView.inputField.textPublisher
+      .removeDuplicates()
+      .compactMap { $0 }
+      .sink { [unowned self] in viewModel.didInput($0) }
+      .store(in: &cancellables)
+
+    screenView.restoreView.restoreButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toRestoreList(from: self) }
+      .store(in: &cancellables)
+
+    screenView.inputField.returnPublisher
+      .sink { [unowned self] in
+        if screenView.nextButton.isEnabled {
+          viewModel.didTapRegister()
+        } else {
+          screenView.inputField.endEditing(true)
         }
-    }
-
-    private func setupScrollView() {
-        scrollViewController.scrollView.backgroundColor = .white
-
-        addChild(scrollViewController)
-        view.addSubview(scrollViewController.view)
-        scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
-        scrollViewController.didMove(toParent: self)
-        scrollViewController.contentView = screenView
-    }
-
-    private func setupBindings() {
-        viewModel.hud
-            .receive(on: DispatchQueue.main)
-            .sink { [hud] in hud.update(with: $0) }
-            .store(in: &cancellables)
-
-        screenView.inputField.textPublisher
-            .removeDuplicates()
-            .compactMap { $0 }
-            .sink { [unowned self] in viewModel.didInput($0) }
-            .store(in: &cancellables)
-
-        screenView.restoreView.restoreButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toRestoreList(from: self) }
-            .store(in: &cancellables)
-
-        screenView.inputField.returnPublisher
-            .sink { [unowned self] in
-                if screenView.nextButton.isEnabled {
-                    viewModel.didTapRegister()
-                } else {
-                    screenView.inputField.endEditing(true)
-                }
-            }.store(in: &cancellables)
-
-        screenView.nextButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewModel.didTapRegister() }
-            .store(in: &cancellables)
-
-        viewModel.greenPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toWelcome(from: self) }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .map(\.status)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.update(status: $0) }
-            .store(in: &cancellables)
-    }
+      }.store(in: &cancellables)
+
+    screenView.nextButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewModel.didTapRegister() }
+      .store(in: &cancellables)
+
+    viewModel.greenPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toWelcome(from: self) }
+      .store(in: &cancellables)
+
+    viewModel.state
+      .map(\.status)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.update(status: $0) }
+      .store(in: &cancellables)
+  }
+
+  private func presentInfo(
+    title: String,
+    subtitle: String,
+    urlString: String = ""
+  ) {
+    let actionButton = CapsuleButton()
+    actionButton.set(
+      style: .seeThrough,
+      title: Localized.Settings.InfoDrawer.action
+    )
+
+    let drawer = DrawerController(with: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerLinkText(
+        text: subtitle,
+        urlString: urlString,
+        spacingAfter: 37
+      ),
+      DrawerStack(views: [
+        actionButton,
+        FlexibleSpace()
+      ])
+    ])
+
+    actionButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-    private func presentInfo(
-        title: String,
-        subtitle: String,
-        urlString: String = ""
-    ) {
-        let actionButton = CapsuleButton()
-        actionButton.set(
-            style: .seeThrough,
-            title: Localized.Settings.InfoDrawer.action
-        )
-
-        let drawer = DrawerController(with: [
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerLinkText(
-                text: subtitle,
-                urlString: urlString,
-                spacingAfter: 37
-            ),
-            DrawerStack(views: [
-                actionButton,
-                FlexibleSpace()
-            ])
-        ])
-
-        actionButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+    coordinator.toDrawer(drawer, from: self)
+  }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift b/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
index 6def35a43a53695ff916c62761f73f3091966af8..9bed33d2acdb20c9e684c1614583bff9f8c129f6 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
@@ -1,4 +1,3 @@
-import Theme
 import UIKit
 import Shared
 import Combine
@@ -7,89 +6,90 @@ import DrawerFeature
 import DependencyInjection
 
 public final class OnboardingWelcomeController: UIViewController {
-    @KeyObject(.username, defaultValue: "") var username: String
-    @Dependency private var coordinator: OnboardingCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
+  @KeyObject(.username, defaultValue: "") var username: String
 
-    lazy private var screenView = OnboardingWelcomeView()
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: OnboardingCoordinating
 
-    private var cancellables = Set<AnyCancellable>()
-    private var drawerCancellables = Set<AnyCancellable>()
+  lazy private var screenView = OnboardingWelcomeView()
 
-    public override func loadView() {
-        view = screenView
-    }
+  private var cancellables = Set<AnyCancellable>()
+  private var drawerCancellables = Set<AnyCancellable>()
 
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar.customize(translucent: true)
-    }
+  public override func loadView() {
+    view = screenView
+  }
 
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupBindings()
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar.customize(translucent: true)
+  }
 
-        screenView.setupTitle(Localized.Onboarding.Welcome.title(username))
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupBindings()
 
-        screenView.didTapInfo = { [weak self] in
-            self?.presentInfo(
-                title: Localized.Onboarding.Welcome.Info.title,
-                subtitle: Localized.Onboarding.Welcome.Info.subtitle,
-                urlString: "https://links.xx.network/ud"
-            )
-        }
+    screenView.setupTitle(Localized.Onboarding.Welcome.title(username))
+
+    screenView.didTapInfo = { [weak self] in
+      self?.presentInfo(
+        title: Localized.Onboarding.Welcome.Info.title,
+        subtitle: Localized.Onboarding.Welcome.Info.subtitle,
+        urlString: "https://links.xx.network/ud"
+      )
     }
+  }
 
-    private func setupBindings() {
-        screenView.continueButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in coordinator.toEmail(from: self) }
-            .store(in: &cancellables)
+  private func setupBindings() {
+    screenView.continueButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in coordinator.toEmail(from: self) }
+      .store(in: &cancellables)
 
-        screenView.skipButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in coordinator.toChats(from: self) }
-            .store(in: &cancellables)
-    }
+    screenView.skipButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in coordinator.toChats(from: self) }
+      .store(in: &cancellables)
+  }
 
-    private func presentInfo(
-        title: String,
-        subtitle: String,
-        urlString: String = ""
-    ) {
-        let actionButton = CapsuleButton()
-        actionButton.set(
-            style: .seeThrough,
-            title: Localized.Settings.InfoDrawer.action
-        )
+  private func presentInfo(
+    title: String,
+    subtitle: String,
+    urlString: String = ""
+  ) {
+    let actionButton = CapsuleButton()
+    actionButton.set(
+      style: .seeThrough,
+      title: Localized.Settings.InfoDrawer.action
+    )
 
-        let drawer = DrawerController(with: [
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerLinkText(
-                text: subtitle,
-                urlString: urlString,
-                spacingAfter: 37
-            ),
-            DrawerStack(views: [
-                actionButton,
-                FlexibleSpace()
-            ])
-        ])
+    let drawer = DrawerController(with: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerLinkText(
+        text: subtitle,
+        urlString: urlString,
+        spacingAfter: 37
+      ),
+      DrawerStack(views: [
+        actionButton,
+        FlexibleSpace()
+      ])
+    ])
 
-        actionButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
+    actionButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-        coordinator.toDrawer(drawer, from: self)
-    }
+    coordinator.toDrawer(drawer, from: self)
+  }
 }
diff --git a/Sources/Permissions/RequestPermissionController.swift b/Sources/Permissions/RequestPermissionController.swift
index d892ab60e8722633e8d7c2930eb7ec97b4049d8c..6aa33347a74af25cd0abba5e1a30211bda19ac84 100644
--- a/Sources/Permissions/RequestPermissionController.swift
+++ b/Sources/Permissions/RequestPermissionController.swift
@@ -1,100 +1,99 @@
 import UIKit
-import Theme
 import Shared
 import Combine
 import DependencyInjection
 
 public enum PermissionType {
-    case camera
-    case library
-    case microphone
+  case camera
+  case library
+  case microphone
 }
 
 public final class RequestPermissionController: UIViewController {
-    @Dependency private var permissions: PermissionHandling
-    @Dependency private var statusBarController: StatusBarStyleControlling
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var permissions: PermissionHandling
 
-    lazy private var screenView = RequestPermissionView()
+  lazy private var screenView = RequestPermissionView()
 
-    private var type: PermissionType!
-    private var cancellables = Set<AnyCancellable>()
+  private var type: PermissionType!
+  private var cancellables = Set<AnyCancellable>()
 
-    public override func loadView() {
-        view = screenView
-    }
+  public override func loadView() {
+    view = screenView
+  }
 
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar.customize(backgroundColor: Asset.neutralWhite.color)
-    }
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar.customize(backgroundColor: Asset.neutralWhite.color)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupBindings()
+  }
+
+  public func setup(type: PermissionType) {
+    self.type = type
 
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupBindings()
+    switch type {
+    case .camera:
+      screenView.setup(
+        title: Localized.Chat.Actions.Permission.Camera.title,
+        subtitle: Localized.Chat.Actions.Permission.Camera.subtitle,
+        image: Asset.permissionCamera.image
+      )
+    case .library:
+      screenView.setup(
+        title: Localized.Chat.Actions.Permission.Library.title,
+        subtitle: Localized.Chat.Actions.Permission.Library.subtitle,
+        image: Asset.permissionLibrary.image
+      )
+    case .microphone:
+      screenView.setup(
+        title: Localized.Chat.Actions.Permission.Microphone.title,
+        subtitle: Localized.Chat.Actions.Permission.Microphone.subtitle,
+        image: Asset.permissionMicrophone.image
+      )
     }
+  }
 
-    public func setup(type: PermissionType) {
-        self.type = type
+  private func setupBindings() {
+    screenView.notNowButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [weak self] in
+        self?.navigationController?.popViewController(animated: true)
+      }.store(in: &cancellables)
 
+    screenView.continueButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
         switch type {
         case .camera:
-            screenView.setup(
-                title: Localized.Chat.Actions.Permission.Camera.title,
-                subtitle: Localized.Chat.Actions.Permission.Camera.subtitle,
-                image: Asset.permissionCamera.image
-            )
+          permissions.requestCamera { [weak self] _ in
+            DispatchQueue.main.async {
+              self?.navigationController?.popViewController(animated: true)
+            }
+          }
         case .library:
-            screenView.setup(
-                title: Localized.Chat.Actions.Permission.Library.title,
-                subtitle: Localized.Chat.Actions.Permission.Library.subtitle,
-                image: Asset.permissionLibrary.image
-            )
+          permissions.requestPhotos { [weak self] _ in
+            DispatchQueue.main.async {
+              self?.navigationController?.popViewController(animated: true)
+            }
+          }
         case .microphone:
-            screenView.setup(
-                title: Localized.Chat.Actions.Permission.Microphone.title,
-                subtitle: Localized.Chat.Actions.Permission.Microphone.subtitle,
-                image: Asset.permissionMicrophone.image
-            )
+          permissions.requestMicrophone { [weak self] _ in
+            DispatchQueue.main.async {
+              self?.navigationController?.popViewController(animated: true)
+            }
+          }
+        case .none:
+          break
         }
-    }
-
-    private func setupBindings() {
-        screenView.notNowButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [weak self] in
-                self?.navigationController?.popViewController(animated: true)
-            }.store(in: &cancellables)
-
-        screenView.continueButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                switch type {
-                case .camera:
-                    permissions.requestCamera { [weak self] _ in
-                        DispatchQueue.main.async {
-                            self?.navigationController?.popViewController(animated: true)
-                        }
-                    }
-                case .library:
-                    permissions.requestPhotos { [weak self] _ in
-                        DispatchQueue.main.async {
-                            self?.navigationController?.popViewController(animated: true)
-                        }
-                    }
-                case .microphone:
-                    permissions.requestMicrophone { [weak self] _ in
-                        DispatchQueue.main.async {
-                            self?.navigationController?.popViewController(animated: true)
-                        }
-                    }
-                case .none:
-                    break
-                }
-            }.store(in: &cancellables)
-    }
+      }.store(in: &cancellables)
+  }
 
 }
diff --git a/Sources/Presentation/Presenting.swift b/Sources/Presentation/Presenting.swift
index 1baf98d11fe94e90217c41b39c081175cd00bcb9..7de9932742a7f81f90e0dab7ba1f958d36e86757 100644
--- a/Sources/Presentation/Presenting.swift
+++ b/Sources/Presentation/Presenting.swift
@@ -1,5 +1,5 @@
 import UIKit
-import Theme
+import Shared
 
 public protocol Presenting {
     func present(_ target: UIViewController..., from parent: UIViewController)
@@ -24,7 +24,7 @@ public struct ModalPresenter: Presenting {
     public init() {}
 
     public func present(_ target: UIViewController..., from parent: UIViewController) {
-        let statusBarVC = StatusBarViewController(target.first!)
+        let statusBarVC = RootViewController(target.first!)
         statusBarVC.modalPresentationStyle = .fullScreen
         parent.present(statusBarVC, animated: true)
     }
diff --git a/Sources/ProfileFeature/Controllers/ProfileController.swift b/Sources/ProfileFeature/Controllers/ProfileController.swift
index 750c5342b31ddad18660f94aa784f3b22ef520b3..f6b04009f92f47c91d586ff848b55e835f0e837b 100644
--- a/Sources/ProfileFeature/Controllers/ProfileController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfileController.swift
@@ -1,225 +1,224 @@
 import HUD
-import DrawerFeature
 import UIKit
-import Theme
 import Shared
 import Combine
+import DrawerFeature
 import DependencyInjection
 
 public final class ProfileController: UIViewController {
-    @Dependency private var hud: HUD
-    @Dependency private var coordinator: ProfileCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    lazy private var screenView = ProfileView()
-
-    private let viewModel = ProfileViewModel()
-    private var cancellables = Set<AnyCancellable>()
-    private var drawerCancellables = Set<AnyCancellable>()
-
-    public override func loadView() {
-        view = screenView
-    }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        statusBarController.style.send(.lightContent)
-        navigationController?.navigationBar
-            .customize(backgroundColor: Asset.neutralBody.color)
-        viewModel.refresh()
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        screenView.cardComponent.nameLabel.text = viewModel.username!
-        setupNavigationBar()
-        setupBindings()
-    }
-
-    private func setupNavigationBar() {
-        navigationItem.backButtonTitle = ""
-
-        let menuButton = UIButton()
-        menuButton.tintColor = Asset.neutralWhite.color
-        menuButton.setImage(Asset.chatListMenu.image, for: .normal)
-        menuButton.addTarget(self, action: #selector(didTapMenu), for: .touchUpInside)
-        menuButton.snp.makeConstraints { $0.width.equalTo(50) }
-
-        navigationItem.leftBarButtonItem = UIBarButtonItem(customView: menuButton)
-    }
-
-    private func setupBindings() {
-        viewModel.hud
-            .receive(on: DispatchQueue.main)
-            .sink { [hud] in hud.update(with: $0) }
-            .store(in: &cancellables)
-
-        screenView.emailView.actionButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                if screenView.emailView.currentValue != nil {
-                    presentDrawer(
-                        title: Localized.Profile.Delete.title(
-                            Localized.Profile.Email.title.capitalized
-                        ),
-                        subtitle: Localized.Profile.Delete.subtitle(
-                            Localized.Profile.Email.title.lowercased(), Localized.Profile.Email.title.lowercased()
-                        ),
-                        actionTitle: Localized.Profile.Delete.action(
-                            Localized.Profile.Email.title
-                        )) {
-                            self.viewModel.didTapDelete(isEmail: true)
-                        }
-                } else {
-                    coordinator.toEmail(from: self)
-                }
-            }.store(in: &cancellables)
-
-        screenView.phoneView.actionButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                if screenView.phoneView.currentValue != nil {
-                    presentDrawer(
-                        title: Localized.Profile.Delete.title(
-                            Localized.Profile.Phone.title.capitalized
-                        ),
-                        subtitle: Localized.Profile.Delete.subtitle(
-                            Localized.Profile.Phone.title.lowercased(), Localized.Profile.Phone.title.lowercased()
-                        ),
-                        actionTitle: Localized.Profile.Delete.action(
-                            Localized.Profile.Phone.title
-                        )) {
-                            self.viewModel.didTapDelete(isEmail: false)
-                        }
-                } else {
-                    coordinator.toPhone(from: self)
-                }
-            }.store(in: &cancellables)
-
-        screenView.cardComponent.avatarView.editButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in viewModel.didRequestLibraryAccess() }
-            .store(in: &cancellables)
-
-        viewModel.navigation
-            .receive(on: DispatchQueue.main)
-            .removeDuplicates()
-            .sink { [unowned self] in
-                switch $0 {
-                case .library:
-                    presentDrawer(
-                        title: Localized.Profile.Photo.title,
-                        subtitle: Localized.Profile.Photo.subtitle,
-                        actionTitle: Localized.Profile.Photo.continue) {
-                            self.coordinator.toPhotos(from: self)
-                        }
-                case .libraryPermission:
-                    coordinator.toPermission(type: .library, from: self)
-                case .none:
-                    break
-                }
-
-                viewModel.didNavigateSomewhere()
-            }.store(in: &cancellables)
-
-        viewModel.state
-            .map(\.email)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.emailView.set(value: $0) }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .map(\.phone)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.phoneView.set(value: $0) }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .map(\.photo)
-            .compactMap { $0 }
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.cardComponent.image = $0 }
-            .store(in: &cancellables)
-    }
-
-    private func presentDrawer(
-        title: String,
-        subtitle: String,
-        actionTitle: String,
-        action: @escaping () -> Void
-    ) {
-        let actionButton = DrawerCapsuleButton(model: .init(
-            title: actionTitle,
-            style: .red
-        ))
-
-        let drawer = DrawerController(with: [
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
+  @Dependency var hud: HUD
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: ProfileCoordinating
+
+  lazy private var screenView = ProfileView()
+
+  private let viewModel = ProfileViewModel()
+  private var cancellables = Set<AnyCancellable>()
+  private var drawerCancellables = Set<AnyCancellable>()
+
+  public override func loadView() {
+    view = screenView
+  }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    barStylist.styleSubject.send(.lightContent)
+    navigationController?.navigationBar
+      .customize(backgroundColor: Asset.neutralBody.color)
+    viewModel.refresh()
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    screenView.cardComponent.nameLabel.text = viewModel.username!
+    setupNavigationBar()
+    setupBindings()
+  }
+
+  private func setupNavigationBar() {
+    navigationItem.backButtonTitle = ""
+
+    let menuButton = UIButton()
+    menuButton.tintColor = Asset.neutralWhite.color
+    menuButton.setImage(Asset.chatListMenu.image, for: .normal)
+    menuButton.addTarget(self, action: #selector(didTapMenu), for: .touchUpInside)
+    menuButton.snp.makeConstraints { $0.width.equalTo(50) }
+
+    navigationItem.leftBarButtonItem = UIBarButtonItem(customView: menuButton)
+  }
+
+  private func setupBindings() {
+    viewModel.hud
+      .receive(on: DispatchQueue.main)
+      .sink { [hud] in hud.update(with: $0) }
+      .store(in: &cancellables)
+
+    screenView.emailView.actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        if screenView.emailView.currentValue != nil {
+          presentDrawer(
+            title: Localized.Profile.Delete.title(
+              Localized.Profile.Email.title.capitalized
             ),
-            DrawerText(
-                font: Fonts.Mulish.regular.font(size: 16.0),
-                text: subtitle,
-                color: Asset.neutralBody.color,
-                alignment: .left,
-                lineHeightMultiple: 1.1,
-                spacingAfter: 37
+            subtitle: Localized.Profile.Delete.subtitle(
+              Localized.Profile.Email.title.lowercased(), Localized.Profile.Email.title.lowercased()
             ),
-            actionButton
-        ])
-
-        actionButton.action
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
+            actionTitle: Localized.Profile.Delete.action(
+              Localized.Profile.Email.title
+            )) {
+              self.viewModel.didTapDelete(isEmail: true)
+            }
+        } else {
+          coordinator.toEmail(from: self)
+        }
+      }.store(in: &cancellables)
+
+    screenView.phoneView.actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        if screenView.phoneView.currentValue != nil {
+          presentDrawer(
+            title: Localized.Profile.Delete.title(
+              Localized.Profile.Phone.title.capitalized
+            ),
+            subtitle: Localized.Profile.Delete.subtitle(
+              Localized.Profile.Phone.title.lowercased(), Localized.Profile.Phone.title.lowercased()
+            ),
+            actionTitle: Localized.Profile.Delete.action(
+              Localized.Profile.Phone.title
+            )) {
+              self.viewModel.didTapDelete(isEmail: false)
+            }
+        } else {
+          coordinator.toPhone(from: self)
+        }
+      }.store(in: &cancellables)
+
+    screenView.cardComponent.avatarView.editButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in viewModel.didRequestLibraryAccess() }
+      .store(in: &cancellables)
+
+    viewModel.navigation
+      .receive(on: DispatchQueue.main)
+      .removeDuplicates()
+      .sink { [unowned self] in
+        switch $0 {
+        case .library:
+          presentDrawer(
+            title: Localized.Profile.Photo.title,
+            subtitle: Localized.Profile.Photo.subtitle,
+            actionTitle: Localized.Profile.Photo.continue) {
+              self.coordinator.toPhotos(from: self)
+            }
+        case .libraryPermission:
+          coordinator.toPermission(type: .library, from: self)
+        case .none:
+          break
+        }
 
-                    action()
-                }
-            }.store(in: &drawerCancellables)
+        viewModel.didNavigateSomewhere()
+      }.store(in: &cancellables)
+
+    viewModel.state
+      .map(\.email)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.emailView.set(value: $0) }
+      .store(in: &cancellables)
+
+    viewModel.state
+      .map(\.phone)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.phoneView.set(value: $0) }
+      .store(in: &cancellables)
+
+    viewModel.state
+      .map(\.photo)
+      .compactMap { $0 }
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.cardComponent.image = $0 }
+      .store(in: &cancellables)
+  }
+
+  private func presentDrawer(
+    title: String,
+    subtitle: String,
+    actionTitle: String,
+    action: @escaping () -> Void
+  ) {
+    let actionButton = DrawerCapsuleButton(model: .init(
+      title: actionTitle,
+      style: .red
+    ))
+
+    let drawer = DrawerController(with: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerText(
+        font: Fonts.Mulish.regular.font(size: 16.0),
+        text: subtitle,
+        color: Asset.neutralBody.color,
+        alignment: .left,
+        lineHeightMultiple: 1.1,
+        spacingAfter: 37
+      ),
+      actionButton
+    ])
+
+    actionButton.action
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+
+          action()
+        }
+      }.store(in: &drawerCancellables)
 
-        coordinator.toDrawer(drawer, from: self)
-    }
+    coordinator.toDrawer(drawer, from: self)
+  }
 
-    @objc private func didTapMenu() {
-        coordinator.toSideMenu(from: self)
-    }
+  @objc private func didTapMenu() {
+    coordinator.toSideMenu(from: self)
+  }
 }
 
 extension ProfileController: UIImagePickerControllerDelegate {
-    public func imagePickerController(
-        _ picker: UIImagePickerController,
-        didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]
-    ) {
-        var image: UIImage?
-
-        if let originalImage = info[.originalImage] as? UIImage {
-            image = originalImage
-        }
-
-        if let croppedImage = info[.editedImage] as? UIImage {
-            image = croppedImage
-        }
+  public func imagePickerController(
+    _ picker: UIImagePickerController,
+    didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]
+  ) {
+    var image: UIImage?
+
+    if let originalImage = info[.originalImage] as? UIImage {
+      image = originalImage
+    }
 
-        guard let image = image else {
-            picker.dismiss(animated: true)
-            return
-        }
+    if let croppedImage = info[.editedImage] as? UIImage {
+      image = croppedImage
+    }
 
-        picker.dismiss(animated: true)
-        viewModel.didChoosePhoto(image)
+    guard let image = image else {
+      picker.dismiss(animated: true)
+      return
     }
+
+    picker.dismiss(animated: true)
+    viewModel.didChoosePhoto(image)
+  }
 }
 
 extension ProfileController: UINavigationControllerDelegate {}
diff --git a/Sources/ProfileFeature/Controllers/ProfileEmailController.swift b/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
index 799cbae557abf3808f8f297fadfff08ffb9d8bb3..f06b1f30d4b756ac5b9403753aa8e6876ba0e0fa 100644
--- a/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
@@ -2,83 +2,82 @@ import HUD
 import UIKit
 import Shared
 import Combine
-import Theme
 import DependencyInjection
 import ScrollViewController
 
 public final class ProfileEmailController: UIViewController {
-    @Dependency private var hud: HUD
-    @Dependency private var coordinator: ProfileCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
+  @Dependency var hud: HUD
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: ProfileCoordinating
 
-    lazy private var screenView = ProfileEmailView()
-    lazy private var scrollViewController = ScrollViewController()
+  lazy private var screenView = ProfileEmailView()
+  lazy private var scrollViewController = ScrollViewController()
 
-    private let viewModel = ProfileEmailViewModel()
-    private var cancellables = Set<AnyCancellable>()
+  private let viewModel = ProfileEmailViewModel()
+  private var cancellables = Set<AnyCancellable>()
 
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar
-            .customize(backgroundColor: Asset.neutralWhite.color)
-    }
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar
+      .customize(backgroundColor: Asset.neutralWhite.color)
+  }
 
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupScrollView()
-        setupBindings()
-    }
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupScrollView()
+    setupBindings()
+  }
 
-    private func setupScrollView() {
-        addChild(scrollViewController)
-        view.addSubview(scrollViewController.view)
-        scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
-        scrollViewController.didMove(toParent: self)
-        scrollViewController.contentView = screenView
-        scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
-    }
+  private func setupScrollView() {
+    addChild(scrollViewController)
+    view.addSubview(scrollViewController.view)
+    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.didMove(toParent: self)
+    scrollViewController.contentView = screenView
+    scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
+  }
 
-    private func setupBindings() {
-        viewModel.hud
-            .receive(on: DispatchQueue.main)
-            .sink { [hud] in hud.update(with: $0) }
-            .store(in: &cancellables)
+  private func setupBindings() {
+    viewModel.hud
+      .receive(on: DispatchQueue.main)
+      .sink { [hud] in hud.update(with: $0) }
+      .store(in: &cancellables)
 
-        screenView.inputField.textPublisher
-            .sink { [unowned self] in viewModel.didInput($0) }
-            .store(in: &cancellables)
+    screenView.inputField.textPublisher
+      .sink { [unowned self] in viewModel.didInput($0) }
+      .store(in: &cancellables)
 
-        screenView.inputField.returnPublisher
-            .sink { [unowned self] in screenView.inputField.endEditing(true) }
-            .store(in: &cancellables)
+    screenView.inputField.returnPublisher
+      .sink { [unowned self] in screenView.inputField.endEditing(true) }
+      .store(in: &cancellables)
 
-        viewModel.state
-            .map(\.confirmation)
-            .receive(on: DispatchQueue.main)
-            .compactMap { $0 }
-            .sink { [unowned self] in
-                viewModel.clearUp()
-                coordinator.toCode(with: $0, from: self) { _, _ in
-                    if let viewControllers = self.navigationController?.viewControllers {
-                        self.navigationController?.popToViewController(
-                            viewControllers[viewControllers.count - 3],
-                            animated: true
-                        )
-                    }
-                }
-            }
-            .store(in: &cancellables)
+    viewModel.state
+      .map(\.confirmation)
+      .receive(on: DispatchQueue.main)
+      .compactMap { $0 }
+      .sink { [unowned self] in
+        viewModel.clearUp()
+        coordinator.toCode(with: $0, from: self) { _, _ in
+          if let viewControllers = self.navigationController?.viewControllers {
+            self.navigationController?.popToViewController(
+              viewControllers[viewControllers.count - 3],
+              animated: true
+            )
+          }
+        }
+      }
+      .store(in: &cancellables)
 
-        viewModel.state.map(\.status)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.update(status: $0) }
-            .store(in: &cancellables)
+    viewModel.state.map(\.status)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.update(status: $0) }
+      .store(in: &cancellables)
 
-        screenView.saveButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewModel.didTapNext() }
-            .store(in: &cancellables)
-    }
+    screenView.saveButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewModel.didTapNext() }
+      .store(in: &cancellables)
+  }
 }
diff --git a/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift b/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
index 34fbd10bf1cabcb14ae5b93474d0d3b8b835b369..0b1264850c2049efbbffc11fe8f33b09d88028d8 100644
--- a/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
@@ -2,99 +2,98 @@ import HUD
 import UIKit
 import Shared
 import Combine
-import Theme
 import DependencyInjection
 import ScrollViewController
 
 public final class ProfilePhoneController: UIViewController {
-    @Dependency private var hud: HUD
-    @Dependency private var coordinator: ProfileCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
+  @Dependency var hud: HUD
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: ProfileCoordinating
 
-    lazy private var screenView = ProfilePhoneView()
-    lazy private var scrollViewController = ScrollViewController()
+  lazy private var screenView = ProfilePhoneView()
+  lazy private var scrollViewController = ScrollViewController()
 
-    private let viewModel = ProfilePhoneViewModel()
-    private var cancellables = Set<AnyCancellable>()
+  private let viewModel = ProfilePhoneViewModel()
+  private var cancellables = Set<AnyCancellable>()
 
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar
-            .customize(backgroundColor: Asset.neutralWhite.color)
-    }
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar
+      .customize(backgroundColor: Asset.neutralWhite.color)
+  }
 
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupScrollView()
-        setupBindings()
-    }
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupScrollView()
+    setupBindings()
+  }
 
-    private func setupScrollView() {
-        addChild(scrollViewController)
-        view.addSubview(scrollViewController.view)
-        scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
-        scrollViewController.didMove(toParent: self)
-        scrollViewController.contentView = screenView
-        scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
-    }
+  private func setupScrollView() {
+    addChild(scrollViewController)
+    view.addSubview(scrollViewController.view)
+    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.didMove(toParent: self)
+    scrollViewController.contentView = screenView
+    scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
+  }
 
-    private func setupBindings() {
-        viewModel.hud
-            .receive(on: DispatchQueue.main)
-            .sink { [hud] in hud.update(with: $0) }
-            .store(in: &cancellables)
+  private func setupBindings() {
+    viewModel.hud
+      .receive(on: DispatchQueue.main)
+      .sink { [hud] in hud.update(with: $0) }
+      .store(in: &cancellables)
 
-        screenView.inputField.textPublisher
-            .sink { [unowned self] in viewModel.didInput($0) }
-            .store(in: &cancellables)
+    screenView.inputField.textPublisher
+      .sink { [unowned self] in viewModel.didInput($0) }
+      .store(in: &cancellables)
 
-        screenView.inputField.returnPublisher
-            .sink { [unowned self] in screenView.inputField.endEditing(true) }
-            .store(in: &cancellables)
+    screenView.inputField.returnPublisher
+      .sink { [unowned self] in screenView.inputField.endEditing(true) }
+      .store(in: &cancellables)
 
-        screenView.inputField.codePublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                coordinator.toCountries(from: self) { self.viewModel.didChooseCountry($0) }
-            }.store(in: &cancellables)
+    screenView.inputField.codePublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        coordinator.toCountries(from: self) { self.viewModel.didChooseCountry($0) }
+      }.store(in: &cancellables)
 
-        viewModel.state
-            .map(\.confirmation)
-            .receive(on: DispatchQueue.main)
-            .compactMap { $0 }
-            .sink { [unowned self] in
-                viewModel.clearUp()
-                coordinator.toCode(with: $0, from: self) { _, _ in
-                    if let viewControllers = self.navigationController?.viewControllers {
-                        self.navigationController?.popToViewController(
-                            viewControllers[viewControllers.count - 3],
-                            animated: true
-                        )
-                    }
-                }
-            }.store(in: &cancellables)
+    viewModel.state
+      .map(\.confirmation)
+      .receive(on: DispatchQueue.main)
+      .compactMap { $0 }
+      .sink { [unowned self] in
+        viewModel.clearUp()
+        coordinator.toCode(with: $0, from: self) { _, _ in
+          if let viewControllers = self.navigationController?.viewControllers {
+            self.navigationController?.popToViewController(
+              viewControllers[viewControllers.count - 3],
+              animated: true
+            )
+          }
+        }
+      }.store(in: &cancellables)
 
-        viewModel.state
-            .map(\.country)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                screenView.inputField.set(prefix: $0.prefixWithFlag)
-                screenView.inputField.update(placeholder: $0.example)
-            }
-            .store(in: &cancellables)
+    viewModel.state
+      .map(\.country)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.inputField.set(prefix: $0.prefixWithFlag)
+        screenView.inputField.update(placeholder: $0.example)
+      }
+      .store(in: &cancellables)
 
-        viewModel.state
-            .map(\.status)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.update(status: $0) }
-            .store(in: &cancellables)
+    viewModel.state
+      .map(\.status)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.update(status: $0) }
+      .store(in: &cancellables)
 
-        screenView.saveButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewModel.didTapNext() }
-            .store(in: &cancellables)
-    }
+    screenView.saveButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewModel.didTapNext() }
+      .store(in: &cancellables)
+  }
 }
diff --git a/Sources/RequestsFeature/Controllers/RequestsContainerController.swift b/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
index f3f7b3937059b0b30185e139b79b597f338061ca..ef723bcb358bbbd0d532c1138a0053be75334883 100644
--- a/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
@@ -1,118 +1,117 @@
 import UIKit
-import Theme
 import Shared
 import Combine
 import ContactFeature
 import DependencyInjection
 
 public final class RequestsContainerController: UIViewController {
-    @Dependency private var coordinator: RequestsCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: RequestsCoordinating
 
-    lazy private var screenView = RequestsContainerView()
-    private var cancellables = Set<AnyCancellable>()
+  lazy private var screenView = RequestsContainerView()
+  private var cancellables = Set<AnyCancellable>()
 
-    public override func loadView() {
-        view = screenView
-        screenView.scrollView.delegate = self
+  public override func loadView() {
+    view = screenView
+    screenView.scrollView.delegate = self
 
-        addChild(screenView.sentController)
-        addChild(screenView.failedController)
-        addChild(screenView.receivedController)
+    addChild(screenView.sentController)
+    addChild(screenView.failedController)
+    addChild(screenView.receivedController)
 
-        screenView.sentController.didMove(toParent: self)
-        screenView.failedController.didMove(toParent: self)
-        screenView.receivedController.didMove(toParent: self)
+    screenView.sentController.didMove(toParent: self)
+    screenView.failedController.didMove(toParent: self)
+    screenView.receivedController.didMove(toParent: self)
 
-        screenView.bringSubviewToFront(screenView.segmentedControl)
-    }
+    screenView.bringSubviewToFront(screenView.segmentedControl)
+  }
 
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        statusBarController.style.send(.darkContent)
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    barStylist.styleSubject.send(.darkContent)
 
-        navigationController?.navigationBar
-            .customize(backgroundColor: Asset.neutralWhite.color)
-    }
+    navigationController?.navigationBar
+      .customize(backgroundColor: Asset.neutralWhite.color)
+  }
 
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupNavigationBar()
-        setupBindings()
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupNavigationBar()
+    setupBindings()
 
-        if let stack = navigationController?.viewControllers, stack.count > 1 {
-            if stack[stack.count - 2].isKind(of: ContactController.self) {
-                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
-                    guard let self = self else { return }
+    if let stack = navigationController?.viewControllers, stack.count > 1 {
+      if stack[stack.count - 2].isKind(of: ContactController.self) {
+        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
+          guard let self = self else { return }
 
-                    let point = CGPoint(x: self.screenView.frame.width, y: 0.0)
-                    self.screenView.scrollView.setContentOffset(point, animated: true)
-                }
-            }
+          let point = CGPoint(x: self.screenView.frame.width, y: 0.0)
+          self.screenView.scrollView.setContentOffset(point, animated: true)
         }
+      }
     }
-
-    private func setupNavigationBar() {
-        navigationItem.backButtonTitle = ""
-
-        let titleLabel = UILabel()
-        titleLabel.text = Localized.Requests.title
-        titleLabel.textColor = Asset.neutralActive.color
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 18.0)
-
-        let menuButton = UIButton()
-        menuButton.tintColor = Asset.neutralDark.color
-        menuButton.setImage(Asset.chatListMenu.image, for: .normal)
-        menuButton.addTarget(self, action: #selector(didTapMenu), for: .touchUpInside)
-        menuButton.snp.makeConstraints { $0.width.equalTo(50) }
-
-        navigationItem.leftBarButtonItem = UIBarButtonItem(
-            customView: UIStackView(arrangedSubviews: [menuButton, titleLabel])
-        )
-    }
-
-    private func setupBindings() {
-        screenView
-            .sentController
-            .connectionsPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toSearch(from: self) }
-            .store(in: &cancellables)
-
-        screenView
-            .segmentedControl
-            .receivedRequestsButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] _ in
-                screenView.scrollView.setContentOffset(.zero, animated: true)
-            }.store(in: &cancellables)
-
-        screenView
-            .segmentedControl
-            .sentRequestsButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] _ in
-                let point = CGPoint(x: screenView.frame.width, y: 0.0)
-                screenView.scrollView.setContentOffset(point, animated: true)
-            }.store(in: &cancellables)
-
-        screenView
-            .segmentedControl
-            .failedRequestsButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] _ in
-                let point = CGPoint(x: screenView.frame.width * 2.0, y: 0.0)
-                screenView.scrollView.setContentOffset(point, animated: true)
-            }.store(in: &cancellables)
-    }
-
-    @objc private func didTapMenu() {
-        coordinator.toSideMenu(from: self)
-    }
+  }
+
+  private func setupNavigationBar() {
+    navigationItem.backButtonTitle = ""
+
+    let titleLabel = UILabel()
+    titleLabel.text = Localized.Requests.title
+    titleLabel.textColor = Asset.neutralActive.color
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 18.0)
+
+    let menuButton = UIButton()
+    menuButton.tintColor = Asset.neutralDark.color
+    menuButton.setImage(Asset.chatListMenu.image, for: .normal)
+    menuButton.addTarget(self, action: #selector(didTapMenu), for: .touchUpInside)
+    menuButton.snp.makeConstraints { $0.width.equalTo(50) }
+
+    navigationItem.leftBarButtonItem = UIBarButtonItem(
+      customView: UIStackView(arrangedSubviews: [menuButton, titleLabel])
+    )
+  }
+
+  private func setupBindings() {
+    screenView
+      .sentController
+      .connectionsPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toSearch(from: self) }
+      .store(in: &cancellables)
+
+    screenView
+      .segmentedControl
+      .receivedRequestsButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] _ in
+        screenView.scrollView.setContentOffset(.zero, animated: true)
+      }.store(in: &cancellables)
+
+    screenView
+      .segmentedControl
+      .sentRequestsButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] _ in
+        let point = CGPoint(x: screenView.frame.width, y: 0.0)
+        screenView.scrollView.setContentOffset(point, animated: true)
+      }.store(in: &cancellables)
+
+    screenView
+      .segmentedControl
+      .failedRequestsButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] _ in
+        let point = CGPoint(x: screenView.frame.width * 2.0, y: 0.0)
+        screenView.scrollView.setContentOffset(point, animated: true)
+      }.store(in: &cancellables)
+  }
+
+  @objc private func didTapMenu() {
+    coordinator.toSideMenu(from: self)
+  }
 }
 
 extension RequestsContainerController: UIScrollViewDelegate {
-    public func scrollViewDidScroll(_ scrollView: UIScrollView) {
-        screenView.segmentedControl.updateSwipePercentage(scrollView.contentOffset.x / view.frame.width)
-    }
+  public func scrollViewDidScroll(_ scrollView: UIScrollView) {
+    screenView.segmentedControl.updateSwipePercentage(scrollView.contentOffset.x / view.frame.width)
+  }
 }
diff --git a/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift b/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
index 0a30d05fb32b5ec4d3eb54b1fdeb9ced674a17ac..c5a9118966df113885bae7de0d6d4538470d4bff 100644
--- a/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
@@ -5,7 +5,6 @@ import Shared
 import Combine
 import XXModels
 import Countries
-import ToastFeature
 import DrawerFeature
 import DependencyInjection
 
diff --git a/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift
index e23720943c3e900c1c322c2d717a4884a97c6d27..86dd95914ac5871a15497b22529901f39bfe4e49 100644
--- a/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift
+++ b/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift
@@ -7,7 +7,6 @@ import Defaults
 import XXModels
 import Defaults
 import XXClient
-import ToastFeature
 import ReportingFeature
 import CombineSchedulers
 import DependencyInjection
diff --git a/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift b/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
index fd4f97899558664da35f86da6c1ebfaa8438b0d8..4f6f1d9b9a0befadf8ea5060e556cf890207e64c 100644
--- a/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
@@ -1,11 +1,11 @@
 import UIKit
-import Theme
+import Shared
 import Combine
 import DependencyInjection
 
 public final class RestoreSuccessController: UIViewController {
+  @Dependency var barStylist: StatusBarStylist
   @Dependency var coordinator: RestoreCoordinating
-  @Dependency var statusBarController: StatusBarStyleControlling
 
   lazy private var screenView = RestoreSuccessView()
   private var cancellables = Set<AnyCancellable>()
@@ -16,7 +16,7 @@ public final class RestoreSuccessController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    statusBarController.style.send(.darkContent)
+    barStylist.styleSubject.send(.darkContent)
     navigationController?.navigationBar.customize(translucent: true)
   }
 
diff --git a/Sources/ScanFeature/Controllers/ScanContainerController.swift b/Sources/ScanFeature/Controllers/ScanContainerController.swift
index 41df6a8705056d9f68ef82366b890d6e07f4140f..9105e1329ddbbeab058bc0497100dfb7945db2f0 100644
--- a/Sources/ScanFeature/Controllers/ScanContainerController.swift
+++ b/Sources/ScanFeature/Controllers/ScanContainerController.swift
@@ -1,190 +1,189 @@
 import UIKit
-import Theme
 import Shared
 import Combine
 import DrawerFeature
 import DependencyInjection
 
 public final class ScanContainerController: UIViewController {
-    @Dependency private var coordinator: ScanCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    lazy private var screenView = ScanContainerView()
-
-    private let scanController = ScanController()
-    private var cancellables = Set<AnyCancellable>()
-    private var drawerCancellables = Set<AnyCancellable>()
-    private let displayController = ScanDisplayController()
-    private let pageController = UIPageViewController(
-        transitionStyle: .scroll,
-        navigationOrientation: .horizontal
-    )
-
-    public override func loadView() {
-        view = screenView
-
-        addChild(pageController)
-        screenView.addSubview(pageController.view)
-        pageController.view.snp.makeConstraints {
-            $0.top.equalTo(screenView.stackView.snp.bottom)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalTo(screenView)
-        }
-
-        pageController.delegate = self
-        pageController.dataSource = self
-        pageController.didMove(toParent: self)
-        pageController.setViewControllers([scanController], direction: .forward, animated: true)
-        screenView.bringSubviewToFront(screenView.stackView)
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: ScanCoordinating
+
+  lazy private var screenView = ScanContainerView()
+
+  private let scanController = ScanController()
+  private var cancellables = Set<AnyCancellable>()
+  private var drawerCancellables = Set<AnyCancellable>()
+  private let displayController = ScanDisplayController()
+  private let pageController = UIPageViewController(
+    transitionStyle: .scroll,
+    navigationOrientation: .horizontal
+  )
+
+  public override func loadView() {
+    view = screenView
+
+    addChild(pageController)
+    screenView.addSubview(pageController.view)
+    pageController.view.snp.makeConstraints {
+      $0.top.equalTo(screenView.stackView.snp.bottom)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalTo(screenView)
     }
 
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        statusBarController.style.send(.lightContent)
-        navigationController?.navigationBar.customize(translucent: true)
+    pageController.delegate = self
+    pageController.dataSource = self
+    pageController.didMove(toParent: self)
+    pageController.setViewControllers([scanController], direction: .forward, animated: true)
+    screenView.bringSubviewToFront(screenView.stackView)
+  }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    barStylist.styleSubject.send(.lightContent)
+    navigationController?.navigationBar.customize(translucent: true)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupNavigationBar()
+    setupBindings()
+
+    displayController.didTapInfo = { [weak self] in
+      self?.presentInfo(
+        title: Localized.Scan.Info.title,
+        subtitle: Localized.Scan.Info.subtitle
+      )
     }
 
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupNavigationBar()
-        setupBindings()
-
-        displayController.didTapInfo = { [weak self] in
-            self?.presentInfo(
-                title: Localized.Scan.Info.title,
-                subtitle: Localized.Scan.Info.subtitle
-            )
-        }
-
-        displayController.didTapAddEmail = { [weak self] in
-            guard let self = self else { return }
-            self.coordinator.toEmail(from: self)
-        }
+    displayController.didTapAddEmail = { [weak self] in
+      guard let self = self else { return }
+      self.coordinator.toEmail(from: self)
+    }
 
-        displayController.didTapAddPhone = { [weak self] in
-            guard let self = self else { return }
-            self.coordinator.toPhone(from: self)
-        }
+    displayController.didTapAddPhone = { [weak self] in
+      guard let self = self else { return }
+      self.coordinator.toPhone(from: self)
     }
+  }
 
-    private func setupNavigationBar() {
-        navigationItem.backButtonTitle = ""
+  private func setupNavigationBar() {
+    navigationItem.backButtonTitle = ""
 
-        let titleLabel = UILabel()
-        titleLabel.text = "QR Code"
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 18.0)
-        titleLabel.textColor = Asset.neutralWhite.color
+    let titleLabel = UILabel()
+    titleLabel.text = "QR Code"
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 18.0)
+    titleLabel.textColor = Asset.neutralWhite.color
 
-        let menuButton = UIButton()
-        menuButton.tintColor = Asset.neutralWhite.color
-        menuButton.setImage(Asset.chatListMenu.image, for: .normal)
-        menuButton.addTarget(self, action: #selector(didTapMenu), for: .touchUpInside)
-        menuButton.snp.makeConstraints { $0.width.equalTo(50) }
+    let menuButton = UIButton()
+    menuButton.tintColor = Asset.neutralWhite.color
+    menuButton.setImage(Asset.chatListMenu.image, for: .normal)
+    menuButton.addTarget(self, action: #selector(didTapMenu), for: .touchUpInside)
+    menuButton.snp.makeConstraints { $0.width.equalTo(50) }
 
-        navigationItem.leftBarButtonItem = UIBarButtonItem(
-            customView: UIStackView(arrangedSubviews: [menuButton, titleLabel])
-        )
-    }
-
-    private func setupBindings() {
-        screenView.leftButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] _ in
-                screenView.leftButton.set(selected: true)
-                screenView.rightButton.set(selected: false)
-                pageController.setViewControllers([scanController], direction: .reverse, animated: true, completion: nil)
-            }.store(in: &cancellables)
-
-        screenView.rightButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] _ in
-                screenView.leftButton.set(selected: false)
-                screenView.rightButton.set(selected: true)
-                pageController.setViewControllers([displayController], direction: .forward, animated: true, completion: nil)
-            }.store(in: &cancellables)
-    }
+    navigationItem.leftBarButtonItem = UIBarButtonItem(
+      customView: UIStackView(arrangedSubviews: [menuButton, titleLabel])
+    )
+  }
+
+  private func setupBindings() {
+    screenView.leftButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] _ in
+        screenView.leftButton.set(selected: true)
+        screenView.rightButton.set(selected: false)
+        pageController.setViewControllers([scanController], direction: .reverse, animated: true, completion: nil)
+      }.store(in: &cancellables)
+
+    screenView.rightButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] _ in
+        screenView.leftButton.set(selected: false)
+        screenView.rightButton.set(selected: true)
+        pageController.setViewControllers([displayController], direction: .forward, animated: true, completion: nil)
+      }.store(in: &cancellables)
+  }
+
+  @objc private func didTapMenu() {
+    coordinator.toSideMenu(from: self)
+  }
+
+  private func presentInfo(title: String, subtitle: String) {
+    let actionButton = CapsuleButton()
+    actionButton.set(
+      style: .seeThrough,
+      title: Localized.Settings.InfoDrawer.action
+    )
 
-    @objc private func didTapMenu() {
-        coordinator.toSideMenu(from: self)
-    }
+    let drawer = DrawerController(with: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerText(
+        font: Fonts.Mulish.regular.font(size: 16.0),
+        text: subtitle,
+        color: Asset.neutralBody.color,
+        alignment: .left,
+        lineHeightMultiple: 1.1,
+        spacingAfter: 37
+      ),
+      DrawerStack(views: [
+        actionButton,
+        FlexibleSpace()
+      ])
+    ])
+
+    actionButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-    private func presentInfo(title: String, subtitle: String) {
-        let actionButton = CapsuleButton()
-        actionButton.set(
-            style: .seeThrough,
-            title: Localized.Settings.InfoDrawer.action
-        )
-
-        let drawer = DrawerController(with: [
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerText(
-                font: Fonts.Mulish.regular.font(size: 16.0),
-                text: subtitle,
-                color: Asset.neutralBody.color,
-                alignment: .left,
-                lineHeightMultiple: 1.1,
-                spacingAfter: 37
-            ),
-            DrawerStack(views: [
-                actionButton,
-                FlexibleSpace()
-            ])
-        ])
-
-        actionButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+    coordinator.toDrawer(drawer, from: self)
+  }
 }
 
 extension ScanContainerController: UIPageViewControllerDataSource {
-    public func pageViewController(
-        _ pageViewController: UIPageViewController,
-        viewControllerAfter viewController: UIViewController
-    ) -> UIViewController? {
-        guard viewController != displayController else { return nil }
-        return displayController
-    }
-
-    public func pageViewController(
-        _ pageViewController: UIPageViewController,
-        viewControllerBefore viewController: UIViewController
-    ) -> UIViewController? {
-        guard viewController != scanController else { return nil }
-        return scanController
-    }
+  public func pageViewController(
+    _ pageViewController: UIPageViewController,
+    viewControllerAfter viewController: UIViewController
+  ) -> UIViewController? {
+    guard viewController != displayController else { return nil }
+    return displayController
+  }
+
+  public func pageViewController(
+    _ pageViewController: UIPageViewController,
+    viewControllerBefore viewController: UIViewController
+  ) -> UIViewController? {
+    guard viewController != scanController else { return nil }
+    return scanController
+  }
 }
 
 
 extension ScanContainerController: UIPageViewControllerDelegate {
-    public func pageViewController(
-        _ pageViewController: UIPageViewController,
-        didFinishAnimating finished: Bool,
-        previousViewControllers: [UIViewController],
-        transitionCompleted completed: Bool
-    ) {
-        guard finished, completed else { return }
-
-        if previousViewControllers.contains(scanController) {
-            screenView.leftButton.set(selected: false)
-            screenView.rightButton.set(selected: true)
-        } else {
-            screenView.leftButton.set(selected: true)
-            screenView.rightButton.set(selected: false)
-        }
+  public func pageViewController(
+    _ pageViewController: UIPageViewController,
+    didFinishAnimating finished: Bool,
+    previousViewControllers: [UIViewController],
+    transitionCompleted completed: Bool
+  ) {
+    guard finished, completed else { return }
+
+    if previousViewControllers.contains(scanController) {
+      screenView.leftButton.set(selected: false)
+      screenView.rightButton.set(selected: true)
+    } else {
+      screenView.leftButton.set(selected: true)
+      screenView.rightButton.set(selected: false)
     }
+  }
 }
diff --git a/Sources/SearchFeature/Controllers/SearchContainerController.swift b/Sources/SearchFeature/Controllers/SearchContainerController.swift
index 15cb91be299d187b5dffb2f82bb68bb1c9f19d80..69665f8c946e0887c5ff5ba2d186944bcd9728d4 100644
--- a/Sources/SearchFeature/Controllers/SearchContainerController.swift
+++ b/Sources/SearchFeature/Controllers/SearchContainerController.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Theme
 import Shared
 import Combine
 import XXModels
@@ -7,182 +6,182 @@ import DrawerFeature
 import DependencyInjection
 
 public final class SearchContainerController: UIViewController {
-    @Dependency var coordinator: SearchCoordinating
-    @Dependency var statusBarController: StatusBarStyleControlling
-
-    lazy private var screenView = SearchContainerView()
-
-    private var contentOffset: CGPoint?
-    private var cancellables = Set<AnyCancellable>()
-    private let leftController: SearchLeftController
-    private let viewModel = SearchContainerViewModel()
-    private let rightController = SearchRightController()
-    private var drawerCancellables = Set<AnyCancellable>()
-
-    public init(_ invitation: String? = nil) {
-        self.leftController = .init(invitation)
-        super.init(nibName: nil, bundle: nil)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func loadView() {
-        view = screenView
-        embedControllers()
-    }
-
-    public func startSearchingFor(_ string: String) {
-        leftController.viewModel.invitation = string
-        leftController.viewModel.viewDidAppear()
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: SearchCoordinating
+
+  lazy private var screenView = SearchContainerView()
+
+  private var contentOffset: CGPoint?
+  private var cancellables = Set<AnyCancellable>()
+  private let leftController: SearchLeftController
+  private let viewModel = SearchContainerViewModel()
+  private let rightController = SearchRightController()
+  private var drawerCancellables = Set<AnyCancellable>()
+
+  public init(_ invitation: String? = nil) {
+    self.leftController = .init(invitation)
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func loadView() {
+    view = screenView
+    embedControllers()
+  }
+
+  public func startSearchingFor(_ string: String) {
+    leftController.viewModel.invitation = string
+    leftController.viewModel.viewDidAppear()
+  }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar.customize(
+      backgroundColor: Asset.neutralWhite.color
+    )
+
+    if let contentOffset = self.contentOffset {
+      screenView.scrollView.setContentOffset(contentOffset, animated: true)
     }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar.customize(
-            backgroundColor: Asset.neutralWhite.color
-        )
-
-        if let contentOffset = self.contentOffset {
-            screenView.scrollView.setContentOffset(contentOffset, animated: true)
+  }
+
+  public override func viewWillDisappear(_ animated: Bool) {
+    super.viewWillDisappear(animated)
+    contentOffset = screenView.scrollView.contentOffset
+  }
+
+  public override func viewDidAppear(_ animated: Bool) {
+    super.viewDidAppear(animated)
+    viewModel.didAppear()
+    rightController.viewModel.viewWillAppear()
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupNavigationBar()
+    setupBindings()
+  }
+
+  private func setupNavigationBar() {
+    let title = UILabel()
+    title.text = Localized.Ud.title
+    title.textColor = Asset.neutralActive.color
+    title.font = Fonts.Mulish.semiBold.font(size: 18.0)
+
+    navigationItem.leftBarButtonItem = UIBarButtonItem(customView: title)
+    navigationItem.leftItemsSupplementBackButton = true
+  }
+
+  private func setupBindings() {
+    screenView.segmentedControl
+      .actionPublisher
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        if $0 == .qr {
+          let point = CGPoint(x: screenView.frame.width, y: 0.0)
+          screenView.scrollView.setContentOffset(point, animated: true)
+          leftController.endEditing()
+        } else {
+          screenView.scrollView.setContentOffset(.zero, animated: true)
+          leftController.viewModel.didSelectItem($0)
         }
+      }.store(in: &cancellables)
+
+    viewModel.coverTrafficPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in presentCoverTrafficDrawer() }
+      .store(in: &cancellables)
+  }
+
+  private func embedControllers() {
+    addChild(leftController)
+    addChild(rightController)
+
+    screenView.scrollView.addSubview(leftController.view)
+    screenView.scrollView.addSubview(rightController.view)
+
+    leftController.view.snp.makeConstraints {
+      $0.top.equalTo(screenView.segmentedControl.snp.bottom)
+      $0.width.equalTo(screenView)
+      $0.bottom.equalTo(screenView)
+      $0.left.equalToSuperview()
+      $0.right.equalTo(rightController.view.snp.left)
     }
 
-    public override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-        contentOffset = screenView.scrollView.contentOffset
-    }
-
-    public override func viewDidAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-        viewModel.didAppear()
-        rightController.viewModel.viewWillAppear()
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupNavigationBar()
-        setupBindings()
+    rightController.view.snp.makeConstraints {
+      $0.top.equalTo(screenView.segmentedControl.snp.bottom)
+      $0.width.equalTo(screenView)
+      $0.bottom.equalTo(screenView)
     }
 
-    private func setupNavigationBar() {
-        let title = UILabel()
-        title.text = Localized.Ud.title
-        title.textColor = Asset.neutralActive.color
-        title.font = Fonts.Mulish.semiBold.font(size: 18.0)
-
-        navigationItem.leftBarButtonItem = UIBarButtonItem(customView: title)
-        navigationItem.leftItemsSupplementBackButton = true
-    }
-
-    private func setupBindings() {
-        screenView.segmentedControl
-            .actionPublisher
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                if $0 == .qr {
-                    let point = CGPoint(x: screenView.frame.width, y: 0.0)
-                    screenView.scrollView.setContentOffset(point, animated: true)
-                    leftController.endEditing()
-                } else {
-                    screenView.scrollView.setContentOffset(.zero, animated: true)
-                    leftController.viewModel.didSelectItem($0)
-                }
-            }.store(in: &cancellables)
-
-        viewModel.coverTrafficPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in presentCoverTrafficDrawer() }
-            .store(in: &cancellables)
-    }
-
-    private func embedControllers() {
-        addChild(leftController)
-        addChild(rightController)
-
-        screenView.scrollView.addSubview(leftController.view)
-        screenView.scrollView.addSubview(rightController.view)
+    leftController.didMove(toParent: self)
+    rightController.didMove(toParent: self)
+  }
+}
 
-        leftController.view.snp.makeConstraints {
-            $0.top.equalTo(screenView.segmentedControl.snp.bottom)
-            $0.width.equalTo(screenView)
-            $0.bottom.equalTo(screenView)
-            $0.left.equalToSuperview()
-            $0.right.equalTo(rightController.view.snp.left)
+extension SearchContainerController {
+  private func presentCoverTrafficDrawer() {
+    let enableButton = CapsuleButton()
+    enableButton.set(
+      style: .brandColored,
+      title: Localized.ChatList.Traffic.positive
+    )
+
+    let dismissButton = CapsuleButton()
+    dismissButton.set(
+      style: .seeThrough,
+      title: Localized.ChatList.Traffic.negative
+    )
+
+    let drawer = DrawerController(with: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: Localized.ChatList.Traffic.title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerText(
+        font: Fonts.Mulish.regular.font(size: 16.0),
+        text: Localized.ChatList.Traffic.subtitle,
+        color: Asset.neutralBody.color,
+        alignment: .left,
+        lineHeightMultiple: 1.1,
+        spacingAfter: 39
+      ),
+      DrawerStack(
+        axis: .horizontal,
+        spacing: 20,
+        distribution: .fillEqually,
+        views: [enableButton, dismissButton]
+      )
+    ])
+
+    enableButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didEnableCoverTraffic()
         }
-
-        rightController.view.snp.makeConstraints {
-            $0.top.equalTo(screenView.segmentedControl.snp.bottom)
-            $0.width.equalTo(screenView)
-            $0.bottom.equalTo(screenView)
+      }.store(in: &drawerCancellables)
+
+    dismissButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
         }
+      }.store(in: &drawerCancellables)
 
-        leftController.didMove(toParent: self)
-        rightController.didMove(toParent: self)
-    }
-}
-
-extension SearchContainerController {
-    private func presentCoverTrafficDrawer() {
-        let enableButton = CapsuleButton()
-        enableButton.set(
-            style: .brandColored,
-            title: Localized.ChatList.Traffic.positive
-        )
-
-        let dismissButton = CapsuleButton()
-        dismissButton.set(
-            style: .seeThrough,
-            title: Localized.ChatList.Traffic.negative
-        )
-
-        let drawer = DrawerController(with: [
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: Localized.ChatList.Traffic.title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerText(
-                font: Fonts.Mulish.regular.font(size: 16.0),
-                text: Localized.ChatList.Traffic.subtitle,
-                color: Asset.neutralBody.color,
-                alignment: .left,
-                lineHeightMultiple: 1.1,
-                spacingAfter: 39
-            ),
-            DrawerStack(
-                axis: .horizontal,
-                spacing: 20,
-                distribution: .fillEqually,
-                views: [enableButton, dismissButton]
-            )
-        ])
-
-        enableButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                    self.viewModel.didEnableCoverTraffic()
-                }
-            }.store(in: &drawerCancellables)
-
-        dismissButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+    coordinator.toDrawer(drawer, from: self)
+  }
 }
diff --git a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
index 67b8d649a9875a94d8da43aade89be448e4262e3..e7a0921a149c6cb95f288a68912fe970cc4d93e6 100644
--- a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
+++ b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
@@ -9,7 +9,6 @@ import XXClient
 import Defaults
 import Countries
 import CustomDump
-import ToastFeature
 import NetworkMonitor
 import ReportingFeature
 import CombineSchedulers
diff --git a/Sources/SettingsFeature/Controllers/SettingsController.swift b/Sources/SettingsFeature/Controllers/SettingsController.swift
index e58a347096e53ddefc3014517c4f11c946a06429..af68cf87bf8803e6282b23bc9340aa25404c63cd 100644
--- a/Sources/SettingsFeature/Controllers/SettingsController.swift
+++ b/Sources/SettingsFeature/Controllers/SettingsController.swift
@@ -1,300 +1,299 @@
 import HUD
-import DrawerFeature
 import UIKit
-import Theme
 import Shared
 import Combine
+import DrawerFeature
 import DependencyInjection
 import ScrollViewController
 
 public final class SettingsController: UIViewController {
-    @Dependency private var hud: HUD
-    @Dependency private var coordinator: SettingsCoordinating
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    lazy private var scrollViewController = ScrollViewController()
-    lazy private var screenView = SettingsView {
-        switch $0 {
-        case .icognitoKeyboard:
-            self.presentInfo(
-                title: Localized.Settings.InfoDrawer.Icognito.title,
-                subtitle: Localized.Settings.InfoDrawer.Icognito.subtitle
-            )
-        case .biometrics:
-            self.presentInfo(
-                title: Localized.Settings.InfoDrawer.Biometrics.title,
-                subtitle: Localized.Settings.InfoDrawer.Biometrics.subtitle
-            )
-        case .notifications:
-            self.presentInfo(
-                title: Localized.Settings.InfoDrawer.Notifications.title,
-                subtitle: Localized.Settings.InfoDrawer.Notifications.subtitle,
-                urlString: "https://links.xx.network/denseids"
-            )
-
-        case .dummyTraffic:
-            self.presentInfo(
-                title: Localized.Settings.InfoDrawer.Traffic.title,
-                subtitle: Localized.Settings.InfoDrawer.Traffic.subtitle,
-                urlString: "https://links.xx.network/covertraffic"
-            )
-        }
-    }
-
-    private let viewModel = SettingsViewModel()
-    private var cancellables = Set<AnyCancellable>()
-    private var drawerCancellables = Set<AnyCancellable>()
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        statusBarController.style.send(.darkContent)
-        navigationController?.navigationBar
-            .customize(backgroundColor: Asset.neutralWhite.color)
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-
-        setupNavigationBar()
-        setupScrollView()
-        setupBindings()
-
-        viewModel.loadCachedSettings()
-    }
-
-    private func setupNavigationBar() {
-        navigationItem.backButtonTitle = ""
-
-        let titleLabel = UILabel()
-        titleLabel.text = Localized.Settings.title
-        titleLabel.textColor = Asset.neutralActive.color
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 18.0)
-
-        let menuButton = UIButton()
-        menuButton.tintColor = Asset.neutralDark.color
-        menuButton.setImage(Asset.chatListMenu.image, for: .normal)
-        menuButton.addTarget(self, action: #selector(didTapMenu), for: .touchUpInside)
-        menuButton.snp.makeConstraints { $0.width.equalTo(50) }
-
-        navigationItem.leftBarButtonItem = UIBarButtonItem(
-            customView: UIStackView(arrangedSubviews: [menuButton, titleLabel])
-        )
-    }
-
-    private func setupScrollView() {
-        scrollViewController.view.backgroundColor = Asset.neutralWhite.color
-
-        addChild(scrollViewController)
-        view.addSubview(scrollViewController.view)
-
-        scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
-        scrollViewController.didMove(toParent: self)
-        scrollViewController.contentView = screenView
+  @Dependency var hud: HUD
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var coordinator: SettingsCoordinating
+
+  lazy private var scrollViewController = ScrollViewController()
+  lazy private var screenView = SettingsView {
+    switch $0 {
+    case .icognitoKeyboard:
+      self.presentInfo(
+        title: Localized.Settings.InfoDrawer.Icognito.title,
+        subtitle: Localized.Settings.InfoDrawer.Icognito.subtitle
+      )
+    case .biometrics:
+      self.presentInfo(
+        title: Localized.Settings.InfoDrawer.Biometrics.title,
+        subtitle: Localized.Settings.InfoDrawer.Biometrics.subtitle
+      )
+    case .notifications:
+      self.presentInfo(
+        title: Localized.Settings.InfoDrawer.Notifications.title,
+        subtitle: Localized.Settings.InfoDrawer.Notifications.subtitle,
+        urlString: "https://links.xx.network/denseids"
+      )
+
+    case .dummyTraffic:
+      self.presentInfo(
+        title: Localized.Settings.InfoDrawer.Traffic.title,
+        subtitle: Localized.Settings.InfoDrawer.Traffic.subtitle,
+        urlString: "https://links.xx.network/covertraffic"
+      )
     }
+  }
+
+  private let viewModel = SettingsViewModel()
+  private var cancellables = Set<AnyCancellable>()
+  private var drawerCancellables = Set<AnyCancellable>()
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    barStylist.styleSubject.send(.darkContent)
+    navigationController?.navigationBar
+      .customize(backgroundColor: Asset.neutralWhite.color)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+
+    setupNavigationBar()
+    setupScrollView()
+    setupBindings()
+
+    viewModel.loadCachedSettings()
+  }
+
+  private func setupNavigationBar() {
+    navigationItem.backButtonTitle = ""
+
+    let titleLabel = UILabel()
+    titleLabel.text = Localized.Settings.title
+    titleLabel.textColor = Asset.neutralActive.color
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 18.0)
+
+    let menuButton = UIButton()
+    menuButton.tintColor = Asset.neutralDark.color
+    menuButton.setImage(Asset.chatListMenu.image, for: .normal)
+    menuButton.addTarget(self, action: #selector(didTapMenu), for: .touchUpInside)
+    menuButton.snp.makeConstraints { $0.width.equalTo(50) }
+
+    navigationItem.leftBarButtonItem = UIBarButtonItem(
+      customView: UIStackView(arrangedSubviews: [menuButton, titleLabel])
+    )
+  }
+
+  private func setupScrollView() {
+    scrollViewController.view.backgroundColor = Asset.neutralWhite.color
+
+    addChild(scrollViewController)
+    view.addSubview(scrollViewController.view)
+
+    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.didMove(toParent: self)
+    scrollViewController.contentView = screenView
+  }
+
+  private func setupBindings() {
+    viewModel.hud
+      .receive(on: DispatchQueue.main)
+      .sink { [hud] in hud.update(with: $0) }
+      .store(in: &cancellables)
+
+    screenView.inAppNotifications.switcherView
+      .publisher(for: .valueChanged)
+      .sink { [weak viewModel] in viewModel?.didToggleInAppNotifications() }
+      .store(in: &cancellables)
+
+    screenView.dummyTraffic.switcherView
+      .publisher(for: .valueChanged)
+      .sink { [weak viewModel] in viewModel?.didToggleDummyTraffic() }
+      .store(in: &cancellables)
+
+    screenView.remoteNotifications.switcherView
+      .publisher(for: .valueChanged)
+      .sink { [weak viewModel] in viewModel?.didTogglePushNotifications() }
+      .store(in: &cancellables)
+
+    screenView.hideActiveApp.switcherView
+      .publisher(for: .valueChanged)
+      .sink { [weak viewModel] in viewModel?.didToggleHideActiveApps() }
+      .store(in: &cancellables)
+
+    screenView.icognitoKeyboard.switcherView
+      .publisher(for: .valueChanged)
+      .sink { [weak viewModel] in viewModel?.didToggleIcognitoKeyboard() }
+      .store(in: &cancellables)
+
+    screenView.biometrics.switcherView
+      .publisher(for: .valueChanged)
+      .sink { [weak viewModel] in viewModel?.didToggleBiometrics() }
+      .store(in: &cancellables)
+
+    screenView.privacyPolicyButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        presentDrawer(
+          title: Localized.Settings.Drawer.title(Localized.Settings.privacyPolicy),
+          subtitle: Localized.Settings.Drawer.subtitle(Localized.Settings.privacyPolicy),
+          actionTitle: Localized.ChatList.Dashboard.open) {
+            guard let url = URL(string: "https://elixxir.io/privategrity-corporation-privacy-policy/") else { return }
+            UIApplication.shared.open(url, options: [:])
+          }
+      }.store(in: &cancellables)
+
+    screenView.disclosuresButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        presentDrawer(
+          title: Localized.Settings.Drawer.title(Localized.Settings.disclosures),
+          subtitle: Localized.Settings.Drawer.subtitle(Localized.Settings.disclosures),
+          actionTitle: Localized.ChatList.Dashboard.open) {
+            guard let url = URL(string: "https://elixxir.io/privategrity-corporation-terms-of-use/") else { return }
+            UIApplication.shared.open(url, options: [:])
+          }
+      }.store(in: &cancellables)
+
+    screenView.deleteButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toDelete(from: self) }
+      .store(in: &cancellables)
+
+    screenView.accountBackupButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toBackup(from: self) }
+      .store(in: &cancellables)
+
+    screenView.advancedButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in coordinator.toAdvanced(from: self) }
+      .store(in: &cancellables)
+
+    viewModel.state
+      .map(\.isBiometricsPossible)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [weak screenView] in screenView?.biometrics.switcherView.isEnabled = $0 }
+      .store(in: &cancellables)
+
+    viewModel.state
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] state in
+        screenView.biometrics.switcherView.setOn(state.isBiometricsEnabled, animated: true)
+        screenView.hideActiveApp.switcherView.setOn(state.isHideActiveApps, animated: true)
+        screenView.icognitoKeyboard.switcherView.setOn(state.isIcognitoKeyboard, animated: true)
+        screenView.inAppNotifications.switcherView.setOn(state.isInAppNotification, animated: true)
+        screenView.remoteNotifications.switcherView.setOn(state.isPushNotification, animated: true)
+        screenView.dummyTraffic.switcherView.setOn(state.isDummyTrafficOn, animated: true)
+      }.store(in: &cancellables)
+  }
+
+  private func presentDrawer(
+    title: String,
+    subtitle: String,
+    actionTitle: String,
+    action: @escaping () -> Void
+  ) {
+    let actionButton = CapsuleButton()
+    actionButton.setStyle(.red)
+    actionButton.setTitle(actionTitle, for: .normal)
+
+    let cancelButton = CapsuleButton()
+    cancelButton.setStyle(.seeThrough)
+    cancelButton.setTitle(Localized.ChatList.Dashboard.cancel, for: .normal)
+
+    let drawer = DrawerController(with: [
+      DrawerImage(
+        image: Asset.drawerNegative.image
+      ),
+      DrawerText(
+        font: Fonts.Mulish.semiBold.font(size: 18.0),
+        text: title,
+        color: Asset.neutralActive.color
+      ),
+      DrawerText(
+        font: Fonts.Mulish.semiBold.font(size: 14.0),
+        text: subtitle,
+        color: Asset.neutralWeak.color,
+        lineHeightMultiple: 1.35,
+        spacingAfter: 25
+      ),
+      DrawerStack(
+        spacing: 20.0,
+        views: [actionButton, cancelButton]
+      )
+    ])
+
+    actionButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+
+          action()
+        }
+      }.store(in: &drawerCancellables)
 
-    private func setupBindings() {
-        viewModel.hud
-            .receive(on: DispatchQueue.main)
-            .sink { [hud] in hud.update(with: $0) }
-            .store(in: &cancellables)
-
-        screenView.inAppNotifications.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [weak viewModel] in viewModel?.didToggleInAppNotifications() }
-            .store(in: &cancellables)
-
-        screenView.dummyTraffic.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [weak viewModel] in viewModel?.didToggleDummyTraffic() }
-            .store(in: &cancellables)
-
-        screenView.remoteNotifications.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [weak viewModel] in viewModel?.didTogglePushNotifications() }
-            .store(in: &cancellables)
-
-        screenView.hideActiveApp.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [weak viewModel] in viewModel?.didToggleHideActiveApps() }
-            .store(in: &cancellables)
-
-        screenView.icognitoKeyboard.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [weak viewModel] in viewModel?.didToggleIcognitoKeyboard() }
-            .store(in: &cancellables)
-
-        screenView.biometrics.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [weak viewModel] in viewModel?.didToggleBiometrics() }
-            .store(in: &cancellables)
-
-        screenView.privacyPolicyButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                presentDrawer(
-                    title: Localized.Settings.Drawer.title(Localized.Settings.privacyPolicy),
-                    subtitle: Localized.Settings.Drawer.subtitle(Localized.Settings.privacyPolicy),
-                    actionTitle: Localized.ChatList.Dashboard.open) {
-                        guard let url = URL(string: "https://elixxir.io/privategrity-corporation-privacy-policy/") else { return }
-                        UIApplication.shared.open(url, options: [:])
-                    }
-            }.store(in: &cancellables)
-
-        screenView.disclosuresButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                presentDrawer(
-                    title: Localized.Settings.Drawer.title(Localized.Settings.disclosures),
-                    subtitle: Localized.Settings.Drawer.subtitle(Localized.Settings.disclosures),
-                    actionTitle: Localized.ChatList.Dashboard.open) {
-                        guard let url = URL(string: "https://elixxir.io/privategrity-corporation-terms-of-use/") else { return }
-                        UIApplication.shared.open(url, options: [:])
-                    }
-            }.store(in: &cancellables)
-
-        screenView.deleteButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toDelete(from: self) }
-            .store(in: &cancellables)
-
-        screenView.accountBackupButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toBackup(from: self) }
-            .store(in: &cancellables)
-
-        screenView.advancedButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toAdvanced(from: self) }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .map(\.isBiometricsPossible)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [weak screenView] in screenView?.biometrics.switcherView.isEnabled = $0 }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] state in
-                screenView.biometrics.switcherView.setOn(state.isBiometricsEnabled, animated: true)
-                screenView.hideActiveApp.switcherView.setOn(state.isHideActiveApps, animated: true)
-                screenView.icognitoKeyboard.switcherView.setOn(state.isIcognitoKeyboard, animated: true)
-                screenView.inAppNotifications.switcherView.setOn(state.isInAppNotification, animated: true)
-                screenView.remoteNotifications.switcherView.setOn(state.isPushNotification, animated: true)
-                screenView.dummyTraffic.switcherView.setOn(state.isDummyTrafficOn, animated: true)
-            }.store(in: &cancellables)
-    }
+    cancelButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          self?.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-    private func presentDrawer(
-        title: String,
-        subtitle: String,
-        actionTitle: String,
-        action: @escaping () -> Void
-    ) {
-        let actionButton = CapsuleButton()
-        actionButton.setStyle(.red)
-        actionButton.setTitle(actionTitle, for: .normal)
-
-        let cancelButton = CapsuleButton()
-        cancelButton.setStyle(.seeThrough)
-        cancelButton.setTitle(Localized.ChatList.Dashboard.cancel, for: .normal)
-
-        let drawer = DrawerController(with: [
-            DrawerImage(
-                image: Asset.drawerNegative.image
-            ),
-            DrawerText(
-                font: Fonts.Mulish.semiBold.font(size: 18.0),
-                text: title,
-                color: Asset.neutralActive.color
-            ),
-            DrawerText(
-                font: Fonts.Mulish.semiBold.font(size: 14.0),
-                text: subtitle,
-                color: Asset.neutralWeak.color,
-                lineHeightMultiple: 1.35,
-                spacingAfter: 25
-            ),
-            DrawerStack(
-                spacing: 20.0,
-                views: [actionButton, cancelButton]
-            )
-        ])
-
-        actionButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-
-                    action()
-                }
-            }.store(in: &drawerCancellables)
-
-        cancelButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    self?.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+    coordinator.toDrawer(drawer, from: self)
+  }
 
-    @objc private func didTapMenu() {
-        coordinator.toSideMenu(from: self)
-    }
+  @objc private func didTapMenu() {
+    coordinator.toSideMenu(from: self)
+  }
 }
 
 extension SettingsController {
-    private func presentInfo(
-        title: String,
-        subtitle: String,
-        urlString: String = ""
-    ) {
-        let actionButton = CapsuleButton()
-        actionButton.set(
-            style: .seeThrough,
-            title: Localized.Settings.InfoDrawer.action
-        )
-
-        let drawer = DrawerController(with: [
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerLinkText(
-                text: subtitle,
-                urlString: urlString,
-                spacingAfter: 37
-            ),
-            DrawerStack(views: [
-                actionButton,
-                FlexibleSpace()
-            ])
-        ])
-
-        actionButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    guard let self = self else { return }
-                    self.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+  private func presentInfo(
+    title: String,
+    subtitle: String,
+    urlString: String = ""
+  ) {
+    let actionButton = CapsuleButton()
+    actionButton.set(
+      style: .seeThrough,
+      title: Localized.Settings.InfoDrawer.action
+    )
+
+    let drawer = DrawerController(with: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerLinkText(
+        text: subtitle,
+        urlString: urlString,
+        spacingAfter: 37
+      ),
+      DrawerStack(views: [
+        actionButton,
+        FlexibleSpace()
+      ])
+    ])
+
+    actionButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink {
+        drawer.dismiss(animated: true) { [weak self] in
+          guard let self = self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    coordinator.toDrawer(drawer, from: self)
+  }
 }
diff --git a/Sources/Shared/Controllers/RootViewController.swift b/Sources/Shared/Controllers/RootViewController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..3e1fcac17b6a17905d8450bf5a5d264326e9a990
--- /dev/null
+++ b/Sources/Shared/Controllers/RootViewController.swift
@@ -0,0 +1,146 @@
+import UIKit
+import Combine
+import DependencyInjection
+
+public final class RootViewController: UIViewController {
+  @Dependency var barStylist: StatusBarStylist
+  @Dependency var toastDispatcher: ToastController
+
+  var toastTimer: Timer?
+  let content: UIViewController?
+  let toastTopPadding: CGFloat = 10
+  var cancellables = Set<AnyCancellable>()
+  var topToastConstraint: NSLayoutConstraint?
+
+  public init(_ content: UIViewController?) {
+    self.content = content
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override var preferredStatusBarStyle: UIStatusBarStyle  {
+    barStylist.styleSubject.value
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+
+    if let content {
+      addChild(content)
+      view.addSubview(content.view)
+      content.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+      content.view.frame = view.bounds
+      content.didMove(toParent: self)
+    } else {
+      view.isUserInteractionEnabled = false
+    }
+
+    barStylist
+      .styleSubject
+      .receive(on: DispatchQueue.main)
+      .sink { [weak self] _ in
+        UIView.animate(withDuration: 0.2) {
+          self?.setNeedsStatusBarAppearanceUpdate()
+        }
+      }.store(in: &cancellables)
+
+    toastDispatcher.currentToast
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] model in
+        let toastView = ToastView(model: model)
+        add(toastView: toastView)
+        present(toastView: toastView)
+      }.store(in: &cancellables)
+  }
+
+  @objc private func didPanToast(_ sender: UIPanGestureRecognizer) {
+    guard let toastView = sender.view else { return }
+
+    switch sender.state {
+    case .began, .changed:
+      toastTimer?.invalidate()
+      let padding = toastTopPadding + min(0, sender.translation(in: view).y)
+      topToastConstraint?.constant = padding
+
+    case .cancelled, .ended, .failed:
+      let halfFrameHeight = -0.5 * toastView.frame.height
+      let verticalTranslation = sender.translation(in: toastView).y
+      let didSwipeAboveHalf = verticalTranslation < halfFrameHeight
+
+      if didSwipeAboveHalf {
+        dismiss(toastView: toastView)
+      } else {
+        present(toastView: toastView)
+      }
+
+    case .possible:
+      break
+    @unknown default:
+      break
+    }
+  }
+
+  private func dismiss(toastView: UIView) {
+    toastView.isUserInteractionEnabled = false
+    topToastConstraint?.constant = -(toastView.frame.height + view.safeAreaLayoutGuide.layoutFrame.minY)
+
+    topToastConstraint = nil
+    UIView.animate(withDuration: 0.25) {
+      self.view.setNeedsLayout()
+      self.view.layoutIfNeeded()
+    } completion: { _ in
+      toastView.isUserInteractionEnabled = true
+      toastView.removeFromSuperview()
+      self.toastDispatcher.dismissCurrentToast()
+    }
+  }
+
+  private func add(toastView: UIView) {
+    let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(didPanToast(_:)))
+    toastView.addGestureRecognizer(gestureRecognizer)
+
+    toastView.translatesAutoresizingMaskIntoConstraints = false
+    view.addSubview(toastView)
+
+    NSLayoutConstraint.activate([
+      toastView.heightAnchor.constraint(equalToConstant: 78),
+      toastView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 20),
+      toastView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor, constant: -20)
+    ])
+
+    topToastConstraint = toastView.topAnchor.constraint(
+      equalTo: view.safeAreaLayoutGuide.topAnchor,
+      constant: -(toastView.frame.height + view.safeAreaLayoutGuide.layoutFrame.height)
+    )
+
+    topToastConstraint?.isActive = true
+
+    view.setNeedsLayout()
+    view.layoutIfNeeded()
+  }
+
+  private func present(toastView: UIView) {
+    toastView.isUserInteractionEnabled = false
+    topToastConstraint?.constant = toastTopPadding
+
+    UIView.animate(
+      withDuration: 0.5,
+      delay: 0,
+      usingSpringWithDamping: 1,
+      initialSpringVelocity: 0.5,
+      options: .curveEaseInOut
+    ) {
+      self.view.setNeedsLayout()
+      self.view.layoutIfNeeded()
+    } completion: { _ in
+      toastView.isUserInteractionEnabled = true
+
+      self.toastTimer?.invalidate()
+      self.toastTimer = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { [weak self] _ in
+        guard let self = self else { return }
+        self.dismiss(toastView: toastView)
+      }
+    }
+  }
+}
diff --git a/Sources/Shared/Controllers/StatusBarStyling.swift b/Sources/Shared/Controllers/StatusBarStyling.swift
new file mode 100644
index 0000000000000000000000000000000000000000..07941553057aa151e0f9e7b5dd5eee84ed580eed
--- /dev/null
+++ b/Sources/Shared/Controllers/StatusBarStyling.swift
@@ -0,0 +1,7 @@
+import UIKit
+import Combine
+
+public struct StatusBarStylist {
+  public init() {}
+  public let styleSubject = CurrentValueSubject<UIStatusBarStyle, Never>(.lightContent)
+}
diff --git a/Sources/ToastFeature/ToastController.swift b/Sources/Shared/Controllers/ToastController.swift
similarity index 100%
rename from Sources/ToastFeature/ToastController.swift
rename to Sources/Shared/Controllers/ToastController.swift
diff --git a/Sources/ToastFeature/ToastModel.swift b/Sources/Shared/Controllers/ToastModel.swift
similarity index 98%
rename from Sources/ToastFeature/ToastModel.swift
rename to Sources/Shared/Controllers/ToastModel.swift
index 06dd2a03fde9743309246e6438cdb9ca37383efc..001539d4dc907791e154a6c66ff8bf1b56e0c8c2 100644
--- a/Sources/ToastFeature/ToastModel.swift
+++ b/Sources/Shared/Controllers/ToastModel.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Shared
 
 public struct ToastModel {
     let id: UUID
diff --git a/Sources/Shared/Views/ToastView.swift b/Sources/Shared/Views/ToastView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..bf1254429a07344f7ba7c20b9dee19e13ebeff03
--- /dev/null
+++ b/Sources/Shared/Views/ToastView.swift
@@ -0,0 +1,77 @@
+import UIKit
+import Combine
+
+final class ToastView: UIView {
+  let titleLabel = UILabel()
+  let subtitleLabel = UILabel()
+  let leftImageView = UIImageView()
+  let rightButton = UIButton()
+  let verticalStackView = UIStackView()
+  let horizontalStackView = UIStackView()
+  var cancellables = Set<AnyCancellable>()
+
+  init(model: ToastModel) {
+    super.init(frame: .zero)
+    backgroundColor = model.color
+    layer.cornerRadius = 18.0
+
+    titleLabel.textColor = .white
+    subtitleLabel.textColor = .white
+    leftImageView.contentMode = .center
+
+    titleLabel.numberOfLines = 0
+    subtitleLabel.numberOfLines = 0
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
+    subtitleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
+
+    leftImageView.image = Asset.sharedSuccess.image
+    leftImageView.setContentHuggingPriority(.required, for: .horizontal)
+
+    rightButton.titleLabel?.numberOfLines = 0
+    rightButton.titleLabel?.textAlignment = .center
+    rightButton.titleLabel?.font = Fonts.Mulish.bold.font(size: 12.0)
+
+    verticalStackView.axis = .vertical
+    verticalStackView.distribution = .fill
+    verticalStackView.addArrangedSubview(titleLabel)
+    verticalStackView.addArrangedSubview(subtitleLabel)
+
+    horizontalStackView.spacing = 12
+    horizontalStackView.addArrangedSubview(leftImageView)
+    horizontalStackView.addArrangedSubview(verticalStackView)
+    horizontalStackView.addArrangedSubview(rightButton)
+
+    addSubview(horizontalStackView)
+
+    horizontalStackView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(17)
+      $0.left.equalToSuperview().offset(20)
+      $0.right.equalToSuperview().offset(-20)
+      $0.bottom.equalToSuperview().offset(-17)
+    }
+
+    titleLabel.text = model.title
+    leftImageView.image = model.leftImage
+
+    if let subtitle = model.subtitle {
+      subtitleLabel.text = subtitle
+      subtitleLabel.numberOfLines = 0
+    } else {
+      subtitleLabel.isHidden = true
+    }
+
+    if let buttonTitle = model.buttonTitle {
+      rightButton.setTitle(buttonTitle, for: .normal)
+      rightButton.setContentHuggingPriority(.required, for: .horizontal)
+    } else {
+      rightButton.isHidden = true
+    }
+
+    rightButton
+      .publisher(for: .touchUpInside)
+      .sink { model.onTapClosure?() }
+      .store(in: &cancellables)
+  }
+
+  required init?(coder: NSCoder) { nil }
+}
diff --git a/Sources/TermsFeature/TermsConditionsController.swift b/Sources/TermsFeature/TermsConditionsController.swift
index d458ffe114d7bf80c9d2ba4b3ffe347c2e8ada48..08a6081f497f40ba68303c86fba00f8cedd4a705 100644
--- a/Sources/TermsFeature/TermsConditionsController.swift
+++ b/Sources/TermsFeature/TermsConditionsController.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Theme
 import WebKit
 import Shared
 import Combine
@@ -7,80 +6,79 @@ import Defaults
 import DependencyInjection
 
 public final class TermsConditionsController: UIViewController {
-    @Dependency var coordinator: TermsCoordinator
-    @Dependency var statusBarController: StatusBarStyleControlling
+  @Dependency var coordinator: TermsCoordinator
 
-    @KeyObject(.username, defaultValue: nil) var username: String?
-    @KeyObject(.acceptedTerms, defaultValue: false) var didAcceptTerms: Bool
+  @KeyObject(.username, defaultValue: nil) var username: String?
+  @KeyObject(.acceptedTerms, defaultValue: false) var didAcceptTerms: Bool
 
-    lazy private var screenView = TermsConditionsView()
+  lazy private var screenView = TermsConditionsView()
 
-    private var cancellables = Set<AnyCancellable>()
+  private var cancellables = Set<AnyCancellable>()
 
-    public override func loadView() {
-        view = screenView
-    }
+  public override func loadView() {
+    view = screenView
+  }
 
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        navigationController?.navigationBar.customize(
-            translucent: true,
-            tint: Asset.neutralWhite.color
-        )
-    }
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    navigationController?.navigationBar.customize(
+      translucent: true,
+      tint: Asset.neutralWhite.color
+    )
+  }
 
-    public override func viewDidLayoutSubviews() {
-        super.viewDidLayoutSubviews()
+  public override func viewDidLayoutSubviews() {
+    super.viewDidLayoutSubviews()
 
-        let gradient = CAGradientLayer()
-        gradient.colors = [
-            UIColor(red: 122/255, green: 235/255, blue: 239/255, alpha: 1).cgColor,
-            UIColor(red: 56/255, green: 204/255, blue: 232/255, alpha: 1).cgColor,
-            UIColor(red: 63/255, green: 186/255, blue: 253/255, alpha: 1).cgColor,
-            UIColor(red: 98/255, green: 163/255, blue: 255/255, alpha: 1).cgColor
-        ]
+    let gradient = CAGradientLayer()
+    gradient.colors = [
+      UIColor(red: 122/255, green: 235/255, blue: 239/255, alpha: 1).cgColor,
+      UIColor(red: 56/255, green: 204/255, blue: 232/255, alpha: 1).cgColor,
+      UIColor(red: 63/255, green: 186/255, blue: 253/255, alpha: 1).cgColor,
+      UIColor(red: 98/255, green: 163/255, blue: 255/255, alpha: 1).cgColor
+    ]
 
-        gradient.startPoint = CGPoint(x: 0, y: 0)
-        gradient.endPoint = CGPoint(x: 1, y: 1)
+    gradient.startPoint = CGPoint(x: 0, y: 0)
+    gradient.endPoint = CGPoint(x: 1, y: 1)
 
-        gradient.frame = screenView.bounds
-        screenView.layer.insertSublayer(gradient, at: 0)
-    }
+    gradient.frame = screenView.bounds
+    screenView.layer.insertSublayer(gradient, at: 0)
+  }
 
-    public override func viewDidLoad() {
-        super.viewDidLoad()
+  public override func viewDidLoad() {
+    super.viewDidLoad()
 
-        screenView.radioComponent
-            .radioButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in
-                screenView.radioComponent.isEnabled.toggle()
-                screenView.nextButton.isEnabled = screenView.radioComponent.isEnabled
-                UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
-            }.store(in: &cancellables)
+    screenView.radioComponent
+      .radioButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        screenView.radioComponent.isEnabled.toggle()
+        screenView.nextButton.isEnabled = screenView.radioComponent.isEnabled
+        UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
+      }.store(in: &cancellables)
 
-        screenView.nextButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in
-                didAcceptTerms = true
+    screenView.nextButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        didAcceptTerms = true
 
-                if let _ = username {
-                    coordinator.presentChatList(self)
-                } else {
-                    coordinator.presentUsername(self)
-                }
-            }.store(in: &cancellables)
+        if let _ = username {
+          coordinator.presentChatList(self)
+        } else {
+          coordinator.presentUsername(self)
+        }
+      }.store(in: &cancellables)
 
-        screenView.showTermsButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] _ in
-                let webView = WKWebView()
-                let webController = UIViewController()
-                webController.view.addSubview(webView)
-                webView.snp.makeConstraints { $0.edges.equalToSuperview() }
-                webView.load(URLRequest(url: URL(string: "https://elixxir.io/eula")!))
-                present(webController, animated: true)
-            }.store(in: &cancellables)
-    }
+    screenView.showTermsButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] _ in
+        let webView = WKWebView()
+        let webController = UIViewController()
+        webController.view.addSubview(webView)
+        webView.snp.makeConstraints { $0.edges.equalToSuperview() }
+        webView.load(URLRequest(url: URL(string: "https://elixxir.io/eula")!))
+        present(webController, animated: true)
+      }.store(in: &cancellables)
+  }
 }
diff --git a/Sources/Theme/StatusBarViewController.swift b/Sources/Theme/StatusBarViewController.swift
deleted file mode 100644
index d5dd7b000aa81a0180a517e69dc347016fa7a74c..0000000000000000000000000000000000000000
--- a/Sources/Theme/StatusBarViewController.swift
+++ /dev/null
@@ -1,59 +0,0 @@
-import UIKit
-import Combine
-import DependencyInjection
-
-public protocol StatusBarStyleControlling {
-    var style: CurrentValueSubject<UIStatusBarStyle, Never> { get }
-}
-
-public struct StatusBarController: StatusBarStyleControlling {
-    public init() {}
-
-    public let style = CurrentValueSubject<UIStatusBarStyle, Never>(.lightContent)
-}
-
-public final class StatusBarViewController: UIViewController {
-    private let content: UIViewController?
-    private var cancellables = Set<AnyCancellable>()
-
-    @Dependency private var statusBarController: StatusBarStyleControlling
-
-    public init(_ content: UIViewController?) {
-        self.content = content
-        super.init(nibName: nil, bundle: nil)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override var preferredStatusBarStyle: UIStatusBarStyle  {
-        statusBarController.style.value
-    }
-
-    public override func loadView() {
-        let view = UIView()
-        view.backgroundColor = .clear
-        self.view = view
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-
-        if let content = content {
-            addChild(content)
-            view.addSubview(content.view)
-            content.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
-            content.view.frame = view.bounds
-            content.didMove(toParent: self)
-        } else {
-            view.isUserInteractionEnabled = false
-        }
-
-        statusBarController.style
-            .receive(on: DispatchQueue.main)
-            .sink { [weak self] style in
-                UIView.animate(withDuration: 0.2) {
-                    self?.setNeedsStatusBarAppearanceUpdate()
-                }
-            }.store(in: &cancellables)
-    }
-}
diff --git a/Sources/Theme/ThemeController.swift b/Sources/Theme/ThemeController.swift
deleted file mode 100644
index 255f1063f39a94670b4a9e4e7bbbe81e54956a73..0000000000000000000000000000000000000000
--- a/Sources/Theme/ThemeController.swift
+++ /dev/null
@@ -1,41 +0,0 @@
-import UIKit
-import Combine
-import Defaults
-
-public enum Theme: Int {
-    case system = 0
-    case dark
-
-    public var userInterfaceStyle: UIUserInterfaceStyle {
-        switch self {
-        case .system:
-            return .unspecified
-        case .dark:
-            return .dark
-        }
-    }
-}
-
-public protocol ThemeControlling {
-    var theme: CurrentValueSubject<Theme, Never> { get }
-}
-
-public final class ThemeController: ThemeControlling {
-    // MARK: Stored
-
-    @KeyObject(.theme, defaultValue: 0) var storedTheme: Int
-
-    // MARK: Properties
-
-    private var cancellables = Set<AnyCancellable>()
-    public let theme = CurrentValueSubject<Theme, Never>(.system)
-
-    // MARK: Lifecycle
-
-    public init() {
-        theme.send(Theme(rawValue: storedTheme) ?? .system)
-
-        theme.sink { [unowned self] in storedTheme = $0.rawValue }
-            .store(in: &cancellables)
-    }
-}
diff --git a/Sources/Theme/Window.swift b/Sources/Theme/Window.swift
deleted file mode 100644
index 8afb304005d85a8657b2f6bb2b1b5dba7a039546..0000000000000000000000000000000000000000
--- a/Sources/Theme/Window.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-import UIKit
-import Combine
-import DependencyInjection
-
-public final class Window: UIWindow {
-    @Dependency private var themeController: ThemeControlling
-
-    private var cancellables = Set<AnyCancellable>()
-
-    public init() {
-        super.init(frame: UIScreen.main.bounds)
-
-        themeController.theme
-            .sink { [unowned self] in overrideUserInterfaceStyle = $0.userInterfaceStyle }
-            .store(in: &cancellables)
-    }
-
-    required init?(coder: NSCoder) { nil }
-}
diff --git a/Sources/ToastFeature/ToastView.swift b/Sources/ToastFeature/ToastView.swift
deleted file mode 100644
index c5c96561df06b942bd640a30cdf308bed014a80f..0000000000000000000000000000000000000000
--- a/Sources/ToastFeature/ToastView.swift
+++ /dev/null
@@ -1,78 +0,0 @@
-import UIKit
-import Shared
-import Combine
-
-final class ToastView: UIView {
-    private let titleLabel = UILabel()
-    private let subtitleLabel = UILabel()
-    private let leftImageView = UIImageView()
-    private let rightButton = UIButton()
-    private let verticalStackView = UIStackView()
-    private let horizontalStackView = UIStackView()
-    private var cancellables = Set<AnyCancellable>()
-
-    init(model: ToastModel) {
-        super.init(frame: .zero)
-        backgroundColor = model.color
-        layer.cornerRadius = 18.0
-
-        titleLabel.textColor = .white
-        subtitleLabel.textColor = .white
-        leftImageView.contentMode = .center
-
-        titleLabel.numberOfLines = 0
-        subtitleLabel.numberOfLines = 0
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
-        subtitleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
-
-        leftImageView.image = Asset.sharedSuccess.image
-        leftImageView.setContentHuggingPriority(.required, for: .horizontal)
-
-        rightButton.titleLabel?.numberOfLines = 0
-        rightButton.titleLabel?.textAlignment = .center
-        rightButton.titleLabel?.font = Fonts.Mulish.bold.font(size: 12.0)
-
-        verticalStackView.axis = .vertical
-        verticalStackView.distribution = .fill
-        verticalStackView.addArrangedSubview(titleLabel)
-        verticalStackView.addArrangedSubview(subtitleLabel)
-
-        horizontalStackView.spacing = 12
-        horizontalStackView.addArrangedSubview(leftImageView)
-        horizontalStackView.addArrangedSubview(verticalStackView)
-        horizontalStackView.addArrangedSubview(rightButton)
-
-        addSubview(horizontalStackView)
-
-        horizontalStackView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(17)
-            $0.left.equalToSuperview().offset(20)
-            $0.right.equalToSuperview().offset(-20)
-            $0.bottom.equalToSuperview().offset(-17)
-        }
-
-        titleLabel.text = model.title
-        leftImageView.image = model.leftImage
-
-        if let subtitle = model.subtitle {
-            subtitleLabel.text = subtitle
-            subtitleLabel.numberOfLines = 0
-        } else {
-            subtitleLabel.isHidden = true
-        }
-
-        if let buttonTitle = model.buttonTitle {
-            rightButton.setTitle(buttonTitle, for: .normal)
-            rightButton.setContentHuggingPriority(.required, for: .horizontal)
-        } else {
-            rightButton.isHidden = true
-        }
-
-        rightButton
-            .publisher(for: .touchUpInside)
-            .sink { model.onTapClosure?() }
-            .store(in: &cancellables)
-    }
-
-    required init?(coder: NSCoder) { nil }
-}
diff --git a/Sources/ToastFeature/ToastViewController.swift b/Sources/ToastFeature/ToastViewController.swift
deleted file mode 100644
index 35c68a531da1d7197d3ed709472c07b452d463c6..0000000000000000000000000000000000000000
--- a/Sources/ToastFeature/ToastViewController.swift
+++ /dev/null
@@ -1,134 +0,0 @@
-import UIKit
-import Combine
-import DependencyInjection
-
-public final class ToastViewController: UIViewController {
-    @Dependency private var controller: ToastController
-
-    private var timer: Timer?
-    private let content: UIViewController
-    private let toastTopPadding: CGFloat = 10
-    private var cancellables = Set<AnyCancellable>()
-    private var topToastConstraint: NSLayoutConstraint?
-
-    public init(_ content: UIViewController) {
-        self.content = content
-        super.init(nibName: nil, bundle: nil)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func loadView() {
-        let view = UIView()
-        view.backgroundColor = .clear
-        self.view = view
-    }
-
-    override public func viewDidLoad() {
-        super.viewDidLoad()
-
-        addChild(content)
-        view.addSubview(content.view)
-        content.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
-        content.view.frame = view.bounds
-        content.didMove(toParent: self)
-
-        controller.currentToast
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] model in
-                let toastView = ToastView(model: model)
-                add(toastView: toastView)
-                present(toastView: toastView)
-            }.store(in: &cancellables)
-    }
-
-    @objc private func didPanToast(_ sender: UIPanGestureRecognizer) {
-        guard let toastView = sender.view else { return }
-
-        switch sender.state {
-        case .began, .changed:
-            timer?.invalidate()
-            let padding = toastTopPadding + min(0, sender.translation(in: view).y)
-            topToastConstraint?.constant = padding
-
-        case .cancelled, .ended, .failed:
-            let halfFrameHeight = -0.5 * toastView.frame.height
-            let verticalTranslation = sender.translation(in: toastView).y
-            let didSwipeAboveHalf = verticalTranslation < halfFrameHeight
-
-            if didSwipeAboveHalf {
-                dismiss(toastView: toastView)
-            } else {
-                present(toastView: toastView)
-            }
-
-        case .possible:
-            break
-        @unknown default:
-            break
-        }
-    }
-
-    private func dismiss(toastView: UIView) {
-        toastView.isUserInteractionEnabled = false
-        topToastConstraint?.constant = -(toastView.frame.height + view.safeAreaLayoutGuide.layoutFrame.minY)
-
-        topToastConstraint = nil
-        UIView.animate(withDuration: 0.25) {
-            self.view.setNeedsLayout()
-            self.view.layoutIfNeeded()
-        } completion: { _ in
-            toastView.isUserInteractionEnabled = true
-            toastView.removeFromSuperview()
-            self.controller.dismissCurrentToast()
-        }
-    }
-
-    private func add(toastView: UIView) {
-        let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(didPanToast(_:)))
-        toastView.addGestureRecognizer(gestureRecognizer)
-
-        toastView.translatesAutoresizingMaskIntoConstraints = false
-        view.addSubview(toastView)
-
-        NSLayoutConstraint.activate([
-            toastView.heightAnchor.constraint(equalToConstant: 78),
-            toastView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 20),
-            toastView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor, constant: -20)
-        ])
-
-        topToastConstraint = toastView.topAnchor.constraint(
-            equalTo: view.safeAreaLayoutGuide.topAnchor,
-            constant: -(toastView.frame.height + view.safeAreaLayoutGuide.layoutFrame.height)
-        )
-
-        topToastConstraint?.isActive = true
-
-        view.setNeedsLayout()
-        view.layoutIfNeeded()
-    }
-
-    private func present(toastView: UIView) {
-        toastView.isUserInteractionEnabled = false
-        topToastConstraint?.constant = toastTopPadding
-
-        UIView.animate(
-            withDuration: 0.5,
-            delay: 0,
-            usingSpringWithDamping: 1,
-            initialSpringVelocity: 0.5,
-            options: .curveEaseInOut
-        ) {
-            self.view.setNeedsLayout()
-            self.view.layoutIfNeeded()
-        } completion: { _ in
-            toastView.isUserInteractionEnabled = true
-
-            self.timer?.invalidate()
-            self.timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { [weak self] _ in
-                guard let self = self else { return }
-                self.dismiss(toastView: toastView)
-            }
-        }
-    }
-}
diff --git a/Tests/OnboardingFeatureTests/Coordinator/OnboardingCoordinatorSpec.swift b/Tests/OnboardingFeatureTests/Coordinator/OnboardingCoordinatorSpec.swift
index 2ffb72ee0e6560a6162eace8dcbd0fa788a87197..fdf5e58c4ca17d0ec192af873f89383b86d3d44d 100644
--- a/Tests/OnboardingFeatureTests/Coordinator/OnboardingCoordinatorSpec.swift
+++ b/Tests/OnboardingFeatureTests/Coordinator/OnboardingCoordinatorSpec.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Quick
-import Theme
 import Nimble
 import Combine
 import TestHelpers
diff --git a/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved b/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
index b1975fc1c84bad46fd59eaa07c5716d0682d0931..659e607ccb07a4ee550069a01dc5b919f4c25419 100644
--- a/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -275,6 +275,7 @@
       "kind" : "remoteSourceControl",
       "location" : "https://github.com/darrarski/Shout.git",
       "state" : {
+        "branch" : "master",
         "revision" : "df5a662293f0ac15eeb4f2fd3ffd0c07b73d0de0"
       }
     },