diff --git a/Package.swift b/Package.swift
index 531a2a484d66914bc8be79ec1849b335ea29dcee..5bf030c00f28088c6d70459394fe54d3528c22d4 100644
--- a/Package.swift
+++ b/Package.swift
@@ -137,6 +137,7 @@ let package = Package(
         .target(name: "ChatFeature"),
         .target(name: "MenuFeature"),
         .target(name: "PushFeature"),
+        .target(name: "XXNavigation"),
         .target(name: "TermsFeature"),
         .target(name: "CrashService"),
         .target(name: "BackupFeature"),
@@ -152,8 +153,6 @@ let package = Package(
         .target(name: "ReportingFeature"),
         .target(name: "OnboardingFeature"),
         .target(name: "ContactListFeature"),
-        .target(name: "XXNavigation"),
-        .product(name: "Navigation", package: "Navigation"),
       ]
     ),
     .testTarget(
@@ -193,12 +192,14 @@ let package = Package(
       name: "Permissions",
       dependencies: [
         .target(name: "Shared"),
+        .target(name: "XXNavigation"),
         .target(name: "DependencyInjection"),
       ]
     ),
     .target(
       name: "XXNavigation",
       dependencies: [
+        .target(name: "DrawerFeature"),
         .target(name: "DependencyInjection"),
         .product(name: "Navigation", package: "Navigation"),
         .product(name: "XXModels", package: "client-ios-db"),
@@ -244,10 +245,8 @@ let package = Package(
       name: "Countries",
       dependencies: [
         .target(name: "Shared"),
+        .target(name: "XXNavigation"),
         .target(name: "DependencyInjection"),
-      ],
-      resources: [
-        .process("Resources"),
       ]
     ),
     .target(
@@ -306,6 +305,7 @@ let package = Package(
       dependencies: [
         .target(name: "Shared"),
         .target(name: "Presentation"),
+        .target(name: "XXNavigation"),
         .target(name: "DependencyInjection"),
         .product(name: "XXDatabase", package: "client-ios-db"),
         .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
@@ -326,14 +326,6 @@ let package = Package(
         .product(name: "ScrollViewController", package: "ScrollViewController"),
       ]
     ),
-    .testTarget(
-      name: "ContactFeatureTests",
-      dependencies: [
-        .target(name: "ContactFeature"),
-        .product(name: "Quick", package: "Quick"),
-        .product(name: "Nimble", package: "Nimble"),
-      ]
-    ),
     .target(
       name: "ChatFeature",
       dependencies: [
@@ -343,23 +335,16 @@ let package = Package(
         .target(name: "Voxophone"),
         .target(name: "Permissions"),
         .target(name: "Presentation"),
+        .target(name: "XXNavigation"),
         .target(name: "DrawerFeature"),
         .target(name: "ChatInputFeature"),
         .target(name: "ReportingFeature"),
         .target(name: "DependencyInjection"),
         .product(name: "ChatLayout", package: "ChatLayout"),
         .product(name: "DifferenceKit", package: "DifferenceKit"),
-        .product(name: "ScrollViewController", package: "ScrollViewController"),
         .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
         .product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
-      ]
-    ),
-    .testTarget(
-      name: "ChatFeatureTests",
-      dependencies: [
-        .target(name: "ChatFeature"),
-        .product(name: "Quick", package: "Quick"),
-        .product(name: "Nimble", package: "Nimble"),
+        .product(name: "ScrollViewController", package: "ScrollViewController"),
       ]
     ),
     .target(
@@ -376,14 +361,6 @@ let package = Package(
         .product(name: "XXDatabase", package: "client-ios-db"),
       ]
     ),
-    .testTarget(
-      name: "SearchFeatureTests",
-      dependencies: [
-        .target(name: "SearchFeature"),
-        .product(name: "Quick", package: "Quick"),
-        .product(name: "Nimble", package: "Nimble"),
-      ]
-    ),
     .target(
       name: "LaunchFeature",
       dependencies: [
@@ -409,6 +386,7 @@ let package = Package(
         .target(name: "Shared"),
         .target(name: "Defaults"),
         .target(name: "Presentation"),
+        .target(name: "XXNavigation"),
       ]
     ),
     .target(
@@ -420,14 +398,6 @@ let package = Package(
         .product(name: "DifferenceKit", package: "DifferenceKit"),
       ]
     ),
-    .testTarget(
-      name: "RequestsFeatureTests",
-      dependencies: [
-        .target(name: "RequestsFeature"),
-        .product(name: "Quick", package: "Quick"),
-        .product(name: "Nimble", package: "Nimble"),
-      ]
-    ),
     .target(
       name: "ProfileFeature",
       dependencies: [
@@ -448,14 +418,6 @@ let package = Package(
         .product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
       ]
     ),
-    .testTarget(
-      name: "ProfileFeatureTests",
-      dependencies: [
-        .target(name: "ProfileFeature"),
-        .product(name: "Quick", package: "Quick"),
-        .product(name: "Nimble", package: "Nimble"),
-      ]
-    ),
     .target(
       name: "ChatListFeature",
       dependencies: [
@@ -463,6 +425,7 @@ let package = Package(
         .target(name: "Defaults"),
         .target(name: "MenuFeature"),
         .target(name: "ChatFeature"),
+        .target(name: "XXNavigation"),
         .target(name: "ProfileFeature"),
         .target(name: "SettingsFeature"),
         .target(name: "ContactListFeature"),
@@ -470,14 +433,6 @@ let package = Package(
         .product(name: "DifferenceKit", package: "DifferenceKit"),
       ]
     ),
-    .testTarget(
-      name: "ChatListFeatureTests",
-      dependencies: [
-        .target(name: "ChatListFeature"),
-        .product(name: "Quick", package: "Quick"),
-        .product(name: "Nimble", package: "Nimble"),
-      ]
-    ),
     .target(
       name: "OnboardingFeature",
       dependencies: [
@@ -496,20 +451,13 @@ let package = Package(
         .product(name: "ScrollViewController", package: "ScrollViewController"),
       ]
     ),
-    .testTarget(
-      name: "OnboardingFeatureTests",
-      dependencies: [
-        .target(name: "OnboardingFeature"),
-        .product(name: "Quick", package: "Quick"),
-        .product(name: "Nimble", package: "Nimble"),
-      ]
-    ),
     .target(
       name: "MenuFeature",
       dependencies: [
         .target(name: "Shared"),
         .target(name: "Defaults"),
         .target(name: "Presentation"),
+        .target(name: "XXNavigation"),
         .target(name: "DrawerFeature"),
         .target(name: "ReportingFeature"),
         .target(name: "DependencyInjection"),
@@ -546,14 +494,6 @@ let package = Package(
         .product(name: "SnapKit", package: "SnapKit"),
       ]
     ),
-    .testTarget(
-      name: "ScanFeatureTests",
-      dependencies: [
-        .target(name: "ScanFeature"),
-        .product(name: "Quick", package: "Quick"),
-        .product(name: "Nimble", package: "Nimble"),
-      ]
-    ),
     .target(
       name: "ContactListFeature",
       dependencies: [
@@ -564,14 +504,6 @@ let package = Package(
         .product(name: "DifferenceKit", package: "DifferenceKit"),
       ]
     ),
-    .testTarget(
-      name: "ContactListFeatureTests",
-      dependencies: [
-        .target(name: "ContactListFeature"),
-        .product(name: "Quick", package: "Quick"),
-        .product(name: "Nimble", package: "Nimble"),
-      ]
-    ),
     .target(
       name: "SettingsFeature",
       dependencies: [
@@ -590,14 +522,6 @@ let package = Package(
         .product(name: "ScrollViewController", package: "ScrollViewController"),
       ]
     ),
-    .testTarget(
-      name: "SettingsFeatureTests",
-      dependencies: [
-        .target(name: "SettingsFeature"),
-        .product(name: "Quick", package: "Quick"),
-        .product(name: "Nimble", package: "Nimble"),
-      ]
-    ),
     .target(
       name: "CollectionView",
       dependencies: [
diff --git a/Sources/App/AppDelegate.swift b/Sources/App/AppDelegate.swift
index a10b8e67138fc8563e7b20f43891d21ad241ce7a..25a3041a36827376d2fc3dc0a60e41bd82522b48 100644
--- a/Sources/App/AppDelegate.swift
+++ b/Sources/App/AppDelegate.swift
@@ -1,17 +1,17 @@
 import UIKit
-import Navigation
 import BackgroundTasks
 
 import Shared
-import XXModels
-import XXLogger
 import Defaults
 import PushFeature
 import LaunchFeature
 import CrashReporting
 import DependencyInjection
 
+import XXModels
+import XXLogger
 import XXClient
+import XXNavigation
 import XXMessengerClient
 
 import CloudFiles
diff --git a/Sources/App/DependencyRegistrator.swift b/Sources/App/DependencyRegistrator.swift
index 1217667eec9b64be80a4d8fd39e9c28b17c19651..795e5d7d5b106e3f2de2061d9b4a241c046ad253 100644
--- a/Sources/App/DependencyRegistrator.swift
+++ b/Sources/App/DependencyRegistrator.swift
@@ -43,7 +43,6 @@ import ContactListFeature
 
 import Shared
 import XXClient
-import Navigation
 import XXNavigation
 import KeychainAccess
 import XXMessengerClient
@@ -112,6 +111,7 @@ struct DependencyRegistrator {
       SetStackNavigator(),
 
       OpenUpNavigator(),
+      OpenLeftNavigator(),
 
       PresentOnboardingStartNavigator(
         screen: OnboardingStartController.init,
@@ -168,13 +168,110 @@ struct DependencyRegistrator {
       PresentDrawerNavigator(
         screen: DrawerController.init(_:),
         navigationController: { navController }
+      ),
+      PresentContactListNavigator(
+        screen: ContactListController.init,
+        navigationController: { navController }
+      ),
+      PresentMenuNavigator(
+        screen: MenuController.init(_:),
+        navigationController: { navController }
+      ),
+      PresentScanNavigator(
+        screen: ScanContainerController.init,
+        navigationController: { navController }
+      ),
+      PresentNewGroupNavigator(
+        screen: CreateGroupController.init,
+        navigationController: { navController }
+      ),
+      PresentCountryListNavigator(
+        screen: CountryListController.init(_:),
+        navigationController: { navController }
+      ),
+      PresentProfileNavigator(
+        screen: ProfileController.init,
+        navigationController: { navController }
+      ),
+      PresentSettingsNavigator(
+        screen: SettingsController.init,
+        navigationController: { navController }
+      ),
+      PresentSettingsAdvancedNavigator(
+        screen: SettingsAdvancedController.init,
+        navigationController: { navController }
+      ),
+      PresentSettingsBackupNavigator(
+        screen: BackupController.init,
+        navigationController: { navController }
+      ),
+      PresentSettingsAccountDeleteNavigator(
+        screen: AccountDeleteController.init,
+        navigationController: { navController }
+      ),
+      PresentContactNavigator(
+        screen: ContactController.init(_:),
+        navigationController: { navController }
+      ),
+      PresentActivitySheetNavigator(
+        screen: { UIActivityViewController(
+          activityItems: $0,
+          applicationActivities: nil
+        )},
+        navigationController: { navController }
+      ),
+      PresentProfileEmailNavigator(
+        screen: ProfileEmailController.init,
+        navigationController: { navController }
+      ),
+      PresentProfilePhoneNavigator(
+        screen: ProfilePhoneController.init,
+        navigationController: { navController }
+      ),
+      PresentPermissionRequestNavigator(
+        screen: RequestPermissionController.init,
+        navigationController: { navController }
+      ),
+      PresentPhotoLibraryNavigator(
+        screen: UIImagePickerController.init,
+        navigationController: { navController }
+      ),
+      PresentProfileCodeNavigator(
+        screen: ProfileCodeController.init(_:_:_:),
+        navigationController: { navController }
       )
-      //        searchFactory: SearchContainerController.init,
-      //        restoreListFactory: RestoreListController.init,
-      //        countriesFactory: CountryListController.init(_:),
     ) as Navigator)
   }
 
+  //    container.register(
+  //      ProfileCoordinator(
+  //        imagePickerFactory: UIImagePickerController.init,
+  //        permissionFactory: RequestPermissionController.init,
+  //        countriesFactory: CountryListController.init(_:)
+  //        //codeFactory: ProfileCodeController.init(_:_:)
+  //      ) as ProfileCoordinating)
+
+  //    container.register(
+  //      SearchCoordinator(
+  //        contactsFactory: ContactListController.init,
+  //        requestsFactory: RequestsContainerController.init,
+  //        contactFactory: ContactController.init(_:),
+  //        countriesFactory: CountryListController.init(_:)
+  //      ) as SearchCoordinating)
+
+  //    container.register(
+  //      ContactListCoordinator(
+  //        scanFactory: ScanContainerController.init,
+  //        searchFactory: SearchContainerController.init,
+  //        newGroupFactory: CreateGroupController.init,
+  //        requestsFactory: RequestsContainerController.init,
+  //        contactFactory: ContactController.init(_:),
+  //        singleChatFactory: SingleChatController.init(_:),
+  //        groupChatFactory: GroupChatController.init(_:),
+  //        sideMenuFactory: MenuController.init(_:_:),
+  //        groupDrawerFactory: CreateDrawerController.init(_:_:)
+  //      ) as ContactListCoordinating)
+
   static private func registerCommonDependencies() {
     var environment: MessengerEnvironment = .live()
     environment.ndfEnvironment = .mainnet
@@ -197,129 +294,6 @@ struct DependencyRegistrator {
     container.register(HUDController())
     container.register(ToastController())
     container.register(StatusBarStylist())
-
-    container.register(
-      TermsCoordinator.live(
-        usernameFactory: OnboardingUsernameController.init,
-        chatListFactory: ChatListController.init
-      )
-    )
-
-    container.register(
-      BackupCoordinator(
-        sftpFactory: BackupSFTPController.init(_:),
-        passphraseFactory: BackupPassphraseController.init(_:_:)
-      ) as BackupCoordinating)
-
-    container.register(
-      MenuCoordinator(
-        scanFactory: ScanContainerController.init,
-        chatsFactory: ChatListController.init,
-        profileFactory: ProfileController.init,
-        settingsFactory: SettingsController.init,
-        contactsFactory: ContactListController.init,
-        requestsFactory: RequestsContainerController.init
-      ) as MenuCoordinating)
-
-    container.register(
-      SearchCoordinator(
-        contactsFactory: ContactListController.init,
-        requestsFactory: RequestsContainerController.init,
-        contactFactory: ContactController.init(_:),
-        countriesFactory: CountryListController.init(_:)
-      ) as SearchCoordinating)
-
-    container.register(
-      ProfileCoordinator(
-        emailFactory: ProfileEmailController.init,
-        phoneFactory: ProfilePhoneController.init,
-        imagePickerFactory: UIImagePickerController.init,
-        permissionFactory: RequestPermissionController.init,
-        sideMenuFactory: MenuController.init(_:_:),
-        countriesFactory: CountryListController.init(_:)
-        //codeFactory: ProfileCodeController.init(_:_:)
-      ) as ProfileCoordinating)
-
-    container.register(
-      SettingsCoordinator(
-        backupFactory: BackupController.init,
-        advancedFactory: SettingsAdvancedController.init,
-        accountDeleteFactory: AccountDeleteController.init,
-        sideMenuFactory: MenuController.init(_:_:)
-      ) as SettingsCoordinating)
-
-    container.register(
-      RestoreCoordinator(
-        successFactory: RestoreSuccessController.init,
-        chatListFactory: ChatListController.init,
-        restoreFactory: RestoreController.init(_:),
-        sftpFactory: RestoreSFTPController.init(_:),
-        passphraseFactory: RestorePassphraseController.init(_:_:)
-      ) as RestoreCoordinating)
-
-    container.register(
-      ChatCoordinator(
-        retryFactory: RetrySheetController.init,
-        webFactory: WebScreen.init(_:),
-        previewFactory: QLPreviewController.init,
-        contactFactory: ContactController.init(_:),
-        imagePickerFactory: UIImagePickerController.init,
-        permissionFactory: RequestPermissionController.init
-      ) as ChatCoordinating)
-
-    container.register(
-      ContactCoordinator(
-        requestsFactory: RequestsContainerController.init,
-        singleChatFactory: SingleChatController.init(_:),
-        imagePickerFactory: UIImagePickerController.init,
-        nicknameFactory: NicknameController.init(_:_:)
-      ) as ContactCoordinating)
-
-    container.register(
-      RequestsCoordinator(
-        searchFactory: SearchContainerController.init,
-        contactFactory: ContactController.init(_:),
-        singleChatFactory: SingleChatController.init(_:),
-        groupChatFactory: GroupChatController.init(_:),
-        sideMenuFactory: MenuController.init(_:_:),
-        nicknameFactory: NicknameController.init(_:_:)
-      ) as RequestsCoordinating)
-
-    container.register(
-      ContactListCoordinator(
-        scanFactory: ScanContainerController.init,
-        searchFactory: SearchContainerController.init,
-        newGroupFactory: CreateGroupController.init,
-        requestsFactory: RequestsContainerController.init,
-        contactFactory: ContactController.init(_:),
-        singleChatFactory: SingleChatController.init(_:),
-        groupChatFactory: GroupChatController.init(_:),
-        sideMenuFactory: MenuController.init(_:_:),
-        groupDrawerFactory: CreateDrawerController.init(_:_:)
-      ) as ContactListCoordinating)
-
-    container.register(
-      ScanCoordinator(
-        emailFactory: ProfileEmailController.init,
-        phoneFactory: ProfilePhoneController.init,
-        contactsFactory: ContactListController.init,
-        requestsFactory: RequestsContainerController.init,
-        contactFactory: ContactController.init(_:),
-        sideMenuFactory: MenuController.init(_:_:)
-      ) as ScanCoordinating)
-
-
-    container.register(
-      ChatListCoordinator(
-        scanFactory: ScanContainerController.init,
-        searchFactory: SearchContainerController.init,
-        newGroupFactory: CreateGroupController.init,
-        contactsFactory: ContactListController.init,
-        contactFactory: ContactController.init(_:),
-        singleChatFactory: SingleChatController.init(_:),
-        groupChatFactory: GroupChatController.init(_:),
-        sideMenuFactory: MenuController.init(_:_:)
-      ) as ChatListCoordinating)
   }
 }
 
@@ -339,27 +313,27 @@ extension PasswordStorage {
 private enum AlternativeUDConstants {
   static let address = "46.101.98.49:18001"
   static let cert = """
-            -----BEGIN CERTIFICATE-----
-            MIIDbDCCAlSgAwIBAgIJAOUNtZneIYECMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNV
-            BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQx
-            GzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJp
-            cDAeFw0xOTAzMDUxODM1NDNaFw0yOTAzMDIxODM1NDNaMGgxCzAJBgNVBAYTAlVT
-            MRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNV
-            BAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJpcDCCASIw
-            DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPP0WyVkfZA/CEd2DgKpcudn0oDh
-            Dwsjmx8LBDWsUgQzyLrFiVigfUmUefknUH3dTJjmiJtGqLsayCnWdqWLHPJYvFfs
-            WYW0IGF93UG/4N5UAWO4okC3CYgKSi4ekpfw2zgZq0gmbzTnXcHF9gfmQ7jJUKSE
-            tJPSNzXq+PZeJTC9zJAb4Lj8QzH18rDM8DaL2y1ns0Y2Hu0edBFn/OqavBJKb/uA
-            m3AEjqeOhC7EQUjVamWlTBPt40+B/6aFJX5BYm2JFkRsGBIyBVL46MvC02MgzTT9
-            bJIJfwqmBaTruwemNgzGu7Jk03hqqS1TUEvSI6/x8bVoba3orcKkf9HsDjECAwEA
-            AaMZMBcwFQYDVR0RBA4wDIIKKi5jbWl4LnJpcDANBgkqhkiG9w0BAQUFAAOCAQEA
-            neUocN4AbcQAC1+b3To8u5UGdaGxhcGyZBlAoenRVdjXK3lTjsMdMWb4QctgNfIf
-            U/zuUn2mxTmF/ekP0gCCgtleZr9+DYKU5hlXk8K10uKxGD6EvoiXZzlfeUuotgp2
-            qvI3ysOm/hvCfyEkqhfHtbxjV7j7v7eQFPbvNaXbLa0yr4C4vMK/Z09Ui9JrZ/Z4
-            cyIkxfC6/rOqAirSdIp09EGiw7GM8guHyggE4IiZrDslT8V3xIl985cbCxSxeW1R
-            tgH4rdEXuVe9+31oJhmXOE9ux2jCop9tEJMgWg7HStrJ5plPbb+HmjoX3nBO04E5
-            6m52PyzMNV+2N21IPppKwA==
-            -----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDbDCCAlSgAwIBAgIJAOUNtZneIYECMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQx
+GzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJp
+cDAeFw0xOTAzMDUxODM1NDNaFw0yOTAzMDIxODM1NDNaMGgxCzAJBgNVBAYTAlVT
+MRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNV
+BAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJpcDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPP0WyVkfZA/CEd2DgKpcudn0oDh
+Dwsjmx8LBDWsUgQzyLrFiVigfUmUefknUH3dTJjmiJtGqLsayCnWdqWLHPJYvFfs
+WYW0IGF93UG/4N5UAWO4okC3CYgKSi4ekpfw2zgZq0gmbzTnXcHF9gfmQ7jJUKSE
+tJPSNzXq+PZeJTC9zJAb4Lj8QzH18rDM8DaL2y1ns0Y2Hu0edBFn/OqavBJKb/uA
+m3AEjqeOhC7EQUjVamWlTBPt40+B/6aFJX5BYm2JFkRsGBIyBVL46MvC02MgzTT9
+bJIJfwqmBaTruwemNgzGu7Jk03hqqS1TUEvSI6/x8bVoba3orcKkf9HsDjECAwEA
+AaMZMBcwFQYDVR0RBA4wDIIKKi5jbWl4LnJpcDANBgkqhkiG9w0BAQUFAAOCAQEA
+neUocN4AbcQAC1+b3To8u5UGdaGxhcGyZBlAoenRVdjXK3lTjsMdMWb4QctgNfIf
+U/zuUn2mxTmF/ekP0gCCgtleZr9+DYKU5hlXk8K10uKxGD6EvoiXZzlfeUuotgp2
+qvI3ysOm/hvCfyEkqhfHtbxjV7j7v7eQFPbvNaXbLa0yr4C4vMK/Z09Ui9JrZ/Z4
+cyIkxfC6/rOqAirSdIp09EGiw7GM8guHyggE4IiZrDslT8V3xIl985cbCxSxeW1R
+tgH4rdEXuVe9+31oJhmXOE9ux2jCop9tEJMgWg7HStrJ5plPbb+HmjoX3nBO04E5
+6m52PyzMNV+2N21IPppKwA==
+-----END CERTIFICATE-----
 """
   static let contact = """
 <xxc(2)7mbKFLE201WzH4SGxAOpHjjehwztIV+KGifi5L/PYPcDkAZiB9kZo+Dl3Vc7dD2SdZCFMOJVgwqGzfYRDkjc8RGEllBqNxq2sRRX09iQVef0kJQUgJCHNCOcvm6Ki0JJwvjLceyFh36iwK8oLbhLgqEZY86UScdACTyBCzBIab3ob5mBthYc3mheV88yq5PGF2DQ+dEvueUm+QhOSfwzppAJA/rpW9Wq9xzYcQzaqc3ztAGYfm2BBAHS7HVmkCbvZ/K07Xrl4EBPGHJYq12tWAN/C3mcbbBYUOQXyEzbSl/mO7sL3ORr0B4FMuqCi8EdlD6RO52pVhY+Cg6roRH1t5Ng1JxPt8Mv1yyjbifPhZ5fLKwxBz8UiFORfk0/jnhwgm25LRHqtNRRUlYXLvhv0HhqyYTUt17WNtCLATSVbqLrFGdy2EGadn8mP+kQNHp93f27d/uHgBNNe7LpuYCJMdWpoG6bOqmHEftxt0/MIQA8fTtTm3jJzv+7/QjZJDvQIv0SNdp8HFogpuwde+GuS4BcY7v5xz+ArGWcRR63ct2z83MqQEn9ODr1/gAAAgA7szRpDDQIdFUQo9mkWg8xBA==xxc>
diff --git a/Sources/BackupFeature/Controllers/BackupConfigController.swift b/Sources/BackupFeature/Controllers/BackupConfigController.swift
index 9fd0b2735bab16831a77ee46d13c186b07c65b0a..79cbd4384d0376dd9727528c8d43ae74e853c703 100644
--- a/Sources/BackupFeature/Controllers/BackupConfigController.swift
+++ b/Sources/BackupFeature/Controllers/BackupConfigController.swift
@@ -2,333 +2,333 @@ import UIKit
 import Shared
 import Combine
 import CloudFiles
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 
 final class BackupConfigController: UIViewController {
-    @Dependency private var coordinator: BackupCoordinating
-
-    private lazy var screenView = BackupConfigView()
-
-    private let viewModel: BackupConfigViewModel
-    private var cancellables = Set<AnyCancellable>()
-    private var drawerCancellables = Set<AnyCancellable>()
+  @Dependency var navigator: Navigator
+
+  private lazy var screenView = BackupConfigView()
+
+  private let viewModel: BackupConfigViewModel
+  private var cancellables = Set<AnyCancellable>()
+  private var drawerCancellables = Set<AnyCancellable>()
+
+  private var wifiOnly = false
+  private var manualBackups = false
+  private var serviceName: String = ""
+
+  override func loadView() {
+    view = screenView
+  }
+
+  init(_ viewModel: BackupConfigViewModel) {
+    self.viewModel = viewModel
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    setupBindings()
+  }
+
+  private func setupBindings() {
+    viewModel.actionState()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in screenView.actionView.setState($0) }
+      .store(in: &cancellables)
+
+    viewModel.connectedServices()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in decorate(connectedServices: $0) }
+      .store(in: &cancellables)
+
+    viewModel.enabledService()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in decorate(enabledService: $0) }
+      .store(in: &cancellables)
+
+    viewModel.automatic()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.frequencyDetailView.subtitleLabel.text = $0 ? "Automatic" : "Manual"
+        manualBackups = !$0
+      }.store(in: &cancellables)
+
+    viewModel.wifiOnly()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.infrastructureDetailView.subtitleLabel.text = $0 ? "Wi-Fi Only" : "Wi-Fi and Cellular"
+        wifiOnly = $0
+      }.store(in: &cancellables)
+
+    viewModel.lastBackup()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        guard let backup = $0 else {
+          screenView.latestBackupDetailView.subtitleLabel.text = "Never"
+          return
+        }
 
-    private var wifiOnly = false
-    private var manualBackups = false
-    private var serviceName: String = ""
+        screenView.latestBackupDetailView.subtitleLabel.text = backup.lastModified.backupStyle()
+      }.store(in: &cancellables)
+
+    screenView.actionView.backupNowButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewModel.didTapBackupNow() }
+      .store(in: &cancellables)
+
+    screenView.frequencyDetailView
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in presentFrequencyDrawer(manual: manualBackups) }
+      .store(in: &cancellables)
+
+    screenView.infrastructureDetailView
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in presentInfrastructureDrawer(wifiOnly: wifiOnly) }
+      .store(in: &cancellables)
+
+    screenView.googleDriveButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewModel.didTapService(.drive, self) }
+      .store(in: &cancellables)
+
+    screenView.googleDriveButton.switcherView
+      .publisher(for: .valueChanged)
+      .sink { [unowned self] in viewModel.didToggleService(self, .drive, screenView.googleDriveButton.switcherView.isOn) }
+      .store(in: &cancellables)
+
+    screenView.dropboxButton.switcherView
+      .publisher(for: .valueChanged)
+      .sink { [unowned self] in viewModel.didToggleService(self, .dropbox, screenView.dropboxButton.switcherView.isOn) }
+      .store(in: &cancellables)
+
+    screenView.sftpButton.switcherView
+      .publisher(for: .valueChanged)
+      .sink { [unowned self] in viewModel.didToggleService(self, .sftp, screenView.sftpButton.switcherView.isOn) }
+      .store(in: &cancellables)
+
+    screenView.iCloudButton.switcherView
+      .publisher(for: .valueChanged)
+      .sink { [unowned self] in viewModel.didToggleService(self, .icloud, screenView.iCloudButton.switcherView.isOn) }
+      .store(in: &cancellables)
+
+    screenView.dropboxButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewModel.didTapService(.dropbox, self) }
+      .store(in: &cancellables)
+
+    screenView.sftpButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewModel.didTapService(.sftp, self) }
+      .store(in: &cancellables)
+
+    screenView.iCloudButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewModel.didTapService(.icloud, self) }
+      .store(in: &cancellables)
+  }
+
+  private func decorate(enabledService: CloudService?) {
+    var button: BackupSwitcherButton?
+
+    switch enabledService {
+    case .none:
+      break
+    case .icloud:
+      serviceName = Localized.Backup.iCloud
+      button = screenView.iCloudButton
+    case .dropbox:
+      serviceName = Localized.Backup.dropbox
+      button = screenView.dropboxButton
+    case .drive:
+      serviceName = Localized.Backup.googleDrive
+      button = screenView.googleDriveButton
+    case .sftp:
+      serviceName = Localized.Backup.sftp
+      button = screenView.sftpButton
+    }
 
-    override func loadView() {
-        view = screenView
+    screenView.enabledSubtitleLabel.text
+    = Localized.Backup.Config.disclaimer(serviceName)
+    screenView.frequencyDetailView.titleLabel.text
+    = Localized.Backup.Config.frequency(serviceName).uppercased()
+
+    guard let button = button else {
+      screenView.sftpButton.isHidden = false
+      screenView.iCloudButton.isHidden = false
+      screenView.dropboxButton.isHidden = false
+      screenView.googleDriveButton.isHidden = false
+
+      screenView.sftpButton.switcherView.isOn = false
+      screenView.iCloudButton.switcherView.isOn = false
+      screenView.dropboxButton.switcherView.isOn = false
+      screenView.googleDriveButton.switcherView.isOn = false
+
+      screenView.frequencyDetailView.isHidden = true
+      screenView.enabledSubtitleView.isHidden = true
+      screenView.latestBackupDetailView.isHidden = true
+      screenView.infrastructureDetailView.isHidden = true
+      return
     }
 
-    init(_ viewModel: BackupConfigViewModel) {
-        self.viewModel = viewModel
-        super.init(nibName: nil, bundle: nil)
+    screenView.frequencyDetailView.isHidden = false
+    screenView.enabledSubtitleView.isHidden = false
+    screenView.latestBackupDetailView.isHidden = false
+    screenView.infrastructureDetailView.isHidden = false
+
+    [screenView.iCloudButton,
+     screenView.dropboxButton,
+     screenView.googleDriveButton,
+     screenView.sftpButton].forEach {
+      $0.isHidden = $0 != button
+      $0.switcherView.isOn = $0 == button
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  private func decorate(connectedServices: Set<CloudService>) {
+    if connectedServices.contains(.icloud) {
+      screenView.iCloudButton.showSwitcher(enabled: false)
+    } else {
+      screenView.iCloudButton.showChevron()
+    }
 
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        setupBindings()
+    if connectedServices.contains(.dropbox) {
+      screenView.dropboxButton.showSwitcher(enabled: false)
+    } else {
+      screenView.dropboxButton.showChevron()
     }
 
-    private func setupBindings() {
-        viewModel.actionState()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.actionView.setState($0) }
-            .store(in: &cancellables)
-
-        viewModel.connectedServices()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in decorate(connectedServices: $0) }
-            .store(in: &cancellables)
-
-        viewModel.enabledService()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in decorate(enabledService: $0) }
-            .store(in: &cancellables)
-
-        viewModel.automatic()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                screenView.frequencyDetailView.subtitleLabel.text = $0 ? "Automatic" : "Manual"
-                manualBackups = !$0
-            }.store(in: &cancellables)
-
-        viewModel.wifiOnly()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                screenView.infrastructureDetailView.subtitleLabel.text = $0 ? "Wi-Fi Only" : "Wi-Fi and Cellular"
-                wifiOnly = $0
-            }.store(in: &cancellables)
-
-        viewModel.lastBackup()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                guard let backup = $0 else {
-                    screenView.latestBackupDetailView.subtitleLabel.text = "Never"
-                    return
-                }
-
-                screenView.latestBackupDetailView.subtitleLabel.text = backup.lastModified.backupStyle()
-            }.store(in: &cancellables)
-
-        screenView.actionView.backupNowButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewModel.didTapBackupNow() }
-            .store(in: &cancellables)
-
-        screenView.frequencyDetailView
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in presentFrequencyDrawer(manual: manualBackups) }
-            .store(in: &cancellables)
-
-        screenView.infrastructureDetailView
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in presentInfrastructureDrawer(wifiOnly: wifiOnly) }
-            .store(in: &cancellables)
-
-        screenView.googleDriveButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewModel.didTapService(.drive, self) }
-            .store(in: &cancellables)
-
-        screenView.googleDriveButton.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [unowned self] in viewModel.didToggleService(self, .drive, screenView.googleDriveButton.switcherView.isOn) }
-            .store(in: &cancellables)
-
-        screenView.dropboxButton.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [unowned self] in viewModel.didToggleService(self, .dropbox, screenView.dropboxButton.switcherView.isOn) }
-            .store(in: &cancellables)
-
-        screenView.sftpButton.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [unowned self] in viewModel.didToggleService(self, .sftp, screenView.sftpButton.switcherView.isOn) }
-            .store(in: &cancellables)
-
-        screenView.iCloudButton.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [unowned self] in viewModel.didToggleService(self, .icloud, screenView.iCloudButton.switcherView.isOn) }
-            .store(in: &cancellables)
-
-        screenView.dropboxButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewModel.didTapService(.dropbox, self) }
-            .store(in: &cancellables)
-
-        screenView.sftpButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewModel.didTapService(.sftp, self) }
-            .store(in: &cancellables)
-
-        screenView.iCloudButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewModel.didTapService(.icloud, self) }
-            .store(in: &cancellables)
+    if connectedServices.contains(.drive) {
+      screenView.googleDriveButton.showSwitcher(enabled: false)
+    } else {
+      screenView.googleDriveButton.showChevron()
     }
 
-    private func decorate(enabledService: CloudService?) {
-        var button: BackupSwitcherButton?
-
-        switch enabledService {
-        case .none:
-            break
-        case .icloud:
-            serviceName = Localized.Backup.iCloud
-            button = screenView.iCloudButton
-        case .dropbox:
-            serviceName = Localized.Backup.dropbox
-            button = screenView.dropboxButton
-        case .drive:
-            serviceName = Localized.Backup.googleDrive
-            button = screenView.googleDriveButton
-        case .sftp:
-            serviceName = Localized.Backup.sftp
-            button = screenView.sftpButton
+    if connectedServices.contains(.sftp) {
+      screenView.sftpButton.showSwitcher(enabled: false)
+    } else {
+      screenView.sftpButton.showChevron()
+    }
+  }
+
+  private func presentInfrastructureDrawer(wifiOnly: Bool) {
+    let cancelButton = DrawerCapsuleButton(model: .init(
+      title: Localized.ChatList.Dashboard.cancel,
+      style: .seeThrough
+    ))
+    let wifiOnlyButton = DrawerRadio(
+      title: "Wi-Fi Only",
+      isSelected: wifiOnly
+    )
+    let wifiAndCellularButton = DrawerRadio(
+      title: "Wi-Fi and Cellular",
+      isSelected: !wifiOnly,
+      spacingAfter: 40
+    )
+
+    wifiOnlyButton
+      .action
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didChooseWifiOnly(true)
         }
-
-        screenView.enabledSubtitleLabel.text
-        = Localized.Backup.Config.disclaimer(serviceName)
-        screenView.frequencyDetailView.titleLabel.text
-        = Localized.Backup.Config.frequency(serviceName).uppercased()
-
-        guard let button = button else {
-            screenView.sftpButton.isHidden = false
-            screenView.iCloudButton.isHidden = false
-            screenView.dropboxButton.isHidden = false
-            screenView.googleDriveButton.isHidden = false
-
-            screenView.sftpButton.switcherView.isOn = false
-            screenView.iCloudButton.switcherView.isOn = false
-            screenView.dropboxButton.switcherView.isOn = false
-            screenView.googleDriveButton.switcherView.isOn = false
-
-            screenView.frequencyDetailView.isHidden = true
-            screenView.enabledSubtitleView.isHidden = true
-            screenView.latestBackupDetailView.isHidden = true
-            screenView.infrastructureDetailView.isHidden = true
-            return
+      }.store(in: &drawerCancellables)
+
+    wifiAndCellularButton
+      .action
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didChooseWifiOnly(false)
         }
-
-        screenView.frequencyDetailView.isHidden = false
-        screenView.enabledSubtitleView.isHidden = false
-        screenView.latestBackupDetailView.isHidden = false
-        screenView.infrastructureDetailView.isHidden = false
-
-        [screenView.iCloudButton,
-         screenView.dropboxButton,
-         screenView.googleDriveButton,
-         screenView.sftpButton].forEach {
-            $0.isHidden = $0 != button
-            $0.switcherView.isOn = $0 == button
+      }.store(in: &drawerCancellables)
+
+    cancelButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
         }
-    }
-
-    private func decorate(connectedServices: Set<CloudService>) {
-        if connectedServices.contains(.icloud) {
-            screenView.iCloudButton.showSwitcher(enabled: false)
-        } else {
-            screenView.iCloudButton.showChevron()
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
+      DrawerText(
+        font: Fonts.Mulish.extraBold.font(size: 28.0),
+        text: Localized.Backup.Config.infrastructure,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 30
+      ),
+      wifiOnlyButton,
+      wifiAndCellularButton,
+      cancelButton
+    ]))
+  }
+
+  private func presentFrequencyDrawer(manual: Bool) {
+    let cancelButton = DrawerCapsuleButton(model: .init(
+      title: Localized.ChatList.Dashboard.cancel,
+      style: .seeThrough
+    ))
+    let manualButton = DrawerRadio(
+      title: "Manual",
+      isSelected: manual
+    )
+    let automaticButton = DrawerRadio(
+      title: "Automatic",
+      isSelected: !manual,
+      spacingAfter: 40
+    )
+    manualButton
+      .action
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didChooseAutomatic(false)
         }
-
-        if connectedServices.contains(.dropbox) {
-            screenView.dropboxButton.showSwitcher(enabled: false)
-        } else {
-            screenView.dropboxButton.showChevron()
+      }.store(in: &drawerCancellables)
+
+    automaticButton
+      .action
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didChooseAutomatic(true)
         }
-
-        if connectedServices.contains(.drive) {
-            screenView.googleDriveButton.showSwitcher(enabled: false)
-        } else {
-            screenView.googleDriveButton.showChevron()
+      }.store(in: &drawerCancellables)
+
+    cancelButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
         }
-
-        if connectedServices.contains(.sftp) {
-            screenView.sftpButton.showSwitcher(enabled: false)
-        } else {
-            screenView.sftpButton.showChevron()
-        }
-    }
-
-    private func presentInfrastructureDrawer(wifiOnly: Bool) {
-        let cancelButton = DrawerCapsuleButton(model: .init(
-            title: Localized.ChatList.Dashboard.cancel,
-            style: .seeThrough
-        ))
-
-        let wifiOnlyButton = DrawerRadio(
-            title: "Wi-Fi Only",
-            isSelected: wifiOnly
-        )
-
-        let wifiAndCellularButton = DrawerRadio(
-            title: "Wi-Fi and Cellular",
-            isSelected: !wifiOnly,
-            spacingAfter: 40
-        )
-
-        let drawer = DrawerController([
-            DrawerText(
-                font: Fonts.Mulish.extraBold.font(size: 28.0),
-                text: Localized.Backup.Config.infrastructure,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 30
-            ),
-            wifiOnlyButton,
-            wifiAndCellularButton,
-            cancelButton
-        ])
-
-        wifiOnlyButton.action
-            .sink { [unowned self] in
-                viewModel.didChooseWifiOnly(true)
-
-                drawer.dismiss(animated: true) { [weak self] in
-                    self?.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        wifiAndCellularButton.action
-            .sink { [unowned self] in
-                viewModel.didChooseWifiOnly(false)
-
-                drawer.dismiss(animated: true) { [weak self] in
-                    self?.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        cancelButton.action
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    self?.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
-
-    private func presentFrequencyDrawer(manual: Bool) {
-        let cancelButton = DrawerCapsuleButton(model: .init(
-            title: Localized.ChatList.Dashboard.cancel,
-            style: .seeThrough
-        ))
-
-        let manualButton = DrawerRadio(
-            title: "Manual",
-            isSelected: manual
-        )
-
-        let automaticButton = DrawerRadio(
-            title: "Automatic",
-            isSelected: !manual,
-            spacingAfter: 40
-        )
-
-        let drawer = DrawerController([
-            DrawerText(
-                font: Fonts.Mulish.extraBold.font(size: 28.0),
-                text: Localized.Backup.Config.frequency(serviceName),
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 30
-            ),
-            manualButton,
-            automaticButton,
-            cancelButton
-        ])
-
-        manualButton.action
-            .sink { [unowned self] in
-                viewModel.didChooseAutomatic(false)
-
-                drawer.dismiss(animated: true) { [weak self] in
-                    self?.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        automaticButton.action
-            .sink { [unowned self] in
-                viewModel.didChooseAutomatic(true)
-
-                drawer.dismiss(animated: true) { [weak self] in
-                    self?.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        cancelButton.action
-            .receive(on: DispatchQueue.main)
-            .sink {
-                drawer.dismiss(animated: true) { [weak self] in
-                    self?.drawerCancellables.removeAll()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
+      DrawerText(
+        font: Fonts.Mulish.extraBold.font(size: 28.0),
+        text: Localized.Backup.Config.frequency(serviceName),
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 30
+      ),
+      manualButton,
+      automaticButton,
+      cancelButton
+    ]))
+  }
 }
diff --git a/Sources/BackupFeature/Coordinator/BackupCoordinator.swift b/Sources/BackupFeature/Coordinator/BackupCoordinator.swift
deleted file mode 100644
index 9ef0fdfb6087c96941953ef25b5bafdf686b1a80..0000000000000000000000000000000000000000
--- a/Sources/BackupFeature/Coordinator/BackupCoordinator.swift
+++ /dev/null
@@ -1,91 +0,0 @@
-import UIKit
-import Shared
-import Presentation
-import ScrollViewController
-
-public typealias SFTPDetailsClosure = (String, String, String) -> Void
-
-public protocol BackupCoordinating {
-  func toDrawer(
-    _: UIViewController,
-    from: UIViewController
-  )
-
-  func toSFTP(
-    from: UIViewController,
-    detailsClosure: @escaping SFTPDetailsClosure
-  )
-
-  func toPassphrase(
-    from: UIViewController,
-    cancelClosure: @escaping EmptyClosure,
-    passphraseClosure: @escaping StringClosure
-  )
-}
-
-public struct BackupCoordinator: BackupCoordinating {
-  var pushPresenter: Presenting = PushPresenter()
-  var fullscreenPresenter: Presenting = FullscreenPresenter()
-
-  var sftpFactory: (@escaping SFTPDetailsClosure) -> UIViewController
-
-  var passphraseFactory: (
-    @escaping EmptyClosure,
-    @escaping StringClosure
-  ) -> UIViewController
-
-  public init(
-    sftpFactory: @escaping (
-      @escaping SFTPDetailsClosure
-    ) -> UIViewController,
-    passphraseFactory: @escaping (
-      @escaping EmptyClosure,
-      @escaping StringClosure
-    ) -> UIViewController
-  ) {
-    self.sftpFactory = sftpFactory
-    self.passphraseFactory = passphraseFactory
-  }
-}
-
-public extension BackupCoordinator {
-  func toSFTP(
-    from parent: UIViewController,
-    detailsClosure: @escaping SFTPDetailsClosure
-  ) {
-    let screen = sftpFactory(detailsClosure)
-    pushPresenter.present(screen, from: parent)
-  }
-
-  func toDrawer(
-    _ screen: UIViewController,
-    from parent: UIViewController
-  ) {
-    let target = ScrollViewController.embedding(screen)
-    fullscreenPresenter.present(target, from: parent)
-  }
-
-  func toPassphrase(
-    from parent: UIViewController,
-    cancelClosure: @escaping EmptyClosure,
-    passphraseClosure: @escaping StringClosure
-  ) {
-    let screen = passphraseFactory(cancelClosure, passphraseClosure)
-    let target = ScrollViewController.embedding(screen)
-    fullscreenPresenter.present(target, from: parent)
-  }
-}
-
-extension ScrollViewController {
-  static func embedding(_ viewController: UIViewController) -> ScrollViewController {
-    let scrollViewController = ScrollViewController()
-    scrollViewController.addChild(viewController)
-    scrollViewController.contentView = viewController.view
-    scrollViewController.wrapperView.handlesTouchesOutsideContent = false
-    scrollViewController.wrapperView.alignContentToBottom = true
-    scrollViewController.scrollView.bounces = false
-
-    viewController.didMove(toParent: scrollViewController)
-    return scrollViewController
-  }
-}
diff --git a/Sources/BackupFeature/Service/BackupService.swift b/Sources/BackupFeature/Service/BackupService.swift
index 4c888b8824c3b8fe3b5919332c29eac2e11bf796..18e057f07faa66824f50831b22779c45ce789822 100644
--- a/Sources/BackupFeature/Service/BackupService.swift
+++ b/Sources/BackupFeature/Service/BackupService.swift
@@ -28,7 +28,7 @@ public final class BackupService {
 
   public var settingsPublisher: AnyPublisher<CloudSettings, Never> {
     settings.handleEvents(receiveSubscription: { [weak self] _ in
-      guard let self = self else { return }
+      guard let self else { return }
       self.connectedServicesSubject.send(CloudFilesManager.all.linkedServices())
       self.fetchBackupOnAllProviders()
     }).eraseToAnyPublisher()
@@ -117,10 +117,7 @@ public final class BackupService {
   func initializeBackup(passphrase: String) {
     do {
       try messenger.startBackup(
-        password: passphrase,
-        params: .init(
-          username: username!
-        )
+        password: passphrase
       )
     } catch {
       print(">>> Exception when calling `messenger.startBackup`: \(error.localizedDescription)")
diff --git a/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift b/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift
index 38adaf920874de8e0cd1cfad00049a9396a03e8e..edaf65b5d141053d00c5793815addd5e17af44ba 100644
--- a/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift
+++ b/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift
@@ -8,6 +8,7 @@ import Foundation
 import DependencyInjection
 
 import CloudFiles
+import XXNavigation
 
 enum BackupActionState {
   case backupFinished
@@ -33,9 +34,9 @@ struct BackupConfigViewModel {
 extension BackupConfigViewModel {
   static func live() -> Self {
     class Context {
+      @Dependency var navigator: Navigator
       @Dependency var service: BackupService
       @Dependency var hudController: HUDController
-      @Dependency var coordinator: BackupCoordinating
     }
 
     let context = Context()
@@ -56,22 +57,22 @@ extension BackupConfigViewModel {
           context.service.stopBackups()
           return
         }
-        context.coordinator.toPassphrase(from: controller, cancelClosure: {
+        context.navigator.perform(PresentPassphrase(onCancel: {
           context.service.toggle(service: service, enabling: false)
-        }, passphraseClosure: { passphrase in
+        }, onPassphrase: { passphrase in
           context.hudController.show(.init(
             content: "Initializing and securing your backup file will take few seconds, please keep the app open."
           ))
           context.service.toggle(service: service, enabling: enabling)
           context.service.initializeBackup(passphrase: passphrase)
           context.hudController.dismiss()
-        })
+        }))
       },
       didTapService: { service, controller in
         if service == .sftp {
-          context.coordinator.toSFTP(from: controller) { host, username, password in
+          context.navigator.perform(PresentSFTP { host, username, password in
             context.service.setupSFTP(host: host, username: username, password: password)
-          }
+          })
           return
         }
 
diff --git a/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift b/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift
index 109bc6ef897924e5e9075111630b3ee95bbf0863..14931edd25effc5a99196ef03d8cf183356b39db 100644
--- a/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift
+++ b/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift
@@ -54,7 +54,7 @@ final class BackupSFTPViewModel {
     let anyController = UIViewController()
 
     DispatchQueue.global().async { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       do {
         try CloudFilesManager.sftp(
           host: host,
diff --git a/Sources/ChatFeature/Controllers/GroupChatController.swift b/Sources/ChatFeature/Controllers/GroupChatController.swift
index e101c03535310fcdbfab685901633919921e6bb6..0634e2cc6aa63eaded3d3e3ab58bed91fbe8d5ca 100644
--- a/Sources/ChatFeature/Controllers/GroupChatController.swift
+++ b/Sources/ChatFeature/Controllers/GroupChatController.swift
@@ -4,6 +4,7 @@ import Combine
 import XXModels
 import Voxophone
 import ChatLayout
+import XXNavigation
 import DrawerFeature
 import DifferenceKit
 import ReportingFeature
@@ -19,13 +20,12 @@ typealias OutgoingFailedGroupReplyCell = CollectionCell<FlexibleSpace, ReplyStac
 
 public final class GroupChatController: UIViewController {
   @Dependency var database: Database
+  @Dependency var navigator: Navigator
   @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!
   private lazy var header = GroupHeaderView()
   private let inputComponent: ChatInputView
@@ -34,6 +34,7 @@ public final class GroupChatController: UIViewController {
   private let viewModel: GroupChatViewModel
   private let layoutDelegate = LayoutDelegate()
   private var cancellables = Set<AnyCancellable>()
+  private var drawerCancellables = Set<AnyCancellable>()
   private let chatLayout = CollectionViewChatLayout()
   private var sections = [ArraySection<ChatSection, Message>]()
   private var currentInterfaceActions = SetActor<Set<InterfaceActions>, ReactionTypes>()
@@ -44,7 +45,6 @@ public final class GroupChatController: UIViewController {
   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),
@@ -148,7 +148,7 @@ public final class GroupChatController: UIViewController {
 
   private func setupInputController() {
     inputComponent.setMaxHeight { [weak self] in
-      guard let self = self else { return 150 }
+      guard let self else { return 150 }
 
       let maxHeight = self.collectionView.frame.height
       - self.collectionView.adjustedContentInset.top
@@ -167,24 +167,104 @@ public final class GroupChatController: UIViewController {
   }
 
   private func setupBindings() {
-    viewModel.routesPublisher
+    viewModel
+      .routesPublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
         switch $0 {
         case .waitingRound:
-          coordinator.toDrawer(makeWaitingRoundDrawer(), from: self)
+          let button = DrawerCapsuleButton(model: .init(
+            title: Localized.Chat.RoundDrawer.action,
+            style: .brandColored
+          ))
+
+          button
+            .action
+            .receive(on: DispatchQueue.main)
+            .sink { [unowned self] in
+              navigator.perform(DismissModal(from: self)) { [weak self] in
+                guard let self else { return }
+                self.drawerCancellables.removeAll()
+              }
+            }.store(in: &drawerCancellables)
+
+          navigator.perform(PresentDrawer(items: [
+            DrawerText(
+              font: Fonts.Mulish.semiBold.font(size: 14.0),
+              text: Localized.Chat.RoundDrawer.title,
+              color: Asset.neutralWeak.color,
+              lineHeightMultiple: 1.35,
+              spacingAfter: 25
+            ), button
+          ]))
+
         case .webview(let urlString):
-          coordinator.toWebview(with: urlString, from: self)
+          navigator.perform(PresentWebsite(url: URL(string: urlString)!))
         }
       }.store(in: &cancellables)
 
-    viewModel.reportPopupPublisher
+    viewModel
+      .reportPopupPublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] contact in
-        presentReportDrawer(contact)
+        let cancelButton = CapsuleButton()
+        cancelButton.setStyle(.seeThrough)
+        cancelButton.setTitle(Localized.Chat.Report.cancel, for: .normal)
+
+        let reportButton = CapsuleButton()
+        reportButton.setStyle(.red)
+        reportButton.setTitle(Localized.Chat.Report.action, for: .normal)
+
+        reportButton
+          .publisher(for: .touchUpInside)
+          .receive(on: DispatchQueue.main)
+          .sink { [unowned self] in
+            navigator.perform(DismissModal(from: self)) { [weak self] in
+              guard let self else { return }
+              self.drawerCancellables.removeAll()
+              let screenshot = try! self.makeAppScreenshot()
+              self.viewModel.report(contact: contact, screenshot: screenshot) {
+                self.collectionView.reloadData()
+              }
+            }
+          }.store(in: &drawerCancellables)
+
+        cancelButton
+          .publisher(for: .touchUpInside)
+          .receive(on: DispatchQueue.main)
+          .sink { [unowned self] in
+            navigator.perform(DismissModal(from: self)) { [weak self] in
+              guard let self else { return }
+              self.drawerCancellables.removeAll()
+            }
+          }.store(in: &drawerCancellables)
+
+        navigator.perform(PresentDrawer(items: [
+          DrawerImage(
+            image: Asset.drawerNegative.image
+          ),
+          DrawerText(
+            font: Fonts.Mulish.semiBold.font(size: 18.0),
+            text: Localized.Chat.Report.title,
+            color: Asset.neutralActive.color
+          ),
+          DrawerText(
+            font: Fonts.Mulish.semiBold.font(size: 14.0),
+            text: Localized.Chat.Report.subtitle,
+            color: Asset.neutralWeak.color,
+            lineHeightMultiple: 1.35,
+            spacingAfter: 25
+          ),
+          DrawerStack(
+            axis: .vertical,
+            spacing: 20.0,
+            views: [reportButton, cancelButton]
+          )
+        ]))
       }.store(in: &cancellables)
 
-    viewModel.messages
+    viewModel
+      .messages
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] sections in
         func process() {
@@ -234,45 +314,7 @@ public final class GroupChatController: UIViewController {
   }
 
   @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()
-      }
-    }
-    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([text, button])
-
-    button.action
-      .receive(on: DispatchQueue.main)
-      .sink { [weak drawer] in
-        drawer?.dismiss(animated: true)
-      }.store(in: &drawer.cancellables)
-
-    return drawer
+    navigator.perform(PresentMemberList(members: viewModel.info.members))
   }
 
   func scrollToBottom(completion: (() -> Void)? = nil) {
@@ -290,7 +332,7 @@ public final class GroupChatController: UIViewController {
     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 }
+        guard let self else { return }
 
         self.collectionView.contentOffset = CGPoint(x: self.collectionView.contentOffset.x, y: initialOffset + (delta * percentage))
         if percentage == 1.0 {
@@ -598,7 +640,7 @@ extension GroupChatController: UICollectionViewDelegate {
       previewProvider: nil
     ) { [weak self] suggestedActions in
 
-      guard let self = self else { return nil }
+      guard let self else { return nil }
 
       let item = self.sections[indexPath.section].elements[indexPath.item]
 
diff --git a/Sources/ChatFeature/Controllers/SheetController.swift b/Sources/ChatFeature/Controllers/SheetController.swift
index b0f9ed2937c7b4a57ebfc3458d4aa028f73d4737..12dd2e5a2a0e4b888f64e9277973109f19a8cadf 100644
--- a/Sources/ChatFeature/Controllers/SheetController.swift
+++ b/Sources/ChatFeature/Controllers/SheetController.swift
@@ -2,50 +2,51 @@ import UIKit
 import Combine
 
 final class SheetController: UIViewController {
-    enum Action {
-        case clear
-        case details
-        case report
-    }
-
-    private lazy var screenView = SheetView()
-
-    var actionPublisher: AnyPublisher<Action, Never> {
-        actionRelay.eraseToAnyPublisher()
-    }
-
-    private var cancellables = Set<AnyCancellable>()
-    private let actionRelay = PassthroughSubject<Action, Never>()
-
-    public override func loadView() {
-        view = screenView
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-
-        screenView.clearButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in
-                dismiss(animated: true) { [weak actionRelay] in
-                    actionRelay?.send(.clear)
-                }
-            }.store(in: &cancellables)
-
-        screenView.detailsButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in
-                dismiss(animated: true) { [weak actionRelay] in
-                    actionRelay?.send(.details)
-                }
-            }.store(in: &cancellables)
-
-        screenView.reportButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in
-                dismiss(animated: true) { [weak actionRelay] in
-                    actionRelay?.send(.report)
-                }
-            }.store(in: &cancellables)
-    }
+  enum Action {
+    case clear
+    case details
+    case report
+  }
+
+  private lazy var screenView = SheetView()
+
+  var actionPublisher: AnyPublisher<Action, Never> {
+    actionRelay.eraseToAnyPublisher()
+  }
+
+  private var cancellables = Set<AnyCancellable>()
+  private let actionRelay = PassthroughSubject<Action, Never>()
+
+  public override func loadView() {
+    view = screenView
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+
+    screenView
+      .clearButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak actionRelay] in
+          actionRelay?.send(.clear)
+        }
+      }.store(in: &cancellables)
+
+    screenView.detailsButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak actionRelay] in
+          actionRelay?.send(.details)
+        }
+      }.store(in: &cancellables)
+
+    screenView.reportButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak actionRelay] in
+          actionRelay?.send(.report)
+        }
+      }.store(in: &cancellables)
+  }
 }
diff --git a/Sources/ChatFeature/Controllers/SingleChatController.swift b/Sources/ChatFeature/Controllers/SingleChatController.swift
index 9f2f7f8227bbf3696cedc3916b1ea1c6f582ab12..5c3a7b277acf8d89a7e74ddef2a8f097320f37eb 100644
--- a/Sources/ChatFeature/Controllers/SingleChatController.swift
+++ b/Sources/ChatFeature/Controllers/SingleChatController.swift
@@ -6,6 +6,7 @@ import QuickLook
 import XXModels
 import Voxophone
 import ChatLayout
+import XXNavigation
 import DrawerFeature
 import DifferenceKit
 import ChatInputFeature
@@ -23,9 +24,9 @@ extension Message: Differentiable {
 
 public final class SingleChatController: UIViewController {
   @Dependency var logger: XXLogger
+  @Dependency var navigator: Navigator
   @Dependency var voxophone: Voxophone
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: ChatCoordinating
   @Dependency var reportingStatus: ReportingStatus
   @Dependency var makeReportDrawer: MakeReportDrawer
   @Dependency var makeAppScreenshot: MakeAppScreenshot
@@ -45,6 +46,7 @@ public final class SingleChatController: UIViewController {
   private let viewModel: SingleChatViewModel
   private let layoutDelegate = LayoutDelegate()
   private var cancellables = Set<AnyCancellable>()
+  private var drawerCancellables = Set<AnyCancellable>()
   private let chatLayout = CollectionViewChatLayout()
   private var sections = [ArraySection<ChatSection, Message>]()
   private var currentInterfaceActions: SetActor<Set<InterfaceActions>, ReactionTypes> = SetActor()
@@ -134,8 +136,6 @@ public final class SingleChatController: UIViewController {
     screenView.bringSubviewToFront(screenView.snackBar)
   }
 
-  // MARK: Private
-
   private func setupCollectionView() {
     chatLayout.configure(layoutDelegate)
     collectionView = .init(on: screenView, with: chatLayout)
@@ -192,7 +192,7 @@ public final class SingleChatController: UIViewController {
 
   private func setupInputController() {
     inputComponent.setMaxHeight { [weak self] in
-      guard let self = self else { return 150 }
+      guard let self else { return 150 }
 
       let maxHeight = self.collectionView.frame.height
       - self.collectionView.adjustedContentInset.top
@@ -215,19 +215,43 @@ public final class SingleChatController: UIViewController {
       .sink { [unowned self] in
         switch $0 {
         case .library:
-          coordinator.toLibrary(from: self)
+          navigator.perform(PresentPhotoLibrary())
         case .camera:
-          coordinator.toCamera(from: self)
+          navigator.perform(PresentCamera())
         case .cameraPermission:
-          coordinator.toPermission(type: .camera, from: self)
+          navigator.perform(PresentPermissionRequest(type: .camera))
         case .microphonePermission:
-          coordinator.toPermission(type: .microphone, from: self)
+          navigator.perform(PresentPermissionRequest(type: .microphone))
         case .libraryPermission:
-          coordinator.toPermission(type: .library, from: self)
+          navigator.perform(PresentPermissionRequest(type: .library))
         case .webview(let urlString):
-          coordinator.toWebview(with: urlString, from: self)
+          navigator.perform(PresentWebsite(url: URL(string: urlString)!))
         case .waitingRound:
-          coordinator.toDrawer(makeWaitingRoundDrawer(), from: self)
+          let button = DrawerCapsuleButton(model: .init(
+            title: Localized.Chat.RoundDrawer.action,
+            style: .brandColored
+          ))
+
+          button
+            .action
+            .receive(on: DispatchQueue.main)
+            .sink { [unowned self] in
+              navigator.perform(DismissModal(from: self)) { [weak self] in
+                guard let self else { return }
+                self.drawerCancellables.removeAll()
+              }
+            }.store(in: &drawerCancellables)
+
+          navigator.perform(PresentDrawer(items: [
+            DrawerText(
+              font: Fonts.Mulish.semiBold.font(size: 14.0),
+              text: Localized.Chat.RoundDrawer.title,
+              color: Asset.neutralWeak.color,
+              lineHeightMultiple: 1.35,
+              spacingAfter: 25
+            ),
+            button
+          ]))
         case .none:
           break
         }
@@ -237,14 +261,15 @@ public final class SingleChatController: UIViewController {
   }
 
   private func setupBindings() {
-    sheet.actionPublisher
+    sheet
+      .actionPublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
         switch $0 {
         case .clear:
           presentDeleteAllDrawer()
         case .details:
-          coordinator.toContact(viewModel.contact, from: self)
+          navigator.perform(PresentContact(contact: viewModel.contact))
         case .report:
           presentReportDrawer()
         }
@@ -261,19 +286,23 @@ public final class SingleChatController: UIViewController {
         }
       }.store(in: &cancellables)
 
-    viewModel.reportPopupPublisher
+    viewModel
+      .reportPopupPublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
         presentReportDrawer()
       }.store(in: &cancellables)
 
-    viewModel.isOnline
+    viewModel
+      .isOnline
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
-      .sink { [weak screenView] in screenView?.displayNetworkIssue(!$0) }
-      .store(in: &cancellables)
+      .sink { [weak screenView] in
+        screenView?.displayNetworkIssue(!$0)
+      }.store(in: &cancellables)
 
-    viewModel.messages
+    viewModel
+      .messages
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] sections in
         func process() {
@@ -337,7 +366,7 @@ public final class SingleChatController: UIViewController {
     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 }
+        guard let self else { return }
 
         self.collectionView.contentOffset = CGPoint(x: self.collectionView.contentOffset.x, y: initialOffset + (delta * percentage))
         if percentage == 1.0 {
@@ -359,42 +388,62 @@ public final class SingleChatController: UIViewController {
     }
   }
 
-  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
-    ))
+  private func presentReportDrawer() {
+    let cancelButton = CapsuleButton()
+    cancelButton.setStyle(.seeThrough)
+    cancelButton.setTitle(Localized.Chat.Report.cancel, for: .normal)
 
-    let drawer = DrawerController([text, button])
+    let reportButton = CapsuleButton()
+    reportButton.setStyle(.red)
+    reportButton.setTitle(Localized.Chat.Report.action, for: .normal)
 
-    button.action
+    reportButton
+      .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned drawer] in drawer.dismiss(animated: true) }
-      .store(in: &drawer.cancellables)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          let screenshot = try! self.makeAppScreenshot()
+          self.viewModel.report(screenshot: screenshot) { success in
+            guard success else { return }
+            self.navigationController?.popViewController(animated: true)
+          }
+        }
+      }.store(in: &drawerCancellables)
 
-    return drawer
-  }
+    cancelButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-  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)
+    navigator.perform(PresentDrawer(items: [
+      DrawerImage(
+        image: Asset.drawerNegative.image
+      ),
+      DrawerText(
+        font: Fonts.Mulish.semiBold.font(size: 18.0),
+        text: Localized.Chat.Report.title,
+        color: Asset.neutralActive.color
+      ),
+      DrawerText(
+        font: Fonts.Mulish.semiBold.font(size: 14.0),
+        text: Localized.Chat.Report.subtitle,
+        color: Asset.neutralWeak.color,
+        lineHeightMultiple: 1.35,
+        spacingAfter: 25
+      ),
+      DrawerStack(
+        axis: .vertical,
+        spacing: 20.0,
+        views: [reportButton, cancelButton]
+      )
+    ]))
   }
 
   private func presentDeleteAllDrawer() {
@@ -406,7 +455,28 @@ public final class SingleChatController: UIViewController {
     cancelButton.setStyle(.seeThrough)
     cancelButton.setTitle(Localized.Chat.Clear.cancel, for: .normal)
 
-    let drawer = DrawerController([
+    clearButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didRequestDeleteAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    cancelButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
       DrawerImage(
         image: Asset.drawerNegative.image
       ),
@@ -426,23 +496,7 @@ public final class SingleChatController: UIViewController {
         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)
-
-    coordinator.toDrawer(drawer, from: self)
+    ]))
   }
 
   private func previewItemAt(_ indexPath: IndexPath) {
@@ -453,17 +507,15 @@ public final class SingleChatController: UIViewController {
 
     let ft = viewModel.getFileTransferWith(id: ftid)
     fileURL = FileManager.url(for: "\(ft.name).\(ft.type)")
-    coordinator.toPreview(from: self)
+    //coordinator.toPreview(from: self)
   }
 
-  // MARK: Selectors
-
   @objc private func didTapDots() {
-    coordinator.toMenuSheet(sheet, from: self)
+    //coordinator.toMenuSheet(sheet, from: self)
   }
 
   @objc private func didTapInfo() {
-    coordinator.toContact(viewModel.contact, from: self)
+    navigator.perform(PresentContact(contact: viewModel.contact))
   }
 }
 
@@ -638,7 +690,7 @@ extension SingleChatController: UICollectionViewDelegate {
       previewProvider: nil
     ) { [weak self] _ in
 
-      guard let self = self else { return nil }
+      guard let self else { return nil }
       let item = self.sections[indexPath.section].elements[indexPath.item]
 
       var children = [
diff --git a/Sources/ChatFeature/Coordinator/ChatCoordinator.swift b/Sources/ChatFeature/Coordinator/ChatCoordinator.swift
deleted file mode 100644
index 5c9045dded7d2202c7b23dd12364d6af83c3ccdb..0000000000000000000000000000000000000000
--- a/Sources/ChatFeature/Coordinator/ChatCoordinator.swift
+++ /dev/null
@@ -1,105 +0,0 @@
-import UIKit
-import Shared
-import XXModels
-import QuickLook
-import Permissions
-import Presentation
-
-public protocol ChatCoordinating {
-    func toCamera(from: UIViewController)
-    func toLibrary(from: UIViewController)
-    func toPreview(from: UIViewController)
-    func toRetrySheet(from: UIViewController)
-    func toContact(_: Contact, from: UIViewController)
-    func toWebview(with: String, from: UIViewController)
-    func toDrawer(_: UIViewController, from: UIViewController)
-    func toMenuSheet(_: UIViewController, from: UIViewController)
-    func toPermission(type: PermissionType, from: UIViewController)
-    func toMembersList(_: UIViewController, from: UIViewController)
-}
-
-public struct ChatCoordinator: ChatCoordinating {
-    var pushPresenter: Presenting = PushPresenter()
-    var modalPresenter: Presenting = ModalPresenter()
-    var bottomPresenter: Presenting = BottomPresenter()
-
-    var retryFactory: () -> UIViewController
-    var webFactory: (String) -> UIViewController
-    var previewFactory: () -> QLPreviewController
-    var contactFactory: (Contact) -> UIViewController
-    var imagePickerFactory: () -> UIImagePickerController
-    var permissionFactory: () -> RequestPermissionController
-
-    public init(
-        retryFactory: @escaping () -> UIViewController,
-        webFactory: @escaping (String) -> UIViewController,
-        previewFactory: @escaping () -> QLPreviewController,
-        contactFactory: @escaping (Contact) -> UIViewController,
-        imagePickerFactory: @escaping () -> UIImagePickerController,
-        permissionFactory: @escaping () -> RequestPermissionController
-    ) {
-        self.webFactory = webFactory
-        self.retryFactory = retryFactory
-        self.previewFactory = previewFactory
-        self.contactFactory = contactFactory
-        self.permissionFactory = permissionFactory
-        self.imagePickerFactory = imagePickerFactory
-    }
-}
-
-public extension ChatCoordinator {
-    func toPreview(from parent: UIViewController) {
-        let screen = previewFactory()
-        screen.delegate = (parent as? QLPreviewControllerDelegate)
-        screen.dataSource = (parent as? QLPreviewControllerDataSource)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toLibrary(from parent: UIViewController) {
-        let screen = imagePickerFactory()
-        screen.delegate = (parent as? (UIImagePickerControllerDelegate & UINavigationControllerDelegate))
-        screen.allowsEditing = false
-        modalPresenter.present(screen, from: parent)
-    }
-
-    func toCamera(from parent: UIViewController) {
-        let screen = imagePickerFactory()
-        screen.delegate = (parent as? (UIImagePickerControllerDelegate & UINavigationControllerDelegate))
-        screen.sourceType = .camera
-        screen.allowsEditing = false
-        modalPresenter.present(screen, from: parent)
-    }
-
-    func toRetrySheet(from parent: UIViewController) {
-        let screen = retryFactory()
-        bottomPresenter.present(screen, from: parent)
-    }
-
-    func toContact(_ contact: Contact, from parent: UIViewController) {
-        let screen = contactFactory(contact)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toWebview(with urlString: String, from parent: UIViewController) {
-        let screen = webFactory(urlString)
-        modalPresenter.present(screen, from: parent)
-    }
-
-    func toPermission(type: PermissionType, from parent: UIViewController) {
-        let screen = permissionFactory()
-        screen.setup(type: type)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toMembersList(_ screen: UIViewController, from parent: UIViewController) {
-        bottomPresenter.present(screen, from: parent)
-    }
-
-    func toDrawer(_ drawer: UIViewController, from parent: UIViewController) {
-        bottomPresenter.present(drawer, from: parent)
-    }
-
-    func toMenuSheet(_ screen: UIViewController, from parent: UIViewController) {
-        bottomPresenter.present(screen, from: parent)
-    }
-}
diff --git a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
index 4b95f84bd3e3d68a85b5a75c49e813a2f4730e0e..5aa7c08abf32158141327036995b87021543c648 100644
--- a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
+++ b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
@@ -120,7 +120,7 @@ final class SingleChatViewModel: NSObject {
       .store(in: &cancellables)
     
     healthCancellable = messenger.cMix.get()!.addHealthCallback(.init(handle: { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       self.networkMonitor.update($0)
     }))
   }
@@ -362,7 +362,7 @@ final class SingleChatViewModel: NSObject {
     )
     
     DispatchQueue.global().async { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       
       do {
         message = try self.database.saveMessage(message)
diff --git a/Sources/ChatListFeature/Controller/ChatListController.swift b/Sources/ChatListFeature/Controller/ChatListController.swift
index 34c6fac7f659f1435d76ab904073de80ce971bb9..35768fd49fb5ed0d0cdb6f69859b16551f7648b0 100644
--- a/Sources/ChatListFeature/Controller/ChatListController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListController.swift
@@ -3,54 +3,55 @@ import Shared
 import Combine
 import XXModels
 import MenuFeature
+import XXNavigation
 import DependencyInjection
 
 public final class ChatListController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: ChatListCoordinating
-
+  
   private lazy var screenView = ChatListView()
   private lazy var topLeftView = ChatListTopLeftNavView()
   private lazy var topRightView = ChatListTopRightNavView()
   private lazy var tableController = ChatListTableController(viewModel)
   private lazy 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)
     }
   }
-
+  
   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()
@@ -58,64 +59,66 @@ public final class ChatListController: UIViewController {
     setupNavigationBar()
     setupRecentContacts()
   }
-
+  
   private func setupNavigationBar() {
     navigationItem.leftBarButtonItem = UIBarButtonItem(customView: topLeftView)
     navigationItem.rightBarButtonItem = UIBarButtonItem(customView: topRightView)
-
-    topRightView.actionPublisher
+    
+    topRightView
+      .actionPublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
         switch $0 {
         case .didTapSearch:
-          coordinator.toSearch(from: self)
+          navigator.perform(PresentSearch(replacing: false))
         case .didTapNewGroup:
-          coordinator.toNewGroup(from: self)
+          navigator.perform(PresentNewGroup())
         }
       }.store(in: &cancellables)
-
-    viewModel.badgeCountPublisher
+    
+    viewModel
+      .badgeCountPublisher
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in topLeftView.updateBadge($0) }
-      .store(in: &cancellables)
-
-    topLeftView.actionPublisher
+      .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)
+      .sink { [unowned self] in
+        navigator.perform(PresentMenu(currentItem: .chats))
+      }.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()
     }
-
     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
@@ -124,26 +127,30 @@ public final class ChatListController: UIViewController {
       cell.setup(title: title, image: contact.photo)
       return cell
     }
-
+    
     screenView.listContainerView.collectionView.delegate = self
     screenView.listContainerView.collectionView.dataSource = collectionDataSource
-
-    viewModel.recentsPublisher
+    
+    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
+    screenView
+      .searchView
       .rightPublisher
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in coordinator.toScan(from: self) }
-      .store(in: &cancellables)
-
-    screenView.searchView
+      .sink { [unowned self] in
+        navigator.perform(PresentScan())
+      }.store(in: &cancellables)
+    
+    screenView
+      .searchView
       .textPublisher
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
@@ -151,7 +158,7 @@ public final class ChatListController: UIViewController {
         viewModel.updateSearch(query: query)
         screenView.searchListContainerView.emptyView.updateSearched(content: query)
       }.store(in: &cancellables)
-
+    
     Publishers.CombineLatest(
       viewModel.searchPublisher,
       screenView.searchView.textPublisher.removeDuplicates()
@@ -164,30 +171,29 @@ public final class ChatListController: UIViewController {
         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
+    }.store(in: &cancellables)
+    
+    screenView
+      .searchView
       .isEditingPublisher
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in isEditingSearch = $0 }
-      .store(in: &cancellables)
-
-    viewModel.chatsPublisher
+      .sink { [unowned self] in
+        isEditingSearch = $0
+      }.store(in: &cancellables)
+    
+    viewModel
+      .chatsPublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
         guard $0.isEmpty == false else {
@@ -195,30 +201,36 @@ public final class ChatListController: UIViewController {
           screenView.listContainerView.emptyView.isHidden = false
           return
         }
-
         screenView.listContainerView.bringSubviewToFront(tableController.view)
         screenView.listContainerView.emptyView.isHidden = true
-      }
-      .store(in: &cancellables)
-
-    screenView.searchListContainerView
-      .emptyView.searchButton
+      }.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
+      .sink { [unowned self] in
+        navigator.perform(PresentSearch(replacing: false))
+      }.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
+      .sink { [unowned self] in
+        navigator.perform(PresentContactList())
+      }.store(in: &cancellables)
+    
+    viewModel
+      .isOnline
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
-      .sink { [weak screenView] connected in screenView?.showConnectingBanner(!connected) }
-      .store(in: &cancellables)
+      .sink { [weak screenView] connected in
+        screenView?.showConnectingBanner(!connected)
+      }.store(in: &cancellables)
   }
 }
 
@@ -228,7 +240,7 @@ extension ChatListController: UICollectionViewDelegate {
     didSelectItemAt indexPath: IndexPath
   ) {
     if let contact = collectionDataSource.itemIdentifier(for: indexPath) {
-      coordinator.toSingleChat(with: contact, from: self)
+      navigator.perform(PresentChat(contact: contact))
     }
   }
 }
diff --git a/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift b/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift
index c1651f2668c2a0dee962cc43511e88d58e47cc77..3ea3a7825fdce9140fe4d6a3b0279a603a5d6d26 100644
--- a/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift
@@ -1,128 +1,126 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import DependencyInjection
 
 class ChatSearchListTableViewDiffableDataSource: UITableViewDiffableDataSource<SearchSection, SearchItem> {
-    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
-        switch snapshot().sectionIdentifiers[section] {
-        case .chats:
-            return "CHATS"
-        case .connections:
-            return "CONNECTIONS"
-        }
+  override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
+    switch snapshot().sectionIdentifiers[section] {
+    case .chats:
+      return "CHATS"
+    case .connections:
+      return "CONNECTIONS"
     }
+  }
 }
 
 final class ChatSearchTableController: UITableViewController {
-    @Dependency private var coordinator: ChatListCoordinating
-
-    private let viewModel: ChatListViewModel
-    private let cellHeight: CGFloat = 83.0
-    private var cancellables = Set<AnyCancellable>()
-    private var tableDataSource: ChatSearchListTableViewDiffableDataSource?
-
-    init(_ viewModel: ChatListViewModel) {
-        self.viewModel = viewModel
-        super.init(style: .grouped)
-
-        tableDataSource = ChatSearchListTableViewDiffableDataSource(
-            tableView: tableView
-        ) { table, indexPath, item in
-            let cell = table.dequeueReusableCell(forIndexPath: indexPath, ofType: ChatListCell.self)
-            switch item {
-            case .chat(let info):
-                switch info {
-                case .group(let group):
-                    cell.setupGroup(
-                        name: group.name,
-                        date: group.createdAt,
-                        preview: nil,
-                        unreadCount: 0
-                    )
-
-                case .groupChat(let groupChatInfo):
-                    cell.setupGroup(
-                        name: groupChatInfo.group.name,
-                        date: groupChatInfo.lastMessage.date,
-                        preview: groupChatInfo.lastMessage.text,
-                        unreadCount: groupChatInfo.unreadCount
-                    )
-
-                case .contactChat(let contactChatInfo):
-                    cell.setupContact(
-                        name: (contactChatInfo.contact.nickname ?? contactChatInfo.contact.username) ?? "",
-                        image: contactChatInfo.contact.photo,
-                        date: contactChatInfo.lastMessage.date,
-                        unreadCount: contactChatInfo.unreadCount,
-                        preview: contactChatInfo.lastMessage.text
-                    )
-                }
-
-            case .connection(let contact):
-                cell.setupContact(
-                    name: (contact.nickname ?? contact.username) ?? "",
-                    image: contact.photo,
-                    date: nil,
-                    unreadCount: 0,
-                    preview: contact.username ?? ""
-                )
-            }
-
-            return cell
+  @Dependency var navigator: Navigator
+
+  private let viewModel: ChatListViewModel
+  private let cellHeight: CGFloat = 83.0
+  private var cancellables = Set<AnyCancellable>()
+  private var tableDataSource: ChatSearchListTableViewDiffableDataSource?
+  
+  init(_ viewModel: ChatListViewModel) {
+    self.viewModel = viewModel
+    super.init(style: .grouped)
+    
+    tableDataSource = ChatSearchListTableViewDiffableDataSource(
+      tableView: tableView
+    ) { table, indexPath, item in
+      let cell = table.dequeueReusableCell(forIndexPath: indexPath, ofType: ChatListCell.self)
+      switch item {
+      case .chat(let info):
+        switch info {
+        case .group(let group):
+          cell.setupGroup(
+            name: group.name,
+            date: group.createdAt,
+            preview: nil,
+            unreadCount: 0
+          )
+          
+        case .groupChat(let groupChatInfo):
+          cell.setupGroup(
+            name: groupChatInfo.group.name,
+            date: groupChatInfo.lastMessage.date,
+            preview: groupChatInfo.lastMessage.text,
+            unreadCount: groupChatInfo.unreadCount
+          )
+          
+        case .contactChat(let contactChatInfo):
+          cell.setupContact(
+            name: (contactChatInfo.contact.nickname ?? contactChatInfo.contact.username) ?? "",
+            image: contactChatInfo.contact.photo,
+            date: contactChatInfo.lastMessage.date,
+            unreadCount: contactChatInfo.unreadCount,
+            preview: contactChatInfo.lastMessage.text
+          )
         }
+        
+      case .connection(let contact):
+        cell.setupContact(
+          name: (contact.nickname ?? contact.username) ?? "",
+          image: contact.photo,
+          date: nil,
+          unreadCount: 0,
+          preview: contact.username ?? ""
+        )
+      }
+      
+      return cell
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-
-        tableView.separatorStyle = .none
-        tableView.tableFooterView = UIView()
-        tableView.sectionIndexColor = .blue
-        tableView.register(ChatListCell.self)
-        tableView.dataSource = tableDataSource
-        view.backgroundColor = Asset.neutralWhite.color
-
-        viewModel.searchPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in tableDataSource?.apply($0, animatingDifferences: false) }
-            .store(in: &cancellables)
-    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    
+    tableView.separatorStyle = .none
+    tableView.tableFooterView = UIView()
+    tableView.sectionIndexColor = .blue
+    tableView.register(ChatListCell.self)
+    tableView.dataSource = tableDataSource
+    view.backgroundColor = Asset.neutralWhite.color
+    
+    viewModel.searchPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in tableDataSource?.apply($0, animatingDifferences: false) }
+      .store(in: &cancellables)
+  }
 }
 
 extension ChatSearchTableController {
-    override func tableView(
-        _ tableView: UITableView,
-        heightForRowAt: IndexPath
-    ) -> CGFloat {
-        return cellHeight
-    }
-
-    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        if let item = tableDataSource?.itemIdentifier(for: indexPath) {
-            switch item {
-            case .chat(let chatInfo):
-                switch chatInfo {
-                case .group(let group):
-                    if let groupInfo = viewModel.groupInfo(from: group) {
-                        coordinator.toGroupChat(with: groupInfo, from: self)
-                    }
-
-                case .groupChat(let info):
-                    if let groupInfo = viewModel.groupInfo(from: info.group) {
-                        coordinator.toGroupChat(with: groupInfo, from: self)
-                    }
-
-                case .contactChat(let info):
-                    guard info.contact.authStatus == .friend else { return }
-                    coordinator.toSingleChat(with: info.contact, from: self)
-                }
-
-            case .connection(let contact):
-                coordinator.toContact(contact, from: self)
-            }
+  override func tableView(
+    _ tableView: UITableView,
+    heightForRowAt: IndexPath
+  ) -> CGFloat {
+    return cellHeight
+  }
+  
+  override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+    if let item = tableDataSource?.itemIdentifier(for: indexPath) {
+      switch item {
+      case .chat(let chatInfo):
+        switch chatInfo {
+        case .group(let group):
+          if let groupInfo = viewModel.groupInfo(from: group) {
+            navigator.perform(PresentGroupChat(model: groupInfo))
+          }
+        case .groupChat(let info):
+          if let groupInfo = viewModel.groupInfo(from: info.group) {
+            navigator.perform(PresentGroupChat(model: groupInfo))
+          }
+        case .contactChat(let info):
+          guard info.contact.authStatus == .friend else { return }
+          navigator.perform(PresentChat(contact: info.contact))
         }
+      case .connection(let contact):
+        navigator.perform(PresentContact(contact: contact))
+      }
     }
+  }
 }
diff --git a/Sources/ChatListFeature/Controller/ChatListSheetController.swift b/Sources/ChatListFeature/Controller/ChatListSheetController.swift
index 79ad33eb198d177dee3618d27f4f455d6f1d94fc..6b0d2d1d1c2a1754f02a4efb4b1ac8d6631c7a2a 100644
--- a/Sources/ChatListFeature/Controller/ChatListSheetController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListSheetController.swift
@@ -2,41 +2,46 @@ import UIKit
 import Combine
 
 public final class ChatListSheetController: UIViewController {
-    public enum Action {
-        case delete
-        case deleteAll
-    }
-
-    private lazy var screenView = ChatListMenuView()
-
-    var didChooseAction: (Action) -> Void
-    private var cancellables = Set<AnyCancellable>()
-
-    public init(_ didChooseAction: @escaping ChatListSheetClosure) {
-        self.didChooseAction = didChooseAction
-        super.init(nibName: nil, bundle: nil)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func loadView() {
-        view = screenView
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupBindings()
-    }
-
-    private func setupBindings() {
-        screenView.deleteButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in dismiss(animated: true) { [weak self] in self?.didChooseAction(.delete) }}
-            .store(in: &cancellables)
-
-        screenView.deleteAllButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in dismiss(animated: true) { [weak self] in self?.didChooseAction(.deleteAll) }}
-            .store(in: &cancellables)
-    }
+  private lazy var screenView = ChatListMenuView()
+  
+  private let didTapDelete: () -> Void
+  private let didTapDeleteAll: () -> Void
+  private var cancellables = Set<AnyCancellable>()
+  
+  public init(
+    _ didTapDelete: @escaping () -> Void,
+    _ didTapDeleteAll: @escaping () -> Void
+  ) {
+    self.didTapDelete = didTapDelete
+    self.didTapDeleteAll = didTapDeleteAll
+    super.init(nibName: nil, bundle: nil)
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  public override func loadView() {
+    view = screenView
+  }
+  
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+
+    screenView
+      .deleteButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak self] in
+          self?.didTapDelete()
+        }
+      }.store(in: &cancellables)
+
+    screenView
+      .deleteAllButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        dismiss(animated: true) { [weak self] in
+          self?.didTapDeleteAll()
+        }
+      }.store(in: &cancellables)
+  }
 }
diff --git a/Sources/ChatListFeature/Controller/ChatListTableController.swift b/Sources/ChatListFeature/Controller/ChatListTableController.swift
index ed8bd0e9bcf323ee00ba46155ad2e5fc417ac626..744b95cccbb4550af20551cca7331f330d210dd1 100644
--- a/Sources/ChatListFeature/Controller/ChatListTableController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListTableController.swift
@@ -2,206 +2,206 @@ import UIKit
 import Shared
 import Combine
 import XXModels
+import XXNavigation
 import DifferenceKit
 import DrawerFeature
 import DependencyInjection
 
 extension ChatInfo: Differentiable {
-    public var differenceIdentifier: ChatInfo.ID { id }
+  public var differenceIdentifier: ChatInfo.ID { id }
 }
 
 final class ChatListTableController: UITableViewController {
-    @Dependency private var coordinator: ChatListCoordinating
-
-    private var rows = [ChatInfo]()
-    private let viewModel: ChatListViewModel
-    private let cellHeight: CGFloat = 83.0
-    private var cancellables = Set<AnyCancellable>()
-    private var drawerCancellables = Set<AnyCancellable>()
-
-    init(_ viewModel: ChatListViewModel) {
-        self.viewModel = viewModel
-        super.init(style: .grouped)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-
-        tableView.separatorStyle = .none
-        tableView.backgroundColor = .clear
-        tableView.alwaysBounceVertical = true
-        tableView.register(ChatListCell.self)
-        tableView.tableFooterView = UIView()
-
-        viewModel
-            .chatsPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                guard !self.rows.isEmpty else {
-                    self.rows = $0
-                    tableView.reloadData()
-                    return
-                }
-
-                self.tableView.reload(
-                    using: StagedChangeset(source: self.rows, target: $0),
-                    deleteSectionsAnimation: .automatic,
-                    insertSectionsAnimation: .automatic,
-                    reloadSectionsAnimation: .none,
-                    deleteRowsAnimation: .automatic,
-                    insertRowsAnimation: .automatic,
-                    reloadRowsAnimation: .none
-                ) { [unowned self] in
-                    self.rows = $0
-                }
-            }.store(in: &cancellables)
-    }
+  @Dependency var navigator: Navigator
+
+  private var rows = [ChatInfo]()
+  private let viewModel: ChatListViewModel
+  private let cellHeight: CGFloat = 83.0
+  private var cancellables = Set<AnyCancellable>()
+  private var drawerCancellables = Set<AnyCancellable>()
+  
+  init(_ viewModel: ChatListViewModel) {
+    self.viewModel = viewModel
+    super.init(style: .grouped)
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    
+    tableView.separatorStyle = .none
+    tableView.backgroundColor = .clear
+    tableView.alwaysBounceVertical = true
+    tableView.register(ChatListCell.self)
+    tableView.tableFooterView = UIView()
+    
+    viewModel
+      .chatsPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        guard !self.rows.isEmpty else {
+          self.rows = $0
+          tableView.reloadData()
+          return
+        }
+        
+        self.tableView.reload(
+          using: StagedChangeset(source: self.rows, target: $0),
+          deleteSectionsAnimation: .automatic,
+          insertSectionsAnimation: .automatic,
+          reloadSectionsAnimation: .none,
+          deleteRowsAnimation: .automatic,
+          insertRowsAnimation: .automatic,
+          reloadRowsAnimation: .none
+        ) { [unowned self] in
+          self.rows = $0
+        }
+      }.store(in: &cancellables)
+  }
 }
 
 extension ChatListTableController {
-    override func tableView(
-        _ tableView: UITableView,
-        numberOfRowsInSection: Int
-    ) -> Int {
-        return rows.count
+  override func tableView(
+    _ tableView: UITableView,
+    numberOfRowsInSection: Int
+  ) -> Int {
+    return rows.count
+  }
+  
+  override func tableView(
+    _ tableView: UITableView,
+    heightForRowAt: IndexPath
+  ) -> CGFloat {
+    return cellHeight
+  }
+  
+  override func tableView(
+    _ tableView: UITableView,
+    trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath
+  ) -> UISwipeActionsConfiguration? {
+    
+    let delete = UIContextualAction(style: .normal, title: nil) { [weak self] _, _, complete in
+      guard let self else { return }
+      self.didRequestDeletionOf(self.rows[indexPath.row])
+      complete(true)
     }
-
-    override func tableView(
-        _ tableView: UITableView,
-        heightForRowAt: IndexPath
-    ) -> CGFloat {
-        return cellHeight
+    
+    delete.image = Asset.chatListDeleteSwipe.image
+    delete.backgroundColor = Asset.accentDanger.color
+    return UISwipeActionsConfiguration(actions: [delete])
+  }
+  
+  override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+    switch rows[indexPath.row] {
+    case .group(let group):
+      if let groupInfo = viewModel.groupInfo(from: group) {
+        navigator.perform(PresentGroupChat(model: groupInfo))
+      }
+    case .groupChat(let info):
+      if let groupInfo = viewModel.groupInfo(from: info.group) {
+        navigator.perform(PresentGroupChat(model: groupInfo))
+      }
+    case .contactChat(let info):
+      guard info.contact.authStatus == .friend else { return }
+      navigator.perform(PresentChat(contact: info.contact))
     }
-
-    override func tableView(
-        _ tableView: UITableView,
-        trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath
-    ) -> UISwipeActionsConfiguration? {
-
-        let delete = UIContextualAction(style: .normal, title: nil) { [weak self] _, _, complete in
-            guard let self = self else { return }
-            self.didRequestDeletionOf(self.rows[indexPath.row])
-            complete(true)
-        }
-
-        delete.image = Asset.chatListDeleteSwipe.image
-        delete.backgroundColor = Asset.accentDanger.color
-        return UISwipeActionsConfiguration(actions: [delete])
+  }
+  
+  override func tableView(
+    _ tableView: UITableView,
+    cellForRowAt indexPath: IndexPath
+  ) -> UITableViewCell {
+    
+    let cell = tableView.dequeueReusableCell(forIndexPath: indexPath, ofType: ChatListCell.self)
+    
+    switch rows[indexPath.row] {
+    case .group(let group):
+      cell.setupGroup(
+        name: group.name,
+        date: group.createdAt,
+        preview: nil,
+        unreadCount: 0
+      )
+      
+    case .groupChat(let info):
+      cell.setupGroup(
+        name: info.group.name,
+        date: info.lastMessage.date,
+        preview: info.lastMessage.text,
+        unreadCount: info.unreadCount
+      )
+      
+    case .contactChat(let info):
+      cell.setupContact(
+        name: (info.contact.nickname ?? info.contact.username) ?? "",
+        image: info.contact.photo,
+        date: info.lastMessage.date,
+        unreadCount: info.unreadCount,
+        preview: info.lastMessage.text
+      )
     }
-
-    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        switch rows[indexPath.row] {
-        case .group(let group):
-            if let groupInfo = viewModel.groupInfo(from: group) {
-                coordinator.toGroupChat(with: groupInfo, from: self)
-            }
-
-        case .groupChat(let info):
-            if let groupInfo = viewModel.groupInfo(from: info.group) {
-                coordinator.toGroupChat(with: groupInfo, from: self)
-            }
-
-        case .contactChat(let info):
-            guard info.contact.authStatus == .friend else { return }
-            coordinator.toSingleChat(with: info.contact, from: self)
-        }
-    }
-
-    override func tableView(
-        _ tableView: UITableView,
-        cellForRowAt indexPath: IndexPath
-    ) -> UITableViewCell {
-
-        let cell = tableView.dequeueReusableCell(forIndexPath: indexPath, ofType: ChatListCell.self)
-
-        switch rows[indexPath.row] {
-        case .group(let group):
-            cell.setupGroup(
-                name: group.name,
-                date: group.createdAt,
-                preview: nil,
-                unreadCount: 0
-            )
-
-        case .groupChat(let info):
-            cell.setupGroup(
-                name: info.group.name,
-                date: info.lastMessage.date,
-                preview: info.lastMessage.text,
-                unreadCount: info.unreadCount
-            )
-
-        case .contactChat(let info):
-            cell.setupContact(
-                name: (info.contact.nickname ?? info.contact.username) ?? "",
-                image: info.contact.photo,
-                date: info.lastMessage.date,
-                unreadCount: info.unreadCount,
-                preview: info.lastMessage.text
-            )
-        }
-
-        return cell
+    
+    return cell
+  }
+  
+  private func didRequestDeletionOf(_ item: ChatInfo) {
+    let title: String
+    let subtitle: String
+    let actionTitle: String
+    let actionClosure: () -> Void
+    
+    switch item {
+    case .group(let group):
+      title = Localized.ChatList.DeleteGroup.title
+      subtitle = Localized.ChatList.DeleteGroup.subtitle
+      actionTitle = Localized.ChatList.DeleteGroup.action
+      actionClosure = { [weak viewModel] in viewModel?.leave(group) }
+      
+    case .contactChat(let info):
+      title = Localized.ChatList.Delete.title
+      subtitle = Localized.ChatList.Delete.subtitle
+      actionTitle = Localized.ChatList.Delete.delete
+      actionClosure = { [weak viewModel] in viewModel?.clear(info.contact) }
+      
+    case .groupChat(let info):
+      title = Localized.ChatList.DeleteGroup.title
+      subtitle = Localized.ChatList.DeleteGroup.subtitle
+      actionTitle = Localized.ChatList.DeleteGroup.action
+      actionClosure = { [weak viewModel] in viewModel?.leave(info.group) }
     }
-
-    private func didRequestDeletionOf(_ item: ChatInfo) {
-        let title: String
-        let subtitle: String
-        let actionTitle: String
-        let actionClosure: () -> Void
-
-        switch item {
-        case .group(let group):
-            title = Localized.ChatList.DeleteGroup.title
-            subtitle = Localized.ChatList.DeleteGroup.subtitle
-            actionTitle = Localized.ChatList.DeleteGroup.action
-            actionClosure = { [weak viewModel] in viewModel?.leave(group) }
-
-        case .contactChat(let info):
-            title = Localized.ChatList.Delete.title
-            subtitle = Localized.ChatList.Delete.subtitle
-            actionTitle = Localized.ChatList.Delete.delete
-            actionClosure = { [weak viewModel] in viewModel?.clear(info.contact) }
-
-        case .groupChat(let info):
-            title = Localized.ChatList.DeleteGroup.title
-            subtitle = Localized.ChatList.DeleteGroup.subtitle
-            actionTitle = Localized.ChatList.DeleteGroup.action
-            actionClosure = { [weak viewModel] in viewModel?.leave(info.group) }
+    
+    let actionButton = DrawerCapsuleButton(
+      model: .init(title: actionTitle, style: .red)
+    )
+
+    actionButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) {
+          self.drawerCancellables.removeAll()
+          actionClosure()
         }
-
-        let actionButton = DrawerCapsuleButton(model: .init(title: actionTitle, style: .red))
-
-        let drawer = DrawerController([
-            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()
-                    actionClosure()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
+      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
+    ]))
+  }
 }
diff --git a/Sources/ChatListFeature/Coordinator/ChatListCoordinator.swift b/Sources/ChatListFeature/Coordinator/ChatListCoordinator.swift
deleted file mode 100644
index 57f94bb3ad0e3d07ebf4781549b6762c14d17c35..0000000000000000000000000000000000000000
--- a/Sources/ChatListFeature/Coordinator/ChatListCoordinator.swift
+++ /dev/null
@@ -1,102 +0,0 @@
-import UIKit
-import Shared
-import XXModels
-import MenuFeature
-import ChatFeature
-import Presentation
-
-public typealias ChatListSheetClosure = (ChatListSheetController.Action) -> Void
-
-public protocol ChatListCoordinating {
-    func toScan(from: UIViewController)
-    func toSearch(from: UIViewController)
-    func toContacts(from: UIViewController)
-    func toNewGroup(from: UIViewController)
-    func toSideMenu(from: UIViewController)
-    func toContact(_: Contact, from: UIViewController)
-    func toSingleChat(with: Contact, from: UIViewController)
-    func toDrawer(_: UIViewController, from: UIViewController)
-    func toGroupChat(with: GroupInfo, from: UIViewController)
-}
-
-public struct ChatListCoordinator: ChatListCoordinating {
-    var pushPresenter: Presenting = PushPresenter()
-    var modalPresenter: Presenting = ModalPresenter()
-    var sidePresenter: Presenting = SideMenuPresenter()
-    var bottomPresenter: Presenting = BottomPresenter()
-
-    var scanFactory: () -> UIViewController
-    var searchFactory: (String?) -> UIViewController
-    var newGroupFactory: () -> UIViewController
-    var contactsFactory: () -> UIViewController
-    var contactFactory: (Contact) -> UIViewController
-    var singleChatFactory: (Contact) -> UIViewController
-    var groupChatFactory: (GroupInfo) -> UIViewController
-    var sideMenuFactory: (MenuItem, UIViewController) -> UIViewController
-
-    public init(
-        scanFactory: @escaping () -> UIViewController,
-        searchFactory: @escaping (String?) -> UIViewController,
-        newGroupFactory: @escaping () -> UIViewController,
-        contactsFactory: @escaping () -> UIViewController,
-        contactFactory: @escaping (Contact) -> UIViewController,
-        singleChatFactory: @escaping (Contact) -> UIViewController,
-        groupChatFactory: @escaping (GroupInfo) -> UIViewController,
-        sideMenuFactory: @escaping (MenuItem, UIViewController) -> UIViewController
-    ) {
-        self.scanFactory = scanFactory
-        self.searchFactory = searchFactory
-        self.contactFactory = contactFactory
-        self.newGroupFactory = newGroupFactory
-        self.contactsFactory = contactsFactory
-        self.sideMenuFactory = sideMenuFactory
-        self.groupChatFactory = groupChatFactory
-        self.singleChatFactory = singleChatFactory
-    }
-}
-
-public extension ChatListCoordinator {
-    func toSearch(from parent: UIViewController) {
-        let screen = searchFactory(nil)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toScan(from parent: UIViewController) {
-        let screen = scanFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toContacts(from parent: UIViewController) {
-        let screen = contactsFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toContact(_ contact: Contact, from parent: UIViewController) {
-        let screen = contactFactory(contact)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toSingleChat(with contact: Contact, from parent: UIViewController) {
-        let screen = singleChatFactory(contact)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toGroupChat(with group: GroupInfo, from parent: UIViewController) {
-        let screen = groupChatFactory(group)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toSideMenu(from parent: UIViewController) {
-        let screen = sideMenuFactory(.chats, parent)
-        sidePresenter.present(screen, from: parent)
-    }
-
-    func toNewGroup(from parent: UIViewController) {
-        let screen = newGroupFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toDrawer(_ drawer: UIViewController, from parent: UIViewController) {
-        bottomPresenter.present(drawer, from: parent)
-    }
-}
diff --git a/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift b/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift
index 3792e0c14aebb66f4229c6d246d9cfe22cc9f379..f9214da7daf4627883032d5c9eb3a476d9d6de33 100644
--- a/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift
+++ b/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift
@@ -29,20 +29,20 @@ final class ChatListViewModel {
   @Dependency var groupManager: GroupChat
   @Dependency var hudController: HUDController
   @Dependency var reportingStatus: ReportingStatus
-
+  
   // TO REFACTOR:
   var isOnline: AnyPublisher<Bool, Never> {
     Just(.init(true)).eraseToAnyPublisher()
   }
-
+  
   var myId: Data {
     try! messenger.e2e.get()!.getContact().getId()
   }
-
+  
   var chatsPublisher: AnyPublisher<[ChatInfo], Never> {
     chatsSubject.eraseToAnyPublisher()
   }
-
+  
   var recentsPublisher: AnyPublisher<RecentsSnapshot, Never> {
     let query = Contact.Query(
       authStatus: [.friend],
@@ -50,7 +50,7 @@ final class ChatListViewModel {
       isBlocked: reportingStatus.isEnabled() ? false : nil,
       isBanned: reportingStatus.isEnabled() ? false : nil
     )
-
+    
     return database.fetchContactsPublisher(query)
       .replaceError(with: [])
       .map {
@@ -61,13 +61,13 @@ final class ChatListViewModel {
         return snapshot
       }.eraseToAnyPublisher()
   }
-
+  
   var searchPublisher: AnyPublisher<SearchSnapshot, Never> {
     let contactsQuery = Contact.Query(
       isBlocked: reportingStatus.isEnabled() ? false : nil,
       isBanned: reportingStatus.isEnabled() ? false : nil
     )
-
+    
     return Publishers.CombineLatest3(
       database.fetchContactsPublisher(contactsQuery)
         .replaceError(with: [])
@@ -84,42 +84,42 @@ final class ChatListViewModel {
         let nickname = $0.nickname?.lowercased().contains(query.lowercased()) ?? false
         return username || nickname
       }.map(SearchItem.connection)
-
+      
       let chatItems = chats.filter {
         switch $0 {
         case .group(let group):
           return group.name.lowercased().contains(query.lowercased())
-
+          
         case .groupChat(let info):
           let name = info.group.name.lowercased().contains(query.lowercased())
           let last = info.lastMessage.text.lowercased().contains(query.lowercased())
           return name || last
-
+          
         case .contactChat(let info):
           let username = info.contact.username?.lowercased().contains(query.lowercased()) ?? false
           let nickname = info.contact.nickname?.lowercased().contains(query.lowercased()) ?? false
           let lastMessage = info.lastMessage.text.lowercased().contains(query.lowercased())
           return username || nickname || lastMessage
-
+          
         }
       }.map(SearchItem.chat)
-
+      
       var snapshot = SearchSnapshot()
-
+      
       if connectionItems.count > 0 {
         snapshot.appendSections([.connections])
         snapshot.appendItems(connectionItems, toSection: .connections)
       }
-
+      
       if chatItems.count > 0 {
         snapshot.appendSections([.chats])
         snapshot.appendItems(chatItems, toSection: .chats)
       }
-
+      
       return snapshot
     }.eraseToAnyPublisher()
   }
-
+  
   var badgeCountPublisher: AnyPublisher<Int, Never> {
     let groupQuery = Group.Query(authStatus: [.pending])
     let contactsQuery = Contact.Query(
@@ -133,7 +133,7 @@ final class ChatListViewModel {
       isBlocked: reportingStatus.isEnabled() ? false : nil,
       isBanned: reportingStatus.isEnabled() ? false : nil
     )
-
+    
     return Publishers.CombineLatest(
       database.fetchContactsPublisher(contactsQuery).replaceError(with: []),
       database.fetchGroupsPublisher(groupQuery).replaceError(with: [])
@@ -141,11 +141,11 @@ final class ChatListViewModel {
     .map { $0.0.count + $0.1.count }
     .eraseToAnyPublisher()
   }
-
+  
   private var cancellables = Set<AnyCancellable>()
   private let searchSubject = CurrentValueSubject<String, Never>("")
   private let chatsSubject = CurrentValueSubject<[ChatInfo], Never>([])
-
+  
   init() {
     database.fetchChatInfosPublisher(
       ChatInfo.Query(
@@ -168,14 +168,14 @@ final class ChatListViewModel {
     .sink { [unowned self] in chatsSubject.send($0) }
     .store(in: &cancellables)
   }
-
+  
   func updateSearch(query: String) {
     searchSubject.send(query)
   }
-
+  
   func leave(_ group: Group) {
     hudController.show()
-
+    
     do {
       try groupManager.leaveGroup(groupId: group.id)
       try database.deleteMessages(.init(chat: .group(group.id)))
@@ -185,17 +185,17 @@ final class ChatListViewModel {
       hudController.show(.init(error: error))
     }
   }
-
+  
   func clear(_ contact: XXModels.Contact) {
     _ = try? database.deleteMessages(.init(chat: .direct(myId, contact.id)))
   }
-
+  
   func groupInfo(from group: Group) -> GroupInfo? {
     let query = GroupInfo.Query(groupId: group.id)
     guard let info = try? database.fetchGroupInfos(query).first else {
       return nil
     }
-
+    
     return info
   }
 }
diff --git a/Sources/ChatListFeature/Views/ChatListCell.swift b/Sources/ChatListFeature/Views/ChatListCell.swift
index bb455395abbc36921e364b27a5ca07e573726ea3..e097c7fc6c3731d78c76fbbab9a58cdfb6548b64 100644
--- a/Sources/ChatListFeature/Views/ChatListCell.swift
+++ b/Sources/ChatListFeature/Views/ChatListCell.swift
@@ -2,156 +2,156 @@ import UIKit
 import Shared
 
 final class ChatListCell: UITableViewCell {
-    private let titleLabel = UILabel()
-    private let unreadView = UIView()
-    private let unreadCountLabel = UILabel()
-    private let previewLabel = UILabel()
-    private let dateLabel = UILabel()
-    private let avatarView = AvatarView()
-    private var lastDate: Date? {
-        didSet { updateTimeAgoLabel() }
+  let titleLabel = UILabel()
+  let unreadView = UIView()
+  let unreadCountLabel = UILabel()
+  let previewLabel = UILabel()
+  let dateLabel = UILabel()
+  let avatarView = AvatarView()
+  var lastDate: Date? {
+    didSet { updateTimeAgoLabel() }
+  }
+  
+  private var timer: Timer?
+  
+  deinit { timer?.invalidate() }
+  
+  override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+    super.init(style: style, reuseIdentifier: reuseIdentifier)
+    
+    previewLabel.numberOfLines = 2
+    dateLabel.textAlignment = .right
+    
+    unreadView.layer.cornerRadius = 8
+    avatarView.layer.cornerRadius = 21
+    avatarView.layer.masksToBounds = true
+    
+    dateLabel.textAlignment = .right
+    selectedBackgroundView = UIView()
+    unreadView.backgroundColor = .clear
+    backgroundColor = Asset.neutralWhite.color
+    dateLabel.textColor = Asset.neutralWeak.color
+    titleLabel.textColor = Asset.neutralActive.color
+    unreadCountLabel.textColor = Asset.neutralWhite.color
+    
+    dateLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
+    unreadCountLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
+    
+    timer = Timer.scheduledTimer(withTimeInterval: 59, repeats: true) { [weak self] _ in
+      self?.updateTimeAgoLabel()
     }
-
-    private var timer: Timer?
-
-    deinit { timer?.invalidate() }
-
-    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
-        super.init(style: style, reuseIdentifier: reuseIdentifier)
-
-        previewLabel.numberOfLines = 2
-        dateLabel.textAlignment = .right
-
-        unreadView.layer.cornerRadius = 8
-        avatarView.layer.cornerRadius = 21
-        avatarView.layer.masksToBounds = true
-
-        dateLabel.textAlignment = .right
-        selectedBackgroundView = UIView()
-        unreadView.backgroundColor = .clear
-        backgroundColor = Asset.neutralWhite.color
-        dateLabel.textColor = Asset.neutralWeak.color
-        titleLabel.textColor = Asset.neutralActive.color
-        unreadCountLabel.textColor = Asset.neutralWhite.color
-
-        dateLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
-        unreadCountLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
-
-        timer = Timer.scheduledTimer(withTimeInterval: 59, repeats: true) { [weak self] _ in
-            self?.updateTimeAgoLabel()
-        }
-
-        dateLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
-
-        contentView.addSubview(titleLabel)
-        contentView.addSubview(unreadView)
-        contentView.addSubview(avatarView)
-        contentView.addSubview(previewLabel)
-        contentView.addSubview(dateLabel)
-        unreadView.addSubview(unreadCountLabel)
-
-        avatarView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(14)
-            $0.left.equalToSuperview().offset(24)
-            $0.width.height.equalTo(48)
-        }
-
-        unreadCountLabel.snp.makeConstraints {
-            $0.center.equalToSuperview()
-        }
-
-        titleLabel.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(10)
-            $0.left.equalTo(avatarView.snp.right).offset(16)
-            $0.right.lessThanOrEqualTo(dateLabel.snp.left).offset(-10)
-        }
-
-        dateLabel.snp.makeConstraints {
-            $0.top.equalTo(titleLabel)
-            $0.right.equalToSuperview().offset(-25)
-        }
-
-        previewLabel.snp.makeConstraints {
-            $0.left.equalTo(titleLabel)
-            $0.top.equalTo(titleLabel.snp.bottom).offset(2)
-            $0.right.lessThanOrEqualTo(unreadView.snp.left).offset(-3)
-            $0.bottom.lessThanOrEqualToSuperview().offset(-10)
-        }
-
-        unreadView.snp.makeConstraints {
-            $0.right.equalTo(dateLabel)
-            $0.centerY.equalTo(previewLabel)
-            $0.width.height.equalTo(20)
-        }
+    
+    dateLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
+    
+    contentView.addSubview(titleLabel)
+    contentView.addSubview(unreadView)
+    contentView.addSubview(avatarView)
+    contentView.addSubview(previewLabel)
+    contentView.addSubview(dateLabel)
+    unreadView.addSubview(unreadCountLabel)
+    
+    avatarView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(14)
+      $0.left.equalToSuperview().offset(24)
+      $0.width.height.equalTo(48)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    override func prepareForReuse() {
-        super.prepareForReuse()
-        lastDate = nil
-        titleLabel.text = nil
-        unreadCountLabel.text = nil
-        previewLabel.attributedText = nil
-        avatarView.prepareForReuse()
+    
+    unreadCountLabel.snp.makeConstraints {
+      $0.center.equalToSuperview()
     }
-
-    private func updateTimeAgoLabel() {
-        if let date = lastDate {
-            dateLabel.text = date.asRelativeFromNow()
-        }
+    
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(10)
+      $0.left.equalTo(avatarView.snp.right).offset(16)
+      $0.right.lessThanOrEqualTo(dateLabel.snp.left).offset(-10)
     }
-
-    func setupContact(
-        name: String,
-        image: Data?,
-        date: Date?,
-        unreadCount: Int,
-        preview: String
-    ) {
-        titleLabel.text = name
-        setPreview(string: preview)
-        avatarView.setupProfile(title: name, image: image, size: .large)
-        unreadCountLabel.text = "\(unreadCount)"
-        unreadView.backgroundColor = unreadCount > 0 ? Asset.brandPrimary.color : .clear
-
-        if let date = date {
-            lastDate = date
-        } else {
-            dateLabel.text = nil
-        }
+    
+    dateLabel.snp.makeConstraints {
+      $0.top.equalTo(titleLabel)
+      $0.right.equalToSuperview().offset(-25)
     }
-
-    func setupGroup(
-        name: String,
-        date: Date,
-        preview: String?,
-        unreadCount: Int
-    ) {
-        lastDate = date
-        titleLabel.text = name
-        setPreview(string: preview)
-        avatarView.setupGroup(size: .large)
-        unreadCountLabel.text = "\(unreadCount)"
-        unreadView.backgroundColor = unreadCount > 0 ? Asset.brandPrimary.color : .clear
+    
+    previewLabel.snp.makeConstraints {
+      $0.left.equalTo(titleLabel)
+      $0.top.equalTo(titleLabel.snp.bottom).offset(2)
+      $0.right.lessThanOrEqualTo(unreadView.snp.left).offset(-3)
+      $0.bottom.lessThanOrEqualToSuperview().offset(-10)
     }
-
-    private func setPreview(string: String?) {
-        guard let preview = string else {
-            previewLabel.attributedText = nil
-            return
-        }
-
-        let paragraphStyle = NSMutableParagraphStyle()
-        paragraphStyle.lineHeightMultiple = 1.1
-
-        previewLabel.attributedText = NSAttributedString(
-            string: preview,
-            attributes: [
-                .paragraphStyle: paragraphStyle,
-                .font: Fonts.Mulish.regular.font(size: 14.0),
-                .foregroundColor: Asset.neutralSecondaryAlternative.color
-            ])
+    
+    unreadView.snp.makeConstraints {
+      $0.right.equalTo(dateLabel)
+      $0.centerY.equalTo(previewLabel)
+      $0.width.height.equalTo(20)
+    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  override func prepareForReuse() {
+    super.prepareForReuse()
+    lastDate = nil
+    titleLabel.text = nil
+    unreadCountLabel.text = nil
+    previewLabel.attributedText = nil
+    avatarView.prepareForReuse()
+  }
+  
+  private func updateTimeAgoLabel() {
+    if let date = lastDate {
+      dateLabel.text = date.asRelativeFromNow()
+    }
+  }
+  
+  func setupContact(
+    name: String,
+    image: Data?,
+    date: Date?,
+    unreadCount: Int,
+    preview: String
+  ) {
+    titleLabel.text = name
+    setPreview(string: preview)
+    avatarView.setupProfile(title: name, image: image, size: .large)
+    unreadCountLabel.text = "\(unreadCount)"
+    unreadView.backgroundColor = unreadCount > 0 ? Asset.brandPrimary.color : .clear
+    
+    if let date = date {
+      lastDate = date
+    } else {
+      dateLabel.text = nil
+    }
+  }
+  
+  func setupGroup(
+    name: String,
+    date: Date,
+    preview: String?,
+    unreadCount: Int
+  ) {
+    lastDate = date
+    titleLabel.text = name
+    setPreview(string: preview)
+    avatarView.setupGroup(size: .large)
+    unreadCountLabel.text = "\(unreadCount)"
+    unreadView.backgroundColor = unreadCount > 0 ? Asset.brandPrimary.color : .clear
+  }
+  
+  private func setPreview(string: String?) {
+    guard let preview = string else {
+      previewLabel.attributedText = nil
+      return
     }
+    
+    let paragraphStyle = NSMutableParagraphStyle()
+    paragraphStyle.lineHeightMultiple = 1.1
+    
+    previewLabel.attributedText = NSAttributedString(
+      string: preview,
+      attributes: [
+        .paragraphStyle: paragraphStyle,
+        .font: Fonts.Mulish.regular.font(size: 14.0),
+        .foregroundColor: Asset.neutralSecondaryAlternative.color
+      ])
+  }
 }
diff --git a/Sources/ChatListFeature/Views/ChatListContainerView.swift b/Sources/ChatListFeature/Views/ChatListContainerView.swift
index 1be2c99cf0e9cc736f0c02acd1b9c3e54f5be688..b34fc50bb3690707488c0842058c818b1092de6a 100644
--- a/Sources/ChatListFeature/Views/ChatListContainerView.swift
+++ b/Sources/ChatListFeature/Views/ChatListContainerView.swift
@@ -1,114 +1,95 @@
 import UIKit
 import Shared
 
-final class ChatSearchListContainerView: UIView{
-    let emptyView = ChatSearchEmptyView()
-
-    init() {
-        super.init(frame: .zero)
-
-        addSubview(emptyView)
-
-        emptyView.snp.makeConstraints {
-            $0.edges.equalToSuperview()
-        }
-    }
-
-    required init?(coder: NSCoder) { nil }
-}
-
 final class ChatListContainerView: UIView {
-    let separatorView = UIView()
-    let emptyView = ChatListEmptyView()
-    let collectionContainerView = UIView()
-    lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
-
-    private let layout: UICollectionViewFlowLayout = {
-        let layout = UICollectionViewFlowLayout()
-        layout.minimumLineSpacing = 35
-        layout.itemSize = CGSize(width: 56, height: 80)
-        layout.scrollDirection = .horizontal
-        return layout
-    }()
-
-    init() {
-        super.init(frame: .zero)
-
-        collectionView.showsHorizontalScrollIndicator = false
-        separatorView.backgroundColor = Asset.neutralLine.color
-        collectionView.backgroundColor = Asset.neutralWhite.color
-        collectionView.contentInset = UIEdgeInsets(top: 0, left: 30, bottom: 0, right: 30)
-
-        addSubview(emptyView)
-        addSubview(collectionContainerView)
-        collectionContainerView.addSubview(collectionView)
-        collectionContainerView.addSubview(separatorView)
-
-        collectionContainerView.snp.makeConstraints {
-            $0.bottom.equalTo(snp.top)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.height.equalTo(110)
-        }
-
-        collectionView.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-        }
-
-        separatorView.snp.makeConstraints {
-            $0.top.equalTo(collectionView.snp.bottom).offset(20)
-            $0.height.equalTo(1)
-            $0.left.equalToSuperview().offset(24)
-            $0.right.equalToSuperview().offset(-24)
-            $0.bottom.equalToSuperview()
-        }
-
-        emptyView.snp.makeConstraints {
-            $0.top.equalTo(collectionContainerView.snp.bottom)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
+  let separatorView = UIView()
+  let emptyView = ChatListEmptyView()
+  let collectionContainerView = UIView()
+  lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
+  
+  private let layout: UICollectionViewFlowLayout = {
+    let layout = UICollectionViewFlowLayout()
+    layout.minimumLineSpacing = 35
+    layout.itemSize = CGSize(width: 56, height: 80)
+    layout.scrollDirection = .horizontal
+    return layout
+  }()
+  
+  init() {
+    super.init(frame: .zero)
+    
+    collectionView.showsHorizontalScrollIndicator = false
+    separatorView.backgroundColor = Asset.neutralLine.color
+    collectionView.backgroundColor = Asset.neutralWhite.color
+    collectionView.contentInset = UIEdgeInsets(top: 0, left: 30, bottom: 0, right: 30)
+    
+    addSubview(emptyView)
+    addSubview(collectionContainerView)
+    collectionContainerView.addSubview(collectionView)
+    collectionContainerView.addSubview(separatorView)
+    
+    collectionContainerView.snp.makeConstraints {
+      $0.bottom.equalTo(snp.top)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.height.equalTo(110)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    func showRecentsCollection(_ show: Bool) {
-        if show == true && collectionContainerView.alpha != 0.0 ||
-            show == false && collectionContainerView.alpha == 0.0 {
-            return
-        }
-
-        if show == true {
-            collectionContainerView.alpha = 0.0
-            collectionContainerView.snp.updateConstraints {
-                $0.bottom.equalTo(snp.top).offset(collectionContainerView.bounds.height + 20)
-            }
-
-            UIView.animate(withDuration: 0.3, delay: 0.3, options: .curveEaseInOut) {
-                self.collectionContainerView.alpha = 1.0
-            }
-
-            UIView.animate(withDuration: 0.3, delay: 0.15, options: .curveEaseInOut) {
-                self.setNeedsLayout()
-                self.layoutIfNeeded()
-            }
-        } else {
-            collectionContainerView.alpha = 1.0
-            collectionContainerView.snp.updateConstraints {
-                $0.bottom.equalTo(snp.top)
-            }
-
-            UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseInOut) {
-                self.collectionContainerView.alpha = 0.0
-            }
-
-            UIView.animate(withDuration: 0.2, delay: 0.15, options: .curveEaseInOut) {
-                self.setNeedsLayout()
-                self.layoutIfNeeded()
-            }
-        }
+    collectionView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+    }
+    separatorView.snp.makeConstraints {
+      $0.top.equalTo(collectionView.snp.bottom).offset(20)
+      $0.height.equalTo(1)
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
+      $0.bottom.equalToSuperview()
+    }
+    emptyView.snp.makeConstraints {
+      $0.top.equalTo(collectionContainerView.snp.bottom)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  func showRecentsCollection(_ show: Bool) {
+    if show == true && collectionContainerView.alpha != 0.0 ||
+        show == false && collectionContainerView.alpha == 0.0 {
+      return
+    }
+    
+    if show == true {
+      collectionContainerView.alpha = 0.0
+      collectionContainerView.snp.updateConstraints {
+        $0.bottom.equalTo(snp.top).offset(collectionContainerView.bounds.height + 20)
+      }
+      
+      UIView.animate(withDuration: 0.3, delay: 0.3, options: .curveEaseInOut) {
+        self.collectionContainerView.alpha = 1.0
+      }
+      
+      UIView.animate(withDuration: 0.3, delay: 0.15, options: .curveEaseInOut) {
+        self.setNeedsLayout()
+        self.layoutIfNeeded()
+      }
+    } else {
+      collectionContainerView.alpha = 1.0
+      collectionContainerView.snp.updateConstraints {
+        $0.bottom.equalTo(snp.top)
+      }
+      
+      UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseInOut) {
+        self.collectionContainerView.alpha = 0.0
+      }
+      
+      UIView.animate(withDuration: 0.2, delay: 0.15, options: .curveEaseInOut) {
+        self.setNeedsLayout()
+        self.layoutIfNeeded()
+      }
     }
+  }
 }
diff --git a/Sources/ChatListFeature/Views/ChatListEmptyView.swift b/Sources/ChatListFeature/Views/ChatListEmptyView.swift
index 374e184970bcad877ee7ca507369bb219df32265..449c71451b679c18f6ae8fda508d9678b648773d 100644
--- a/Sources/ChatListFeature/Views/ChatListEmptyView.swift
+++ b/Sources/ChatListFeature/Views/ChatListEmptyView.swift
@@ -2,47 +2,47 @@ import UIKit
 import Shared
 
 final class ChatListEmptyView: UIView {
-    private let titleLabel = UILabel()
-    private let stackView = UIStackView()
-    private(set) var contactsButton = CapsuleButton()
-
-    init() {
-        super.init(frame: .zero)
-
-        backgroundColor = Asset.neutralWhite.color
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.lineHeightMultiple = 1.2
-        paragraph.alignment = .center
-
-        titleLabel.numberOfLines = 0
-        titleLabel.attributedText = NSAttributedString(
-            string: Localized.ChatList.emptyTitle,
-            attributes: [
-                .paragraphStyle: paragraph,
-                .foregroundColor: Asset.neutralActive.color,
-                .font: Fonts.Mulish.bold.font(size: 24.0)
-            ]
-        )
-
-        contactsButton.setStyle(.brandColored)
-        contactsButton.setTitle(Localized.ChatList.action, for: .normal)
-
-        stackView.spacing = 24
-        stackView.axis = .vertical
-        stackView.alignment = .center
-        stackView.addArrangedSubview(titleLabel)
-        stackView.addArrangedSubview(contactsButton)
-
-        addSubview(stackView)
-
-        stackView.snp.makeConstraints {
-            $0.centerY.equalToSuperview()
-            $0.top.greaterThanOrEqualToSuperview()
-            $0.left.equalToSuperview().offset(24)
-            $0.right.equalToSuperview().offset(-24)
-            $0.bottom.lessThanOrEqualToSuperview()
-        }
+  let titleLabel = UILabel()
+  let stackView = UIStackView()
+  let contactsButton = CapsuleButton()
+  
+  init() {
+    super.init(frame: .zero)
+    
+    backgroundColor = Asset.neutralWhite.color
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.lineHeightMultiple = 1.2
+    paragraph.alignment = .center
+    
+    titleLabel.numberOfLines = 0
+    titleLabel.attributedText = NSAttributedString(
+      string: Localized.ChatList.emptyTitle,
+      attributes: [
+        .paragraphStyle: paragraph,
+        .foregroundColor: Asset.neutralActive.color,
+        .font: Fonts.Mulish.bold.font(size: 24.0)
+      ]
+    )
+    
+    contactsButton.setStyle(.brandColored)
+    contactsButton.setTitle(Localized.ChatList.action, for: .normal)
+    
+    stackView.spacing = 24
+    stackView.axis = .vertical
+    stackView.alignment = .center
+    stackView.addArrangedSubview(titleLabel)
+    stackView.addArrangedSubview(contactsButton)
+    
+    addSubview(stackView)
+    
+    stackView.snp.makeConstraints {
+      $0.centerY.equalToSuperview()
+      $0.top.greaterThanOrEqualToSuperview()
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
+      $0.bottom.lessThanOrEqualToSuperview()
     }
-
-    required init?(coder: NSCoder) { nil }
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/ChatListFeature/Views/ChatListMenuView.swift b/Sources/ChatListFeature/Views/ChatListMenuView.swift
index 132b38402fd0ebdf08be0d569e45bfc93793275e..4c700f31414cb2a0d107c076c282bafd6380e16c 100644
--- a/Sources/ChatListFeature/Views/ChatListMenuView.swift
+++ b/Sources/ChatListFeature/Views/ChatListMenuView.swift
@@ -3,67 +3,71 @@ import Shared
 import Combine
 
 final class ChatListMenuView: UIToolbar {
-    enum Action {
-        case delete
-        case deleteAll
-    }
-
-    let stackView = UIStackView()
-    let deleteButton = UIButton()
-    let deleteAllButton = UIButton()
-
-    @Published var isDeleteEnabled = false
-
-    var publisher: AnyPublisher<Action, Never> {
-        actionRelay.eraseToAnyPublisher()
-    }
-
-    private var cancellables = Set<AnyCancellable>()
-    private let actionRelay = PassthroughSubject<Action, Never>()
-
-    init() {
-        super.init(frame: .zero)
-        setup()
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    private func setup() {
-        clipsToBounds = true
-        layer.cornerRadius = 15
-        barTintColor = Asset.neutralSecondary.color
-
-        deleteButton.setImage(Asset.chatListMenuDelete.image, for: .normal)
-        deleteAllButton.setTitleColor(Asset.accentDanger.color, for: .normal)
-        deleteAllButton.setTitle(Localized.ChatList.Menu.deleteAll, for: .normal)
-        deleteAllButton.titleLabel?.font = Fonts.Mulish.semiBold.font(size: 14.0)
-
-        stackView.spacing = 35
-        stackView.addArrangedSubview(deleteButton)
-        stackView.addArrangedSubview(deleteAllButton)
-        stackView.distribution = .fillEqually
-        addSubview(stackView)
-
-        translatesAutoresizingMaskIntoConstraints = false
-
-        $isDeleteEnabled
-            .assign(to: \.isEnabled, on: deleteButton)
-            .store(in: &cancellables)
-
-        deleteButton.publisher(for: .touchUpInside)
-            .sink { [weak actionRelay] in actionRelay?.send(.delete) }
-            .store(in: &cancellables)
-
-        deleteAllButton.publisher(for: .touchUpInside)
-            .sink { [weak actionRelay] in actionRelay?.send(.deleteAll) }
-            .store(in: &cancellables)
-
-        stackView.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-            make.bottom.equalToSuperview().offset(-10)
-            make.height.equalTo(83)
-        }
+  enum Action {
+    case delete
+    case deleteAll
+  }
+  
+  let stackView = UIStackView()
+  let deleteButton = UIButton()
+  let deleteAllButton = UIButton()
+  
+  @Published var isDeleteEnabled = false
+  
+  var publisher: AnyPublisher<Action, Never> {
+    actionRelay.eraseToAnyPublisher()
+  }
+  
+  var cancellables = Set<AnyCancellable>()
+  let actionRelay = PassthroughSubject<Action, Never>()
+  
+  init() {
+    super.init(frame: .zero)
+    setup()
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  private func setup() {
+    clipsToBounds = true
+    layer.cornerRadius = 15
+    barTintColor = Asset.neutralSecondary.color
+    
+    deleteButton.setImage(Asset.chatListMenuDelete.image, for: .normal)
+    deleteAllButton.setTitleColor(Asset.accentDanger.color, for: .normal)
+    deleteAllButton.setTitle(Localized.ChatList.Menu.deleteAll, for: .normal)
+    deleteAllButton.titleLabel?.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    
+    stackView.spacing = 35
+    stackView.addArrangedSubview(deleteButton)
+    stackView.addArrangedSubview(deleteAllButton)
+    stackView.distribution = .fillEqually
+    addSubview(stackView)
+    
+    translatesAutoresizingMaskIntoConstraints = false
+    
+    $isDeleteEnabled
+      .assign(to: \.isEnabled, on: deleteButton)
+      .store(in: &cancellables)
+    
+    deleteButton
+      .publisher(for: .touchUpInside)
+      .sink { [weak actionRelay] in
+        actionRelay?.send(.delete)
+      }.store(in: &cancellables)
+    
+    deleteAllButton
+      .publisher(for: .touchUpInside)
+      .sink { [weak actionRelay] in
+        actionRelay?.send(.deleteAll)
+      }.store(in: &cancellables)
+    
+    stackView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
+      $0.bottom.equalToSuperview().offset(-10)
+      $0.height.equalTo(83)
     }
+  }
 }
diff --git a/Sources/ChatListFeature/Views/ChatListRecentContactCell.swift b/Sources/ChatListFeature/Views/ChatListRecentContactCell.swift
index 4adbdeef783245dcd73a1697f8325654952ab3e2..6f452d4e51b3a0a39cee4ded26339cc143fd894a 100644
--- a/Sources/ChatListFeature/Views/ChatListRecentContactCell.swift
+++ b/Sources/ChatListFeature/Views/ChatListRecentContactCell.swift
@@ -2,88 +2,84 @@ import UIKit
 import Shared
 
 final class ChatListRecentContactCell: UICollectionViewCell {
-    private let titleLabel = UILabel()
-    private let containerView = UIView()
-    private let avatarView = AvatarView()
-
-    override init(frame: CGRect) {
-        super.init(frame: frame)
-
-        contentView.backgroundColor = .white
-
-        let newLabel = UILabel()
-        newLabel.text = "NEW"
-        newLabel.textColor = Asset.neutralWhite.color
-        newLabel.font = Fonts.Mulish.bold.font(size: 8.0)
-
-        let newContainerView = UIView()
-        newContainerView.layer.cornerRadius = 6.0
-        newContainerView.layer.masksToBounds = true
-        newContainerView.backgroundColor = Asset.accentSafe.color
-
-        titleLabel.numberOfLines = 2
-        titleLabel.textAlignment = .center
-        titleLabel.lineBreakMode = .byWordWrapping
-        titleLabel.textColor = Asset.neutralDark.color
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
-
-        contentView.addSubview(titleLabel)
-        contentView.addSubview(containerView)
-
-        containerView.addSubview(avatarView)
-        containerView.addSubview(newContainerView)
-
-        newContainerView.addSubview(newLabel)
-
-        containerView.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-        }
-
-        newContainerView.snp.makeConstraints {
-            $0.top.equalTo(containerView.snp.top)
-            $0.right.equalTo(containerView.snp.right)
-        }
-
-        newLabel.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(3)
-            $0.center.equalToSuperview()
-            $0.left.equalToSuperview().offset(3)
-        }
-
-        avatarView.snp.makeConstraints {
-            $0.width.equalTo(48)
-            $0.height.equalTo(48)
-            $0.top.equalToSuperview().offset(4)
-            $0.left.equalToSuperview().offset(4)
-            $0.right.equalToSuperview().offset(-4)
-            $0.bottom.equalToSuperview().offset(-4)
-        }
-
-        titleLabel.snp.makeConstraints {
-            $0.centerX.equalToSuperview()
-            $0.top.equalTo(containerView.snp.bottom).offset(5)
-            $0.left.greaterThanOrEqualToSuperview()
-            $0.right.lessThanOrEqualToSuperview()
-            $0.bottom.lessThanOrEqualToSuperview()
-        }
+  let titleLabel = UILabel()
+  let containerView = UIView()
+  let avatarView = AvatarView()
+  
+  override init(frame: CGRect) {
+    super.init(frame: frame)
+    
+    contentView.backgroundColor = .white
+    
+    let newLabel = UILabel()
+    newLabel.text = "NEW"
+    newLabel.textColor = Asset.neutralWhite.color
+    newLabel.font = Fonts.Mulish.bold.font(size: 8.0)
+    
+    let newContainerView = UIView()
+    newContainerView.layer.cornerRadius = 6.0
+    newContainerView.layer.masksToBounds = true
+    newContainerView.backgroundColor = Asset.accentSafe.color
+    
+    titleLabel.numberOfLines = 2
+    titleLabel.textAlignment = .center
+    titleLabel.lineBreakMode = .byWordWrapping
+    titleLabel.textColor = Asset.neutralDark.color
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    
+    contentView.addSubview(titleLabel)
+    contentView.addSubview(containerView)
+    
+    containerView.addSubview(avatarView)
+    containerView.addSubview(newContainerView)
+    
+    newContainerView.addSubview(newLabel)
+    
+    containerView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    override func prepareForReuse() {
-        super.prepareForReuse()
-        titleLabel.text = nil
-        avatarView.prepareForReuse()
+    newContainerView.snp.makeConstraints {
+      $0.top.equalTo(containerView.snp.top)
+      $0.right.equalTo(containerView.snp.right)
     }
-
-    func setup(title: String, image: Data?) {
-        titleLabel.text = title
-        avatarView.setupProfile(
-            title: title,
-            image: image,
-            size: .large
-        )
+    newLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(3)
+      $0.center.equalToSuperview()
+      $0.left.equalToSuperview().offset(3)
+    }
+    avatarView.snp.makeConstraints {
+      $0.width.equalTo(48)
+      $0.height.equalTo(48)
+      $0.top.equalToSuperview().offset(4)
+      $0.left.equalToSuperview().offset(4)
+      $0.right.equalToSuperview().offset(-4)
+      $0.bottom.equalToSuperview().offset(-4)
+    }
+    titleLabel.snp.makeConstraints {
+      $0.centerX.equalToSuperview()
+      $0.top.equalTo(containerView.snp.bottom).offset(5)
+      $0.left.greaterThanOrEqualToSuperview()
+      $0.right.lessThanOrEqualToSuperview()
+      $0.bottom.lessThanOrEqualToSuperview()
     }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  override func prepareForReuse() {
+    super.prepareForReuse()
+    titleLabel.text = nil
+    avatarView.prepareForReuse()
+  }
+  
+  func setup(title: String, image: Data?) {
+    titleLabel.text = title
+    avatarView.setupProfile(
+      title: title,
+      image: image,
+      size: .large
+    )
+  }
 }
diff --git a/Sources/ChatListFeature/Views/ChatListTopLeftNavView.swift b/Sources/ChatListFeature/Views/ChatListTopLeftNavView.swift
index 6cc8a78df568a521afbb39b6fe69cd4197aa5e4e..7ed956f4f3736c5c96bebdeaf59f8b7d198bc78f 100644
--- a/Sources/ChatListFeature/Views/ChatListTopLeftNavView.swift
+++ b/Sources/ChatListFeature/Views/ChatListTopLeftNavView.swift
@@ -3,70 +3,72 @@ import Shared
 import Combine
 
 final class ChatListTopLeftNavView: UIView {
-    private let titleLabel = UILabel()
-    private let badgeLabel = UILabel()
-    private let menuButton = UIButton()
-    private let stackView = UIStackView()
-    private let badgeContainerView = UIView()
-
-    var actionPublisher: AnyPublisher<Void, Never> {
-        actionSubject.eraseToAnyPublisher()
+  let titleLabel = UILabel()
+  let badgeLabel = UILabel()
+  let menuButton = UIButton()
+  let stackView = UIStackView()
+  let badgeContainerView = UIView()
+  
+  var actionPublisher: AnyPublisher<Void, Never> {
+    actionSubject.eraseToAnyPublisher()
+  }
+  
+  private let actionSubject = PassthroughSubject<Void, Never>()
+  
+  init() {
+    super.init(frame: .zero)
+    
+    titleLabel.text = Localized.ChatList.title
+    titleLabel.textColor = Asset.neutralActive.color
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 18.0)
+    
+    menuButton.tintColor = Asset.neutralDark.color
+    menuButton.setImage(Asset.chatListMenu.image, for: .normal)
+    menuButton.addTarget(self, action: #selector(didTapMenu), for: .touchUpInside)
+    
+    badgeLabel.textColor = Asset.neutralWhite.color
+    badgeLabel.font = Fonts.Mulish.bold.font(size: 12.0)
+    
+    badgeContainerView.layer.cornerRadius = 5
+    badgeContainerView.layer.masksToBounds = true
+    badgeContainerView.backgroundColor = Asset.brandPrimary.color
+    
+    badgeContainerView.addSubview(badgeLabel)
+    menuButton.addSubview(badgeContainerView)
+    stackView.addArrangedSubview(menuButton)
+    stackView.addArrangedSubview(titleLabel)
+    addSubview(stackView)
+    
+    badgeLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(3)
+      $0.center.equalToSuperview()
+      $0.left.equalToSuperview().offset(3)
     }
-
-    private let actionSubject = PassthroughSubject<Void, Never>()
-
-    init() {
-        super.init(frame: .zero)
-
-        titleLabel.text = Localized.ChatList.title
-        titleLabel.textColor = Asset.neutralActive.color
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 18.0)
-
-        menuButton.tintColor = Asset.neutralDark.color
-        menuButton.setImage(Asset.chatListMenu.image, for: .normal)
-        menuButton.addTarget(self, action: #selector(didTapMenu), for: .touchUpInside)
-
-        badgeLabel.textColor = Asset.neutralWhite.color
-        badgeLabel.font = Fonts.Mulish.bold.font(size: 12.0)
-
-        badgeContainerView.layer.cornerRadius = 5
-        badgeContainerView.layer.masksToBounds = true
-        badgeContainerView.backgroundColor = Asset.brandPrimary.color
-
-        badgeContainerView.addSubview(badgeLabel)
-        menuButton.addSubview(badgeContainerView)
-        stackView.addArrangedSubview(menuButton)
-        stackView.addArrangedSubview(titleLabel)
-        addSubview(stackView)
-
-        badgeLabel.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(3)
-            $0.center.equalToSuperview()
-            $0.left.equalToSuperview().offset(3)
-        }
-
-        badgeContainerView.snp.makeConstraints {
-            $0.centerY.equalTo(menuButton.snp.top)
-            $0.centerX.equalTo(menuButton.snp.right).multipliedBy(0.8)
-        }
-
-        menuButton.snp.makeConstraints { $0.width.equalTo(50) }
-        stackView.snp.makeConstraints { $0.edges.equalToSuperview() }
+    badgeContainerView.snp.makeConstraints {
+      $0.centerY.equalTo(menuButton.snp.top)
+      $0.centerX.equalTo(menuButton.snp.right).multipliedBy(0.8)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    @objc private func didTapMenu() {
-        actionSubject.send()
+    menuButton.snp.makeConstraints {
+      $0.width.equalTo(50)
     }
-
-    func updateBadge(_ count: Int) {
-        guard count > 0 else {
-            badgeContainerView.isHidden = true
-            return
-        }
-
-        badgeLabel.text = "\(count)"
-        badgeContainerView.isHidden = false
+    stackView.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  @objc private func didTapMenu() {
+    actionSubject.send()
+  }
+  
+  func updateBadge(_ count: Int) {
+    guard count > 0 else {
+      badgeContainerView.isHidden = true
+      return
     }
+    
+    badgeLabel.text = "\(count)"
+    badgeContainerView.isHidden = false
+  }
 }
diff --git a/Sources/ChatListFeature/Views/ChatListTopRightNavView.swift b/Sources/ChatListFeature/Views/ChatListTopRightNavView.swift
index 817893e1a1df3d5f50cf241cfb0d5b60ababe2ae..182187b997840d7d7d7164f29b5fe4501cabf551 100644
--- a/Sources/ChatListFeature/Views/ChatListTopRightNavView.swift
+++ b/Sources/ChatListFeature/Views/ChatListTopRightNavView.swift
@@ -3,47 +3,53 @@ import Shared
 import Combine
 
 final class ChatListTopRightNavView: UIView {
-    enum Action {
-        case didTapSearch
-        case didTapNewGroup
+  enum Action {
+    case didTapSearch
+    case didTapNewGroup
+  }
+  
+  var actionPublisher: AnyPublisher<Action, Never> {
+    actionSubject.eraseToAnyPublisher()
+  }
+  
+  let stackView = UIStackView()
+  let searchButton = UIButton()
+  let newGroupButton = UIButton()
+  let actionSubject = PassthroughSubject<Action, Never>()
+  
+  init() {
+    super.init(frame: .zero)
+    
+    searchButton.tintColor = Asset.neutralDark.color
+    newGroupButton.tintColor = Asset.neutralDark.color
+    searchButton.setImage(Asset.chatListUd.image, for: .normal)
+    newGroupButton.setImage(Asset.chatListNewGroup.image, for: .normal)
+    searchButton.addTarget(self, action: #selector(didTapSearch), for: .touchUpInside)
+    newGroupButton.addTarget(self, action: #selector(didTapNewGroup), for: .touchUpInside)
+    
+    stackView.spacing = 10
+    stackView.addArrangedSubview(newGroupButton)
+    stackView.addArrangedSubview(searchButton)
+    addSubview(stackView)
+    
+    searchButton.snp.makeConstraints {
+      $0.width.equalTo(40)
     }
-
-    var actionPublisher: AnyPublisher<Action, Never> {
-        actionSubject.eraseToAnyPublisher()
+    newGroupButton.snp.makeConstraints {
+      $0.width.equalTo(40)
     }
-
-    private let stackView = UIStackView()
-    private let searchButton = UIButton()
-    private let newGroupButton = UIButton()
-    private let actionSubject = PassthroughSubject<Action, Never>()
-
-    init() {
-        super.init(frame: .zero)
-
-        searchButton.tintColor = Asset.neutralDark.color
-        newGroupButton.tintColor = Asset.neutralDark.color
-        searchButton.setImage(Asset.chatListUd.image, for: .normal)
-        newGroupButton.setImage(Asset.chatListNewGroup.image, for: .normal)
-        searchButton.addTarget(self, action: #selector(didTapSearch), for: .touchUpInside)
-        newGroupButton.addTarget(self, action: #selector(didTapNewGroup), for: .touchUpInside)
-
-        stackView.spacing = 10
-        stackView.addArrangedSubview(newGroupButton)
-        stackView.addArrangedSubview(searchButton)
-        addSubview(stackView)
-
-        searchButton.snp.makeConstraints { $0.width.equalTo(40) }
-        newGroupButton.snp.makeConstraints { $0.width.equalTo(40) }
-        stackView.snp.makeConstraints { $0.edges.equalToSuperview() }
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    @objc private func didTapSearch() {
-        actionSubject.send(.didTapSearch)
-    }
-
-    @objc private func didTapNewGroup() {
-        actionSubject.send(.didTapNewGroup)
+    stackView.snp.makeConstraints {
+      $0.edges.equalToSuperview()
     }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  @objc private func didTapSearch() {
+    actionSubject.send(.didTapSearch)
+  }
+  
+  @objc private func didTapNewGroup() {
+    actionSubject.send(.didTapNewGroup)
+  }
 }
diff --git a/Sources/ChatListFeature/Views/ChatListView.swift b/Sources/ChatListFeature/Views/ChatListView.swift
index 03a407980700123d9843d9239e4822b9247dac63..4bfe400fe287e385551605d1b9c9f343f168f241 100644
--- a/Sources/ChatListFeature/Views/ChatListView.swift
+++ b/Sources/ChatListFeature/Views/ChatListView.swift
@@ -2,79 +2,71 @@ import UIKit
 import Shared
 
 final class ChatListView: UIView {
-    let snackBar = SnackBar()
-    let containerView = UIView()
-    let searchView = SearchComponent()
-    let listContainerView = ChatListContainerView()
-    let searchListContainerView = ChatSearchListContainerView()
+  let snackBar = SnackBar()
+  let containerView = UIView()
+  let searchView = SearchComponent()
+  let listContainerView = ChatListContainerView()
+  let searchListContainerView = ChatSearchListContainerView()
+  
+  init() {
+    super.init(frame: .zero)
 
-    init() {
-        super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+    listContainerView.backgroundColor = Asset.neutralWhite.color
+    searchListContainerView.backgroundColor = Asset.neutralWhite.color
+    searchView.update(placeholder: Localized.ChatList.Search.title)
 
-        backgroundColor = Asset.neutralWhite.color
-        listContainerView.backgroundColor = Asset.neutralWhite.color
-        searchListContainerView.backgroundColor = Asset.neutralWhite.color
-        searchView.update(placeholder: Localized.ChatList.Search.title)
+    addSubview(snackBar)
+    addSubview(searchView)
+    addSubview(containerView)
+    containerView.addSubview(searchListContainerView)
+    containerView.addSubview(listContainerView)
 
-        addSubview(snackBar)
-        addSubview(searchView)
-        addSubview(containerView)
-        containerView.addSubview(searchListContainerView)
-        containerView.addSubview(listContainerView)
-
-        setupConstraints()
+    snackBar.snp.makeConstraints {
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalTo(snp.top)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    func showConnectingBanner(_ show: Bool) {
-        if show == true {
-            snackBar.alpha = 0.0
-            snackBar.snp.updateConstraints {
-                $0.bottom
-                    .equalTo(snp.top)
-                    .offset(snackBar.bounds.height)
-            }
-        } else {
-            snackBar.alpha = 1.0
-            snackBar.snp.updateConstraints {
-                $0.bottom.equalTo(snp.top)
-            }
-        }
-
-        UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseInOut) {
-            self.setNeedsLayout()
-            self.layoutIfNeeded()
-            self.snackBar.alpha = show ? 1.0 : 0.0
-        }
+    searchView.snp.makeConstraints {
+      $0.top.equalTo(snackBar.snp.bottom).offset(20)
+      $0.left.equalToSuperview().offset(20)
+      $0.right.equalToSuperview().offset(-20)
     }
-
-    private func setupConstraints() {
-        snackBar.snp.makeConstraints {
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalTo(snp.top)
-        }
-
-        searchView.snp.makeConstraints {
-            $0.top.equalTo(snackBar.snp.bottom).offset(20)
-            $0.left.equalToSuperview().offset(20)
-            $0.right.equalToSuperview().offset(-20)
-        }
-
-        containerView.snp.makeConstraints {
-            $0.top.equalTo(searchView.snp.bottom)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
-
-        listContainerView.snp.makeConstraints {
-            $0.edges.equalToSuperview()
-        }
-
-        searchListContainerView.snp.makeConstraints {
-            $0.edges.equalToSuperview()
-        }
+    containerView.snp.makeConstraints {
+      $0.top.equalTo(searchView.snp.bottom)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
+    listContainerView.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+    }
+    searchListContainerView.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  func showConnectingBanner(_ show: Bool) {
+    if show == true {
+      snackBar.alpha = 0.0
+      snackBar.snp.updateConstraints {
+        $0.bottom
+          .equalTo(snp.top)
+          .offset(snackBar.bounds.height)
+      }
+    } else {
+      snackBar.alpha = 1.0
+      snackBar.snp.updateConstraints {
+        $0.bottom.equalTo(snp.top)
+      }
+    }
+    
+    UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseInOut) {
+      self.setNeedsLayout()
+      self.layoutIfNeeded()
+      self.snackBar.alpha = show ? 1.0 : 0.0
     }
+  }
 }
diff --git a/Sources/ChatListFeature/Views/ChatSearchEmptyView.swift b/Sources/ChatListFeature/Views/ChatSearchEmptyView.swift
index 2fe1471c5d1f7d9d967a2ca24b50a6950c4067c3..ec55193886cf161efbdf1159737ce16281fb334a 100644
--- a/Sources/ChatListFeature/Views/ChatSearchEmptyView.swift
+++ b/Sources/ChatListFeature/Views/ChatSearchEmptyView.swift
@@ -2,56 +2,56 @@ import UIKit
 import Shared
 
 final class ChatSearchEmptyView: UIView {
-    private let titleLabel = UILabel()
-    private let stackView = UIStackView()
-    private let descriptionLabel = UILabel()
-    private(set) var searchButton = CapsuleButton()
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        titleLabel.textColor = Asset.brandPrimary.color
-        titleLabel.font = Fonts.Mulish.bold.font(size: 24.0)
-
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.lineHeightMultiple = 1.2
-
-        descriptionLabel.numberOfLines = 0
-        descriptionLabel.attributedText = NSAttributedString(
-            string: "was not found in your connections or in a chat. Click below to search for them as a new connection.",
-            attributes: [
-                .paragraphStyle: paragraph,
-                .foregroundColor: Asset.neutralActive.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0)
-            ]
-        )
-
-        searchButton.setStyle(.brandColored)
-        searchButton.setTitle("Search for a connection", for: .normal)
-
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(titleLabel)
-        stackView.addArrangedSubview(descriptionLabel)
-        stackView.addArrangedSubview(searchButton)
-
-        stackView.setCustomSpacing(10, after: titleLabel)
-        stackView.setCustomSpacing(30, after: descriptionLabel)
-
-        addSubview(stackView)
-
-        stackView.snp.makeConstraints {
-            $0.centerY.equalToSuperview().multipliedBy(0.5)
-            $0.top.greaterThanOrEqualToSuperview()
-            $0.left.equalToSuperview().offset(24)
-            $0.right.equalToSuperview().offset(-24)
-            $0.bottom.lessThanOrEqualToSuperview()
-        }
+  let titleLabel = UILabel()
+  let stackView = UIStackView()
+  let descriptionLabel = UILabel()
+  let searchButton = CapsuleButton()
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+
+    titleLabel.textColor = Asset.brandPrimary.color
+    titleLabel.font = Fonts.Mulish.bold.font(size: 24.0)
+
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.lineHeightMultiple = 1.2
+
+    descriptionLabel.numberOfLines = 0
+    descriptionLabel.attributedText = NSAttributedString(
+      string: "was not found in your connections or in a chat. Click below to search for them as a new connection.",
+      attributes: [
+        .paragraphStyle: paragraph,
+        .foregroundColor: Asset.neutralActive.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0)
+      ]
+    )
+
+    searchButton.setStyle(.brandColored)
+    searchButton.setTitle("Search for a connection", for: .normal)
+
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(titleLabel)
+    stackView.addArrangedSubview(descriptionLabel)
+    stackView.addArrangedSubview(searchButton)
+
+    stackView.setCustomSpacing(10, after: titleLabel)
+    stackView.setCustomSpacing(30, after: descriptionLabel)
+
+    addSubview(stackView)
+
+    stackView.snp.makeConstraints {
+      $0.centerY.equalToSuperview().multipliedBy(0.5)
+      $0.top.greaterThanOrEqualToSuperview()
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
+      $0.bottom.lessThanOrEqualToSuperview()
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 
-    func updateSearched(content: String) {
-        titleLabel.text = content
-    }
+  func updateSearched(content: String) {
+    titleLabel.text = content
+  }
 }
diff --git a/Sources/ChatListFeature/Views/ChatSearchListContainerView.swift b/Sources/ChatListFeature/Views/ChatSearchListContainerView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..75c25dc6402403b45afd9c33bc72fb4c2d515a09
--- /dev/null
+++ b/Sources/ChatListFeature/Views/ChatSearchListContainerView.swift
@@ -0,0 +1,17 @@
+import UIKit
+
+final class ChatSearchListContainerView: UIView {
+  let emptyView = ChatSearchEmptyView()
+
+  init() {
+    super.init(frame: .zero)
+
+    addSubview(emptyView)
+
+    emptyView.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
+}
diff --git a/Sources/ContactFeature/Controllers/ContactController.swift b/Sources/ContactFeature/Controllers/ContactController.swift
index 87a3f073ad467c00a5e3797cdcc190cb5cd52443..11e82eaa12b371101d465b795df317af4739ff26 100644
--- a/Sources/ContactFeature/Controllers/ContactController.swift
+++ b/Sources/ContactFeature/Controllers/ContactController.swift
@@ -2,13 +2,14 @@ import UIKit
 import Shared
 import Combine
 import XXModels
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 import ScrollViewController
 
 public final class ContactController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: ContactCoordinating
 
   private lazy var screenView = ContactView()
   private lazy var scrollViewController = ScrollViewController()
@@ -47,11 +48,14 @@ public final class ContactController: UIViewController {
     setupBindings()
 
     screenView.didTapSend = { [weak self] in
-      guard let self = self else { return }
-      self.coordinator.toSingleChat(with: self.viewModel.contact, from: self)
+      guard let self else { return }
+      self.navigator.perform(PresentChat(
+        contact: self.viewModel.contact
+      ))
     }
     screenView.didTapInfo = { [weak self] in
-      self?.presentInfo(
+      guard let self else { return }
+      self.presentInfo(
         title: Localized.Contact.SendMessage.Info.title,
         subtitle: Localized.Contact.SendMessage.Info.subtitle,
         urlString: "https://links.xx.network/cmix"
@@ -72,40 +76,54 @@ public final class ContactController: UIViewController {
   }
 
   private func setupBindings() {
-    screenView.cardComponent.avatarView.editButton
+    screenView
+      .cardComponent
+      .avatarView
+      .editButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in coordinator.toPhotos(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentPhotoLibrary())
+      }.store(in: &cancellables)
 
-    viewModel.statePublisher
+    viewModel
+      .statePublisher
       .map(\.photo)
       .compactMap { $0 }
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in screenView.cardComponent.image = $0 }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        screenView.cardComponent.image = $0
+      }.store(in: &cancellables)
 
-    viewModel.statePublisher
+    viewModel
+      .statePublisher
       .map(\.title)
       .compactMap { $0 }
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in screenView.cardComponent.nameLabel.text = $0 }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        screenView.cardComponent.nameLabel.text = $0
+      }.store(in: &cancellables)
 
-    viewModel.popPublisher
+    viewModel
+      .popPublisher
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in navigationController?.popViewController(animated: true) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigationController?.popViewController(animated: true)
+      }.store(in: &cancellables)
 
-    viewModel.popToRootPublisher
+    viewModel
+      .popToRootPublisher
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in navigationController?.popToRootViewController(animated: true) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigationController?.popToRootViewController(animated: true)
+      }.store(in: &cancellables)
 
-    viewModel.successPublisher
+    viewModel
+      .successPublisher
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in screenView.updateToSuccess() }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        screenView.updateToSuccess()
+      }.store(in: &cancellables)
 
     setupScannedBindings()
     setupReceivedBindings()
@@ -115,17 +133,24 @@ public final class ContactController: UIViewController {
   }
 
   private func setupSuccessBindings() {
-    screenView.successView.keepAdding
+    screenView
+      .successView
+      .keepAdding
       .publisher(for: .touchUpInside)
-      .sink { [unowned self] in navigationController?.popViewController(animated: true) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigationController?.popViewController(animated: true)
+      }.store(in: &cancellables)
 
-    screenView.successView.sentRequests
+    screenView
+      .successView
+      .sentRequests
       .publisher(for: .touchUpInside)
-      .sink { [unowned self] in coordinator.toRequests(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentRequests())
+      }.store(in: &cancellables)
 
-    viewModel.statePublisher
+    viewModel
+      .statePublisher
       .map(\.username)
       .removeDuplicates()
       .combineLatest(
@@ -137,49 +162,52 @@ public final class ContactController: UIViewController {
          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
+    screenView
+      .scannedView.add
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
-        coordinator.toNickname(
-          from: self,
-          prefilled: (viewModel.contact.nickname ?? viewModel.contact.username) ?? "",
-          viewModel.didTapRequest(with:)
-        )
+        let nickname = (viewModel.contact.nickname ?? viewModel.contact.username) ?? ""
+        navigator.perform(PresentNickname(prefilled: nickname) { [weak self] in
+          guard let self else { return }
+          self.viewModel.didTapRequest(with: $0)
+        })
       }.store(in: &cancellables)
   }
 
   private func setupReceivedBindings() {
-    screenView.receivedView.accept
+    screenView
+      .receivedView.accept
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
-        coordinator.toNickname(
-          from: self,
-          prefilled: (viewModel.contact.nickname ?? viewModel.contact.username) ?? "",
-          viewModel.didTapAccept(_:)
-        )
+        let nickname = (viewModel.contact.nickname ?? viewModel.contact.username) ?? ""
+        navigator.perform(PresentNickname(prefilled: nickname) { [weak self] in
+          guard let self else { return }
+          self.viewModel.didTapAccept($0)
+        })
       }.store(in: &cancellables)
 
-    screenView.receivedView.reject
+    screenView
+      .receivedView.reject
       .publisher(for: .touchUpInside)
-      .sink { [weak viewModel] in viewModel?.didTapReject() }
-      .store(in: &cancellables)
+      .sink { [weak viewModel] in
+        viewModel?.didTapReject()
+      }.store(in: &cancellables)
   }
 
   private func setupInProgressBindings() {
-    viewModel.statePublisher
+    viewModel
+      .statePublisher
       .map(\.username)
       .removeDuplicates()
       .combineLatest(
@@ -202,10 +230,12 @@ public final class ContactController: UIViewController {
         }
       }.store(in: &cancellables)
 
-    screenView.inProgressView.feedback
+    screenView
+      .inProgressView.feedback
       .button.publisher(for: .touchUpInside)
-      .sink { [weak viewModel] in viewModel?.didTapResend() }
-      .store(in: &cancellables)
+      .sink { [weak viewModel] in
+        viewModel?.didTapResend()
+      }.store(in: &cancellables)
   }
 
   private func setupConfirmedBindings() {
@@ -225,15 +255,16 @@ public final class ContactController: UIViewController {
         nicknameAttribute.set(title: Localized.Contact.nickname, value: $0.0, style: .requiredEditable)
         screenView.confirmedView.stackView.insertArrangedSubview(nicknameAttribute, at: 0)
 
-        nicknameAttribute.actionButton.publisher(for: .touchUpInside)
+        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 nickname = (viewModel.contact.nickname ?? viewModel.contact.username) ?? ""
+            navigator.perform(PresentNickname(prefilled: nickname, completion: { [weak self] in
+              guard let self else { return }
+              self.viewModel.didUpdateNickname($0)
+            }))
+          }.store(in: &cancellables)
 
         let usernameAttribute = AttributeComponent()
         usernameAttribute.set(title: Localized.Contact.username, value: $0.1)
@@ -262,10 +293,13 @@ public final class ContactController: UIViewController {
           .store(in: &cancellables)
       }.store(in: &cancellables)
 
-    screenView.confirmedView.clearButton
+    screenView
+      .confirmedView
+      .clearButton
       .publisher(for: .touchUpInside)
-      .sink { [unowned self] in presentClearDrawer() }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        presentClearDrawer()
+      }.store(in: &cancellables)
   }
 
   private func presentClearDrawer() {
@@ -277,7 +311,28 @@ public final class ContactController: UIViewController {
     cancelButton.setStyle(.seeThrough)
     cancelButton.setTitle(Localized.Contact.Clear.cancel, for: .normal)
 
-    let drawer = DrawerController([
+    clearButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didTapClear()
+        }
+      }.store(in: &drawerCancellables)
+
+    cancelButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
       DrawerImage(
         image: Asset.drawerNegative.image
       ),
@@ -297,27 +352,7 @@ public final class ContactController: UIViewController {
         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)
+    ]))
   }
 }
 
@@ -360,7 +395,17 @@ extension ContactController {
       title: Localized.Settings.InfoDrawer.action
     )
 
-    let drawer = DrawerController([
+    actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
       DrawerText(
         font: Fonts.Mulish.bold.font(size: 26.0),
         text: title,
@@ -377,18 +422,7 @@ extension ContactController {
         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() {
@@ -397,7 +431,18 @@ extension ContactController {
       style: .red
     ))
 
-    let drawer = DrawerController([
+    actionButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didTapDelete()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
       DrawerText(
         font: Fonts.Mulish.bold.font(size: 26.0),
         text: Localized.Contact.Delete.Drawer.title,
@@ -411,18 +456,6 @@ extension ContactController {
         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)
+    ]))
   }
 }
diff --git a/Sources/ContactFeature/Controllers/NicknameController.swift b/Sources/ContactFeature/Controllers/NicknameController.swift
index 2492083e2f4ed93fd910acf8a8f80c024117399b..509f2cba9aba1b2c02699dbb96341908d1b6d5fd 100644
--- a/Sources/ContactFeature/Controllers/NicknameController.swift
+++ b/Sources/ContactFeature/Controllers/NicknameController.swift
@@ -46,7 +46,7 @@ public final class NicknameController: UIViewController {
 
     private func setupKeyboard() {
         keyboardListener.keyboardFrameWillChange = { [weak self] keyboard in
-            guard let self = self else { return }
+            guard let self else { return }
 
             let inset = self.view.frame.height - self.view.convert(keyboard.frame, from: nil).minY
 
diff --git a/Sources/ContactFeature/Coordinator/ContactCoordinator.swift b/Sources/ContactFeature/Coordinator/ContactCoordinator.swift
deleted file mode 100644
index 2b366da6b634495937099e42482b3a1cb49337ee..0000000000000000000000000000000000000000
--- a/Sources/ContactFeature/Coordinator/ContactCoordinator.swift
+++ /dev/null
@@ -1,69 +0,0 @@
-import UIKit
-import Shared
-import XXModels
-import ChatFeature
-import Presentation
-
-public protocol ContactCoordinating: AnyObject {
-    func toPhotos(from: UIViewController)
-    func toRequests(from: UIViewController)
-    func toSingleChat(with: Contact, from: UIViewController)
-    func toDrawer(_: UIViewController, from: UIViewController)
-    func toNickname(from: UIViewController, prefilled: String, _: @escaping StringClosure)
-}
-
-public final class ContactCoordinator: ContactCoordinating {
-    var pushPresenter: Presenting = PushPresenter()
-    var modalPresenter: Presenting = ModalPresenter()
-    var bottomPresenter: Presenting = BottomPresenter()
-    var replacePresenter: Presenting = ReplacePresenter(mode: .replaceBackwards(SingleChatController.self))
-
-    var requestsFactory: () -> UIViewController
-    var singleChatFactory: (Contact) -> UIViewController
-    var imagePickerFactory: () -> UIImagePickerController
-    var nicknameFactory: (String, @escaping StringClosure) -> UIViewController
-
-    public init(
-        requestsFactory: @escaping () -> UIViewController,
-        singleChatFactory: @escaping (Contact) -> UIViewController,
-        imagePickerFactory: @escaping () -> UIImagePickerController,
-        nicknameFactory: @escaping (String, @escaping StringClosure) -> UIViewController
-    ) {
-        self.requestsFactory = requestsFactory
-        self.singleChatFactory = singleChatFactory
-        self.imagePickerFactory = imagePickerFactory
-        self.nicknameFactory = nicknameFactory
-    }
-}
-
-public extension ContactCoordinator {
-    func toPhotos(from parent: UIViewController) {
-        let screen = imagePickerFactory()
-        screen.delegate = (parent as? (UIImagePickerControllerDelegate & UINavigationControllerDelegate))
-        screen.allowsEditing = true
-        modalPresenter.present(screen, from: parent)
-    }
-
-    func toNickname(
-        from parent: UIViewController,
-        prefilled: String,
-        _ completion: @escaping StringClosure
-    ) {
-        let screen = nicknameFactory(prefilled, completion)
-        bottomPresenter.present(screen, from: parent)
-    }
-
-    func toRequests(from parent: UIViewController) {
-        let screen = requestsFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toDrawer(_ drawer: UIViewController, from parent: UIViewController) {
-        bottomPresenter.present(drawer, from: parent)
-    }
-
-    func toSingleChat(with contact: Contact, from parent: UIViewController) {
-        let screen = singleChatFactory(contact)
-        replacePresenter.present(screen, from: parent)
-    }
-}
diff --git a/Sources/ContactFeature/ViewModels/ContactViewModel.swift b/Sources/ContactFeature/ViewModels/ContactViewModel.swift
index 3876c0b98eaaa5280e3129956a7a38075df36c53..43e861d7150230e226dcf67b2ec72f2694e0cbe7 100644
--- a/Sources/ContactFeature/ViewModels/ContactViewModel.swift
+++ b/Sources/ContactFeature/ViewModels/ContactViewModel.swift
@@ -105,7 +105,7 @@ final class ContactViewModel {
     contact.authStatus = .requesting
     
     backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       
       do {
         try self.database.saveContact(self.contact)
@@ -149,7 +149,7 @@ final class ContactViewModel {
     contact.authStatus = .requesting
     
     backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       
       do {
         try self.database.saveContact(self.contact)
@@ -193,7 +193,7 @@ final class ContactViewModel {
     contact.authStatus = .confirming
     
     backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       
       do {
         try self.database.saveContact(self.contact)
diff --git a/Sources/ContactListFeature/Controllers/ContactListController.swift b/Sources/ContactListFeature/Controllers/ContactListController.swift
index 0b276e5f97881413d5e8ad561b181674196809b3..a21f9ae92b76a0523e4a5b07eac9a22b2f183340 100644
--- a/Sources/ContactListFeature/Controllers/ContactListController.swift
+++ b/Sources/ContactListFeature/Controllers/ContactListController.swift
@@ -1,11 +1,12 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import DependencyInjection
 
 public final class ContactListController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: ContactListCoordinating
 
   private lazy var screenView = ContactListView()
   private lazy var tableController = ContactListTableController(viewModel)
@@ -65,55 +66,65 @@ public final class ContactListController: UIViewController {
 
     navigationItem.rightBarButtonItem = UIBarButtonItem(customView: rightStack)
 
-    search.snp.makeConstraints { $0.width.equalTo(40) }
+    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.view.snp.makeConstraints {
+      $0.top.equalTo(screenView.topStackView.snp.bottom)
+      $0.left.bottom.right.equalToSuperview()
     }
-
     tableController.didMove(toParent: self)
   }
 
   private func setupBindings() {
-    tableController.didTap
+    tableController
+      .didTap
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in coordinator.toSingleChat(with: $0, from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentChat(contact: $0))
+      }.store(in: &cancellables)
 
-    screenView.requestsButton
+    screenView
+      .requestsButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in coordinator.toRequests(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentRequests())
+      }.store(in: &cancellables)
 
-    screenView.newGroupButton
+    screenView
+      .newGroupButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in coordinator.toNewGroup(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentNewGroup())
+      }.store(in: &cancellables)
 
-    screenView.searchButton
+    screenView
+      .searchButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in coordinator.toSearch(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentSearch(replacing: false))
+      }.store(in: &cancellables)
 
-    viewModel.requestCount
+    viewModel
+      .requestCount
       .receive(on: DispatchQueue.main)
-      .sink { [weak screenView] in screenView?.requestsButton.updateNotification($0) }
-      .store(in: &cancellables)
+      .sink { [weak screenView] in
+        screenView?.requestsButton.updateNotification($0)
+      }.store(in: &cancellables)
 
-    viewModel.contacts
+    viewModel
+      .contacts
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
         screenView.stackView.isHidden = !$0.isEmpty
-
         if $0.isEmpty {
           screenView.bringSubviewToFront(screenView.stackView)
         }
@@ -121,14 +132,14 @@ public final class ContactListController: UIViewController {
   }
 
   @objc private func didTapSearch() {
-    coordinator.toSearch(from: self)
+    navigator.perform(PresentSearch(replacing: false))
   }
 
   @objc private func didTapScan() {
-    coordinator.toScan(from: self)
+    navigator.perform(PresentScan())
   }
 
   @objc private func didTapMenu() {
-    coordinator.toSideMenu(from: self)
+    navigator.perform(PresentMenu(currentItem: .contacts))
   }
 }
diff --git a/Sources/ContactListFeature/Controllers/CreateGroupController.swift b/Sources/ContactListFeature/Controllers/CreateGroupController.swift
index 8f2b2c93626f0390b2713d4f50adf7eb6e145bd2..d772b6307b3364427653b75b5b96dc33467c0b90 100644
--- a/Sources/ContactListFeature/Controllers/CreateGroupController.swift
+++ b/Sources/ContactListFeature/Controllers/CreateGroupController.swift
@@ -2,185 +2,192 @@ import UIKit
 import Shared
 import Combine
 import XXModels
+import XXNavigation
 import DependencyInjection
 
 public final class CreateGroupController: UIViewController {
-    @Dependency private var coordinator: ContactListCoordinating
-
-    private lazy var titleLabel = UILabel()
-    private lazy var createButton = UIButton()
-    private lazy var screenView = CreateGroupView()
-
-    private var selectedElements = [Contact]() {
-        didSet { screenView.tableView.reloadData() }
-    }
-    private let viewModel = CreateGroupViewModel()
-    private var cancellables = Set<AnyCancellable>()
-    private var tableDataSource: UITableViewDiffableDataSource<SectionId, Contact>!
-    private var collectionDataSource: UICollectionViewDiffableDataSource<SectionId, Contact>!
-
-    private var count = 0 {
-        didSet {
-            createButton.isEnabled = count >= 2 && count <= 10
-
-            let text = Localized.CreateGroup.title("\(count)")
-            let attString = NSMutableAttributedString(string: text)
-            attString.addAttribute(.font, value: Fonts.Mulish.semiBold.font(size: 18.0) as Any)
-            attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
-            attString.addAttributes(attributes: [
-                .foregroundColor: Asset.neutralDisabled.color,
-                .font: Fonts.Mulish.regular.font(size: 14.0) as Any
-            ], betweenCharacters: "#")
-
-            titleLabel.attributedText = attString
-            titleLabel.sizeToFit()
-        }
-    }
-
-    public override func loadView() {
-        view = screenView
+  @Dependency var navigator: Navigator
+
+  private lazy var titleLabel = UILabel()
+  private lazy var createButton = UIButton()
+  private lazy var screenView = CreateGroupView()
+
+  private var selectedElements = [Contact]() {
+    didSet { screenView.tableView.reloadData() }
+  }
+  private let viewModel = CreateGroupViewModel()
+  private var cancellables = Set<AnyCancellable>()
+  private var tableDataSource: UITableViewDiffableDataSource<SectionId, Contact>!
+  private var collectionDataSource: UICollectionViewDiffableDataSource<SectionId, Contact>!
+
+  private var count = 0 {
+    didSet {
+      createButton.isEnabled = count >= 2 && count <= 10
+
+      let text = Localized.CreateGroup.title("\(count)")
+      let attString = NSMutableAttributedString(string: text)
+      attString.addAttribute(.font, value: Fonts.Mulish.semiBold.font(size: 18.0) as Any)
+      attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
+      attString.addAttributes(attributes: [
+        .foregroundColor: Asset.neutralDisabled.color,
+        .font: Fonts.Mulish.regular.font(size: 14.0) as Any
+      ], betweenCharacters: "#")
+
+      titleLabel.attributedText = attString
+      titleLabel.sizeToFit()
     }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        navigationController?.navigationBar
-            .customize(backgroundColor: Asset.neutralWhite.color)
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupNavigationBar()
-        setupTableAndCollection()
-        setupBindings()
-
-        count = 0
+  }
+
+  public override func loadView() {
+    view = screenView
+  }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    navigationController?.navigationBar
+      .customize(backgroundColor: Asset.neutralWhite.color)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupNavigationBar()
+    setupTableAndCollection()
+    setupBindings()
+
+    count = 0
+  }
+
+  private func setupNavigationBar() {
+    navigationItem.leftBarButtonItem = UIBarButtonItem(customView: titleLabel)
+    navigationItem.leftItemsSupplementBackButton = true
+
+    createButton.setTitle(Localized.CreateGroup.create, for: .normal)
+    createButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
+    createButton.titleLabel?.font = Fonts.Mulish.semiBold.font(size: 16.0)
+    createButton.setTitleColor(Asset.neutralDisabled.color, for: .disabled)
+    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: createButton)
+  }
+
+  private func setupTableAndCollection() {
+    screenView.tableView.rowHeight = 64.0
+    screenView.tableView.register(AvatarCell.self)
+    screenView.collectionView.register(CreateGroupCollectionCell.self)
+
+    collectionDataSource = UICollectionViewDiffableDataSource<SectionId, Contact>(
+      collectionView: screenView.collectionView
+    ) { [weak viewModel] collectionView, indexPath, contact in
+      let cell: CreateGroupCollectionCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+
+      let title = (contact.nickname ?? contact.username) ?? ""
+      cell.setup(title: title, image: contact.photo)
+      cell.didTapRemove = { viewModel?.didSelect(contact: contact) }
+
+      return cell
     }
 
-    private func setupNavigationBar() {
-        navigationItem.leftBarButtonItem = UIBarButtonItem(customView: titleLabel)
-        navigationItem.leftItemsSupplementBackButton = true
-
-        createButton.setTitle(Localized.CreateGroup.create, for: .normal)
-        createButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
-        createButton.titleLabel?.font = Fonts.Mulish.semiBold.font(size: 16.0)
-        createButton.setTitleColor(Asset.neutralDisabled.color, for: .disabled)
-        navigationItem.rightBarButtonItem = UIBarButtonItem(customView: createButton)
-    }
-
-    private func setupTableAndCollection() {
-        screenView.tableView.rowHeight = 64.0
-        screenView.tableView.register(AvatarCell.self)
-        screenView.collectionView.register(CreateGroupCollectionCell.self)
-
-        collectionDataSource = UICollectionViewDiffableDataSource<SectionId, Contact>(
-            collectionView: screenView.collectionView
-        ) { [weak viewModel] collectionView, indexPath, contact in
-            let cell: CreateGroupCollectionCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-            let title = (contact.nickname ?? contact.username) ?? ""
-            cell.setup(title: title, image: contact.photo)
-            cell.didTapRemove = { viewModel?.didSelect(contact: contact) }
-
-            return cell
-        }
-
-        tableDataSource = DiffEditableDataSource<SectionId, Contact>(
-            tableView: screenView.tableView
-        ) { [weak self] tableView, indexPath, contact in
-            let cell = tableView.dequeueReusableCell(forIndexPath: indexPath, ofType: AvatarCell.self)
-            let title = (contact.nickname ?? contact.username) ?? ""
-
-            cell.setup(title: title, image: contact.photo)
+    tableDataSource = DiffEditableDataSource<SectionId, Contact>(
+      tableView: screenView.tableView
+    ) { [weak self] tableView, indexPath, contact in
+      let cell = tableView.dequeueReusableCell(forIndexPath: indexPath, ofType: AvatarCell.self)
+      let title = (contact.nickname ?? contact.username) ?? ""
 
-            if let selectedElements = self?.selectedElements, selectedElements.contains(contact) {
-                tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
-            } else {
-                tableView.deselectRow(at: indexPath, animated: true)
-            }
+      cell.setup(title: title, image: contact.photo)
 
-            return cell
-        }
+      if let selectedElements = self?.selectedElements, selectedElements.contains(contact) {
+        tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
+      } else {
+        tableView.deselectRow(at: indexPath, animated: true)
+      }
 
-        screenView.tableView.delegate = self
-        screenView.tableView.dataSource = tableDataSource
-        screenView.collectionView.dataSource = collectionDataSource
+      return cell
     }
 
-    private func setupBindings() {
-        let selected = viewModel.selected.share()
-
-        selected
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                screenView.collectionView.isHidden = $0.count < 1
-
-                count = $0.count
-                selectedElements = $0
-            }.store(in: &cancellables)
-
-        selected.map { selectedContacts in
-            var snapshot = NSDiffableDataSourceSnapshot<SectionId, Contact>()
-            let sections = [SectionId()]
-            snapshot.appendSections(sections)
-            sections.forEach { section in snapshot.appendItems(selectedContacts, toSection: section) }
-            return snapshot
-        }
-        .receive(on: DispatchQueue.main)
-        .sink { [unowned self] in collectionDataSource.apply($0) }
-        .store(in: &cancellables)
-
-        viewModel.contacts
-            .map { contacts in
-                var snapshot = NSDiffableDataSourceSnapshot<SectionId, Contact>()
-                let sections = [SectionId()]
-                snapshot.appendSections(sections)
-                sections.forEach { section in snapshot.appendItems(contacts, toSection: section) }
-                return snapshot
-            }
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                tableDataSource.apply($0, animatingDifferences: tableDataSource.snapshot().numberOfItems > 0)
-            }.store(in: &cancellables)
-
-        screenView.searchComponent.textPublisher
-            .removeDuplicates()
-            .sink { [unowned self] in viewModel.filter($0) }
-            .store(in: &cancellables)
-
-        viewModel.info
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toGroupChat(with: $0, from: self) }
-            .store(in: &cancellables)
-
-        createButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                coordinator.toGroupDrawer(
-                    with: count,
-                    from: self, { (name, welcome) in
-                        self.viewModel.create(
-                            name: name,
-                            welcome: welcome,
-                            members: self.selectedElements
-                        )
-                    }
-                )
-            }.store(in: &cancellables)
+    screenView.tableView.delegate = self
+    screenView.tableView.dataSource = tableDataSource
+    screenView.collectionView.dataSource = collectionDataSource
+  }
+
+  private func setupBindings() {
+    let selected = viewModel.selected.share()
+
+    selected
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.collectionView.isHidden = $0.count < 1
+
+        count = $0.count
+        selectedElements = $0
+      }.store(in: &cancellables)
+
+    selected.map { selectedContacts in
+      var snapshot = NSDiffableDataSourceSnapshot<SectionId, Contact>()
+      let sections = [SectionId()]
+      snapshot.appendSections(sections)
+      sections.forEach { section in snapshot.appendItems(selectedContacts, toSection: section) }
+      return snapshot
     }
+    .receive(on: DispatchQueue.main)
+    .sink { [unowned self] in collectionDataSource.apply($0) }
+    .store(in: &cancellables)
+
+    viewModel
+      .contacts
+      .map { contacts in
+        var snapshot = NSDiffableDataSourceSnapshot<SectionId, Contact>()
+        let sections = [SectionId()]
+        snapshot.appendSections(sections)
+        sections.forEach { section in snapshot.appendItems(contacts, toSection: section) }
+        return snapshot
+      }
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        tableDataSource.apply($0, animatingDifferences: tableDataSource.snapshot().numberOfItems > 0)
+      }.store(in: &cancellables)
+
+    screenView
+      .searchComponent
+      .textPublisher
+      .removeDuplicates()
+      .sink { [unowned self] in
+        viewModel.filter($0)
+      }.store(in: &cancellables)
+
+    viewModel
+      .info
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(PresentGroupChat(model: $0))
+      }.store(in: &cancellables)
+
+    createButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+//        coordinator.toGroupDrawer(
+//          with: count,
+//          from: self, { (name, welcome) in
+//            self.viewModel.create(
+//              name: name,
+//              welcome: welcome,
+//              members: self.selectedElements
+//            )
+//          }
+//        )
+      }.store(in: &cancellables)
+  }
 }
 
 extension CreateGroupController: UITableViewDelegate {
-    public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        if let contact = tableDataSource.itemIdentifier(for: indexPath) {
-            viewModel.didSelect(contact: contact)
-        }
+  public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+    if let contact = tableDataSource.itemIdentifier(for: indexPath) {
+      viewModel.didSelect(contact: contact)
     }
+  }
 
-    public func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
-        if let contact = tableDataSource.itemIdentifier(for: indexPath) {
-            viewModel.didSelect(contact: contact)
-        }
+  public func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
+    if let contact = tableDataSource.itemIdentifier(for: indexPath) {
+      viewModel.didSelect(contact: contact)
     }
+  }
 }
diff --git a/Sources/ContactListFeature/Coordinator/ContactListCoordinator.swift b/Sources/ContactListFeature/Coordinator/ContactListCoordinator.swift
deleted file mode 100644
index 650f031d8739feeb64b38ff2befd1f3993937421..0000000000000000000000000000000000000000
--- a/Sources/ContactListFeature/Coordinator/ContactListCoordinator.swift
+++ /dev/null
@@ -1,128 +0,0 @@
-import UIKit
-import Shared
-import XXModels
-import MenuFeature
-import ChatFeature
-import Presentation
-import ContactFeature
-import ScrollViewController
-
-public protocol ContactListCoordinating {
-    func toScan(from: UIViewController)
-    func toSearch(from: UIViewController)
-    func toRequests(from: UIViewController)
-    func toNewGroup(from: UIViewController)
-    func toSideMenu(from: UIViewController)
-    func toContact(_: Contact, from: UIViewController)
-    func toSingleChat(with: Contact, from: UIViewController)
-    func toGroupChat(with: GroupInfo, from: UIViewController)
-    func toGroupDrawer(with: Int, from: UIViewController, _: @escaping (String, String?) -> Void)
-}
-
-public struct ContactListCoordinator: ContactListCoordinating {
-    var pushPresenter: Presenting = PushPresenter()
-    var sidePresenter: Presenting = SideMenuPresenter()
-    var bottomPresenter: Presenting = BottomPresenter()
-    var fullscreenPresenter: Presenting = FullscreenPresenter()
-    var replacePresenter: Presenting = ReplacePresenter(mode: .replaceLast)
-
-    var scanFactory: () -> UIViewController
-    var searchFactory: (String?) -> UIViewController
-    var newGroupFactory: () -> UIViewController
-    var requestsFactory: () -> UIViewController
-    var contactFactory: (Contact) -> UIViewController
-    var singleChatFactory: (Contact) -> UIViewController
-    var groupChatFactory: (GroupInfo) -> UIViewController
-    var sideMenuFactory: (MenuItem, UIViewController) -> UIViewController
-    var groupDrawerFactory: (Int, @escaping (String, String?) -> Void) -> UIViewController
-
-    public init(
-        scanFactory: @escaping () -> UIViewController,
-        searchFactory: @escaping (String?) -> UIViewController,
-        newGroupFactory: @escaping () -> UIViewController,
-        requestsFactory: @escaping () -> UIViewController,
-        contactFactory: @escaping (Contact) -> UIViewController,
-        singleChatFactory: @escaping (Contact) -> UIViewController,
-        groupChatFactory: @escaping (GroupInfo) -> UIViewController,
-        sideMenuFactory: @escaping (MenuItem, UIViewController) -> UIViewController,
-        groupDrawerFactory: @escaping (Int, @escaping (String, String?) -> Void) -> UIViewController
-    ) {
-        self.scanFactory = scanFactory
-        self.searchFactory = searchFactory
-        self.contactFactory = contactFactory
-        self.newGroupFactory = newGroupFactory
-        self.requestsFactory = requestsFactory
-        self.sideMenuFactory = sideMenuFactory
-        self.groupChatFactory = groupChatFactory
-        self.singleChatFactory = singleChatFactory
-        self.groupDrawerFactory = groupDrawerFactory
-    }
-}
-
-public extension ContactListCoordinator {
-    func toGroupDrawer(
-        with count: Int,
-        from parent: UIViewController,
-        _ completion: @escaping (String, String?) -> Void
-    ) {
-        let screen = ScrollViewController.embedding(groupDrawerFactory(count, completion))
-        fullscreenPresenter.present(screen, from: parent)
-    }
-
-    func toSingleChat(
-        with contact: Contact,
-        from parent: UIViewController
-    ) {
-        let screen = singleChatFactory(contact)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toScan(from parent: UIViewController) {
-        let screen = scanFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toSearch(from parent: UIViewController) {
-        let screen = searchFactory(nil)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toRequests(from parent: UIViewController) {
-        let screen = requestsFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toNewGroup(from parent: UIViewController) {
-        let screen = newGroupFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toContact(_ contact: Contact, from parent: UIViewController) {
-        let screen = contactFactory(contact)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toGroupChat(with info: GroupInfo, from parent: UIViewController) {
-        let screen = groupChatFactory(info)
-        replacePresenter.present(screen, from: parent)
-    }
-
-    func toSideMenu(from parent: UIViewController) {
-        let screen = sideMenuFactory(.contacts, parent)
-        sidePresenter.present(screen, from: parent)
-    }
-}
-
-extension ScrollViewController {
-    static func embedding(_ viewController: UIViewController) -> ScrollViewController {
-        let scrollViewController = ScrollViewController()
-        scrollViewController.addChild(viewController)
-        scrollViewController.contentView = viewController.view
-        scrollViewController.wrapperView.handlesTouchesOutsideContent = false
-        scrollViewController.wrapperView.alignContentToBottom = true
-        scrollViewController.scrollView.bounces = false
-
-        viewController.didMove(toParent: scrollViewController)
-        return scrollViewController
-    }
-}
diff --git a/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift b/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift
index 724aa19f108c22ff8164bdfae69a38ddbd92c8e1..d24fd2e9f37c0477ff46efacbfd5606d38c243b2 100644
--- a/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift
+++ b/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift
@@ -87,7 +87,7 @@ final class CreateGroupViewModel {
     hudController.show()
 
     backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
 
       do {
         let report = try self.groupManager.makeGroup(
diff --git a/Sources/Countries/Country.swift b/Sources/Countries/Country.swift
deleted file mode 100644
index acb0bae1d468c7cf3abba10f20a59e7c8d803949..0000000000000000000000000000000000000000
--- a/Sources/Countries/Country.swift
+++ /dev/null
@@ -1,45 +0,0 @@
-import os
-import Foundation
-
-public struct Country {
-    public var name: String
-    public var code: String
-    public var flag: String
-    public var regex: String
-    public var prefix: String
-    public var example: String
-    public var prefixWithFlag: String { "\(flag) \(prefix)" }
-
-    public static func fromMyPhone() -> Self {
-        let all = all()
-
-        guard let country = all.filter({ $0.code == Locale.current.regionCode }).first else {
-            return all.filter { $0.code == "US" }.first!
-        }
-
-        return country
-    }
-
-    public static func all() -> [Self] {
-        guard let url = Bundle.module.url(forResource: "country_codes", withExtension: "json"),
-              let data = try? Data(contentsOf: url),
-              let countries = try? JSONDecoder().decode([Country].self, from: data) else {
-                  fatalError("Can't handle country codes json")
-              }
-
-        return countries
-    }
-
-    public static func findFrom(_ number: String) -> Self {
-        all().first { country in
-            let start = number.index(number.startIndex, offsetBy: number.count - 2)
-            let end = number.index(start, offsetBy: number.count - (number.count - 2))
-
-            return country.code == String(number[start ..< end])
-        }!
-    }
-}
-
-extension Country: Hashable {}
-extension Country: Equatable {}
-extension Country: Decodable {}
diff --git a/Sources/Countries/CountryListController.swift b/Sources/Countries/CountryListController.swift
index 5956946f6ea8f5edb51740f0204c34716a300519..4a526743c57c383560f5221759166a26111ac9e8 100644
--- a/Sources/Countries/CountryListController.swift
+++ b/Sources/Countries/CountryListController.swift
@@ -1,21 +1,22 @@
-import os
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import DependencyInjection
 
-public final class CountryListController: UIViewController {
+public final class CountryListController: UIViewController, UITableViewDelegate {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
 
   private lazy var screenView = CountryListView()
 
-  private var didChoose: ((Country) -> Void)!
+  private let completion: (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
+  public init(_ completion: @escaping (Country) -> Void) {
+    self.completion = completion
     super.init(nibName: nil, bundle: nil)
   }
 
@@ -25,7 +26,6 @@ public final class CountryListController: UIViewController {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = ""
     barStylist.styleSubject.send(.darkContent)
-
     navigationController?.navigationBar.customize(
       backgroundColor: Asset.neutralWhite.color,
       shadowColor: Asset.neutralDisabled.color
@@ -38,28 +38,16 @@ public final class CountryListController: UIViewController {
 
   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)
+    screenView
+      .tableView
+      .register(CountryListCell.self)
 
-    navigationItem.leftBarButtonItem = UIBarButtonItem(customView: title)
-    navigationItem.leftItemsSupplementBackButton = true
-  }
-
-  private func setupBindings() {
-    viewModel.countries
+    viewModel
+      .countries
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in dataSource.apply($0, animatingDifferences: false) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        dataSource.apply($0, animatingDifferences: false)
+      }.store(in: &cancellables)
 
     dataSource = UITableViewDiffableDataSource<SectionId, Country>(
       tableView: screenView.tableView
@@ -71,22 +59,23 @@ public final class CountryListController: UIViewController {
       return cell
     }
 
-    screenView.searchComponent
+    screenView
+      .searchComponent
       .textPublisher
       .removeDuplicates()
-      .sink { [unowned self] in viewModel.didSearchFor($0) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        viewModel.didSearchFor($0)
+      }.store(in: &cancellables)
 
     screenView.tableView.delegate = self
     screenView.tableView.dataSource = dataSource
+    viewModel.fetchCountryList()
   }
 
   public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
     if let country = dataSource.itemIdentifier(for: indexPath) {
-      didChoose(country)
-      navigationController?.popViewController(animated: true)
+      completion(country)
+      navigator.perform(DismissModal(from: self))
     }
   }
 }
-
-extension CountryListController: UITableViewDelegate {}
diff --git a/Sources/LaunchFeature/LaunchController.swift b/Sources/LaunchFeature/LaunchController.swift
index 2eb224ca240c4dbb8e1f55c0ba4003c8d28eeb1b..8207138c6a4581ac6fc6d4a3a96943b2a7dc6a39 100644
--- a/Sources/LaunchFeature/LaunchController.swift
+++ b/Sources/LaunchFeature/LaunchController.swift
@@ -1,7 +1,6 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
 import PushFeature
 import XXNavigation
 import DrawerFeature
@@ -10,8 +9,9 @@ import DependencyInjection
 public final class LaunchController: UIViewController {
   @Dependency var navigator: Navigator
 
-  private let viewModel = LaunchViewModel()
   private lazy var screenView = LaunchView()
+
+  private let viewModel = LaunchViewModel()
   public var pendingPushRoute: PushRouter.Route?
   private var cancellables = Set<AnyCancellable>()
   private var drawerCancellables = Set<AnyCancellable>()
@@ -123,6 +123,7 @@ public final class LaunchController: UIViewController {
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) {
+          self.drawerCancellables.removeAll()
           self.viewModel.didRefuseUpdating()
         }
       }.store(in: &drawerCancellables)
diff --git a/Sources/LaunchFeature/LaunchViewModel+Messenger.swift b/Sources/LaunchFeature/LaunchViewModel+Messenger.swift
index 2971fe40e65127804228af2c8b0a06df90ea3311..364be5cf10c6295580e83fc02ec1ccd06ad36651 100644
--- a/Sources/LaunchFeature/LaunchViewModel+Messenger.swift
+++ b/Sources/LaunchFeature/LaunchViewModel+Messenger.swift
@@ -440,6 +440,5 @@ extension LaunchViewModel {
       try? messenger.resumeBackup()
     }
     // TODO: Biometric auth
-
   }
 }
diff --git a/Sources/MenuFeature/Controllers/MenuController.swift b/Sources/MenuFeature/Controllers/MenuController.swift
index dbd587248752db7580356c9f40a79541110867f3..b14abe7b5a09efa282f8ee00e4602393473389fc 100644
--- a/Sources/MenuFeature/Controllers/MenuController.swift
+++ b/Sources/MenuFeature/Controllers/MenuController.swift
@@ -1,39 +1,23 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 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
-}
-
 public final class MenuController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: MenuCoordinating
 
   private lazy var screenView = MenuView()
 
-  private let previousItem: MenuItem
+  private let currentItem: 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
+  public init(_ currentItem: MenuItem) {
+    self.currentItem = currentItem
     super.init(nibName: nil, bundle: nil)
   }
 
@@ -45,13 +29,11 @@ public final class MenuController: UIViewController {
 
   public override func viewDidLoad() {
     super.viewDidLoad()
-
     screenView.headerView.set(
       username: viewModel.username,
       image: viewModel.avatar
     )
-
-    screenView.select(item: previousItem)
+    screenView.select(item: currentItem)
     screenView.xxdkVersionLabel.text = "XXDK \(viewModel.xxdk)"
     screenView.buildLabel.text = Localized.Menu.build(viewModel.build)
     screenView.versionLabel.text = Localized.Menu.version(viewModel.version)
@@ -69,72 +51,81 @@ public final class MenuController: UIViewController {
   }
 
   private func setupBindings() {
-    screenView.headerView.scanButton
+    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)
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self, self.currentItem != .scan else { return }
+          self.navigator.perform(PresentScan())
         }
       }.store(in: &cancellables)
 
-    screenView.headerView.nameButton
+    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)
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self, self.currentItem != .profile else { return }
+          self.navigator.perform(PresentProfile())
         }
       }.store(in: &cancellables)
 
-    screenView.scanButton
+    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)
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self, self.currentItem != .scan else { return }
+          self.navigator.perform(PresentScan())
         }
       }.store(in: &cancellables)
 
-    screenView.chatsButton
+    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)
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self, self.currentItem != .chats else { return }
+          self.navigator.perform(PresentChatList())
         }
       }.store(in: &cancellables)
 
-    screenView.contactsButton
+    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)
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self, self.currentItem != .contacts else { return }
+          self.navigator.perform(PresentContactList())
         }
       }.store(in: &cancellables)
 
-    screenView.settingsButton
+    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)
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self, self.currentItem != .settings else { return }
+          self.navigator.perform(PresentSettings())
         }
       }.store(in: &cancellables)
 
-    screenView.dashboardButton
+    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 }
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self, self.currentItem != .dashboard else { return }
           self.presentDrawer(
             title: Localized.ChatList.Dashboard.title,
             subtitle: Localized.ChatList.Dashboard.subtitle,
@@ -145,22 +136,24 @@ public final class MenuController: UIViewController {
         }
       }.store(in: &cancellables)
 
-    screenView.requestsButton
+    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)
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self, self.currentItem != .requests else { return }
+          self.navigator.perform(PresentRequests())
         }
       }.store(in: &cancellables)
 
-    screenView.joinButton
+    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 }
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self, self.currentItem != .join else { return }
           self.presentDrawer(
             title: Localized.ChatList.Join.title,
             subtitle: Localized.ChatList.Join.subtitle,
@@ -171,23 +164,25 @@ public final class MenuController: UIViewController {
         }
       }.store(in: &cancellables)
 
-    screenView.shareButton
+    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
-          )
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self, self.currentItem != .share else { return }
+          self.navigator.perform(PresentActivitySheet(items: [
+            Localized.Menu.shareContent(self.viewModel.referralDeeplink)
+          ]))
         }
       }.store(in: &cancellables)
 
-    viewModel.requestCount
+    viewModel
+      .requestCount
       .receive(on: DispatchQueue.main)
-      .sink { [weak screenView] in screenView?.requestsButton.updateNotification($0) }
-      .store(in: &cancellables)
+      .sink { [weak screenView] in
+        screenView?.requestsButton.updateNotification($0)
+      }.store(in: &cancellables)
   }
 
   private func presentDrawer(
@@ -201,7 +196,18 @@ public final class MenuController: UIViewController {
       style: .red
     ))
 
-    let drawer = DrawerController([
+    actionButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          action()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
       DrawerText(
         font: Fonts.Mulish.bold.font(size: 26.0),
         text: title,
@@ -218,17 +224,6 @@ public final class MenuController: UIViewController {
         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/MenuFeature/Coordinator/MenuCoordinator.swift b/Sources/MenuFeature/Coordinator/MenuCoordinator.swift
deleted file mode 100644
index 3e7d20cc85f6a4afa7e50e2f8133bdf041f5ace6..0000000000000000000000000000000000000000
--- a/Sources/MenuFeature/Coordinator/MenuCoordinator.swift
+++ /dev/null
@@ -1,73 +0,0 @@
-import UIKit
-import Presentation
-
-public protocol MenuCoordinating {
-    func toFlow(_ item: MenuItem, from: UIViewController)
-    func toDrawer(_: UIViewController, from: UIViewController)
-    func toActivityController(with: [Any], from: UIViewController)
-}
-
-public struct MenuCoordinator: MenuCoordinating {
-    var modalPresenter: Presenting = ModalPresenter()
-    var bottomPresenter: Presenting = BottomPresenter()
-    var replacePresenter: Presenting = ReplacePresenter()
-
-    var scanFactory: () -> UIViewController
-    var chatsFactory: () -> UIViewController
-    var profileFactory: () -> UIViewController
-    var settingsFactory: () -> UIViewController
-    var contactsFactory: () -> UIViewController
-    var requestsFactory: () -> UIViewController
-    var activityControllerFactory: ([Any]) -> UIViewController
-    = { UIActivityViewController(activityItems: $0, applicationActivities: nil) }
-
-    public init(
-        scanFactory: @escaping () -> UIViewController,
-        chatsFactory: @escaping () -> UIViewController,
-        profileFactory: @escaping () -> UIViewController,
-        settingsFactory: @escaping () -> UIViewController,
-        contactsFactory: @escaping () -> UIViewController,
-        requestsFactory: @escaping () -> UIViewController
-    ) {
-        self.scanFactory = scanFactory
-        self.chatsFactory = chatsFactory
-        self.profileFactory = profileFactory
-        self.settingsFactory = settingsFactory
-        self.contactsFactory = contactsFactory
-        self.requestsFactory = requestsFactory
-    }
-}
-
-public extension MenuCoordinator {
-    func toDrawer(_ drawer: UIViewController, from parent: UIViewController) {
-        bottomPresenter.present(drawer, from: parent)
-    }
-
-    func toFlow(_ item: MenuItem, from parent: UIViewController) {
-        let controller: UIViewController
-
-        switch item {
-        case .scan:
-            controller = scanFactory()
-        case .chats:
-            controller = chatsFactory()
-        case .profile:
-            controller = profileFactory()
-        case .contacts:
-            controller = contactsFactory()
-        case .requests:
-            controller = requestsFactory()
-        case .settings:
-            controller = settingsFactory()
-        default:
-            fatalError()
-        }
-
-        replacePresenter.present(controller, from: parent)
-    }
-
-    func toActivityController(with items: [Any], from parent: UIViewController) {
-        let screen = activityControllerFactory(items)
-        modalPresenter.present(screen, from: parent)
-    }
-}
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift b/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift
index 82044ac6f26b271bc9977519260ed1370b3a8d6e..4fd0f373363cab887e9980fb224c5fc18874065c 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift
@@ -1,7 +1,6 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
 import XXNavigation
 import DrawerFeature
 import DependencyInjection
@@ -142,9 +141,20 @@ public final class OnboardingCodeController: UIViewController {
 
   private func presentInfo(title: String, subtitle: String) {
     let actionButton = CapsuleButton()
-    actionButton.set(style: .seeThrough, title: Localized.Settings.InfoDrawer.action)
+    actionButton.set(
+      style: .seeThrough,
+      title: Localized.Settings.InfoDrawer.action
+    )
+    actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) {
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-    let drawer = DrawerController([
+    navigator.perform(PresentDrawer(items: [
       DrawerText(
         font: Fonts.Mulish.bold.font(size: 26.0),
         text: title,
@@ -164,17 +174,6 @@ public final class OnboardingCodeController: UIViewController {
         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)
-
-//    navigator.perform(PresentDrawer())
+    ]))
   }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift b/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
index 3844b24cd957422f2736e76db95e529e13fbbc07..0c52a7a14872486a1d1ca2cb82bf655ad4255e75 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
@@ -1,7 +1,6 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
 import XXNavigation
 import DrawerFeature
 import DependencyInjection
@@ -20,13 +19,13 @@ public final class OnboardingEmailController: UIViewController {
 
   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()
-    navigationItem.backButtonTitle = " "
     setupScrollView()
     setupBindings()
     screenView.didTapInfo = { [weak self] in
@@ -114,43 +113,32 @@ public final class OnboardingEmailController: UIViewController {
       style: .seeThrough,
       title: Localized.Settings.InfoDrawer.action
     )
-
-//    navigator.perform(PresentDrawer([
-//      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)
+    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()
-        //      }
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) {
+          self.drawerCancellables.removeAll()
+        }
       }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
+      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()
+      ])
+    ]))
   }
 }
-
-  //        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)
-  //        }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift b/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
index 1e64773787bb8bb46eaebb12ae86a5134a6c8166..62c8d84656005f3915f7000ec5a3dc09b37ee2b4 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
@@ -1,7 +1,6 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
 import XXNavigation
 import DrawerFeature
 import DependencyInjection
@@ -20,13 +19,13 @@ public final class OnboardingPhoneController: UIViewController {
 
   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()
-    navigationItem.backButtonTitle = " "
     setupScrollView()
     setupBindings()
     screenView.didTapInfo = { [weak self] in
@@ -93,7 +92,11 @@ public final class OnboardingPhoneController: UIViewController {
       .codePublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentCountryList())
+        navigator.perform(PresentCountryList(completion: { [weak self] in
+          guard let self else { return }
+          self.navigator.perform(DismissModal(from: self))
+          self.viewModel.didChooseCountry($0)
+        }))
       }.store(in: &cancellables)
 
     viewModel
@@ -132,8 +135,16 @@ public final class OnboardingPhoneController: UIViewController {
       style: .seeThrough,
       title: Localized.Settings.InfoDrawer.action
     )
+    actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) {
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-    let drawer = DrawerController([
+    navigator.perform(PresentDrawer(items: [
       DrawerText(
         font: Fonts.Mulish.bold.font(size: 26.0),
         text: title,
@@ -150,27 +161,6 @@ public final class OnboardingPhoneController: UIViewController {
         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)
-
-//    navigator.perform(PresentDrawer())
+    ]))
   }
 }
-
-//        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)
-//        }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift b/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
index ac5df16e70833d47132b4c0f4ab8ac8d20c5c486..c6307fc9595a1b87e25b352622aa01e4355cbc52 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Combine
-import Navigation
 import XXNavigation
 import DependencyInjection
 
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift b/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
index 7edb740b5feebeb134d655e4fdfc76d90d9739b5..ef80c6594b2d28cdcea31c9d2c7b014999f2e5ee 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
@@ -1,7 +1,6 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
 import XXNavigation
 import DrawerFeature
 import DependencyInjection
@@ -115,8 +114,16 @@ public final class OnboardingUsernameController: UIViewController {
       style: .seeThrough,
       title: Localized.Settings.InfoDrawer.action
     )
+    actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) {
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-    let drawer = DrawerController([
+    navigator.perform(PresentDrawer(items: [
       DrawerText(
         font: Fonts.Mulish.bold.font(size: 26.0),
         text: title,
@@ -133,17 +140,6 @@ public final class OnboardingUsernameController: UIViewController {
         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)
-
-//    navigator.perform(PresentDrawer())
+    ]))
   }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift b/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
index 69033a19f3555a189f36d0094fceebdcc34ab600..0aaa842ae2c5a2171e91b72d0082bda4aeb8f192 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
@@ -2,7 +2,6 @@ import UIKit
 import Shared
 import Combine
 import Defaults
-import Navigation
 import XXNavigation
 import DrawerFeature
 import DependencyInjection
@@ -29,12 +28,26 @@ public final class OnboardingWelcomeController: UIViewController {
 
   public override func viewDidLoad() {
     super.viewDidLoad()
-    setupBindings()
+    screenView.setupTitle(
+      Localized.Onboarding.Welcome.title(username)
+    )
+    screenView
+      .continueButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        navigator.perform(PresentOnboardingEmail())
+      }.store(in: &cancellables)
 
-    screenView.setupTitle(Localized.Onboarding.Welcome.title(username))
+    screenView
+      .skipButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        navigator.perform(PresentChatList())
+      }.store(in: &cancellables)
 
     screenView.didTapInfo = { [weak self] in
-      self?.presentInfo(
+      guard let self else { return }
+      self.presentInfo(
         title: Localized.Onboarding.Welcome.Info.title,
         subtitle: Localized.Onboarding.Welcome.Info.subtitle,
         urlString: "https://links.xx.network/ud"
@@ -42,57 +55,42 @@ public final class OnboardingWelcomeController: UIViewController {
     }
   }
 
-  private func setupBindings() {
-    screenView.continueButton.publisher(for: .touchUpInside)
-      .sink { [unowned self] in
-        navigator.perform(PresentOnboardingEmail())
-      }.store(in: &cancellables)
-
-    screenView.skipButton.publisher(for: .touchUpInside)
-      .sink { [unowned self] in
-        navigator.perform(PresentChatList())
-      }.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([
-//      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)
-//
-//    navigator.perform(PresentDrawer())
+    let actionButton = CapsuleButton()
+    actionButton.set(
+      style: .seeThrough,
+      title: Localized.Settings.InfoDrawer.action
+    )
+    actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) {
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
+      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()
+      ])
+    ]))
   }
 }
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingCodeViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingCodeViewModel.swift
index 47fde15f13ce19fb1767eecaf97b8efc8389a36a..98826365d3d83ecc8dc78367bf6de3db72475fbc 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingCodeViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingCodeViewModel.swift
@@ -52,7 +52,7 @@ final class OnboardingCodeViewModel {
     guard stateSubject.value.resendDebouncer == 0 else { return }
     stateSubject.value.resendDebouncer = 60
     timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {  [weak self] in
-      guard let self = self, self.stateSubject.value.resendDebouncer > 0 else {
+      guard let self, self.stateSubject.value.resendDebouncer > 0 else {
         $0.invalidate()
         return
       }
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift
index ad07d4a74bd7f42300b9577d8a66c3615f9482e0..29c0f4b2124e3ea7447fbf3402165fc284ba5bcd 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift
@@ -36,7 +36,7 @@ final class OnboardingEmailViewModel {
   func didTapNext() {
     hudController.show()
     scheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       do {
         let confirmationId = try self.messenger.ud.get()!.sendRegisterFact(
           .init(type: .email, value: self.stateSubject.value.input)
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift
index 435d12a9ade3c59eefb4d977ebdabd68765e22e6..4f66f0bb6ff68da0c5ff40746d47cf8e4bb71c9d 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift
@@ -44,7 +44,7 @@ final class OnboardingPhoneViewModel {
   func didTapNext() {
     hudController.show()
     scheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       let content = "\(self.stateSubject.value.input)\(self.stateSubject.value.country.code)"
       do {
         let confirmationId = try self.messenger.ud.get()!.sendRegisterFact(
diff --git a/Sources/Permissions/RequestPermissionController.swift b/Sources/Permissions/RequestPermissionController.swift
index d424df1507181051669db9b0eac0b93c7033f663..cde2e784397cf81ebb99c8e43062e1d3376ea39f 100644
--- a/Sources/Permissions/RequestPermissionController.swift
+++ b/Sources/Permissions/RequestPermissionController.swift
@@ -1,43 +1,42 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import DependencyInjection
 
-public enum PermissionType {
-  case camera
-  case library
-  case microphone
-}
-
 public final class RequestPermissionController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
   @Dependency var permissions: PermissionHandling
 
   private lazy var screenView = RequestPermissionView()
 
-  private var type: PermissionType!
+  private let permissionType: PermissionType
   private var cancellables = Set<AnyCancellable>()
 
   public override func loadView() {
     view = screenView
   }
 
+  public init(_ permissionType: PermissionType) {
+    self.permissionType = permissionType
+    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)
+    navigationController?.navigationBar
+      .customize(backgroundColor: Asset.neutralWhite.color)
   }
 
   public override func viewDidLoad() {
     super.viewDidLoad()
-    setupBindings()
-  }
 
-  public func setup(type: PermissionType) {
-    self.type = type
-
-    switch type {
+    switch permissionType {
     case .camera:
       screenView.setup(
         title: Localized.Chat.Actions.Permission.Camera.title,
@@ -57,43 +56,44 @@ public final class RequestPermissionController: UIViewController {
         image: Asset.permissionMicrophone.image
       )
     }
-  }
 
-  private func setupBindings() {
-    screenView.notNowButton
+    screenView
+      .notNowButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [weak self] in
-        self?.navigationController?.popViewController(animated: true)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self))
       }.store(in: &cancellables)
 
-    screenView.continueButton
+    screenView
+      .continueButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        switch type {
+        switch permissionType {
         case .camera:
           permissions.requestCamera { [weak self] _ in
-            DispatchQueue.main.async {
-              self?.navigationController?.popViewController(animated: true)
-            }
+            guard let self else { return }
+            self.shouldDismissModal()
           }
         case .library:
           permissions.requestPhotos { [weak self] _ in
-            DispatchQueue.main.async {
-              self?.navigationController?.popViewController(animated: true)
-            }
+            guard let self else { return }
+            self.shouldDismissModal()
           }
         case .microphone:
           permissions.requestMicrophone { [weak self] _ in
-            DispatchQueue.main.async {
-              self?.navigationController?.popViewController(animated: true)
-            }
+            guard let self else { return }
+            self.shouldDismissModal()
           }
-        case .none:
-          break
         }
       }.store(in: &cancellables)
   }
 
+  private func shouldDismissModal() {
+    DispatchQueue.main.async { [weak self] in
+      guard let self else { return }
+      self.navigator.perform(DismissModal(from: self))
+    }
+  }
 }
diff --git a/Sources/ProfileFeature/Controllers/ProfileCodeController.swift b/Sources/ProfileFeature/Controllers/ProfileCodeController.swift
index 60036d37c7fb75b60eff10ef9ed16ba81abe27a3..dedb64d4e5592204a74587a7c63f0653dc958867 100644
--- a/Sources/ProfileFeature/Controllers/ProfileCodeController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfileCodeController.swift
@@ -1,7 +1,6 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
 import XXNavigation
 import DependencyInjection
 import ScrollViewController
@@ -18,13 +17,6 @@ public final class ProfileCodeController: UIViewController {
   private let viewModel: ProfileCodeViewModel
   private var cancellables = Set<AnyCancellable>()
 
-  public override func viewWillAppear(_ animated: Bool) {
-    super.viewWillAppear(animated)
-    navigationItem.backButtonTitle = ""
-    navigationController?.navigationBar
-      .customize(backgroundColor: Asset.neutralWhite.color)
-  }
-
   public init(
     _ isEmail: Bool,
     _ content: String,
@@ -42,38 +34,50 @@ public final class ProfileCodeController: UIViewController {
 
   required init?(coder: NSCoder) { nil }
 
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    navigationController?.navigationBar
+      .customize(backgroundColor: Asset.neutralWhite.color)
+  }
+
   public override func viewDidLoad() {
     super.viewDidLoad()
     setupScrollView()
     setupBindings()
 
-//    var content: String!
-//
-//    if confirmation.isEmail {
-//      content = confirmation.content
-//    } else {
-//      let country = Country.findFrom(confirmation.content)
-//      content = "\(country.prefix)\(confirmation.content.dropLast(2))"
-//    }
-//
-//    screenView.set(content, isEmail: confirmation.isEmail)
+    if isEmail {
+      screenView.set(content, isEmail: true)
+    } else {
+      let country = Country.findFrom(content)
+      screenView.set(
+        "\(country.prefix)\(content.dropLast(2))",
+        isEmail: false
+      )
+    }
   }
 
   private func setupScrollView() {
     addChild(scrollViewController)
     view.addSubview(scrollViewController.view)
-    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.view.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+    }
     scrollViewController.didMove(toParent: self)
     scrollViewController.contentView = screenView
     scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
   }
 
   private func setupBindings() {
-    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)
 
-    viewModel.statePublisher
+    viewModel
+      .statePublisher
       .map(\.status)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
@@ -86,29 +90,46 @@ public final class ProfileCodeController: UIViewController {
         }
       }.store(in: &cancellables)
 
-    screenView.saveButton
+    screenView
+      .saveButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in viewModel.didTapNext() }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        viewModel.didTapNext()
+      }.store(in: &cancellables)
 
-    viewModel.statePublisher
+    viewModel
+      .statePublisher
       .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)
+          screenView.resendButton.setTitle(
+            Localized.Profile.Code.resend(""), for: .normal
+          )
         } else {
-          screenView.resendButton.setTitle(Localized.Profile.Code.resend("(\($0))"), for: .disabled)
+          screenView.resendButton.setTitle(
+            Localized.Profile.Code.resend("(\($0))"), for: .disabled
+          )
         }
       }.store(in: &cancellables)
 
-    screenView.resendButton
+    screenView
+      .resendButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in viewModel.didTapResend() }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        viewModel.didTapResend()
+      }.store(in: &cancellables)
+
+    viewModel
+      .statePublisher
+      .map(\.didConfirm)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        guard let navigationController, $0 == true else { return }
+        navigator.perform(PopToRoot(on: navigationController))
+      }.store(in: &cancellables)
   }
 }
diff --git a/Sources/ProfileFeature/Controllers/ProfileController.swift b/Sources/ProfileFeature/Controllers/ProfileController.swift
index 58a74cd0a6cca98ed8c29fa4520abc223e7466a0..49ac0ea4aabb9328ee34b4059e623b8f46840c3d 100644
--- a/Sources/ProfileFeature/Controllers/ProfileController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfileController.swift
@@ -1,12 +1,13 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 
 public final class ProfileController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: ProfileCoordinating
 
   private lazy var screenView = ProfileView()
 
@@ -64,7 +65,7 @@ public final class ProfileController: UIViewController {
               self.viewModel.didTapDelete(isEmail: true)
             }
         } else {
-          coordinator.toEmail(from: self)
+          navigator.perform(PresentProfileEmail())
         }
       }.store(in: &cancellables)
 
@@ -86,17 +87,22 @@ public final class ProfileController: UIViewController {
               self.viewModel.didTapDelete(isEmail: false)
             }
         } else {
-          coordinator.toPhone(from: self)
+          navigator.perform(PresentProfilePhone())
         }
       }.store(in: &cancellables)
 
-    screenView.cardComponent.avatarView.editButton
+    screenView
+      .cardComponent
+      .avatarView
+      .editButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in viewModel.didRequestLibraryAccess() }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        viewModel.didRequestLibraryAccess()
+      }.store(in: &cancellables)
 
-    viewModel.navigation
+    viewModel
+      .navigation
       .receive(on: DispatchQueue.main)
       .removeDuplicates()
       .sink { [unowned self] in
@@ -106,38 +112,43 @@ public final class ProfileController: UIViewController {
             title: Localized.Profile.Photo.title,
             subtitle: Localized.Profile.Photo.subtitle,
             actionTitle: Localized.Profile.Photo.continue) {
-              self.coordinator.toPhotos(from: self)
-            }
+              self.navigator.perform(PresentPhotoLibrary())
+          }
         case .libraryPermission:
-          coordinator.toPermission(type: .library, from: self)
+          self.navigator.perform(PresentPermissionRequest(type: .library))
         case .none:
           break
         }
-
         viewModel.didNavigateSomewhere()
       }.store(in: &cancellables)
 
-    viewModel.state
+    viewModel
+      .state
       .map(\.email)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in screenView.emailView.set(value: $0) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        screenView.emailView.set(value: $0)
+      }.store(in: &cancellables)
 
-    viewModel.state
+    viewModel
+      .state
       .map(\.phone)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in screenView.phoneView.set(value: $0) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        screenView.phoneView.set(value: $0)
+      }.store(in: &cancellables)
 
-    viewModel.state
+    viewModel
+      .state
       .map(\.photo)
       .compactMap { $0 }
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in screenView.cardComponent.image = $0 }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        screenView.cardComponent.image = $0
+      }.store(in: &cancellables)
   }
 
   private func presentDrawer(
@@ -151,7 +162,18 @@ public final class ProfileController: UIViewController {
       style: .red
     ))
 
-    let drawer = DrawerController([
+    actionButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          action()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
       DrawerText(
         font: Fonts.Mulish.bold.font(size: 26.0),
         text: title,
@@ -168,24 +190,11 @@ public final class ProfileController: UIViewController {
         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)
+    ]))
   }
 
   @objc private func didTapMenu() {
-    coordinator.toSideMenu(from: self)
+    navigator.perform(PresentMenu(currentItem: .profile))
   }
 }
 
diff --git a/Sources/ProfileFeature/Controllers/ProfileEmailController.swift b/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
index 4607733668aff428fbbd43c074b03ece88244039..3bfa34e1bdcc4435324485cf9ad8f525cbeb71fa 100644
--- a/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
@@ -1,12 +1,13 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import DependencyInjection
 import ScrollViewController
 
 public final class ProfileEmailController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: ProfileCoordinating
 
   private lazy var screenView = ProfileEmailView()
   private lazy var scrollViewController = ScrollViewController()
@@ -18,8 +19,7 @@ public final class ProfileEmailController: UIViewController {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = ""
     barStylist.styleSubject.send(.darkContent)
-    navigationController?.navigationBar
-      .customize(backgroundColor: Asset.neutralWhite.color)
+    navigationController?.navigationBar.customize(backgroundColor: Asset.neutralWhite.color)
   }
 
   public override func viewDidLoad() {
@@ -56,19 +56,17 @@ public final class ProfileEmailController: UIViewController {
 
     viewModel
       .statePublisher
-      .map(\.confirmationId)
       .receive(on: DispatchQueue.main)
-      .compactMap { $0 }
       .sink { [unowned self] in
+        guard let id = $0.confirmationId else { return }
         viewModel.clearUp()
-//        coordinator.toCode(with: $0, from: self) { _, _ in
-//          if let viewControllers = self.navigationController?.viewControllers {
-//            self.navigationController?.popToViewController(
-//              viewControllers[viewControllers.count - 3],
-//              animated: true
-//            )
-//          }
-//        }
+        navigator.perform(
+          PresentProfileCode(
+            isEmail: true,
+            content: $0.input,
+            confirmationId: id
+          )
+        )
       }.store(in: &cancellables)
 
     viewModel
diff --git a/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift b/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
index 1708fc9e3211c274b616f89db6b4e23e22961bae..60e1aef40eb7b3dd7a5f5c4befa4d01f49529840 100644
--- a/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
@@ -1,12 +1,13 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import DependencyInjection
 import ScrollViewController
 
 public final class ProfilePhoneController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: ProfileCoordinating
 
   private lazy var screenView = ProfilePhoneView()
   private lazy var scrollViewController = ScrollViewController()
@@ -31,62 +32,79 @@ public final class ProfilePhoneController: UIViewController {
   private func setupScrollView() {
     addChild(scrollViewController)
     view.addSubview(scrollViewController.view)
-    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.view.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+    }
     scrollViewController.didMove(toParent: self)
     scrollViewController.contentView = screenView
     scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
   }
 
   private func setupBindings() {
-    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
+    screenView
+      .inputField
+      .codePublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        coordinator.toCountries(from: self) { self.viewModel.didChooseCountry($0) }
+        navigator.perform(PresentCountryList(completion: { [weak self] in
+          guard let self else { return }
+          self.viewModel.didChooseCountry($0)
+        }))
       }.store(in: &cancellables)
 
-    viewModel.statePublisher
-      .map(\.confirmationId)
+    viewModel
+      .statePublisher
       .receive(on: DispatchQueue.main)
-      .compactMap { $0 }
       .sink { [unowned self] in
+        guard let id = $0.confirmationId, let content = $0.content else { return }
         viewModel.clearUp()
-//        coordinator.toCode(with: $0, from: self) { _, _ in
-//          if let viewControllers = self.navigationController?.viewControllers {
-//            self.navigationController?.popToViewController(
-//              viewControllers[viewControllers.count - 3],
-//              animated: true
-//            )
-//          }
-//        }
+        navigator.perform(
+          PresentProfileCode(
+            isEmail: false,
+            content: content,
+            confirmationId: id
+          )
+        )
       }.store(in: &cancellables)
 
-    viewModel.statePublisher
+    viewModel
+      .statePublisher
       .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.statePublisher
+    viewModel
+      .statePublisher
       .map(\.status)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in screenView.update(status: $0) }
-      .store(in: &cancellables)
+      .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/Coordinator/ProfileCoordinator.swift b/Sources/ProfileFeature/Coordinator/ProfileCoordinator.swift
deleted file mode 100644
index 59b569efd6bf53c6e5a670edea90eb3810a308f5..0000000000000000000000000000000000000000
--- a/Sources/ProfileFeature/Coordinator/ProfileCoordinator.swift
+++ /dev/null
@@ -1,89 +0,0 @@
-import UIKit
-import Shared
-import Countries
-import Permissions
-import MenuFeature
-import Presentation
-
-public protocol ProfileCoordinating {
-    func toEmail(from: UIViewController)
-    func toPhone(from: UIViewController)
-    func toPhotos(from: UIViewController)
-    func toSideMenu(from: UIViewController)
-    func toDrawer(_: UIViewController, from: UIViewController)
-    func toPermission(type: PermissionType, from: UIViewController)
-
-    func toCountries(
-        from: UIViewController,
-        _: @escaping (Country) -> Void
-    )
-}
-
-public struct ProfileCoordinator: ProfileCoordinating {
-    var pushPresenter: Presenting = PushPresenter()
-    var modalPresenter: Presenting = ModalPresenter()
-    var sidePresenter: Presenting = SideMenuPresenter()
-    var bottomPresenter: Presenting = BottomPresenter()
-
-    var emailFactory: () -> UIViewController
-    var phoneFactory: () -> UIViewController
-    var imagePickerFactory: () -> UIImagePickerController
-    var permissionFactory: () -> RequestPermissionController
-    var sideMenuFactory: (MenuItem, UIViewController) -> UIViewController
-    var countriesFactory: (@escaping (Country) -> Void) -> UIViewController
-
-    public init(
-        emailFactory: @escaping () -> UIViewController,
-        phoneFactory: @escaping () -> UIViewController,
-        imagePickerFactory: @escaping () -> UIImagePickerController,
-        permissionFactory: @escaping () -> RequestPermissionController, // ⚠️
-        sideMenuFactory: @escaping (MenuItem, UIViewController) -> UIViewController,
-        countriesFactory: @escaping (@escaping (Country) -> Void) -> UIViewController
-    ) {
-        self.emailFactory = emailFactory
-        self.phoneFactory = phoneFactory
-        self.sideMenuFactory = sideMenuFactory
-        self.countriesFactory = countriesFactory
-        self.permissionFactory = permissionFactory
-        self.imagePickerFactory = imagePickerFactory
-    }
-}
-
-public extension ProfileCoordinator {
-    func toEmail(from parent: UIViewController) {
-        let screen = emailFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toPhone(from parent: UIViewController) {
-        let screen = phoneFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toPermission(type: PermissionType, from parent: UIViewController) {
-        let screen = permissionFactory()
-        screen.setup(type: type)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toDrawer(_ drawer: UIViewController, from parent: UIViewController) {
-        bottomPresenter.present(drawer, from: parent)
-    }
-
-    func toCountries(from parent: UIViewController, _ onChoose: @escaping (Country) -> Void) {
-        let screen = countriesFactory(onChoose)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toPhotos(from parent: UIViewController) {
-        let screen = imagePickerFactory()
-        screen.delegate = (parent as? (UIImagePickerControllerDelegate & UINavigationControllerDelegate))
-        screen.allowsEditing = true
-        modalPresenter.present(screen, from: parent)
-    }
-
-    func toSideMenu(from parent: UIViewController) {
-        let screen = sideMenuFactory(.profile, parent)
-        sidePresenter.present(screen, from: parent)
-    }
-}
diff --git a/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift
index 173c8e199ad09c928387672e165ef4a6049b4388..280270744e8c326f31f061befe77fb323b98ca08 100644
--- a/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift
@@ -52,7 +52,7 @@ final class ProfileCodeViewModel {
     guard stateSubject.value.resendDebouncer == 0 else { return }
     stateSubject.value.resendDebouncer = 60
     timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {  [weak self] in
-      guard let self = self, self.stateSubject.value.resendDebouncer > 0 else {
+      guard let self, self.stateSubject.value.resendDebouncer > 0 else {
         $0.invalidate()
         return
       }
diff --git a/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift
index 6e0f17fe540e2b7271adacc3a330965efeda45e3..d2fd3b5ad6e3f5a97998033c711a9cb7ec443ad2 100644
--- a/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift
@@ -10,7 +10,6 @@ import DependencyInjection
 final class ProfileEmailViewModel {
   struct ViewState: Equatable {
     var input: String = ""
-    var content: String?
     var confirmationId: String?
     var status: InputField.ValidationStatus = .unknown(nil)
   }
@@ -25,29 +24,29 @@ final class ProfileEmailViewModel {
   private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
   private var scheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
 
+  func clearUp() {
+    stateSubject.value.confirmationId = nil
+  }
+
   func didInput(_ string: String) {
     stateSubject.value.input = string
     validate()
   }
 
-  func clearUp() {
-    stateSubject.value.confirmationId = nil
-  }
-
   func didTapNext() {
     hudController.show()
     scheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       do {
         let confirmationId = try self.messenger.ud.get()!.sendRegisterFact(
           .init(type: .email, value: self.stateSubject.value.input)
         )
         self.hudController.dismiss()
         self.stateSubject.value.confirmationId = confirmationId
-        self.stateSubject.value.content = self.stateSubject.value.input
       } catch {
+        self.hudController.dismiss()
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
-        self.hudController.show(.init(content: xxError))
+        self.stateSubject.value.status = .invalid(xxError)
       }
     }
   }
diff --git a/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
index 8adc37cc12c0631c39a3320d20d9158d5c2d478b..c341c5987beb3ab949b75be99901919648a1f2d0 100644
--- a/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
@@ -44,7 +44,7 @@ final class ProfilePhoneViewModel {
   func didTapNext() {
     hudController.show()
     scheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       let content = "\(self.stateSubject.value.input)\(self.stateSubject.value.country.code)"
       do {
         let confirmationId = try self.messenger.ud.get()!.sendRegisterFact(
diff --git a/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
index 996af851422553118ed892921bbcb6a585a4fdcc..72ef85939cd977efd357a9df04bb651268561470 100644
--- a/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
@@ -86,7 +86,7 @@ final class ProfileViewModel {
     hudController.show()
 
     backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
 
       do {
         try self.messenger.ud.get()!.removeFact(
diff --git a/Sources/RequestsFeature/Controllers/RequestsContainerController.swift b/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
index 7a878ab38d46b56b292d35456e8c3494e326c185..464890cdf6cc33275a4765cc42b2dbb1229bae7e 100644
--- a/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
@@ -1,12 +1,13 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import ContactFeature
 import DependencyInjection
 
 public final class RequestsContainerController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: RequestsCoordinating
 
   private lazy var screenView = RequestsContainerView()
   private var cancellables = Set<AnyCancellable>()
@@ -42,7 +43,7 @@ public final class RequestsContainerController: UIViewController {
     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 }
+          guard let self else { return }
 
           let point = CGPoint(x: self.screenView.frame.width, y: 0.0)
           self.screenView.scrollView.setContentOffset(point, animated: true)
@@ -75,8 +76,9 @@ public final class RequestsContainerController: UIViewController {
       .sentController
       .connectionsPublisher
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in coordinator.toSearch(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentSearch(replacing: false))
+      }.store(in: &cancellables)
 
     screenView
       .segmentedControl
@@ -106,7 +108,7 @@ public final class RequestsContainerController: UIViewController {
   }
 
   @objc private func didTapMenu() {
-    coordinator.toSideMenu(from: self)
+    navigator.perform(PresentMenu(currentItem: .requests))
   }
 }
 
diff --git a/Sources/RequestsFeature/Controllers/RequestsFailedController.swift b/Sources/RequestsFeature/Controllers/RequestsFailedController.swift
index bb62744b37d88cec22b8362938be2cb32ef954d2..94d4a38228d3c52025d6ab50582864353f45e553 100644
--- a/Sources/RequestsFeature/Controllers/RequestsFailedController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsFailedController.swift
@@ -23,7 +23,7 @@ final class RequestsFailedController: UIViewController {
             let cell: RequestCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
             cell.setupFor(requestFailed: request)
             cell.didTapStateButton = { [weak self] in
-                guard let self = self else { return }
+                guard let self else { return }
                 self.viewModel.didTapStateButtonFor(request: request)
             }
             return cell
diff --git a/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift b/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
index 279f29b627f8a072609868fd3686c6138d435e68..3ebd5792eee5a14951dc6a3616c38f3a16169f37 100644
--- a/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
@@ -3,561 +3,591 @@ import Shared
 import Combine
 import XXModels
 import Countries
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 
 final class RequestsReceivedController: UIViewController {
-    @Dependency var toaster: ToastController
-    @Dependency var coordinator: RequestsCoordinating
-
-    private lazy var screenView = RequestsReceivedView()
-    private var cancellables = Set<AnyCancellable>()
-    private let viewModel = RequestsReceivedViewModel()
-    private var drawerCancellables = Set<AnyCancellable>()
-    private var dataSource: UICollectionViewDiffableDataSource<Section, RequestReceived>?
-
-    override func loadView() {
-        view = screenView
+  @Dependency var navigator: Navigator
+  @Dependency var toaster: ToastController
+
+  private lazy var screenView = RequestsReceivedView()
+  private var cancellables = Set<AnyCancellable>()
+  private let viewModel = RequestsReceivedViewModel()
+  private var drawerCancellables = Set<AnyCancellable>()
+  private var dataSource: UICollectionViewDiffableDataSource<Section, RequestReceived>?
+
+  override func loadView() {
+    view = screenView
+  }
+
+  override func viewDidLoad() {
+    super.viewDidLoad()
+
+    screenView.collectionView.delegate = self
+    screenView.collectionView.register(RequestCell.self)
+    screenView.collectionView.register(RequestReceivedEmptyCell.self)
+    screenView.collectionView.registerSectionHeader(RequestsBlankSectionHeader.self)
+    screenView.collectionView.registerSectionHeader(RequestsHiddenSectionHeader.self)
+
+    dataSource = UICollectionViewDiffableDataSource<Section, RequestReceived>(
+      collectionView: screenView.collectionView
+    ) { collectionView, indexPath, requestReceived in
+      guard let request = requestReceived.request else {
+        let cell: RequestReceivedEmptyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+        return cell
+      }
+
+      let cell: RequestCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+      cell.setupFor(requestReceived: requestReceived, isHidden: indexPath.section == 1)
+      cell.didTapStateButton = { [weak self] in
+        guard let self else { return }
+        self.viewModel.didTapStateButtonFor(request: request)
+      }
+
+      return cell
     }
 
-    override func viewDidLoad() {
-        super.viewDidLoad()
-
-        screenView.collectionView.delegate = self
-        screenView.collectionView.register(RequestCell.self)
-        screenView.collectionView.register(RequestReceivedEmptyCell.self)
-        screenView.collectionView.registerSectionHeader(RequestsBlankSectionHeader.self)
-        screenView.collectionView.registerSectionHeader(RequestsHiddenSectionHeader.self)
-
-        dataSource = UICollectionViewDiffableDataSource<Section, RequestReceived>(
-            collectionView: screenView.collectionView
-        ) { collectionView, indexPath, requestReceived in
-            guard let request = requestReceived.request else {
-                let cell: RequestReceivedEmptyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-                return cell
-            }
-
-            let cell: RequestCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-            cell.setupFor(requestReceived: requestReceived, isHidden: indexPath.section == 1)
-            cell.didTapStateButton = { [weak self] in
-                guard let self = self else { return }
-                self.viewModel.didTapStateButtonFor(request: request)
-            }
-
-            return cell
-        }
+    dataSource?.supplementaryViewProvider = { [weak self] collectionView, kind, indexPath in
+      let reuseIdentifier: String
 
-        dataSource?.supplementaryViewProvider = { [weak self] collectionView, kind, indexPath in
-            let reuseIdentifier: String
+      if indexPath.section == Section.appearing.rawValue {
+        reuseIdentifier = String(describing: RequestsBlankSectionHeader.self)
+      } else {
+        reuseIdentifier = String(describing: RequestsHiddenSectionHeader.self)
+      }
 
-            if indexPath.section == Section.appearing.rawValue {
-                reuseIdentifier = String(describing: RequestsBlankSectionHeader.self)
-            } else {
-                reuseIdentifier = String(describing: RequestsHiddenSectionHeader.self)
-            }
+      let cell = collectionView.dequeueReusableSupplementaryView(
+        ofKind: kind,
+        withReuseIdentifier: reuseIdentifier,
+        for: indexPath
+      )
 
-            let cell = collectionView.dequeueReusableSupplementaryView(
-                ofKind: kind,
-                withReuseIdentifier: reuseIdentifier,
-                for: indexPath
-            )
+      if let cell = cell as? RequestsHiddenSectionHeader, let self = self {
+        cell.switcherView.setOn(self.viewModel.isShowingHiddenRequests, animated: true)
 
-            if let cell = cell as? RequestsHiddenSectionHeader, let self = self {
-                cell.switcherView.setOn(self.viewModel.isShowingHiddenRequests, animated: true)
+        cell.switcherView
+          .publisher(for: .valueChanged)
+          .sink { self.viewModel.didToggleHiddenRequestsSwitcher() }
+          .store(in: &cell.cancellables)
+      }
 
-                cell.switcherView
-                    .publisher(for: .valueChanged)
-                    .sink { self.viewModel.didToggleHiddenRequestsSwitcher() }
-                    .store(in: &cell.cancellables)
-            }
-
-            return cell
-        }
-
-        viewModel.verifyingPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in presentVerifyingDrawer() }
-            .store(in: &cancellables)
-
-        viewModel.itemsPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in dataSource?.apply($0, animatingDifferences: true) }
-            .store(in: &cancellables)
-
-        viewModel.contactConfirmationPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in presentSingleRequestSuccessDrawer(forContact: $0) }
-            .store(in: &cancellables)
-
-        viewModel.groupConfirmationPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in presentGroupRequestSuccessDrawer(forGroup: $0) }
-            .store(in: &cancellables)
+      return cell
     }
+
+    viewModel
+      .verifyingPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        presentVerifyingDrawer()
+      }.store(in: &cancellables)
+
+    viewModel
+      .itemsPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dataSource?.apply($0, animatingDifferences: true)
+      }.store(in: &cancellables)
+
+    viewModel
+      .contactConfirmationPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        presentSingleRequestSuccessDrawer(forContact: $0)
+      }.store(in: &cancellables)
+
+    viewModel
+      .groupConfirmationPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        presentGroupRequestSuccessDrawer(forGroup: $0)
+      }.store(in: &cancellables)
+  }
 }
 
 extension RequestsReceivedController: UICollectionViewDelegate {
-    func collectionView(_: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        guard let request = dataSource?.itemIdentifier(for: indexPath)?.request else { return }
-
-        switch request {
-        case .group(let group):
-            guard group.authStatus == .pending || group.authStatus == .hidden else { return }
-            presentGroupRequestDrawer(forGroup: group)
-        case .contact(let contact):
-            guard contact.authStatus == .verified || contact.authStatus == .hidden else { return }
-            presentSingleRequestDrawer(forContact: contact)
-        }
+  func collectionView(_: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+    guard let request = dataSource?.itemIdentifier(for: indexPath)?.request else { return }
+
+    switch request {
+    case .group(let group):
+      guard group.authStatus == .pending || group.authStatus == .hidden else { return }
+      presentGroupRequestDrawer(forGroup: group)
+    case .contact(let contact):
+      guard contact.authStatus == .verified || contact.authStatus == .hidden else { return }
+      presentSingleRequestDrawer(forContact: contact)
     }
+  }
 }
 
 // MARK: - Group Request Success Drawer
 
 extension RequestsReceivedController {
-    func presentGroupRequestSuccessDrawer(forGroup group: Group) {
-        drawerCancellables.removeAll()
-
-        var items: [DrawerItem] = []
-
-        let drawerTitle = DrawerText(
-            font: Fonts.Mulish.bold.font(size: 12.0),
-            text: Localized.Requests.Drawer.Group.Success.title,
-            color: Asset.accentSuccess.color,
-            spacingAfter: 20,
-            leftImage: Asset.requestAccepted.image
-        )
-
-        let drawerNickname = DrawerText(
-            font: Fonts.Mulish.extraBold.font(size: 26.0),
-            text: group.name,
-            color: Asset.neutralDark.color,
-            spacingAfter: 20
-        )
-
-        let drawerSubtitle = DrawerText(
-            font: Fonts.Mulish.regular.font(size: 16.0),
-            text: Localized.Requests.Drawer.Group.Success.subtitle,
-            color: Asset.neutralDark.color,
-            spacingAfter: 20
-        )
-
-        items.append(contentsOf: [
-            drawerTitle,
-            drawerNickname,
-            drawerSubtitle
-        ])
-
-        let drawerSendButton = DrawerCapsuleButton(
-            model: .init(
-                title: Localized.Requests.Drawer.Group.Success.send,
-                style: .brandColored
-            ), spacingAfter: 5
-        )
-
-        let drawerLaterButton = DrawerCapsuleButton(
-            model: .init(
-                title: Localized.Requests.Drawer.Group.Success.later,
-                style: .simplestColoredBrand
-            )
-        )
-
-        items.append(contentsOf: [
-            drawerSendButton,
-            drawerLaterButton
-        ])
-
-        let drawer = DrawerController(items)
-
-        drawerSendButton.action
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                drawer.dismiss(animated: true) {
-                    let chatInfo = self.viewModel.groupChatWith(group: group)
-                    self.coordinator.toGroupChat(with: chatInfo, from: self)
-                }
-            }.store(in: &drawerCancellables)
-
-        drawerLaterButton.action
-            .sink { drawer.dismiss(animated: true) }
-            .store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+  func presentGroupRequestSuccessDrawer(forGroup group: Group) {
+    drawerCancellables.removeAll()
+
+    var items: [DrawerItem] = []
+
+    let drawerTitle = DrawerText(
+      font: Fonts.Mulish.bold.font(size: 12.0),
+      text: Localized.Requests.Drawer.Group.Success.title,
+      color: Asset.accentSuccess.color,
+      spacingAfter: 20,
+      leftImage: Asset.requestAccepted.image
+    )
+
+    let drawerNickname = DrawerText(
+      font: Fonts.Mulish.extraBold.font(size: 26.0),
+      text: group.name,
+      color: Asset.neutralDark.color,
+      spacingAfter: 20
+    )
+
+    let drawerSubtitle = DrawerText(
+      font: Fonts.Mulish.regular.font(size: 16.0),
+      text: Localized.Requests.Drawer.Group.Success.subtitle,
+      color: Asset.neutralDark.color,
+      spacingAfter: 20
+    )
+
+    items.append(contentsOf: [
+      drawerTitle,
+      drawerNickname,
+      drawerSubtitle
+    ])
+
+    let drawerSendButton = DrawerCapsuleButton(
+      model: .init(
+        title: Localized.Requests.Drawer.Group.Success.send,
+        style: .brandColored
+      ), spacingAfter: 5
+    )
+
+    let drawerLaterButton = DrawerCapsuleButton(
+      model: .init(
+        title: Localized.Requests.Drawer.Group.Success.later,
+        style: .simplestColoredBrand
+      )
+    )
+
+    items.append(contentsOf: [
+      drawerSendButton,
+      drawerLaterButton
+    ])
+
+    drawerSendButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.navigator.perform(PresentGroupChat(
+            model: self.viewModel.groupChatWith(group: group)
+          ))
+        }
+      }.store(in: &drawerCancellables)
+
+    drawerLaterButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: items))
+  }
 }
 
 // MARK: - Single Request Success Drawer
 
 extension RequestsReceivedController {
-    func presentSingleRequestSuccessDrawer(forContact contact: Contact) {
-        drawerCancellables.removeAll()
-
-        var items: [DrawerItem] = []
-
-        let drawerTitle = DrawerText(
-            font: Fonts.Mulish.bold.font(size: 12.0),
-            text: Localized.Requests.Drawer.Single.Success.title,
-            color: Asset.accentSuccess.color,
-            spacingAfter: 20,
-            leftImage: Asset.requestAccepted.image
-        )
-
-        let drawerNickname = DrawerText(
-            font: Fonts.Mulish.extraBold.font(size: 26.0),
-            text: (contact.nickname ?? contact.username) ?? "",
-            color: Asset.neutralDark.color,
-            spacingAfter: 20
-        )
-
-        let drawerSubtitle = DrawerText(
-            font: Fonts.Mulish.regular.font(size: 16.0),
-            text: Localized.Requests.Drawer.Single.Success.subtitle,
-            color: Asset.neutralDark.color,
-            spacingAfter: 20
-        )
-
-        items.append(contentsOf: [
-            drawerTitle,
-            drawerNickname,
-            drawerSubtitle
-        ])
-
-        let drawerSendButton = DrawerCapsuleButton(
-            model: .init(
-                title: Localized.Requests.Drawer.Single.Success.send,
-                style: .brandColored
-            ), spacingAfter: 5
-        )
-
-        let drawerLaterButton = DrawerCapsuleButton(
-            model: .init(
-                title: Localized.Requests.Drawer.Single.Success.later,
-                style: .simplestColoredBrand
-            )
-        )
-
-        items.append(contentsOf: [
-            drawerSendButton,
-            drawerLaterButton
-        ])
-
-        let drawer = DrawerController(items)
-
-        drawerSendButton.action
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                drawer.dismiss(animated: true) {
-                    self.coordinator.toSingleChat(with: contact, from: self)
-                }
-            }.store(in: &drawerCancellables)
-
-        drawerLaterButton.action
-            .receive(on: DispatchQueue.main)
-            .sink { drawer.dismiss(animated: true) }
-            .store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+  func presentSingleRequestSuccessDrawer(forContact contact: Contact) {
+    drawerCancellables.removeAll()
+
+    var items: [DrawerItem] = []
+
+    let drawerTitle = DrawerText(
+      font: Fonts.Mulish.bold.font(size: 12.0),
+      text: Localized.Requests.Drawer.Single.Success.title,
+      color: Asset.accentSuccess.color,
+      spacingAfter: 20,
+      leftImage: Asset.requestAccepted.image
+    )
+
+    let drawerNickname = DrawerText(
+      font: Fonts.Mulish.extraBold.font(size: 26.0),
+      text: (contact.nickname ?? contact.username) ?? "",
+      color: Asset.neutralDark.color,
+      spacingAfter: 20
+    )
+
+    let drawerSubtitle = DrawerText(
+      font: Fonts.Mulish.regular.font(size: 16.0),
+      text: Localized.Requests.Drawer.Single.Success.subtitle,
+      color: Asset.neutralDark.color,
+      spacingAfter: 20
+    )
+
+    items.append(contentsOf: [
+      drawerTitle,
+      drawerNickname,
+      drawerSubtitle
+    ])
+
+    let drawerSendButton = DrawerCapsuleButton(
+      model: .init(
+        title: Localized.Requests.Drawer.Single.Success.send,
+        style: .brandColored
+      ), spacingAfter: 5
+    )
+
+    let drawerLaterButton = DrawerCapsuleButton(
+      model: .init(
+        title: Localized.Requests.Drawer.Single.Success.later,
+        style: .simplestColoredBrand
+      )
+    )
+
+    items.append(contentsOf: [
+      drawerSendButton,
+      drawerLaterButton
+    ])
+
+    drawerSendButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.navigator.perform(PresentChat(contact: contact))
+        }
+      }.store(in: &drawerCancellables)
+
+    drawerLaterButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: items))
+  }
 }
 
 // MARK: - Group Request Drawer
 
 extension RequestsReceivedController {
-    func presentGroupRequestDrawer(forGroup group: Group) {
-        drawerCancellables.removeAll()
-
-        var items: [DrawerItem] = []
-
-        let drawerTitle = DrawerText(
-            font: Fonts.Mulish.bold.font(size: 12.0),
-            text: Localized.Requests.Drawer.Group.title,
-            spacingAfter: 20
-        )
-
-        let drawerGroupName = DrawerText(
-            font: Fonts.Mulish.extraBold.font(size: 26.0),
-            text: group.name,
-            color: Asset.neutralDark.color,
-            spacingAfter: 25
-        )
-
-        items.append(contentsOf: [
-            drawerTitle,
-            drawerGroupName
-        ])
-
-        let drawerLoading = DrawerLoadingRetry()
-        drawerLoading.startSpinning()
+  func presentGroupRequestDrawer(forGroup group: Group) {
+    drawerCancellables.removeAll()
 
-        items.append(drawerLoading)
+    var items: [DrawerItem] = []
 
-        let drawerTable = DrawerTable(spacingAfter: 23)
+    let drawerTitle = DrawerText(
+      font: Fonts.Mulish.bold.font(size: 12.0),
+      text: Localized.Requests.Drawer.Group.title,
+      spacingAfter: 20
+    )
 
-        drawerLoading.retryPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                drawerLoading.startSpinning()
+    let drawerGroupName = DrawerText(
+      font: Fonts.Mulish.extraBold.font(size: 26.0),
+      text: group.name,
+      color: Asset.neutralDark.color,
+      spacingAfter: 25
+    )
 
-                viewModel.fetchMembers(group) { [weak self] in
-                    guard let _ = self else { return }
+    items.append(contentsOf: [
+      drawerTitle,
+      drawerGroupName
+    ])
 
-                    switch $0 {
-                    case .success(let models):
-                        DispatchQueue.main.async {
-                            drawerTable.update(models: models)
-                            drawerLoading.stopSpinning(withRetry: false)
-                        }
-                    case .failure:
-                        drawerLoading.stopSpinning(withRetry: true)
-                    }
-                }
-            }.store(in: &drawerCancellables)
+    let drawerLoading = DrawerLoadingRetry()
+    drawerLoading.startSpinning()
 
-        viewModel.fetchMembers(group) { [weak self] in
-            guard let _ = self else { return }
-
-            switch $0 {
-            case .success(let models):
-                DispatchQueue.main.async {
-                    drawerTable.update(models: models)
-                    drawerLoading.stopSpinning(withRetry: false)
-                }
-            case .failure:
-                drawerLoading.stopSpinning(withRetry: true)
-            }
-        }
-
-        items.append(drawerTable)
+    items.append(drawerLoading)
 
-        let drawerAcceptButton = DrawerCapsuleButton(
-            model: .init(
-                title: Localized.Requests.Drawer.Group.accept,
-                style: .brandColored
-            ), spacingAfter: 5
-        )
+    let drawerTable = DrawerTable(spacingAfter: 23)
 
-        let drawerHideButton = DrawerCapsuleButton(
-            model: .init(
-                title: Localized.Requests.Drawer.Group.hide,
-                style: .simplestColoredBrand
-            ), spacingAfter: 5
-        )
-
-        items.append(contentsOf: [drawerAcceptButton, drawerHideButton])
+    drawerLoading.retryPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        drawerLoading.startSpinning()
 
-        let drawer = DrawerController(items)
+        viewModel.fetchMembers(group) { [weak self] in
+          guard let _ = self else { return }
 
-        drawerAcceptButton.action
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                drawer.dismiss(animated: true) {
-                    self.viewModel.didRequestAccept(group: group)
-                }
+          switch $0 {
+          case .success(let models):
+            DispatchQueue.main.async {
+              drawerTable.update(models: models)
+              drawerLoading.stopSpinning(withRetry: false)
             }
-            .store(in: &drawerCancellables)
-
-        drawerHideButton.action
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                drawer.dismiss(animated: true) {
-                    self.viewModel.didRequestHide(group: group)
-                }
-            }
-            .store(in: &drawerCancellables)
-
-        coordinator.toDrawerBottom(drawer, from: self)
-    }
-}
+          case .failure:
+            drawerLoading.stopSpinning(withRetry: true)
+          }
+        }
+      }.store(in: &drawerCancellables)
 
-// MARK: - Single Request Drawer
+    viewModel.fetchMembers(group) { [weak self] in
+      guard let _ = self else { return }
 
-extension RequestsReceivedController {
-    func presentSingleRequestDrawer(forContact contact: Contact) {
-        drawerCancellables.removeAll()
-
-        var items: [DrawerItem] = []
-
-        let drawerTitle = DrawerText(
-            font: Fonts.Mulish.bold.font(size: 12.0),
-            text: Localized.Requests.Drawer.Single.title,
-            spacingAfter: 20
-        )
-
-        let drawerUsername = DrawerText(
-            font: Fonts.Mulish.extraBold.font(size: 26.0),
-            text: contact.username ?? "",
-            color: Asset.neutralDark.color,
-            spacingAfter: 25
-        )
-
-        items.append(contentsOf: [
-            drawerTitle,
-            drawerUsername
-        ])
-
-        let drawerEmailTitle = DrawerText(
-            font: Fonts.Mulish.bold.font(size: 12.0),
-            text: Localized.Requests.Drawer.Single.email,
-            color: Asset.neutralWeak.color,
-            spacingAfter: 5
-        )
-
-        if let email = contact.email {
-            let drawerEmailContent = DrawerText(
-                font: Fonts.Mulish.regular.font(size: 16.0),
-                text: email,
-                spacingAfter: 25
-            )
-
-            items.append(contentsOf: [
-                drawerEmailTitle,
-                drawerEmailContent
-            ])
+      switch $0 {
+      case .success(let models):
+        DispatchQueue.main.async {
+          drawerTable.update(models: models)
+          drawerLoading.stopSpinning(withRetry: false)
         }
+      case .failure:
+        drawerLoading.stopSpinning(withRetry: true)
+      }
+    }
 
-        let drawerPhoneTitle = DrawerText(
-            font: Fonts.Mulish.bold.font(size: 12.0),
-            text: Localized.Requests.Drawer.Single.phone,
-            color: Asset.neutralWeak.color,
-            spacingAfter: 5
-        )
-
-        if let phone = contact.phone {
-            let drawerPhoneContent = DrawerText(
-                font: Fonts.Mulish.regular.font(size: 16.0),
-                text: "\(Country.findFrom(phone).prefix) \(phone.dropLast(2))",
-                spacingAfter: 30
-            )
-
-            items.append(contentsOf: [
-                drawerPhoneTitle,
-                drawerPhoneContent
-            ])
+    items.append(drawerTable)
+
+    let drawerAcceptButton = DrawerCapsuleButton(
+      model: .init(
+        title: Localized.Requests.Drawer.Group.accept,
+        style: .brandColored
+      ), spacingAfter: 5
+    )
+
+    let drawerHideButton = DrawerCapsuleButton(
+      model: .init(
+        title: Localized.Requests.Drawer.Group.hide,
+        style: .simplestColoredBrand
+      ), spacingAfter: 5
+    )
+
+    items.append(contentsOf: [drawerAcceptButton, drawerHideButton])
+
+    drawerAcceptButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didRequestAccept(group: group)
         }
+      }.store(in: &drawerCancellables)
+
+    drawerHideButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didRequestHide(group: group)
+        }
+      }.store(in: &drawerCancellables)
 
-        let drawerNicknameTitle = DrawerText(
-            font: Fonts.Mulish.bold.font(size: 16.0),
-            text: Localized.Requests.Drawer.Single.nickname,
-            color: Asset.neutralDark.color,
-            spacingAfter: 21
-        )
-
-        items.append(drawerNicknameTitle)
-
-        let drawerNicknameInput = DrawerInput(
-            placeholder: contact.username ?? "",
-            validator: .init(
-                wrongIcon: .image(Asset.sharedError.image),
-                correctIcon: .image(Asset.sharedSuccess.image),
-                shouldAcceptPlaceholder: true
-            ),
-            spacingAfter: 29
-        )
-
-        items.append(drawerNicknameInput)
-
-        let drawerAcceptButton = DrawerCapsuleButton(
-            model: .init(
-                title: Localized.Requests.Drawer.Single.accept,
-                style: .brandColored
-            ), spacingAfter: 5
-        )
-
-        let drawerHideButton = DrawerCapsuleButton(
-            model: .init(
-                title: Localized.Requests.Drawer.Single.hide,
-                style: .simplestColoredBrand
-            ), spacingAfter: 5
-        )
-
-        items.append(contentsOf: [drawerAcceptButton, drawerHideButton])
-
-        let drawer = DrawerController(items)
-
-        var nickname: String?
-        var allowsSave = true
-
-        drawerNicknameInput.validationPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { allowsSave = $0 }
-            .store(in: &drawerCancellables)
-
-        drawerNicknameInput.inputPublisher
-            .receive(on: DispatchQueue.main)
-            .sink {
-                guard !$0.isEmpty else {
-                    nickname = contact.username
-                    return
-                }
-
-                nickname = $0
-            }
-            .store(in: &drawerCancellables)
-
-        drawerAcceptButton.action
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                guard allowsSave else { return }
-
-                drawer.dismiss(animated: true) {
-                    self.viewModel.didRequestAccept(contact: contact, nickname: nickname)
-                }
-            }
-            .store(in: &drawerCancellables)
-
-        drawerHideButton.action
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                drawer.dismiss(animated: true) {
-                    self.viewModel.didRequestHide(contact: contact)
-                }
-            }
-            .store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+    navigator.perform(PresentDrawer(items: items))
+  }
 }
 
-// MARK: - Verifying Drawer
+// MARK: - Single Request Drawer
 
 extension RequestsReceivedController {
-    func presentVerifyingDrawer() {
-        drawerCancellables.removeAll()
-
-        var items: [DrawerItem] = []
-
-        let drawerTitle = DrawerText(
-            font: Fonts.Mulish.extraBold.font(size: 26.0),
-            text: Localized.Requests.Received.Verifying.title,
-            spacingAfter: 20
-        )
+  func presentSingleRequestDrawer(forContact contact: Contact) {
+    drawerCancellables.removeAll()
+
+    var items: [DrawerItem] = []
+
+    let drawerTitle = DrawerText(
+      font: Fonts.Mulish.bold.font(size: 12.0),
+      text: Localized.Requests.Drawer.Single.title,
+      spacingAfter: 20
+    )
+
+    let drawerUsername = DrawerText(
+      font: Fonts.Mulish.extraBold.font(size: 26.0),
+      text: contact.username ?? "",
+      color: Asset.neutralDark.color,
+      spacingAfter: 25
+    )
+
+    items.append(contentsOf: [
+      drawerTitle,
+      drawerUsername
+    ])
+
+    let drawerEmailTitle = DrawerText(
+      font: Fonts.Mulish.bold.font(size: 12.0),
+      text: Localized.Requests.Drawer.Single.email,
+      color: Asset.neutralWeak.color,
+      spacingAfter: 5
+    )
+
+    if let email = contact.email {
+      let drawerEmailContent = DrawerText(
+        font: Fonts.Mulish.regular.font(size: 16.0),
+        text: email,
+        spacingAfter: 25
+      )
+
+      items.append(contentsOf: [
+        drawerEmailTitle,
+        drawerEmailContent
+      ])
+    }
 
-        let drawerSubtitle = DrawerText(
-            font: Fonts.Mulish.regular.font(size: 16.0),
-            text: Localized.Requests.Received.Verifying.subtitle,
-            spacingAfter: 40
-        )
+    let drawerPhoneTitle = DrawerText(
+      font: Fonts.Mulish.bold.font(size: 12.0),
+      text: Localized.Requests.Drawer.Single.phone,
+      color: Asset.neutralWeak.color,
+      spacingAfter: 5
+    )
+
+    if let phone = contact.phone {
+      let drawerPhoneContent = DrawerText(
+        font: Fonts.Mulish.regular.font(size: 16.0),
+        text: "\(Country.findFrom(phone).prefix) \(phone.dropLast(2))",
+        spacingAfter: 30
+      )
+
+      items.append(contentsOf: [
+        drawerPhoneTitle,
+        drawerPhoneContent
+      ])
+    }
 
-        items.append(contentsOf: [
-            drawerTitle,
-            drawerSubtitle
-        ])
+    let drawerNicknameTitle = DrawerText(
+      font: Fonts.Mulish.bold.font(size: 16.0),
+      text: Localized.Requests.Drawer.Single.nickname,
+      color: Asset.neutralDark.color,
+      spacingAfter: 21
+    )
+
+    items.append(drawerNicknameTitle)
+
+    let drawerNicknameInput = DrawerInput(
+      placeholder: contact.username ?? "",
+      validator: .init(
+        wrongIcon: .image(Asset.sharedError.image),
+        correctIcon: .image(Asset.sharedSuccess.image),
+        shouldAcceptPlaceholder: true
+      ),
+      spacingAfter: 29
+    )
+
+    items.append(drawerNicknameInput)
+
+    let drawerAcceptButton = DrawerCapsuleButton(
+      model: .init(
+        title: Localized.Requests.Drawer.Single.accept,
+        style: .brandColored
+      ), spacingAfter: 5
+    )
+
+    let drawerHideButton = DrawerCapsuleButton(
+      model: .init(
+        title: Localized.Requests.Drawer.Single.hide,
+        style: .simplestColoredBrand
+      ), spacingAfter: 5
+    )
+
+    items.append(contentsOf: [drawerAcceptButton, drawerHideButton])
+
+    var nickname: String?
+    var allowsSave = true
+
+    drawerNicknameInput
+      .validationPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { allowsSave = $0 }
+      .store(in: &drawerCancellables)
+
+    drawerNicknameInput
+      .inputPublisher
+      .receive(on: DispatchQueue.main)
+      .sink {
+        guard !$0.isEmpty else {
+          nickname = contact.username
+          return
+        }
 
-        let drawerDoneButton = DrawerCapsuleButton(
-            model: .init(
-                title: Localized.Requests.Received.Verifying.action,
-                style: .brandColored
-            ), spacingAfter: 5
-        )
+        nickname = $0
+      }.store(in: &drawerCancellables)
+
+    drawerAcceptButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        guard allowsSave else { return }
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didRequestAccept(contact: contact, nickname: nickname)
+        }
+      }.store(in: &drawerCancellables)
+
+    drawerHideButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didRequestHide(contact: contact)
+        }
+      }.store(in: &drawerCancellables)
 
-        items.append(drawerDoneButton)
+    navigator.perform(PresentDrawer(items: items))
+  }
+}
 
-        let drawer = DrawerController(items)
+// MARK: - Verifying Drawer
 
-        drawerDoneButton.action
-            .receive(on: DispatchQueue.main)
-            .sink { drawer.dismiss(animated: true) }
-            .store(in: &drawerCancellables)
+extension RequestsReceivedController {
+  func presentVerifyingDrawer() {
+    drawerCancellables.removeAll()
+
+    var items: [DrawerItem] = []
+
+    let drawerTitle = DrawerText(
+      font: Fonts.Mulish.extraBold.font(size: 26.0),
+      text: Localized.Requests.Received.Verifying.title,
+      spacingAfter: 20
+    )
+
+    let drawerSubtitle = DrawerText(
+      font: Fonts.Mulish.regular.font(size: 16.0),
+      text: Localized.Requests.Received.Verifying.subtitle,
+      spacingAfter: 40
+    )
+
+    items.append(contentsOf: [
+      drawerTitle,
+      drawerSubtitle
+    ])
+
+    let drawerDoneButton = DrawerCapsuleButton(
+      model: .init(
+        title: Localized.Requests.Received.Verifying.action,
+        style: .brandColored
+      ), spacingAfter: 5
+    )
+
+    items.append(drawerDoneButton)
+
+    drawerDoneButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-        coordinator.toDrawer(drawer, from: self)
-    }
+    navigator.perform(PresentDrawer(items: items))
+  }
 }
diff --git a/Sources/RequestsFeature/Controllers/RequestsSentController.swift b/Sources/RequestsFeature/Controllers/RequestsSentController.swift
index 7edec9380f4adba716f64797ddef883821f1ddcf..ff9e0384959f18ecf25abeab1ac534acca50db01 100644
--- a/Sources/RequestsFeature/Controllers/RequestsSentController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsSentController.swift
@@ -29,7 +29,7 @@ final class RequestsSentController: UIViewController {
             let cell: RequestCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
             cell.setupFor(requestSent: requestSent)
             cell.didTapStateButton = { [weak self] in
-                guard let self = self else { return }
+                guard let self else { return }
                 self.viewModel.didTapStateButtonFor(request: requestSent)
             }
             return cell
diff --git a/Sources/RequestsFeature/Coordinator/RequestsCoordinator.swift b/Sources/RequestsFeature/Coordinator/RequestsCoordinator.swift
deleted file mode 100644
index 9e8297c0e7af060767d4711271d124d72a596ae5..0000000000000000000000000000000000000000
--- a/Sources/RequestsFeature/Coordinator/RequestsCoordinator.swift
+++ /dev/null
@@ -1,119 +0,0 @@
-import UIKit
-import Shared
-import XXModels
-import MenuFeature
-import Presentation
-import ContactFeature
-import ScrollViewController
-
-public protocol RequestsCoordinating {
-    func toSearch(from: UIViewController)
-    func toSideMenu(from: UIViewController)
-    func toContact(_: Contact, from: UIViewController)
-    func toSingleChat(with: Contact, from: UIViewController)
-    func toGroupChat(with: GroupInfo, from: UIViewController)
-    func toDrawer(_:  UIViewController, from: UIViewController)
-    func toDrawerBottom(_:  UIViewController, from: UIViewController)
-    func toNickname(from: UIViewController, prefilled: String, _: @escaping StringClosure)
-}
-
-public struct RequestsCoordinator: RequestsCoordinating {
-    var pushPresenter: Presenting = PushPresenter()
-    var sidePresenter: Presenting = SideMenuPresenter()
-    var bottomPresenter: Presenting = BottomPresenter()
-    var fullscreenPresenter: Presenting = FullscreenPresenter()
-
-    var searchFactory: (String?) -> UIViewController
-    var contactFactory: (Contact) -> UIViewController
-    var singleChatFactory: (Contact) -> UIViewController
-    var groupChatFactory: (GroupInfo) -> UIViewController
-    var sideMenuFactory: (MenuItem, UIViewController) -> UIViewController
-    var nicknameFactory: (String, @escaping StringClosure) -> UIViewController
-
-    public init(
-        searchFactory: @escaping (String?) -> UIViewController,
-        contactFactory: @escaping (Contact) -> UIViewController,
-        singleChatFactory: @escaping (Contact) -> UIViewController,
-        groupChatFactory: @escaping (GroupInfo) -> UIViewController,
-        sideMenuFactory: @escaping (MenuItem, UIViewController) -> UIViewController,
-        nicknameFactory: @escaping (String, @escaping StringClosure) -> UIViewController
-    ) {
-        self.searchFactory = searchFactory
-        self.contactFactory = contactFactory
-        self.nicknameFactory = nicknameFactory
-        self.sideMenuFactory = sideMenuFactory
-        self.groupChatFactory = groupChatFactory
-        self.singleChatFactory = singleChatFactory
-    }
-}
-
-public extension RequestsCoordinator {
-    func toSingleChat(
-        with contact: Contact,
-        from parent: UIViewController
-    ) {
-        let screen = singleChatFactory(contact)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toGroupChat(
-        with info: GroupInfo,
-        from parent: UIViewController
-    ) {
-        let screen = groupChatFactory(info)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toDrawer(
-        _ drawer: UIViewController,
-        from parent: UIViewController
-    ) {
-        let target = ScrollViewController.embedding(drawer)
-        fullscreenPresenter.present(target, from: parent)
-    }
-
-    func toDrawerBottom(
-        _ drawer: UIViewController,
-        from parent: UIViewController
-    ) {
-        bottomPresenter.present(drawer, from: parent)
-    }
-
-    func toSearch(from parent: UIViewController) {
-        let screen = searchFactory(nil)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toNickname(
-        from parent: UIViewController,
-        prefilled: String,
-        _ completion: @escaping StringClosure
-    ) {
-        let screen = nicknameFactory(prefilled, completion)
-        bottomPresenter.present(screen, from: parent)
-    }
-
-    func toContact(_ contact: Contact, from parent: UIViewController) {
-        let screen = contactFactory(contact)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toSideMenu(from parent: UIViewController) {
-        let screen = sideMenuFactory(.requests, parent)
-        sidePresenter.present(screen, from: parent)
-    }
-}
-
-extension ScrollViewController {
-    static func embedding(_ viewController: UIViewController) -> ScrollViewController {
-        let scrollViewController = ScrollViewController()
-        scrollViewController.addChild(viewController)
-        scrollViewController.contentView = viewController.view
-        scrollViewController.wrapperView.handlesTouchesOutsideContent = false
-        scrollViewController.wrapperView.alignContentToBottom = true
-        scrollViewController.scrollView.bounces = false
-
-        viewController.didMove(toParent: scrollViewController)
-        return scrollViewController
-    }
-}
diff --git a/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift
index 351d3b37dc6a61dc181c4de6b6e372564e371bb5..1f54896ac8714898c7ca8a7c52e3237fb08ec58e 100644
--- a/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift
+++ b/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift
@@ -47,7 +47,7 @@ final class RequestsFailedViewModel {
     
     hudController.show()
     backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       
       do {
         if request.status == .failedToRequest {
diff --git a/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift
index 055b7236fe3bb5a870414f1cf1de5bc1e2f169c6..64ec65957fa8965cbe4b78819baab058132f8ca6 100644
--- a/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift
+++ b/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift
@@ -147,7 +147,7 @@ final class RequestsReceivedViewModel {
     
     if request.status == .failedToVerify {
       backgroundScheduler.schedule { [weak self] in
-        guard let self = self else { return }
+        guard let self else { return }
         
         do {
           contact.authStatus = .verificationInProgress
@@ -188,7 +188,7 @@ final class RequestsReceivedViewModel {
     hudController.show()
     
     backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       
       do {
         try self.groupManager.joinGroup(serializedGroupData: group.serialized)
@@ -257,7 +257,7 @@ final class RequestsReceivedViewModel {
     contact.nickname = nickname ?? contact.username
     
     backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       
       do {
         try self.database.saveContact(contact)
diff --git a/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift
index 4936e676dc099bd4de02bba55e88b5765e5368fb..718b673fe6cb2b7b85fc40ee1a7792b251050b26 100644
--- a/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift
+++ b/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift
@@ -69,7 +69,7 @@ final class RequestsSentViewModel {
     
     hudController.show()
     backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       
       do {
         var includedFacts: [Fact] = []
diff --git a/Sources/RestoreFeature/Controllers/RestoreController.swift b/Sources/RestoreFeature/Controllers/RestoreController.swift
index f88ead1da0327ede349a9e1fdf3a4b0d5eb0b13a..d1a57aa2f85ff7be12b8573c4b1fc362117798a1 100644
--- a/Sources/RestoreFeature/Controllers/RestoreController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreController.swift
@@ -1,134 +1,135 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 
 public final class RestoreController: UIViewController {
-    @Dependency private var coordinator: RestoreCoordinating
-
-    private lazy var screenView = RestoreView()
-
-    private let viewModel: RestoreViewModel
-    private var cancellables = Set<AnyCancellable>()
-    private var drawerCancellables = Set<AnyCancellable>()
-
-    public init(_ details: RestorationDetails) {
-        viewModel = .init(details: details)
-        super.init(nibName: nil, bundle: nil)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func loadView() {
-        view = screenView
-        presentWarning()
-    }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        navigationController?.navigationBar.customize(translucent: true)
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupNavigationBar()
-        setupBindings()
-    }
-
-    private func setupNavigationBar() {
-        let title = UILabel()
-        title.text = Localized.AccountRestore.header
-        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.stepPublisher
-        .receive(on: DispatchQueue.main)
-        .removeDuplicates()
-        .sink { [unowned self] in
-          screenView.updateFor(step: $0)
-
-          if $0 == .wrongPass {
-            coordinator.toPassphrase(
-              from: self,
-              cancelClosure: { self.dismiss(animated: true) },
-              passphraseClosure: { pwd in
-                self.viewModel.retryWith(passphrase: pwd)
-              }
-            )
-
-            return
-          }
-
-          if $0 == .done {
-            coordinator.toSuccess(from: self)
-          }
-        }.store(in: &cancellables)
-
-      screenView.backButton
-        .publisher(for: .touchUpInside)
-        .sink { [unowned self] in didTapBack() }
-        .store(in: &cancellables)
-
-      screenView.cancelButton
-        .publisher(for: .touchUpInside)
-        .sink { [unowned self] in didTapBack() }
-        .store(in: &cancellables)
-
-      screenView.restoreButton
-        .publisher(for: .touchUpInside)
-        .sink { [unowned self] in
-          coordinator.toPassphrase(
-            from: self,
-            cancelClosure: { self.dismiss(animated: true) },
-            passphraseClosure: { pwd in
-              self.viewModel.didTapRestore(passphrase: pwd)
-            }
-          )
-        }.store(in: &cancellables)
-    }
-
-    @objc private func didTapBack() {
-        navigationController?.popViewController(animated: true)
-    }
+  @Dependency var navigator: Navigator
+
+  private lazy var screenView = RestoreView()
+
+  private let viewModel: RestoreViewModel
+  private var cancellables = Set<AnyCancellable>()
+  private var drawerCancellables = Set<AnyCancellable>()
+
+  public init(_ details: RestorationDetails) {
+    viewModel = .init(details: details)
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func loadView() {
+    view = screenView
+    presentWarning()
+  }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    navigationController?.navigationBar.customize(translucent: true)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupNavigationBar()
+    setupBindings()
+  }
+
+  private func setupNavigationBar() {
+    let title = UILabel()
+    title.text = Localized.AccountRestore.header
+    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
+      .stepPublisher
+      .receive(on: DispatchQueue.main)
+      .removeDuplicates()
+      .sink { [unowned self] in
+        screenView.updateFor(step: $0)
+        if $0 == .wrongPass {
+          navigator.perform(PresentPassphrase(onCancel: {
+            navigator.perform(DismissModal(from: self))
+          }, onPassphrase: { [weak self] passphrase in
+            guard let self else { return }
+            self.viewModel.retryWith(passphrase: passphrase)
+          }))
+          return
+        }
+        if $0 == .done {
+//          coordinator.toSuccess(from: self)
+        }
+      }.store(in: &cancellables)
+
+    screenView
+      .backButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        didTapBack()
+      }.store(in: &cancellables)
+
+    screenView
+      .cancelButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        didTapBack()
+      }.store(in: &cancellables)
+
+    screenView
+      .restoreButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        navigator.perform(PresentPassphrase(onCancel: {
+          navigator.perform(DismissModal(from: self))
+        }, onPassphrase: { [weak self] passphrase in
+          guard let self else { return }
+          self.viewModel.didTapRestore(passphrase: passphrase)
+        }))
+      }.store(in: &cancellables)
+  }
+
+  @objc private func didTapBack() {
+    navigationController?.popViewController(animated: true)
+  }
 }
 
 extension RestoreController {
-    private func presentWarning() {
-        let actionButton = DrawerCapsuleButton(model: .init(
-            title: Localized.AccountRestore.Warning.action,
-            style: .brandColored
-        ))
-
-        let drawer = DrawerController([
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: Localized.AccountRestore.Warning.title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerText(
-                text: Localized.AccountRestore.Warning.subtitle,
-                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()
-                }
-            }.store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+  private func presentWarning() {
+    let actionButton = DrawerCapsuleButton(model: .init(
+      title: Localized.AccountRestore.Warning.action,
+      style: .brandColored
+    ))
+
+    actionButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: Localized.AccountRestore.Warning.title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerText(
+        text: Localized.AccountRestore.Warning.subtitle,
+        spacingAfter: 37
+      ),
+      actionButton
+    ]))
+  }
 }
diff --git a/Sources/RestoreFeature/Controllers/RestoreListController.swift b/Sources/RestoreFeature/Controllers/RestoreListController.swift
index 6e85c99fb155a90394836d095964fa2dbc1e49b4..84ebee37d75a0b3157884c8358bedbba7cd73f83 100644
--- a/Sources/RestoreFeature/Controllers/RestoreListController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreListController.swift
@@ -1,11 +1,12 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 
 public final class RestoreListController: UIViewController {
-  @Dependency var coordinator: RestoreCoordinating
+  @Dependency var navigator: Navigator
 
   private lazy var screenView = RestoreListView()
 
@@ -27,23 +28,20 @@ public final class RestoreListController: UIViewController {
   public override func viewDidLoad() {
     super.viewDidLoad()
 
-    viewModel.sftpPublisher
+    viewModel
+      .sftpPublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] _ in
-        coordinator.toSFTP(from: self) { [weak self] host, username, password in
+        navigator.perform(PresentSFTP { [weak self] host, username, password in
           guard let self else { return }
-          self.viewModel.setupSFTP(
-            host: host,
-            username: username,
-            password: password
-          )
-        }
+          self.viewModel.setupSFTP(host: host, username: username, password: password)
+        })
       }.store(in: &cancellables)
 
     viewModel.detailsPublisher
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in
-        coordinator.toRestore(with: $0, from: self)
+      .sink { [unowned self] _ in
+//        coordinator.toRestore(with: $0, from: self)
       }.store(in: &cancellables)
 
     screenView.cancelButton
@@ -97,7 +95,17 @@ extension RestoreListController {
       style: .brandColored
     ))
 
-    let drawer = DrawerController([
+    actionButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
       DrawerText(
         font: Fonts.Mulish.bold.font(size: 26.0),
         text: Localized.AccountRestore.Warning.title,
@@ -108,17 +116,6 @@ extension RestoreListController {
         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()
-        }
-      }.store(in: &drawerCancellables)
-
-    coordinator.toDrawer(drawer, from: self)
+    ]))
   }
 }
diff --git a/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift b/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
index 13c313630e6607b91526922991df2191de0766c0..83c70aa55f64b8d545166b1d3f1d598f02995130 100644
--- a/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
@@ -1,11 +1,12 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import DependencyInjection
 
 public final class RestoreSuccessController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: RestoreCoordinating
 
   private lazy var screenView = RestoreSuccessView()
   private var cancellables = Set<AnyCancellable>()
@@ -44,9 +45,11 @@ public final class RestoreSuccessController: UIViewController {
   }
 
   private func setupBindings() {
-    screenView.nextButton
+    screenView
+      .nextButton
       .publisher(for: .touchUpInside)
-      .sink { [unowned self] in coordinator.toChats(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentChatList())
+      }.store(in: &cancellables)
   }
 }
diff --git a/Sources/RestoreFeature/Coordinator/RestoreCoordinator.swift b/Sources/RestoreFeature/Coordinator/RestoreCoordinator.swift
deleted file mode 100644
index ee3e429c60263a60bbd3df20fb7fbdc91c8e7f1c..0000000000000000000000000000000000000000
--- a/Sources/RestoreFeature/Coordinator/RestoreCoordinator.swift
+++ /dev/null
@@ -1,116 +0,0 @@
-import UIKit
-import Shared
-import Presentation
-import ScrollViewController
-
-public typealias SFTPDetailsClosure = (String, String, String) -> Void
-
-public protocol RestoreCoordinating {
-  func toChats(from: UIViewController)
-  func toSuccess(from: UIViewController)
-  func toDrawer(_: UIViewController, from: UIViewController)
-  func toRestore(with: RestorationDetails, from: UIViewController)
-
-  func toSFTP(
-    from: UIViewController,
-    detailsClosure: @escaping SFTPDetailsClosure
-  )
-
-  func toPassphrase(
-    from: UIViewController,
-    cancelClosure: @escaping EmptyClosure,
-    passphraseClosure: @escaping StringClosure
-  )
-}
-
-public struct RestoreCoordinator: RestoreCoordinating {
-  var pushPresenter: Presenting = PushPresenter()
-  var bottomPresenter: Presenting = BottomPresenter()
-  var replacePresenter: Presenting = ReplacePresenter()
-  var fullscreenPresenter: Presenting = FullscreenPresenter()
-
-  var successFactory: () -> UIViewController
-  var chatListFactory: () -> UIViewController
-  var restoreFactory: (RestorationDetails) -> UIViewController
-  var sftpFactory: (@escaping SFTPDetailsClosure) -> UIViewController
-
-  var passphraseFactory: (
-    @escaping EmptyClosure,
-    @escaping StringClosure
-  ) -> UIViewController
-
-  public init(
-    successFactory: @escaping () -> UIViewController,
-    chatListFactory: @escaping () -> UIViewController,
-    restoreFactory: @escaping (RestorationDetails) -> UIViewController,
-    sftpFactory: @escaping (
-      @escaping SFTPDetailsClosure
-    ) -> UIViewController,
-    passphraseFactory: @escaping (
-      @escaping EmptyClosure,
-      @escaping StringClosure
-    ) -> UIViewController
-  ) {
-    self.sftpFactory = sftpFactory
-    self.successFactory = successFactory
-    self.restoreFactory = restoreFactory
-    self.chatListFactory = chatListFactory
-    self.passphraseFactory = passphraseFactory
-  }
-}
-
-public extension RestoreCoordinator {
-  func toSFTP(
-    from parent: UIViewController,
-    detailsClosure: @escaping SFTPDetailsClosure
-  ) {
-    let screen = sftpFactory(detailsClosure)
-    pushPresenter.present(screen, from: parent)
-  }
-
-  func toRestore(
-    with details: RestorationDetails,
-    from parent: UIViewController
-  ) {
-    let screen = restoreFactory(details)
-    pushPresenter.present(screen, from: parent)
-  }
-
-  func toChats(from parent: UIViewController) {
-    let screen = chatListFactory()
-    replacePresenter.present(screen, from: parent)
-  }
-
-  func toSuccess(from parent: UIViewController) {
-    let screen = successFactory()
-    replacePresenter.present(screen, from: parent)
-  }
-
-  func toDrawer(_ drawer: UIViewController, from parent: UIViewController) {
-    bottomPresenter.present(drawer, from: parent)
-  }
-
-  func toPassphrase(
-    from parent: UIViewController,
-    cancelClosure: @escaping EmptyClosure,
-    passphraseClosure: @escaping StringClosure
-  ) {
-    let screen = passphraseFactory(cancelClosure, passphraseClosure)
-    let target = ScrollViewController.embedding(screen)
-    fullscreenPresenter.present(target, from: parent)
-  }
-}
-
-extension ScrollViewController {
-  static func embedding(_ viewController: UIViewController) -> ScrollViewController {
-    let scrollViewController = ScrollViewController()
-    scrollViewController.addChild(viewController)
-    scrollViewController.contentView = viewController.view
-    scrollViewController.wrapperView.handlesTouchesOutsideContent = false
-    scrollViewController.wrapperView.alignContentToBottom = true
-    scrollViewController.scrollView.bounces = false
-
-    viewController.didMove(toParent: scrollViewController)
-    return scrollViewController
-  }
-}
diff --git a/Sources/RestoreFeature/ViewModels/RestoreSFTPViewModel.swift b/Sources/RestoreFeature/ViewModels/RestoreSFTPViewModel.swift
index bb81db9e12002ae7cf205eed0c7c728bc2b0d564..d7ffd3e5bfd3bbe701bc36e24e6eec14a6343840 100644
--- a/Sources/RestoreFeature/ViewModels/RestoreSFTPViewModel.swift
+++ b/Sources/RestoreFeature/ViewModels/RestoreSFTPViewModel.swift
@@ -52,7 +52,7 @@ final class RestoreSFTPViewModel {
     let anyController = UIViewController()
 
     DispatchQueue.global().async { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
       do {
         try CloudFilesManager.sftp(
           host: host,
diff --git a/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift b/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
index 14fe7a357499280599ff880287b667dd2859ff6c..c3d2cbe2a8cacdc553e3c52bd3b208ac720d770f 100644
--- a/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
+++ b/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
@@ -97,7 +97,7 @@ final class RestoreViewModel {
     stepSubject.send(.parsingData)
 
     DispatchQueue.global().async { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
 
       do {
         print(">>> Calling messenger destroy")
@@ -109,8 +109,8 @@ final class RestoreViewModel {
           backupPassphrase: self.passphrase
         )
 
-        self.username = result.restoredParams.username
         let facts = try self.messenger.ud.tryGet().getFacts()
+        self.username = facts.get(.username)!.value
         self.email = facts.get(.email)?.value
         self.phone = facts.get(.phone)?.value
 
diff --git a/Sources/ScanFeature/Controllers/ScanContainerController.swift b/Sources/ScanFeature/Controllers/ScanContainerController.swift
index a85c06a797e1013275d261d2cbc51bdbf298db4f..ab6dc5f929e583305b9f8e7377f2d4d8fa4835a9 100644
--- a/Sources/ScanFeature/Controllers/ScanContainerController.swift
+++ b/Sources/ScanFeature/Controllers/ScanContainerController.swift
@@ -1,12 +1,13 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 
 public final class ScanContainerController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: ScanCoordinating
 
   private lazy var screenView = ScanContainerView()
 
@@ -30,7 +31,6 @@ public final class ScanContainerController: UIViewController {
       $0.right.equalToSuperview()
       $0.bottom.equalTo(screenView)
     }
-
     pageController.delegate = self
     pageController.dataSource = self
     pageController.didMove(toParent: self)
@@ -50,20 +50,19 @@ public final class ScanContainerController: UIViewController {
     setupBindings()
 
     displayController.didTapInfo = { [weak self] in
-      self?.presentInfo(
+      guard let self else { return }
+      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)
+      guard let self else { return }
+      self.navigator.perform(PresentProfileEmail())
     }
-
     displayController.didTapAddPhone = { [weak self] in
-      guard let self = self else { return }
-      self.coordinator.toPhone(from: self)
+      guard let self else { return }
+      self.navigator.perform(PresentProfilePhone())
     }
   }
 
@@ -87,7 +86,8 @@ public final class ScanContainerController: UIViewController {
   }
 
   private func setupBindings() {
-    screenView.leftButton
+    screenView
+      .leftButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] _ in
         screenView.leftButton.set(selected: true)
@@ -95,7 +95,8 @@ public final class ScanContainerController: UIViewController {
         pageController.setViewControllers([scanController], direction: .reverse, animated: true, completion: nil)
       }.store(in: &cancellables)
 
-    screenView.rightButton
+    screenView
+      .rightButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] _ in
         screenView.leftButton.set(selected: false)
@@ -105,7 +106,7 @@ public final class ScanContainerController: UIViewController {
   }
 
   @objc private func didTapMenu() {
-    coordinator.toSideMenu(from: self)
+    navigator.perform(PresentMenu(currentItem: .scan))
   }
 
   private func presentInfo(title: String, subtitle: String) {
@@ -115,7 +116,17 @@ public final class ScanContainerController: UIViewController {
       title: Localized.Settings.InfoDrawer.action
     )
 
-    let drawer = DrawerController([
+    actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
       DrawerText(
         font: Fonts.Mulish.bold.font(size: 26.0),
         text: title,
@@ -135,18 +146,7 @@ public final class ScanContainerController: UIViewController {
         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/ScanFeature/Controllers/ScanController.swift b/Sources/ScanFeature/Controllers/ScanController.swift
index 8f05a9446e07f4dacbca8620964dada79e23bd12..8482be4d599b7e84cfc8764d56c57fc4f1f88607 100644
--- a/Sources/ScanFeature/Controllers/ScanController.swift
+++ b/Sources/ScanFeature/Controllers/ScanController.swift
@@ -2,115 +2,122 @@ import UIKit
 import Shared
 import Combine
 import Permissions
+import XXNavigation
 import CombineSchedulers
 import DependencyInjection
 
 final class ScanController: UIViewController {
-    @Dependency private var coordinator: ScanCoordinating
-    @Dependency private var permissions: PermissionHandling
-
-    private lazy var screenView = ScanView()
-
-    var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
-
-    private var status: ScanStatus?
-    private let camera: CameraType
-    private let viewModel = ScanViewModel()
-    private var cancellables = Set<AnyCancellable>()
-
-    init(camera: CameraType = Camera()) {
-         #if DEBUG
-         self.camera = MockCamera()
-         #else
-        self.camera = camera
-         #endif
-
-        super.init(nibName: nil, bundle: nil)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    override func loadView() {
-        view = screenView
-    }
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        screenView.layer.insertSublayer(camera.previewLayer, at: 0)
-        setupBindings()
-    }
-
-    override func viewDidLayoutSubviews() {
-        super.viewDidLayoutSubviews()
-        camera.previewLayer.frame = screenView.bounds
+  @Dependency var navigator: Navigator
+  @Dependency var permissions: PermissionHandling
+  
+  private lazy var screenView = ScanView()
+  
+  var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
+  
+  private var status: ScanStatus?
+  private let camera: CameraType
+  private let viewModel = ScanViewModel()
+  private var cancellables = Set<AnyCancellable>()
+  
+  init(camera: CameraType = Camera()) {
+#if DEBUG
+    self.camera = MockCamera()
+#else
+    self.camera = camera
+#endif
+    
+    super.init(nibName: nil, bundle: nil)
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  override func loadView() {
+    view = screenView
+  }
+  
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    screenView.layer.insertSublayer(camera.previewLayer, at: 0)
+    setupBindings()
+  }
+  
+  override func viewDidLayoutSubviews() {
+    super.viewDidLayoutSubviews()
+    camera.previewLayer.frame = screenView.bounds
+  }
+  
+  override func viewDidAppear(_ animated: Bool) {
+    super.viewDidAppear(animated)
+    viewModel.resetScanner()
+    startCamera()
+  }
+  
+  override func viewWillDisappear(_ animated: Bool) {
+    super.viewWillDisappear(animated)
+    backgroundScheduler.schedule { [weak self] in
+      guard let self else { return }
+      self.camera.stop()
     }
-
-    override func viewDidAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-        viewModel.resetScanner()
-        startCamera()
-    }
-
-    override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-        backgroundScheduler.schedule { [weak self] in
-            guard let self = self else { return }
-            self.camera.stop()
+  }
+  
+  private func startCamera() {
+    permissions.requestCamera { [weak self] granted in
+      guard let self else { return }
+      
+      if granted {
+        self.backgroundScheduler.schedule {
+          self.camera.start()
         }
-    }
-
-    private func startCamera() {
-        permissions.requestCamera { [weak self] granted in
-            guard let self = self else { return }
-
-            if granted {
-                self.backgroundScheduler.schedule {
-                    self.camera.start()
-                }
-            } else {
-                DispatchQueue.main.async {
-                    self.status = .failed(.cameraPermission)
-                    self.screenView.update(with: .failed(.cameraPermission))
-                }
-            }
+      } else {
+        DispatchQueue.main.async {
+          self.status = .failed(.cameraPermission)
+          self.screenView.update(with: .failed(.cameraPermission))
         }
+      }
     }
-
-    private func setupBindings() {
-        viewModel.contactPublisher
-            .receive(on: DispatchQueue.main)
-            .delay(for: 1, scheduler: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toContact($0, from: self) }
-            .store(in: &cancellables)
-
-        viewModel.statePublisher
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                status = $0
-                screenView.update(with: $0)
-            }.store(in: &cancellables)
-
-        screenView.actionButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                switch status {
-                case .failed(.cameraPermission):
-                    guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
-                    UIApplication.shared.open(url, options: [:])
-                case .failed(.requestOpened):
-                    coordinator.toRequests(from: self)
-                case .failed(.alreadyFriends):
-                    coordinator.toContacts(from: self)
-                default:
-                    break
-                }
-            }.store(in: &cancellables)
-
-        camera
-            .dataPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] data in viewModel.didScanData(data) }
-            .store(in: &cancellables)
-    }
+  }
+  
+  private func setupBindings() {
+    viewModel
+      .contactPublisher
+      .receive(on: DispatchQueue.main)
+      .delay(for: 1, scheduler: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(PresentContact(contact: $0))
+      }.store(in: &cancellables)
+    
+    viewModel
+      .statePublisher
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        status = $0
+        screenView.update(with: $0)
+      }.store(in: &cancellables)
+    
+    screenView
+      .actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        switch status {
+        case .failed(.cameraPermission):
+          guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
+          UIApplication.shared.open(url, options: [:])
+        case .failed(.requestOpened):
+          navigator.perform(PresentRequests())
+        case .failed(.alreadyFriends):
+          navigator.perform(PresentContactList())
+        default:
+          break
+        }
+      }.store(in: &cancellables)
+    
+    camera
+      .dataPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        viewModel.didScanData($0)
+      }.store(in: &cancellables)
+  }
 }
diff --git a/Sources/ScanFeature/Coordinator/ScanCoordinator.swift b/Sources/ScanFeature/Coordinator/ScanCoordinator.swift
deleted file mode 100644
index cfdc386a14896148ffff2844e62df64a61d2f40d..0000000000000000000000000000000000000000
--- a/Sources/ScanFeature/Coordinator/ScanCoordinator.swift
+++ /dev/null
@@ -1,87 +0,0 @@
-import UIKit
-import XXModels
-import MenuFeature
-import Presentation
-import ContactFeature
-
-public protocol ScanCoordinating {
-    func toEmail(from: UIViewController)
-    func toPhone(from: UIViewController)
-    func toContacts(from: UIViewController)
-    func toRequests(from: UIViewController)
-    func toSideMenu(from: UIViewController)
-    func toContact(_: Contact, from: UIViewController)
-    func toDrawer(_: UIViewController, from: UIViewController)
-}
-
-public struct ScanCoordinator: ScanCoordinating {
-    var pushPresenter: Presenting = PushPresenter()
-    var sidePresenter: Presenting = SideMenuPresenter()
-    var bottomPresenter: Presenting = BottomPresenter()
-    var replacePresenter: Presenting = ReplacePresenter(mode: .replaceLast)
-
-    var emailFactory: () -> UIViewController
-    var phoneFactory: () -> UIViewController
-    var contactsFactory: () -> UIViewController
-    var requestsFactory: () -> UIViewController
-    var contactFactory: (Contact) -> UIViewController
-    var sideMenuFactory: (MenuItem, UIViewController) -> UIViewController
-
-    public init(
-        emailFactory: @escaping () -> UIViewController,
-        phoneFactory: @escaping () -> UIViewController,
-        contactsFactory: @escaping () -> UIViewController,
-        requestsFactory: @escaping () -> UIViewController,
-        contactFactory: @escaping (Contact) -> UIViewController,
-        sideMenuFactory: @escaping (MenuItem, UIViewController) -> UIViewController
-    ) {
-        self.emailFactory = emailFactory
-        self.phoneFactory = phoneFactory
-        self.contactFactory = contactFactory
-        self.contactsFactory = contactsFactory
-        self.requestsFactory = requestsFactory
-        self.sideMenuFactory = sideMenuFactory
-    }
-}
-
-public extension ScanCoordinator {
-    func toContact(
-        _ contact: Contact,
-        from parent: UIViewController
-    ) {
-        let screen = contactFactory(contact)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toDrawer(
-        _ drawer: UIViewController,
-        from parent: UIViewController
-    ) {
-        bottomPresenter.present(drawer, from: parent)
-    }
-
-    func toRequests(from parent: UIViewController) {
-        let screen = requestsFactory()
-        replacePresenter.present(screen, from: parent)
-    }
-
-    func toContacts(from parent: UIViewController) {
-        let screen = contactsFactory()
-        replacePresenter.present(screen, from: parent)
-    }
-
-    func toSideMenu(from parent: UIViewController) {
-        let screen = sideMenuFactory(.scan, parent)
-        sidePresenter.present(screen, from: parent)
-    }
-
-    func toEmail(from parent: UIViewController) {
-        let screen = emailFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toPhone(from parent: UIViewController) {
-        let screen = phoneFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-}
diff --git a/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift b/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift
index 00be78ca17fc1a4c30ce13e166bf5c0e18b7f6f3..d67716bc57d7d03ad09ce2381da75ce3ba33567d 100644
--- a/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift
+++ b/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift
@@ -1,4 +1,5 @@
 import UIKit
+import Shared
 import Combine
 import Defaults
 import Countries
diff --git a/Sources/SearchFeature/Controllers/SearchContainerController.swift b/Sources/SearchFeature/Controllers/SearchContainerController.swift
index a78f5993fb3a7381f0f337884a8e03a878324bac..6e81b0dfc7bafc4bde8ef647c79a6ec4bd829b46 100644
--- a/Sources/SearchFeature/Controllers/SearchContainerController.swift
+++ b/Sources/SearchFeature/Controllers/SearchContainerController.swift
@@ -2,12 +2,13 @@ import UIKit
 import Shared
 import Combine
 import XXModels
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 
 public final class SearchContainerController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: SearchCoordinating
 
   private lazy var screenView = SearchContainerView()
 
@@ -130,14 +131,34 @@ extension SearchContainerController {
       style: .brandColored,
       title: Localized.ChatList.Traffic.positive
     )
-
     let dismissButton = CapsuleButton()
     dismissButton.set(
       style: .seeThrough,
       title: Localized.ChatList.Traffic.negative
     )
 
-    let drawer = DrawerController([
+    enableButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didEnableCoverTraffic()
+        }
+      }.store(in: &drawerCancellables)
+
+    dismissButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
       DrawerText(
         font: Fonts.Mulish.bold.font(size: 26.0),
         text: Localized.ChatList.Traffic.title,
@@ -159,29 +180,6 @@ extension SearchContainerController {
         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)
+    ]))
   }
 }
diff --git a/Sources/SearchFeature/Controllers/SearchLeftController.swift b/Sources/SearchFeature/Controllers/SearchLeftController.swift
index bc6b1fbd5f78c9fc6a62b705f11bdf929a6e1faf..8370152285392b1d722c41013a687dee5c254502 100644
--- a/Sources/SearchFeature/Controllers/SearchLeftController.swift
+++ b/Sources/SearchFeature/Controllers/SearchLeftController.swift
@@ -4,445 +4,469 @@ import Combine
 import XXModels
 import Defaults
 import Countries
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 
 final class SearchLeftController: UIViewController {
-    @Dependency var coordinator: SearchCoordinating
-
-    @KeyObject(.email, defaultValue: nil) var email: String?
-    @KeyObject(.phone, defaultValue: nil) var phone: String?
-    @KeyObject(.sharingEmail, defaultValue: false) var isSharingEmail: Bool
-    @KeyObject(.sharingPhone, defaultValue: false) var isSharingPhone: Bool
-
-    private lazy var screenView = SearchLeftView()
-
-    let viewModel: SearchLeftViewModel
-    private var dataSource: SearchDiffableDataSource!
-    private var drawerCancellables = Set<AnyCancellable>()
-    private let adrpURLString = "https://links.xx.network/adrp"
-
-    private var cancellables = Set<AnyCancellable>()
-    private var hudCancellables = Set<AnyCancellable>()
-
-    init(_ invitation: String? = nil) {
-        self.viewModel = .init(invitation)
-        super.init(nibName: nil, bundle: nil)
-    }
-
-    required init?(coder: NSCoder) { nil }
+  @Dependency var navigator: Navigator
+  @KeyObject(.email, defaultValue: nil) var email: String?
+  @KeyObject(.phone, defaultValue: nil) var phone: String?
+  @KeyObject(.sharingEmail, defaultValue: false) var isSharingEmail: Bool
+  @KeyObject(.sharingPhone, defaultValue: false) var isSharingPhone: Bool
+
+  private lazy var screenView = SearchLeftView()
+
+  private(set) var viewModel: SearchLeftViewModel
+  private var dataSource: SearchDiffableDataSource!
+  private var drawerCancellables = Set<AnyCancellable>()
+  private let adrpURLString = "https://links.xx.network/adrp"
+
+  private var cancellables = Set<AnyCancellable>()
+  private var hudCancellables = Set<AnyCancellable>()
+
+  init(_ invitation: String? = nil) {
+    self.viewModel = .init(invitation)
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  override func loadView() {
+    view = screenView
+  }
+
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    setupTableView()
+    setupBindings()
+  }
+
+  override func viewDidAppear(_ animated: Bool) {
+    super.viewDidAppear(animated)
+    viewModel.viewDidAppear()
+  }
+
+  func endEditing() {
+    screenView.inputField.endEditing(true)
+  }
+
+  private func setupTableView() {
+    screenView.tableView.separatorStyle = .none
+    screenView.tableView.tableFooterView = UIView()
+    screenView.tableView.register(AvatarCell.self)
+    screenView.tableView.dataSource = dataSource
+    screenView.tableView.delegate = self
+
+    dataSource = SearchDiffableDataSource(
+      tableView: screenView.tableView
+    ) { tableView, indexPath, item in
+      let contact: Contact
+      let cell = tableView.dequeueReusableCell(forIndexPath: indexPath, ofType: AvatarCell.self)
+
+      let h1Text: String
+      var h2Text: String?
+
+      switch item {
+      case .stranger(let stranger):
+        contact = stranger
+        h1Text = stranger.username ?? ""
+
+        if stranger.authStatus == .requested {
+          h2Text = "Request pending"
+        } else if stranger.authStatus == .requestFailed {
+          h2Text = "Request failed"
+        }
 
-    override func loadView() {
-        view = screenView
-    }
+      case .connection(let connection):
+        contact = connection
+        h1Text = (connection.nickname ?? contact.username) ?? ""
 
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        setupTableView()
-        setupBindings()
+        if connection.nickname != nil {
+          h2Text = contact.username ?? ""
+        }
+      }
+
+      cell.setup(
+        title: h1Text,
+        image: contact.photo,
+        firstSubtitle: h2Text,
+        secondSubtitle: contact.email,
+        thirdSubtitle: contact.phone,
+        showSeparator: false,
+        sent: contact.authStatus == .requested
+      )
+
+      cell.didTapStateButton = { [weak self] in
+        guard let self else { return }
+        self.viewModel.didTapResend(contact: contact)
+        cell.updateToResent()
+      }
+
+      return cell
     }
+  }
+
+  private func setupBindings() {
+    //        viewModel.hudPublisher
+    //            .removeDuplicates()
+    //            .receive(on: DispatchQueue.main)
+    //            .sink { [unowned self] in
+    //                hud.update(with: $0)
+    //
+    //                if case .onAction = $0, let hudBtn = hud.actionButton {
+    //                    hudBtn.publisher(for: .touchUpInside)
+    //                        .receive(on: DispatchQueue.main)
+    //                        .sink { [unowned self] in viewModel.didTapCancelSearch() }
+    //                        .store(in: &self.hudCancellables)
+    //                } else {
+    //                    hudCancellables.forEach { $0.cancel() }
+    //                    hudCancellables.removeAll()
+    //                }
+    //            }
+    //            .store(in: &cancellables)
+
+    viewModel
+      .statePublisher
+      .map(\.item)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.updateUIForItem(item: $0)
+      }.store(in: &cancellables)
+
+    viewModel
+      .statePublisher
+      .map(\.country)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.countryButton.setFlag($0.flag, prefix: $0.prefix)
+      }.store(in: &cancellables)
+
+    viewModel
+      .statePublisher
+      .map(\.input)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.inputField.update(content: $0)
+      }.store(in: &cancellables)
+
+    viewModel
+      .statePublisher
+      .compactMap(\.snapshot)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.placeholderView.isHidden = true
+        screenView.emptyView.isHidden = $0.numberOfItems != 0
+        dataSource.apply($0, animatingDifferences: false)
+      }.store(in: &cancellables)
+
+    screenView
+      .placeholderView
+      .infoPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        presentSearchDisclaimer()
+      }.store(in: &cancellables)
+
+    screenView
+      .countryButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(PresentCountryList(completion: { [weak self] in
+          guard let self else { return }
+          self.viewModel.didPick(country: $0)
+        }))
+      }.store(in: &cancellables)
+
+    screenView
+      .inputField
+      .textPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        viewModel.didEnterInput($0)
+      }.store(in: &cancellables)
+
+    screenView
+      .inputField
+      .returnPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] _ in
+        viewModel.didStartSearching()
+      }.store(in: &cancellables)
+
+    screenView
+      .inputField
+      .isEditingPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] isEditing in
+        UIView.animate(withDuration: 0.25) {
+          self.screenView.placeholderView.titleLabel.alpha = isEditing ? 0.1 : 1.0
+          self.screenView.placeholderView.subtitleWithInfo.alpha = isEditing ? 0.1 : 1.0
+        }
+      }.store(in: &cancellables)
+
+    viewModel
+      .successPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        presentSucessDrawerFor(contact: $0)
+      }.store(in: &cancellables)
+  }
+
+  private func presentSearchDisclaimer() {
+    let actionButton = CapsuleButton()
+    actionButton.set(
+      style: .seeThrough,
+      title: Localized.Ud.Placeholder.Drawer.action
+    )
+
+    actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
+      DrawerText(
+        font: Fonts.Mulish.bold.font(size: 26.0),
+        text: Localized.Ud.Placeholder.Drawer.title,
+        color: Asset.neutralActive.color,
+        alignment: .left,
+        spacingAfter: 19
+      ),
+      DrawerLinkText(
+        text: Localized.Ud.Placeholder.Drawer.subtitle,
+        urlString: adrpURLString,
+        spacingAfter: 37
+      ),
+      DrawerStack(views: [
+        actionButton,
+        FlexibleSpace()
+      ])
+    ]))
+  }
+
+  private func presentSucessDrawerFor(contact: Contact) {
+    var items: [DrawerItem] = []
+
+    let drawerTitle = DrawerText(
+      font: Fonts.Mulish.extraBold.font(size: 26.0),
+      text: Localized.Ud.NicknameDrawer.title,
+      color: Asset.neutralDark.color,
+      spacingAfter: 20
+    )
+
+    let drawerSubtitle = DrawerText(
+      font: Fonts.Mulish.regular.font(size: 16.0),
+      text: Localized.Ud.NicknameDrawer.subtitle,
+      color: Asset.neutralDark.color,
+      spacingAfter: 20
+    )
+
+    items.append(contentsOf: [
+      drawerTitle,
+      drawerSubtitle
+    ])
+
+    let drawerNicknameInput = DrawerInput(
+      placeholder: contact.username!,
+      validator: .init(
+        wrongIcon: .image(Asset.sharedError.image),
+        correctIcon: .image(Asset.sharedSuccess.image),
+        shouldAcceptPlaceholder: true
+      ),
+      spacingAfter: 29
+    )
+
+    items.append(drawerNicknameInput)
+
+    let drawerSaveButton = DrawerCapsuleButton(
+      model: .init(
+        title: Localized.Ud.NicknameDrawer.save,
+        style: .brandColored
+      ), spacingAfter: 5
+    )
+
+    items.append(drawerSaveButton)
+
+    let drawer = DrawerController(items)
+    var nickname: String?
+    var allowsSave = true
+
+    drawerNicknameInput
+      .validationPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { allowsSave = $0 }
+      .store(in: &drawerCancellables)
+
+    drawerNicknameInput
+      .inputPublisher
+      .receive(on: DispatchQueue.main)
+      .sink {
+        guard !$0.isEmpty else {
+          nickname = contact.username
+          return
+        }
 
-    override func viewDidAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-        viewModel.viewDidAppear()
-    }
+        nickname = $0
+      }
+      .store(in: &drawerCancellables)
 
-    func endEditing() {
-        screenView.inputField.endEditing(true)
-    }
+    drawerSaveButton.action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        guard allowsSave else { return }
 
-    private func setupTableView() {
-        screenView.tableView.separatorStyle = .none
-        screenView.tableView.tableFooterView = UIView()
-        screenView.tableView.register(AvatarCell.self)
-        screenView.tableView.dataSource = dataSource
-        screenView.tableView.delegate = self
-
-        dataSource = SearchDiffableDataSource(
-            tableView: screenView.tableView
-        ) { tableView, indexPath, item in
-            let contact: Contact
-            let cell = tableView.dequeueReusableCell(forIndexPath: indexPath, ofType: AvatarCell.self)
-
-            let h1Text: String
-            var h2Text: String?
-
-            switch item {
-            case .stranger(let stranger):
-                contact = stranger
-                h1Text = stranger.username ?? ""
-
-                if stranger.authStatus == .requested {
-                    h2Text = "Request pending"
-                } else if stranger.authStatus == .requestFailed {
-                    h2Text = "Request failed"
-                }
-
-            case .connection(let connection):
-                contact = connection
-                h1Text = (connection.nickname ?? contact.username) ?? ""
-
-                if connection.nickname != nil {
-                    h2Text = contact.username ?? ""
-                }
-            }
-
-            cell.setup(
-                title: h1Text,
-                image: contact.photo,
-                firstSubtitle: h2Text,
-                secondSubtitle: contact.email,
-                thirdSubtitle: contact.phone,
-                showSeparator: false,
-                sent: contact.authStatus == .requested
-            )
-
-            cell.didTapStateButton = { [weak self] in
-                guard let self = self else { return }
-                self.viewModel.didTapResend(contact: contact)
-                cell.updateToResent()
-            }
-
-            return cell
+        drawer.dismiss(animated: true) {
+          self.viewModel.didSet(nickname: nickname ?? contact.username!, for: contact)
         }
+      }
+      .store(in: &drawerCancellables)
+
+    //coordinator.toNicknameDrawer(drawer, from: self)
+  }
+
+  private func presentRequestDrawer(forContact contact: Contact) {
+    var items: [DrawerItem] = []
+
+    let drawerTitle = DrawerText(
+      font: Fonts.Mulish.extraBold.font(size: 26.0),
+      text: Localized.Ud.RequestDrawer.title,
+      color: Asset.neutralDark.color,
+      spacingAfter: 20
+    )
+
+    var subtitleFragment = "Share your information with #\(contact.username ?? "")"
+
+    if let email = contact.email {
+      subtitleFragment.append(contentsOf: " (\(email))#")
+    } else if let phone = contact.phone {
+      subtitleFragment.append(contentsOf: " (\(Country.findFrom(phone).prefix) \(phone.dropLast(2)))#")
+    } else {
+      subtitleFragment.append(contentsOf: "#")
     }
 
-    private func setupBindings() {
-//        viewModel.hudPublisher
-//            .removeDuplicates()
-//            .receive(on: DispatchQueue.main)
-//            .sink { [unowned self] in
-//                hud.update(with: $0)
-//
-//                if case .onAction = $0, let hudBtn = hud.actionButton {
-//                    hudBtn.publisher(for: .touchUpInside)
-//                        .receive(on: DispatchQueue.main)
-//                        .sink { [unowned self] in viewModel.didTapCancelSearch() }
-//                        .store(in: &self.hudCancellables)
-//                } else {
-//                    hudCancellables.forEach { $0.cancel() }
-//                    hudCancellables.removeAll()
-//                }
-//            }
-//            .store(in: &cancellables)
-
-        viewModel.statePublisher
-            .map(\.item)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.updateUIForItem(item: $0) }
-            .store(in: &cancellables)
-
-        viewModel.statePublisher
-            .map(\.country)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.countryButton.setFlag($0.flag, prefix: $0.prefix) }
-            .store(in: &cancellables)
-
-        viewModel.statePublisher
-            .map(\.input)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in screenView.inputField.update(content: $0) }
-            .store(in: &cancellables)
-
-        viewModel.statePublisher
-            .compactMap(\.snapshot)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                screenView.placeholderView.isHidden = true
-                screenView.emptyView.isHidden = $0.numberOfItems != 0
-
-                dataSource.apply($0, animatingDifferences: false)
-            }.store(in: &cancellables)
-
-        screenView.placeholderView
-            .infoPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in presentSearchDisclaimer() }
-            .store(in: &cancellables)
-
-        screenView.countryButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                coordinator.toCountries(from: self) { [weak self] country in
-                    guard let self = self else { return }
-                    self.viewModel.didPick(country: country)
-                }
-            }.store(in: &cancellables)
-
-        screenView.inputField
-            .textPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in viewModel.didEnterInput($0) }
-            .store(in: &cancellables)
-
-        screenView.inputField
-            .returnPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] _ in viewModel.didStartSearching() }
-            .store(in: &cancellables)
-
-        screenView.inputField
-            .isEditingPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] isEditing in
-                UIView.animate(withDuration: 0.25) {
-                    self.screenView.placeholderView.titleLabel.alpha = isEditing ? 0.1 : 1.0
-                    self.screenView.placeholderView.subtitleWithInfo.alpha = isEditing ? 0.1 : 1.0
-                }
-            }.store(in: &cancellables)
-
-        viewModel.successPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in presentSucessDrawerFor(contact: $0) }
-            .store(in: &cancellables)
+    subtitleFragment.append(contentsOf: " so they know its you.")
+
+    let drawerSubtitle = DrawerText(
+      font: Fonts.Mulish.regular.font(size: 16.0),
+      text: subtitleFragment,
+      color: Asset.neutralDark.color,
+      spacingAfter: 31.5,
+      customAttributes: [
+        .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
+        .foregroundColor: Asset.brandPrimary.color
+      ]
+    )
+
+    items.append(contentsOf: [
+      drawerTitle,
+      drawerSubtitle
+    ])
+
+    if let email = email {
+      let drawerEmail = DrawerSwitch(
+        title: Localized.Ud.RequestDrawer.email,
+        content: email,
+        spacingAfter: phone != nil ? 23 : 31,
+        isInitiallyOn: isSharingEmail
+      )
+
+      items.append(drawerEmail)
+
+      drawerEmail.isOnPublisher
+        .receive(on: DispatchQueue.main)
+        .sink { [weak self] in self?.isSharingEmail = $0 }
+        .store(in: &drawerCancellables)
     }
 
-    private func presentSearchDisclaimer() {
-        let actionButton = CapsuleButton()
-        actionButton.set(
-            style: .seeThrough,
-            title: Localized.Ud.Placeholder.Drawer.action
-        )
-
-        let drawer = DrawerController([
-            DrawerText(
-                font: Fonts.Mulish.bold.font(size: 26.0),
-                text: Localized.Ud.Placeholder.Drawer.title,
-                color: Asset.neutralActive.color,
-                alignment: .left,
-                spacingAfter: 19
-            ),
-            DrawerLinkText(
-                text: Localized.Ud.Placeholder.Drawer.subtitle,
-                urlString: adrpURLString,
-                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: &self.drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+    if let phone = phone {
+      let drawerPhone = DrawerSwitch(
+        title: Localized.Ud.RequestDrawer.phone,
+        content: "\(Country.findFrom(phone).prefix) \(phone.dropLast(2))",
+        spacingAfter: 31,
+        isInitiallyOn: isSharingPhone
+      )
 
-    private func presentSucessDrawerFor(contact: Contact) {
-        var items: [DrawerItem] = []
-
-        let drawerTitle = DrawerText(
-            font: Fonts.Mulish.extraBold.font(size: 26.0),
-            text: Localized.Ud.NicknameDrawer.title,
-            color: Asset.neutralDark.color,
-            spacingAfter: 20
-        )
-
-        let drawerSubtitle = DrawerText(
-            font: Fonts.Mulish.regular.font(size: 16.0),
-            text: Localized.Ud.NicknameDrawer.subtitle,
-            color: Asset.neutralDark.color,
-            spacingAfter: 20
-        )
-
-        items.append(contentsOf: [
-            drawerTitle,
-            drawerSubtitle
-        ])
-
-        let drawerNicknameInput = DrawerInput(
-            placeholder: contact.username!,
-            validator: .init(
-                wrongIcon: .image(Asset.sharedError.image),
-                correctIcon: .image(Asset.sharedSuccess.image),
-                shouldAcceptPlaceholder: true
-            ),
-            spacingAfter: 29
-        )
-
-        items.append(drawerNicknameInput)
-
-        let drawerSaveButton = DrawerCapsuleButton(
-            model: .init(
-                title: Localized.Ud.NicknameDrawer.save,
-                style: .brandColored
-            ), spacingAfter: 5
-        )
-
-        items.append(drawerSaveButton)
-
-        let drawer = DrawerController(items)
-        var nickname: String?
-        var allowsSave = true
-
-        drawerNicknameInput.validationPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { allowsSave = $0 }
-            .store(in: &drawerCancellables)
-
-        drawerNicknameInput.inputPublisher
-            .receive(on: DispatchQueue.main)
-            .sink {
-                guard !$0.isEmpty else {
-                    nickname = contact.username
-                    return
-                }
-
-                nickname = $0
-            }
-            .store(in: &drawerCancellables)
-
-        drawerSaveButton.action
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                guard allowsSave else { return }
-
-                drawer.dismiss(animated: true) {
-                    self.viewModel.didSet(nickname: nickname ?? contact.username!, for: contact)
-                }
-            }
-            .store(in: &drawerCancellables)
-
-        coordinator.toNicknameDrawer(drawer, from: self)
-    }
-
-    private func presentRequestDrawer(forContact contact: Contact) {
-        var items: [DrawerItem] = []
+      items.append(drawerPhone)
 
-        let drawerTitle = DrawerText(
-            font: Fonts.Mulish.extraBold.font(size: 26.0),
-            text: Localized.Ud.RequestDrawer.title,
-            color: Asset.neutralDark.color,
-            spacingAfter: 20
-        )
-
-        var subtitleFragment = "Share your information with #\(contact.username ?? "")"
+      drawerPhone.isOnPublisher
+        .receive(on: DispatchQueue.main)
+        .sink { [weak self] in self?.isSharingPhone = $0 }
+        .store(in: &drawerCancellables)
+    }
 
-        if let email = contact.email {
-            subtitleFragment.append(contentsOf: " (\(email))#")
-        } else if let phone = contact.phone {
-            subtitleFragment.append(contentsOf: " (\(Country.findFrom(phone).prefix) \(phone.dropLast(2)))#")
-        } else {
-            subtitleFragment.append(contentsOf: "#")
+    let drawerSendButton = DrawerCapsuleButton(
+      model: .init(
+        title: Localized.Ud.RequestDrawer.send,
+        style: .brandColored
+      ), spacingAfter: 5
+    )
+
+    let drawerCancelButton = DrawerCapsuleButton(
+      model: .init(
+        title: Localized.Ud.RequestDrawer.cancel,
+        style: .simplestColoredBrand
+      ), spacingAfter: 5
+    )
+
+    items.append(contentsOf: [drawerSendButton, drawerCancelButton])
+
+    drawerSendButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          self.viewModel.didTapRequest(contact: contact)
         }
-
-        subtitleFragment.append(contentsOf: " so they know its you.")
-
-        let drawerSubtitle = DrawerText(
-            font: Fonts.Mulish.regular.font(size: 16.0),
-            text: subtitleFragment,
-            color: Asset.neutralDark.color,
-            spacingAfter: 31.5,
-            customAttributes: [
-                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
-                .foregroundColor: Asset.brandPrimary.color
-            ]
-        )
-
-        items.append(contentsOf: [
-            drawerTitle,
-            drawerSubtitle
-        ])
-
-        if let email = email {
-            let drawerEmail = DrawerSwitch(
-                title: Localized.Ud.RequestDrawer.email,
-                content: email,
-                spacingAfter: phone != nil ? 23 : 31,
-                isInitiallyOn: isSharingEmail
-            )
-
-            items.append(drawerEmail)
-
-            drawerEmail.isOnPublisher
-                .receive(on: DispatchQueue.main)
-                .sink { [weak self] in self?.isSharingEmail = $0 }
-                .store(in: &drawerCancellables)
+      }.store(in: &drawerCancellables)
+
+    drawerCancelButton
+      .action
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
         }
+      }.store(in: &drawerCancellables)
 
-        if let phone = phone {
-            let drawerPhone = DrawerSwitch(
-                title: Localized.Ud.RequestDrawer.phone,
-                content: "\(Country.findFrom(phone).prefix) \(phone.dropLast(2))",
-                spacingAfter: 31,
-                isInitiallyOn: isSharingPhone
-            )
-
-            items.append(drawerPhone)
-
-            drawerPhone.isOnPublisher
-                .receive(on: DispatchQueue.main)
-                .sink { [weak self] in self?.isSharingPhone = $0 }
-                .store(in: &drawerCancellables)
-        }
-
-        let drawerSendButton = DrawerCapsuleButton(
-            model: .init(
-                title: Localized.Ud.RequestDrawer.send,
-                style: .brandColored
-            ), spacingAfter: 5
-        )
-
-        let drawerCancelButton = DrawerCapsuleButton(
-            model: .init(
-                title: Localized.Ud.RequestDrawer.cancel,
-                style: .simplestColoredBrand
-            ), spacingAfter: 5
-        )
-
-        items.append(contentsOf: [drawerSendButton, drawerCancelButton])
-        let drawer = DrawerController(items)
-
-        drawerSendButton.action
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                drawer.dismiss(animated: true) {
-                    self.viewModel.didTapRequest(contact: contact)
-                }
-            }.store(in: &drawerCancellables)
-
-        drawerCancelButton.action
-            .receive(on: DispatchQueue.main)
-            .sink { drawer.dismiss(animated: true) }
-            .store(in: &drawerCancellables)
-
-        coordinator.toDrawer(drawer, from: self)
-    }
+    navigator.perform(PresentDrawer(items: items))
+  }
 }
 
 extension SearchLeftController: UITableViewDelegate {
-    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        if let item = dataSource.itemIdentifier(for: indexPath) {
-            switch item {
-            case .stranger(let contact):
-                didTap(contact: contact)
-            case .connection(let contact):
-                didTap(contact: contact)
-            }
-        }
+  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+    if let item = dataSource.itemIdentifier(for: indexPath) {
+      switch item {
+      case .stranger(let contact):
+        didTap(contact: contact)
+      case .connection(let contact):
+        didTap(contact: contact)
+      }
     }
+  }
 
-    func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
-        (view as! UITableViewHeaderFooterView).textLabel?.textColor = Asset.neutralWeak.color
-    }
+  func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
+    (view as! UITableViewHeaderFooterView).textLabel?.textColor = Asset.neutralWeak.color
+  }
 
-    private func didTap(contact: Contact) {
-        guard contact.authStatus == .stranger else {
-            coordinator.toContact(contact, from: self)
-            return
-        }
-
-        presentRequestDrawer(forContact: contact)
+  private func didTap(contact: Contact) {
+    guard contact.authStatus == .stranger else {
+      navigator.perform(PresentContact(contact: contact))
+      return
     }
+
+    presentRequestDrawer(forContact: contact)
+  }
 }
diff --git a/Sources/SearchFeature/Controllers/SearchRightController.swift b/Sources/SearchFeature/Controllers/SearchRightController.swift
index 4541af0f7fb5cf16f9411edfbe71661f9a2da3d1..cbd9789826b16d026e9111d0572a66511d99c625 100644
--- a/Sources/SearchFeature/Controllers/SearchRightController.swift
+++ b/Sources/SearchFeature/Controllers/SearchRightController.swift
@@ -1,81 +1,88 @@
 import UIKit
 import Combine
+import XXNavigation
 import DependencyInjection
 
 final class SearchRightController: UIViewController {
-    @Dependency var coordinator: SearchCoordinating
+  @Dependency var navigator: Navigator
 
-    private lazy var screenView = SearchRightView()
+  private lazy var screenView = SearchRightView()
 
-    private var cancellables = Set<AnyCancellable>()
-    private let cameraController = CameraController()
-    private(set) var viewModel = SearchRightViewModel()
+  private var cancellables = Set<AnyCancellable>()
+  private let cameraController = CameraController()
+  private(set) var viewModel = SearchRightViewModel()
 
-    override func loadView() {
-        view = screenView
-    }
+  override func loadView() {
+    view = screenView
+  }
 
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        screenView.layer.insertSublayer(cameraController.previewLayer, at: 0)
-        setupBindings()
-    }
+  override func viewDidLayoutSubviews() {
+    super.viewDidLayoutSubviews()
+    cameraController.previewLayer.frame = screenView.bounds
+  }
 
-    override func viewDidLayoutSubviews() {
-        super.viewDidLayoutSubviews()
-        cameraController.previewLayer.frame = screenView.bounds
-    }
+  override func viewWillDisappear(_ animated: Bool) {
+    super.viewWillDisappear(animated)
+    viewModel.viewWillDisappear()
+  }
 
-    override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-        viewModel.viewWillDisappear()
-    }
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    screenView.layer.insertSublayer(
+      cameraController.previewLayer, at: 0
+    )
 
-    private func setupBindings() {
-        cameraController
-            .dataPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in viewModel.didScan(data: $0) }
-            .store(in: &cancellables)
+    cameraController
+      .dataPublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        viewModel.didScan(data: $0)
+      }.store(in: &cancellables)
 
-        viewModel.cameraSemaphorePublisher
-            .removeDuplicates()
-            .receive(on: DispatchQueue.global())
-            .sink { [unowned self] setOn in
-                if setOn {
-                    cameraController.start()
-                } else {
-                    cameraController.stop()
-                }
-            }.store(in: &cancellables)
+    viewModel
+      .cameraSemaphorePublisher
+      .removeDuplicates()
+      .receive(on: DispatchQueue.global())
+      .sink { [unowned self] in
+        if $0 {
+          cameraController.start()
+        } else {
+          cameraController.stop()
+        }
+      }.store(in: &cancellables)
 
-        viewModel.foundPublisher
-            .receive(on: DispatchQueue.main)
-            .delay(for: 1, scheduler: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toContact($0, from: self) }
-            .store(in: &cancellables)
+    viewModel
+      .foundPublisher
+      .receive(on: DispatchQueue.main)
+      .delay(for: 1, scheduler: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(PresentContact(contact: $0))
+      }.store(in: &cancellables)
 
-        viewModel.statusPublisher
-            .receive(on: DispatchQueue.main)
-            .removeDuplicates()
-            .sink { [unowned self] in screenView.update(status: $0) }
-            .store(in: &cancellables)
+    viewModel
+      .statusPublisher
+      .receive(on: DispatchQueue.main)
+      .removeDuplicates()
+      .sink { [unowned self] in
+        screenView.update(status: $0)
+      }.store(in: &cancellables)
 
-        screenView.actionButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                switch viewModel.statusSubject.value {
-                case .failed(.cameraPermission):
-                    guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
-                    UIApplication.shared.open(url, options: [:])
-                case .failed(.requestOpened):
-                    coordinator.toRequests(from: self)
-                case .failed(.alreadyFriends):
-                    coordinator.toContacts(from: self)
-                default:
-                    break
-                }
-            }.store(in: &cancellables)
-    }
+    screenView
+      .actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        switch viewModel.statusSubject.value {
+        case .failed(.cameraPermission):
+          guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
+          UIApplication.shared.open(url, options: [:])
+        case .failed(.requestOpened):
+          navigator.perform(PresentRequests())
+        case .failed(.alreadyFriends):
+          navigator.perform(PresentContactList())
+        default:
+          break
+        }
+      }.store(in: &cancellables)
+  }
 }
diff --git a/Sources/SearchFeature/Coordinator/SearchCoordinator.swift b/Sources/SearchFeature/Coordinator/SearchCoordinator.swift
deleted file mode 100644
index 053e5b659fb1d3179c7d184e4ca30263d556b1cc..0000000000000000000000000000000000000000
--- a/Sources/SearchFeature/Coordinator/SearchCoordinator.swift
+++ /dev/null
@@ -1,83 +0,0 @@
-import UIKit
-import XXModels
-import Countries
-import Presentation
-import ScrollViewController
-
-public protocol SearchCoordinating {
-    func toRequests(from: UIViewController)
-    func toContacts(from: UIViewController)
-    func toContact(_: Contact, from: UIViewController)
-    func toDrawer(_: UIViewController, from: UIViewController)
-    func toNicknameDrawer(_: UIViewController, from: UIViewController)
-    func toCountries(from: UIViewController, _: @escaping (Country) -> Void)
-}
-
-public struct SearchCoordinator {
-    var pushPresenter: Presenting = PushPresenter()
-    var bottomPresenter: Presenting = BottomPresenter()
-    var replacePresenter: Presenting = ReplacePresenter()
-    var fullscreenPresenter: Presenting = FullscreenPresenter()
-
-    var contactsFactory: () -> UIViewController
-    var requestsFactory: () -> UIViewController
-    var contactFactory: (Contact) -> UIViewController
-    var countriesFactory: (@escaping (Country) -> Void) -> UIViewController
-
-    public init(
-        contactsFactory: @escaping () -> UIViewController,
-        requestsFactory: @escaping () -> UIViewController,
-        contactFactory: @escaping (Contact) -> UIViewController,
-        countriesFactory: @escaping (@escaping (Country) -> Void) -> UIViewController
-    ) {
-        self.contactFactory = contactFactory
-        self.contactsFactory = contactsFactory
-        self.requestsFactory = requestsFactory
-        self.countriesFactory = countriesFactory
-    }
-}
-
-extension SearchCoordinator: SearchCoordinating {
-    public func toRequests(from parent: UIViewController) {
-        let screen = requestsFactory()
-        replacePresenter.present(screen, from: parent)
-    }
-
-    public func toContacts(from parent: UIViewController) {
-        let screen = contactsFactory()
-        replacePresenter.present(screen, from: parent)
-    }
-
-    public func toContact(_ contact: Contact, from parent: UIViewController) {
-        let screen = contactFactory(contact)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    public func toDrawer(_ drawer: UIViewController, from parent: UIViewController) {
-        bottomPresenter.present(drawer, from: parent)
-    }
-
-    public func toCountries(from parent: UIViewController, _ onChoose: @escaping (Country) -> Void) {
-        let screen = countriesFactory(onChoose)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    public func toNicknameDrawer(_ target: UIViewController, from parent: UIViewController) {
-        let screen = ScrollViewController.embedding(target)
-        fullscreenPresenter.present(screen, from: parent)
-    }
-}
-
-extension ScrollViewController {
-    static func embedding(_ viewController: UIViewController) -> ScrollViewController {
-        let scrollViewController = ScrollViewController()
-        scrollViewController.addChild(viewController)
-        scrollViewController.contentView = viewController.view
-        scrollViewController.wrapperView.handlesTouchesOutsideContent = false
-        scrollViewController.wrapperView.alignContentToBottom = true
-        scrollViewController.scrollView.bounces = false
-
-        viewController.didMove(toParent: scrollViewController)
-        return scrollViewController
-    }
-}
diff --git a/Sources/SearchFeature/ViewModels/SearchContainerViewModel.swift b/Sources/SearchFeature/ViewModels/SearchContainerViewModel.swift
index b221c6fea0631a7d8cb6963b309adc3e75a865f3..9306052b15cd56eb80c7d649635936fab0676334 100644
--- a/Sources/SearchFeature/ViewModels/SearchContainerViewModel.swift
+++ b/Sources/SearchFeature/ViewModels/SearchContainerViewModel.swift
@@ -39,7 +39,7 @@ final class SearchContainerViewModel {
         guard pushNotifications == false else { return }
 
         pushHandler.requestAuthorization { [weak self] result in
-            guard let self = self else { return }
+            guard let self else { return }
 
             switch result {
             case .success(let granted):
diff --git a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
index 969152bdb251cdbb5fcdb27f94931a9928e599c5..8f21ff47a2f5d6fab2517d555ec355b623afc529 100644
--- a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
+++ b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
@@ -116,7 +116,7 @@ final class SearchLeftViewModel {
     }
 
     retry(max: 5, retryStrategy: .delay(seconds: 2)) { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
 
       do {
         let nrr = try self.messenger.cMix.get()!.getNodeRegistrationStatus()
@@ -125,7 +125,7 @@ final class SearchLeftViewModel {
         throw NodeRegistrationError.unhealthyNet
       }
     }.finalCatch { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
 
       if case .unhealthyNet = $0 as? NodeRegistrationError {
         self.hudController.show(.init(content: "Network is not healthy yet, try again within the next minute or so."))
@@ -147,7 +147,7 @@ final class SearchLeftViewModel {
     }
 
     backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
 
       do {
         let report = try SearchUD.live(
@@ -199,7 +199,7 @@ final class SearchLeftViewModel {
     contact.authStatus = .requesting
 
     backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
 
       do {
         try self.database.saveContact(contact)
@@ -245,7 +245,7 @@ final class SearchLeftViewModel {
     contact.authStatus = .requesting
 
     backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
+      guard let self else { return }
 
       do {
         try self.database.saveContact(contact)
@@ -349,7 +349,7 @@ final class SearchLeftViewModel {
     Deferred {
       Future { promise in
         retry(max: timeout, retryStrategy: .delay(seconds: 1)) { [weak self] in
-          guard let self = self else { return }
+          guard let self else { return }
           _ = try self.messenger.cMix.get()!.getNodeRegistrationStatus()
           promise(.success(()))
         }.finalCatch {
diff --git a/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift b/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift
index de6a06eadb6119ca128e7f0aac9205712ec8aca6..d4361d500d2894c05dd73c7ea5259eaa6ea12179 100644
--- a/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift
+++ b/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift
@@ -46,7 +46,7 @@ final class SearchRightViewModel {
 
     func viewWillAppear() {
         permissions.requestCamera { [weak self] granted in
-            guard let self = self else { return }
+            guard let self else { return }
 
             if granted {
                 self.statusSubject.value = .reading
diff --git a/Sources/SearchFeature/Views/SearchLeftPlaceholderView.swift b/Sources/SearchFeature/Views/SearchLeftPlaceholderView.swift
index 7742ff1d64c56151a88ae9b5ae47e82ebb59dc1b..001c6687f16c73fab73f9c0bb2734b549a79d2ed 100644
--- a/Sources/SearchFeature/Views/SearchLeftPlaceholderView.swift
+++ b/Sources/SearchFeature/Views/SearchLeftPlaceholderView.swift
@@ -44,7 +44,7 @@ final class SearchLeftPlaceholderView: UIView {
                 .font: Fonts.Mulish.regular.font(size: 16.0)
             ],
             didTapInfo: { [weak self] in
-                guard let self = self else { return }
+                guard let self else { return }
                 self.infoSubject.send(())
             }
         )
diff --git a/Sources/SettingsFeature/Controllers/AccountDeleteController.swift b/Sources/SettingsFeature/Controllers/AccountDeleteController.swift
index 31674910b97735d82456859454c56c4325c9c18d..e46450c207851cf223dae475cd409e865063a526 100644
--- a/Sources/SettingsFeature/Controllers/AccountDeleteController.swift
+++ b/Sources/SettingsFeature/Controllers/AccountDeleteController.swift
@@ -2,112 +2,123 @@ import UIKit
 import Shared
 import Combine
 import Defaults
+import XXNavigation
 import DrawerFeature
 import ScrollViewController
 import DependencyInjection
 
 public final class AccountDeleteController: UIViewController {
-    @KeyObject(.username, defaultValue: "") var username: String
-
-    @Dependency var coordinator: SettingsCoordinating
-
-    private lazy var screenView = AccountDeleteView()
-    private lazy var scrollViewController = ScrollViewController()
-
-    private let viewModel = AccountDeleteViewModel()
-    private var cancellables = Set<AnyCancellable>()
-    private var drawerCancellables = Set<AnyCancellable>()
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationController?.navigationBar
-            .customize(backgroundColor: Asset.neutralWhite.color)
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupScrollView()
-        setupBindings()
-
-        screenView.update(username: username)
-
-        screenView.setInfoClosure { [weak self] in
-            self?.presentInfo(
-                title: Localized.Settings.Delete.Info.title,
-                subtitle: Localized.Settings.Delete.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
+  @Dependency var navigator: Navigator
+  @KeyObject(.username, defaultValue: "") var username: String
+
+  private lazy var screenView = AccountDeleteView()
+  private lazy var scrollViewController = ScrollViewController()
+
+  private let viewModel = AccountDeleteViewModel()
+  private var cancellables = Set<AnyCancellable>()
+  private var drawerCancellables = Set<AnyCancellable>()
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationController?.navigationBar
+      .customize(backgroundColor: Asset.neutralWhite.color)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupScrollView()
+    setupBindings()
+
+    screenView.update(username: username)
+
+    screenView.setInfoClosure { [weak self] in
+      guard let self else { return }
+      self.presentInfo(
+        title: Localized.Settings.Delete.Info.title,
+        subtitle: Localized.Settings.Delete.Info.subtitle
+      )
     }
-
-    private func setupBindings() {
-        screenView.cancelButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in dismiss(animated: true) }
-            .store(in: &cancellables)
-
-        screenView.inputField.textPublisher
-            .sink { [unowned self] in screenView.update(status: $0 == username ? .valid("") : .invalid("")) }
-            .store(in: &cancellables)
-
-        screenView.confirmButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in
-                DispatchQueue.global().async { [weak self] in
-                    self?.viewModel.didTapDelete()
-                }
-            }.store(in: &cancellables)
-
-        screenView.cancelButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in navigationController?.popViewController(animated: true) }
-            .store(in: &cancellables)
-    }
-
-    private func presentInfo(title: String, subtitle: String) {
-        let actionButton = CapsuleButton()
-        actionButton.set(
-            style: .seeThrough,
-            title: Localized.Settings.InfoDrawer.action
+  }
+
+  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() {
+    screenView
+      .cancelButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dismiss(animated: true)
+      }.store(in: &cancellables)
+
+    screenView
+      .inputField
+      .textPublisher
+      .sink { [unowned self] in
+        screenView.update(
+          status: $0 == username ?
+            .valid("") : .invalid("")
         )
-
-        let drawer = DrawerController([
-            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)
-    }
+      }.store(in: &cancellables)
+
+    screenView
+      .confirmButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        viewModel.didTapDelete()
+      }.store(in: &cancellables)
+
+    screenView
+      .cancelButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        navigationController?.popViewController(animated: true)
+      }.store(in: &cancellables)
+  }
+
+  private func presentInfo(title: String, subtitle: String) {
+    let actionButton = CapsuleButton()
+    actionButton.set(
+      style: .seeThrough,
+      title: Localized.Settings.InfoDrawer.action
+    )
+    actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
+      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()
+      ])
+    ]))
+  }
 }
diff --git a/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift b/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift
index 62dcd6294bc38a0746a9cccef50bc2194a1269cb..a0e33f9b9bb4980f4e63f95c68c47c1bfc64dd7d 100644
--- a/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift
+++ b/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift
@@ -1,90 +1,111 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import DependencyInjection
 
 public final class SettingsAdvancedController: UIViewController {
-    @Dependency private var coordinator: SettingsCoordinating
-
-    private lazy var screenView = SettingsAdvancedView()
-
-    private var cancellables = Set<AnyCancellable>()
-    private let viewModel = SettingsAdvancedViewModel()
-
-    public override func loadView() {
-        view = screenView
-    }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        navigationController?.navigationBar
-            .customize(backgroundColor: Asset.neutralWhite.color)
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupNavigationBar()
-        setupBindings()
-
-        viewModel.loadCachedSettings()
-    }
-
-    private func setupNavigationBar() {
-        let title = UILabel()
-        title.text = Localized.Settings.Advanced.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.downloadLogsButton
-            .publisher(for: .touchUpInside)
-            .sink { [weak viewModel] in viewModel?.didTapDownloadLogs() }
-            .store(in: &cancellables)
-
-        screenView.logRecordingSwitcher.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [weak viewModel] in viewModel?.didToggleRecordLogs() }
-            .store(in: &cancellables)
-
-        screenView.showUsernamesSwitcher.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [weak viewModel] in viewModel?.didToggleShowUsernames() }
-            .store(in: &cancellables)
-
-        screenView.crashReportingSwitcher.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [weak viewModel] in viewModel?.didToggleCrashReporting() }
-            .store(in: &cancellables)
-
-        screenView.reportingSwitcher.switcherView
-            .publisher(for: .valueChanged)
-            .compactMap { [weak screenView] _ in screenView?.reportingSwitcher.switcherView.isOn }
-            .sink { [weak viewModel] isOn in viewModel?.didSetReporting(enabled: isOn) }
-            .store(in: &cancellables)
-
-        viewModel.sharePublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in coordinator.toActivityController(with: [$0], from: self) }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .removeDuplicates()
-            .map(\.isReportingOptional)
-            .sink { [unowned self] in screenView.reportingSwitcher.isHidden = !$0 }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .removeDuplicates()
-            .sink { [unowned self] state in
-                screenView.logRecordingSwitcher.switcherView.setOn(state.isRecordingLogs, animated: true)
-                screenView.crashReportingSwitcher.switcherView.setOn(state.isCrashReporting, animated: true)
-                screenView.showUsernamesSwitcher.switcherView.setOn(state.isShowingUsernames, animated: true)
-                screenView.reportingSwitcher.switcherView.setOn(state.isReportingEnabled, animated: true)
-            }.store(in: &cancellables)
-    }
+  @Dependency var navigator: Navigator
+
+  private lazy var screenView = SettingsAdvancedView()
+
+  private var cancellables = Set<AnyCancellable>()
+  private let viewModel = SettingsAdvancedViewModel()
+
+  public override func loadView() {
+    view = screenView
+  }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    navigationController?.navigationBar
+      .customize(backgroundColor: Asset.neutralWhite.color)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupNavigationBar()
+    setupBindings()
+
+    viewModel.loadCachedSettings()
+  }
+
+  private func setupNavigationBar() {
+    let title = UILabel()
+    title.text = Localized.Settings.Advanced.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
+      .downloadLogsButton
+      .publisher(for: .touchUpInside)
+      .sink { [weak viewModel] in
+        viewModel?.didTapDownloadLogs()
+      }.store(in: &cancellables)
+
+    screenView
+      .logRecordingSwitcher
+      .switcherView
+      .publisher(for: .valueChanged)
+      .sink { [weak viewModel] in
+        viewModel?.didToggleRecordLogs()
+      }.store(in: &cancellables)
+
+    screenView
+      .showUsernamesSwitcher
+      .switcherView
+      .publisher(for: .valueChanged)
+      .sink { [weak viewModel] in
+        viewModel?.didToggleShowUsernames()
+      }.store(in: &cancellables)
+
+    screenView
+      .crashReportingSwitcher
+      .switcherView
+      .publisher(for: .valueChanged)
+      .sink { [weak viewModel] in
+        viewModel?.didToggleCrashReporting()
+      }.store(in: &cancellables)
+
+    screenView
+      .reportingSwitcher
+      .switcherView
+      .publisher(for: .valueChanged)
+      .compactMap { [weak screenView] _ in
+        screenView?.reportingSwitcher.switcherView.isOn
+      }.sink { [weak viewModel] isOn in
+        viewModel?.didSetReporting(enabled: isOn)
+      }.store(in: &cancellables)
+
+    viewModel
+      .sharePublisher
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(PresentActivitySheet(items: [$0]))
+      }.store(in: &cancellables)
+
+    viewModel
+      .state
+      .removeDuplicates()
+      .map(\.isReportingOptional)
+      .sink { [unowned self] in
+        screenView.reportingSwitcher.isHidden = !$0
+      }.store(in: &cancellables)
+
+    viewModel
+      .state
+      .removeDuplicates()
+      .sink { [unowned self] state in
+        screenView.logRecordingSwitcher.switcherView.setOn(state.isRecordingLogs, animated: true)
+        screenView.crashReportingSwitcher.switcherView.setOn(state.isCrashReporting, animated: true)
+        screenView.showUsernamesSwitcher.switcherView.setOn(state.isShowingUsernames, animated: true)
+        screenView.reportingSwitcher.switcherView.setOn(state.isReportingEnabled, animated: true)
+      }.store(in: &cancellables)
+  }
 }
diff --git a/Sources/SettingsFeature/Controllers/SettingsController.swift b/Sources/SettingsFeature/Controllers/SettingsController.swift
index 5cce068e5dfceae71439bc1c7f9e4a3047548275..08dce114d3a2c0aad67b07a6a2da30846209bc86 100644
--- a/Sources/SettingsFeature/Controllers/SettingsController.swift
+++ b/Sources/SettingsFeature/Controllers/SettingsController.swift
@@ -1,13 +1,14 @@
 import UIKit
 import Shared
 import Combine
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 import ScrollViewController
 
 public final class SettingsController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: SettingsCoordinating
 
   private lazy var scrollViewController = ScrollViewController()
   private lazy var screenView = SettingsView {
@@ -80,47 +81,66 @@ public final class SettingsController: UIViewController {
 
   private func setupScrollView() {
     scrollViewController.view.backgroundColor = Asset.neutralWhite.color
-
     addChild(scrollViewController)
     view.addSubview(scrollViewController.view)
-
-    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.view.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+    }
     scrollViewController.didMove(toParent: self)
     scrollViewController.contentView = screenView
   }
 
   private func setupBindings() {
-    screenView.inAppNotifications.switcherView
+    screenView
+      .inAppNotifications
+      .switcherView
       .publisher(for: .valueChanged)
-      .sink { [weak viewModel] in viewModel?.didToggleInAppNotifications() }
-      .store(in: &cancellables)
+      .sink { [weak viewModel] in
+        viewModel?.didToggleInAppNotifications()
+      }.store(in: &cancellables)
 
-    screenView.dummyTraffic.switcherView
+    screenView
+      .dummyTraffic
+      .switcherView
       .publisher(for: .valueChanged)
-      .sink { [weak viewModel] in viewModel?.didToggleDummyTraffic() }
-      .store(in: &cancellables)
+      .sink { [weak viewModel] in
+        viewModel?.didToggleDummyTraffic()
+      }.store(in: &cancellables)
 
-    screenView.remoteNotifications.switcherView
+    screenView
+      .remoteNotifications
+      .switcherView
       .publisher(for: .valueChanged)
-      .sink { [weak viewModel] in viewModel?.didTogglePushNotifications() }
-      .store(in: &cancellables)
+      .sink { [weak viewModel] in
+        viewModel?.didTogglePushNotifications()
+      }.store(in: &cancellables)
 
-    screenView.hideActiveApp.switcherView
+    screenView
+      .hideActiveApp
+      .switcherView
       .publisher(for: .valueChanged)
-      .sink { [weak viewModel] in viewModel?.didToggleHideActiveApps() }
-      .store(in: &cancellables)
+      .sink { [weak viewModel] in
+        viewModel?.didToggleHideActiveApps()
+      }.store(in: &cancellables)
 
-    screenView.icognitoKeyboard.switcherView
+    screenView
+      .icognitoKeyboard
+      .switcherView
       .publisher(for: .valueChanged)
-      .sink { [weak viewModel] in viewModel?.didToggleIcognitoKeyboard() }
-      .store(in: &cancellables)
+      .sink { [weak viewModel] in
+        viewModel?.didToggleIcognitoKeyboard()
+      }.store(in: &cancellables)
 
-    screenView.biometrics.switcherView
+    screenView
+      .biometrics
+      .switcherView
       .publisher(for: .valueChanged)
-      .sink { [weak viewModel] in viewModel?.didToggleBiometrics() }
-      .store(in: &cancellables)
+      .sink { [weak viewModel] in
+        viewModel?.didToggleBiometrics()
+      }.store(in: &cancellables)
 
-    screenView.privacyPolicyButton
+    screenView
+      .privacyPolicyButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
@@ -133,7 +153,8 @@ public final class SettingsController: UIViewController {
           }
       }.store(in: &cancellables)
 
-    screenView.disclosuresButton
+    screenView
+      .disclosuresButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
@@ -146,32 +167,41 @@ public final class SettingsController: UIViewController {
           }
       }.store(in: &cancellables)
 
-    screenView.deleteButton
+    screenView
+      .deleteButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in coordinator.toDelete(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentSettingsAccountDelete())
+      }.store(in: &cancellables)
 
-    screenView.accountBackupButton
+    screenView
+      .accountBackupButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in coordinator.toBackup(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentSettingsBackup())
+      }.store(in: &cancellables)
 
-    screenView.advancedButton
+    screenView
+      .advancedButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in coordinator.toAdvanced(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentSettingsAdvanced())
+      }.store(in: &cancellables)
 
-    viewModel.state
+    viewModel
+      .state
       .map(\.isBiometricsPossible)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
-      .sink { [weak screenView] in screenView?.biometrics.switcherView.isEnabled = $0 }
-      .store(in: &cancellables)
+      .sink { [weak screenView] in
+        screenView?.biometrics.switcherView.isEnabled = $0
+      }.store(in: &cancellables)
 
-    viewModel.state
+    viewModel
+      .state
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] state in
@@ -198,7 +228,27 @@ public final class SettingsController: UIViewController {
     cancelButton.setStyle(.seeThrough)
     cancelButton.setTitle(Localized.ChatList.Dashboard.cancel, for: .normal)
 
-    let drawer = DrawerController([
+    actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+          action()
+        }
+      }.store(in: &drawerCancellables)
+
+    cancelButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
+
+    navigator.perform(PresentDrawer(items: [
       DrawerImage(
         image: Asset.drawerNegative.image
       ),
@@ -218,32 +268,11 @@ public final class SettingsController: UIViewController {
         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)
+    ]))
   }
 
   @objc private func didTapMenu() {
-    coordinator.toSideMenu(from: self)
+    navigator.perform(PresentMenu(currentItem: .settings))
   }
 }
 
@@ -258,8 +287,17 @@ extension SettingsController {
       style: .seeThrough,
       title: Localized.Settings.InfoDrawer.action
     )
+    actionButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        navigator.perform(DismissModal(from: self)) { [weak self] in
+          guard let self else { return }
+          self.drawerCancellables.removeAll()
+        }
+      }.store(in: &drawerCancellables)
 
-    let drawer = DrawerController([
+    navigator.perform(PresentDrawer(items: [
       DrawerText(
         font: Fonts.Mulish.bold.font(size: 26.0),
         text: title,
@@ -276,17 +314,6 @@ extension SettingsController {
         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/SettingsFeature/Coordinator/SettingsCoordinator.swift b/Sources/SettingsFeature/Coordinator/SettingsCoordinator.swift
deleted file mode 100644
index 73de549152915e86ff93f911c5e28626dff74d00..0000000000000000000000000000000000000000
--- a/Sources/SettingsFeature/Coordinator/SettingsCoordinator.swift
+++ /dev/null
@@ -1,70 +0,0 @@
-import UIKit
-import Shared
-import MenuFeature
-import Presentation
-
-public protocol SettingsCoordinating {
-    func toBackup(from: UIViewController)
-    func toDelete(from: UIViewController)
-    func toAdvanced(from: UIViewController)
-    func toSideMenu(from: UIViewController)
-    func toDrawer(_: UIViewController, from: UIViewController)
-    func toActivityController(with: [Any], from: UIViewController)
-}
-
-public struct SettingsCoordinator: SettingsCoordinating {
-    var pushPresenter: Presenting = PushPresenter()
-    var modalPresenter: Presenting = ModalPresenter()
-    var sidePresenter: Presenting = SideMenuPresenter()
-    var bottomPresenter: Presenting = BottomPresenter()
-
-    var backupFactory: () -> UIViewController
-    var advancedFactory: () -> UIViewController
-    var accountDeleteFactory: () -> UIViewController
-    var sideMenuFactory: (MenuItem, UIViewController) -> UIViewController
-    var activityControllerFactory: ([Any]) -> UIViewController
-    = { UIActivityViewController(activityItems: $0, applicationActivities: nil) }
-
-    public init(
-        backupFactory: @escaping () -> UIViewController,
-        advancedFactory: @escaping () -> UIViewController,
-        accountDeleteFactory: @escaping () -> UIViewController,
-        sideMenuFactory: @escaping (MenuItem, UIViewController) -> UIViewController
-    ) {
-        self.backupFactory = backupFactory
-        self.advancedFactory = advancedFactory
-        self.sideMenuFactory = sideMenuFactory
-        self.accountDeleteFactory = accountDeleteFactory
-    }
-}
-
-public extension SettingsCoordinator {
-    func toAdvanced(from parent: UIViewController) {
-        let screen = advancedFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toDelete(from parent: UIViewController) {
-        let screen = accountDeleteFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toBackup(from parent: UIViewController) {
-        let screen = backupFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toDrawer(_ drawer: UIViewController, from parent: UIViewController) {
-        bottomPresenter.present(drawer, from: parent)
-    }
-
-    func toActivityController(with items: [Any], from parent: UIViewController) {
-        let screen = activityControllerFactory(items)
-        modalPresenter.present(screen, from: parent)
-    }
-
-    func toSideMenu(from parent: UIViewController) {
-        let screen = sideMenuFactory(.settings, parent)
-        sidePresenter.present(screen, from: parent)
-    }
-}
diff --git a/Sources/SettingsFeature/ViewModels/AccountDeleteViewModel.swift b/Sources/SettingsFeature/ViewModels/AccountDeleteViewModel.swift
index bb1b4cb37d1a0f536ab355a2d67efd809e6bab9b..55f48f6c2d8f2aeb612f2a14a0a82fff49cdc5c9 100644
--- a/Sources/SettingsFeature/ViewModels/AccountDeleteViewModel.swift
+++ b/Sources/SettingsFeature/ViewModels/AccountDeleteViewModel.swift
@@ -1,5 +1,5 @@
-import Shared
 import Retry
+import Shared
 import Combine
 import Defaults
 import Keychain
@@ -51,7 +51,7 @@ final class AccountDeleteViewModel {
       ))
     } catch {
       DispatchQueue.main.async { [weak self] in
-        guard let self = self else { return }
+        guard let self else { return }
         self.hudController.show(.init(error: error))
       }
     }
diff --git a/Sources/SettingsFeature/ViewModels/SettingsAdvancedViewModel.swift b/Sources/SettingsFeature/ViewModels/SettingsAdvancedViewModel.swift
index 3ec9be365abd621e7c1d9d421aff530d0560acc7..42814774096428e76ca0d38fdff1cec951aa757e 100644
--- a/Sources/SettingsFeature/ViewModels/SettingsAdvancedViewModel.swift
+++ b/Sources/SettingsFeature/ViewModels/SettingsAdvancedViewModel.swift
@@ -7,87 +7,87 @@ import ReportingFeature
 import DependencyInjection
 
 struct AdvancedViewState: Equatable {
-    var isRecordingLogs = false
-    var isCrashReporting = false
-    var isShowingUsernames = false
-    var isReportingEnabled = false
-    var isReportingOptional = false
+  var isRecordingLogs = false
+  var isCrashReporting = false
+  var isShowingUsernames = false
+  var isReportingEnabled = false
+  var isReportingOptional = false
 }
 
 final class SettingsAdvancedViewModel {
-    @KeyObject(.recordingLogs, defaultValue: true) var isRecordingLogs: Bool
-    @KeyObject(.crashReporting, defaultValue: true) var isCrashReporting: Bool
+  @KeyObject(.recordingLogs, defaultValue: true) var isRecordingLogs: Bool
+  @KeyObject(.crashReporting, defaultValue: true) var isCrashReporting: Bool
 
-    private var cancellables = Set<AnyCancellable>()
-    private let isShowingUsernamesKey = "isShowingUsernames"
+  private var cancellables = Set<AnyCancellable>()
+  private let isShowingUsernamesKey = "isShowingUsernames"
 
-    @Dependency private var logger: XXLogger
-    @Dependency private var crashReporter: CrashReporter
-    @Dependency private var reportingStatus: ReportingStatus
+  @Dependency private var logger: XXLogger
+  @Dependency private var crashReporter: CrashReporter
+  @Dependency private var reportingStatus: ReportingStatus
 
-    var sharePublisher: AnyPublisher<URL, Never> { shareRelay.eraseToAnyPublisher() }
-    private let shareRelay = PassthroughSubject<URL, Never>()
+  var sharePublisher: AnyPublisher<URL, Never> { shareRelay.eraseToAnyPublisher() }
+  private let shareRelay = PassthroughSubject<URL, Never>()
 
-    var state: AnyPublisher<AdvancedViewState, Never> { stateRelay.eraseToAnyPublisher() }
-    private let stateRelay = CurrentValueSubject<AdvancedViewState, Never>(.init())
+  var state: AnyPublisher<AdvancedViewState, Never> { stateRelay.eraseToAnyPublisher() }
+  private let stateRelay = CurrentValueSubject<AdvancedViewState, Never>(.init())
 
-    func loadCachedSettings() {
-        stateRelay.value.isRecordingLogs = isRecordingLogs
-        stateRelay.value.isCrashReporting = isCrashReporting
-        stateRelay.value.isReportingOptional = reportingStatus.isOptional()
+  func loadCachedSettings() {
+    stateRelay.value.isRecordingLogs = isRecordingLogs
+    stateRelay.value.isCrashReporting = isCrashReporting
+    stateRelay.value.isReportingOptional = reportingStatus.isOptional()
 
-        reportingStatus
-            .isEnabledPublisher()
-            .sink { [weak stateRelay] in stateRelay?.value.isReportingEnabled = $0 }
-            .store(in: &cancellables)
+    reportingStatus
+      .isEnabledPublisher()
+      .sink { [weak stateRelay] in stateRelay?.value.isReportingEnabled = $0 }
+      .store(in: &cancellables)
 
-        guard let defaults = UserDefaults(suiteName: "group.elixxir.messenger") else {
-            print("^^^ Couldn't access user defaults in the app group container \(#file):\(#line)")
-            return
-        }
-
-        guard let isShowingUsernames = defaults.value(forKey: isShowingUsernamesKey) as? Bool else {
-            defaults.set(false, forKey: isShowingUsernamesKey)
-            return
-        }
+    guard let defaults = UserDefaults(suiteName: "group.elixxir.messenger") else {
+      print("^^^ Couldn't access user defaults in the app group container \(#file):\(#line)")
+      return
+    }
 
-        stateRelay.value.isShowingUsernames = isShowingUsernames
+    guard let isShowingUsernames = defaults.value(forKey: isShowingUsernamesKey) as? Bool else {
+      defaults.set(false, forKey: isShowingUsernamesKey)
+      return
     }
 
-    func didToggleShowUsernames() {
-        stateRelay.value.isShowingUsernames.toggle()
+    stateRelay.value.isShowingUsernames = isShowingUsernames
+  }
 
-        guard let defaults = UserDefaults(suiteName: "group.elixxir.messenger") else {
-            print("^^^ Couldn't access user defaults in the app group container \(#file):\(#line)")
-            return
-        }
+  func didToggleShowUsernames() {
+    stateRelay.value.isShowingUsernames.toggle()
 
-        defaults.set(stateRelay.value.isShowingUsernames, forKey: isShowingUsernamesKey)
+    guard let defaults = UserDefaults(suiteName: "group.elixxir.messenger") else {
+      print("^^^ Couldn't access user defaults in the app group container \(#file):\(#line)")
+      return
     }
 
-    func didToggleRecordLogs() {
-        if isRecordingLogs == true {
-            XXLogger.stop()
-        } else {
-            XXLogger.start()
-        }
+    defaults.set(stateRelay.value.isShowingUsernames, forKey: isShowingUsernamesKey)
+  }
 
-        isRecordingLogs.toggle()
-        stateRelay.value.isRecordingLogs.toggle()
+  func didToggleRecordLogs() {
+    if isRecordingLogs == true {
+      XXLogger.stop()
+    } else {
+      XXLogger.start()
     }
 
-    func didTapDownloadLogs() {
-        let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
-        shareRelay.send(url.appendingPathComponent("swiftybeaver.log"))
-    }
+    isRecordingLogs.toggle()
+    stateRelay.value.isRecordingLogs.toggle()
+  }
 
-    func didToggleCrashReporting() {
-        isCrashReporting.toggle()
-        stateRelay.value.isCrashReporting.toggle()
-        crashReporter.setEnabled(isCrashReporting)
-    }
+  func didTapDownloadLogs() {
+    let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
+    shareRelay.send(url.appendingPathComponent("swiftybeaver.log"))
+  }
 
-    func didSetReporting(enabled: Bool) {
-        reportingStatus.enable(enabled)
-    }
+  func didToggleCrashReporting() {
+    isCrashReporting.toggle()
+    stateRelay.value.isCrashReporting.toggle()
+    crashReporter.setEnabled(isCrashReporting)
+  }
+
+  func didSetReporting(enabled: Bool) {
+    reportingStatus.enable(enabled)
+  }
 }
diff --git a/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift b/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift
index 3bea57bea7fd39113ad41e087d41883b639a427f..4337264c1fcd97117547e4b8f61d971446e195cc 100644
--- a/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift
+++ b/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift
@@ -89,7 +89,7 @@ final class SettingsViewModel {
     }
     
     permissions.requestBiometrics { [weak self] result in
-      guard let self = self else { return }
+      guard let self else { return }
       
       switch result {
       case .success(let granted):
@@ -112,7 +112,7 @@ final class SettingsViewModel {
     
     if enable == true {
       pushHandler.requestAuthorization { [weak self] result in
-        guard let self = self else { return }
+        guard let self else { return }
         
         switch result {
         case .success(let granted):
@@ -129,7 +129,7 @@ final class SettingsViewModel {
       }
     } else {
       backgroundScheduler.schedule { [weak self] in
-        guard let self = self else { return }
+        guard let self else { return }
         
         do {
           try UnregisterForNotifications.live(
@@ -140,6 +140,7 @@ final class SettingsViewModel {
         } catch {
           let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
           self.hudController.show(.init(content: xxError))
+
         }
         
         self.pushNotifications = false
diff --git a/Sources/SettingsFeature/Views/AccountDeleteView.swift b/Sources/SettingsFeature/Views/AccountDeleteView.swift
index e4aef7f5642929216a84e9e7b889ec0d3fa095ff..791bec294559a098af1594448b41e0b30a7e4ad3 100644
--- a/Sources/SettingsFeature/Views/AccountDeleteView.swift
+++ b/Sources/SettingsFeature/Views/AccountDeleteView.swift
@@ -3,118 +3,114 @@ import Shared
 import InputField
 
 final class AccountDeleteView: UIView {
-    let titleLabel = UILabel()
-    let subtitleView = TextWithInfoView()
-    let iconImageView = UIImageView()
-    let inputField = InputField()
-
-    let stackView = UIStackView()
-    let confirmButton = CapsuleButton()
-    let cancelButton = CapsuleButton()
-
-    var didTapInfo: (() -> Void)?
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-        iconImageView.image = Asset.settingsDeleteLarge.image
-
-        iconImageView.contentMode = .center
-
-        inputField.setup(
-            style: .regular,
-            title: Localized.Settings.Delete.input,
-            placeholder: "",
-            leftView: .image(Asset.personGray.image),
-            subtitleColor: Asset.neutralDisabled.color,
-            allowsEmptySpace: false,
-            autocapitalization: .none
-        )
-
-        titleLabel.text = Localized.Settings.Delete.title
-        titleLabel.textAlignment = .center
-        titleLabel.textColor = Asset.neutralActive.color
-        titleLabel.font = Fonts.Mulish.bold.font(size: 32.0)
-
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .center
-        paragraph.lineHeightMultiple = 1.1
-
-        subtitleView.setup(
-            text: Localized.Settings.Delete.subtitle,
-            attributes: [
-                .foregroundColor: Asset.neutralActive.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0),
-                .paragraphStyle: paragraph
-            ],
-            didTapInfo: { self.didTapInfo?() }
-        )
-
-        confirmButton.setStyle(.red)
-        confirmButton.isEnabled = false
-        confirmButton.setTitle(Localized.Settings.Delete.delete, for: .normal)
-        cancelButton.setStyle(.simplestColoredRed)
-        cancelButton.setTitle(Localized.Settings.Delete.cancel, for: .normal)
-
-        stackView.spacing = 12
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(confirmButton)
-        stackView.addArrangedSubview(cancelButton)
-
-        addSubview(iconImageView)
-        addSubview(inputField)
-        addSubview(titleLabel)
-        addSubview(subtitleView)
-        addSubview(stackView)
-
-        iconImageView.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(30)
-            make.centerX.equalToSuperview()
-        }
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalTo(iconImageView.snp.bottom).offset(34)
-            make.centerX.equalToSuperview()
-        }
-
-        subtitleView.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(20)
-            make.left.equalToSuperview().offset(50)
-            make.right.equalToSuperview().offset(-50)
-        }
-
-        inputField.snp.makeConstraints { make in
-            make.top.equalTo(subtitleView.snp.bottom).offset(50)
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-        }
-
-        stackView.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(20)
-            make.left.equalToSuperview().offset(50)
-            make.right.equalToSuperview().offset(-50)
-            make.bottom.equalToSuperview().offset(-44)
-        }
+  let titleLabel = UILabel()
+  let subtitleView = TextWithInfoView()
+  let iconImageView = UIImageView()
+  let inputField = InputField()
+
+  let stackView = UIStackView()
+  let confirmButton = CapsuleButton()
+  let cancelButton = CapsuleButton()
+
+  var didTapInfo: (() -> Void)?
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+    iconImageView.image = Asset.settingsDeleteLarge.image
+
+    iconImageView.contentMode = .center
+
+    inputField.setup(
+      style: .regular,
+      title: Localized.Settings.Delete.input,
+      placeholder: "",
+      leftView: .image(Asset.personGray.image),
+      subtitleColor: Asset.neutralDisabled.color,
+      allowsEmptySpace: false,
+      autocapitalization: .none
+    )
+
+    titleLabel.text = Localized.Settings.Delete.title
+    titleLabel.textAlignment = .center
+    titleLabel.textColor = Asset.neutralActive.color
+    titleLabel.font = Fonts.Mulish.bold.font(size: 32.0)
+
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .center
+    paragraph.lineHeightMultiple = 1.1
+
+    subtitleView.setup(
+      text: Localized.Settings.Delete.subtitle,
+      attributes: [
+        .foregroundColor: Asset.neutralActive.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0),
+        .paragraphStyle: paragraph
+      ],
+      didTapInfo: { self.didTapInfo?() }
+    )
+
+    confirmButton.setStyle(.red)
+    confirmButton.isEnabled = false
+    confirmButton.setTitle(Localized.Settings.Delete.delete, for: .normal)
+    cancelButton.setStyle(.simplestColoredRed)
+    cancelButton.setTitle(Localized.Settings.Delete.cancel, for: .normal)
+
+    stackView.spacing = 12
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(confirmButton)
+    stackView.addArrangedSubview(cancelButton)
+
+    addSubview(iconImageView)
+    addSubview(inputField)
+    addSubview(titleLabel)
+    addSubview(subtitleView)
+    addSubview(stackView)
+
+    iconImageView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(30)
+      $0.centerX.equalToSuperview()
     }
+    titleLabel.snp.makeConstraints {
+      $0.top.equalTo(iconImageView.snp.bottom).offset(34)
+      $0.centerX.equalToSuperview()
+    }
+    subtitleView.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(20)
+      $0.left.equalToSuperview().offset(50)
+      $0.right.equalToSuperview().offset(-50)
+    }
+    inputField.snp.makeConstraints {
+      $0.top.equalTo(subtitleView.snp.bottom).offset(50)
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
+    }
+    stackView.snp.makeConstraints {
+      $0.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(20)
+      $0.left.equalToSuperview().offset(50)
+      $0.right.equalToSuperview().offset(-50)
+      $0.bottom.equalToSuperview().offset(-44)
+    }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 
-    func setInfoClosure(_ closure: @escaping () -> Void) {
-        didTapInfo = closure
-    }
+  func setInfoClosure(_ closure: @escaping () -> Void) {
+    didTapInfo = closure
+  }
 
-    func update(username: String) {
-        inputField.update(placeholder: username)
-    }
+  func update(username: String) {
+    inputField.update(placeholder: username)
+  }
 
-    func update(status: InputField.ValidationStatus) {
-        inputField.update(status: status)
+  func update(status: InputField.ValidationStatus) {
+    inputField.update(status: status)
 
-        switch status {
-        case .valid:
-            confirmButton.isEnabled = true
-        case .invalid, .unknown:
-            confirmButton.isEnabled = false
-        }
+    switch status {
+    case .valid:
+      confirmButton.isEnabled = true
+    case .invalid, .unknown:
+      confirmButton.isEnabled = false
     }
+  }
 }
diff --git a/Sources/SettingsFeature/Views/SettingsAdvancedView.swift b/Sources/SettingsFeature/Views/SettingsAdvancedView.swift
index 0e5e5d89159fbb554f78dd781f5a9d3d4cdfe9da..750a175c208d29335c7c3354724de1b920c82d64 100644
--- a/Sources/SettingsFeature/Views/SettingsAdvancedView.swift
+++ b/Sources/SettingsFeature/Views/SettingsAdvancedView.swift
@@ -2,63 +2,60 @@ import UIKit
 import Shared
 
 final class SettingsAdvancedView: UIView {
-    let stackView = UIStackView()
-    let downloadLogsButton = UIButton()
-    let logRecordingSwitcher = SettingsSwitcher()
-    let crashReportingSwitcher = SettingsSwitcher()
-    let showUsernamesSwitcher = SettingsSwitcher()
-    let reportingSwitcher = SettingsSwitcher()
-
-    init() {
-        super.init(frame: .zero)
-
-        backgroundColor = Asset.neutralWhite.color
-        downloadLogsButton.setImage(Asset.settingsDownload.image, for: .normal)
-
-        showUsernamesSwitcher.set(
-            title: Localized.Settings.Advanced.ShowUsername.title,
-            text: Localized.Settings.Advanced.ShowUsername.description,
-            icon: Asset.settingsHide.image
-        )
-
-        logRecordingSwitcher.set(
-            title: Localized.Settings.Advanced.Logs.title,
-            text: Localized.Settings.Advanced.Logs.description,
-            icon: Asset.settingsLogs.image,
-            extraAction: downloadLogsButton
-        )
-
-        crashReportingSwitcher.set(
-            title: Localized.Settings.Advanced.Crashes.title,
-            text: Localized.Settings.Advanced.Crashes.description,
-            icon: Asset.settingsCrash.image
-        )
-
-        reportingSwitcher.set(
-            title: Localized.Settings.Advanced.Reporting.title,
-            text: Localized.Settings.Advanced.Reporting.description,
-            icon: Asset.settingsCrash.image
-        )
-
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(logRecordingSwitcher)
-        stackView.addArrangedSubview(crashReportingSwitcher)
-        stackView.addArrangedSubview(showUsernamesSwitcher)
-        stackView.addArrangedSubview(reportingSwitcher)
-
-        stackView.setCustomSpacing(20, after: logRecordingSwitcher)
-        stackView.setCustomSpacing(10, after: crashReportingSwitcher)
-        stackView.setCustomSpacing(10, after: showUsernamesSwitcher)
-        stackView.setCustomSpacing(10, after: reportingSwitcher)
-
-        addSubview(stackView)
-
-        stackView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(24)
-            $0.left.equalToSuperview().offset(16)
-            $0.right.equalToSuperview().offset(-16)
-        }
+  let stackView = UIStackView()
+  let downloadLogsButton = UIButton()
+  let logRecordingSwitcher = SettingsSwitcher()
+  let crashReportingSwitcher = SettingsSwitcher()
+  let showUsernamesSwitcher = SettingsSwitcher()
+  let reportingSwitcher = SettingsSwitcher()
+
+  init() {
+    super.init(frame: .zero)
+
+    backgroundColor = Asset.neutralWhite.color
+    downloadLogsButton.setImage(Asset.settingsDownload.image, for: .normal)
+
+    showUsernamesSwitcher.set(
+      title: Localized.Settings.Advanced.ShowUsername.title,
+      text: Localized.Settings.Advanced.ShowUsername.description,
+      icon: Asset.settingsHide.image
+    )
+    logRecordingSwitcher.set(
+      title: Localized.Settings.Advanced.Logs.title,
+      text: Localized.Settings.Advanced.Logs.description,
+      icon: Asset.settingsLogs.image,
+      extraAction: downloadLogsButton
+    )
+    crashReportingSwitcher.set(
+      title: Localized.Settings.Advanced.Crashes.title,
+      text: Localized.Settings.Advanced.Crashes.description,
+      icon: Asset.settingsCrash.image
+    )
+    reportingSwitcher.set(
+      title: Localized.Settings.Advanced.Reporting.title,
+      text: Localized.Settings.Advanced.Reporting.description,
+      icon: Asset.settingsCrash.image
+    )
+
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(logRecordingSwitcher)
+    stackView.addArrangedSubview(crashReportingSwitcher)
+    stackView.addArrangedSubview(showUsernamesSwitcher)
+    stackView.addArrangedSubview(reportingSwitcher)
+
+    stackView.setCustomSpacing(20, after: logRecordingSwitcher)
+    stackView.setCustomSpacing(10, after: crashReportingSwitcher)
+    stackView.setCustomSpacing(10, after: showUsernamesSwitcher)
+    stackView.setCustomSpacing(10, after: reportingSwitcher)
+
+    addSubview(stackView)
+
+    stackView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(24)
+      $0.left.equalToSuperview().offset(16)
+      $0.right.equalToSuperview().offset(-16)
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/SettingsFeature/Views/SettingsSwitcher.swift b/Sources/SettingsFeature/Views/SettingsSwitcher.swift
index 8b928746226f12ba5ddc5873de50d66989284f8d..5a59b17fa3d7274215d498cd8d9ea050fc4201ee 100644
--- a/Sources/SettingsFeature/Views/SettingsSwitcher.swift
+++ b/Sources/SettingsFeature/Views/SettingsSwitcher.swift
@@ -2,218 +2,216 @@ import UIKit
 import Shared
 
 final class SettingsSwitcher: UIView {
-    let titleLabel = UILabel()
-    let textLabel = UILabel()
-    let iconImageView = UIImageView()
-    let separatorView = UIView()
-    let switcherView = UISwitch()
-    let stackView = UIStackView()
-    let verticalStackView = UIStackView()
-
-    init() {
-        super.init(frame: .zero)
-
-        textLabel.textColor = Asset.neutralWeak.color
-        titleLabel.textColor = Asset.neutralActive.color
-        switcherView.onTintColor = Asset.brandPrimary.color
-        separatorView.backgroundColor = Asset.neutralLine.color
-
-        iconImageView.contentMode = .center
-        iconImageView.setContentHuggingPriority(.required, for: .horizontal)
-
-        textLabel.numberOfLines = 0
-        textLabel.font = Fonts.Mulish.regular.font(size: 12.0)
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
-
-        addSubview(stackView)
-        addSubview(separatorView)
-
-        verticalStackView.spacing = 3
-        verticalStackView.axis = .vertical
-        verticalStackView.addArrangedSubview(titleLabel)
-        verticalStackView.addArrangedSubview(textLabel)
-
-        let icon = iconImageView.pinning(at: .top(0))
-
-        stackView.spacing = 8
-        stackView.addArrangedSubview(icon)
-        stackView.addArrangedSubview(verticalStackView)
-        stackView.addArrangedSubview(switcherView.pinning(at: .top(0)))
-
-        stackView.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(16)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.equalToSuperview().offset(-20)
-        }
-
-        separatorView.snp.makeConstraints { make in
-            make.height.equalTo(1)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.equalToSuperview()
-        }
+  let titleLabel = UILabel()
+  let textLabel = UILabel()
+  let iconImageView = UIImageView()
+  let separatorView = UIView()
+  let switcherView = UISwitch()
+  let stackView = UIStackView()
+  let verticalStackView = UIStackView()
+
+  init() {
+    super.init(frame: .zero)
+
+    textLabel.textColor = Asset.neutralWeak.color
+    titleLabel.textColor = Asset.neutralActive.color
+    switcherView.onTintColor = Asset.brandPrimary.color
+    separatorView.backgroundColor = Asset.neutralLine.color
+
+    iconImageView.contentMode = .center
+    iconImageView.setContentHuggingPriority(.required, for: .horizontal)
+
+    textLabel.numberOfLines = 0
+    textLabel.font = Fonts.Mulish.regular.font(size: 12.0)
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
+
+    addSubview(stackView)
+    addSubview(separatorView)
+
+    verticalStackView.spacing = 3
+    verticalStackView.axis = .vertical
+    verticalStackView.addArrangedSubview(titleLabel)
+    verticalStackView.addArrangedSubview(textLabel)
+
+    let icon = iconImageView.pinning(at: .top(0))
+
+    stackView.spacing = 8
+    stackView.addArrangedSubview(icon)
+    stackView.addArrangedSubview(verticalStackView)
+    stackView.addArrangedSubview(switcherView.pinning(at: .top(0)))
+
+    stackView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(16)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview().offset(-20)
+    }
+    separatorView.snp.makeConstraints {
+      $0.height.equalTo(1)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  func set(
+    title: String,
+    text: String? = nil,
+    icon: UIImage? = nil,
+    separator: Bool = true,
+    extraAction: UIButton? = nil
+  ) {
+    titleLabel.text = title
+
+    if let content = text {
+      let paragraphStyle = NSMutableParagraphStyle()
+      paragraphStyle.lineHeightMultiple = 1.5
+
+      textLabel.attributedText = NSAttributedString(
+        string: content, attributes: [.paragraphStyle: paragraphStyle]
+      )
+    } else {
+      verticalStackView.removeArrangedSubview(textLabel)
+    }
+
+    if let icon = icon {
+      iconImageView.image = icon
+    } else {
+      stackView.removeArrangedSubview(iconImageView)
+    }
+
+    if let button = extraAction {
+      stackView.insertArrangedSubview(button.pinning(at: .top(0)), at: 2)
     }
 
-    required init?(coder: NSCoder) { nil }
-
-    func set(
-        title: String,
-        text: String? = nil,
-        icon: UIImage? = nil,
-        separator: Bool = true,
-        extraAction: UIButton? = nil
-    ) {
-        titleLabel.text = title
-
-        if let content = text {
-            let paragraphStyle = NSMutableParagraphStyle()
-            paragraphStyle.lineHeightMultiple = 1.5
-
-            textLabel.attributedText = NSAttributedString(
-                string: content, attributes: [.paragraphStyle: paragraphStyle]
-            )
-        } else {
-            verticalStackView.removeArrangedSubview(textLabel)
-        }
-
-        if let icon = icon {
-            iconImageView.image = icon
-        } else {
-            stackView.removeArrangedSubview(iconImageView)
-        }
-
-        if let button = extraAction {
-            stackView.insertArrangedSubview(button.pinning(at: .top(0)), at: 2)
-        }
-
-        guard separator == true else {
-            separatorView.removeFromSuperview()
-            return
-        }
+    guard separator == true else {
+      separatorView.removeFromSuperview()
+      return
     }
+  }
 }
 
 final class SettingsInfoSwitcher: UIView {
-    let titleView = TextWithInfoView()
-    let textLabel = UILabel()
-    let iconImageView = UIImageView()
-    let separatorView = UIView()
-    let switcherView = UISwitch()
-    let stackView = UIStackView()
-    let verticalStackView = UIStackView()
-
-    var didTapInfo: (() -> Void)?
-
-    init() {
-        super.init(frame: .zero)
-
-        textLabel.textColor = Asset.neutralWeak.color
-        switcherView.onTintColor = Asset.brandPrimary.color
-        separatorView.backgroundColor = Asset.neutralLine.color
-
-        iconImageView.contentMode = .center
-        iconImageView.setContentHuggingPriority(.required, for: .horizontal)
-
-        textLabel.numberOfLines = 0
-        textLabel.font = Fonts.Mulish.regular.font(size: 12.0)
-        textLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
-
-        addSubview(stackView)
-        addSubview(separatorView)
-
-        let titleContainer = UIView()
-        titleContainer.addSubview(titleView)
-        titleView.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(-10)
-            make.left.equalToSuperview().offset(-4)
-            make.right.equalToSuperview()
-            make.bottom.equalToSuperview().offset(10)
-        }
-
-        verticalStackView.spacing = 3
-        verticalStackView.axis = .vertical
-        verticalStackView.addArrangedSubview(titleContainer.pinning(at: .left(0)))
-        verticalStackView.addArrangedSubview(textLabel)
-
-        let icon = iconImageView.pinning(at: .top(0))
-
-        let switcherContainer = UIView()
-        switcherContainer.addSubview(switcherView)
-        switcherView.setContentCompressionResistancePriority(.required, for: .horizontal)
-        switcherContainer.setContentCompressionResistancePriority(.required, for: .horizontal)
-
-        switcherView.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.lessThanOrEqualToSuperview()
-        }
-
-        stackView.spacing = 8
-        stackView.addArrangedSubview(icon)
-        stackView.addArrangedSubview(verticalStackView)
-        stackView.addArrangedSubview(switcherContainer)
-
-        stackView.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(16)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.equalToSuperview().offset(-20)
-        }
-
-        separatorView.snp.makeConstraints { make in
-            make.height.equalTo(1)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.equalToSuperview()
-        }
+  let titleView = TextWithInfoView()
+  let textLabel = UILabel()
+  let iconImageView = UIImageView()
+  let separatorView = UIView()
+  let switcherView = UISwitch()
+  let stackView = UIStackView()
+  let verticalStackView = UIStackView()
+
+  var didTapInfo: (() -> Void)?
+
+  init() {
+    super.init(frame: .zero)
+
+    textLabel.textColor = Asset.neutralWeak.color
+    switcherView.onTintColor = Asset.brandPrimary.color
+    separatorView.backgroundColor = Asset.neutralLine.color
+
+    iconImageView.contentMode = .center
+    iconImageView.setContentHuggingPriority(.required, for: .horizontal)
+
+    textLabel.numberOfLines = 0
+    textLabel.font = Fonts.Mulish.regular.font(size: 12.0)
+    textLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
+
+    addSubview(stackView)
+    addSubview(separatorView)
+
+    let titleContainer = UIView()
+    titleContainer.addSubview(titleView)
+    titleView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(-10)
+      $0.left.equalToSuperview().offset(-4)
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview().offset(10)
+    }
+
+    verticalStackView.spacing = 3
+    verticalStackView.axis = .vertical
+    verticalStackView.addArrangedSubview(titleContainer.pinning(at: .left(0)))
+    verticalStackView.addArrangedSubview(textLabel)
+
+    let icon = iconImageView.pinning(at: .top(0))
+
+    let switcherContainer = UIView()
+    switcherContainer.addSubview(switcherView)
+    switcherView.setContentCompressionResistancePriority(.required, for: .horizontal)
+    switcherContainer.setContentCompressionResistancePriority(.required, for: .horizontal)
+
+    switcherView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.lessThanOrEqualToSuperview()
+    }
+
+    stackView.spacing = 8
+    stackView.addArrangedSubview(icon)
+    stackView.addArrangedSubview(verticalStackView)
+    stackView.addArrangedSubview(switcherContainer)
+
+    stackView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(16)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview().offset(-20)
+    }
+    separatorView.snp.makeConstraints {
+      $0.height.equalTo(1)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  func set(
+    title: String,
+    text: String? = nil,
+    icon: UIImage? = nil,
+    separator: Bool = true,
+    extraAction: UIButton? = nil,
+    didTapInfo: (() -> Void)? = nil
+  ) {
+    self.didTapInfo = didTapInfo
+
+    titleView.setup(
+      text: title,
+      attributes: [
+        .foregroundColor: Asset.neutralActive.color,
+        .font: Fonts.Mulish.semiBold.font(size: 14.0) as Any
+      ], didTapInfo: { self.didTapInfo?() }
+    )
+
+    if let content = text {
+      let paragraphStyle = NSMutableParagraphStyle()
+      paragraphStyle.lineHeightMultiple = 1.5
+
+      textLabel.attributedText = NSAttributedString(
+        string: content, attributes: [.paragraphStyle: paragraphStyle]
+      )
+    } else {
+      verticalStackView.removeArrangedSubview(textLabel)
+    }
+
+    if let icon = icon {
+      iconImageView.image = icon
+    } else {
+      stackView.removeArrangedSubview(iconImageView)
+    }
+
+    if let button = extraAction {
+      stackView.insertArrangedSubview(button.pinning(at: .top(0)), at: 2)
     }
 
-    required init?(coder: NSCoder) { nil }
-
-    func set(
-        title: String,
-        text: String? = nil,
-        icon: UIImage? = nil,
-        separator: Bool = true,
-        extraAction: UIButton? = nil,
-        didTapInfo: (() -> Void)? = nil
-    ) {
-        self.didTapInfo = didTapInfo
-
-        titleView.setup(
-            text: title,
-            attributes: [
-                .foregroundColor: Asset.neutralActive.color,
-                .font: Fonts.Mulish.semiBold.font(size: 14.0) as Any
-            ], didTapInfo: { self.didTapInfo?() }
-        )
-
-        if let content = text {
-            let paragraphStyle = NSMutableParagraphStyle()
-            paragraphStyle.lineHeightMultiple = 1.5
-
-            textLabel.attributedText = NSAttributedString(
-                string: content, attributes: [.paragraphStyle: paragraphStyle]
-            )
-        } else {
-            verticalStackView.removeArrangedSubview(textLabel)
-        }
-
-        if let icon = icon {
-            iconImageView.image = icon
-        } else {
-            stackView.removeArrangedSubview(iconImageView)
-        }
-
-        if let button = extraAction {
-            stackView.insertArrangedSubview(button.pinning(at: .top(0)), at: 2)
-        }
-
-        guard separator == true else {
-            separatorView.removeFromSuperview()
-            return
-        }
+    guard separator == true else {
+      separatorView.removeFromSuperview()
+      return
     }
+  }
 }
diff --git a/Sources/SettingsFeature/Views/SettingsView.swift b/Sources/SettingsFeature/Views/SettingsView.swift
index 8f17926c9bc885d82d5625d83eb7cfdf1eae6807..450e8aa60f347de50a3b9efc46316f9f73dbf81d 100644
--- a/Sources/SettingsFeature/Views/SettingsView.swift
+++ b/Sources/SettingsFeature/Views/SettingsView.swift
@@ -2,181 +2,176 @@ import UIKit
 import Shared
 
 final class SettingsView: UIView {
-    enum InfoTapped {
-        case dummyTraffic
-        case biometrics
-        case notifications
-        case icognitoKeyboard
+  enum InfoTapped {
+    case dummyTraffic
+    case biometrics
+    case notifications
+    case icognitoKeyboard
+  }
+
+  let generalStack = UIStackView()
+  let generalTitle = UILabel()
+  let biometrics = SettingsInfoSwitcher()
+  let remoteNotifications = SettingsInfoSwitcher()
+  let dummyTraffic = SettingsInfoSwitcher()
+  let inAppNotifications = SettingsSwitcher()
+
+  let chatStack = UIStackView()
+  let chatTitle = UILabel()
+  let hideActiveApp = SettingsSwitcher()
+  let icognitoKeyboard = SettingsInfoSwitcher()
+
+  let otherStackView = UIStackView()
+  let privacyPolicyButton = RowButton()
+  let disclosuresButton = RowButton()
+  let advancedButton = RowButton()
+  let accountBackupButton = RowButton()
+  let deleteButton = RowButton()
+
+  let didTap: (InfoTapped) -> Void
+
+  init(didTap: @escaping (InfoTapped) -> Void) {
+    self.didTap = didTap
+
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+
+    setupGeneralStack()
+    setupChatStack()
+    setupOtherStack()
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  private func setupGeneralStack() {
+    generalTitle.text = Localized.Settings.general
+    generalTitle.textColor = Asset.neutralActive.color
+    generalTitle.font = Fonts.Mulish.semiBold.font(size: 18.0)
+
+    remoteNotifications.set(
+      title: Localized.Settings.RemoteNotifications.title,
+      text: Localized.Settings.RemoteNotifications.description,
+      icon: Asset.settingsNotifications.image
+    ) { self.didTap(.notifications) }
+
+    inAppNotifications.set(
+      title: Localized.Settings.InAppNotifications.title,
+      text: Localized.Settings.InAppNotifications.description,
+      icon: Asset.settingsNotifications.image
+    )
+
+    dummyTraffic.set(
+      title: Localized.Settings.Traffic.title,
+      text: Localized.Settings.Traffic.subtitle,
+      icon: Asset.settingsBiometrics.image,
+      separator: false,
+      didTapInfo: { self.didTap(.dummyTraffic) }
+    )
+
+    biometrics.set(
+      title: Localized.Settings.Biometrics.title,
+      text: Localized.Settings.Biometrics.description,
+      icon: Asset.settingsBiometrics.image,
+      separator: false
+    ) { self.didTap(.biometrics) }
+
+    generalStack.axis = .vertical
+    generalStack.addArrangedSubview(remoteNotifications)
+    generalStack.addArrangedSubview(dummyTraffic)
+    generalStack.addArrangedSubview(inAppNotifications)
+    generalStack.addArrangedSubview(biometrics)
+
+    addSubview(generalTitle)
+    addSubview(generalStack)
+
+    generalTitle.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(24)
+      $0.left.equalToSuperview().offset(21)
     }
 
-    let generalStack = UIStackView()
-    let generalTitle = UILabel()
-    let biometrics = SettingsInfoSwitcher()
-    let remoteNotifications = SettingsInfoSwitcher()
-    let dummyTraffic = SettingsInfoSwitcher()
-    let inAppNotifications = SettingsSwitcher()
-
-    let chatStack = UIStackView()
-    let chatTitle = UILabel()
-    let hideActiveApp = SettingsSwitcher()
-    let icognitoKeyboard = SettingsInfoSwitcher()
-
-    let otherStackView = UIStackView()
-    let privacyPolicyButton = RowButton()
-    let disclosuresButton = RowButton()
-    let advancedButton = RowButton()
-    let accountBackupButton = RowButton()
-    let deleteButton = RowButton()
-
-    let didTap: (InfoTapped) -> Void
-
-    init(didTap: @escaping (InfoTapped) -> Void) {
-        self.didTap = didTap
-
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        setupGeneralStack()
-        setupChatStack()
-        setupOtherStack()
+    generalStack.snp.makeConstraints {
+      $0.top.equalTo(generalTitle.snp.bottom).offset(8)
+      $0.left.equalToSuperview().offset(16)
+      $0.right.equalToSuperview().offset(-16)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    private func setupGeneralStack() {
-        generalTitle.text = Localized.Settings.general
-        generalTitle.textColor = Asset.neutralActive.color
-        generalTitle.font = Fonts.Mulish.semiBold.font(size: 18.0)
-
-        remoteNotifications.set(
-            title: Localized.Settings.RemoteNotifications.title,
-            text: Localized.Settings.RemoteNotifications.description,
-            icon: Asset.settingsNotifications.image
-        ) { self.didTap(.notifications) }
-
-        inAppNotifications.set(
-            title: Localized.Settings.InAppNotifications.title,
-            text: Localized.Settings.InAppNotifications.description,
-            icon: Asset.settingsNotifications.image
-        )
-
-        dummyTraffic.set(
-            title: Localized.Settings.Traffic.title,
-            text: Localized.Settings.Traffic.subtitle,
-            icon: Asset.settingsBiometrics.image,
-            separator: false,
-            didTapInfo: { self.didTap(.dummyTraffic) }
-        )
-
-        biometrics.set(
-            title: Localized.Settings.Biometrics.title,
-            text: Localized.Settings.Biometrics.description,
-            icon: Asset.settingsBiometrics.image,
-            separator: false
-        ) { self.didTap(.biometrics) }
-
-        generalStack.axis = .vertical
-        generalStack.addArrangedSubview(remoteNotifications)
-        generalStack.addArrangedSubview(dummyTraffic)
-        generalStack.addArrangedSubview(inAppNotifications)
-        generalStack.addArrangedSubview(biometrics)
-
-        addSubview(generalTitle)
-        addSubview(generalStack)
-
-        generalTitle.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(24)
-            make.left.equalToSuperview().offset(21)
-        }
-
-        generalStack.snp.makeConstraints { make in
-            make.top.equalTo(generalTitle.snp.bottom).offset(8)
-            make.left.equalToSuperview().offset(16)
-            make.right.equalToSuperview().offset(-16)
-        }
+  }
+
+  private func setupChatStack() {
+    chatTitle.text = Localized.Settings.chat
+    chatTitle.textColor = Asset.neutralActive.color
+    chatTitle.font = Fonts.Mulish.semiBold.font(size: 18.0)
+
+    hideActiveApp.set(
+      title: Localized.Settings.HideActiveApps.title,
+      text: Localized.Settings.HideActiveApps.description,
+      icon: Asset.settingsHide.image
+    )
+
+    icognitoKeyboard.set(
+      title: Localized.Settings.IcognitoKeyboard.title,
+      text: Localized.Settings.IcognitoKeyboard.description,
+      icon: Asset.settingsKeyboard.image
+    ) { self.didTap(.icognitoKeyboard) }
+
+    chatStack.axis = .vertical
+    chatStack.addArrangedSubview(hideActiveApp)
+    chatStack.addArrangedSubview(icognitoKeyboard)
+
+    addSubview(chatTitle)
+    addSubview(chatStack)
+
+    chatTitle.snp.makeConstraints {
+      $0.top.equalTo(generalStack.snp.bottom).offset(20)
+      $0.left.equalToSuperview().offset(21)
     }
-
-    private func setupChatStack() {
-        chatTitle.text = Localized.Settings.chat
-        chatTitle.textColor = Asset.neutralActive.color
-        chatTitle.font = Fonts.Mulish.semiBold.font(size: 18.0)
-
-        hideActiveApp.set(
-            title: Localized.Settings.HideActiveApps.title,
-            text: Localized.Settings.HideActiveApps.description,
-            icon: Asset.settingsHide.image
-        )
-
-        icognitoKeyboard.set(
-            title: Localized.Settings.IcognitoKeyboard.title,
-            text: Localized.Settings.IcognitoKeyboard.description,
-            icon: Asset.settingsKeyboard.image
-        ) { self.didTap(.icognitoKeyboard) }
-
-        chatStack.axis = .vertical
-        chatStack.addArrangedSubview(hideActiveApp)
-        chatStack.addArrangedSubview(icognitoKeyboard)
-
-        addSubview(chatTitle)
-        addSubview(chatStack)
-
-        chatTitle.snp.makeConstraints { make in
-            make.top.equalTo(generalStack.snp.bottom).offset(20)
-            make.left.equalToSuperview().offset(21)
-        }
-
-        chatStack.snp.makeConstraints { make in
-            make.top.equalTo(chatTitle.snp.bottom).offset(8)
-            make.left.equalToSuperview().offset(16)
-            make.right.equalToSuperview().offset(-16)
-        }
+    chatStack.snp.makeConstraints {
+      $0.top.equalTo(chatTitle.snp.bottom).offset(8)
+      $0.left.equalToSuperview().offset(16)
+      $0.right.equalToSuperview().offset(-16)
     }
-
-    private func setupOtherStack() {
-        privacyPolicyButton.setup(
-            title: Localized.Settings.privacyPolicy,
-            icon: Asset.settingsPrivacy.image,
-            separator: false
-        )
-
-        disclosuresButton.setup(
-            title: Localized.Settings.disclosures,
-            icon: Asset.settingsFolder.image
-        )
-
-        advancedButton.setup(
-            title: Localized.Settings.advanced,
-            icon: Asset.settingsAdvanced.image
-        )
-
-        accountBackupButton.setup(
-            title: Localized.Settings.Advanced.AccountBackup.title,
-            icon: Asset.settingsAdvanced.image,
-            style: .clean,
-            separator: false
-        )
-
-        deleteButton.setup(
-            title: Localized.Settings.delete,
-            icon: Asset.settingsDelete.image,
-            style: .delete,
-            separator: false
-        )
-
-        otherStackView.axis = .vertical
-        otherStackView.addArrangedSubview(privacyPolicyButton)
-        otherStackView.addArrangedSubview(disclosuresButton)
-        otherStackView.addArrangedSubview(accountBackupButton)
-        otherStackView.addArrangedSubview(advancedButton)
-        otherStackView.addArrangedSubview(deleteButton)
-
-        addSubview(otherStackView)
-
-        otherStackView.snp.makeConstraints { make in
-            make.top.equalTo(chatStack.snp.bottom).offset(15)
-            make.left.equalToSuperview().offset(16)
-            make.right.equalToSuperview().offset(-16)
-            make.bottom.lessThanOrEqualToSuperview().offset(-20)
-        }
+  }
+
+  private func setupOtherStack() {
+    privacyPolicyButton.setup(
+      title: Localized.Settings.privacyPolicy,
+      icon: Asset.settingsPrivacy.image,
+      separator: false
+    )
+    disclosuresButton.setup(
+      title: Localized.Settings.disclosures,
+      icon: Asset.settingsFolder.image
+    )
+    advancedButton.setup(
+      title: Localized.Settings.advanced,
+      icon: Asset.settingsAdvanced.image
+    )
+    accountBackupButton.setup(
+      title: Localized.Settings.Advanced.AccountBackup.title,
+      icon: Asset.settingsAdvanced.image,
+      style: .clean,
+      separator: false
+    )
+    deleteButton.setup(
+      title: Localized.Settings.delete,
+      icon: Asset.settingsDelete.image,
+      style: .delete,
+      separator: false
+    )
+
+    otherStackView.axis = .vertical
+    otherStackView.addArrangedSubview(privacyPolicyButton)
+    otherStackView.addArrangedSubview(disclosuresButton)
+    otherStackView.addArrangedSubview(accountBackupButton)
+    otherStackView.addArrangedSubview(advancedButton)
+    otherStackView.addArrangedSubview(deleteButton)
+
+    addSubview(otherStackView)
+
+    otherStackView.snp.makeConstraints {
+      $0.top.equalTo(chatStack.snp.bottom).offset(15)
+      $0.left.equalToSuperview().offset(16)
+      $0.right.equalToSuperview().offset(-16)
+      $0.bottom.lessThanOrEqualToSuperview().offset(-20)
     }
+  }
 }
diff --git a/Sources/Shared/Controllers/RootViewController.swift b/Sources/Shared/Controllers/RootViewController.swift
index 86f20217da41497cebbce7f6667dd8c129feffc7..ee367e2eff71b7bae66484ead5b1a40f7646cf25 100644
--- a/Sources/Shared/Controllers/RootViewController.swift
+++ b/Sources/Shared/Controllers/RootViewController.swift
@@ -159,7 +159,7 @@ extension RootViewController {
 
       self.toastTimer?.invalidate()
       self.toastTimer = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { [weak self] _ in
-        guard let self = self else { return }
+        guard let self else { return }
         self.dismiss(toastView: toastView)
       }
     }
diff --git a/Sources/Shared/Models/Country.swift b/Sources/Shared/Models/Country.swift
new file mode 100644
index 0000000000000000000000000000000000000000..8d25ca75aba8358d5fe18265a7febd7e4887e6f9
--- /dev/null
+++ b/Sources/Shared/Models/Country.swift
@@ -0,0 +1,44 @@
+import Foundation
+
+public struct Country {
+  public var name: String
+  public var code: String
+  public var flag: String
+  public var regex: String
+  public var prefix: String
+  public var example: String
+  public var prefixWithFlag: String { "\(flag) \(prefix)" }
+
+  public static func fromMyPhone() -> Self {
+    let all = all()
+
+    guard let country = all.filter({ $0.code == Locale.current.regionCode }).first else {
+      return all.filter { $0.code == "US" }.first!
+    }
+
+    return country
+  }
+
+  public static func all() -> [Self] {
+    guard let url = Bundle.module.url(forResource: "country_codes", withExtension: "json"),
+          let data = try? Data(contentsOf: url),
+          let countries = try? JSONDecoder().decode([Country].self, from: data) else {
+      fatalError("Can't handle country codes json")
+    }
+
+    return countries
+  }
+
+  public static func findFrom(_ number: String) -> Self {
+    all().first { country in
+      let start = number.index(number.startIndex, offsetBy: number.count - 2)
+      let end = number.index(start, offsetBy: number.count - (number.count - 2))
+
+      return country.code == String(number[start ..< end])
+    }!
+  }
+}
+
+extension Country: Hashable {}
+extension Country: Equatable {}
+extension Country: Decodable {}
diff --git a/Sources/Shared/Models/HUDModel.swift b/Sources/Shared/Models/HUDModel.swift
index a68d3bc389311ee80cc38c58aa0a3c347eb7c1ba..ddc8fb5c2cd3ae20e8733147c937e66c59411b96 100644
--- a/Sources/Shared/Models/HUDModel.swift
+++ b/Sources/Shared/Models/HUDModel.swift
@@ -5,6 +5,7 @@ public struct HUDModel {
   var content: String?
   var actionTitle: String?
   var hasDotAnimation: Bool
+  var isAutoDismissable: Bool
   var onTapClosure: (() -> Void)?
 
   public init(
@@ -12,6 +13,7 @@ public struct HUDModel {
     content: String? = nil,
     actionTitle: String? = nil,
     hasDotAnimation: Bool = false,
+    isAutoDismissable: Bool = false,
     onTapClosure: (() -> Void)? = nil
   ) {
     self.title = title
@@ -19,6 +21,7 @@ public struct HUDModel {
     self.actionTitle = actionTitle
     self.onTapClosure = onTapClosure
     self.hasDotAnimation = hasDotAnimation
+    self.isAutoDismissable = isAutoDismissable
   }
 
   public init(
@@ -30,6 +33,7 @@ public struct HUDModel {
     self.actionTitle = actionTitle
     self.onTapClosure = onTapClosure
     self.title = Localized.Hud.Error.title
+    self.isAutoDismissable = onTapClosure == nil
     self.content = error.localizedDescription
   }
 }
diff --git a/Sources/Shared/Models/MenuItem.swift b/Sources/Shared/Models/MenuItem.swift
new file mode 100644
index 0000000000000000000000000000000000000000..072b5033e3332dea3a70fbab4a5275c78c7d1b27
--- /dev/null
+++ b/Sources/Shared/Models/MenuItem.swift
@@ -0,0 +1,11 @@
+public enum MenuItem {
+  case join
+  case scan
+  case chats
+  case share
+  case profile
+  case contacts
+  case requests
+  case settings
+  case dashboard
+}
diff --git a/Sources/Shared/Models/PermissionType.swift b/Sources/Shared/Models/PermissionType.swift
new file mode 100644
index 0000000000000000000000000000000000000000..43d28fbd1c764364136544729d5adab320e5db20
--- /dev/null
+++ b/Sources/Shared/Models/PermissionType.swift
@@ -0,0 +1,5 @@
+public enum PermissionType {
+  case camera
+  case library
+  case microphone
+}
diff --git a/Sources/Countries/Resources/country_codes.json b/Sources/Shared/Resources/country_codes.json
similarity index 100%
rename from Sources/Countries/Resources/country_codes.json
rename to Sources/Shared/Resources/country_codes.json
diff --git a/Sources/TermsFeature/TermsConditionsController.swift b/Sources/TermsFeature/TermsConditionsController.swift
index d426489d9e8793bdaddc539020786585d7f0ac90..8d7229337b60ffdb74cf3821f301903d956e8666 100644
--- a/Sources/TermsFeature/TermsConditionsController.swift
+++ b/Sources/TermsFeature/TermsConditionsController.swift
@@ -3,17 +3,17 @@ import WebKit
 import Shared
 import Combine
 import Defaults
+import XXNavigation
 import DependencyInjection
 
 public final class TermsConditionsController: UIViewController {
-  @Dependency var coordinator: TermsCoordinator
+  @Dependency var navigator: Navigator
 
   @KeyObject(.username, defaultValue: nil) var username: String?
   @KeyObject(.acceptedTerms, defaultValue: false) var didAcceptTerms: Bool
 
-  private lazy var screenView = TermsConditionsView()
-
   private var cancellables = Set<AnyCancellable>()
+  private lazy var screenView = TermsConditionsView()
 
   public override func loadView() {
     view = screenView
@@ -30,7 +30,6 @@ public final class TermsConditionsController: UIViewController {
 
   public override func viewDidLayoutSubviews() {
     super.viewDidLayoutSubviews()
-
     let gradient = CAGradientLayer()
     gradient.colors = [
       UIColor(red: 122/255, green: 235/255, blue: 239/255, alpha: 1).cgColor,
@@ -38,18 +37,16 @@ public final class TermsConditionsController: UIViewController {
       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.frame = screenView.bounds
     screenView.layer.insertSublayer(gradient, at: 0)
   }
 
   public override func viewDidLoad() {
     super.viewDidLoad()
-
-    screenView.radioComponent
+    screenView
+      .radioComponent
       .radioButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
@@ -58,19 +55,20 @@ public final class TermsConditionsController: UIViewController {
         UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
       }.store(in: &cancellables)
 
-    screenView.nextButton
+    screenView
+      .nextButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
         didAcceptTerms = true
-
-        if let _ = username {
-          coordinator.presentChatList(self)
+        if username != nil {
+          navigator.perform(PresentChatList())
         } else {
-          coordinator.presentUsername(self)
+          navigator.perform(PresentOnboardingUsername())
         }
       }.store(in: &cancellables)
 
-    screenView.showTermsButton
+    screenView
+      .showTermsButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] _ in
         let webView = WKWebView()
diff --git a/Sources/TermsFeature/TermsCoordinator.swift b/Sources/TermsFeature/TermsCoordinator.swift
deleted file mode 100644
index 05e4fc6243da998037f92e9d3cad65845deb08e4..0000000000000000000000000000000000000000
--- a/Sources/TermsFeature/TermsCoordinator.swift
+++ /dev/null
@@ -1,25 +0,0 @@
-import UIKit
-import Presentation
-
-public struct TermsCoordinator {
-    var presentChatList: (UIViewController) -> Void
-    var presentUsername: (UIViewController) -> Void
-}
-
-public extension TermsCoordinator {
-    static func live(
-        usernameFactory: @escaping () -> UIViewController,
-        chatListFactory: @escaping () -> UIViewController
-    ) -> Self {
-        .init(
-            presentChatList: { parent in
-                let presenter = ReplacePresenter()
-                presenter.present(chatListFactory(), from: parent)
-            },
-            presentUsername: { parent in
-                let presenter = PushPresenter()
-                presenter.present(usernameFactory(), from: parent)
-            }
-        )
-    }
-}
diff --git a/Sources/VersionChecking/VersionChecking.swift b/Sources/VersionChecking/VersionChecking.swift
index 820a2aac66a5db65577ab4e39109c33256e26e7a..5acc10b5a6def59c701fa794cd2fe720b532d5ce 100644
--- a/Sources/VersionChecking/VersionChecking.swift
+++ b/Sources/VersionChecking/VersionChecking.swift
@@ -14,13 +14,7 @@ public struct VersionCheck {
 }
 
 public extension VersionCheck {
-  static let mock: Self = .init { $0(.outdated(.init(
-    appUrl: "https://testflight.apple.com/join/L1Rj0so3",
-    minimum: "2.0",
-    isRequired: false,
-    recommended: "5.0",
-    minimumMessage: "This app version is not supported anymore, please update to the latest version to keep enjoying our app"
-  ))) }
+  static let mock: Self = .init { $0(.upToDate) }
 
   static let live: Self = .init { completion in
     let request = URLRequest(
diff --git a/Sources/XXNavigation/Actions/PresentChat.swift b/Sources/XXNavigation/Actions/PresentChat.swift
deleted file mode 100644
index db7e63b684ae1c3f876898b0a8be36235be25ad3..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentChat.swift
+++ /dev/null
@@ -1,12 +0,0 @@
-import XXModels
-import Navigation
-
-public struct PresentChat: Navigation.Action {
-  public var contact: Contact
-  public var animated: Bool = true
-
-  public init(contact: Contact, animated: Bool = true) {
-    self.contact = contact
-    self.animated = animated
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentChatList.swift b/Sources/XXNavigation/Actions/PresentChatList.swift
deleted file mode 100644
index 69f3f9423e6521c326a97676fb532f348fb990e9..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentChatList.swift
+++ /dev/null
@@ -1,9 +0,0 @@
-import Navigation
-
-public struct PresentChatList: Navigation.Action {
-  public var animated: Bool = true
-
-  public init(animated: Bool = true) {
-    self.animated = animated
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentCountryList.swift b/Sources/XXNavigation/Actions/PresentCountryList.swift
deleted file mode 100644
index adb7ee1d5cd5524e6249cbfd7acb5e4870b25aa2..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentCountryList.swift
+++ /dev/null
@@ -1,9 +0,0 @@
-import Navigation
-
-public struct PresentCountryList: Navigation.Action {
-  public var animated: Bool = true
-
-  public init(animated: Bool = true) {
-    self.animated = animated
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentDrawer.swift b/Sources/XXNavigation/Actions/PresentDrawer.swift
deleted file mode 100644
index 01e878b3ec02bd211213f9e1fb2f73f95a0de0bc..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentDrawer.swift
+++ /dev/null
@@ -1,18 +0,0 @@
-import Navigation
-import DrawerFeature
-
-public struct PresentDrawer: Navigation.Action {
-  public var items: [DrawerItem]
-  public var animated: Bool = true
-  public var dismissable: Bool = true
-
-  public init(
-    items: [DrawerItem],
-    animated: Bool = true,
-    dismissable: Bool = true
-  ) {
-    self.items = items
-    self.animated = animated
-    self.dismissable = dismissable
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentGroupChat.swift b/Sources/XXNavigation/Actions/PresentGroupChat.swift
deleted file mode 100644
index 39219036447e529dc504f88fb5787fec9a874bc0..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentGroupChat.swift
+++ /dev/null
@@ -1,12 +0,0 @@
-import XXModels
-import Navigation
-
-public struct PresentGroupChat: Navigation.Action {
-  public var model: GroupInfo
-  public var animated: Bool = true
-
-  public init(model: GroupInfo, animated: Bool = true) {
-    self.model = model
-    self.animated = animated
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentOnboardingCode.swift b/Sources/XXNavigation/Actions/PresentOnboardingCode.swift
deleted file mode 100644
index 59f0926ffd0191eb7c7b644735ed084f257b2d5e..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentOnboardingCode.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-import Navigation
-
-public struct PresentOnboardingCode: Navigation.Action {
-  public var isEmail: Bool
-  public var content: String
-  public var animated: Bool = true
-  public var confirmationId: String
-
-  public init(
-    isEmail: Bool,
-    content: String,
-    confirmationId: String,
-    animated: Bool = true
-  ) {
-    self.animated = animated
-    self.isEmail = isEmail
-    self.content = content
-    self.confirmationId = confirmationId
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentOnboardingEmail.swift b/Sources/XXNavigation/Actions/PresentOnboardingEmail.swift
deleted file mode 100644
index 6d418378dff1fbbca972e4462eef57b696c66b81..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentOnboardingEmail.swift
+++ /dev/null
@@ -1,9 +0,0 @@
-import Navigation
-
-public struct PresentOnboardingEmail: Navigation.Action {
-  public var animated: Bool = true
-
-  public init(animated: Bool = true) {
-    self.animated = animated
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentOnboardingPhone.swift b/Sources/XXNavigation/Actions/PresentOnboardingPhone.swift
deleted file mode 100644
index 6a104049e8fe4d5b5fdd3b2d191dee07830e8882..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentOnboardingPhone.swift
+++ /dev/null
@@ -1,9 +0,0 @@
-import Navigation
-
-public struct PresentOnboardingPhone: Navigation.Action {
-  public var animated: Bool = true
-
-  public init(animated: Bool = true) {
-    self.animated = animated
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentOnboardingStart.swift b/Sources/XXNavigation/Actions/PresentOnboardingStart.swift
deleted file mode 100644
index fc0bf22983ff45874174090db069f2425f01df0f..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentOnboardingStart.swift
+++ /dev/null
@@ -1,9 +0,0 @@
-import Navigation
-
-public struct PresentOnboardingStart: Navigation.Action {
-  public var animated: Bool = true
-
-  public init(animated: Bool = true) {
-    self.animated = animated
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentOnboardingUsername.swift b/Sources/XXNavigation/Actions/PresentOnboardingUsername.swift
deleted file mode 100644
index 5a828dc48edaf5b90b7c7261956566b578902448..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentOnboardingUsername.swift
+++ /dev/null
@@ -1,9 +0,0 @@
-import Navigation
-
-public struct PresentOnboardingUsername: Navigation.Action {
-  public var animated: Bool = true
-
-  public init(animated: Bool = true) {
-    self.animated = animated
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentOnboardingWelcome.swift b/Sources/XXNavigation/Actions/PresentOnboardingWelcome.swift
deleted file mode 100644
index 1c4120896abf0bb0efdb12b2833d7ccfc68beca9..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentOnboardingWelcome.swift
+++ /dev/null
@@ -1,9 +0,0 @@
-import Navigation
-
-public struct PresentOnboardingWelcome: Navigation.Action {
-  public var animated: Bool = true
-
-  public init(animated: Bool = true) {
-    self.animated = animated
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentRestoreList.swift b/Sources/XXNavigation/Actions/PresentRestoreList.swift
deleted file mode 100644
index 8a7fbb5a13ec80c6db8e2795e5b2bca77b283511..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentRestoreList.swift
+++ /dev/null
@@ -1,9 +0,0 @@
-import Navigation
-
-public struct PresentRestoreList: Navigation.Action {
-  public var animated: Bool = true
-
-  public init(animated: Bool = true) {
-    self.animated = animated
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentSearch.swift b/Sources/XXNavigation/Actions/PresentSearch.swift
deleted file mode 100644
index 7cb33ba23d3822d86a8800dba3dcbe23cc7a857b..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentSearch.swift
+++ /dev/null
@@ -1,11 +0,0 @@
-import Navigation
-
-public struct PresentSearch: Navigation.Action {
-  public var searching: String?
-  public var animated: Bool = true
-
-  public init(searching: String? = nil, animated: Bool = true) {
-    self.searching = searching
-    self.animated = animated
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentTermsAndConditions.swift b/Sources/XXNavigation/Actions/PresentTermsAndConditions.swift
deleted file mode 100644
index 2df2ad38f1c0a317ba640620df29e214288b975c..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Actions/PresentTermsAndConditions.swift
+++ /dev/null
@@ -1,14 +0,0 @@
-import Navigation
-
-public struct PresentTermsAndConditions: Navigation.Action {
-  public var animated: Bool = true
-  public var popAllowed: Bool = true
-
-  public init(
-    animated: Bool = true,
-    popAllowed: Bool = true
-  ) {
-    self.animated = animated
-    self.popAllowed = popAllowed
-  }
-}
diff --git a/Sources/XXNavigation/Actions/PresentRequests.swift b/Sources/XXNavigation/Chat/PresentCamera.swift
similarity index 52%
rename from Sources/XXNavigation/Actions/PresentRequests.swift
rename to Sources/XXNavigation/Chat/PresentCamera.swift
index 0f9718f0bef74244a1f5d9db5ef7d4030d408ded..ad8bd440798aae1044a8a4fc851da5da96b80da4 100644
--- a/Sources/XXNavigation/Actions/PresentRequests.swift
+++ b/Sources/XXNavigation/Chat/PresentCamera.swift
@@ -1,7 +1,7 @@
 import Navigation
 
-public struct PresentRequests: Navigation.Action {
-  public var animated: Bool = true
+public struct PresentCamera: Navigation.Action {
+  public var animated: Bool
 
   public init(animated: Bool = true) {
     self.animated = animated
diff --git a/Sources/XXNavigation/Navigators/PresentChatNavigator.swift b/Sources/XXNavigation/Chat/PresentChat.swift
similarity index 75%
rename from Sources/XXNavigation/Navigators/PresentChatNavigator.swift
rename to Sources/XXNavigation/Chat/PresentChat.swift
index 2714bc558042e4a4f34a20755504db4761a7caac..52593d967d8d384263603aecada75a9ee8c44131 100644
--- a/Sources/XXNavigation/Navigators/PresentChatNavigator.swift
+++ b/Sources/XXNavigation/Chat/PresentChat.swift
@@ -3,6 +3,19 @@ import XXModels
 import Navigation
 import DependencyInjection
 
+public struct PresentChat: Navigation.Action {
+  public var contact: Contact
+  public var animated: Bool
+
+  public init(
+    contact: Contact,
+    animated: Bool = true
+  ) {
+    self.contact = contact
+    self.animated = animated
+  }
+}
+
 public struct PresentChatNavigator: TypedNavigator {
   @Dependency var navigator: Navigator
   var screen: (Contact) -> UIViewController
diff --git a/Sources/XXNavigation/Navigators/PresentChatListNavigator.swift b/Sources/XXNavigation/Chat/PresentChatList.swift
similarity index 81%
rename from Sources/XXNavigation/Navigators/PresentChatListNavigator.swift
rename to Sources/XXNavigation/Chat/PresentChatList.swift
index 0d83657ff6061938ccdd2fa28be330470aa9240a..8fc96301d15a6d32483bb0171da7ab959f623e48 100644
--- a/Sources/XXNavigation/Navigators/PresentChatListNavigator.swift
+++ b/Sources/XXNavigation/Chat/PresentChatList.swift
@@ -2,6 +2,14 @@ import UIKit
 import Navigation
 import DependencyInjection
 
+public struct PresentChatList: Navigation.Action {
+  public var animated: Bool = true
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
 public struct PresentChatListNavigator: TypedNavigator {
   @Dependency var navigator: Navigator
   var screen: () -> UIViewController
diff --git a/Sources/XXNavigation/Navigators/PresentGroupChatNavigator.swift b/Sources/XXNavigation/Chat/PresentGroupChat.swift
similarity index 75%
rename from Sources/XXNavigation/Navigators/PresentGroupChatNavigator.swift
rename to Sources/XXNavigation/Chat/PresentGroupChat.swift
index a44485bc3007338c6a0bc20654738dd77597aafd..7770475e019de1a50fdee060a09b9d8ce3f3642f 100644
--- a/Sources/XXNavigation/Navigators/PresentGroupChatNavigator.swift
+++ b/Sources/XXNavigation/Chat/PresentGroupChat.swift
@@ -3,6 +3,19 @@ import XXModels
 import Navigation
 import DependencyInjection
 
+public struct PresentGroupChat: Navigation.Action {
+  public var model: GroupInfo
+  public var animated: Bool
+
+  public init(
+    model: GroupInfo,
+    animated: Bool = true
+  ) {
+    self.model = model
+    self.animated = animated
+  }
+}
+
 public struct PresentGroupChatNavigator: TypedNavigator {
   @Dependency var navigator: Navigator
   var screen: (GroupInfo) -> UIViewController
diff --git a/Sources/XXNavigation/Chat/PresentMemberList.swift b/Sources/XXNavigation/Chat/PresentMemberList.swift
new file mode 100644
index 0000000000000000000000000000000000000000..628c0613293c385df483a234190fa25814f660c9
--- /dev/null
+++ b/Sources/XXNavigation/Chat/PresentMemberList.swift
@@ -0,0 +1,15 @@
+import XXModels
+import Navigation
+
+public struct PresentMemberList: Navigation.Action {
+  public var members: [Contact]
+  public var animated: Bool
+
+  public init(
+    members: [Contact],
+    animated: Bool = true
+  ) {
+    self.members = members
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Chat/PresentNewGroup.swift b/Sources/XXNavigation/Chat/PresentNewGroup.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e04adf504fb79c8c7119d6e117ce690efe477bad
--- /dev/null
+++ b/Sources/XXNavigation/Chat/PresentNewGroup.swift
@@ -0,0 +1,30 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentNewGroup: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
+public struct PresentNewGroupNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentNewGroup, completion: @escaping () -> Void) {
+    let pushAction = Push(screen(), on: navigationController(), animated: action.animated)
+    navigator.perform(pushAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Chat/PresentWebsite.swift b/Sources/XXNavigation/Chat/PresentWebsite.swift
new file mode 100644
index 0000000000000000000000000000000000000000..cb46909b6b0181dea8943af3f036c1d0bd6220bb
--- /dev/null
+++ b/Sources/XXNavigation/Chat/PresentWebsite.swift
@@ -0,0 +1,15 @@
+import Navigation
+import Foundation
+
+public struct PresentWebsite: Navigation.Action {
+  public var url: URL
+  public var animated: Bool
+
+  public init(
+    url: URL,
+    animated: Bool = true
+  ) {
+    self.url = url
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Contact/PresentContact.swift b/Sources/XXNavigation/Contact/PresentContact.swift
new file mode 100644
index 0000000000000000000000000000000000000000..4addb00c45b3a83668214c3cfe98678d8adae4ee
--- /dev/null
+++ b/Sources/XXNavigation/Contact/PresentContact.swift
@@ -0,0 +1,36 @@
+import UIKit
+import XXModels
+import Navigation
+import DependencyInjection
+
+public struct PresentContact: Navigation.Action {
+  public var contact: Contact
+  public var animated: Bool
+
+  public init(
+    contact: Contact,
+    animated: Bool = true
+  ) {
+    self.contact = contact
+    self.animated = animated
+  }
+}
+
+public struct PresentContactNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: (Contact) -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentContact, completion: @escaping () -> Void) {
+    let pushAction = Push(screen(action.contact), on: navigationController(), animated: action.animated)
+    navigator.perform(pushAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping (Contact) -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Contact/PresentContactList.swift b/Sources/XXNavigation/Contact/PresentContactList.swift
new file mode 100644
index 0000000000000000000000000000000000000000..f6f328f4f112a4cbb7eeb83c343bec6ce75b9235
--- /dev/null
+++ b/Sources/XXNavigation/Contact/PresentContactList.swift
@@ -0,0 +1,30 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentContactList: Navigation.Action {
+  public var animated: Bool = true
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
+public struct PresentContactListNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentContactList, completion: @escaping () -> Void) {
+    let setStackAction = SetStack([screen()], on: navigationController(), animated: action.animated)
+    navigator.perform(setStackAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Contact/PresentNickname.swift b/Sources/XXNavigation/Contact/PresentNickname.swift
new file mode 100644
index 0000000000000000000000000000000000000000..11d691e28a773d4c46d818440e12e38f1ae6df90
--- /dev/null
+++ b/Sources/XXNavigation/Contact/PresentNickname.swift
@@ -0,0 +1,17 @@
+import Navigation
+
+public struct PresentNickname: Navigation.Action {
+  public var prefilled: String?
+  public var completion: (String) -> Void
+  public var animated: Bool
+
+  public init(
+    prefilled: String?,
+    completion: @escaping (String) -> Void,
+    animated: Bool = true
+  ) {
+    self.prefilled = prefilled
+    self.completion = completion
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/CustomActions/OpenLeft.swift b/Sources/XXNavigation/CustomActions/OpenLeft.swift
new file mode 100644
index 0000000000000000000000000000000000000000..4296f39eba6c5eb0fa04cbc731f689b641d00f3e
--- /dev/null
+++ b/Sources/XXNavigation/CustomActions/OpenLeft.swift
@@ -0,0 +1,310 @@
+import UIKit
+import Navigation
+
+/// Open left view controller on provided parent view controller
+public struct OpenLeft: Action {
+  /// - Parameters:
+  ///   - viewController: View controller to present
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  public init(
+    _ viewController: UIViewController,
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.viewController = viewController
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// View controller to present
+  public var viewController: UIViewController
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `OpenLeft` action
+public struct OpenLeftNavigator: TypedNavigator {
+  let transitioningDelegate = SidePresenter()
+
+  public init() {}
+
+  public func perform(_ action: OpenLeft, completion: @escaping () -> Void) {
+    action.viewController.transitioningDelegate = transitioningDelegate
+    action.viewController.modalPresentationStyle = .overFullScreen
+
+    action.parent.present(
+      action.viewController,
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
+
+final class SidePresenter: NSObject, UIViewControllerTransitioningDelegate {
+  public init(dismissInteractor: SideMenuDismissInteracting = SideMenuDismissInteractor(),
+              menuAnimator: SideMenuAnimating = SideMenuAnimator(),
+              viewAnimator: UIViewAnimating.Type = UIView.self) {
+    self.dismissInteractor = dismissInteractor
+    self.menuAnimator = menuAnimator
+    self.viewAnimator = viewAnimator
+    super.init()
+  }
+
+  let dismissInteractor: SideMenuDismissInteracting
+  let menuAnimator: SideMenuAnimating
+  let viewAnimator: UIViewAnimating.Type
+
+  // MARK: Presenting
+
+  public func present(_ viewControllers: UIViewController..., from parent: UIViewController) {
+    guard let screen = viewControllers.first else {
+      fatalError("Tried to present empty list of view controllers")
+    }
+
+    screen.modalPresentationStyle = .overFullScreen
+    screen.transitioningDelegate = self
+    parent.present(screen, animated: true)
+  }
+
+  // MARK: UIViewControllerTransitioningDelegate
+
+  public func animationController(
+    forPresented presented: UIViewController,
+    presenting: UIViewController,
+    source: UIViewController
+  ) -> UIViewControllerAnimatedTransitioning? {
+    SideMenuPresentTransition(dismissInteractor: dismissInteractor,
+                              menuAnimator: menuAnimator,
+                              viewAnimator: viewAnimator)
+  }
+
+  public func animationController(
+    forDismissed dismissed: UIViewController
+  ) -> UIViewControllerAnimatedTransitioning? {
+    SideMenuDismissTransition(menuAnimator: menuAnimator,
+                              viewAnimator: viewAnimator)
+  }
+
+  public func interactionControllerForDismissal(
+    using animator: UIViewControllerAnimatedTransitioning
+  ) -> UIViewControllerInteractiveTransitioning? {
+    dismissInteractor.interactionInProgress ? dismissInteractor : nil
+  }
+}
+
+public protocol SideMenuAnimating {
+  func animate(in containerView: UIView, to progress: CGFloat)
+}
+
+public struct SideMenuAnimator: SideMenuAnimating {
+  public init() {}
+
+  public func animate(in containerView: UIView, to progress: CGFloat) {
+    guard let fromView = containerView.viewWithTag(SideMenuPresentTransition.fromViewTag)
+    else { return }
+
+    let cornerRadius = progress * 24
+    let shadowOpacity = Float(progress)
+    let offsetX = containerView.bounds.size.width * 0.5 * progress
+    let offsetY = containerView.bounds.size.height * 0.08 * progress
+    let scale = 1 - (0.25 * progress)
+
+    fromView.subviews.first?.layer.cornerRadius = cornerRadius
+    fromView.layer.shadowOpacity = shadowOpacity
+    fromView.transform = CGAffineTransform.identity
+      .translatedBy(x: offsetX, y: offsetY)
+      .scaledBy(x: scale, y: scale)
+  }
+}
+
+import UIKit
+import Shared
+
+public protocol SideMenuDismissInteracting: UIViewControllerInteractiveTransitioning {
+  var interactionInProgress: Bool { get }
+
+  func setup(view: UIView, action: @escaping EmptyClosure)
+}
+
+public final class SideMenuDismissInteractor: UIPercentDrivenInteractiveTransition, SideMenuDismissInteracting {
+  private var action: EmptyClosure?
+  private var shouldFinishTransition = false
+
+  // MARK: SideMenuDismissInteracting
+
+  public var interactionInProgress = false
+
+  public func setup(view: UIView, action: @escaping EmptyClosure) {
+    let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
+    view.addGestureRecognizer(panRecognizer)
+
+    let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_:)))
+    view.addGestureRecognizer(tapRecognizer)
+
+    self.action = action
+  }
+
+  // MARK: Gesture handling
+
+  @objc
+  private func handleTapGesture(_ recognizer: UITapGestureRecognizer) {
+    action?()
+  }
+
+  @objc
+  private func handlePanGesture(_ recognizer: UIPanGestureRecognizer) {
+    guard let view = recognizer.view,
+          let containerView = view.superview
+    else { return }
+
+    let viewWidth = containerView.bounds.size.width
+    guard viewWidth > 0 else { return }
+
+    let translation = recognizer.translation(in: view)
+    let progress = min(1, max(0, -translation.x / (viewWidth * 0.8)))
+
+    switch recognizer.state {
+    case .possible, .failed:
+      interactionInProgress = false
+
+    case .began:
+      interactionInProgress = true
+      shouldFinishTransition = false
+      action?()
+
+    case .changed:
+      shouldFinishTransition = progress >= 0.5
+      update(progress)
+
+    case .cancelled:
+      interactionInProgress = false
+      cancel()
+
+    case .ended:
+      interactionInProgress = false
+      shouldFinishTransition ? finish() : cancel()
+
+    @unknown default:
+      interactionInProgress = false
+      cancel()
+    }
+  }
+}
+
+import UIKit
+
+final class SideMenuDismissTransition: NSObject, UIViewControllerAnimatedTransitioning {
+
+  init(menuAnimator: SideMenuAnimating,
+       viewAnimator: UIViewAnimating.Type) {
+    self.menuAnimator = menuAnimator
+    self.viewAnimator = viewAnimator
+    super.init()
+  }
+
+  let menuAnimator: SideMenuAnimating
+  let viewAnimator: UIViewAnimating.Type
+
+  // MARK: UIViewControllerAnimatedTransitioning
+
+  func transitionDuration(using context: UIViewControllerContextTransitioning?) -> TimeInterval { 0.25 }
+
+  func animateTransition(using context: UIViewControllerContextTransitioning) {
+    viewAnimator.animate(
+      withDuration: transitionDuration(using: context),
+      animations: {
+        self.menuAnimator.animate(in: context.containerView, to: 0)
+      },
+      completion: { _ in
+        let isCancelled = context.transitionWasCancelled
+        context.completeTransition(isCancelled == false)
+      }
+    )
+  }
+}
+
+import UIKit
+import Shared
+
+final class SideMenuPresentTransition: NSObject, UIViewControllerAnimatedTransitioning {
+  static let fromViewTag = UUID().hashValue
+
+  init(
+    dismissInteractor: SideMenuDismissInteracting,
+    menuAnimator: SideMenuAnimating,
+    viewAnimator: UIViewAnimating.Type
+  ) {
+    self.dismissInteractor = dismissInteractor
+    self.menuAnimator = menuAnimator
+    self.viewAnimator = viewAnimator
+    super.init()
+  }
+
+  let dismissInteractor: SideMenuDismissInteracting
+  let menuAnimator: SideMenuAnimating
+  let viewAnimator: UIViewAnimating.Type
+
+  // MARK: UIViewControllerAnimatedTransitioning
+
+  func transitionDuration(using context: UIViewControllerContextTransitioning?) -> TimeInterval { 0.25 }
+
+  func animateTransition(using context: UIViewControllerContextTransitioning) {
+    guard let fromVC = context.viewController(forKey: .from),
+          let fromSnapshot = fromVC.view.snapshotView(afterScreenUpdates: true),
+          let toVC = context.viewController(forKey: .to)
+    else {
+      context.completeTransition(false)
+      return
+    }
+
+    context.containerView.addSubview(toVC.view)
+    toVC.view.frame = context.containerView.bounds
+
+    let fromView = UIView()
+    fromView.tag = Self.fromViewTag
+    context.containerView.addSubview(fromView)
+    fromView.frame = context.containerView.bounds
+    fromView.layer.shadowColor = UIColor.black.cgColor
+    fromView.layer.shadowOpacity = 1
+    fromView.layer.shadowOffset = .zero
+    fromView.layer.shadowRadius = 32
+    fromView.addSubview(fromSnapshot)
+    fromSnapshot.frame = fromView.bounds
+    fromSnapshot.layer.cornerRadius = 0
+    fromSnapshot.layer.masksToBounds = true
+
+    dismissInteractor.setup(
+      view: fromView,
+      action: { fromVC.dismiss(animated: true) }
+    )
+
+    viewAnimator.animate(
+      withDuration: transitionDuration(using: context),
+      animations: {
+        self.menuAnimator.animate(in: context.containerView, to: 1)
+      },
+      completion: { _ in
+        let isCancelled = context.transitionWasCancelled
+        context.completeTransition(isCancelled == false)
+      }
+    )
+  }
+}
+
+import UIKit
+import Shared
+
+public protocol UIViewAnimating {
+  static func animate(
+    withDuration duration: TimeInterval,
+    animations: @escaping EmptyClosure,
+    completion: ((Bool) -> Void)?
+  )
+}
+
+extension UIView: UIViewAnimating {}
diff --git a/Sources/XXNavigation/Export.swift b/Sources/XXNavigation/Export.swift
new file mode 100644
index 0000000000000000000000000000000000000000..dfaf1c7dee21b7c7c0700eefa1427f605b50b501
--- /dev/null
+++ b/Sources/XXNavigation/Export.swift
@@ -0,0 +1 @@
+@_exported import Navigation
diff --git a/Sources/XXNavigation/Navigators/PresentCountryListNavigator.swift b/Sources/XXNavigation/Navigators/PresentCountryListNavigator.swift
deleted file mode 100644
index a5842927631bbdcfeabaf629a9d024ef332989fa..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Navigators/PresentCountryListNavigator.swift
+++ /dev/null
@@ -1,23 +0,0 @@
-import UIKit
-import Navigation
-import DependencyInjection
-
-public struct PresentCountryListNavigator: TypedNavigator {
-  @Dependency var navigator: Navigator
-  var screen: () -> UIViewController
-  var navigationController: () -> UINavigationController
-
-  public func perform(_ action: PresentCountryList, completion: @escaping () -> Void) {
-    if let topViewController = navigationController().topViewController {
-      let modalAction = PresentModal(screen(), from: topViewController)
-    }
-  }
-
-  public init(
-    screen: @escaping () -> UIViewController,
-    navigationController: @escaping () -> UINavigationController
-  ) {
-    self.screen = screen
-    self.navigationController = navigationController
-  }
-}
diff --git a/Sources/XXNavigation/Navigators/PresentSearchNavigator.swift b/Sources/XXNavigation/Navigators/PresentSearchNavigator.swift
deleted file mode 100644
index d4ce74c1aa5c4459da7e77cf01b532656b4c6b2b..0000000000000000000000000000000000000000
--- a/Sources/XXNavigation/Navigators/PresentSearchNavigator.swift
+++ /dev/null
@@ -1,22 +0,0 @@
-import UIKit
-import Navigation
-import DependencyInjection
-
-public struct PresentSearchNavigator: TypedNavigator {
-  @Dependency var navigator: Navigator
-  var screen: (String?) -> UIViewController
-  var navigationController: () -> UINavigationController
-
-  public func perform(_ action: PresentSearch, completion: @escaping () -> Void) {
-    let setStackAction = SetStack([screen(action.searching)], on: navigationController(), animated: action.animated)
-    navigator.perform(setStackAction, completion: completion)
-  }
-
-  public init(
-    screen: @escaping (String?) -> UIViewController,
-    navigationController: @escaping () -> UINavigationController
-  ) {
-    self.screen = screen
-    self.navigationController = navigationController
-  }
-}
diff --git a/Sources/XXNavigation/Navigators/PresentOnboardingCodeNavigator.swift b/Sources/XXNavigation/Onboarding/PresentOnboardingCode.swift
similarity index 66%
rename from Sources/XXNavigation/Navigators/PresentOnboardingCodeNavigator.swift
rename to Sources/XXNavigation/Onboarding/PresentOnboardingCode.swift
index 359dc109c0988272e2f12fda44e00b995249873e..be83f0d1ca3df6fe2ef25d8163968ab30be6491f 100644
--- a/Sources/XXNavigation/Navigators/PresentOnboardingCodeNavigator.swift
+++ b/Sources/XXNavigation/Onboarding/PresentOnboardingCode.swift
@@ -2,6 +2,25 @@ import UIKit
 import Navigation
 import DependencyInjection
 
+public struct PresentOnboardingCode: Navigation.Action {
+  public var isEmail: Bool
+  public var content: String
+  public var confirmationId: String
+  public var animated: Bool
+
+  public init(
+    isEmail: Bool,
+    content: String,
+    confirmationId: String,
+    animated: Bool = true
+  ) {
+    self.isEmail = isEmail
+    self.content = content
+    self.confirmationId = confirmationId
+    self.animated = animated
+  }
+}
+
 public struct PresentOnboardingCodeNavigator: TypedNavigator {
   @Dependency var navigator: Navigator
   var screen: (Bool, String, String) -> UIViewController
diff --git a/Sources/XXNavigation/Navigators/PresentOnboardingEmailNavigator.swift b/Sources/XXNavigation/Onboarding/PresentOnboardingEmail.swift
similarity index 81%
rename from Sources/XXNavigation/Navigators/PresentOnboardingEmailNavigator.swift
rename to Sources/XXNavigation/Onboarding/PresentOnboardingEmail.swift
index 190941d857a7e8e917793cc8ebbd3e8f43fbb7eb..4d8905ad69e2558837b07f4fe6846939ede3a482 100644
--- a/Sources/XXNavigation/Navigators/PresentOnboardingEmailNavigator.swift
+++ b/Sources/XXNavigation/Onboarding/PresentOnboardingEmail.swift
@@ -2,6 +2,14 @@ import UIKit
 import Navigation
 import DependencyInjection
 
+public struct PresentOnboardingEmail: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
 public struct PresentOnboardingEmailNavigator: TypedNavigator {
   @Dependency var navigator: Navigator
   var screen: () -> UIViewController
diff --git a/Sources/XXNavigation/Navigators/PresentOnboardingPhoneNavigator.swift b/Sources/XXNavigation/Onboarding/PresentOnboardingPhone.swift
similarity index 81%
rename from Sources/XXNavigation/Navigators/PresentOnboardingPhoneNavigator.swift
rename to Sources/XXNavigation/Onboarding/PresentOnboardingPhone.swift
index 674a2ad3fcf41f635a749838a95a2cc76ef42b09..e890add38eaafc9c4dcf9711dfd866f2204ea71f 100644
--- a/Sources/XXNavigation/Navigators/PresentOnboardingPhoneNavigator.swift
+++ b/Sources/XXNavigation/Onboarding/PresentOnboardingPhone.swift
@@ -2,6 +2,14 @@ import UIKit
 import Navigation
 import DependencyInjection
 
+public struct PresentOnboardingPhone: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
 public struct PresentOnboardingPhoneNavigator: TypedNavigator {
   @Dependency var navigator: Navigator
   var screen: () -> UIViewController
diff --git a/Sources/XXNavigation/Navigators/PresentOnboardingStartNavigator.swift b/Sources/XXNavigation/Onboarding/PresentOnboardingStart.swift
similarity index 81%
rename from Sources/XXNavigation/Navigators/PresentOnboardingStartNavigator.swift
rename to Sources/XXNavigation/Onboarding/PresentOnboardingStart.swift
index 050b67906daa1308a768f170d681006a580a0e55..c7dfbc31d05f6b9420f652ef5af43b2cb566f990 100644
--- a/Sources/XXNavigation/Navigators/PresentOnboardingStartNavigator.swift
+++ b/Sources/XXNavigation/Onboarding/PresentOnboardingStart.swift
@@ -2,6 +2,14 @@ import UIKit
 import Navigation
 import DependencyInjection
 
+public struct PresentOnboardingStart: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
 public struct PresentOnboardingStartNavigator: TypedNavigator {
   @Dependency var navigator: Navigator
   var screen: () -> UIViewController
diff --git a/Sources/XXNavigation/Navigators/PresentOnboardingUsernameNavigator.swift b/Sources/XXNavigation/Onboarding/PresentOnboardingUsername.swift
similarity index 81%
rename from Sources/XXNavigation/Navigators/PresentOnboardingUsernameNavigator.swift
rename to Sources/XXNavigation/Onboarding/PresentOnboardingUsername.swift
index 964ee10098af06d6c43daf2ad38916dc0727bc3d..48fa7be535ea610b787e79c79187d613fa548870 100644
--- a/Sources/XXNavigation/Navigators/PresentOnboardingUsernameNavigator.swift
+++ b/Sources/XXNavigation/Onboarding/PresentOnboardingUsername.swift
@@ -2,6 +2,14 @@ import UIKit
 import Navigation
 import DependencyInjection
 
+public struct PresentOnboardingUsername: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
 public struct PresentOnboardingUsernameNavigator: TypedNavigator {
   @Dependency var navigator: Navigator
   var screen: () -> UIViewController
diff --git a/Sources/XXNavigation/Navigators/PresentOnboardingWelcomeNavigator.swift b/Sources/XXNavigation/Onboarding/PresentOnboardingWelcome.swift
similarity index 81%
rename from Sources/XXNavigation/Navigators/PresentOnboardingWelcomeNavigator.swift
rename to Sources/XXNavigation/Onboarding/PresentOnboardingWelcome.swift
index e5fc1ed453a2da56e468e21a09aab68e5691ddea..7a55f0e60e8cd742e2f68f02eaa2ccbb36222ea3 100644
--- a/Sources/XXNavigation/Navigators/PresentOnboardingWelcomeNavigator.swift
+++ b/Sources/XXNavigation/Onboarding/PresentOnboardingWelcome.swift
@@ -2,6 +2,14 @@ import UIKit
 import Navigation
 import DependencyInjection
 
+public struct PresentOnboardingWelcome: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
 public struct PresentOnboardingWelcomeNavigator: TypedNavigator {
   @Dependency var navigator: Navigator
   var screen: () -> UIViewController
diff --git a/Sources/XXNavigation/Navigators/PresentTermsAndConditionsNavigator.swift b/Sources/XXNavigation/Onboarding/PresentTermsAndConditions.swift
similarity index 76%
rename from Sources/XXNavigation/Navigators/PresentTermsAndConditionsNavigator.swift
rename to Sources/XXNavigation/Onboarding/PresentTermsAndConditions.swift
index 61ad413e57ea6a92a3e2712a8909e0bd7af217a1..a71b7f79c5e684168acfb26cbb7b09a3c5e89dfc 100644
--- a/Sources/XXNavigation/Navigators/PresentTermsAndConditionsNavigator.swift
+++ b/Sources/XXNavigation/Onboarding/PresentTermsAndConditions.swift
@@ -2,6 +2,19 @@ import UIKit
 import Navigation
 import DependencyInjection
 
+public struct PresentTermsAndConditions: Navigation.Action {
+  public var popAllowed: Bool
+  public var animated: Bool
+
+  public init(
+    popAllowed: Bool = true,
+    animated: Bool = true
+  ) {
+    self.popAllowed = popAllowed
+    self.animated = animated
+  }
+}
+
 public struct PresentTermsAndConditionsNavigator: TypedNavigator {
   @Dependency var navigator: Navigator
   var screen: () -> UIViewController
diff --git a/Sources/XXNavigation/PresentActivitySheet.swift b/Sources/XXNavigation/PresentActivitySheet.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c13c1faa5de1ba12b30971bc813d4763788d47f3
--- /dev/null
+++ b/Sources/XXNavigation/PresentActivitySheet.swift
@@ -0,0 +1,42 @@
+import UIKit
+import XXModels
+import Navigation
+import DependencyInjection
+
+public struct PresentActivitySheet: Navigation.Action {
+  public var items: [Any]
+  public var animated: Bool
+
+  public init(
+    items: [Any],
+    animated: Bool = true
+  ) {
+    self.items = items
+    self.animated = animated
+  }
+}
+
+public struct PresentActivitySheetNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: ([Any]) -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentActivitySheet, completion: @escaping () -> Void) {
+    if let topViewController = navigationController().topViewController {
+      let modalAction = PresentModal(
+        screen(action.items),
+        from: topViewController,
+        animated: action.animated
+      )
+      navigator.perform(modalAction, completion: completion)
+    }
+  }
+
+  public init(
+    screen: @escaping ([Any]) -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/PresentCountryList.swift b/Sources/XXNavigation/PresentCountryList.swift
new file mode 100644
index 0000000000000000000000000000000000000000..2a8504ea9ff15e3b6ff190fb3efb3de0c1aa27fe
--- /dev/null
+++ b/Sources/XXNavigation/PresentCountryList.swift
@@ -0,0 +1,38 @@
+import UIKit
+import Shared
+import Navigation
+import DependencyInjection
+
+public struct PresentCountryList: Navigation.Action {
+  public var completion: ((Country) -> Void)
+  public var animated: Bool
+
+  public init(
+    completion: @escaping (Country) -> Void,
+    animated: Bool = true
+  ) {
+    self.animated = animated
+    self.completion = completion
+  }
+}
+
+public struct PresentCountryListNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: (@escaping (Country) -> Void) -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentCountryList, completion: @escaping () -> Void) {
+    if let topViewController = navigationController().topViewController {
+      let modalAction = PresentModal(screen(action.completion), from: topViewController)
+      navigator.perform(modalAction, completion: completion)
+    }
+  }
+
+  public init(
+    screen: @escaping (@escaping (Country) -> Void) -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentDrawerNavigator.swift b/Sources/XXNavigation/PresentDrawer.swift
similarity index 73%
rename from Sources/XXNavigation/Navigators/PresentDrawerNavigator.swift
rename to Sources/XXNavigation/PresentDrawer.swift
index aec7278800720dbb2471ac9786f09b465d50adde..fe5812eb93eccdd45d079d737a4348d6b8004259 100644
--- a/Sources/XXNavigation/Navigators/PresentDrawerNavigator.swift
+++ b/Sources/XXNavigation/PresentDrawer.swift
@@ -3,6 +3,22 @@ import Navigation
 import DrawerFeature
 import DependencyInjection
 
+public struct PresentDrawer: Navigation.Action {
+  public var items: [DrawerItem]
+  public var dismissable: Bool
+  public var animated: Bool
+
+  public init(
+    items: [DrawerItem],
+    dismissable: Bool = true,
+    animated: Bool = true
+  ) {
+    self.items = items
+    self.dismissable = dismissable
+    self.animated = animated
+  }
+}
+
 public struct PresentDrawerNavigator: TypedNavigator {
   @Dependency var navigator: Navigator
   var screen: ([DrawerItem]) -> UIViewController
diff --git a/Sources/XXNavigation/PresentMenu.swift b/Sources/XXNavigation/PresentMenu.swift
new file mode 100644
index 0000000000000000000000000000000000000000..129766250c3e00a28a7c34e32cdd2d20c9506775
--- /dev/null
+++ b/Sources/XXNavigation/PresentMenu.swift
@@ -0,0 +1,42 @@
+import UIKit
+import Shared
+import Navigation
+import DependencyInjection
+
+public struct PresentMenu: Navigation.Action {
+  public var currentItem: MenuItem
+  public var animated: Bool
+
+  public init(
+    currentItem: MenuItem,
+    animated: Bool = true
+  ) {
+    self.currentItem = currentItem
+    self.animated = animated
+  }
+}
+
+public struct PresentMenuNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var navigationController: () -> UINavigationController
+  var screen: (MenuItem) -> UIViewController
+
+  public func perform(_ action: PresentMenu, completion: @escaping () -> Void) {
+    if let topViewController = navigationController().topViewController {
+      let openLeftAction = OpenLeft(
+        screen(action.currentItem),
+        from: topViewController,
+        animated: action.animated
+      )
+      navigator.perform(openLeftAction, completion: completion)
+    }
+  }
+
+  public init(
+    screen: @escaping (MenuItem) -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/PresentPermissionRequest.swift b/Sources/XXNavigation/PresentPermissionRequest.swift
new file mode 100644
index 0000000000000000000000000000000000000000..f8d5e5e1d9140441a60fbb56d1dd83c79bd89136
--- /dev/null
+++ b/Sources/XXNavigation/PresentPermissionRequest.swift
@@ -0,0 +1,38 @@
+import UIKit
+import Shared
+import Navigation
+import DependencyInjection
+
+public struct PresentPermissionRequest: Navigation.Action {
+  public var type: PermissionType
+  public var animated: Bool
+
+  public init(
+    type: PermissionType,
+    animated: Bool = true
+  ) {
+    self.type = type
+    self.animated = animated
+  }
+}
+
+public struct PresentPermissionRequestNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: (PermissionType) -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentPermissionRequest, completion: @escaping () -> Void) {
+    if let topViewController = navigationController().topViewController {
+      let modalAction = PresentModal(screen(action.type), from: topViewController)
+      navigator.perform(modalAction, completion: completion)
+    }
+  }
+
+  public init(
+    screen: @escaping (PermissionType) -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/PresentPhotoLibrary.swift b/Sources/XXNavigation/PresentPhotoLibrary.swift
new file mode 100644
index 0000000000000000000000000000000000000000..d0170d0adb561c33c4fc7b2da742d4bcd1bee08c
--- /dev/null
+++ b/Sources/XXNavigation/PresentPhotoLibrary.swift
@@ -0,0 +1,34 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentPhotoLibrary: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
+public struct PresentPhotoLibraryNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIImagePickerController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentPhotoLibrary, completion: @escaping () -> Void) {
+    if let topViewController = navigationController().topViewController {
+      let imagePicker = screen()
+      imagePicker.delegate = topViewController as? UIImagePickerControllerDelegate & UINavigationControllerDelegate
+      let modalAction = PresentModal(imagePicker, from: topViewController)
+      navigator.perform(modalAction, completion: completion)
+    }
+  }
+
+  public init(
+    screen: @escaping () -> UIImagePickerController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/PresentScan.swift b/Sources/XXNavigation/PresentScan.swift
new file mode 100644
index 0000000000000000000000000000000000000000..def9482eca5a8f289357da8c60e2dd406347382a
--- /dev/null
+++ b/Sources/XXNavigation/PresentScan.swift
@@ -0,0 +1,30 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentScan: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
+public struct PresentScanNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentScan, completion: @escaping () -> Void) {
+    let setStackAction = SetStack([screen()], on: navigationController(), animated: action.animated)
+    navigator.perform(setStackAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/PresentSearch.swift b/Sources/XXNavigation/PresentSearch.swift
new file mode 100644
index 0000000000000000000000000000000000000000..d62a767b1691e25ee912e9c7144ad8442971f4f8
--- /dev/null
+++ b/Sources/XXNavigation/PresentSearch.swift
@@ -0,0 +1,43 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentSearch: Navigation.Action {
+  public var searching: String?
+  public var replacing: Bool
+  public var animated: Bool
+
+  public init(
+    searching: String? = nil,
+    replacing: Bool = true,
+    animated: Bool = true
+  ) {
+    self.searching = searching
+    self.replacing = replacing
+    self.animated = animated
+  }
+}
+
+public struct PresentSearchNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: (String?) -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentSearch, completion: @escaping () -> Void) {
+    let navAction: Action
+    if action.replacing {
+      navAction = SetStack([screen(action.searching)], on: navigationController(), animated: action.animated)
+    } else {
+      navAction = Push(screen(action.searching), on: navigationController(), animated: action.animated)
+    }
+    navigator.perform(navAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping (String?) -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Profile/PresentProfile.swift b/Sources/XXNavigation/Profile/PresentProfile.swift
new file mode 100644
index 0000000000000000000000000000000000000000..4eb70e97538ff6191ae960ac15c510d8452033fe
--- /dev/null
+++ b/Sources/XXNavigation/Profile/PresentProfile.swift
@@ -0,0 +1,30 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentProfile: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
+public struct PresentProfileNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentProfile, completion: @escaping () -> Void) {
+    let setStackAction = SetStack([screen()], on: navigationController(), animated: action.animated)
+    navigator.perform(setStackAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Profile/PresentProfileCode.swift b/Sources/XXNavigation/Profile/PresentProfileCode.swift
new file mode 100644
index 0000000000000000000000000000000000000000..887c88b01799ef9096ad1baba3cc49a3218089a8
--- /dev/null
+++ b/Sources/XXNavigation/Profile/PresentProfileCode.swift
@@ -0,0 +1,42 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentProfileCode: Navigation.Action {
+  public var isEmail: Bool
+  public var content: String
+  public var confirmationId: String
+  public var animated: Bool
+
+  public init(
+    isEmail: Bool,
+    content: String,
+    confirmationId: String,
+    animated: Bool = true
+  ) {
+    self.isEmail = isEmail
+    self.content = content
+    self.confirmationId = confirmationId
+    self.animated = animated
+  }
+}
+
+public struct PresentProfileCodeNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: (Bool, String, String) -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentProfileCode, completion: @escaping () -> Void) {
+    let controller = screen(action.isEmail, action.content, action.confirmationId)
+    let pushAction = Push(controller, on: navigationController(), animated: action.animated)
+    navigator.perform(pushAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping (Bool, String, String) -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Profile/PresentProfileEmail.swift b/Sources/XXNavigation/Profile/PresentProfileEmail.swift
new file mode 100644
index 0000000000000000000000000000000000000000..0a150af86056c094f62295b08cc3f6d19bd2049a
--- /dev/null
+++ b/Sources/XXNavigation/Profile/PresentProfileEmail.swift
@@ -0,0 +1,30 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentProfileEmail: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
+public struct PresentProfileEmailNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentProfileEmail, completion: @escaping () -> Void) {
+    let pushAction = Push(screen(), on: navigationController(), animated: action.animated)
+    navigator.perform(pushAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Profile/PresentProfilePhone.swift b/Sources/XXNavigation/Profile/PresentProfilePhone.swift
new file mode 100644
index 0000000000000000000000000000000000000000..37966c9d959f96ace1e880f49b94edf25b7dea2b
--- /dev/null
+++ b/Sources/XXNavigation/Profile/PresentProfilePhone.swift
@@ -0,0 +1,30 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentProfilePhone: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
+public struct PresentProfilePhoneNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentProfilePhone, completion: @escaping () -> Void) {
+    let pushAction = Push(screen(), on: navigationController(), animated: action.animated)
+    navigator.perform(pushAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/RestoreAndBackup/PresentPassphrase.swift b/Sources/XXNavigation/RestoreAndBackup/PresentPassphrase.swift
new file mode 100644
index 0000000000000000000000000000000000000000..b566ea3c0baa6c4d2187fa575b56814aa1ae07b4
--- /dev/null
+++ b/Sources/XXNavigation/RestoreAndBackup/PresentPassphrase.swift
@@ -0,0 +1,17 @@
+import Navigation
+
+public struct PresentPassphrase: Navigation.Action {
+  public var onCancel: () -> Void
+  public var onPasspharse: (String) -> Void
+  public var animated: Bool
+
+  public init(
+    onCancel: @escaping () -> Void,
+    onPassphrase: @escaping (String) -> Void,
+    animated: Bool = true
+  ) {
+    self.onCancel = onCancel
+    self.onPasspharse = onPassphrase
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentRequestsNavigator.swift b/Sources/XXNavigation/RestoreAndBackup/PresentRequests.swift
similarity index 82%
rename from Sources/XXNavigation/Navigators/PresentRequestsNavigator.swift
rename to Sources/XXNavigation/RestoreAndBackup/PresentRequests.swift
index c39d439b5e3ef13fb5cc8179b48353b3e14943d6..812da622318e2912155a0c4710cc4d9379356321 100644
--- a/Sources/XXNavigation/Navigators/PresentRequestsNavigator.swift
+++ b/Sources/XXNavigation/RestoreAndBackup/PresentRequests.swift
@@ -2,6 +2,14 @@ import UIKit
 import Navigation
 import DependencyInjection
 
+public struct PresentRequests: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
 public struct PresentRequestsNavigator: TypedNavigator {
   @Dependency var navigator: Navigator
   var screen: () -> UIViewController
diff --git a/Sources/XXNavigation/Navigators/PresentRestoreListNavigator.swift b/Sources/XXNavigation/RestoreAndBackup/PresentRestoreList.swift
similarity index 81%
rename from Sources/XXNavigation/Navigators/PresentRestoreListNavigator.swift
rename to Sources/XXNavigation/RestoreAndBackup/PresentRestoreList.swift
index 0e9a783a9eb3f21b5fb61653208fc740bf952b35..23b40ab0c8418b576b159119fe4cf420b9055a96 100644
--- a/Sources/XXNavigation/Navigators/PresentRestoreListNavigator.swift
+++ b/Sources/XXNavigation/RestoreAndBackup/PresentRestoreList.swift
@@ -2,6 +2,14 @@ import UIKit
 import Navigation
 import DependencyInjection
 
+public struct PresentRestoreList: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
 public struct PresentRestoreListNavigator: TypedNavigator {
   @Dependency var navigator: Navigator
   var screen: () -> UIViewController
diff --git a/Sources/XXNavigation/RestoreAndBackup/PresentSFTP.swift b/Sources/XXNavigation/RestoreAndBackup/PresentSFTP.swift
new file mode 100644
index 0000000000000000000000000000000000000000..d19e06c5a2ce5213042c426a091b1e1e71aa3c32
--- /dev/null
+++ b/Sources/XXNavigation/RestoreAndBackup/PresentSFTP.swift
@@ -0,0 +1,14 @@
+import Navigation
+
+public struct PresentSFTP: Navigation.Action {
+  public var completion: (String, String, String) -> Void
+  public var animated: Bool
+
+  public init(
+    completion: @escaping (String, String, String) -> Void,
+    animated: Bool = true
+  ) {
+    self.completion = completion
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Settings/PresentSettings.swift b/Sources/XXNavigation/Settings/PresentSettings.swift
new file mode 100644
index 0000000000000000000000000000000000000000..932a18686f3b5e0781d43c0ecedebac18228f21d
--- /dev/null
+++ b/Sources/XXNavigation/Settings/PresentSettings.swift
@@ -0,0 +1,30 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentSettings: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
+public struct PresentSettingsNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentSettings, completion: @escaping () -> Void) {
+    let setStackAction = SetStack([screen()], on: navigationController(), animated: action.animated)
+    navigator.perform(setStackAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Settings/PresentSettingsAccountDelete.swift b/Sources/XXNavigation/Settings/PresentSettingsAccountDelete.swift
new file mode 100644
index 0000000000000000000000000000000000000000..74119fe226140a447f5b574e21de1e0682a96a5f
--- /dev/null
+++ b/Sources/XXNavigation/Settings/PresentSettingsAccountDelete.swift
@@ -0,0 +1,30 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentSettingsAccountDelete: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
+public struct PresentSettingsAccountDeleteNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentSettingsAccountDelete, completion: @escaping () -> Void) {
+    let pushAction = Push(screen(), on: navigationController(), animated: action.animated)
+    navigator.perform(pushAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Settings/PresentSettingsAdvanced.swift b/Sources/XXNavigation/Settings/PresentSettingsAdvanced.swift
new file mode 100644
index 0000000000000000000000000000000000000000..fd258eba0acd68622cb438dc5842645abf7c80b1
--- /dev/null
+++ b/Sources/XXNavigation/Settings/PresentSettingsAdvanced.swift
@@ -0,0 +1,30 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentSettingsAdvanced: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
+public struct PresentSettingsAdvancedNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentSettingsAdvanced, completion: @escaping () -> Void) {
+    let pushAction = Push(screen(), on: navigationController(), animated: action.animated)
+    navigator.perform(pushAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Settings/PresentSettingsBackup.swift b/Sources/XXNavigation/Settings/PresentSettingsBackup.swift
new file mode 100644
index 0000000000000000000000000000000000000000..62a6e243e5a6936954b53925a0e1ed144d9eaf09
--- /dev/null
+++ b/Sources/XXNavigation/Settings/PresentSettingsBackup.swift
@@ -0,0 +1,30 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentSettingsBackup: Navigation.Action {
+  public var animated: Bool
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
+
+public struct PresentSettingsBackupNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentSettingsBackup, completion: @escaping () -> Void) {
+    let pushAction = Push(screen(), on: navigationController(), animated: action.animated)
+    navigator.perform(pushAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Tests/ChatFeatureTests/Coordinator/ChatCoordinatorSpec.swift b/Tests/ChatFeatureTests/Coordinator/ChatCoordinatorSpec.swift
deleted file mode 100644
index afc03f67c8065a3a0e76079b02d9aa161af9d73c..0000000000000000000000000000000000000000
--- a/Tests/ChatFeatureTests/Coordinator/ChatCoordinatorSpec.swift
+++ /dev/null
@@ -1,118 +0,0 @@
-import UIKit
-import Quick
-import Nimble
-import TestHelpers
-
-@testable import ChatFeature
-
-final class ChatCoordinatorSpec: QuickSpec {
-    override func spec() {
-        context("init") {
-            var sut: ChatCoordinator!
-            var pusher: PresenterDouble!
-            var bottomPresenter: PresenterDouble!
-
-            var retryController: UIViewController!
-            var contactController: UIViewController!
-
-            beforeEach {
-                pusher = PresenterDouble()
-                bottomPresenter = PresenterDouble()
-                retryController = UIViewController()
-                contactController = UIViewController()
-
-                sut = ChatCoordinator(
-                    retryFactory: { retryController },
-                    contactFactory: { _ in contactController }
-                )
-
-                sut.pusher = pusher
-                sut.bottomPresenter = bottomPresenter
-            }
-
-            afterEach {
-                sut = nil
-                pusher = nil
-                bottomPresenter = nil
-                retryController = nil
-                contactController = nil
-            }
-
-            context("when presenting retry sheet") {
-                var parent: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    sut.toRetrySheet(from: parent)
-                }
-
-                it("should present RetrySheetController") {
-                    expect(bottomPresenter.didPresentFrom).to(be(parent))
-                    expect(bottomPresenter.didPresentTarget).to(be(retryController))
-                }
-            }
-
-            context("when presenting members list") {
-                var target: UIViewController!
-                var parent: UIViewController!
-
-                beforeEach {
-                    target = UIViewController()
-                    parent = UIViewController()
-                    sut.toMembersList(target, from: parent)
-                }
-
-                it("should present MembersController") {
-                    expect(bottomPresenter.didPresentFrom).to(be(parent))
-                    expect(bottomPresenter.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting Popup") {
-                var target: UIViewController!
-                var parent: UIViewController!
-
-                beforeEach {
-                    target = UIViewController()
-                    parent = UIViewController()
-                    sut.toPopup(target, from: parent)
-                }
-
-                it("should present Popup") {
-                    expect(bottomPresenter.didPresentFrom).to(be(parent))
-                    expect(bottomPresenter.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting Contact") {
-                var parent: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    sut.toContact(.dummy, from: parent)
-                }
-
-                it("should present ContactController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(contactController))
-                }
-            }
-
-            context("when presenting menu sheet") {
-                var target: UIViewController!
-                var parent: UIViewController!
-
-                beforeEach {
-                    target = UIViewController()
-                    parent = UIViewController()
-                    sut.toMenuSheet(target, from: parent)
-                }
-
-                it("should present SheetController") {
-                    expect(bottomPresenter.didPresentFrom).to(be(parent))
-                    expect(bottomPresenter.didPresentTarget).to(be(target))
-                }
-            }
-        }
-    }
-}
diff --git a/Tests/ChatListFeatureTests/Coordinator/ChatListCoordinatorSpec.swift b/Tests/ChatListFeatureTests/Coordinator/ChatListCoordinatorSpec.swift
deleted file mode 100644
index dc4a069cb02759b7d3eda601d20408e7c075a74b..0000000000000000000000000000000000000000
--- a/Tests/ChatListFeatureTests/Coordinator/ChatListCoordinatorSpec.swift
+++ /dev/null
@@ -1,243 +0,0 @@
-import UIKit
-import Quick
-import Nimble
-import MenuFeature
-import TestHelpers
-
-@testable import ChatListFeature
-
-final class ChatListCoordinatorSpec: QuickSpec {
-    override func spec() {
-        context("init") {
-            var sut: ChatListCoordinator!
-            var sider: PresenterDouble!
-            var pusher: PresenterDouble!
-            var bottomPresenter: PresenterDouble!
-
-            var scanScreen: UIViewController!
-            var searchScreen: UIViewController!
-            var profileScreen: UIViewController!
-            var settingsScreen: UIViewController!
-            var contactsScreen: UIViewController!
-            var requestsScreen: UIViewController!
-
-            beforeEach {
-                sider = PresenterDouble()
-                pusher = PresenterDouble()
-                bottomPresenter = PresenterDouble()
-
-                scanScreen = UIViewController()
-                searchScreen = UIViewController()
-                profileScreen = UIViewController()
-                settingsScreen = UIViewController()
-                contactsScreen = UIViewController()
-                requestsScreen = UIViewController()
-
-                sut = ChatListCoordinator(
-                    scanFactory: { scanScreen },
-                    searchFactory: { searchScreen },
-                    profileFactory: { profileScreen },
-                    settingsFactory: { settingsScreen },
-                    contactsFactory: { contactsScreen },
-                    requestsFactory: { requestsScreen }
-                )
-
-                sut.sider = sider
-                sut.pusher = pusher
-                sut.bottomPresenter = bottomPresenter
-            }
-
-            afterEach {
-                sut = nil
-                pusher = nil
-                sider = nil
-                scanScreen = nil
-                searchScreen = nil
-                profileScreen = nil
-                settingsScreen = nil
-                contactsScreen = nil
-                requestsScreen = nil
-                bottomPresenter = nil
-            }
-
-            context("when presenting chat") {
-                var target: UIViewController!
-                var parent: UIViewController!
-
-                beforeEach {
-                    target = UIViewController()
-                    parent = UIViewController()
-                    sut.singleChatFactory = { _ in target }
-                    sut.toSingleChat(with: .dummy, from: parent)
-                }
-
-                it("should present ChatController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting side menu") {
-                var parent: Delegate!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = Delegate()
-                    target = UIViewController()
-                    sut.sideMenuFactory = { _ in target }
-                    sut.toSideMenu(from: parent)
-                }
-
-                it("should present side menu") {
-                    expect(sider.didPresentFrom).to(be(parent))
-                    expect(sider.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting search") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.searchFactory = { target }
-                    sut.toSearch(from: parent)
-                }
-
-                it("should present SearchController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting scan") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.scanFactory = { target }
-                    sut.toScan(from: parent)
-                }
-
-                it("should present ScanController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting profile") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.profileFactory = { target }
-                    sut.toProfile(from: parent)
-                }
-
-                it("should present ProfileController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting contacts") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.contactsFactory = { target }
-                    sut.toContacts(from: parent)
-                }
-
-                it("should present ContactListController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting settings") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.settingsFactory = { target }
-                    sut.toSettings(from: parent)
-                }
-
-                it("should present SettingsController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting group chat") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.groupChatFactory = { _ in target }
-                    sut.toGroupChat(with: .init(
-                        group: .dummy,
-                        members: [],
-                        lastMessage: nil
-                    ), from: parent)
-                }
-
-                it("should present GroupChatController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting popup") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.toPopup(target, from: parent)
-                }
-
-                it("should present Popup") {
-                    expect(bottomPresenter.didPresentFrom).to(be(parent))
-                    expect(bottomPresenter.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting requests") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.requestsFactory = { target }
-                    sut.toRequests(from: parent)
-                }
-
-                it("should present RequestsContainer") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-        }
-    }
-}
-
-// MARK: - Delegate
-
-private final class Delegate: UIViewController, MenuDelegate {
-    func didSelect(item: MenuItem) {}
-}
diff --git a/Tests/ContactFeatureTests/Coordinator/ContactCoordinatorSpec.swift b/Tests/ContactFeatureTests/Coordinator/ContactCoordinatorSpec.swift
deleted file mode 100644
index 1a4026f8fb294636e838d257a33ef40fbf06aca1..0000000000000000000000000000000000000000
--- a/Tests/ContactFeatureTests/Coordinator/ContactCoordinatorSpec.swift
+++ /dev/null
@@ -1,129 +0,0 @@
-import UIKit
-import Quick
-import Nimble
-import ChatFeature
-import TestHelpers
-
-@testable import ContactFeature
-
-final class ContactCoordinatorSpec: QuickSpec {
-    override func spec() {
-        context("init") {
-            var sut: ContactCoordinator!
-            var pusher: PresenterDouble!
-            var replacer: PresenterDouble!
-            var presenter: PresenterDouble!
-            var bottomPresenter: PresenterDouble!
-
-            var requestsScreen: UIViewController!
-
-            beforeEach {
-                pusher = PresenterDouble()
-                replacer = PresenterDouble()
-                presenter = PresenterDouble()
-                requestsScreen = UIViewController()
-                bottomPresenter = PresenterDouble()
-
-                sut = ContactCoordinator(requestsFactory: { requestsScreen })
-
-                sut.pusher = pusher
-                sut.replacer = replacer
-                sut.presenter = presenter
-                sut.bottomPresenter = bottomPresenter
-            }
-
-            afterEach {
-                sut = nil
-                pusher = nil
-                replacer = nil
-                presenter = nil
-                requestsScreen = nil
-                bottomPresenter = nil
-            }
-
-            context("when presenting image picker") {
-                var parent: UIViewController!
-                var target: UIImagePickerController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIImagePickerController()
-                    sut.imagePickerFactory = { target }
-                    sut.toPhotos(from: parent)
-                }
-
-                it("should present UIImagePickerController") {
-                    expect(presenter.didPresentFrom).to(be(parent))
-                    expect(presenter.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting single chat") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.singleChatFactory = { _ in target }
-                    sut.toSingleChat(with: .dummy, from: parent)
-                }
-
-                it("should present ChatController") {
-                    expect(replacer.didPresentFrom).to(be(parent))
-                    expect(replacer.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting nickname") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.nicknameFactory = { _,_ in target }
-                    sut.toNickname(from: parent, prefilled: "", { _ in })
-                }
-
-                it("should present NickameController") {
-                    expect(bottomPresenter.didPresentFrom).to(be(parent))
-                    expect(bottomPresenter.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting requests") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.requestsFactory = { target }
-                    sut.toRequests(from: parent)
-                }
-
-                it("should present RequestsController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting popup") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.toPopup(target, from: parent)
-                }
-
-                it("should present Popup") {
-                    expect(bottomPresenter.didPresentFrom).to(be(parent))
-                    expect(bottomPresenter.didPresentTarget).to(be(target))
-                }
-            }
-        }
-    }
-}
diff --git a/Tests/ContactListFeatureTests/Coordinator/ContactListCoordinatorSpec.swift b/Tests/ContactListFeatureTests/Coordinator/ContactListCoordinatorSpec.swift
deleted file mode 100644
index ce494c1f73b2b8765832d99341f51b37f2fd7676..0000000000000000000000000000000000000000
--- a/Tests/ContactListFeatureTests/Coordinator/ContactListCoordinatorSpec.swift
+++ /dev/null
@@ -1,162 +0,0 @@
-import UIKit
-import Quick
-import Nimble
-import TestHelpers
-
-@testable import ContactListFeature
-
-final class ContactListCoordinatorSpec: QuickSpec {
-    override func spec() {
-        context("init") {
-            var sut: ContactListCoordinator!
-            var pusher: PresenterDouble!
-            var replacer: PresenterDouble!
-            var bottomPresenter: PresenterDouble!
-            var fullscreenPresenter: PresenterDouble!
-
-            var scanScreen: UIViewController!
-            var groupScreen: UIViewController!
-            var searchScreen: UIViewController!
-            var requestsScreen: UIViewController!
-
-            beforeEach {
-                scanScreen = UIViewController()
-                searchScreen = UIViewController()
-
-                sut = ContactListCoordinator(
-                    scanFactory: { scanScreen },
-                    searchFactory: { searchScreen },
-                    newGroupFactory: { groupScreen },
-                    requestsFactory: { requestsScreen }
-                )
-
-                pusher = PresenterDouble()
-                replacer = PresenterDouble()
-                bottomPresenter = PresenterDouble()
-                fullscreenPresenter = PresenterDouble()
-
-                sut.pusher = pusher
-                sut.replacer = replacer
-                sut.bottomPresenter = bottomPresenter
-                sut.fullscreenPresenter = fullscreenPresenter
-            }
-
-            afterEach {
-                sut = nil
-                pusher = nil
-                replacer = nil
-                scanScreen = nil
-                groupScreen = nil
-                searchScreen = nil
-                requestsScreen = nil
-                bottomPresenter = nil
-                fullscreenPresenter = nil
-            }
-
-            context("when presenting contact details") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.contactFactory = { _ in target }
-                    sut.toContact(.dummy, from: parent)
-                }
-
-                it("should present contact details screen") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting SearchScreen") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.searchFactory = { target }
-                    sut.toSearch(from: parent)
-                }
-
-                it("should present SearchScreen") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting scan screen") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.scanFactory = { target }
-                    sut.toScan(from: parent)
-                }
-
-                it("should present qr screen") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting new group") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.newGroupFactory = { target }
-                    sut.toNewGroup(from: parent)
-                }
-
-                it("should present new group") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting group chat") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.groupChatFactory = { _ in target }
-                    sut.toGroupChat(with: .init(
-                        group: .dummy,
-                        members: [],
-                        lastMessage: nil
-                    ), from: parent)
-                }
-
-                it("should present group chat") {
-                    expect(replacer.didPresentFrom).to(be(parent))
-                    expect(replacer.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting group popup") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.groupPopupFactory = { _,_ in target }
-                    sut.toGroupPopup(with: 0, from: parent, { _,_  in })
-                }
-
-                it("should present group popup") {
-                    expect(fullscreenPresenter.didPresentFrom).to(be(parent))
-                }
-            }
-        }
-    }
-}
diff --git a/Tests/OnboardingFeatureTests/Coordinator/OnboardingCoordinatorSpec.swift b/Tests/OnboardingFeatureTests/Coordinator/OnboardingCoordinatorSpec.swift
deleted file mode 100644
index fdf5e58c4ca17d0ec192af873f89383b86d3d44d..0000000000000000000000000000000000000000
--- a/Tests/OnboardingFeatureTests/Coordinator/OnboardingCoordinatorSpec.swift
+++ /dev/null
@@ -1,244 +0,0 @@
-import UIKit
-import Quick
-import Nimble
-import Combine
-import TestHelpers
-import DependencyInjection
-
-@testable import OnboardingFeature
-
-final class OnboardingCoordinatorSpec: QuickSpec {
-    override func spec() {
-        context("init") {
-            var sut: OnboardingCoordinator!
-            var pusher: PresenterDouble!
-            var replacer: PresenterDouble!
-            var bottomPresenter: PresenterDouble!
-            var chatsController: UIViewController!
-
-            beforeEach {
-                pusher = PresenterDouble()
-                replacer = PresenterDouble()
-                bottomPresenter = PresenterDouble()
-
-                chatsController = UIViewController()
-
-                DependencyInjection.Container.shared
-                    .register(StatusBarControllerDouble() as StatusBarStyleControlling)
-
-                sut = OnboardingCoordinator(chatListFactory: { chatsController })
-
-                sut.pusher = pusher
-                sut.replacer = replacer
-                sut.bottomPresenter = bottomPresenter
-            }
-
-            afterEach {
-                sut = nil
-                pusher = nil
-                replacer = nil
-                bottomPresenter = nil
-                chatsController = nil
-            }
-
-            context("when presenting success") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.successFactory = { _ in target }
-                    sut.toSuccess(isEmail: false, from: parent)
-                }
-
-                it("should present OnboardingSuccessController") {
-                    expect(replacer.didPresentFrom).to(be(parent))
-                    expect(replacer.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting username") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.usernameFactory = { _ in target }
-                    sut.toUsername(with: "", from: parent)
-                }
-
-                it("should present OnboardingUsernameController") {
-                    expect(replacer.didPresentFrom).to(be(parent))
-                    expect(replacer.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting chats") {
-                var parent: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    sut.toChats(from: parent)
-                }
-
-                it("should present ChatsController") {
-                    expect(replacer.didPresentFrom).to(be(parent))
-                    expect(replacer.didPresentTarget).to(be(chatsController))
-                }
-            }
-
-            context("when presenting email") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.emailFactory = { target }
-                    sut.toEmail(from: parent)
-                }
-
-                it("should present OnboardingEmailController") {
-                    expect(replacer.didPresentFrom).to(be(parent))
-                    expect(replacer.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting phone") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.phoneFactory = { target }
-                    sut.toPhone(from: parent)
-                }
-
-                it("should present OnboardingPhoneController") {
-                    expect(replacer.didPresentFrom).to(be(parent))
-                    expect(replacer.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting countries") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.countriesFactory = { _ in target }
-                    sut.toCountries(from: parent, { _ in })
-                }
-
-                it("should present CountriesController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting popup") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.toPopup(target, from: parent)
-                }
-
-                it("should present Popup") {
-                    expect(bottomPresenter.didPresentFrom).to(be(parent))
-                    expect(bottomPresenter.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting welcome") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.welcomeFactory = { target }
-                    sut.toWelcome(from: parent)
-                }
-
-                it("should present OnboardingWelcomeScreen") {
-                    expect(replacer.didPresentFrom).to(be(parent))
-                    expect(replacer.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting start") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.startFactory = { _ in target }
-                    sut.toStart(with: "ndf", from: parent)
-                }
-
-                it("should present OnboardingStartScreen") {
-                    expect(replacer.didPresentFrom).to(be(parent))
-                    expect(replacer.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting email confirmation") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.emailConfirmationFactory = { _,_ in target }
-                    sut.toEmailConfirmation(with: .init(content: ""), from: parent, completion: { _ in })
-                }
-
-                it("should present OnboardingEmailConfirmationScreen") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting phone confirmation") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.phoneConfirmationFactory = { _,_ in target }
-                    sut.toPhoneConfirmation(with: .init(content: ""), from: parent, completion: { _ in })
-                }
-
-                it("should present OnboardingPhoneConfirmationScreen") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-        }
-    }
-}
-
-// MARK: - StatusBarControllerDouble
-
-private final class StatusBarControllerDouble: StatusBarStyleControlling {
-    var didSetStyle: UIStatusBarStyle?
-
-    let style = CurrentValueSubject<UIStatusBarStyle, Never>(.lightContent)
-    var cancellables = Set<AnyCancellable>()
-
-    init() {
-        style
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in didSetStyle = $0 }
-            .store(in: &cancellables)
-    }
-}
diff --git a/Tests/ProfileFeatureTests/Coordinator/ProfileCoordinatorSpec.swift b/Tests/ProfileFeatureTests/Coordinator/ProfileCoordinatorSpec.swift
deleted file mode 100644
index 1352033a3a098ffcb773820ff2c4f7cd1defb0e0..0000000000000000000000000000000000000000
--- a/Tests/ProfileFeatureTests/Coordinator/ProfileCoordinatorSpec.swift
+++ /dev/null
@@ -1,140 +0,0 @@
-import UIKit
-import Quick
-import Nimble
-import TestHelpers
-
-@testable import ProfileFeature
-
-final class ProfileCoordinatorSpec: QuickSpec {
-    override func spec() {
-        context("init") {
-            var sut: ProfileCoordinator!
-            var pusher: PresenterDouble!
-            var presenter: PresenterDouble!
-            var bottomPresenter: PresenterDouble!
-
-            beforeEach {
-                sut = ProfileCoordinator()
-                pusher = PresenterDouble()
-                presenter = PresenterDouble()
-                bottomPresenter = PresenterDouble()
-
-                sut.pusher = pusher
-                sut.presenter = presenter
-                sut.bottomPresenter = bottomPresenter
-            }
-
-            afterEach {
-                sut = nil
-                pusher = nil
-                presenter = nil
-                bottomPresenter = nil
-            }
-
-            context("when presenting image picker") {
-                var parent: UIViewController!
-                var target: UIImagePickerController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIImagePickerController()
-                    sut.imagePickerFactory = { target }
-                    sut.toPhotos(from: parent)
-                }
-
-                it("should present UIImagePickerController") {
-                    expect(presenter.didPresentFrom).to(be(parent))
-                    expect(presenter.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting email") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.emailFactory = { target }
-                    sut.toEmail(from: parent)
-                }
-
-                it("should present ProfileEmailController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting phone") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.phoneFactory = { target }
-                    sut.toPhone(from: parent)
-                }
-
-                it("should present ProfilePhoneController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting popup") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.toPopup(target, from: parent)
-                }
-
-                it("should present Popup") {
-                    expect(bottomPresenter.didPresentFrom).to(be(parent))
-                    expect(bottomPresenter.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting countries") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.countriesFactory = { _ in target }
-                    sut.toCountries(from: parent, { _ in })
-                }
-
-                it("should present CountriesController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting code") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.codeFactory = { _,_ in target }
-
-                    sut.toCode(
-                        with: .init(content: ""),
-                        from: parent
-                    ) { _,_ in }
-                }
-
-                it("should present CodeController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-        }
-    }
-}
diff --git a/Tests/RequestsFeatureTests/Coordinator/RequestsCoordinatorSpec.swift b/Tests/RequestsFeatureTests/Coordinator/RequestsCoordinatorSpec.swift
deleted file mode 100644
index d27a5c47a5c30c6274e9206597058f32f37d4bf4..0000000000000000000000000000000000000000
--- a/Tests/RequestsFeatureTests/Coordinator/RequestsCoordinatorSpec.swift
+++ /dev/null
@@ -1,100 +0,0 @@
-import Quick
-import UIKit
-import Nimble
-import TestHelpers
-
-@testable import RequestsFeature
-
-final class RequestsCoordinatorSpec: QuickSpec {
-    override func spec() {
-        context("init") {
-            var sut: RequestsCoordinator!
-            var pusher: PresenterDouble!
-            var bottomPresenter: PresenterDouble!
-            var searchController: UIViewController!
-
-            beforeEach {
-                pusher = PresenterDouble()
-                bottomPresenter = PresenterDouble()
-                searchController = UIViewController()
-
-                sut = RequestsCoordinator(searchFactory: { searchController })
-
-                sut.pusher = pusher
-                sut.bottomPresenter = bottomPresenter
-            }
-
-            afterEach {
-                sut = nil
-                pusher = nil
-                bottomPresenter = nil
-                searchController = nil
-            }
-
-            context("when presenting search") {
-                var parent: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    sut.toSearch(from: parent)
-                }
-
-                it("should present SearchController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(searchController))
-                }
-            }
-
-            context("when presenting contact") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.contactFactory = { _ in target }
-                    sut.toContact(.dummy, from: parent)
-                }
-
-                it("should present ContactController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting VerifyingFactory") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.verifyingFactory = { target }
-                    sut.toVerifying(from: parent)
-                }
-
-                it("should present VerifyingScreen") {
-                    expect(bottomPresenter.didPresentFrom).to(be(parent))
-                    expect(bottomPresenter.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting nickname") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.nicknameFactory = { _,_ in target }
-                    sut.toNickname(from: parent, prefilled: "", { _ in })
-                }
-
-                it("should present NicknameController") {
-                    expect(bottomPresenter.didPresentFrom).to(be(parent))
-                    expect(bottomPresenter.didPresentTarget).to(be(target))
-                }
-            }
-        }
-    }
-}
diff --git a/Tests/ScanFeatureTests/Coordinator/ScanCoordinatorSpec.swift b/Tests/ScanFeatureTests/Coordinator/ScanCoordinatorSpec.swift
deleted file mode 100644
index 1d35eb46404cda5ea0de8c9f4328143b48a1a841..0000000000000000000000000000000000000000
--- a/Tests/ScanFeatureTests/Coordinator/ScanCoordinatorSpec.swift
+++ /dev/null
@@ -1,87 +0,0 @@
-import UIKit
-import Quick
-import Nimble
-import TestHelpers
-
-@testable import ScanFeature
-
-final class ScanCoordinatorSpec: QuickSpec {
-    override func spec() {
-        context("init") {
-            var sut: ScanCoordinator!
-            var pusher: PresenterDouble!
-            var replacer: PresenterDouble!
-
-            var contactsController: UIViewController!
-            var requestsController: UIViewController!
-
-            beforeEach {
-                pusher = PresenterDouble()
-                replacer = PresenterDouble()
-                contactsController = UIViewController()
-                requestsController = UIViewController()
-
-                sut = ScanCoordinator(
-                    contactsFactory: { contactsController },
-                    requestsFactory: { requestsController }
-                )
-
-                sut.pusher = pusher
-                sut.replacer = replacer
-            }
-
-            afterEach {
-                sut = nil
-                pusher = nil
-                replacer = nil
-                contactsController = nil
-                requestsController = nil
-            }
-
-            context("when presenting add") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.contactFactory = { _ in target }
-                    sut.toContact(.dummy, from: parent)
-                }
-
-                it("should present ContactController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting contacts") {
-                var parent: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    sut.toContacts(from: parent)
-                }
-
-                it("should present ContactListController") {
-                    expect(replacer.didPresentFrom).to(be(parent))
-                    expect(replacer.didPresentTarget).to(be(contactsController))
-                }
-            }
-
-            context("when presenting requests") {
-                var parent: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    sut.toRequests(from: parent)
-                }
-
-                it("should present RequestsController") {
-                    expect(replacer.didPresentFrom).to(be(parent))
-                    expect(replacer.didPresentTarget).to(be(requestsController))
-                }
-            }
-        }
-    }
-}
diff --git a/Tests/SearchFeatureTests/Coordinator/SearchCoordinatorSpec.swift b/Tests/SearchFeatureTests/Coordinator/SearchCoordinatorSpec.swift
deleted file mode 100644
index cb8056fc51c485738266260cbb0b8a6a7c08036a..0000000000000000000000000000000000000000
--- a/Tests/SearchFeatureTests/Coordinator/SearchCoordinatorSpec.swift
+++ /dev/null
@@ -1,80 +0,0 @@
-import UIKit
-import Quick
-import Nimble
-import TestHelpers
-
-@testable import SearchFeature
-
-final class SearchCoordinatorSpec: QuickSpec {
-    override func spec() {
-        context("init") {
-            var sut: SearchCoordinator!
-            var pusher: PresenterDouble!
-            var bottomPresenter: PresenterDouble!
-
-            beforeEach {
-                sut = SearchCoordinator()
-                pusher = PresenterDouble()
-                bottomPresenter = PresenterDouble()
-                sut.pusher = pusher
-                sut.bottomPresenter = bottomPresenter
-            }
-
-            afterEach {
-                sut = nil
-                pusher = nil
-                bottomPresenter = nil
-            }
-
-            context("when presenting add screen") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.contactFactory = { _ in target }
-                    sut.toContact(.dummy, from: parent)
-                }
-
-                it("should present AddScreen") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting popup") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.toPopup(target, from: parent)
-                }
-
-                it("should present Popup") {
-                    expect(bottomPresenter.didPresentFrom).to(be(parent))
-                    expect(bottomPresenter.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting countries") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.countriesFactory = { _ in target }
-                    sut.toCountries(from: parent, { _ in })
-                }
-
-                it("should present CountriesController") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-        }
-    }
-}
diff --git a/Tests/SettingsFeatureTests/Coordinator/SettingsCoordinatorSpec.swift b/Tests/SettingsFeatureTests/Coordinator/SettingsCoordinatorSpec.swift
deleted file mode 100644
index 610e7b9b3eeb85b4bbb3db5c2274efbf0a6d3edf..0000000000000000000000000000000000000000
--- a/Tests/SettingsFeatureTests/Coordinator/SettingsCoordinatorSpec.swift
+++ /dev/null
@@ -1,79 +0,0 @@
-import UIKit
-import Quick
-import Nimble
-import TestHelpers
-
-@testable import SettingsFeature
-
-final class SettingsCoordinatorSpec: QuickSpec {
-    override func spec() {
-        context("init") {
-            var sut: SettingsCoordinator!
-            var pusher: PresenterDouble!
-            var presenter: PresenterDouble!
-            var bottomPresenter: PresenterDouble!
-
-            beforeEach {
-                pusher = PresenterDouble()
-                presenter = PresenterDouble()
-                bottomPresenter = PresenterDouble()
-
-                sut = SettingsCoordinator()
-
-                sut.pusher = pusher
-                sut.presenter = presenter
-                sut.bottomPresenter = bottomPresenter
-            }
-
-            context("when presenting advanced settings") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.advancedFactory = { target }
-                    sut.toAdvanced(from: parent)
-                }
-
-                it("should present AdvancedScreen") {
-                    expect(pusher.didPresentFrom).to(be(parent))
-                    expect(pusher.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting Popup") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.toPopup(target, from: parent)
-                }
-
-                it("should present Popup") {
-                    expect(bottomPresenter.didPresentFrom).to(be(parent))
-                    expect(bottomPresenter.didPresentTarget).to(be(target))
-                }
-            }
-
-            context("when presenting ActivityViewController") {
-                var parent: UIViewController!
-                var target: UIViewController!
-
-                beforeEach {
-                    parent = UIViewController()
-                    target = UIViewController()
-                    sut.activityControllerFactory = { _ in target }
-                    sut.toActivityController(with: [0], from: parent)
-                }
-
-                it("should present ActivityViewController") {
-                    expect(presenter.didPresentFrom).to(be(parent))
-                    expect(presenter.didPresentTarget).to(be(target))
-                }
-            }
-        }
-    }
-}